JVM系列笔记目录
- 虚拟机的根底概念
- class文件构造
- class文件加载过程
- jvm内存模型
- JVM罕用指令
- GC与调优
调优前的根底概念
- 吞吐量:用户代码工夫 /(用户代码执行工夫 + 垃圾回收工夫)
- 响应工夫:STW越短,响应工夫越好
- 所谓调优,首先确定,谋求啥?吞吐量优先,还是响应工夫优先?还是在满足肯定的响应工夫的状况下,要求达到多大的吞吐量。如科学计算、数据挖掘:吞吐量优先;网站、GU、 API 等谋求响应工夫。
什么是调优
- 依据需要进行JVM布局和预调优
- 优化JVM运行环境(慢、卡顿)
- 解决JVM运行过程中呈现的各种问题(如OOM)
依据需要进行JVM布局和预调优
调优一般来说,从业务场景开始,没有业务场景的调优都是耍流氓;无监控 (压力测试,能看到后果),不调优。
步骤
- 熟悉业务场景
- 抉择回收器组合,没有最好的GC,只有最适宜的GC。谋求响应工夫或进展工夫抉择CMS、G1、ZGC谋求吞吐量 可抉择PS。
- 计算内存需要(经验值 1.5G -16G)
- 选定CPU(越高越好)
- 设定年代大小,降级年代
- 设定日志参数,日志文件全放一个?10T日志怎么查。能够设置滚动日志如
-Xloggc:/opt/xxx/logs/xxx-xxx-gc-%t.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=20M -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCCause
, 或是每天产生一个日志文件。 - 察看日志状况
提供一个简略的案例剖析
案例1:垂直电商,最高每日百万订单,解决订单零碎须要什么样的服务器配置?
这个问题比拟业余,因为很多不同的服务器配置都能撑持(1.5G -16G)。能够具体分析:一天中特定的高峰期1小时有360000订单集, 1000个订单/秒,能够依据经验值估算须要的内存配置。如果非要要计算,能够这么算:一个订单产生须要多少内存?512K * 1000,须要500M内存。
从另外业余的角度思考:要求响应工夫100ms,这种状况下能够通过压测的形式找到合乎的服务器配置。
优化JVM运行环境(慢、卡顿)
提供一个简略的案例剖析。
有一个50万PV的材料类网站(从磁盘提取文档到内存)原服务器32位,1.5G的堆.用户反馈网站比拟迟缓,因而公司决定降级。新的服务器为64位,16G的堆内存,后果用户反馈卡顿非常重大,反而比以前效率更低了。
- 为什么原网站慢?很多用户浏览数据,很多数据load到内存,内存不足,频繁GC,STW长,响应工夫变慢。
- 为什么会更卡顿?内存越大,FGC工夫越长
- 如何解决?能够换垃圾回收器,如从PS 换为PN + CMS 或者是1.8以上的间接用G1。
零碎CPU常常100%,如何调优?(面试高频)
CPU100%那么肯定有线程在占用系统资源,
- 找出哪个过程cpu高(top)
- 该过程中的哪个线程cpu高(top -Hp)
- 导出该线程的堆栈 (jstack)
- 查找哪个办法(栈帧)耗费工夫长 (jstack)
- 比照工作线程占比高还是垃圾回收线程占比高
零碎内存飙高,如何调优(面试高频)
思路: 导出堆内存(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对象不停地起定时线程去解决,导致这些对象越来越多