iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >如何解决JAVA内存泄漏问题
  • 504
分享到

如何解决JAVA内存泄漏问题

2023-06-20 15:06:37 504人浏览 八月长安
摘要

本篇内容介绍了“如何解决JAVA内存泄漏问题”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!目录什么是内存泄漏内存泄漏的原因内存泄漏有哪些情况

本篇内容介绍了“如何解决JAVA内存泄漏问题”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

目录
  • 什么是内存泄漏

  • 内存泄漏的原因

  • 内存泄漏有哪些情况

    • 1 代码中没有及时释放,导致内存无法回收。

    • 2 资源未关闭造成的内存泄漏

    • 3 全局缓存持有的对象不使用的时候没有及时移除,导致一直在内存中无法移除

    • 4 静态集合

    • 5 堆外内存无法回收

    • 内存泄漏的解决办法

    • 内存问题排查

      • 第一步 首先确认逻辑问题

      • 分析GC是否正常执行

      • 第三步 确认下版本新增代码的改动,尽快从代码上找出问题。

      • 开启各种命令行和 导出 dump 各种工具分析

  • 总结

    1、什么是内存泄漏

    内存泄漏是指无用对象(不再使用的对象)持续占有内存或无用对象的内存得不到及时释放,从而造成内存空间的浪费称为内存泄漏。随着垃圾回收器活动的增加以及内存占用的不断增加,程序性能会逐渐表现出来下降,极端情况下,会引发OutOfMemoryError导致程序崩溃。

    2、内存泄漏的原因

    JVM 虚拟机是使用引用计数法和可达性分析来判断对象是否可回收,本质是判断一个对象是否还被引用,如果没有引用则回收。在开发的过程中,由于代码的实现不同就会出现很多种内存泄漏问题,让gc 系统误以为此对象还在引用中,无法回收,造成内存泄漏。

    3、内存泄漏有哪些情况

    3.1 代码中没有及时释放,导致内存无法回收。

    下面的代码,因为是双向链表,但是断开的不够彻底,prev节点依然引用这当前正在使用的节点,导致无法回收

    public class Listnode {    int val;    ListNode next;    ListNode prev;    ListNode() {    }    ListNode(int val) {        this.val = val;    }    public ListNode(int val, ListNode next, ListNode prev) {        this.val = val;        this.next = next;        this.prev = prev;    }    public static void main(String[] args) {        ListNode curr = new ListNode(1);        ListNode prev = new ListNode(2);        ListNode next = new ListNode(3);        curr.prev = prev;        curr.next = next;        curr.prev = null;    }}
    public static void main(String[] args) {        ListNode curr = new ListNode(1);        ListNode prev = new ListNode(2);        ListNode next = new ListNode(3);        curr.prev = prev;        curr.next = next;        curr.prev = null;    }}

    3.2 资源未关闭造成的内存泄漏

    各种连接,如数据库连接、网络连接和io连接等,文件读写等,可以使用 try-with-resources 读取完文件,自动资源释放

    try (RandoMaccessFile raf = new RandomAccessFile(filePath, "r");) {        Image image = null;while((image = parseImage(raf)) != null){            imageList.add(image);        }        return imageList;} catch(Exception e){    log.error("parse file error, path: {},", path, e);    return null;}

    3.3 全局缓存持有的对象不使用的时候没有及时移除,导致一直在内存中无法移除

    3.4 静态集合类

    HashMap、LinkedList等等。如果这些容器为静态的,那么它们的生命周期与程序一致,则容器中的对象在程序结束之前将不能被释放,从而造成内存泄漏。生命周期长的对象持有短生命周期对象的引用,尽管短生命周期的对象不再使用,但是因为长生命周期对象持有它的引用而导致不能被回收。

    3.5 堆外内存无法回收

    堆外内存不受gc的管理,可能因为第三方的bug出现内存泄漏

    4、内存泄漏的解决办法

    尽量减少使用静态变量,或者使用完及时 赋值为 null。

    明确内存对象的有效作用域,尽量缩小对象的作用域,能用局部变量处理的不用成员变量,因为局部变量弹栈会自动回收;

    减少长生命周期的对象持有短生命周期的引用;

    使用StringBuilder和StringBuffer进行字符串连接,Sting和StringBuilder以及StringBuffer等都可以代表字符串,其中String字符串代表的是不可变的字符串,后两者表示可变的字符串。如果使用多个String对象进行字符串连接运算,在运行时可能产生大量临时字符串,这些字符串会保存在内存中从而导致程序性能下降。

    对于不需要使用的对象手动设置null值,不管GC何时会开始清理,我们都应及时的将无用的对象标记为可被清理的对象;

    各种连接(数据库连接,网络连接,IO连接)操作,务必显示调用close关闭。

    5、内存问题排查

    没有任何一个程序员想要出现这种问题,但是出现了问题也要解决,内存泄漏的主要表象就是内存不足,内存告警之后如何判断是否有内存泄漏。

    第一步 首先确认逻辑问题

    查看内存中对象的数量和大小,判断是否在合理的范围,如果在合理的范围内,增大内存配置,调整内存比例就可以了。

    命令:

    jmap -heap pid

    如何解决JAVA内存泄漏问题

    第二步:分析gc是否正常执行

    命令:

    jstat -gcutil <pid> 1000

    如何解决JAVA内存泄漏问题

    S0 — Heap上的 Survivor space 0 区已使用空间的百分比    S1 — Heap上的 Survivor space 1 区已使用空间的百分比    E — Heap上的 Eden space 区已使用空间的百分比    O   — Heap上的 Old space 区已使用空间的百分比    P   — Perm space 区已使用空间的百分比YGC — 从应用程序启动到采样时发生 Young GC 的次数YGCT– 从应用程序启动到采样时 Young GC 所用的时间(单位秒)    FGC — 从应用程序启动到采样时发生 Full GC 的次数FGCT– 从应用程序启动到采样时 Full GC 所用的时间(单位秒)    GCT — 从应用程序启动到采样时用于垃圾回收的总时间(单位秒)LGCC - 进行GC的原因(低版本jdk可能没有这一列)

    从这里观察gc是否异常,也可以根据这个进行jvm内存分配调优,来提高性能降低gc对性能的损耗

    第三步 确认下版本新增代码的改动,尽快从代码上找出问题。
    第四步:开启各种命令行和 导出 dump 各种工具分析
    -XX:+HeapDumpOnOutOfMemoryError-XX:OnError-XX:+ShowMessageBoxOnError

    推荐使用jprofile 进行本地分析,可以不用记住那么多命令。

    如何解决JAVA内存泄漏问题

    总结:

    现在的服务器内存虽然很大,但是且用且珍惜,不要等到出现问题了才知道后果,在开发中规范自己代码,用完的对象及时释放,减少垃圾对象。出现问题了也不要慌,仔细分析代码,一切都是有原因的。

    “如何解决JAVA内存泄漏问题”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

    --结束END--

    本文标题: 如何解决JAVA内存泄漏问题

    本文链接: https://www.lsjlt.com/news/298030.html(转载时请注明来源链接)

    有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

    本篇文章演示代码以及资料文档资料下载

    下载Word文档到电脑,方便收藏和打印~

    下载Word文档
    猜你喜欢
    • c++中函数返回值的类型是由什么决定的
      在 c++ 中,函数返回值类型由其函数原型的类型决定,包括:函数原型指定返回值类型:在函数名称后跟冒号,再跟返回值类型。默认返回值类型为 int:如果不指定返回值类型,默认类型为 int...
      99+
      2024-05-14
      c++
    • 在c++中,什么叫函数的返回值
      在 c++ 中,函数只能返回一个值。解决方法:引用传递、结构体或类、out 参数。没有返回值的函数可以使用 void 类型,表示不返回任何值。 什么是 C++ 中函数的返回值? 在 C...
      99+
      2024-05-14
      c++
    • c++中static的作用和用法
      c++ 中的 static 关键字用于声明静态变量、函数或类成员,使其在程序生命周期内存在或与类的每个实例关联。具体用法如下:静态变量:在函数外声明,仅创建一份副本,在程序启动时初始化且...
      99+
      2024-05-14
      c++
    • static在c和c++中的区别
      static关键字在c和c++中用于控制变量的生命周期和作用域。在c中,它延长局部变量和限制全局变量的作用域。在c++中,它还用于定义类成员变量和函数、命名空间中的变量和函数,以及函数内...
      99+
      2024-05-14
      c语言 c++ 作用域
    • c++中a++与++a的区别
      c++ 中 a++ 和 ++a 区别:后缀递增 a++ 先返回原始值,再递增;前缀递增 ++a 先递增,再返回递增后的值。 C++ 中 a++ 与 ++a 的区别 在 C++ 中,a+...
      99+
      2024-05-14
      c++
    • if else在c++中的用法
      在 c++ 中,if else 语句根据条件执行不同代码块的语法为:if (condition) { } else { }。它可用于:检查数字是否为正数根据条件执行嵌套 if els...
      99+
      2024-05-14
      c++
    • struct在c和c++中的区别
      c和c++中struct的区别包括:c中成员默认公开访问,c++中默认私有访问。c++可以在struct定义中初始化成员,c中不允许。c++支持成员函数,c不支持。c++不支持匿名str...
      99+
      2024-05-14
      c++
    • c++中的所有函数都是传值调用吗
      函数调用类型可分为传值调用和引用调用,默认采用传值调用,传值调用中形参接收实参副本,引用调用中形参接收实参引用,对形参进行的修改也会影响实参。 C++中的函数调用类型 C++中,函数调...
      99+
      2024-05-14
      c++
    • c++中ifdef的用法
      c++ 中的 #ifdef 预处理器指令用于根据预定义宏是否存在来编译或不编译代码块。它的语法是 #ifdef ,其作用包括:检查宏是否存在,如果宏已定义,则编译其后的代码块;实现条件编...
      99+
      2024-05-14
      c++
    • c++中的函数调用有哪几种方式?它们有什么区别
      c++ 中的函数调用方式有 4 种:值传递(复制实参值,不影响实参)、引用传递(传递实参地址,修改形参值会修改实参)、指针传递(传递实参指向的内存地址,修改指向的值会影响实参)、rval...
      99+
      2024-05-14
      c++
    软考高级职称资格查询
    编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
    • 官方手机版

    • 微信公众号

    • 商务合作