有人知道如何通过编程找到java类加载器实际从哪里加载类吗?
我经常在大型项目中工作,其中类路径非常长,手动搜索实际上不是一个选择。我最近有一个问题,其中类加载器加载了一个不正确的类版本,因为它在类路径的两个不同的地方。
那么,如何让类加载器告诉我实际的类文件来自磁盘的哪个位置呢?
< em >编辑:< / em >如果类加载器实际上由于版本不匹配(或其他原因)而无法加载类,我们是否可以在它读取文件之前找到它试图读取的文件?
假设你正在使用一个名为MyClass的类,下面的代码应该可以工作:
MyClass
MyClass.class.getClassLoader();
能否获得.class文件在磁盘上的位置取决于类加载器本身。例如,如果您正在使用BCEL之类的东西,那么某个类甚至可能没有磁盘上的表示。
我认为最相关的障碍是如果你有一个自定义类加载器(从db或ldap加载)
这里有一个例子:
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
getClass().getProtectionDomain().getCodeSource().getLocation();
这是我们使用的:
public static String getClassResource(Class<?> klass) { return klass.getClassLoader().getResource( klass.getName().replace('.', '/') + ".class").toString(); }
getClass().getProtectionDomain().getCodeSource().getLocation()
另一种查找类从哪里加载的方法(不操作源代码)是使用选项-verbose:class启动Java VM
-verbose:class
当对象的ClassLoader被注册为null时,Jon的版本就失败了,这似乎意味着它是由引导ClassLoader加载的。
ClassLoader
null
这个方法可以解决这个问题:
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"; }
只编辑第一行:__abc1 .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/
也许是糟糕的风格,但很好!
这种方法对文件和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();
简单的方法:
System.out.println (java.lang.String.class.getResource (String.class.getSimpleName () + " . class "));
例子:
jar:文件:/ D: / Java / jdk1.8 / jre / lib / rt.jar ! / Java / lang / String.class
或
String obj = "简单测试"; System.out.println (obj.getClass () .getResource (obj.getClass () .getSimpleName () + " . class ")); < / p >