您的位置:首页 > 其它

JVM内存结构

2013-09-09 15:39 176 查看
JVM包含两个子系统和两个组件。
子系统分别是ClassLoader和ExecutionEngine,两个组件是Runtime Data Area和Native Interface,其中,Runtime Data Area中就包含了我们常说的JVM内存。

Runtime Data Area又将内存分为不同的区域,用户存储不同的数据:

Method Area —— 方法区,被ClassLoader所装载的class文件以及相关的方法信息、域信息、静态变量等都存放在这个区域内。该区域是所有java线程共享。

当虚拟机装载某个类型时,它使用类装载器,定位对应的class文件,然后读入这个class文件内容并传输到虚拟机中,虚拟机会提取其中的类型信息,并将这些信息存储到方法区。该类型中的类(静态)变量同样也存储到方法区中。因为被所有线程共享,要考虑多线程访问的同步问题。

Heap —— 堆区,用来存放java对象和数组,通常所说的GC(垃圾回收器)就是针对该区域,一个java虚拟机实例只有一个堆,直接由java虚拟机进行管理,在虚拟机启动的时候创建,该区域被所有线程共享。堆可以动态的分配内存大小,存取速度比较慢。

每一个java程序独占一个jvm实例,每一个jvm实例只有一个堆空间,因此此java程序的所有线程共享这个堆。因此每个java程序都有自己独立的堆空间,不会彼此干扰。但是同一java程序的多个线程都共享着一个堆空间,就得考虑多线程访问对象(堆数据)的问题(还有,并发访问静态属性、单例等等,具体情况具体分析)。

Stack —— 栈区,用来存放JVM内存指令,每个线程都有自己的栈。优势是,存取速度比较快,栈里面的数据可以共享,但是内存中的数据大小和生存期必须是确定的,缺乏灵活性。

java程序以帧为单位保存线程的运行状态。虚拟机只会对java stack执行两种操作:以帧为单位的压栈或出栈。每当线程调用一个方法的时候,就对当前状态作为一个帧保存到java stack中(压栈),当调用一个方法返回时,从java stack中弹出一个栈(出栈)。栈的大小有一定的限制,可能会出现StackOverFlow的问题。

Program Counter Register ——程序计数器, 每一个线程都有自己的PC寄存器,是该线程启动时创建的。PC寄存器的内容总是指向下一条被执行的指令的地址。

Native Method Stack ——本地方法栈, 保存本地方法进入区域的地址。对于一个运行中的java程序而言,它还可能用到一些跟本地方法相关的数据区。当某个线程调用一个本地方法时,它就进入了一个全新的并且不受虚拟机控制的世界。本地方法可能通过本地方法接口来访问虚拟机的运行时数据区,还可以做任何它想做的事情。比如调用寄存器、在操作系统中分配内存等等。总之,本地方法具有和JVM相同的能力和权限。

通常,可以将JVM分为堆区和非堆区,堆为上面的Heap区域,剩下的都是非堆区域。GC主要针对的是堆区域。



垃圾分代回收算法

基于对对象生命周期分析后得出的垃圾回收算法。把对象分为年轻代、年老代、持久代,对不同生命周期的对象使用不同的算法进行回收。

java的内存模型分为:

Young(年轻代)

Tenured(年老代)

Perm(永久代)

1、年轻代(JVM中heap的一部分)

年轻代分为三个区,一个Eden区,两个Survivor区。大部分对象在Eden区中生成,当Eden满了的时候,程序又需要创建新的对象,此时JVM的垃圾回收器将对Eden区域进行垃圾回收,将Eden区中不再被其它对象所引用的对象进行销毁工作。将还有其它对象引用的对象将被移动Survivor-0区(两个中的一个,Survivor区用于存放垃圾回收器回收时幸存下来的对象),当这个Survivor-0区满了的时候,进行垃圾回收销毁没有被其它引用对象引用的java对象,此区的存活的对象将被移动到另一个Survivor-1区,如果Survivor-1区有足够空间就放到Survivor-1区,如果Survivor-1也满了,JVM会对Survivor-1进行垃圾回收,销毁没有被其它引用对象引用的java对象,将幸存的java对象移动到养老区。

2、年老代(JVM中heap的一部分)

年老代存放的是从年轻代存活的对象。一般来说年老代存放的都是生命周期比较长的对象。

如果从Survivor-1移动到年老代的时候,年老代有足够空间则放到年老区,如果年老区没有足够空间,则JVM的垃圾回收期会对年老区进行垃圾回收,销毁没有被其它引用对象引用的java对象,并保留那些被其它引用对象引用的java对象。如果最后,年老区、Survivor-0、Survivor-1、Eden都满了(空间不够),则JVM会抛出“JVM堆空间溢出”(java.lang.OutOfMemoryError:Java heap space“,即堆空间满了,没有足够空间来存放创建的对象。

3、持久代(JVM中method area)

用于存放静态文件,如java类、方法、(静态)属性等。持久代对垃圾回收没有显著影响,但是有些应用可能动态生成和调用一些class,如hibernate,这时,需要设置一个比较大的持久代空间来存放这些运行过程中新增的类。持久代大小通过-XX:MaxPerSize=进行设置

年轻代和年老代组成了堆内存。

永久代则是非堆内存的组成部分。主要存放加载Class类及对象如class本身,method,field等等。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  jvm 虚拟机 内存 对象