运行时数据区域

image.png

  • 程序计数器

1.当前线程所执行的字节码的行号指示器
2.由于java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的, 因此, 为了线程切换后能够恢复到正确的执行位置, 每条线程都需要有一个独立的程序计数器, 这块内存区域”线程私有”
3.此内存区域是java虚拟机规范中没有规定任何OOM的区域

  • 虚拟机栈

1.线程私有, 生命周期与线程相同
2.描述的是java方法执行的内存模型, 每个方法被执行的同时都会创建一个栈帧用于存储局部变量表,操作栈, 动态链接,方法出口等信息, 每一个方法被调用直至执行完成的过程, 就对应着一个栈帧在虚拟机中从入栈到出栈的过程.
3.如果线程请求的栈深度大于虚拟机所允许的深度, 将抛出StackOverflow异常, 如果虚拟机栈可以动态拓展, 当拓展又无法申请到足够的内存时, 会抛出OutOfMemory异常

  • 本地方法栈

1.为虚拟机使用到的native方法服务
2.同虚拟机栈一样, 线程私有, 会抛两种异常

  • java堆

1.线程共享, 在虚拟机启动时创建
2.此内存区域的唯一目的是存放对象实例
3.如果在堆中没有内存完成实例分配, 并且堆也无法再拓展时,将会抛出OutOfMemory异常

  • 方法区

1.线程共享
2.用来存储已被虚拟机加载的类信息, 常量, 静态变量, 即时编译器编译后的代码等数据
3.垃圾收集行为较少出现, 内存回收主要针对常量池的回收以及对类型的卸载

  • 运行时常量池

1.属于方法区

  • 直接内存

1.直接内存不是虚拟机运行时数据区的一部分, 但这部分内存也会被频繁的使用

对象访问

  • 使用句柄

java堆中划分出一块内存作为句柄池, 用来存储对象的句柄地址; reference存储对象的句柄地址

image.png

  • 直接指针

reference中存储就是对象地址

image.png

比较:
1.使用句柄好处是reference中存储的稳定的句柄地址, 在对象被移动时只会改变句柄中的实例数据指针,而reference本身不需要被修改
2.使用直接指针的好处是节省了一次指针定位的时间开销

Sun HotSpot使用直接指针的方式进行对象访问

OutOfMemoryError异常

Java堆溢出

模拟java堆溢出: 不断的创建对象, 并保证GCRoots到对象之间有可达路径来避免垃圾回收机制来清除这些对象, 就会在对象数量达到最大堆的容量限制后产生内存溢出异常
OOM示例代码:

  1. /**
  2. * HeapOOM
  3. * VM Args: -Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError
  4. * @author xinzhang
  5. * @author Shenzhen Greatonce Co Ltd
  6. * @version 2020/1/15
  7. */
  8. public class HeapOOM {
  9. static class OOMObject {
  10. }
  11. public static void main(String[] args) {
  12. ArrayList<OOMObject> list = new ArrayList<>();
  13. while (true) {
  14. list.add(new OOMObject());
  15. }
  16. }
  17. }

JVM配置:

  1. -Xms20m
  2. -Xmx20m
  3. -Xmn10m
  4. -XX:+HeapDumpOnOutOfMemoryError
  5. -XX:HeapDumpPath=C:\Users\Administrator\Desktop\JVM
  6. -XX:+PrintGCDetails
  7. -XX:SurvivorRatio=8

