概述

当排查各种内存溢出, 内存泄漏问题时, 当垃圾收集成为系统到达更高并发量的瓶颈时, 我们就需要对这些自动化的技术实施必要的监控和调节

JAVA程序运行时区域的各个部分

  • 程序计数器, 虚拟机栈, 本地方法栈随线程而生而灭, 栈中的栈帧随着方法的进入和退出有条不紊的执行着入栈和出栈的操作, 每一个栈帧中分配多少内存基本上是类结构确定下来就已知的, 因此这几个区域的内存分配和回收都具有确定性
  • JAVA堆则不一样, 一个接口中多个实现类需要的内存可能不一样, 一个方法中多个分支需要的内存也可能不一样, 只有在程序运行期间才能知道会创建哪些对象, 这部分内存的分配和回收都是动态的

对象已死?

引用计数法

给对象添加一个引用计数器, 每有一个地方引用它时, 计数器值+1, 当引用失效时, 计数器-1, 任何时刻计数器为0的对象就是不可能再被使用的
java语言没有选用引用计数法来管理内存
问题: 很难解决对象之间的循环引用问题
循环引用示例代码:

  1. /**
  2. * ReferenceCountingGC
  3. * VM Args: -XX:+PrintGCDetails
  4. * @author xinzhang
  5. * @author Shenzhen Greatonce Co Ltd
  6. * @version 2020/2/7
  7. */
  8. public class ReferenceCountingGC {
  9. private Object instance = null;
  10. private static final int _1MB = 1024 * 1024;
  11. /**
  12. * 占点内存以便观察GC日志
  13. */
  14. private byte[] bigSize = new byte[2 * _1MB];
  15. public static void main(String[] args) {
  16. ReferenceCountingGC objA = new ReferenceCountingGC();
  17. ReferenceCountingGC objB = new ReferenceCountingGC();
  18. objA.instance = objB;
  19. objB.instance = objA;
  20. System.gc();
  21. }
  22. }

