我正在研究类路径的动态修改。我找到了一种效果很好的解决方案,但它使用显式调用 addURL() 来实现。(大概在启动时)
但是,如果默认类加载器似乎无法找到类,我想在运行时拦截类加载过程以定位类。我尝试将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 的 findClass() 和 loadClass( ) 被调用?唯一一次调用 loadClass 是在下面的 main() 函数中显式调用 loadClass。
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] ...");
}
}
}
编辑:我已经查看了这些问题:
编辑:我认为 kdgregory 在下面所说的是正确的,一旦我明确使用我的类加载器(参见代码中的行[***]
作为注释),从该类执行的所有代码都将导致来自同一个类加载器的隐式类加载。然而,我的 DynClassLoader0.loadClass() 永远不会被调用,除非在最外层的显式调用期间。