ClassLoader加载器
JVM提供三种加载器:Bootstrap(根加载器,也称系统类加载器)、PlatformClassLoader类加载器(平台类加载器)|| ExtClassLoaderr类加载器(平台类加载器) JDK 1.8、AppClassLoader(应用程序类加载器)
JVM为什么提供三种类加载器
答:为了系统安全,设置了不同级别的的类加载器,在装载类的时候,采用的是“全盘负责委托机制"。不同加载器加载不同的类。
获取根加载器
/**
* 根加载器不是java编写的,而是C++编写的。所以输出:null
*/
public class Main {
public static void main(String[] args) {
String str="sdugfu";
System.out.println(str.getClass().getClassLoader());
}
}
输出:null
三个加载器的验证
public class Main2 {
}
public class Test {
public static void main(String[] args) {
Main2 main2 = new Main2();
System.out.println(main2.getClass().getClassLoader());
System.out.println(main2.getClass().getClassLoader().getParent());
System.out.println(main2.getClass().getClassLoader().getParent().getParent());
}
输出:
sun.misc.Launcher$AppClassLoader@18b4aac2
sun.misc.Launcher$ExtClassLoader@1540e19d
null
自定义加载类
public class Message {
public void send(){
System.out.println("发生消息");
}
}
package com.wu.类加载器.自定义类加载器;
import java.io.*;
public class MyClassLoader extends ClassLoader {
private static final String MESSAGE_CLASS_PATH="C:\\1\\out\\production\\1\\com\\wu\\类加载器\\自定义类加载器\\Message.class";
/**
* 进行指定类操作
* @param className
* @return
* @throws Exception
*/
public Class<?> loadData(String className) throws Exception {
byte[] data = this.loadClassData(); //读取二进制
if (data!=null){
//开始读取
return super.defineClass(className,data,0,data.length);
//生成了Class文件
}
return null;
}
/**
* 相当于加载Class文件
* 通过文件进行类加载
* @return
*/
private byte[] loadClassData() throws Exception {
InputStream inputStream=null;
ByteArrayOutputStream bos=null;
byte[] data =null;
try {
bos=new ByteArrayOutputStream(); //实例化内存流
inputStream=new FileInputStream(new File(MESSAGE_CLASS_PATH)); //文件流加载
inputStream.transferTo(bos); //读取数据 。transferTo 1.9 才有的属性
data=bos.toByteArray(); //字节数据取出
} catch (Exception e) {
e.printStackTrace();
}finally {
if (inputStream!=null){ //关闭
inputStream.close();
}
if (bos!=null){ //关闭
bos.close();
}
}
//返回读取到的数据
return data;
}
}
package com.wu.类加载器.自定义类加载器;
import java.lang.reflect.Method;
/**
* 测试自定义加载类
* 并证明先使用自己定义的
*/
public class Test {
public static void main(String[] args) throws Exception {
MyClassLoader myClassLoader = new MyClassLoader();
Class<?> aClass = myClassLoader.loadData("com.wu.类加载器.自定义类加载器.Message");
Object o = aClass.getDeclaredConstructor().newInstance();
System.out.println(o.getClass().getClassLoader());
System.out.println(o.getClass().getClassLoader().getParent());
System.out.println(o.getClass().getClassLoader().getParent().getParent());
Method method = aClass.getMethod("send");
method.invoke(o);
}
}