######內存區域劃分
-
程序計數器 線程私有
線程私有 用於記錄當前線程執行代碼的位置,如果在執行native方法,則此計數器爲空
此區域不會產生內存溢出 -
java虛擬機棧 -xss
線程私有,每個方法執行時會創建棧幀,用於記錄局部變量、方法出口等信息
棧幀在方法執行時會有出棧入棧過程代表着方法的執行過程
棧溢出: 線程請求的棧深度大於虛擬機的深度拋出
內存溢出:棧長度不可擴展 遞歸調用方法 -
本地方法棧
使用native方法服務 -
java 堆 -Xmx -Xms
線程共享 存放對象實例
內存溢出:循環創建對象 -
方法區(jdk8之前爲永久代,jdk8及以後爲metaspace)-XX:PermSize -XX:MaxPermSize
線程共享,存儲類信息、常量、靜態變量等數據
類的版本 字段、方法、接口
溢出:通過反射不斷實例化動態類 -
運行時常量池(屬於方法區中的一塊)
存放編譯器生成的各種字面量和符號引用
String,intern()方法 相當於將字符串對象搬進常量池-XX:+HeapDumpOnOutOfMemoryError
可以讓虛擬機在內存溢出時dump出當前內存堆轉儲存快照
#####虛擬機及垃圾算法
a.引用計數法
在對象中添加一個引用計數器,當有地方引用這個對象時,加一,引用失效時減一,
引用爲零時獎盃回收(jvm不使用,無法解決相互引用的問題)
b.可達性分析算法
對GCroot進行向下搜索,發現對象不可用時將被清除
可被識別爲GCroot的對象:
虛擬機棧
方法的類屬性引用的對象
常量引用的對象
本地方法棧引用的對象
回收算法:
標記清除算法 單線程
效率問題 會暫停使用線程 進行標記,將可以清除的對象打上標記 在進行清除
複製算法
空間問題 分成倆倆塊區域,先標記,將標記存活的對象複製到另一區域,先前區域清空
標記-整理算法
分代收集算法
老對象長期存活在老年代,大對象直接進老年代
垃圾回收器:
serial 單線程操作 會暫停用戶線程,進行回收
parnew 多線程 多個回收器進行回收 在性能上並不一定比serial強
parallel 採用複製算法(新生代收集器) 多線程 相比parnew提高吞吐量
吞吐量:cpu用於運行用戶代碼的時間與cpu消耗的總時間的比值
= (用戶代碼執行的時間 )/(用戶執行的時間+ 垃圾回收所佔的時間 )
-XX :MaxGcPauseMillils 垃圾收集器最大停頓時間
-XX: GCTimeRatio:吞吐量大小
cms
g1
#####jdk常用工具
#####類加載機制
#######class文件組成
- javac 編譯java代碼
- javap -c 反編譯java文件 打印助記符
- javap -verbose 打印更多信息 分析class字節碼的魔數、版本號、常量池、類信息、類的構造方法、類的方法信息、類的變量及成員變量信息。
使用UE查看class二進制文件
#####字節碼整體結構
1.魔數: 所有class文件的魔數(前四個字節)爲固定值:CA FE BA BE
2.小版本號: 2個字節
3.主版本號:2個字節 jdk1.0的主版本號爲45,往後的版本每增加一個版本這個值加一,比如jdk1.8的值爲52
4.常量池(2+n個字節):緊接着主版本後後面,存儲java類的資源,java中定義的方法和變量信息、字面量及符號引用,final修飾的常量,字段和方法的名稱和描述等
常量池結構:常量池主要由常量池數量和常量池數組共同組成,常量池數量跟在版本後後面,2個字節,常量池數組跟在常量池數量後面,與數組不同,
常量池數組中不同的元素的類型、結構不同,長度也不同。
但是,每一個元素的第一個數據都是一個標誌位u1,佔一個字節。jvm解析常量池時,會根據這個u1類型來獲取元素的具體類型。
常量池數組元素的個數 = 常量池數 - 1
常量池的索引從1開始,常量池數據類型11種
在jvm規範中,每個變量字段都有描述信息,描述信息主要的作用是描述字段的數據類型、方法的參數列表(包括數量、類型、順序)與返回值,根據描述規則,
基本數據類型和代表返回值的void類型都用一個大寫字母表示,對象類型則使用L加對象的全限定名錶示。爲了壓縮字節碼文件的體積,對於基本數據類型,jvm只使用一個大寫字母來表示
B -byte C -char D -double F -float I -int J -long S short Z -boolean V -void L -對象類型,String類表示爲Ljava/lang/String;
對於數組類型來說,每一個維度使用前置的[表示,如int[]被記錄爲[I,String[][]被記錄爲[[Ljava/lang/String;
用描述符描述方法時,按照先參數列表,後返回值的順序來描述。參數列表按照參數的嚴格順序放在一組()之內,如:String getName(int i, String j)的描述符爲:(I,Ljava/long/String)Ljava/lang/String;
5. 訪問標誌(2個字節) 權限修飾符
6. 當前類名(2字節)
7. 父類名(2字節)
8. 接口信息(2+n個字節)
9. 字段信息(2+n個字節)
10. 方法信息(2+n個字節)
11. 屬性信息(2+n個字節)