Java 运行时数据区域
定义
Java虚拟机把所管理的内存划分为不同的区域,总称为运行时数据区域。
数据区域用途各不相同,有的随虚拟机启动而存在,有的随线程的生命周期存在。
根据《Java虚拟机规范(Java SE7版)》规定,Java虚拟机将数据区域划分为:程序计数器、Java虚拟机栈、本地方法栈、Java堆、方法区(运行时常量池)。
程序计数器
• 线程私有,每个线程都有一个用来记录字节码执行位置。
• 一块内存区域,java虚拟机规范中唯一没有规定OutOfMemoryError的区域。
• java字节码解释器通过改变计数器的值实现分支、跳转、循环、异常处理、线程恢复等操作。
• 如果执行的是Java方法,则存储的是虚拟机字节码指令地址;如果是Native方法,则存储为空。
Java虚拟机栈
• 所谓的栈内存指的就是Java虚拟机栈。
• Java方法的运行,都会生成一个栈帧,用来存储执行Java方法的局部变量、操作数栈、动态链接、方法出口等信息。
• 一个Java方法的执行到结束,对应为一个栈帧的出栈与入栈。
• 虚拟机栈可以为固定内存,也可动态扩展。如果线程请求栈深度大于虚拟机深度,则会报StackOverflowError;如果动态扩展时无法申请到足够内存,则会报OutOfMemoryError。
本地方法栈
• 与Java虚拟机栈类似,但是是为Native方法的执行提供服务。
• 也会抛出StackOverflowError与OutOfMemoryError。
Java堆
• 各线程共享区域。
• 是java虚拟机管理的最大的一块内存区域。
• 是Java对象实例存储的空间。
• 是垃圾收集器主要工作区域。
• 存储空间逻辑上连续,物理上可以不连续。
• 可设置为固定大小或动态扩展,如果动态扩展时无法申请到足够内存,则会报OutOfMemoryError。
方法区
• 各线程共享区域。
• 用于存储已被Java虚拟机加载的类信息,常量,静态变量、即时编译器编译后的代码等。
• 方法区无法内存分配需求时,会抛出OutOfMemoryError。
运行时常量池
• 是方法区的一部分。
• Class类文件中有一项是常量池,用来存放编译期生成的字面量和符号引用。
• 类加载后常量池存储在方法区内的运行时常量池。
• 具有动态性,非编译期间的新的常量也可放入运行时常量池中。
直接内存
• 不是Java虚拟机规范定义的内存区域。
• JDK1.4后新加入的NI/O(New Input/Output)类,引入了仅与通道(Channel)与缓存。(Buffer)的I/O方式,可以直接通过Native函数库分配堆外内存。
• 内存收到本机总内存及处理器寻址空间的限制。直接内存无法内存分配需求时,会抛出OutOfMemoryError。