java内存区域的划分

     java虚拟机在运行时会将它所管理的内存区域划分为若干个不同的数据区域,主要分为程序计数器,java虚拟机栈,本地方法栈,java堆,方法区和运行时常量池等。

     程序计数器是每一个线程的私有区域,执行字节码的行号指示器。此内存区域是java虚拟机规范里面唯一没有规定outofmemoryerror的区域。

     java虚拟机栈也是线程私有区域。每个方法在执行的同时都会创建一个栈帧,用于存储局部变量表,操作数栈,方法接口信息等。每一个方法从调用到执行结束,就对应着一个栈帧的入栈和出栈。局部变量表存放了编译期可知的各种基本数据类型,boolean,byte,char,short,int,float,long,double等,其中64位长度的long和double类型的数据会占用2个局部变量空间。局部变量表的内存空间在编译期完成分配。

    在java虚拟机规范里面,对java虚拟机栈规定了两种异常状况。如果线程请求的深度大于虚拟机允许的深度,将会抛出stackoverflow异常。如果虚拟机栈在动态扩展时无法申请到足够的内存,就会抛出outofmemoryError异常。

    本地方法栈与虚拟机栈所发挥的作用是类似的,不过本地方法栈是为虚拟机执行native方法服务的,也会抛出两种类型的错误。

    java堆是java虚拟机管理的内存中最大的一块,是所有线程共享的一块内存区域。此内存区域的唯一目的就是存放对象实例,所有的对象实例以及数组都要在堆上分配,从内存的回收角度来看,由于现在收集器基本都采用分代收集器,所以java堆中可以区分为新生代和老年代。

   方法区与java堆一样是线程共享的内存区域。它用于存储已被虚拟机加载的类信息,常量,静态变量,即时编译器后的代码等数据。方法区又被称为永久代。本质上两者并不等同。仅仅是因为hotspot虚拟机的设计团队选择把GC分代收集扩展至方法区。这样的hotspot的垃圾收集器可以像管理java堆一样管理这部分内存。java虚拟机规范对方法区的限制非常宽松。除了和java堆一样不需要连续的内存和可以选择固定大小或者可扩展外,还可以选择不实现垃圾收集。这区域的内存回收目标主要是针对常量池的回收和对类型的卸载。当方法去无法满足内存分配需求时,将会抛出outofmemoryError异常。

    运行时常量池,是方法区的一部分。class文件除了有关的版本字段,方法,接口等描述信息外,还有一项信息是常量池,用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常量池中存放。

   运行时常量池相比于class文件常量池的另一个重要特征是具备动态性。java语言并不要求常量一定只有编译期才能产生。运行期间也可能将新的常量放入池中。

猜你喜欢

转载自cmuzgb.iteye.com/blog/2226472