内存泄漏只是一个不再被程序使用的对象或变量仍然占据内存中的存储空间。当内存泄漏时,会导致部分内存不可用,当指向内存空间的指针不再存在时,内存将永远无法到达,内存空间将被侵蚀一点。因此,迫切需要避免内存泄漏。内部内存泄漏是典型的内存泄漏。以下是介绍避免内部内存泄漏三种方式。
这种类型的内存泄漏的原因是内部类必须始终能够访问其外部类型-并不总是与JVM计划一起使用。从简单的嵌套过程到内存缺陷错误(并可能关闭JVM)是内部内存泄漏的完整过程。我们总结了三种避免内部内存泄漏的方法。
一、内部类引用外部类
内部类的任何实例都包含对其外部类的隐藏引用。例如,考虑以下内容EnclosingClass带嵌套的EnclosedClass非静态成员声明:
public class EnclosingClass
{
public class EnclosedClass
{
}
}
为了更好地理解这种联系,我们可以使用上述源代码(javac EnclosingClass.java)Enclosingclass.class和EnclosingClass$EnclosedClass.class,然后检查后者的类文件。JDK包含Javap(Java打印)反汇编文件的工具。在命令行上,以EnclosingClass$EnclosedClass为依据的javap如下:
javap EnclosingClass$EnclosedClass
观察以下输出,显示包含以下内容的合成(制造)final EnclosingClass this$Enclosingclass:
Compiled from "EnclosingClass.java"
public class EnclosingClass$EnclosedClass {
final EnclosingClass this$0;
public EnclosingClass$EnclosedClass(EnclosingClass);
}
二、构造函数获取封闭类引用
上面的输出显示带有EnclosingClass参数的构造函数。javap使用-v(verbose)在选项执行中,我们将观察到结构函数将EnclosingClass对象引用并保存在this$0字段中:
final EnclosingClass this$0;
descriptor: LEnclosingClass;
flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC
public EnclosingClass$EnclosedClass(EnclosingClass);
descriptor: (LEnclosingClass;)V
flags: (0x0001) ACC_PUBLIC
Code:
stack=2, locals=2, args_size=2
0: aload_0
1: aload_1
2: putfield #1 // Field this$0:LEnclosingClass;
5: aload_0
6: invokespecial #2 // Method java/lang/Object."":()V
9: return
LineNumberTable:
line 3: 0
声明一种新的方法
接下来,假设在另一个实例类中声明了一种方法EnclosingClass,然后是EnclosedClass。下一个代码片段揭示了这个实例序列:
EnclosingClass ec = new EnclosingClass();
ec.new EnclosedClass();
以下javap输出显示了此源代码的字节码转换。第18行显示了正确的呼叫EnclosingClass$EnclosedClass(EnclosingClass)。该调用是将封闭类引用保存在封闭类中:
0: new #2 // class EnclosingClass
3: dup
4: invokespecial #3 // Method EnclosingClass."":()V
7: astore_1
8: new #4 // class EnclosingClass$EnclosedClass
11: dup
12: aload_1
13: dup
14: invokestatic #5 // Method java/util/Objects.requireNonNull:(Ljava/lang/Object;)Ljava/lang/Object;
17: pop
18: invokespecial #6 // Method EnclosingClass$EnclosedClass."":(LEnclosingClass;)V
21: pop
22: return
虽然我们可以采取措施避免内部内存泄漏,但一些内存泄漏的发生确实是不可能预防的。这就要求我们从根本上解决内存泄漏的问题,在编程过程中尽快释放无用对象的参考,尽量少使用静态变量,使用对象池技术来提高系统性能,避免内部类内存泄漏的出现。