JVM(一):java内存区域

来源:互联网 发布:hadoop 处理数据 编辑:程序博客网 时间:2024/05/21 03:21

1. 程序计数器

程序计数器是一块儿比较小的内存区域,在JVM中可以理解为一个提示器,通过改变自身的值去告诉JVM下一步应该做什么,比如分支,跳转,循环,异常处理等等。

在JVM中,每个线程都有对应需要处理的事情,而不同的线程相互之间不能同时进行处理同一件事情,所以每个线程有它自己的程序计数器,这一类的内存区域被称为“线程私有”的内存区域。

如果JVM下一步应该执行的是一个java方法,那么计数器中存储的就是对应的字节码指令的地址,如果是native的方法,那么存储的就是undefined。

在这个区域中,虚拟机规范没有定义任何OutOfMemoryError的情况。


2. Java虚拟机栈

Java虚拟机栈对应的就是一个方法执行的内存模型,是一块线程私有的内存,当一个方法执行的时候,虚拟机就会在栈中创建一个对应的栈帧,方法开始执行,则栈帧入栈,方法执行完毕,则栈帧出栈。

栈帧中存储了这个方法中的局部变量表,操作数栈,动态链接,方法出口等信息。

局部变量表中存放了基本类型信息和引用类型信息。

在这个区域当中,虚拟机规范定义了两种异常情况:

第一种:StackOverflowError,当线程请求的栈深度大于虚拟机允许的最大深度,则会抛出此异常。

第二种:OutOfMemoryError:如果虚拟机支持动态扩展,但是在扩展的时候无法申请到足够的内存,则会抛出此异常。


3. 本地方法栈

本地方法栈和Java虚拟机栈发挥的作用基本类似,也是一块线程私有的内存,不同点在于Java虚拟机栈执行的Java方法,也就是字节码文件,但是本地方法栈执行的native方法。在某些虚拟机中,本地方法栈和虚拟机栈是合并的。

虚拟机规范中对本地方法栈也定义了StackOverflowError和OutOfMemorError,抛出的条件和虚拟机栈一样。


4. Java堆

Java堆是虚拟机管理的最大的一块内存,是线程共享的一块内存,同样是GC管理的主要内存,所以也被称为GC堆(如果参加某些面试,当面试官提起GC堆的时候不要蒙,GC堆就是Java堆)。

这块儿内存中基本上存储的都是对象实例(但不是绝对的)。

在堆内存中,根据内存回收的角度上来讲,还可以细分为新生代和老年代,这是基于GC的分代回收算法划分的。

在新生代中,还可以分为Eden空间,From Survivor空间和To Survivor空间。

无论哪个空间,存放的都是对象实例,和内容无关。

根据虚拟机规范,java堆可以处于物理上不连续,只要逻辑上连续即可的内存空间中,在这块内存中虚拟机规范规定了OutOfMemoryError,当堆中没有内存完成实例分配的时候,就会抛出此异常。


5. 方法区

和Java堆一样,都是线程共享的区域,用来储存已被虚拟机加载的类的信息,包括常量,静态资源,即时编译器编译后的代码数据等。

在部分虚拟机,必须HotSpot虚拟机中,GC的管理区域扩展到了方法区,所以方法区在这一类的虚拟机中也被称为“永久代”,但是使用永久代来实现方法区,会更容易碰到内存溢出的情况,因为对于GC来讲,对方法区的回收不是一件容易事,

根据虚拟机规范,如果方法区无法满足内存分配需求时,则会抛出OutOfMemoryError。


6. 运行时常量池

运行时常量池属于方法区的一部分,除了存放着类版本,字段,方法,接口等描述信息外,最重要的还有常量池,存放了各种字面量和符号引用。

因为是方法区的一部分,所以内存收到方法区的限制,如果常量池无法再申请到内存时就会抛出OutOfMemoryError



原创粉丝点击