理解JVM之JAVA运行时内存区域

  java运行时内存区域划分为方法区,堆区,虚拟机栈区,本地方法栈,程序计数器.其中方法区跟堆区是线程共享的数据区,其他的是线程私有的数据区.

1.程序计数器

  程序计数器(PC)是一块较小的内存,他是存储当前线程执行的字节码的行号指示器,可以类比硬件中PC,硬件中的PC用于指示当前程序执行的代码在内存中的内存地址.

2.JAVA虚拟机栈

  虚拟机栈描述的是JAVA方法执行的内存模型.每个方法在执行时都会创建一直栈帧用于存储局部变量表,操作数栈,动态链接,方法出口灯信息.每一个方法从调用到结束都对应一个栈帧在虚拟机栈中的入栈出栈.局部变量表存储的是编译期间可知的各种基本数据类型,对象引用和返回地址.基本数据类型有boolean,byte,char,short,int,float,long,double,其中boolean是1位,byte是8位即1个字节,char,short是16位即2个字节,float,int是32位即4个字节,long,double是64位即4个字节.在虚拟机栈中,64位的数据会占用两个局部变量空间,其他的只占用一个.

  在该区域有两个异常状况:如果线程请求的深度大于虚拟机允许的深度,会抛出StackOverflow异常,如果虚拟机栈可扩展,且扩展时无法申请到足够的内存会抛出OutOfMemoryError异常.

3.本地方法栈

  本地方发栈与虚拟机栈的作用非常相似,区别就在于前者执行的是本地方法,候着执行的是java方法.本地方法使用的语言,方式,数据结构没有强制规定,虚拟机可自由实现.

4.java堆

  该区域是用于存放对象实例的,几乎所有的对象实例以及数组都在这里分配..java堆是垃圾收集器管理的主要取悦,从内存回收的角度来看,由于现在收集器基本采用分代收集算法,所以java堆可分为:新生代和老年代.再细致一点分为Eden空间,From Survivor空间,To survivor空间等,从内存分配的角度看,线程共享的java堆可分出多个线程私有的分配缓冲区.无论如何划分,java堆始终存放的是对象实例.java堆是逻辑上连续的空间,就跟磁盘一样.关于这里提到的堆空间分区可以看下我的另一片关于java垃圾回收机制的博客.

5.方法区

  该区域用于存储虚拟机加载的类信息,常量,静态变量,及时编译器编译后额代码等数据.存储常量的区域我们可称为常量池.这个区域的回收主要针对于常量池以及类型的卸载.

6.运行时常量池

  这里额外介绍运行时常量池,它是方法区的一部分.class文件中除了有类的版本,字段,接口,方法等信息之外,还有一项是常量池,用于存放编译期间生成的各种字面量和符号引用,这部分内容在类加载后进入方法区的运行时常量池存放.运行时常量区是具备动态性的.该区域的常量不一定是编译器才产生的,运行期间新的常量也可以放入池中.这点特性利用的最多的就是String类的intern()方法.

posted @ 2018-03-16 12:04  随花四散  阅读(342)  评论(0编辑  收藏  举报