Utilisant maven pour construire nos projets, la migration est simple et consiste à configurer le plugin compiler pour qu’il soit capable de trouver votre jdk7.
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>2.5.1</version> <configuration> <source>1.7</source> <target>1.7</target> <verbose>true</verbose> <compilerArguments> <verbose /> <encoding>cp1252</encoding> </compilerArguments> <executable>"${env.JAVA_HOME_7}/bin/javac"</executable> </configuration> </plugin>
Problème de compatibilité ?
A chaque nouvelle version du JDK, le bytecode peut évoluer. Le fichier class contient un numéro de version (majeur.mineur) qui permet d’identifier cette dernière. Pour le JDK7 le numéro de version est 51.0.
Si vous essayez d’exécuter du code Java7 sur un jre6 vous obtiendrez par exemple le message
java.lang.UnsupportedClassVersionError: com/boiron/gcl/presentation/Lanceur : Unsupported major.minor version 51.0
Dans mon cas j’ai été étonné de tomber sur cette exception au lancement du runtime
Caused by: java.lang.VerifyError: Expecting a stackmap frame at branch target 15 in method com.boiron.gcl.client.domain.ModaliteFacturationHisto.$javassist_write_modeReglement(Ljava/lang/String;)V at offset 6 at java.lang.Class.getDeclaredMethods0(Native Method)
La JVM fait plusieurs contrôles d’un fichier class au moment de son chargement. A partir de Java 7, le mode de vérification se fait maintenant par type checking pour tout fichier dont le numéro de version est >=50.0 (Java>=6) et fait par de l’inférence de type pour les autres.
Le contrôle évolue pour prendre en compte les nouvelles pratiques. En effet il y a de plus en plus d’outils qui manipulent le bytecode et il est demandé à ces outils d’aller plus loin dans les contrôles et notamment de mettre à jour la stackmap frame. L’exception générée dans le cas où le fichier ne passe le type checking est celle que je vous ai présenté plus haut. Cette exception est déclenchée même si le bytecode passe la vérification par inférence de type.
Un hack temporaire
Pour laisser aux développeurs le temps d’adapter leurs outils, la vérification par type checking peut être désactivée. Mais il faut savoir que ceci est temporaire.
Si vous utilisez l’option -XX:-UseSplitVerifier vous désactiver cette nouvelle méthode et rester sur de la vérification par inférence
Cette option sera dépréciée dans la version 8 du JDK (voir la jira) et certainement supprimée plus tard.
Si je reviens à mon exception, mon problème vient de javassist que j’utilise avec Hibernate pour instrumenter le bytecode. Si vous êtes dans le même cas vos choix seront limités car il faut les toutes dernières versions. Vous devrez utiliser l’option pour désactiver la vérification par type checking. Les tests unitaires peuvent aussi poser problème et si vous utiliser maven configurez le plugin surefire de cette manière
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <configuration> <jvm>${env.JAVA_HOME_7}/bin/java</jvm> <argLine>-XX:-UseSplitVerifier</argLine> <systemPropertyVariables> <log4j.configuration>log4j.xml</log4j.configuration> </systemPropertyVariables> </configuration> </plugin>
Références
Spécification de la JVM v7
Problème de compatibilté entre la version 7 et 6 du JDK
Aucun commentaire:
Enregistrer un commentaire
Remarque : Seul un membre de ce blog est autorisé à enregistrer un commentaire.