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
- 類加載之後的
連接階段
- 類加載之後的