HOME/Articles/

JVM虚拟机

Article Outline

查看java内存状态的命令

  • 1、jstat -gc pid 1000 1000 //解释:查看pid 的java内存状态, 1000ms打印一次,共打印1000次

通过这个命令,可以看到java项目的内存使用情况。首先,启动java项目,然后在命令行中运行jps,可以看到各个项目的pid,通过pid,结合以上的命令,即可查看。

 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT    CGC    CGCT     GCT

 0.0   1024.0  0.0   959.4  35840.0  24576.0   41984.0    28472.0   32640.0 31329.7 4736.0 4233.4     11    0.093   0      0.000   2      0.015
0.109
 0.0   1024.0  0.0   959.4  35840.0  24576.0   41984.0    28472.0   32640.0 31329.7 4736.0 4233.4     11    0.093   0      0.000   2      0.015
0.109
 0.0   1024.0  0.0   959.4  35840.0  25600.0   41984.0    28472.0   32640.0 31329.7 4736.0 4233.4     11    0.093   0      0.000   2      0.015
0.109
SOC S0幸存区的容量(kb)
S1C S1幸存区的容量(KB)
S0U S0区目前使用的空间
S1U S1区目前使用的空间
EC 年轻代中Eden(伊甸园)的容量
EU 年轻代中Eden(伊甸园)中已使用的空间
OC Old代的容量
OU Old已使用的容量
YGC 年轻GC的次数
YGCT 年轻GC的用时总时长
FGC fullgc的次数
FGCT fullgc的总时长

更多的内容见:https://docs.oracle.com/javase/7/docs/technotes/tools/share/jstat.html

关于gc的算法

分代假设:

大部分新生对象很快无用,存活时间较长的对象,可能接下来会存活更长时间。 根据分代假设,将内存进一步划分,以便针对不同的对象,不同的区域,采用不同的处理策略。

对象分配在新生代的Eden区,标记阶段存活的对象会复制到存活区,(两个存活区S0,S1 互换角色),对象存活到一定周期会提升到老年代。(标记存活的对象+非空存活区S0的对象,一起复制到另一个空的存活区S1中;然后,eden和非空存活区S0的对象都被直接清除,这时,S0中为空,下次标记清除,则将S1和Eden中的存活对象复制到S0中),默认15代以后会晋升到老年代。

根据分代假设:老年代为存活时间较长的对象,默认会继续存活,所以采用移动清除的方式:

  • 1、标记所有通过GCroot可以引用到的对象。
  • 2、删除所有不可达对象。
  • 3、整理老年代空间中的内容,将所有存活的对象复制,从老年代空间开始的地方开始存放。(为了保证大对象和晋升的对象有存放的空间)

可作为根对象:

  • 1、当前正在执行的方法里的局部变量和输入参数
  • 2、活动线程
  • 3、所有类的静态字段
  • 4、JNI引用

GC的几种方式

1、串行GC serial GC

年轻代使用mark-copy算法,老年代使用mark-sweep-compact 算法

年轻代和老年代都是单线程的gc,都会触发STW,会停止所有的应用线程

缺点

不能充分利用多核cpu,cpu利用率高,暂停时间长

优点

适合百MB堆内存的JVM,且是单核CPU,虽然暂停,但是回收效率高。

2、并行GC parallelGC

和串行GC回收方式相同,使用多线程。

3、CMSGC concurrent mark and sweep GC

对年轻代采用并行的mark-copy(标记-复制)算法,对老年代主要使用并发标记清除(mark-sweep)算法。

CMSgc的设计目标是避免在老年代垃圾回收时,出现长时间的卡顿。采用2种方式实现:

  • 不对老年代整理,而是采用空闲列表管理内存空间的回收
  • 在标记清除阶段的大部分工作都和应用线程一起并发执行,但是GC线程会和应用线程抢占CPU资源,CMS使用的并发线程数 = cpu core/4

如果服务器是多核服务器,并且主要调优目标是降低GC停顿导致的系统延迟,可以选用CMSGC。

cms的6个阶段

  • 初始标记:STW 标记所有根对象(根直接引用对象,年轻代中存活对象)
  • 并发标记:在1的基础上,遍历老年代,标记存活对象。
  • 并发预清理:标记1-2过程中状态变化的对象。
  • 最终标记: STW 完成老年代的全部存活标记
  • 并发清理:删除无用对象,回收空间
  • 并发重置:重置CMS算法相关的内部数据,为下一次GC准备。