动力节点旗下在线教育品牌  |  咨询热线:400-8080-105 学Java全栈,上蛙课网
首页 > 文章

避免内部类内存泄漏三种方式

08-07 17:24 222浏览
举报 T字号
  • 大字
  • 中字
  • 小字

内存泄漏简单来说就是一个不再被程序使用的对象或变量还在内存中占有存储空间的情况。内存泄漏的情况下,会造成部分内存不可用的情况,而且指向这块内存空间的指针不再存在时,这块内存也就永远不可达了,内存空间就这么一点点被蚕食。因此,避免内存泄漏刻不容缓。而内部类的内存泄漏是内存泄漏的典型。下面为大家介绍避免内部类内存泄漏三种方式

之所以会发生这种类型的内存泄漏,是因为内部类必须始终能够访问其外部类-并非总是与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

    尽管我们能够采取措施避免内部类内存泄漏,但是有些内存泄漏的发生真的是防不胜防。这就需要我们从根源上解决内存泄漏的问题,在编程过程中要尽早释放无用对象的引用,尽量少用静态变量运用对象池技术以提高系统性能,避免内存泄露的出现。

0人推荐
共同学习,写下你的评论
0条评论
天鹏桑
程序员天鹏桑

12篇文章贡献57547字

作者相关文章更多>

推荐相关文章更多>

Java数据结构

HelloWorld10-31 08:24

浅谈MySQL中SQL优化的常用方法

军哥08-12 23:29

五分钟读懂UML类图

江湖人称小李白12-10 10:41

MyBatis开发框架的四大核心

IT逐梦者08-17 21:43

一次搞定continue,break和return

HelloWorld11-06 11:19

发评论

举报

0/150

取消