<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    云自無心水自閑

    天平山上白云泉,云自無心水自閑。何必奔沖山下去,更添波浪向人間!
    posts - 288, comments - 524, trackbacks - 0, articles - 6
      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理
    Java虛擬機規范規定JVM的內存分為了好幾塊,比如堆,棧,程序計數器,方法區等,而Hotspot jvm的實現中,將堆內存分為了三部分,新生代,老年代,持久帶,其中持久帶實現了規范中規定的方法區,而內存模型中不同的部分都會出現相應的OOM錯誤,接下來我們就分開來討論一下。 

    棧溢出(StackOverflowError) 

    棧溢出拋出java.lang.StackOverflowError錯誤,出現此種情況是因為方法運行的時候棧的深度超過了虛擬機容許的最大深度所致。 

    出現這種情況,一般情況下是程序錯誤所致的,比如寫了一個死遞歸,就有可能造成此種情況。 下面我們通過一段代碼來模擬一下此種情況的內存溢出。 
    Java代碼 
    1. import java.util.*;  
    2. import java.lang.*;  
    3. public class OOMTest{  
    4.    
    5.   public void stackOverFlowMethod(){  
    6.       stackOverFlowMethod();  
    7.   }  
    8.    
    9.   public static void main(String... args){  
    10.       OOMTest oom = new OOMTest();  
    11.       oom.stackOverFlowMethod();  
    12.   }  
    13.    
    14. }  

    運行上面的代碼,會拋出如下的異常: 
    引用

    Exception in thread "main" java.lang.StackOverflowError 
            at OOMTest.stackOverFlowMethod(OOMTest.java:6) 

    堆溢出(OutOfMemoryError:java heap space) 

    堆內存溢出的時候,虛擬機會拋出java.lang.OutOfMemoryError:java heap space,出現此種情況的時候,我們需要根據內存溢出的時候產生的dump文件來具體分析(需要增加-XX:+HeapDumpOnOutOfMemoryErrorjvm啟動參數)。出現此種問題的時候有可能是內存泄露,也有可能是內存溢出了。 
    如果內存泄露,我們要找出泄露的對象是怎么被GC ROOT引用起來,然后通過引用鏈來具體分析泄露的原因。 
    如果出現了內存溢出問題,這往往是程序本生需要的內存大于了我們給虛擬機配置的內存,這種情況下,我們可以采用調大-Xmx來解決這種問題。 

    下面我們通過如下的代碼來演示一下此種情況的溢出: 
    Java代碼 
    1. import java.util.*;  
    2. import java.lang.*;  
    3. public class OOMTest{  
    4.    
    5.         public static void main(String... args){  
    6.                 List<byte[]> buffer = new ArrayList<byte[]>();  
    7.                 buffer.add(new byte[10*1024*1024]);  
    8.         }  
    9.    
    10. }  

    我們通過如下的命令運行上面的代碼: 

    Java代碼 
    1. java -verbose:gc -Xmn10M -Xms20M -Xmx20M -XX:+PrintGC OOMTest  


    程序輸入如下的信息: 
    引用

    [GC 1180K->366K(19456K), 0.0037311 secs] 
    [Full GC 366K->330K(19456K), 0.0098740 secs] 
    [Full GC 330K->292K(19456K), 0.0090244 secs] 
    Exception in thread "main" java.lang.OutOfMemoryError: Java heap space 
            at OOMTest.main(OOMTest.java:7) 

    從運行結果可以看出,JVM進行了一次Minor gc和兩次的Major gc,從Major gc的輸出可以看出,gc以后old區使用率為134K,而字節數組為10M,加起來大于了old generation的空間,所以拋出了異常,如果調整-Xms21M,-Xmx21M,那么就不會觸發gc操作也不會出現異常了。 

    通過上面的實驗其實也從側面驗證了一個結論:當對象大于新生代剩余內存的時候,將直接放入老年代,當老年代剩余內存還是無法放下的時候,出發垃圾收集,收集后還是不能放下就會拋出內存溢出異常了 

    持久帶溢出(OutOfMemoryError: PermGen space) 

    我們知道Hotspot jvm通過持久帶實現了Java虛擬機規范中的方法區,而運行時的常量池就是保存在方法區中的,因此持久帶溢出有可能是運行時常量池溢出,也有可能是方法區中保存的class對象沒有被及時回收掉或者class信息占用的內存超過了我們配置。當持久帶溢出的時候拋出java.lang.OutOfMemoryError: PermGen space。 
    我在工作可能在如下幾種場景下出現此問題。 

    1.使用一些應用服務器的熱部署的時候,我們就會遇到熱部署幾次以后發現內存溢出了,這種情況就是因為每次熱部署的后,原來的class沒有被卸載掉。 
    2.如果應用程序本身比較大,涉及的類庫比較多,但是我們分配給持久帶的內存(通過-XX:PermSize和-XX:MaxPermSize來設置)比較小的時候也可能出現此種問題。 
    3.一些第三方框架,比如spring,hibernate都通過字節碼生成技術(比如CGLib)來實現一些增強的功能,這種情況可能需要更大的方法區來存儲動態生成的Class文件。 
    我們知道Java中字符串常量是放在常量池中的,String.intern()這個方法運行的時候,會檢查常量池中是否存和本字符串相等的對象,如果存在直接返回對常量池中對象的引用,不存在的話,先把此字符串加入常量池,然后再返回字符串的引用。那么我們就可以通過String.intern方法來模擬一下運行時常量區的溢出.下面我們通過如下的代碼來模擬此種情況: 
    Java代碼 
    1. import java.util.*;  
    2. import java.lang.*;  
    3. public class OOMTest{  
    4.    
    5.         public static void main(String... args){  
    6.                 List<String> list = new ArrayList<String>();  
    7.                 while(true){  
    8.                         list.add(UUID.randomUUID().toString().intern());  
    9.                 }  
    10.         }  
    11.    
    12. }  

    我們通過如下的命令運行上面代碼: 
    java -verbose:gc -Xmn5M -Xms10M -Xmx10M -XX:MaxPermSize=1M -XX:+PrintGC OOMTest 
    運行后的輸入如下圖所示: 
    引用

    Exception in thread "main" java.lang.OutOfMemoryError: PermGen space 
            at java.lang.String.intern(Native Method) 
            at OOMTest.main(OOMTest.java:8) 

    通過上面的代碼,我們成功模擬了運行時常量池溢出的情況,從輸出中的PermGen space可以看出確實是持久帶發生了溢出,這也驗證了,我們前面說的Hotspot jvm通過持久帶來實現方法區的說法。 

    OutOfMemoryError:unable to create native thread 

    最后我們在來看看java.lang.OutOfMemoryError:unable to create natvie thread這種錯誤。 出現這種情況的時候,一般是下面兩種情況導致的: 

    1.程序創建的線程數超過了操作系統的限制。對于Linux系統,我們可以通過ulimit -u來查看此限制。 
    給虛擬機分配的內存過大,導致創建線程的時候需要的native內存太少。我們都知道操作系統對每個進程的內存是有限制的,我們啟動Jvm,相當于啟動了一個進程,假如我們一個進程占用了4G的內存,那么通過下面的公式計算出來的剩余內存就是建立線程棧的時候可以用的內存。 線程棧總可用內存=4G-(-Xmx的值)- (-XX:MaxPermSize的值)- 程序計數器占用的內存 通過上面的公式我們可以看出,-Xmx 和 MaxPermSize的值越大,那么留給線程棧可用的空間就越小,在-Xss參數配置的棧容量不變的情況下,可以創建的線程數也就越小。因此如果是因為這種情況導致的unable to create native thread,那么要么我們增大進程所占用的總內存,或者減少-Xmx或者-Xss來達到創建更多線程的目的。


    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 精品视频在线免费观看| 中国一级毛片免费看视频| 67pao强力打造国产免费| 亚洲Av永久无码精品三区在线| 深夜A级毛片视频免费| 亚洲综合激情五月丁香六月| 亚洲黄色免费在线观看| 久久亚洲春色中文字幕久久久| 日本三级在线观看免费| 国产亚洲一区二区三区在线观看| 久久九九免费高清视频 | 成人免费视频网站www| 亚洲中文无码av永久| 免费无码精品黄AV电影| 亚洲欧美自偷自拍另类视 | 亚洲?V无码乱码国产精品| 国产精品亚洲专区在线播放 | 91福利视频免费观看| 亚洲人成电影在线观看网| 全免费A级毛片免费看网站| 国产成人精品久久亚洲高清不卡| 亚洲国产精品成人久久蜜臀 | 中文字幕亚洲专区| 中文字幕无码免费久久| 亚洲福利视频网站| 亚洲av无码一区二区三区乱子伦| 国产啪精品视频网免费| 亚洲国产成人超福利久久精品| 真人做人试看60分钟免费视频| 亚洲欧洲国产成人精品| 无码一区二区三区免费视频| www亚洲精品久久久乳| 亚洲日本在线观看视频| 国产午夜精品理论片免费观看| 日韩精品一区二区亚洲AV观看| 一区二区无码免费视频网站 | 中文字幕亚洲精品无码| 四虎永久在线精品免费影视| 国产亚洲精品免费视频播放| 亚洲国产精品网站久久| 亚洲成a人片在线观看久|