打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
第1课:实战演示jvm内存四大类型问题:heap、stack、contant、directmemory等

JVM前置知识

零、参数设置:

   设置VM options:

 -verbose:gc -Xms10M -Xmx10M -XX:MaxDirectMemorySize=5M -Xss228K -XX:+PrintGCDetails

  JVM启动参数共分为三类:
      1、标准参数(-),所有的JVM实现都必须实现这些参数的功能,而且向后兼容。例如:-verbose:class(输出jvm载入类的相关信息,当jvm报告说找不到类或者类冲突时可此进行诊断);-verbose:gc(输出每次GC的相关情况);-verbose:jni(输出native方法调用的相关情况,一般用于诊断jni调用错误信息)。
      2、非标准参数(-X),默认jvm实现这些参数的功能,但是并不保证所有jvm实现都满足,且不保证向后兼容。例如:-Xms512m;-Xmx512m;-Xmn200m;-Xss128k;-Xloggc:file(与-verbose:gc功能类似,只是将每次GC事件的相关情况记录到一个文件中,文件的位置最好在本地,以避免网络的潜在问题。若与verbose命令同时出现在命令行中,则以-Xloggc为准)。
      3、非Stable参数(-XX),此类参数各个jvm实现会有所不同,将来可能会随时取消,需要慎重使用。例如:-XX:PermSize=64m;-XX:MaxPermSize=512m。


  参数含义:
    -verbose:gc  输出虚拟机中GC的详细情况
    -Xms  JVM启动时申请的初始Heap值,默认为操作系统物理内存的1/64但小于1G。默认当空余堆内存大于70%时,JVM会减小heap的大小到-Xms指定的大小,可通过-XX:MaxHeapFreeRation=来指定这个比列。Server端JVM最好将-Xms和-Xmx设为相同值,避免每次垃圾回收完成后JVM重新分配内存;开发测试机JVM可以保留默认值。(例如:-Xms4g)
    -Xmx  JVM可申请的最大Heap值,默认值为物理内存的1/4但小于1G,默认当空余堆内存小于40%时,JVM会增大Heap到-Xmx指定的大小,可通过-XX:MinHeapFreeRation=来指定这个比列。最佳设值应该视物理内存大小及计算机内其他内存开销而定。(例如:-Xmx4g)
    -XX  JVM初始分配的非堆内存
    -Xss   Java每个线程的Stack大小。JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。根据应用的线程所需内存大小进行调整。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。(例如:-Xss1024K)

  查看更多参数含义:JVM常用内存参数配置

一、HeapOutOfMemory

    1.问题描述:

  1. [Full GC (Ergonomics) [PSYoungGen: 944K->890K(2048K)] [ParOldGen: 7129K->7129K(7168K)] 8074K->8019K(9216K), [Metaspace: 3357K->3357K(1056768K)], 0.1213761 secs] [Times: user=0.27 sys=0.00, real=0.12 secs]
  2. [Full GC (Allocation Failure) Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
  3. at java.util.Arrays.copyOf(Arrays.java:3210)
  4. at java.util.Arrays.copyOf(Arrays.java:3181)
  5. at java.util.ArrayList.grow(ArrayList.java:265)
  6. at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:239)
  7. at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:231)
  8. at java.util.ArrayList.add(ArrayList.java:462)
  9. at JVM.HeapOutOfMemory.main(HeapOutOfMemory.java:20)
  10. [PSYoungGen: 890K->890K(2048K)] [ParOldGen: 7129K->7129K(7168K)] 8019K->8019K(9216K), [Metaspace: 3357K->3357K(1056768K)], 0.0858551 secs] [Times: user=0.24 sys=0.00, real=0.09 secs]
  11. Heap
  12. PSYoungGen total 2048K, used 939K [0x00000000ffd00000, 0x0000000100000000, 0x0000000100000000)
  13. eden space 1024K, 91% used [0x00000000ffd00000,0x00000000ffdeaeb0,0x00000000ffe00000)
  14. from space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
  15. to space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
  16. ParOldGen total 7168K, used 7129K [0x00000000ff600000, 0x00000000ffd00000, 0x00000000ffd00000)
  17. object space 7168K, 99% used [0x00000000ff600000,0x00000000ffcf64c0,0x00000000ffd00000)
  18. Metaspace used 3388K, capacity 4500K, committed 4864K, reserved 1056768K
  19. class space used 352K, capacity 388K, committed 512K, reserved 1048576K


    2.堆(Heap)和非堆(Non-heap)内存
        a)按照官方的说法:“Java 虚拟机具有一个堆,堆是运行时数据区域,所有类实例和数组的内存均从此处分配。堆是在 Java 虚拟机启动时创建的。”,“在JVM中堆之外的内存称为非堆内存(Non-heap memory)”。
        b)可以看出JVM主要管理两种类型的内存:堆和非堆。简单来说堆就是Java代码可用的内存,是留给开发人员使用的;非堆就是JVM留给自己用的,所以方法区、JVM内部处理或优化所需的内存(如JIT编译后的代码缓存)、每个类结构(如运行时常数池、字段和方法数据)以及方法和构造方法的代码都在非堆内存中。
    3.堆内存分配
        a)JVM初始分配的堆内存由-Xms指定,默认是物理内存的1/64;JVM最大分配的堆内存由-Xmx指定,默认是物理内存的1/4。默认空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制;空余堆内存大于70%时,JVM会减少堆直到-Xms的最小限制。因此服务器一般设置-Xms、-Xmx 相等以避免在每次GC 后调整堆的大小。
        b)说明:如果-Xmx 不指定或者指定偏小,应用可能会导致java.lang.OutOfMemory错误,此错误来自JVM,不是Throwable的,无法用try...catch捕捉。
    4.非堆内存分配
        a)JVM使用-XX:PermSize设置非堆内存初始值,默认是物理内存的1/64;由XX:MaxPermSize设置最大非堆内存的大小,默认是物理内存的1/4。(还有一说:MaxPermSize缺省值和-server -client选项相关,-server选项下默认MaxPermSize为64m,-client选项下默认MaxPermSize为32m。这个我没有实验。)
    5.演示案例代码:

  1. package JVM;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. /**
  5. * FileName: HeapOutOfMemory
  6. * Author: hadoop
  7. * Email: 3165845957@qq.com
  8. * Date: 18-10-27 下午9:45
  9. * Description:一般情况下,heap中只存在对象
  10. */
  11. class Person{}
  12. public class HeapOutOfMemory {
  13. public static void main(String[] args){
  14. System.out.println("HeapOutOfMemory");
  15. List<Person> persons = new ArrayList<Person>();
  16. int counter = 0;
  17. while (true){
  18. persons.add(new Person());
  19. System.out.println("Instance: "+ (++counter));
  20. }
  21. }
  22. }

 

