it-swarm.com.ru

Как узнать, какие классы загружаются из каких JAR-файлов?

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

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

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

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

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

ПРИМЕЧАНИЕ: я нашел этот вопрос это подмножество моего вопроса, связанного с классами, загруженными из версионных jar-файлов.

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

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

30
cwash

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

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

56
Jason Day

Из кода можно позвонить:

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

(Обратите внимание, что getProtectionDomain может, к сожалению, возвращать null (плохой дизайн), поэтому «правильный код» проверит это.)

14
Tom Hawtin - tackline

Существует флаг 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: Classelling MBean и можете включить/выключить ее на лету. Это полезно, если вы хотите включить его только при выполнении определенного фрагмента кода.

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

4
cwash

В 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

0
cwash

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

  public static final class Jmx {

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

и вот простой модульный тест для его экспорта и вызова:

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

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

0
user2179737