logo头像
Snippet 博客主题

Java八股文查漏补缺-JVM-1-内存区域模型

0 写在前面

  Java八股文查漏补缺系列是针对Java八股复习时,针对在面试时候,问的问题可能比较深入,在JavaGuide网站中的一些八股文可能不够用,根据自己的面试经验进行一些学习补充.

  八股文背不如理解,理解深刻,知道底层原理,才能更加牢固。呜呜!直接上题

本文目标:完善JVM内存区域状态!

1. 运行时区域

1.1 PC程序计数器

1.2 虚拟机栈

  • 分配大小:不存在GC问题,分配大小可以动态也可也固定

  • 存储单位:栈帧

    当正常return,栈帧弹出,抛出异常,也会弹出

    内部结构:

    1. 局部变量表:存方法参数与定义在方法的局部变量(基本数据类型与对象引用
    2. 操作数栈:保存计算的中间结构
    3. 动态连接:执行运行时的常量池的方法引用,比如:描述一个方法调用了另外的其他方法时,就是通过常量池中指向方法的符号引用来表示的,那么动态链接的作用就是为了将这些符号引用转换为调用方法的直接引用
    4. 方法返回地址:存正常返回与异常返回的地址
    5. 附件信息

1.3 本地方法栈

1.4 堆内存

逻辑上分代,理由是优化GC性能

分代:

  • 新生代:Eden、from、to 8:1:1(Minor GC)

    • 新创建对象放在Eden区
    • Eden满后,执行一次Minor GC,将幸存者放在from或者to中
    • 多次Minor GC的幸存者放在老年代中
  • 老年代:old(Major GC)

    • 幸存者进入old
    • 大对象直接进入old
  • 元空间:jdk8后直接用物理内存(JVM规范中的方法区实现

    如何设置堆大小:

    • Xms:起始内存

    • Xmx:最大内存

      一般这两者都一样,省的GC后重新计算堆内存大小

1.5 方法区(有垃圾回收!)

方法区?元空间?永久代?什么意思

永久代、元空间都是方法区的实现!

jdk8后,没有永久代,只有元空间!元空间的内存是物理内存了而不是像之前一样分配的虚拟机内存

存储内容:

  • 类的类型信息

  • 方法信息

  • 运行时的常量池:存放各自字面量与符号引用

    JDK8后字符串常量池、静态变量在堆里了

2. 发生OOM的区域

  1. 堆:创建了大量对象并且无法被GC回收
  2. 方法区:方法区用于存储类信息、常量、静态变量等数据。如果加载的类过多,或者某个类中包含大量的静态变量或常量,就可能导致方法区内存溢出
  3. 栈:用于存储线程的方法调用栈帧、局部变量和部分运算结果。如果应用程序中存在递归调用或者方法调用层级很深,导致栈帧过多,就会导致栈内存溢出。
  4. 本地方法栈:本地方法栈用于执行本地(Native)方法。如果本地方法调用过程中出现错误,导致本地方法栈溢出,也会触发OOM错误。
  5. 直接内存:直接内存是通过 ByteBuffer.allocateDirect() 方法分配的堆外内存,不受Java堆大小的限制。如果应用程序频繁地创建大量的直接内存对象,但是没有及时释放,就会导致直接内存溢出。(堆外内存需要程序员手动管理,堆外内存可以通过NIO直接访问,不需要进行Java堆到堆外内存的数据拷贝)