GC学习入门 看这一篇就够了(基于Oracle JDK 8) (2)

并行, 类比串行, 是微观概念, 即在每一个时刻都有多个任务在同时执行, 形象点理解为多管齐下, 串行可理解为单列队列, 同一时刻只能执行一个任务.

事实上, 并行是并发的一种实现方式, 还有一种并发的实现方式, 即我们熟悉的时间片切换 --- 任务A执行一段时间, CPU再切换到任务B执行一段时间, 如此交替执行. 时间片切换在微观上仍然是串行 --- 某一具体时刻只有一个任务在执行, 而在宏观上, 即一段时间内, 有多个任务得到了执行.

总结: 并行必须在多核多处理器或分布式系统(本质还是多核多处理器)中才能发生, 而单核处理器上只能发生时间片切换.

3.4 G1 收集器(Garbage First GC)

G1垃圾回收器在 Oracle JDK 7 开始提供完整支持, 它是 server 型的 GC, 主要针对多核处理器和大内存的服务器, 能够以很高的概率 满足开发人员对停顿时间的要求, 同时还能保证高吞吐量.

与 CMS 收集器相比, G1收集器的优势:

1) 基于标记-整理算法, 不会产生大量的内存碎片;

2) 可以更加精确地控制停顿时间, 在不牺牲吞吐量前提下, 实现低停顿垃圾回收.

G1收集器的实现原理:

G1收集器能够避免全区域的垃圾收集, 它把堆内存划分为大小固定的几个独立区域, 并跟踪这些区域的垃圾收集进度, 同时在后台维护一个优先级列表, 每次根据所允许的收集时间, 优先回收垃圾最多的区域.

—— 区域划分和优先级区域回收机制, 确保G1收集器可以在有限的时间内获得最高的垃圾收集效率.

G1的长期目标是取代CMS (Concurrent Mark-Sweep Collector) 并发标记-清除收集器.

3.5 其他概念说明

为了更大程度地榨取机器性能, 新生代的收集器都使用了复制算法, 老年代的收集器都使用 标记-清除 或 标记-整理 算法. 关于各算法详情, 请参阅: JVM内存管理———垃圾搜集器参数精解.

在实际应用中, 需要对JVM的新生代、老年代分别选择合适的垃圾收集器.

这里新生代和老年代都分别有三种实现, 但由于收集器的实现方式不同, 部分组合无法一起配合工作, 经过验证, 这六种垃圾收集器只有六种可用组合.

4 GC 的配置参数 4.1 参数名称的说明 4.1.1 标准参数(-)

所有 JVM 都必须支持这些参数的功能, 而且向后兼容, 如:

-client : 设置 JVM 使用 client 模式, 特点是启动速度比较快, 但运行时性能和内存管理效率不高. 通常用于客户端应用程序或开发调试; 在32位环境下直接运行 Java 程序默认启用该模式.

-server : 设置 JVM 使 server 模式, 特点是启动速度比较慢, 但运行时性能和内存管理效率很高, 适用于生产环境; 在具有64位能力的JDK环境下默认启用该模式.

4.1.2 非标准参数(-X)

各 JVM 厂商应该都实现这些参数的功能, 但是并不保证所有的 JVM 实现都满足, 且不保证向后兼容;

4.1.3 非稳定参数(-XX)

此类参数各个JVM实现会有所不同, 将来可能会不被支持, 需要慎重使用.

注意: 在"-XX:"后的参数若不需要赋值, 即只是用来配置开启或关闭相应选项, 则需要有 "+" (开启) 或 "-" (禁止) , 否则应用程序将在日志文件 (如 Tomcat 的日志文件 catalina.out ) 中抛出如下错误:

Missing +/- setting for VM option 'UseConcMarkSweepGC'. Error: Could not create the Java Virtual Machine. Error: A fatal exception has occurred. Program will exit.

可以看出, 这里缺少了 "+/-" 符号, 导致虚拟机启动异常, 修改后即可正常启动.

