-xms和-xmx设置完之后,堆的大小就真的是设置的大小吗?
前面看了jdk的几个查看jvm信息的命令,然后只看不动手,不用回头就忘记的干干净净了。还是实际使用一下,然后顺便结合着jvm的内存分区,再深层次的记录一下几个分区的名称、大小、gc器、等等。首先,查看一个进程,筛选一个进程,就可以使用jps -mvl ,m让他带上方法参数,v带上设置的jvm参数,l显示完整的运行main方法名称。完了之后,就可以看到这个pid的好多信息了。但是这个看到的不全,还是
前面看了jdk的几个查看jvm信息的命令,然后只看不动手,不用回头就忘记的干干净净了。还是实际使用一下,然后顺便结合着jvm的内存分区,再深层次的记录一下几个分区的名称、大小、gc器、等等。
首先,查看一个进程,筛选一个进程,就可以使用jps -mvl ,m让他带上方法参数,v带上设置的jvm参数,l显示完整的运行main方法名称。
完了之后,就可以看到这个pid的好多信息了。但是这个看到的不全,还是有些虚拟机默认的参数是看不到的,这个时候已经拿到了pid,再使用jinfo -flags pid,就会显示这个pid的手动在脚本里面显示的设置的各种参数,再加上虚拟机自动设置的默认值的参数,看一个pid的jvm设置就更完全了。
然后,还打算看看这个pid的gc情况,就可以使用jstat -gc 1s 100 意思就是1s执行一次,执行100次,连续的看内存的gc才能发现问题。
下面是 jinfo -flags pid的输出
* 命令:jinfo -flags 64363
* 输出:
* Attaching to process ID 64363, please wait...
* Debugger attached successfully.
* Server compiler detected.
* JVM version is 25.131-b11
*
* Non-default VM flags: -XX:+AlwaysPreTouch -XX:CICompilerCount=4 -XX:CMSInitiatingOccupancyFraction=75
* -XX:+HeapDumpOnOutOfMemoryError
* -XX:InitialHeapSize=4294967296 -XX:MaxHeapSize=4294967296
* -XX:MaxNewSize=697892864
* -XX:MaxTenuringThreshold=6 -XX:MinHeapDeltaBytes=196608
* -XX:NewSize=697892864
* -XX:OldPLABSize=16
* -XX:OldSize=3597074432
* -XX:ThreadStackSize=1024
* -XX:+UseCMSInitiatingOccupancyOnly -XX:+UseCompressedClassPointers
* -XX:+UseCompressedOops -XX:+UseConcMarkSweepGC -XX:+UseFastUnorderedTimeStamps
* -XX:+UseParNewGC
*
* Command line: -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSInitiatingOccupancyOnly
* -XX:+AlwaysPreTouch -Xss1m -Djava.awt.headless=true -Dfile.encoding=UTF-8 -Djna.nosys=true
* -Djdk.io.permissionsUseCanonicalPath=true -Dio.netty.noUnsafe=true -Dio.netty.noKeySetOptimization=true
* -Dio.netty.recycler.maxCapacityPerThread=0 -Dlog4j.shutdownHookEnabled=false -Dlog4j2.disable.jmx=true
* -Dlog4j.skipJansi=true -XX:+HeapDumpOnOutOfMemoryError
* -Xms4g
* -Xmx4g
* -Des.path.home=/home/lxk/elasticsearch
*
从 command line里面可以看到,通过-Xms最小-Xmx最大都是4g,不让堆自动扩展,是不是以为这个heap的大小就是完整的4个g呢?我之前一直以为是这样的,直到下面的因为好奇而测试了一下,好像不是的。
下面是一个jstat -gc pid 的执行结果
* 命令:jstat -gc 64363
* 输出:
* S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
* 68096.0 68096.0 0.0 16160.3 545344.0 397868.8 3512768.0 2109826.5 71216.0 66507.1 9304.0 8046.9 22389 942.637 270 15.966 958.603
*
这个jstat -gc其实已经把堆区的信息表达的差不多了,要是觉得这个还不够的话。
还有个jdk提供的命令,jmap -heap pid。他打印的也差不多是这个吧。
他可就不能批次执行,然后很直观的看每个分区的内存变化了。
要是打算看看内存活着live的对象具体是啥,就需要使用
jmap -histo:live pid,这个也比较重要。不过我这次是好奇大小问题。
然后,我就好奇,s区+e区+o区最终会不会等于堆heap的大小。
然后就有了下面的测试代码
package com.lxk.jdk.jvm.gc;
import java.text.DecimalFormat;
/**
* 在 jdk1.8 前提下测试堆里面的各区间的大小
* 参考 jps和jstat2个jdk提供的内存监控工具。
*
* @author LiXuekai on 2020/6/5
*/
public class HeapSizeTest {
public static void main(String[] args) {
// jinfo 出来的jvm参数,这三个的单位是 byte 字节
long maxHeapSize = 4294967296L,
newSize = 697892864L,
oldSize = 3597074432L;
System.out.println("InitialHeapSize = MaxHeapSize = " + showNumberBetter(maxHeapSize));
long all = newSize + oldSize;
System.out.println("newSize + oldSize = " + showNumberBetter(all));
System.out.println("newSize + oldSize == maxHeapSize is true.");
System.out.println("NewSize is " + showNumberBetter(newSize));
System.out.println("OldSize is " + showNumberBetter(oldSize));
// jstat 出来的jvm参数 下面的这些个的但是 k bytes KB
long s0 = 68096L,
s1 = 68096L,
eden = 545344L,
old = 3512768L,
mc = 71216,
ccs = 9304;
long young = s0 + s1 + eden;
System.out.println("s0 + s1 + eden = " + showNumberBetter(young));
long heap = young + old;
System.out.println("young + old = " + showNumberBetter(heap));
long total = heap + mc + ccs;
System.out.println("heap + mc + ccs = " + showNumberBetter(total));
}
private static String showNumberBetter(long number) {
DecimalFormat df = new DecimalFormat("#,###");
return df.format(number);
}
}
代码运行结果:
初始化的堆的大小是4.29个g,new区和old区的大小加起来和这个初始化堆的大小是一致的。
经常说新生代被分成2个s区和一个eden区,但是从上面的代码计算来看 s0 + s1 +Eden != newSize,稍微小了一丢丢。
jstat -gc 看到的old 的capacity的大小也比jinfo -flags看到的oldsize小一丢丢。
那最后的young + old =heap 也就少了
后面的heap + m + ccs 这个值就有点四不像了。
怎么这么加呢!
jdk1.8之后,metasapce区变成了本地内存,在堆之外,跟堆没关系。所以强行把他们加在一起,没道理。
ccs,是类压缩空间。说是针对64bit的系统优化的。
我就是看gc出来那么几个区,想都加一起,看看能否等于上面的初始化堆的大小。
当然是不可能的了,因为写代码的时候,我还没去了解啥是metaspace,啥是ccsc和ccscu呢。
更多推荐
所有评论(0)