二、StackOverFlow

    1.问题描述

  1. [GC (Allocation Failure) [PSYoungGen: 2048K->496K(2560K)] 2048K->613K(9728K), 0.0490609 secs] [Times: user=0.00 sys=0.00, real=0.05 secs]
  2. [GC (Allocation Failure) [PSYoungGen: 2544K->512K(2560K)] 2661K->1063K(9728K), 0.0040749 secs] [Times: user=0.01 sys=0.00, real=0.01 secs]
  3. [GC (Allocation Failure) [PSYoungGen: 2560K->512K(2560K)] 3111K->1696K(9728K), 0.0031524 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
  4. StackOverFlow
  5. Exception in thread "main" java.lang.StackOverflowError
  6. at JVM.StackOverFlow.count(StackOverFlow.java:15)
  7. at JVM.StackOverFlow.count(StackOverFlow.java:15)
  8. at JVM.StackOverFlow.count(StackOverFlow.java:15)
  9. at JVM.StackOverFlow.count(StackOverFlow.java:15)
  10. Heap
  11. PSYoungGen total 2560K, used 2533K [0x00000000ffd00000, 0x0000000100000000, 0x0000000100000000)
  12. eden space 2048K, 98% used [0x00000000ffd00000,0x00000000ffef94a8,0x00000000fff00000)
  13. from space 512K, 100% used [0x00000000fff00000,0x00000000fff80000,0x00000000fff80000)
  14. to space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
  15. ParOldGen total 7168K, used 1184K [0x00000000ff600000, 0x00000000ffd00000, 0x00000000ffd00000)
  16. object space 7168K, 16% used [0x00000000ff600000,0x00000000ff728048,0x00000000ffd00000)
  17. Metaspace used 3379K, capacity 4496K, committed 4864K, reserved 1056768K
  18. class space used 352K, capacity 388K, committed 512K, reserved 1048576K

    2. 在java虚拟机规范中,定义了在虚拟机栈和本地方法栈中会产生StackOverflowError。
    3. 虚拟机栈和本地方法栈一般就是我们说的Java内存管理中的栈。
    4. 虚拟机栈和本地方法栈是线程之间的独立内存,每一个线程在创建时,Java虚拟机都会给该线程分配一块独立的内存区域,一般将此内存区域划分为虚拟机栈,本地方法栈,程序计数器。
    5. 虚拟机栈中存储了方法执行时相关信息,每个方法在调用时都会在虚拟机栈中创建一个方法帧,方法帧中包含了局部变量,操作数,动态链接,方法出口等信息。
    6. 本地方法栈和虚拟机栈基本相同,不同的是本地方法栈是针对线程中的native方法.
    7. 程序计数器包含了一个程序执行指针,指向了字节码当前执行的行数。
    8. 在java虚拟机规范中,虚拟机栈和本地方法栈都会出现StackOverflowError和OutofMemoryError,程序计数器是Java虚拟机中唯一一块不会产生error的内存区域。
    9. StackOverflowError代表的是,当栈深度超过虚拟机分配给线程的栈大小时就会出现此error。
    10. OutofMemoryError代表的是,当再申请新的内存时,虚拟机分配给线程的内存大小中无法再分配新的内存,就会出现此error。
    11. -Xss1024M虚拟机参数可以设置虚拟机分配给每个线程的内存大小,程序计数器占很小的内存(可以忽略),一般此内存和线程栈内存相等。
    12. 在HotSpot虚拟机中,是将虚拟机栈和本地方法栈合二为一的
    13. 演示案例代码:

  1. package JVM;
  2. /**
  3. * FileName: StackOverFlow
  4. * Author: hadoop
  5. * Email: 3165845957@qq.com
  6. * Date: 18-10-27 下午10:00
  7. * Description:
  8. */
  9. public class StackOverFlow {
  10. private int counter;
  11. public void count(){
  12. counter++;
  13. count();
  14. }
  15. public static void main(String[] agrs){
  16. System.out.println("StackOverFlow");
  17. StackOverFlow stackOverFlow = new StackOverFlow();
  18. try{
  19. stackOverFlow.count();
  20. }catch (Exception e){
  21. e.printStackTrace();
  22. throw e;
  23. }
  24. }
  25. }

三、JVM:ContantOutOfMemory

    1.问题描述:

  1. [GC (Allocation Failure) [PSYoungGen: 2048K->496K(2560K)] 2048K->653K(9728K), 0.0026792 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
  2. [GC (Allocation Failure) [PSYoungGen: 2544K->496K(2560K)] 2701K->1110K(9728K), 0.0026725 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
  3. [GC (Allocation Failure) [PSYoungGen: 2544K->496K(2560K)] 3158K->1732K(9728K), 0.0036126 secs] [Times: user=0.01 sys=0.00, real=0.01 secs]
  4. [GC (Allocation Failure) [PSYoungGen: 2544K->496K(2560K)] 3780K->2950K(9728K), 0.0060662 secs] [Times: user=0.01 sys=0.00, real=0.01 secs]
  5. [GC (Allocation Failure) [PSYoungGen: 2296K->496K(2560K)] 4750K->4615K(9728K), 0.0064617 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]
  6. [GC (Allocation Failure) [PSYoungGen: 2544K->496K(1536K)] 6663K->6384K(8704K), 0.0070902 secs] [Times: user=0.02 sys=0.00, real=0.01 secs]
  7. [Full GC (Ergonomics) [PSYoungGen: 496K->0K(1536K)] [ParOldGen: 5888K->5633K(7168K)] 6384K->5633K(8704K), [Metaspace: 3312K->3312K(1056768K)], 0.1418446 secs] [Times: user=0.22 sys=0.01, real=0.14 secs]
  8. [GC (Allocation Failure) [PSYoungGen: 1024K->1024K(2048K)] 6657K->6665K(9216K), 0.0051471 secs] [Times: user=0.02 sys=0.00, real=0.01 secs]
  9. [Full GC (Ergonomics) [PSYoungGen: 1024K->0K(2048K)] [ParOldGen: 5641K->6289K(7168K)] 6665K->6289K(9216K), [Metaspace: 3322K->3322K(1056768K)], 0.0962849 secs] [Times: user=0.22 sys=0.00, real=0.10 secs]
  10. [Full GC (Ergonomics) [PSYoungGen: 1024K->511K(2048K)] [ParOldGen: 6914K->7009K(7168K)] 7938K->7520K(9216K), [Metaspace: 3322K->3322K(1056768K)], 0.1231337 secs] [Times: user=0.27 sys=0.00, real=0.12 secs]
  11. [Full GC (Ergonomics) [PSYoungGen: 1024K->1023K(2048K)] [ParOldGen: 7009K->7009K(7168K)] 8033K->8032K(9216K), [Metaspace: 3322K->3322K(1056768K)], 0.0475116 secs] [Times: user=0.09 sys=0.00, real=0.05 secs]
  12. [Full GC (Ergonomics) [PSYoungGen: 1024K->1023K(2048K)] [ParOldGen: 7009K->7009K(7168K)] 8033K->8033K(9216K), [Metaspace: 3322K->3322K(1056768K)], 0.0920466 secs] [Times: user=0.11 sys=0.00, real=0.09 secs]
  13. [Full GC (Ergonomics) [PSYoungGen: 1023K->1023K(2048K)] [ParOldGen: 7009K->7009K(7168K)] 8033K->8033K(9216K), [Metaspace: 3322K->3322K(1056768K)], 0.0540682 secs] [Times: user=0.11 sys=0.00, real=0.06 secs]
  14. [Full GC (Ergonomics) [PSYoungGen: 1023K->1023K(2048K)] [ParOldGen: 7010K->7010K(7168K)] 8034K->8034K(9216K), [Metaspace: 3322K->3322K(1056768K)], 0.0566520 secs] [Times: user=0.09 sys=0.00, real=0.05 secs]
  15. [Full GC (Ergonomics) [PSYoungGen: 1023K->1023K(2048K)] [ParOldGen: 7012K->7012K(7168K)] 8036K->8036K(9216K), [Metaspace: 3322K->3322K(1056768K)], 0.0477663 secs] [Times: user=0.09 sys=0.00, real=0.05 secs]
  16. [Full GC (Ergonomics) [PSYoungGen: 1023K->1023K(2048K)] [ParOldGen: 7014K->7014K(7168K)] 8038K->8038K(9216K), [Metaspace: 3322K->3322K(1056768K)], 0.0495801 secs] [Times: user=0.11 sys=0.00, real=0.05 secs]
  17. [Full GC (Ergonomics) [PSYoungGen: 1023K->1023K(2048K)] [ParOldGen: 7016K->7016K(7168K)] 8040K->8040K(9216K), [Metaspace: 3322K->3322K(1056768K)], 0.0487939 secs] [Times: user=0.10 sys=0.00, real=0.05 secs]
  18. [Full GC (Ergonomics) [PSYoungGen: 1023K->1023K(2048K)] [ParOldGen: 7017K->7017K(7168K)] 8041K->8041K(9216K), [Metaspace: 3322K->3322K(1056768K)], 0.0695323 secs] [Times: user=0.08 sys=0.00, real=0.07 secs]
  19. [Full GC (Ergonomics) [PSYoungGen: 1023K->1023K(2048K)] [ParOldGen: 7019K->7019K(7168K)] 8043K->8043K(9216K), [Metaspace: 3322K->3322K(1056768K)], 0.0549496 secs] [Times: user=0.11 sys=0.00, real=0.06 secs]
  20. [Full GC (Ergonomics) [PSYoungGen: 1023K->1023K(2048K)] [ParOldGen: 7021K->7021K(7168K)] 8045K->8045K(9216K), [Metaspace: 3322K->3322K(1056768K)], 0.0677872 secs] [Times: user=0.12 sys=0.00, real=0.06 secs]
  21. [Full GC (Ergonomics) [PSYoungGen: 1023K->1023K(2048K)] [ParOldGen: 7023K->7023K(7168K)] 8047K->8047K(9216K), [Metaspace: 3322K->3322K(1056768K)], 0.0775448 secs] [Times: user=0.11 sys=0.00, real=0.08 secs]
  22. [Full GC (Ergonomics) [PSYoungGen: 1023K->1023K(2048K)] [ParOldGen: 7024K->7014K(7168K)] 8048K->8038K(9216K), [Metaspace: 3322K->3322K(1056768K)], 0.0715184 secs] [Times: user=0.13 sys=0.00, real=0.07 secs]
  23. [Full GC (Ergonomics) [PSYoungGen: 1023K->1023K(2048K)] [ParOldGen: 7016K->7016K(7168K)] 8040K->8040K(9216K), [Metaspace: 3322K->3322K(1056768K)], 0.0444939 secs] [Times: user=0.11 sys=0.00, real=0.04 secs]
  24. [Full GC (Ergonomics) [PSYoungGen: 1023K->1023K(2048K)] [ParOldGen: 7018K->7018K(7168K)] 8042K->8042K(9216K), [Metaspace: 3322K->3322K(1056768K)], 0.0597435 secs] [Times: user=0.13 sys=0.00, real=0.06 secs]
  25. [Full GC (Ergonomics) [PSYoungGen: 1023K->1023K(2048K)] [ParOldGen: 7019K->7019K(7168K)] 8043K->8043K(9216K), [Metaspace: 3322K->3322K(1056768K)], 0.0584104 secs] [Times: user=0.13 sys=0.00, real=0.06 secs]
  26. [Full GC (Ergonomics) [PSYoungGen: 1023K->1023K(2048K)] [ParOldGen: 7021K->7021K(7168K)] 8045K->8045K(9216K), [Metaspace: 3322K->3322K(1056768K)], 0.0617825 secs] [Times: user=0.12 sys=0.01, real=0.06 secs]
  27. [Full GC (Ergonomics) [PSYoungGen: 1023K->1023K(2048K)] [ParOldGen: 7023K->7023K(7168K)] 8047K->8047K(9216K), [Metaspace: 3322K->3322K(1056768K)], 0.0648371 secs] [Times: user=0.11 sys=0.00, real=0.06 secs]
  28. [Full GC (Ergonomics) [PSYoungGen: 1023K->1023K(2048K)] [ParOldGen: 7025K->7025K(7168K)] 8049K->8049K(9216K), [Metaspace: 3322K->3322K(1056768K)], 0.0520684 secs] [Times: user=0.11 sys=0.00, real=0.06 secs]
  29. [Full GC (Ergonomics) [PSYoungGen: 1023K->1023K(2048K)] [ParOldGen: 7026K->7026K(7168K)] 8050K->8050K(9216K), [Metaspace: 3322K->3322K(1056768K)], 0.0701839 secs] [Times: user=0.09 sys=0.00, real=0.07 secs]
  30. [Full GC (Ergonomics) [PSYoungGen: 1023K->1023K(2048K)] [ParOldGen: 7028K->7019K(7168K)] 8052K->8043K(9216K), [Metaspace: 3322K->3322K(1056768K)], 0.1053345 secs] [Times: user=0.20 sys=0.00, real=0.10 secs]
  31. [Full GC (Ergonomics) [PSYoungGen: 1023K->1023K(2048K)] [ParOldGen: 7020K->7020K(7168K)] 8044K->8044K(9216K), [Metaspace: 3322K->3322K(1056768K)], 0.0581744 secs] [Times: user=0.09 sys=0.00, real=0.05 secs]
  32. [Full GC (Ergonomics) [PSYoungGen: 1023K->1023K(2048K)] [ParOldGen: 7022K->7022K(7168K)] 8046K->8046K(9216K), [Metaspace: 3322K->3322K(1056768K)], 0.0901339 secs] [Times: user=0.11 sys=0.00, real=0.09 secs]
  33. [Full GC (Ergonomics) [PSYoungGen: 1023K->1023K(2048K)] [ParOldGen: 7024K->7024K(7168K)] 8048K->8048K(9216K), [Metaspace: 3322K->3322K(1056768K)], 0.0673643 secs] [Times: user=0.09 sys=0.01, real=0.07 secs]
  34. [Full GC (Ergonomics) [PSYoungGen: 1023K->1023K(2048K)] [ParOldGen: 7026K->7018K(7168K)] 8050K->8042K(9216K), [Metaspace: 3322K->3322K(1056768K)], 0.1752974 secs] [Times: user=0.22 sys=0.01, real=0.17 secs]
  35. [Full GC (Ergonomics) [PSYoungGen: 1023K->1023K(2048K)] [ParOldGen: 7020K->7020K(7168K)] 8044K->8044K(9216K), [Metaspace: 3322K->3322K(1056768K)], 0.0569987 secs] [Times: user=0.10 sys=0.00, real=0.06 secs]
  36. [Full GC (Ergonomics) [PSYoungGen: 1023K->1023K(2048K)] [ParOldGen: 7022K->7022K(7168K)] 8046K->8046K(9216K), [Metaspace: 3322K->3322K(1056768K)], 0.0758067 secs] [Times: user=0.09 sys=0.00, real=0.08 secs]
  37. [Full GC (Ergonomics) [PSYoungGen: 1023K->1023K(2048K)] [ParOldGen: 7024K->7024K(7168K)] 8048K->8048K(9216K), [Metaspace: 3322K->3322K(1056768K)], 0.0953409 secs] [Times: user=0.12 sys=0.00, real=0.09 secs]
  38. [Full GC (Ergonomics) [PSYoungGen: 1023K->1023K(2048K)] [ParOldGen: 7025K->7025K(7168K)] 8049K->8049K(9216K), [Metaspace: 3322K->3322K(1056768K)], 0.1097731 secs] [Times: user=0.13 sys=0.00, real=0.11 secs]
  39. [Full GC (Ergonomics) [PSYoungGen: 1023K->1023K(2048K)] [ParOldGen: 7027K->7027K(7168K)] 8051K->8051K(9216K), [Metaspace: 3322K->3322K(1056768K)], 0.0865261 secs] [Times: user=0.12 sys=0.00, real=0.09 secs]
  40. [Full GC (Ergonomics) [PSYoungGen: 1023K->1023K(2048K)] [ParOldGen: 7029K->7029K(7168K)] 8053K->8053K(9216K), [Metaspace: 3322K->3322K(1056768K)], 0.0862111 secs] [Times: user=0.11 sys=0.00, real=0.09 secs]
  41. [Full GC (Ergonomics) [PSYoungGen: 1023K->1023K(2048K)] [ParOldGen: 7031K->7031K(7168K)] 8055K->8055K(9216K), [Metaspace: 3322K->3322K(1056768K)], 0.0693013 secs] [Times: user=0.10 sys=0.00, real=0.07 secs]
  42. [Full GC (Ergonomics) [PSYoungGen: 1023K->1023K(2048K)] [ParOldGen: 7032K->7032K(7168K)] 8056K->8056K(9216K), [Metaspace: 3322K->3322K(1056768K)], 0.0580946 secs] [Times: user=0.12 sys=0.00, real=0.06 secs]
  43. [Full GC (Ergonomics) [PSYoungGen: 1023K->1023K(2048K)] [ParOldGen: 7034K->7034K(7168K)] 8058K->8058K(9216K), [Metaspace: 3322K->3322K(1056768K)], 0.0684948 secs] [Times: user=0.11 sys=0.00, real=0.06 secs]
  44. [Full GC (Ergonomics) [PSYoungGen: 1023K->1023K(2048K)] [ParOldGen: 7036K->7036K(7168K)] 8060K->8060K(9216K), [Metaspace: 3322K->3322K(1056768K)], 0.1060725 secs] [Times: user=0.10 sys=0.00, real=0.11 secs]
  45. [Full GC (Ergonomics) [PSYoungGen: 1023K->1023K(2048K)] [ParOldGen: 7038K->7038K(7168K)] 8062K->8062K(9216K), [Metaspace: 3322K->3322K(1056768K)], 0.0869178 secs] [Times: user=0.12 sys=0.00, real=0.09 secs]
  46. [Full GC (Ergonomics) [PSYoungGen: 1023K->1023K(2048K)] [ParOldGen: 7039K->7039K(7168K)] 8063K->8063K(9216K), [Metaspace: 3322K->3322K(1056768K)], 0.0939717 secs] [Times: user=0.13 sys=0.00, real=0.09 secs]
  47. [Full GC (Ergonomics) [PSYoungGen: 1023K->1023K(2048K)] [ParOldGen: 7041K->7041K(7168K)] 8065K->8065K(9216K), [Metaspace: 3322K->3322K(1056768K)], 0.0907118 secs] [Times: user=0.10 sys=0.01, real=0.09 secs]
  48. [Full GC (Ergonomics) [PSYoungGen: 1023K->1023K(2048K)] [ParOldGen: 7043K->7043K(7168K)] 8067K->8067K(9216K), [Metaspace: 3322K->3322K(1056768K)], 0.0598796 secs] [Times: user=0.08 sys=0.00, real=0.06 secs]
  49. [Full GC (Ergonomics) [PSYoungGen: 1023K->1023K(2048K)] [ParOldGen: 7045K->7045K(7168K)] 8069K->8069K(9216K), [Metaspace: 3322K->3322K(1056768K)], 0.0761027 secs] [Times: user=0.13 sys=0.00, real=0.08 secs]
  50. [Full GC (Ergonomics) [PSYoungGen: 1023K->1023K(2048K)] [ParOldGen: 7046K->7046K(7168K)] 8070K->8070K(9216K), [Metaspace: 3322K->3322K(1056768K)], 0.0587829 secs] [Times: user=0.08 sys=0.00, real=0.06 secs]
  51. [Full GC (Ergonomics) [PSYoungGen: 1023K->1023K(2048K)] [ParOldGen: 7048K->7048K(7168K)] 8072K->8072K(9216K), [Metaspace: 3322K->3322K(1056768K)], 0.0822265 secs] [Times: user=0.09 sys=0.00, real=0.08 secs]
  52. [Full GC (Ergonomics) [PSYoungGen: 1023K->1023K(2048K)] [ParOldGen: 7050K->7050K(7168K)] 8074K->8074K(9216K), [Metaspace: 3322K->3322K(1056768K)], 0.0579012 secs] [Times: user=0.09 sys=0.00, real=0.06 secs]
  53. [Full GC (Ergonomics) [PSYoungGen: 1023K->1023K(2048K)] [ParOldGen: 7052K->7052K(7168K)] 8076K->8076K(9216K), [Metaspace: 3322K->3322K(1056768K)], 0.0837761 secs] [Times: user=0.11 sys=0.00, real=0.08 secs]
  54. [Full GC (Ergonomics) Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
  55. [PSYoungGen: 1023K->0K(2048K)] [ParOldGen: 7068K->988K(7168K)] 8092K->988K(9216K), [Metaspace: 3347K->3347K(1056768K)], 0.0276618 secs] [Times: user=0.04 sys=0.00, real=0.03 secs]
  56. Heap
  57. PSYoungGen total 2048K, used 28K [0x00000000ffd00000, 0x0000000100000000, 0x0000000100000000)
  58. eden space 1024K, 2% used [0x00000000ffd00000,0x00000000ffd07060,0x00000000ffe00000)
  59. from space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
  60. to space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
  61. ParOldGen total 7168K, used 988K [0x00000000ff600000, 0x00000000ffd00000, 0x00000000ffd00000)
  62. object space 7168K, 13% used [0x00000000ff600000,0x00000000ff6f70a8,0x00000000ffd00000)
  63. Metaspace used 3354K, capacity 4496K, committed 4864K, reserved 1056768K
  64. class space used 352K, capacity 388K, committed 512K, reserved 1048576K
  65. at java.lang.Integer.toString(Integer.java:401)
  66. at java.lang.String.valueOf(String.java:3099)
  67. at JVM.ConstantOutOfMemory.main(ConstantOutOfMemory.java:21)

    2.GC overhead limt exceed检查是Hotspot VM 1.6定义的一个策略,通过统计GC时间来预测是否要OOM了,提前抛出异常,防止OOM发生。Sun 官方对此的定义是:“并行/并发回收器在GC回收时间过长时会抛出OutOfMemroyError。过长的定义是,超过98%的时间用来做GC并且回收了不到2%的堆内存。用来避免内存过小造成应用不能正常工作。“
    3.起初开来这玩意只能用来Catch住释放内存资源,避免应用挂掉。后来发现一般情况下这个策略不能拯救你的应用,但是可以在应用挂掉之前做最后的挣扎,比如数据保存或者保存现场(Heap Dump)。而且有些时候这个策略还会带来问题,比如加载某个大的内存数据时频繁OOM。
    4.假如你也生产环境中遇到了这个问题,在不知道原因时不要简单的猜测和规避。可以通过-verbose:gc -XX:+PrintGCDetails看下到底什么原因造成了异常。通常原因都是因为old区占用过多导致频繁Full GC,最终导致GC overhead limit exceed。如果gc log不够可以借助于JProfile等工具查看内存的占用,old区是否有内存泄露。分析内存泄露还有一个方法-XX:+HeapDumpOnOutOfMemoryError,这样OOM时会自动做Heap Dump,可以拿MAT来排查了。还要留意young区,如果有过多短暂对象分配,可能也会抛这个异常。
    5.日志的信息不难理解,就是每次gc时打条日志,记录GC的类型,前后大小和时间。举个例子。

  1. [GC (Allocation Failure) [PSYoungGen: 2296K->496K(2560K)] 4750K->4615K(9728K), 0.0064617 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]
  2. [GC (Allocation Failure) [PSYoungGen: 2544K->496K(1536K)] 6663K->6384K(8704K), 0.0070902 secs] [Times: user=0.02 sys=0.00, real=0.01 secs]
  3. [GC (Allocation Failure) [PSYoungGen: 1024K->1024K(2048K)] 6657K->6665K(9216K), 0.0051471 secs] [Times: user=0.02 sys=0.00, real=0.01 secs]
  4. [Full GC (Ergonomics) [PSYoungGen: 1024K->0K(2048K)] [ParOldGen: 5641K->6289K(7168K)] 6665K->6289K(9216K), [Metaspace: 3322K->3322K(1056768K)], 0.0962849 secs] [Times: user=0.22 sys=0.00, real=0.10 secs]
  5. [Full GC (Ergonomics) [PSYoungGen: 1024K->511K(2048K)] [ParOldGen: 6914K->7009K(7168K)] 7938K->7520K(9216K), [Metaspace: 3322K->3322K(1056768K)], 0.1231337 secs] [Times: user=0.27 sys=0.00, real=0.12 secs]

    6.GC和Full GC代表gc的停顿类型,Full GC代表stop-the-world。箭头两边是gc前后的区空间大小,分别是young区、tenured区和perm区,括号里是该区的总大小。冒号前面是gc发生的时间,单位是秒,从jvm启动开始计算。DefNew代表Serial收集器,为Default New Generation的缩写,类似的还有PSYoungGen,代表Parallel Scavenge收集器。这样可以通过分析日志找到导致GC overhead limit exceeded的原因,通过调节相应的参数解决问题。
    7.文中涉及到的名词解释:
        a)Eden Space:堆内存池,大多数对象在这里分配内存空间。
        b)Survivor Space:堆内存池,存储在Eden Space的gc中存活下来的对象。
        c)Tenured Generation:堆内存池,存储Survivor Space中存活过几次gc的对象。
        d)Permanent Generation:非堆空间,存储的是class和method对象。
        e)Code Cache:非堆空间,JVM用来存储编译和存储native code。
    8.演示案例代码:

  1. package JVM;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. /**
  5. * FileName: ConstantOutOfMemory
  6. * Author: hadoop
  7. * Email: 3165845957@qq.com
  8. * Date: 18-10-27 下午10:35
  9. * Description:
  10. */
  11. public class ConstantOutOfMemory {
  12. public static void main(String[] args){
  13. try{
  14. List<String> stringList = new ArrayList<String>();
  15. int item = 0;
  16. while (true){
  17. stringList.add(String.valueOf(item++).intern());
  18. }
  19. }catch (Exception e){
  20. e.printStackTrace();
  21. throw e;
  22. }
  23. }
  24. }

