首页 > 系统相关 >Java内存泄漏

Java内存泄漏

时间:2025-01-16 14:59:35浏览次数:3  
标签:泄漏 Java 对象 回收 内存 objectList 引用

内存管理基础:

Java 使用 堆内存(Heap)来存储对象,所有通过 new 关键字创建的对象都会分配到堆内存中。垃圾回收(GC)是自动进行的,它负责清理那些不再被引用的对象。Java的垃圾回收机制通过标记清除(Mark-Sweep)算法来决定哪些对象可以被回收。

内存泄漏的基本概念:

内存泄漏指的是程序中有些对象即使不再需要,仍然保持有有效引用。由于这些对象仍然可达,垃圾回收器无法回收它们,从而导致内存被持续占用,最终可能会导致 OutOfMemoryError

内存泄漏发生的过程:

内存泄漏的根本原因是对象的引用未被及时清除。为了形象理解,我们可以使用一个图示来说明内存泄漏发生的过程。

1. 正常的垃圾回收过程:

在一个正常的 Java 程序中,创建的对象可能在使用完后不再需要,但只要没有被引用,垃圾回收器会及时回收这些对象,释放内存。

图示:

Heap 内存
+-------------------+  <-- 堆内存
|  Object 1         |  <-- 对象 1 被创建
|  Object 2         |  <-- 对象 2 被创建
|                   |
+-------------------+

对象 1 和对象 2 都被引用
JVM 垃圾回收器运行时发现对象 1 和对象 2 都是可达的,垃圾回收器不会回收它们

内存回收后:

Heap 内存
+-------------------+  <-- 堆内存
|  Object 2         |  <-- 只有对象 2 被引用
+-------------------+

对象 1 不再被引用,可以被垃圾回收器回收,释放内存
2. 内存泄漏的场景:

内存泄漏的发生通常是在某些情况下,对象没有及时释放引用,从而导致它们不能被垃圾回收器回收。

图示:

Heap 内存
+-------------------+  <-- 堆内存
|  Object 1         |  <-- 对象 1 被创建并分配内存
|  Object 2         |  <-- 对象 2 被创建并分配内存
|                   |
+-------------------+

此时对象 1 和对象 2 都有引用指向它们

假设在程序的某个地方,Object 1 被保存在了一个集合中,但程序不再需要它。即便 Object 1 已经不再被使用,objectList 仍然持有对 Object 1 的引用,所以 垃圾回收器不能回收它

Heap 内存
+-------------------+  <-- 堆内存
|  Object 1         |  <-- 对象 1 被保留
|  Object 2         |  <-- 对象 2 被创建
|                   |
+-------------------+

对象 1 和对象 2 都被引用,但对象 1 的引用是多余的

如果不断地向 objectList 中添加对象,且没有清理机制(如 clear() 或移除引用),堆内存会不断增长,最终可能会导致 OutOfMemoryError

具体的内存泄漏示例:

import java.util.ArrayList;
import java.util.List;

public class MemoryLeakExample {
    private List<Object> objectList = new ArrayList<>();

    public void createMemoryLeak() {
        while (true) {
            objectList.add(new Object());  // 持续创建新的对象并加入到 objectList
        }
    }

    public static void main(String[] args) {
        MemoryLeakExample example = new MemoryLeakExample();
        example.createMemoryLeak();  // 启动内存泄漏方法
    }
}

在这个例子中,objectList 会无限增长,每次循环都会创建一个新的 Object 对象并加入到列表中。由于 objectList 持有对这些对象的引用,垃圾回收器无法回收它们,从而导致内存泄漏。

如何发生内存泄漏:
  • objectList 中的对象不断增加,直到程序运行内存用尽。
  • 每个新创建的对象都被保存在 objectList 中,且引用没有被清除。
内存状态变化:
  1. 对象创建阶段:
Heap 内存
+--------------------+
|  Object 1          |  <-- Object 1 被创建
|  Object 2          |  <-- Object 2 被创建
|                    |
+--------------------+

objectList 持有对 Object 1 和 Object 2 的引用
  1. 持续创建阶段:
