JVM二

不打扰是莪最后的温柔 提交于 2020-03-14 20:21:54

12.GC详解

垃圾回收:分代收集算法不同的区域使用不同的回收算法

Young代:GC频繁区域

Old代:GC次数较少

Perm代:不会产生GC!

一个对象的历程:

JVM在进行GC时,并非每次都对三个区域进行扫描的。大部分的时候都是指的新生代。

普通GC:只针对新生代【GC】

Full GC:主要是针对老年代,偶尔伴随新生代【Full GC】

1.JVM内存模型,每个区中存放什么?

2.堆中的分区:Eden,S from to,老年代,说说他们的特点。

3.GC的三种收集算法:标记清除,标记整理,复制算法,请你谈谈他的特点?

13.GC四大算法

引用计数法:

特点:每个对象都有一个引用计数器,每当对象被引用一次,计数器+1,如果引用失效,则计数器-1,如果为0,则GC可以清理。

缺点:

  • 计数器维护麻烦
  • 循环引用无法处理

JVM一般不采用这种方式(JVM一般采用可达性算法。)

复制算法

年轻代就是用的复制算法

1、一般普通GC之后,差不多Eden几乎都是空的了

2、每次存活的对象,都会被从from区和Eden区活着的对象复制到to区,这时from和to会发生一次交换:谁空谁是to,每当幸存一次,就会导致这个对象的年龄+1;如果这个年龄值大于15(默认值),就会进入养老区。

优点:没有标记和清楚的过程,效率高,没有内存碎片

缺点:to区永远是空的,需要浪费双倍的空间

Eden区,对象存活率极低。官方统计:99%的对象都会在使用一次之后,引用失效!推荐使用复制算法。

标记清除算法

老年代一般使用这个,但是会和我们后面的整理压缩一起使用。

优点:不需要额外的空间

缺点:两次扫描,耗时较为严重,会产生内存碎片,不连续。

标记整理算法

优化了标记清除算法的缺点,没有了内存碎片,但是耗时可能也较为严重。

如果空间中很少或者不经常发生GC,那么可以考虑使用标记整理算法。

小结:

内存效率:复制算法>标记清除算法>标记整理 (时间复杂度)

内存整齐度:复制算法=标记整理>标记清除

内存利用率:标记整理=标记清除>复制算法

年轻代:

Eden区:对象存活率极低,推荐使用复制算法

老年代:

区域比较大,对象存活率较高,推荐使用标记整理算法

14.JVM垃圾回收的时候如何确定垃圾,GC Roots

垃圾:简单说就是不再被引用的对象。

如果我们要进行垃圾回收,第一步:判断这个对象是否可以回收!

引用计数法

Java中,引用和对象都是有关联的,如果要操作对象,就要通过引用进行。

可达性分析算法:

一切都是从GC Roots这个对象开始遍历的,只要在这个树里面,就不是垃圾。

什么是GC Roots(4种)

1、虚拟机栈中引用的对象

2、类中的静态属性引用的对象

3、方法区中的常量

4、本地方法栈中的native方法引用的对象。

public class GCRoots{
        
    // private byte[] array = new byte[100*1024*1024]; // 开辟内空间!
    // private static GCRoots2 t2; // GC root;
    // private static final GCRoots3 t3 = new GCRoots3(); // GC root;
    
    // 引用远远不止于此,强引用,软引用,弱引用,虚引用! 四个类的使用!
    public static void m1(){
        GCRoots g1 = new GCRoots(); //GCroot
        System.gc();
    }
    
    public static void main(String[] args){
        m1();
    }

}

15. -X、-XX参数你用过哪些,JVM有哪些常用参数?

15.1 标配参数

在各种版本之间都很稳定,很少有变化。

java -version

java -help

java -showversion

...

15.2 X参数(了解)

java -Xint 解释执行

java -Xcomp 第一次使用就编译成本地的代码

java -Xmixed 混合模式(Java默认)

15.3 重点(XX参数boolean形)

语法:-XX:+(-) 某个属性值;+代表开启某个功能,-代表关闭某个功能。

开启PrintGCDetails功能后

15.4 XX参数之key=value形

元空间大小:jinfo -flag MetaspaceSize 进程号

-XX:MetaspaceSize=10m(一般有默认值,不需要修改)

