提起JVM,大家應該腦海中浮現出下面這個結構圖
Jvm結構中元空間和堆是線程共享 ,其他是線程私有.
我們編寫的java源代碼,先編譯成了二進制字節碼,在通過類加載器放到了Jvm中運行。
元空間:類的一些信息都放在了元空間,比如字段,靜態屬性,方法,常量等。
堆:類創建的實例對象都放到堆,例如通過new出來的對象,jdk8後 原來的永久區內的字符串常量也移到了堆。
一篇文章帶你瞭解堆GC
堆內存診斷:
jps工具 :查看當前系統中有哪些java進程
jmap工具:查看堆內存佔用情況
jconsole工具:圖形界面,多功能監測工具,可連續監測
堆裏的對象調用方法時又會用到程序計數器,虛擬機棧,本地方法棧。
虛擬機棧:想象成子彈夾,子彈都是先壓進去後出來,並且只能使用最頂部的那顆子彈。JVM是基於棧結構的運行環境。
程序在執行方法時,會向內存中申請開闢一個空間,稱之爲棧幀,我們把每個方法的當初一顆子彈壓入虛擬機棧中。
虛擬機棧包含:
- 局部變量表:存放方法參數和局部變量的區域
- 操作棧:初始化狀態爲空的桶式結構棧,相當於戰鬥的士兵
- 動態連接:每個棧中包含一個放在常量池中的對當前方法的引用
- 方法返回地址:方法的退出,相當於子彈射擊後出退出彈夾。
一個彈夾是有容量限制的,如果子彈過多會導致裝不進去,所以棧幀過多導致棧內存溢出。
如果一顆子彈又特別特別大,可能也會導致裝不進去了,所以棧幀過大也可能導致棧內存溢出。
程序計數器:用來記住下一條jvm指令的執行地址,此區域不會發生內存溢出
解釋器:方法執行時每行代碼通過它來解釋成機器可以看懂的機器碼
即時編譯器:方法裏面重複調用的熱點代碼,會由JIT編譯優化
GC:對堆裏面不在引用的對象進行垃圾回收
本地方法接口:調用底層操作系統的功能方法。