JVM学习笔记 番外2 - 类加载器的一些梳理
类加载器的双亲:
- 类加载器中的父子关系,并不是 java 对象中的继承关系;
双亲委派机制的意义:
- 避免类的重复加载,当父加载器已经加载过了就不会再加载了,保证每个类对象只有一份;
- 保证 java 核心 API 的安全性,避免被篡改
- 若网络中有一个类 java.lang.Object 被要求加载进内存,子类加载器会委派给双亲加载器直至到 bootstrap classloader,根类加载器会查询内存中已加载的类对象,发现已加载过就不会再次加载而是直接返回已经存在的类,防止核心 api 库被篡改;
用户不能以 java.、javax.、sun.* 为开头的包名 定义类,避免混淆;
package java.cat;
public class MyObject {
}
package new_package.jvm.test;
import java.cat.MyObject;
public class ClassLoaderTest {
public static void main(String[] args) {
ClassLoader classLoader2 = MyObject.class.getClassLoader();
System.out.println(classLoader2);
}
}
Exception in thread "main" java.lang.SecurityException: Prohibited package name: java.cat
at java.lang.ClassLoader.preDefineClass(ClassLoader.java:662)
at java.lang.ClassLoader.defineClass(ClassLoader.java:761)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)
at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at new_package.jvm.bv1o7411v7DS.ClassLoaderTest.main(ClassLoaderTest.java:19)
ClassLoader 类中的四个关键方法:
- loadClass
- 双亲委派的实现
- 轻易不要覆盖此方法
- findClass
- 自定义类加载器,主要实现的方法
- defineClass
- 根据 byte[] 转换成 jvm 能识别的 Class 对象
- resolveClass
- 类加载之后的
连接阶段
- 类加载之后的