Docker java程序jvm分析

   由于我项目制作的java运行镜像都是基于anapsix/alpine-java,这个是目前最小的java镜像,jdk的版本是1.8的。anapsix/alpine-java是一个jre的镜像,如果你要做jvm分析,需要准备tools.jar,jstat,jmap文件。下面就是我的实际操作步骤。

一、准备tools.jar,jstat,jmap 并拷贝到docker容器里面

     我这里只用到jstat和jmap,jstat用于在容器里面直接观察jvm状况。jmap用于生成heapdump文件,生成的heapdump文件,通过MemoryAnalyzer工具分析java堆里面的对象。

  为什么需要用到tools.jar,其实tools.jar包装了jstat,jmap,jinfo等需要的内容。

[ellis@localhost bin]# find /usr -name java
/usr/local/share/swig/3.0.0/java
/usr/java
/usr/java/jdk1.8.0_181-amd64/jre/bin/java
/usr/java/jdk1.8.0_181-amd64/bin/java
/usr/bin/java

[ellis@localhost bin]# docker container ls|grep processor
22a5379ac905        my-registry:5000/processor:lastest                                "/bin/sh ./start…"   17 hours ago        Up 17 hours         14051/tcp                                             dev-smarthome-processor.1.mosm97bkvnnsr4v3dku7vjrhk

[ellis@localhost bin]# docker exec -it 22a5379ac905 /bin/sh
/data # find / -name java
/etc/ssl/certs/java
/opt/jdk1.8.0_202/jre/bin/java
/data # exit
[ellis@localhost bin]# docker cp /usr/java/jdk1.8.0_181-amd64/lib/tools.jar 22a5379ac905:/opt/jdk1.8.0_202/jre/lib
[ellis@localhost bin]# docker cp /usr/java/jdk1.8.0_181-amd64/bin/jstat 22a5379ac905:/opt/jdk1.8.0_202/bin
[ellis@localhost bin]# docker cp /usr/java/jdk1.8.0_181-amd64/bin/jmap 22a5379ac905:/opt/jdk1.8.0_202/bin

二、进入docker容器,分析jvm

    下面是用jstat统计给出结果如下,可以看出的YGC(年轻代GC次数)达到6668次,而我的程序运行才几个小时而已,实在恐怖,究竟是什么原因导致的呢?由于我采用的是ParallelGC收集器,配置了JVM参数-XX:+UseAdaptiveSizePolicy,这个是一个自动策略,会自动调节新生代和老年代比例,目前我的新生代跟老年代内存比例(4096:57344)= 1: 14,Edem : from : to =2048:1024:1024=2:1:1。GC次数那么多,看来是新生代跟老年代内存比例问题,由于新生代内存太少导致GC频繁,得调整新生代内存大小。

    另外要说明的是为什么在容器里需要配置-XX:+PrintFlagsFinal -XX:+UnlockExperimentalVMOptions 虚拟参数,这是因为从Java 9之后(8u131+),能够更好的在限制jvm堆内存大小,而不用通过Xms来设置。实际上通过Xms来设置其实相当于做了两层限制,本来容器就可以限制可以使用的最大内存大小。而在程序里面通过jvm参数-Xmx来设置jvm堆内存大小,显示不灵活动态。

[ellis@localhost bin]# docker exec -it 22a5379ac905 /bin/sh
/data # ps -ef|grep java
    8 root     11:24 java -server -XX:+PrintFlagsFinal -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:+UseParallelGC -XX:ParallelGCThreads=8 -XX:MaxGCPauseMillis=20 -XX:+UseAdaptiveSizePolicy -XX:+HeapDumpOnOutOfMemoryError -XX:+ExitOnOutOfMemoryError -jar -Dspring.profiles.active=testrd -Dserver.port=4051 -Dsmart.instanceId=02 -Dsmart.homePath=/tmp/ ./processor.jar
  218 root      0:00 grep java

/data # jstat -gc 8 5000
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT   
1024.0 1024.0 288.0   0.0    2048.0   983.5    57344.0    51986.7   97408.0 94070.6 11648.0 11003.2   6668   45.186  289    52.234   97.420
1024.0 1024.0 288.0   0.0    2048.0   1592.5   57344.0    51986.7   97408.0 94070.6 11648.0 11003.2   6668   45.186  289    52.234   

统计列含义

S0C:第一个Survivor Space 理解新生代From区容量

S1C:第二个Survivor Space 理解为新生代To区容量

S0U:第一个Survivor Space 理解新生代From区已使用的容量

S1U:第二个Survivor Space 理解为新生代To区已使用的容量

EC:新生代Edem容量

EU:新生代Edem已使用的容量

OC:老年代区容量

OU:老年代区已使用的容量

MC:Mataspace区容量

MU:Mataspace区实际使用量

CCSC:压缩类空间大小(不是很懂,先标记一下)

CCSU:压缩类空间使用率(不是很懂,先标记一下)

YGC:年轻代垃圾回收次数

YGCT:年轻代垃圾回收时间

FGC:年老代垃圾回收次数

FGCT:年老代垃圾回收时间

GCT:总垃圾回收时间

 

S0:新生代From区域使用率

S0:新生代To区域使用率

E:新生代Edem区使用率

O:老年代使用率,OU/OC

M:Matespace区使用率,MU/MC

CCS:压缩类空间使用率

三、生headump文件

/data # jmap -dump:format=b,file=processor_dump.hprof 8
/data # exit
[ellis@localhost bin]# docker cp 22a5379ac905:/data/processor_dump.hprof .

 

你可能感兴趣的:(JVM,微服)