JVM学习一:学习java内存区域

来源:互联网 发布:淘宝抢购 加入购物车 编辑:程序博客网 时间:2024/05/18 02:54

java内存区域包括:程序计数器、虚拟机栈、本地方法栈、java堆、方法区。

其中在我们平常的理解中java的内存模型一方面是栈,另一方面是堆,这两个区域是与java程序运行时关系较大的区域,也是OutofMemoryError经常发生的地方。因此先从我们最先接触到的栈与堆说起。

一、java内存区域栈分为虚拟机栈与本地方法栈,均是线程私有的。

其中虚拟机栈是用于java方法执行的内存模型,在每个方法执行时会创建一个栈帧,主要存储局部变量表、操作数栈、动态链表、方法接口等信息。

其中局部变量表是我们最熟悉的结构,主要存放编译时可知的基本数据类型(boolean、byte、int、long、short、double、float、char)、对象引用、returnAddress类型。

对于虚拟栈java规范规定了两个异常:(1)线程申请的栈深度大于虚拟机允许的深度,抛出stackoverflowerror异常;

(2)如虚拟机栈可动态扩展,如果扩展时无法申请到足够的内存,则抛出OutofMemoryError。

本地方法栈为java虚拟机使用的本地方法提供服务,该区域视虚拟机具体实现,在sun hotspot中它与虚拟机栈合二为一。同样也将抛出stackoverflowerror异常和抛出OutofMemoryError。

二、java堆

java堆是线程共享的,唯一的用途就是存放对象实例。

java堆中存放的对象实例按分代算法来看分为:新生代与老年代。

再细致点分为Eden、from survivor、to survivor等区。

从内存分配的角度看,它分为各个线程私有的缓冲区(TLAB)。

java堆逻辑上连续,物理上不一定连续。如果堆中没有足够的内存完成对象实例的存储,并且堆大小无法扩展,则抛出OutMemoryError异常。


前边针对我们熟悉的堆与栈进行了一些介绍,下面介绍被我们忽略的一些区域。

一、程序计数器

该区域相对较小,是线程私有的。它理解为程序执行的字节码的行号指示器。

如果虚拟机执行java方法则该区域记录指令地址,而当虚拟机执行native方法时,该区为空。

此区域也是java虚拟机规范中唯一一个没有规定任何OutofMemoryError的区域。

二、方法区(Non-heap)

该区域为线程共享区域,它主要用于存储已经被虚拟机加载的类信息、常量、静态变量、即时编译出后的代码等数据。

在hotspot虚拟机中该区域被称为“永久代”、应该说使用永久代来实现方法区,并通过gc统一管理该区域。

当方法区无法满足内存分配需求时,将抛出OutofMemoryError。

三、运行时常量池

该区域为方法区的一部分,用于存放class文件编译生成的各种字面量与符号引用。

该区域根据提供商实现的虚拟机的需求来实现,java虚拟机规范并未对此区域做要求。

该区域还具备动态性,运行时产生的新的常量也将存放在本区域中。如String的inten()方法

四、直接内存

该区域并非虚拟机运行时的数据区,也不是java虚拟机规范中定义的内存区域。

nio中提供一些方法,如通道(channel)、buffer等,它们可以直接使用Native函数库直接分配堆外内存。

该区域不会受到虚拟机内存的大小的限制,但是会受本机总内存的限制。也可能导致OutofMemoryError。




0 0
原创粉丝点击