1) Method Area
2) Heap
3) Java Stacks
4) PC Registers
5) Native Method Stacks
JAVA的JVM的内存模型大致可分为3个区:
堆区:
1.存储的全部是对象,每个对象都包含一个与之对应的class的信息。(class的目的是得到操作指令)
2.jvm只有一个堆区(heap)被所有线程共享,堆中不存放基本类型和对象引用,只存放对象本身
栈区:
线程在执行一个Java方法时候,它的PC寄存器总是指向下一条需要执行的指令, 而它的Java栈则保存线程中Java方法的调用状态,比如: 它的局部变量、传入方法的参数、返回值、以及运算的中间结果等。
1.每个线程包含一个栈区,栈中只保存基础数据类型的对象和自定义对象的引用(不是对象),对象都存放在堆区中
2.每个栈中的数据(原始类型和对象引用)都是私有的,其他栈不能访问。
本地方法栈:
当某个线程调用一个本地方法时,它就进入了一个全新的并且不再受虚拟机限制的本地方法栈。本地方法可以通过本地方法接口来访问虚拟机的运行时数据区,它和虚拟机拥有同样的权限(能力)。
任何本地方法接口都会使用某种本地方法栈。当线程调用Java方法时,虚拟机会创建一个新的栈帧并压入Java栈。然而当它调用的是本地方法时,虚拟机会保持Java栈不变,不再在线程的Java栈中压入新的帧,虚拟机只是简单地动态链接并直接调用指定的本地方法。
如果某个虚拟机实现的本地方法接口是使用C连接模型的话,那么它的本地方法栈就是C栈。当C程序调用一个C函数时,其栈操作都是确定的。传递给该函数的参数以某个确定的顺序压入栈,它的返回值也以确定的方式传回调用者。
方法区:
1.又叫静态区,跟堆一样,被所有的线程共享。方法区包含所有的class和static变量。
2.方法区中包含的都是在整个程序中永远唯一的元素,如类型的基本信息, 常量池, 字段信息, 方法信息, 静态变量, ClassLoader的引用等变量。
? Perm
Perm代主要保存classs,method,filed对象,这部门的空间一般不会溢出,除非一次性加载了很多的类,不过在涉及到热部署的应用服务器的时候,有时候会遇到java.lang.OutOfMemoryError : PermGen space 的错误,造成这个错误的很大原因就有可能是每次都重新部署,但是重新部署后,类的class没有被卸载掉,这样就造成了大量的class对象保存在了perm中。
? Tenured
Tenured区主要保存生命周期长的对象,一般是一些老的对象,当一些对象在Young复制转移一定的次数以后,对象就会被转移到Tenured区,一般如果系统中用了application级别的缓存,缓存中的对象往往会被转移到这一区间。
? Young
Young区被划分为三部分,Eden区和两个大小严格相同的Survivor区,其中Survivor区间中,某一时刻只有其中一个是被使用的,另外一个留做垃圾收集时复制对象用,在Young区间变满的时候,minor GC就会将存活的对象移到空闲的Survivor区间中,根据JVM的策略,在经过几次垃圾收集后,任然存活于Survivor的对象将被移动到Tenured区间。
标准参数-,所有的JVM实现都必须实现这些参数的功能,而且向后兼容,-client
非标准参数-X ,默认JVM实现此功能,但是不保证所有JVM都实行,而且不保证向后兼容,-Xmxn
非稳定参数-XX,此类参数各个JVM的实现会有不同,而且随时可能消失,+XX:-UseParallelGC
-Xmx3550m:设置JVM最大可用内存为3550M。默认是物理内存的1/4但小于1G。
-XX:MinHeapFreeRatio=40:修改垃圾回收之后堆中可用内存的最小百分比,缺省值是40。如果垃圾回收后至少还有40%的堆内存没有被释放,则系统将增加堆的尺寸。-Xms、-Xmx相等时无效.
-XX:MaxHeapFreeRatio=70: 改变垃圾回收之后和堆内存缩小之前可用堆内存的最大百分比,缺省值为70。这意味着如果在垃圾回收之后还有大于70%的堆内存,则系统就会减少堆的尺寸。-Xms、-Xmx相等时无效.
-Xms3550m:设置JVM初始内存为3550m。此值可以设置与-Xmx相同,以避免每次垃圾回收完成后JVM重新分配内存。默认是物理内存的1/64但小于1G。-Xmx -Xms之差就是Virtual空间的大小。
-Xmn2g:设置年轻代大小为2G。整个JVM内存大小=年轻代大小 + 年老代大小 + 持久代大小。持久代一般固定大小为64m,所以增大年轻代后,将会减小年老代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。
-Xss128k:设置每个线程的堆栈大小。JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。更具应用的线程所需内存大小进行调整。
-XX:NewRatio=4:设置年轻代(包括Eden和两个Survivor区)与年老代的比值(除去持久代)。设置为4,则年轻代与年老代所占比值为1:4,年轻代占整个堆栈的1/5
-XX:SurvivorRatio=4:设置年轻代中Eden区与Survivor区的大小比值。设置为4,则两个Survivor区与一个Eden区的比值为2:4,一个Survivor区占整个年轻代的1/6, 默认是32.
-XX:PermSize=16M-XX:MaxPermSize=16M: 设置持久代大小为16m。
-XX:PretenureSizeThreshold=3m:对象超过多大是直接在旧生代分配,新生代采用Parallel Scavenge GC时无效.
-XX:LargePageSizeInBytes=128M:Javaheap的分页页面大小, 默认4m
-XX:TLABWasteTargetPercent:JVM所占用的主要内存都是从堆空间分配的,堆是所有线程共享的,因此在堆上分配内存需要加锁,Sun JDK为提升效率,会为每个新建的线程在Eden上分配一块独立的空间由该线程独享,这块空间称为TLAB(Thread Local Allocation Buffer)。其大小由JVM根据运行情况计算得到,也可通过参数-XX:TLABWasteTargetPercent来设置TLAB可占用的Eden空间的百分比,默认值为1%。在TLAB上分配内存不需要加锁,因此JVM在给线程中的对象分配内存时会尽量在TLAB上分配。如果对象过大或TLAB用完,则仍然在堆上进行分配。
-XX:MaxTenuringThreshold=0:设置垃圾最大年龄。如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代。对于年老代比较多的应用,可以提高效率。默认值是32, 在linux64的java6下默认值是15, 对于并行收集器无效.
-XX:+DoEscapeAnalysis开启了逸出分析,某些情况所有性能有了很大的提高
-XX:+AggressiveOpts加快编译,jdk5U6引入, JDK6默认启用.
-XX:+UseBiasedLocking 锁机制的性能改善.
-XX:SoftRefLRUPolicyMSPerMB 每兆堆空闲空间中SoftReference的存活时间.
-XX:+UseFastAccessorMethods原始类型get,set方法的优化.
-XX:+DisableExplicitGC禁止java程序中的System.gc()的调用.
-XX:+UseCompressedOops 压缩指针,起到节约内存占用的新参数,JDK1.6u14开始
-XX:CompileThreshold当某个方法被调用+循环次数累计超过该值时,触发标准的JIT编译,默认CompileThreshold= 10000;
-XX:InterpreterBackwardBranchLimit当某个方法调用+循环次数累计超过该值时,触发OSR形式的JIT编译,10070
-XX:+PrintEscapeAnalysis打印逃逸分析
-XX:+PrintAssembly 打印JIT编译器变成x86指令
版权声明:本文为博主原创文章,未经博主允许不得转载。