Подтвердить что ты не робот

Как узнать, какие классы загружены из JAR?

Есть ли способ определить, какие классы загружаются из банок во время выполнения?

Я уверен, что мы все были в JAR ад раньше. Я столкнулся с этой проблемой много проблем с поиском ClassNotFoundException и NoClassDefFoundError для проектов. Я бы хотел избежать поиска всех экземпляров класса в баночках и использования процесса устранения кода, вызывающего CNFE, чтобы найти виновника.

Будут ли какие-либо инструменты профилирования или управления предоставлять вам такую ​​информацию?

Эта проблема очень раздражает, потому что мы должны иметь эту информацию во время загрузки класса. Должен быть способ добраться до него или записать его и найти, но я ничего не знаю, что сделаю это, не так ли?

Я знаю, что OSGi и версии пакетов/модулей нацелены на то, чтобы сделать это не проблемой... но, похоже, в ближайшее время он не уйдет.:)

ПРИМЕЧАНИЕ. Я обнаружил, что это question является подмножеством моего вопроса, связанного с классами, загружаемыми с версированных банок.

Обновление. В некоторой степени это объясняет стратегию поиска класса внутри jars (либо в текущем каталоге), либо в вашем M2_REPO. JarScan, сканировать все файлы JAR во всех подпапках для определенного класса

Обновление 2: также несколько связано, JBoss Tattletale

4b9b3361

Ответ 1

Передача переключателя -verbose:class в команду java будет печатать каждый загруженный класс и где он был загружен.

Joops также является хорошим инструментом для поиска недостающих классов раньше времени.

Ответ 2

Из кода, который вы можете вызвать:

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

(Примечание. getProtectionDomain может, к сожалению, возвратить null (плохой дизайн), поэтому для этого будет проверен "правильный код".)

Ответ 3

Существует MBean для флага JVM, упомянутого выше в Jason Day.

Если вы используете JBoss, вы можете покрутить это по требованию с помощью JMX, если вы добавите собственный JMX-сервер MBean в свою конфигурацию. Добавьте следующие -D:

-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"

И затем вы можете увидеть этот параметр в разделе java.lang: Classloading MBean и можете в любое время разрезать его/выключить. Это полезно, если вы только хотите, чтобы он выполнял определенный фрагмент кода.

Существует также MBean, который позволит вам ввести полное имя класса и посмотреть, где он был загружен из иерархии классов. MBean называется LoaderRepository, и вы хотите вызвать операцию displayClassInfo(), передав FQCN.

Ответ 4

В WebSphere (WAS) вы можете использовать функцию "Class Loader Viewer"

Сначала включите средство просмотра загрузчика классов, щелкнув "Серверы" > "Типы серверов" > "Серверы приложений WebSphere" > "имя_сервера" > "Служба просмотра загрузчика класса", включите службу и перезапустите сервер.

Затем вы можете перейти в "Устранение неполадок" > "Просмотрщик классов" и выполнить поиск имени вашего класса или пакета.

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

Ответ 5

Вы можете легко экспортировать операцию JMX для доступа к информации о пакете для любого загруженного класса в вашем процессе, например:

  public static final class Jmx {

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

и вот простой unit test для экспорта и вызова:

  @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);
  }

все это основано на использовании небольшой библиотеки утилит из spf4j (http://www.spf4j.org)

вы можете увидеть этот код в и тест в