共计 2114 个字符,预计需要花费 6 分钟才能阅读完成。
整理一下 JVM 的面试题,别让自己在面试官面签懵逼了就好。。。
1. JVM 虚拟机
1.1 什么是 java 虚拟机
Java 虚拟机是一个可以执行 Java 字节码的虚拟机进程。Java 源文件被编译成能被 Java 虚拟机执行的字节码文件。
1.2 平台无关性
一次编译,到处执行(Write Once ,Run Anywhere)。
Java 被设计成允许应用程序可以运行在任意的平台,而不需要程序员为每一个平台单独重写或者是重新编译。Java 虚拟机让这个变为可能,因为它知道底层硬件平台的指令长度和其他特性。
1.3 JVM 的主要组成部分?及其作用?
- 类加载器(ClassLoader)
- 运行时数据区(Runtime Data Area)
- 执行引擎(Execution Engine)
- 本地库接口(Native Interface)
组件的作用:首先通过类加载器(ClassLoader)会把 Java 代码转换成字节码,运行时数据区(Runtime Data Area)再把字节码加载到内存中,而字节码文件只是 JVM 的一套指令集规范,并不能直接交个底层操作系统去执行,因此需要特定的命令解析器执行引擎(Execution Engine),将字节码翻译成底层系统指令,再交由 CPU 去执行,而这个过程中需要调用其他语言的本地库接口(Native Interface)来实现整个程序的功能。
1.4 引用的分类
- 强引用:GC 时不会被回收
- 软引用:描述有用但不是必须的对象,在发生内存溢出异常之前被回收
- 弱引用:描述有用但不是必须的对象,在下一次 GC 时被回收
- 虚引用(幽灵引用 / 幻影引用): 无法通过虚引用获得对象,用 PhantomReference 实现虚引用,虚引用用来在 GC 时返回一个通知。
1.5 垃圾回收机制算法
- 标记 - 清除算法,“标记 - 清除”(Mark-Sweep)算法,如它的名字一样,算法分为“标记”和“清除”两个阶段:首先标记出所有需要回收的对象,在标记完成后统一回收掉所有被标记的对象。
- 复制算法,“复制”(Copying)的收集算法,它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。
- 标记 - 压缩算法,标记过程仍然与“标记 - 清除”算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存
- 分代收集算法,“分代收集”(Generational Collection)算法,把 Java 堆分为新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法。
1.6 JVM 性能调优方法
- 设定堆内存大小
-Xmx:堆内存最大限制。
- 设定新生代大小。新生代不宜太小,否则会有大量对象涌入老年代
-XX:NewSize:新生代大小
-XX:NewRatio 新生代和老生代占比
-XX:SurvivorRatio:伊甸园空间和幸存者空间的占比 - 设定垃圾回收器
年轻代用 -XX:+UseParNewGC
老生代用 -XX:+UseConcMarkSweepGC
1.7 JVM 调优工具
常用调优工具分为两类:
- jdk 自带监控工具:jconsole 和 jvisualvm
- 第三方有:MAT(Memory Analyzer Tool)、GChisto。
详细描述为:
- jconsole,Java Monitoring and Management Console 是从 java5 开始,在 JDK 中自带的 java 监控和管理控制台,用于对 JVM 中内存,线程和类等的监控
- jvisualvm,jdk 自带全能工具,可以分析内存快照、线程快照;监控内存变化、GC 变化等。
- MAT,Memory Analyzer Tool,一个基于 Eclipse 的内存分析工具,是一个快速、功能丰富的 Java heap 分析工具,它可以帮助我们查找内存泄漏和减少内存消耗
- GChisto,一款专业分析 gc 日志的工具
1.8 么判断对象是否可以被回收
- 引用计数器:为每个对象创建一个引用计数,有对象引用时计数器 +1,引用被释放时计数 -1,当计数器为 0 时就可以被回收。它有一个缺点不能解决循环引用的问题;
- 可达性分析:从 GC Roots 开始向下搜索,搜索所走过的路径称为引用链。当一个对象到 GC Roots 没有任何引用链相连时,则证明此对象是可以被回收的。
1.9 什么是双亲委派机制
当某个类加载器需要加载某个.class 文件时,它首先把这个任务委托给他的上级类加载器,递归这个操作,如果上级的类加载器没有加载,自己才会去加载这个类。
1.10 双亲委派机制的作用
- 防止重复加载同一个.class。通过委托去向上面问一问,加载过了,就不用再加载一遍。保证数据安全。
- 保证核心.class 不能被篡改。通过委托方式,不会去篡改核心.class,即使篡改也不会去加载,即使加载也不会是同一个.class 对象了。不同的加载器加载同一个.class 也不是同一个 Class 对象。这样保证了 Class 执行安全。
1.11 堆栈
功能方面:堆是用来存放对象的,栈是用来执行程序的。
共享性:堆是线程共享的,栈是线程私有的。
空间大小:堆大小远远大于栈。
个人网站
http://www.zhouzhaodong.xyz
正文完