Java常见面试题(二)Java虚拟机(JVM)相关,长期更新中....

1、谈谈 JVM 内存区域的划分?

  • 堆(Heap),它是 Java 内存管理的核心区域,是线程共享的一块内存区域,用来放置 Java 对象实例,几乎所有创建的 Java 对象实例都是被直接分配在堆上。堆被所有的线程共享,在虚拟机启动时,我们指定的“Xmx”之类参数就是用来指定最大堆空间等指标。
  • 方法区(Method Area)。这也是所有线程共享的一块内存区域,用于存储所谓的元(Meta)数据,例如类结构信息,以及对应的运行时常量池、字段、方法代码等。
  • Java 虚拟机栈(Java Virtual Machine Stack),早期也叫 Java 栈。每个线程在创建时都会创建一个虚拟机栈,其内部保存一个个的栈帧(Stack Frame),对应着一次次的 Java 方法调用。
  • 本地方法栈(Native Method Stack)。它和 Java 虚拟机栈是非常相似的,支持对本地方法的调用,也是每个线程都会创建一个 。PS:在 Oracle Hotspot JVM 中,本地方法栈和 Java 虚拟机栈是在同一块儿区域,这完全取决于技术实现的决定,并未在规范中强制。
  • 程序计数器(PC,Program Counter Register)。在 JVM 规范中,每个线程都有它自己的程序计数器,并且任何时间一个线程都只有一个方法在执行,也就是所谓的当前方法。程序计数器会存储当前线程正在执行的 Java 方法的 JVM 指令地址。
    在这里插入图片描述
    PS:运行时常量池(Run-Time Constant Pool),是方法区的一部分,常量池可以存放各种常量信息,不管是编译期生成的各种字面量,还是需要在运行时决定的符号引用。

2、JVM 哪些区域可能发生 OutOfMemoryError(OOM)?

OutOfMemoryError (OOM)通俗点儿说,就是 JVM 内存不够用了,没有空闲内存,并且垃圾收集器也无法提供更多内存。在抛出 OutOfMemoryError 之前,通常垃圾收集器会被触发,尽其所能去清理出空间。
除了程序计数器,其他区域都有可能会因为可能的空间不足发生 OutOfMemoryError,简单总结如下:

  • 堆(Heap)内存不足是最常见的 OOM 原因之一,抛出的错误信息是“java.lang.OutOfMemoryError:Java heap space”,原因可能千奇百怪,例如,可能存在内存泄漏问题;也很有可能就是堆的大小不合理,比如我们要处理比较大的数据量,但是没有显式指定 JVM 堆大小或者指定数值偏小;或者出现 JVM 处理引用不及时,导致堆积起来,内存无法释放等。
  • Java 虚拟机栈和本地方法栈,
  • 而对于 Java 虚拟机栈本地方法栈,这里要稍微复杂一点。如果我们写一段程序不断的进行递归调用,而且没有退出条件,就会导致不断地进行压栈。类似这种情况,JVM 实际会抛出 StackOverFlowError,如果 JVM 试图去扩展栈空间的的时候失败,则会抛出 OutOfMemoryError。
  • 对于JDK1.8之前的版本,因为永久代的大小是有限的,并且 JVM 对永久代垃圾回收(如,常量池回收、卸载不再需要的类型)非常不积极,所以当我们不断添加新类型的时候,永久代出现 OutOfMemoryError 也非常多见,尤其是在运行时存在大量动态类型生成的场合,对应的异常信息,会标记出来和永久代相关:java.lang.OutOfMemoryError: PermGen space
  • JDK1.8引入元数据区,方法区内存已经不再那么窘迫,所以相应的 OOM 有所改观,出现 OOM,异常信息则变成了:java.lang.OutOfMemoryError: Metaspace

3、如何监控和诊断 JVM 堆内和堆外内存使用?

这两篇文章总结的不错:https://www.cnblogs.com/ysocean/p/11311667.html
https://www.cnblogs.com/ysocean/p/11415514.html

4、Java 常见的垃圾收集器有哪些?

参考:https://www.cnblogs.com/ysocean/p/11117365.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章