java既然存在gc線程,為什么還存在內存泄漏?


1.既然 Java 的垃圾回收機制能夠自動的回收內存,怎么還會出現內存泄漏的情況呢?這個問題,我們需要知道 GC 在什么時候回收內存對象,什么樣的內存對象會被 GC 認為是“不再使用”的。

Java中對內存對象的訪問,使用的是引用的方式。在 Java 代碼中我們維護一個內存對象的引用變量,通過這個引用變量的值,我們可以訪問到對應的內存地址中的內存對象空間。在 Java 程序中,這個引用變量本身既可以存放堆內存中,又可以放在代碼棧的內存中(與基本數據類型相同)。 GC 線程會從代碼棧中的引用變量開始跟蹤,從而判定哪些內存是正在使用的。如果 GC 線程通過這種方式,無法跟蹤到某一塊堆內存,那么 GC 就認為這塊內存將不再使用了(因為代碼中已經無法訪問這塊內存了)。

通過這種有向圖的內存管理方式,當一個內存對象失去了所有的引用之后,GC 就可以將其回收。反過來說,如果這個對象還存在引用,那么它將不會被 GC 回收,哪怕是 Java 虛擬機拋出 OutOfMemoryError 。

2.java內存泄漏的根本原因是?

答:內存對象明明已經不需要的時候,還仍然保留着這塊內存和它的訪問方式(引用)。

3.堆溢出:靜態集合類中存儲對象

java.lang.OutOfMemoryError: Java heap space

4.棧溢出

java.lang.StackOverflowError

5.代碼棧是什么?

答:

Vector v = new  Vector( 10 );  
 for  ( int  i = 1 ;i < 100 ; i ++ ){  
 Object o = new  Object();  
 v.add(o);  
 o = null ;  
 }
在這個例子中,代碼棧中存在Vector 對象的引用 v 和 Object 對象的引用 o 。
在 For 循環中,我們不斷的生成新的對象,然后將其添加到 Vector 對象中,之后將 o 引用置空。問題是當 o 引用被置空后,
如果發生 GC ,
我們創建的 Object 對象是否能夠被 GC 回收呢?
答案是否定的。
因為, GC 在跟蹤代碼棧中的引用時,
會發現 v 引用,而繼續往下跟蹤,就會發現 v 引用指向的內存空間中又存在指向 Object 對象的引用。也就是說盡管 o 引用已經被置空,
但是 Object 對象仍然存在其他的引用,是可以被訪問到的,所以 GC 無法將其釋放掉。
如果在此循環之后, Object 對象對程序已經沒有任何作用,
那么我們就認為此 Java 程序發生了內存泄漏。

7.內存泄漏在哪個領域比較常見?
答:在移動設備對於內存和 CPU都有較嚴格的限制的情況下, Java 的內存溢出會導致程序效率低下、占用大量不需要的內存等問題。這將導致整個機器性能變差,
嚴重的也會引起拋出 OutOfMemoryError ,導致程序崩潰。

 8.如何避免內存泄漏?

答:明確引用變量的生命周期,是方法內部的局部變量,還是類實例變量,與類實例生命周期相同的要聲明為實例變量。

要避免這種情況下的內存泄露,要求我們以C/C++ 的內存管理思維來管理自己分配的內存。第一,是在聲明對象引用之前,明確內存對象的有效作用域。在一個函數內有效的內存對象,應該聲明為 local 變量,與類實例生命周期相同的要聲明為實例變量……以此類推。第二,在內存對象不再需要時,記得手動將其引用置空。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM