Java堆分配空间
Java从堆上分配空间的速度,可以和其他语言从堆栈上分配空间的速度相媲美。其中垃圾回收器起到了重要作用。
在一些Java虚拟机(JVM)中,每分配一个新对象,Java的“堆指针”就会移动到没有分配的区域。在垃圾回收器工作的时候,一面回收垃圾,一面重新排列堆中的对象,使之紧凑。这样,就实现了一种高速的堆模型。
引用计数技术
引用计数技术是一种简单但速度很慢的垃圾回收技术。在每个对象中都有一个引用计数器,每当有引用指向对象的时候,引用计数器就加1,当引用离开作用域或者是被置为null时,引用计数器就减1。垃圾回收器会遍历所有的对象,如果某个对象的引用计数器为0,就回收该对象占用的内存空间。
引用计数技术有一个很大的缺陷:如果存在交互循环引用的对象组,则对象的引用计数器不为0,需要回收的时候也无法回收。
引用计数技术效率低下,且存在明显缺陷。
JVM垃圾回收器基于的思想
对任何存活的对象,一定能够追溯到其存在于堆栈中或者静态存储区中的引用。
从堆栈或静态存储区出发,遍历所有的引用,找出引用所指向的对象,然后找出该对象所有的引用,重复操作,就能找出所有的引用和对象的对应网络。
停止-复制工作模式
在这种工作模式下工作的垃圾回收器会先暂停当前程序的运行,将堆中所有存活的对象复制到一个新的堆中,没有被复制的对象就是垃圾,需要被回收。复制时,新堆中的对象排列是紧凑的。
“复制式回收器”有两大缺陷:
- 工作时需要两个堆,将对象在两个堆之间来回复制,需要的空间是原来的两倍。所以有些JVM会从堆中分配出几块较大的内存,复制动作发生在这些块之间。
- 工作时需要复制对象,然而当程序进入稳定状态后,可能只会产生少量垃圾,甚至不产生垃圾,但垃圾回收器还是需要将所有存活的对象复制一遍,这是对资源的很大浪费。
标记-清扫工作模式
在这种工作模式下工作的垃圾回收器,在每找到一个存活的对象时,就会给这个对象设置一个标记,当所有的标记工作都结束后,进行清理工作,所有没有标记的对象内存都将被回收。在这种工作模式下回收垃圾后,剩下的堆空间是不连续的,需要垃圾回收器再进行空间的整理。
JVM的自适应的垃圾回收技术
Java虚拟机会进行监视,如果空间中的所有对象很稳定,垃圾较少,垃圾回收器会切换到标记-清扫工作模式;如果空间中的垃圾较多,垃圾回收器就会切换到停止-复制工作模式。