Java常見的幾種內存溢出及解決方案- xiaoxi

文章推薦指數: 80 %
投票人數:10人

JVM Heap(堆)溢出:java.lang.OutOfMemoryError: Java heap space. JVM在啟動的時候會自動設置JVM Heap的值, 可以利用JVM提供的-Xmn -Xms -Xmx等 ... 關閉廣告 IT工程師數位筆記本 跳到主文 Ifyougivesomeoneaprogram,youwillfrustratethemforaday;ifyouteachthemhowtoprogram,youwillfrustratethemforalifetime.IT 這段話的意思是,如果你交給某人一隻程式,你將折磨他一整天;如果你教會某人如何寫程式,你將折磨他一輩子。

部落格全站分類:數位生活 相簿 部落格 留言 名片 BloggerAds Dec15Fri201723:04 Java常見的幾種內存溢出及解決方案-xiaoxi 文章出處 1.JVMHeap(堆)溢出:java.lang.OutOfMemoryError:Javaheapspace     JVM在啟動的時候會自動設置JVMHeap的值,可以利用JVM提供的-Xmn-Xms-Xmx等選項可進行設置。

Heap的大小是YoungGeneration和TenuredGeneraion之和。

在JVM中如果98%的時間是用于GC,且可用的Heapsize不足2%的時候將拋出此異常信息。

解決方法:手動設置JVMHeap(堆)的大小。

Java堆用于儲存對象實例。

當需要為對象實例分配內存,而堆的內存占用又已經達到-Xmx設置的最大值。

將會拋出OutOfMemoryError異常。

例子如下: packagecom.demo.test; importjava.util.ArrayList; importjava.util.List; /** *VMArgs:-Xms5m-Xmx5m */ publicclassHeapOOM{ publicstaticvoidmain(String[]args){ intcount=0; Listlist=newArrayList(); while(true){ list.add(newObject()); System.out.println(++count); } } } 然后在運行時設置jvm參數,如下:  -Xmx為5m。

其中的一次測試結果為,當count的值累加到360145時,發生如下異常: Exceptioninthread"main"java.lang.OutOfMemoryError:Javaheapspace atjava.util.Arrays.copyOf(Arrays.java:2245) atjava.util.Arrays.copyOf(Arrays.java:2219) atjava.util.ArrayList.grow(ArrayList.java:213) atjava.util.ArrayList.ensureCapacityInternal(ArrayList.java:187) atjava.util.ArrayList.add(ArrayList.java:411) atcom.demo.test.HeapOOM.main(HeapOOM.java:12) 修改-Xmx為10m。

其中的一次測試結果為,當count的值累加到540217時,發生OutOfMemoryError異常。

隨著-Xmx參數值的增大,java堆中可以存儲的對象也越多。

 2.PermGenspace溢出:java.lang.OutOfMemoryError:PermGenspace      PermGenspace的全稱是PermanentGenerationspace,是指內存的永久保存區域。

為什么會內存溢出,這是由于這塊內存主要是被JVM存放Class和Meta信息的,Class在被Load的時候被放入PermGenspace區域,它和存放Instance的Heap區域不同,sun的GC不會在主程序運行期對PermGenspace進行清理,所以如果你的APP會載入很多CLASS的話,就很可能出現PermGenspace溢出。

一般發生在程序的啟動階段。

解決方法:通過-XX:PermSize和-XX:MaxPermSize設置永久代大小即可。

     方法區用于存放java類型的相關信息,如類名、訪問修飾符、常量池、字段描述、方法描述等。

在類裝載器加載class文件到內存的過程中,虛擬機會提取其中的類型信息,并將這些信息存儲到方法區。

當需要存儲類信息而方法區的內存占用又已經達到-XX:MaxPermSize設置的最大值,將會拋出OutOfMemoryError異常。

對于這種情況的測試,基本的思路是運行時產生大量的類去填滿方法區,直到溢出。

這里需要借助CGLib直接操作字節碼運行時,生成了大量的動態類。

