1、jvm 如何構建一個實例?
創建對象過程:
A a = new A() ;
- 加載類{ClassLoader 加載 .class 文件到內存1. 經過javac 編譯後的 字節碼(.class)文件 被 ClassLoader 加載進內存 (進入方法區);
2. 在方法區中 生成 Class 對象 - Class 對象;
3. 創建實例對象;
4. 將實例對象放入 堆中 ;
執行靜態代碼塊 和 靜態初始化語句} - 執行 new ,申請一片內存空間;
- 調用構造器,創建一個空白對象;
- 子類調用父類構造器;
- 構造器執行{執行構造代碼塊和初始化語句構造器內容}
通過 new 創建實例對象和反射創建實例,都繞不開 Class 對象。
2、類加載器 加載 .class 文件:
分為三步驟:
1. 檢查1是否已經加載,有就直接返回,避免重複加載;
- 當前緩存中確實沒有該類,遵循父優先加載機制,加載 .class文件;
- 上面兩步都失敗,調用 findClass() 方法加載。
注: ClassLoader 類本身是抽象類,不能通過 new 創建對象。因此 ClassLoader 中的 findClass() 方法 只用來拋出異常。就是說 父類 ClassLoader 中的 findClass() 無法加載 .class 文件。
ClassLoader 類中的 findClass() 方法 :
protected Class findClass(String var1) throws ClassNotFoundException { throw new ClassNotFoundException(var1); }
根據需求重寫父類 findClass() 方法。
defineClass() ClassLoader 定義的方法,目的是 根據 .class 文件的字節數組 byte[] b 造出對應的 Class 對象 ( Class )。
2、反射 API 日常開發的主要作用:
- 創建對象
- 反射調用方法
創建實例的難點在於,很多人不知道clazz.newInstance()底層還是調用Contructor對象的newInstance()。所以,要想調用clazz.newInstance(),必須保證編寫類的時候有個無參構造。
關鍵字: 創建對象 ClassLoader 內存