java內(nèi)存模型

方法區(qū)和對所有線程共享的內(nèi)存區(qū)域;java棧、本地方法棧和程序計(jì)數(shù)器運(yùn)行是線程私有的內(nèi)存區(qū)域

? ? ?java堆:是java虛擬機(jī)管理內(nèi)存最大的一塊。java堆被所有線程共享的內(nèi)存區(qū)域。虛擬機(jī)啟動(dòng)創(chuàng)建。幾乎所有對象實(shí)例都在這里分配內(nèi)存。

? ? ?方法區(qū):是各個(gè)線程共享的內(nèi)存區(qū)域,用于存儲(chǔ)已被虛擬機(jī)加載的類信息、常量、靜態(tài)變量、即時(shí)編譯器編譯后的代碼數(shù)據(jù)。

? ? ?程序計(jì)數(shù)器:是一小塊內(nèi)存空間,作用可以看做當(dāng)前線程所執(zhí)行的字節(jié)碼的行號(hào)指示器。

? ? ?jvm棧: 虛擬機(jī)棧描述的是java方法執(zhí)行的內(nèi)存模型:每個(gè)方法被執(zhí)行的時(shí)候都會(huì)同時(shí)創(chuàng)建一個(gè)棧幀用于存儲(chǔ)局部變量表、操作棧、動(dòng)態(tài)鏈接、方法出口等信息。每個(gè)方法被調(diào)用直至執(zhí)行完成的過程,對應(yīng)著一個(gè)棧幀在虛擬機(jī)棧中從入棧的過程。

? ? 本地方法棧:則是為虛擬機(jī)使用到的native放大服務(wù)。

面試題

JVM知識(shí)(http://blog.csdn.net/u012257955/article/details/70890702)

1.什么情況下會(huì)發(fā)生棧內(nèi)存溢出?

? ? ?類中和引用變量過多使用了Static修飾

? ? ?使用了大量的遞歸或無限遞歸

? ? ?使用了大量循環(huán)或死循環(huán)

? ? ?是否使用了向數(shù)據(jù)庫查詢所有記錄的方法,數(shù)據(jù)量大超過10萬多條造成內(nèi)存溢出。

? ? ?是否使用了“非字面量字符串進(jìn)行+”的操作。因?yàn)镾tring類的內(nèi)容是不可變的,每次運(yùn)行"+"就會(huì)產(chǎn)生新的對象,如果過多會(huì)造成新String對象過多,從而導(dǎo)致JVM沒有及時(shí)回收而出現(xiàn)內(nèi)存溢出

2.JVM堆內(nèi)存結(jié)構(gòu)分配

? ? ?jvm堆內(nèi)存分為新生代和舊生代。新生代分為Eden區(qū)和Survivor區(qū)。

? ? ?新生代通常占JVM堆內(nèi)存的1/3,新生代存儲(chǔ)新創(chuàng)建對象,比較小對象,老年代存是比較大活的久的對象,老年代占的內(nèi)存比較大。新生代里的Eden區(qū)通常占年輕代的4/5,兩個(gè)Survivor分別占新生代的1/10

? ? 2.1 講解一下當(dāng)對象A創(chuàng)建之后,對象A在各個(gè)區(qū)之間的流轉(zhuǎn)過程

? ? ? ?1) 對象A被new出來之后,是被存放在Eden區(qū)的。

? ? ? ?2) 當(dāng)發(fā)生一次GC之后,Eden區(qū)存活下來的對象A會(huì)被復(fù)制到Survivor 1區(qū)(此時(shí)Survivor 1為To Survivor);Survivor 0 (此時(shí)為From Survivor)中存活的對象也會(huì)被復(fù)制到Survivor 1中。

? ? ? ?3) GC會(huì)清空Eden和Survivor 0 (即From Survivor)中存儲(chǔ)的所有對象。因?yàn)镋den和Survivor 0 中存活的對象都被復(fù)制到 Survivor 1中了,所以清空是沒問題的。

