Java 内部类有坑。。100 % 内存泄露!()

  本篇文章为你整理了Java 内部类有坑。。100 % 内存泄露!()的详细内容,包含有 Java 内部类有坑。。100 % 内存泄露!,希望能帮助你了解 Java 内部类有坑。。100 % 内存泄露!。

  分享Java技术,高并发编程,分布式技术,架构设计,Java面试题,算法,行业动态,程序人生等。

  
来源:https://knife.blog.csdn.net/article/details/124946774

  今天给大家分享一种,Java内部类使用不当导致的内存泄露问题,最终导致内存溢出!希望能够帮助到大家!

  「说明」

  本文介绍 Java 内部类持有外部类导致内存泄露的原因以及其解决方案。

  「为什么内部类持有外部类会导致内存泄露?」

  非静态内部类会持有外部类,如果有地方引用了这个非静态内部类,会导致外部类也被引用,垃圾回收时无法回收这个外部类(即使外部类已经没有其他地方在使用了)。

  「解决方案」

  不要让其他的地方持有这个非静态内部类的引用,直接在这个非静态内部类执行业务。

  将非静态内部类改为静态内部类。内部类改为静态的之后,它所引用的对象或属性也必须是静态的,所以静态内部类无法获得外部对象的引用,只能从 JVM 的 Method Area(方法区)获取到static类型的引用。

  为什么要持有外部类

  Java 语言中,非静态内部类的主要作用有两个:

  当内部类只在外部类中使用时,匿名内部类可以让外部不知道它的存在,从而减少了代码的维护工作。

  当内部类持有外部类时,它就可以直接使用外部类中的变量了,这样可以很方便的完成调用,如下代码所示:

  

package org.example.a;

 

  class Outer{

   private String outerName = "Tony";

   class Inner{

   private String name;

   public Inner() {

   this.name = outerName;

   Inner createInner() {

   return new Inner();

  public class Demo {

   public static void main(String[] args) {

   Outer.Inner inner = new Outer().createInner();

   System.out.println(inner);

  

 

  但是,静态内部类就无法持有外部类和其非静态字段了。另外,最新 Java 面试题整理:https://www.javastack.cn/mst/

  比如下边这样就会报错

  

package org.example.a;

 

  class Outer{

   private String outerName = "Tony";

   static class Inner{

   private String name;

   public Inner() {

   this.name = outerName;

   Inner createInner() {

   return new Inner();

  public class Demo {

   public static void main(String[] args) {

   Outer.Inner inner = new Outer().createInner();

   System.out.println(inner);

  

 

  报错:

  实例:持有外部类

  「代码」

  

package org.example.a;

 

  class Outer{

   class Inner {

   Inner createInner() {

   return new Inner();

  public class Demo {

   public static void main(String[] args) {

   Outer.Inner inner = new Outer().createInner();

   System.out.println(inner);

  

 

  「断点调试」

  可以看到:内部类持有外部类的对象的引用,是以“this$0”这个字段来保存的。

  实例:不持有外部类

  「代码」

  

package org.example.a;

 

  class Outer{

   static class Inner {

   Inner createInner() {

   return new Inner();

  public class Demo {

   public static void main(String[] args) {

   Outer.Inner inner = new Outer().createInner();

   System.out.println(inner);

  

 

  更多 Java 教程及示例:https://github.com/javastacks/javastack

  「断点调试」

  可以发现:内部类不再持有外部类了。

  实例:内存泄露

  「简介」

  若内部类持有外部类的引用,对内部类的使用很多时,会导致外部类数目很多。此时,就算是外部类的数据没有被用到,外部类的数据所占空间也不会被释放。

  本处在外部类存放大量的数据来模拟。

  「代码」

  

package org.example.a;

 

  import java.util.ArrayList;

  import java.util.List;

  class Outer{

   private int[] data;

   public Outer(int size) {

   this.data = new int[size];

   class Innner{

   Innner createInner() {

   return new Innner();

  public class Demo {

   public static void main(String[] args) {

   List Object list = new ArrayList ();

   int counter = 0;

   while (true) {

   list.add(new Outer(100000).createInner());

   System.out.println(counter++);

  

 

  「测试」

  可以看到:运行了八千多次的时候就内存溢出了。

  我换了一台 mac 电脑,4000 多就内存溢出了。

  不会内存泄露的方案

  「简介」

  内部类改为静态的之后,它所引用的对象或属性也必须是静态的,所以静态内部类无法获得外部对象的引用,只能从 JVM 的 Method Area(方法区)获取到 static 类型的引用。

  「代码」

  

package org.example.a;

 

  import java.util.ArrayList;

  import java.util.List;

  class Outer{

   private int[] data;

   public Outer(int size) {

   this.data = new int[size];

   static class Inner {

   Inner createInner() {

   return new Inner();

  public class Demo {

   public static void main(String[] args) {

   List Object list = new ArrayList ();

   int counter = 0;

   while (true) {

   list.add(new Outer(100000).createInner());

   System.out.println(counter++);

  

 

  「测试」

  可以发现:循环了四十多万次都没有内存溢出。

  近期热文推荐:

  1.1,000+ 道 Java面试题及答案整理(2022最新版)

  2.劲爆!Java 协程要来了。。。

  3.Spring Boot 2.x 教程,太全了!

  4.别再写满屏的爆爆爆炸类了,试试装饰器模式,这才是优雅的方式!!

  5.《Java开发手册(嵩山版)》最新发布,速速下载!

  觉得不错,别忘了随手点赞+转发哦!

  以上就是Java 内部类有坑。。100 % 内存泄露!()的详细内容,想要了解更多 Java 内部类有坑。。100 % 内存泄露!的内容,请持续关注盛行IT软件开发工作室。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: