JVM详解
一、JVM内存管理模型
JVM内存结构布局,如下图:

JVM内存结构主要有三大块:堆内存、方法区和栈。
堆内存(Heap)是JVM中最大的一块,由年轻代和老年代组成,而年轻代内存又分为三个部分:Eden空间、From Survivor空间、To Survivor空间,默认情况下年轻代是按照8:1:1的比例来分配;
Java堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。
如果在堆内没有完成实例分配,并且堆也无法再扩展时,将会抛出OutOfMemoryError异常。
方法区(Method Area)存储类信息、常量、静态变量等数据,是线程共享的区域,为与Java堆区分开来,方法区还有一个别名交Non-Heap(非堆)。
有的人也把方法区称为“永久代”(Permanent Generation)。当方法区无法满足内存分配需求时,将抛出OutOfMemoryError异常。
栈又分为Java虚拟机栈和本地方法栈,主要用于方法的执行。
JVM内存≈Heap(堆内存)+PermGen(方法区)+Thrend(栈)
Heap(堆内存)=Young(年轻代)+Old(老年代),官方文件建议年轻代占整个堆内存的3/8,老年代占整个堆的5/8,。
Young(年轻代)=EdenSpace+FromSurvivor+ToSurvivor,一般Eden区与两个存活区的内存大小比例是 8:1:1。
控制参数
-
-Xms设置堆的最小空间大小。
-
-Xmx设置堆的最大空间大小。
-
-XX:NewSize设置新生代最小空间大小。
-
-XX:MaxNewSize设置新生代最大空间大小。
-
-XX:PermSize设置永久代最小空间大小。
-
-XX:MaxPermSize设置永久代最大空间大小。
-
-Xss设置每个线程的堆栈大小。
二、JVM垃圾回收机制

1、new出来的对象先放在Eden区,Eden区放满以后触发YoungGC(垃圾回收),释放不再使用的对象(不再被调用的对象),并将存活的对象移到S1存活区。
2、第二次Eden区又满了,再次触发YoungGC,这次是Eden区和S1区一起YoungGC。把Eden区和S1区的存活对象移到S2存活区,释放Eden区和S1区不再使用的对象,Eden区和S1区都被清空了。同时将S1和S2相互转换,S2存活的对象移到S1,则S2被清空。
3、按照上面的步骤一直触发YoungGC,如果一次YoungGC时存活区满了,则将存活的对象移到老年代。
4、一直这样循环直到老年代满了,就触发FullGC。首先清除老年代中没有被引用的对象,再对Eden区进行GC,还对持久带进行GC。
5、老年代满了以后,执行FullGC也释放不了内存空间,就会报内存溢出的错误了。
类对象什么时候进入老年代:
a、大对象直接进入老年代:Eden区放不下直接进入老年代
b、长期存活的对象进入老年代:以Young GC次数进行判断的,默认次数15次后进入老年代
c、执行Young GC时,存活区放不下时,存活对象也直接进入老年代
三、JVM内存调优思路
首先需要注意的是在对JVM内存调优的时候不能只看操作系统级Java进程所占用的内存,这个数值不能准确的反应堆内存的真实占用情况,因为GC过后这个值是不会变化的,因此内存调优的时候要更多的使用JDK提供的内存查看工具,比如JConsole、Java VisualVM。
对JVM内存的系统级的调优主要的目的是减少Young GC的频率和Full GC的次数,过多的GC和Full GC是会占用很多系统资源(主要是CPU),影响系统的推吐量。特别要关注Full GC,因为它对整个堆内存进行整理,会影响效率。而导致Full GC一般由于以下几种情况引起的:
1、老年代空间不足
调优时尽量让对象再年轻代Young GC时被回收,让对象在年轻代多存活一段时间,不要创建过大的对象及数组,避免直接在老年代创建对象。
2、Pemanet Generation(方法区)空间不足
增大Perm Gen空间,避免太多静态对象。
3、System.gc()被显示调用
垃圾回收不要手动触发,尽量依靠JVM自身的机制,调优手段主要是通过控制堆内存的各个部分的比例和GC策略来实现。
下面来看看各个部分比例不良配置会导致什么后果:
1)年轻代设置过小
导致年轻代Young GC次数非常频繁,增大系统消耗。
导致大对象直接进入老年代,占据了老年代剩余空间,诱发Full GC。
2)年轻代设置过大
年轻代设置过大会导致老年代过小,从而诱发Full GC。
年轻代设置过大会导致Young GC耗时大幅度增加。
一般来说年轻代占整个堆内存的1/3比较合适。
3)Survivor设置过小
导致对象从Eden区直接进入到老年代,降低了在年轻代的存活时间。
4)Survivor设置过大
导致Eden区过小,增加了Young GC的频率。

浙公网安备 33010602011771号