Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/308.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
查找从何处加载java类_Java_Classpath_Classloader - Fatal编程技术网

查找从何处加载java类

查找从何处加载java类,java,classpath,classloader,Java,Classpath,Classloader,有人知道如何通过编程找出java类装入器实际从何处装入类吗 我经常在大型项目中工作,在这些项目中,类路径变得非常长,手动搜索实际上不是一种选择。我最近遇到了一个问题,类加载器加载了一个不正确的类版本,因为它位于两个不同位置的类路径上 那么,如何让类加载器告诉我实际的类文件来自磁盘上的什么地方呢 编辑:如果类加载器由于版本不匹配(或其他原因)而无法加载该类,那么我们是否可以在读取该类之前找出该类试图读取的文件?假设您使用的是名为MyClass的类,则以下操作应该有效: MyClass.class.

有人知道如何通过编程找出java类装入器实际从何处装入类吗

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

那么,如何让类加载器告诉我实际的类文件来自磁盘上的什么地方呢


编辑:如果类加载器由于版本不匹配(或其他原因)而无法加载该类,那么我们是否可以在读取该类之前找出该类试图读取的文件?

假设您使用的是名为
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
这就是我们所使用的:

public static String getClassResource(Class<?> klass) {
  return klass.getClassLoader().getResource(
     klass.getName().replace('.', '/') + ".class").toString();
}
公共静态字符串getClassResource(类klass){
返回klass.getClassLoader().getResource(
klass.getName().replace('.','/')+“.class”).toString();
}
这取决于类加载器实现:
getClass().getProtectionDomain().getCodeSource().getLocation()

找到类从何处加载的另一种方法(无需操作源)是使用以下选项启动Java VM:
-verbose:class

当对象的
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";
}
公共静态字符串(对象o){
如果(o==null){
返回null;
}
c类=o.getClass();
ClassLoader=c.getClassLoader();
if(loader==null){
//尝试引导类加载器-从系统类加载器的最终父级获得。
loader=ClassLoader.getSystemClassLoader();
while(loader!=null&&loader.getParent()!=null){
loader=loader.getParent();
}
}
if(加载程序!=null){
String name=c.getCanonicalName();
URL resource=loader.getResource(name.replace(“.”,“/”)+“.class”);
if(资源!=null){
返回resource.toString();
}
}
返回“未知”;
}

只编辑第一行:
Main
.class

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

System.out.println(path);

也许是糟糕的风格,但很好

此方法适用于文件和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: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


是的,尽管它不能与安装的安全管理器一起工作,并且没有所需的权限。仅供参考,NPE=Null指针异常。嗯!只要你有一个实例的引用,这个方法是首选的,因为你可以从两个不同的位置加载同一个类。当从Java 9+模块调用时,这个方法也不起作用(当然,你在2008年不可能知道)。这个方法工作得很好,并且不存在处理null类的问题ClassLoader@ries如果一个人不需要以编程的方式来做这件事,那么这绝对是一条路,它确实解决了我的问题。然而,OP明确提出了如何通过编程实现这一点。为了减少冗余类型,还可以使用较短的版本:
Test.class.getResource(“Test.class”)
,该版本不重复包名。如果该类是编译的,例如从.groovy文件编译的,该怎么办?@meriton:Or,要在重构中生存:
Test.class.getResource(Test.class.getSimpleName()+“.class”)
For
BouncyCastleProvider
需要完整的包名。
getClassLoader()
可能返回
null
。有关此方法的扩展,请参阅。这将返回用于加载类的类加载器,不是吗?它找不到.class文件的位置?不,找不到。类加载器实际上可以引用到完全不同的类路径-这意味着它将完全无法读取实际的类位置。需要是:URL classUrl=MyClass.class.getClassLoader().getResource(“/”+className);类是重要的部分-getClass()可以返回代理!然后,您可以获得MyClass$$EnhancerBySpringCGLIB$$a98db882.class这样的名称,以及空URL。
Class clazz = Class.forName(nameOfClassYouWant);

URL resourceUrl = clazz.getResource("/" + clazz.getCanonicalName().replace(".", "/") + ".class");
InputStream classStream = resourceUrl.openStream(); // load the bytecode, if you wish
        String className = MyClass.class.getName().replace(".", "/")+".class";
        URL classUrl  = MyClass.class.getClassLoader().getResource(className);
        String fullPath = classUrl==null ? null : classUrl.getPath();