Est-il sûr d’utiliser -XX: -UseSplitVerifier?

Il existe des problèmes de compatibilité connus avec le code compilé JDK7 utilisant l’instrumentation. Comme pour http://www.oracle.com/technetwork/java/javase/compatibility-417013.html

Les classfiles avec le numéro de version 51 sont vérifiés exclusivement à l’aide du vérificateur de vérification de type. Par conséquent, les méthodes doivent avoir des atsortingbuts StackMapTable, le cas échéant. Pour les classfiles avec la version 50, la machine virtuelle Java Hotspot basculerait (et continuerait) à basculer vers le vérificateur d’inférence de type si les stackmaps du fichier étaient manquants ou incorrects. Ce comportement de basculement ne se produit pas pour les fichiers de classe avec la version 51 (la version par défaut pour Java SE 7). Tout outil modifiant le bytecode dans un fichier de classe version 51 doit être sûr de mettre à jour les informations de stackmap pour qu’elles soient cohérentes avec le bytecode afin de réussir la vérification.

La solution consiste à utiliser -XX:-UseSplitVerifier comme résumé ici: https://community.oracle.com/blogs/fabriziogiudici/2012/05/07/understanding-subtle-new-behaviours-jdk-7

Comment est-ce sécuritaire? Je suppose qu’Oracle a mis cette vérification en ligne pour une raison. Si je ne l’utilise pas, je risque peut-être d’autres problèmes.

Quelles peuvent être les conséquences de l’utilisation de -XX:-UseSplitVerifier ?

Merci,

Piotr.

En bref, c’est parfaitement sûr.

Depuis Java 6, le compilateur Oracle a créé des fichiers de classe avec un StackMapTable. L’idée de base est que le compilateur peut spécifier explicitement le type d’object, au lieu de le faire. Cela accélère le temps d’exécution, en échange de temps supplémentaire pendant la compilation et d’une certaine complexité dans le fichier de classe compilé (StackMapTable).

A titre expérimental, il n’était pas activé par défaut dans le compilateur Java 6. Le moteur d’exécution vérifie par défaut le type d’object lui-même si aucun StackMapTable n’existe.

Jusqu’à Java 7. Oracle l’a rendu obligatoire: le compilateur les génère et le moteur d’exécution les vérifie. Il utilise toujours l’ancien vérificateur si le StackMapTable n’est pas là … mais uniquement sur les fichiers de classe de Java 6 ou version antérieure (version 50). Les fichiers de classe Java 7 (version 51) sont requirejs pour utiliser le StackMapTable, ce qui fait que le runtime ne les réduira pas de la même manière.

Cela n’est un problème que si vos fichiers de classe ont été générés sans StackMapTable. Par exemple, si vous avez utilisé une machine virtuelle Java non Oracle. Ou si vous avez joué avec le bytecode par la suite – comme si vous utilisiez l’instrument pour l’utiliser avec un débogueur, un optimiseur ou un parsingur de couverture de code.

Mais vous pouvez le contourner! La machine virtuelle Java d’Oracle fournit le paramètre -XX: + UseSplitVerifier pour forcer le moteur d’exécution à revenir à l’ancien vérificateur de type. Il ne se soucie pas de StackMapTable.

En pratique, l’optimisation attendue de la vitesse et de l’efficacité de l’exécution ne s’est pas concrétisée: s’il existe, cela n’a pas été suffisant pour quiconque. Comme le nouveau vérificateur de types ne fournit aucune nouvelle fonctionnalité (juste l’optimisation), il est parfaitement sûr de le désactiver.

L’explication d’Oracle se trouve à l’ adresse http://www.oracle.com/technetwork/java/javase/compatibility-417013.html si vous recherchez JSR 202.

Oui, c’est sûr. Comme le dit Judebert, cela ralentit légèrement le chargement des classes.

Pour append un peu plus d’informations: Qu’est-ce qu’une table StackMap? Eh bien, le vérificateur Bytecode doit faire deux passages sur le code dans le fichier de classe pour valider les types de données appropriés qui sont transmis et utilisés. La première, qui est la plus lente, parsing en continu toutes les twigs du code pour voir quel type de données pourrait se trouver sur la stack à chaque instruction de bytecode. La seconde passe examine chaque instruction pour voir si elle peut fonctionner correctement sur tous ces types.

Voici la clé: le compilateur dispose déjà de toutes les informations que la première passe génère – ainsi (en Java 6 et 7) il les stocke dans une table StackMap du fichier de classe.

Cela accélère le chargement des classes car le chargeur de classes n’a pas à effectuer ce premier passage. C’est pourquoi on l’appelle un vérificateur de partage, car le travail est divisé entre le compilateur et le mécanisme de chargement à l’exécution. Lorsque vous utilisez l’option -XX: -UseSplitVerifier, vous indiquez à Java de faire les deux passes au moment du chargement de la classe (et d’ignorer toute table StackMap). De nombreux produits (tels que les profileurs modifiant le bytecode au moment du chargement) ne connaissaient pas la table StackMap initialement. Par conséquent, lorsqu’ils ont modifié les classes au moment du chargement, la table StackMap du compilateur était obsolète et entraînait des erreurs.

Pour résumer, l’option -XX: -UseSplitVerifier ralentit le chargement de la classe. Cela n’affecte pas la sécurité, les performances d’exécution ou les fonctionnalités.

Des frameworks de cartes empilables ont été ajoutés à Java 7 et «prashant» affirme que l’idée est erronée et propose que les développeurs utilisent toujours le drapeau -XX:-UseSplitVerifier pour éviter de les utiliser.

En savoir plus: Java 7 Bytecode Verifier: énorme retour en arrière pour la JVM