一,C/C++
学过C/C++的都应该非常清除,我们需要自己管理内存,每次动态分配的内存单位都需要自己手动进行释放。如果忘记释放C/C++编译器并不会自动检测出并为你释放该内存,这样的话很容易导致内存泄漏。这也是C/C++比较难的原因之一。
二,Java
Java不需要关心对象的释放,这个过程交给了垃圾回收器。Java的垃圾回收器会定期扫描栈和静态存储区,遍历所有的引用,找出活的对象。
Java虚拟机是一种自适应的工作模式,它有两种模式,一种是"标记-清扫"模式,一种是"停止-复制"模式。
Java虚拟机会进行检测,他会自动切换工作模式,一般情况下要是没有垃圾产生,他会切换到"标记-清扫",这种模式速度很慢,但是如果程序只产生少量垃圾或者不产生垃圾的时候这种模式就很快。但是这种模式会导致大量的不连续的堆空间。导致内存利用率比较低。
另一种模式是"停止-复制",这种模式并不是在后台进行工作。而是会将程序停止,它也会扫描栈和静态存储区遍历所有活的引用,然后停止程序运行,并将所有存活的对象从旧堆复制到新堆。这就导致了大量的内存复制行为。内存分配以较大的"块"为单位,如果某个对象较大,它会占用单独的块。复制行为是以块为单位进行的。有了块,垃圾回收器就可以将对象复制到废弃的块。每个块都有年代数来记录自己是否存活。通常块在某处被引用,其年代数就加1,大型对象不会被复制,只是年代数加1,含有小型对象的那些块就会被复制并整理。Java虚拟机会监视,如果所有的对象都很稳定,垃圾回收的效率降低就会切换为"标记-清扫"模式。
同样道理,Java虚拟机会跟踪"标记-清扫"的效果,如果堆空间产生来大量的碎片的话,就会切换为"停止-复制"模式。这就是"自适应"的由来。