JVM基础探究

JVM探究

  • 请你谈谈你对JVM的理解?java8虚拟机和之前的变化更新?
  • 什么是OOM,什么是栈溢出StackOverFlowError?怎么分析?
  • JVM的常用调优参数有哪些?
  • 内存 快照如何抓取,怎么分析Dump文件?
  • 谈谈JVM中,你对类加载器的认识?
  1. JVM的位置

  2. JVM的体系结构

  3. 类加载器

    1. 虚拟机自带的加载器

    2. 启动类加载器(根加载器)rt.jar包

    3. 扩展类加载器 /lib/ext,父类加载器为null。null的原因是java访问不到,因为java的基层是用C、C++写的。

    4. 应用程序加载器 ,父加载器为扩展类加载器

  4. 双亲委派机制

即用一个类时,会向上委托,一直到根加载器,若找到就用根加载器中的类,找不到就抛出异常,在子类即扩展类加载器中找,找到就用,找不到就再向下,层层递进,直到找到,若最后都没找到就抛出一个ClassNotFound。

  1. 沙箱安全机制

  2. Native

    1. 凡是带了native关键字的,表名java作用范围达不到了,需要调用底层C语言库。会进入本地方法栈,调用本地方法接口(JNI)

    2. JNI的作用是扩展java的使用,融合不同的语言为java使用。最初是融合C和C++。

    3. java诞生的时候C和C++横行,想要立足,必须调用C和C++程序,因此,在内存中专门开辟了一块标记区域:Native Method Area,登记native方法,最终在执行的时候通过JNI加载本地方法库中的方法

  3. PC寄存器

    程序计数器:每个线程都有一个程序计数器,是线程私有的,就是一个指针,指向方法区中的方法字节码(用来存储指向一条指令的地址,也即将要执行的指令代码),再执行引擎读向下一条指令,是一个非常小的空间,几乎可以忽略不计。

  4. 方法区(Method Area)

    方法区是被所有线程共享,所有字段和方法字节码,以及一些特殊方法,如构造函数,接口代码也在此定义,简单说,所有定义方法的信息都保存在该区域,该区域属于共享区间。

    静态方法、常量、类信息(构造函数,接口定义),运行时的常量池存在方法区中,但是实例变量存在堆内存中,和方法区无关。

    static、final、Class、常量池

  5. 栈:先进后出(桶)

    队列:先进先出(FIFO)

    栈内存,主要负责程序的运行,生命周期和线程同步,线程结束,栈也就释放内存,对于栈来说不存在垃圾回收。

    栈:8大基本类型+对象引用+实例的方法

    栈满了:StackOverflowError

  6. 三种JVM

    • sun公司的Hotspot

    • BEA: JRockit

    • IBM: J9 Vm

  7. 堆(Heap)

    • 一个JVM只有一个堆内存,堆内存的大小是可以调节的。

    类加载器读取了类文件后,一般会把什么东西放到堆中?类、方法、常量、变量~,保存引用类型的真是对象;

    • 新生区(伊甸园区)Young/New

    • 养老区 Old

    • 永久区

      • 说明:一般垃圾回收回收新生区的伊甸园区,而经历了垃圾回收没有被回收的就会进入幸存区(幸存0区和幸存1区也是不断交换的而不是固定的)。而在幸存区定了一个次数(例30次),若在经历30次的垃圾回收后,就会进入老年区。一般GC垃圾回收发生在伊甸园区和老年区。

      • 堆内存满了:OOM

      • JDK8以后,永久区改名为元空间

  8. 新生区、老年区

    新生区:

    • 类:诞生和成长的地方,甚至死亡
    • 伊甸园:所有的对象都是在伊甸园区new出来的
    • 幸存者去(0,1)

    ​ 过程:假设伊甸园区有10个空间,当伊甸园区满了之后,就会触发一次轻GC,将没有引用的对象回收,而还有引用的对象就会进入幸存者区,当幸存者区也满了之后,就会触发一次重GC,将伊甸园区和幸存者区都清一遍,幸存下来的进入老年区,当老年区经历多次重GC后也满了,就会出现OOM。

    经研究:99%对象都是临时对象

  9. 永久区

    这个区域常驻内存的,用来存放Java自带的Class对象,Interface元数据。存储的都是Java运行时的一些环境或类信息,一般不存在垃圾回收,在关闭JVM的时候就会释放这个区域的内存。

    永久区什么时候会崩掉呢?

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

  10. 堆内存调优

    -Xms:设置初始化内存大小,默认1/4

    -Xmx:设置最大分配内存,默认1/64

    -Xms1024m -Xmx1024m -XX:+PrintGCDetailse:打印GC垃圾回收信息

    -Xms1m -Xmx8m -XX:+HeapDumpOnOutOfMemoryError:OOM的Dump

  11. GC

    GC垃圾回收并不是对这三个统一回收,GC垃圾回收发生在新生代与老年代,其中大部分在新生代。

    • 新生代
    • 幸存区(from,to)
    • 老年区

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

    GC题目:

    • JVM的内存模型和分区,详细到每个区放什么?

    • 堆里面的分区有哪些?Eden,from,to,老年区,说说他们的特点。

    • GC的算法有哪些?标记清除法,标记压缩,复制算法,引用计数器,怎么用的?

      引用计数法:

      计数器进行计数,对象C被引用0次,所以会被清除出去。

      复制算法:

      复制算法就是将幸存区中一个里面的数据复制到另一个里面,这时,空的那个就变成to区。这个算法是为了保证to区永远干净。

      • 好处:没有内存碎片
      • 缺点:浪费了内存空间。永远有一半空间是空的(to区)

      复制算法的最佳使用场景:对象存活度较低的时候。

    • 标记清除算法

      对内存中的对象进行扫描,对存活的对象进行标记,然后将没有标记的对象进行清除。

      优点:不需要额外的空间

      缺点:两次扫描,浪费时间,且会产生内存碎片。

    • 标记压缩(也称标记清除压缩)

      在标记清除的基础上,再次扫描,向一端移动存活对象。但多了一个移动成本。

    • 轻GC和重GC分别在什么时候发生?

    总结:

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

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

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

    年轻代:

    • 存活率低
    • 复制算法

    老年代:

    • 标记清除
  12. JMM(Java Memory Model:Java内存模型)

    1. 什么是JMM

    2. 它干嘛的?(官方、其他人的博客、对应的视频)

      作用:缓存一致性协议,用于定义数据读写规则。(遵守,找到这个规则)

    3. 它该如何学习?

posted @ 2020-07-08 12:15  我是橘子  阅读(119)  评论(0编辑  收藏  举报