我有一个自定义类加载器,如下所示
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class MyClassLoader extends ClassLoader
{
public String invoke(final String className, final String methodName, final String someString)
{
try {
final ClassLoader classLoader = getClass().getClassLoader();
final Class loadedClass = classLoader.loadClass(className);
final Constructor constructor = loadedClass.getConstructor();
final Object myClassObject = constructor.newInstance();
final Method method = loadedClass.getMethod(methodName, String.class);
final Object testStr = method.invoke(myClassObject, someString);
System.out.println(loadedClass.getClassLoader());
return (String) testStr;
}
catch (final ClassNotFoundException e) {
e.printStackTrace();
}
catch (final Exception e) {
e.printStackTrace();
}
return null;
}
}
和一个名为Bus
的类public class Bus
{
public static String connection(final String incoming)
{
return "Bus " + incoming;
}
}
和测试代码的Tester类
public class Tester
{
public static void main(final String[] args) throws InterruptedException
{
for (int i = 0; i < 3; i++) {
final MyClassLoader mcl = new MyClassLoader();
final String s = mcl.invoke("Bus", "connection", "awesome");
System.out.println("Tester: " + s);
Thread.sleep(300);
}
}
}
问题:为什么MyClassLoader中的sysout总是打印相同的对象(a.k.a类加载器)?我做错了什么?
我想要实现的是Tester类中的每次迭代,我希望将Bus类加载到新的类加载器中
答案 0 :(得分:2)
您的自定义类加载器MyClassLoader
使用loadClass(String className)
的{{1}}方法。java.lang.ClassLoader
loadClass
方法的工作原理是委派,唯一性和可见性。首先你的自定义ClassLoader
检查父classLoader是否已经加载了类。由于你还没有定义MyClassLoader的父classLoader,它需要{{1}使用MyClassLoader
的getSystemClassLoader()。所以实际上,你的类被SystemClassLoader加载,所有的对象都由一个Classloader加载。通过唯一性原则,每个类都是仅由父母或其自身加载一次。
http://docs.oracle.com/javase/7/docs/api/java/lang/ClassLoader.html#ClassLoader()
您的MyClassLoader目前如何运作: -
SystemClassLoader
使用java.lang.ClassLoader
加载类
public class MyClassLoader extends ClassLoader
{
//supplied by compiler
public MyClassLoader(){
super();
}
}
的默认构造函数
java.lang.ClassLoader
java.lang.ClassLoader 的 SystemClassLoader
方法: -
protected ClassLoader() {
this.parent = getSystemClassLoader();
initialized = true;
}
答案 1 :(得分:1)
您需要实现自己的类加载器,而不是仅使用System类加载器。这是一种相当简单的方法,只有在类文件位于预期目录中时才有效。
public class MyClassLoader extends ClassLoader
{
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
try {
byte b[] = Files.readAllBytes(Paths.get("target/classes/"+name+".class"));
ByteBuffer bb = ByteBuffer.wrap(b);
return super.defineClass(name, bb,null);
} catch (IOException ex) {
return super.loadClass(name);
}
}
public String invoke(final String className, final String methodName, final String someString)
{
try {
final ClassLoader classLoader = this;
...