面试4_JVM

本文详细介绍了JVM的类加载过程,包括加载、验证、准备、解析和初始化五个阶段。讲解了双亲委派模型及其优点,并讨论了哪些场景会破坏这一模型。此外,还涵盖了内存模型的各个区域,如程序计数器、虚拟机栈、本地方法栈、堆和方法区,以及对象的内存布局。同时,文章深入探讨了常量池的类型和垃圾回收的相关机制,包括判断方法、收集算法和GCRoots。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


参考链接:

  1. JVM 类加载机制
  2. 双亲委派模式的优点
  3. JVM 运行时数据区
  4. Java对象的内存布局
  5. Minor GC(Young GC)、Full GC、Major GC、Old GC
  6. JVM面试题一
  7. JVM面试题二
  8. 垃圾收集原理和垃圾收集器
  9. JVM面试题三

一、类加载过程

  • 其中验证、准备、解析3个部分统称为 连接
加载
验证
准备
解析
初始化
使用
卸载

加载: 寻找class的字节流文件,并导入,内存中生成 java.lang.Class 对象

  1. 通过一个类的全限定名来获取定义此类的二进制字节流
  2. 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构
  3. 内存中生成一个代表这个类的java.lang.Class 对象,作为方法区这个类的各种数据的访问入口。

验证:验证class字节流文件的正确性

  1. 文件格式验证
  2. 元数据验证
  3. 字节码验证
  4. 符号引用验证

准备:为static变量分配内存、设置零值

解析:常量池内的符号引用–>直接引用

解析动作主要针对类或接口、字段、类方法、接口方法、方法类型、方法句柄和调用点限定符这7类符号引用进行。

初始化:static变量、static代码块 初始化


二、类加载器类别

启动类加载器

  1. 加载<JAVA_HOME>\lib目录中且虚拟机识别的类库
  2. 或被-Xbootclasspath参数所指定的路径中的、且虚拟机识别的类库

扩展类加载器

  1. sun.misc.Launcher$ExtClassLoader实现
  2. 负责加载<JAVA_HOME>\lib\ext目录中的,或者被java.ext.dirs系统变量所指定的路径中的所有类库

应用程序类加载器(系统类加载器)

  1. sun.misc.Launcher$AppClassLoader实现
  2. 负责加载用户类路径(ClassPath)上所指定的类库

三、双亲委派模型

什么是双亲委派模型

如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到顶层的启动类加载器中,只有当父加载器反馈无法完成这个加载请求(它的搜索范围中没有找到所需的类)时,子加载器才尝试自己去加载


双亲委派模式的优点

  1. 避免重复加载
    1. Java 类随着它的类加载器一起具备了一种带有优先级的层次关系,可以避免类的重复加载。
  2. 避免核心库篡改
    1. 发现该类已被加载,并不会重新加载网络传递的过来的java.lang.Integer,而直接返回已加载过的Integer.class,这样便可以防止核心API库被随意篡改。

哪些场景破坏了双亲委派模型

  1. 线程上下文类加载器,典型的:JDBC 使用线程上下文类加载器加载 Driver 实现类

  2. Tomcat 的多 Web 应用程序

  3. OSGI 实现模块化热部署


为什么破坏双亲委派模型

以Tomcat 为例

Tomcat 容器可以同时部署多个 Web 应用程序,多个 Web 应用程序很容易存在依赖同一个 jar 包,但是版本不一样的情况。例如应用1和应用2都依赖了 spring ,应用1使用的 3.2.* 版本,而应用2使用的是 4.3.* 版本。

如果遵循双亲委派模型,很容易出现兼容性问题。

因此,Tomcat 只能选择破坏双亲委派模型。


如何破坏双亲委派模型

  1. 继承 ClassLoader,重写 loadClass 方法,实现自己的逻辑,不要每次都先委托给父类加载

  2. 上下文类加载器


四、内存模型(运行时数据区)

程序计数器

  1. 线程私有,当前线程所执行的字节码的行号指示器

  2. Java 方法(不是 native 的),正在执行的 Java 虚拟机字节码指令的地址。

  3. 本地(native)方法,空(undefined)。

Java虚拟机栈

  1. 存储栈帧:局部变量表、操作数栈、动态链接、方法出口等信息

本地方法栈

  1. 与 Java 虚拟机栈作用相似,为Native方法服务

  1. 线程共享,存储**类实例对象**

方法区

  1. 线程共享,存储**类加载信息、常量、static变量**

