所谓的 JVM 优化,其实就是针对运行系统的 JVM 进程优化内存分配和垃圾回收,尽可能减少垃圾回收的频率,降低垃圾回收的时间,减少垃圾回收对系统运行的影响。
而进行垃圾回收是有专门的垃圾回收线程的,针对不同的内存区域会选择不同的垃圾回收器,垃圾回收器针对不同区域使用特定的垃圾回收算法;
例如,针对新生代我们会用 ParNew 垃圾回收器来进行回收,然后 ParNew 垃圾回收器针对新生代采用的就是复制算法来垃圾回收。这个时候垃圾回收器,就会把 Eden 区中的存活对象都标记出来,然后全部转移到 Survivor1 去,接着一次性清空掉 Eden 中的垃圾对象。
JVM 的痛点:Stop the World
使用 JVM 的最大的痛点,就是在垃圾回收的过程中,会直接停止我们写的 Java 应用系统的所有工作线程,不让系统程序创建新的对象了,尽可能让垃圾线程可以专心的进行垃圾回收的工作。
此时,JVM 会在后台直接进入 Stop the World 状态。
例如:
- Minor GC 要运行 100ms,那么系统直接停顿 100ms 不能处理任何请求,平时用户体验十几毫秒就有响应,现在需要等待几百毫秒;
- 上一个计算系统案例,平均七八分钟一次 Full GC,一次就几十秒,那么每个七八分钟就卡死30秒,这样的用户体验是非常糟糕的;
为了减少 Stop the World 的时间,JVM 不断迭代,不断优化垃圾回收器的机制和算法,尽可能降低垃圾回收的频率,垃圾回收的时间:
- 针对新生代的单线程的 Serial 垃圾回收器,很少用,运行时会暂停系统的工作线程;
- 现在常用的新生代的多线程的 ParNew 垃圾回收器,支持多线程并发执行,启动多个垃圾回收线程清理垃圾对象,缩短回收时间;
- 针对老年代的多线程的 CMS 垃圾回收器,支持多线程并发执行;
- 最新的现在很多公司在使用的 G1 垃圾回收器,复杂的机制大大的降低了 Stop the World 时间;