一個程序大概執行流程:
jvm主要分爲三個部分(執行過程):類裝載子系統 -> jvm內存模型(運行時數據區中:淺藍色爲線程私有,灰黃色爲線程共有) -> 執行引擎
現在通過下面的這個例子來更加深刻的理解上面的流程
-
1、java代碼編譯生成字節碼文件(編譯器)
-
2、jvm調用字節碼文件,啓動類裝載子系統
-
3、加載完成以後來到程序的入口:main方法
-
4、我們看到,main方法主要做了兩件事兒,一:創建math類的實例,(new 關鍵字會將math實例存儲在 堆 中),二:調用compute方法。
-
4.1、這裏在重提一下堆的內存空間,堆分爲了年輕代(三分之一)和老年代(三分之二)
-
4.2、新建的對象先會進入Eden(伊甸園區…),滿了之後會進行一波minor gc(執行引擎),然後沒有回收掉的一些東西會進入from,form滿了會進入to(survivor區不會出發GC,並且 總有一個區(from,to)是空的,因爲他們是複製的,該數據15次之後就會進入老年區),然後進入老年區,(注意,老年的區的曲線圖應該是一直增長,然後不變(滿了)),老年代垃圾清理是 full GC,當所有區都滿了就會報錯,
各位可以自己去做個試驗 (循環創建新的對象) ,下面的數據圖來源(visualvm)
-
-
5、創建好實例,去調用compute方法時,會將對應的一系列的變量存入 棧 中。(棧用來存放一些運行時的局部變量)
-
6、進入compute方法,就進入了棧
我們通過反彙編,拿到反彙編代碼。可以看到,compute方法的詳細執行流程 可以通過:jvm指令手冊 來查看具體的含義
具體而言就是做了如下的事情:將1壓入操作數棧(iconst_1,此命令中的數字1代表的是第一個位置的局部變量的意思),然後在賦值給局部變量表中給的a(istore_1),2也同理,指令前面的數字就是程序計數器 所記錄的數字,一步步的執行結束以後,會將執行的結果返回(ireturn),也就到了方法出口;
idea中怎麼查看class的反彙編代碼?
1、找到你想反彙編的class文件,一般在target文件下,點擊 open in terminal
2、鍵入命令:javap -c s.class > s.txt
,javap -c
是反編譯文件的命令(自帶),s.class
是指定我們反編譯的字節碼文件,> s.txt
在當前目錄生成反編譯好的txt文件。(javap -v可以生成更加詳細的反編譯代碼)3、然後在對應的目錄下就可以看到生成的反彙編代碼
7、最後的流程:
我們可以看到,運行時數據區(即內存模型)之間是相互有聯繫的