Java内存区

1,224 阅读3分钟

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类库。