1. 程式人生 > >Java千百問_07JVM架構(013)_java什麼情況會記憶體溢位

Java千百問_07JVM架構(013)_java什麼情況會記憶體溢位

1、Java堆什麼情況會溢位

所有物件的例項都在Java堆上分配記憶體,堆大小由-Xmx和-Xms來調節,如果程式使用的記憶體超過了堆最大記憶體(-Xmx),則會溢位Java heap space

例項:

public class HeapOOM { 

    static class OOMObject{} 

    /**
     * @param args
     */ 
    public static void main(String[] args) { 
        List<OOMObject> list = new ArrayList<OOMObject>(); 

        while
(true){ list.add(new OOMObject()); } } }

加上JVM引數執行:

-verbose:gc -Xms10M -Xmx10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:+HeapDumpOnOutOfMemoryError

其中-verbose:gc是為了列印GC過程的詳細情況,上述程式就能很快報出記憶體溢位(OOM)
Exception in thread “main” java.lang.OutOfMemoryError: Java heap space

並且能自動生成Dump檔案,Dump記錄了程序記憶體的完整資訊。

2、Java方法區什麼情況會溢位

方法區(永久代)是存放虛擬機器載入類的相關資訊(如類、靜態變數和常量),大小由-XX:PermSize和-XX:MaxPermSize來調節,類太多有可能使永久代溢位PermGen space。Java 8 以後移除了方法區,取而代之的是本地元空間Metaspace,大小由-XX:MetaspaceSize和-XX:MaxMetaspaceSize調節,移除的錯誤也變為java.lang.OutOfMemoryError: Metaspace。

例項:

