Java 内存管理机制
在 C++语言中,如果需要动态分配一块内存,程序员需要负责这块内存的整个生命
周期。从申请分配、到使用、再到最后的释放。这样的过程非常灵活,但是却十分繁琐,程
序员很容易由于疏忽而忘记释放内存,从而导致内存的泄露。Java 语言对内存管理做了
自己的优化,这就是垃圾回收机制。Java 的几乎所有内存对象都是在堆内存上分配(基
本数据类型除外),然后由 GC(garbage collection)负责自动回收不再使用的内存。
上面是 Java 内存管理机制的基本情况。但是如果仅仅理解到这里,我们在实际的项目
开发中仍然会遇到内存泄漏的问题。也许有人表示怀疑,
既然 Java 的垃圾回收机制能够
自动的回收内存,怎么还会出现内存泄漏的情况呢?
这个问题,我们需要知道 GC 在什
么时候回收内存对象,什么样的内存对象会被 GC
“
”
认为是 不再使用 的。
Java 中对内存对象的访问,使用的是引用的方式。在 Java 代码中我们维护一个内存对
象的引用变量,通过这个引用变量的值,我们可以访问到对应的内存地址中的内存对象
空间。在 Java 程序中,这个引用变量本身既可以存放堆内存中,又可以放在代码栈的内
存中(与基本数据类型相同)。GC 线程会从代码栈中的引用变量开始跟踪,从而判定哪
些内存是正在使用的。如果 GC 线程通过这种方式,无法跟踪到某一块堆内存,那么 GC
就认为这块内存将不再使用了(因为代码中已经无法访问这块内存了)。
通过这种有向图的内存管理方式,当一个内存对象失去了所有的引用之后,GC 就可
以将其回收。反过来说,如果这个对象还存在引用,那么它将不会被 GC 回收,哪怕是
Java 虚拟机抛出 OutOfMemoryError。
Java 内存泄露
一般来说内存泄漏有两种情况。一种情况如在 C/C++语言中的,在堆中的分配的内存,
在没有将其释放掉的时候,就将所有能访问这块内存的方式都删掉(如指针重新赋值);
另一种情况则是在内存对象明明已经不需要的时候,还仍然保留着这块内存和它的访问
方式(引用)。第一种情况,在 Java 中已经由于垃圾回收机制的引入,得到了很好的解
决。所以,Java 中的内存泄漏,主要指的是第二种情况。
可能光说概念太抽象了,大家可以看一下这样的例子: