1. 类加载器的作用
通过一个类的全限定名来获取描述此类的二进制字节流
我们通过代码看一下“加载”过程
public static void main(String[] args){
ClassLoader myLoader = new ClassLoader() {
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
try {
//1. 根据类的全限定名获取定义此类的二进制字节流
String fileName = name.substring(name.lastIndexOf(".")+1)+".class";
InputStream is = getClass().getResourceAsStream(fileName);
if (is == null)
return super.loadClass(name);
byte[] b = new byte[is.available()];
is.read(b);
//2. 将字节流转化为方法区的运行时数据结构
return defineClass(name, b, 0, b.length);
}catch (IOException e) {
throw new ClassNotFoundException(name);
}
}
};
//3. 在内存中生成一个类的Class对象
Object obj = myLoader.loadClass("类的全路径");
}
注意class对象其实是存在方法区中的呀
2. 如何确定一个类的唯一性
需要由加载它的类加载器+类本身
3. 类加载器的种类
- 启动类加载器(Bootstrap ClassLoader)是虚拟机自身的一部分
启动类加载器只会加载在<JAVA_HOME>\lib目录中的,或在指定路径中的,并且是虚拟机识别的类库加载到虚拟机中
画个重点,后面会考哦~ - 扩展类加载器
- 应用程序类加载器
- 自定义类加载器
4. 双亲委派模式有什么用?
- Java类随着类加载器一起具备了优先级,无论哪一级类加载器要加载类C,都由同一个类加载器执行加载
- 书中给了个反例,比如我们自己写了一个java.lang.Object,系统中存在了两个Object类,加载器会不知道该加载哪个类
而在双亲委派模式中,这个自定义的Object类永远都不会被加载运行,因为它不是虚拟机能识别的类啊(黄字)