例子如下: packagecom.demo.test; importjava.lang.reflect.Method; importnet.sf.cglib.proxy.Enhancer; importnet.sf.cglib.proxy.MethodProxy; importnet.sf.cglib.proxy.MethodInterceptor; /** *VMArgs:-XX:PermSize=10M-XX:MaxPermSize=10M */ publicclassMethodAreaOOM{ publicstaticvoidmain(String[]args){ intcount=0; while(true){ Enhancerenhancer=newEnhancer(); enhancer.setSuperclass(MethodAreaOOM.class); enhancer.setUseCache(false); enhancer.setCallback(newMethodInterceptor(){ publicObjectintercept(Objectobj,Methodmethod,Object[]args,MethodProxyproxy)throwsThrowable{ returnproxy.invoke(obj,args); } }); enhancer.create(); System.out.println(++count); } } } -XX:MaxPermSize為10m。

其中的一次測試結果為,當count的值累加到800時,發生如下異常:  Causedby:java.lang.OutOfMemoryError:PermGenspace atjava.lang.ClassLoader.defineClass1(NativeMethod) atjava.lang.ClassLoader.defineClass(ClassLoader.java:792) ...8more 隨著-XX:MaxPermSize參數值的增大,java方法區中可以存儲的類型數據也越多。

3.棧溢出:java.lang.StackOverflowError:ThreadStackspace      棧溢出了,JVM依然是采用棧式的虛擬機,這個和C和Pascal都是一樣的。

函數的調用過程都體現在堆棧和退棧上了。

調用構造函數的“層”太多了,以致于把棧區溢出了。

通常來講,一般棧區遠遠小于堆區的,因為函數調用過程往往不會多于上千層,而即便每個函數調用需要1K的空間(這個大約相當于在一個C函數內聲明了256個int類型的變量),那么棧區也不過是需要1MB的空間。

通常棧的大小是1-2MB的。

通俗一點講就是單線程的程序需要的內存太大了。

通常遞歸也不要遞歸的層次過多,很容易溢出。

解決方法:1:修改程序。

2:通過-Xss:來設置每個線程的Stack大小即可。

在Java虛擬機規范中,對這個區域規定了兩種異常狀況:StackOverflowError和OutOfMemoryError異常。

(1)StackOverflowError異常       每當java程序代碼啟動一個新線程時,Java虛擬機都會為它分配一個Java棧。

Java棧以幀為單位保存線程的運行狀態。

當線程調用java方法時,虛擬機壓入一個新的棧幀到該線程的java棧中。

只要這個方法還沒有返回,它就一直存在。

如果線程的方法嵌套調用層次太多(如遞歸調用),隨著java棧中幀的逐漸增多,最終會由于該線程java棧中所有棧幀大小總和大于-Xss設置的值,而產生StackOverflowError內存溢出異常。

例子如下: packagecom.demo.test; /** *VMArgs:-Xss128k */ publicclassJavaVMStackSOF{ privateintcount=0; publicstaticvoidmain(String[]args){ newJavaVMStackSOF().method(); } publicvoidmethod(){ System.out.println(++count); method(); } } -Xss為128k。

其中的一次測試結果為,當count的值累加到2230時,發生如下異常: Exceptioninthread"main"java.lang.StackOverflowError atsun.nio.cs.UTF_8.updatePositions(UTF_8.java:77) atsun.nio.cs.UTF_8$Encoder.encodeArrayLoop(UTF_8.java:564) atsun.nio.cs.UTF_8$Encoder.encodeLoop(UTF_8.java:619) atjava.nio.charset.CharsetEncoder.encode(CharsetEncoder.java:561) atsun.nio.cs.StreamEncoder.implWrite(StreamEncoder.java:271) atsun.nio.cs.StreamEncoder.write(StreamEncoder.java:125) atjava.io.OutputStreamWriter.write(OutputStreamWriter.java:207) atjava.io.BufferedWriter.flushBuffer(BufferedWriter.java:129) atjava.io.PrintStream.write(PrintStream.java:526) atjava.io.PrintStream.print(PrintStream.java:597) atjava.io.PrintStream.println(PrintStream.java:736) atcom.demo.test.JavaVMStackSOF.method(JavaVMStackSOF.java:15)     隨著-Xss參數值的增大,可以嵌套的方法調用層次也相應增加。

綜上所述,StackOverflowError異常是由于方法調用的層次太深,最終導致為某個線程分配的所有棧幀大小總和大于-Xss設置的值,從而發生StackOverflowError異常。

(2)OutOfMemoryError異常 java程序代碼啟動一個新線程時,沒有足夠的內存空間為該線程分配java棧(一個線程java棧的大小由-Xss參數確定),jvm則拋出OutOfMemoryError異常。

