一、JVM介绍

  1. 什么是JVM?Java 虚拟机(JVM)是运行 Java 字节码的虚拟机。屏蔽了底层操作系统的差距,使得java程序能够“一次编译,随处可以运行”。

  2. JVM的组成部分有哪些?JVM由类加载器、运行时数据区、执行引擎等组成。

  3. 类加载器有哪些?类加载器分为启动类加载器、扩展类加载器和应用程序类加载器

  4. 运行时数据区包括哪些部分?运行时数据区包括方法区、堆、栈、程序计数器和本地方法栈等部分。

  5. 什么是垃圾回收?垃圾回收是JVM的一项重要功能,它负责在程序运行时自动回收不再使用的内存空间。

  6. 垃圾回收算法有哪些?垃圾回收算法包括标记-清除算法、标记-复制算法、标记-整理算法和分代收集算法等。

  7. 什么是类加载机制?类加载机制是指JVM将类的字节码从磁盘加载到内存,并进行链接和初始化的过程

  8. 什么是内存泄漏?内存泄漏是指程序中的某个对象占用的内存空间无法被垃圾回收器回收,导致内存使用率持续增加,最终导致内存溢出

 在字节码转变为机器码这一步 JVM 类加载器首先加载字节码文件,然后通过解释器逐行解释执行

 

三、编译型&解释型语言

1、编译型语言:编译器一次性把源代码转变为机器码。执行速度快,开发效率低。例如c++,c

2、解释型语言:解释器一句一句将源代码翻译成机器码,执行速度慢,开发效率高,例如python,PHP

 

四、Java内存区域

五大区域:堆、方法区、虚拟机栈、本地方法栈以及程序计数器

1、堆和方法区是线程共享的。

1)堆存放的是对象,也是GC垃圾回收的区域。分为三部分:新生代、老年代、永久代。而新生代又分为eden、s0、s1三部分。

大部分情况下,新对象会先在eden区分配内存,在一次垃圾回收后,如果该对象还存活则会进入s0或者s1,并且对象的年龄加1,当年龄超过15,则会晋升到老年代

 2)方法区:存放静态变量、常量以及类信息

2、程序计数器、栈是线程独有的

1)程序计数器:记录下一条要执行的指令

2)栈:由一个个栈帧组成,栈帧存放的是局部变量以及动态链接、操作数栈

 

五、对象创建过程

第一步:类加载检查,若未加载则先进行类加载过程

第二步:分配内存,有两种方式:指针碰撞和空闲链表

第三步:初始化零值

第四步:设置对象头,表示该对象是哪个类,以及类的元信息等

第五步:执行初始化方法,这样一个对象才算生产出来了

 

六、类加载过程

1、加载:加载 Java 类的字节码( .class 文件)到 JVM 中,并生成一个class对象。主要是通过类加载器完成的,具体使用哪个类加载器是由双亲委派模型决定的。

2、连接:分为验证、准备、解析三步。验证就是验证class文件的合法性和安全性;准备是为类的静态变量分配内存并设置初始值;解析是将常量池的符号引用替换为直接引用的过程。

3、初始化

 

七、类加载器

作用:加载 Java 类的字节码( .class 文件)到 JVM 中,并生成一个class对象。

JVM 中内置了三个重要的 ClassLoader

  1. BootstrapClassLoader(启动类加载器):最顶层的加载类,由 C++实现,通常表示为 null,并且没有父级,主要用来加载 JDK 内部的核心类库( %JAVA_HOME%/lib目录下的 rt.jarresources.jarcharsets.jar等 jar 包和类)以及被 -Xbootclasspath参数指定的路径下的所有类。
  2. ExtensionClassLoader(扩展类加载器):主要负责加载 %JRE_HOME%/lib/ext 目录下的 jar 包和类以及被 java.ext.dirs 系统变量所指定的路径下的所有类。
  3. AppClassLoader(应用程序类加载器):面向我们用户的加载器,负责加载当前应用 classpath 下的所有 jar 包和类。

除了这三种类加载器之外,用户还可以加入自定义的类加载器来进行拓展。

双亲委派模型的过程:当要加载一个类时,他首先不会自己去加载,而是将加载的请求委派给父类,自底向上查找并判断类是否被加载,如果未加载则自顶向下尝试加载类

 双亲委派模型保证了 Java 程序的稳定运行,可以避免类的重复加载。

打破双亲委派模型则需要自定义一个类加载器并且重写 loadClass() 方法。

八、垃圾回收

1、GC分类

部分收集 (Partial GC):

  • 新生代收集(Minor GC / Young GC):只对新生代进行垃圾收集;
  • 老年代收集(Major GC / Old GC):只对老年代进行垃圾收集。需要注意的是 Major GC 在有的语境中也用于指代整堆收集;
  • 混合收集(Mixed GC):对整个新生代和部分老年代进行垃圾收集。

整堆收集 (Full GC):收集整个 Java 堆和方法区

 

2、对象死亡判断方法

1、引用计数法

给对象中添加一个引用计数器,当有一个地方引用它,计数器加一,引用失效则减一,计数器为0时则回收

2、可达性分析

根据一系列GC roots作为起点,从这些节点开始往下搜索,节点走过的路径称为引用链,当一个对象到GC roots没有任何引用链则说明此对象要回收

GC roots有哪些:

  • 虚拟机栈(栈帧中的本地变量表)中引用的对象
  • 本地方法栈(Native 方法)中引用的对象
  • 方法区中类静态属性引用的对象
  • 方法区中常量引用的对象
  • 所有被同步锁持有的对象

 

3、垃圾清除算法

1)标记-清除算法:分为标记清除两个阶段,首先标记所有不需要回收的对象,然后再标记完成后统一回收没有被标记的对象。会产生大量的内存碎片

2)标记-复制算法:将内存分为两块,每次只使用其中的一块。当一块内存使用完后,把还存活的对象移到另一块,然后再把这块内存清空

3)标记-整理算法:分为标记和整理两阶段,首先标记所有不需要回收的对象,再把这些对象往一端移动,然后清理掉边界外的内存。适合老年代

4)分代收集算法:新生代选择标记-复制算法,老年代选择标记-清除或者标记整理算法

 

4、垃圾收集器

1)serial串行收集器:单线程收集器,在垃圾回收过程中其他线程必须暂停。新生代采用标记-复制算法,老年代采用标记-整理算法。

2)CMS收集器:并发收集器,使得垃圾回收线程和用户线程可以同时工作。CMS 收集器是一种 “标记-清除”算法实现的,具体过程如下:

第一步:初始标记,暂停其他线程,记录与root相连的对象

第二步:并发标记,同时开启垃圾回收线程和用户线程,不断更新可达的对象

第三步:重新标记,修正标记记录

第四步:并发清除,回收未被标记的对象