前言

Java通过垃圾回收机制,可以自动的管理内存,这对开发人员来说是多么美好的事啊。但垃圾回收器并不是万能的,它能够处理大部分场景下的内存清理、内存泄露以及内存优化。但它也并不是万能的。
不然,我们在实践的过程中也不会出现那么多因内存泄露导致的生产事件了。但很多内存泄露时间也是因为开发人员使用不当导致的。
本篇文章我们就来聊聊内存泄露的原因是什么,如何识别内存泄露,以及如果在应用程序中进行处理。

什么是内存泄露

什么是内存泄露,通俗的来说就是堆中的一些对象已经不会再被使用了,但垃圾收集器却无法将它们从内存中清除。
内存泄漏很严重的问题,因为它会阻塞内存资源并随着时间的推移降低系统性能。如果不进行有效的处理,最终的结果将会使应用程序耗尽内存资源,无法正常服务,导致程序崩溃,抛出java.lang.OutOfMemoryError异常。
堆内存中通常有两种类型的对象:被引用的对象和未被引用的对象。被引用的对象是应用程序中仍然具有活跃的引用,而未被引用的对象则没有任何活跃的引用。
垃圾收集器会回收那些未被引用的对象,但不会回收那些还在被引用的对象。这也是内存泄露发生的源头。
内存泄露往往有以下表象:
当应用程序长时间连续运行时,性能严重下降;抛出OutOfMemoryError异常;程序莫名其妙的自动崩溃;应用程序耗尽链接对象。
当然,如果打印GC日志,有些场景下还会看到频繁执行full GC等状况。下面就具体分析一下这些场景和处理方案。

Java中内存泄露分类

在任何一个应用程序中,发生内存泄露往往由很多原因构成。下面我们就聊聊最常见的一些内存泄露场景。

静态属性导致内存泄露

会导致内存泄露的一种情况就是大量使用static静态变量。在Java中,静态属性的生命周期通常伴随着应用整个生命周期(除非ClassLoader符合垃圾回收的条件)。
下面来看一个具体的会导致内存泄露的实例:
public class StaticTest {publicstatic List