我只知道双亲委派机制还有可以自写个类加载器,其它的一脸懵逼。
我自写的类加载器,以及从应用类加载器调用自写类加载器加载的那个类的main方法代码如下:
package classloadertest;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* 父类加载器加载子加载器
* @author LENOVO
*
*/
public class MyLoader extends ClassLoader{
MyLoader(){
}
MyLoader(ClassLoader parent){//父加载器一个默认构造
super(parent);
}
/**
* 重写这个即可,不破坏双亲委派模型
*/
@Override
public Class<?> findClass(String name) {
FileInputStream in;
try {
in = new FileInputStream(
new File("E:\\java\\class\\web-inf\\" + name.replace( '.', '\\')+".class"));
ByteArrayOutputStream out = new ByteArrayOutputStream();
int ch = 0;
while ((ch = in.read()) != -1) {
out.write(ch);
}
byte[] data = out.toByteArray();
return defineClass(name, data, 0, data.length);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
MyLoader myLoader=new MyLoader(null);
try {
Class<?> c=myLoader.loadClass("test2.Test2");//返回的就是class
//class.forname
//A.class
Object t2=c.newInstance();//因为不能导入另一个classpath下的包,所以定位为obj对象
System.out.println("test2类加载器:"+t2.getClass().getClassLoader());
System.out.println("当前运行线程的加载器:"+Thread.currentThread().getContextClassLoader());//当前运行线程的加载器
for(int i=0;i<t2.getClass().getMethods().length;i++) {
System.out.println(t2.getClass().getMethods()[i]);
}
// System.out.println(System.getProperty("java.system.class.loader"));
// System.out.println("当前程序classLoader名:"+getSystemClassLoader());
// System.out.println("系统引导程序clsPath:"+System.getProperty("sun.boot.class.path"));
// System.out.println("拓展程序clsPath:"+System.getProperty("java.ext.dirs"));
// System.out.println("当前java程序的classPath:"+System.getProperty("java.class.path"));
Method[] methods=c.getMethods();//所有的方法,包括父类 基类的方法等等
for(Method method:methods)
{
System.out.println(method.getName());
}
methods=c.getDeclaredMethods();//类自身声明的方法
for(Method method:methods)
{
System.out.println("d-"+method.getName());
}
//获取具体的方法,执行另一个类加载器的代码
Method m=c.getMethod("main", String[].class);
System.out.println(m.getName());
Object o=m.invoke(null,(Object)new String[] {});//静态方法 不需要传实体; 这不就实现了 父加载器调用子加载器的方法了吗?那什么spi为什么说父调不了子呢
System.out.println(o);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
目前很穷,需要尽快提升能力,不能花时间研究这个问题,留待日后再深究。