web-dev-qa-db-fra.com

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

Il existe des problèmes de compatibilité connus avec le code compilé JDK7 utilisant l'instrumentation. Quant à http://www.Oracle.com/technetwork/Java/javase/compatibility-417013.html

Les fichiers de classe avec le numéro de version 51 sont exclusivement vérifiés à l'aide du vérificateur de vérification de type, et donc les méthodes doivent avoir des attributs StackMapTable lorsque cela est approprié. Pour les fichiers de classe avec la version 50, la machine virtuelle Java Hotspot basculerait (et continue de basculer) vers le vérificateur d'inférence de type si les cartes de pile dans le fichier étaient manquantes ou incorrectes. 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 qui modifie le bytecode dans un fichier de classe de la version 51 doit être sûr de mettre à jour les informations de la carte de pile pour être cohérent avec le bytecode afin de passer 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

Est-ce sûr? Je suppose qu'Oracle a mis ce chèque pour une raison. Si je ne l'utilise pas, je risque de risquer d'autres problèmes.

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

Merci,

Piotr.

48
ThamP

Bref, c'est parfaitement sûr.

Depuis Java 6, le compilateur d'Oracle a créé des fichiers de classe avec un StackMapTable. L'idée de base est que le compilateur peut spécifier explicitement quel est le type d'un objet, au lieu de le faire exécuter par le runtime. fournit une petite accélération dans l'exécution, en échange d'un temps supplémentaire pendant la compilation et d'une certaine complexité dans le fichier de classe compilé (le StackMapTable susmentionné).

En tant que fonctionnalité expérimentale, elle n'était pas activée par défaut dans le compilateur Java 6. Le moteur d'exécution par défaut vérifie les types d'objet lui-même si aucun StackMapTable n'existe.

Jusqu'à Java 7. Oracle l'a rendu obligatoire: le compilateur les génère et le runtime les vérifie. Il utilise toujours l'ancien vérificateur si le StackMapTable n'est pas là ... mais uniquement sur les fichiers de classe à partir de Java 6 ou version antérieure (version 50). Java 7 fichiers de classe (version 51) sont nécessaires pour utiliser le StackMapTable, et donc le runtime ne coupez-les du même jeu.

Ce 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 l'instrumentation pour l'utiliser avec un débogueur, un optimiseur ou un analyseur de couverture de code.

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

Dans la pratique, l'optimisation espérée de la vitesse d'exécution et de l'efficacité ne s'est pas matérialisée: si elle existe, elle n'a suffi à personne de s'en rendre compte. Comme le nouveau vérificateur de type ne fournit pas de nouvelles fonctionnalités (juste l'optimisation), il est parfaitement sûr de le désactiver.

L'explication d'Oracle est à http://www.Oracle.com/technetwork/Java/javase/compatibility-417013.html si vous recherchez JSR 202.

54
Judebert

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

Pour ajouter un peu plus d'informations: Qu'est-ce qu'une table StackMap exactement? Eh bien, le vérificateur Bytecode doit effectuer deux passes 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 passe, qui est la plus lente, analyse le flux de toutes les branches du code pour voir quel type de données pourrait être sur la pile à chaque instruction de bytecode. La deuxième passe examine chaque instruction pour voir si elle peut valablement fonctionner sur tous ces types.

Voici la clé: le compilateur a déjà toutes les informations à portée de main que le premier passage génère - donc (dans Java 6 & 7) il le stocke dans une table StackMap dans le fichier de classe.

Cela accélère le chargement de classe car le chargeur de classe n'a pas à faire cette première passe. C'est pourquoi il est appelé un vérificateur divisé, car le travail est divisé entre le compilateur et le mécanisme de chargement d'exécution. Lorsque vous utilisez l'option -XX: -UseSplitVerifier, vous dites à Java de faire les deux passe au moment du chargement de la classe (et d'ignorer toute table StackMap). De nombreux produits ( comme les profileurs qui modifient le bytecode au moment du chargement) ne connaissaient pas la table StackMap au départ, donc quand ils ont modifié les classes au moment du chargement, la table StackMap du compilateur était obsolète et a provoqué des erreurs.

Donc, pour résumer, l'option -XX: -UseSplitVerifier ralentit le chargement des classes. Il n'affecte pas la sécurité, les performances d'exécution ou les fonctionnalités.

24
Dave C

Des cadres de carte de pile ont été ajoutés dans Java 7 et "prashant" soutient que l'idée est erronée et propose que les développeurs utilisent toujours le -XX:-UseSplitVerifier flag pour éviter de les utiliser.

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

13
user605331