Java ClassLoader類加載器基礎詳解
1. 類加載
- JVM 首次使用某個類時,需通過 ClassPath 查找該類的 .class 文件
- 將 .class 文件中對類的描述信息加載到內存中,進行保存
- 加載時機
- 創(chuàng)建對象
- 創(chuàng)建子類對象
- 訪問靜態(tài)屬性
- 調用靜態(tài)方法
- 主動加載:
Class.forName("full-name")
1.1 class 文件
包名、類名、父類、屬性、方法、構造方法.....
2. 類加載器
- 在運行期間,如果我們要產生某個類的對象,JVM 會檢測該類型的 Class 對象是否已被加載; 如果沒有加載,JVM 會根據類的名稱找到 .class 文件并加載它
- Class 對象代表 Java 應用程序在運行時所加載的類或接口實例,每加載一個類,
JVM自動生成一個Class對象;
2.1 ClassLoader的分類
- Bootstrap ClassLoader 啟動類加載器(引導類加載器)
- ExtClassLoader 擴展類加載器(Java9 之后改為 Platform Classloader)
- Application Classloader(系統(tǒng)類加載器或應用類加載器)
默認的類加載器 - 自定義類加載器,父類加載器為AppClassLoader
2.2 ClassLoader 層次結構
- 系統(tǒng)類加載器
--父-->擴展類加載器--父-->引導類加載器 - 除了引導類加載器之外,所有的類加載器都有一個父類加載器。 通過 getParent()方法可以得到
注意:父加載器不是父類
2.3 類與類加載器
- 在JVM中表示兩個class對象是否為同一個類對象的兩個必要條件
- 類的全限定名必須一致
- 加載這個類的ClassLoader必須相同
- 在JVM中,即使這個兩個類對象(class對象)來源同一個Class文件,被同一個虛擬機所加載,但只要加載它們的ClassLoader實例對象不同,那么這兩個類對象也是不相等的
2.3 獲取 ClassLoader
@Test
public void getClassLoader() {
Class<?> clazz = String.class;
ClassLoader classLoader = clazz.getClassLoader();
System.out.println(classLoader);
// null, 根加載器并不是由Java語言實現的,因此拿不到根加載器對象
}@Test
public void getClassLoader2() throws ClassNotFoundException {
// this.getClass().getClassLoader();
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
Class<?> clazz = classLoader.loadClass("com.example.concrete.common.domain.User");
System.out.println(classLoader);
System.out.println(classLoader.getParent());
}打印結果
sun.misc.Launcher$AppClassLoader@18b4aac2
sun.misc.Launcher$ExtClassLoader@51efea79
2.4 獲得class對象的三種方法
方式一:對象.getClass()
String str = "hello"; Class<?> clazz = str.getClass();
方式二:類.classClass<?> clazz = String.class;
方式三:Class. forName() 動態(tài)加載類
// 靜態(tài)方法 forName("類的全限定名")
Class<?> clazz3 = Class.forName("java.lang.String");3. ClassLoader 分析
loadClass(String name)
findClass(String name)
defineClass(String name, byte[] b, int off, int len)
// ClassLoader 的默認實現就是雙親委托
public abstract class ClassLoader {
//每個類加載器都有個父加載器
private final ClassLoader parent;
public Class<?> loadClass(String name) throws ClassNotFoundException {
return loadClass(name, false);
}
protected Class<?> findClass(String name) throws ClassNotFoundException {
throw new ClassNotFoundException(name);
}
protected final Class<?> defineClass(String name, byte[] b, int off, int len) throws ClassFormatError {
return defineClass(name, b, off, len, null);
}
}name: 類的全限定名
public Class<?> loadClass(String name) throws ClassNotFoundException {
return loadClass(name, false);
}
/**
* classpath 就是一組目錄的集合;classpath 是 JVM 用到的一個環(huán)境變量,它用來指示 JVM 如何搜索class
* 在啟動 JVM 時設置 classpath 變量
* java -cp or java -classpath .;C:\work\project1\bin;C:\shared abc.xyz.Hello
* 如果不設置,JVM 默認的 classpath 為. 即當前目錄
*/
String classpath = System.getProperty("java.class.path");
Properties properties = System.getProperties();
Set<String> strings = properties.stringPropertyNames();
for (String string : strings) {
System.out.println(string);
}
/**
* 若以“/”開頭的,表示要從項目的 ClassPath 開始的( /mapper/xxx.xml ),
* 如果前面沒有這個“/”,那么表示的就是相對于該類的路徑繼續(xù)往下
*/
URL resource = classLoader.getResource(""); // file:/.../target/classes/
URL resource1 = classLoader.getResource("bean.xml"); // file:/.../target/classes/bean.xml4. Classpath
- lib 和 classes 同屬 classpath,訪問優(yōu)先級為: lib > classes
- Java 項目 /src 目錄下的文件(*.xml, *.properties)編譯后會放到 WEB-INF/classes 目錄,默認的 classpath 就是 WEB-INF/classes
- WEB-INF/ 是資源目錄,客戶端不能直接訪問
- Maven 項目 resources 目錄下的文件編譯后在
BOOT-INF/classes
4.1 maven 項目 classpath 路徑
Maven 項目目錄
src
|-- main
|-- java
|-- com.xxx
|-- resources
|-- application.yml編譯后目錄
target
|-- classes
|-- com.xxx
|-- application.yml打包的 jar 解壓后目錄
|-- BOOT-INF
|-- classes
|-- com.xxx
|-- application.yml
|-- lib
|-- org.springframework.boot.loader...引用 classpath 路徑下的文件,只需在文件名前加 classpath:
classpath:application-*.xml # 子目錄 classpath:config/*.xml # **/ 表示任意目錄 classpath:**/bean.xml
4.2 classpath vs classpath*
classpath在當前classpath 中查找,只加載第一個 classpath 路徑classpath*不僅包含 class 路徑, 還包括 jar 文件(classpath目錄)classpath*會從所有的classpath中加載文件
classpath:*.xml classpath*:config.xml
以上就是Java ClassLoader類加載器基礎詳解的詳細內容,更多關于Java ClassLoader類加載器的資料請關注腳本之家其它相關文章!
相關文章
Java實現STL中的全排列函數next_permutation()
在算法競賽中,全排列問題是一個經典且常見的題目,傳統(tǒng)的遞歸方法在處理較大的n時會遇到堆棧內存限制的問題,本文介紹了一種避免遞歸,使用next_permutation函數實現全排列的方法,感興趣的朋友跟隨小編一起看看吧2024-09-09
MyBatis-Plus使用ActiveRecord(AR)實現CRUD
本文將結合實例代碼,介紹MyBatis-Plus使用ActiveRecord(AR)實現CRUD,文中通過示例代碼介紹的非常詳細,需要的朋友們下面隨著小編來一起學習學習吧2021-07-07