例子如下: packagecom.demo.test; /** *VMArgs:-Xss128k */ publicclassJavaVMStackOOM{ publicstaticvoidmain(String[]args){ intcount=0; while(true){ Threadthread=newThread(newRunnable(){ publicvoidrun(){ while(true){ try{ Thread.sleep(5000); }catch(Exceptione){ } } } }); thread.start(); System.out.println(++count); } } } -Xss為128k。

其中的一次測試結果為,當count的值累加到11958時,發生如下異常: Exceptioninthread"main"java.lang.OutOfMemoryError:unabletocreatenewnativethread atjava.lang.Thread.start0(NativeMethod) atjava.lang.Thread.start(Thread.java:693) atcom.demo.test.JavaVMStackOOM.main(JavaVMStackOOM.java:21) 隨著-Xss參數值的增大,java程序可以創建的總線程數越少。

4.所以Server容器啟動的時候我們經常關心和設置JVM的幾個參數如下: -Xms:javaHeap初始大小,默認是物理內存的1/64。

-Xmx:javaHeap最大值,不可超過物理內存。

-Xmn:younggeneration的heap大小,一般設置為Xmx的3、4分之一。

增大年輕代后,將會減小年老代大小,可以根據監控合理設置。

-Xss:每個線程的Stack大小,而最佳值應該是128K,默認值好像是512k。

-XX:PermSize:設定內存的永久保存區初始大小,缺省值為64M。

-XX:MaxPermSize:設定內存的永久保存區最大大小,缺省值為64M。

-XX:SurvivorRatio:Eden區與Survivor區的大小比值,設置為8,則兩個Survivor區與一個Eden區的比值為2:8,一個Survivor區占整個年輕代的1/10。

-XX:+UseParallelGC:F年輕代使用并發收集,而年老代仍舊使用串行收集。

-XX:+UseParNewGC:設置年輕代為并行收集,JDK5.0以上,JVM會根據系統配置自行設置,所無需再設置此值。

-XX:ParallelGCThreads:并行收集器的線程數,值最好配置與處理器數目相等同樣適用于CMS。

-XX:+UseParallelOldGC:年老代垃圾收集方式為并行收集(ParallelCompacting)。

-XX:MaxGCPauseMillis:每次年輕代垃圾回收的最長時間(最大暫停時間),如果無法滿足此時間,JVM會自動調整年輕代大小,以滿足此值。

-XX:+ScavengeBeforeFullGC:FullGC前調用YGC,默認是true。

實例如:JAVA_OPTS=”-Xms4g-Xmx4g-Xmn1024m-XX:PermSize=320M-XX:MaxPermSize=320m-XX:SurvivorRatio=6″ 第一種OutOfMemoryError:PermGenspace 發生這種問題的原意是程序中使用了大量的jar或class,使java虛擬機裝載類的空間不夠,與PermanentGenerationspace有關。

解決這類問題有以下兩種辦法: 1、增加java虛擬機中的XX:PermSize和XX:MaxPermSize參數的大小,其中XX:PermSize是初始永久保存區域大小,XX:MaxPermSize是最大永久保存區域大小。

如針對tomcat6.0,在catalina.sh或catalina.bat文件中一系列環境變量名說明結束處(大約在70行左右)增加一行:JAVA_OPTS="-XX:PermSize=64M-XX:MaxPermSize=128m"如果是windows服務器還可以在系統環境變量中設置。

感覺用tomcat發布sprint+struts+hibernate架構的程序時很容易發生這種內存溢出錯誤。

使用上述方法,我成功解決了部署ssh項目的tomcat服務器經常宕機的問題。

2、清理應用程序中web-inf/lib下的jar,如果tomcat部署了多個應用,很多應用都使用了相同的jar,可以將共同的jar移到tomcat共同的lib下,減少類的重復加載。

這種方法是網上部分人推薦的,我沒試過,但感覺減少不了太大的空間,最靠譜的還是第一種方法。

第二種OutOfMemoryError:Javaheapspace 發生這種問題的原因是java虛擬機創建的對象太多,在進行垃圾回收之間,虛擬機分配的到堆內存空間已經用滿了,與Heapspace有關。

解決這類問題有兩種思路: 1、檢查程序,看是否有死循環或不必要地重復創建大量對象。

找到原因后,修改程序和算法。

