Java内存
Java内存空间主要分为5部分:
堆(heap),栈(stack,虚拟机栈),方法区(method area,永久代Permenant Generation),本地方法栈(native method stack),程序计数器。
每个线程都有自己的程序计数器,是线程独享的。
线程如果执行一个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最大允许分配的非堆内存,按需分配