java避免内存泄露_Java防止非静态内部类内存泄漏
內存泄漏
一個不會被使用的對象,因為另一個正在使用的對象持有該對象的引用,導致它不能正常被回收,而停留在堆內存中,從而導致內存泄漏。
最壞的情況下,由于大量的內存泄漏,最終導致jvm的內存耗盡,致使程序奔潰。也可能會導致內存空間不足,jvm出現頻繁的GC。
代碼示例
import java.util.ArrayList;
class OuterClass
{
private int[] data;
public OuterClass(int size)
{
data = new int[size];
}
class InnerClass
{
}
InnerClass getInnerClassObject()
{
return new InnerClass();
}
}
public class MemoryLeak
{
public static void main(String[] args)
{
ArrayList al = new ArrayList<>();
int counter = 0;
while (true)
{
al.add(new OuterClass(100000).getInnerClassObject());
System.out.println(counter++);
}
}
}
執行以上代碼,輸出結果,最終導致了堆內存溢出。
7639
7640
7641
7642
7643
7644
7645
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at EnclosingClass.(MemoryLeak.java:9)
at MemoryLeak.main(MemoryLeak.java:30)
原因分析
我們使用java提供的工具javap,可以對編譯生成的.class文件做分析。也可以使用一些反編譯工具對生成的.class反編譯,也可以看到內部類的代碼實現。
javap OuterClass$InnerClass
輸出類似于:
Compiled from "OuterClass.java"
public class OuterClass$InnerClass {
final OuterClass this$0;
public OuterClass$InnerClass(OuterClass);
}
可以看到內部類InnerClass存在一個this$0的OuterClass的變量,此變量是通過InnerClass的構造函數傳進來的。
示例代碼中創建了一個數組列表ArrayList,它將用來存放InnerClass的對象。生成InnerClass對象前,需要先構造OuterClass。OuterClass構造時默認創建了一個100000大小的整型數組。相當于一個初始化的OuterClass默認占用10000個int整型的空間。在MemoryLeak,通過循環while不斷向a1添加InnerClass對象。對于每次循環來說new OuterClass后,就不會再使用OuterClass對象。但通過分析內部了的實現,即使OuterClass對象不會再被使用,內部類InnerClass對象里還是保存了大對象OuterClass,導致OuterClass的生命周期是和InnerClass一樣,最終導致內存泄漏。
非靜態內部類使用注意
1、如果外部類是一個大對象,必須要謹慎使用非靜態內部類,特別時生命周期長的非靜態內部類,這樣容易造成內存溢出OutOfMemoryError。
2、之所以強調非靜態,對于靜態內部類來說,它的內部實現是不存放外部類的,所以再合理編碼的情況下,使用靜態內部類。
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的java避免内存泄露_Java防止非静态内部类内存泄漏的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 结合 category 工作原理分析 O
- 下一篇: 【Foreign】采蘑菇 [点分治]