1、什麼情況下會發生堆、棧內存溢出。
堆溢出:方法執行時創建的棧幀超過了棧的深度 ,最有可能就是方法遞歸調用。
棧溢出:heap space表示堆空間,堆中主要存儲的是對象。不斷的new對象會導致堆中的空間溢出
2、JVM的內存結構,Eden和Survivor比例。
JVM區域總體分兩類,heap區和非heap區。
heap區又分爲:
- Eden Space(伊甸園)、
- Survivor Space(倖存者區)、
- Old Gen(老年代)。
非heap區又分:
- Code Cache(代碼緩存區);
- Perm Gen(永久代);(jdk1.8爲元空間)
- Jvm Stack(java虛擬機棧);
- Local Method Statck(本地方法棧);
1個Eden區和2個Survivor區(分別叫from和to)。默認比例爲8:1
3、JVM內存爲什麼要分成新生代,老年代,持久代。新生代中爲什麼要分爲Eden和Survivor。
Eden和Survivor的比例是8:1.
首先說如果沒有Survivor區會出現什麼情況:此時每觸發一次Minor GC,就會把Eden區的對象複製到老年代,這樣當老年代滿了之後會觸發Major Gc(通常伴隨着MinorGC,可以看做Full GC),比較耗時。
如果只有1個Survivor區,那當Eden區滿了之後,就會複製對象到Survivor區,容易產生內存碎片化。嚴重影響性能。
所以使用2個Survivor區,始終保持有一個空的Survivor區,可以避免內存碎片化。
Survivor減少被送到老年代的對象,進而減少Full GC的發生,Survivor的預篩選保證,只有經歷多次Minor GC還能在新生代中存活的對象,纔會被送到老年代。
4、JVM中一次完整的GC流程是怎樣的,對象如何晉升到老年代,說說你知道的幾種主要的JVM參 數。
對象誕生即新生代->eden,在進行minor gc過程中,如果依舊存活,移動到from,變成Survivor,進行標記代數,如此檢查一定次數後,晉升爲老年代。
https://wangkang007.gitbooks.io/jvm/content/jvmcan_shu_xiang_jie.html
5、垃圾回收算法的實現原理
引用計數,標記-清除,標記-整理,複製,分代收集
https://blog.csdn.net/zdp072/article/details/51116081
6、你知道哪幾種垃圾收集器,各自的優缺點,重點講下cms和G1,包括原理,流程,優缺點。
Serial、parNew、ParallelScavenge、SerialOld、ParallelOld、CMS、G1
CMS:
一、初始標記:此時標記需要用戶線程停下來;
二、併發標記:此時標記可以和用戶線程一起運行;
三、重新標記:此時標記需要用戶線程停下來,主要母的是爲了對併發標記的垃圾進行審覈;
四、併發清除:與用戶線程一起與運行進行垃圾清除;
缺點:
1、CMS收集器對cpu資源非常敏感;
2、CMS收集器無法清除浮動垃圾;
3、cms基於標記清除的算法實現的,所以內存碎片會產生過多。
G1收集器:
1、初始標記:標記GC Root能直接關聯的對象,並且修改TAMS的值,讓下一階段的用戶進行併發運行是,能夠正確運用Region創建新對象,這階段需要停頓,但停頓時間很短
2、併發標記:從GC Root開始對堆進行可達性分析,找出存活的對象,這段耗時較長,但可以與用戶線程併發執行。
3、最終標記是爲了修正在併發標記階段因用戶程序繼續運作導致標記產生變動的那一部分的標記記錄,虛擬機將這部分標記記錄在線程Remembered Set中,這階段需要停頓線程,但是可並行執行。
4、篩選回收:首先對各個Region的回收價值和成本進行排序,根據用戶所期待的GC停頓時間來制定回收計劃,這個階段也可以與用戶線程並行執行,但由於只回收一部分的Region,時間是用戶可控制的,而且停頓用戶線程將大幅度提高收集效率。
7、當出現了內存溢出,你怎麼排錯。
首先分析是什麼類型的內存溢出,對應的調整參數或者優化代碼。
https://wangkang007.gitbooks.io/jvm/content/4jvmdiao_you.html
8、JVM內存模型的相關知識瞭解多少,比如重排序,內存屏障,happen-before,主內存,工作 內存等。
- 內存屏障:爲了保障執行順序和可見性的一條cpu指令
- 重排序:爲了提高性能,編譯器和處理器會對執行進行重拍
- happen-before:操作間執行的順序關係。有些操作先發生。
- 主內存:共享變量存儲的區域即是主內存
- 工作內存:每個線程copy的本地內存,存儲了該線程以讀/寫共享變量的副本
9、簡單說說你瞭解的類加載器,可以打破雙親委派麼,怎麼打破。
類加載器 就是根據指定全限定名稱將class文件加載到JVM內存,轉爲Class對象。
- 啓動類加載器(Bootstrap ClassLoader):由C++語言實現(針對HotSpot),負責將存放在\lib目錄或-Xbootclasspath參數指定的路徑中的類庫加載到內存中。
- 其他類加載器:由Java語言實現,繼承自抽象類ClassLoader。如:
- 擴展類加載器(Extension ClassLoader):負責加載\lib\ext目錄或java.ext.dirs系統變量指定的路徑中的所有類庫。
- 應用程序類加載器(Application ClassLoader)。負責加載用戶類路徑(classpath)上的指定類庫,我們可以直接使用這個類加載器。一般情況,如果我們沒有自定義類加載器默認就是用這個加載器。
打破: 線程上下文加載器(Thread Context ClassLoader) 打破雙親委派機制則不僅要繼承ClassLoader類,還要重寫loadClass和findClass方法。
1:自己寫一個類加載器
2:重寫loadclass方法
3:重寫findclass方法
10、講講JAVA的反射機制。
Java程序在運行狀態可以動態的獲取類的所有屬性和方法,並實例化該類,調用方法的功能
11、你們線上應用的JVM參數有哪些。
-server (64位無需此參數)
Xms6000M
-Xmx6000M
-Xmn500M
-XX:PermSize=500M
-XX:MaxPermSize=500M
-XX:SurvivorRatio=65536
-XX:MaxTenuringThreshold=0
-Xnoclassgc
-XX:+DisableExplicitGC
-XX:+UseParNewGC
-XX:+UseConcMarkSweepGC
-XX:+UseCMSCompactAtFullCollection
-XX:CMSFullGCsBeforeCompaction=0
-XX:+CMSClassUnloadingEnabled
-XX:-CMSParallelRemarkEnabled
-XX:CMSInitiatingOccupancyFraction=90
-XX:SoftRefLRUPolicyMSPerMB=0
-XX:+PrintClassHistogram
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-XX:+PrintHeapAtGC
-Xloggc:log/gc.log
12、G1和cms區別,吞吐量優先和響應優先的垃圾收集器選擇。
Cms是以獲取最短回收停頓時間爲目標的收集器。基於標記-清除算法實現。比較佔用cpu資源,切易造成碎片。
G1是面向服務端的垃圾收集器,是jdk9默認的收集器,基於標記-整理算法實現。可利用多核、多cpu,保留分代,實現可預測停頓,可控。 、
https://blog.csdn.net/KilluaZoldyck/article/details/75081875
怎麼打出線程棧信息。
利用jps 、 top 、jstack命令找到進程中耗時最大的線程,以及線程狀態等等,同時最後還可以顯示出死鎖的線程 查找:Found one Java-level deadlock 即可
https://my.oschina.net/liufukin/blog/2222495
請解釋如下jvm參數的含義:
-server -Xms512m -Xmx512m -Xss1024K
-XX:PermSize=256m -XX:MaxPermSize=512m -
XX:MaxTenuringThreshold=20 XX:CMSInitiatingOccupancyFraction=80 -
XX:+UseCMSInitiatingOccupancyOnly。
Server模式啓動
最小堆內存512m
最大512m
每個線程棧空間1m
永久代256
最大永久代256
最大轉爲老年代檢查次數20
Cms回收開啓時機:內存佔用80%
只以CMS的閾值來收集垃圾
註釋:
-XX:+UseCMSInitiatingOccupancyOnly
-XX+UseCMSInitiatingOccupancyOnly標誌來命令JVM不基於運行時收集的數據來啓動CMS垃圾收集週期。而是當該標誌被開啓時,JVM通過CMSInitiatingOccupancyFraction的值進行每一次CMS收集,而不僅僅是第一次。大多數情況下,JVM比我們自己能作出更好的垃圾收集決策。只有當我們充足的理由(比如測試)並且對應用程序產生的對象的生命週期有深刻的認知時,才應使用該標誌。