Найти, откуда загружается класс Java - PullRequest
166 голосов
/ 23 октября 2008

Кто-нибудь знает, как программно узнать, откуда на самом деле загрузчик классов Java загружает класс?

Я часто работаю над большими проектами, в которых путь к классам становится очень длинным, а поиск вручную не всегда возможен. У меня недавно была проблема , когда загрузчик классов загружал неправильную версию класса, потому что он находился в пути к классам в двух разных местах.

Итак, как я могу заставить загрузчик классов сказать мне, откуда на диске берется фактический файл класса?

Редактировать: Как насчет того, если загрузчик классов действительно не может загрузить класс из-за несоответствия версий (или чего-то еще), есть ли в любом случае, мы могли бы узнать, какой файл пытается читать, прежде чем он прочитает это?

Ответы [ 10 ]

173 голосов
/ 23 октября 2008

Вот пример:

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
92 голосов
/ 23 октября 2008

Другой способ узнать, откуда загружается класс (без манипулирования источником), - запустить Java VM с параметром: -verbose:class

71 голосов
/ 23 октября 2008
getClass().getProtectionDomain().getCodeSource().getLocation();
26 голосов
/ 23 октября 2008

Это то, что мы используем:

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

Это будет работать в зависимости от реализации ClassLoader: getClass().getProtectionDomain().getCodeSource().getLocation()

16 голосов
/ 21 октября 2013

Версия Джона не работает, когда объект ClassLoader зарегистрирован как null, что, по-видимому, означает, что он был загружен загрузчиком 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";
}
4 голосов
/ 22 апреля 2015

Редактировать только 1-ю строку: 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/

Возможно, плохой стиль, но отлично работает!

1 голос
/ 20 октября 2017

Как правило, нам не нужно использовать жесткое кодирование. Сначала мы можем получить className, а затем использовать ClassLoader для получения URL-адреса класса.

        String className = MyClass.class.getName().replace(".", "/")+".class";
        URL classUrl  = MyClass.class.getClassLoader().getResource(className);
        String fullPath = classUrl==null ? null : classUrl.getPath();
1 голос
/ 23 октября 2008

Посмотрите на этот похожий вопрос. Инструмент для обнаружения того же класса ..

Я думаю, что наиболее важным препятствием является наличие у вас пользовательского загрузчика классов (загрузка из БД или ldap)

0 голосов
/ 15 февраля 2017

Этот подход работает как для файлов, так и для jar-файлов:

Class clazz = Class.forName(nameOfClassYouWant);

URL resourceUrl = clazz.getResource("/" + clazz.getCanonicalName().replace(".", "/") + ".class");
InputStream classStream = resourceUrl.openStream(); // load the bytecode, if you wish
0 голосов
/ 23 октября 2008

Предполагая, что вы работаете с классом с именем MyClass, должно работать следующее:

MyClass.class.getClassLoader();

Возможность определения местоположения файла .class на диске зависит от самого загрузчика классов. Например, если вы используете что-то вроде BCEL, определенный класс может даже не иметь представления на диске.

...