標籤:沒有 flow 參數 java_opts error 對象 地區 java記憶體 動態代理
JAVA的記憶體分為方法區、虛擬機器棧、本地方法棧、堆、程式計數器五個部分,除程式計數器外,其它部分都可能出現記憶體溢出OOM(OutOfMemeryError)。
1、記憶體溢出和記憶體流失的區別
記憶體溢出 (Out Of Memory):是指程式在申請記憶體時,沒有足夠的記憶體空間供其使用,出現Out Of Memory。
記憶體泄露 (Memory Leak):是指程式在申請記憶體後,由於某種原因無法釋放已申請的記憶體空間,導致這塊記憶體無法再次被利用,造成系統記憶體的浪費。一次記憶體泄露危害可以忽略,但記憶體泄露堆積的後果很嚴重,無論多少記憶體,遲早會被佔光。
2、記憶體溢出詳解
2.1.Java虛擬機器棧與本地方法棧
每個線程棧的大小控制參數時 -Xss。
Java虛擬機器在棧中定義了兩種異常,StrackOverFlowError和OutOfMemoryError:unable to create new native thread。當請求棧的深度大於java虛擬機器所允許的最大深度則拋出StrackOverFlowError;如果Java虛擬機器在棧擴充時,沒有申請到足夠的空間時,則拋出OutOfMemoryError:unable to create new native thread。
StrackOverFlowError:單線程內佔用記憶體超過了棧的大小-Xss
出現情境
一、局部數組或集合過大。一般出現在大查詢或大匯出的情況下。
二、方法調用太多。一般出現在遞迴調用層次太多或死迴圈時。
三、指標或數組越界。這種情況最常見,例如進行字串拷貝,或處理使用者輸入等等。
解決方式
最佳化程式、減少方式的調用、增大-Xss參數
OutOfMemoryError:unable to create new native thread:多線程佔用的記憶體超過了可用記憶體(進程可用記憶體(32位作業系統時為2G)-Xmx-MaxPermSize-虛擬機器本身耗費的記憶體和程式計數器使用的記憶體)
解決方式
減少線程數量、降低-Xss的大小(即減少每個線程擁有的記憶體大小)、降低-Xmx以及MaxPermSize的大小擴大留給棧的空間
2.方法區記憶體溢出
方法區的大小通過-PermSize和-MaxPermSize控制。
當持久帶溢出的時候拋出 java.lang.OutOfMemoryError: PermGen space
因為類常量和運行時常量也儲存在方法區中,所以運行時常量過多也可導致方法區的OOM,但是沒有直接控制常量池大小的參數,只能通過-PermSize和-MaxPermSize來間接控制。
出現情境
一、在Spring以及Hibernate,Mybatis中都會使用GeneratedConstructorAccessor、動態代理以及CGLib位元組碼增強技術的等動態產生類,那麼就需要強大的方法區來支撐。
二、運行時常量池溢出
三、使用一些應用伺服器的熱部署的時候,我們就會遇到熱部署幾次以後發現記憶體溢出了,這種情況就是因為每次熱部署的後,原來的Class沒有被卸載掉。
解決方式
一、增加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伺服器經常宕機的問題。
二、清理應用程式中web-inf/lib下的jar,如果tomcat部署了多個應用,很多應用都使用了相同的jar,可以將共同的jar移到tomcat共同的lib下,減少類的重複載入。這種方法是網上部分人推薦的,我沒試過,但感覺減少不了太大的空間,最靠譜的還是第一種方法。
3.堆記憶體溢出
堆的大小通過-Xms和-Xmx設定
堆記憶體溢出的時候,虛擬機器會拋出 java.lang.OutOfMemoryError:java heap space
出現情境
建立對象時如果沒有可以分配的堆記憶體,JVM就會拋出OutOfMemoryError:java heap space異常
解決方式
首先需要分清是記憶體溢出還是記憶體泄露
(1)如果是記憶體溢出,則通過 調大 -Xms,-Xmx參數。
(2)如果是記憶體泄露,則看對象如何被 GC Root 引用。
出現此種情況的時候,我們需要根據記憶體溢出的時候產生的 dump 檔案來具體分析(需要增加 -XX:+HeapDump
OnOutOfMemoryError jvm啟動參數)。出現此種問題的時候有可能是記憶體流失,也有可能是記憶體溢出了。
1、配置方法
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=${目錄}。
2、參數說明
(1)-XX:+HeapDumpOnOutOfMemoryError參數表示當JVM發生OOM時,自動產生DUMP檔案。
(2)-XX:HeapDumpPath=${目錄}參數表示產生DUMP檔案的路徑,也可以指定檔案名稱,例如:-XX:HeapDu
mpPath=${目錄}/java_heapdump.hprof。如果不指定檔案名稱,預設為:java_<pid><date><time>_heapDu
mp.hprof。
如果是記憶體流失,我們要找出記憶體流失的對象是怎麼被GC ROOT引用起來,然後通過引用鏈來具體分析泄露的
原因。
如果出現了記憶體溢出問題,這往往是程式本生需要的記憶體大於了我們給虛擬機器設定的記憶體,這種情況下,我
們可以採用調大-Xmx來解決這種問題。
JAVA記憶體溢出