JVM 探究

JVM 探究

  • 请你探探你对jvm的理解?java8虚拟机和之前的变化更新?

  • 什么是OOM,什么是栈溢出StackOverFlowError?怎么分析

  • JVM的常用调优参数有哪些

  • 内存快照如何抓取,怎么分析Dump文件?知道吗?

  • 读读JVM中,类加载器你的认识?

    1.jvm的位置

    在操作系统之上

    2.jvm的体系结构

    image-20201225165212797

    3.类加载器

    ​ 作用:加载Class文件 ~ new Student();

    image-20201225171030879

    1 .虚拟机自带的加载器

    1. 启动类(根)加载器

    2. 扩展类加载器

    3. 应用程序加载器

    4.双亲委派机制

    package lang;
    
    import javax.sound.midi.Soundbank;
    import java.sql.SQLOutput;
    
    public class String {
        //双亲委派机制,安全
        //1.APP--->EXC---BOOT(最终执行)
        //BOOT
        //EXC
        //APP
        public Stirng toString(){
            return "hello";
        }
    
        public static void main(String[] args) {
            String s =new String();
            System.out.println(s.getClass().getClassLoader());
            s.toString();
        }
    
        /**
         * 1. 类加载器收到类加载的请求
         * 2. 将这个请求向上委托给父亲加载器去完成,一直向上委托,知道启动类加载器
         * 3. 启动加载器检查是否能够加载当前这个类,额能加载就结束。
         *
         */
    }
    
    

    5.沙箱安全机制

    6.Native

    7.PC寄存器

    8.方法区: static,final,Class,常量池

    9.栈

    10.三种jvm

    11.堆

    image-20201227130203965

    真相:经过研究,99%的对象都是临时对象!

    12.新生区、老年区

    • 新生区
    • 类:诞生和成长的地方,甚至死亡;
      • 伊甸园,所有的对象都是在伊甸园区new出来的!

    13、永久区

    这个区域常驻内存的。用来存放JDK自带携带的Class对象。Interface元数据,存储的是java运行时的一些环境或类信息~

    一个启动类,加载了大量的第三方jar包。Tomcat部署了太多的应用,大量动态生产的反射类。不断的被加载。直到内存满,就会出现OOM

    • jdk1.6 之前:永久代,常量池在方法区:
    • jdk 1.7:永久代,但是慢慢的退化了,去永久代,常量池在堆中
    • jdk 1.8之后:无永久代,常量池在元空间
    • image-20201227132258922

    image-20201227132437543

    14堆内存调优

    package hao;
    
    public class Demo2 {
        public static void main(String[] args) {
            //返回虚拟机视图使用的最大内存
            long max =Runtime.getRuntime().maxMemory();  //字节 1024*1024
            //返回jvm的初始化总内存
            long total =Runtime.getRuntime().totalMemory();
    
            System.out.println("max="+max+"字节\t"+(max/(double)1024/1024)+"MB");
            System.out.println("total="+max+"字节\t"+(total/(double)1024/1024)+"MB");
            // 默认情况下: 分配的总内存 是电脑内存的1/4,而初始化的内存:1/64
    
        }
        //OOM:
            //1.尝试扩大内存看结果
            //2.分析内存,看一下那个地方出现了问题(专业工具)
        // -Xms1024m -Xmx1024m -XX:+PrintGCDetails
    
        // 305664K +699392K =1005056 K =981.5M
    }
    
    
    "C:\Program Files\Java\jdk1.8.0_251\bin\java.exe" -Xms1024m -Xmx1024m -XX:+PrintGCDetails "-javaagent:D:\app\appInstall\IntelliJ IDEA 2020.1.1\lib\idea_rt.jar=3763:D:\app\appInstall\IntelliJ IDEA 2020.1.1\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_251\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_251\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_251\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_251\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_251\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_251\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_251\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_251\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_251\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_251\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_251\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_251\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_251\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_251\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_251\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_251\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_251\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_251\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_251\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_251\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_251\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_251\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_251\jre\lib\rt.jar;D:\workspace\java\网络编程\target\classes" hao.Demo2
    max=1029177344字节	981.5MB
    total=1029177344字节	981.5MB
    Heap
     PSYoungGen      total 305664K, used 20971K [0x00000000eab00000, 0x0000000100000000, 0x0000000100000000)
      eden space 262144K, 8% used [0x00000000eab00000,0x00000000ebf7afb8,0x00000000fab00000)
      from space 43520K, 0% used [0x00000000fd580000,0x00000000fd580000,0x0000000100000000)
      to   space 43520K, 0% used [0x00000000fab00000,0x00000000fab00000,0x00000000fd580000)
     ParOldGen       total 699392K, used 0K [0x00000000c0000000, 0x00000000eab00000, 0x00000000eab00000)
      object space 699392K, 0% used [0x00000000c0000000,0x00000000c0000000,0x00000000eab00000)
     Metaspace       used 3229K, capacity 4496K, committed 4864K, reserved 1056768K
      class space    used 347K, capacity 388K, committed 512K, reserved 1048576K
    

    image-20201227135928028

    15 GC 垃圾回收,主要是在伊甸园区和养老区~

    ​ 假设内存满了,OOM,堆内存不够!

    ​ 1.常用算法

    在一个项目中,突然出现了OOM故障,那么该如何排除~ 研究为什么出错~

    • 能够看到代码第几行出错:内存快照分析工具,MAT,Jprofiler
    • Dubug,一行行分析代码!

    MAT,Jprofiler作用

    • 分析Dump内存文件,快速定位内存泄漏;

    • 获得堆中的数据

    • 获得大的对象

    • 。。。

    • image-20201227145729595

image-20201227150208221

总结

JVM 在进行GC时,并不是对这三个区域统一回收。大部分时候,回收都是新生代~

  • 新生代

  • 幸存区 (form, to)

  • 老年区

  • 年轻代:

    • 存活率低
    • 复制算法!

    老年代:

    • 区域大:存活率
    • 标记清除(内存碎片不是太多)+标记压缩混合实现

GC 两种类:轻GC (普通的GC),重GC(全局GC)

GC题目:

  • JVM的内存模型和分区 -详细到每个区放什么?
  • 堆里面的分区有哪些?Eden,form,to,老年区,说说他们的特点!
  • GC的算法有哪些?标记清除法,标记压缩,复制算法,引用计数器,怎么用的?
  • 轻GC和重GC分别在什么时候发生?

引用计数法:

image-20201227151446212

复制算法

image-20201227152457678

image-20201227153001602

标记清除算法

image-20201227153213413

  • 优点:不需要额外的空间!
  • 缺点:两次扫描,严重浪费时间,会产生内存碎片。

标记压缩

再优化

image-20201227153532999

总结

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

内存整齐度:复制算法 =标记压缩算法》标记清除算法

内存利用率:标记压缩算法 =标记清除算法》复制算法

思考一个问题:难道没有最优算法吗?

答案:没有,没有最好的算法,只有最适合的算法 -----》GC:分代收集算法

JMM

1.什么是JMM?

JMM

posted @ 2020-12-29 11:27  learning豪  阅读(54)  评论(0编辑  收藏  举报