JVM面经
- 1. 介绍下 Java 内存区域(运行时数据区)?
- 2. Java 对象的创建过程(五步)?
- 3. 内存分配并发问题?
- 4. 对象的访问定位的两种方式(句柄和直接指针两种方式)
- 5. 对象的内存布局?
- 6. 如何判断对象是否死亡(两种方法)?
- 7. 简单的介绍一下强引用、软引用、弱引用、虚引用?
- 8. JVM 内存分配与回收?
- 9. 如何判断一个常量是废弃常量?
- 10. 如何判断一个类是无用的类?
- 11. 垃圾收集有哪些算法,各自的特点?
- 12. HotSpot 为什么要分为新生代和老年代?
- 13. 为什么要有Survivor区?
- 14. 为什么要加两个Survivor?
- 13. 常见的垃圾回收器有哪些?
- 14. 介绍一下 CMS,G1 收集器?
- 15. Minor Gc 和 Full GC 有什么不同呢?
- 16. 类加载过程?
- 17. 类加载器?
- 18. Class 文件结构总结?
- 19. 深拷贝和浅拷贝?
- 20. Java内存溢出五种OOM?
- 21. 简述分代垃圾回收器是怎么工作的?
- 22. JVM常见的参数配置?
1. 介绍下 Java 内存区域(运行时数据区)?
2. Java 对象的创建过程(五步)?
3. 内存分配并发问题?
4. 对象的访问定位的两种方式(句柄和直接指针两种方式)
5. 对象的内存布局?
6. 如何判断对象是否死亡(两种方法)?
7. 简单的介绍一下强引用、软引用、弱引用、虚引用?
8. JVM 内存分配与回收?
9. 如何判断一个常量是废弃常量?
- 运行时常量池主要回收的是废弃的常量。那么,我们如何判断一个常量是废弃常量呢?
- JDK1.7 之前运行时常量池逻辑包含字符串常量池存放在方法区, 此时 hotspot 虚拟机对方法区的实现为永久代
- JDK1.7 字符串常量池被从方法区拿到了堆中, 这里没有提到运行时常量池,也就是说字符串常量池被单独拿到堆,运行时常量池剩下的东西还在方法区, 也就是 hotspot 中的永久代 。
- JDK1.8 hotspot 移除了永久代用元空间(Metaspace)取而代之, 这时候字符串常量池还在堆, 运行时常量池还在方法区, 只不过方法区的实现从永久代变成了元空间(Metaspace)
- 假如在字符串常量池中存在字符串 “abc”,如果当前没有任何 String 对象引用该字符串常量的话,就说明常量 “abc” 就是废弃常量,如果这时发生内存回收的话而且有必要的话,“abc” 就会被系统清理出常量池了。
10. 如何判断一个类是无用的类?
-
方法区主要回收的是无用的类,那么如何判断一个类是无用的类的呢?
-
判定一个常量是否是“废弃常量”比较简单,而要判定一个类是否是“无用的类”的条件则相对苛刻许多。类需要同时满足下面 3 个条件才能算是 “无用的类” :
- 该类所有的实例都已经被回收,也就是 Java 堆中不存在该类的任何实例。
- 加载该类的 ClassLoader 已经被回收。
- 该类对应的 java.lang.Class 对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。
-
虚拟机可以对满足上述 3 个条件的无用类进行回收,这里说的仅仅是“可以”,而并不是和对象一样不使用了就会必然被回收。
11. 垃圾收集有哪些算法,各自的特点?
12. HotSpot 为什么要分为新生代和老年代?
- 因为有的对象寿命长,有的对象寿命短。应该将寿命长的对象放在一个区,寿命短的对象放在一个区。不同的区采用不同的垃圾收集算法。寿命短的区清理频次高一点,寿命长的区清理频次低一点。提高效率。
13. 为什么要有Survivor区?
- 如果没有Survivor区,那么Eden每次满了清理垃圾,存活的对象被迁移到老年区,老年区满了,就会触发Full GC,Full GC是非常耗时的,解决办法:
- 增加老年代内存,那么老年代清理频次减少,但清理一次花费时间更长。
- 减少老年代内存,老年代一次FullGC时间更少,频率增加。
- 都不行,只有再加一层Survivor。将Eden区满了的对象,添加到Survivor区,等对象反复清理几遍之后都没清理掉,再放到老年区,这样老年区的压力就会小很多。即Survivor相当于一个筛子,筛掉生命周期短的,将生命周期长的放到老年代区,减少老年代被清理的次数。
14. 为什么要加两个Survivor?
- 如果有三个区,这样就总可以保持一个是空的,这样我清理垃圾的时候,就可以将存活对象全部都整齐的放到一个空的内存中,不产生内存碎片了。
13. 常见的垃圾回收器有哪些?
14. 介绍一下 CMS,G1 收集器?
15. Minor Gc 和 Full GC 有什么不同呢?
-
Minor GC 是俗称,新生代(新生代分为一个 Eden区和两个Survivor区)的垃圾收集叫做 Minor GC。当 Eden 区的空间耗尽了怎么办?这个时候 Java虚拟机便会触发一次 Minor GC来收集新生代的垃圾,存活下来的对象,则会被送到 Survivor区。
-
Full GC 就是收集整个堆,包括新生代,老年代,永久代(在JDK 1.8及以后,永久代会被移除,换为metaspace)等收集所有部分的模式
-
Major GC通常是跟full GC是等价的,收集整个GC堆,但因为 HotSpot VM发展这么多年,外界对各种名词的解读已经完全混乱了,当有人说"Major GC"的时候一定要问清楚他想要指的是上面的 full GC还是 old GC
16. 类加载过程?
17. 类加载器?
18. Class 文件结构总结?
19. 深拷贝和浅拷贝?
-
浅拷贝(shallowCopy)只是增加了一个指针指向已存在的内存地址,
-
深拷贝(deepCopy)是增加了一个指针并且申请了一个新的内存,使这个增加的指针指向这个新的内存,
-
使用深拷贝的情况下,释放内存的时候不会因为出现浅拷贝时释放同一个内存的错误。
-
浅复制:仅仅是指向被复制的内存地址,如果原地址发生改变,那么浅复制出来的对象也会相应的改变。
-
深复制:在计算机中开辟一块新的内存地址用于存放复制的对象。
20. Java内存溢出五种OOM?
21. 简述分代垃圾回收器是怎么工作的?
-
分代回收器有两个分区:老生代和新生代,新生代默认的空间占比总空间的 1/3,老生代的默认占比是 2/3。
-
新生代使用的是复制算法,新生代里有 3 个分区:Eden、To Survivor、From Survivor,它们的默认占比是 8:1:1,它的执行流程如下:
-
把 Eden + From Survivor 存活的对象放入 To Survivor 区;
- 清空 Eden 和 From Survivor 分区;
- From Survivor 和 To Survivor 分区交换,From Survivor 变 To Survivor,To Survivor 变 From Survivor。
- 每次在 From Survivor 到 To Survivor 移动时都存活的对象,年龄就 +1,当年龄到达 15(默认配置是 15)时,升级为老生代。大对象也会直接进入老生代。
-
老生代当空间占用到达某个值之后就会触发全局垃圾收回,一般使用标记整理的执行算法。以上这些循环往复就构成了整个分代垃圾回收的整体执行流程。
22. JVM常见的参数配置?
23. 调优命令有哪些?
-
jps,JVM Process Status Tool,显示指定系统内所有的HotSpot虚拟机进程。
-
jstat,JVM statistics Monitoring是用于监视虚拟机运行时状态信息的命令,它可以显示出虚拟机进程中的类装载、内存、垃圾收集、JIT编译等运行数据。
-
jmap,JVM Memory Map命令用于生成heap dump文件
-
jhat,JVM Heap Analysis Tool命令是与jmap搭配使用,用来分析jmap生成的dump,jhat内置了一个微型的HTTP/HTML服务器,生成dump的分析结果后,可以在浏览器中查看
-
jstack,用于生成java虚拟机当前时刻的线程快照。
-
jinfo,JVM Configuration info 这个命令作用是实时查看和调整虚拟机运行参数
本文详细探讨了Java内存区域、对象创建过程、并发内存分配、对象访问与布局、对象死亡判断、引用类型、内存分配回收、常量与类判断、垃圾收集算法、新生代与老年代设计、Survivor区作用、常见垃圾回收器、类加载与调优等内容,助你理解JVM内存管理的复杂性。


被折叠的 条评论
为什么被折叠?



