成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

論JVM爆炸的幾種姿勢(shì)及自救方法

hyuan / 620人閱讀

摘要:方法區(qū)溢出在的方法區(qū)中,它主要存放了類(lèi)的信息,常量,靜態(tài)變量等。運(yùn)行結(jié)果簡(jiǎn)單解決思路一般來(lái)說(shuō)此類(lèi)問(wèn)題多出現(xiàn)在存在遞歸的地方,要從代碼里重新審視遞歸未結(jié)束的原因,若遞歸的方法沒(méi)問(wèn)題可以根據(jù)實(shí)際情況調(diào)整參數(shù)的大小。

前言

如今不管是在面試還是在我們的工作中,OOM總是不斷的出現(xiàn)在我們的視野中,所以我們有必要去了解一下導(dǎo)致OOM的原因以及一些基本的調(diào)整方法,大家可以通過(guò)下面的事例來(lái)了解一下什么樣的代碼會(huì)導(dǎo)致OOM,幫助我們以后在工作中能夠通過(guò)異常信息來(lái)判斷是JVM里面哪個(gè)區(qū)域出現(xiàn)了問(wèn)題。

先介紹一下筆者的相關(guān)編碼環(huán)境。

jdk:java version "1.8.0_121"

ide:IntelliJ IDEA 2019.1 (Community Edition)

正文
1.Java堆溢出

Java中的堆存儲(chǔ)的都是對(duì)象實(shí)例,當(dāng)我們不斷的創(chuàng)建對(duì)象,而GC的時(shí)候又不能回收,當(dāng)存儲(chǔ)的對(duì)象大小超過(guò)了-Xmx的值,這時(shí)候則會(huì)出現(xiàn)OutOfMemoryError.[-XX:+HeapDumpOnOutOfMemoryError]參數(shù)可以讓jvm出現(xiàn)內(nèi)存溢出的時(shí)候dump出內(nèi)存堆轉(zhuǎn)儲(chǔ)快照。

/**
 * VM Args: -Xms10m -Xmx10m -XX:+HeapDumpOnOutOfMemoryError
 * @author wangzenghuang
 */
public class HeapOOMDemo {
    public static void main(String[] args) {
        List stringList = new ArrayList<>();
        while(true){
            stringList.add("str");
        }
    }
}

運(yùn)行結(jié)果,發(fā)生OOM,并且在我們項(xiàng)目的根目錄dump出當(dāng)前的內(nèi)存堆快照

java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid1376.hprof ...
Heap dump file created [7972183 bytes in 0.047 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Arrays.java:3210)
    at java.util.Arrays.copyOf(Arrays.java:3181)
    at java.util.ArrayList.grow(ArrayList.java:261)
    at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:235)
    at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:227)
    at java.util.ArrayList.add(ArrayList.java:458)
    at HeapOOMDemo.main(HeapOOMDemo.java:12)

Process finished with exit code 1

簡(jiǎn)單解決思路

那么發(fā)生這個(gè)問(wèn)題以后我們的解決思路有哪些呢?我們可以利用一些工具(例如Eclipse Memory Analyzer
)來(lái)分析dump出的文件,一般來(lái)說(shuō),當(dāng)生產(chǎn)環(huán)境發(fā)生OOM,比較常見(jiàn)的一個(gè)原因是發(fā)生了內(nèi)存泄漏,用工具可以分析出泄露的對(duì)象到GC Root的引用鏈,從而定位到問(wèn)題代碼。假如經(jīng)過(guò)分析后發(fā)現(xiàn)內(nèi)存中的對(duì)象都是“必須存活”的對(duì)象,這時(shí)候就要思考下項(xiàng)目中是否把“-Xms跟-Xmx”設(shè)置得太小了(當(dāng)然這里也不是隨意調(diào)大,需要結(jié)合機(jī)器的物理內(nèi)存情況),再者需要留意代碼中是否有一些長(zhǎng)生命周期的對(duì)象,從代碼中優(yōu)化內(nèi)存消耗。

2.方法區(qū)溢出

