说一下Java的内存模型?
根据JDK8规范,JVM运行时,内存共分为:
- 虚拟机栈
- 堆
- 方法区(元空间)
- 程序计数器
- 本地方法栈
还有一部分内存叫 直接内存,属于操作系统的本地内存,也是可以操作的

程序计数器:用于存储当前线程正在执行的Java方法的JVM指令地址
- 可以看作是当前线程所执行的字节码的行号指示器
- 如果线程执行的是 Native 方法,计数器值为 null
- 是虚拟机中唯一没有规定
OutOfMemoryError情况的区域,同时也是线程私有的内存区域
Java虚拟机栈:每个线程都有自己的独立的Java虚拟机栈,生命周期与线程相同
- 每个方法在执行时都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息
- 可能会抛出
StackOverflowError和OutOfMemoryError异常 - 同时也是线程私有的内存区域
本地方法栈:与 Java 虚拟机栈类似,主要为虚拟机使用到的 Native 方法服务
- 本地方法执行时也会创建栈帧
- 样可能出现
StackOverflowError和OutOfMemoryError两种错误
Java堆:是JVM的最大一块内存区域,被所有线程共享
- 在虚拟机启动时创建,用于存放对象实例
- 从内存回收角度,堆被划分为新生代和老年代,新生代又分为 Eden 区和两个 Survivor 区(From Survivor 和 To Survivor)
- 如果在堆中没有内存完成实例分配,并且堆也无法扩展时会抛出
OutOfMemoryError异常
方法区(元空间):在 JDK 1.8 及以后的版本中,方法区被元空间取代
- 用于存储已被虚拟机加载的类信息、常量、静态变量等数据
- 是所有线程共享的内存区域
- 方法区可以选择不实现垃圾收集,内存不足时会抛出
OutOfMemoryError异常
运行时常量池:是方法区的一部分
- 用于存放编译期生成的各种字面量和符号引用,具有动态性,运行时也可将新的常量放入池中
- 当无法申请到足够内存时,会抛出
OutOfMemoryError异常
直接内存:不属于JVM运行时数据区的一部分,通过 NIO 类引入,是一种堆外内存,可以显著提高 I/O 性能
- 直接内存的使用受到本机总内存的限制
- 若分配不当,可能导致
OutOfMemoryError异常
方法区中的方法的执行过程?
当程序中通过某个对象或类直接调用某个方法时,主要通过以下几步:
- 解析方法调用:JVM会根据方法的符号引用,找到实际的方法地址
- 栈帧创建:在调用一个方法前,JVM会在当前线程的Java虚拟机栈中为该方法分配一个新的栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息
- 执行方法:执行方法内的字节码指令,涉及的操作可能包括局部变量的读写、操作数栈的操作、跳转控制、对象创建、方法调用等
- 返回处理:方法执行完毕后,可能会返回一个结果给调用者,并清理当前栈帧,恢复调用者的执行环境