Java虚拟机—JVM(面试)

作者:加菲猫 2018-06-18 334 0

JVM 特性

平台无关性,在不同平台上运行不需要重新编译,JVM 在执行字节码时,会把字节码解释成具体平台上的机器指令。

JVM 内存模型

方法区(线程共享):常量、静态变量、JIT(即时编译器)编译后的代码。

堆内存(线程共享):垃圾回收的主要场所。

程序计数器:当前线程执行的字节码的位置指示器。

虚拟机栈(栈内存):局部变量、基本数据类型变量、堆内存中对象的引用变量。

本地方法栈:为 JVM 提供使用 native 方法的服务。

堆和栈的区别

栈常用于保存方法桢和局部变量,而对象总是在堆上。栈通常比堆小,也不会在多个线程间共享,堆被整个 JVM 的所有线程共享。

JVM 的内存分配

基本数据类型比变量和对象的引用都是在栈分配的。

堆内存用来存放由 new 创建的对象和数组。

类变量(static 修饰的变量),程序在一加载的时候就在堆中为类变量分配内存,堆中的内存地址存放在栈中。

实例变量:当使用 new 的时候,系统在堆中开辟并不一定是连续的空间分配给变量,是根据零散的堆内存地址,通过哈希算法换算为一长串数字,作为这个变量在堆中的物理位置。 当实例变量的引用丢失后,将被 GC 列入可回收名单中,但并不是马上就释放堆中的内存。

局部变量: 声明在方法或代码段里,执行到它的时候在栈中开辟内存,当局部变量脱离作用域,内存立即释放。

什么情况下会出现内存溢出,内存泄漏?

Java 线程栈

JVM 新生代到年老代的晋升过程的判断条件是什么?

JVM 出现 fullGC 很频繁,怎么去线上排查问题?

类加载为什么要使用双亲委派模式?有没有什么场景是打破了这个模式的?

类的实例化顺序

先静态方法,后构造方法。先父类,后子类。

JVM 的垃圾回收机制,何时触发 MinorGC、FullGC 等操作?

垃圾回收机制最基本的做法是分代回收。内存中的区域被划分成不同的世代(新生、老年、永久),对象根据存活的时间被保存到对应世代的区域中。在新生代分配内存,经过几轮 GC 还存活的对象,会被复制到老年代中。永久代用来保存类信息、代码段等不变的数据。

MinorGC:新生代又分为 Eden 区和 Survivor 区,当 Eden 区满时,会触发 MinorGC 操作。

FullGC 的触发条件:

  • 调用 System.gc() 时,系统建议执行 FullGC,但不是必须的。

  • 老年代空间不足。

  • 方法区空间不足。

  • 通过 MinorGC 后进入老年代的大小 > 老年代的可用内存。

  • 由 Eden 区和 From Space 区向 To Space 区复制时,对象大小 > To Space 可用内存,则把该对象转存到老年代,且老年代的可用内存 < 该对象大小。

JVM 中一次完整的 GC 流程(从 ygc 到 fgc)

各种回收器的优缺点(重点 CMS、G1)

垃圾回收算法

标记-清除:图书馆里有很多人在看书,管理员想要收集不被看的书,于是他让所有同学起立,询问每个人哪本书是不看的,并标记下来。询问完所有人后,同学们坐下继续看书,管理员再查找做过标记的书,把它们收集起来。

  • 每次进行垃圾回收时,会暂停程序的运行。(让所有同学起立)

  • 需要间隔性的检查,标记和清除的过程相对较慢。

  • 在标记清除后,可能会产生大量的内存碎片,导致需要为大对象分配空间时,由于找不到足够大的内存空间,而不得不引发另一次 GC 过程。

标记-复制:管理员为了更好的发现不被看的书,将图书馆一分为二(A 区和 B 区),同一时刻只有一块区域允许看书。一开始 A 区开放,当管理员想要回收 A 区没有人看的书时,广播通知“正在看书的同学拿着你的书到 B 区”。等所有同学都到了 B 区,管理员只要把 A 区剩下的书收集起来,就完成了工作。下次回收的时候,再让看书的同学到 A 区,如此循环往复即可。

  • 可用空间被缩小为原来的一半,空间利用率降低了。

  • 回收过程中会暂停程序的运行。

标记-整理:标记过程与“标记-清除”中的标记一样,整理过程是让存活的对象都向另一端移动,然后直接清理掉边界以外的内容。

  • 回收过程中会暂停程序的运行。

  • 不是实时的。

分代回收:根据对象生命周期中的不同状态,选择不同的回收算法。

  • 新生代:标记-复制。每次回收都会有大量对象死去。

  • 老年代:标记-清除 / 标记-整理。大部分对象都处在存活状态,再有大对象需要分配内存,又没有外部内存空间。

  • 永久代:不回收。

如何判断一个对象是否应该被回收?

对象存活性判断的常用方法有两种:引用计数法、对象可达性分析。

由于引用计数法存在互相引用导致无法进行 GC 的问题,所以 JVM 多使用对象可达性分析算法。

调用 System.gc() 会发生什么?

通知 GC 开始工作,但 GC 真正开始的时间不确定。

OOM 错误、stackoverflow 错误、permgen space 错误

发表评论

下一篇: 上一篇: