大厂面试必备(三)——JVM(Java虚拟机)

p#### 一、运行时数据区-帧栈详解
在这里插入图片描述
    完整的Java虚拟机是由三部分组成的:类装载子系统、运行时数据区(内存模型)、字节码执行引擎。其中运行时数据区包含了堆、栈(线程)、本地方法栈、方法区(元空间)、程序计数器。
    堆:堆是Java对象的存储区域,任何用new字段分配的Java对象实例和数组,都被分配在堆上,Java堆可使用-Xms -Xmx进行内存控制,值得一提的是从JDK1.7版本之后,运行时常量池从方法区移到了堆上。
    方法区:它用于存储已被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据,方法区在JDK1.7版本及以前被称为永久代,从JDK1.8永久代被移除。
    虚拟机栈:虚拟机栈中执行每个方法的时候,都会创建一个栈帧用于存储局部变量表,操作数栈,动态链接,方法出口等信息。
    本地方法栈:与虚拟机栈发挥的作用相似,相比于虚拟机栈为Java方法服务,本地方法栈为虚拟机使用的Native方法服务,执行每个本地方法的时候,都会创建一个栈帧用于存储局部变量表,操作数栈,动态链接,方法出口等信息。
    程序计数器:指示Java虚拟机下一条需要执行的字节码指令。
    栈的主要作用是放各个线程的局部变量。那么栈是如何存放这些局部变量的,这就涉及到另一个词——栈帧。比如一个类有多个方法,当一个线程执行到一个方法的时候,虚拟机会马上给这个方法分配一个独立的一块内存区域(即栈帧),一个方法对应一块栈帧内存区域。
在这里插入图片描述
    这里的栈也就是我们平时所说的数据结构的栈,符合先进后出的原则。如图,当线程执行main方法的时候,栈会分配一个栈帧存放main方法的局部变量。当main方法调用compute方法时,栈会分配一个栈帧存放compute方法的局部变量并且进栈。当compute方法执行结束后,存放compute方法局部变量的栈帧就会被销毁(出栈);接着mian方法会继续往后执行,当main方法执行结束后,main方法的栈帧才被销毁(出栈)。符合先进后出的规律。

二、堆

1、可达性分析算法

    将“GC Roots”对象作为起点,从这些节点开始向下搜索引用的对象,找到的对象都标记为非垃圾对象,其余未标记的对象都是垃圾对象。
    GC Roots根节点:线程栈的本地变量、静态变量、本地方法栈的变量等等。
在这里插入图片描述

2、垃圾回收机制在这里插入图片描述

    当对象刚创建的时候,会存放在Eden区;当Eden区内存空间不足的时候,会进行一次垃圾回收,即minor gc;有被引用的对象会通过复制算法移动到此时的From区,并且这些对象上的一个叫“分代年龄”的变量会加1,而不在引用链上的对象就会被回收。当进行第二次minor gc时,Eden区和From区上的有被引用的对象会通过复制算法被移动到To区,并且对象的“分代年龄”变量加1,没有被引用的对象被回收;此时,To区变成From区,From区变成To区;如此往复,当对象的“分代年龄”变量值为15时,该对象会被复制移动到老年代。(默认分代年龄15时会移动到老年代,但是这个值我们是可以修改的)
    那是不是老年代的对象就永远存在,不会被回收呢?其实,老年代的内存大小也是有限的,当老年代空间不足的时候,会进行一次full GC,对整个堆区域进行垃圾回收,如果回收过后还是空间不足,那么此时就会出现——内存溢出异常(java.lang.OutOfMemoryError)。
    每进行一次full GC的时候,线程都会被停止,出现STW(stop the word)现象(虽然minor gc也会STW,但是时间很短,用户几乎感知不到)。如果经常出现STW,用户体验是非常不好的,所以需要通过虚拟机调优来减少STW的出现。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章