首页 > 其他 > 详细

JVM探索(一)

时间:2015-10-28 20:55:32      阅读:237      评论:0      收藏:0      [点我收藏+]
测试的样例代码:
public class Main {
  public static void main(String[] argsthrows Exception {
    // get name representing the running Java virtual machine.
    String name = ManagementFactory.getRuntimeMXBean().getName();
    System.out.println(name);
    // get pid
    String pid = name.split("@")[0];
    System.out.println("Pid is:" + pid);
    Thread.sleep(20000);
    byte[] alloc1alloc2alloc3alloc4;
    alloc1 = new byte[2 * 1024 * 1024];
    Thread.sleep(2000);
    alloc2 = new byte[2 * 1024 * 1024];
    Thread.sleep(2000);
    alloc3 = new byte[2 * 1024 * 1024];
    Thread.sleep(2000);
    alloc4 = new byte[2 * 1024 * 1024];
    Thread.sleep(2000);
  } 
1. 我们使用的配置是:
-Xmx20M                 最大堆的大小          
-Xms20M                 初始堆的大小
-XX:+PrintHeapAtGC    打印垃圾回收前后的信息

输出的信息:
  1. {Heap before GC invocations=1 (full 0):
  2. PSYoungGen total 6656K, used 5053K [0x00000000ff900000, 0x0000000100000000, 0x0000000100000000)
  3. eden space 6144K, 82% used [0x00000000ff900000,0x00000000ffdef590,0x00000000fff00000)
  4. from space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
  5. to space 512K, 0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000)
  6. ParOldGen total 13824K, used 0K [0x00000000feb80000, 0x00000000ff900000, 0x00000000ff900000)
  7. object space 13824K, 0% used [0x00000000feb80000,0x00000000feb80000,0x00000000ff900000)
  8. PSPermGen total 21504K, used 2792K [0x00000000f9980000, 0x00000000fae80000, 0x00000000feb80000)
  9. object space 21504K, 12% used [0x00000000f9980000,0x00000000f9c3a170,0x00000000fae80000)
  10. Heap after GC invocations=1 (full 0):
  11. PSYoungGen total 6656K, used 488K [0x00000000ff900000, 0x0000000100000000, 0x0000000100000000)
  12. eden space 6144K, 0% used [0x00000000ff900000,0x00000000ff900000,0x00000000fff00000)
  13. from space 512K, 95% used [0x00000000fff00000,0x00000000fff7a020,0x00000000fff80000)
  14. to space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
  15. ParOldGen total 13824K, used 4176K [0x00000000feb80000, 0x00000000ff900000, 0x00000000ff900000)
  16. object space 13824K, 30% used [0x00000000feb80000,0x00000000fef94020,0x00000000ff900000)
  17. PSPermGen total 21504K, used 2792K [0x00000000f9980000, 0x00000000fae80000, 0x00000000feb80000)
  18. object space 21504K, 12% used [0x00000000f9980000,0x00000000f9c3a170,0x00000000fae80000)
  19. }

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行:

PSYoungGen total 6656K, used 5053K [0x00000000ff900000, 0x0000000100000000, 0x0000000100000000)
eden space 6144K, 82% used [0x00000000ff900000,0x00000000ffdef590,0x00000000fff00000)
from space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
to space 512K, 0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000)
ParOldGen total 13824K, used 0K [0x00000000feb80000, 0x00000000ff900000, 0x00000000ff900000)
object space 13824K, 0% used [0x00000000feb80000,0x00000000feb80000,0x00000000ff900000)
PSPermGen total 21504K, used 2792K [0x00000000f9980000, 0x00000000fae80000, 0x00000000feb80000)
object space 21504K, 12% used [0x00000000f9980000,0x00000000f9c3a170,0x00000000fae80000)




PSYoungGen 表示这次运行中jvm自动选择了Parallel Scavenge收集器,垃圾回收大致的共有四种常见的回收机制,主要是:
  1. 串行垃圾回收器(Serial Garbage Collector)
  2. 并行垃圾回收器(Parallel Garbage Collector)
  3. 并发标记扫描垃圾回收器(CMS Garbage Collector)
  4. G1垃圾回收器(G1 Garbage Collector)
  5. 具体的哪一种,在什么场合使用,我们在JVM探索(二)中进行说明。此次不作为重点

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

我们根据jstat检测的输出的图片可以退出m,n默认的大小:
技术分享

