Я изучаю динамическую модификацию пути к классам. Я нашел одно решение, которое хорошо работает, но делает это с помощью явного вызова добавить URL(). (предположительно при запуске)
Однако я хотел бы перехватить процесс загрузки классов во время выполнения, чтобы найти классы, если загрузчик классов по умолчанию не может их найти. Я попытался создать подкласс ClassLoader, чтобы он просто делегирует findClass() и loadClass() значениям по умолчанию и распечатывает строку отладки, сообщающую мне, что эти методы были вызваны, но они, кажется, никогда не вызываются, когда мой класс использует зависимые классы через неявную загрузку классов, например
// regular object instantiation with 'new'
BrowserLauncher launcher;
launcher = new BrowserLauncher();
// static methods
Foobar.doSomethingOrOther();
// Class.forName()
Class cl = Class.forName("foo.bar.baz");
// reflection on a Class object obtained statically
Class<Foobar> cl = Foobar.class;
// do something with cl, like call static methods or newInstance()
Как работает загрузка классов в этих обстоятельствах? (по сравнению с более простым случаем, когда Classloader.loadClass () вызывается явно)
Вот моя попытка создать собственный загрузчик классов ниже. Если я использую DynClassLoader0.main () со списком аргументов {"some.package.SomeClass", "foo", "bar", "baz"}, а some.package.SomeClass ссылается на другие классы, найденные во внешних файлах .jar, используя один из методов, перечисленных выше, почему мои DynClassLoader0 не найдутClass () и loadClass () позвонить? Единственный раз, когда вызывается loadClass, - это явный вызов loadClass в функции main () ниже.
package com.example.test.classloader;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class DynClassLoader0 extends ClassLoader {
public DynClassLoader0()
{
super();
}
public DynClassLoader0(ClassLoader parent)
{
super(parent);
}
public void runMain(String classname, String[] args) throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException
{
// [***] here we explicitly use our classloader.
Class<?> cl = loadClass(classname);
Method main = cl.getMethod("main", String[].class);
main.invoke(null, new Object[] {args});
}
@Override protected Class<?> findClass(String name) throws ClassNotFoundException
{
System.out.println("findClass("+name+")");
return super.findClass(name);
}
@Override public Class<?> loadClass(String name) throws ClassNotFoundException
{
System.out.println("loadClass("+name+")");
return super.loadClass(name);
}
static public void main(String[] args)
{
// classname, then args
if (args.length >= 1)
{
String[] classArgs = new String[args.length-1];
System.arraycopy(args, 1, classArgs, 0, args.length-1);
ClassLoader currentThreadClassLoader
= Thread.currentThread().getContextClassLoader();
DynClassLoader0 classLoader = new DynClassLoader0(currentThreadClassLoader);
// Replace the thread classloader - assumes
// you have permissions to do so
Thread.currentThread().setContextClassLoader(classLoader);
try {
classLoader.runMain(args[0], classArgs);
}
catch (Exception e) {
e.printStackTrace();
}
}
else
{
System.out.println("usage: DynClassLoader {classname} [arg0] [arg1] ...");
}
}
}
edit: Я уже рассмотрел эти вопросы:
- Как изменить CLASSPATH в Java?
- Можно ли «добавить» к пути к классам динамически в java ?
- Добавление файлов в путь к классам java во время выполнения.
edit: Я подумал, что то, что kdgregory говорит ниже, правильно, что как только я использую свой загрузчик классов явно (см. строку в коде с [***] в качестве комментария), весь код, выполняемый из этого класса, вызовет неявную загрузку классов из того же загрузчика классов. Однако мой DynClassLoader0.loadClass () никогда не вызывается, кроме как во время самого внешнего явного вызова.