java进程内存一直没释放_面试官:一个线程OOM,进程里其他线程还能运行么?...
引言
這題是一個網(wǎng)友@大臉貓愛吃魚給我的提問,出自今年校招美團(tuán)三面的一個真題。大致如下
一個進(jìn)程有3個線程,如果一個線程拋出oom,其他兩個線程還能運(yùn)行么?先說一下答案,答案是還能運(yùn)行
不瞞大家說,真在面試中,我遇到這一題,我估計也是答錯。因為我初看到這一題,內(nèi)心嘿嘿一笑,覺得這題是在考察JVM的內(nèi)存結(jié)構(gòu)。我第一反應(yīng)是OOM的常見情況堆溢出,也就是下面的這種異常
java.lang.OutOfMemoryError: Java heap space先回憶一下,多線程中棧與堆是公有的還是私有的?回答如下
在多線程環(huán)境下,每個線程擁有一個棧和一個程序計數(shù)器。棧和程序計數(shù)器用來保存線程的執(zhí)行歷史和線程的執(zhí)行狀態(tài),是線程私有的資源。其他的資源(比如堆、地址空間、全局變量)是由同一個進(jìn)程內(nèi)的多個線程共享。也就是說,堆是線程共享。那么一個線程堆拋出OOM異常,我第一反應(yīng)是另外兩個線程也拋出OOM異常,畢竟堆是共有的,大家應(yīng)該都拋出異常。于是,我機(jī)智的讓@大臉貓愛吃魚寫個代碼去測試一下,結(jié)果我被啪啪啪打臉了。
測試代碼偽如下
一個線程去構(gòu)造堆溢出,每隔1S申請一次堆,代碼長下面這樣
new Thread(() -> {List<byte[]> list=new ArrayList<byte[]>();while(true){System.out.println(new Date().toString()+Thread.currentThread()+"==");byte[] b = new byte[1024*1024*1];list.add(b);try {Thread.sleep(1000);} catch (Exception e) {e.printStackTrace();}} }).start();另一個線程,睡眠1秒然后輸出就好,代碼長下面這樣
new Thread(() -> {while(true){System.out.println(new Date().toString()+Thread.currentThread()+"==");try {Thread.sleep(1000);} catch (Exception e) {e.printStackTrace();}} }).start();結(jié)果,輸出是長下面這樣的
大家發(fā)現(xiàn)了么,一個線程溢出了,其他線程還在跑,這好像和我們的認(rèn)知不大一樣。坦白說,我看到這個結(jié)果,瞬間覺得自己一世英名毀于一旦,從此無法抬起頭來做人。沒辦法了,只能亮出工具來看一下了。
先說一下,在本例測試中,參數(shù)如下
-Xms16m -Xmx32m -Xms 初始堆內(nèi)存 -Xmx 最大堆內(nèi)存接下來,亮出JvisualVM看堆的變化,注意看上面那張圖,拋出OOM的時間約在00:11:45左右,因此我們需要重點關(guān)注00:11:45左右的曲線變化,如下圖所示
如圖所示,我們仔細(xì)觀察一下在00:11:44~00:11:45之間曲線變化,你會發(fā)現(xiàn)使用堆的數(shù)量,突然間急劇下滑!這代表著一點,當(dāng)一個線程拋出OOM異常后,它所占據(jù)的內(nèi)存資源會全部被釋放掉,從而不會影響其他線程的運(yùn)行!
講到這里大家應(yīng)該懂了,此題的答案為一個線程溢出后,進(jìn)程里的其他線程還能照常運(yùn)行。
寫在最后:
更多關(guān)于Java的技術(shù)和資訊可以關(guān)注我的專欄:
Java架構(gòu)筑基?zhuanlan.zhihu.com專欄免費給大家分享Java架構(gòu)的學(xué)習(xí)資料和視頻
總結(jié)
以上是生活随笔為你收集整理的java进程内存一直没释放_面试官:一个线程OOM,进程里其他线程还能运行么?...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: jmeter 核心_初识性能测试工具JM
- 下一篇: 大华web对接文档_分分钟了解Web接口