很多人在談論內存洩露問題
當然對於c/c++來說
這個應該是老掉牙的問題
但是很多Java人員也越來越多得討論這個問題
我這裡寫個小結
希望對大家有一定的參考價值
內存洩漏的慨念 c/c++是程序員自己管理內存
Java內存是由GC自動回收的
我雖然不是很熟悉C++
不過這個應該沒有犯常識性錯誤吧
什麼是內存洩露?
內存洩露是指系統中存在無法回收的內存
有時候會造成內存不足或系統崩潰
在C/C++中分配了內存不釋放的情況就是內存洩露
Java存在內存洩露
我們必須先承認這個
才可以接著討論
雖然Java存在內存洩露
但是基本上不用很關心它
特別是那些對代碼本身就不講究的就更不要去關心這個了
Java中的內存洩露當然是指
存在無用但是垃圾回收器無法回收的對象
而且即使有內存洩露問題存在
也不一定會表現出來
Java中參數都是傳值的
對於基本類型
大家基本上沒有異議
但是對於引用類型我們也不能有異議
Java內存洩露情況 JVM回收算法是很復雜的
我也不知道他們怎麼實現的
但是我只知道他們要實現的就是
對於沒有被引用的對象是可以回收的
所以你要造成內存洩露就要做到
持有對無用對象的引用!
不要以為這個很容易做到
既然無用
你怎麼還會持有它的引用? 既然你還持有它
它怎麼會是無用的呢?
我實在想不到比那個堆棧更經典的例子了
以致於我還要引用別人的例子
下面的例子不是我想到的
是書上看到的
當然如果沒有在書上看到
可能過一段時間我自己也想的到
可是那時我說是我自己想到的也沒有人相信的
public class Stack {
private Object[] elements=new Object[
];
private int size =
;
public void push(Object e){
ensureCapacity();
elements[size++] = e;
}
public Object pop(){
if( size ==
)
throw new EmptyStackException();
return elements[
size];
}
private void ensureCapacity(){
if(elements
length == size){
Object[] oldElements = elements;
elements = new Object[
* elements
length+
];
System
arraycopy(oldElements
elements
size);
}
}
}
上面的原理應該很簡單
假如堆棧加了
個元素
然後全部彈出來
雖然堆棧是空的
沒有我們要的東西
但是這是個對象是無法回收的
這個才符合了內存洩露的兩個條件
無用
無法回收
但是就是存在這樣的東西也不一定會導致什麼樣的後果
如果這個堆棧用的比較少
也就浪費了幾個K內存而已
反正我們的內存都上G了
哪裡會有什麼影響
再說這個東西很快就會被回收的
有什麼關系
下面看兩個例子
例子
public class Bad{
public static Stack s=Stack();
static{
s
push(new Object());
s
pop(); //這裡有一個對象發生內存洩露
s
push(new Object()); //上面的對象可以被回收了
等於是自愈了
}
}
因為是static
就一直存在到程序退出
但是我們也可以看到它有自愈功能
就是說如果你的Stack最多有
個對象
那麼最多也就只有
個對象無法被回收其實這個應該很容易理解
Stack內部持有
個引用
最壞的情況就是他們都是無用的
因為我們一旦放新的進取
以前的引用自然消失!
例子
public class NotTooBad{
public void doSomething(){
Stack s=new Stack();
s
push(new Object());
//other code
s
pop();//這裡同樣導致對象無法回收
內存洩露
}//退出方法
s自動無效
s可以被回收
Stack內部的引用自然沒了
所以
//這裡也可以自愈
而且可以說這個方法不存在內存洩露問題
不過是晚一點
//交給GC而已
因為它是封閉的
對外不開放
可以說上面的代碼
%的
//情況是不會造成任何影響的
當然你寫這樣的代碼不會有什麼壞的影響
但是
//絕對可以說是垃圾代碼!沒有矛盾吧
我在裡面加一個空的for循環也不會有
//什麼太大的影響吧
你會這麼做嗎?
}
上面兩個例子都不過是小打小鬧
但是C/C++中的內存洩露就不是Bad了
而是Worst了
他們如果一處沒有回收就永遠無法回收
頻繁的調用這個方法內存不就用光了!因為Java還有自愈功能(我自己起的名字
還沒申請專利)
所以Java的內存洩露問題幾乎可以忽略了
但是知道的人就不要犯了
不知者無罪!Java存在內存洩露
但是也不要誇大其辭
如果你對Java都不是很熟
你根本就不用關心這個
我說過你無意中寫出內存洩露的例子就像你中一千萬一樣概率小
開玩笑了
其實應該是小的多的多!
而且即使你有幸寫出這樣的代碼
中獎了!基本上都是一包洗衣粉
不會讓你發財
對系統沒有什麼大的影響
杞人憂天的情況 無話可說型
Object obj=new Object();
obj=null;
//這個完全多此一舉
因為退出了作用范圍
對象的引用自動消失
//不要在你的程序中出現這樣的語句
沒有錯
但是就是不雅觀
思考不對型
void func(Object o){
o=new Object();
return
}
當我們知道Java參數是傳值
就知道上面的方法什麼也沒錯
就是申請了一個對象然後再丟給GC
因為是傳值
這裡的o是一個調用時候的拷貝
會不會無法回收?不就是拷貝嗎
退出方法什麼都沒了
這個對象怎麼會留的住
盡量避免型
class A{
B b=new B(this);
}
class B{
A a;
B(A a){this
a=a;}
}
這個存在互相引用
可能導致孤島現象
但是這個不會造成內存洩露不過我自己覺得這個會降低GC的效率
就從我的智力來看
我覺得這種情況比一般情況難以判斷怎麼回收!當然GC比我聰明
不過應該也要動一點腦子吧
From:http://tw.wingwit.com/Article/program/Java/JSP/201311/19325.html