定義:Java Virtual Machine -java程序的運行環境(java二進制字節碼的運行環境)
好處:
一次編寫,到處運行
自動內存管理,垃圾回收
數組下標越界檢測
多態
比較:jvm/jre/jdk
常見的JVM:HotSpot
學習路線👇
內存結構
1.程序計數器
定義:
Program Counter Register 程序計數器(寄存器)?
(程序計數器)作用:記住下一條jvm指令的執行地址
特點:
線程私有的
不會存在內存移除
2.?虛擬機棧
棧——線程運行需要的內存空間
棧幀——每個方法運行時需要的內存
一個棧由多個棧幀組成
每個線程運行時需要的內存,稱為虛擬機棧
每個棧由多個棧幀組成,每個棧幀對應著每次方法調用時所占的內存
每個線程只能有一個活動棧幀,對應著當前正在執行的那個方法
問題:
1.垃圾回收是否涉及棧內存??
垃圾回收只回收堆內存的無用項。不需要對棧內存進行垃圾回收的處理。
2.棧內存分配越大越好嗎?
棧并不是越大越好,大只是更多次的方法遞歸調用。并不能增加效率,反而會減少線程數量。
3.方法內的局部變量是否線程安全?
如果方法內局部變量沒有逃離方法的作用范圍,他是線程安全的。
如果是局部變量引用了對象,并逃離方法的作用范圍,需要考慮線程安全。
棧內存溢出
棧幀過多導致棧內存溢出(無限遞歸)
棧幀過大導致棧內存溢出
線程運行診斷
案例1:cpu占用過多
定位,用top定位哪個進程對cpu的占用過高
ps H -eo pid,tid,%cpu|grep 進程id(用ps命令進一步定位是哪個線程引起的cpu占用過高)
jstack 進程id(可以根據線程id找到有問題的線程,進一步定位到問題代碼的源碼行號)
案例2:程序運行很長時間沒有結果
jstack 進程id,可能是多個線程發生了死鎖
3.本地方法棧
Java虛擬機調用本地方法,需要給這些本地方法提供內存。
本地代碼,不是用java編寫的。Java有限制,不能直接和操作系統打交道,就需要由c或c++編寫的本地方法,來真正的和操作系統底層的API打交道。native?
4.堆
通過new關鍵字,創建的對象都會使用堆內存
特點:
它是線程共享的,堆中對象都需要考慮線程安全的問題。
有垃圾回收機制。
堆內存溢出
對象被當成垃圾回收的條件是沒有人使用他,如果不斷地產生對象,而產生的新對象永遠有人在使用,這樣的對象達到一定數量,就會導致堆內存耗盡。
堆內存診斷
工具:
19_堆_內存診斷_jmap_嗶哩嗶哩_bilibili
20_堆_內存診斷_jconsole_嗶哩嗶哩_bilibili
21_堆_內存診斷_jvirsualvm_嗶哩嗶哩_bilibili
5.方法區
方法區是所有Java虛擬機線程共享的區,它存儲了跟類相關的區(成員變量、方法數據、成員方法構造器方法以及他們的代碼)。
方法區在虛擬機啟動時被創建,邏輯上是堆的組成部分。?