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之类的东西,某个类可能甚至没有磁盘表示。