public class
MethodAreaOOM {
static class OOMOjbect{} /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub while(true){ Enhancer eh = new Enhancer(); eh.setSuperclass(OOMOjbect.class); eh.setUseCache(false); eh.setCallback(new MethodInterceptor(){ @Override public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable { // TODO Auto-generated method stub return arg3.invokeSuper(arg0, arg2); } }); eh.create(); } } }

加上永久代的JVM引數後:

-XX:PermSize=10M -XX:MaxPermSize=10M

執行後會報如下異常
Exception in thread “main” java.lang.OutOfMemoryError: PermGen space

靜態變數或常量也會有可能撐爆方法區

public class ConstantOOM { 

    /**
     * @param args
     */ 
    public static void main(String[] args) { 
        // TODO Auto-generated method stub 
        List<String> list = new ArrayList<String>(); 
        int i=0; 
        while(true){ 
            list.add(String.valueOf(i++).intern()); 
        } 
    } 

} 

同樣加上JVM引數:

-XX:PermSize=10M -XX:MaxPermSize=10M

執行後報如下異常
Exception in thread “main” java.lang.OutOfMemoryError: PermGen space

3、Java棧和本地方法棧什麼情況會溢位

是存放執行緒呼叫方法時儲存區域性變數、操作、方法出口等與方法執行相關的資訊,棧大小由-Xss來調節,方法呼叫層次太多會使棧溢位StackOverflowError

例項:

package com.cutesource; 

public class StackOOM { 

    /**
     * @param args
     */ 

    private int stackLength = 1; 

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

    public static void main(String[] args) throws Throwable{ 
        // TODO Auto-generated method stub 
        StackOOM oom = new StackOOM(); 
        try{ 
            oom.stackLeak(); 
        }catch(Throwable err){ 
            System.out.println("Stack length:" + oom.stackLength); 
            throw err; 
        } 

    } 

} 

設定JVM引數:

-Xss128k

執行報出異常
Exception in thread “main” java.lang.StackOverflowError

打印出Stack length:1007,這裡可以看出,128k的棧容量能承載深度為1007的方法呼叫。當然這個錯誤很少見,一般只會出現無限迴圈的遞迴中,另外,執行緒太多也會佔滿棧區域(執行緒內分配了自己的棧,但是程序中所有執行緒可使用的棧總大小是一定的):

package com.cutesource; 

public class StackOOM { 

    /**
     * @param args
     */ 

    private int stackLength = 1; 

    private void dontStop(){ 
        while(true){ 
            try{Thread.sleep(1000);}catch(Exception err){} 
        } 
    } 

    public void stackLeakByThread(){ 
        while(true){ 
            Thread t = new Thread(new Runnable(){ 

                @Override 
                public void run() { 
                    // TODO Auto-generated method stub 
                    dontStop(); 
                } 

            }); 
            t.start(); 
            stackLength++; 
        } 
    } 

    public static void main(String[] args) throws Throwable{ 
        // TODO Auto-generated method stub 
        StackOOM oom = new StackOOM(); 
        try{ 
            oom.stackLeakByThread(); 
        }catch(Throwable err){ 
            System.out.println("Stack length:" + oom.stackLength); 
            throw err; 
        } 

    } 

} 

執行報出異常:
Exception in thread “main” java.lang.OutOfMemoryError:unable to create new native thread

在windows上執行這個例子要很小心,可能會出現系統假死的情況,需要重啟機器。

相關推薦

Java_07JVM架構013_java什麼情況記憶體溢位

1、Java堆什麼情況會溢位 所有物件的例項都在Java堆上分配記憶體,堆大小由-Xmx和-Xms來調節,如果程式使用的記憶體超過了堆最大記憶體(-Xmx),則會溢位Java heap space。 例項: public class Hea

Java_07JVM架構001_java記憶體模型是什麼樣的

1、什麼是記憶體模型   Java平臺自動集成了執行緒以及多處理器技術,這種整合程度比Java以前誕生的計算機語言要厲害很多。Java針對多種異構平臺的獨立性,使得多執行緒技術也具有了開拓性的一面。    瞭解執行緒和程序看這裡:執行緒和程序有什麼

Java_07JVM架構012_fullGC、minorGC、magorGC有什麼區別

1、fullGC、minorGC、majorGC有什麼區別 fullGC、minorGC、majorGC還有youngGC是Java垃圾處理機制(GC)的名詞,區分這幾個概念非常簡單: 老

Java_07JVM架構003_記憶體分配有哪些策略

1、記憶體分配有哪些策略 我們從編譯原理講起,不同的開發環境、開發語言都會有不同的策略。一般來說,程式執行時有三種記憶體分配策略:靜態的、棧式的、堆式的 靜態儲存 是指在編譯時就能夠確定

Java_03基礎語法013_>、>>、>>>有什麼區別

1、>、>>、>>>有什麼區別 瞭解java運算子看這裡:java種的運算子都有哪些 瞭解java運算子優先順序看這裡:java運算子的優先順序是怎樣的

Java_03基本的語法005_二進制是如何做位運算的

無符號 img 進制 amp 取整 查找 進行 href 有符號 點擊進入_很多其它_Java千百問二進制是如何做位運算的程序中的全部數在計算機內存中都是以二進制的形式儲存的。位運算說白了,就是直接對整數在內存中的二進制位進行操作。其它運算符看這裏:java種的運算符都

Java_05面向對象005_接口和抽象類有什麽差別

src ack function 興趣 沒有 序列 面向 問題 serial 點擊進入_很多其它_Java千百問 1、接口和抽象類有什麽差別 在Java語言中。抽象類abstract class和接口interface是抽象定義的兩種機制。 正

Java_05面向對象008_java中覆蓋是什麽

返回 類變量 默認 public -m view ati 面向對象 text 點擊進入_很多其它_Java千百問 1、什麽是覆蓋 在java中,覆蓋是針對繼承才有的概念,某一個子類須要某些方法或屬性,但又不想使用父類中的同名的方法或屬性,就須要使

Java_06資料結構021_StringBuffer/StringBuilder有什麼區別

1、StringBuilder是什麼 StringBuilder是非執行緒安全的可變字串類。 java.lang.StringBuilder這個可變的字元序列類是5.0新增的。繼承於AbstractStringBuilder(大部分方法都在該類實現)

Java_05面向物件011_引用傳遞和值傳遞有什麼區別

1、什麼是值傳遞 值傳遞,是將記憶體空間中某個儲存單元中存放的值,傳送給另一個儲存單元。(java中的儲存單元並不是實體記憶體的地址,但具有相關性) 例如: //定義了一個改變引數值的函式 public static void changeVa

Java_04異常處理002_java如何捕獲異常

1、如何捕獲異常 捕獲的方法是使用try/catch關鍵字。將可能產生異常,並且需要捕獲的程式碼塊使用try/catch圍繞,如果產生了異常即可捕獲到,將直接中斷try程式碼塊,同時執行catch

Java_03基本語法001_區域性變數、類變數、例項變數有什麼區別

區域性變數、類變數、例項變數有什麼區別 在聊區域性變數、類變數、例項變數有什麼區別之前,我們需要了解一下Java變數。 1、Java變數是什麼 在數學世界中,我們知道有常量、變數。 舉一個例

Java_02基本使用011_如何編寫單執行緒Socket程式

1、如何編寫單執行緒Socket程式 瞭解Socket看這裡:Socket是什麼 編寫Socket最簡單的就是單執行緒的Socket,但基本上是沒有實用意義的,因為在實際的應用中基本上是不止於一個Client的。一般都是多執行緒Socket程式。

Java_05面向物件002_package和import作用是什麼

1、java中package是什麼 即包。簡單地說,它是分類class(類)與interface(介面)的方式。 在Java開發中,將會寫數以百計的類和介面,因此,對它們分類是必須的。 瞭解更多類看這裡:類、物件到底有什麼祕密 瞭解更多介面看這裡

Java_02基本使用015_java如何通過彙編方式執行

1、java如何通過彙編方式執行 java本身不能通過彙編方式執行。但是,我們可以通過某些外掛,在執行中將java程式碼解釋為彙編指令,讓我們能夠通過分析執行的彙編指令來查詢一些問題,也可以幫

Java_05面向物件008_java中覆蓋是什麼

1、什麼是覆蓋 在java中,覆蓋是針對繼承才有的概念,某一個子類需要某些方法或屬性,但又不想使用父類中的同名的方法或屬性,就需要使用覆蓋。 直白的來說,就是在子類中編寫與父類同名、同參數、

Java_06資料結構006_java基本資料型別如何轉換

1、基本型別如何相互轉換 我們看到,將一種型別的值賦給另一種型別是很常見的。在Java中,boolean型別與所有其他7種類型都不能進行轉換,這一點很明確。 對於其他7中數值型別,它們之間都可以進行轉換,但是可能會存在精度損失或者其他一些變化。 j

JAVA面試常知識總結

try catch finally 的詳細用法: 1 public static int testBasic(){ 2 int i = 1; 3 try{ 4 i++; 5 System.out.printl

JAVA面試常知識總結

JAVA中的引數傳遞總結先看兩道筆試題: 1 public class Test2 { 2 3 public static void main (String [] args) { 4 StringBuffer a = new StringBuff

JAVA面試常知識總結——JVM

堆疊(Stack) : 如子彈入彈夾一樣 先進後出佇列(Queue):如排隊過隧道 先進先出ps:java中建立的物件都是放在java堆中的,方法區放置的是類的資訊,又叫靜態區,跟堆一樣,被所有的執行緒共享。方法區包含所有的class和static變數。 2.方法區中包含的都是在整個程式中永遠唯一的元素,如c