new arraylist内存_如何避免内部类中的内存泄漏

d253eaf96d6931b12dad9de7f1098e6e.gif

我先假设读者已经熟悉在Java代码中使用嵌套类的基础知识。在本文里,我将展示嵌套类的陷阱,内部类在JVM中引起内存泄漏和内存不足错误的地方。之所以会发生这种类型的内存泄漏,是因为内部类必须始终能够访问其外部类。从简单的嵌套过程到内存不足错误(并可能关闭JVM)是一个过程。我们一步步看他是如何产生的。

步骤1:内部类引用其外部类

内部类的任何实例都包含对其外部类的隐式引用。例如,考虑以下带有嵌套的EnclosedClass非静态成员类的EnclosingClass声明:

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);

}

步骤2:构造函数获取封闭的类引用

上面的输出显示了带有EnclosingClass参数的构造函数。使用-v(详细)选项执行javap,可以观察到构造函数在this $ 0字段中保存了EnclosingClass对象引用:

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

步骤3:声明一个新方法

接下来,我们另一个类中声明一个方法,实例化EnclosingClass,然后实例化EnclosedClass。例如:

EnclosingClass ec = newEnclosingClass();

ec.newEnclosedClass();

下面的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

内存泄漏的解剖

在以上示例中,根据应用程序代码,可能会耗尽内存并收到内存不足错误,从而导致JVM终止。下面的清单演示了这种情况。

import java.util.ArrayList;

class EnclosingClass

{

private int[] data;

public EnclosingClass(int size)

{

data = new int[size];

}

class EnclosedClass

{

}

EnclosedClass getEnclosedClassObject()

{

return new EnclosedClass();

}

}

public class MemoryLeak

{

public static void main(String[] args)

{

ArrayList al = new ArrayList<>();

int counter = 0;

while (true)

{

al.add(new EnclosingClass(100000).getEnclosedClassObject());

System.out.println(counter++);

}

}

}

EnclosingClass声明一个引用整数数组的私有数据字段。数组的大小传递给此类的构造函数,并实例化该数组。

EnclosingClass还声明EnclosedClass,一个嵌套的非静态成员类,以及一个实例化EnclosedClass的方法,并返回此实例。

MemoryLeak的main()方法首先创建一个java.util.ArrayList来存储EnclosingClass.EnclosedClass对象。现在,观察内存泄漏是如何发生的。

将计数器初始化为0后,main()进入无限while循环,该循环重复实例化EnclosedClass并将其添加到数组列表中。然后打印(或递增)计数器。

每个存储的EnclosedClass对象都维护对其外部对象的引用,该对象引用100,000个32位整数(或400,000字节)的数组。在对内部对象进行垃圾收集之前,无法对外部对象进行垃圾收集。最终,该应用程序将耗尽内存。

javac MemoryLeak.java

java MemoryLeak

我们将观察到如下输出(当然在不同的机器上,最后的数字可能不一样):

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)

7b2fd73c922beae881ff56702e3bd406.png

往期精选

CHOICENESS

83a60f3ea5cd31cbc3d1ea719da9fae3.png

7e0881dac320e1b5fb1a5e761781a9d6.png

59e2645fea19540c27bc11721ca12c83.png

95c992c21788eff221b13fd0256e036f.png是兄弟,就来“kan”70329868d59d4b533e31a37e94596fb6.gif

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/489750.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

git stash简介

原文&#xff1a;http://gitbook.liuhui998.com/4_5.html 一、基本操作当你正在做一项复杂的工作时, 发现了一个和当前工作不相关但是又很讨厌的bug. 你这时想先修复bug再做手头的工作, 那么就可以用 git stash 来保存当前的工作状态, 等你修复完bug后,执行反储藏(unstash)操作…

马斯克:“星链”卫星已能提供服务

来源&#xff1a;一财网美国太空探索技术公司首席执行官埃隆马斯克22日称&#xff0c;该公司发射的“星链”卫星已能提供天基互联网服务。马斯克当天在社交媒体推特上发布的一条推文中说&#xff0c;“正在通过‘星链’卫星发送这条推文”。2分钟后&#xff0c;他发推文表示&am…

python dict遍历_python 字典(dict)遍历的四种方法性能测试报告

python中&#xff0c;遍历dict的方法有四种。但这四种遍历的性能如何呢&#xff1f;我做了如下的测试l [(x,x) for x in xrange(10000)]d dict(l)from time import clockt0clock()for i in d:t i d[i]t1clock()for k,v in d.items():t k vt2clock()for k,v in d.iteritem…

sqlplus连mysql库_sqlplus连接数据库

sqlplus连接到远程数据库我一直以为sqlplus是服务器端的软件&#xff0c;今天我才知道sqlplus是客户端软件&#xff0c;用sqlplus也能连接到远程数据库。windows下具体连接方法如下&#xff1a;如果已经配置过tnsname方法一.在运行或者命令窗口里面先输入sqlplus/n...文章张振磊…

OpenGL ES入门

OpenGL ES渲染管线概述 渲染管线一般是由显示芯片GPU内部处理图形信号的并行处理单元组成&#xff0c;这些并行处理单元之间是独立的&#xff0c;从另一个角度看&#xff0c;渲染管线实际上也是一系列绘制过程&#xff0c;这一系列过程的输入是待绘制物体的相关描述信息&#x…

【前沿】MIT搞了个进取型机器人!能研究学习对象操纵的基础

来源&#xff1a;中国机器人网 前言&#xff1a;MIT的研究让数据有了机器人的方向麻省理工学院的研究人员已经汇编了一个数据集&#xff0c;该数据集捕获了物理上推动数百个不同对象的机器人系统的详细行为。研究人员可以使用数据集&#xff08;同类中规模最大&#xff0c;种类…