四、DirectMemoryOutOfMemory

    1.问题描述:

  1. [GC (Allocation Failure) [PSYoungGen: 2048K->496K(2560K)] 2048K->653K(9728K), 0.0025417 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]
  2. [GC (Allocation Failure) [PSYoungGen: 2544K->496K(2560K)] 2701K->1077K(9728K), 0.0051084 secs] [Times: user=0.01 sys=0.00, real=0.01 secs]
  3. [GC (Allocation Failure) [PSYoungGen: 2544K->496K(2560K)] 3125K->1711K(9728K), 0.0027141 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]
  4. [GC (System.gc()) [PSYoungGen: 1180K->496K(2560K)] 2394K->1807K(9728K), 0.0036020 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]
  5. [Full GC (System.gc()) [PSYoungGen: 496K->0K(2560K)] [ParOldGen: 1310K->1302K(7168K)] 1807K->1302K(9728K), [Metaspace: 3215K->3215K(1056768K)], 0.0264088 secs] [Times: user=0.05 sys=0.00, real=0.03 secs]
  6. Error:instance created 1
  7. java.lang.OutOfMemoryError: Direct buffer memory
  8. at java.nio.Bits.reserveMemory(Bits.java:695)
  9. at java.nio.DirectByteBuffer.<init>(DirectByteBuffer.java:123)
  10. at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:311)
  11. at JVM.DirectMemoryOutOfMemory.main(DirectMemoryOutOfMemory.java:18)
  12. Heap
  13. PSYoungGen total 2560K, used 204K [0x00000000ffd00000, 0x0000000100000000, 0x0000000100000000)
  14. eden space 2048K, 10% used [0x00000000ffd00000,0x00000000ffd33350,0x00000000fff00000)
  15. from space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
  16. to space 512K, 0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000)
  17. ParOldGen total 7168K, used 1302K [0x00000000ff600000, 0x00000000ffd00000, 0x00000000ffd00000)
  18. object space 7168K, 18% used [0x00000000ff600000,0x00000000ff745a88,0x00000000ffd00000)
  19. Metaspace used 3351K, capacity 4496K, committed 4864K, reserved 1056768K
  20. class space used 352K, capacity 388K, committed 512K, reserved 1048576K

    2.创建Buffer对象时,可以选择从JVM堆中分配内存,也可以OS本地内存中分配,由于本地缓冲区避免了缓冲区复制,在性能上相对堆缓冲区有一定优势,但同时也存在一些弊端。
    3.两种缓冲区对应的API如下:
        a)JVM堆缓冲区:ByteBuffer.allocate(size)
        b)本地缓冲区:ByteBuffer.allocateDirect(size)
    4.从堆中分配的缓冲区为普通的Java对象,生命周期与普通的Java对象一样,当不再被引用时,Buffer对象会被回收。而直接缓冲区(DirectBuffer)为本地内存,并不在Java堆中,也不能被JVM垃圾回收。由于直接缓冲区在JVM里被包装进Java对象DirectByteBuffer中,当它的包装类被垃圾回收时,会调用相应的JNI方法释放本地内存,所以本地内存的释放也依赖于JVM中DirectByteBuffer对象的回收。
    5.由于垃圾回收本身成本较高,一般JVM在堆内存未耗尽时,不会进行垃圾回收操作。我们知道在32位机器上,每个进程的最大可用内存为4G,用户可用内存在大概为3G左右,如果为堆分配过大的内存时,本地内存可用空间就会相应减少。当我们为堆分配较多的内存时,JVM可能会在相当长的时间内不会进行垃圾回收操作,从而本地内存不断分配,无法释放,最终导致OutOfMemoryError。
    6.由此可见,在使用直接缓冲区之前,需要做出权衡:
        a)堆缓冲区的性能已经相当高,若无必要,使用堆缓冲区足矣。若确实有提升性能的必要时,再考虑使用本地缓冲区。
        b)为JVM分配堆内存时,并不是越大越好,堆内存越大,本地内存就越小,根据具体情况决定,主要针对32位机器,64位机器上不存在该问题
    7.演示案例代码:

  1. package JVM;
  2. import java.nio.ByteBuffer;
  3. /**
  4. * FileName: DirectMemoryOutOfMemory
  5. * Author: hadoop
  6. * Email: 3165845957@qq.com
  7. * Date: 18-10-27 下午10:41
  8. * Description:
  9. */
  10. public class DirectMemoryOutOfMemory {
  11. private static final int ONE_GB = 1024*1024*1024;
  12. private static int count = 1;
  13. public static void main(String[] args){
  14. try {
  15. while (true){
  16. ByteBuffer buffer = ByteBuffer.allocateDirect(ONE_GB);
  17. count++;
  18. }
  19. }catch (Exception e){
  20. System.out.println("Exception:instance created "+count);
  21. e.printStackTrace();
  22. }catch (Error e){
  23. System.out.println("Error:instance created "+count);
  24. e.printStackTrace();
  25. }
  26. }
  27. }

 

 参考网络资料:   Java修改JVM内存大小整理。(java heap space 解决方案)

                             StackOverflowError的分析和理解

                             java.lang.OutOfMemoryError:GC overhead limit exceeded填坑心得

                             DirectBuffer及内存泄漏

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
jdk8 Metaspace 调优
不可思议,竟然还有人不会查看GC垃圾回收日志?
通过JMX控制在full GC前后做heap dump
gc的日志分析
Java 堆内存
Java的强引用、软引用、弱引用、虚引用
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服