Я пишу игровой движок, в котором мне нужно проанализировать каждый класс, упомянутый в моей программе. Поскольку это игровой движок, он должен быть присоединен к проекту клиента как файл JAR. Изнутри этого JAR-файла я должен иметь возможность сканировать каждый класс, который используется клиентом.Как установить класс ClassLoader как классLoader JVM для загрузки ВСЕХ классов (включая классы jar)?
Поэтому я думал, что должен создать пользовательский ClassLoader! Переопределяя ClassLoader, я могу взглянуть на каждый класс, который используется при его загрузке.
Я начал немного поиграть с ClassLoaders. Вот что я сделал: (я украл этот загрузчик классов от JavaWorld просто играть с ним)
public class SimpleClassLoader extends ClassLoader {
private HashMap<String, Class> classes = new HashMap<String, Class>();
public SimpleClassLoader() {
}
/**
* This sample function for reading class implementations reads
* them from the local file system
*/
private byte getClassImplFromDataBase(String className)[] {
System.out.println(" >>>>>> Fetching the implementation of "+className);
byte result[];
try {
FileInputStream fi = new FileInputStream("store\\"+className+".impl");
result = new byte[fi.available()];
fi.read(result);
return result;
} catch (Exception e) {
/*
* If we caught an exception, either the class wasnt found or it
* was unreadable by our process.
*/
return null;
}
}
/**
* This is a simple version for external clients since they
* will always want the class resolved before it is returned
* to them.
*/
public Class loadClass(String className) throws ClassNotFoundException {
return (loadClass(className, true));
}
/**
* This is the required version of loadClass which is called
* both from loadClass above and from the internal function
* FindClassFromClass.
*/
public synchronized Class loadClass(String className, boolean resolveIt)
throws ClassNotFoundException {
Class result;
byte classData[];
System.out.println(className);
System.out.println(" >>>>>> Load class : "+className);
/* Check our local cache of classes */
result = (Class)classes.get(className);
if (result != null) {
System.out.println(" >>>>>> returning cached result.");
return result;
}
/* Check with the primordial class loader */
try {
result = super.findSystemClass(className);
System.out.println(" >>>>>> returning system class (in CLASSPATH).");
return result;
} catch (ClassNotFoundException e) {
System.out.println(" >>>>>> Not a system class.");
}
/* Try to load it from our repository */
classData = getClassImplFromDataBase(className);
if (classData == null) {
throw new ClassNotFoundException();
}
/* Define it (parse the class file) */
result = defineClass(classData, 0, classData.length);
if (result == null) {
throw new ClassFormatError();
}
if (resolveIt) {
resolveClass(result);
}
classes.put(className, result);
System.out.println(" >>>>>> Returning newly loaded class.");
return result;
}
}
Тогда я решил проверить:
public class Test
{
public static void main(String args[]) throws ClassNotFoundException
{
SimpleClassLoader s = new SimpleClassLoader();
Thread.currentThread().setContextClassLoader(s);
Foo myfoo = new Foo(); //local class
ArrayList myList = new ArrayList(); //class from JAR file
//both should have been loaded from my SimpleClassLoader
System.out.println(s + "\n\tshould be equal to\n" + myfoo.getClass().getClassLoader());
System.out.println("\tand also to: \n" + myList.getClass().getClassLoader());
/*
OUTPUT:
[email protected]
should be equal to
[email protected]
and also to:
null
***
bizarre results: why are ArrayList and Foo not being loaded by my classloader?
*/
}
}
Создает пользовательский ClassLoader правильный подход к проблеме, описанной вверху?
Почему запускается загрузчик системного класса? Как заставить JVM использовать MY classloader, для всех потоков? (не только первый поток, я хочу, чтобы каждый новый поток создавал для автоматического использования моего загрузчика классов)
Я понимаю, что с помощью «системы делегирования» родительский ClassLoader сначала пытается загрузить класс; это может быть причиной того, что мой ClassLoader ничего не загружает. Если я прав, как отключить эту функцию? Как я могу загрузить загрузчик MY classloader?
См. Ответы на [этот вопрос здесь] (http://stackoverflow.com/questions/10192453/java-classloader-change/10192692#10192692). –