Java内存泄漏!为什么会泄漏?如何泄漏?怎么定位?

Java 中发生内存泄漏 5 个场景以及解决方法 前言 说到垃圾回收(Garbage Collection,GC),很多人就会自然而然地把它和 Java 联系起来。在 Java 中,程序员不需要去关心内存动态分配和垃圾回收的问题,这一切都交给了JVM 来处理。顾名思义,垃圾回收就是释放垃圾占用的空间,但垃圾回收器并不是万能的,它能够处理大部分场景下的内存清理、内存泄露以及内存优化。但它也并不是万能的,不然我们在项目实践过程中也不会出现那么多的内存泄漏的问题,很多的内存泄漏都是因为开发人员操作不当导致的。 本篇文章我们就来聊聊内存泄露的原因是什么,以及如何在 阅读详情

JVM应该可以算Java中最为核心的部分了,其中开箱即用的内存管理又是JVM中的核心组成部分。我们都知道JVM的内存管理具有垃圾回收功能(Java Garbage Collector),编码时只需要new而无需主动的释放(类似于C++中的delete操作),所以Java中比较少出现内存泄露的情况。比较少出现,并不一定就不会出现,那么Java程序在什么时候会出现内存泄露呢?出现内存泄露该如何排查呢?

Java程序为什么会有内存泄露

什么是内存泄露呢?内存泄露可以定义为:当一个对象已经不再被应用程序使用以后,它所占用的内存没有得到及时的释放,导致内存使用量随着时间的推移不断的增加,最终导致应用程序崩溃的现象(Java中会在new新对象的时候抛出OutOfMemoryError)。
对于Java程序而言,当一个Object已经不会被程序所使用,但是它还被其它对象所引用,从而导致GC的时候无法被回收,从而导致内存泄露。
下图比较直观的展示了Java内存泄露发生的情形:
在这里插入图片描述

从上图我们可以把对象分为两大类:被引用的和不被引用的。垃圾回收的时候释放那些不被引用的对象,被引用的对象则不会被释放,即便是这些对象后续一直都没有被用过。
定位Java内存泄露是比较麻烦的事情,需要使用到JVM提供的多种工具来进行内存分析,并且往往还需要结合代码进行分析。

Java堆内存泄露

首先我们来看看Java程序中最为常见的堆内存泄露。
如果想要直观的模拟出堆内存泄露,我们需要设置一个较小的堆(内存泄露是独立存在的,和对内存大小无关,不过较小的堆内存大小可以更直观的观察到内存泄露)。
我们可以通过如下两个启动参数设置对内存大小:

-Xms<size>
-Xmx<size>

通过静态变量来演示内存泄露

首先我们通过如下的代码来看看看看正常Java代码运行时的内存变化情况:

public class TestApplication {
  private static void test(){
      List<Integer> list = new ArrayList<Integer>();
      for(int i = 0; i < 500000; i++){
          list.add(i);
      }
  }

  public static void main(String[] args) throws InterruptedException {
      int k = 1;
      while(true){
          test();
          if(k == 10) {
              System.gc();
              k = 1;
          }
          k ++;
          Thread.sleep(1000);
      }
  }
}

启动参数:-Xms20m -Xmx20m
运行是的内存变化图:
在这里插入图片描述
在我们的代码中我们每秒调用一次test方法,这个方法中会往list中添加数据,但是在方法返回之后就处于无引用状态了(并不一定会立马进行GC),我们每10秒钟调用一次System.gc()(full GC)。从内存监控图上也能够直观的观察到堆内存的使用变化曲线。接下来我们对上面的代码做一下修改。

静态变量保存了过多不在使用的对象引用导致的内存泄露是我们编码过程中最为常见的一种内存泄露方式。下面的代码就演示了这个情况:

public class TestApplication {

    private static List<Integer> list = new ArrayList<Integer>();
    private static void test(){
        for(int i = 0; i < 10000; i++){
            list.add(i);
        }
    }

    public static void main(String[] args) throws InterruptedException {
        int k = 1;
        while(true){
            test();
            if(k == 10) {
                System.gc();
                k = 1;
            }
            k ++;
            Thread.sleep(1000);
        }
    }
}

为了更加直观的观察内存变化,我稍微调整了一下每次插入的数据个数,启动参数仍旧和上面一下。这个时候我们能够得到如下图所示的内存变化曲线:
在这里插入图片描述
从曲线中我们可以发现,堆内存使用量一直在增加,并没有和前一个示例一样在full GC后释放没有使用的堆内存,每次调用test方法后添加到list中的对象都会被list所引用,所以GC是不会收集并释放内存的。

