2008-10-22 9 views
145

Кто-нибудь знает, как программно узнать, откуда загружается класс java classloader?Найти, где класс java загружен с

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

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

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

+4

@JarrodRoberson Я не думаю, что это следует рассматривать как дубликат http://stackoverflow.com/questions/11747833/getting-filesystem-path-of-class-being-executed так как этот вопрос был задан вопрос в 2008 году, и этот вопрос был задан в 2012 году. – luke 2015-05-07 15:56:09

ответ

148

Вот пример:

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 
+23

Чтобы сократить избыточную типизацию, можно также использовать более короткую версию: `Test.class.getResource (« Test.class »)`, которая не повторяет имя пакета. – meriton 2013-02-01 16:42:01

+1

Что делать, если класс скомпилирован, например. из файла .groovy? – 2013-06-28 00:58:43

-1

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

MyClass.class.getClassLoader(); 

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

+0

Это возвращает ClassLoader, используемый для загрузки класса, не так ли? Он не находит, где находится файл .class? – 2014-09-26 05:46:21

+1

Нет, нет. Классный загрузчик действительно может ссылаться на совершенно другой путь класса - означает, что он полностью не сможет определить фактическое местоположение класса. – 2015-03-07 18:16:29

1

Посмотрите на этот похожий вопрос. Tool to discover same class..

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

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

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

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

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

84

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

16

Версия Jon's не работает, когда объект 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

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

Может быть плохой стиль, но работает отлично!

0

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

Class clazz = Class.forName(nameOfClassYouWant); 

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

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

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

 Смежные вопросы

  • Нет связанных вопросов^_^