堆、栈区别

区别
物理地址不连续连续
内存运行期分配编译期分配
存放内容对象实例局部变量、操作数栈、方法出口等信息

Java对象的内存布局

  1. 对象头:包括堆对象的布局、类型、GC状态、同步状态和标识哈希码的基本信息。
    1. mark word 存储运行时数据
    2. klass pointer 类型指针 通过该指针来确定对象是哪个类的实例。
  2. 实例数据:存放类的数据信息,父类的信息,对象字段属性信息
  3. 对齐填充

五、常量池类型

class 文件常量池

  1. 存放编译期生成的各种字面量、符号引用
    1. 字面量:如文本字符串、声明为 final 的常量值
    2. 符号引用:以一组符号来描述所引用的目标

运行时常量池

  1. 运行时常量池是 class 文件中每一个类或接口的常量池表(constant_pool table)的运行时表示形式

字符串常量池(StringTable)

  1. 哈希表全局唯一、共享

运行时常量池、字符串常量池的关联

  1. 在字符串解析时会有关联
  2. CONSTANT_String_info类型的常量,经过解析(resolve)之后,同样存的是字符串的引用,并且和 StringTable 驻留的引用的是一致的。

六、四种引用

强引用

只要强引用还存在,就永远不会回收。

软引用

  1. 描述一些还有用但并非必需的对象
  2. 使用SoftReference类来实现软引用
  3. 在系统将要发生内存溢出异常之前,将会把这些对象列进回收范围之中进行第二次回收

弱引用

  1. 描述非必需对象的
  2. 使用WeakReference类来实现弱引用
  3. 被弱引用关联的对象只能生存到下一次垃圾收集发生之前

虚引用

  1. 使用PhantomReference类来实现虚引用
  2. 无法通过虚引用来取得一个对象实例
  3. 虚引用对象被收集器回收时收到一个系统通知

七、垃圾回收

7.1 垃圾判断方法

引用计数法
可达性分析算法:对象到GC Roots不可达时回收

7.2 垃圾收集算法

标记 - 清除算法
  1. 标记、清除效率都不高
  2. 产生大量不连续的内存碎片
复制算法
  1. 内存缩小为原来的一半
标记 - 整理算法
  1. 存活的对象向一端移动,然后直接清理掉端边界以外的内存。

7.3 Eden、From、To区比例

8:1:1

-XX:SurvivorRatio=8

7.4 MinGC / Young GC

  1. Eden满时触发
  2. Eden -> s0 复制算法
  3. s0 -> s1 复制算法,s0、s1之间复制15次的对象放入老年区

7.5 FullGC

  1. 触发机制
    1. 调用System.gc,但不必然执行
    2. 老年代满
    3. 方法区满
    4. MinGC后进入老年代的平均大小大于老年代的可用内存
    5. Eden、s0、s1复制时,对象大小大于To Space可用内存,则把该对象转存到老年代,且老年代的可用内存小于该对象大小

7.6 新生代 --> 老年代

  1. YoungGC对象太大放不进Survivor区
  2. s0、s1之间复制15次的对象
  3. Survivor中相同年龄所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代

7.7 Full GC后老年代空间变小?

  1. HotSpot的Full GC实现中,默认新生代里所有活的对象都要晋升到老年代,实在晋升不了才会留在新生代。

7.8 GC Root有哪些

  1. 虚拟机栈(栈帧中的本地变量表)中引用的对象。
  2. 方法区中类静态属性引用的对象
  3. 方法区中常量引用的对象
  4. 本地方法栈中JNI(即一般说的Native方法)引用的对象。

垃圾收集器

CMS

  1. 缺点:
    1. 对CPU资源非常敏感
    2. 无法处理浮动垃圾
    3. 内存碎片化

G1

  1. 特点
    1. 并行与并发
    2. 分代收集
    3. 空间整合
    4. 可预测的停顿
      1. 跟踪各个Region里面的垃圾堆积的价值大小
      2. 在后台维护一个优先列表
      3. 每次根据允许的收集时间,优先回收价值最大的Region

CMS、G1区别

区别CMSG1
区域老年代新生代、老年代
回收算法标记-清除(内存碎片化标记-整理
停顿时间最短停顿时间可建立可预测的停顿时间模型
回收步骤1. 初始标记
2. 并发标记
3. 重新标记
4. 并发清理
1. 初始标记
2. 并发标记
3. 最终标记
4. 筛选回收
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值