Heap 内存
+--------------------+
|  Object 1          |  <-- Object 1 持续存在
|  Object 2          |  <-- Object 2 持续存在
|  Object 3          |  <-- Object 3 被创建
|  Object 4          |  <-- Object 4 被创建
|                    |
+--------------------+

每次循环都会创建新的对象并加入 objectList 中
  1. 内存泄漏阶段:
Heap 内存
+--------------------+
|  Object 1          |  <-- Object 1 被保留在内存中
|  Object 2          |  <-- Object 2 被保留在内存中
|  Object 3          |  <-- Object 3 被保留在内存中
|  Object 4          |  <-- Object 4 被保留在内存中
|                    |
+--------------------+

这些对象永远无法被垃圾回收,因为 objectList 持有对它们的引用

内存泄漏的影响:

  1. 内存消耗增加:
    • 每次创建的对象会持续占用堆内存,导致内存消耗不断增加。
  1. 最终导致 OutOfMemoryError
    • 随着时间的推移,内存占用越来越大,最终 JVM 无法分配更多的内存,抛出 OutOfMemoryError 异常。

如何避免内存泄漏:

  1. 显式清理引用
    • 当对象不再需要时,应该及时清理引用。例如,可以使用 objectList.clear()objectList = null
  1. 使用 WeakReferenceSoftReference
    • 如果你想缓存对象,但又希望垃圾回收器能够在内存紧张时回收它们,可以使用弱引用(WeakReference)和软引用(SoftReference)。
  1. 定期监控内存
    • 使用 Java 的内存分析工具(如 VisualVM、JProfiler、MAT)来定期检查程序的内存使用情况,发现可能的内存泄漏。

内存泄漏的根本原因:

  • 对象无法被回收:只要某个对象仍然被任何地方持有引用,垃圾回收器就无法回收这个对象。即使这些对象已经不再有用,仍然会占用内存。
  • 持久引用:在上述代码中,objectList 持有对所有创建对象的引用,导致即使 Object 对象不再被需要,它们仍然无法被垃圾回收器回收。

现实中的内存泄漏场景:

  1. 数据库连接池中的连接未关闭:如果你使用了数据库连接池,并且忘记在使用完数据库连接后释放连接,连接就会一直被持有,而数据库连接本身也无法被回收,导致内存泄漏。
  2. 监听器和回调未移除:比如在事件驱动的系统中,如果某个对象注册了事件监听器或回调函数,并且在事件完成后没有及时注销这个监听器,监听器就会保持对对象的引用,导致该对象无法被垃圾回收。
  3. 缓存机制未清理:如果你在程序中使用了缓存,并且缓存中的数据不断增加而没有清理机制,缓存中的对象就会一直持有引用,最终导致内存泄漏。

如何避免内存泄漏:

  1. 显式清理引用:在不再需要使用某个对象时,要显式地将其引用设为 null,或者从集合中移除它,这样垃圾回收器就能识别到这些对象不再被引用,最终可以回收它们。
  2. 适时关闭资源:例如数据库连接、文件流、网络连接等在使用完后一定要及时关闭,以避免这些资源持续占用内存。
  3. 使用 WeakReferenceSoftReference:这类引用会在对象没有强引用时允许对象被垃圾回收。例如,你可以使用 WeakHashMap 来存储缓存,缓存中的对象会在没有强引用时被回收。
  4. 使用工具检测:可以使用内存分析工具(如 VisualVM、JProfiler、Eclipse MAT 等)来检查程序中的内存泄漏。通过分析堆的快照,查看哪些对象无法被垃圾回收。

结论:

内存泄漏是由于对象被不必要的引用保持,导致垃圾回收器无法回收这些对象,从而占用内存。在 Java 中,理解垃圾回收机制,并遵循良好的资源管理习惯,可以有效地避免内存泄漏问题。

标签:泄漏,Java,对象,回收,内存,objectList,引用
From: https://blog.csdn.net/qq_39842184/article/details/145183617

