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

Java 8 Lambda Expressions & Streams
Java 8 Lambda Expressions & StreamsJava 8 Lambda Expressions & Streams
Java 8 Lambda Expressions & StreamsNewCircle Training
 
PUC SE Day 2019 - SpringBoot
PUC SE Day 2019 - SpringBootPUC SE Day 2019 - SpringBoot
PUC SE Day 2019 - SpringBootJosué Neis
 
JavaScript Event Loop
JavaScript Event LoopJavaScript Event Loop
JavaScript Event LoopDesignveloper
 
Spring boot - an introduction
Spring boot - an introductionSpring boot - an introduction
Spring boot - an introductionJonathan Holloway
 
Java Spring framework, Dependency Injection, DI, IoC, Inversion of Control
Java Spring framework, Dependency Injection, DI, IoC, Inversion of ControlJava Spring framework, Dependency Injection, DI, IoC, Inversion of Control
Java Spring framework, Dependency Injection, DI, IoC, Inversion of ControlArjun Thakur
 
Java 8-streams-collectors-patterns
Java 8-streams-collectors-patternsJava 8-streams-collectors-patterns
Java 8-streams-collectors-patternsJosé Paumard
 
Java 9 Module System Introduction
Java 9 Module System IntroductionJava 9 Module System Introduction
Java 9 Module System IntroductionDan Stine
 
Introduction à spring boot
Introduction à spring bootIntroduction à spring boot
Introduction à spring bootAntoine Rey
 
JVM Mechanics: When Does the JVM JIT & Deoptimize?
JVM Mechanics: When Does the JVM JIT & Deoptimize?JVM Mechanics: When Does the JVM JIT & Deoptimize?
JVM Mechanics: When Does the JVM JIT & Deoptimize?Doug Hawkins
 
Spring Framework - MVC
Spring Framework - MVCSpring Framework - MVC
Spring Framework - MVCDzmitry Naskou
 
Service Worker Presentation
Service Worker PresentationService Worker Presentation
Service Worker PresentationKyle Dorman
 
FHIR Server 安裝與使用
FHIR Server 安裝與使用FHIR Server 安裝與使用
FHIR Server 安裝與使用Lorex L. Yang
 
Spring boot
Spring bootSpring boot
Spring bootsdeeg
 

Tendances (20)

Java 8 Lambda Expressions & Streams
Java 8 Lambda Expressions & StreamsJava 8 Lambda Expressions & Streams
Java 8 Lambda Expressions & Streams
 
Drools
DroolsDrools
Drools
 
PUC SE Day 2019 - SpringBoot
PUC SE Day 2019 - SpringBootPUC SE Day 2019 - SpringBoot
PUC SE Day 2019 - SpringBoot
 
JavaScript Event Loop
JavaScript Event LoopJavaScript Event Loop
JavaScript Event Loop
 
Spring boot - an introduction
Spring boot - an introductionSpring boot - an introduction
Spring boot - an introduction
 
Java Spring framework, Dependency Injection, DI, IoC, Inversion of Control
Java Spring framework, Dependency Injection, DI, IoC, Inversion of ControlJava Spring framework, Dependency Injection, DI, IoC, Inversion of Control
Java Spring framework, Dependency Injection, DI, IoC, Inversion of Control
 
Java 8-streams-collectors-patterns
Java 8-streams-collectors-patternsJava 8-streams-collectors-patterns
Java 8-streams-collectors-patterns
 
NodeJS for Beginner
NodeJS for BeginnerNodeJS for Beginner
NodeJS for Beginner
 
Spring boot
Spring bootSpring boot
Spring boot
 
Java 9 Module System Introduction
Java 9 Module System IntroductionJava 9 Module System Introduction
Java 9 Module System Introduction
 
Java 11 to 17 : What's new !?
Java 11 to 17 : What's new !?Java 11 to 17 : What's new !?
Java 11 to 17 : What's new !?
 
Introduction à spring boot
Introduction à spring bootIntroduction à spring boot
Introduction à spring boot
 
Spring Boot
Spring BootSpring Boot
Spring Boot
 
JVM Mechanics: When Does the JVM JIT & Deoptimize?
JVM Mechanics: When Does the JVM JIT & Deoptimize?JVM Mechanics: When Does the JVM JIT & Deoptimize?
JVM Mechanics: When Does the JVM JIT & Deoptimize?
 
Java 8 streams
Java 8 streamsJava 8 streams
Java 8 streams
 
Java 8 - DateTime
Java 8 - DateTimeJava 8 - DateTime
Java 8 - DateTime
 
Spring Framework - MVC
Spring Framework - MVCSpring Framework - MVC
Spring Framework - MVC
 
Service Worker Presentation
Service Worker PresentationService Worker Presentation
Service Worker Presentation
 
FHIR Server 安裝與使用
FHIR Server 安裝與使用FHIR Server 安裝與使用
FHIR Server 安裝與使用
 
Spring boot
Spring bootSpring boot
Spring boot
 

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
 
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, 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
 
Accessibilite numérique : où en est-on ? webinar FFFOD 151207
Accessibilite numérique : où en est-on ? webinar FFFOD 151207Accessibilite numérique : où en est-on ? webinar FFFOD 151207
Accessibilite numérique : où en est-on ? webinar FFFOD 151207FFFOD
 

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
 
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, 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
 
Accessibilite numérique : où en est-on ? webinar FFFOD 151207
Accessibilite numérique : où en est-on ? webinar FFFOD 151207Accessibilite numérique : où en est-on ? webinar FFFOD 151207
Accessibilite numérique : où en est-on ? webinar FFFOD 151207
 
La democracia como religión
La democracia como religión La democracia como religión
La democracia como religión
 

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