明耀

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

由于Java程序是交由JVM执行的,所以我们在谈Java内存区域划分的时候事实上是指JVM内存区域划分。

java虚拟机在执行java程序的过程中会把它所管理的内存划分为若干个不同的数据区域,这些区域都有各自的用途已及创建和销毁的时间。java虚拟机所管理的内存将会包括以下几个运行时数据区域。

第一块:程序计数器

多线程时,当线程数超过CPU数量或CPU内核数量,线程之间就要根据时间片轮询抢夺CPU时间资源,因此为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各条线程之间计数器互不影响,独立存储,如果如果执行的是JAVA方法,计数器记录正在执行的java字节码地址,如果执行的是native方法(一个Native Method就是一个java调用非java代码的接口。一个Native Method是这样一个java的方法:该方法的实现由非java语言实现),则计数器为空。

第二块:JVM栈

线程私有的,与线程在同一时间创建。管理JAVA方法执行的内存模型。每个方法执行时都会创建一个栈帧来存储方法的的变量表、操作数栈、动态链接方法、返回值、返回地址等信息。

变量表存放了编译期可知的各种基本数据类型(boolean 、byte、char、short、int、float、long、double)对象引用(reference类型,它不等同于对象本身,可能是一个指向对象起始地址的引用指针,也可能是指向一个代表对象的句柄会其他与此对象相关的位置)和returnAddress(指向了一条字节码指令的地址)。

栈的大小决定了方法调用的可达深度(递归多少层次,或嵌套调用多少层其他方法,-Xss参数可以设置虚拟机栈大小)。栈的大小可以是固定的,或者是动态扩展的。如果请求的栈深度大于最大可用深度,则抛出stackOverflowError;如果栈是可动态扩展的,但没有内存空间支持扩展,则抛出OutofMemoryError。

第三块:堆(Heap)

它是JVM用来存储对象实例以及数组值的区域,可以认为Java中所有通过new创建的对象的内存都在此分配,Heap中的对象的内存需要等待GC进行回收。

 

(1) 堆是JVM中所有线程共享的一块内存区域,在虚拟机启动时创建,在其上进行对象内存的分配均需要进行加锁,这也导致了new对象的开销是比较大的

(2) Java堆中还可以细分为新生代和老年代。所有新创建的Object 都将会存储在新生代Yong Generation中。如果Young Generation的数据在一次或多次GC后存活下来,那么将被转移到OldGeneration。

新生代又可进一步细分为Eden Space、survivorSpace0(s0,from space)、survivorSpace1(s1,to space)。刚创建的对象都放入Eden Space中,s0和s1都至少经过一次GC并幸存。如果幸存对象经过一定时间仍存在,则进入老年代(tenured)。

(3) Sun Hotspot JVM为了提升对象内存分配的效率,对于所创建的线程都会分配一块独立的空间TLAB(Thread Local Allocation Buffer线程私有的分配缓冲区),其大小由JVM根据运行的情况计算而得,在TLAB上分配对象时不需要加锁,因此JVM在给线程的对象分配内存时会尽量的在TLAB上分配,在这种情况下JVM中分配对象内存的性能和C基本是一样高效的,但如果对象过大的话则仍然是直接使用堆空间分配

(4) TLAB仅作用于新生代的Eden Space,因此在编写Java程序时,通常多个小的对象比大的对象分配起来更加高效。

第四块:方法区域(Method Area)

(1)在Sun JDK中这块区域对应的为PermanetGeneration,又称为持久代。

(2)方法区域存放了所加载的类的信息(名称、修饰符等)、类中的静态变量、类中定义为final类型的常量、类中的Field信息、类中的方法信息,当开发人员在程序中通过Class对象中的getName、isInterface等方法来获取信息时,这些数据都来源于方法区域,同时方法区域也是全局共享的,在一定的条件下它也会被GC(回收的基本条件至少有:所有该类的实例被回收,而且装载该类的ClassLoader被回收),当方法区域需要使用的内存超过其允许的大小时,会抛出OutOfMemory的错误信息。

第五块:运行时常量池(Runtime Constant Pool)

运行时常量池是方法区的一部分,存放的为类中的固定的常量信息、方法和Field的引用信息等

第六块:本地方法栈(Native Method Stacks)

和虚拟机栈功能相似,但管理的不是JAVA方法,是本地方法,JVM采用本地方法栈来支持native方法的执行,此区域用于存储每个native方法调用的状态。

posted on 2017-08-07 16:44  明耀  阅读(133)  评论(0编辑  收藏  举报