java进度条_自学java你需要知道的,适合编程小白

1. java学习网站之前在很多学习网站上学习过Java&#xff0c;踩过很多坑&#xff0c;今天给大家推荐一个比较好用的Java学习网站&#xff0c;希望大家能少踩坑Java教程 | 项目实践一站式java学习这个网站的针对性强&#xff0c;如果你是想学习Java&#xff0c;在这个网站学习就…

软考考前冲刺第一章计算机硬件基础知识

1.原码表示法和补码表示法是计算机中用于表示数据的两种编码方法&#xff0c;在计算机系统中常采用补码来表示和运算数据&#xff0c;原因是采用补码可以简化计算机运算部件的设计。 在计算机中&#xff0c;各类运算都可以采用补码进行&#xff0c;特别是对于有符号数的运算。在…

既然使用神经网络也可以解决分类问题,那SVM、决策树这些算法还有什么意义呢?...

来源&#xff1a;Jerry的算法和NLPJerry的算法和NLP先说下结论&#xff1a;没有一个模型是万能的&#xff0c;需要根据数据选择适合的模型。在机器学习中&#xff0c;数据大概可以分成四大类&#xff1a;图像 (Image)&#xff0c;序列(Sequence)&#xff0c;图(Graph) 和表格(T…

python解包的概念_Python学习第176课——tar解包和压缩

上节我们学习了tar命令打包和查看tar文件中的内容&#xff0c;这节我们继续熟悉tar解包以及其他操作。上节我们把桌面上的linux文件夹里面的东西打了一个包&#xff0c;打包后的文件也在桌面上&#xff0c;叫tar_linux.tar。●tar解包现在我们把tar_linux.tar这个打包文件进行解…

chardet java_java实现文件编码监测

java实现文件编码监测最近在做一个文档的翻译项目&#xff0c;可文档的编码不知道&#xff0c;听头疼的。尝试了很多方法最后发现JCharDet这个工具可以轻松解决这个问题。于是作此笔记希望日后提醒自己以及帮助又需要的人。package com.uujava.mbfy.test;import java.io.Buffer…

使用python处理子域名爆破工具subdomainsbrute结果txt

近期学习了一段时间python&#xff0c;结合自己的安全从业经验&#xff0c;越来越感觉到安全测试是一个体力活。如果没有良好的coding能力去自动化的话&#xff0c;无疑会把安全测试效率变得很低。 作为安全测试而言&#xff0c;第一步往往要通过爆破目标站的一级域名开始。作为…

美陆军将在2020年军演中测试人工智能新应用

▲美陆军利用人工智能技术探测隐藏的目标&#xff0c;例如这辆伪装的M109A6自行榴弹炮来源&#xff1a; 美国《防务快讯》/图片来自互联网 编者按美陆军人工智能工作组负责人表示&#xff0c;陆军已开发出可检测“侦察照片”中隐藏目标的人工智能技术&#xff0c;并将在明年举行…

python 同时发多个请求_PythonWebServer如何同时处理多个请求

源于知乎上一个问题&#xff1a;https://www.zhihu.com/question/56472691/answer/293292349对于初学Web开发&#xff0c;理解一个web server如何能同事处理多个请求很重要。当然更重要的是&#xff0c;理解你通过浏览器发送的请求web server是怎么处理的&#xff0c;然后怎么返…

java关于hashmap编程题_LeetCode算法题-Design HashMap(Java实现)

这是悦乐书的第299次更新&#xff0c;第318篇原创01 看题和准备今天介绍的是LeetCode算法题中Easy级别的第167题(顺位题号是706)。在不使用任何内置哈希表库的情况下设计HashMap。具体而言&#xff0c;你的设计应包括以下功能&#xff1a;put(key&#xff0c;value)&#xff1a…

Nature:1000种植物的测序揭示10亿年来的进化

来源&#xff1a;生物通千种植物转录组计划&#xff08;1,000 Plants Project&#xff0c;1KP&#xff09;是由加拿大科学家在2008年11月发起的&#xff0c;召集了将近200名植物学家对1,100多种植物的基因进行测序和分析。如今&#xff0c;这个项目的研究成果发表在《Nature》杂…

CodeForces 688B - Lovely Palindromes(思路)

题意&#xff1a;输出第n&#xff08;1 < n < 10^100000&#xff09;大的偶数长度的回文数。&#xff08;最小的为11&#xff09; 因为长度是偶数&#xff0c;所以前后两半之间是相互对称的&#xff0c;又因为一个数字的大小主要取决于较高位数的大小&#xff0c;所以数字…

python 查询sqlserver 视图_SQL Server 2017 数据库教与学(教学大纲,含Python+SQL Server案例)...

原标题&#xff1a;SQL Server 2017 数据库教与学(教学大纲&#xff0c;含PythonSQL Server案例)本书提供PythonSQL Server案例SQL Server教学大纲一、课程的性质和教学目的课程性质&#xff1a;数据库技术是各类信息系统、管理系统的基础。SQL Server数据库是微软公司的一款数…

java 通过反射得到命名空间_利用反射得到一个命名空间下的所有类,并调用?...

当年话下Assembly.LoadFrom("assemblyName").GetTypes();Assembly.Load("assemblyName").GetTypes();遍历&#xff0c; 再通过Type.GetInterface(""),如果结果不为null&#xff0c;那就说明找到了再Activator.CreateInstance(“”)即可还是写段代…

量子霸权之争

来源&#xff1a; 原理这一个月以来&#xff0c;量子计算机领域吸引了许多人的关注&#xff0c;因为关于谷歌已经实现了人们期待已久的里程碑——“量子霸权”&#xff08;也被称为”量子优越性“&#xff09;的消息不胫而走。“量子霸权”是加州理工学院的理论物理学家John Pr…