Java内存区域
JDK1.7 VS JDK1.8
堆 (Heap)
- 定义: 堆是Java虚拟机(JVM)中用于存放对象实例和数组的内存区域。它是Java内存管理的核心部分,负责动态分配内存。
- 特点: 堆内存是线程共享的,所有线程都可以访问堆中的对象。堆空间也可以分为新生代和老年代,用于垃圾回收(GC)管理。
方法区 (Method Area)
- 定义: 方法区是JVM中用于存储类的结构信息、常量、静态变量、即时编译器编译后的代码等数据的内存区域。
- 特点: 方法区是所有线程共享的,存放类的元数据(如类的结构、方法的信息、字段的信息)和静态变量。
String 常量池 (String Pool)
- 定义: String 常量池是JVM中用于优化String对象的存储的区域。它是方法区的一部分,用来存放被编译器识别为常量的String对象。
- 特点: 如果多个String字面量(即在代码中直接写的字符串)有相同的值,那么这些字面量会被存储在常量池中,并且这些字符串对象是共享的。
运行时常量池 (Runtime Constant Pool)
- 定义: 运行时常量池是方法区中的一个部分,用于存储编译期生成的各种字面量和符号引用。它是在类加载后创建的,并且可以动态添加常量。
- 特点: 运行时常量池在运行时可以包含编译期间生成的常量和动态生成的常量。
虚拟机栈 (JVM Stack)
- 定义: 虚拟机栈用于存储方法调用时的栈帧。每个线程在执行时都会有一个虚拟机栈,用于存储局部变量、操作数栈、动态链接和方法出口信息。
- 特点: 每个线程都有自己的虚拟机栈,栈帧是线程私有的,栈帧的生命周期与方法的调用和返回相关。
- 异常:
- StackOverFlowError: 若栈的内存大小不允许动态扩展,那么当线程请求栈的深度超过当前 Java 虚拟机栈的最大深度的时候,就抛出 StackOverFlowError 错误
- OutOfMemoryError: 如果栈的内存大小可以动态扩展, 如果虚拟机在动态扩展栈时无法申请到足够的内存空间,则抛出OutOfMemoryError异常。
局部变量表
- 定义:存储方法的参数和局部变量。
-
操作数栈
- 定义:存储计算过程中的临时数据和计算结果
动态链接
- 定义:处理方法调用的符号引用到实际引用的解析。
方法返回信息
- 定义:处理方法执行后的返回值和控制流转移。
本地方法栈 (Native Method Stack)
- 定义: 本地方法栈与虚拟机栈类似,但是它专门用于处理本地方法(用C、C++等语言编写的方法)的调用。
- 特点: 本地方法栈的结构与虚拟机栈相似,但它存储的是本地方法调用的相关信息,而不是Java方法调用的信息。
- 异常:
- StackOverFlowError: 若栈的内存大小不允许动态扩展,那么当线程请求栈的深度超过当前 Java 虚拟机栈的最大深度的时候,就抛出 StackOverFlowError 错误
- OutOfMemoryError: 如果栈的内存大小可以动态扩展, 如果虚拟机在动态扩展栈时无法申请到足够的内存空间,则抛出OutOfMemoryError异常。
程序计数器 (Program Counter Register)
- 定义: 程序计数器是一个小的内存空间,用于存储当前线程正在执行的字节码指令的地址。
- 特点: 每个线程都有自己的程序计数器,线程切换时不会影响其他线程的程序计数器。程序计数器对于线程的执行顺序和调度是至关重要的。
- 异常:程序计数器是唯一一个不会出现 OutOfMemoryError 的内存区域,它的生命周期随着线程的创建而创建,随着线程的结束而死亡。
元空间
- 定义: 元空间是JVM中用于存储类元数据的内存区域。它负责存储类的结构信息,如类的定义、方法信息、字段信息等。
- 特点:
- 本地内存: 元空间的内存管理不再依赖于JVM堆,而是直接使用本地系统内存。这减少了由于方法区导致的内存管理问题。
- 动态调整: 元空间的大小可以根据需要动态调整,JVM可以根据系统的内存情况来分配或回收空间。这有助于避免方法区的OutOfMemoryError问题。
- 配置: 元空间的大小可以通过JVM参数进行配置。常用的参数包括:
-XX:MetaspaceSize=: 设置元空间的初始大小。
-XX:MaxMetaspaceSize=: 设置元空间的最大大小。 - 垃圾回收: 元空间的垃圾回收会在类卸载时触发,这与旧版方法区的垃圾回收机制类似,但管理上更为灵活。