关于java:JVM系列6GC与调优3

34次阅读

共计 3023 个字符,预计需要花费 8 分钟才能阅读完成。

JVM 系列笔记目录

  • 虚拟机的根底概念
  • class 文件构造
  • class 文件加载过程
  • jvm 内存模型
  • JVM 罕用指令
  • GC 与调优

调优前的根底概念

  1. 吞吐量:用户代码工夫 /(用户代码执行工夫 + 垃圾回收工夫)
  2. 响应工夫:STW 越短,响应工夫越好
  3. 所谓调优,首先确定,谋求啥?吞吐量优先,还是响应工夫优先?还是在满足肯定的响应工夫的状况下,要求达到多大的吞吐量。如科学计算、数据挖掘:吞吐量优先; 网站、GU、API 等谋求响应工夫。

什么是调优

  1. 依据需要进行 JVM 布局和预调优
  2. 优化 JVM 运行环境(慢、卡顿)
  3. 解决 JVM 运行过程中呈现的各种问题(如 OOM)
  • 依据需要进行 JVM 布局和预调优

    调优一般来说,从业务场景开始,没有业务场景的调优都是耍流氓;无监控(压力测试,能看到后果),不调优。

    步骤

    1. ​ 熟悉业务场景
    2. 抉择回收器组合,没有最好的 GC, 只有最适宜的 GC。谋求响应工夫或进展工夫抉择 CMS、G1、ZGC 谋求吞吐量 可抉择 PS。
    3. 计算内存需要(经验值 1.5G -16G)
    4. 选定 CPU(越高越好)
    5. 设定年代大小,降级年代
    6. 设定日志参数,日志文件全放一个?10T 日志怎么查。能够设置滚动日志如 -Xloggc:/opt/xxx/logs/xxx-xxx-gc-%t.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=20M -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCCause,或是每天产生一个日志文件。
    7. 察看日志状况

    提供一个简略的案例剖析

    案例 1:垂直电商,最高每日百万订单,解决订单零碎须要什么样的服务器配置?

    这个问题比拟业余,因为很多不同的服务器配置都能撑持(1.5G -16G)。能够具体分析:一天中特定的高峰期 1 小时有 360000 订单集,1000 个订单 / 秒,能够依据经验值估算须要的内存配置。如果非要要计算,能够这么算:一个订单产生须要多少内存?512K * 1000,须要 500M 内存。

    从另外业余的角度思考:要求响应工夫 100ms,这种状况下能够通过压测的形式找到合乎的服务器配置。

  • 优化 JVM 运行环境(慢、卡顿)
    1. 提供一个简略的案例剖析。

      有一个 50 万 PV 的材料类网站(从磁盘提取文档到内存)原服务器 32 位,1.5G 的堆. 用户反馈网站比拟迟缓,因而公司决定降级。新的服务器为 64 位,16G 的堆内存,后果用户反馈卡顿非常重大,反而比以前效率更低了。

      1. 为什么原网站慢? 很多用户浏览数据,很多数据 load 到内存,内存不足,频繁 GC,STW 长,响应工夫变慢。
      2. 为什么会更卡顿?内存越大,FGC 工夫越长
      3. 如何解决?能够换垃圾回收器,如从 PS 换为 PN + CMS 或者是 1.8 以上的间接用 G1。
    2. 零碎 CPU 常常 100%,如何调优?(面试高频)

      CPU100% 那么肯定有线程在占用系统资源,

      1. 找出哪个过程 cpu 高(top)
      2. 该过程中的哪个线程 cpu 高(top -Hp)
      3. 导出该线程的堆栈 (jstack)
      4. 查找哪个办法(栈帧)耗费工夫长 (jstack)
      5. 比照工作线程占比高还是垃圾回收线程占比高
    3. 零碎内存飙高,如何调优(面试高频)

      思路:导出堆内存 (jmap); 应用工具如(jhat jvisualvm mat jprofiler) 剖析

  • 解决 JVM 运行过程中呈现的各种问题

    提供一个测试案例来阐明剖析过程和罕用的工具,代码如下:

    /**

*/

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 -Xms20M -Xmx20M -XX:+UseParallelGC -XX:+HeapDumpOnOutOfMemoryError T15_FullGC_Problem01`

2. 个别是运维团队首先受到报警信息(CPU、Memory)3. top 命令察看到问题:内存一直增长,CPU 占用率居高不下

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

5. jps 定位具体 java 过程;jstack  pid  定位线程情况,重点关注:WAITING BLOCKED

   >  waiting on <0x0000000088ca3310> (a java.lang.Object)
   >    如果有一个过程中 100 个线程,很多线程都在 waiting on <xx>,肯定要找到是哪个线程持有这把锁。怎么找?搜寻 jstack dump 的信息,找 <xx>,看哪个线程持有这把锁处于 RUNNABLE 状态。6. jinfo pid 查看 JVM 的状况,个别用途不大。7. 通过 jstat -gc 动静察看 gc 状况;或是浏览 GC 日志发现频繁 GC;或是通过 arthas 察看 gc 状况。8. 在线定位,查找有多少对象产生,留神大量的对象,应用 `jmap -histo pid |head -20`

9. `jmap -dump:format=b,file=xxx pid ` 能够在线堆转储,然而要谨慎影响很大。> 线上零碎内存特地大,jmap 执行期间对过程产生很大影响,甚至卡顿(电商不适宜)。>
   > 如何解决?启动时候设定参数 HeapDumpOnOutOfMemoryError,OOM 的 时候会主动产生堆转储文件;如果线上很多服务器备份(高可用),停掉这台服务器对其它服务没影响也能够在线堆转储;在线定位也能够用阿里的 arthas。10. 应用 MAT/jhat/jvisualvm 进行 dump 文件剖析。> 倡议应用 MAT/jvisualvm 装入剖析,界面敌对且反对简单查问

11. 最难的一点:定位到代码中的问题

    > 示例代码的问题是:线程池使用不当引起 OOM;不停 new CardInfo 对象不停地起定时线程去解决,导致这些对象越来越多

正文完
 0