zoukankan      html  css  js  c++  java
  • JVM探索(一)

    JVM测试的样例代码:
    import java.lang.management.ManagementFactory;
    /**
     * @author zhailzh
     * 
     * @Date 2015年10月31日——下午14:18:15
     * 
     */
    public class Main {
      private static final int _1m = 1024 * 1024;
      public static void main(String[] argsthrows Exception {
        String name = ManagementFactory.getRuntimeMXBean().getName();
        System.out.println(name);
        // get pid
        String pid = name.split("@")[0];
        System.out.println("Pid is:" + pid);
        Thread.sleep(80000);
        byte[] alloc1alloc2alloc3alloc4;
        alloc1 = new byte[2 * _1m];
        Thread.sleep(2000);
        alloc2 = new byte[2 * _1m];
        Thread.sleep(2000);
        alloc3 = new byte[2 * _1m];
        Thread.sleep(2000);
        alloc4 = new byte[4 * _1m];
        Thread.sleep(6000);
      }
    }  
    1. 我们使用的配置是:
    -Xmx20M                 最大堆的大小          
    -Xms20M                 初始堆的大小
    -Xmn10M                 新生代的大小
    -XX:+PrintHeapAtGC    打印垃圾回收前后的信息
     -XX:+UseParNewGC   使用serial/serial old 垃圾回收器
    输出的信息:
    1. {Heap before GC invocations=0 (full 0):
    2. par new generation total 9216K, used 7145K [0x00000000f9a00000, 0x00000000fa400000, 0x00000000fa400000)
    3. eden space 8192K, 87% used [0x00000000f9a00000, 0x00000000fa0fa540, 0x00000000fa200000)
    4. from space 1024K, 0% used [0x00000000fa200000, 0x00000000fa200000, 0x00000000fa300000)
    5. to space 1024K, 0% used [0x00000000fa300000, 0x00000000fa300000, 0x00000000fa400000)
    6. tenured generation total 10240K, used 0K [0x00000000fa400000, 0x00000000fae00000, 0x00000000fae00000)
    7. the space 10240K, 0% used [0x00000000fa400000, 0x00000000fa400000, 0x00000000fa400200, 0x00000000fae00000)
    8. compacting perm gen total 21248K, used 2792K [0x00000000fae00000, 0x00000000fc2c0000, 0x0000000100000000)
    9. the space 21248K, 13% used [0x00000000fae00000, 0x00000000fb0ba1d0, 0x00000000fb0ba200, 0x00000000fc2c0000)
    10. No shared spaces configured.
    11. Heap after GC invocations=1 (full 0):
    12. par new generation total 9216K, used 541K [0x00000000f9a00000, 0x00000000fa400000, 0x00000000fa400000)
    13. eden space 8192K, 0% used [0x00000000f9a00000, 0x00000000f9a00000, 0x00000000fa200000)
    14. from space 1024K, 52% used [0x00000000fa300000, 0x00000000fa387788, 0x00000000fa400000)
    15. to space 1024K, 0% used [0x00000000fa200000, 0x00000000fa200000, 0x00000000fa300000)
    16. tenured generation total 10240K, used 6144K [0x00000000fa400000, 0x00000000fae00000, 0x00000000fae00000)
    17. the space 10240K, 60% used [0x00000000fa400000, 0x00000000faa00030, 0x00000000faa00200, 0x00000000fae00000)
    18. compacting perm gen total 21248K, used 2792K [0x00000000fae00000, 0x00000000fc2c0000, 0x0000000100000000)
    19. the space 21248K, 13% used [0x00000000fae00000, 0x00000000fb0ba1d0, 0x00000000fb0ba200, 0x00000000fc2c0000)
    20. No shared spaces configured.
    21. }

    jstat监测:



    首先对jstat上面的指标进行介绍:S0、S1 代表的是幸存1区,幸存2区或者叫做from或者to区。E 代表伊甸区,P代表老年代,
    YGC垃圾回收的次数,T代表时间,FGC代表full gc。c 代表总量, u代表使用量。那么S0C表示幸存1区
    的总容量为512M,S0U表示幸存1区使用了0M,EC表示伊甸区的容量,OU老年代的使用的量。


    那我们来分析输出的日志:
    第一行:Heap before GC invocations=1 (full 0), 翻译过来就是:
    触发第一次GC调用,FullGC调用为0的时候

    第2到9行:
    par new generation total 9216K, used 7145K [0x00000000f9a00000, 0x00000000fa400000, 0x00000000fa400000)
    eden space 8192K, 87% used [0x00000000f9a00000, 0x00000000fa0fa540, 0x00000000fa200000)
    from space 1024K, 0% used [0x00000000fa200000, 0x00000000fa200000, 0x00000000fa300000)
    to space 1024K, 0% used [0x00000000fa300000, 0x00000000fa300000, 0x00000000fa400000)
    tenured generation total 10240K, used 0K [0x00000000fa400000, 0x00000000fae00000, 0x00000000fae00000)
    the space 10240K, 0% used [0x00000000fa400000, 0x00000000fa400000, 0x00000000fa400200, 0x00000000fae00000)
    compacting perm gen total 21248K, used 2792K [0x00000000fae00000, 0x00000000fc2c0000, 0x0000000100000000)
    the space 21248K, 13% used [0x00000000fae00000, 0x00000000fb0ba1d0, 0x00000000fb0ba200, 0x00000000fc2c0000)

    par new generation 表示我们使用的设置:年轻代使用的是serial垃圾回收器
    垃圾回收大致的共有四种常见的回收机制,主要是:
    1. 串行垃圾回收器(Serial Garbage Collector)
    2. 并行垃圾回收器(Parallel Garbage Collector)
    3. 并发标记扫描垃圾回收器(CMS Garbage Collector)
    4. G1垃圾回收器(G1 Garbage Collector)
    5. 具体的哪一种,在什么场合使用,我们在JVM探索(二)中进行说明。此次不作为重点

    我们知道默认使用的是串行垃圾回收器,我们首先看一下内存的模型和第一次触发
    先贴上两张图,
    图1:

    图2:

    这里说明一点:PermanentSpace就是在hotspot 的JVM的永久代,也可以说是上面的非堆的内存的部分
    我们根据jstat检测的输出的图片可以退出m,n默认的大小:


    初始化堆的大小为20M,最大的也是20M,那么我们看一下具体的分配:伊甸区为8192 ,伊甸1区1024,伊甸2区1024,所以说SurvivorRatio
    的默认值为8,不过hotSpot的文档上面说默认值为32

    文档的名称是:Memory Management in the Java HotSpot™ Virtual Machine  -------Sun Microsystems April 2006

    那么:m值呢?NewRatio 新生代的大小为: 10240:(1024*2+ 8192 )=1, 因为新生代的大小直接通过-xmn 来进行
    设定。这个就和文档上面的说的默认值不一样的。



    总的堆大小是20M,分配开来就是1024*2+8192+10240= 20M 。 
    持久代的大小为:21248,大约是20M,印象中默认的方法区或者持久带的大小和整个堆的大小差不多。

    JVM的堆中内存的分配,我们已经清楚了,现在我们看一下GC是如何触发的,先看触发前,各个区的大小:

    第2到9行:

    par new generation total 9216K, used 7145K [0x00000000f9a00000, 0x00000000fa400000, 0x00000000fa400000)
    eden space 8192K, 87% used [0x00000000f9a00000, 0x00000000fa0fa540, 0x00000000fa200000)
    from space 1024K, 0% used [0x00000000fa200000, 0x00000000fa200000, 0x00000000fa300000)
    to space 1024K, 0% used [0x00000000fa300000, 0x00000000fa300000, 0x00000000fa400000)
    tenured generation total 10240K, used 0K [0x00000000fa400000, 0x00000000fae00000, 0x00000000fae00000)
    the space 10240K, 0% used [0x00000000fa400000, 0x00000000fa400000, 0x00000000fa400200, 0x00000000fae00000)
    compacting perm gen total 21248K, used 2792K [0x00000000fae00000, 0x00000000fc2c0000, 0x0000000100000000)
    the space 21248K, 13% used [0x00000000fae00000, 0x00000000fb0ba1d0, 0x00000000fb0ba200, 0x00000000fc2c0000)

    新生代的总的大小为9216,eden为8192,from为1024,to为1024。
    (新生代的大小就是eden+一个幸存区from的大小,这个比较的有意思,为什么分为了三个部分?为什么不直接就是两部分,幸存区为什么被分为了两个?)
    数据和jstat集测的大小一样:

    我们从这个更加详细的截图中,可以看到内存的分配1001.3-> 3049.3 分配了2048,也就是2M的内存,对应的java语句就是:
    alloc1 = new byte[2 * _1m];
    首先分配的是伊甸区的内存,然后就是3049.3--->5097.3分配了2048,还是2M的内存,对应的java语句就是:
    alloc2 = new byte[2 * _1m];
    然后下一个java语句就是:
    alloc3 = new byte[2 * _1m];; 按照原来的分配方式到了7145.3
    alloc4 = new byte[4 * _1m];

    在分配4M的时候,可定会大于伊甸区的大小8192,所以触发了minor gc 

    资料或者网上搜集的资料都显示:触发minor gc的条件是 eden区满了的时候会触发一次,新生代
    的大小是eden+from的大小?为什么不是eden+from满了以后,在触发minor gc呢?

    触发一次YGC:输出的日志是:
    Heap after GC invocations=1 (full 0):
    par new generation total 9216K, used 541K [0x00000000f9a00000, 0x00000000fa400000, 0x00000000fa400000)
    eden space 8192K, 0% used [0x00000000f9a00000, 0x00000000f9a00000, 0x00000000fa200000)
    from space 1024K, 52% used [0x00000000fa300000, 0x00000000fa387788, 0x00000000fa400000)
    to space 1024K, 0% used [0x00000000fa200000, 0x00000000fa200000, 0x00000000fa300000)
    tenured generation total 10240K, used 6144K [0x00000000fa400000, 0x00000000fae00000, 0x00000000fae00000)
    the space 10240K, 60% used [0x00000000fa400000, 0x00000000faa00030, 0x00000000faa00200, 0x00000000fae00000)
    compacting perm gen total 21248K, used 2792K [0x00000000fae00000, 0x00000000fc2c0000, 0x0000000100000000)
    the space 21248K, 13% used [0x00000000fae00000, 0x00000000fb0ba1d0, 0x00000000fb0ba200, 0x00000000fc2c0000)
    No shared spaces configured.

    YGC的基本的动作:
    • 检索heap中的对象,将还能通过GC roots能够遍历到的对象copy到to区中,由于上面分配的alloc1 ,alloc2 ,alloc3均活着,所以需要copy到to里面去 
    • 如果需要copy的对象没法进入from区中,触发分配担保机制,则将其晋升到老年代,本例中即发生了这种情况,3个2MB的数组全部晋升到老生代(OU:6144)
    • 清理eden和from中无用的垃圾
    • 互换from和to空间
    申请最后一个的4M的内存的时候,还是放在了伊甸区,伊甸区的使用变为了4423.9。

    非常感谢:




  • 相关阅读:
    mybatis3这个问题我晕为什么对于配置信息的节点放的位置也会报错
    QTP的那些事增删改查中的增加操作的测试用例及其脚本设计思路
    QTP的那些事importsheet注意的一些事情
    mybatis3中的结果集
    QTP的那些事终极项目脚本设计思路及其测试查询功能的一些实际项目体会
    mybatis+spring整合的几个好的例子
    QTP的那些事操作excel数据需要注意的事
    hibernate4的使用第一步环境搭建
    项目中关于IFRAME引发的问题【出现率很高】
    oracle直接sql语句后台递归查询返回一个树
  • 原文地址:https://www.cnblogs.com/zhailzh/p/0242cea8863dd91ffca50596d25f7bae.html
Copyright © 2011-2022 走看看