JVM new Object() 都做了什么?類是怎么被加載到內(nèi)存的?

比起死板的理論,我更喜歡靈活的代碼操作,畢竟程序不是靜態(tài)的,程序是靜態(tài)的,是千變?nèi)f化的,每一行代碼,在不同時間執(zhí)行都可能產(chǎn)生不同的結(jié)果,每學(xué)一個理論,最終都需要踐踏實地的實踐,或是應(yīng)用在項目中,或是自己寫一個小demo,有了輸出,才有了更好的收獲。

今天寫一些new Object()做了哪些事

首先簡單寫一個方法

public class ObjectDemo {
    public static void main(String[] args) {
        Object obj = new Object();
    }

}

然后找到這個類的class文件地址

執(zhí)行javac - p ObjectDemo 輸出字節(jié)碼(匯編碼)

 Code:
    0: new           #2                  // class java/lang/Object
    3: dup
    4: invokespecial #1                  // Method java/lang/Object."":
    7: astore_1
    8: return

上面就是計算機(jī)要執(zhí)行的匯編碼

一 從匯編碼的角度解釋這個過程

  1. new 首先jvm看如果沒有對象的class那么就會去找這個class,然后進(jìn)行加載對象中屬性,并且將對象中的每一個屬性,都放到在堆中開辟的內(nèi)存空間中,并且產(chǎn)生一個指針(對象引用),并將這個指針壓入棧中。
  2. dup 上一步將對象引用壓入了棧,現(xiàn)在將這個引用復(fù)制一個,并且也壓入棧,這時候棧中就有了兩個對象引用,但是,他們的分工不同,一個是負(fù)責(zé)設(shè)置屬性值的,另一個是負(fù)責(zé)對象引用的
  3. invokespecial 這一步是用來初始化的,比如構(gòu)造方法,靜態(tài)代碼塊啥的

二 從程序執(zhí)行的角度

  1. 首先檢查這個對象有沒有在metaspace(元空間,他是描述對象信息的數(shù)據(jù),在本地內(nèi)存中分配)下,如果沒有,那么就通過雙親委派機(jī)制,去查找這個對象的class,如果有就加載,如果沒有就報錯,ClassNotFoundException,是不是很熟悉
  2. 分配內(nèi)存空間,找到對象了,就得給對象分配內(nèi)存空間了,計算對象需要空間大小,分配空間
  3. 設(shè)置默認(rèn)值
  4. 設(shè)置對象頭
  5. 執(zhí)行初始化方法,比如構(gòu)造方法。

三 雙親委派

上面提到雙親委派機(jī)制,再簡單說說這個機(jī)制,java的ClassLoader類加載器有三層

  1. Bootstrap classLoader: 主要負(fù)責(zé)加載核心的類庫(java.lang.*等),構(gòu)造ExtClassLoader和
  2. ExtensionClassLoader:主要負(fù)責(zé)加載jre/lib/ext目錄下的一些擴(kuò)展的jar。
  3. ApplicationClassLoader:主要負(fù)責(zé)加載應(yīng)用程序的主函數(shù)類

然后通過一個類分析加載的流程

 protected Class<?> loadClass(String name, boolean resolve)throws ClassNotFoundException
    {
            // 首先,檢查是否已經(jīng)被類加載器加載過
            Class<?> c = findLoadedClass(name);
            if (c == null) {
                try {
                    // 存在父加載器,遞歸的交由父加載器
                    if (parent != null) {
                        c = parent.loadClass(name, false);
                    } else {
                        // 直到最上面的Bootstrap類加載器
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                    // ClassNotFoundException thrown if class not found
                    // from the non-null parent class loader
                }
                if (c == null) {
                    // If still not found, then invoke findClass in order
                    // to find the class.
                    c = findClass(name);
                }
            }
            return c;
}

意思就是 加載一個類時,先看看自己能不能加載,如果不能加載就看是否存在父加載器,如果存在就判斷父加載器能不能加載如果能就加載如果不能就繼續(xù)向上,如果到頂了還是不能加載,那就向下,判斷子加載器能不能加載,直到找到能夠加載的子加載器,如果找不到就拋出異常。

為什么要這么干呢,主要是防止危險代碼的植入,比如程序運行時,有人串改了String類的實現(xiàn),那么jvm會判斷這個類有沒有被加載,如果加載了就不回加載這個類,那么就不用擔(dān)心被串改了。

四 類加載

類加載是jvn工作的第一步,他的實現(xiàn)過程有幾步

  1. 加載 將class文件以流的形式放到內(nèi)存,并轉(zhuǎn)化為Class實例
  2. 驗證 驗證這些類是否合規(guī),類型是否正確
  3. 準(zhǔn)備 對靜態(tài)變量分配內(nèi)存,賦值默認(rèn)值
  4. 解析 解析類,確報對象之間相互引用的正確性
  5. 初始化 執(zhí)行類構(gòu)造器方法
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容