您的位置:首页 > 其它

JVM内存管理

2015-08-08 17:06 197 查看
读《深入理解Java虚拟机》Chapter2 Java内存区域与内存溢出异常,记录笔记如下:

JVM总内存由JVM启动时向OS申请的,大小可伸缩。【受限于OS的内存管理?待确认】

JVM进程所占内存可分为:

线程私有内存:

1 程序计数器(Program Counter Register)

记录线程当前执行的字节码的行号指示器。大小为4B,内存上连续。生命周期与线程相同。如果线程正在执行java方法,计数器的值是正在执行的虚拟机字节码指令的地址;如果正在执行Native方法,计数器值为空(Undefined)。对这块内存(寄存器?)的操作不会导致OutOfMemoryError异常。

分支、循环、跳转、异常处理、线程切换功能需要依赖计数器完成。【原理待了解】

2 Java虚拟机栈(JVM Stacks)

Java虚拟机栈存储了线程的栈帧(Stack Frame)(而非栈帧的引用)。每个方法从调用直至执行完成(正常结束或异常结束)的过程,对应其栈帧在虚拟机栈中入栈到出栈的过程。Java虚拟机栈中可能有多个栈帧,其中只有栈顶位置的栈帧是活动的,即是当前栈帧(Current Frame),该栈帧对应的java方法是当前方法(Current Method),定义这个方法的类是当前类(Current Class)。

如果当前方法调用了其他方法,或当前方法执行结束,那么这个方法的栈帧就不再是当前栈帧。当一个新的方法被调用,一个新的栈帧也随之创建,并且随着程序控制权移交到新的方法而成为新的当前栈帧。当方法返回之际,当前栈帧会传回此方法的执行结果给前一个栈帧,在方法返回之后,当前栈帧已出栈,前一个栈帧成为当前栈帧(即Java虚拟机栈栈顶位置的栈帧)。

Java虚拟机栈中存储了线程的全部栈帧。生命周期与线程相同。Java虚拟机栈不需要保证内存上连续。

栈帧(Frame)是用来存储数据和部分过程结果的数据结构,同时也被用来处理动态链接(Dynamic Linking)、方法返回值和异常分派(Dispatch Exception)。栈帧随着方法的调用而创建,随着方法的结束而销毁(销毁?出栈)。

当线程请求分配的栈容量超过Java虚拟机栈允许的最大容量时,Java虚拟机将会抛出StackOverflowError异常。

如果Java虚拟机栈可以动态扩展,但扩展时无法申请到足够的内存,或新建线程时没有足够的内存去创建对应的虚拟机栈,Java虚拟机将会抛出OutOfMemoryError异常。

3 本地方法栈(Native Method Stacks)

本地方法栈是Java虚拟机实现的传统的栈(C Stacks),用来支撑Native方法的执行。生命周期与线程相同。不需要保证内存上连续。类似于JVM Stacks,会抛出StackOverflowError及OutOfMemoryError异常。

共享内存区:

1 Java堆(Java Heap)

生命周期与jvm生命周期相同。空间可伸缩。不需要保证内存上连续。由GC(Garbage Collector)管理。所有的对象实例及数组都在堆上分配:

The heap is the runtime data area from which memory for all class instances and arrays is allocated.

当堆中没有内存完成实例分配,并且堆也无法扩展时,将会抛出OutOfMemoryError异常。

2 方法区(Method Area)

存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码。Java虚拟机规范把方法区描述为堆的一个逻辑部分。也称Non-Heap。方法区的内存位置由虚拟机实现。内存管理由虚拟机实现。

生命周期与jvm生命周期相同。空间可伸缩。不需要保证内存上连续。

方法区中包含:

运行时常量池(Runtime Constant Pool)。Java语音并不要求常量一定只有编译器才能产生,也就是并非预置入Class文件中常量池的内容才能进入方法区运行时常量池,运行期间也可能将新的常量放入池中。

Class文件常量池,包括字段和方法数据;构造函数和普通方法的字节码内容;一些类、接口初始化时用到的特殊方法。【存疑】

方法区内存不足以分配时,将会抛出OutOfMemoryError异常。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: