Ⅰ java內存溢出是什麼情況
首先先說一下JVM內存結構問題,JVM為兩塊:PermanentSapce和HeapSpace,其中x0dx0aHeap = }。PermantSpace負責保存反射對象,一般不用配置。JVM的Heap區可以通過-X參數來設定。x0dx0a 當一個URL被訪問時,內存申請過程如下:x0dx0aA. JVM會試圖為相關Java對象在Eden中初始化一塊內存區域x0dx0aB. 當Eden空間足夠時,內存申請結束。否則到下一步x0dx0aC. JVM試圖釋放在Eden中所有不活躍的對象(這屬於1或更高級的垃圾回收), 釋放後若Eden空間仍然不足以放入新對象,則試圖將部分Eden中活躍對象放入Survivor區x0dx0aD. Survivor區被用來作為Eden及OLD的中間交換區域,當OLD區空間足夠時,Survivor區的對象會被移到Old區,否則會被保留在Survivor區x0dx0aE. 當OLD區空間不夠時,JVM會在OLD區進行完全的垃圾收集(0級)x0dx0aF. 完全垃圾收集後,若Survivor及OLD區仍然無法存放從Eden復制過來的部分對象,導致JVM無法在Eden區為新對象創建內存區域,則出現」out of memory錯誤」x0dx0ax0dx0aJVM調優建議:x0dx0ax0dx0ams/mx:定義YOUNG+OLD段的總尺寸,ms為JVM啟動時YOUNG+OLD的內存大小;mx為最大可佔用的YOUNG+OLD內存大小。在用戶生產環境上一般將這兩個值設為相同,以減少運行期間系統在內存申請上所花的開銷。x0dx0aNewSize/MaxNewSize:定義YOUNG段的尺寸,NewSize為JVM啟動時YOUNG的內存大小;MaxNewSize為最大可佔用的YOUNG內存大小。在用戶生產環境上一般將這兩個值設為相同,以減少運行期間系統在內存申請上所花的開銷。x0dx0aPermSize/MaxPermSize:定義Perm段的尺寸,PermSize為JVM啟動時Perm的內存大小;MaxPermSize為最大可佔用的Perm內存大小。在用戶生產環境上一般將這兩個值設為相同,以減少運行期間系統在內存申請上所花的開銷。x0dx0aSurvivorRatio:設置Survivor空間和Eden空間的比例x0dx0ax0dx0a內存溢出的可能性x0dx0ax0dx0a1. OLD段溢出x0dx0a這種內存溢出是最常見的情況之一,產生的原因可能是:x0dx0a1) 設置的內存參數過小(ms/mx, NewSize/MaxNewSize)x0dx0a2) 程序問題x0dx0a單個程序持續進行消耗內存的處理,如循環幾千次的字元串處理,對字元串處理應建議使用StringBuffer。此時不會報內存溢出錯,卻會使系統持續垃圾收集,無法處理其它請求,相關問題程序可通過Thread Dump獲取(見系統問題診斷一章)單個程序所申請內存過大,有的程序會申請幾十乃至幾百兆內存,此時JVM也會因無法申請到資源而出現內存溢出,對此首先要找到相關功能,然後交予程序員修改,要找到相關程序,必須在Apache日誌中尋找。x0dx0a當Java對象使用完畢後,其所引用的對象卻沒有銷毀,使得JVM認為他還是活躍的對象而不進行回收,這樣累計佔用了大量內存而無法釋放。由於目前市面上還沒有對系統影響小的內存分析工具,故此時只能和程序員一起定位。x0dx0ax0dx0a2. Perm段溢出x0dx0a通常由於Perm段裝載了大量的Servlet類而導致溢出,目前的解決辦法:x0dx0a1) 將PermSize擴大,一般256M能夠滿足要求x0dx0a2) 若別無選擇,則只能將servlet的路徑加到CLASSPATH中,但一般不建議這么處理x0dx0ax0dx0a3. C Heap溢出x0dx0a系統對C Heap沒有限制,故C Heap發生問題時,Java進程所佔內存會持續增長,直到佔用所有可用系統內存x0dx0ax0dx0a參數說明:x0dx0ax0dx0aJVM 堆內存(heap)設置選項 x0dx0a 參數格式 x0dx0a 說 明 x0dx0a x0dx0a設置新對象生產堆內存(Setting the Newgeneration heap size) x0dx0a -XX:NewSize x0dx0a 通過這個選項可以設置Java新對象生產堆內存。在通常情況下這個選項的數值為1 024的整數倍並且大於1MB。這個值的取值規則為,一般情況下這個值-XX:NewSize是最大堆內存(maximum heap size)的四分之一。增加這個選項值的大小是為了增大較大數量的短生命周期對象 x0dx0ax0dx0a增加Java新對象生產堆內存相當於增加了處理器的數目。並且可以並行地分配內存,但是請注意內存的垃圾回收卻是不可以並行處理的 x0dx0a x0dx0a設置最大新對象生產堆內存(Setting the maximum New generation heap size) x0dx0a -XX:MaxNewSize x0dx0a 通過這個選項可以設置最大Java新對象生產堆內存。通常情況下這個選項的數值為1 024的整數倍並且大於1MB x0dx0ax0dx0a其功用與上面的設置新對象生產堆內存-XX:NewSize相同x0dx0ax0dx0a設置新對象生產堆內存的比例(Setting New heap size ratios) x0dx0a -XX:SurvivorRatio x0dx0a 新對象生產區域通常情況下被分為3個子區域:伊甸園,與兩個殘存對象空間,這兩個空間的大小是相同的。通過用-XX:SurvivorRatio=X選項配置伊甸園與殘存對象空間(Eden/survivor)的大小的比例。你可以試著將這個值設置為8,然後監控、觀察垃圾回收的工作情況x0dx0ax0dx0a設置堆內存池的最大值(Setting maximum heap size) x0dx0a -Xmx x0dx0a 通過這個選項可以要求系統為堆內存池分配內存空間的最大值。通常情況下這個選項的數值為1 024的整數倍並且大於1 MB x0dx0ax0dx0a一般情況下這個值(-Xmx)與最小堆內存(minimum heap size _Xms)相同,以降低垃圾回收的頻度 x0dx0a x0dx0a取消垃圾回收 x0dx0a -Xnoclassgc x0dx0a 這個選項用來取消系統對特定類的垃圾回收。它可以防止當這個類的所有引用丟失之後,這個類仍被引用時不會再一次被重新裝載,因此這個選項將增大系統堆內存的空間 x0dx0a x0dx0a設置棧內存的大小 x0dx0a -Xss x0dx0a 這個選項用來控制本地線程棧的大小,當這個選項被設置的較大(>2MB)時將會在很大程度上降低系統的性能。因此在設置這個值時應該格外小心,調整後要注意觀察系統的性能,不斷調整以期達到最優 x0dx0a x0dx0a最後說一句,你的機器的連接數設置也至關重要,連接的關閉最好把時間設置的少些,那些連接非常耗費資源。也是引起內存泄露的主要原因。
Ⅱ Java內存溢出主要有哪些類型
主要有三種類型
第一種OutOfMemoryError: PermGen space
發生這種問題的原意是程序中使用了大量的jar或class,使java虛擬機裝載類的空間不夠,與Permanent Generation space有關。解決這類問題有以下兩種辦法:
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: Java heap space
發生這種問題的原因是java虛擬機創建的對象太多,在進行垃圾回收之間,虛擬機分配的到堆內存空間已經用滿了,與Heap space有關。解決這類問題有兩種思路:
1. 檢查程序,看是否有死循環或不必要地重復創建大量對象。找到原因後,修改程序和演算法。
我以前寫一個使用K-Means文本聚類演算法對幾萬條文本記錄(每條記錄的特徵向量大約10來個)進行文本聚類時,由於程序細節上有問題,就導致了Java heap space的內存溢出問題,後來通過修改程序得到了解決。
2. 增加Java虛擬機中Xms(初始堆大小)和Xmx(最大堆大小)參數的大小。如:set JAVA_OPTS= -Xms256m -Xmx1024m
第三種OutOfMemoryError:unable to create new native thread
這種錯誤在Java線程個數很多的情況下容易發生
Ⅲ java有內存溢出嗎如果有是什麼情況
內存溢出是指應用系統中存在無法回收的內存或使用的內存過多,最終使得程序運行要用到的內存大於虛擬機能提供的最大內存。
所以我們應該明確:存在內存溢出的因不一定導致內存溢出的果。。。
1。JAVA操作文本文件為什麼超過3萬行就內存益處啊?
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(fileName)));
//PrintWriter out = new PrintWriter(fileName);
//FileOutputStream out = new FileOutputStream(fileName);
while (rs.next()) {
for (int j = 1; j <= totalColumn; j++) {
out.write(rs.getObject(j).toString());
out.write("\t");
}
out.write("\n");
out.flush();
}
}
我在代碼中 寫了 out.flush()用來刷新該流的緩沖; 可是當我的記錄數超過3W時就報了內存益處的問題了,難道JAVA不能邊讀邊寫嗎?還是out這個對象隨著指向的fileName文件的邊大佔用內存也大了嗎??到底怎麼來實現用JAVA寫更多的數據而不內存益處呢
答案是:就在while(rs.next()) 當rs.next()時內存不斷增大,而不是寫流的問題,JAVA的ResultSet真是麻煩,而且ResultSet還不能clone(); 所以記得在做項目的時候,經常要設置:jdbc.setMaxRows(100*10000); //設置能容納100萬行記錄-----這個就是防止內存泄露的哈------------------- 內存中載入的數據量過於龐大,如一次從資料庫取出過多數據;
jdbc.setQueryTimeout(60*30); //設置超時時間是30分鍾
2。java中的內存泄露的情況:長生命周期的對象持有短生命周期對象的引用就很可能發生內存泄露,盡管短生命周期對象已經不再需要,但是因為長生命周期對象持有它的引用而導致不能被回收,這就是java中內存泄露的發生場景,通俗地說,就是程序員可能創建了一個對象,以後一直不再使用這個對象,這個對象卻一直被引用,即這個對象無用但是卻無法被垃圾回收器回收的,這就是java中可能出現內存泄露的情況,例如,緩存系統,我們載入了一個對象放在緩存中(例如放在一個全局map對象中),然後一直不再使用它,這個對象一直被緩存引用,但卻不再被使用。
public class Stack { //長生命周期
private Object[] elements=new Object[10]; //當數組容器中沒有東西時是無用的,但是無法回收~~elements是短生命周期
private int size = 0;
public void push(Object e){
ensureCapacity();
elements[size++] = e;
}
public Object pop(){
if( size == 0)
throw new EmptyStackException();
//這里還是引用了,只是指針變位置變化而已,他確實返回了那個對象,但是他卻沒有斷開那個對象的引用,也就是說有兩個地方會持有這個對象的引用,調用pop的地方,和elements中
return elements[--size];
}
private void ensureCapacity(){
if(elements.length == size){
Object[] oldElements = elements;
elements = new Object[2 * elements.length+1];
System.array(oldElements,0, elements, 0, size);
}
}
}
上面的原理應該很簡單,假如堆棧加了10個元素,然後全部彈出來,雖然堆棧是空的,沒有我們要的東西,但是這是個對象是無法回收的,這個才符合了內存泄露的兩個條件(必要條件):無用,無法回收。
例子1
public class Bad{
public static Stack s=Stack();
static{
s.push(new Object());
s.pop(); //這里有一個對象發生內存泄露
s.push(new Object()); //上面的對象可以被回收了,等於是自愈了,因為引用被覆蓋了
}
}
因為是static,就一直存在到程序退出,但是我們也可以看到它有自愈功能,就是說如果你的Stack最多有100個對象,那麼最多也就只有100個對象無法被回收其實這個應該很容易理解,Stack內部持有100個引用,最壞的情況就是他們都是無用的,因為我們一旦放新的進取,以前的引用自然消失!
內存泄露的另外一種情況:當一個對象被存儲進HashSet集合中以後,就不能修改這個對象中的那些參與計算哈希值的欄位了,否則,對象修改後的哈希值與最初存儲進HashSet集合中時的哈希值就不同了,在這種情況下,即使在contains方法使用該對象的當前引用作為的參數去HashSet集合中檢索對象,也將返回找不到對象的結果,這也會導致無法從HashSet集合中單獨刪除當前對象,造成內存泄露。
這是屬於: 集合類中有對對象的引用,使用完後未清空,使得JVM不能回收;
3。代碼中存在死循環或循環產生過多重復的對象實體;
4。啟動參數內存值設定的過小;
Ⅳ java內存溢出的問題如何排查
java程序大家都知道,內存溢出是經常見的錯誤,下面從基本的開始分析!
內存溢出是由於沒被引用的對象(垃圾)過多造成JVM沒有及時回收,造成的內存溢出。如果出現這種現象可行代碼排查:
一)是否App中的類中和引用變數過多使用了Static修飾 如public staitc Student s;在類中的屬性中使用 static修飾的最好只用基本類型或字元串。如public static int i = 0; //public static String str;
二)是否App中使用了大量的遞歸或無限遞歸(遞歸中用到了大量的建新的對象)
三)是否App中使用了大量循環或死循環(循環中用到了大量的新建的對象)
四)檢查App中是否使用了向資料庫查詢所有記錄的方法。即一次性全部查詢的方法,如果數據量超過10萬多條了,就可能會造成內存溢出。所以在查詢時應採用「分頁查詢」。
五)檢查是否有數組,List,Map中存放的是對象的引用而不是對象,因為這些引用會讓對應的對象不能被釋放。會大量存儲在內存中。
六)檢查是否使用了「非字面量字元串進行+」的操作。因為String類的內容是不可變的,每次運行"+"就會產生新的對象,如果過多會造成新String對象過多,從而導致JVM沒有及時回收而出現內存溢出。
如String s1 = "My name";
String s2 = "is";
String s3 = "xuwei";
String str = s1 + s2 + s3 +.........;這是會容易造成內存溢出的
但是String str = "My name" + " is " + " xuwei" + " nice " + " to " + " meet you"; //但是這種就不會造成內存溢出。因為這是」字面量字元串「,在運行"+"時就會在編譯期間運行好。不會按照JVM來執行的。
在使用String,StringBuffer,StringBuilder時,如果是字面量字元串進行"+"時,應選用String性能更好;如果是String類進行"+"時,在不考慮線程安全時,應選用StringBuilder性能更好。
知道原因了,解決起來就非常簡單了。
Ⅳ java內存溢出
使用Java程序從資料庫中查詢大量的數據時出現異常:java.lang.OutOfMemoryError: Java heap space
在JVM中如果98%的時間是用於GC且可用的 Heap size 不足2%的時候將拋出此異常信息。
JVM堆的設置是指java程序運行過程中JVM可以調配使用的內存空間的設置.JVM在啟動的時候會自動設置Heap size的值,其初始空間(即-Xms)是物理內存的1/64,最大空間(-Xmx)是物理內存的1/4。可以利用JVM提供的-Xmn -Xms -Xmx等選項可進行設置。
例如:java -jar -Xmn16m -Xms64m -Xmx128m MyApp.jar
如果Heap Size設置偏小,除了這些異常信息外,還會發現程序的響應速度變慢了。GC佔用了更多的時間,而應用分配到的執行時間較少。
Heap Size 最大不要超過可用物理內存的80%,一般的要將-Xms和-Xmx選項設置為相同,而-Xmn為1/4的-Xmx值。
Heap size的 -Xms -Xmn 設置不要超出物理內存的大小。否則會提示「Error occurred ring initialization of VM Could not reserve enough space for object heap」。
這個問題的根源是jvm虛擬機的默認Heap大小是64M,可以通過設置其最大和最小值來實現.設置的方法主要是幾個.
1.可以在windows 更改系統環境變數加上JAVA_OPTS=-Xms64m -Xmx512m
2,如果用的tomcat,在windows下,可以在C:\tomcat5.5.9\bin\catalina.bat 中加上:
set JAVA_OPTS=-Xms64m -Xmx256m
位置在: rem Guess CATALINA_HOME if not defined 這行的下面加合適.
3.如果是linux系統
Linux 在{tomcat_home}/bin/catalina.sh的前面,加 set JAVA_OPTS='-Xms64 -Xmx512'