Найти, где класс java загружен из
Кто-нибудь знает, как программно узнать, откуда загружается класс java classloader?
Я часто работаю над большими проектами, где путь к классам очень длинный, а ручной поиск на самом деле не вариант. У меня недавно возникла проблема где загрузчик классов загружал неправильную версию класса, потому что он находился в пути к классам в двух разных местах.
Итак, как я могу заставить classloader рассказать мне, где на диске появляется фактический файл класса?
Изменить: Что, если загрузчик классов фактически не загрузит класс из-за несоответствия версии (или что-то еще), есть ли способ узнать, какой файл пытается его прочитать, прежде чем он прочитает это?
Ответы
Ответ 1
Вот пример:
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
Ответ 2
Еще один способ узнать, откуда загружен класс (без использования источника) - запустить Java VM с помощью опции: -verbose:class
Ответ 3
getClass().getProtectionDomain().getCodeSource().getLocation();
Ответ 4
Это то, что мы используем:
public static String getClassResource(Class<?> klass) {
return klass.getClassLoader().getResource(
klass.getName().replace('.', '/') + ".class").toString();
}
Это будет работать в зависимости от реализации ClassLoader:
getClass().getProtectionDomain().getCodeSource().getLocation()
Ответ 5
Версия Jon не работает, когда объект 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";
}
Ответ 6
Изменить только 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/
Может быть, плохой стиль, но отлично работает!
Ответ 7
Взгляните на этот похожий вопрос.
Инструмент для обнаружения того же класса..
Я думаю, что наиболее важным препятствием является то, что у вас есть пользовательский загрузчик классов (загрузка из db или ldap)
Ответ 8
Этот подход работает как для файлов, так и для банок:
Class clazz = Class.forName(nameOfClassYouWant);
URL resourceUrl = clazz.getResource("/" + clazz.getCanonicalName().replace(".", "/") + ".class");
InputStream classStream = resourceUrl.openStream(); // load the bytecode, if you wish
Ответ 9
Обычно мы не используем hardcoding. Мы можем сначала получить className, а затем использовать ClassLoader для получения URL-адреса класса.
String className = MyClass.class.getName().replace(".", "/")+".class";
URL classUrl = MyClass.class.getClassLoader().getResource(className);
String fullPath = classUrl==null ? null : classUrl.getPath();
Ответ 10
Предполагая, что вы работаете с классом с именем MyClass
, должно работать следующее:
MyClass.class.getClassLoader();
Независимо от того, вы можете получить локальное расположение файла .class на диске, зависит от самого загрузчика класса. Например, если вы используете что-то вроде BCEL, определенный класс может даже не иметь представления на диске.