有谁知道如何以编程方式找出java类加载器实际从哪里加载类?
我经常在大型项目中工作,其中类路径变得很长,手动搜索并不是一个真正的选择。我最近遇到了一个问题,即类加载器加载了一个不正确的类版本,因为它位于两个不同位置的类路径上。
那么如何让类加载器告诉我实际的类文件来自磁盘的哪个位置?
编辑:如果类加载器由于版本不匹配(或其他原因)实际上无法加载类怎么办,无论如何我们可以在读取它之前找出它试图读取的文件吗?
有谁知道如何以编程方式找出java类加载器实际从哪里加载类?
我经常在大型项目中工作,其中类路径变得很长,手动搜索并不是一个真正的选择。我最近遇到了一个问题,即类加载器加载了一个不正确的类版本,因为它位于两个不同位置的类路径上。
那么如何让类加载器告诉我实际的类文件来自磁盘的哪个位置?
编辑:如果类加载器由于版本不匹配(或其他原因)实际上无法加载类怎么办,无论如何我们可以在读取它之前找出它试图读取的文件吗?
这是一个例子:
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()
ClassLoader
当对象被注册时,Jon 的版本失败,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/
也许风格不好,但效果很好!
通常,我们不使用硬编码。我们可以先获取className,然后使用ClassLoader获取class URL。
String className = MyClass.class.getName().replace(".", "/")+".class";
URL classUrl = MyClass.class.getClassLoader().getResource(className);
String fullPath = classUrl==null ? null : classUrl.getPath();
看看这个类似的问题。 发现同一类的工具..
我认为最相关的障碍是您是否有自定义类加载器(从 db 或 ldap 加载)
简单的方法:
System.out.println(java.lang.String.class.getResource(String.class.getSimpleName()+".class"));
输出示例:
jar:file:/D:/Java/jdk1.8/jre/lib/rt.jar!/java/lang/String.class
或者
String obj = "简单测试"; System.out.println(obj.getClass().getResource(obj.getClass().getSimpleName()+".class"));
输出示例:
jar:file:/D:/Java/jdk1.8/jre/lib/rt.jar!/java/lang/String.class
这种方法适用于文件和罐子:
Class clazz = Class.forName(nameOfClassYouWant);
URL resourceUrl = clazz.getResource("/" + clazz.getCanonicalName().replace(".", "/") + ".class");
InputStream classStream = resourceUrl.openStream(); // load the bytecode, if you wish
假设您正在使用名为 的类MyClass
,则以下内容应该有效:
MyClass.class.getClassLoader();
能否获得 .class 文件的磁盘位置取决于类加载器本身。例如,如果您使用 BCEL 之类的东西,则某个类甚至可能没有磁盘表示。