在jvm的方法區(qū)中,它主要存放了類(lèi)的信息,常量,靜態(tài)變量等。在jdk8以前是通過(guò)“-XX:PermSize,-XX:MaxPermSize”來(lái)調(diào)整這個(gè)區(qū)域的值,但是從8開(kāi)始呢,永久代的概念被MetaSpace(元空間)代替了,對(duì)應(yīng)的參數(shù)也變成了“-XX:MetaspaceSize,-XX:MaxMetaspaceSize”。在這個(gè)例子中使用CGLib來(lái)動(dòng)態(tài)生成一些類(lèi),方便我們實(shí)驗(yàn)操作。

/**
 * VM Args: -XX:MetaspaceSize=5m -XX:MaxMetaspaceSize=5m
 * @author wangzenghuang
 */
public class MethodAreaOOMDemo {
    public static void main(String[] args) {
        while(true){
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(OOMObject.class);
            enhancer.setUseCache(false);
            enhancer.setCallback(new MethodInterceptor() {
                public Object intercept(Object obj, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                    return methodProxy.invokeSuper(obj,objects);
                }
            });
            enhancer.create();
        }
    }
    static class OOMObject{}
}

運(yùn)行結(jié)果

Exception in thread "main" java.lang.OutOfMemoryError: Metaspace

簡(jiǎn)單解決方法

這個(gè)問(wèn)題的話,一般來(lái)說(shuō)根據(jù)情況調(diào)整方法區(qū)的大小就行了,網(wǎng)上也有人說(shuō)可以去掉MetaSpace的的大小限制,但是不建議這么干,畢竟不可控的事情我們要少點(diǎn)干,很容易給自己埋雷。

3.棧溢出

對(duì)于我們來(lái)說(shuō),還有一個(gè)熟悉的錯(cuò)誤,那就是“StackOverflowError”,它是由線程請(qǐng)求的棧深度超過(guò)了jvm允許的最大范圍而產(chǎn)生的。“-Xss”參數(shù)可以設(shè)置棧容量。

/**
 * VM Args: -Xss128k
 * @author wangzenghuang
 */
public class StackOFDemo {
    private static int stackLength = 1;

    public void stackLeak(){
        stackLength++;
        stackLeak();
    }

    public static void main(String[] args) {
        StackOFDemo stackOFDemo = new StackOFDemo();
        try {
            stackOFDemo.stackLeak();
        }catch (Throwable e){
            System.out.println("length : "+ stackLength);
            throw e;
        }
    }
}

運(yùn)行結(jié)果

length : 983
Exception in thread "main" java.lang.StackOverflowError
    at StackOFDemo.stackLeak(StackOFDemo.java:10)
    at StackOFDemo.stackLeak(StackOFDemo.java:10)
    ...

簡(jiǎn)單解決思路

一般來(lái)說(shuō)此類(lèi)問(wèn)題多出現(xiàn)在存在遞歸的地方,要從代碼里重新審視遞歸未結(jié)束的原因,若遞歸的方法沒(méi)問(wèn)題可以根據(jù)實(shí)際情況調(diào)整“-Xss”參數(shù)的大小。還有一些代碼的循壞依賴(lài)也會(huì)造成此類(lèi)情況,

4.直接內(nèi)存溢出

本機(jī)直接內(nèi)存默認(rèn)與“-Xmx”設(shè)定的值一樣大,可以通過(guò)“-XX:MaxDirectMemorySize”修改。

/**
 * VM Args: -Xmx20m -XX:MaxDirectMemorySize=10
 * @author wangzenghuang
 */
public class DirectMemoryOOMDemo {
    private static final int _1MB = 1024 * 1024;

    public static void main(String[] args) throws IllegalAccessException {
        Field field = Unsafe.class.getDeclaredFields()[0];
        field.setAccessible(true);
        Unsafe unsafe = (Unsafe) field.get(null);
        while (true){
            unsafe.allocateMemory(_1MB);
        }
    }
}

運(yùn)行結(jié)果

呃,一運(yùn)行這段代碼idea直接閃退了,查閱其他資料可以得知當(dāng)DirectMemory導(dǎo)致內(nèi)存溢出時(shí),Heap Dump文件是很小的,如果程序中有使用NIO的情況可以檢查一下。

總結(jié)

這里所展示的代碼只是可以觸發(fā)jvm的各種錯(cuò)誤,但是并不代表這是唯一的觸發(fā)錯(cuò)誤的方方式,假如我們的代碼比較復(fù)雜,有時(shí)候遇到類(lèi)似錯(cuò)誤的時(shí)候還是需要耐心分析。

