文章目录
1 JVM内存模型及分区
JVM分为堆区、栈区(虚拟机栈和本地方法栈)、方法区、程序计数器
- 堆:存放对象实例,垃圾回收主要针对堆区。
- 虚拟机栈:描述方法执行的内存模型,每个方法执行时创建一个栈帧存放方法的局部变量表、操作数栈、返回地址等信息。
- 本地方法栈:为本地方法服务。
- 方法区:存储被虚拟机加载的类信息、常量、静态变量等数据。
- 程序计数器:记录当前线程执行的行号。
2 Java类加载过程
加载
验证
准备
解析
初始化
- 加载
- 通过全类名获取类的二进制字节流
- 将二进制字节流中的静态存储结构转化为方法区的运行是数据结构
- 在内存中生成类的Class对象,作为该类的数据访问入口
- 验证
- 文件格式验证
- 元数据验证
- 字节码验证
- 符号引入验证
- 准备:在方法区内为类变量分配内存并设置为0值
- 解析:将符号引用转化为直接引用
- 初始化:真正初始化,开始执行类中定义的Java程序
3 什么是类加载器?
- 实现通过类的全限定名获取该类二进制字节流的代码
4 都有哪些类加载器?
- 启动类加载器(BootstrapClassLoader)用来加载Java核心类库,无法被Java程序直接引用
- 扩展类加载器(ExtensionClassLoader)用来加载Java扩展库,JVM会提供一个目录(/lib/ext)
- 系统类加载器(SystemClassLoader)根据Java应用的类路径来加载Java类,一般Java应用类都是由它完成的。
- 用户自定义类加载器,通过继承java.lang.ClassLoader类的方式实现
5 简述双亲委派机制及其优点
当一个类收到类加载请求时,首先判断当前类是否被加载过,若加载过则直接返回。若没被加载过,首先将类加载请求转发给父类加载器,一直转发到启动类加载器,当父类无法完成时由自己加载。
优点:
- 避免类的重复加载。相同的类被不同的类加载器加载会产生不同的类,双亲委派保证了java程序的稳定运行。
- 保护程序安全,保证核心API不被修改。
6 简述Java垃圾回收机制
- GC是垃圾收集的意思(Gabage Collection),Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的.
- 在java中,程序员是不需要显式的去释放一个对象的内存的,而是由虚拟机自行执行。
- 在JVM中,有一个垃圾回收线程,它是低优先级的,在正常情况下是不会执行的,只有在虚拟机空闲或者当前堆内存不足时,才会触发执行,扫描那些没有被任何引用的对象,并将它们添加到要回收的集合中,进行回收。
7 判断对象是否存活(GC对象的判定方法)
引用计数法
可达性算法
- 引用计数法
设置引用计数器,对象被引用计数器加 1,引用失效时计数器减 1,如果计数器为 0 则被标记为垃圾。会存在对象间循环引用的问题,一般不使用这种方法。 - 可达性算法
通过 GC Roots 的根对象作为起始节点,从这些节点开始,根据引用关系向下搜索,如果某个对象没有被搜到,则会被标记为垃圾。
可作为 GC Roots 的对象包括虚拟机栈和本地方法栈中引用的对象、类静态属性引用的对象、常量引用的对象。
8 垃圾回收方法
- 标记清除算法:先标记需清除的对象,之后统一回收。这种方法效率不高,会产生大量不连续的碎片,导致以后程序在分配较大的对象时,由于没有充足的连续内存而提前触发一次GC动作。
- 标记复制算法:将可用内存按容量划分为大小相等的两块,每次只使用其中一块。当使用的这块空间用完了,就将存活对象复制到另一块,再把已使用过的内存空间一次清理掉。内存浪费严重。
- 标记整理算法:先标记存活对象,然后让所有存活对象向一端移动,之后清理端边界以外的内存。
- 分代收集算法:根据对象的生存周期,将堆分为新生代和老年代。
在新生代中,由于对象生存期短,每次回收都会有大量对象死去,那么这时就采用复制算法。
老年代里的对象存活率较高,没有额外的空间进行分配担保,所以可以使用标记-整理 或者 标记-清除。
9 垃圾回收优点:有效防止内存泄漏
内存泄露就是指一个不再被程序使用的对象或变量一直被占据在内存中。
10 Java 中的内存泄露的情况
长生命周期的对象持有短生命周期对象的引用就很可能发生内存泄露,尽管短生命周期对象已经不再需要,但是因为长生命周期对象持有它的引用而导致不能被回收,这就是 Java 中内存泄露的发生场景。
通俗地说,就是程序员可能创建了一个对象,以后一直不再使用这个对象,这个对象却一直被引用,即这个对象无用但是却无法被垃圾回收器回收的,这就是 java 中可能出现内存泄露的情况,例如,缓存系统,我们加载了一个对象放在缓存中 (例如放在一个全局 map 对象中),然后一直不再使用它,这个对象一直被缓存引用,但却不再被使用。
11 简述Java引用类型
- 强引用:被强引用关联的对象不会被回收。一般采用 new 方法创建强引用。
- 弱引用:垃圾收集器碰到即回收,也就是说它只能存活到下一次垃圾回收发生之前。一般采用WeakReference 类来创建弱引用。
- 软引用:被软引用关联的对象只有在内存不够的情况下才会被回收。一般采用 SoftReference 类来创建软引用。
- 虚引用:无法通过该引用获取对象。唯一目的就是为了能在对象被回收时收到一个系统通知。虚引用必须与引用队列联合使用。