方法區->類信息,靜態變量
堆->數組對象java
虛擬機棧-> 方法
本地方法棧->本地方法庫 native面試
線程隔離 ,比較小的內存空間,當前線程所執行的字節碼的行號
線程是一個獨立的執行單元,由 CPU執行
惟一沒有 OOM 的地方,由虛擬機維護,因此不會出現 OOM算法
執行的是Java方法segmentfault
方法的調用就是棧幀入虛擬機棧的過程
棧幀:局部變量表(變量) 、操做數棧(存放a+b的結果 )、 動態連接(對對象引用的地址),方法出口(return的值)
線程請求的棧深度大於虛擬機所容許的深度StackOverflowError數組
執行的是 native 方法的一塊 java內存區域,同樣有 棧幀
hotspot將 Java 虛擬機棧和本地方法棧合二爲一
jvm標準是 java 虛擬機棧和本地方法棧分開安全
java內存中存放對象實例的區域,幾乎全部的對象實例都在這裏分配
全部線程共享
新生代、老年代
jmap -heap pid;多線程
各個線程共享的內存區域
存儲已被虛擬機加載的類的信息、常量、靜態變量、即時編譯器編譯後的代碼等數據
Hotspot用永久代實現方法區(讓垃圾回收器能夠管理方法區),對常量池的回收和卸載
方法區會拋出 OOM,當他沒法知足內存分配需求時併發
運行時常量池是方法區的一部分,Class 中除了字段、方法、接口的 常量池,存放編譯器生成的字面量和符號引用,這部份內容由類加載後進入方法區的運行時常量池中存放。app
StringTable是HashSet結構
方法區的一部分,受到方法區的限制,依然會 OOMjvm
<init> -> static方法 static代碼塊
1) 指針碰撞(內存比較整齊)
步驟:1. 分配內存 2. 移動指針,非原子步驟可能出現併發問題,Java虛擬機採用 CAS 配上失敗重試的方式保證更新操做的原子性
2)空閒列表(內存比較亂)
存儲堆內存空閒地址
步驟:1.分配內存 2. 修改空閒列表地址 非原子步驟可能出現併發問題,Java虛擬機採用 CAS 配上失敗重試的方式保證更新操做的原子性
對象屬性的值->實例數據
對象頭 64 位機器存 64 位,32 位機器存 32 位,8 的倍數
對比:
當對象實例分配給一個變量時,該變量計數設置爲 1,當任何其餘變量被賦值爲這個對象的引用的時,計數+1 (a =b,則b的引用對象實例計數器+1),當一個對象實例的某個引用超過了生命週期(方法執行完)或者被設置爲一個新值,則該對象的實例引用計數器 -1
沒法解決循環引用
可達性分析
GC Root (虛擬機棧中的引用的對象、本地方法棧中引用的對象、方法區靜態屬性引用的對象、方法區常量引用的對象)
標記須要回收的對象,在標記完成後統一回收
不足:
1.效率問題,標記清除 2 個過程效率都不高
2.空間問題,標記清除後產生大量不連續的內存碎片,碎片過多當程序須要分配較大的對象時,沒法找到足夠的連續內存而不得不提早觸發一次垃圾回收動做
內存塊 A存活的對象複製到內存塊 B (Survivor to)裏,而後將內存塊A (Eden + Survivor from)清空,
只有少部分對象移動,更多的對象是要被回收的
Eden:Survivor from:Survivor to=8:1:1
98%對象「朝生夕亡」,新生代可用內存容量 90%(80%+10%),98%的對象可回收是通常狀況,當小於 90%的對象被回收的時候(10%以上的對象存活時),則 Survivor to 空間不夠,則須要依賴老年代進行分配擔保
老年代不適合複製算法
步驟:
單線程垃圾回收器,用戶線程到安全點先暫定,而後 GC 線程單線程串行進行,等 GC 線程回收完,而後用戶線程再繼續
特色:Stop the world
場景:桌面應用 (gc時間短)
用於新生代,client 端
Serial收集器的多線程版本
用於新生代,惟一能和CMS 收集器配合工做,運行在 server 模式下
-XX:ParallelGCThreads 限制垃圾收集器線程數 = CPU 核數(過多會致使上下文切換消耗)
並行:多條垃圾收集線程並行工做,用戶線程仍然處於等待狀態
併發:用戶線程與垃圾收集器同時執行,用戶線程和垃圾線程在不一樣 CPU 上執行
新生代收集器,複製算法,並行的多線程收集器
關注吞吐量優先的收集器(吞吐量 = CPU 運行用戶代碼執行時間/CPU 執行總時間 ,好比: 99%時間執行用戶線程,1%時間回收垃圾,這時吞吐量爲 99%)高吞吐量能夠高效率利用 CPU 時間,儘快完成程序的運算任務,適合在後臺運算而不須要太多的交互任務
CMS 關注縮短垃圾回收停頓時間,適合與用戶交互的程序,良好的響應速度能提高用戶體驗
-XX:MaxGCPauseMillis 參數 GC 停頓時間,參數太小會頻繁 GC
-XX:GCTimeRatio 參數,默認 99%(用戶線程時間佔 CPU 總時間的 99%)
是Serial 收集器的老年代版本
單線程老年代收集器,採用「標記-整理」算法
是 Parallel Scavenge收集器的老年代版本
多線程老年代收集器,採用「標記-整理」算法
獲取最短回收停頓時間爲目標的收集器,採用「標記-清除」算法,用於互聯網、B/S 系統重視響應的系統
步驟:
缺點 :
面向服務端應用的垃圾收集器
Region->Remembered Set (解決 循環引用 )
檢查 Reference (程序對reference類型寫操做,檢查 reference 引用類型)
步驟:
優點:
Java 堆分佈圖
對象分配的規則:
大對象是指須要大量連續內存空間的 Java 對象,最典型的大對象是是那種很長的字符串以及數組
-XX:PretenureSizeThreshold 設置大於該值的對象直接分配在老年代,避免在 Eden 區以及 2 個Survivior區之間發生大量的內存複製
逃逸分析:分析對象動態做用域,當一個對象在方法中被定義後,它可能被外部方法所引用,稱爲方法逃逸。甚至還有可能被外部線程訪問到,好比賦值給類變量或其餘線程中訪問的實例變量,稱爲線程逃逸。
棧上分配:把方法中的變量和對象直接分配到棧上,方法執行完後自動銷燬,不須要垃圾回收介入,從而提升系統性能
-XX:+DoEscapeAnalysis 開啓逃逸分析(jdk1.8默認開啓 )
-XX:-DoEscapeAnalysis 關閉逃逸分析
jmap -heap 9366;
jmap -histo 9366 | more; 顯示堆中對象統計
jmap -dump:format=b,file=/Users/mousycoder/Desktop/a.bin 9366 生成dump文件
-Xmx20m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/Users/mousycoder/Desktop/
jhat /Users/mousycoder/Desktop/java_pid9783.hprof 圖形分析Heap
select s.toString() from java.lang.String s where (s.value != null && s.value.length > 1000 )
shutdownHook 在關閉以前執行的任務
jstack -l -F pid 強制輸出
基於 JMX 的可視化監視、管理工具
開啓 JMX 端口
nohup java -Xms800m -Xmx800m -Djava.rmi.server.hostname=192.168.1.250 -Dcom.sun.management.jmx
remote.port=1111 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -jar hc-charging-
server.jar &
互聯網開發流程
Jconsole 內存分析思考過程
Minor GC:當 Eden 區滿,觸發 Minor GC
FullGC:
建議:
解決方法:list.contain->set.contain->布隆過濾器(用戶量大和用戶量小系統解決方案不同)
解決方法:jstack 以及 new thread帶上名稱
FullGC 出現正常頻率爲一天 1~2 次
解決方案:jmap , heap dump on oom + jhat
heap堆使用率很低,可是有 OOM 以及 Full GC
解決方法:btrace ,directMemory增大
解決方案: MQ
結構:
1.魔數
2.class 文件版本
3.常量池
4.訪問標誌
5.類索引、父類索引、接口索引集合
6.字段表集合
7.方法表集合
8.屬性表集合
CAFEBABE
棧幀指向該棧所屬方法引用
invokestatic、invokespecial、invokevirtual、invokeinterface、invokedynamic
編譯期間決定,主要是重載,支持最優選擇重載
針對重寫
## 動態語言支持
多線程中重排序用同步來保證,否則會出現莫名其妙問題