Java 整体内存结构
JVM内存区域分为程序计数器,虚拟机栈,本地方法栈,方法区,堆
程序计数器:存放下一条指令在方法中的偏移量。线程私有,即每个线程都会有一个。也可以看做是线程所执行的字节码的行号指示器,字节码解释器的工作就是通过改变这个计数器的值来选取下一条需要执行的指令。
虚拟机栈:程序计数器,虚拟机栈,和本地方法栈都是线程私有。在虚拟机栈有,有局部变量区和操作数区。人们经常说的JVM内存分为堆内存和栈内存(这 是一个比较笼统的说法)中的栈内存也就是指这个虚拟机栈的内存。当线程请求的栈的深度大于虚拟机所允许的深度时,就会抛出StackOverFlow 异常;如果虚拟机栈可以动态扩展,当扩展的时候无法申请足够的内存,会抛出OutOfMemory异常。
本地方法栈:主要用来支持native方法,记录native方法调用的状态。可以把native 方法看成是 java 调用 非 java 代码的一个接口。主要用于允许Java 和其他语言,比如 C 语言进行交互。
方法区:主要存储已经加载的类的信息,线程共享,比如构造函数的信息,方法的信息,常量的信息。Class对象提供的getXXX()方法取得的类的信息就是从JVM方法区中得到。Ps:JVM方法区是永久代的一个子集,常量池也是放在JVM方法区中。
堆:主要目的是用来存放数组和对象,线程共享。同时, 堆也是内存溢出和垃圾回收的主要区域。
Java 堆内存结构
在JVM堆中,又分为新生代,老生代
新生代中,又分为eden区域和两个Survivor区域。默认比例为8:1:1,也就是说,可以用的内存为90%,当然,可以用-XX:SurvivorRatio设置eden和Survivor的比值,默认为8:1。
Java 堆内存和非堆内存参数
-XX:Persize:设置非堆内存初始值,默认为1/64。
-XX:MaxPersize:设置非堆内存最大值,默认为1/4.
-Xss:设置每个线程占用堆内存大小,现在默认为1M,以前为256K。设置线程越小,堆内存大小不变,可以创造的线程数越多(当然有一个限度)。但是这个值也需要经过严格的测试再设置。
-Xms:JVM堆初始分配内存。默认为物理内存的1/64,当默认堆内存的空余空间小于40%的时候,这个堆内存就会自动增长到-Xmx指定的最大堆分配内存。
-Xmx :JVM的最大堆分配内存。默认为物理内存的1/4,当空余内存大于70%的时候,该堆内存又会自动减少到-Xms指定的内存。
-Xmn:指定新生代的内存大小。当堆大小不变的情况下,新生代越大,老生代越小,默认新生代和老年代的比例为1:2,而且这个比例会严重影响系统性能,sun推荐为新生代占整个堆内存3/8。
-XX:SurvivorRatio:新生代中,又分为eden区域和两个Survivor区域。默认比例为8:1:1,也就是说,可以用的内存为90%。该参数用来设置eden和Survivor的比值,默认为8:1。