Find where java class is loaded from
有人知道如何编程地找出Java类加载器从何处加载该类吗?
我经常在大型项目中工作,在这些项目中,类路径非常长,手动搜索实际上不是一个选项。我最近遇到了一个问题,类加载器加载了一个不正确的类版本,因为它位于类路径的两个不同位置。
那么,如何让类加载器告诉我实际类文件在磁盘上的来源呢?
编辑:如果由于版本不匹配(或其他原因),类加载器实际上无法加载类,那么我们是否可以在读取之前找到它尝试读取的文件?
下面是一个例子:
1 2 3 4 5 6 7 8 9 10 | package foo; public class Test { public static void main(String[] args) { ClassLoader loader = Test.class.getClassLoader(); System.out.println(loader.getResource("foo/Test.class")); } } |
打印出来:
1 | file:/C:/Users/Jon/Test/foo/Test.class |
另一种方法是从(不操纵源)加载一个类的方法是用选项EDCOX1(2)启动Java VM。
1 | getClass().getProtectionDomain().getCodeSource().getLocation(); |
这就是我们使用的:
1 2 3 4 | public static String getClassResource(Class<?> klass) { return klass.getClassLoader().getResource( klass.getName().replace('.', '/') +".class").toString(); } |
这将取决于类加载器的实现:
当对象的
此方法处理该问题:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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"; } |
只编辑第一行:
1 2 3 4 |
输出:
1 | /C:/Users/Test/bin/ |
也许风格不好,但效果很好!
通常,我们不知道使用什么硬编码。我们可以先获取类名,然后使用ClassLoader获取类URL。
1 2 3 |
看看这个类似的问题。发现同一类的工具..
我认为最相关的障碍是如果您有一个定制的类加载器(从DB或LDAP加载)
这种方法适用于文件和JAR:
1 2 3 4 | Class clazz = Class.forName(nameOfClassYouWant); URL resourceUrl = clazz.getResource("/" + clazz.getCanonicalName().replace(".","/") +".class"); InputStream classStream = resourceUrl.openStream(); // load the bytecode, if you wish |
假设您使用的是一个名为
1 | MyClass.class.getClassLoader(); |
是否可以获取.class文件的磁盘上位置取决于类加载器本身。例如,如果您使用的是BCEL,那么某个类甚至可能没有磁盘上的表示。