内存泄漏简单来说就是一个不再被程序使用的对象或变量还在内存中占有存储空间的情况。内存泄漏的情况下,会造成部分内存不可用的情况,而且指向这块内存空间的指针不再存在时,这块内存也就永远不可达了,内存空间就这么一点点被蚕食。因此,避免内存泄漏刻不容缓。而内部类的内存泄漏是内存泄漏的典型。下面为大家介绍避免内部类内存泄漏三种方式。
之所以会发生这种类型的内存泄漏,是因为内部类必须始终能够访问其外部类-并非总是与JVM的计划一起使用。从简单的嵌套过程到内存不足错误(并可能关闭JVM)是一个内部类内存泄漏的完整过程。我们针对内部类内存泄漏的过程,总结出了三种避免内部类内存泄漏的三种方式。
一、内部类引用其外部类
内部类的任何实例都包含对其外部类的隐式引用。例如,考虑以下EnclosingClass带有嵌套的EnclosedClass非静态成员类的声明:
public class EnclosingClass
{
public class EnclosedClass
{
}
}
为了更好地理解这种联系,我们可以将上面的源代码(javac EnclosingClass.java)编译为EnclosingClass.class和EnclosingClass$EnclosedClass.class,然后检查后者的类文件。JDK包含javap用于反汇编类文件的(Java打印)工具。在命令行上,遵循javap以EnclosingClass$EnclosedClass如下:
javap EnclosingClass$EnclosedClass
观察以下输出,该输出显示了包含以下内容的合成(制造)final EnclosingClass this$0字段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
尽管我们能够采取措施避免内部类内存泄漏,但是有些内存泄漏的发生真的是防不胜防。这就需要我们从根源上解决内存泄漏的问题,在编程过程中要尽早释放无用对象的引用,尽量少用静态变量运用对象池技术以提高系统性能,避免内部类内存泄露的出现。
HelloWorld10-31 08:24
军哥08-12 23:29
江湖人称小李白12-10 10:41
IT逐梦者08-17 21:43
HelloWorld11-06 11:19