• JVM学习六


    GC调优

    JVM常用命令行参数

    参数查询(linux环境):
    在这里插入图片描述

    • JVM的命令行参数参考:https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html

    • HotSpot参数分类

      标准: - 开头,所有的HotSpot都支持

      非标准:-X 开头,特定版本HotSpot支持特定命令

      不稳定:-XX 开头,下个版本可能取消

      java -version

      java -X

    小程序:

    public class T01_HelloGC {
        public static void main(String[] args) {
            System.out.println("Hello GC");
            List list = new LinkedList();
            for(;;) {
                byte[] b = new byte[1024 * 1024];
                list.add(b);
            }
        }
    }
    
    

    首先来看:java -XX:+PrintCommandLineFlags HelloGC
    在这里插入图片描述

    输出如下信息:

    -XX:InitialHeapSize=257560512 -XX:MaxHeapSize=4120968192 -XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC 
    Connected to the target VM, address: '127.0.0.1:11937', transport: 'socket'
    Hello GC
    Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    
    
    Process finished with exit code 1
    
    

    initialHeapSize起始堆大小,
    maxHeapSize最大堆大小
    注意:
    内存有两种方式对虚拟机产生影响,第一种是内存泄漏(memory leak,废了的对象未回收空间)【不一定会产生内存溢出】,第二种是内存溢出(out of memory)

    2、指令2:-Xmn10M -Xms40M -Xmx60M -XX:+PrintCommandLineFlags -XX:+PrintGC
    一般我们-Xms和-Xmx堆最小和最大的大小设置成一样的,因为这样可以避免堆空间的弹性伸缩【当空间不够用了往大了弹,当空间大于我们使用的时候则往小弹】
    -xmn:设置年轻代的大小
    此外除了PrintGC以外还有PrintGCDetails,PrintGCTimeStamps【打印GC时间信息】,PrintGCCauses【打印GC产生的原因】

    -XX:InitialHeapSize=41943040 -XX:MaxHeapSize=62914560 -XX:MaxNewSize=10485760//最大的年轻代大小 -XX:NewSize=10485760 -XX:+PrintCommandLineFlags -XX:+PrintGC -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC 
    Connected to the target VM, address: '127.0.0.1:12207', transport: 'socket'
    Hello GC
    GC:产生的YGC  GC产生的原因:(Allocation Failure) 年轻代堆经过一次回收之后从多大变成多大:7782K->6176K(39936K)
    [GC (Allocation Failure)  7782K->6176K(39936K), 0.0019873 secs]
    [GC (Allocation Failure)  13666K->13360K(39936K), 0.0024044 secs]
    [GC (Allocation Failure)  20761K->20432K(39936K), 0.0012763 secs]
    [GC (Allocation Failure)  27754K->27664K(39936K), 0.0012923 secs]
    //Old区域越来越大产生FullGC
    [Full GC (Ergonomics)  27664K->27309K(54272K), 0.0076299 secs]
    [GC (Allocation Failure)  34633K->34701K(53760K), 0.0021145 secs]
    [GC (Allocation Failure)  42019K->41901K(50688K), 0.0013010 secs]
    [Full GC (Ergonomics)  41901K->41646K(56832K), 0.0025557 secs]
    [GC (Allocation Failure)  44794K->44846K(58368K), 0.0007178 secs]
    [Full GC (Ergonomics)  44846K->44718K(58368K), 0.0020880 secs]
    [GC (Allocation Failure)  47858K->47886K(58368K), 0.0007106 secs]
    [Full GC (Ergonomics)  47886K->47790K(58368K), 0.0027907 secs]
    [GC (Allocation Failure)  50925K->50958K(58368K), 0.0008849 secs]
    [Full GC (Ergonomics)  50958K->50862K(58368K), 0.0028238 secs]
    [Full GC (Ergonomics)  53994K->53934K(58368K), 0.0036053 secs]
    [Full GC (Allocation Failure)  53934K->53918K(58368K), 0.0084963 secs]
    //FullGC也清理不掉了则抛出OOM异常
    Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    
    Process finished with exit code 1
    
    

    再来看下面这个:-XX:+UseConcMarkSweepGC -XX:+PrintCommandLineFlags -XX:+PrintGC
    会发现使用CMS垃圾回收器,回收对象会更频繁。

    -XX:InitialHeapSize=257560512 -XX:MaxHeapSize=4120968192 -XX:MaxNewSize=1134141440 -XX:MaxTenuringThreshold=6 -XX:OldPLABSize=16 -XX:+PrintCommandLineFlags -XX:+PrintGC -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseConcMarkSweepGC -XX:-UseLargePagesIndividualAllocation -XX:+UseParNewGC 
    Connected to the target VM, address: '127.0.0.1:8895', transport: 'socket'
    Hello GC
    [GC (Allocation Failure)  66830K->62272K(243520K), 0.0180578 secs]
    [GC (Allocation Failure)  129432K->127830K(243520K), 0.0212170 secs]
    //初始标记
    [GC (CMS Initial Mark)  128854K(243520K), 0.0001601 secs]
    [GC (Allocation Failure)  194666K->194294K(263052K), 0.0213963 secs]
    [GC (Allocation Failure)  261144K->260829K(329872K), 0.0209205 secs]
    [GC (Allocation Failure)  327688K->327391K(395664K), 0.0267197 secs]
    [GC (Allocation Failure)  394255K->393955K(462484K), 0.0658935 secs]
    [GC (Allocation Failure)  460825K->460518K(529304K), 0.0351816 secs]
    [GC (Allocation Failure)  527389K->527080K(596124K), 0.0232964 secs]
    [GC (Allocation Failure)  593953K->593641K(661916K), 0.0210760 secs]
    [GC (Allocation Failure)  660514K->660205K(728736K), 0.0188286 secs]
    [GC (Allocation Failure)  727079K->726768K(795556K), 0.0205322 secs]
    [GC (Allocation Failure)  793642K->793332K(862376K), 0.0234916 secs]
    [GC (Allocation Failure)  860207K->859893K(928168K), 0.0210479 secs]
    [GC (Allocation Failure)  926767K->926455K(994988K), 0.0200434 secs]
    [GC (Allocation Failure)  993330K->993018K(1061808K), 0.0192223 secs]
    [GC (Allocation Failure)  1059893K->1059582K(1128628K), 0.0200241 secs]
    [GC (Allocation Failure)  1126457K->1126145K(1194420K), 0.0188897 secs]
    [GC (Allocation Failure)  1193020K->1192706K(1261240K), 0.0190581 secs]
    [GC (Allocation Failure)  1259580K->1259266K(1328060K), 0.0214457 secs]
    [GC (Allocation Failure)  1326141K->1325831K(1394880K), 0.0243835 secs]
    [GC (Allocation Failure)  1392705K->1392397K(1460672K), 0.0234791 secs]
    [GC (Allocation Failure)  1459272K->1458958K(1527492K), 0.0245448 secs]
    [GC (Allocation Failure)  1525832K->1525518K(1594312K), 0.0220823 secs]
    [GC (Allocation Failure)  1592393K->1592081K(1661132K), 0.0207116 secs]
    [GC (Allocation Failure)  1658956K->1658643K(1726924K), 0.0199758 secs]
    [GC (Allocation Failure)  1725518K->1725208K(1793744K), 0.0197700 secs]
    [GC (Allocation Failure)  1792083K->1791766K(1860564K), 0.0199459 secs]
    [GC (Allocation Failure)  1858641K->1858329K(1927384K), 0.0192443 secs]
    [GC (Allocation Failure)  1925204K->1924893K(1993176K), 0.0210410 secs]
    [GC (Allocation Failure)  1991768K->1991456K(2059996K), 0.0196798 secs]
    [GC (Allocation Failure)  2058331K->2058017K(2126816K), 0.0206533 secs]
    [GC (Allocation Failure)  2124891K->2124581K(2193636K), 0.0213093 secs]
    [GC (Allocation Failure)  2191456K->2191146K(2259428K), 0.0198410 secs]
    [GC (Allocation Failure)  2258020K->2257706K(2326248K), 0.0195975 secs]
    [GC (Allocation Failure)  2324581K->2324269K(2393068K), 0.0184608 secs]
    [GC (Allocation Failure)  2391143K->2390831K(2459888K), 0.0220385 secs]
    [GC (Allocation Failure)  2457706K->2457396K(2525680K), 0.0213528 secs]
    [GC (Allocation Failure)  2524271K->2523956K(2592500K), 0.0220963 secs]
    [GC (Allocation Failure)  2590831K->2590519K(2659320K), 0.0231794 secs]
    [GC (Allocation Failure)  2657394K->2657081K(2726140K), 0.0248919 secs]
    [GC (Allocation Failure)  2723956K->2723642K(2791932K), 0.0229990 secs]
    [GC (Allocation Failure)  2790517K->2790209K(2858752K), 0.0217714 secs]
    [GC (Allocation Failure)  2857083K->2856769K(2925572K), 0.0201481 secs]
    [GC (Allocation Failure)  2923644K->2923332K(2992392K), 0.0206791 secs]
    [GC (CMS Final Remark)  2924356K(2992392K), 0.0017975 secs]
    [Full GC (Allocation Failure)  2989853K->2988836K(2994432K), 0.3383998 secs]
    [Full GC (Allocation Failure)  2993570K->2992932K(2994432K), 0.0073082 secs]
    [Full GC (Allocation Failure)  2992932K->2992916K(2994432K), 0.5134662 secs]
    [GC (CMS Initial Mark)  2992916K(2994432K), 0.0001844 secs]
    Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    
    Process finished with exit code 1
    
    
    1. java -XX:+PrintFlagsInitial 默认参数值【可以查看所有JVM启动的参数】
      在这里插入图片描述

    java -XX:+PrintFlagsFinal 最终参数值
    在这里插入图片描述

    java -XX:+PrintFlagsFinal | grep xxx 找到对应的参数
    java -XX:+PrintFlagsFinal -version |grep GC
    注意windows中用findstr:
    在这里插入图片描述

    常见垃圾回收器组合参数设定
    • -XX:+UseSerialGC = Serial New (DefNew) + Serial Old

      • 小型程序。默认情况下不会是这种选项,HotSpot会根据计算及配置和JDK版本自动选择收集器
    • -XX:+UseParNewGC = ParNew + SerialOld

      • 这个组合已经很少用(在某些版本中已经废弃)
      • https://stackoverflow.com/questions/34962257/why-remove-support-for-parnewserialold-anddefnewcms-in-the-future
    • -XX:+UseConcurrentMarkSweepGC = ParNew + CMS + Serial Old

    • -XX:+UseParallelGC = Parallel Scavenge + Parallel Old (1.8默认) 【PS + SerialOld】

    • -XX:+UseParallelOldGC = Parallel Scavenge + Parallel Old

    • -XX:+UseG1GC = G1

    • Linux中没找到默认GC的查看方法,而windows中会打印UseParallelGC

      • java +XX:+PrintCommandLineFlags -version
      • 通过GC的日志来分辨
    • Linux下1.8版本默认的垃圾回收器到底是什么?

      • 1.8.0_181 默认(看不出来)Copy MarkCompact
      • 1.8.0_222 默认 PS + PO
    GC日志详解

    还是上面的那个程序:
    设置JVM参数: -Xmn10M -Xms40M -Xmx60M -XX:+PrintCommandLineFlags -XX:+PrintGCDetails【设置输出GC的详细信息】
    在这里插入图片描述

    -XX:InitialHeapSize=41943040 -XX:MaxHeapSize=62914560 -XX:MaxNewSize=10485760 -XX:NewSize=10485760 -XX:+PrintCommandLineFlags -XX:+PrintGCDetails -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC 
    Connected to the target VM, address: '127.0.0.1:10121', transport: 'socket'
    Hello GC
    [GC (Allocation Failure) [PSYoungGen: 7782K->1016K(9216K)] 7782K->6176K(39936K), 0.0016007 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 【用户态占用时间,内核态占用时间,总占用多少时间】
    [GC (Allocation Failure) [PSYoungGen: 8506K->1000K(9216K)] 13666K->13344K(39936K), 0.0015698 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
    [GC (Allocation Failure) [PSYoungGen: 8401K->920K(9216K)] 20745K->20440K(39936K), 0.0022407 secs] [Times: user=0.13 sys=0.03, real=0.00 secs] 
    [GC (Allocation Failure) [PSYoungGen: 8242K->1016K(9216K)] 27762K->27704K(39936K), 0.0015286 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
    [Full GC (Ergonomics) [PSYoungGen: 1016K->0K(9216K)] [ParOldGen: 26688K->27309K(45056K)] 27704K->27309K(54272K), [Metaspace: 3326K->3326K(1056768K)], 0.0090290 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
    [GC (Allocation Failure) [PSYoungGen: 7324K->224K(8704K)] 34633K->34701K(53760K), 0.0016893 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
    [GC (Allocation Failure) [PSYoungGen: 7541K->1248K(5632K)] 42019K->41869K(50688K), 0.0011368 secs] [Times: user=0.08 sys=0.06, real=0.00 secs] 
    [Full GC (Ergonomics) [PSYoungGen: 1248K->0K(5632K)] [ParOldGen: 40621K->41646K(51200K)] 41869K->41646K(56832K), [Metaspace: 3326K->3326K(1056768K)], 0.0022957 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
    [GC (Allocation Failure) [PSYoungGen: 3148K->2144K(7168K)] 44794K->44814K(58368K), 0.0008460 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
    [Full GC (Ergonomics) [PSYoungGen: 2144K->0K(7168K)] [ParOldGen: 42670K->44718K(51200K)] 44814K->44718K(58368K), [Metaspace: 3326K->3326K(1056768K)], 0.0026632 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
    [GC (Allocation Failure) [PSYoungGen: 3140K->2176K(7168K)] 47858K->47918K(58368K), 0.0010636 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
    [Full GC (Ergonomics) [PSYoungGen: 2176K->0K(7168K)] [ParOldGen: 45742K->47790K(51200K)] 47918K->47790K(58368K), [Metaspace: 3326K->3326K(1056768K)], 0.0019098 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
    [GC (Allocation Failure) [PSYoungGen: 3135K->2144K(7168K)] 50925K->50958K(58368K), 0.0007480 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
    [Full GC (Ergonomics) [PSYoungGen: 2144K->0K(7168K)] [ParOldGen: 48814K->50862K(51200K)] 50958K->50862K(58368K), [Metaspace: 3326K->3326K(1056768K)], 0.0020609 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
    [Full GC (Ergonomics) [PSYoungGen: 3131K->3072K(7168K)] [ParOldGen: 50862K->50862K(51200K)] 53994K->53934K(58368K), [Metaspace: 3326K->3326K(1056768K)], 0.0017782 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
    [Full GC (Allocation Failure) [PSYoungGen: 3072K->3072K(7168K)] [ParOldGen: 50862K->50846K(51200K)] 53934K->53918K(58368K), [Metaspace: 3326K->3326K(1056768K)], 0.0071556 secs] [Times: user=0.02 sys=0.00, real=0.01 secs] 
    Heap
     PSYoungGen      total 7168K, used 3212K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
      eden space 4096K, 78% used [0x00000000ff600000,0x00000000ff923038,0x00000000ffa00000)
      from space 3072K, 0% used [0x00000000ffa00000,0x00000000ffa00000,0x00000000ffd00000)
      to   space 3072K, 0% used [0x00000000ffd00000,0x00000000ffd00000,0x0000000100000000)
     ParOldGen       total 51200K, used 50846K [0x00000000fc400000, 0x00000000ff600000, 0x00000000ff600000)
      object space 51200K, 99% used [0x00000000fc400000,0x00000000ff5a7b30,0x00000000ff600000)
     Metaspace       used 3357K, capacity 4620K, committed 4864K, reserved 1056768K
      class space    used 360K, capacity 392K, committed 512K, reserved 1048576K
    

    其后的堆信息:
    年轻代,total=eden+1个survivor,因为复制算法,所以每次只会使用一个S0或者S1区域,还有一块区域空着留着复制
    turnured generation是old区,说明了总的空间是多少
    [0x00000000fec00000, 0x00000000ff2a0000, 0x00000000ff2a0000)
    如上地址信息分别代表起始地址是在哪,然后使用空间的结束地址,以及整体空间的结束地址。

    metaspace元数据区
    class space 专门给class信息做存储的空间
    在这里插入图片描述

    JVM调优

    调优前的概念

    1、吞吐量:用户代码时间/(用户代码执行时间+垃圾回收时间) ->吞吐量大说明程序越好【大量的计算用在程序计算上面,垃圾回收计算相对较少】
    2、响应时间:STW越短,响应时间越好【将大量时间用在垃圾回收上面】响应时间目前是要求最多的
    需要确定:
    吞吐量优先还是响应时间优先?还是在满足一定的响应时间的情况下,要求多大的吞吐量。

    如做科学计算及数据挖掘:吞吐量优先(一般采用PS+PO)
    响应时间优先:网站,GUI界面,对外提供的API(1.8 G1或者PN+CMS)【G1(推荐内存够大的情况使用)CMS的吞吐量要比CMS低一些,大概在15%左右】

    什么是调优

    1、根据需求进行JVM规划和预调优
    2、优化运行JVM运行环境
    3、解决JVM运行过程中出现的各种问题(OOM【只是一部分】)

    调优规划和预调优

    调优:从业务场景开始,没有业务场景的调优就是耍流氓
    无监控【这里的监控指的是压力测试】,不调优
    步骤:
    1、熟悉业务场景(没有最好的垃圾回收器,只有最合适的垃圾回收期)
    2、响应时间,停顿时间【CMS G1 ZGC】(需要给用户做响应)
    3、吞吐量:用户代码时间/(用户代码执行时间+垃圾回收时间)【PS垃圾回收器】
    【根据以上需求选定回收器的组合】
    4、计算内存需求(内存大回收的慢一些,内存小回收的快一些)
    5、选定CPU(越高越好)
    6、设定日志参数:
    -Xloggc:/opt/xxx/logs/xxx-xxx-gc-%t.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=20M -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCCause

    -Xloggc:/opt/xxx/logs/xxx-xxx-gc-%t.log :日志文件,产生按照系统时间产生
    -XX:+UseGCLogFileRotation: 循环产生五个日志文件
    -XX:NumberOfGCLogFiles=5 :五个记录GC日志的文件
    -XX:GCLogFileSize=20M:每个文件的大小为20M
    能控制日志文件的总大小为100M

    案例1:垂直电商【只卖某种产品】,最高每日百万订单,处理订单系统需要什么样的服务器配置?

    很多服务器的配置都能支撑,可以找交易量最高峰的时间,假设每天五点到七点有720000订单在这两个
    小时产生,平均一小时产生360000订单,每秒产生100个订单(找一小时内的高峰期,1000订单/秒)
    在这个高峰时间架构要能撑住。【经验值:
    一个订单产生需要多少内存?按照512k来计算, 1000个订单高峰则需要500M内存
    如果要求响应时间在100ms的情况下,做压测来估算。
    所以一般需要估算系统的内存以及CPU,不行则加CPU扩展内存,实在不行则上云

    案例2:12306遭遇春节大规模抢票应该如何支撑?
    号称并发量100W最高
    CDN【在全国各个地方做缓存】->LVS->NGINX->业务系统->每台机器1W并发(单机10k问题),100台机器
    12306用户下单可能会用到的模型为:用户下单->减库存和订单(redis kafka)同时异步进行->等待付款减库存
    最后还会把压力压倒一台服务器。【可以做分布式本地库存+单独服务器做库存均衡】
    大流量处理方式:分而治之

    优化环境

    有一个50万PV的资料类网站(从磁盘提取文档到内存)原服务器32位,1.5G
    的堆,用户反馈网站比较缓慢,因此公司决定升级,新的服务器为64位,16G
    的堆内存,结果用户反馈卡顿十分严重,反而比以前效率更低了

    为什么原网站慢?
    很多用户浏览数据,很多数据load到内存,内存不足,频繁GC,STW长,响应时间变慢
    为什么会更卡顿?
    内存越大,FGC时间越长
    如何优化?
    PS -> PN + CMS 或者 G1

    如果一个系统CPU经常100%,如何调优?
    CPU100%那么一定有线程在占用系统资源
    1、找出哪个进程CPU高(top)
    2、该进程中的哪个线程CPU高(top -HP)
    3、导出该线程的堆栈(jstack)
    4、查找哪个方法(栈帧)消耗时间(jstack)
    5、区分是工作线程占比高还是垃圾回收线程占比高
    系统内存飙高,如何查找问题?
    1、导出堆内存(jmap)
    2、分析(jhat,jvisualvm mat jprofiler)

  • 相关阅读:
    直接插入排序
    @Linux系统安装部署Sql Server(MSSQL)
    拯救工程师,远程开发C++的四大秘笈|视频教程
    AI+医疗:使用神经网络进行医学影像识别分析 ⛵
    C++ 访问说明符详解:封装数据,控制访问,提升安全性
    阿里2022“研究型实习生”计划公布,开放200多个科研选题
    云服务器遭到黑客入侵植入木马病毒排查过程
    Java版企业电子采购招标系统源码
    notepad++ 批量替换删除指定字符之后 或者 之前的字符,Notepad+批量替换使用大全
    OPC UA:工业领域的“HTML”
  • 原文地址:https://blog.csdn.net/lsdstone/article/details/126860811