avatar

JVM的一些问题

一、 JVM的内存划分

二、 JAVA类加载的全过程是怎样的?什么是双亲委派机制?有什么作用?一个对象从加载到JVM,再到被GC清除,都经历了什么过程?

JAVA的类加载器: AppClassLoader->ExtClassloader -> BootStrap Classloader

每种类加载器都有他自己的加载目录

JAVA中的类加载器:AppClassLoader , ExtClassLoader -> URLClassLoader -> SecureClassLoader -> ClassLoader

每个类加载器对他加载过的类,都是有一个缓存的

双亲委派模型:向上委托查找,向下委托加载。 作用:保护Java的类不会被应用程序覆盖

类加载过程:

类加载过程: 加载 -> 连接 -> 初始化

加载: 把Java的字节码数据加载到JVM内存当中,并映射成JVM认可的数据结构。

连接:分为三个小的阶段: 1、 验证:检查加载到的字节信息是否符合JVM规则

2、 准备:创建类或者接口的静态变量,并赋初始值 半初始化状态

3、 解析:把符号引用转化为直接引用

初始化:

三、一个对象从加载到JVM,再到被GC清除都经历了什么

  1. 用户创建一个对象,JVM首先需要到方法去找对象的类型信息,然后再创建对象。
  2. JVM要实例化一个对象,首先要在堆当中先创建一个对象。->半初始化状态
  3. 对象首先会分配在堆内存中新生代的Eden。然后经过一次Minor GC,如果对象存活,就会进入S区。在后续的每次GC中,如果对象一直存活,就会在S区来回拷贝,每移动一次,年龄加1。->多大年龄才会移入老年代?年龄最大15,超过一定年龄后,对象转入老年代。
  4. 当方法执行结束后,栈中的指针会先移除掉。
  5. 堆中的对象,经过Full GC,就会被标记为垃圾,然后被GC线程清理掉。

怎么确定一个对象到底是不是垃圾?什么是Gc root

有两种定位垃圾的方式:

  1. 引用计数:这种方式是给堆内存当中的每个对象记录一个引用个数。引用个数为0的就认为是垃圾。这是早期JDK中使用的方式。引用计数无法解决循环引用的问题。

  2. 根可达算法:这种方式是在内存中,从引用根对象向下一直找引用,找不到的对象就是垃圾。

    哪些是GC Root?

    Stack -> JVM Stack , Native Stack ,Class类,run-time constant pool 常量池, static reference 静态变量。

    四、 JVM有哪些垃圾回收算法

    MarkSweep 标记清除算法

    这个算法分为两个阶段,标记阶段:把垃圾内存标记出来 清除阶段:直接将垃圾内存回收。

这种算法是比较简单的,但是有个严重的问题,会产生大量的内存碎片

Coping 拷贝算法

为了解决标记清除算法的内存碎片问题,就产生了拷贝算法。拷贝算法将内存氛围大小相等的两半,每次只使用其中一半。垃圾回收时,将当前这一块的存活对象全部拷贝到另一半,然后当前这一半就可以直接清除。

这种算法没有内存碎片,但是他的问题就在于浪费空间。而且,他的效率跟存活的对象个数有关。

MarkCompack 标记压缩算法

为了解决拷贝算法的缺陷,就引出了标记压缩算法。这种熟饭在标记阶段跟标记清除算法是一样的,但是在完成标记之后,不是直接清理垃圾内存,而是将存活对象往一端移动,然后将端边界以外的所有内存直接清除。

这三种算法各种利弊,各有适合的场景。

五、JVM有哪些垃圾回收器?他们都是怎么工作的?什么是STW?他们都发生在哪些阶段?什么是三色标记?如何解决错标记和漏标记的问题?为什么要设计那么多的垃圾回收器?

STW: Stop-The_World 是在垃圾回收算法执行过程当中,需要将JVM内存冻结的一种状态。在STW状态下啊,JAVA的所有线程都是停止执行的,GC线程除外,native方法可以执行,但是不能与JVM交互。GC各种算法优化的 重点,就是减少StW,同时这也是JVM调优的重点。

JVM的垃圾回收器:

文章作者: 无知的小狼
文章链接: https://bytedance.press/2021/04/05/20210401/JVM%E7%9A%84%E4%B8%80%E4%BA%9B%E9%97%AE%E9%A2%98/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 无知的小狼

评论