SlideShare une entreprise Scribd logo
1  sur  59
Télécharger pour lire hors ligne
Un ch'ti peu de lambda
des lambdas à l'ombre du beffroi


Rémi Forax
 Décembre 2012
Moi
MCF à l'université Paris Est Marne-La-Vallée
Joue avec Java depuis trop longtemp pour
l'avouer
Créateur de langage dynamique ou pas
Expert pour les JSR 292 (invokedynamic) et
JSR 335 (lambda)
Contributeur OpenJDK, ASM, Tatoo, PHP.reboot, JDart,
etc...
Les lambdaaaaahs
Pourquoi
  par ce que Java c'était trop simple ??

Comment
  on va tout casser Java ??

Sous le capot
  surtout ne pas toucher à la VM ??
Partie I
Introduction aux lambdas
Dit papa, c'est quoi des lambdas ?
private static ArrayList<File> subDirectories(File directory) {
  ArrayList<File> directories = new ArrayList<>();
  File[] files = directory.listFiles();
  for(File file: files) {
     if (file.isDirectory()) {
         directories.add(file);
     }
  }
  return directories;
}

public static void main(String[] args) {
  File file = new File(".");
  for(File dir: subDirectories(file)) {
     System.out.println(dir);
  }
}
Parties codantes
private static ArrayList<File> subDirectories(File directory) {
  ArrayList<File> directories = new ArrayList<>();
  File[] files = directory.listFiles();
  for(File file: files) {
     if (file.isDirectory()) {
         directories.add(file);
     }
  }
  return directories;
}

public static void main(String[] args) {
  File file = new File(".");
  for(File dir: subDirectories(file)) {
     System.out.println(dir);
  }
}
Seconde version
private static File[] subDirectories(File directory) {
  return file.listFiles(new FileFilter() {
      @Override
      public boolean accept(File path) {
        return path.isDirectory();
      }
  });
}

public static void main(String[] args) {
  File file = new File(".");
  for(File dir: subDirectories(file)) {
     System.out.println(dir);
  }
}
Parties codantes
private static File[] subDirectories(File directory) {
  return file.listFiles(new FileFilter() {
      @Override
      public boolean accept(File path) {
        return path.isDirectory();
      }
  });
}

public static void main(String[] args) {
  File file = new File(".");
  for(File dir: subDirectories(file)) {
     System.out.println(dir);
  }
}
Problème des classes anonymes
Une classe anonyme est pas super adaptée
  visuellement
    Verbeux, rapport signal/bruit pas satisfaisant

  sémantiquement
    On veut envoyer une expression, créont une classe ...

  performance
    création d'un objet à chaque appel
    +1 classe sur le disque
    +1 instance de java.lang.Class + métadata en mémoire
Comment font les autres langages ?
 Lisp/Clojure closure's
 Ruby block
 Groovy Closure
 Scala/C# lambda
 Javascript/Python anonymous function
 Python comprehension/C# Linq

 Pourquoi introduire les lambdas en Java ?
   les classes anonymes couvrent déjà le besoin ??
L'excuse multicore
On a plein de coeurs et on sait pas quoi en faire !

Si une partie du code est transformable en objet

On peut distribuer / paralleliser l'exécution

Presque magique
  Enfin, si on a un effet de bord, on est mort !
Sans lambda ...
private static File[] subDirectories(File directory) {
  return file.listFiles(new FileFilter() {
      @Override
      public boolean accept(File path) {
        return path.isDirectory();
      }
  });
}

public static void main(String[] args) {
  File file = new File(".");
  for(File dir: subDirectories(file)) {
     System.out.println(dir);
  }
}
Avec une lambda ...
private static File[] subDirectories(File directory) {
  FileFilter filter = (File path) -> path.isDirectory();
  return file.listFiles(filter);
}

public static void main(String[] args) {
  File file = new File(".");
  for(File dir: subDirectories(file)) {
     System.out.println(dir);
  }
}
Syntaxe pour les expressions
sans paramètre
  () -> System.out.println("welcome to the land of shtis")

avec un paramètre (inférence)
  employee -> employee.isManager()

avec plusieurs paramètres
  en déclarant les types
    (int x, int y) -> x == y
  sans déclarer les types (inférence)
    (x, y) -> x == y
Syntaxe pour les instructions
sans paramètre
  () -> {
    System.out.println("welcome to the land of shtis");
  }

avec un paramètre (inférence)
  employee -> {
    return employee.isManager();
  }

avec plusieurs paramètres (inférence)
  (index1, index2) -> {
    list.set(index1, list.get(index2));
  }
Sémantique
Typé par une functional interface (ex SAM)
  Runnable, Callable, Filter, Function, ...

Une lambda n'est pas un objet
  “this” représente la classe courante pas la lambda

Une lambda est convertissable en un objet qui
implante une functional interface
En utilisant l'inférence
private static File[] subDirectories(File directory) {
  return file.listFiles(
     path -> path.isDirectory()
  );
}

public static void main(String[] args) {
  File file = new File(".");
  for(File dir: subDirectories(file)) {
     System.out.println(dir);
  }
}
Comment l'inférence marche ?
le compilo regarde le(s) type(s) target(s)
  FileFilter filter = path -> path.isDirectory();


l'interface FileFilter est déclarée
  interface FileFilter {
     boolean accept(File file);
  }

utilise jamais le body de la lambda !
  Java != Haskell
Method Reference
private static File[] subDirectories(File directory) {
  return file.listFiles(
     File::isDirectory
  );
}

public static void main(String[] args) {
  File file = new File(".");
  for(File dir: subDirectories(file)) {
     System.out.println(dir);
  }
}
Method Reference
Raccourçi si la lambda délègue juste à une
méthode

On utilise :: rien que pour embéter les C++eux


Si la méthode est surchargée, l'inférence
utilise le target type pour trouver les types des
paramétres
Et les collections
Avoir des lambdas c'est bien, mais sans
support au niveau des APIs ...

Nouvelle interface java.util.Stream
  Sequentielle ou parallele
  Operations
    intermédiaire
       filter, map, sorted, distinct, flatMap ...
    terminales
       reduce, forEach, into, findFirst ...
Full Stream
private static ArrayList<File> subDirectories(
                                   File directory) {
  return Arrays.stream(directory.listFiles()).
     filter(File::isDirectory).
     into(new ArrayList<>());
}

public static void main(String[] args) {
  File file = new File(".");
  for(File dir: subDirectories(file)) {
     System.out.println(dir);
  }
}
Avec tout dans le main()
La méthode subdirectories() sert pas vraiment !

