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

30 篇文章 1 订阅

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.问题描述:

[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] 
[Full GC (Allocation Failure) Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
	at java.util.Arrays.copyOf(Arrays.java:3210)
	at java.util.Arrays.copyOf(Arrays.java:3181)
	at java.util.ArrayList.grow(ArrayList.java:265)
	at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:239)
	at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:231)
	at java.util.ArrayList.add(ArrayList.java:462)
	at JVM.HeapOutOfMemory.main(HeapOutOfMemory.java:20)
[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] 
Heap
 PSYoungGen      total 2048K, used 939K [0x00000000ffd00000, 0x0000000100000000, 0x0000000100000000)
  eden space 1024K, 91% used [0x00000000ffd00000,0x00000000ffdeaeb0,0x00000000ffe00000)
  from space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
  to   space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
 ParOldGen       total 7168K, used 7129K [0x00000000ff600000, 0x00000000ffd00000, 0x00000000ffd00000)
  object space 7168K, 99% used [0x00000000ff600000,0x00000000ffcf64c0,0x00000000ffd00000)
 Metaspace       used 3388K, capacity 4500K, committed 4864K, reserved 1056768K
  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.演示案例代码:

package JVM;

import java.util.ArrayList;
import java.util.List;

/**
 * FileName: HeapOutOfMemory
 * Author:   hadoop
 * Email:    3165845957@qq.com
 * Date:     18-10-27 下午9:45
 * Description:一般情况下,heap中只存在对象
 */
class Person{}
public class HeapOutOfMemory {
    public static void main(String[] args){
        System.out.println("HeapOutOfMemory");
        List<Person> persons = new ArrayList<Person>();
        int counter = 0;
        while (true){
            persons.add(new Person());
            System.out.println("Instance: "+ (++counter));
        }
    }
}

 

二、StackOverFlow

    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] 
[GC (Allocation Failure) [PSYoungGen: 2544K->512K(2560K)] 2661K->1063K(9728K), 0.0040749 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 
[GC (Allocation Failure) [PSYoungGen: 2560K->512K(2560K)] 3111K->1696K(9728K), 0.0031524 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
StackOverFlow
Exception in thread "main" java.lang.StackOverflowError
	at JVM.StackOverFlow.count(StackOverFlow.java:15)
	at JVM.StackOverFlow.count(StackOverFlow.java:15)
	at JVM.StackOverFlow.count(StackOverFlow.java:15)
	at JVM.StackOverFlow.count(StackOverFlow.java:15)
Heap
 PSYoungGen      total 2560K, used 2533K [0x00000000ffd00000, 0x0000000100000000, 0x0000000100000000)
  eden space 2048K, 98% used [0x00000000ffd00000,0x00000000ffef94a8,0x00000000fff00000)
  from space 512K, 100% used [0x00000000fff00000,0x00000000fff80000,0x00000000fff80000)
  to   space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
 ParOldGen       total 7168K, used 1184K [0x00000000ff600000, 0x00000000ffd00000, 0x00000000ffd00000)
  object space 7168K, 16% used [0x00000000ff600000,0x00000000ff728048,0x00000000ffd00000)
 Metaspace       used 3379K, capacity 4496K, committed 4864K, reserved 1056768K
  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. 演示案例代码:

package JVM;

/**
 * FileName: StackOverFlow
 * Author:   hadoop
 * Email:    3165845957@qq.com
 * Date:     18-10-27 下午10:00
 * Description:
 */

public class StackOverFlow {
    private int counter;
    public void count(){
        counter++;
        count();
    }
    public static void main(String[] agrs){
        System.out.println("StackOverFlow");
        StackOverFlow stackOverFlow = new StackOverFlow();
        try{
            stackOverFlow.count();
        }catch (Exception e){
            e.printStackTrace();
            throw e;
        }
    }
}

三、JVM:ContantOutOfMemory

    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] 
[GC (Allocation Failure) [PSYoungGen: 2544K->496K(2560K)] 2701K->1110K(9728K), 0.0026725 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
[GC (Allocation Failure) [PSYoungGen: 2544K->496K(2560K)] 3158K->1732K(9728K), 0.0036126 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 
[GC (Allocation Failure) [PSYoungGen: 2544K->496K(2560K)] 3780K->2950K(9728K), 0.0060662 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 
[GC (Allocation Failure) [PSYoungGen: 2296K->496K(2560K)] 4750K->4615K(9728K), 0.0064617 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [PSYoungGen: 2544K->496K(1536K)] 6663K->6384K(8704K), 0.0070902 secs] [Times: user=0.02 sys=0.00, real=0.01 secs] 
[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] 
[GC (Allocation Failure) [PSYoungGen: 1024K->1024K(2048K)] 6657K->6665K(9216K), 0.0051471 secs] [Times: user=0.02 sys=0.00, real=0.01 secs] 
[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] 
[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] 
[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] 
[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] 
[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] 
[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] 
[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] 
[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] 
[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] 
[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] 
[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] 
[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] 
[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] 
[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] 
[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] 
[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] 
[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] 
[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] 
[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] 
[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] 
[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] 
[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] 
[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] 
[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] 
[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] 
[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] 
[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] 
[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] 
[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] 
[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] 
[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] 
[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] 
[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] 
[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] 
[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] 
[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] 
[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] 
[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] 
[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] 
[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] 
[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] 
[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] 
[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] 
[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] 
[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] 
[Full GC (Ergonomics) Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
[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] 
Heap
 PSYoungGen      total 2048K, used 28K [0x00000000ffd00000, 0x0000000100000000, 0x0000000100000000)
  eden space 1024K, 2% used [0x00000000ffd00000,0x00000000ffd07060,0x00000000ffe00000)
  from space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
  to   space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
 ParOldGen       total 7168K, used 988K [0x00000000ff600000, 0x00000000ffd00000, 0x00000000ffd00000)
  object space 7168K, 13% used [0x00000000ff600000,0x00000000ff6f70a8,0x00000000ffd00000)
 Metaspace       used 3354K, capacity 4496K, committed 4864K, reserved 1056768K
  class space    used 352K, capacity 388K, committed 512K, reserved 1048576K
	at java.lang.Integer.toString(Integer.java:401)
	at java.lang.String.valueOf(String.java:3099)
	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的类型,前后大小和时间。举个例子。

[GC (Allocation Failure) [PSYoungGen: 2296K->496K(2560K)] 4750K->4615K(9728K), 0.0064617 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [PSYoungGen: 2544K->496K(1536K)] 6663K->6384K(8704K), 0.0070902 secs] [Times: user=0.02 sys=0.00, real=0.01 secs] 
[GC (Allocation Failure) [PSYoungGen: 1024K->1024K(2048K)] 6657K->6665K(9216K), 0.0051471 secs] [Times: user=0.02 sys=0.00, real=0.01 secs] 
[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] 
[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.演示案例代码:

package JVM;

import java.util.ArrayList;
import java.util.List;

/**
 * FileName: ConstantOutOfMemory
 * Author:   hadoop
 * Email:    3165845957@qq.com
 * Date:     18-10-27 下午10:35
 * Description:
 */
public class ConstantOutOfMemory {
    public static void main(String[] args){
        try{
            List<String> stringList = new ArrayList<String>();
            int item = 0;
            while (true){
                stringList.add(String.valueOf(item++).intern());
            }
        }catch (Exception e){
            e.printStackTrace();
            throw e;
        }
    }
}

四、DirectMemoryOutOfMemory

    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] 
[GC (Allocation Failure) [PSYoungGen: 2544K->496K(2560K)] 2701K->1077K(9728K), 0.0051084 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 
[GC (Allocation Failure) [PSYoungGen: 2544K->496K(2560K)] 3125K->1711K(9728K), 0.0027141 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] 
[GC (System.gc()) [PSYoungGen: 1180K->496K(2560K)] 2394K->1807K(9728K), 0.0036020 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] 
[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] 
Error:instance created 1
java.lang.OutOfMemoryError: Direct buffer memory
	at java.nio.Bits.reserveMemory(Bits.java:695)
	at java.nio.DirectByteBuffer.<init>(DirectByteBuffer.java:123)
	at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:311)
	at JVM.DirectMemoryOutOfMemory.main(DirectMemoryOutOfMemory.java:18)
Heap
 PSYoungGen      total 2560K, used 204K [0x00000000ffd00000, 0x0000000100000000, 0x0000000100000000)
  eden space 2048K, 10% used [0x00000000ffd00000,0x00000000ffd33350,0x00000000fff00000)
  from space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
  to   space 512K, 0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000)
 ParOldGen       total 7168K, used 1302K [0x00000000ff600000, 0x00000000ffd00000, 0x00000000ffd00000)
  object space 7168K, 18% used [0x00000000ff600000,0x00000000ff745a88,0x00000000ffd00000)
 Metaspace       used 3351K, capacity 4496K, committed 4864K, reserved 1056768K
  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.演示案例代码:

package JVM;

import java.nio.ByteBuffer;

/**
 * FileName: DirectMemoryOutOfMemory
 * Author:   hadoop
 * Email:    3165845957@qq.com
 * Date:     18-10-27 下午10:41
 * Description:
 */
public class DirectMemoryOutOfMemory {
    private static final int ONE_GB = 1024*1024*1024;
    private static int count = 1;
    public static void main(String[] args){
        try {
            while (true){
                ByteBuffer buffer = ByteBuffer.allocateDirect(ONE_GB);
                count++;
            }
        }catch (Exception e){
            System.out.println("Exception:instance created "+count);
            e.printStackTrace();
        }catch (Error e){
            System.out.println("Error:instance created "+count);
            e.printStackTrace();
        }
    }
}

 

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

                             StackOverflowError的分析和理解

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

                             DirectBuffer及内存泄漏

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值