JVM内存模型

来源:互联网 发布:docker web mysql 编辑:程序博客网 时间:2024/06/03 21:04

一、程序计数器(Program Counter Register):

类似于PC寄存器,记录线程的执行位置,线程私有,执行JAVA方法时存储执行指令的地址。

唯一一个在JAVA虚拟机规范中没有规定任何OutOfMemoryError情况的区域。


二、虚拟机栈(VM Stack)

线程私有,每次调用一个方法就开辟一个栈帧,执行结束后弹出。

栈的默认大小是1M。


栈帧(Stack Frame):

{

局部变量表:存放编译期可知的各种基本数据类型、对象引用(reference)和returnAddress类型。其中long 和double类型的数据会占用两个局部变量空间(Slot),其余只占用一个。Slot是可以重用的,但Slot中的变量超出了作用域,那么下一次分配Slot的时候会覆盖原来的数据。Slot对对象的引用会影响GC。

操作数栈:和局部变量区一样,操作数栈也是被组织成一个字长为单位的数组。但是操作数栈不是通过索引来访问,而是通过标准的栈操作(压栈和出栈)来访问。

}


三、本地方法栈(Native Stack):

和虚拟机栈相似,执行Native方法时使用,虚拟机规范对于本地方法栈中,方法使用的语言、使用方式和数据结构没有强制规定,最常用的HotSpot虚拟机直接将本地方法栈和虚拟机栈合二为一。


四、JAVA堆(JAVA Heap)

对于大多数应用来说JAVA Heap是JVM说管理的内存中最大的一块。JAVA堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。

JAVA Heap主要用于存放对象实例,几乎所有的对象实例都在这里分配内存。

JAVA Heap是GC的主要区域,分为

{

新生代(The NewGenerational Heap)默认4M,此区域一般为JVM内存的1/15大小

{

Eden区:绝大多数刚创建的对象会分配在Eden区,其中的大多数对象很快就会消亡,Eden区是连续的内存空间,因此在其上分配内存极快。

Survivor区:

{

Survivor区:

当Eden区满的时候执行Minor GC,并将剩余的对象添加到Survivor区。


Empty Survivor区:

当Survivor区满的时候将其中活着的对象复制到Empty Survivor区,然后清空Survivor区,紧接着现在Empty Survivor区成为Survivor区,

之前的Survivor成为Empty Survivor区,以后Eden区满了活着的对象就会放在当前Survivor区

}

}

老年代(Tenured Genaration)

{

Tenured区:

当一个对象在Survivor两个区游荡了n(可设置)个来回之后,对象进入Tenured区。除此之外,如果对象较大,年轻代空间不足,则大对象会直接分配到老年代上

}

}


五、方法区(Method Area)

跟堆一样是被各个线程共享的内存区域,用于存储被虚拟机加载的类信息、产量、静态变量。

在JVM启动时创建。

方法区的容量是可以固定大小的,也可以随着程序执行的需求动态扩展,方法区在实际内存空间中可以是不连续的。


/*****************************

// 

public class Test {

public static void main(String[] args) {

Test t = new Test();

//JVM将Test类信息加载到方法区, new Test()产生的实例存在堆区,Test引用保存在栈区

}

}

******************************/


六、运行时常量池(Runtime Constant Pool)

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


七、直接内存(Direct Memory)

直接内存比不是虚拟机运行时数据区的一部分,也不是JAVA虚拟机规范中定义的内存区域,但是这部分内存也被频繁的使用,而且有可能导致内存溢出

0 0
原创粉丝点击