JVM实战

一、内存溢出

虚拟机栈和本地方法栈溢出:-Xss256k

package com.jedis;

import java.util.LinkedList;
import java.util.List;

public class Demo1 {
    private int len = 1;
    
    private void fun() {
        len++;
        fun();
    }
    
    public static void main(String[] args) {
        Demo1 t = new Demo1();
        try {
            t.fun();
        } catch (Throwable e) {
            System.out.println("Length = " + t.len);
            e.printStackTrace();
        }
    }
    
}

/* 
 Length = 3257
 java.lang.StackOverflowError
*/
栈溢出

Java堆溢出:-Xms5M -Xmx5M -XX:+PrintGCDetails -verbose:gc

package com.jedis;

import java.util.LinkedList;
import java.util.List;

public class Demo1 {

    public static void main(String[] args) {
        List<Object> list = new LinkedList<>();
        int i = 0;
        while(true) {
            i++;
            if(i%10000==0) System.out.println("i = " + i);
            list.add(new Object());
        }
        //String[] strings = new String[1000000000];
    }
    
}
Java堆溢出

方法区和运行时常量池溢出:-XX:MaxMetaspaceSize=3M

package com.jedis;

import java.util.LinkedList;
import java.util.List;

public class Demo1 {

    public static void main(String[] args) {
        List<Object> list = new LinkedList<>();
    }
    
}
/*
Error occurred during initialization of VM
OutOfMemoryError: Metaspace
*/
方法区溢出

本地直接内存溢出:-Xmx10M -XX:MaxDirectMemorySize=10M

package com.jedis;

import java.lang.reflect.Field;

public class Demo1 {
    
    public static void main(String[] args) {
        Field unsafeField = Unsafe.class.getDeclaredField()[0];
        unsafeField.setAccessible(true);
        Unsafe unsafeInstance = (Unsafe)unsafeField.get(null);
        while(true) {
            unsafeInstance.allocateMemory(1024*1024);
        }
    }
}

/* 
*/
直接内存溢出

二、垃圾收集器与内存分配策略

GC要做的事:

1、Where/Which?

2、When?

3、How?

where:堆/方法区(元数据空间)

which:引用计数法/可达性分析法

引用计数缺点:相互引用

A +1

B +1

C 0

A-->B

B-->A 

A、B组成孤岛,但是两个在计数上不为0

python-引用计数法

---

可达性分析:

GC Roots

1、虚拟机栈引用的对象

2、方法区类属性引用的对象

3、方法区常量引用的对象

----

怎么回收?

标记-清除算法(Mark-Sweep):直接把可回收的标记后清除——>不连续内存碎片——>无法放下大对象

复制算法(Copying):区域一分为二,存活对象一一复制过来,然后一股脑的把另一个全部释放——>内存拷贝耗时、任何时候都有一半空间空着

标记-整理算法(Mark-Compact):存活对象按照某种顺序排列——>标记、移动耗时

分代收集算法:90%对象朝生夕死——>堆分为新生代(刚new的对象)、老年代(活过多少次GC过程提取到老年代)——>定制不同的GC算法

G1:JDK1.8后常用了——>把新生代、老年代分的更小

Eden:to survival:from survival

8:1:1

原文地址:https://www.cnblogs.com/Roni-i/p/10804620.html