您的位置:首页 > 编程语言 > Java开发

JVM - Java内存区域

2017-11-09 22:25 267 查看
Java 与 C++ 之间有一堵由内存动态分配和垃圾收集技术所围成的“高墙”,墙外面的人想进去,墙里面的人却想出来。

一、运行时数据区

PC(Program Counter)寄存器

  每个线程都有自己的寄存器,用于存储正在执行的字节码指令的地址。

Java虚拟机栈(Java Virtual Machine Stack)

  每个线程都有自己的栈(Java Virtual Machine Stack),与线程同时创建,用于存储栈帧(Frame)。作用与传统语言如C语言中的栈非常类似,就是用于存储局部变量与一些过程结果(其实也是局部变量)的地方,可以称为局部变量表。

  栈的容量不够会抛出StackOverflowError异常。

Java堆(Heap)

  堆在虚拟机启动的时候被创建,是可供各条线程共享的运行内存区域,也是供所有类实例和数组对象分配内存的区域,这些对象被自动存储管理系统(Automatic Storage Management System),也即是常说的“Garbage Collector(垃圾收集器)”所管理的各种对象,这些受管理的对象无需,也无法显式地被销毁。

  堆的容量不够会抛出OutOfMemoryError

方法区(Method Area)

  方法区的概念是作为堆的逻辑组成部分,可供各条线程共享,类似传统语言如C语言中的编译代码存储区(Storage Area Of Compiled Code)或者操作系统进程的正文段(Text Segment),存储每个类的结构信息,如运行时常量池(Runtime Constant Pool)、字段和方法数据、构造函数、普通方法的字节码内容、还包括一些在类、实例、接口初始化时用到的特殊方法。

运行时常量池(Runtime Constant Pool)

  如上,常量池分配在方法区中,所以位于堆区。顾名思义,它包括各种常量:如编译期即可知的字面量、还有运行期才获得的方法或字段引用。运行时常量池扮演了类似传统语言中符号表(Symbol Table)的角色。

本地方法栈(Native Method Stack)

  指用来支持native方法(指使用非Java语言编写的方法)执行而使用的传统的栈(通常称之为“C Stack”)。

二、直接内存(Direct Memeory)

直接分配的堆外内存,称为直接内存,所谓堆外,就是上述的Java堆以外,堆外内存不受虚拟机的自动存储管理系统也即Carbage Collector垃圾收集器所管理,显然不受Java堆大小的限制,但仍受物理主机总内存的限制,所以当直接内存分配增加超出主机物理内存限制时,抛出OutOfMemeoryErro异常。

在JDK 1.4中新加入了NIO(New Input/Output)类,引入了一种基于通常(Channel)与缓冲区(Buffer)的I/O方式,它可以使用Native函数直接分配内存(在Java堆以外),然后通过一个存储在Java堆中的DirectBuffer对象作为这块内存的引用进行操作。这样能在一些场景中显著提高性能,因为避免了在Java堆和Native堆中来回复制数据。

三、总结

数据区相当于段式内存管理架构中的data段,以上6个区的介绍,主要有寄存器(Program Counter)、Stack和Heap,通常栈Stack都是线程私有的,而堆Heap是共享的。

PC(Program Counter): PC是线程私有的,即每个线程拥有各自的PC。

Stack: 分有Java Virtual Machine Stack(在规范第一版中叫Java Stack)和Native Method Stack

Java Stack: 线程私有,用于存储局部变量

Native Method Stack:线程私有,用于支持native方法

Heap: 线程共享,用于存储类的实例和数组等,通常是new出来的对象。

Method Area 与堆一样,线程共享,作为堆的逻辑组成部分,存储每个类的结构信息:

运行时常量池

字段和方法数据

函数(构造函数、普通函数还有一些特殊方法)的字节码

StackOverflowError 和 OutOfMemoryError

如果线程请求的栈容量超过虚拟机所允许的最大容量时,将抛出StackOverflowError,可能的区有:

Java Virtual Machine Stack

Native Method Stack

如果实际所需的堆超过了自动内存管理系统能提供的最大容量,将抛出一个OutOfMemory
b09c
Error异常,可能区有:

显然堆区会抛出OutOfMemoryError。

方法区的内存空间不能满足分配请求,将抛出OutOfMemoryError。

当创建类或接口的时候,如果构造运行时常量池所需要的空间超过了方法区所能提供的最大值,那Java虚拟机会抛出一个OutOfMemoryError。

如果Java Virtual Machine Stack能够扩展,并且扩展的动作已经尝试过,但是目前无法申请到足够的内在去完成扩展,或者在建立新的纯种时没有足够的内存去创建对应的虚拟机栈,Java虚拟机将抛出一个OutOfMemoryError异常。

Native Method Stack 同 Java Virtual Machine Stack一样。

参考:

1. 《Java虚拟机规范(Java SE 7版)》

2. 《深入理解Java虚拟机——JVM高级特性与最佳实践》
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: