范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

6款Java8自带工具,轻松分析定位JVM问题

  这篇文章中介绍下如何使用 JDK 自带工具来分析和定位 Java 程序的问题。
  使用 JDK 自带工具查看 JVM 情况
  JDK 自带了很多命令行甚至是图形界面工具,帮助我们查看 JVM 的一些信息。比如,在我的机器上运行 ls 命令,可以看到 JDK 8 提供了非常多的工具或程序:
  接下来,我会与你介绍些常用的监控工具。你也可以先通过下面这张图了解下各种工具的基本作用:
  为了测试这些工具,我们先来写一段代码:启动 10 个死循环的线程,每个线程分配一个 10MB 左右的字符串,然后休眠 10 秒。可以想象到,这个程序会对 GC 造成压力: //启动10个线程 IntStream.rangeClosed(1, 10).mapToObj(i -> new Thread(() -> {     while (true) {         //每一个线程都是一个死循环,休眠10秒,打印10M数据         String payload = IntStream.rangeClosed(1, 10000000)                 .mapToObj(__ -> "a")                 .collect(Collectors.joining("")) + UUID.randomUUID().toString();         try {             TimeUnit.SECONDS.sleep(10);         } catch (InterruptedException e) {             e.printStackTrace();         }         System.out.println(payload.length());     } })).forEach(Thread::start);   TimeUnit.HOURS.sleep(1);
  修改 pom.xml,配置 spring-boot-maven-plugin 插件打包的 Java 程序的 main 方法类:      org.springframework.boot     spring-boot-maven-plugin              org.geekbang.time.commonmistakes.troubleshootingtools.jdktool.CommonMistakesApplication               
  然后使用 java -jar 启动进程,设置 JVM 参数,让堆最小最大都是 1GB: java -jar common-mistakes-0.0.1-SNAPSHOT.jar -Xms1g -Xmx1g
  完成这些准备工作后,我们就可以使用 JDK 提供的工具,来观察分析这个测试程序了。
  jps
  首先,使用 jps 得到 Java 进程列表,这会比使用 ps 来的方便:    ~ jps 12707 22261 Launcher 23864 common-mistakes-0.0.1-SNAPSHOT.jar 15608 RemoteMavenServer36 23243 Main 23868 Jps 22893 KotlinCompileDaemon
  jinfo
  然后,可以使用 jinfo 打印 JVM 的各种参数:    ~ jinfo 23864 Java System Properties: #Wed Jan 29 12:49:47 CST 2020 ... user.name=zhuye path.separator=: os.version=10.15.2 java.runtime.name=Java(TM) SE Runtime Environment file.encoding=UTF-8 java.vm.name=Java HotSpot(TM) 64-Bit Server VM ...   VM Flags: -XX:CICompilerCount=4 -XX:ConcGCThreads=2 -XX:G1ConcRefinementThreads=8 -XX:G1HeapRegionSize=1048576 -XX:GCDrainStackTargetSize=64 -XX:InitialHeapSize=268435456 -XX:MarkStackSize=4194304 -XX:MaxHeapSize=4294967296 -XX:MaxNewSize=2576351232 -XX:MinHeapDeltaBytes=1048576 -XX:NonNMethodCodeHeapSize=5835340 -XX:NonProfiledCodeHeapSize=122911450 -XX:ProfiledCodeHeapSize=122911450 -XX:ReservedCodeCacheSize=251658240 -XX:+SegmentedCodeCache -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseG1GC   VM Arguments: java_command: common-mistakes-0.0.1-SNAPSHOT.jar -Xms1g -Xmx1g java_class_path (initial): common-mistakes-0.0.1-SNAPSHOT.jar Launcher Type: SUN_STANDARD
  查看第 15 行和 19 行可以发现,我们设置 JVM 参数的方式不对,-Xms1g 和 -Xmx1g 这两个参数被当成了 Java 程序的启动参数 ,整个 JVM 目前最大内存是 4GB 左右,而不是 1GB。最近整理了一份最新的面试资料,里面收录了2021年各个大厂的面试题,打算跳槽的小伙伴不要错过,点击领取吧!
  因此,当我们怀疑 JVM 的配置很不正常的时候,要第一时间使用工具来确认参数。除了使用工具确认 JVM 参数外,你也可以打印 VM 参数和程序参数: System.out.println("VM options"); System.out.println(ManagementFactory.getRuntimeMXBean().getInputArguments().stream().collect(Collectors.joining(System.lineSeparator()))); System.out.println("Program arguments"); System.out.println(Arrays.stream(args).collect(Collectors.joining(System.lineSeparator())));
  把 JVM 参数放到 -jar 之前,重新启动程序,可以看到如下输出,从输出也可以确认这次 JVM 参数的配置正确了:    target git:(master)   java -Xms1g -Xmx1g -jar common-mistakes-0.0.1-SNAPSHOT.jar test VM options -Xms1g -Xmx1g Program arguments test
  jvisualvm
  然后,启动另一个重量级工具 jvisualvm 观察一下程序,可以在概述面板再次确认 JVM 参数设置成功了:
  继续观察监视面板可以看到,JVM 的 GC 活动基本是 10 秒发生一次,堆内存在 250MB 到 900MB 之间波动,活动线程数是 22。我们可以在监视面板看到 JVM 的基本情况,也可以直接在这里进行手动 GC 和堆 Dump 操作:
  jconsole如果希望看到各个内存区的 GC 曲线图,可以使用 jconsole 观察。jconsole 也是一个综合性图形界面监控工具,比 jvisualvm 更方便的一点是,可以用曲线的形式监控各种数据,包括 MBean 中的属性值:
  jstat
  同样,如果没有条件使用图形界面(毕竟在 Linux 服务器上,我们主要使用命令行工具),又希望看到 GC 趋势的话,我们可以使用 jstat 工具。
  jstat 工具允许以固定的监控频次输出 JVM 的各种监控指标,比如使用 -gcutil 输出 GC 和内存占用汇总信息,每隔 5 秒输出一次,输出 100 次,可以看到 Young GC 比较频繁,而 Full GC 基本 10 秒一次:    ~ jstat -gcutil 23940 5000 100   S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT    CGC    CGCT     GCT   0.00 100.00   0.36  87.63  94.30  81.06    539   14.021    33    3.972   837    0.976   18.968   0.00 100.00   0.60  69.51  94.30  81.06    540   14.029    33    3.972   839    0.978   18.979   0.00   0.00   0.50  99.81  94.27  81.03    548   14.143    34    4.002   840    0.981   19.126   0.00 100.00   0.59  70.47  94.27  81.03    549   14.177    34    4.002   844    0.985   19.164   0.00 100.00   0.57  99.85  94.32  81.09    550   14.204    34    4.002   845    0.990   19.196   0.00 100.00   0.65  77.69  94.32  81.09    559   14.469    36    4.198   847    0.993   19.659   0.00 100.00   0.65  77.69  94.32  81.09    559   14.469    36    4.198   847    0.993   19.659   0.00 100.00   0.70  35.54  94.32  81.09    567   14.763    37    4.378   853    1.001   20.142   0.00 100.00   0.70  41.22  94.32  81.09    567   14.763    37    4.378   853    1.001   20.142   0.00 100.00   1.89  96.76  94.32  81.09    574   14.943    38    4.487   859    1.007   20.438   0.00 100.00   1.39  39.20  94.32  81.09    575   14.946    38    4.487   861    1.010   20.442
  其中,S0 表示 Survivor0 区占用百分比,S1 表示 Survivor1 区占用百分比,E 表示 Eden 区占用百分比,O 表示老年代占用百分比,M 表示元数据区占用百分比,YGC 表示年轻代回收次数,YGCT 表示年轻代回收耗时,FGC 表示老年代回收次数,FGCT 表示老年代回收耗时。
  jstat 命令的参数众多,包含 -class、-compiler、-gc 等。Java 8、Linux/Unix 平台 jstat 工具的完整介绍,你可以查看这里。jstat 定时输出的特性,可以方便我们持续观察程序的各项指标。
  继续来到线程面板可以看到,大量以 Thread 开头的线程基本都是有节奏的 10 秒运行一下,其他时间都在休眠,和我们的代码逻辑匹配:
  点击面板的线程 Dump 按钮,可以查看线程瞬时的线程栈:
  jstack
  通过命令行工具 jstack,也可以实现抓取线程栈的操作:    ~ jstack 23940 2020-01-29 13:08:15 Full thread dump Java HotSpot(TM) 64-Bit Server VM (11.0.3+12-LTS mixed mode):  ...  "main" #1 prio=5 os_prio=31 cpu=440.66ms elapsed=574.86s tid=0x00007ffdd9800000 nid=0x2803 waiting on condition  [0x0000700003849000]    java.lang.Thread.State: TIMED_WAITING (sleeping)   at java.lang.Thread.sleep(java.base@11.0.3/Native Method)   at java.lang.Thread.sleep(java.base@11.0.3/Thread.java:339)   at java.util.concurrent.TimeUnit.sleep(java.base@11.0.3/TimeUnit.java:446)   at org.geekbang.time.commonmistakes.troubleshootingtools.jdktool.CommonMistakesApplication.main(CommonMistakesApplication.java:41)   at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(java.base@11.0.3/Native Method)   at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(java.base@11.0.3/NativeMethodAccessorImpl.java:62)   at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(java.base@11.0.3/DelegatingMethodAccessorImpl.java:43)   at java.lang.reflect.Method.invoke(java.base@11.0.3/Method.java:566)   at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48)   at org.springframework.boot.loader.Launcher.launch(Launcher.java:87)   at org.springframework.boot.loader.Launcher.launch(Launcher.java:51)   at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:52)  "Thread-1" #13 prio=5 os_prio=31 cpu=17851.77ms elapsed=574.41s tid=0x00007ffdda029000 nid=0x9803 waiting on condition  [0x000070000539d000]    java.lang.Thread.State: TIMED_WAITING (sleeping)   at java.lang.Thread.sleep(java.base@11.0.3/Native Method)   at java.lang.Thread.sleep(java.base@11.0.3/Thread.java:339)   at java.util.concurrent.TimeUnit.sleep(java.base@11.0.3/TimeUnit.java:446)   at org.geekbang.time.commonmistakes.troubleshootingtools.jdktool.CommonMistakesApplication.lambda$null$1(CommonMistakesApplication.java:33)   at org.geekbang.time.commonmistakes.troubleshootingtools.jdktool.CommonMistakesApplication$Lambda$41/0x00000008000a8c40.run(Unknown Source)   at java.lang.Thread.run(java.base@11.0.3/Thread.java:834)   ...
  抓取后可以使用类似fastthread (https://fastthread.io/)这样的在线分析工具来分析线程栈。
  jcmd
  最后,我们来看一下 Java HotSpot 虚拟机的 NMT 功能。
  通过 NMT,我们可以观察细粒度内存使用情况,设置 -XX:NativeMemoryTracking=summary/detail 可以开启 NMT 功能,开启后可以使用 jcmd 工具查看 NMT 数据。
  我们重新启动一次程序,这次加上 JVM 参数以 detail 方式开启 NMT: -Xms1g -Xmx1g -XX:ThreadStackSize=256k -XX:NativeMemoryTracking=detail
  在这里,我们还增加了 -XX:ThreadStackSize 参数,并将其值设置为 256k,也就是期望把线程栈设置为 256KB。我们通过 NMT 观察一下设置是否成功。
  启动程序后执行如下 jcmd 命令,以概要形式输出 NMT 结果。可以看到,当前有 32 个线程,线程栈总共保留了差不多 4GB 左右的内存。我们明明配置线程栈最大 256KB 啊,为什么会出现 4GB 这么夸张的数字呢,到底哪里出了问题呢?    ~ jcmd 24404 VM.native_memory summary 24404:   Native Memory Tracking:   Total: reserved=6635310KB, committed=5337110KB -                 Java Heap (reserved=1048576KB, committed=1048576KB)                             (mmap: reserved=1048576KB, committed=1048576KB)   -                     Class (reserved=1066233KB, committed=15097KB)                             (classes #902)                             (malloc=9465KB #908)                             (mmap: reserved=1056768KB, committed=5632KB)   -                    Thread (reserved=4209797KB, committed=4209797KB)                             (thread #32)                             (stack: reserved=4209664KB, committed=4209664KB)                             (malloc=96KB #165)                             (arena=37KB #59)   -                      Code (reserved=249823KB, committed=2759KB)                             (malloc=223KB #730)                             (mmap: reserved=249600KB, committed=2536KB)   -                        GC (reserved=48700KB, committed=48700KB)                             (malloc=10384KB #135)                             (mmap: reserved=38316KB, committed=38316KB)   -                  Compiler (reserved=186KB, committed=186KB)                             (malloc=56KB #105)                             (arena=131KB #7)   -                  Internal (reserved=9693KB, committed=9693KB)                             (malloc=9661KB #2585)                             (mmap: reserved=32KB, committed=32KB)   -                    Symbol (reserved=2021KB, committed=2021KB)                             (malloc=1182KB #334)                             (arena=839KB #1)   -    Native Memory Tracking (reserved=85KB, committed=85KB)                             (malloc=5KB #53)                             (tracking overhead=80KB)   -               Arena Chunk (reserved=196KB, committed=196KB)                             (malloc=196KB)
  重新以 VM.native_memory detail 参数运行 jcmd: jcmd 24404 VM.native_memory detail
  可以看到,有 16 个可疑线程,每一个线程保留了 262144KB 内存,也就是 256MB (通过下图红框可以看到,使用关键字 262144KB for Thread Stack from 搜索到了 16 个结果):
  其实,ThreadStackSize 参数的单位是 KB,所以我们如果要设置线程栈 256KB,那么应该设置 256 而不是 256k。重新设置正确的参数后,使用 jcmd 再次验证下:
  除了用于查看 NMT 外,jcmd 还有许多功能。我们可以通过 help,看到它的所有功能: jcmd 24781 help
  除了 jps、jinfo、jcmd、jstack、jstat、jconsole、jvisualvm 外,JDK 中还有一些工具,你可以通过官方文档查看完整介绍。
  官方文档:https://docs.oracle.com/javase/8/docs/technotes/tools/

又一项技术领先全球,美国科学家坦言,先进的不像中国制造科学技术领域的研究一直是各国之间的优势比较。尽管芯片领域的科学研究仍有很大的突破空间,但在其他科学技术领域,我国对技术的掌握程度甚至领先于世界水平。科学技术的进步对每个国家都至关重游戏本行业开始变天,30系显卡产品已经上市2020年是命运多舛的一年,不仅整个世界都出现了混乱,笔记本电脑行业也产生了些许动荡。因为疫情的缘故,本来被称为夕阳产业的笔记本行业迎来了一次难得的回暖,再加上20系显卡和AMD锐同是5G轻旗舰,荣耀X10比iQOOZ1差多少?性能与拍照旗舰的对决随着高端5G手机市场产品趋近饱和,各大手机厂商开始把5G手机竞争的主战场转移到2000元出头的价位段上。最近发布的iQOOZ1和荣耀X10便是这一价位5G手机中的佼佼者,下面我们就它的出现建筑工人又要失业了?24小时工作不间断,细思极恐由于人工智能的发展,一些体力工作者逐渐面临失业。例如,在当前的工厂中,许多流水线已被人工智能取代,人工智能不仅可以有效地完成工作,而且可以提高速度,减少危险的发生。可以看出,人工智学慧网CEO京东直播带货首秀,载歌载舞花样送福利2020年开局,突如其来的疫情,改变了人们的生活习惯,也在重构着人们的消费方式,直播带货的星火越发燎原,引发全民浪潮。各大企业CEO纷纷下场,投身直播队伍,亲自为自家产品卖力吆喝带红米还有后手?可看到配置后我慌了,就问你干得过谁?之前我们一直认为小米会针对荣耀X10生产一款千元水桶机红米10X,主打高性价比和5G。但在联发科宣布G85处理器不支持5G之后,小编逐渐对它失去了耐心,但万万没想到的是,红米竟然还RedmiK30对比realmeX50,最后还是它赢了说到性价比,用户第一时间会想到小米手机,其RedmiK305G的起价不到2000元,一度成为5G手机性价比的代名词。毕竟,如今5G手机普遍昂贵。另外,它在相机屏幕以及参配上有着相当不仅有女性机器人,男性机器人也即将上市,男同胞们地位岌岌可危随着科学技术的不断进步,为我们的生活添加了许多色彩,特别是人工智能的出现,使我们感受到了未来世界的美好。目前,中国正在加快5G建设步伐,人工智能将得到更快的发展。以扫地机器人为例,2017年全国广播电视行业统计公报的喜与忧近日,国家广播电视总局财务司公布了2017年全国广播电视行业统计公报(以下简称公报),有喜有忧,喜的是网络视听以及新媒体广告等业务高速增长,国家投入进一步加大忧的是传统电视收入和有西安等二线城市如何有效抢占影响力?4月19日,西安市旅游发展委员会与抖音短视频在西安举行新闻发布会宣布达成战略合作,双方计划将基于抖音的全系产品,在世界范围内更好地宣传推广西安的文化旅游资源,进一步扩大西安在世界范华商传媒低调深耕三四线二三里不是网红故事,而是战略升级在传统媒体转型进程中,业界似乎很少听到华商传媒的声音。作为唯一一家在全国运营都市报的传媒集团,低调务实似乎一直是华商传媒的风格,但是,在网红时代,这家传媒集团的声音似乎又太过沉寂。
双十一最想下单的好物推荐清单跟着买就对了双11剁手节忍不住加购了这几件高逼格好物不但改变生活质量,还能带来新鲜感,性价比超级高。不管是蜗居还是租房用心布置和装扮的房间才有生活的气息。生活不止于眼前的苟且,还有诗与远方!话家里添置哪些好物,让你的幸福感爆棚?家电早已成为我们生活中的一部分了,人人都离不开它。那么,家里添置哪些好物,让你的幸福感爆棚?对于需要购买家电的家庭来说,双十一马上到了,可以趁机准备几款小家电给家里来一次小小的改头哪款K歌软件最好用?这几款一定要收藏唱歌不仅缓解压力,还能有助于提高人体免疫力。当今时代大屏或者大屏投影仪也能助你练歌。在成为K歌之王之前,首先你需要安装几款K歌软件,一款好的K歌软件可以让你锦上添花,想唱就唱,唱得顶配版一加8T为何瞬间被抢光?用户的反馈刺激到了我一加8T开售了,被秒空?买个手机这样电子产品跟闹着玩似的,忽然感觉国人好富裕。1分钟破亿10分钟破两亿的销量实在是震惊到我了,12256GB版本更是直接被秒空,瞬间成为数码圈讨论的全新A3入门奥迪新贵,造型激进运动,加长轴距媲美B级车外观造型更为激进帅气,内饰设计更具未来感,整车品质感也有了全面的提升,从以上种种表现来看,奥迪A3的全新换代似乎就是一次大革命,本就以最入门级车型为定位的奥迪豪车,这样一来势必吸引春享好礼领克西北大区甘青宁新藏五省联合品鉴会生而全球开放互联领克汽车是由吉利汽车沃尔沃汽车和吉利控股集团合资成立的新时代高端品牌。领克为个性开放的都市人群而生,重塑人与车之间的关系,创造全新的生活形态。2021年4月24日,小米新Logo引起热议,网友这设计跟乐橙logo太像了小米正式发布的新Logo是由日本国际著名设计师原研哉操刀设计,仅仅在原有Logo上加了一行代码bo,rderradius19px,就是加了一个圆角矩形的样式。这样简洁的设计就值20boss直聘崩了网友神评论打工人太多了BOSS直聘是一款直聘模式的P2P在线应聘软件,用户可在App上通过聊天的方式,与企业高管,甚至是创始人一对一沟通,更快速地获得Offer。boss直聘居然崩了?是因为毕业季找工作陈思诚和佟丽娅宣布离婚,网友纷纷为佟丽娅送祝福在520这个全民欢腾的日子里,大家还在朋友圈看着红包转账秀恩爱的截图吃着狗粮,陈思诚佟丽娅宣布离婚的新闻率先打破清晨的宁静,两人似乎全然不顾传统与偏见,就这么猝不及防地为大家加餐了星巴克APP崩了,网友感叹只是想喝杯咖啡怎么就这么难好多网友都说就想喝个咖啡结果星巴克APP崩了,你们的星巴克APP还好用吗?原来是5月18日星巴克推出了买满150元赠送电脑包的活动。此次活动吸引了大量的人气,导致星巴克APP系统崩宇航员太空吃播名场面,食物直接飞进嘴巴里,网友真萌经过中国航空事业的多年发展,我们的航天员不但能在太空中吃饱饭,而且还能吃到120多种食品。据说食谱是按航天员喜好定制的,四次任务乘组的12名航天员,都能吃到自己喜欢吃的食物。食谱周