查找从哪里加载java类

luk*_*uke 171 java classpath classloader

有谁知道如何以编程方式找出java类加载器实际加载类的位置?

我经常在大型项目上工作,其中类路径变得非常长并且手动搜索不是真正的选项.我最近遇到了一个问题,类加载器加载了一个不正确的类版本,因为它位于两个不同位置的类路径中.

那么我怎样才能让类加载器告诉我实际的类文件来自磁盘的哪个位置?

编辑:如果由于版本不匹配(或其他东西),类加载器实际上无法加载类,那么我们是否可以找到它在读取之前尝试读取的文件?

Jon*_*eet 178

这是一个例子:

package foo;

public class Test
{
    public static void main(String[] args)
    {
        ClassLoader loader = Test.class.getClassLoader();
        System.out.println(loader.getResource("foo/Test.class"));
    }
}
Run Code Online (Sandbox Code Playgroud)

打印出来的:

file:/C:/Users/Jon/Test/foo/Test.class
Run Code Online (Sandbox Code Playgroud)

  • @meriton:或者,为了生存refactorinsgs:`Test.class.getResource(Test.class.getSimpleName()+".class")` (31认同)
  • 为了减少冗余类型,还可以使用较短的版本:`Test.class.getResource("Test.class")`,它不重复包名. (30认同)
  • `getClassLoader()`有可能返回`null`.有关此方法的扩展,请参见[此处](http://stackoverflow.com/a/19494116/823393). (2认同)

小智 94

找出加载类的位置(不需要操作源)的另一种方法是使用以下选项启动Java VM: -verbose:class

  • 这非常有效,并且没有使用null ClassLoader处理类的问题 (6认同)
  • @ries如果不需要以编程方式执行此操作,那么绝对可以这样做,它确实解决了我的问题。但是,OP专门询问了如何以编程方式执行此操作。 (2认同)

小智 73

getClass().getProtectionDomain().getCodeSource().getLocation();
Run Code Online (Sandbox Code Playgroud)

  • 是的,虽然它不能与安装的安全管理器一起使用,也没有所需的权限. (4认同)
  • 从 Java 9+ 模块调用时也不起作用(当然,您在 2008 年不可能知道)。 (2认同)

Jev*_*nov 26

这就是我们使用的:

public static String getClassResource(Class<?> klass) {
  return klass.getClassLoader().getResource(
     klass.getName().replace('.', '/') + ".class").toString();
}
Run Code Online (Sandbox Code Playgroud)

这将取决于ClassLoader实现: getClass().getProtectionDomain().getCodeSource().getLocation()


Old*_*eon 16

当对象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";
}
Run Code Online (Sandbox Code Playgroud)


ece*_*rer 5

只编辑第一行:Main.class

Class<?> c = Main.class;
String path = c.getResource(c.getSimpleName() + ".class").getPath().replace(c.getSimpleName() + ".class", "");

System.out.println(path);
Run Code Online (Sandbox Code Playgroud)

输出:

/C:/Users/Test/bin/
Run Code Online (Sandbox Code Playgroud)

也许风格不好但效果很好!