Java虚拟机必知必会
763字约3分钟
2024-10-23
JVM的组成?
- 类加载器:用于加载 .class 文件并初始化类
- 内存区域:数据存放的模型
- 执行引擎:执行字节码
- 本地方法调用:调用 native 本地方法(C/C++)
类加载器如何加载一个类?
- 加载(读取.class二进制字节流,转换成方法区动态数据结构,堆中创建对象)
- 链接(校验、准备(静态变量赋默认值)、解析(符号引用->直接引用))
- 初始化(静态变量赋初值)
什么时候初始化 ?
- 遇到 new、getstatic、putstatic、invokestatic 字节码关键字
- 反射
- 父类未初始化先初始化父类
- 虚拟机启动时,主类
全盘负责双亲委派机制
- 当一个 classloader 加载一个类时,其依赖和引用也由这个类加载器加载
- 类加载器先委派父加载器加载,父加载器找不到目标类才由子加载器加载
好处?安全,保证所有基础的类都是由 RootClassLoader 来加载的。
有没有例外?有。线程上下文类加载器(Thread Context ClassLoader),父类加载器可以请求子类加载器去完成类加载的动作。
类加载器如何判断两个类相同?
- 类全限定名相同
- 加载该类的类加载器相同
JVM的内存模型
- 程序计数器(线程隔离)
- 本地方法栈(线程隔离)
- Java虚拟机栈(线程隔离)
- 堆(线程共享)
- 方法区(线程共享)(JDK1.8升级为元空间)
什么是动态链接?
.class文件中有很多符号引用,一部分在类加载的时候转化为直接引用(称为静态链接),另一部分在每一次运行期间转化为直接引用,这部分被称为动态链接。
垃圾回收算法
针对新生代,很多被清理,用标记-清除法,但效率低,碎片多。用复制算法较好(Eden、Survior1、Survior2)
复制算法先只使用 Eden、Survior1,垃圾回收的时候,把幸存的复制到 Survior2,然后清空 Eden和Survior1,之后只使用 Eden、Survior2 。
针对老年代,只有很少被清理,标记-整理算法。从GC Roots出发标记存活的对象,移动到内存的一端,将另一端全部清除。
哪些可以作为 GC-ROOT ?
- 类静态属性中引用的对象
- 常量引用的对象
- Java虚拟机栈和本地方法栈引用的对象
Java四种引用?
后三种引用只是可以让开发者通过代码方式来决定对象回收时机。一般不需要做调整,JVM GC 会为我们做垃圾回收。
- 强引用:new 对象,宁愿 OOM 也不回收
- 软引用:内存快不够时回收
- 弱引用:下一次GC就回收
- 虚引用:对象被回收时我们会收到一个通知