Java内存区域
- 1 分钟前Java虚拟机定义了若干种程序运行期间会使用到的运行时数据区,其中有一些会随着虚拟机启动创建,随着虚拟机退出而销毁。另外一些则是与线程一一对应的,这些与线程对应的数据区域会随着线程的开始和结束而创建和销毁。
Program Counter Register
Java虚拟机可以支持多条线程同时执行,每一条Java虚拟机线程都有自己的Program Counter Register,它可以看做是当前线程所执行的字节码的行号指示器。
由于Java虚拟机的多线程其实是通过线程轮流切换并分配处理器执行时间来实现的,在任何一个时刻,一个处理器都只会执行一条线程中的指令,每条线程独立,各条线程之间的计数器互不影响,这类内存区域就称为“线程私有”的内存。
如果该线程的当前方法不是Native的,那么计数器的值就保存为JVM正在执行的字节码指令的地址;如果是Native方法,那么计数器的值为空(Undefined)。
Java Virtual Machine Stacks
Java虚拟机栈和计数器一样都是线程私有的,生命周期与线程相同。每个方法在执行的同时都会创建一个栈帧(Stack Frame)用于存储局部变量和一些尚未算好的结果、方法的调用和返回。 每一个方法从调用到返回的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。
Java 虚拟机规范既允许Java 虚拟机栈被实现成固定大小,也允许根据计算动态来扩展 和收缩。
Java虚拟机栈可能发生两种异常状况:
-
StackOverflowError异常:线程请求分配的栈容量超过Java虚拟机栈允许的最大容量
-
OutOfMemoryError异常:虚拟机可以动态扩展,扩展时无法申请到足够的内存;在创建新线程时没有足够的内存去创建对应的虚拟机栈
Native Method Stack
Java虚拟机栈是为虚拟机执行Java方法服务,本地方法栈就是虚拟机实现使用C Stack来支持使用Java语言以外其他语言编写的方法的执行。
本地方法栈可以实现成固定大小或者根据计算来动态扩展和收缩。
本地方法栈可能发生的异常和Java虚拟机栈一样。
Java Heap
在Java虚拟机中,堆(heap)是可供各个线程共享的运行时内存区域,也是供所有类实例和数组对象分配内存的区域。
Java堆在虚拟机启动时就被创建,它存储了自动内存管理系统,也就是垃圾收集器(Garbage Collected)所管理的各种对象。
Java堆的容量可以是固定的,也可以随着程序执行的需求动态扩展,并在不需要过多空间时自动收缩。Java堆所使用的内存不需要保证是连续的。
Java堆可能发生的异常状况: OutOfMemoryError异常:在堆中没有内存完成实力分配,并且堆也无法再扩展
Method Area
方法区是线程共享的区域,用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
方法区在虚拟机启动的时候创建,方法区是堆的逻辑组成部分。它有一个别名叫Non-Heap,简单的虚拟机实现可以选择在这个区域不实现垃圾收集与压缩。
方法区的容量的固定的,也可以随着程序执行的需求动态扩展,并在不需要过多空间的时候自动收缩。方法去所使用的内存可以是不连续的。
Runtime Constant Pool
运行时常量池是方法区的一部分,是class文件中每一个类或接口的常量池表的运行时表示形式,包括各种各样的常量。
每一个运行时常量池都在Java虚拟机的方法区中分配,在加载类和接口到虚拟机后,就创建对应的运行时常量池。
运行时常量池具备动态性,并不一定要求常量只有编译期才能产生,运行期间也可能将新的常量放入池中。这种特性用的比较多的便是String类的intent()方法。
- OutOfMemoryError异常:构造运行时常量池所需要的内存空间超过了方法区所能提供的最大值
参考资料:《Java虚拟机规范(Java SE 8版)》、《深入理解Java虚拟机》