? ? ? ?4) 交換Survivor 0和Survivor 1的角色:即此時(shí)有數(shù)據(jù)的Survivor 1作為From Survivor,被清空的Survivor 0作為To Survivor。要保證在GC發(fā)生之前,To Survivor永遠(yuǎn)是空的那個(gè)

? ? ? 5) 下次GC發(fā)生時(shí),重復(fù)上述步驟。將Eden中存活的對象復(fù)制到To Survivor,將From Survivor中活的對象也復(fù)制到To Survivor。

? ? ? 6)當(dāng)一個(gè)對象在Survivor中存活了很久就會(huì)在發(fā)生GC時(shí)被復(fù)制到舊生代中。這樣做的好處減少內(nèi)存碎片。新生代這種算法是標(biāo)記-復(fù)制算法

老年代采用標(biāo)記-清除算法(產(chǎn)生許多內(nèi)存碎片)

3. JVM的內(nèi)存結(jié)構(gòu)

JVM內(nèi)存結(jié)構(gòu)分為兩種類型

? ? ?線程安全:虛擬機(jī)棧、本地方法棧、程序計(jì)數(shù)器

? ? ?非線程安全:堆、方法區(qū)

? ? ?虛擬機(jī)棧:每個(gè)java方法執(zhí)行時(shí),都會(huì)在內(nèi)存中創(chuàng)建空間存儲(chǔ)java方法中的局部變量和方法的出入口等信息。

? ? ?本地方法棧:每個(gè)調(diào)用本地方法(java調(diào)用非java代碼的接口)時(shí),用來存儲(chǔ)本地方法中的局部變量,方法的出入口信息;

? ? ?程序計(jì)數(shù)器: 當(dāng)前程序執(zhí)行class文件的行號(hào)指示器,通過控制來決定下一段要執(zhí)行的字節(jié)碼指令,跳轉(zhuǎn),循環(huán),異常處理

? ? ?堆:每個(gè)對象創(chuàng)建都在堆上進(jìn)行堆分為新生代,老生代。新生代有一個(gè)Eden和兩個(gè)Survivor組成,默認(rèn)比例是8:2。也可以使用-XXSurvivorRatio來改變百分比

? ? ?方法區(qū):用來存放類的版本,類的方法還有static修飾的對象等信息

? ?jvm參數(shù):-Xms:初始堆大小 ?-Xmx:堆最大內(nèi)存 -Xss:棧內(nèi)存 -XX:PermSize 初始永久帶內(nèi)存 -XX:MaxPermSize 最大永久帶內(nèi)存

4. 當(dāng)出現(xiàn)了內(nèi)存溢出,你怎么排錯(cuò)

? ? ? ?首先查看控制臺(tái)錯(cuò)誤日志,使用jdk自帶的工具查看系統(tǒng)系統(tǒng)堆棧日志,定位內(nèi)存溢出的空間確定是堆、棧還是永生代,如果堆內(nèi)存查看是否創(chuàng)建大對象,如果是棧內(nèi)存溢出查看是否產(chǎn)生死循環(huán)

5.JVM內(nèi)存模型的相關(guān)知識(shí)了解多少,比如重排序,內(nèi)存屏障,happen-before,主內(nèi)存,工作內(nèi)存等

? ? 重排序:jvm在不影響代碼最終結(jié)果的情況下,可以亂序執(zhí)行

? ? 內(nèi)存屏障:可以阻擋編譯器優(yōu)化,也可以阻擋處理器優(yōu)化。按照內(nèi)存屏障規(guī)則禁止重排序(是CPU指令,用于控制特定條件下重排序呵呵內(nèi)存可見性)

happens-before原則:

? ?1.單線程A操作在B之前,多線程下A肯定在B之前

? ?2.monitor在加鎖情況下,持有鎖肯定先執(zhí)行。

? ?3.volatile修飾,寫先于讀發(fā)生

? ?4.線程啟動(dòng)在之前start,死亡在一切之后end。線程操作在一切中斷之前

? ?5.一個(gè)對象構(gòu)造函數(shù)結(jié)束都該對象finalizer的開始前

? ? 6.傳遞性

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容