天天看點

java記憶體洩漏(java記憶體洩漏排查)

java中會存在記憶體洩漏嗎?

會。如:int i,i2; return (i-i2); //when i為足夠大的正數,i2為足夠大的負數。結果會造成溢位,導緻錯誤。

以上是我對于這個問題的解答,希望能夠幫到大家。

如何防止JAVA記憶體洩漏?

MAP等集合對象會始終存有對對象的引用,使得這些對象不能被GC回收 請采納我的答案。

如何編寫一個java記憶體洩露程式?

自己改一下下面的代碼,把堆棧中的元素改成mp3類型的或更大點的東西

4.Java中參數都是傳值的。

對于基本類型,大家基本上沒有異議,但是對于引用類型我們也不能有異議。

Java記憶體洩露情況

JVM回收算法 是很複雜的,我也不知道他們怎麼實作的,但是我隻知道他們要實作的就是:對于沒有被引用的對象是可以回收的。是以你要造成記憶體洩露就要做到:

持有對無用對象的引用!

不要以為這個很輕易做到,既然無用,你怎麼還會持有它的引用? 既然你還持有它,它怎麼會是無用的呢?

以下以堆棧更經典這個經典的例子來剖析。

Java代碼

public class Stack { 
 private Object[] elements=new Object[10]; 
 private int size = 0; 
 public void push(Object e){ 
 ensureCapacity(); 
 elements[size++] = e; 
 public Object pop(){ 
 if( size == 0) 
throw new EmptyStackException(); 
return elements[--size]; 
private void ensureCapacity(){ 
 if(elements.length == size){ 
 Object[] oldElements = elements; 
 elements = new Object[2 * elements.length+1]; 
 System.arraycopy(oldElements,0, elements, 0, size);      

上面的原理應該很簡單,假如堆棧加了10個元素,然後全部彈出來,雖然堆棧是空的,沒有我們要的東西,但是這是個對象是無法回收的,這個才符合了記憶體洩露的兩個條件:無用,無法回收。

但是就是存在這樣的東西也不一定會導緻什麼樣的後果,假如這個堆棧用的比較少,也就浪費了幾個K記憶體而已,反正我們的記憶體都上G了,哪裡會有什麼影響,再說這個東西很快就會被回收的,有什麼關系。下面看兩個例子。

例子1

Java代碼

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個引用,最壞的情況就是他們都是無用的,因為我們一旦放新的進取,以前的引用自然消失!

例子2

Java代碼

public class NotTooBad{ 
 public void doSomething(){ 
 Stack s=new Stack(); 
 s.push(new Object()); 
 //other code 
 s.pop();//這裡同樣導緻對象無法回收,記憶體洩露. 
 }//退出方法,s自動無效,s可以被回收,Stack内部的引用自然沒了,是以 
 //這裡也可以自愈,而且可以說這個方法不存在記憶體洩露問題,不過是晚一點 
 //交給GC而已,因為它是封閉的,對外不開放,可以說上面的代碼99.9999%的 
 //情況是不會造成任何影響的,當然你寫這樣的代碼不會有什麼壞的影響,但是 
 //絕對可以說是垃圾代碼!沒有沖突吧,我在裡面加一個空的for循環也不會有 
 //什麼太大的影響吧,你會這麼做嗎?      

}1、首先得搞清楚什麼叫記憶體洩露,簡單來說就是一個東西放在記憶體裡的時間太長了,當你的程式都跑完了,它還存在那裡。這時它是白白的占用了你的記憶體,累積起來占用的記憶體越來越多……最後就會導緻jvm報錯:out of memory。

2、一般情況下,别人如果能指出你的系統(程式)記憶體溢出,這個人應該還是挺厲害的。通常對于新人來說,喜歡把變量直接定義在class下(此時稱之為執行個體變量,或者成員變量),那麼在方法裡調用後,這個執行個體變量是不會被釋放的,大量的這樣使用就可能會引發記憶體洩露。

3、把變量定義在方法裡,當這個方法執行完畢後記憶體就得到釋放了,這是個好習慣。

4、如果想要看到記憶體溢出,可以按這樣的思路去嘗試一下:定義一個靜态的執行個體變量(list或其它集合),然後在一個方法裡循環往這個靜态變量塞東西,直到這個執行個體變量撐爆你的jvm記憶體。很快你就能看到out of memory……

import java.util.arraylist;
import java.util.list;
public class memorytest {
 private static list list = new arraylist();
 private static int count = 0;
 public static void main(string[] args) throws interruptedexception {
 system.out.println("申請前的可用記憶體 = "+getfreememory());
 while(true){
list.add(new byte[1024*1024]);//用執行個體變量申請1m記憶體,當方法執行完畢時,這個static的變量是不會被釋放
count++;
if (count % 100 == 0) {
system.out.println("目前list.size()="+list.size()+",可用記憶體 = "+getfreememory());
thread.sleep(500);
}
 public static long getfreememory() {
return runtime.getruntime().freememory() / (1024 * 1024);      

}不用這樣吧,jdk1.6裡面有個可以檢視記憶體映像的可視化工具,你可以用它來看記憶體中的各個對象的記憶體占用情況,一些ide裡面也有這樣的工具

java不容易記憶體洩露,但一旦洩露,查找起來還是很不容易的,網上有人發過一些自己發現過的錯誤,你可以去搜一下,參考下List list = new ArrayList();

long l;

for(;;) list.add((l++)+"test")

java在什麼情況下會出現記憶體洩露

記憶體洩露就是指一個不再被程式使用的對象或變量一直被占據在記憶體中。java中的記憶體洩露的情況:

1.長生命周期的對象持有短生命周期對象的引用就很可能發生記憶體洩露,例如,緩存系統,我們加載了一個對象放在緩存中(例如放在一個全局map對象中),然後一直不再使用它,這個對象一直被緩存引用,但卻不再被使用。

2.集合類,而如果集合類是全局性的變量(比如類中的靜态屬性,全局性的map等即有靜态引用或final一直指向它),那麼沒有相應的删除機制,很可能導緻集合所占用的記憶體隻增不減,是以提供這樣的删除機制或者定期清除政策非常必要。