jinfo -flag MaxTenuringThreshold 进程号(该参数主要是控制新生代需要经历多少次GC晋升到老年代中的最大阈值,在JVM中用4个bit存储(放在对象头中),所以其最大值是15

-XX:MaxTenuringThreshold=15

试图把值改为大于15的会出现如下错误:

查看所有默认值:

Non-default VM flags—默认的JVM参数

-XX:InitialHeapSize=268435456 默认初始堆大小

-XX:MaxHeapSize=4265607168 初始的最大内存

-XX:MaxNewSize=1421869056 最大的新生区大小

-XX:+UseParallelGC 并行GC垃圾回收器

JVM version is 25.191-b12
Non-default VM flags: -XX:CICompilerCount=4 -XX:InitialHeapSize=268435456 - XX:MaxHeapSize=4265607168 -XX:MaxNewSize=1421869056 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=89128960 -XX:OldSize=179306496 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC
Command line: -javaagent:D:\Dev_Soft\IDEA\lib\idea_rt.jar=64948:D:\Dev_Soft\IDEA\bin -Dfile.encoding=UTF-8

-Xms,-Xms是什么参数

1.-Xms:初始堆的大小;等价于:-XX:InitialHeapSize=268435456

2.-Xms:最大堆的大小;等价于:-XX:MaxHeapSize=4265607168

初始的默认参数到底有多少?

java -XX:+PrintFlagsInitial 查看Java环境初始默认值。这里面只要显示的值,我们都可以手动赋值,但不建议修改,了解即可。

= 默认值

:=被修改过的值

java -XX:+PrintFlagsFinal -Xss128k ;查看被修改过的值,启动的时候判断

java -XX:+PrintCommandLineFlags -version;打印出用户手动设置的XX选项

16. 项目中常用的JVM参数有哪些

-Xms

-Xmx

-Xss 线程栈大小设置,默认512k—1024k

-Xmn 设置年轻代的大小,一般不动

-XX:MetaSpaceSize 设置元空间的大小,这个在本地内存中,一般不动

-XX:PrintGCDetails 打印垃圾回收信息

-XX:SurvivorRatio

设置新生代中的s0/s1空间的比例;

uintx SurvivorRatio = 8 代表:Eden:s0:s1=8:1:1

uintx SurvivorRatio = 4 代表:Eden:s0:s1=4:1:1

-XX:NewRatio 设置年轻代与老年代的占比

NewRatio = 2 代表:新生代是1,老年代是2,默认新生代整个堆的1/3;

-XX:MaxTenuringThreshold

进入老年区的存活阈值

MaxTenuringThreshold=15

17. OOM的认识

java.lang.StackOverflowError:栈溢出

public class OOMDemo {

    public static void main(String[] args) {
        a();
    }

    public static void a(){
        a();
    }
}

java.lang.OutOfMemoryError: Java heap space

public class OOMDemo {
//-Xms10m -Xmx10m
    public static void main(String[] args) {
        String str = "aldksjflaksdjf";
        while (true){
            str += str + new Random(999999999)
                    + new Random(999999999);
        }
    }
}

java.lang.OutOfMemoryError: GC overhead limit exceeded

GC回收时间过长也会导致OOM;

可能CPU占用率一直是100%,GC但是没有什么效果。

public class OOMDemo {
//-Xms10m -Xmx10m -XX:MaxDirectMemorySize=5m -XX:+PrintGCDetails
    public static void main(String[] args) {
        int i = 0;
        List<String> list = new ArrayList<>();
        try {
            while (true){
                list.add(String.valueOf(++i).intern());
            }
        } catch (Throwable e) {
            System.out.println("i==>"+i);
            e.printStackTrace();
            throw e;
        }
    }
}

java.lang.OutOfMemoryError: Direct buffer memory 基础缓冲区的错误

public class OOMDemo {
//-Xms10m -Xmx10m -XX:MaxDirectMemorySize=5 -XX:+PrintGCDetails
    public static void main(String[] args) throws InterruptedException {
        System.out.println("配置的MaxDirectMemorySize:"+VM.maxDirectMemory()/(double)1024/1024+"MB");
        TimeUnit.SECONDS.sleep(2);
//        ByteBuffer.allocate():分配JVM的堆内存,属于GC管辖
//        ByteBuffer.allocateDirect()分配本地OS内存,不属于GC管辖
        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(6*1024*1024);
    }
}

java.lang.OutOfMemoryError: unable to create native Thread

高并发,unable to create native Thread 这个错误更多的时候和平台有关

1、应用创建的线程太多

2、服务器不允许你创建这么多线程。

public class TDemo {
    public static void main(String[] args) {
        for (int i = 1; ; i++) {
            System.out.println("i===>>>"+i);
            new Thread(()->{
                try {
                    Thread.sleep(Integer.MAX_VALUE);
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
            },String.valueOf(i)).start();
        }
    }
}

1、服务器线程不够了,超过了限制,也会爆出OOM异常。

java.lang.OutOfMemoryError: Metaspace 元空间报错

Java8之后使用元空间代替永久代,使用的是本地内存!

元空间里面存储的是:

1、虚拟机加载类信息

2、常量池

3、静态变量

4、编译后的代码

......

// -XX:MetaspaceSize=10m -XX:MaxMetaspaceSize=10m
public class OomDemo {
    
    static class OOMTest{}

    public static void main(String[] args) throws Throwable {

        int i = 0; // 模拟计数器

        try {
            while (true){
                i++;
                // 不断的加载对象! Spring的 cglib;
                Enhancer enhancer = new Enhancer();
                enhancer.setSuperclass(OOMTest.class);
                enhancer.setUseCache(false);
                enhancer.setCallback(new MethodInterceptor() {
                    @Override
                    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                        return method.invoke(o,args);
                    }
                });
                enhancer.create();
            }
        } catch (Throwable e) {
            System.out.println("i=>"+i);
            e.printStackTrace();
        }
        
    }
}

18. 请你谈谈垃圾收集器

GC算法(引用计数器,复制,标记清除,标记整理)方法论,垃圾收集器就是对应的落地实现。

4种垃圾收集器

1、串行垃圾回收器(STW:Stop The World)单线程

2、并行垃圾回收器(多线程工作,也会导致STW)

3、并发垃圾回收器(在回收垃圾的同时,可以正常执行线程,并行处理,但如果是单CPU,只能交替执行。)

4、G1垃圾回收器(将堆内存分割成不同的区域,然后并发的对其进行垃圾回收,Java9之后,默认使用G1)

垃圾回收器

查看默认的垃圾回收器

java -XX:+PrintCommandLineFlags -version

java的GC回收器主要有哪些?(以前7种,现在6种)

DefNew:默认的新一代【Serial串行】

Tenured:老年代【Serial Old】

ParNew:并行新一代【并行ParNew】

PSYoungGen:并行清楚年轻代【Parallel Scavcegn】

ParOldGen:并行老年区

Server/Client模式

默认现在都是Server模式;Client几乎不会使用

32位的Window操作系统,默认都是Client的JVM模式

64位的默认都是Server模式。

不同的垃圾回收器对应的机制不同。

串行GC

-Xms10m -Xmx10m -XX:+PrintGCDetails -XX:+UseSerialGC

新生代:DefNew——老年代:Tenured

Serial——Serial Old

并行GC【不推荐使用】

-Xms10m -Xmx10m -XX:+PrintGCDetails -XX:+UseParNewGC

新生代:ParNew——老年代:Tenured

JDK8默认的GC

-Xms10m -Xmx10m -XX:+PrintGCDetails -XX:+UseParallelGC

使用标准,如果选择垃圾回收器

1、单CPU,单机程序,内存小

-XX:+UseSerialGC

2、多CPU,单机程序,内存小

-XX:+UseParNewGC

3、多CPU,但是不希望有时间停顿,快速响应。

-XX:+UseParNewGC或者-XX:+UseParallelGC

19. G1垃圾回收器

以前的垃圾回收器的特点

1、年轻代和老年代是各自独立的内存区域

2、年轻代使用Eden+s0+s1复制算法

3、老年代收集必须扫描整个老年代的区域

4、垃圾回收器原则:尽可能少而快的执行GC

G1垃圾回收器

G1(Garbage First)收集器;面向服务器端的应用的收集器。

-Xms10m -Xmx10m -XX:+PrintGCDetails -XX:+UseG1GC

G1可以自定义垃圾回收的时间!

-XX:MaxGCPauseMillis=100 最大的GC停顿时间单位:毫秒,JVM尽可能的保证停顿小于这个时间!

G1优点

1、没有内存碎片

2、可以精准控制垃圾回收时间。

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!