Java 内存区域
1. 运行时数据区域
1.1 程序计数器(Program Counter Register)
是一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器。在Java虚拟机的概念模型里,字节码解释
器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令。
1.2 Java虚拟机栈
Java虚拟机栈(Java Virtual Machine Stack)也是线程私有的,它的生命周期与线程相同
,虚拟机栈描述的是Java方法执行的线程的内存模型:每个方法被执行的时候,Java虚拟机都会同步创建一个栈帧(
Stack Frame)用于存储局部变量表、操作数栈、动态连接、方法出口等信息,每一个方法被调用直至执行完毕的
过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。
1.3 本地方法栈(Native Method Stacks)
本地方法栈与虚拟机栈所发挥的作用是非常相似的,其区别只是虚拟机栈为虚拟机执行Java方法服务,而本地方法栈则是
为虚拟机使用到的本地方法服务。在HotSpot虚拟机中本地方法栈和虚拟机栈是同一个。
1.4 Java堆区(Java Heap)
Java堆是被所有线程共享的一块内存区域,在虚拟机开启的时候创建。Java堆是垃圾收集器管理的内存区域。
1.5 方法区(Method Area)
方法区与Java堆一样,是各个线程共享的内存区域,它用于存储被虚拟机加载的类型信息、常量、静态变量、即时编译
器编译后的代码缓存。虽然《Java虚拟机规范》中把方法区描述为堆的一个逻辑部分,但它确有一个别名叫做”非堆“(
Non-Heap)。JDK6 的时候HotSpot开发团队计划放弃永久代,改为采用(Native Memory
)来实现方法区,到JDK8已经全部由本地方法实现的元空间(Metaspace)来代替。
1.6 运行时常量池(Runtime Constant Pool)
运行时常量池是方法区的一部分。Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量
池表(Constant Pool Table),用于存放编译期生成的各种字面量与符号引用,这部分内容将在类加载
后放到方法区的运行时常量池中。
1.7 直接内存(Direct Memory)
直接内存并不是虚拟机运行时数据区的一部分,在JDK1.4中新加入了NIO(New Input/Output)类
。引入一种基于通道(Channel)与缓冲区(Buffer)的I/O方式,它可以使用Native函数库直接分配
堆外内存,然后通过一个存储在Java堆里面的DirectByteBuffer 对象作为这块内存的引用进行操作,
这样能在一些场景中显著提升性能,因为避免了在Java堆和Native堆中来回复制数据。