séquence
Cet article étudie principalement certaines précautions pour la migration vers Java9.
Types de migration
1. Le code n'est pas modulaire, migrez d'abord vers JDK9 pour utiliser l'API de JDK9
2. Le code est également migré modulaire
Certaines choses à noter
Cours illisibles
Par exemple, Sun.Security.x509 est classé dans le module Java.base dans Java9, mais le module n'exporte pas le package.
Vous pouvez modifier les paramètres des exportations en ajoutant - Add-Exports Java.base / Sun.Security.x509 = All-Named lors de l'exécution
Classe interne
Par exemple, Sun.Misc.unsafe voulait à l'origine utiliser l'équipe Oracle JDK, mais comme ces classes sont trop largement utilisées, Java9 a fait des compromis afin d'être en rétrocassemblée, mais n'a classé ces classes que dans le module JDK.UnSupported et n'a pas limité leur liaison.
➜ ~ Java -d jdk.unsupportedjdk.unsupported@9exports com.sun.nio.fileexports sun.miscexports sun.reflectquires java.base mandatens sun.miscopens sun.reflect
Classe supprimée
Java9 supprimé Sun.Misc.base64Encoder, dans ce cas, vous ne pouvez utiliser que d'autres API à la place, comme Java.util.base64
CLASSPATH VS PATH MODULE
Java9 a introduit un système de modules, et son propre JDK a également été modularisé et le chemin de module a été introduit pour Block ClassPath. C'est-à-dire que le chemin de module est préféré dans Java9. Après tout, JDK lui-même est modulaire. Si l'application elle-même n'est pas modulaire, Java9 est implicitement modularisé par des modules sans nom et des mécanismes de modules automatiques. Bien sûr, ClassPath peut continuer à être utilisé sur Java9, comme l'utilisation du chemin de module.
Un pot sans modularité sera classé comme modules sans nom dans ClassPath; Dans le chemin de module, il sera automatiquement créé en tant que modules automatiques (un module automatique déclarera que la transitif dépend de tous les modules nommés et sans nom, puis exportera son propre package)
Un nom de package ne peut pas apparaître dans plusieurs modules (packages Split)
Étant donné que les exportations peuvent être spécifiées vers d'autres modules dans des modules, si plusieurs modules exportent le même nom de package, cela entraînera une confusion. Surtout s'il existe d'autres bibliothèques de classe qui nécessitent ces deux modules en même temps, vous ne savez pas quel module doit être référencé.
Dépendances transitives
Si les paramètres d'interface ou le type de retour d'un module utilisent les classes d'autres modules, il est recommandé de nécessiter des modules transitifs dont il dépend.
Faites attention aux dépendances circulaires
Lors de la conception de modules, déterminez s'il y aura autant que possible les dépendances circulaires. Si c'est le cas, vous devez les repenser.
Utiliser des services pour implémenter des dépendances facultatives
Les services conviennent particulièrement au découplage des dépendances des appelants et des classes de mise en œuvre. Si l'interface dispose de plusieurs classes d'implémentation, l'appelant n'a pas besoin d'exiger toutes les classes d'implémentation, mais ne nécessite que l'interface requise et utilise le type de services pour charger les instances de la classe d'implémentation. Le découplage est obtenu en ajoutant dynamiquement des modules d'implémentation dans le chemin de module.
Gestion de la version du module
module-info.java ne prend pas en charge la déclaration des numéros de version, mais lors de la création de packages JAR, vous pouvez les définir --module-Version. Cependant, lorsque le système de module recherche des modules, il utilise toujours le nom du module pour rechercher (s'il existe plusieurs modules en double dans le chemin de module, le système de module saura utiliser le premier trouvé et ignorer automatiquement le module suivant avec le même nom). Le problème de dépendance de la version n'est pas dans le cadre de la solution du système du module et est laissé aux outils de gestion de dépendance tels que Maven pour gérer.
Accès aux ressources du module
Après modularisation, le fichier de ressources est également protégé et le module ne peut accéder qu'au fichier de ressources du module lui-même. Si un accès croisé du module est requis, vous devez également utiliser le modulayer pour trouver le module cible, puis appeler le module cible pour charger le fichier de ressources du module.
Utilisation de la réflexion
Cela implique le problème de réflexion profonde. La réflexion dite profonde est d'appeler l'élément non public d'une classe par la réflexion. Les exportations de module-info.java déclarent que le package permet uniquement la classe à laquelle le package appartient directement permet d'accéder à son élément public et n'autorise pas les appels de réflexion aux éléments non publics.
La réflexion doit être autorisée par les déclarations spéciales dans le système des modules (en utilisant des déclarations d'ouvre pour permettre une réflexion profonde), ce qui conduit à de nombreuses bibliothèques de classe qui utilisent une réflexion telle que Spring, qui nécessitent une configuration supplémentaire pour être migrée vers Java9. Il y a deux solutions: l'une consiste à ouvrir le nom du package aux modules qui nécessitent une réflexion, tels que Spring.beans, etc.; L'autre consiste à ouvrir directement l'intégralité du module.
Le permis par défaut --Lelegal-Access =, et ce paramètre ne s'applique qu'aux packages avant Java9 qui ne sont pas autorisés à accéder à Java9, et ne s'applique pas à de nouveaux packages qui ne sont pas autorisés à accéder à Java9. (Il est recommandé de se définir pour nier lors de la migration vers un système modulaire)
Cependant, dans le système des modules, les noms de packages sont différents et il n'y a pas de relation d'héritage. Par exemple, com.service.func1 et com.service.func2 sont différents packages. Vous ne pouvez pas simplement ouvrir le service, mais vous devez les spécifier séparément, ce qui conduit à plus de packages qui nécessitent une ouverture. Par conséquent, l'ouverture de l'ensemble du module peut être plus facile à utiliser, mais c'est aussi une approche relativement rude.La méthode ci-dessus consiste à apporter des modifications dans le module d'origine-info.java. Une autre méthode consiste à modifier la relation d'origine via la commande spécifiée lors de l'exécution de Java ou Javac. Par exemple
Java ... --Add-ouvre-module source / source-package = module cible
Si vous avez besoin d'exporter vers des modules sans nom, le module cible est tous non nommé
Bien sûr, s'il s'agit d'un nouveau système, il n'est pas recommandé d'utiliser la réflexion. Méthode Handles et VarHandles peuvent être utilisés.
FAQ et mesures
ClassNotFoundException / NoclassdeffoundError
Par exemple, javax.xml.bind.jaxbException, JaxB a été classé dans le module java.xml.bind et est ajouté après la dénomination de Java.
--Add-modules java.xml.bind
Si vous souhaitez économiser des ennuis, ajoutez $ java_home et toute la bibliothèque tierce au chemin de module, puis faites
- Add-Modules All-Module Cheat
Accès réfléchissant illégal par xxx à la méthode java.lang.classloader.defineclass
La réflexion provoque, car l'ancien système n'a pas de module-info, ajouter des paramètres à la dénomination Java et le modifier.
--Add-ouvre Java.Base / Java.lang = All-Unnamed
Déterminer le module de dépendance
Analyse via IDE ou JDEPS
JDEPS - CLASS-CLASS-PATH 'Classes / Lib / *' -Recursive -Summary App.jar
JDEPS n'est qu'une analyse de code statique. S'il y a une classe qui utilise la réflexion, vous ne pouvez pas l'analyser. Vous devez l'exiger manuellement. Si la dépendance est facultative, vous pouvez nécessiter une statique.
Problèmes de lisibilité pour les tests unitaires de module
Si un module est utilisé pour les tests unitaires, le module de test unitaire peut se voir accorder des capacités de lisibilité et de réflexion du module cible via - ADD-EXPORTS OU - ADD-OUVERTS À RUNEUX. De plus, en raison des problèmes de packages divisés, le nom du package de la classe de test unitaire ne peut pas être dupliqué avec le nom du package du module cible. Il s'avère que le test du projet Maven
résumé
Vous pouvez passer à Java9 en deux étapes. Tout d'abord, vous n'êtes pas modulaire en premier, vous ne fonctionz qu'avec JDK9 d'abord; alors vous êtes modulaire.