background image

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 中的内存泄漏,主要指的是第二种情况。
    可能光说概念太抽象了,大家可以看一下这样的例子: