java虛擬機(jī)內(nèi)存溢出及泄漏實(shí)例
測(cè)試參數(shù)設(shè)置:
1、循環(huán)調(diào)用new A()實(shí)現(xiàn)堆溢出,java.lang.OutOfMemoryError: Java heap space,
虛擬機(jī)參數(shù):-Xms1M -Xmx1M -XX:+HeapDumpOnOutOfMemoryError,解釋:將-Xmx和-Xms設(shè)置為一樣可以避免堆自動(dòng)擴(kuò)展,-XX:+HeapDumpOnOutOfMemoryError可以讓虛擬機(jī)在出現(xiàn)內(nèi)存溢出異常時(shí)Dump出當(dāng)前的堆內(nèi)存轉(zhuǎn)儲(chǔ)快照
// while (true){ // new A().do2(); // }
2、循環(huán)調(diào)用對(duì)象引用的方式實(shí)現(xiàn)棧溢出。java.lang.StackOverflowError,
虛擬機(jī)參數(shù):-Xss128k,
解釋:設(shè)置虛擬機(jī)棧的大小為128kn
在單線程下,無論棧幀太大還是虛擬機(jī)棧容量太小,內(nèi)存無法分配的時(shí)候都會(huì)拋出以上錯(cuò)誤
void do2(){ do2(); };
3、循環(huán)調(diào)用String.intern()方法來寫入常量池,常量池溢出。java.lang.OutOfMemoryError: PermGen space
while (true) { list.add(String.valueOf(i++).intern()); }
虛擬機(jī)參數(shù):-XX:PermSize=10M -XX:MaxPermSize=10M,
解釋:表示JVM初始分配的永久代的容量和最大容量。(永久區(qū)內(nèi)存不足,1.8后都在堆上。方法區(qū)=永久代,PermGen space”,即永久代)
四種引用狀態(tài):(類繼承extends WeakReference<Car>)
1、強(qiáng)引用:Object obj = new Object(),只要強(qiáng)引用還存在,垃圾收集器永遠(yuǎn)不會(huì)回收掉被引用的對(duì)象;
2、軟引用:SoftReference,被軟引用關(guān)聯(lián)的對(duì)象會(huì)在內(nèi)存不夠時(shí)被回收。如果這次回收還沒有足夠的內(nèi)存,才會(huì)拋出內(nèi)存溢出異常;SoftReference<byte[]> sr = new SoftReference<byte[]>(bytes);
3、弱引用:WeakReference,被弱引用關(guān)聯(lián)的對(duì)象只能生存到下一次垃圾回收之前;
4、虛引用:PhantomReference,虛引用是用于跟蹤對(duì)象的回收狀態(tài)。
觸發(fā)GC的時(shí)機(jī):
1、當(dāng)年輕代或者老年代滿了,Java虛擬機(jī)無法再為新的對(duì)象分配內(nèi)存空間了,那么Java虛擬機(jī)就會(huì)觸發(fā)一次GC去回收掉那些已經(jīng)不會(huì)再被使用到的對(duì)象
2、System.gc(),Runtime.getRuntime().gc()方法,通常這樣會(huì)觸發(fā)一次的Full GC以及至少一次的Minor GC,不一定就立即回收。
3、在當(dāng)前服務(wù)器空閑或堆中老年代等占用率較大時(shí)觸發(fā)。
回收無引用對(duì)象占據(jù)的空間,而不是對(duì)象本身。
但真正垃圾回收機(jī)制具體在什么時(shí)間點(diǎn)開始發(fā)生動(dòng)作這同樣是不可預(yù)料的(未開源),這和搶占式的線程在發(fā)生作用時(shí)的原理一樣。
分代收集算法:
新生代收集器和老年代收集器。
標(biāo)記-清除算法
標(biāo)記-整理算法
內(nèi)存溢出和內(nèi)存泄露的區(qū)別:
1、內(nèi)存溢出:程序在分配內(nèi)存的時(shí)候沒有足夠大的空間了。
2、內(nèi)存泄漏:程序在申請(qǐng)內(nèi)存之后,沒有辦法釋放掉內(nèi)存,它始終占用著內(nèi)存,即被分配的對(duì)象可達(dá)但無用。內(nèi)存泄露一般都是因?yàn)閮?nèi)存中有一塊很大的對(duì)象,但是無法釋放。 會(huì)導(dǎo)致內(nèi)存溢出。
并行與并發(fā):
1、并行:指多條垃圾收集器線程運(yùn)行;
2、并發(fā):指用戶線程和垃圾收集器線程同時(shí)工作。
類加載機(jī)制:
1、加載(生成java.lang.class對(duì)象)、驗(yàn)證、準(zhǔn)備、解析、初始化(賦值過程)、使用(Using)和卸載(Unloading)這7個(gè)階段
2、其中驗(yàn)證(字節(jié)流包含的信息是否正確,是否符合jvm)、
準(zhǔn)備(為類變量即靜態(tài)變量賦值,賦0)、
解析(將符號(hào)引用替換為直接引用,class文件轉(zhuǎn)內(nèi)存)3個(gè)部分統(tǒng)稱為連接(Linking)
3、加載階段:獲取.class文件的二進(jìn)制流;
將類信息、靜態(tài)變量、字節(jié)碼、常量這些.class文件中的內(nèi)容放入方法區(qū)
在內(nèi)存中生成一個(gè)代表這個(gè).class文件的java.lang.Class對(duì)象,作為方法區(qū)這個(gè)類的各種數(shù)據(jù)的訪問入口。
4、初始化階段做的事就是調(diào)用client>方法給static變量賦予用戶指定的值以及執(zhí)行靜態(tài)代碼塊。
雙親委派模型:(啟動(dòng)類加載器>擴(kuò)展類加載器>應(yīng)用程序類加載器>自定義類加載器)
一個(gè)類加載器收到了類加載的請(qǐng)求,把這個(gè)請(qǐng)求委派給父類加載器去完成,父類完不成,自己才去完成。
先行發(fā)生原則:
Java內(nèi)存中的有序性僅僅依靠synchronized和volatile來約束是不行,依靠程序調(diào)用次序規(guī)則判斷setter和getter順序。
Minor GC : 清理年輕帶內(nèi)存, 無法為一個(gè)新的對(duì)象分配空間。
Major GC : 是清理老年代,許多 Major GC 是由 Minor GC 觸發(fā)的
Full GC : 是清理整個(gè)堆空間—包括年輕代和老年代
相關(guān)文章
SpringBoot實(shí)戰(zhàn)之處理異常案例詳解
這篇文章主要介紹了SpringBoot實(shí)戰(zhàn)之處理異常案例詳解,本篇文章通過簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-09-09springboot程序啟動(dòng)慢-未配置hostname的解決
這篇文章主要介紹了springboot程序啟動(dòng)慢-未配置hostname的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08java實(shí)現(xiàn)簡(jiǎn)單驗(yàn)證碼生成
這篇文章主要介紹了java實(shí)現(xiàn)簡(jiǎn)單驗(yàn)證碼生成,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-10-10java 獲取request中的請(qǐng)求參數(shù)代碼詳解
這篇文章主要介紹了java 獲取request中的請(qǐng)求參數(shù)的方法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值 ,需要的朋友可以參考下2019-05-05SpringBoot集成Redisson實(shí)現(xiàn)延遲隊(duì)列的場(chǎng)景分析
這篇文章主要介紹了SpringBoot集成Redisson實(shí)現(xiàn)延遲隊(duì)列,本文通過場(chǎng)景分析實(shí)例代碼相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-04-04