如何探索从哪些JAR加载哪些类?

时间:2009-06-03 20:53:52

标签: java profiling classloader jar

有没有办法确定在运行时从哪些jar加载哪些类?

我确信我们以前都在JAR地狱。我在项目的ClassNotFoundExceptionNoClassDefFoundError问题上遇到了很多问题。我想避免在罐子里找到一个类的所有实例,并在代码上使用消除过程导致CNFE找到罪魁祸首。

任何分析或管理工具都会为您提供此类信息吗?

这个问题非常烦人,因为我们应该在加载类时获得这些信息。必须有一种方法可以达到它,或记录它并找到它,但我知道什么都不会做到这一点,对吗?

我知道OSGi和版本化的软件包/模块旨在使这个问题成为一个问题......但它似乎很快就会消失。 :)

注意:我发现这个question是我的问题的一个子集,与从版本化的jar加载的类有关。

更新:有点相关,这篇文章解释了在jars(当前目录下)或M2_REPO中搜索类的策略。 JarScan, scan all JAR files in all subfolders for specific class

更新2 :也有些相关,JBoss Tattletale

5 个答案:

答案 0 :(得分:56)

-verbose:class开关传递给java命令将打印加载的每个类及其加载位置。

Joops也是提前查找缺失类的好工具。

答案 1 :(得分:14)

您可以致电代码:

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

(注意,getProtectionDomain可能会遗憾地返回null(设计不当),因此“正确的代码”会检查该内容。)

答案 2 :(得分:4)

Jason Day上面提到了JVM标志的MBean。

如果您正在使用JBoss,如果您将原生JMX MBean服务器添加到您的配置中,您可以使用JMX按需旋转。添加以下-D's:

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

答案 3 :(得分:0)

在WebSphere(WAS)中,您可以使用名为" Class Loader Viewer"

的功能

首先单击Servers>启用类加载器查看器。服务器类型> WebSphere应用程序服务器> server_name>类加载器查看器服务,启用服务并重新启动服务器。

然后你可以去故障排除>类加载器查看器并搜索您的类或包名称。

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

答案 4 :(得分:0)

您可以轻松导出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