Java基礎(chǔ)-內(nèi)存溢出是怎么回事?

內(nèi)存溢出(out of memory)的意思是程序在申請內(nèi)存時,沒有足夠的空間給其使用,出現(xiàn)out of memory ;例如創(chuàng)建了一個integer對象,單給這個對象存儲數(shù)據(jù)的時候放了一個long類型的數(shù)據(jù),這時就會出現(xiàn)內(nèi)存溢出了。下面列舉一下引起內(nèi)存溢出的幾種原因:

1、內(nèi)存中加載的數(shù)據(jù)量過于龐大;

2、集合類中有對對象的引用,使用完后未清空,使得JVM不能回收,造成內(nèi)存中大量的垃圾數(shù)據(jù);

3、代碼中存在死循環(huán)或者循環(huán)產(chǎn)生過多的重復(fù)的實體對象

4、啟動參數(shù)內(nèi)存值設(shè)定的過小

5、程序中使用第三方軟件中存在BUG;

內(nèi)存溢出常見的解決方案:

1、最直接的辦法就是修改JVM的啟動參數(shù),直接增加內(nèi)存。(-Xms,-Xmx參數(shù),具體請直接上網(wǎng)百度)

2、檢查錯誤日志,查看“OutOfMemory”錯誤前是否有其他異常或錯誤。

3、對代碼進行排查和分析,找出可能發(fā)生內(nèi)存溢出的位置。

4、使用內(nèi)存查看工具動態(tài)查看內(nèi)存使用情況。

下面是從網(wǎng)上找到的關(guān)于內(nèi)存溢出原因及解決方案的資料(自己進行了歸納精簡):

我們啟動tomcat出現(xiàn)的內(nèi)存溢出實際上就是JVM的內(nèi)存溢出。對內(nèi)存溢出進行深度剖析,首先需要對JVM有關(guān)內(nèi)存方面的知識有一定的了解。

JVM管理的內(nèi)存可以分兩種:堆和非堆。

堆是運行時的數(shù)據(jù)區(qū)域,在Java虛擬機啟動時創(chuàng)建,所有的類實例和數(shù)組的內(nèi)存都在此處分配,簡單的說就是Java代碼可以用的內(nèi)存,是給開發(fā)人員用的。

堆內(nèi)存的分配:JVM初始分配的內(nèi)存由-Xms指定,默認是物理內(nèi)存的1/64;JVM最大分配的內(nèi)存由-Xmx指 定,默認是物理內(nèi)存的1/4。默認空余堆內(nèi)存小于40%時,JVM就會增大堆直到-Xmx的最大限制;空余堆內(nèi)存大于70%時,JVM會減少堆直到-Xms的最小限制。

非堆內(nèi)存是JVM自己用的,所以方法區(qū)、JVM內(nèi)部處理或優(yōu)化所需的內(nèi)存、每個類的結(jié)構(gòu)以及方法和構(gòu)造方法的代碼都在非堆內(nèi)存中,運行期間GC不會釋放其空間。

非堆內(nèi)存的分配:JVM使用-XX:PermSize設(shè)置非堆內(nèi)存初始值,默認是物理內(nèi)存的1/64;由XX:MaxPermSize設(shè)置最大非堆內(nèi)存的大小,默認是物理內(nèi)存的1/4。

三種內(nèi)存溢出異常介紹

1. OutOfMemoryError: Java heap space? 堆溢出

內(nèi)存溢出主要存在問題就是出現(xiàn)在這個情況中。當(dāng)在JVM中如果98%的時間是用于GC且可用的 Heap size 不足2%的時候?qū)伋龃水惓P畔ⅰ?/p>

2. OutOfMemoryError: PermGen space?? 非堆溢出(永久保存區(qū)域溢出)

這種錯誤常見在web服務(wù)器對JSP進行pre compile的時候。如果你的WEB APP下都用了大量的第三方j(luò)ar, 其大小超過了jvm默認的大小(4M)那么就會產(chǎn)生此錯誤信息了。如果web app用了大量的第三方j(luò)ar或者應(yīng)用有太多的class文件而恰好MaxPermSize設(shè)置較小,超出了也會導(dǎo)致這塊內(nèi)存的占用過多造成溢出,或者tomcat熱部署時侯不會清理前面加載的環(huán)境,只會將context更改為新部署的,非堆存的內(nèi)容就會越來越多。