4.2 串行 GC 参数 -XX:+UseSerialGC # 使用 Serial & Serial Old 串行收集器(JDK 5以前的主要收集方式), 是client模式的默认设置. 4.3 并行 GC 参数(吞吐量优先) -XX:+UseParNewGC # 使用 ParNew & Serial Old 收集器, 即对新生代使用并行收集, 提高收集效率(缩短Young GC的时间), 不推荐. -XX:+UseParallelGC # 使用 Parallel Scavenge & Parallel Old 并行收集器, 吞吐量优先, 会消耗更多内存, 是server模式的默认设置. -XX:+UseParallelOldGC # 对老年代使用 Parallel Old 并行收集器(JDK 6开始支持). -XX:ParallelGCThreads=20 # 配置并行收集器的线程数, 即并行执行垃圾收集任务的线程个数. # 此值最好与CPU处理器的个数相同(默认即相同). -XX:GCTimeRatio=49 # 设置系统用作GC的时间比例, 如49, 则GC时间比为 1/(1+49) = 2%, 即Java用2%的时间来做垃圾收集. # 如果此值设置过大, 即GC时间太少导致GC无法完成, JVM会压缩新生代的大小以适应此配置. -XX:MaxGCPauseMillis=100 # 设置每次新生代垃圾收集的最长毫秒值, 如果时间久而新生代的大小不足以支撑到此时间, # JVM会自动调整新生代的大小以满足此值. 若仍然无法满足, 则会调整GCTimeRatio. -XX:+UseAdaptiveSizePolicy # 使并行收集器自动设定 Eden 区的大小与相应的 Survivor 区的比例, # 以达到目标系统规定的最低响应时间或收集频率等. 建议在使用并行收集器时始终开启此选项. 4.4 并发 GC 参数(响应时间优先) -XX:+UseConcMarkSweepGC # JDK 5开始提供支持, 以响应时间优先--即缩短Full GC的时间. # JVM 会根据系统配置自行设置使用 ParNewGC & CMS(Serial Old作为替补)收集器. # 建议在 Heap Size 较大且 Full GC 时间较长, 对响应时间的需求大于对吞吐量的需求, 能够承受垃圾回收线程和应用线程共享CPU资源等情况下使用. -XX:+UseCMSCompactAtFullCollection # CMS是不会移动内存的, 此参数设置在每次Full GC后对老年代空间进行压缩整理, 会影响性能, 但是能减少内存碎片. -XX:CMSInitiatingOccupancyFraction=70 # 触发CMS收集器的内存占用阈值, 默认为90%: 当老年代内存空间使用率达到90%时, 就开始对老年代进行CMS并发垃圾收集. # 这个参数设置不当, 将发生promotion failed(晋升失败). -XX:CMSFullGCsBeforeCompaction=10 # 由于并发收集器不对内存空间进行压缩整理, 所以运行一段时间后会产生"碎片", 使得运行效率降低. 此配置项用来设置在几次GC后触发一次内存整理. # 此配置项即将被移除(JDK 8已不建议使用). 4.5 G1 GC 参数 -XX:+UseG1GC # 使用G1收集器 -XX:MaxGCPauseMillis=200 # 设置回收器的最大停顿毫秒值, 这是一个概率目标, JVM将尽最大努力去实现它. -XX:G1ReservePercent=15 # 设置堆的临时上限, 以防止因堆扩大失败而导致的异常. 默认值是10. -XX:G1HeapRegionSize=16 # 使用 G1 的 Java 堆细分为大小相等的区域(Region), 此选项是设置单个区域的大小, 默认值是基于堆大小的一种人体工效划分, 最小值是1Mb, 最大值是32Mb. # 人体工效: 根据平台相关的默认选择和根据需求动态垃圾回收的行为统称为人体工效, 人体工效的作用就是可以通过少量的命令行选项就可以让JVM提供最合适的性能. 4.6 通用 GC 参数 -Xnoclassgc # 禁用类垃圾收集, 能提高性能. -XX:MaxHeapFreeRatio=70 # GC过后堆的最大空闲空间比例, 避免过渡压缩 -XX:MinHeapFreeRatio=40 # GC过后堆的最小空闲空间比例, 避免过度膨胀 -XX:MaxTenuringThreshold=5 # 晋升老年代的最大年龄, 默认为15: 新生代对象在15次 Minor GC 后将被转移至老年代. --- 必须在0-15之间. # 如果设置为0, 等同于去掉了新生代的空间, 新生代对象将会越过 Survivor 区直接进入老年代, 很快就会占满老年代发生Full GC. # 同时, 这在老年代对象较多的应用中却可以提高效率. # 如果将此值调大, 则新生代对象会在 Survivor 区进行多次复制, 即增加了对象在新生代的存活时间. -XX:PretenureSizeThreshold=10 # 晋升老年代的对象的大小, 默认为0. 比如设为10M, 则超过10M的对象将越过 Eden区, 直接存入老年代. -XX:+UseThreadPriorities # 启用本地线程优先级API, 使 java.lang.Thread.setPriority() 生效, 不启用则无效 -XX:+DisableExplicitGC # 禁用写在程序中的 System.gc(), 即禁止开发人员调用 gc() 方法影响性能. -XX:+ExplicitGCInvokesConcurrent # 配置 System.gc() 可以和应用程序一起并发执行. # System.gc() 用来回收不用的内存, 此方法只是"建议" JVM 回收内存, 不能强制回收, 具体回收时机由 JVM 决定. -XX:TargetSurvivorRatio=90 # 允许90%的 Survivor 区被占用(JVM默认为50%), 提高对于 Survivor 区的使用率 -XX:SoftRefLRUPolicyMSPerMB=1 # Soft Reference(弱引用)在虚拟机中比在客户机中存活的时间更长, 其清除频率可用此命令来控制. # 此命令用来指定每 MB 堆空间中 Soft Reference 存活的秒数, 默认值为1000毫秒: 对象的最后一个强引用被收集之后, 存活1秒钟. # 这是个近似值: Soft Reference只会在垃圾收集时才会被清除, 而垃圾收集并不总是发生. 可改为0, 客户机中不使用就立即清除. 4.7 其他说明

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpsjyf.html