内存泄露的根源和剖析有哪些经验可以分享?
- 内容介绍
- 文章标签
- 相关推荐
本文共计1587个文字,预计阅读时间需要7分钟。
经验之谈:内存泄露的原因及分析内存泄露是Javaer最常听到关于内存的问题之一。本文就来谈谈这件事。内存泄露与资源泄露什么是泄露?在计算机语境下,泄露通常指的是资源没有被正确释放,导致资源无法被再次利用。在Java环境下,常见的泄露包括内存泄露和资源泄露。
内存泄露与资源泄露有什么区别?内存泄露指的是程序中分配的内存无法被垃圾回收机制回收,导致内存占用持续增加。资源泄露则是指程序中使用的资源(如文件、数据库连接等)没有被正确关闭或释放,导致资源无法被再次使用。
内存泄露的原因内存泄露的原因有很多,以下是一些常见的原因:
1.对象生命周期过长:创建的对象没有被及时回收,因为它们引用了其他对象。
2.循环引用:两个或多个对象相互引用,导致垃圾回收器无法回收它们。
3.静态变量:静态变量在程序运行期间一直存在,如果它们引用了其他对象,则可能导致内存泄露。
4.监听器或回调:注册的监听器或回调没有被正确移除,导致相关对象无法被回收。
内存泄露的分析
分析内存泄露通常需要以下步骤:1.识别问题:通过日志、堆转储分析等手段识别内存泄露。
2.定位问题:通过代码分析、堆转储分析等手段定位内存泄露的源头。
3.解决问题:根据定位到的问题,修改代码,释放不再需要的资源。
总结
内存泄露是Java程序中常见的问题,了解其产生的原因和解决方法对于Java开发者来说至关重要。通过本文的介绍,希望读者能够对内存泄露有更深入的了解。 经验之谈:内存泄露的原因以及分析内存泄露是Javaer听到最多的关于内存的事了,这篇文章就来谈谈这件事。
内存泄露与资源泄露什么是泄露?泄露在计算机语境下,通常指的是某个资源无法被访问,也无法被释放。
内存泄露一般发生在某个对象的引用丢失,无法再访问到该引用,但是该引用却依旧引用着某个对象,导致这个对象无法回收,最终导致内存溢出OOM。
资源泄露一般发生在连接池,IO流等场景,如从连接池中每次都新建连接但不关闭,每次都打开新的IO流但不关闭,等等情况。
内存泄露发生的情况内存泄露多发生于static的集合中,比如当你定义了一个static HashMap,此时将某个key-value放入其中后,方法段结束。
这时,除非调用map的clear方法,否则显然该value将无限持有对象的引用,无法释放。
public static Map<String,Object> objectMap=new HashMap<>();
public static void main(String[] args) {
Integer a=new Integer(1);
objectMap.put("testKey",a);
}
这种写法看似可笑,却很难避免,尤其在大量框架代码中,反而更容易发生,因为大部分框架代码对业务代码的增强,都是通过AOP方式来做的,此时对业务代码来说,这类隐式的static Map难以防范。
内存使用过高,一定是内存泄露吗?内存使用过高,并不一定是内存泄露导致的结果,具体要看内存堆的分析。
一般内存泄露最直观的体现就是:
- 内存使用高
- GC回收不了内存,即GC前后堆大小几乎无变化
- JVM疯狂GC,CPU打满
- Java进程触发Linux操作系统的OOM-killer,Java进程被杀死
- 或者CPU被GC任务打满,服务器实际宕机。
但是这不一定是泄露导致的,也有可能是内存的错误使用导致的,不过大同小异,主要还是需要排查异常内存的使用。
Ps:之所以作者这么说,是因为作者曾经在线上遇到了架构组修改日志框架,错误的将日志内容作为了key存入了map,本应的key-value应该为traceId-日志内容,结果架构组却将key-value搞反了,导致大量的巨大key打满了内存,堆dump文件里全是几十k几十k的字符串。
如何避免内存泄露根据上面说的内存泄露多数发生的情况,避免内存泄露的策略也就十分简单了。
- 尽量使用局部变量
- 减少使用static集合
- 如果必要的使用static集合,尽量使用弱引用等低级引用。比如参照ThreadLocal中的设计:TheadLocal原理
内存泄露或内存持续使用较高时,通常通过堆的情况来排查。
首先可以通过jmap -histo:live pid|less 命令,查看堆内对象使用情况。此时如果内存泄露,一般都是会某个基本类型对象过多,然后可以与正常的服务作对比,看哪个对象的数量异常的多,此时如果可以判断出来,也没必要dump了。
如果通过jmap无法断定,则可以使用jmap -dump:live,format=b,file=
将dump文件通过java原生的软件或者eclipse的mat工具,就可以看到哪些对象占用过多,此时你应该关注的是非基本类型对象的其他对象,因为一般来说都是基本类型的数量和大小最多。
一般来说,你会看到以下现象:
- 某个map的Node十分多,有几十万个。
- 某个框架的某个对象十分多。
- char数据,也就是C[],占用十分多,因为有很多大字符串。
本文共计1587个文字,预计阅读时间需要7分钟。
经验之谈:内存泄露的原因及分析内存泄露是Javaer最常听到关于内存的问题之一。本文就来谈谈这件事。内存泄露与资源泄露什么是泄露?在计算机语境下,泄露通常指的是资源没有被正确释放,导致资源无法被再次利用。在Java环境下,常见的泄露包括内存泄露和资源泄露。
内存泄露与资源泄露有什么区别?内存泄露指的是程序中分配的内存无法被垃圾回收机制回收,导致内存占用持续增加。资源泄露则是指程序中使用的资源(如文件、数据库连接等)没有被正确关闭或释放,导致资源无法被再次使用。
内存泄露的原因内存泄露的原因有很多,以下是一些常见的原因:
1.对象生命周期过长:创建的对象没有被及时回收,因为它们引用了其他对象。
2.循环引用:两个或多个对象相互引用,导致垃圾回收器无法回收它们。
3.静态变量:静态变量在程序运行期间一直存在,如果它们引用了其他对象,则可能导致内存泄露。
4.监听器或回调:注册的监听器或回调没有被正确移除,导致相关对象无法被回收。
内存泄露的分析
分析内存泄露通常需要以下步骤:1.识别问题:通过日志、堆转储分析等手段识别内存泄露。
2.定位问题:通过代码分析、堆转储分析等手段定位内存泄露的源头。
3.解决问题:根据定位到的问题,修改代码,释放不再需要的资源。
总结
内存泄露是Java程序中常见的问题,了解其产生的原因和解决方法对于Java开发者来说至关重要。通过本文的介绍,希望读者能够对内存泄露有更深入的了解。 经验之谈:内存泄露的原因以及分析内存泄露是Javaer听到最多的关于内存的事了,这篇文章就来谈谈这件事。
内存泄露与资源泄露什么是泄露?泄露在计算机语境下,通常指的是某个资源无法被访问,也无法被释放。
内存泄露一般发生在某个对象的引用丢失,无法再访问到该引用,但是该引用却依旧引用着某个对象,导致这个对象无法回收,最终导致内存溢出OOM。
资源泄露一般发生在连接池,IO流等场景,如从连接池中每次都新建连接但不关闭,每次都打开新的IO流但不关闭,等等情况。
内存泄露发生的情况内存泄露多发生于static的集合中,比如当你定义了一个static HashMap,此时将某个key-value放入其中后,方法段结束。
这时,除非调用map的clear方法,否则显然该value将无限持有对象的引用,无法释放。
public static Map<String,Object> objectMap=new HashMap<>();
public static void main(String[] args) {
Integer a=new Integer(1);
objectMap.put("testKey",a);
}
这种写法看似可笑,却很难避免,尤其在大量框架代码中,反而更容易发生,因为大部分框架代码对业务代码的增强,都是通过AOP方式来做的,此时对业务代码来说,这类隐式的static Map难以防范。
内存使用过高,一定是内存泄露吗?内存使用过高,并不一定是内存泄露导致的结果,具体要看内存堆的分析。
一般内存泄露最直观的体现就是:
- 内存使用高
- GC回收不了内存,即GC前后堆大小几乎无变化
- JVM疯狂GC,CPU打满
- Java进程触发Linux操作系统的OOM-killer,Java进程被杀死
- 或者CPU被GC任务打满,服务器实际宕机。
但是这不一定是泄露导致的,也有可能是内存的错误使用导致的,不过大同小异,主要还是需要排查异常内存的使用。
Ps:之所以作者这么说,是因为作者曾经在线上遇到了架构组修改日志框架,错误的将日志内容作为了key存入了map,本应的key-value应该为traceId-日志内容,结果架构组却将key-value搞反了,导致大量的巨大key打满了内存,堆dump文件里全是几十k几十k的字符串。
如何避免内存泄露根据上面说的内存泄露多数发生的情况,避免内存泄露的策略也就十分简单了。
- 尽量使用局部变量
- 减少使用static集合
- 如果必要的使用static集合,尽量使用弱引用等低级引用。比如参照ThreadLocal中的设计:TheadLocal原理
内存泄露或内存持续使用较高时,通常通过堆的情况来排查。
首先可以通过jmap -histo:live pid|less 命令,查看堆内对象使用情况。此时如果内存泄露,一般都是会某个基本类型对象过多,然后可以与正常的服务作对比,看哪个对象的数量异常的多,此时如果可以判断出来,也没必要dump了。
如果通过jmap无法断定,则可以使用jmap -dump:live,format=b,file=
将dump文件通过java原生的软件或者eclipse的mat工具,就可以看到哪些对象占用过多,此时你应该关注的是非基本类型对象的其他对象,因为一般来说都是基本类型的数量和大小最多。
一般来说,你会看到以下现象:
- 某个map的Node十分多,有几十万个。
- 某个框架的某个对象十分多。
- char数据,也就是C[],占用十分多,因为有很多大字符串。

