怎么选择垃圾回收器?
- 优先让
JVM
自适应, 调整堆的大小 - 串行收集器: 内存小于 100M; 单核、单机机器, 并且没有停顿时间的要求
- 并行收集器: 多
CPU
、 高吞吐量、允许停顿时间超过 1 秒 - 并发收集器: 多
CPU
、追求低停顿时间、快速响应(比如延迟不能超过1秒
, 如互联网应用) - 官方推荐
G1
, 性能高。现在互联网的项目, 基本都是使用G1
特别说明:
- 没有最好的收集器, 更没有万能的收集器
- 调优永远是针对特定场景、特定需求,不存在一劳永逸的收集器
七款垃圾收集器
- 串行回收器:
Serial
、Serial Old
- 并行回收器:
Parnew
、Parallel Scavenge
、Parallel Old
- 并发回收器:
CMS
、G1
- 新生代收集器:
Serial
、Parnew
、Parallel Scavenge
; - 老年代收集器:
Serial Old
、Parallel Old
、CMS
; - 整争堆收集器:
G1
;
垃圾收集器 | 分类 | 作用位置 | 使用算法 | 特点 | 适用场景 |
---|---|---|---|---|---|
Serial | 串行运行 | 作用于新生代 | 复制算法 | 响应速度优先 | 适用于单 CPU 环境下的 client 模式 |
ParNew | 并行运行 | 作用于新生代 | 复制算法 | 响应速度优先 | 多 CPU 环境 Server模式下与CMS配合使用 |
Parallel | 并行运行 | 作用于新生代 | 复制算法 | 吞吐量优先 | 适用于后台运算而不需要太多交互的场景 |
Serial Old | 串行运行 | 作用于老年代 | 标记-压缩算法 | 响应速度优先 | 适用于单 CPU 环境下的 client模式 |
Parallel Old | 并行运行 | 作用于老年代 | 标记-压缩算法 | 吞吐量优先 | 适用于后台运算而不需要太多交互的场景 |
CMS | 并发运行 | 作用于老年代 | 标记-清除算法 | 响应速度优先 | 适用于互联网或 B/S 业务 |
G1 | 并发、并行运行 | 作用于新生代、老年代 | 标记压缩算法、复制算法 | 响应速度优先 | 面向服务端应用 |
怎么选择垃圾回收器: Java 垃圾收集器的配置对于 JVM 优化来说是一个很重要的选择, 选择合适的垃圾手机器可以让 JVM 的性能有一个很大的提升。怎么选择垃圾收集器?
- 优先调整堆的大小让 JVM 自适应完成
- 如果内存小于 100M, 使用串行收集器
- 如果是单核、单机机器, 并且没有停顿时间的要求, 串行收集器
- 如果是多 CPU、需要高吞吐量、允许停顿时间超过1秒, 选择并行或者JVM自己选择
- 如果是多 CPU、追求停顿时间, 需快速响应(比如延迟不能超过1秒, 如互联网应用), 使用并发收集器
- 官方推荐 G1, 性能高. 现在互联网的项目, 基本都是使用 G1.
JVM 运行时的数据区域:
- 方法区(Method Area): 用于存储类的结构信息,包括类的字节码、静态变量、常量池、方法信息等。在 JDK8及之前的版本中, 方法区被实现为永元代(Permanent Generation), 而在 JDK8 及之后的版本中, 方法区被实现为元空间(Metaspace)。
- 堆(Heap): 用于存储对象实例。堆是 Java 程序中最常用的内存区域。 所有通过关键字
new
创建的对象都会在堆上分配内存。堆被所有线程共享, 是 Java 中垃圾回收的主要区域。 - 虚拟机栈(VM Stack): 每个线程在运行时都会有一个栈, 用于存储方法的局部变量、方法参数、中间计算结果等。每个方法在执行时会创建一个栈帧,栈帧包含了 方法的局部变量表、操作数栈、动态链接等信息。
- 本地方法栈(Native Method Stack): 类似于虚拟机栈, 但是用于执行本地(Native)方法。本地方法栈存储了使用其他编程语言(如C、C++)编写的本地方法的相关数据。
- 程序计数器(Program Counter Register): 每个线程都有一个程序计数器,用于指示当前线程执行的字节码的地址。在任何时候,每个线程都只会执行一个方法 的代码,程序计数器用于记录线程当前执行的位置。