3. OutOfMemoryError: unable to create new native thread.?? 無法創(chuàng)建新的線程

這種現(xiàn)象比較少見,也比較奇怪,主要是和jvm與系統(tǒng)內(nèi)存的比例有關(guān)。這種怪事是因為JVM已經(jīng)被系統(tǒng)分配了大量的內(nèi)存(比如1.5G),并且它至少要占用可用內(nèi)存的一半。

如何設(shè)置JVM的內(nèi)存分配

(1)當(dāng)在命令提示符下啟動并使用JVM時(只對當(dāng)前運行的類Test生效):

java -Xmx128m -Xms64m -Xmn32m -Xss16m Test

(2)當(dāng)在集成開發(fā)環(huán)境下(如eclipse)啟動并使用JVM時:

a. 在eclipse根目錄下打開eclipse.ini,默認內(nèi)容為(這里設(shè)置的是運行當(dāng)前開發(fā)工具的JVM內(nèi)存分配):? -vmargs -Xms40m -Xmx256m -vmargs表示以下為虛擬機設(shè)置參數(shù),可修改其中的參數(shù)值,也可添加-Xmn,-Xss,另外,eclipse.ini內(nèi)還可以設(shè)置非?? 堆內(nèi)存,如:-XX:PermSize=56m,-XX:MaxPermSize=128m。

b. 打開eclipse-窗口-首選項-Java-已安裝的JRE(對在當(dāng)前開發(fā)環(huán)境中運行的java程序皆生效)? 編輯當(dāng)前使用的JRE,在缺省VM參數(shù)中輸入:-Xmx128m -Xms64m -Xmn32m –Xss16m。

c. 打開eclipse-運行-運行-Java應(yīng)用程序(只對所設(shè)置的java類生效)? 選定需設(shè)置內(nèi)存分配的類-自變量,在VM自變量中輸入:-Xmx128m -Xms64m -Xmn32m -Xss16m? 注:如果在同一開發(fā)環(huán)境中同時進行了b和c設(shè)置,則b設(shè)置生效,c設(shè)置無效,如:? 開發(fā)環(huán)境的設(shè)置為:-Xmx256m,而類Test的設(shè)置為:-Xmx128m -Xms64m,則運行Test時生效的設(shè)置為:? -Xmx256m -Xms64m。

(3)當(dāng)在服務(wù)器環(huán)境下(如Tomcat)啟動并使用JVM時(對當(dāng)前服務(wù)器環(huán)境下所以Java程序生效):

a. 設(shè)置環(huán)境變量:? 變量名:CATALINA_OPTS? 變量值:-Xmx128m -Xms64m -Xmn32m -Xss16m。

b. 打開Tomcat根目錄下的bin文件夾,編輯catalina.bat,將其中的%CATALINA_OPTS%(共有四處)替換為:-Xmx128m -Xms64m -Xmn32m -Xss16m。

c. 若沒有catalina.bat,只有tomcat.exe,tomcat6w.exe;則可以在啟動tomcat6w.exe 后 右鍵配置--Java--java option 下面輸入:-Xmx256m –Xms64m

也可以找到注冊表HKEY_LOCAL_MACHINE\SOFTWARE\Apache Software Foundation\TomcatService Manager\Tomcat6\Parameters\JavaOptions原值為 -Dcatalina.home="C:\ApacheGroup\Tomcat 6.0" -Djava.endorsed.dirs="C:\ApacheGroup\Tomcat 6.0\common\endorsed" -Xrs 加入? -Xms300m? -Xmx350m? (我的是加入-Xmx350m,tomcat才能啟動,加入-Xms300m? -Xmx350m反而tomcat都不能啟動)重起tomcat服務(wù),設(shè)置生效。

以上內(nèi)容摘自http://blog.csdn.net/thunder0709/article/details/16855195

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容