首页 > 代码库 > JVM调优-计算活跃数据大小

JVM调优-计算活跃数据大小


活跃数据,有时候也叫做存活数据,指应用处于稳定运行状态下,在Java堆里面长期存活的对象的大小。换一句话说,就是应用在稳定运行的状态下,FullGC之后,Java堆的所占的空间大小(内存的占用情况)。

1、活跃数据计算的重要性

         Java应用的活跃数据大小的计算,是我们进行JVM调优的一个必备的过程,如果我们不知道这个系统的活跃数据有多少,那么我们怎么给他分配合适的内存?因此,计算活跃数据大小是JVM调优的的重要一步。

         Java应用的活跃数据大小可以通过GC日志收集。

活跃数据主要包括两块,老年代的大小和永久代的大小。

2、活跃数据的查看方式

为了更好的计算应用程序的活跃数据大小,最好在多次FULLGC之后再查看JAVA堆的占用情况。但是话又要说回来,很多JVM因为内存设置的不合理,导致大量FULL GC的出现,如果用这个数据来指导调优,会陷入越调试越乱的怪圈;

与此同时,有的系统已经经过了优化,或者碰上了好运气,随便设置一个参数,结果刚刚好,FULLGC从来没有发生过,这样的情况,通过GC日志收集几乎就看不到FULL GC发生。这种情况,可以使用一些工具,强制进行垃圾回收,触发FULLGC事件。比如用JDK自带的JConsole触发。

计算活跃数据是我JVM调优的核心。

首先看一个样例,在实际应用用要找到FULL GC比较容易,但是整个系统搬上来比较麻烦,写一个简单的例子,模拟FULLGC出现的情况。

3、计算活跃数据(模拟FULL GC)的源代码

packagecom.gc;

 

importjava.util.ArrayList;

importjava.util.List;

 

/**

 * 简单的模拟FULLGC,用来计算活跃数据大小

 * 参数:-Xms30m-Xmx60m -XX:+UseParallelGC -XX:+PrintGCDetails

 * @author 范芳铭

 */

publicclass EasyActiveData {

         public byte[] placeHolder = newbyte[1024 * 1024]; //占位符 1M

         public static void main(String[] args)throws Exception{

                   activeData();

         }

        

         private static void activeData() throwsException{

                   List<EasyActiveData>list_a = new ArrayList<EasyActiveData>();

                   List<EasyActiveData>list_b = new ArrayList<EasyActiveData>();

                  

                   for(int j=0; j < 25;j ++){

                            EasyActiveDataserial = new EasyActiveData();

                            list_a.add(serial);

                   }

                   Thread.sleep(100);//停顿下

 

                   for(int j=0; j < 30;j ++){

                            EasyActiveDataserial = new EasyActiveData();

                            list_b.add(serial);

                   }

                   Thread.sleep(100);//停顿下

 

                  

                   while(true){

                            EasyActiveDataserial = new EasyActiveData();

                            serial =  list_a.get(0);

                            serial = null;

                            serial =list_b.get(0);;

                           

                            Thread.sleep(100);//停顿10毫秒

                   }

         }

}

运行参数

-Xms30m  启动内存

-Xmx60m  最大内存

-XX:+UseParallelGC 选用的垃圾回收方式

-XX:+PrintGCDetails  打印GC明细

4、运行结果

 [Full GC [PSYoungGen: 48K->0K(4416K)][PSOldGen: 30879K->30879K(39488K)] 30927K->30879K(43904K) [PSPermGen:2086K->2086K(12288K)], 0.0028453 secs] [Times: user=0.00 sys=0.00, real=0.00secs]

[GC [PSYoungGen:4098K->48K(4416K)] 34977K->35023K(43904K), 0.0035403 secs] [Times:user=0.00 sys=0.00, real=0.00 secs]

[Full GC [PSYoungGen:48K->0K(4416K)] [PSOldGen: 34975K->34975K(44672K)]35023K->34975K(49088K) [PSPermGen: 2086K->2086K(12288K)], 0.0026413 secs][Times: user=0.00 sys=0.00, real=0.00 secs]

