简述
在JVM中,就是应用先停下来,然后GC工作线程,赶紧扫描一遍,看看哪些对象是还有用,哪些是没用的
java 对象内存申请过程:
1.JVM 会试图为相关 Java 对象在 Eden 中初始化一块内存区域;当 Eden 空间足够时,内存申请结束。否则到下一步;
2.JVM 试图释放在 Eden 中所有不活跃的对象(minor collection),释放后若 Eden 空间仍然不足以放入新对象,则试图将部分 Eden 中活跃对象放入 Survivor 区;
3.Survivor 区被用来作为 Eden 及 old 的中间交换区域,当 old 区空间足够时,Survivor 区的对象会被移到 Old 区,否则会被保留在 Survivor 区;
4. 当 old 区空间不够时,JVM 会在 old 区进行 major collection;
5. 垃圾收集后,若 Survivor 及 old 区仍然无法存放从 Eden 复制过来的部分对象,导致 JVM 无法在 Eden 区为新对象创建内存区域,则出现 “Out of memory 错误”;
Stop-The-World:
在新生代进行的 GC 叫做 minor GC,在老年代进行的 GC 都叫 major GC,Full GC 同时作用于新生代和老年代。在垃圾回收过程中经常涉及到对对象的挪动(比如上文提到的对象在 Survivor 0 和 Survivor 1 之间的复制),进而导致需要对对象引用进行更新。为了保证引用更新的正确性,Java 将暂停所有其他的线程,这种情况被称为 “Stop-The-World”,导致系统全局停顿。Stop-The-World 对系统性能存在影响,因此垃圾回收的一个原则是尽量减少“Stop-The-World” 的时间。
不同垃圾收集器的 Stop-The-World 情况,Serial、Parallel 和 CMS 收集器均存在不同程度的 Stop-The-Word 情况;而即便是最新的 G1 收集器也不例外。
- Java 中一种全局暂停的现象, jvm 挂起状态
- 全局停顿,所有 Java 代码停止,native 代码可以执行,但不能和 JVM 交互
- 多半由于 jvm 的 GC 引起,如:
- 老年代空间不足。
- 永生代(jkd7)或者元数据空间(jkd8)不足。
3.System.gc() 方法调用。
4.CMS GC 时出现 promotion failed 和 concurrent mode failure
5.YoungGC 时晋升老年代的内存平均值大于老年代剩余空间 - 有连续的大对象需要分配
- 除了 GC 还有以下原因:
1.Dump 线程 — 人为因素。
2. 死锁检查。
3. 堆 Dump— 人为因素。
Full GC 是清理整个堆空间—包括年轻代和老年代。
GC 时为什么会有全局停顿?
类比在聚会时打扫房间,聚会时很乱,又有新的垃圾产生,房间永远打扫不干净,只有让大家停止活动了,才能将房间打扫干净。当 gc 线程在处理垃圾的时候,其它 java 线程要停止才能彻底清除干净,否则会影响 gc 线程的处理效率增加 gc 线程负担,特别是在垃圾标记的时候。
危害
- 长时间服务停止,没有响应
- 遇到 HA 系统,可能引起主备切换,严重危害生产环境。
- 新生代的 gc 时间比较短(),危害小。
- 老年代的 gc 有时候时间短,但是有时候比较长几秒甚至 100 秒 — 几十分钟都有。
- 堆越大花的时间越长。
GC中Stop the world(STW)
CMS会在找GCroot时和第二次查找时STW ,查找完毕就结束STW开始清理垃圾
G1会在找GCRoot时和第二次查找时STW,需要等垃圾清理完才结束