死磕Java虚拟机-性能调优实战篇

2 篇文章 0 订阅

Java命令分为如下三种

1.  以java - 开头:标准参数

2.  以java -X 开头:非标参数

 

3.  以java -XX 开头:性能调优主要用这个开头的参数,但是无法找到相关参数的帮助文档,下面我教大家几个常用的命令

 

  • -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:+UseConc(urrent)MarkSweepGC = 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

 

java -XX:+PrintFlagsFinal   会打印所有的JVM参数 

 

4.  小案例如下:

package com.fengyaof.jvm.sikejvm;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class FullGC_Problem01 {

    private static class CardInfo {
        BigDecimal price = new BigDecimal(0.0);
        String name = "张三";
        int age = 5;
        Date birthday = new Date();

        public void m() {

        }
    }

    private static ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(50,
            new ThreadPoolExecutor.DiscardPolicy());

    public static void main(String[] args) throws InterruptedException {
        executor.setMaximumPoolSize(50);

        for (; ; ) {
            modelFit();
            Thread.sleep(100);
        }

    }

    private static void modelFit() {
        List<CardInfo> taskList = getAllCardInfo();
        taskList.forEach(info -> {
            executor.scheduleWithFixedDelay(new Runnable() {
                @Override
                public void run() {
                    info.m();
                }
            }, 2, 3, TimeUnit.SECONDS);
        });
    }

    private static List<CardInfo> getAllCardInfo() {
        List<CardInfo> taskList = new ArrayList<>();

        for (int i = 0; i < 100; i++) {
            CardInfo info = new CardInfo();
            taskList.add(info);
        }

        return taskList;
    }

}

 

我们在Linux上面用这个命令去运行:

 

java -Xms100M -Xmx100M -XX:+PrintGC com.fengyaof.jvm.sikejvm.FullGC_Problem01

 

命令运行如下: 我们可以分析出程序运行到一定的时候,Full GC每次回收的内存是2k,非常少。

 

我们看看top运行的内存变化:CPU上升的很高,内存消耗百分比(MEM)没有明显变化说明垃圾基本没有回收。

 

 

那么我们如何定位问题:

1) 先使用下jps 查看进程号

 

2) 打印进程号的信息:jinfo 1471

 

3) 使用命令 jstat -gc 1471 1000 (1471代表进程号,1000代表刷新频率)

 

4) 把进程里面所有的线程列举出来 jstack 1471 

    这个命令可以检查死锁:

 

5)  jmap -histo 1697 | head -20

这个命令可以把类型有多少个对象找出来,这个命令线上不能用,会暂停服务

 

面试经常会问的问题:CPU飙高,内存飙高,内存泄漏,如何排查?其实arthas一个工具就可以搞定

 

5.  我们用arthas如何进行定位?

 

arthas启动完成后如下图:

 

arthas常用命令讲解:

 

1) dashboard  线程飙高怎么排查,可以使用这个命令

 

2) jvm 查看一些基本的信息

 

3) thread 查看线程的占用情况。

thread中有很好用的命令:找到死锁

thread -b 可以找到死锁

 

4) 例如微服务里面如何查看哪个服务调用占用的内存多,可是使用下面的命令:

1.  先查询某个类,使用模糊查询:sc *com.fengyaof*

 

2.  查询某个类里面的方法:

sm com.fengyaof.jvm.sikejvm.FullGC_Problem01

 

3.  例如我们对类中某个方法有怀疑,我们可以进行跟踪,使用trace 命令

 

下面,我教几个arthas重要的命令。

 

1)  heapdump /root/temp.hprof  把堆导出来做分析

在实际生产过程中,不能使用,服务器会产生暂停。

 

我们用java自带的工具jvisualvm,把这个堆文件分析一下,如图:

 

2) jad 反编译

jad com.fengyaof.jvm.sikejvm.FullGC_Problem01

这个命令很好用,在线可以反编译看看代码是不是最新的。

 

3) 下面有个场景:我发现我们线上环境的某个代码不是最新的,我们该怎么快速替换这个文件呢,不能重启服务。

使用redefine命令,救急使用

 

我们总结一下:

CPU飙高:jstack,arthas中的thread可以揪出哪个线程飙高,可以GC线程,也可能是业务线程。

内存飙高:jmap,查看类中有多少个对象,或者是dump文件查看。

 

GC设定日志参数:

-Xloggc:/path/gc.log 

-XX:+UseGCLogFileRotation 

-XX:NumberOfGClogFiles=5 

-XX:GCLogFileSize=20M

-XX:+PrintGCDetails

-XX:+PrintGCDateStamps

-XX:+PrintGCCause

 

设置OOM的堆存储文件:

-XX:+HeapDumpOnOutOfMemoryError

-XX:HeapDumpPath=C:/temp/oom.hprof

 

想要更多的面试书籍和Java学习资料,可添加微信公众号领取

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值