Java 内存区
程序计数器
同一时刻,一个处理器只会执行一个线程。程序计数器是线程私有的内存区,记录机器码执行位置。如果线程执行Java方法,那么程序计数器中记录JVM字节码地址;如果线程执行本地方法,那么程序计数器内容为空。
Java方法和本地方法
Java方法是用Java语言编写的代码,经过编译存储在class文件的字节码,与平台无关。 本地方法是其他语言编写的代码,和实际的处理器相关,储存在动态连接库,与平台有关。
虚拟机栈
线程私有的内存区。每个Java方法执行时都会创建一个栈帧,用来储存局部变量表、动态链接、操作数栈、方法出口。方法的调用到完成,就是栈帧的入栈和出栈。当请求的栈深度大于虚拟机所允许的深度时抛出StackOverflowError。大部分的虚拟机可以动态扩展栈的大小,扩展时申请不到足够的大小会抛出OutOfMemoryError。
通常,栈指的就是虚拟机栈或虚拟机栈中的局部变量表。
局部变量表
储存基本数据类型和对象引用,所以编译时就已经确定并分配了内存空间,运行时不会改变。
本地方法栈
与虚拟机栈类似的作用,抛出的异常也相同,但虚拟机实现规范对本地方法栈的实现没有要求,HotSpot就把本地方法栈和虚拟机栈合并了。
堆
最大的一块内存区,虚拟机启动时创建。虚拟机实现规范要求堆用来给所有的对象实例和数组分配内存,但随着技术的发展,现在有些情况与此要求不符。
堆是垃圾回收发生的主要区域,由于虚拟机采用分代收集的策略,所以堆又分为新生代、永生代等区域。
堆和栈的空间都不需要在物理上连续,且可以扩展,如果对象在堆上分配时由于内存不足无法分配,抛出OutOfMemoryError。
方法区
存储虚拟机加载的类信息、常量、静态变量等数据。虚拟机实现规范对此内存区的实现没有要求。
内存回收
方法区内存回收时必要的,如常量的回收以及类的卸载。HotSpot虚拟机在方法区也采用分代收集策略,且用永生代实现方法区,这导致了方法区更容易出现内存泄漏的问题。
运行时常量池
运行时常量池中的常量有几个来源:在编译时生成的,class文件中的各种字面量和符号引用;翻译出来的直接引用;运行期间产生的新的常量。
符号引用 编译时虚拟机不知道引用类的实际内存地址,只能用符号引用的方式定位引用类,在类加载时符号引用会转为直接引用。
直接引用 有直接引用的类一定已经装载到了内存中。
直接内存
不是虚拟机规范所定义的内存区,也存在OutOfMemoryError的异常。在某些情况下,虚拟机将对象分配到直接内存可以避免对象在Native堆和Java堆之间复制的开销。
Java 技术体系
Java技术体系主要包括:
- Java语言
- Java虚拟机
- Class文件格式
- Java API类库
- 第三方API类库
JDK是支持Java开发的最小环境,包括Java语言、JVM、Java API类库。