我理解的java-内存模型

cong记
2017-05-09 19:51

Java内存

Java内存空间主要分为5部分:

堆(heap),栈(stack,虚拟机栈),方法区(method area,永久代Permenant Generation),本地方法栈(native method stack),程序计数器。

《我理解的java-内存模型》

程序计数器:当前线程所执行的字节码文件(.class文件)的行号指示器,记录了执行到了哪步命令。

每个线程都有自己的程序计数器,是线程独享的。

线程如果执行一个java方法,程序计数器记录的就是正在执行的指令的地址;如果执行的是native方法,则程序计数器为空。

程序计数器是内存区域中唯一一个没有OutOfMemoryError的地方。

栈:每个方法执行的时候都会创建一个栈帧,存储了局部变量表、操作数栈、动态链接、方法出口的等信息(在字节码执行引擎那一节中会对每一项解释)。

线程独享。

栈中存放基本数据类型,和对象的引用,对象实体在堆中分配。

如果线程请求栈深度大于允许的虚拟机栈深度则抛出StackOverflowError;虚拟机栈可以动态扩展大小(大部分java虚拟机现在都允许),但是当超过物理内存大小限制的时候就抛出OutOfMemoryError。

堆:

分为年轻代(young generation),老年代(old generation)

年轻代:又分为Edon(伊甸区),两个survivor(幸存区)

所有对象一开始都会在新生代生成的,新生代为了过滤掉生命周期短的对象;大部分对象在eden区生成,当eden区满的时候会把其中还存活的对象放入到第一个survivor区里,当第一个survivor区满的时候再把该区域中还存过的对象放入survivor2区中,如果survivor2区中满了就会把还存活的对象放入到老年代中;需要注意,Survivor的两个区是对称的,没先后关系,所以同一个区中可能同时存在从Eden复制过来 对象,和从前一个Survivor复制过来的对象,而复制到年老区的只有从第一个Survivor去过来的对象。而且,Survivor区总有一个是空的。同时,根据程序需要,Survivor区是可以配置为多个的(多于两个),这样可以增加对象在年轻代中的存在时间,减少被放到年老代的可能。

老年代:这其中是经过多次垃圾回收之后还存活的对象,就是生命周期比较长的对象

本地方法栈:和虚拟机栈作用差不多,区别是:栈为虚拟机执行java(字节码)方法,而本地方法栈执行的是Native方法。

本地方法根据不同的虚拟机实现也是不同的。

方法区:用于存放静态文件(如类文件,静态方法等),持久代对垃圾回收没有显著的影响。

jvm内存参数

-vmargs -Xms128M -Xmx512M -XX:PermSize=64M -XX:MaxPermSize=128M

-vmargs 说明后面是VM的参数,所以后面的其实都是JVM的参数了

-Xms128m JVM初始分配的堆内存

-Xmx512m JVM最大允许分配的堆内存,按需分配

-XX:PermSize=64M JVM初始分配的非堆内存

-XX:MaxPermSize=128M JVM最大允许分配的非堆内存,按需分配

    原文作者:java内存模型
    原文地址: https://blog.csdn.net/u011277123/article/details/71720257
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