Annotations, Typages et Généricités, l’API Concurrent en Java, tel était le menu de la soirée du 9 juin 2009 au Paris JUG. Avec 24h de retard, un petit retour qui sera plus court que d’habitude.
La soirée s’est déroulée autour de 3 présentations. Philippe Prados d’Atos Origin, qui publie régulièrement dans différents magazines comme PROgrammez.com ou GNU/Linux Magazine France par exemple. Ensuite Denis Ah-Kang d’Atos Origin, Open Source Center. Et enfin Alexandre Bertails d’Atos Origin, qui a la chance de repasser ce soir après la soirée Web Sémantique du 11 mars dernier.
Les Annotations et la JSR-269
Durant la première partie, Philippe Prados nous a présenté les Annotations en Java 5, puis ensuite la JSR-269 qui permet de créer des Annotations utilisées lors de la compilation du code source vers le bytecode. La JSR-269 « Pluggable Annotation Processing API » est donc une spécification d’annotation qui permet de déclarer des annotations au niveau de la source. Elle ne date pas d’aujourd’hui puisqu’elle est disponible depuis 2006. C’est peut-être inquiétant d’ailleurs de voir que les articles autour de cette spécification ne sont pas très frais comme sur Developpez.com ou TheServerSide.
La présentation était très complète, quoiqu’un peu rapide dans le rythme. Ce que j’ai retenu : ce système d’annotation permet d’ajouter du code comme une interface à une classe existante, il permet en quelques sortes d’écrire des ressources comme un fichier Web.xml automatiquement. C’est donc intéressant dans un premier temps pour la génération de ressources. J’ai ensuite vu une démonstration de génération de code. Difficile de trouver un use-case, de l’aveu même du présentateur. Mais intéressant… pour se dire que cela ressemble un peu trop à de la science-fiction.
Je suis resté plus dubitatif durant la partie sur le pattern Decorator. L’intérêt d’un Dynamix Proxy en Java est justement d’avoir une classe qui implémente des interfaces connues à l’exécution, principe utilisé depuis longtemps en Java… Il faudra que je rédige un truc là-dessus.
A propos des patterns justement, l’un des 23 patterns du Gang Of Four s’appelle Proxy ou Procuration en Français, il appartient à la catégorie patterns structuraux. Le principe de ce pattern est d’envelopper un Objet dans un mandataire et d’utiliser ce mandataire à la place de l’objet original.
Deuxième présentation : java.util.concurrent
Ensuite la deuxième présentation était sur l’api java.util.concurrent. Présenté par Denis Ah-Kang d’Atos Origin. Dans un premier temps, après avoir rappelé les bases de la synchronisation et des problèmes connus en Java, Denis demande la signification de « volatile » à la salle. Grand silence, quelques mains courageuses se lèvent, les réponses arrivent péniblement… ce qui montre aussi que l’on parle d’un mot clé très peu utilisé en Java.
Est-ce que « volatile » n’est pas un mot clé pour indiquer que cette variable est un poulet ? non ce n’est pas cela, dommage José 😉 Rien à voir avec la grippe aviaire.
La bonne réponse : le mot clé volatile est un marqueur pour indiquer à la JVM que la variable sera accédée par plusieurs Threads. Par conséquence, la variable ne sera jamais caché dans le cache de chaque Thread, la valeur sera lue à chaque fois par les différentes Threads en mémoire. Et c’est là que l’on apprend que les Threads ont des caches de variables…
Plus intéressant, lorsque vous mettez ce mot clé « volatile », l’accès à la variable sera effectué dans un bloc synchronized utilisant l’instance. Un simple « synchronized(this) » finalement, comme on le voit lorsque l’on décompile le code avec javap (et pas javac).
Sinon quoi d’autre ? volatile s’utilise sur des objets mais aussi sur des variables simples type « int ». Cela permet de rendre atomique par exemple l’incrémentation d’une variable de type « int i++ », car sachez-le, par défaut un simple « i++ » n’est pas atomique en Java…
Denis montre ensuite justement ce cas précis avec un bout de code simple, où l’on constate que les accès concurrents ne s’effectuent pas correctement.
Dans la suite de la présentation il aborde plus le côté API, la JSR-166 de Doug Lea entre autre. Je vous conseille de lire tranquillement sur internet, sur les différents blogs que vous rencontrez, il y a toujours quelques trucs à savoir. On oublie pas les 12 classes du package « java.util.concurrent.atomic » par exemple, qui vous éviterons des soucis de synchronisation par exemple. La documentation sur ce sujet se trouve dans la javadoc de Java 5.
Sinon pour la suite, je vous renvoie au meilleur article du monde entier cité par les plus grands de ce monde, soyons modeste, hop je suis comme cela : Brillez en société avec votre BlockingDeque. Si Asterix et Obelix n’ont pas lu cet article, ils pourront optimiser leur campagne de chasse.
La pause buffet
Le temps de prendre un peu de quoi boire, je croise pas mal de monde. A chaque fois, ces buffets sont trop courts. En fait nous devrions faire des buffets de 3h et une pause avec une présentation de 30 minutes. Qu’en pensez-vous ?
Et si par exemple j’avais envie de ne faire que la présentation #1 pour ensuite discuter et boire un coup avec d’autres personnes ? Ah l’idée ne vient pas de moi, et cela permettrait même de faire entrer les gens qui ne souhaitent assister QUE à la deuxième présentation… Oh là je mets le souk là.
Dites, vous en pensez quoi vous ?
Vous pouvez laisser un commentaire en dessous ?
Je sais qu’il faut s’inscrire sur le Touilleur Express pour soumettre un commentaire. Je fais cela pour deux raisons : éviter le spam bien entendu, et ensuite revendre 3000$ votre adresse à tout le monde. Certaines adresses ne valent pas un clou sois-dit en passant.
Dernière présentation sur le Typage et la Généricité
J’ai du boulot… Alexandre a fait une grosse présentation, une qui demande 3 heures de travail pour restituer le tout. Je vais faire plus court. Alexandre part d’un message passé par Emmanuel Bernard sur Twitter, en galère avec les templates et la généricité. Exemple que je n’ai pas sous les yeux bien entendu.
Petit rappel d’Alexandre, la différence entre le Typage Statique et le typage Dynamique, entre le Type fort et le typage faible, entre l’Heritage et le Sous-Typage, afin de suivre la suite.
Je retiens tout d’abord que bien que Java soit plutôt « Typage Statique », le bytecode généré est du « Typage Dynamique ». Lorsque les Génériques ont été ajouté à la version 5 de Java, le choix de conserver une compatibilité au niveau du bytecode entraîne des choses pas très belles dans le bytecode.
Pour illustrer ce propos, je vais tenter de refaire l’exemple d’Alexandre (je sens que je suis encore parti pour écrire un billet de 10 pages)
Voici tout d’abord un bout de code Java 1.4 simple
import java.util.*; public class Test { public static void main(String args[]) throws Exception { List l=new ArrayList(); l.add(new Integer(123)); Integer i=(Integer)l.get(0); // notez ici le cast explicite System.out.println(i); // affiche 123 } }
Je compile puis je décompile ma classe :
javac Test.java javap -c Test
Voici le byte code généré :
Compiled from "Test.java" public class Test extends java.lang.Object{ public Test(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."":()V 4: return public static void main(java.lang.String[]) throws java.lang.Exception; Code: 0: new #2; //class java/util/ArrayList 3: dup 4: invokespecial #3; //Method java/util/ArrayList." ":()V 7: astore_1 8: aload_1 9: new #4; //class java/lang/Integer 12: dup 13: bipush 123 15: invokespecial #5; //Method java/lang/Integer." ":(I)V 18: invokeinterface #6, 2; //InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z 23: pop 24: aload_1 25: iconst_0 26: invokeinterface #7, 2; //InterfaceMethod java/util/List.get:(I)Ljava/lang/Object; 31: checkcast #4; //class java/lang/Integer 34: astore_2 35: getstatic #8; //Field java/lang/System.out:Ljava/io/PrintStream; 38: aload_2 39: invokevirtual #9; //Method java/io/PrintStream.println:(Ljava/lang/Object;)V 42: return }
On voit notre constructeur par défaut. Le plus intéressant (alexandre tu me corriges si je me trompe) c’est la ligne 18 lorsque l’on ajoute l’Integer dans la liste. L’ajout dans la liste de l’élément de type Integer s’effectue avec l’appel à l’interface de List, qui ici ne sait pas qu’il s’agit d’un Integer. Tout va bien.
A la ligne 26 on dépile l’élément et à la ligne 31 on s’assure que le type retourné est bien un Integer.
Voyons maintenant la version Java 5 du même code, avec les génériques. Je change la valeur stockée pour enregistrer 456 au lieu de 123, pour le reste vous connaissez.
Le code Java tout d’abord
import java.util.*; public class Test { public static void main(String args[]) throws Exception { List<Integer$gt; l=new ArrayList<Integer>(); l.add(new Integer(456)); Integer i=l.get(0); // plus besoin de cast System.out.println(i); } }
Voyons si vous suviez… regardez ce code et dîtes-moi ce que vous en pensez :
Compiled from "Test.java" public class Test extends java.lang.Object{ public Test(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."":()V 4: return public static void main(java.lang.String[]) throws java.lang.Exception; Code: 0: new #2; //class java/util/ArrayList 3: dup 4: invokespecial #3; //Method java/util/ArrayList." ":()V 7: astore_1 8: aload_1 9: new #4; //class java/lang/Integer 12: dup 13: sipush 456 16: invokespecial #5; //Method java/lang/Integer." ":(I)V 19: invokeinterface #6, 2; //InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z 24: pop 25: aload_1 26: iconst_0 27: invokeinterface #7, 2; //InterfaceMethod java/util/List.get:(I)Ljava/lang/Object; 32: checkcast #4; //class java/lang/Integer 35: astore_2 36: getstatic #8; //Field java/lang/System.out:Ljava/io/PrintStream; 39: aload_2 40: invokevirtual #9; //Method java/io/PrintStream.println:(Ljava/lang/Object;)V 43: return }
A part un sipush au lieu d’un bipush ligne 13… c’est la même chose.
Java 5 et 6 ayant gardé une compatibilité descendante au nivea du bytecode, les Generiques ne sont pas exprimés dans le bytecode. Nous retrouvons simplement un « checkcast » ligne 32 afin de vérifier l’object retourné. Et ce, parce que les types des arguments d’une méthode Java sont invariants. C’est pour cette raison qu’à la ligne 19 l’ajout dans la liste est générique, on ajoute un Object dans la liste.
Ce que l’on retiendra donc : les génériques sont là pour nous aider lors de l’écriture du code, mais au final dans le bytecode, on retrouve les mécanismes de cast pour vérifier le type. Intéressant non ?
Alexandre aborde ensuite des sujets comme la JSR-303 « Bean Validation » qui souhaite ajouter des validateurs sur les POJO. Par exemple, une annotation @NonNull. J’en ai parlé il y a un an exactement sur le Touilleur Express dans cet article si cela vous intéresse.
Avec ce que vous avez lu plus haut, et je pense qu’Emmanuel Bernard nous expliquerait cela certainement mieux, comment sera implémenter ce @NonNull dans le bytecode ?
Je pense simplement avec du code que nous aurions écrit autrement, avec un if(objArg!=null)… L’implémentation de ces annotations utilise-t-elle la JSR-269 que nous avons vu au début ? Ou utilise-t-elle un moteur d’enrichissement du bytecode comme ASM ou BCEL ?
Lisez les articles très intéressants sur le blog d’Emmanuel Bernard :
– Constraint composition proposal in Bean Validation (JSR 303)
– Bean Validation (JSR 303) hits proposed final draft
La conclusion d’Alexandre est que les quelques soucis de Typages dans Java font que des langages dynamiques comme Groovy (qui génère du bytecode java) ont le vent en poupe. Alexandre est un fan de Scala, où les problèmes de typages sont résolus dans le langage et où le typage statique est utilisé à sa juste valeur.
Je m’arrête là car il est impossible de tout restituer ici sur le blog, vous verrez la présentation en vidéo dès que nous aurons terminé le montage.
La conclusion de la soirée
Lors de la troisième mi-temps au Falstaff, nous avons finalement pas mal discuté entre les personnes qui font parties de l’organisation du Paris JUG. Je vous laisse quelques photos et aussi quelques vidéos. Spéciale dédicace pour Denis et ses problèmes de « Queue ».
Pour terminer quelques photos et une petite vidéo faite à l’arrache :
A bientôt
PS: dédicace à ma mon épouse qui rentre de l’assemblée générale des copropriétaires pendant que je blogue…
0 no like
Merci pour ce compte rendu… j’aurais aimé être de la partie…
Pour les generics:
je recommande à tous les lecteurs (et lectrices ?) du touilleur de lire et relire le chapitre suivant
http://java.sun.com/docs/books/effective/generics.pdf
(extrait gratuit du bouquin « Effective Java 2d Edition » de Joshua Bloch)
Pour le JUG:
Je trouve que l’idée de permettre plus d’échanges sans forcément veiller jusqu’à 3h du mat’ au Falstaf est très bonne 😉
A creuser donc.