初始化堆的大小为20M,最大的也是20M,那么我们看一下具体的分配:伊甸区为6144k ,伊甸1区512k,伊甸2区512区,所以说SurvivorRatio
的默认值为12,不过hotSpot的文档上面说默认值为32
技术分享
文档的名称是:Memory Management in the Java HotSpot? Virtual Machine  -------Sun Microsystems April 2006
网络搜到默认值说是8,不能统一啊。

那么:m值呢?NewRatio 新生代的大小为: 13824:(512*2+6144)= 2,这个和文档上面的说命比较的统一:
技术分享

总的堆大小是20M,分配开来就是512*2+6144+13824 = 20.5M 。 为什么会多出来0.5M呢?
持久代的大小为:21504k,即是21M的内存,这个分配是怎么来的,不是很清楚啊。

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

第2到9行:

PSYoungGen total 6656K, used 5053K [0x00000000ff900000, 0x0000000100000000, 0x0000000100000000)
eden space 6144K, 82% used [0x00000000ff900000,0x00000000ffdef590,0x00000000fff00000)
from space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
to space 512K, 0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000)
ParOldGen total 13824K, used 0K [0x00000000feb80000, 0x00000000ff900000, 0x00000000ff900000)
object space 13824K, 0% used [0x00000000feb80000,0x00000000feb80000,0x00000000ff900000)
PSPermGen total 21504K, used 2792K [0x00000000f9980000, 0x00000000fae80000, 0x00000000feb80000)
object space 21504K, 12% used [0x00000000f9980000,0x00000000f9c3a170,0x00000000fae80000)


年轻代的总的大小为6656k,eden为6144k,from为512k,to为512k(为什么相加不相等呢?)老年代和持久带和下面的基本相同
技术分享
我们从这个更加详细的截图中,可以看到内存的分配957.4---> 3005.4 分配了2048,也就是2M的内存,对应的java语句就是:
alloc1 = new byte[2 * 1024 * 1024]; 
首先分配的是伊甸区的内存,然后就是3005.4--->5053.4 分配了2048,还是2M的内存,对应的java语句就是:
alloc2 = new byte[2 * 1024 * 1024]; 

然后下一个java语句就是: alloc3 = new byte[2 * 1024 * 1024]; 按照原来的分配方式应该是5053.4+2048 = 7101.4 这个
时候就已经大于6144的内存了,触发一次YGC:所以才有:
PSYoungGen total 6656K, used 5053K [0x00000000ff900000, 0x0000000100000000, 0x0000000100000000)
eden space 6144K, 82% used [0x00000000ff900000,0x00000000ffdef590,0x00000000fff00000)
from space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
to space 512K, 0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000)
 这里的82%也就等于5053.4/6144 

这次YGC触发的后果是:
Heap after GC invocations=1 (full 0):
PSYoungGen total 6656K, used 488K [0x00000000ff900000, 0x0000000100000000, 0x0000000100000000)
eden space 6144K, 0% used [0x00000000ff900000,0x00000000ff900000,0x00000000fff00000)
from space 512K, 95% used [0x00000000fff00000,0x00000000fff7a020,0x00000000fff80000)
to space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
ParOldGen total 13824K, used 4176K [0x00000000feb80000, 0x00000000ff900000, 0x00000000ff900000)
object space 13824K, 30% used [0x00000000feb80000,0x00000000fef94020,0x00000000ff900000)
PSPermGen total 21504K, used 2792K [0x00000000f9980000, 0x00000000fae80000, 0x00000000feb80000)
object space 21504K, 12% used [0x00000000f9980000,0x00000000f9c3a170,0x00000000fae80000)

技术分享

YGC的基本的动作:
  • 检索heap中的对象,将还能通过GC roots能够遍历到的对象copy到to区中
  • 如果需要copy的对象没法进入from区中,则将其晋升到老年代,本例中即发生了这种情况,2个2MB的数组全部晋升到老生代(OU:4184)
  • 清理eden和from中无用的垃圾
  • 互换from和to空间
申请最后一个的2M的内存的时候,还是放在了伊甸区,伊甸区的使用从2294变为了4412 。
下一步,调整伊甸区 和幸存区的大小,触发Full gc动作,然后设置不同的垃圾回收器。




JVM探索(一)

原文:http://www.cnblogs.com/zhailzh/p/0242cea8863dd91ffca50596d25f7bae.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!