JVM第八课:JVM调优实战

面试题

案例1:系统CPU经常100%,如何调优?

推理过程是:CPU100%,那么一定有线程在占用系统资源,所以
找出哪个进程cpu高(top命令)
该进程中的哪个线程cpu高(top -Hp)
如果是java程序,导出该线程的堆栈 (jstack命令)
查找哪个方法(栈帧)消耗时间,哪个方法调用的哪个方法 (jstack),然后去看这个方法的代码
工作线程占比高 / 垃圾回收线程占比高?

案例2:系统内存飙高,如何查找问题?

导出堆内存 (jmap)
分析 (jhat jvisualvm mat jprofiler … )

如何监控JVM?

可以使用 jstat jvisualvm jprofiler arthas top…等等

一个案例理解常用工具

Linux环境下:

  1. 测试代码:
package character08;
   
   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 T15_FullGC_Problem01 {
   
       private static class CardInfo {
           BigDecimal price = new BigDecimal(0.0);
           String name = "张三";
           int age = 5;
           Date birthdate = new Date();
   
           public void m() {}
       }
   
       private static ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(50,
               new ThreadPoolExecutor.DiscardOldestPolicy());
   
       public static void main(String[] args) throws Exception {
           executor.setMaximumPoolSize(50);
   
           for (;;){
               modelFit();
               Thread.sleep(100);
           }
       }
   
       private static void modelFit(){
           List<CardInfo> taskList = getAllCardInfo();
           taskList.forEach(info -> {
               // do something
               executor.scheduleWithFixedDelay(() -> {
                   //do sth with info
                   info.m();
   
               }, 2, 3, TimeUnit.SECONDS);
           });
       }
   
       private static List<CardInfo> getAllCardInfo(){
           List<CardInfo> taskList = new ArrayList<>();
   
           for (int i = 0; i < 100; i++) {
               CardInfo ci = new CardInfo();
               taskList.add(ci);
           }
   
           return taskList;
       }
   }
  1. java -Xms200M -Xmx200M -XX:+PrintGC com.mashibing.jvm.gc.T15_FullGC_Problem01

  2. 一般是运维团队首先收到报警信息(CPU过高, Memory占比大…然后你才去查原因)

  3. top命令观察到问题:内存不断增长 CPU占用率居高不下

  4. top -Hp 观察进程中的线程,哪个线程CPU和内存占比高

  5. jps命令定位具体java进程(Linux和windows都能用)
    jstack 定位线程状况,根据jps给的线程号进行定位,重点关注:线程状态是WAITING、BLOCKED
    例如:
    看到线程WAITING状态,且waiting on <0x0000000088ca3310> (a java.lang.Object)
    假如有一个进程中100个线程,很多线程都在waiting on ,一定要找到是哪个线程持有这把锁
    怎么找?搜索jstack dump的信息,找 ,看哪个线程持有这把锁,该线程可能是RUNNABLE状态
    作业:
    1: 写一个死锁程序,用jstack观察
    2: 写一个程序,一个线程持有锁不释放,其他线程等待

  6. 为什么阿里规范里规定,线程的名称(尤其是线程池)都要写有意义的名称?
    为了方便定位!
    怎么样自定义线程池里的线程名称?
    (自定义ThreadFactory)

  7. jinfo pid显示java相关的信息,了解即可,用处不是特别大

  8. jstat -gc 动态观察gc情况 / 阅读GC日志发现频繁GC / arthas观察 / jconsole/jvisualVM/ Jprofiler(最好用,收费)
    jstat -gc 4655 500 : 每个500个毫秒打印GC的情况
    如果面试官问你是怎么定位OOM问题的?如果你回答用图形界面(错误)
    1:已经上线的系统不用图形界面用什么?(命令行cmdline arthas)
    2:图形界面到底用在什么地方?测试!测试的时候进行监控!(压测观察)

  9. jmap - histo 4655 | head -20,查找有多少对象产生,这个命令对线上系统影响不大。

  10. jmap -dump:format=b,file=xxx pid手动导出堆文件,这个命令不能线上用。
    线上系统,内存特别大,jmap执行期间会对进程产生很大影响,甚至卡顿(电商不适合),面试问到可以很多种说法:
    1:设定了参数HeapDump,OOM的时候会自动产生堆转储文件
    2:很多服务器备份(高可用),先把这台机器隔离开,停掉这台服务器对其他服务器不影响
    3:在线定位arthas(一般小点儿公司用不到,这样吹容易露馅儿)

  11. java -Xms20M -Xmx20M -XX:+UseParallelGC -XX:+HeapDumpOnOutOfMemoryError com.mashibing.jvm.gc.T15_FullGC_Problem01

  12. 使用MAT / jhat /jvisualvm 进行dump文件分析
    https://www.cnblogs.com/baihuitestsoftware/articles/6406271.html
    jhat -J-mx512M xxx.dump
    http://192.168.17.11:7000
    拉到最后:找到对应链接
    可以使用OQL查找特定问题对象

  13. 找到代码的问题

jconsole远程连接

  1. 程序启动时加入参数

    java -Djava.rmi.server.hostname=192.168.17.11 -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=11111 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false XXX

  2. 如果遭遇 Local host name unknown:XXX的错误,修改/etc/hosts文件,把XXX加入进去

    192.168.17.11 basic localhost localhost.localdomain localhost4 localhost4.localdomain4
    ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6

  3. 关闭linux防火墙(实战中应该打开对应端口)

    service iptables stop
    chkconfig iptables off #永久关闭

  4. windows上打开 jconsole远程连接 192.168.17.11:11111

jvisualvm远程连接

https://www.cnblogs.com/liugh/p/7620336.html (简单做法)

你可能感兴趣的:(JVM,java,面试,开发语言)