有谁知道如何以编程方式找出java类加载器实际加载类的位置?
我经常处理大型项目,其中类路径变得非常长并且手动搜索不是真正的选项。我最近有一个problem,其中类加载器正在加载一个不正确的类版本,因为它位于两个不同位置的类路径中。
那么我怎样才能让类加载器告诉我实际的类文件来自磁盘的哪个位置?
编辑: 如果由于版本不匹配(或其他原因)类加载器实际上无法加载类,那么我们是否可以找到哪个文件它在读它之前试图阅读吗?
答案 0 :(得分:173)
以下是一个例子:
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
答案 1 :(得分:92)
找出加载类的位置(不操作源)的另一种方法是使用以下选项启动Java VM:-verbose:class
答案 2 :(得分:71)
getClass().getProtectionDomain().getCodeSource().getLocation();
答案 3 :(得分:26)
这就是我们使用的:
public static String getClassResource(Class<?> klass) {
return klass.getClassLoader().getResource(
klass.getName().replace('.', '/') + ".class").toString();
}
这将取决于ClassLoader实现:
getClass().getProtectionDomain().getCodeSource().getLocation()
答案 4 :(得分:16)
当对象的ClassLoader
注册为null
时,Jon的版本失败,这似乎暗示它是由引导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";
}
答案 5 :(得分:4)
仅编辑第一行: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/
也许风格不好但工作正常!
答案 6 :(得分:1)
看看这个类似的问题。 Tool to discover same class..
我认为最相关的障碍是如果你有一个自定义类加载器(从db或ldap加载)
答案 7 :(得分:1)
通常,我们不使用硬编码。我们可以先获取className,然后使用ClassLoader获取类URL。
String className = MyClass.class.getName().replace(".", "/")+".class";
URL classUrl = MyClass.class.getClassLoader().getResource(className);
String fullPath = classUrl==null ? null : classUrl.getPath();
答案 8 :(得分:1)
简单方法:
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”));
输出示例:
jar:文件:/ D:/Java/jdk1.8/jre/lib/rt.jar!/java/lang/String.class
答案 9 :(得分:0)
这种方法适用于文件和罐子:
Class clazz = Class.forName(nameOfClassYouWant);
URL resourceUrl = clazz.getResource("/" + clazz.getCanonicalName().replace(".", "/") + ".class");
InputStream classStream = resourceUrl.openStream(); // load the bytecode, if you wish
答案 10 :(得分:-1)
假设您正在使用名为MyClass
的类,则以下内容应该有效:
MyClass.class.getClassLoader();
是否可以获取.class文件的磁盘位置取决于类加载器本身。例如,如果你使用像BCEL这样的东西,某个类甚至可能没有磁盘表示。