對於內存泄漏,首先想到的是C語言,其實不然,java中也有各種的內存泄漏。對於java程序員,在虛擬即中,不需要為每一個新建對象去delete/free內存,不容易出現內存泄漏。但是,正
是由於這種機制,java中如果出現了內存泄漏將是一個很麻煩的事情,所以,對java虛擬機的內存使用的掌握能很好的幫助你排除問題。
java內存有幾種:程序計數器,虛擬機棧,方法常量區,堆,本地方法棧,直接內存。既然分析內存泄漏,那就從這幾種內存逐一分析。
1,程序計數器:是一個較小的內存空間,是但錢線程的字節碼行號指示器,這個不會出現內存泄漏。
2,虛擬即棧:虛擬即棧拋出的異常叫做StackOverFlowError異常,指的就是棧內存溢出。虛擬機棧內存溢出主要又兩個原因:
(1)棧深度超過限制。jvm虛擬機對虛擬機棧是有大小限制的,如果單一性線程的棧深度超過了這限制,會拋出StackOverFlowError(其中,每個棧的棧大小也影響這個限制的,比如在一個棧中只做一個復制操作棧深度超過10000就溢出了,但是如果一個棧中還定義了很多變量,分配了一些內存,可能超過6000就會溢出)
如以下代碼(測試):
public class Main {private int stackLength = 1;public void stackLeak(){stackLength ++;stackLeak();}public static void main(String[]args){Main main = new Main();try{main.stackLeak();}catch(Error e){System.out.println("stack length:" + main.stackLength);throw e;}}}
輸出結果:
stack length:6745Exception in thread "main" java.lang.StackOverflowError at Main.stackLeak(Main.java:12) at Main.stackLeak(Main.java:13)
(2)虛擬機在擴展是無法分配到足夠的內存。
3,方法常量區。你可以通過以下設置 -XX:PermSize=3M -XX:MaxPermSize=3M 然后在項目中加載大量的類,即會產生內存泄漏,泄漏信息為PermGen space.或者在常量去加入大
量數據也可能會報以上錯誤。不過在jdk1.7及以上版本,通過String.intern()方法並不會把常量去擠破,因為常量區存放的是新建字符串的引用。
4,堆。堆溢出是最常見的內存溢出情況。堆中存放的是對象的信息。如果項目中產生的對象過大,又由於彼此引用而不能被GC回收時,就會出現內存溢出。舉例看下具體情況:
代碼:
public class Test {public static void main(String[]args){List<People> list = new ArrayList<People>();while(true){list.add(new People());}}public static class People {public String name = "zeng";public int age = 24;}}
輸出:
java.lang.OutOfMemoryError: Java heap spaceDumping heap to java_pid16912.hprof ...Heap dump file created [76764870 bytes in 0.978 secs]Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at Test.main(Test.java:12)
對於堆溢出,情況主要有兩種,一是對象太多,java內存不夠用,這是可以通過設置堆內存大小來調節,如:Xms500m,Xmx1000m,來給堆分配較大的內存。
第二種就不是那么好弄,很多對象本身你是不用的,但是由於又被其它對象引用,導出gc沒法回收。
5,本地方法棧。這個不受虛擬機管理,但是操作系統本事是有內存限制的。太大也會導致內存泄漏。
6,直接內存。直接內存同樣不受虛擬機管理,同樣受操作系統限制,如果默認則和堆內存一樣,同樣也可以自己設置,如:-XX:MaxDirectMemorySize=1000m
通過以上幾種分析:發現如果出現內存泄漏,最可能的原先是由於堆溢出。這個也可以從異常信息分析出
OutOfMemory -java heap space:堆溢出
OutOfMemory -PerGem space:方法常量區溢出
StackOverFlowError.:棧溢出
至於其余幾種溢出,可以通過分析操作系統內存大小限制以及設置的堆內存,棧內存來判斷。
