有没有办法确定在运行时从哪些jar加载哪些类?
我确信我们以前都在JAR地狱。我在项目的ClassNotFoundException
和NoClassDefFoundError
问题上遇到了很多问题。我想避免在罐子里找到一个类的所有实例,并在代码上使用消除过程导致CNFE找到罪魁祸首。
任何分析或管理工具都会为您提供此类信息吗?
这个问题非常烦人,因为我们应该在加载类时获得这些信息。必须有一种方法可以达到它,或记录它并找到它,但我知道什么都不会做到这一点,对吗?
我知道OSGi和版本化的软件包/模块旨在使这个问题成为一个问题......但它似乎很快就会消失。 :)
注意:我发现这个question是我的问题的一个子集,与从版本化的jar加载的类有关。
更新:有点相关,这篇文章解释了在jars(当前目录下)或M2_REPO中搜索类的策略。 JarScan, scan all JAR files in all subfolders for specific class
更新2 :也有些相关,JBoss Tattletale
答案 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>类加载器查看器服务,启用服务并重新启动服务器。
然后你可以去故障排除>类加载器查看器并搜索您的类或包名称。
答案 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)
的一些小实用程序库