zoukankan      html  css  js  c++  java
  • 新鲜出炉!花了三天整理的JVM复习知识点,面试突击必备!

    此次JVM知识点包含以下几个部分

    1.类加载机制

    2.jvm运行时数据区

    3.java对象内存布局

    4.jvm内存模型

    5.垃圾回收机制

    6.垃圾收集器

    7.问题排查

    一 类加载机制

    主要说的部分是这一块

    那么如何装载呢,这就谈到了咱们的双亲委派机制,简单来说就是类,向上递交,向下加载,源码和图如下

    if (parent != null) {
        c = parent.loadClass(name, false);
      } else {
       //由于BootstrapClassLoader是C++写的,在java中被视为null
        c = findBootstrapClassOrNull(name);
      }
    

      

    那么装载的过程是什么呢,如图

    装载干了啥呢,大白话说就是一个你把一个java文件转换成二进制给jvm处理,官方一点的语言就是:

        ①通过一个类的全限定名获取这个类的二进制字节流。
    
        ②将这个字节流的静态存储结构转换为方法区的运行时数据结构。
    
        ③在堆中生成一个这个二进制字节流的Class对象作为访问入口。
    

    那么链接呢,验证:字面意思,准备:赋默认值,解析:符号引用转换为直接引用

    二 运行时数据区

    话不多说,看法宝,上图

    方法区

    存放:静态变量,常量,即时编译的class文件,类信息。
    区别:1.8之前叫Perm Space 永久代,现在叫Meta Space 元空间

    虚拟机栈

    存放:栈帧;即方法的调用,-Xss可以设置栈大小,默认1M;使栈溢出的使递归。

    构成:局部变量表;方法中定义的变量与方法的参数,

    操作数栈;压栈出栈存放数据的地方,

    动态链接;这个的作用就是知道谁调用的,比方说java中的多态,最后会知道具体是哪个类,
    方法返回地址;字面意思

    存放:对象及数组

    接下来咱们看一下这个指针指向问题

    栈指向堆; 栈帧(方法中有一个变量)即 Object obj = new Object();
    方法区指向堆;静态变量,private static Object obj = new Object();
    堆指向方法区;由于方法区中存放的类信息,所以对于多态如何识别,这一点,就说明堆中有指向方法区的指针。

    三 java对象内存布局

    四 jvm内存模型

    内存模型可以认为是运行时数据区的落地,那么当一个对象来的时候,如何分配内存空间呢

    首先放入Eden区,看够不够,不够,minorGC,再试试Survivor是否足够,如果不够;
    放入老年代看看够不够,不够就来一次Full GC(minorGC+MajorGC);
    如果还不够就OOM了。
    那么对象进入老年代的条件是什么呢

    新生代中年龄大于15;
    大对象(-XX:PretenureSizeThreshold 配置这个,大于这个数的就成为大对象)
    动态年龄:即survivor区中 同一年龄的超过了该区一半,那么大于等于该年龄的对象直接进入老年代
    minorGC,新生代放不下的时候
    那么这里边放了这么对象,该如何回收呢

    五 垃圾回收机制

    什么是垃圾,如何确定垃圾呢

    引用计数法

    没有任何指针指向的就是垃圾,但是无法解决循环引用的问题

    可达性分析

    由GCRoot(静态成员,Thread线程,虚拟机栈的变量表,本地方法栈中的变量,类加载器,常量)作为头,向下顺藤摸瓜,能摸得到的就是好瓜,摸不到的就回收扔了。

    既然已经确定了垃圾,那么如何回收呢

    四种垃圾回收算法

    标记-清除:将标记的清除掉,弊端就是内存不连续,容易产生内存碎片;
    复制:内存分两块,将一端复制到另一端,解决了内存不连续,弊端就是内存有效区只由一半;
    标记-整理:将垃圾回收后压缩整理一下,解决了内存有效区只有一半的问题;
    分代算法:个人认为这个属于一种思想,即对前三种的一种总结;老年代用标记清除,标记整理,新生代用复制
    算法说完了,那么算法的落地,如何实现的呢,这就要说到垃圾收集器了

    六.垃圾收集器

    可以看到从刚开始的Serial到现在的G1乃至ZGC的最多10ms停顿可以看到java一直在寻找最短的停顿时间,这个也是一直优化的方向。

    并行收集:多个线程一起收集

    并发收集:跟用户线程一起跑

    CMS和G1的区别有哪些呢?

    CMS,四个步骤为,初始标记-并发标记-重新标记-并发清理

    G1,四个步骤,初始标记-并发标记-最终标记-筛选回收(对各个Region的回收价值进行排序根据用户期望的GC停顿时间制定回收计划)

    G1可以设置停顿时间(-XX:MaxGCPauseMillis=20),就是因为他的Region,可以理解为一面墙分成了多个砖头,一些砖头的集合称为老年代,一些称为新生代。

    这些都知道了,那么出现错误该如何排查呢

    七 问题排查

    1.频繁FullGC

    导致频繁FullGC的原因有

    System.gc()
    jmap -dump:format=b,fifile=heap.hprof PID

    老年代内存不够
    步骤

    打印FullGC前后的日志 -XX:+HeapDumpBeforFullGC -XX:+HeapDumpAfterFullGC -XX:+HeapDumpPath=a.prof
    使用MAT工具进行分析,可以看堆中占用情况,以及class的新建情况。
    2.线上CPU负载过高排查

    采用TOP命令,查出占用cpu最高的java应用
    top -Hp PID查询出占用cpu最高的线程
    找出该线程ID,转换成16进制 printf "%x " tid
    jstack PID > d.txt
    打开d.txt,查询该16进制的tid就能找到了
    3.吞吐量调优

    使用命令打印出gc.log -XX:+PrintGCDetails -Xloggc:gc.log
    使用gcviewer来分析日志
    根据具体情况调整堆栈大小,停顿时间等参数,再看gcviewer分析出来的数据如何。
    4.死锁排查

    使用 java bin目录下自带的visualVM工具,可远程链接可本地链接
    连接之后,点击线程一栏,便会出现红字 发现死锁
    点击旁边的Dump按钮即可进入dump文件中,往下翻即可看到提示的哪一行出现了死锁,然后定位到代码

  • 相关阅读:
    Linux基本命令
    LR之流程
    Jmeter&Ant构建自动化测试平台
    正则表达式
    搭建wordpress-安装xshell
    git本地文件提交
    Git基本操作
    python-之基本语法
    SQL语句之-简单查询
    postman之请求&断言
  • 原文地址:https://www.cnblogs.com/lwh1019/p/13170209.html
Copyright © 2011-2022 走看看