JVM 小結
JVM
-
1、JVM 的位置
-
執行在作業系統之上的
-
java程式是排在 jre(jvm) 上的
-
所謂的JVM 調優就是在堆裡面調,方法區就是 一個特殊的堆
-
-
2、JVM 的體系結構
-
3、類的載入器
- 作用
-
載入 class 檔案
-
類載入器分為好幾個,有等級
- 1、虛擬機器自帶的載入器
- 2、啟動類(根)載入器
- 3、擴充套件類載入器
- 4、應用程式(系統類)載入器
-
- 作用
-
4、雙親委派機制
-
當某個類載入器需要載入 .class 檔案時,它首先把這個任務委託給他們的上級類載入器,遞迴這個操作,如果上級的類載入器沒有載入,自己才會載入這個類
-
作用:
- 1、防止重複載入同一個 .class。通過委託去向上面問一問,載入過了,就不用再載入一遍。保證資料安全
- 2、保證核心 .class 不能被篡改,通過委託方式,不會去篡改核心 .class 。即使篡改也不會去載入,即使載入也不會是同一個 .class 物件了,不同的載入器載入同一個 .class 也不是同一個 Class 物件,這樣保證了 Class 執行安全。
-
類載入的過程和使用那個載入器
- 1、類載入器收到類載入的請求
- 2、將這個請求向上委託給父類載入器去完成。一直向上委託,直到啟動類載入器
- 3、啟動類載入器檢查是否能夠載入當前這個類,能載入就結束,使用當前的類載入器,否則,丟擲異常,通知子載入器進行載入
-
-
5、沙箱安全機制
-
6、Native
-
JNI (本地方法介面) java native interface
-
// native :
1、凡是帶了 native 關鍵字的,說明 java 的作用範圍達不到了,會去呼叫底層 C 語言的庫
2、會進入本地方法棧,呼叫 JNI, 呼叫本地方法庫,
JNI 的作用就是擴充套件 java 的使用,融合不同的語言為 java 所用,最初是 C、C++
所以在記憶體中開闢了一塊區域,為了登記 native 方法,
3、呼叫其他介面其實還可以使用 Socket、WebService、http、rpc 、restful
-
-
-
7、PC 暫存器
- 程式計數器:Program Counter Register
- 每個執行緒都有一個程式計數器,就是一個指標,指向方法區中的位元組碼(用來儲存儲存指向像一條指令的地址,也即將要執行的指令程式碼),在執行引擎讀取下一條指令, 是一個非常小的記憶體空間,幾乎可以忽略不計
-
8、方法區
-
Method Area:
-
方法區是被所有的執行緒共享,所有欄位和方法位元組碼,以及一些特殊方法,如建構函式,介面程式碼也在此定義,簡單說,所有定義的方法的資訊都儲存在該區域,此區域屬於共享區間,
-
靜態變數、常量、類資訊(構造方法、介面定義),執行時的常量存在方法區中,但是例項變數存在堆記憶體中,和方法區無關
說白了就是:
staic、 final、Class、常量池、、、
-
-
-
-
9、棧
-
資料結構。棧和佇列進行比較
-
棧:先進後出,後進先出
-
所以為什麼 main 方法最後退出?
-
棧溢位、遞迴問題(死迴圈)、無限壓棧 、壓棧超過了棧的深度
-
棧:
-
何時發生棧記憶體溢位?
- 對於一臺伺服器而言,每一個使用者請求,都會產生一個執行緒來處理這個請求,每一個執行緒對應著一個棧、棧會分配記憶體,此時如果請求過多,這時候記憶體就不夠了,就會發生記憶體溢位
-
什麼時候會發生棧溢位 ?
-
棧溢位是指不斷的呼叫方法,不斷的壓棧,最終超出了棧允許的棧的深度,最終超出了棧允許的棧深度,就會發生棧溢位,比如遞迴操作沒有終止,死迴圈
-
-
幫助記憶:
- 可以把記憶體你做一個大箱子,棧比作一個小箱子,棧溢位是指小箱子裝不下了,而棧記憶體溢位是大箱子在也裝不下小箱子了
-
主管程式的執行,生命週期和執行緒同步
-
執行緒結束,棧記憶體你就會釋放
-
對於棧來說,沒有垃圾回收的問題
-
棧裡面放的東西:
- 8 大基本型別+ 物件引用 + 例項的方法
-
棧執行原理:
-
棧、堆、方法區的互動關係
- 棧是類模板,堆是物件例項
-
-
-
佇列: 先進先出 (FIFO)
-
-
10、三種 JVM
- Sun 公司 HotSpot
- IBM J9VM
- BEA JRockit
-
11、堆
-
堆的圖
- 邏輯上存在,物理空間上不一定存在
-
heap、一個 jvm 只有一個堆記憶體,對記憶體的大小是可以調節的
-
12、新生區(伊甸園區)、老年區 、倖存區0, 倖存區1
- 新生區是類誕生和成長的地方,甚至死亡
- 多有的物件都是在一點園區new出來的
-
-
GC 垃圾回收,主要是在伊甸園區和老年區
-
假設記憶體滿了、OOM、java.lang.OutOfMemoryError: java heap space
-
無限字串的例子 - 其實也就是無限 new 物件:
-
VM 引數除錯
-
-
13、永久區
-
這個區域常駐記憶體的,用來存放 jdk 自身攜帶的 Class 物件,Interface 元資料,儲存的是 java 執行時的一些環境或類資訊,這個區域不存在垃圾回收,關閉虛擬機器就會釋放這個區域的記憶體
-
什麼情況下在永久區就崩了呢?
-
一個啟動類載入了大量的第三方 jar 包,tomcat 部署了太多的應用,或者大量動態生成的反射類,不斷的被載入,直到記憶體滿了,就出現 OOM
-
jdk1.6之前: 叫永久代,常量池是在方法區
-
jdk1.7: 永久帶,但是慢慢的退化了,去永久代,常量池在堆中
-
jdk1.8之後:無永久代,常量池在元空間
-
在一個專案中,突然出現 OOM 故障,那麼該如何排除 - 研究為什麼出錯?
-
能夠看到程式碼第幾行出錯:
-
記憶體快照分析工具,MAT、Jprofiler
-
debug: 只能一行行的分析程式碼
-
MAT、Jprofiler作用
- 分析 Dump、記憶體檔案,快速定位記憶體洩漏
- 獲得對中的資料
- 獲得大的物件
-
-
-
-
14、對記憶體調優
-
15、GC (自動垃圾回收機制)
-
Jvm 在進行 GC 時,並不是對以下三個區域統一回收,大部分時候,回收都是新生代,
- 新生代
- 辛存區( from \ to)
- 老年區
- GC 兩種型別: 輕GC(普通 GC), 重 GC (全域性 GC)
-
GC 的題目 :
-
1、JVM 的記憶體模型和分割槽 - 詳細到每個區放什麼?
- 堆
- 方法區
- 本地方法棧
- PC 計數器
- 棧
-
2、堆裡面的分割槽有哪些?
- 新生區(伊甸園)
- 倖存區(from\ to),誰空誰是 to
- 老年區
-
3、GC 的演算法有哪些?
- 標記清除法
- 標記壓縮
- 複製演算法
- 引用計數器
-
4、輕 GC 和 重 GC 分別在什麼時候發生?
-
-
常用演算法
-
16、JMM
-
1、什麼是 JMM?
- Java Memory model Java 記憶體模型
-
2、幹嘛的?
-
作用:快取一致性協議,用於定義資料讀寫的規則(遵守,找到這個規則)
-
JMM 定義了執行緒的主記憶體之間的抽象關係:執行緒之間的共享變數儲存在主記憶體(Main Memory)中,每個執行緒都有一個私有的本地記憶體(Local Memory)
-
CPU 中執行的執行緒從主存中拷貝共享物件 obj 到它的 CPU 快取,把物件 obj 的 count 變數改為 2,但每個變數對執行在右邊 CPU 中的執行緒不可見,因為這個更改還沒有 flush 到主存中,要解決共享物件可見性這個問題,我們可以用 java volilate 關鍵字或者加鎖
-
解決共享物件可見性這個問題: volilate
-
-
3、如何學習?
-
JMM: 抽象的概念 - 理論
-
-
-
17、總結
-
記憶體效率:
- 效率最高: 複製演算法 > 標記清除演算法 > 標記壓縮演算法
- 記憶體整齊度: 複製演算法 = 標記壓縮演算法 > 標記清除演算法
- 記憶體利用率: 標記壓縮演算法 = 標記清除演算法 > 賦值演算法
-
思考一下, 難道沒有最優的演算法嗎?
-
沒有,沒有最好的演算法,只有最合適的演算法 --->
-
分代收集演算法
-
每一代都有不同的演算法
-
年輕代:
- 存活率低
- 複製演算法
-
老年代:
-
區域大: 存活率
-
標記清除(記憶體碎片不是太多) + 標記壓縮混合 實現
-
-
-
-