find从哪里加载Java类

有没有人知道如何编程地找出java classloader实际上从哪里加载类?

我经常在类path变得很长的大型项目上工作,手动search不是真正的select。 我最近遇到了类加载器加载类的不正确版本的问题 ,因为它位于两个不同位置的类path中。

那么如何让类加载器告诉我磁盘上的实际类文件来自哪里?

编辑:如果类加载实际上由于版本不匹配(或其他)而无法加载类,那么无论如何,我们可以找出它在读取之前尝试读取哪个文件?

这是一个例子:

package foo; public class Test { public static void main(String[] args) { ClassLoader loader = Test.class.getClassLoader(); System.out.println(loader.getResource("foo/Test.class")); } } 

这打印出来了:

 file:/C:/Users/Jon/Test/foo/Test.class 

另一种查找从何处加载类的方法是使用以下选项启动Java VM: -verbose:class

 getClass().getProtectionDomain().getCodeSource().getLocation(); 

这是我们使用的:

 public static String getClassResource(Class<?> klass) { return klass.getClassLoader().getResource( klass.getName().replace('.', '/') + ".class").toString(); } 

这将取决于ClassLoader实现: getClass().getProtectionDomain().getCodeSource().getLocation()

Jon的版本在对象的ClassLoader注册为null时失败,这似乎暗示它是由Boot ClassLoader

这个方法处理这个问题:

 public static String whereFrom(Object o) { if ( o == null ) { return null; } Class<?> c = o.getClass(); ClassLoader loader = c.getClassLoader(); if ( loader == null ) { // Try the bootstrap classloader - obtained from the ultimate parent of the System Class Loader. loader = ClassLoader.getSystemClassLoader(); while ( loader != null && loader.getParent() != null ) { loader = loader.getParent(); } } if (loader != null) { String name = c.getCanonicalName(); URL resource = loader.getResource(name.replace(".", "/") + ".class"); if ( resource != null ) { return resource.toString(); } } return "Unknown"; } 

编辑第一行: Main .class

 Class<?> c = Main.class; String path = c.getResource(c.getSimpleName() + ".class").getPath().replace(c.getSimpleName() + ".class", ""); System.out.println(path); 

输出:

 /C:/Users/Test/bin/ 

也许不好的风格,但工作正常!

看看这个类似的问题。 发现同一类的工具

我认为最相关的障碍是如果你有一个自定义类加载器(从db或ldap加载)

这种方法适用于文件和jar子:

 Class clazz = Class.forName(nameOfClassYouWant); URL resourceUrl = clazz.getResource("/" + clazz.getCanonicalName().replace(".", "/") + ".class"); InputStream classStream = resourceUrl.openStream(); // load the bytecode, if you wish 

通常,我们不使用硬编码。 我们可以首先获取className,然后使用ClassLoader获取类的URL。

  String className = MyClass.class.getName().replace(".", "/")+".class"; URL classUrl = MyClass.class.getClassLoader().getResource(className); String fullPath = classUrl==null ? null : classUrl.getPath(); 

假设你正在使用一个名为MyClass的类,下面的代码应该可以工作:

 MyClass.class.getClassLoader(); 

是否可以获取.class文件的磁盘位置取决于类加载器本身。 例如,如果您使用的是BCEL之类的东西,某个类可能甚至没有磁盘表示。