idea配置图:
image.png
运行结果:

  1. "C:\Program Files\Java\jdk1.8.0_221\bin\java.exe" -Xms20m -Xmx20m -Xmn10m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=C:\Users\Administrator\Desktop\JVM -XX:+PrintGCDetails -XX:SurvivorRatio=8 "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2019.3.2\lib\idea_rt.jar=53896: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.HeapOOM
  2. [GC (Allocation Failure) [PSYoungGen: 7942K->1009K(9216K)] 7942K->4364K(19456K), 0.0053354 secs] [Times: user=0.13 sys=0.00, real=0.00 secs]
  3. [GC (Allocation Failure) [PSYoungGen: 9201K->1008K(9216K)] 12556K->9601K(19456K), 0.0087329 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
  4. [Full GC (Ergonomics) [PSYoungGen: 1008K->0K(9216K)] [ParOldGen: 8593K->9500K(10240K)] 9601K->9500K(19456K), [Metaspace: 3284K->3284K(1056768K)], 0.1735993 secs] [Times: user=0.63 sys=0.00, real=0.17 secs]
  5. [Full GC (Ergonomics) [PSYoungGen: 8192K->6143K(9216K)] [ParOldGen: 9500K->9205K(10240K)] 17692K->15348K(19456K), [Metaspace: 3286K->3286K(1056768K)], 0.1917405 secs] [Times: user=0.56 sys=0.00, real=0.19 secs]
  6. [Full GC (Ergonomics) [PSYoungGen: 7756K->7541K(9216K)] [ParOldGen: 9205K->9204K(10240K)] 16961K->16746K(19456K), [Metaspace: 3286K->3286K(1056768K)], 0.1603288 secs] [Times: user=0.97 sys=0.00, real=0.16 secs]
  7. [Full GC (Allocation Failure) [PSYoungGen: 7541K->7541K(9216K)] [ParOldGen: 9204K->9185K(10240K)] 16746K->16726K(19456K), [Metaspace: 3286K->3286K(1056768K)], 0.1741316 secs] [Times: user=0.95 sys=0.00, real=0.17 secs]
  8. java.lang.OutOfMemoryError: Java heap space
  9. Dumping heap to C:\Users\Administrator\Desktop\JVM\java_pid21336.hprof ...
  10. Heap dump file created [28730173 bytes in 0.102 secs]
  11. Heap
  12. PSYoungGen total 9216K, used 7901K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
  13. eden space 8192K, 96% used [0x00000000ff600000,0x00000000ffdb76b0,0x00000000ffe00000)
  14. from space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
  15. to space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
  16. ParOldGen total 10240K, used 9185K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
  17. object space 10240K, 89% used [0x00000000fec00000,0x00000000ff4f8408,0x00000000ff600000)
  18. Metaspace used 3445K, capacity 4500K, committed 4864K, reserved 1056768K
  19. class space used 367K, capacity 388K, committed 512K, reserved 1048576K
  20. Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
  21. at java.util.Arrays.copyOf(Arrays.java:3210)
  22. at java.util.Arrays.copyOf(Arrays.java:3181)
  23. at java.util.ArrayList.grow(ArrayList.java:265)
  24. at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:239)
  25. at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:231)
  26. at java.util.ArrayList.add(ArrayList.java:462)
  27. at top.xinzhang0618.producer.jvm.HeapOOM.main(HeapOOM.java:21)

解决思路
1.通过内存映像分析工具, 对dump出来的堆转储快照进行分析, 重点确认内存中的对象是否是必要的, 也就是先分清是内存泄漏还是内存溢出;
2.若是内存泄漏, 可进一步查看泄漏对象到GCRoots的引用链. 于是就能找到泄漏对象是通过怎样的路径与GCRoots相关联并导致垃圾回收期无法自动回收的, 即可定位到泄漏的代码的位置;
3.若不存在泄漏, 则应该检查虚拟机的堆参数, 与机器物理内存对比是否还可以调大, 从代码上检查是否存在某些对象生命周期过长, 持有状态时间过长的情况, 尝试减少程序运行期间的内存消耗.
**

虚拟机栈和本地方法栈溢出

HotSpot虚拟机中不区分虚拟机栈和本地方法栈, 栈容量只由-Xss参数设定
模拟栈内存溢出(StackOverflowError)

  • 如果线程请求的栈深度大于虚拟机所允许的最大深度, 会抛出StackOverflowError异常
  • 如果虚拟机在拓展栈时无法申请到足够的内存空间, 则会抛出OutOfMemoryError异常

单线程条件下, 使用-Xss参数减少栈内存容量, 并定义大量的本地变量, 增加方法帧中本地变量表的长度;
可以产生SOF异常, 但无法产生OOM异常
SOF示例代码: (JVM配置: -Xss128k)

  1. /**
  2. * JavaVMStackSOF
  3. * VM Args: -Xss128k
  4. * @author xinzhang
  5. * @author Shenzhen Greatonce Co Ltd
  6. * @version 2020/2/6
  7. */
  8. public class JavaVMStackSOF {
  9. private int stackLength = 1;
  10. public void stackLeak() {
  11. stackLength++;
  12. stackLeak();
  13. }
  14. public static void main(String[] args) {
  15. JavaVMStackSOF oom = new JavaVMStackSOF();
  16. try {
  17. oom.stackLeak();
  18. } catch (Throwable e) {
  19. System.out.println("stack length: " + oom.stackLength);
  20. throw e;
  21. }
  22. }
  23. }
  24. 运行结果:
  25. "C:\Program Files\Java\jdk1.8.0_221\bin\java.exe" -Xss128k "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2019.3.2\lib\idea_rt.jar=60211: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.JavaVMStackSOF
  26. stack length: 1000
  27. Exception in thread "main" java.lang.StackOverflowError
  28. at top.xinzhang0618.producer.jvm.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:15)