如何定位和解决内存泄漏

Java的内存泄漏定位一般是比较困难的,需要使用到很多的实践经验和调试技巧。下面是一些比较通用的方法:

  • 可以添加-verbose:gc启动参数来输出Java程序的GC日志。通过分析这些日志,可以知道每次GC后内存是否有增加,如果在缓慢的增加的那,那就有可能是内存泄漏了(当然也需要结合当前的负载)。如果无法添加这个启动参数,也可以使用jstat来查看实时的gc日志。如果条件运行的化可以考虑使用jvisualvm图形化的观察,不过要是线上的化一般没这个条件。
  • 当通过dump出堆内存,然后使用jvisualvm查看分析,一般能够分析出内存中大量存在的对象以及它的类型等。我们可以通过添加-XX:+HeapDumpOnOutOfMemoryError启动参数来自动保存发生OOM时的内存dump。
  • 当确定出大对象,或者大量存在的实例类型以后,我们就需要去review代码,从实际的代码入手来定位到真正发生泄漏的代码。

在这里插入图片描述

扫码关注
头条号:  微信公众号:

Android内存泄漏定位与解决 百度MTC是业界领先的移动应用测试服务平台,为广大开发者在移动应用测试中面临的成本、技术和效率问题提供解决方案。同时分享行业领先的百度技术,作者来自百度员工和业界领袖等。 问题现象 反复点击被测试的Android App的toolbar界面,然后返回再点击。在此重复过程中,发现到一定次数时,页面打开速度变慢,有时达到5s,十分影响用户体验。该问题涉及app所采用的webview框架 阅读详情

相关推荐

Android Studio 分析内存泄漏

内存分析入门

一叶知秋的专栏 7057

注意Java代码的内存泄漏

转自:http://www.189works.com/article-72943-1.html 对于有语言编译基础的同志,要注意了,如果你是刚学java的.那么下面你必须要看.当然本人也是一样,也会出现下面某些错误。所以本人总结了一些。 当然都是个人看法.不代表就是对的.也许有些是错的.同时也希望熟悉JAVA的高高手指出.或者有更好的看法或建议.都可以和我沟通.大家一齐来学习。 同时这也是对

努力成就自我 850

手把手教你用Matlab实现Copula函数:从理论到代码的完整指南

本文提供了一份在MATLAB中实现Copula函数的完整实战指南。从理解Sklar定理和常见Copula家族(如高斯、t、Clayton)的核心概念出发,详细讲解了数据预处理、边缘分布拟合、概率积分变换等关键步骤。通过具体代码示例,手把手演示了Copula模型的拟合、评估、蒙特卡洛模拟,并进阶应用于金融风险度量(如VaR计算)和条件分布分析,帮助读者掌握这一强大的多变量依赖建模工具。

y9z0a1b的博客 953

简单快速定位内存泄漏

两个方法实现快速定位内存泄漏代码!

weixin_45634782的博客 2095

电赛经验分享——赛前准备

⏩ 大家好哇!我是小光,想要成为系统架构师的嵌入式爱好者。⏩在之前的电赛中取得了省一的成绩,本文对电赛比赛前需要准备什么做一个经验分享。加入小光嵌入式交流群(qq群号:737327353)免费获取博主所有资料哦!

qq_52608074的博客 7779

AI数字人短视频数字人口播数字人分身建模流程全解析

在人工智能与计算机图形学蓬勃发展的当下,数字人建模作为打造虚拟数字人的核心环节,其流程复杂且精妙,融合了多种前沿技术与创意构思,为栩栩如生的数字人形象奠定基石。​。

2403_87518095的博客 1447

内存泄漏了,该如何定位

文章目录基本概念内存的分配与回收案例小结 基本概念 普通进程能看到的是内核提供的虚拟内存,虚拟内存通过页表,将虚拟内存映射为物理内存 进程通过malloc() 申请虚拟内存后,并不会立即为其分配物理内存,首次访问时,才通过缺页异常陷入中断中分配内存 为了协调CPU与磁盘间的性能差异,Linux还会使用Cache和Buffer,分别把文件和磁盘读写的数据缓存到内存中 对应用程序来说,动态内存的分配和回收,是既核心又复杂的一个逻辑功能模块,管理内存的过程中,也容易发生各种各样的事故 没正确回收分配的内存,导

凯凯王的技术生涯 1486

时频分析之STFT:短时傅里叶变换的原理与代码实现(非调用Matlab API)

