查找从何处加载 java 类

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/227486/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 11:44:42  来源:igfitidea点击:

Find where java class is loaded from

javaclasspathclassloader

提问by luke

Does anyone know how to programmaticly find out where the java classloader actually loads the class from?

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

I often work on large projects where the classpath gets very long and manual searching is not really an option. I recently had a problemwhere the classloader was loading an incorrect version of a class because it was on the classpath in two different places.

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

So how can I get the classloader to tell me where on disk the actual class file is coming from?

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

Edit:What about if the classloader actually fails to load the class due to a version mismatch (or something else), is there anyway we could find out what file its trying to read before it reads it?

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

采纳答案by Jon Skeet

Here's an example:

下面是一个例子:

package foo;

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

This printed out:

这打印出来:

file:/C:/Users/Jon/Test/foo/Test.class

回答by Daniel Spiewak

Assuming that you're working with a class named MyClass, the following should work:

假设您正在使用一个名为 的类MyClass,以下应该有效:

MyClass.class.getClassLoader();

Whether or not you can get the on-disk location of the .class file is dependent on the classloader itself. For example, if you're using something like BCEL, a certain class may not even have an on-disk representation.

是否可以获得 .class 文件的磁盘位置取决于类加载器本身。例如,如果您使用 BCEL 之类的东西,某个类甚至可能没有磁盘表示。

回答by OscarRyz

Take a look at this similar question. Tool to discover same class..

看看这个类似的问题。 发现同一类的工具..

I think the most relevant obstacle is if you have a custom classloader ( loading from a db or ldap )

我认为最相关的障碍是您是否有自定义类加载器(从 db 或 ldap 加载)

回答by Dave DiFranco

getClass().getProtectionDomain().getCodeSource().getLocation();

回答by Jevgeni Kabanov

This is what we use:

这是我们使用的:

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

This will work depending on the ClassLoader implementation: getClass().getProtectionDomain().getCodeSource().getLocation()

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

回答by jiriki

Another way to find out where a class is loaded from (without manipulating the source) is to start the Java VM with the option: -verbose:class

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

回答by OldCurmudgeon

Jon's version fails when the object's ClassLoaderis registered as nullwhich seems to imply that it was loaded by the Boot ClassLoader.

当对象ClassLoader被注册为null这似乎暗示它是由 Boot 加载时,Jon 的版本失败ClassLoader

This method deals with that issue:

这个方法处理这个问题:

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";
}

回答by ecerer

Edit just 1st line: Main.class

只编辑第一行:Main.class

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

System.out.println(path);

Output:

输出:

/C:/Users/Test/bin/

Maybe bad style but works fine!

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

回答by Adam

This approach works for both files and jars:

这种方法适用于文件和 jars:

Class clazz = Class.forName(nameOfClassYouWant);

URL resourceUrl = clazz.getResource("/" + clazz.getCanonicalName().replace(".", "/") + ".class");
InputStream classStream = resourceUrl.openStream(); // load the bytecode, if you wish

回答by Hongyang

Typically, we don't what to use hardcoding. We can get className first, and then use ClassLoader to get the class URL.

通常,我们不会使用硬编码。我们可以先获取className,然后使用ClassLoader获取类的URL。

        String className = MyClass.class.getName().replace(".", "/")+".class";
        URL classUrl  = MyClass.class.getClassLoader().getResource(className);
        String fullPath = classUrl==null ? null : classUrl.getPath();