web-dev-qa-db-fra.com

Comment explorer quelles classes sont chargées à partir de quels JAR?

Existe-t-il un moyen de déterminer quelles classes sont chargées à partir de quels fichiers jar au moment de l'exécution?

Je suis sûr que nous avons tous été dans l'enfer JAR avant. J'ai souvent rencontré ce problème dans la résolution de problèmes ClassNotFoundExceptions et NoClassDefFoundErrors sur des projets. Je voudrais éviter de trouver toutes les occurrences d'une classe dans des bocaux et d'utiliser un processus d'élimination sur le code, ce qui permettrait à un CNFE de trouver le coupable.

Des outils de profilage ou de gestion vous fourniront-ils ce type d'informations?

Ce problème est super énervant simplement parce que nous devrions avoir cette information au moment où la classe est chargée. Il doit y avoir un moyen d'y arriver, de l'enregistrer et de le trouver, mais je ne connais rien qui puisse faire cela, n'est-ce pas?

Je sais que OSGi et les bundles/modules versionnés ont pour objectif de rendre ce problème non lié à un problème ... mais cela ne semble pas disparaître de si tôt. :)

REMARQUE: J'ai trouvé cette question est un sous-ensemble de ma question relative aux classes chargées à partir de fichiers jar versionnés.

Update : Un peu lié, cet article explique une stratégie pour rechercher une classe dans des fichiers JAR (soit dans le répertoire en cours) ou dans votre M2_REPO. JarScan, analyse tous les fichiers JAR de tous les sous-dossiers pour une classe spécifique

Update 2 : Également quelque peu lié, JBoss Tattletale

30
cwash

Le passage du commutateur -verbose:class à la commande Java imprimera chaque classe chargée et son emplacement d'origine.

Joops est également un outil de Nice pour trouver les classes manquantes à l’avance.

56
Jason Day

De code, vous pouvez appeler:

myObject.getClass().getProtectionDomain().getCodeSource()

(Remarque: getProtectionDomain peut malheureusement renvoyer null (conception incorrecte), afin que le "code approprié" le vérifie.)

14

Il existe un MBean pour le drapeau JVM mentionné par Jason Day ci-dessus.

Si vous utilisez JBoss, vous pouvez modifier cela à la demande à l'aide de JMX, si vous ajoutez le serveur JMX MBean natif à votre configuration. Ajoutez les -D suivants:

-Dcom.Sun.management.jmxremote.port=3333
-Dcom.Sun.management.jmxremote.authenticate=false
-Dcom.Sun.management.jmxremote.ssl=false
-Djboss.platform.mbeanserver 
-Djavax.management.builder.initial=org.jboss.system.server.jmx.MBeanServerBuilderImpl
-DJBOSS_CLASSPATH="../lib/jboss-system-jmx.jar"

Et ensuite, vous pouvez voir ce paramètre sous le MBean Java.lang: Classloading et vous pouvez l'activer/le désactiver à la volée. Ceci est utile si vous ne le souhaitez que lors de l'exécution d'un certain code.

Il existe également un MBean qui vous permettra d'entrer un nom de classe complet et de voir d'où il a été chargé dans la hiérarchie de classes. Le MBean s'appelle LoaderRepository et vous voudrez invoquer l'opération displayClassInfo () en transmettant le FQCN.

4
cwash

Dans WebSphere (WAS), vous pouvez utiliser une fonctionnalité appelée "Visualiseur de chargeur de classes".

Activez tout d'abord le visualiseur de chargeur de classes en cliquant sur Serveurs> Types de serveur> Serveurs d'applications WebSphere> nom_serveur> Service d'affichage du chargeur de classes, activez le service et redémarrez le serveur.

Ensuite, vous pouvez accéder à Dépannage> Afficheur de chargeur de classes et rechercher votre nom de classe ou de package.

https://www-01.ibm.com/support/knowledgecenter/SSAW57_8.5.5/com.ibm.websphere.nd.doc/ae/ttrb_classload_viewer.html?lang=en

0
cwash

Vous pouvez facilement exporter une opération JMX pour accéder aux informations sur les packages de toute classe chargée dans votre processus, par exemple:

  public static final class Jmx {

    @JmxExport
    public static Reflections.PackageInfo getPackageInfo(@JmxExport("className") final String className) {
      return Reflections.getPackageInfo(className);
    }
  }

et voici un simple test unitaire pour l'exporter et l'invoquer:

  @Test
  public void testClassLocator() throws IOException, InstanceNotFoundException, MBeanException, ReflectionException {
    Registry.export(Jmx.class);
    Reflections.PackageInfo info = (Reflections.PackageInfo) Client.callOperation(
            "service:jmx:rmi:///jndi/rmi://:9999/jmxrmi",
            Jmx.class.getPackage().getName(),
            Jmx.class.getSimpleName(), "getPackageInfo", Registry.class.getName());
    System.out.println(info);
    Assert.assertNotNull(info);
  }

tout cela est basé sur quelques petites bibliothèques d’utilitaires de spf4j ( http://www.spf4j.org )

vous pouvez voir ce code à et le test à

0
user2179737