ps: 主要參考?jvm原理
1.jvm為什么保存在操作系統(tǒng)的堆中,而不是棧中?
????????操作系統(tǒng)的堆一般由程序(應(yīng)用)控制釋放,若程序(應(yīng)用)不釋放,程序(應(yīng)用)結(jié)束時可能由OS回收,分配方式類似于鏈表。而棧是由操作系統(tǒng)自動分配釋放,主要存放函數(shù)的參數(shù)值,局部變量值等。操作方式與數(shù)據(jù)結(jié)構(gòu)中的棧相類似。而操作系統(tǒng)的棧是由操作系統(tǒng)管理的,可能隨時進行回收。而要對棧做到自動釋放也是jvm需要考慮的,所以放在堆中就最合適不過了。
2. java虛擬機的生命周期
? ? ? ? java虛擬機的起點會隨著一個java應(yīng)用啟動而啟動,而當虛擬機實例中的所有非守護進程都結(jié)束是,jvm虛擬機的實例才結(jié)束生命。
3.jvm與java應(yīng)用的關(guān)系
? ? ? ? 啟動多少個java應(yīng)用,就啟動了多少個虛擬機。是一對一的關(guān)系。
4. jvm的線程(參考:java守護線程和非守護線程)
? ? jvm存在兩張線程,一種是非守護線程(用戶線程),一種為守護線程。jvm最典型的守護線程就是GC。jvm中只要有非守護進程存在,jvm就不會退出。如果java應(yīng)用主線程已經(jīng)關(guān)閉,但是子線程還在運行,那么jvm就不會退出。
5. GC回收機制
? ? ? 不是創(chuàng)建的變量為空,就進行回收,而是超出了變量的作用域。
6. full Gc 發(fā)生的時機
? ? ?.老年代內(nèi)存空間不足,
? ? ?.新生代往老年代存放的對象占據(jù)內(nèi)存大于當前老年代剩余的可用內(nèi)存空間
7. 了解堆內(nèi)存
? ? 分為三部分,為新生區(qū),養(yǎng)老區(qū)和永久代
新生區(qū): 是一個類誕生、成長和消亡的區(qū)域。新生區(qū)又分為兩部分:伊甸區(qū)(Eden space)和幸存者區(qū)(Survivor pace),所有的類都是在伊甸區(qū)被new出來的。幸存區(qū)有兩個:0區(qū)(Survivor 0 space)和1區(qū)(Survivor 1 space)。當伊甸園的空間用完時,程序又需要創(chuàng)建對象,JVM的垃圾回收器將對伊甸園進行垃圾回收(Minor GC),將伊甸園中的剩余對象移動到幸存0區(qū)。若幸存0區(qū)也滿了,再對該區(qū)進行垃圾回收,然后移動到1區(qū)。那如果1去也滿了呢?再移動到養(yǎng)老區(qū)。若養(yǎng)老區(qū)也滿了,那么這個時候?qū)a(chǎn)生Major GC(FullGCC),進行養(yǎng)老區(qū)的內(nèi)存清理。若養(yǎng)老區(qū)執(zhí)行Full GC 之后發(fā)現(xiàn)依然無法進行對象的保存,就會產(chǎn)生OOM異?!癘utOfMemoryError”。
如果出現(xiàn)java.lang.OutOfMemoryError: Java heap space異常,說明Java虛擬機的堆內(nèi)存不夠。原因有二:
? ??a.Java虛擬機的堆內(nèi)存設(shè)置不夠,可以通過參數(shù)-Xms、-Xmx來調(diào)整。
? ???b.代碼中創(chuàng)建了大量大對象,并且長時間不能被垃圾收集器收集(存在被引用)。
?②?養(yǎng)老區(qū)
? ? ? ?? 養(yǎng)老區(qū)用于保存從新生區(qū)篩選出來的 JAVA 對象,一般池對象都在這個區(qū)域活躍。
? ③?永久區(qū)
? ? ? ?? 永久存儲區(qū)是一個常駐內(nèi)存區(qū)域,用于存放JDK自身所攜帶的 Class,Interface 的元數(shù)據(jù),也就是說它存儲的是運行環(huán)境必須的類信息,被裝載進此區(qū)域的數(shù)據(jù)是不會被垃圾回收器回收掉的,關(guān)閉 JVM 才會釋放此區(qū)域所占用的內(nèi)存。
? ???如果出現(xiàn)java.lang.OutOfMemoryError: PermGen space,說明是Java虛擬機對永久代Perm內(nèi)存設(shè)置不夠。原因有二:
? ???a.?程序啟動需要加載大量的第三方j(luò)ar包。例如:在一個Tomcat下部署了太多的應(yīng)用。
? ? ?b. 大量動態(tài)反射生成的類不斷被加載,最終導(dǎo)致Perm區(qū)被占滿。