运行结果:

  1. "C:\Program Files\Java\jdk1.8.0_221\bin\java.exe" -XX:+PrintGCDetails "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2019.3.2\lib\idea_rt.jar=53807:C:\Program Files\JetBrains\IntelliJ IDEA 2019.3.2\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_221\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\rt.jar;D:\巨益\参考项目\demo\xinzhang-demo\xinzhang-producer\target\classes;C:\XZrepository\com\greatonce\je-core\1.0.2-SNAPSHOT\je-core-1.0.2-20191216.071350-6.jar;C:\XZrepository\org\springframework\spring-context\5.1.5.RELEASE\spring-context-5.1.5.RELEASE.jar;C:\XZrepository\org\springframework\spring-aop\5.1.5.RELEASE\spring-aop-5.1.5.RELEASE.jar;C:\XZrepository\org\springframework\spring-beans\5.1.5.RELEASE\spring-beans-5.1.5.RELEASE.jar;C:\XZrepository\org\springframework\spring-expression\5.1.5.RELEASE\spring-expression-5.1.5.RELEASE.jar;C:\XZrepository\org\aspectj\aspectjweaver\1.9.2\aspectjweaver-1.9.2.jar;C:\XZrepository\org\springframework\spring-context-support\5.1.5.RELEASE\spring-context-support-5.1.5.RELEASE.jar;C:\XZrepository\org\springframework\spring-tx\5.1.5.RELEASE\spring-tx-5.1.5.RELEASE.jar;C:\XZrepository\org\springframework\amqp\spring-amqp\2.1.4.RELEASE\spring-amqp-2.1.4.RELEASE.jar;C:\XZrepository\org\springframework\retry\spring-retry\1.2.4.RELEASE\spring-retry-1.2.4.RELEASE.jar;C:\XZrepository\org\springframework\integration\spring-integration-redis\5.1.3.RELEASE\spring-integration-redis-5.1.3.RELEASE.jar;C:\XZrepository\org\springframework\integration\spring-integration-core\5.1.3.RELEASE\spring-integration-core-5.1.3.RELEASE.jar;C:\XZrepository\io\projectreactor\reactor-core\3.2.6.RELEASE\reactor-core-3.2.6.RELEASE.jar;C:\XZrepository\org\reactivestreams\reactive-streams\1.0.2\reactive-streams-1.0.2.jar;C:\XZrepository\com\alibaba\fastjson\1.2.60\fastjson-1.2.60.jar;C:\XZrepository\commons-codec\commons-codec\1.11\commons-codec-1.11.jar;C:\XZrepository\commons-io\commons-io\2.6\commons-io-2.6.jar;C:\XZrepository\org\mybatis\mybatis\3.4.6\mybatis-3.4.6.jar;C:\XZrepository\javax\servlet\javax.servlet-api\4.0.1\javax.servlet-api-4.0.1.jar;C:\XZrepository\org\quartz-scheduler\quartz\2.3.0\quartz-2.3.0.jar;C:\XZrepository\com\mchange\mchange-commons-java\0.2.11\mchange-commons-java-0.2.11.jar;C:\XZrepository\com\github\jsqlparser\jsqlparser\0.9.5\jsqlparser-0.9.5.jar;C:\XZrepository\com\alibaba\druid\1.1.10\druid-1.1.10.jar;C:\XZrepository\org\mybatis\mybatis-spring\1.3.2\mybatis-spring-1.3.2.jar;C:\XZrepository\mysql\mysql-connector-java\8.0.15\mysql-connector-java-8.0.15.jar;C:\XZrepository\org\slf4j\slf4j-api\1.7.25\slf4j-api-1.7.25.jar;C:\XZrepository\ch\qos\logback\logback-classic\1.2.3\logback-classic-1.2.3.jar;C:\XZrepository\ch\qos\logback\logback-core\1.2.3\logback-core-1.2.3.jar;C:\XZrepository\org\springframework\spring-jdbc\5.1.5.RELEASE\spring-jdbc-5.1.5.RELEASE.jar;C:\XZrepository\org\apache\httpcomponents\httpclient\4.5.7\httpclient-4.5.7.jar;C:\XZrepository\org\apache\httpcomponents\httpcore\4.4.11\httpcore-4.4.11.jar;C:\XZrepository\org\springframework\data\spring-data-redis\2.1.5.RELEASE\spring-data-redis-2.1.5.RELEASE.jar;C:\XZrepository\org\springframework\data\spring-data-keyvalue\2.1.5.RELEASE\spring-data-keyvalue-2.1.5.RELEASE.jar;C:\XZrepository\org\springframework\data\spring-data-commons\2.1.5.RELEASE\spring-data-commons-2.1.5.RELEASE.jar;C:\XZrepository\org\springframework\spring-oxm\5.1.5.RELEASE\spring-oxm-5.1.5.RELEASE.jar;C:\XZrepository\redis\clients\jedis\2.9.1\jedis-2.9.1.jar;C:\XZrepository\org\apache\commons\commons-pool2\2.6.1\commons-pool2-2.6.1.jar;C:\XZrepository\org\springframework\boot\spring-boot-starter-web\2.1.3.RELEASE\spring-boot-starter-web-2.1.3.RELEASE.jar;C:\XZrepository\org\springframework\boot\spring-boot-starter\2.1.3.RELEASE\spring-boot-starter-2.1.3.RELEASE.jar;C:\XZrepository\org\springframework\boot\spring-boot\2.1.3.RELEASE\spring-boot-2.1.3.RELEASE.jar;C:\XZrepository\org\springframework\boot\spring-boot-autoconfigure\2.1.3.RELEASE\spring-boot-autoconfigure-2.1.3.RELEASE.jar;C:\XZrepository\org\springframework\boot\spring-boot-starter-logging\2.1.3.RELEASE\spring-boot-starter-logging-2.1.3.RELEASE.jar;C:\XZrepository\org\apache\logging\log4j\log4j-to-slf4j\2.11.2\log4j-to-slf4j-2.11.2.jar;C:\XZrepository\org\apache\logging\log4j\log4j-api\2.11.2\log4j-api-2.11.2.jar;C:\XZrepository\org\slf4j\jul-to-slf4j\1.7.25\jul-to-slf4j-1.7.25.jar;C:\XZrepository\javax\annotation\javax.annotation-api\1.3.2\javax.annotation-api-1.3.2.jar;C:\XZrepository\org\yaml\snakeyaml\1.23\snakeyaml-1.23.jar;C:\XZrepository\org\springframework\boot\spring-boot-starter-json\2.1.3.RELEASE\spring-boot-starter-json-2.1.3.RELEASE.jar;C:\XZrepository\com\fasterxml\jackson\core\jackson-databind\2.9.8\jackson-databind-2.9.8.jar;C:\XZrepository\com\fasterxml\jackson\core\jackson-annotations\2.9.0\jackson-annotations-2.9.0.jar;C:\XZrepository\com\fasterxml\jackson\core\jackson-core\2.9.8\jackson-core-2.9.8.jar;C:\XZrepository\com\fasterxml\jackson\datatype\jackson-datatype-jdk8\2.9.8\jackson-datatype-jdk8-2.9.8.jar;C:\XZrepository\com\fasterxml\jackson\datatype\jackson-datatype-jsr310\2.9.8\jackson-datatype-jsr310-2.9.8.jar;C:\XZrepository\com\fasterxml\jackson\module\jackson-module-parameter-names\2.9.8\jackson-module-parameter-names-2.9.8.jar;C:\XZrepository\org\springframework\boot\spring-boot-starter-tomcat\2.1.3.RELEASE\spring-boot-starter-tomcat-2.1.3.RELEASE.jar;C:\XZrepository\org\apache\tomcat\embed\tomcat-embed-core\9.0.16\tomcat-embed-core-9.0.16.jar;C:\XZrepository\org\apache\tomcat\embed\tomcat-embed-el\9.0.16\tomcat-embed-el-9.0.16.jar;C:\XZrepository\org\apache\tomcat\embed\tomcat-embed-websocket\9.0.16\tomcat-embed-websocket-9.0.16.jar;C:\XZrepository\org\hibernate\validator\hibernate-validator\6.0.14.Final\hibernate-validator-6.0.14.Final.jar;C:\XZrepository\javax\validation\validation-api\2.0.1.Final\validation-api-2.0.1.Final.jar;C:\XZrepository\org\jboss\logging\jboss-logging\3.3.2.Final\jboss-logging-3.3.2.Final.jar;C:\XZrepository\com\fasterxml\classmate\1.4.0\classmate-1.4.0.jar;C:\XZrepository\org\springframework\spring-web\5.1.5.RELEASE\spring-web-5.1.5.RELEASE.jar;C:\XZrepository\org\springframework\spring-webmvc\5.1.5.RELEASE\spring-webmvc-5.1.5.RELEASE.jar;C:\XZrepository\org\apache\commons\commons-lang3\3.9\commons-lang3-3.9.jar;C:\XZrepository\org\springframework\boot\spring-boot-starter-test\2.1.3.RELEASE\spring-boot-starter-test-2.1.3.RELEASE.jar;C:\XZrepository\org\springframework\boot\spring-boot-test\2.1.3.RELEASE\spring-boot-test-2.1.3.RELEASE.jar;C:\XZrepository\org\springframework\boot\spring-boot-test-autoconfigure\2.1.3.RELEASE\spring-boot-test-autoconfigure-2.1.3.RELEASE.jar;C:\XZrepository\com\jayway\jsonpath\json-path\2.4.0\json-path-2.4.0.jar;C:\XZrepository\net\minidev\json-smart\2.3\json-smart-2.3.jar;C:\XZrepository\net\minidev\accessors-smart\1.2\accessors-smart-1.2.jar;C:\XZrepository\org\ow2\asm\asm\5.0.4\asm-5.0.4.jar;C:\XZrepository\junit\junit\4.12\junit-4.12.jar;C:\XZrepository\org\assertj\assertj-core\3.11.1\assertj-core-3.11.1.jar;C:\XZrepository\org\mockito\mockito-core\2.23.4\mockito-core-2.23.4.jar;C:\XZrepository\net\bytebuddy\byte-buddy\1.9.10\byte-buddy-1.9.10.jar;C:\XZrepository\net\bytebuddy\byte-buddy-agent\1.9.10\byte-buddy-agent-1.9.10.jar;C:\XZrepository\org\objenesis\objenesis\2.6\objenesis-2.6.jar;C:\XZrepository\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar;C:\XZrepository\org\hamcrest\hamcrest-library\1.3\hamcrest-library-1.3.jar;C:\XZrepository\org\skyscreamer\jsonassert\1.5.0\jsonassert-1.5.0.jar;C:\XZrepository\com\vaadin\external\google\android-json\0.0.20131108.vaadin1\android-json-0.0.20131108.vaadin1.jar;C:\XZrepository\org\springframework\spring-core\5.1.5.RELEASE\spring-core-5.1.5.RELEASE.jar;C:\XZrepository\org\springframework\spring-jcl\5.1.5.RELEASE\spring-jcl-5.1.5.RELEASE.jar;C:\XZrepository\org\springframework\spring-test\5.1.5.RELEASE\spring-test-5.1.5.RELEASE.jar;C:\XZrepository\org\xmlunit\xmlunit-core\2.6.2\xmlunit-core-2.6.2.jar;C:\XZrepository\javax\xml\bind\jaxb-api\2.3.1\jaxb-api-2.3.1.jar;C:\XZrepository\javax\activation\javax.activation-api\1.2.0\javax.activation-api-1.2.0.jar;C:\XZrepository\org\springframework\boot\spring-boot-starter-amqp\2.1.3.RELEASE\spring-boot-starter-amqp-2.1.3.RELEASE.jar;C:\XZrepository\org\springframework\spring-messaging\5.1.5.RELEASE\spring-messaging-5.1.5.RELEASE.jar;C:\XZrepository\org\springframework\amqp\spring-rabbit\2.1.4.RELEASE\spring-rabbit-2.1.4.RELEASE.jar;C:\XZrepository\com\rabbitmq\amqp-client\5.4.3\amqp-client-5.4.3.jar;C:\XZrepository\com\alibaba\transmittable-thread-local\2.10.2\transmittable-thread-local-2.10.2.jar" top.xinzhang0618.producer.jvm.gc.ReferenceCountingGC
  2. [GC (System.gc()) [PSYoungGen: 10663K->5411K(76288K)] 10663K->5419K(251392K), 0.0043796 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
  3. [Full GC (System.gc()) [PSYoungGen: 5411K->0K(76288K)] [ParOldGen: 8K->5217K(175104K)] 5419K->5217K(251392K), [Metaspace: 3182K->3182K(1056768K)], 0.0061707 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
  4. Heap
  5. PSYoungGen total 76288K, used 1966K [0x000000076b300000, 0x0000000770800000, 0x00000007c0000000)
  6. eden space 65536K, 3% used [0x000000076b300000,0x000000076b4eb9e8,0x000000076f300000)
  7. from space 10752K, 0% used [0x000000076f300000,0x000000076f300000,0x000000076fd80000)
  8. to space 10752K, 0% used [0x000000076fd80000,0x000000076fd80000,0x0000000770800000)
  9. ParOldGen total 175104K, used 5217K [0x00000006c1800000, 0x00000006cc300000, 0x000000076b300000)
  10. object space 175104K, 2% used [0x00000006c1800000,0x00000006c1d18618,0x00000006cc300000)
  11. Metaspace used 3192K, capacity 4496K, committed 4864K, reserved 1056768K
  12. class space used 346K, capacity 388K, committed 512K, reserved 1048576K

可以看出GC有回收, 说明虚拟机并不是通过引用计数法来判断对象是否存活的

根搜索算法

JAVA和C#都是通过根搜索算法来判定对象是否存活的
这个算法的基本思路是通过一系列的名为”GC Roots”的对象作为起始点, 从这些节点开始向下搜索, 搜索走过的路径称为引用链, 当一个对象到GC Roots没有任何引用链相连(GC Roots到这个对象不可达), 则证明此对象是不可用的.

GC Roots对象:**

  • 虚拟机栈(栈帧中的本地变量表)中引用的对象
  • 方法区中类静态属性引用的对象
  • 方法区中常量引用的对象
  • 本地方法栈中JNI(Native方法)引用的对象

引用类型:

  • 强引用, 类似”Object obj=new Object()”, 永远不会被回收
  • 软引用, 在系统OOM之前会把这些对象列入回收范围, 若回收后内存还不够, 则抛OOM
  • 弱引用, 下一次GC回收
  • 虚引用, 一个对象是否有虚引用的存在, 完全不会对其生存时间构成影响, 也无法通过虚引用来取得一个对象实例, 为一个对象设置虚引用关联的唯一目的是希望在这个对象在被回收时收到一个系统通知

生存还是死亡?

要宣布一个对象死亡, 至少要经历两次标记过程:
对象没有引用链==>第一次标记并进行一次筛选==>判断是否有必要执行finalize()方法:
否(finalize没有被覆盖或已调用一次);
是==>对象的finalize()被放置于低优先级的F-Queue队列去执行(虚拟机并不承诺会等待他运行结束)
==>GC对F-Queue中对象第二次小规模标记==>若对象在finalize方法中成功关联, 则依然存活, 否则被GC

  • 任何对象的finalize()方法只会被系统调用一次
  • 此方法运行代价高昂, 不确定性大, 无法保证各个对象的调用顺序, 因此不建议使用

回收方法区

方法区(HotSpot虚拟机中的永久代)的回收: 废弃常量和无用的类

垃圾收集算法

标记-清除算法

首先标记出所有需要回收的对象, 在标记完成后统一回收掉所有被标记的对象
image.png
缺点:

  • 效率低
  • 产生大量不连续的内存碎片

复制算法

将可用内存按容量划分为大小相等的两块, 每次只使用其中一块, 当这一块内存用完了, 就将存活的对象复制到另外一块上面, 然后再把已使用过的内存空间一次清理掉
image.png
缺点:

  • 内存缩小为原来一半

标记-整理算法

让所有存活的对象都向一端移动, 然后直接清理掉端边界以外的内存
image.png

分代收集算法

根据对象的存活周期的不同将内存划分为几块, JAVA堆分成新生代和老年代
新生代==>复制算法
老年代==>标记-清除算法, 标记-整理算法

垃圾收集器

HotSpot虚拟机1.6版Update22 包含的垃圾收集器
image.png

serial收集器

单线程收集器, 使用复制算法
image.png
缺点: 进行垃圾收集时, 必须暂停其他所有的工作线程
优点: 简单而高效

ParNew收集器

serial收集器的多线程版本, 使用复制算法
image.png

补充:

  • 并行(Parallel): 指多条垃圾收集器线程并行工作, 但此时用户线程依然处于等待状态
  • 并发(Concurrent): 指用户线程与垃圾收集器线程同时执行, 用户线程继续运行, 垃圾收集程序运行于另一个CPU上

Parallel Scavenge收集器

并行的多线程收集器, 使用复制算法, 不同之处在于:

  • 该收集器的目标是达到一个可控制的吞吐量

吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间)

  • 自适应调节策略

打开-XX:UseAdaptiveSizePolicy参数后, 虚拟机会自适应调节合适的停顿时间或最大吞吐量
image.png

Serial Old收集器

serial收集器的老年代版本, 单线程, 使用标记-整理算法, 图见上面

Parallel Old收集器

Parallel Scavenge收集器的老年代版本, 使用多线程标记-整理算法, 图见上面

CMS收集器

Concurrent Mark Sweep收集器是一种以获取最短回收停顿时间为目标的收集器, 基于标记-清除算法
image.png

  • 初始标记-仅标记GC Roots能直接关联到的对象
  • 并发标记-进行GC Root Tracing, 耗时长
  • 重新标记-修正并发标记期间因用户线程工作而产生的标记变动
  • 并发清除-耗时长

优点: 并发收集, 低停顿
缺点: 对CPU资源敏感, 并发阶段耗费资源; 无法处理浮动垃圾, 用户线程并发运行产生浮动垃圾; 标记-清除算法产生大量内存碎片

G1收集器

基于标记-整理算法, 可以非常精确的控制停顿
G1将堆划分为多个大小固定的独立区域, 并跟踪区域中的垃圾堆积程度, 在后台维护一个优先列表, 每次根据允许的收集时间, 优先回收垃圾最多的区域

内存回收与回收策略

对象优先在Eden分配

大多数情况下, 对象在新生代Eden区分配, 当Eden区没有足够的空间分配时, 虚拟机将发起一次Minor GC

补充:
新生代GC(Minor GC): 非常频繁, 回收速度较快
老年代GC(Major GC/Full GC): 速度比上一条慢10倍以上

测试代码:

  1. /**
  2. * Allocation
  3. * VM Args: -Xms20M -Xmx20M -Xmn10M -XX:SurvivorRatio=8 -XX:+PrintGCDetails
  4. * @author xinzhang
  5. * @author Shenzhen Greatonce Co Ltd
  6. * @version 2020/2/8
  7. */
  8. public class Allocation {
  9. private static final int _1MB = 1024 * 1024;
  10. public static void main(String[] args) {
  11. byte[] allocation1, allocation2, allocation3, allocation4;
  12. allocation1 = new byte[2 * _1MB];
  13. allocation2 = new byte[2 * _1MB];
  14. allocation3 = new byte[2 * _1MB];
  15. allocation4 = new byte[4 * _1MB];
  16. }
  17. }

运行结果:

  1. "C:\Program Files\Java\jdk1.8.0_221\bin\java.exe" -Xms20M -Xmx20M -Xmn10M -XX:SurvivorRatio=8 -XX:+PrintGCDetails "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2019.3.2\lib\idea_rt.jar=57504:C:\Program Files\JetBrains\IntelliJ IDEA 2019.3.2\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_221\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\rt.jar;C:\XZrepository\junit\junit\4.11\junit-4.11.jar;C:\XZrepository\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar;D:\巨益\参考项目\demo\xinzhang-demo\xinzhang-producer\target\test-classes;D:\巨益\参考项目\demo\xinzhang-demo\xinzhang-producer\target\classes;C:\XZrepository\com\greatonce\je-core\1.0.2-SNAPSHOT\je-core-1.0.2-20191216.071350-6.jar;C:\XZrepository\org\springframework\spring-context\5.1.5.RELEASE\spring-context-5.1.5.RELEASE.jar;C:\XZrepository\org\springframework\spring-aop\5.1.5.RELEASE\spring-aop-5.1.5.RELEASE.jar;C:\XZrepository\org\springframework\spring-beans\5.1.5.RELEASE\spring-beans-5.1.5.RELEASE.jar;C:\XZrepository\org\springframework\spring-expression\5.1.5.RELEASE\spring-expression-5.1.5.RELEASE.jar;C:\XZrepository\org\aspectj\aspectjweaver\1.9.2\aspectjweaver-1.9.2.jar;C:\XZrepository\org\springframework\spring-context-support\5.1.5.RELEASE\spring-context-support-5.1.5.RELEASE.jar;C:\XZrepository\org\springframework\spring-tx\5.1.5.RELEASE\spring-tx-5.1.5.RELEASE.jar;C:\XZrepository\org\springframework\amqp\spring-amqp\2.1.4.RELEASE\spring-amqp-2.1.4.RELEASE.jar;C:\XZrepository\org\springframework\retry\spring-retry\1.2.4.RELEASE\spring-retry-1.2.4.RELEASE.jar;C:\XZrepository\org\springframework\integration\spring-integration-redis\5.1.3.RELEASE\spring-integration-redis-5.1.3.RELEASE.jar;C:\XZrepository\org\springframework\integration\spring-integration-core\5.1.3.RELEASE\spring-integration-core-5.1.3.RELEASE.jar;C:\XZrepository\io\projectreactor\reactor-core\3.2.6.RELEASE\reactor-core-3.2.6.RELEASE.jar;C:\XZrepository\org\reactivestreams\reactive-streams\1.0.2\reactive-streams-1.0.2.jar;C:\XZrepository\com\alibaba\fastjson\1.2.60\fastjson-1.2.60.jar;C:\XZrepository\commons-codec\commons-codec\1.11\commons-codec-1.11.jar;C:\XZrepository\commons-io\commons-io\2.6\commons-io-2.6.jar;C:\XZrepository\org\mybatis\mybatis\3.4.6\mybatis-3.4.6.jar;C:\XZrepository\javax\servlet\javax.servlet-api\4.0.1\javax.servlet-api-4.0.1.jar;C:\XZrepository\org\quartz-scheduler\quartz\2.3.0\quartz-2.3.0.jar;C:\XZrepository\com\mchange\mchange-commons-java\0.2.11\mchange-commons-java-0.2.11.jar;C:\XZrepository\com\github\jsqlparser\jsqlparser\0.9.5\jsqlparser-0.9.5.jar;C:\XZrepository\com\alibaba\druid\1.1.10\druid-1.1.10.jar;C:\XZrepository\org\mybatis\mybatis-spring\1.3.2\mybatis-spring-1.3.2.jar;C:\XZrepository\mysql\mysql-connector-java\8.0.15\mysql-connector-java-8.0.15.jar;C:\XZrepository\org\slf4j\slf4j-api\1.7.25\slf4j-api-1.7.25.jar;C:\XZrepository\ch\qos\logback\logback-classic\1.2.3\logback-classic-1.2.3.jar;C:\XZrepository\ch\qos\logback\logback-core\1.2.3\logback-core-1.2.3.jar;C:\XZrepository\org\springframework\spring-jdbc\5.1.5.RELEASE\spring-jdbc-5.1.5.RELEASE.jar;C:\XZrepository\org\apache\httpcomponents\httpclient\4.5.7\httpclient-4.5.7.jar;C:\XZrepository\org\apache\httpcomponents\httpcore\4.4.11\httpcore-4.4.11.jar;C:\XZrepository\org\springframework\data\spring-data-redis\2.1.5.RELEASE\spring-data-redis-2.1.5.RELEASE.jar;C:\XZrepository\org\springframework\data\spring-data-keyvalue\2.1.5.RELEASE\spring-data-keyvalue-2.1.5.RELEASE.jar;C:\XZrepository\org\springframework\data\spring-data-commons\2.1.5.RELEASE\spring-data-commons-2.1.5.RELEASE.jar;C:\XZrepository\org\springframework\spring-oxm\5.1.5.RELEASE\spring-oxm-5.1.5.RELEASE.jar;C:\XZrepository\redis\clients\jedis\2.9.1\jedis-2.9.1.jar;C:\XZrepository\org\apache\commons\commons-pool2\2.6.1\commons-pool2-2.6.1.jar;C:\XZrepository\org\springframework\boot\spring-boot-starter-web\2.1.3.RELEASE\spring-boot-starter-web-2.1.3.RELEASE.jar;C:\XZrepository\org\springframework\boot\spring-boot-starter\2.1.3.RELEASE\spring-boot-starter-2.1.3.RELEASE.jar;C:\XZrepository\org\springframework\boot\spring-boot\2.1.3.RELEASE\spring-boot-2.1.3.RELEASE.jar;C:\XZrepository\org\springframework\boot\spring-boot-autoconfigure\2.1.3.RELEASE\spring-boot-autoconfigure-2.1.3.RELEASE.jar;C:\XZrepository\org\springframework\boot\spring-boot-starter-logging\2.1.3.RELEASE\spring-boot-starter-logging-2.1.3.RELEASE.jar;C:\XZrepository\org\apache\logging\log4j\log4j-to-slf4j\2.11.2\log4j-to-slf4j-2.11.2.jar;C:\XZrepository\org\apache\logging\log4j\log4j-api\2.11.2\log4j-api-2.11.2.jar;C:\XZrepository\org\slf4j\jul-to-slf4j\1.7.25\jul-to-slf4j-1.7.25.jar;C:\XZrepository\javax\annotation\javax.annotation-api\1.3.2\javax.annotation-api-1.3.2.jar;C:\XZrepository\org\yaml\snakeyaml\1.23\snakeyaml-1.23.jar;C:\XZrepository\org\springframework\boot\spring-boot-starter-json\2.1.3.RELEASE\spring-boot-starter-json-2.1.3.RELEASE.jar;C:\XZrepository\com\fasterxml\jackson\core\jackson-databind\2.9.8\jackson-databind-2.9.8.jar;C:\XZrepository\com\fasterxml\jackson\core\jackson-annotations\2.9.0\jackson-annotations-2.9.0.jar;C:\XZrepository\com\fasterxml\jackson\core\jackson-core\2.9.8\jackson-core-2.9.8.jar;C:\XZrepository\com\fasterxml\jackson\datatype\jackson-datatype-jdk8\2.9.8\jackson-datatype-jdk8-2.9.8.jar;C:\XZrepository\com\fasterxml\jackson\datatype\jackson-datatype-jsr310\2.9.8\jackson-datatype-jsr310-2.9.8.jar;C:\XZrepository\com\fasterxml\jackson\module\jackson-module-parameter-names\2.9.8\jackson-module-parameter-names-2.9.8.jar;C:\XZrepository\org\springframework\boot\spring-boot-starter-tomcat\2.1.3.RELEASE\spring-boot-starter-tomcat-2.1.3.RELEASE.jar;C:\XZrepository\org\apache\tomcat\embed\tomcat-embed-core\9.0.16\tomcat-embed-core-9.0.16.jar;C:\XZrepository\org\apache\tomcat\embed\tomcat-embed-el\9.0.16\tomcat-embed-el-9.0.16.jar;C:\XZrepository\org\apache\tomcat\embed\tomcat-embed-websocket\9.0.16\tomcat-embed-websocket-9.0.16.jar;C:\XZrepository\org\hibernate\validator\hibernate-validator\6.0.14.Final\hibernate-validator-6.0.14.Final.jar;C:\XZrepository\javax\validation\validation-api\2.0.1.Final\validation-api-2.0.1.Final.jar;C:\XZrepository\org\jboss\logging\jboss-logging\3.3.2.Final\jboss-logging-3.3.2.Final.jar;C:\XZrepository\com\fasterxml\classmate\1.4.0\classmate-1.4.0.jar;C:\XZrepository\org\springframework\spring-web\5.1.5.RELEASE\spring-web-5.1.5.RELEASE.jar;C:\XZrepository\org\springframework\spring-webmvc\5.1.5.RELEASE\spring-webmvc-5.1.5.RELEASE.jar;C:\XZrepository\org\apache\commons\commons-lang3\3.9\commons-lang3-3.9.jar;C:\XZrepository\org\springframework\boot\spring-boot-starter-test\2.1.3.RELEASE\spring-boot-starter-test-2.1.3.RELEASE.jar;C:\XZrepository\org\springframework\boot\spring-boot-test\2.1.3.RELEASE\spring-boot-test-2.1.3.RELEASE.jar;C:\XZrepository\org\springframework\boot\spring-boot-test-autoconfigure\2.1.3.RELEASE\spring-boot-test-autoconfigure-2.1.3.RELEASE.jar;C:\XZrepository\com\jayway\jsonpath\json-path\2.4.0\json-path-2.4.0.jar;C:\XZrepository\net\minidev\json-smart\2.3\json-smart-2.3.jar;C:\XZrepository\net\minidev\accessors-smart\1.2\accessors-smart-1.2.jar;C:\XZrepository\org\ow2\asm\asm\5.0.4\asm-5.0.4.jar;C:\XZrepository\junit\junit\4.12\junit-4.12.jar;C:\XZrepository\org\assertj\assertj-core\3.11.1\assertj-core-3.11.1.jar;C:\XZrepository\org\mockito\mockito-core\2.23.4\mockito-core-2.23.4.jar;C:\XZrepository\net\bytebuddy\byte-buddy\1.9.10\byte-buddy-1.9.10.jar;C:\XZrepository\net\bytebuddy\byte-buddy-agent\1.9.10\byte-buddy-agent-1.9.10.jar;C:\XZrepository\org\objenesis\objenesis\2.6\objenesis-2.6.jar;C:\XZrepository\org\hamcrest\hamcrest-library\1.3\hamcrest-library-1.3.jar;C:\XZrepository\org\skyscreamer\jsonassert\1.5.0\jsonassert-1.5.0.jar;C:\XZrepository\com\vaadin\external\google\android-json\0.0.20131108.vaadin1\android-json-0.0.20131108.vaadin1.jar;C:\XZrepository\org\springframework\spring-core\5.1.5.RELEASE\spring-core-5.1.5.RELEASE.jar;C:\XZrepository\org\springframework\spring-jcl\5.1.5.RELEASE\spring-jcl-5.1.5.RELEASE.jar;C:\XZrepository\org\springframework\spring-test\5.1.5.RELEASE\spring-test-5.1.5.RELEASE.jar;C:\XZrepository\org\xmlunit\xmlunit-core\2.6.2\xmlunit-core-2.6.2.jar;C:\XZrepository\javax\xml\bind\jaxb-api\2.3.1\jaxb-api-2.3.1.jar;C:\XZrepository\javax\activation\javax.activation-api\1.2.0\javax.activation-api-1.2.0.jar;C:\XZrepository\org\springframework\boot\spring-boot-starter-amqp\2.1.3.RELEASE\spring-boot-starter-amqp-2.1.3.RELEASE.jar;C:\XZrepository\org\springframework\spring-messaging\5.1.5.RELEASE\spring-messaging-5.1.5.RELEASE.jar;C:\XZrepository\org\springframework\amqp\spring-rabbit\2.1.4.RELEASE\spring-rabbit-2.1.4.RELEASE.jar;C:\XZrepository\com\rabbitmq\amqp-client\5.4.3\amqp-client-5.4.3.jar;C:\XZrepository\com\alibaba\transmittable-thread-local\2.10.2\transmittable-thread-local-2.10.2.jar;D:\巨益\参考项目\demo\xinzhang-demo\xinzhang-domain\target\classes;D:\巨益\参考项目\demo\xinzhang-demo\xinzhang-consumer\target\classes" top.xinzhang0618.producer.jvm.gc.Allocation
  2. [GC (Allocation Failure) [PSYoungGen: 7775K->1003K(9216K)] 7775K->5381K(19456K), 0.0055620 secs] [Times: user=0.08 sys=0.00, real=0.01 secs]
  3. Heap
  4. PSYoungGen total 9216K, used 7386K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
  5. eden space 8192K, 77% used [0x00000000ff600000,0x00000000ffc3bcb0,0x00000000ffe00000)
  6. from space 1024K, 98% used [0x00000000ffe00000,0x00000000ffefae48,0x00000000fff00000)
  7. to space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
  8. ParOldGen total 10240K, used 4378K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
  9. object space 10240K, 42% used [0x00000000fec00000,0x00000000ff046930,0x00000000ff600000)
  10. Metaspace used 3287K, capacity 4496K, committed 4864K, reserved 1056768K
  11. class space used 353K, capacity 388K, committed 512K, reserved 1048576K

分析:
参数: 堆一共20M, 年轻代10M, 老年代10M, 新生代Eden区:Survivor区=8:1;
运行结果看到新生代总共可用9216k, eden区8192k

大对象直接进入老年代

大对象是指需要连续内存空间的java对象

长期存活的对象将进入老年代

虚拟机给每个对象定义了一个对象年龄计算器, 如果对象在Eden出生并经过一次Minor GC后依然存活, 并且能被Survivor容纳的话, 会被移至Survivor空间, 年龄设为1, 在Survivor空间每熬过一次GC, 年龄加1, 默认15岁晋升到老年代

动态对象年龄判定

如果在Survivor空间中相同年龄所有对象大小的总和大于Survivor空间的一半, 大于等于该年龄的对象就可以直接进入老年代

空间分配担保

在发生Minor GC时, 虚拟机会检测之前每次晋升老年代的平均大小是否大于老年代的剩余空间大小, 如果大于, 将改为直接进行一次Full GC, 如果小于, 则查看HandlerPromotionFailure设置是否允许担保失败, 如果允许, 则只会进行Minor GC, 如果不允许, 则也要改为进行一次Full GC