Найдите, откуда загружается класс java
кто-нибудь знает, как программно узнать, где Java classloader фактически загружает класс?
Я часто работаю над большими проектами, где путь к классам становится очень длинным, и ручной поиск на самом деле не является вариантом. Недавно у меня возникла проблема, когда загрузчик классов загружал неправильную версию класса, потому что он был на пути к классу в двух разных местах.
Итак, как я могу заставить загрузчик классов сказать мне, где на диске находится фактический файл класса откуда?
Edit: что делать, если загрузчик классов на самом деле не удается загрузить класс из-за несоответствия версии (или что-то еще), есть ли в любом случае мы могли бы узнать, какой файл он пытается прочитать, прежде чем он его читает?
10 ответов:
вот пример:
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
другой способ узнать, откуда загружается класс (без манипулирования источником), - это запустить виртуальную машину Java с опцией:
-verbose:class
вот что мы используем:
public static String getClassResource(Class<?> klass) { return klass.getClassLoader().getResource( klass.getName().replace('.', '/') + ".class").toString(); }
это будет работать в зависимости от реализации загрузчика классов:
getClass().getProtectionDomain().getCodeSource().getLocation()
версия Джона терпит неудачу, когда объект
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"; }
редактировать только 1-ая строка:
Main
.классClass<?> c = Main.class; String path = c.getResource(c.getSimpleName() + ".class").getPath().replace(c.getSimpleName() + ".class", ""); System.out.println(path);
выход:
/C:/Users/Test/bin/
может быть, плохой стиль, но работает отлично!
взгляните на этот подобный вопрос. инструмент для обнаружения того же класса..
Я думаю, что самое важное препятствие - это если у вас есть пользовательский загрузчик классов ( загрузка из БД или ldap )
Как правило, мы не используем жесткое кодирование. Сначала мы можем получить className, а затем использовать ClassLoader для получения URL-адреса класса.
String className = MyClass.class.getName().replace(".", "/")+".class"; URL classUrl = MyClass.class.getClassLoader().getResource(className); String fullPath = classUrl==null ? null : classUrl.getPath();
этот подход работает как для файлов, так и коробит:
Class clazz = Class.forName(nameOfClassYouWant); URL resourceUrl = clazz.getResource("/" + clazz.getCanonicalName().replace(".", "/") + ".class"); InputStream classStream = resourceUrl.openStream(); // load the bytecode, if you wish
предполагая, что вы работаете с классом
MyClass
, следующее должно работать:MyClass.class.getClassLoader();
можно ли получить расположение на диске .файл класса зависит от самого загрузчика. Например, если вы используете что-то вроде BCEL, определенный класс может даже не иметь представления на диске.