STFT function [STFT, f, t] = mystft(x, win, hop, nfft, fs) % function: [STFT, f, t] = stft(x, win, hop, nfft, fs) % % Input: % x - signal in the time domain % win - analysis window function % hop - hop size % nfft - numb

frostime的博客 13万+

Java 内存泄露问题详解

内存泄露指的是程序运行时未能正确释放不再使用的内存资源,导致这些内存资源无法被垃圾回收器回收和重新利用。内存泄露会导致程序占用越来越多的内存,最终可能导致内存耗尽和程序崩溃。在Java中,当一个对象不再被引用时,Java的垃圾回收器会自动将其标记为可回收,并在合适的时机释放其占用的内存。然而,如果存在内存泄露的情况,这些不再使用的对象仍然被保留在内存中,无法被垃圾回收器回收。内存泄露可能是由于编程错误、资源管理不当或设计问题引起的。

swadian2008的博客 4938

(C#脚本)Unity中角色移动的几种实现方法,以及心得。(适合新手入门)

PS:首先我们要知道,在C#中Transform组件是可以直接调用的,而其他的(例如:Rigidbody,Animator)都需要通过 GetConpoment<组件的名称>(); 来获取进行实例化。 例子:调用Rigidbody2D private Rigidbody2D rb2D;//声明变量实例化 void Start() { rb2d = GetComponent<Rigidbody2D>();//获取 } 1.对Unity脚本写入有一定的思维了解...

qq_48860282的博客 1万+

11n、11ac、11ax和11be MCS表(全网最全)

1、无线协商速率介绍及计算 2、附11n、11ac、11ax 完整MCS速率表

weixin_41500064的博客 2万+

会不会导致内存泄漏_Java内存泄漏!为什么会泄漏?如何泄漏?怎么定位?

JVM应该可以算Java中最为核心的部分了,其中开箱即用的内存管理又是JVM中的核心组成部分。我们都知道JVM的内存管理具有垃圾回收功能(Java Garbage Collector),编码时只需要new而无需主动的释放(类似于C++中的delete操作),所以Java中比较少出现内存泄露的情况。比较少出现,并不一定就不会出现,那么Java程序在什么时候会出现内存泄露呢?出现内存泄露该如何排查呢?...

weixin_39942451的博客 100

【Bug已解决】codex file edit fails / Write operation denied — CodeX CLI 文件编辑失败解决方案

CodeX CLI 编辑文件时报写入被拒绝,本质是沙箱限制或权限不足。文中给出配置允许目录、修复权限、Git stash 管理冲突等完整方案。

一键难忘的博客 4300

java 内存 泄漏_Java内存泄漏!为什么会泄漏?如何泄漏?怎么定位?

JVM应该可以算Java中最为核心的部分了,其中开箱即用的内存管理又是JVM中的核心组成部分。我们都知道JVM的内存管理具有垃圾回收功能(JavaGarbageCollector),编码时只需要new而无需主动的释放(类似于C++中的delete操作),所以Java中比较少出现内存泄露的情况。比较少出现,并不一定就不会出现,那么Java程序在什么时候会出现内存泄露呢?出现内存泄露该如何排查呢?Ja...

weixin_39914732的博客 291

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

java list 占用内存不释放_Java内存泄漏!为什么会泄漏?如何泄漏?怎么定位?...

JVM应该可以算Java中最为核心的部分了,其中开箱即用的内存管理又是JVM中的核心组成部分。我们都知道JVM的内存管理具有垃圾回收功能(Java Garbage Collector),编码时只需要new而无需主动的释放(类似于C++中的delete操作),所以Java中比较少出现内存泄露的情况。比较少出现,并不一定就不会出现,那么Java程序在什么时候会出现内存泄露呢?出现内存泄露该如何排查呢?...

weixin_39832829的博客 1306

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

【JVM】如何定位、解决内存泄漏和溢出

如何定位JVM内存泄漏和内存溢出问题?实战干货!一文详聊!快速上手!

BugMan的博客 6776

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

在java开发项目中内存泄漏的五大原因,遇到内存泄漏我们该怎么做,怎么避免内存泄漏

​内存泄漏(Memory Leak)是指程序在申请内存后,无法释放已不再使用的内存的情况。通俗来说,就是程序中某些对象已经不再被使用,但由于某些原因仍然被其他对象引用,导致垃圾回收器(Garbage Collector)无法将它们从内存中回收,最终造成内存资源浪费的现象。内存泄漏的本质是对象的生命周期管理不当。在 Java 等具备自动垃圾回收机制的语言中,对象的创建和销毁由系统自动管理,但如果代码中存在不合理的引用关系,会导致对象无法被及时回收,从而占用内存空间。

Chenchen0905_的博客 3260

内存泄漏的追踪及分析定位

内存泄漏指的是程序中不再需要的内存未能被释放,导致内存使用量不断增加,最终可能耗尽所有可用内存。内存泄漏通常发生在手动内存管理的语言中,如 C 和 C++,但在自动内存管理语言如 Java 和 Python 中也可能发生。内存泄漏是一个常见且严重的问题,通过正确的工具和方法可以有效地追踪和定位内存泄漏。在实际开发中,良好的编码习惯和定期的内存监控是预防内存泄漏的重要措施。

技术萌新缓缓升级ing 2856

如何在 Java 中进行内存泄漏分析

确认是否发生内存泄漏:通过jstat观察 GC 状态,确认是否存在问题。生成和分析 Heap Dump:使用jmap获取 Heap Dump 文件,并利用 MAT 或 VisualVM 工具分析。定位问题和修复代码:找到内存泄漏的根源后,通过优化对象管理和生命周期修复问题。

Mylqs的博客 2471

通过长期测试定位java服务内存泄漏问题

长期测试

qq_40664458的博客 4万+

Java内存泄漏的排查

1.内存溢出 一种通俗的说法。 1、内存溢出:你申请了10个字节的空间,但是你在这个空间写入11或以上字节的数据,出现溢出。 2、内存泄漏:你用new申请了一块内存,后来很长时间都不再使用了(按理应该释放),但是因为一直被某个或某些实例所持有导致 GC 不能回收,也就是该被释放的对象没有释放。 下面具体介绍。 1.1 内存溢出 java.lang.OutOfMemoryError,是指程序在申请内存时,没有足够的内存空间供其使用,出现OutOfMemoryError。 产生该错误的原因主要包括:JVM内存过

青鸟飞鱼 1万+

Java 应用内存泄漏的定位过程

最近,笔者负责测试的某个算法模块机器出现大量报警,报警表现为机器CPU持续高占用。该算法模块是一个优化算法,本身就是CPU密集型应用,一开始怀疑可能是算法在正常运算,但很快这种猜测就被推翻:同算法同学确认后,该算法应用只使用了一个核心,而报警时,一个算法进程占用了服务机器的全部8个核心,这显然不是正常计算造成的。首先按照CPU问题的定位思路进行定位,对 Java 调用堆栈进行分析:使用 查看 CPU 占用高的进程: ,从 top 命令的结果看,19272 号进程 CPU 占用率最高,基本确定问题是该进程引

2501_92608043的博客 781

JAVA内存泄漏分析定位

1、为什么会发生内存泄漏 Java如何检测内在泄漏呢?我们需要一些工具进行检测,并发现内存泄漏问题,不然很容易发生down机问题。 编写java程序最为方便的地方就是我们不需要管理内存的分配和释放,一切由jvm来进行处理,当java对象不再被应用时,等到堆内存不够用时,jvm会进行垃圾回收,清除这些对象占用的堆内存空间,如果对象一直被应用,jvm无法对其进行回收,创建新的对象时,无法从Heap中获取足够的内存分配给对象,这时候就会导致内存溢出。而出现内存泄露的地方,一般是不断的往容器中存放对象,而容器没有相

小小白兔兔 1269

JAVA内存泄漏与常见问题定位

JAVA后端开发知识总结(持续更新…) JAVA内存泄漏 文章目录JAVA内存泄漏一、内存溢出二、内存泄漏2.1 定位与解决 一、内存溢出   OutOfMemoryError:JVM内存过小;程序不严密,产生了过多的垃圾。其解决方法在于: 增加JVM的内存大小,特别是对启动参数内存值的设定。 从根本上解决Java内存溢出的唯一方法就是修改程序,及时地释放没用的对象,释放内存空间,避免死循环,防止一次载入太多的数据。 二、内存泄漏   内存泄露,是指程序在申请内存并且用完这块内存后(对象不再需要.

weixin_43415481的博客 2123

java内存泄漏分析

  java.lang.OutOfMemoryError是工作中常见的异常,今天介绍下如何分析java内存泄漏。   java内存分析工具很多,JDK安装目录下自带就有很多优秀的分析工具。分析堆栈时我比较推荐使用MAT,方便,快速。 安装MAT 打开eclipse ---&gt;help---&gt;eclipse marketplace(我在公司一般会下载高版本的eclipse,它带有一个插...

wflh323的专栏 7154
上一篇: 线程池异常信息统一处理,从线程异常信息丢失说起
下一篇: 聊聊几种基本限流算法
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值