在单个线程下, 无论是栈帧太大, 还是虚拟机容量太小, 当内存无法分配时, 都会抛出SOF

多线程条件下,
操作系统内存分配示例: 2G=【Xmx(最大堆容量)】+【MaxPermSize(最大方法区容量)】+【程序计数器(消耗少, 忽略)】+【虚拟机进程本身耗费内存(忽略)】+【虚拟机栈、本地方法栈】
且, 虚拟机栈、本地方法栈=线程的栈容量*线程数量
若建立过多线程导致内存溢出, 可以通过减少最大堆容量和减少栈容量的方式来换取更多的线程
OOM示例代码:(这个看看就好, 就不要轻易运行了)

  1. /**
  2. * JavaVMStackOOM
  3. * VM Args: -Xss2m
  4. *
  5. * @author xinzhang
  6. * @author Shenzhen Greatonce Co Ltd
  7. * @version 2020/2/6
  8. */
  9. public class JavaVMStackOOM {
  10. private void dontStop() {
  11. while (true) {
  12. }
  13. }
  14. public void stackLeakByThread() {
  15. while (true) {
  16. Thread thread = new Thread(new Runnable() {
  17. @Override
  18. public void run() {
  19. dontStop();
  20. }
  21. });
  22. thread.start();
  23. }
  24. }
  25. public static void main(String[] args) {
  26. JavaVMStackOOM oom = new JavaVMStackOOM();
  27. oom.stackLeakByThread();
  28. }
  29. }

运行时常量池溢出

String.intern()—>向运行时常量池中添加内容, 池中有则返回对象, 没有则添加后返回引用
字符串常量池在方法区, 因此可以通过-XX:PermSize和-XX:MaxPermSize限制方法区的大小, 从而间接限制其中常量池的容量
常量池OOM示例代码:(但是实测JDK8会一直运行, 不抛OOM)

  1. /**
  2. * RuntimeConstantPoolOOM
  3. * VM Args: -XX:PermSize=10m -XX:MaxPermSize=10m
  4. *
  5. * @author xinzhang
  6. * @author Shenzhen Greatonce Co Ltd
  7. * @version 2020/2/6
  8. */
  9. public class RuntimeConstantPoolOOM {
  10. public static void main(String[] args) {
  11. // 使用List保持引用, 避免GC
  12. ArrayList<String> list = new ArrayList<>();
  13. int i = 0;
  14. while (true) {
  15. list.add(String.valueOf(i++).intern());
  16. }
  17. }
  18. }

方法区溢出

方法区用于存放class的相关信息, 如类名, 访问修饰符, 常量池, 字段描述, 方法描述等.
模拟方法区溢出的基本记录是运行时产生大量的类去填满方法区
方法区OOM示例代码:(实测JDK8一直运行)

  1. /**
  2. * JavaMethodAreaOOM
  3. * VM Args: -XX:PermSize=10m -XX:MaxPermSize=10m
  4. * @author xinzhang
  5. * @author Shenzhen Greatonce Co Ltd
  6. * @version 2020/2/6
  7. */
  8. public class JavaMethodAreaOOM {
  9. public static void main(String[] args) {
  10. while (true) {
  11. Enhancer enhancer = new Enhancer();
  12. enhancer.setSuperclass(OOMObject.class);
  13. enhancer.setUseCache(false);
  14. enhancer.setCallback(new MethodInterceptor() {
  15. @Override
  16. public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
  17. return methodProxy.invokeSuper(objects, args);
  18. }
  19. });
  20. enhancer.create();
  21. }
  22. }
  23. static class OOMObject {
  24. }
  25. }

在经常动态生成大量class的应用中, 需要特别注意类的回收状况

本机直接内存溢出

DirectMemory可以通过-XX:MaxDirectMemorySize指定, 若不指定, 则默认与-Xmx指定值一样
示例代码:(未测)

  1. /**
  2. * DirectMemoryOOM
  3. * VM Args:-Xmx20m -XX:MaxDirectMemorySize=10M
  4. * @author xinzhang
  5. * @author Shenzhen Greatonce Co Ltd
  6. * @version 2020/2/6
  7. */
  8. public class DirectMemoryOOM {
  9. private static final int _1MB = 1024 * 1024;
  10. public static void main(String[] args) throws IllegalAccessException {
  11. Field unSafeField = Unsafe.class.getDeclaredFields()[0];
  12. unSafeField.setAccessible(true);
  13. Unsafe unsafe = (Unsafe) unSafeField.get(null);
  14. while (true) {
  15. unsafe.allocateMemory(_1MB);
  16. }
  17. }
  18. }