public static void main(String[] args) {
  File directory = new File(".");
  Arrays.stream(directory.listFiles()).
     filter(File::isDirectory).
     forEach(dir -> System.out.println(dir));
}
Capturer la valeur de variables locales
  Et si je veux tous les sous-répertoires dont le nom
  commence par args[0]

  public static void main(String[] args) {
    File directory = new File(".");
    String name = args[0];
    Arrays.stream(directory.listFiles()).
       filter(File::isDirectory).
       filter(dir -> dir.getName().startsWith(name).
       forEach(dir -> System.out.println(dir));
  }

  Une lambda peut capturer les valeurs des variables locales
  (comme avec une classe anonyme)
Pipeline d'élements
Arrays.asStream(array)
collection.stream()         filter     filter      block
iterator.stream()            false       false


        On pousse les élements à travers le pipeline


    Arrays.stream(directory.listFiles()).
        filter(File::isDirectory).
        filter(dir -> dir.getName().startsWith(name).
        forEach(dir -> System.out.println(dir));
Method reference sur une instance
Il est possible de créer une méthode réference sur une
instance


public static void main(String[] args) {
  File directory = new File(".");
  String name = args[0];
  Arrays.stream(directory.listFiles()).
     filter(File::isDirectory).
     filter(path -> path.getName().startsWith(name).
     forEach(System.out::println);
}
En résumé
Java permet de définir des lambdas et des
références sur des méthodes

Une lambda est une expression ou une fonction
anonyme que l'on peut convertir en un objet
pour envoyer à une méthode

L'API des collections est mis à jour pour
supporter les lambdas
Partie II
Changements pour Java
Changements pour Java
Gros problèmes
  Inférence déjà existante pas assez puissante
  Interface pas extensible

Et des petits +
  Effectively final
     Plus besoin de déclarer les variables locales utilisée dans les
     lambdas classes anonymes final
  Eviter les garbages classes
     Mettre les méthodes statiques public/private dans les interfaces
Améliorer l'inférence
Java 5/7 infére
  les variables de type des méthodes
    List<String> list =Array.asList("foo", "bar")
    List<String> list = Collections.emptyList();


  les instantiations de types paramétrés
    List<String> list = new ArrayList<>();

  => mais f(Collections.emptyList()) marche pas !
Inference avec Java 8
Inference pour les types des lambdas
  donc de gauche à droite comme les <>

Inference pour appel de méthode/instantiation
diamond (JEP 101)
  si dans un appel de méthode
    foo(new ArrayList<>()); // ok
  avec propagation
    String s = Collections.emptyList().get(0); // ok
Les demi-dieux de l'inférence




Dan Smith    Maurizio Cimadamore
Extensibilité des interfaces
On veux obtenir un Stream à partir d'une
Collection
  collection.stream()

On ne peut pas ajouter une méthode dans une
interface !

Solution académique: traits (!= Scala traits)
Trait
Un type contenant des méthodes abstraites et
des méthodes concrètes (mais pas de champs)

Ajouter une méthode si l'on fournit l'implantation
ne casse pas la compatibilité

idée: et si on pouvait mettre du code dans une
interface
but, you broke Java !
Default method
Permet de fournir un code par défaut qui est utiliser si il n'en
n'existe pas
interface Iterator<T> {
   public boolean hasNext();
   public T next();

    public default void remove() {
      throw new UnsupportedOperationException();
    }

    public default void forEach(Block<? super T> block) {
      while(hasNext()) {
        block.accept(it.next());
      }
    }
}
Sémantique
La méthode par défaut n'est utilisée que
“par défaut”

interface A {
  default void m() { ... }
}
class B implements A{
  void m() { ... } // pas besoin de A::m !
}
Héritage mutiple ??
interface A {
  default void m() { ... }
}
interface B {
  default void m() { ... }
}
class C implements A, B {
   // compile pas, faut choisir A::m ou B::m
 }
Héritage mutiple
interface A {
  default void m() { ... }
}
interface B {
  default void m() { ... }
}
class C implements A, B {
  // on doit fournir un code pour m()
  public void m() {
     A.super.m(); // on appel m de A
     B.super.m(); // on appel m de B
  }
}
Partie III
dans les entrailles de la VM
Au menu ...
Comment les méthodes par défaut
fonctionnent ?
Comment les lambdas sont compilés ?
Comment les lambdas sont optimisées par la
VM ?
Méthode par défaut
Le compilo ne peut rien faire !
  Sinon on doit recompiler toutes les libraries

Doit être fait par la VM
  mais
   ●   les règles de redéfinition (override) dépendent des generics
   ●   Les générics sont un artifact à la compile pas connu à
       l'exécution (erasure)

La VM doit savoir lire les signatures des generics
Méthode par défaut et erasure
interface Foo<T> {
  default T getFoo() { return ...; }
}
interface Bar {
  String getFoo();
}
class A implements Bar, Foo<String> {
}
Méthode par défaut et erasure
interface Foo<T> {
  default ObjectT getFoo() { return ...; }
}
interface Bar {
  String getFoo();
}
class A implements Bar, Foo<String> {
}

         la VM doit générer deux méthodes
           Object getFoo() et String getFoo()
Méthode par défaut et erasure
interface Foo<T> {
  default ObjectT getFoo() { return ...; }
}
interface Bar {
  String getFoo();
}
class A implements Bar, Foo<String> {
  Object getFoo() {
     return getFoo(); // appel String getFoo()
  }
  String getFoo() {
     return ...; // recopie le bytecode de Foo::getFoo
  }
}
Compiler une lambda naïvement
On créé une méthode synthetic pour le corps de la lambda
On crée une classe anonyme lors de la convertion vers la
functional interface
iterator.forEach(dir -> System.out.println(dir));
devient
iterator.forEach(new Block<File>() {
    public void accept(File dir) {
      return lambda$1(dir);
    }
});
static void lambda$1(File dir) {
  System.out.println(dir);
}
Lambda objet constant ?
A l'exécution, il y a deux sortes de lambdas
  Les lambdas qui ne captures pas de variable ou les
  méthodes référence sur une classe
   ●   path -> path.isDirectory
   ●   File::isDirectory

  Celles qui capture des variables ou les méthode
  référence sur des instances
   ●   path -> path.getName().startsWith(args[0)
   ●   System.out::println
Compiler vers une classe anonyme ?
 Et on se récupère tous les problèmes de perf
 des classes anonymes

 De plus, si une lambda ne capture pas de
 variable, on pourrait au moins la crée que une
 seule fois
   Mais si on utilise un champ static final,
   l'initialisation à lieu même si on ne l'utilise pas
Invokedynamic to rule them all
On veut un mécanisme qui délai l'initialisation au
premier accès
  invokedynamic

On veut un mécanisme qui permet d'indiquer que le
résultat d'un calcul est constant
  invokedynamic

On veut un pointeur de fonction pour éviter la
création des classe anonymes
  java.lang.invoke.MethodHandle
Compiler une lambda
iterator.forEach(dir -> System.out.println(dir));
devient
iterator.forEach(invokedynamic bootstrap [lambda$1]);
static void lambda$1(File dir) {
  System.out.println(dir);
}
CallSite bootstrap(Lookup lookup, String name,
                   MethodType type, MethodHandle mh) {
  if (type.parameterCount() == 0) {
      return new ConstantCallSite(proxy(mh));
  }
  return ...
}
Lambda Proxy
Instance d'une classe qui contient le pointeur de
fonction (MethodHandle) vers la lambda à
exécuter

Il n'y a besoin que d'une classe proxy par
functional interface


Le proxy est généré dynamiquement par la VM,
pas forcément besoin de bytecode associé
Lambda Proxy en pseudo code
Le code Java correspondant est à peu près :
public class Proxy$Block implements Block {
 private final @Stable MethodHandle mh;

    public void accept(Object o) {
      mh.invokeExact(o);
    }
}

invokeExact() est un pointer check + un appel à un
pointeur de fonction
Optimizations lors de l'appel
Avoir 1 seul classe pour 1 interface permet à la VM de
remplacer l'appel à l'interface par le code de la classe
(Class Hierarchy Analysis)

interface Iterator<T> {
   ...
   public default void forEach(Block<? super T> block) {
       while(hasNext()) {
         block.accept(it.next());
       }
   }
}

ici, block est toujours une instance de Proxy$Block
Optimizations lors de l'appel
Si un objet constant dans une boucle, il est sortie de la boucle

interface Iterator<T> {
   ...
   public default void forEach(Block<? super T> block) {
       while(hasNext()) {
         mh.invokeExact(it.next());
       }
   }
}

Dans le cas d'un method handle, il faut inliner le code
référencé par le pointer de fonction (fairy tale mode)
dans le monde merveilleux
              des licornes
On guarde la boucle avec un test sur le method handle
(comme pour l'On Stack Replacement)

interface Iterator<T> {
   ...
   public default void forEach(Block<? super T> block) {
       if (block.mh == lambda$1) {
         while(hasNext()) {
            System.out.println(it.next());
         }
       }
       else deopt();
   }
}

et comme block est pris en paramètre, l'idée est de spécialiser le code à
l'endroit de l'appel ce qui permet de ne pas faire le test
Le léger hic
Le code de la VM qui crée le lambda proxy et qui l'optimise
est pas prêt
  Le plan est prêt depuis longtemps, c'est la réalisation qui prend
  du temps

On doit quand même livrer un truc pour le JDK8

Solution temporaire: la méthode de bootstrap génère une
classe anonyme dynamiquement en utilisant ASM
  On implantera les lambda proxies dans une update du jdk8
En résumé
La première version des lambdas sera pas la
plus optimisée
L'API dans java.util doit être fini pour fin
janvier
La spec de l'inférence pas fini même si ça se
précise

Bref on est grâve à la bourre
Si vous avez du temps libre
et même si vous n'en avez pas !

Downloader la dernière version du jdk8 avec les
lambdas
  http://jdk8.java.net/lambda/

Tester l'API, jouer avec, remonter tous les bugs
  lambda-dev@openjdk.java.net

Contenu connexe

Tendances

Chapitre 11: Expression Lambda et Référence de méthode en Java
Chapitre 11: Expression Lambda et Référence de méthode en JavaChapitre 11: Expression Lambda et Référence de méthode en Java
Chapitre 11: Expression Lambda et Référence de méthode en JavaAziz Darouichi
 
Collection v3
Collection v3Collection v3
Collection v3Sunil OS
 
The Best (and Worst) of Django
The Best (and Worst) of DjangoThe Best (and Worst) of Django
The Best (and Worst) of DjangoJacob Kaplan-Moss
 
Collections Framework
Collections FrameworkCollections Framework
Collections FrameworkSunil OS
 
Concevoir, développer et sécuriser des micro-services avec Spring Boot
Concevoir, développer et sécuriser des micro-services avec Spring BootConcevoir, développer et sécuriser des micro-services avec Spring Boot
Concevoir, développer et sécuriser des micro-services avec Spring BootDNG Consulting
 
Deep Dive Java 17 Devoxx UK
Deep Dive Java 17 Devoxx UKDeep Dive Java 17 Devoxx UK
Deep Dive Java 17 Devoxx UKJosé Paumard
 
LinkedList vs Arraylist- an in depth look at java.util.LinkedList
LinkedList vs Arraylist- an in depth look at java.util.LinkedListLinkedList vs Arraylist- an in depth look at java.util.LinkedList
LinkedList vs Arraylist- an in depth look at java.util.LinkedListMarcus Biel
 
POO Java Chapitre 2 Encapsulation
POO Java Chapitre 2 EncapsulationPOO Java Chapitre 2 Encapsulation
POO Java Chapitre 2 EncapsulationMouna Torjmen
 
Alphorm.com Formation Vue JS 3 : Exploiter la Composition API
Alphorm.com Formation Vue JS 3 : Exploiter la Composition APIAlphorm.com Formation Vue JS 3 : Exploiter la Composition API
Alphorm.com Formation Vue JS 3 : Exploiter la Composition APIAlphorm
 
An Introduction to Gradle for Java Developers
An Introduction to Gradle for Java DevelopersAn Introduction to Gradle for Java Developers
An Introduction to Gradle for Java DevelopersKostas Saidis
 
Intégration de SonarQube dans GitLab ci
Intégration de SonarQube dans GitLab ciIntégration de SonarQube dans GitLab ci
Intégration de SonarQube dans GitLab ciwiemfourati
 
Chap 6 : classes et interfaces
Chap 6 : classes et interfacesChap 6 : classes et interfaces
Chap 6 : classes et interfacesAziz Darouichi
 
Introduction to Ansible
Introduction to AnsibleIntroduction to Ansible
Introduction to AnsibleCoreStack
 

Tendances (20)

Nouveautés de java 8
Nouveautés de java 8Nouveautés de java 8
Nouveautés de java 8
 
Support programmation orientée objet c# .net version f8
Support programmation orientée objet c#  .net version f8Support programmation orientée objet c#  .net version f8
Support programmation orientée objet c# .net version f8
 
Introduction to Vagrant
Introduction to VagrantIntroduction to Vagrant
Introduction to Vagrant
 
Chapitre 11: Expression Lambda et Référence de méthode en Java
Chapitre 11: Expression Lambda et Référence de méthode en JavaChapitre 11: Expression Lambda et Référence de méthode en Java
Chapitre 11: Expression Lambda et Référence de méthode en Java
 
Collection v3
Collection v3Collection v3
Collection v3
 
Corrige tp java
Corrige tp javaCorrige tp java
Corrige tp java
 
Introduction to java 8 stream api
Introduction to java 8 stream apiIntroduction to java 8 stream api
Introduction to java 8 stream api
 
The Best (and Worst) of Django
The Best (and Worst) of DjangoThe Best (and Worst) of Django
The Best (and Worst) of Django
 
Collections Framework
Collections FrameworkCollections Framework
Collections Framework
 
Concevoir, développer et sécuriser des micro-services avec Spring Boot
Concevoir, développer et sécuriser des micro-services avec Spring BootConcevoir, développer et sécuriser des micro-services avec Spring Boot
Concevoir, développer et sécuriser des micro-services avec Spring Boot
 
Deep Dive Java 17 Devoxx UK
Deep Dive Java 17 Devoxx UKDeep Dive Java 17 Devoxx UK
Deep Dive Java 17 Devoxx UK
 
Complete Java Course
Complete Java CourseComplete Java Course
Complete Java Course
 
LinkedList vs Arraylist- an in depth look at java.util.LinkedList
LinkedList vs Arraylist- an in depth look at java.util.LinkedListLinkedList vs Arraylist- an in depth look at java.util.LinkedList
LinkedList vs Arraylist- an in depth look at java.util.LinkedList
 
POO Java Chapitre 2 Encapsulation
POO Java Chapitre 2 EncapsulationPOO Java Chapitre 2 Encapsulation
POO Java Chapitre 2 Encapsulation
 
Alphorm.com Formation Vue JS 3 : Exploiter la Composition API
Alphorm.com Formation Vue JS 3 : Exploiter la Composition APIAlphorm.com Formation Vue JS 3 : Exploiter la Composition API
Alphorm.com Formation Vue JS 3 : Exploiter la Composition API
 
An Introduction to Gradle for Java Developers
An Introduction to Gradle for Java DevelopersAn Introduction to Gradle for Java Developers
An Introduction to Gradle for Java Developers
 
Intégration de SonarQube dans GitLab ci
Intégration de SonarQube dans GitLab ciIntégration de SonarQube dans GitLab ci
Intégration de SonarQube dans GitLab ci
 
Support de cours Spring M.youssfi
Support de cours Spring  M.youssfiSupport de cours Spring  M.youssfi
Support de cours Spring M.youssfi
 
Chap 6 : classes et interfaces
Chap 6 : classes et interfacesChap 6 : classes et interfaces
Chap 6 : classes et interfaces
 
Introduction to Ansible
Introduction to AnsibleIntroduction to Ansible
Introduction to Ansible
 

En vedette

Retours sur java 8 devoxx fr 2016
Retours sur java 8 devoxx fr 2016Retours sur java 8 devoxx fr 2016
Retours sur java 8 devoxx fr 2016Jean-Michel Doudoux
 
Java 8-streams-collectors-patterns
Java 8-streams-collectors-patternsJava 8-streams-collectors-patterns
Java 8-streams-collectors-patternsJosé Paumard
 
50 nouvelles choses que l'on peut faire avec Java 8
50 nouvelles choses que l'on peut faire avec Java 850 nouvelles choses que l'on peut faire avec Java 8
50 nouvelles choses que l'on peut faire avec Java 8José Paumard
 
Les Streams sont parmi nous
Les Streams sont parmi nousLes Streams sont parmi nous
Les Streams sont parmi nousJosé Paumard
 
Alphorm.com Java 8: les nouveautés
Alphorm.com Java 8: les nouveautésAlphorm.com Java 8: les nouveautés
Alphorm.com Java 8: les nouveautésAlphorm
 
Introduction of Java 8 with emphasis on Lambda Expressions and Streams
Introduction of Java 8 with emphasis on Lambda Expressions and StreamsIntroduction of Java 8 with emphasis on Lambda Expressions and Streams
Introduction of Java 8 with emphasis on Lambda Expressions and StreamsEmiel Paasschens
 
Lambda Expressions in Java
Lambda Expressions in JavaLambda Expressions in Java
Lambda Expressions in JavaErhan Bagdemir
 
Linked to ArrayList: the full story
Linked to ArrayList: the full storyLinked to ArrayList: the full story
Linked to ArrayList: the full storyJosé Paumard
 
Java 8 presentation
Java 8 presentationJava 8 presentation
Java 8 presentationVan Huong
 
50 new things you can do with java 8
50 new things you can do with java 850 new things you can do with java 8
50 new things you can do with java 8José Paumard
 
Java 8 Lambda Expressions & Streams
Java 8 Lambda Expressions & StreamsJava 8 Lambda Expressions & Streams
Java 8 Lambda Expressions & StreamsNewCircle Training
 
Java 8, Streams & Collectors, patterns, performances and parallelization
Java 8, Streams & Collectors, patterns, performances and parallelizationJava 8, Streams & Collectors, patterns, performances and parallelization
Java 8, Streams & Collectors, patterns, performances and parallelizationJosé Paumard
 
Présentation f editor by adsonwall
Présentation f editor by adsonwallPrésentation f editor by adsonwall
Présentation f editor by adsonwallCharles Martin-Laval
 
E-tutorat et environnement professionnel - 9R
E-tutorat et environnement professionnel - 9RE-tutorat et environnement professionnel - 9R
E-tutorat et environnement professionnel - 9RFFFOD
 
Modelo de negocio en canvas
Modelo de negocio en canvasModelo de negocio en canvas
Modelo de negocio en canvasGerSon HuallCca
 

En vedette (20)

Retours sur java 8 devoxx fr 2016
Retours sur java 8 devoxx fr 2016Retours sur java 8 devoxx fr 2016
Retours sur java 8 devoxx fr 2016
 
Java 8-streams-collectors-patterns
Java 8-streams-collectors-patternsJava 8-streams-collectors-patterns
Java 8-streams-collectors-patterns
 
50 nouvelles choses que l'on peut faire avec Java 8
50 nouvelles choses que l'on peut faire avec Java 850 nouvelles choses que l'on peut faire avec Java 8
50 nouvelles choses que l'on peut faire avec Java 8
 
Les Streams sont parmi nous
Les Streams sont parmi nousLes Streams sont parmi nous
Les Streams sont parmi nous
 
Alphorm.com Java 8: les nouveautés
Alphorm.com Java 8: les nouveautésAlphorm.com Java 8: les nouveautés
Alphorm.com Java 8: les nouveautés
 
Java 8 Lambda and Streams
Java 8 Lambda and StreamsJava 8 Lambda and Streams
Java 8 Lambda and Streams
 
Introduction of Java 8 with emphasis on Lambda Expressions and Streams
Introduction of Java 8 with emphasis on Lambda Expressions and StreamsIntroduction of Java 8 with emphasis on Lambda Expressions and Streams
Introduction of Java 8 with emphasis on Lambda Expressions and Streams
 
Lambda Expressions in Java
Lambda Expressions in JavaLambda Expressions in Java
Lambda Expressions in Java
 
Java8
Java8Java8
Java8
 
Linked to ArrayList: the full story
Linked to ArrayList: the full storyLinked to ArrayList: the full story
Linked to ArrayList: the full story
 
Java 8 presentation
Java 8 presentationJava 8 presentation
Java 8 presentation
 
Java 8 Lambda Expressions
Java 8 Lambda ExpressionsJava 8 Lambda Expressions
Java 8 Lambda Expressions
 
50 new things you can do with java 8
50 new things you can do with java 850 new things you can do with java 8
50 new things you can do with java 8
 
Java 8 Lambda Expressions & Streams
Java 8 Lambda Expressions & StreamsJava 8 Lambda Expressions & Streams
Java 8 Lambda Expressions & Streams
 
Java 8, Streams & Collectors, patterns, performances and parallelization
Java 8, Streams & Collectors, patterns, performances and parallelizationJava 8, Streams & Collectors, patterns, performances and parallelization
Java 8, Streams & Collectors, patterns, performances and parallelization
 
Presentacion 1
Presentacion 1Presentacion 1
Presentacion 1
 
Gilly News 2010-06
Gilly News 2010-06Gilly News 2010-06
Gilly News 2010-06
 
Présentation f editor by adsonwall
Présentation f editor by adsonwallPrésentation f editor by adsonwall
Présentation f editor by adsonwall
 
E-tutorat et environnement professionnel - 9R
E-tutorat et environnement professionnel - 9RE-tutorat et environnement professionnel - 9R
E-tutorat et environnement professionnel - 9R
 
Modelo de negocio en canvas
Modelo de negocio en canvasModelo de negocio en canvas
Modelo de negocio en canvas
 

Similaire à Java 8 : Un ch'ti peu de lambda

"Input/Ouput, 16 ans après" à Devoxx France 2012
"Input/Ouput, 16 ans après" à Devoxx France 2012"Input/Ouput, 16 ans après" à Devoxx France 2012
"Input/Ouput, 16 ans après" à Devoxx France 2012Jean-Michel Doudoux
 
Le système d&rsquo;E/S en Java
Le système d&rsquo;E/S en JavaLe système d&rsquo;E/S en Java
Le système d&rsquo;E/S en JavaKorteby Farouk
 
Cours de C++, en français, 2002 - Cours 3.4
Cours de C++, en français, 2002 - Cours 3.4Cours de C++, en français, 2002 - Cours 3.4
Cours de C++, en français, 2002 - Cours 3.4Laurent BUNIET
 
Les nouveautés de java 7 et les promesses
Les nouveautés de java 7  et les promessesLes nouveautés de java 7  et les promesses
Les nouveautés de java 7 et les promessesEric Toguem
 
Interface collectionsinter
Interface collectionsinterInterface collectionsinter
Interface collectionsinterRYMAA
 
5- understandinggJava_Collections_v4.pdf
5- understandinggJava_Collections_v4.pdf5- understandinggJava_Collections_v4.pdf
5- understandinggJava_Collections_v4.pdfAliouDiallo24
 
Introduction à scala
Introduction à scalaIntroduction à scala
Introduction à scalaSOAT
 
Geek Time Janvier 2017 : Java 8
Geek Time Janvier 2017 : Java 8Geek Time Janvier 2017 : Java 8
Geek Time Janvier 2017 : Java 8OLBATI
 
MarsJUG - Le classpath n'est pas mort, mais presque
MarsJUG - Le classpath n'est pas mort, mais presqueMarsJUG - Le classpath n'est pas mort, mais presque
MarsJUG - Le classpath n'est pas mort, mais presqueAlexis Hassler
 
Pres_ java_Fichier_Suite_cour sur les fichier en java.pdf
Pres_ java_Fichier_Suite_cour sur les fichier en java.pdfPres_ java_Fichier_Suite_cour sur les fichier en java.pdf
Pres_ java_Fichier_Suite_cour sur les fichier en java.pdfHERGALYOUSSEF
 
201305 - Lambda by R. Forax
201305 - Lambda by R. Forax201305 - Lambda by R. Forax
201305 - Lambda by R. Foraxlyonjug
 
Fork / Join, Parallel Arrays, Lambdas : la programmation parallèle (trop ?) f...
Fork / Join, Parallel Arrays, Lambdas : la programmation parallèle (trop ?) f...Fork / Join, Parallel Arrays, Lambdas : la programmation parallèle (trop ?) f...
Fork / Join, Parallel Arrays, Lambdas : la programmation parallèle (trop ?) f...Normandy JUG
 
De java à swift en 2 temps trois mouvements
De java à swift en 2 temps trois mouvementsDe java à swift en 2 temps trois mouvements
De java à swift en 2 temps trois mouvementsDidier Plaindoux
 
Les principes de base de PHP
 Les principes de base de PHP  Les principes de base de PHP
Les principes de base de PHP EL JAOUARI Ahmed
 

Similaire à Java 8 : Un ch'ti peu de lambda (20)

NIO 2
NIO 2NIO 2
NIO 2
 
"Input/Ouput, 16 ans après" à Devoxx France 2012
"Input/Ouput, 16 ans après" à Devoxx France 2012"Input/Ouput, 16 ans après" à Devoxx France 2012
"Input/Ouput, 16 ans après" à Devoxx France 2012
 
Le système d&rsquo;E/S en Java
Le système d&rsquo;E/S en JavaLe système d&rsquo;E/S en Java
Le système d&rsquo;E/S en Java
 
Cours de C++, en français, 2002 - Cours 3.4
Cours de C++, en français, 2002 - Cours 3.4Cours de C++, en français, 2002 - Cours 3.4
Cours de C++, en français, 2002 - Cours 3.4
 
Présentation nouveauté java7
Présentation nouveauté java7Présentation nouveauté java7
Présentation nouveauté java7
 
Les nouveautés de java 7 et les promesses
Les nouveautés de java 7  et les promessesLes nouveautés de java 7  et les promesses
Les nouveautés de java 7 et les promesses
 
Interface collectionsinter
Interface collectionsinterInterface collectionsinter
Interface collectionsinter
 
5- understandinggJava_Collections_v4.pdf
5- understandinggJava_Collections_v4.pdf5- understandinggJava_Collections_v4.pdf
5- understandinggJava_Collections_v4.pdf
 
Introduction à scala
Introduction à scalaIntroduction à scala
Introduction à scala
 
Php1
Php1Php1
Php1
 
Geek Time Janvier 2017 : Java 8
Geek Time Janvier 2017 : Java 8Geek Time Janvier 2017 : Java 8
Geek Time Janvier 2017 : Java 8
 
MarsJUG - Le classpath n'est pas mort, mais presque
MarsJUG - Le classpath n'est pas mort, mais presqueMarsJUG - Le classpath n'est pas mort, mais presque
MarsJUG - Le classpath n'est pas mort, mais presque
 
Tp n 3 linux
Tp n 3 linuxTp n 3 linux
Tp n 3 linux
 
Pres_ java_Fichier_Suite_cour sur les fichier en java.pdf
Pres_ java_Fichier_Suite_cour sur les fichier en java.pdfPres_ java_Fichier_Suite_cour sur les fichier en java.pdf
Pres_ java_Fichier_Suite_cour sur les fichier en java.pdf
 
201305 - Lambda by R. Forax
201305 - Lambda by R. Forax201305 - Lambda by R. Forax
201305 - Lambda by R. Forax
 
Fork / Join, Parallel Arrays, Lambdas : la programmation parallèle (trop ?) f...
Fork / Join, Parallel Arrays, Lambdas : la programmation parallèle (trop ?) f...Fork / Join, Parallel Arrays, Lambdas : la programmation parallèle (trop ?) f...
Fork / Join, Parallel Arrays, Lambdas : la programmation parallèle (trop ?) f...
 
POO-JAVA-partie-1.pdf
POO-JAVA-partie-1.pdfPOO-JAVA-partie-1.pdf
POO-JAVA-partie-1.pdf
 
De java à swift en 2 temps trois mouvements
De java à swift en 2 temps trois mouvementsDe java à swift en 2 temps trois mouvements
De java à swift en 2 temps trois mouvements
 
Les principes de base de PHP
 Les principes de base de PHP  Les principes de base de PHP
Les principes de base de PHP
 
Php cours
Php coursPhp cours
Php cours
 

Plus de Ch'ti JUG

Bonita Open Solution
Bonita Open SolutionBonita Open Solution
Bonita Open SolutionCh'ti JUG
 
Adobe flash platform java
Adobe flash platform javaAdobe flash platform java
Adobe flash platform javaCh'ti JUG
 
MC3SI Chti Jug Soiree Agilite
MC3SI Chti Jug Soiree AgiliteMC3SI Chti Jug Soiree Agilite
MC3SI Chti Jug Soiree AgiliteCh'ti JUG
 
Chti Jug Octo 16032010 Réduisons le ticket d’entrée de nos projets
Chti Jug Octo 16032010 Réduisons le ticket d’entrée de nos projetsChti Jug Octo 16032010 Réduisons le ticket d’entrée de nos projets
Chti Jug Octo 16032010 Réduisons le ticket d’entrée de nos projetsCh'ti JUG
 
GlassFish ESB Ch'ti JUG
GlassFish ESB Ch'ti JUGGlassFish ESB Ch'ti JUG
GlassFish ESB Ch'ti JUGCh'ti JUG
 
Drools Planner Chtijug 2010
Drools Planner Chtijug 2010Drools Planner Chtijug 2010
Drools Planner Chtijug 2010Ch'ti JUG
 
Lille2010markp
Lille2010markpLille2010markp
Lille2010markpCh'ti JUG
 
Terracotta Ch'ti Jug
Terracotta Ch'ti JugTerracotta Ch'ti Jug
Terracotta Ch'ti JugCh'ti JUG
 

Plus de Ch'ti JUG (10)

Spring 3.1
Spring 3.1Spring 3.1
Spring 3.1
 
Bonita Open Solution
Bonita Open SolutionBonita Open Solution
Bonita Open Solution
 
Adobe flash platform java
Adobe flash platform javaAdobe flash platform java
Adobe flash platform java
 
MC3SI Chti Jug Soiree Agilite
MC3SI Chti Jug Soiree AgiliteMC3SI Chti Jug Soiree Agilite
MC3SI Chti Jug Soiree Agilite
 
Chti Jug Octo 16032010 Réduisons le ticket d’entrée de nos projets
Chti Jug Octo 16032010 Réduisons le ticket d’entrée de nos projetsChti Jug Octo 16032010 Réduisons le ticket d’entrée de nos projets
Chti Jug Octo 16032010 Réduisons le ticket d’entrée de nos projets
 
GlassFish ESB Ch'ti JUG
GlassFish ESB Ch'ti JUGGlassFish ESB Ch'ti JUG
GlassFish ESB Ch'ti JUG
 
Drools Planner Chtijug 2010
Drools Planner Chtijug 2010Drools Planner Chtijug 2010
Drools Planner Chtijug 2010
 
Lille2010markp
Lille2010markpLille2010markp
Lille2010markp
 
HTML5 ADEO
HTML5 ADEOHTML5 ADEO
HTML5 ADEO
 
Terracotta Ch'ti Jug
Terracotta Ch'ti JugTerracotta Ch'ti Jug
Terracotta Ch'ti Jug
 

Java 8 : Un ch'ti peu de lambda

  • 1. Un ch'ti peu de lambda des lambdas à l'ombre du beffroi Rémi Forax Décembre 2012
  • 2. Moi MCF à l'université Paris Est Marne-La-Vallée Joue avec Java depuis trop longtemp pour l'avouer Créateur de langage dynamique ou pas Expert pour les JSR 292 (invokedynamic) et JSR 335 (lambda) Contributeur OpenJDK, ASM, Tatoo, PHP.reboot, JDart, etc...
  • 3. Les lambdaaaaahs Pourquoi par ce que Java c'était trop simple ?? Comment on va tout casser Java ?? Sous le capot surtout ne pas toucher à la VM ??
  • 5. Dit papa, c'est quoi des lambdas ? private static ArrayList<File> subDirectories(File directory) { ArrayList<File> directories = new ArrayList<>(); File[] files = directory.listFiles(); for(File file: files) { if (file.isDirectory()) { directories.add(file); } } return directories; } public static void main(String[] args) { File file = new File("."); for(File dir: subDirectories(file)) { System.out.println(dir); } }
  • 6. Parties codantes private static ArrayList<File> subDirectories(File directory) { ArrayList<File> directories = new ArrayList<>(); File[] files = directory.listFiles(); for(File file: files) { if (file.isDirectory()) { directories.add(file); } } return directories; } public static void main(String[] args) { File file = new File("."); for(File dir: subDirectories(file)) { System.out.println(dir); } }
  • 7. Seconde version private static File[] subDirectories(File directory) { return file.listFiles(new FileFilter() { @Override public boolean accept(File path) { return path.isDirectory(); } }); } public static void main(String[] args) { File file = new File("."); for(File dir: subDirectories(file)) { System.out.println(dir); } }
  • 8. Parties codantes private static File[] subDirectories(File directory) { return file.listFiles(new FileFilter() { @Override public boolean accept(File path) { return path.isDirectory(); } }); } public static void main(String[] args) { File file = new File("."); for(File dir: subDirectories(file)) { System.out.println(dir); } }
  • 9. Problème des classes anonymes Une classe anonyme est pas super adaptée visuellement Verbeux, rapport signal/bruit pas satisfaisant sémantiquement On veut envoyer une expression, créont une classe ... performance création d'un objet à chaque appel +1 classe sur le disque +1 instance de java.lang.Class + métadata en mémoire
  • 10. Comment font les autres langages ? Lisp/Clojure closure's Ruby block Groovy Closure Scala/C# lambda Javascript/Python anonymous function Python comprehension/C# Linq Pourquoi introduire les lambdas en Java ? les classes anonymes couvrent déjà le besoin ??
  • 11. L'excuse multicore On a plein de coeurs et on sait pas quoi en faire ! Si une partie du code est transformable en objet On peut distribuer / paralleliser l'exécution Presque magique Enfin, si on a un effet de bord, on est mort !
  • 12. Sans lambda ... private static File[] subDirectories(File directory) { return file.listFiles(new FileFilter() { @Override public boolean accept(File path) { return path.isDirectory(); } }); } public static void main(String[] args) { File file = new File("."); for(File dir: subDirectories(file)) { System.out.println(dir); } }
  • 13. Avec une lambda ... private static File[] subDirectories(File directory) { FileFilter filter = (File path) -> path.isDirectory(); return file.listFiles(filter); } public static void main(String[] args) { File file = new File("."); for(File dir: subDirectories(file)) { System.out.println(dir); } }
  • 14. Syntaxe pour les expressions sans paramètre () -> System.out.println("welcome to the land of shtis") avec un paramètre (inférence) employee -> employee.isManager() avec plusieurs paramètres en déclarant les types (int x, int y) -> x == y sans déclarer les types (inférence) (x, y) -> x == y
  • 15. Syntaxe pour les instructions sans paramètre () -> { System.out.println("welcome to the land of shtis"); } avec un paramètre (inférence) employee -> { return employee.isManager(); } avec plusieurs paramètres (inférence) (index1, index2) -> { list.set(index1, list.get(index2)); }
  • 16. Sémantique Typé par une functional interface (ex SAM) Runnable, Callable, Filter, Function, ... Une lambda n'est pas un objet “this” représente la classe courante pas la lambda Une lambda est convertissable en un objet qui implante une functional interface
  • 17. En utilisant l'inférence private static File[] subDirectories(File directory) { return file.listFiles( path -> path.isDirectory() ); } public static void main(String[] args) { File file = new File("."); for(File dir: subDirectories(file)) { System.out.println(dir); } }
  • 18. Comment l'inférence marche ? le compilo regarde le(s) type(s) target(s) FileFilter filter = path -> path.isDirectory(); l'interface FileFilter est déclarée interface FileFilter { boolean accept(File file); } utilise jamais le body de la lambda ! Java != Haskell
  • 19. Method Reference private static File[] subDirectories(File directory) { return file.listFiles( File::isDirectory ); } public static void main(String[] args) { File file = new File("."); for(File dir: subDirectories(file)) { System.out.println(dir); } }
  • 20. Method Reference Raccourçi si la lambda délègue juste à une méthode On utilise :: rien que pour embéter les C++eux Si la méthode est surchargée, l'inférence utilise le target type pour trouver les types des paramétres
  • 21. Et les collections Avoir des lambdas c'est bien, mais sans support au niveau des APIs ... Nouvelle interface java.util.Stream Sequentielle ou parallele Operations intermédiaire filter, map, sorted, distinct, flatMap ... terminales reduce, forEach, into, findFirst ...
  • 22. Full Stream private static ArrayList<File> subDirectories( File directory) { return Arrays.stream(directory.listFiles()). filter(File::isDirectory). into(new ArrayList<>()); } public static void main(String[] args) { File file = new File("."); for(File dir: subDirectories(file)) { System.out.println(dir); } }
  • 23. Avec tout dans le main() La méthode subdirectories() sert pas vraiment ! public static void main(String[] args) { File directory = new File("."); Arrays.stream(directory.listFiles()). filter(File::isDirectory). forEach(dir -> System.out.println(dir)); }
  • 24. Capturer la valeur de variables locales Et si je veux tous les sous-répertoires dont le nom commence par args[0] public static void main(String[] args) { File directory = new File("."); String name = args[0]; Arrays.stream(directory.listFiles()). filter(File::isDirectory). filter(dir -> dir.getName().startsWith(name). forEach(dir -> System.out.println(dir)); } Une lambda peut capturer les valeurs des variables locales (comme avec une classe anonyme)
  • 25. Pipeline d'élements Arrays.asStream(array) collection.stream() filter filter block iterator.stream() false false On pousse les élements à travers le pipeline Arrays.stream(directory.listFiles()). filter(File::isDirectory). filter(dir -> dir.getName().startsWith(name). forEach(dir -> System.out.println(dir));
  • 26. Method reference sur une instance Il est possible de créer une méthode réference sur une instance public static void main(String[] args) { File directory = new File("."); String name = args[0]; Arrays.stream(directory.listFiles()). filter(File::isDirectory). filter(path -> path.getName().startsWith(name). forEach(System.out::println); }
  • 27. En résumé Java permet de définir des lambdas et des références sur des méthodes Une lambda est une expression ou une fonction anonyme que l'on peut convertir en un objet pour envoyer à une méthode L'API des collections est mis à jour pour supporter les lambdas
  • 29. Changements pour Java Gros problèmes Inférence déjà existante pas assez puissante Interface pas extensible Et des petits + Effectively final Plus besoin de déclarer les variables locales utilisée dans les lambdas classes anonymes final Eviter les garbages classes Mettre les méthodes statiques public/private dans les interfaces
  • 30. Améliorer l'inférence Java 5/7 infére les variables de type des méthodes List<String> list =Array.asList("foo", "bar") List<String> list = Collections.emptyList(); les instantiations de types paramétrés List<String> list = new ArrayList<>(); => mais f(Collections.emptyList()) marche pas !
  • 31. Inference avec Java 8 Inference pour les types des lambdas donc de gauche à droite comme les <> Inference pour appel de méthode/instantiation diamond (JEP 101) si dans un appel de méthode foo(new ArrayList<>()); // ok avec propagation String s = Collections.emptyList().get(0); // ok
  • 32. Les demi-dieux de l'inférence Dan Smith Maurizio Cimadamore
  • 33. Extensibilité des interfaces On veux obtenir un Stream à partir d'une Collection collection.stream() On ne peut pas ajouter une méthode dans une interface ! Solution académique: traits (!= Scala traits)
  • 34. Trait Un type contenant des méthodes abstraites et des méthodes concrètes (mais pas de champs) Ajouter une méthode si l'on fournit l'implantation ne casse pas la compatibilité idée: et si on pouvait mettre du code dans une interface
  • 35. but, you broke Java !
  • 36.
  • 37. Default method Permet de fournir un code par défaut qui est utiliser si il n'en n'existe pas interface Iterator<T> { public boolean hasNext(); public T next(); public default void remove() { throw new UnsupportedOperationException(); } public default void forEach(Block<? super T> block) { while(hasNext()) { block.accept(it.next()); } } }
  • 38. Sémantique La méthode par défaut n'est utilisée que “par défaut” interface A { default void m() { ... } } class B implements A{ void m() { ... } // pas besoin de A::m ! }
  • 39. Héritage mutiple ?? interface A { default void m() { ... } } interface B { default void m() { ... } } class C implements A, B { // compile pas, faut choisir A::m ou B::m }
  • 40. Héritage mutiple interface A { default void m() { ... } } interface B { default void m() { ... } } class C implements A, B { // on doit fournir un code pour m() public void m() { A.super.m(); // on appel m de A B.super.m(); // on appel m de B } }
  • 41. Partie III dans les entrailles de la VM
  • 42. Au menu ... Comment les méthodes par défaut fonctionnent ? Comment les lambdas sont compilés ? Comment les lambdas sont optimisées par la VM ?
  • 43. Méthode par défaut Le compilo ne peut rien faire ! Sinon on doit recompiler toutes les libraries Doit être fait par la VM mais ● les règles de redéfinition (override) dépendent des generics ● Les générics sont un artifact à la compile pas connu à l'exécution (erasure) La VM doit savoir lire les signatures des generics
  • 44. Méthode par défaut et erasure interface Foo<T> { default T getFoo() { return ...; } } interface Bar { String getFoo(); } class A implements Bar, Foo<String> { }
  • 45. Méthode par défaut et erasure interface Foo<T> { default ObjectT getFoo() { return ...; } } interface Bar { String getFoo(); } class A implements Bar, Foo<String> { } la VM doit générer deux méthodes Object getFoo() et String getFoo()
  • 46. Méthode par défaut et erasure interface Foo<T> { default ObjectT getFoo() { return ...; } } interface Bar { String getFoo(); } class A implements Bar, Foo<String> { Object getFoo() { return getFoo(); // appel String getFoo() } String getFoo() { return ...; // recopie le bytecode de Foo::getFoo } }
  • 47. Compiler une lambda naïvement On créé une méthode synthetic pour le corps de la lambda On crée une classe anonyme lors de la convertion vers la functional interface iterator.forEach(dir -> System.out.println(dir)); devient iterator.forEach(new Block<File>() { public void accept(File dir) { return lambda$1(dir); } }); static void lambda$1(File dir) { System.out.println(dir); }
  • 48. Lambda objet constant ? A l'exécution, il y a deux sortes de lambdas Les lambdas qui ne captures pas de variable ou les méthodes référence sur une classe ● path -> path.isDirectory ● File::isDirectory Celles qui capture des variables ou les méthode référence sur des instances ● path -> path.getName().startsWith(args[0) ● System.out::println
  • 49. Compiler vers une classe anonyme ? Et on se récupère tous les problèmes de perf des classes anonymes De plus, si une lambda ne capture pas de variable, on pourrait au moins la crée que une seule fois Mais si on utilise un champ static final, l'initialisation à lieu même si on ne l'utilise pas
  • 50. Invokedynamic to rule them all On veut un mécanisme qui délai l'initialisation au premier accès invokedynamic On veut un mécanisme qui permet d'indiquer que le résultat d'un calcul est constant invokedynamic On veut un pointeur de fonction pour éviter la création des classe anonymes java.lang.invoke.MethodHandle
  • 51. Compiler une lambda iterator.forEach(dir -> System.out.println(dir)); devient iterator.forEach(invokedynamic bootstrap [lambda$1]); static void lambda$1(File dir) { System.out.println(dir); } CallSite bootstrap(Lookup lookup, String name, MethodType type, MethodHandle mh) { if (type.parameterCount() == 0) { return new ConstantCallSite(proxy(mh)); } return ... }
  • 52. Lambda Proxy Instance d'une classe qui contient le pointeur de fonction (MethodHandle) vers la lambda à exécuter Il n'y a besoin que d'une classe proxy par functional interface Le proxy est généré dynamiquement par la VM, pas forcément besoin de bytecode associé
  • 53. Lambda Proxy en pseudo code Le code Java correspondant est à peu près : public class Proxy$Block implements Block { private final @Stable MethodHandle mh; public void accept(Object o) { mh.invokeExact(o); } } invokeExact() est un pointer check + un appel à un pointeur de fonction
  • 54. Optimizations lors de l'appel Avoir 1 seul classe pour 1 interface permet à la VM de remplacer l'appel à l'interface par le code de la classe (Class Hierarchy Analysis) interface Iterator<T> { ... public default void forEach(Block<? super T> block) { while(hasNext()) { block.accept(it.next()); } } } ici, block est toujours une instance de Proxy$Block
  • 55. Optimizations lors de l'appel Si un objet constant dans une boucle, il est sortie de la boucle interface Iterator<T> { ... public default void forEach(Block<? super T> block) { while(hasNext()) { mh.invokeExact(it.next()); } } } Dans le cas d'un method handle, il faut inliner le code référencé par le pointer de fonction (fairy tale mode)
  • 56. dans le monde merveilleux des licornes On guarde la boucle avec un test sur le method handle (comme pour l'On Stack Replacement) interface Iterator<T> { ... public default void forEach(Block<? super T> block) { if (block.mh == lambda$1) { while(hasNext()) { System.out.println(it.next()); } } else deopt(); } } et comme block est pris en paramètre, l'idée est de spécialiser le code à l'endroit de l'appel ce qui permet de ne pas faire le test
  • 57. Le léger hic Le code de la VM qui crée le lambda proxy et qui l'optimise est pas prêt Le plan est prêt depuis longtemps, c'est la réalisation qui prend du temps On doit quand même livrer un truc pour le JDK8 Solution temporaire: la méthode de bootstrap génère une classe anonyme dynamiquement en utilisant ASM On implantera les lambda proxies dans une update du jdk8
  • 58. En résumé La première version des lambdas sera pas la plus optimisée L'API dans java.util doit être fini pour fin janvier La spec de l'inférence pas fini même si ça se précise Bref on est grâve à la bourre
  • 59. Si vous avez du temps libre et même si vous n'en avez pas ! Downloader la dernière version du jdk8 avec les lambdas http://jdk8.java.net/lambda/ Tester l'API, jouer avec, remonter tous les bugs lambda-dev@openjdk.java.net