我以前寫一個使用K-Means文本聚類算法對幾萬條文本記錄(每條記錄的特征向量大約10來個)進行文本聚類時,由于程序細節上有問題,就導致了Javaheapspace的內存溢出問題,后來通過修改程序得到了解決。

2、增加Java虛擬機中Xms(初始堆大小)和Xmx(最大堆大小)參數的大小。

如:setJAVA_OPTS=-Xms256m-Xmx1024m 文章列表 不含病毒。

www.avast.com 全站熱搜 創作者介紹 大師兄 IT工程師數位筆記本 大師兄發表在痞客邦留言(0)人氣() E-mail轉寄 全站分類:數位生活個人分類:生活學習此分類上一篇:牛頓晚年趨于保守年紀大了趨于保守?沒準是腦子出問題了 此分類下一篇:Spring中的線程池和定時任務功能-vitasyuan 上一篇:牛頓晚年趨于保守年紀大了趨于保守?沒準是腦子出問題了 下一篇:Spring中的線程池和定時任務功能-vitasyuan 歷史上的今天 2017:分享12款令人瞠目結舌的WebVR演示和實驗效果-gbin1 2017:微服務~Eureka實現的服務注冊與發現及服務之間的調用-lori 2017:這才是逼格的花園房 2017:DotNetCore跨平臺~EFCore2.0連接Mysql的煩惱-已解決-lori 2017:德國漁夫稱撿到最古老漂流瓶距今已101年 2017:英國留學專升本申請費2017年英國留學專升本申請 2017:基于nodejs的webSockt(socket.io)-erbingbing 2017:戀愛中女人想要的是什么?孫子兵法告訴你 2017:sys.usb.configwebcam-ahuo 2017:docker~Dockerfile方式建立鏡像HelloWorld-lori 2017:異步與線程阻塞-lori 2017:夏天大米白面不生蟲的妙招 2017:如何在本地測試FabricCode-studyzy 2017:快速解決子線卷曲一招 2017:揭秘風光攝影的秘密(純干貨) 2017:給女兒書六:我們堅信的世界是灰色的 2017:現代中國七大病! 2017:小萌希奧紙尿褲怎么樣小萌希奧代言十九季,時尚辣媽,與小萌盡享繁華 2017:工作會影響你的性格嗎 2017:每年3~5月竟是孩子長高黃金期?做到這5點,孩子多長10公分! 2017:[毛尖是什么茶]圣地毛尖是什么茶 2017:文件下載防文件名亂碼-gaocong 2017:現在教好孩子這三件事,以后才不會吃大虧 2017:美國電影史密斯夫婦美國電影——《史密斯夫婦》* 2017:25個Web前端開發工程師必看的國外大牛和酷站-gbin1 2017:我不相信一見鐘情,因為這座城市太大太冰冷丨每日一片4分43秒 2017:EF架構~mysql中時間戳字段被認為是主鍵自增-lori 2017:情人節最經典的禮物 2017:DotNetCore跨平臺~一起聊聊Microsoft.Extensions.DependencyInjection-lori 2017:androidstudio全局搜索快捷鍵Ctrl+Shift+F失效的解決辦法-strinkbug 2017:看看朝鮮歷史,才知韓國認賊作父、恩將仇報 2017:信仰,就是好好活著 2017:科學看武術(下)(流暢) 2017:[做夢夢見牙掉了]夢見牙齒掉了一顆 2017:法國恐怖“魔鏡”250年己奪38條人命 2017:刀鋒山有個系列任務:攤牌!!請問:刀鋒山有個系列任務叫攤牌!!&刀鋒山 2017:讓男人欲罷不能想看美女欲罷不能是男人的本能 2017:房價段子給你講幾個房價段子,你可別哭啊! 2017:寫作精進:提升寫作的21個技巧! 2017:MySQL--當查詢遇到隱藏字符-TeyGao 2017:12個啟發靈感的創意單頁網站作品 2017:Windows8.1Enterprise(企業版)怎么激活 2017:孩子,請你一定要懂政治 2017:黑帆第一季/全集BlackSails迅雷下載-happyday56 2017:802.11協議精讀13:協議理論性能(Bianchi模型) 2017:12處藏匿外星人的地方 2017:一字秒殺所有《紅樓夢》版本 2017:使用SN.exe對.Net生成的程序集進行簽名-xuhaibiao 2017:白脈椒草養殖養護方法水黃皮養殖方法及養護技巧 2017:linuxfind10天內改動過的文件-ahuo 2017:程序員段子:電腦在手,代碼我有!-gbin1 2017:中國海軍編隊出發參加環太軍演兵力規模僅次美加中國海軍編隊出發參加環太軍演 2017:故宮銅獅子離奇故事故宮銅獅子為什么不能摸?背后離奇事件令人毛骨悚然 2017:租房子不用房東家具為什么不用交租的房子誰也不愿意去住? 2017:物理路徑轉網絡路徑-gaocong 2017:iPhone8發布后那些搞笑Geek段子合輯#精選搞笑GEEK段子-gbin1 2017:mysql的查詢、子查詢及連接查詢-xiaoxi 2017:MySQL5.7mysqlpump備份工具說明-doseoer 2017:血族第四季/全集TheStrain迅雷下載-happyday56 2017:現在的人工智能逆天到什么地步了?-gbin1 2017:瑞投:新加坡房產產權的投資價值 2017:CNN評出10個酒鬼最多的國家,頭牌竟不是中國,也不是俄羅斯 2017:Java中volatile關鍵字解析-xiaoxi 2017:孫中山紀念幣預約兌換孫中山150周年紀念幣如何預約+怎么兌換說明 2017:Nuget~打包時添加powershell初始化腳本-lori 2017:烏克蘭防暴警察被女示威者感動向其求愛 2017:汽車碰撞測試排名關于汽車碰撞測試你了解多少 2017:冬天腳臭怎么辦? 2017:行尸走肉第八季/全集TheWalkingDead迅雷下載-happyday56 2017:每天拍打這幾個經絡,身體通暢好處多 2017:滴滴租車業務上線了?已在上海測試運營能免費送車上門 2017:建設銀行車貸條件建設銀行車貸條件建設銀行車貸資格 2017:世界上最奇葩高薪工作:迪拜撿垃圾 2017:長春市中小學繼續教育長春市中小學(幼兒園)教師繼續教育初中信息_專題_2016創客教育的理解 2017:蜂蜜檸檬水禁忌是什么食用檸檬有什么禁忌 2017:國內真實的七大恐怖變態事件 2017:胃痛怎樣緩解吃什么藥好? 2017:node.js淺談淺談JS中的!=、==、!==、===的用法和區別 2017:[夢見把蛇打死了]夢見蛇被打死 2017:危機邊緣第一季/全集Fringe迅雷下載-happyday56 2017:基于socket.io的AI服務雜談-erbingbing 2017:嘻哈帝國第一季/全集Empire迅雷下載-happyday56 2017:小學生中國傳統文化手抄報圖片 2017:Webpack2視頻教程016-Webpack2中生成SourceMaps-parry 2017:[右眼皮跳]右眼皮跳是怎么回事? 2017:淺談美國西點軍校人才培養特點 2017:天蝎第一季/全集Scorpion迅雷下載-happyday56 2017:[陽新生活網]陽新縣生活網 2017:哄女友開心的肉麻情話最讓女生感動的情話(哄女生開心) 2017:紀錄專輯:奇聞探秘2 2017:呂柳蔭膏滋怎么樣最應該吃呂柳蔭膏滋的十種人,有你嗎? 2017:網絡電視機頂盒被禁如何繼續看電視與視頻 2017:thelectureat700MIT6.001XLecture7Debugging筆記 2017:女生專用混搭皮膚設計我觸摸不到你的溫柔 2017:Linux網絡編程“驚群”問題總結-Anker 2017:商界大佬馬云的勵志分享 2017:Hibernate緩存和懶加載的坑你知道多少?這5個簡單問題回答不上來就不敢說會用hibernate-leotsai 2017:茜之塔繁殖茜之塔繁殖方法 2017:RabbitMQ入門-高效的Work模式-bigdataZJ 2017:#研發解決方案#數據開放實驗室:再戰即席查詢和數據開放-zhengyun_ustc ▲top 留言列表 發表留言 參觀人氣 本日人氣: 累積人氣: 文章搜尋 最新文章 文章精選 文章精選 所有文章列表 誰來我家 熱門文章 文章分類 數位生活(1)生活學習(61838)未分類文章(1846) 最新留言 QRCode POWEREDBY (登入) 回到頁首 回到主文 免費註冊 客服中心 痞客邦首頁 ©2003-2022PIXNET 關閉視窗



請為這篇文章評分?