什么是垃圾( Garbage) 呢?
垃圾是指在运行程序中没有任何指针指向的对象,这个对象就是需要被回收的垃圾。
外文: An object is considered garbage when it can no longer be reached from any pointer in the running program.
如果不及时对内存中的垃圾进行清理,那么,这些垃圾对象所占的内存空间会一直保留到应用程序结束,被保留的空间无法被其他对象使用。甚至可能导致内存溢出。
什么是垃圾( Garbage) 呢?
垃圾是指在运行程序中没有任何指针指向的对象,这个对象就是需要被回收的垃圾。
外文: An object is considered garbage when it can no longer be reached from any pointer in the running program.
如果不及时对内存中的垃圾进行清理,那么,这些垃圾对象所占的内存空间会一直保留到应用程序结束,被保留的空间无法被其他对象使用。甚至可能导致内存溢出。
早期垃圾回收
在早期的C/C+ +时代,垃圾回收基本上是手工进行的。开发人员可以使用new关键字进行内存申请,并使用delete关键字进行内存释放。比如以下代码:
MibBridge *pBridge = new cmBaseGroupBridge ();//如果注册失败,使用Delete释放该对象所占内存区域if (pBridge->Register (kDestroy) != NO_ ERROR)delete pBridge;
这种方式可以灵活控制内存释放的时间,但是会给开发人员带来频繁申请和释放内存的管理负担。倘若有一处内存区间由于程序员编码的问题忘记被回收,那么就会产生内存泄漏,垃圾对象永远无法被清除,随着系统运行时间的不断增长,垃圾对象所耗内存可能持续上升,直到出现内存溢出并造成应用程序崩溃。
1、Serial (old)收集器
这个收集器是一个单线程收集器, 在他进行垃圾收集时, 必须暂停其他工作线程, 直到它收集结束 . (Stop The World)
新生代采用复制算法, 暂停所有用户进程
老年代采用标记 - 整理算法, 暂停所有用户线程 .
早期垃圾回收
在早期的C/C+ +时代,垃圾回收基本上是手工进行的。开发人员可以使用new关键字进行内存申请,并使用delete关键字进行内存释放。比如以下代码:
MibBridge *pBridge = new cmBaseGroupBridge ();//如果注册失败,使用Delete释放该对象所占内存区域if (pBridge->Register (kDestroy) != NO_ ERROR)delete pBridge;
这种方式可以灵活控制内存释放的时间,但是会给开发人员带来频繁申请和释放内存的管理负担。倘若有一处内存区间由于程序员编码的问题忘记被回收,那么就会产生内存泄漏,垃圾对象永远无法被清除,随着系统运行时间的不断增长,垃圾对象所耗内存可能持续上升,直到出现内存溢出并造成应用程序崩溃。
1、Serial (old)收集器
这个收集器是一个单线程收集器, 在他进行垃圾收集时, 必须暂停其他工作线程, 直到它收集结束 . (Stop The World)
新生代采用复制算法, 暂停所有用户进程
老年代采用标记 - 整理算法, 暂停所有用户线程 .
2、ParNew收集器
ParNew收集器实质上是 Serial 收集器的多线程并行版本,
ParNew除了支持多线程并行收集之外, 其他与Serial 收集器相比起来没有太多创新之处 .
并行和并发概念补充:
垃圾回收的多条线程并发来执行垃圾回收, 垃圾回收线程与用户线程是并行, 垃圾回收时, 用户线程是等待的 .
ParNew收集器运行示意图
3、Parallel Scavenge (old) 收集器
Parall Scavenger 收集器也是一款新生代收集器, 它同样是基于 标记 - 复制算法实现的多线程并行收集器 .
Parall Scavenger 收集器 的特点是它的关注点与其他收集器不同 , CMS 等收集器的关注点是尽可能缩短垃圾收集时用户线程的停顿时间, 而 Parall Scavenger 收集器 的目标是达到一个 可控制的吞吐量 .
所谓吞吐量就是处理器用于运行用户代码时间与处理器总消耗时间的比值 .
4、CMS收集器
CMS (Concurrent Mark Sweep) 收集器是一种以获取最短停顿时间为目标的收集器 ,
CMS(Concurrent Mark Sweep)收集器是 HotSpot 虚拟机第一款真正意义上的并发收集器,它第一次实现了让垃圾收集线程与用户线程(基本上)同时工作。
CMS 收集器是 基于 标记 - 清除算法 实现的, 整个过程分为四个步骤 :
初始标记 标记一下 GC Roots 能直接关联到的对象 速度很快
并发标记 从 GC Roots 的直接关联对象开始遍历整个对象图的过程, 这个过程耗时较长但是不需要停顿用户线程 ,可以与用户 线程并发运行.
重新标记 为了修正在并发标记期间, 因用户程序继续运行而导致标记产生变动的那一部分对象的标记记录. 这个阶段的停顿时间会比初始标记阶段长些, 但也远比并发标记阶段的时间短.
并发清除 清除掉标记阶段判断已死亡的对象, 由于不需要移动存活对象, 这个阶段也是并发执行的 .
初始标记 和 重新 标记仍然需要 Stop The World
