系统虚拟机,完全对物理计算机的仿真,vmare.
程序虚拟机,专门为执行单个计算机程序而设计的,jvm
1、 方法区,是各个线程共享的内存区域,用于存储已经被虚拟机加载的类信息,常量、静态变量、即时编译的代码等数据。这个区也会存在垃圾回收,不过回收的目标针对于常量池和对类型的卸载,不过类型的卸载条件比较苛刻,回收成绩令人难以满意。
2、 虚拟机栈,虚拟机栈也是线程私有的,与线程同时创建,描述了java方法执行的内存模型。每个方法执行时,都会创建一个栈帧,来存储方法的变量表、操作数栈、动态链表方法,返回值,返回值地址等信息。栈的大小,决定了方法调用的可达深度(递归多少层,或者嵌套调用多少层其他方法,-Xss参数可以设置虚拟机栈大小)。栈的大小可以是固定的,或者动态扩展。如果请求的栈深度大于最大可用深度(即栈内存满了),则抛出stackOverflowError;如果栈是可动态扩展的,但是没有内存空间支持扩展,则抛出:OutofMemoryError(内存溢出)。||栈是运行时的单位,栈解决程序的运行问题,即程序如何执行,或者说如何处理数据, 在java中一个线程就会相应有一个线程栈与之对应,因为不同的线程执行逻辑有所不同,因此需要一个独立的线程栈。栈因为是运行单位,因此里面存储的信息都是跟当前线程(或程序)相关的信息。包括局部变量、程序运行状态、方法、返回值等等,
3、 本地方法区,和虚拟机栈的功能类似,但是管理的不是java方法,是本地方法,本地方法是用C实现的。
4、java堆,线程共享的,存放所有的对象实例和数据。垃圾回收的主要区域。这片内存区分为新生代和老年代,新生代又分为eden,from(s0),to(s1)。刚创建的对象放在Eden区里面,s0和s1都是至少经过一次GC并幸存的,每一次GC幸存的对象年龄加1,年龄到达一定程度后,对象进入老年区。新生代用复制算法回收对象内存。标记-压缩算法,适合用于老年代的算法(存活对象多于垃圾对象)标记后不复制,而是将存活对象压缩到内存的一端,然后清理边界外的所有对象。
JVM参数:
-XX:+PrintGCDetails 打印垃圾回收信息
-Xms 为Heap区域的初始值,线上环境需要与-Xmx设置为一致,否则capacity的值会来回飘动
-Xmx 为Heap区域的最大值
-Xss(或-ss)线程栈大小(指一个线程的native空间)1.5以后是1M的默认大小
-XX:PermSize与-XX:MaxPermSize 方法区(永久代)的初始大小和最大值(但不是本地方法区)
-XX:NewRatio 老年代与新生代比率
-XX:SurvivorRatio Eden与Survivor的占用比例。例如8表示,一个survivor区占用 1/8 的Eden内存,即1/10的新生代内存,为什么不是1/9?因为我们的新生代有2个survivor,即S1和S22。所以survivor总共是占用新生代内存的 2/10,Eden与新生代的占比则为 8/10。
-XX:MaxHeapFreeRatio GC后,如果发现空闲堆内存占到整个预估的比例小于这个值,则减小堆空间。
-XX:MinHeapFreeRatio GC后,如果发现空闲堆内存占到整个预估的比例大于这个值,则增大堆空间。
-XX:NewSize 新生代大小
JVM调优
在tomcat的conf里的catalina文件里设置参数,打开manager/status看配置
整个JVM可用内存大小=青年代大小 + 老年代大小 + 持久代大小。持久代一般固定大小为64m,所以增大年轻代后,将会减小老年代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8
年轻代和老年代的分配比例为1:2
-Xmx, java heap的最大值,默认是机器物理内存的1/4。
-Xms Java堆初始化时的大小,默认情况是机器物理内存的1/64。
-XX:PermSize 初始化永久内存区域大小
-Xmn直接设置青年代大小。整个JVM可用内存大小=青年代大小 + 老年代大小 + 持久代大小 。持久代一般固定大小为64m,所以增大年轻代后,将会减小老年代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。
-XX:NewRatio控制默认的Young代的大小,例如,设置-XX:NewRatio=3意味着Young代和老年代的比率是1:3。换句话说,Eden和Survivor空间总和是整个堆大小的1/4。
-XX:MaxTenuringThreshold 设置垃圾最大年龄。如果设置为0的话,则年轻代对象不经过Survivor区,直接进入老年代。对于老年代比较多的应用,可以提高效率。如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象在年轻代的存活时间,增加在年轻代即被回收的概率。