[GC [PSYoungGen:4098K->48K(4416K)] 39073K->39119K(49088K), 0.0028593 secs] [Times:user=0.00 sys=0.06, real=0.00 secs]

[GC [PSYoungGen:4146K->48K(4416K)] 43217K->43219K(49088K), 0.0035522 secs] [Times:user=0.00 sys=0.00, real=0.00 secs]

[Full GC [PSYoungGen:48K->0K(4416K)] [PSOldGen: 43171K->43152K(54272K)]43219K->43152K(58688K) [PSPermGen: 2086K->2085K(12288K)], 0.0086702 secs][Times: user=0.00 sys=0.00, real=0.01 secs]

[GC [PSYoungGen:4098K->64K(4416K)] 47250K->47312K(58688K), 0.0032439 secs] [Times:user=0.00 sys=0.06, real=0.00 secs]

[GC [PSYoungGen:4162K->64K(4416K)] 51410K->51416K(58688K), 0.0049324 secs] [Times:user=0.00 sys=0.00, real=0.00 secs]

[Full GC [PSYoungGen:64K->0K(4416K)] [PSOldGen: 51352K->51352K(56768K)] 51416K->51352K(61184K)[PSPermGen: 2085K->2085K(12288K)], 0.0026228 secs] [Times: user=0.00sys=0.00, real=0.00 secs]

[GC [PSYoungGen:4098K->48K(4416K)] 55450K->55496K(61184K), 0.0038392 secs] [Times:user=0.00 sys=0.00, real=0.00 secs]

[Full GC [PSYoungGen:48K->0K(4416K)] [PSOldGen: 55448K->55448K(56768K)]55496K->55448K(61184K) [PSPermGen: 2085K->2085K(12288K)], 0.0025522 secs][Times: user=0.02 sys=0.00, real=0.00 secs]

[Full GC [PSYoungGen:4098K->0K(4416K)] [PSOldGen: 55448K->56472K(56768K)]59546K->56472K(61184K) [PSPermGen: 2085K->2085K(12288K)], 0.0043092 secs]

 …

 

 

5、结果分析和活跃数据大小计算

 [Full GC [PSYoungGen: 48K->0K(4416K)][PSOldGen: 43171K->43152K(54272K)] 43219K->43152K(58688K) [PSPermGen:2086K->2085K(12288K)], 0.0086702 secs] [Times: user=0.00 sys=0.00, real=0.01secs]

[GC [PSYoungGen:4098K->64K(4416K)] 47250K->47312K(58688K), 0.0032439 secs] [Times:user=0.00 sys=0.06, real=0.00 secs]

[GC [PSYoungGen:4162K->64K(4416K)] 51410K->51416K(58688K), 0.0049324 secs] [Times:user=0.00 sys=0.00, real=0.00 secs]

[Full GC [PSYoungGen:64K->0K(4416K)] [PSOldGen: 51352K->51352K(56768K)]51416K->51352K(61184K) [PSPermGen: 2085K->2085K(12288K)], 0.0026228 secs][Times: user=0.00 sys=0.00, real=0.00 secs]

[GC [PSYoungGen:4098K->48K(4416K)] 55450K->55496K(61184K), 0.0038392 secs] [Times:user=0.00 sys=0.00, real=0.00 secs]

从这里可以看出,老年代在慢慢扩大。

[Full GC[PSYoungGen: 64K->0K(4416K)] [PSOldGen: 51352K->51352K(56768K)]51416K->51352K(61184K) [PSPermGen: 2085K->2085K(12288K)], 0.0026228 secs][Times: user=0.00 sys=0.00, real=0.00 secs]

到了这个数据之后,基本稳定下来,大概老年代的空间占用是51352K,老年大的大小基本上就是56768K。永久带占用空间是2085K,大小是12288K

因此,这个程序的活跃数据大小是:51352K+ 2085K约等于55M

JVM调优-计算活跃数据大小