成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

論JVM爆炸的幾種姿勢及自救方法

hyuan / 652人閱讀

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

前言

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

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

jdk:java version "1.8.0_121"

ide:IntelliJ IDEA 2019.1 (Community Edition)

正文
1.Java堆溢出

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

/**
 * 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");
        }
    }
}

運行結果,發(fā)生OOM,并且在我們項目的根目錄dump出當前的內(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

簡單解決思路

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

2.方法區(qū)溢出

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

/**
 * 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{}
}

運行結果

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

簡單解決方法

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

3.棧溢出

對于我們來說,還有一個熟悉的錯誤,那就是“StackOverflowError”,它是由線程請求的棧深度超過了jvm允許的最大范圍而產(chǎn)生的。“-Xss”參數(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;
        }
    }
}

運行結果

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

簡單解決思路

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

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

本機直接內(nèi)存默認與“-Xmx”設定的值一樣大,可以通過“-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);
        }
    }
}

運行結果

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

總結

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

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

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

轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/77495.html

相關文章

  • Java日志正確使用姿勢

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

    UCloud 評論0 收藏0
  • 使用ConcurrentHashMap一定線程安全?

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

    荊兆峰 評論0 收藏0
  • Java核心技術教程整理,長期更新

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

    Anchorer 評論0 收藏0
  • 聊聊Vue.js組件間通信幾種姿勢

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

    Profeel 評論0 收藏0
  • 異步讀取文件幾種姿勢

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

    chinafgj 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<