以下內容:并非作者自己總結,勿噴
android大概了解這些
總結:JVM運行時數據區主要有 私有區域 java棧(先進后去,里面有N個棧幀) 本地棧(native棧), 程序計數器
共享區域 方法區: 存放 類信息 常量 靜態變量 即時編譯期編譯后的代碼
堆:new出來的對象
一:JVM是什么?
可以理解成只是一個翻譯;
它可以跨平臺,跨語音; 各種語言編譯成字節碼,然后通過JVM運行到各種平臺上;
二:JVM的跨平臺與語言無關性
JVM的跨平臺
JVM的語言無關性
三:JVM的整體
JVM的運行過程
java文件 --》javac翻譯,生成class文件,通過類加載器classLoader,JVM會把class加載到運行時數據區(內存),在通過執行引擎
到操作系統上;
JVM就是把字節碼翻譯成機器碼
四:什么是運行時數據區?
Java虛擬機在執行Java程序的過程中會把它所管理的內存劃分為若干個不同的數據區域
它有如下類型
程序計數器、虛擬機棧、本地方法棧、Java堆、方法區(運行時常量池)、直接內存
- 1,白色部分就是線程私有的;
- 2,灰色部分不受線程控制的,共享區域;
線程私有區域
4.1 程序計數器
指向當前線程正在執行的字節碼指令的地址
記錄某個線程當前程序運行到那個位置;如圖
4.1 .1:為什么需要這個程序計數器?
答:JVM是個軟件,有可能程序在跑的時候,cpu被切換出去了(時間輪轉機制),無論單線程還是多線程,有可能程序被終止,這個時候需要記錄程序運行到哪一行;
4.1 .2:JVM內存區域中 唯一不會OOM ;
答: 因為它要記錄一個地址;
4.2 虛擬機棧(JAVA棧)
- 比較重要的一片區域;存儲當前線程運行方法所需的數據,指令、返回地址;
- 它具有先進后出的特點
- 有大小限制
4.2.1:什么是棧幀?
- 虛擬機棧比喻成子彈夾,那棧幀就是子彈;一個方法對應一個棧幀;如圖上面的 運行內存區域.png
- 它包括:局部變量表, 操作數棧 , 動態連接, 完成出口
java 解釋執行是棧(操作數棧)兼容性好,效率偏低,c是寄存器(硬件運算)。移植性差
4.3 本地方法棧(native區)
本地方法棧保存的是native方法的信息,
本地方法棧跟 Java 虛擬機棧的功能類似,Java 虛擬機棧用于管理 Java 函數的調用,而本地方法棧則用于管理本地方法的調用。但本地方法并不是用 Java 實現的,而是由 C 語言實現的。
當一個JVM創建的線程調用native方法后,JVM不再為其在虛擬機棧中創建棧幀,JVM只是簡單地動態鏈接并直接調用native方法
虛擬機規范無強制規定,各版本虛擬機自由實現 HotSpot直接把本地方法棧和虛擬機棧合二為一
線程共享的區域
4.4方法區
存放以下數據
- 類信息
- 常量
- 靜態變量
- 即時編譯期編譯后的代碼
4.4 堆(java堆)
- 對象實例(幾乎所有)
- 數組
Java堆的大小參數設置
-Xmx 堆區內存可被分配的最大上限
-Xms 堆區內存初始內存分配的大小
4.4:為什么共享區域不共用一個區域要分方法區和堆?
堆:對象和數組,頻繁的回收;
直接內存
不是虛擬機運行時數據區的一部分,也不是java虛擬機規范中定義的內存區域;如果使用了NIO,這塊區域會被頻繁使用,在java堆內可以用directByteBuffer對象直接引用并操作;
這塊內存不受java堆大小限制,但受本機總內存的限制,可以通過-XX:MaxDirectMemorySize來設置(默認與堆內存最大值一樣),所以也會出現OOM異常。
五:從底層深入理解運行時數據區
上面代碼內存分布圖如下:
六:深入辨析堆和棧
功能角度:
- 以棧幀的方式存儲方法調用的過程,并存儲方法調用過程中基本數據類型的變量(int、short、long、byte、float、double、boolean、char等)以及對象的引用變量,其內存分配在棧上,變量出了作用域就會自動釋放;
- 而堆內存用來存儲Java中的對象。無論是成員變量,局部變量,還是類變量,它們指向的對象都存儲在堆內存中;
線程獨享還是共享:
- 棧內存歸屬于單個線程,每個線程都會有一個棧內存,其存儲的變量只能在其所屬線程中可見,即棧內存可以理解成線程的私有內存。
- 堆內存中的對象對所有線程可見。堆內存中的對象可以被所有線程訪問。
空間大小
棧的內存要遠遠小于堆內存
六:內存溢出
棧溢出
StackOverflowError 遞歸容易出現堆溢出
內存溢出:申請內存空間,超出最大堆內存空間。
如果是內存溢出,則通過 調大 -Xms,-Xmx參數。
如果不是內存泄漏,就是說內存中的對象卻是都是必須存活的,那么久應該檢查JVM的堆參數設置,與機器的內存對比,看是否還有可以調整的空間,再從代碼上檢查是否存在某些對象生命周期過長、持有狀態時間過長、存儲結構設計不合理等情況,盡量減少程序運行時的內存消耗。方法區溢出
(1) 運行時常量池溢出
(2)方法區中保存的Class對象沒有被及時回收掉或者Class信息占用的內存超過了我們配置。本機直接內存溢出
直接內存的容量可以通過MaxDirectMemorySize來設置(默認與堆內存最大值一樣),所以也會出現OOM異常;
由直接內存導致的內存溢出,一個比較明顯的特征是在HeapDump文件中不會看見有什么明顯的異常情況,如果發生了OOM,同時Dump文件很小,可以考慮重點排查下直接內存方面的原因。
七:虛擬機優化技術
編譯優化技術——方法內聯
方法內聯的優化行為,就是把目標方法的代碼原封不動的“復制”到調用的方法中,避免真實的方法調用而已。
棧的優化技術——棧幀之間數據的共享
在一般的模型中,兩個不同的棧幀的內存區域是獨立的,但是大部分的JVM在實現中會進行一些優化,使得兩個棧幀出現一部分重疊。(主要體現在方法中有參數傳遞的情況),讓下面棧幀的操作數棧和上面棧幀的部分局部變量重疊在一起,這樣做不但節約了一部分空間,更加重要的是在進行方法調用時就可以直接公用一部分數據,無需進行額外的參數復制傳遞了。