相关文章

  • JavaScript防抖与节流的运用
    防抖(Debounce)概念:防抖是指在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。防抖的主要目的是将多次连续触发的事件合并为一次执行,适用于例如输入框输入搜索内容时,避免频繁发送请求,只在用户停止输入一段时间后才发送请求。实现思路:创建一个定时器。......
  • 大数据学习记录,Java基础(4)
    多态多态的形式和体现1.对象的多态性对象的多态性:父类的引用指向子类的对象格式:(父类类型:指子类继承的父类类型,或者实现的接口类型)父类类型变量名=子类对象;例:Personp=newStudent();Objecto=newPerson();//Object类型的变量o,指向Person类型的对象o=newStuden......
  • 大数据学习记录,Java基础(3)
    面向对象面向对象的特征:封装随着系统越来越复杂,类会越来越多,那么类之间的访问边界必须把握好,面向对象的开发原则要遵循“高内聚、低耦合”,而“高内聚,低耦合”的体现之一:高内聚:类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用,尽量方便外部调用......
  • 【Java】若依(ruoyi-cloud)——14.Sentinel支持(服务熔断与降级)
    若依微服务版(ruoyi-Cloud)如何实现熔断和降级?知识前提:对Sentinel的使用有了解若依微服务版启动对nacos服务注册和使用有了解若依微服务版(ruoyi-cloud)中使用sentinel,进行服务熔断与降级。环境要求和前提JDK>=1.8(推荐1.8版本)Mysql>=5.7.0(推荐5.7版本)Redis>=......
  • IO流(Java)
    一、IO体系的核心概念1.什么是IOJava应用程序与外部环境(如文件系统、网络等)之间的数据交换。2.流(1)什么是数据传输的抽象体现3.类型(1)字节流以字节为单位处理数据,主要处理原始二进制数据,比如说图像、声音。主要类包含InputStream和OutputStream。(2)字符流以字符......
  • 东软云医院HIS系统-药房管理系统【Swing窗口+MySQL】(Java课设)
         客官进来看一眼呗,有惊喜!【帮你解决烦恼】:Java课设和计Java毕设太难不会做怎么办?系统类型Swing窗口类型+Mysql数据库存储数据使用范围适合作为Java课设!!!部署环境jdk1.8+Mysql8.0+Idea或eclipse+jdbc运行效果本系统源码地址:东软云医院HIS系统-药房管理系统【Sw......
  • JAVA-Exploit编写(5)--http-request库使用
    目录1.http-request简介2.依赖导入3.GET请求方式3.1test.php3.2基本使用代码实现 3.2请求时请求参数URL编码实现 3.3携带多参数请求3.Post请求方式3.1基本使用3.2携带单个参数请求 3.3携带多个参数请求4.设置代理请求 4.1方式一4.2方式二1.ht......
  • [2834]基于JAVA的著作权登记智慧管理系统的设计与实现
    毕业设计(论文)开题报告表姓名学院专业班级题目基于JAVA的著作权登记智慧管理系统的设计与实现指导老师(一)选题的背景和意义随着科技的发展,数字化技术在各个领域的应用越来越广泛。特别是在知识产权领域,著作权登记、管理、保护等方面的工作也面临着数字化转型的挑战。然而......
  • [2823]基于JAVA的药店销售智慧管理系统的设计与实现
    毕业设计(论文)开题报告表姓名学院专业班级题目基于JAVA的药店销售智慧管理系统的设计与实现指导老师(一)选题的背景和意义在当今社会,药店作为医疗保健服务的重要组成部分,其日常运营管理和药品销售管理对于保障公众健康具有重要意义。随着科技的不断发展和信息化水平的提高......
  • 【附源码】JAVA大学生竞赛管理系统源码+SpringBoot+VUE+前后端分离
    学弟,学妹好,我是爱学习的学姐,今天带来一款优秀的项目:大学生竞赛管理系统 。本文介绍了系统功能与部署安装步骤,如果您有任何问题,也请联系学姐,偶现在是经验丰富的程序员!一.系统演示系统测试截图   系统视频演示 https://githubs.xyz/show/343.mp4 二.系统概述 ......