文章內(nèi)容首發(fā)于微信公眾號(hào)《深夜里的程序猿》,轉(zhuǎn)載請(qǐng)注明出處,侵權(quán)必究。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/77495.html

相關(guān)文章

  • Java日志正確使用姿勢(shì)

    摘要:但是往往越簡(jiǎn)單的東西越容易讓我們忽視,從而導(dǎo)致一些不該有的發(fā)生,作為一名嚴(yán)謹(jǐn)?shù)某绦騿T,怎么能讓這種事情發(fā)生呢所以下面我們就來(lái)了解一下關(guān)于日志的那些正確使用姿勢(shì)。級(jí)別表示出現(xiàn)了嚴(yán)重錯(cuò)誤,程序?qū)?huì)中斷執(zhí)行。 前言 關(guān)于日志,在大家的印象中都是比較簡(jiǎn)單的,只須引入了相關(guān)依賴(lài)包,剩下的事情就是在項(xiàng)目中盡情的打印我們需要的信息了。但是往往越簡(jiǎn)單的東西越容易讓我們忽視,從而導(dǎo)致一些不該有的bug發(fā)...

    UCloud 評(píng)論0 收藏0
  • 使用ConcurrentHashMap一定線程安全?

    摘要:前言老王為何半夜慘叫幾行代碼為何導(dǎo)致服務(wù)器爆炸說(shuō)好的線程安全為何還是出問(wèn)題讓我們一起收看今天的走進(jìn)正文出現(xiàn)背景說(shuō)到的出現(xiàn)背景,還得從說(shuō)起。在跟中,都只是調(diào)用的方法,各自都是原子操作,是線程安全的。 前言 老王為何半夜慘叫?幾行代碼為何導(dǎo)致服務(wù)器爆炸?說(shuō)好的線程安全為何還是出問(wèn)題?讓我們一起收看今天的《走進(jìn)IT》 正文 CurrentHashMap出現(xiàn)背景 說(shuō)到ConcurrentHas...

    荊兆峰 評(píng)論0 收藏0
  • Java核心技術(shù)教程整理,長(zhǎng)期更新

    以下是Java技術(shù)棧微信公眾號(hào)發(fā)布的關(guān)于 Java 的技術(shù)干貨,從以下幾個(gè)方面匯總。 Java 基礎(chǔ)篇 Java 集合篇 Java 多線程篇 Java JVM篇 Java 進(jìn)階篇 Java 新特性篇 Java 工具篇 Java 書(shū)籍篇 Java基礎(chǔ)篇 8張圖帶你輕松溫習(xí) Java 知識(shí) Java父類(lèi)強(qiáng)制轉(zhuǎn)換子類(lèi)原則 一張圖搞清楚 Java 異常機(jī)制 通用唯一標(biāo)識(shí)碼UUID的介紹及使用 字符串...

    Anchorer 評(píng)論0 收藏0
  • 聊聊Vue.js組件間通信幾種姿勢(shì)

    摘要:子組件向父組件通信方法一使用事件父組件向子組件傳遞事件方法,子組件通過(guò)觸發(fā)事件,回調(diào)給父組件。非父子組件兄弟組件之間的數(shù)據(jù)傳遞非父子組件通信,官方推薦使用一個(gè)實(shí)例作為中央事件總線。 寫(xiě)在前面 因?yàn)閷?duì)Vue.js很感興趣,而且平時(shí)工作的技術(shù)棧也是Vue.js,這幾個(gè)月花了些時(shí)間研究學(xué)習(xí)了一下Vue.js源碼,并做了總結(jié)與輸出。 文章的原地址:https://github.com/answ...

    Profeel 評(píng)論0 收藏0
  • 異步讀取文件幾種姿勢(shì)

    摘要:臆想的針對(duì)讀取到的內(nèi)容進(jìn)行操作,比如打印文件內(nèi)容臆想中,讀取文件是有返回值的,將返回值,即文件內(nèi)容,賦給一個(gè)變量,然后決定對(duì)讀取到的內(nèi)容進(jìn)行相應(yīng)的操作,例如打印文件中的內(nèi)容。 臆想的 let fs = require(fs) function readFile(filename){ ... } let content = readFile(config.js) // 針對(duì)讀...

    chinafgj 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<