关系经济人类预测化学自然
中准网
自然科学
知识物理
化学生物
地理解释
预测理解
本质社会
人类现象
行为研究
经济政治
心理结构
关系指导
人文遗产

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

8月24日 溷元楼投稿
  这篇文章中介绍下如何使用JDK自带工具来分析和定位Java程序的问题。
  使用JDK自带工具查看JVM情况
  JDK自带了很多命令行甚至是图形界面工具,帮助我们查看JVM的一些信息。比如,在我的机器上运行ls命令,可以看到JDK8提供了非常多的工具或程序:
  接下来,我会与你介绍些常用的监控工具。你也可以先通过下面这张图了解下各种工具的基本作用:
  为了测试这些工具,我们先来写一段代码:启动10个死循环的线程,每个线程分配一个10MB左右的字符串,然后休眠10秒。可以想象到,这个程序会对GC造成压力:启动10个线程IntStream。rangeClosed(1,10)。mapToObj(inewThread((){while(true){每一个线程都是一个死循环,休眠10秒,打印10M数据StringpayloadIntStream。rangeClosed(1,10000000)。mapToObj(a)。collect(Collectors。joining())UUID。randomUUID()。toString();try{TimeUnit。SECONDS。sleep(10);}catch(InterruptedExceptione){e。printStackTrace();}System。out。println(payload。length());}}))。forEach(Thread::start);TimeUnit。HOURS。sleep(1);
  修改pom。xml,配置springbootmavenplugin插件打包的Java程序的main方法类:plugingroupIdorg。springframework。bootgroupIdspringbootmavenpluginartifactIdconfigurationmainClassorg。geekbang。time。commonmistakes。troubleshootingtools。jdktool。CommonMistakesApplicationmainClassconfigurationplugin
  然后使用javajar启动进程,设置JVM参数,让堆最小最大都是1GB:javajarcommonmistakes0。0。1SNAPSHOT。jarXms1gXmx1g
  完成这些准备工作后,我们就可以使用JDK提供的工具,来观察分析这个测试程序了。
  jps
  首先,使用jps得到Java进程列表,这会比使用ps来的方便:jps1270722261Launcher23864commonmistakes0。0。1SNAPSHOT。jar15608RemoteMavenServer3623243Main23868Jps22893KotlinCompileDaemon
  jinfo
  然后,可以使用jinfo打印JVM的各种参数:jinfo23864JavaSystemProperties:WedJan2912:49:47CST2020。。。user。namezhuyepath。separator:os。version10。15。2java。runtime。nameJava(TM)SERuntimeEnvironmentfile。encodingUTF8java。vm。nameJavaHotSpot(TM)64BitServerVM。。。VMFlags:XX:CICompilerCount4XX:ConcGCThreads2XX:G1ConcRefinementThreads8XX:G1HeapRegionSize1048576XX:GCDrainStackTargetSize64XX:InitialHeapSize268435456XX:MarkStackSize4194304XX:MaxHeapSize4294967296XX:MaxNewSize2576351232XX:MinHeapDeltaBytes1048576XX:NonNMethodCodeHeapSize5835340XX:NonProfiledCodeHeapSize122911450XX:ProfiledCodeHeapSize122911450XX:ReservedCodeCacheSize251658240XX:SegmentedCodeCacheXX:UseCompressedClassPointersXX:UseCompressedOopsXX:UseG1GCVMArguments:javacommand:commonmistakes0。0。1SNAPSHOT。jarXms1gXmx1gjavaclasspath(initial):commonmistakes0。0。1SNAPSHOT。jarLauncherType:SUNSTANDARD
  查看第15行和19行可以发现,我们设置JVM参数的方式不对,Xms1g和Xmx1g这两个参数被当成了Java程序的启动参数,整个JVM目前最大内存是4GB左右,而不是1GB。最近整理了一份最新的面试资料,里面收录了2021年各个大厂的面试题,打算跳槽的小伙伴不要错过,点击领取吧!
  因此,当我们怀疑JVM的配置很不正常的时候,要第一时间使用工具来确认参数。除了使用工具确认JVM参数外,你也可以打印VM参数和程序参数:System。out。println(VMoptions);System。out。println(ManagementFactory。getRuntimeMXBean()。getInputArguments()。stream()。collect(Collectors。joining(System。lineSeparator())));System。out。println(Programarguments);System。out。println(Arrays。stream(args)。collect(Collectors。joining(System。lineSeparator())));
  把JVM参数放到jar之前,重新启动程序,可以看到如下输出,从输出也可以确认这次JVM参数的配置正确了:targetgit:(master)javaXms1gXmx1gjarcommonmistakes0。0。1SNAPSHOT。jartestVMoptionsXms1gXmx1gProgramargumentstest
  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次,可以看到YoungGC比较频繁,而FullGC基本10秒一次:jstatgcutil239405000100S0S1EOMCCSYGCYGCTFGCFGCTCGCCGCTGCT0。00100。000。3687。6394。3081。0653914。021333。9728370。97618。9680。00100。000。6069。5194。3081。0654014。029333。9728390。97818。9790。000。000。5099。8194。2781。0354814。143344。0028400。98119。1260。00100。000。5970。4794。2781。0354914。177344。0028440。98519。1640。00100。000。5799。8594。3281。0955014。204344。0028450。99019。1960。00100。000。6577。6994。3281。0955914。469364。1988470。99319。6590。00100。000。6577。6994。3281。0955914。469364。1988470。99319。6590。00100。000。7035。5494。3281。0956714。763374。3788531。00120。1420。00100。000。7041。2294。3281。0956714。763374。3788531。00120。1420。00100。001。8996。7694。3281。0957414。943384。4878591。00720。4380。00100。001。3939。2094。3281。0957514。946384。4878611。01020。442
  其中,S0表示Survivor0区占用百分比,S1表示Survivor1区占用百分比,E表示Eden区占用百分比,O表示老年代占用百分比,M表示元数据区占用百分比,YGC表示年轻代回收次数,YGCT表示年轻代回收耗时,FGC表示老年代回收次数,FGCT表示老年代回收耗时。
  jstat命令的参数众多,包含class、compiler、gc等。Java8、LinuxUnix平台jstat工具的完整介绍,你可以查看这里。jstat定时输出的特性,可以方便我们持续观察程序的各项指标。
  继续来到线程面板可以看到,大量以Thread开头的线程基本都是有节奏的10秒运行一下,其他时间都在休眠,和我们的代码逻辑匹配:
  点击面板的线程Dump按钮,可以查看线程瞬时的线程栈:
  jstack
  通过命令行工具jstack,也可以实现抓取线程栈的操作:jstack239402020012913:08:15FullthreaddumpJavaHotSpot(TM)64BitServerVM(11。0。312LTSmixedmode):。。。main1prio5osprio31cpu440。66mselapsed574。86stid0x00007ffdd9800000nid0x2803waitingoncondition〔0x0000700003849000〕java。lang。Thread。State:TIMEDWAITING(sleeping)atjava。lang。Thread。sleep(java。base11。0。3NativeMethod)atjava。lang。Thread。sleep(java。base11。0。3Thread。java:339)atjava。util。concurrent。TimeUnit。sleep(java。base11。0。3TimeUnit。java:446)atorg。geekbang。time。commonmistakes。troubleshootingtools。jdktool。CommonMistakesApplication。main(CommonMistakesApplication。java:41)atjdk。internal。reflect。NativeMethodAccessorImpl。invoke0(java。base11。0。3NativeMethod)atjdk。internal。reflect。NativeMethodAccessorImpl。invoke(java。base11。0。3NativeMethodAccessorImpl。java:62)atjdk。internal。reflect。DelegatingMethodAccessorImpl。invoke(java。base11。0。3DelegatingMethodAccessorImpl。java:43)atjava。lang。reflect。Method。invoke(java。base11。0。3Method。java:566)atorg。springframework。boot。loader。MainMethodRunner。run(MainMethodRunner。java:48)atorg。springframework。boot。loader。Launcher。launch(Launcher。java:87)atorg。springframework。boot。loader。Launcher。launch(Launcher。java:51)atorg。springframework。boot。loader。JarLauncher。main(JarLauncher。java:52)Thread113prio5osprio31cpu17851。77mselapsed574。41stid0x00007ffdda029000nid0x9803waitingoncondition〔0x000070000539d000〕java。lang。Thread。State:TIMEDWAITING(sleeping)atjava。lang。Thread。sleep(java。base11。0。3NativeMethod)atjava。lang。Thread。sleep(java。base11。0。3Thread。java:339)atjava。util。concurrent。TimeUnit。sleep(java。base11。0。3TimeUnit。java:446)atorg。geekbang。time。commonmistakes。troubleshootingtools。jdktool。CommonMistakesApplication。lambdanull1(CommonMistakesApplication。java:33)atorg。geekbang。time。commonmistakes。troubleshootingtools。jdktool。CommonMistakesApplicationLambda410x00000008000a8c40。run(UnknownSource)atjava。lang。Thread。run(java。base11。0。3Thread。java:834)。。。
  抓取后可以使用类似fastthread(https:fastthread。io)这样的在线分析工具来分析线程栈。
  jcmd
  最后,我们来看一下JavaHotSpot虚拟机的NMT功能。
  通过NMT,我们可以观察细粒度内存使用情况,设置XX:NativeMemoryTrackingsummarydetail可以开启NMT功能,开启后可以使用jcmd工具查看NMT数据。
  我们重新启动一次程序,这次加上JVM参数以detail方式开启NMT:Xms1gXmx1gXX:ThreadStackSize256kXX:NativeMemoryTrackingdetail
  在这里,我们还增加了XX:ThreadStackSize参数,并将其值设置为256k,也就是期望把线程栈设置为256KB。我们通过NMT观察一下设置是否成功。
  启动程序后执行如下jcmd命令,以概要形式输出NMT结果。可以看到,当前有32个线程,线程栈总共保留了差不多4GB左右的内存。我们明明配置线程栈最大256KB啊,为什么会出现4GB这么夸张的数字呢,到底哪里出了问题呢?jcmd24404VM。nativememorysummary24404:NativeMemoryTracking:Total:reserved6635310KB,committed5337110KBJavaHeap(reserved1048576KB,committed1048576KB)(mmap:reserved1048576KB,committed1048576KB)Class(reserved1066233KB,committed15097KB)(classes902)(malloc9465KB908)(mmap:reserved1056768KB,committed5632KB)Thread(reserved4209797KB,committed4209797KB)(thread32)(stack:reserved4209664KB,committed4209664KB)(malloc96KB165)(arena37KB59)Code(reserved249823KB,committed2759KB)(malloc223KB730)(mmap:reserved249600KB,committed2536KB)GC(reserved48700KB,committed48700KB)(malloc10384KB135)(mmap:reserved38316KB,committed38316KB)Compiler(reserved186KB,committed186KB)(malloc56KB105)(arena131KB7)Internal(reserved9693KB,committed9693KB)(malloc9661KB2585)(mmap:reserved32KB,committed32KB)Symbol(reserved2021KB,committed2021KB)(malloc1182KB334)(arena839KB1)NativeMemoryTracking(reserved85KB,committed85KB)(malloc5KB53)(trackingoverhead80KB)ArenaChunk(reserved196KB,committed196KB)(malloc196KB)
  重新以VM。nativememorydetail参数运行jcmd:jcmd24404VM。nativememorydetail
  可以看到,有16个可疑线程,每一个线程保留了262144KB内存,也就是256MB(通过下图红框可以看到,使用关键字262144KBforThreadStackfrom搜索到了16个结果):
  其实,ThreadStackSize参数的单位是KB,所以我们如果要设置线程栈256KB,那么应该设置256而不是256k。重新设置正确的参数后,使用jcmd再次验证下:
  除了用于查看NMT外,jcmd还有许多功能。我们可以通过help,看到它的所有功能:jcmd24781help
  除了jps、jinfo、jcmd、jstack、jstat、jconsole、jvisualvm外,JDK中还有一些工具,你可以通过官方文档查看完整介绍。
  官方文档:https:docs。oracle。comjavase8docstechnotestools
投诉 评论 转载

荣耀X50Note手机被曝光,采用7。12英寸大屏,6000说真的,荣耀这个手机品牌,确实挺不错的。不光旗舰机型综合性价比不错,就连入门的中低端机型,也是很不错的。比如荣耀的X系列机型,就非常的不错的,使用过的人,都能感受到。最近……拳王泰森休息期间带娇妻庆生,开心大呼要迎接第七个宝宝到来12月3日,英国《镜报》报道了拳王泰森弗瑞在训练休息期间带着妻子帕里斯弗瑞吃生日餐的照片。本周三帕里斯就曾在Instagram上分享了她和这位世界重量级冠军拳王泰森的合照。帕里……没了胆以后,你的肠道还好吗今天就跟大家分享几点对于治疗胆汁型腹泻比较有效的办法。第一点就是饮食上要注意,不要吃太油腻的食物,因为毕竟胆囊切除以后胆汁没有办法按需分配了,当你吃很多油腻的食物后,需要……6款Java8自带工具,轻松分析定位JVM问题这篇文章中介绍下如何使用JDK自带工具来分析和定位Java程序的问题。使用JDK自带工具查看JVM情况JDK自带了很多命令行甚至是图形界面工具,帮助我们查看JVM的……原神太快乐!有万叶后一定要做这7件事万叶不仅能提升你的账号强度,还能带来很多欢乐,毕竟快乐风男不是白叫的。已经抽到万叶的玩家,强烈推荐去做这7件事,还没万叶的话先收藏,以后保准能用上。1。吸猫就是字面……LOL天注定组合重聚!TES官宣S9冠军打野Tian加盟20212022赛季冬季转会期终于落下帷幕,憋气许久的LPL各大战队开始陆续官宣选手离队和新援加盟的消息。作为LPL近年崛起的新生代强队之一,TES战队麾下拥有众多实力强劲的本……陈伟霆前任,陈星旭前任,于小彤前任,看到张新成意外了要是说到哪个领域的爱情分分合合最快,那娱乐圈定是当仁不让的。在娱乐圈中的演员都是有着很多段感情的,特别是在他们有了名气之后,他们的日常生活就会被很多人所关注,所以在网上也常常被……这个底线我们该不该守,要不要守呢?话说自2017年起,P2P行业进入了一个疯狂增长期,最高的时候全国大小网贷平台高达万家,而这些网贷平台却没有一家是合规的,甚至可以说存在就是最大的社会问题,从以往的形式来看,中……国庆川A大军都去哪儿了头条创作挑战赛这个国庆假期远出旅行out了川A出城大军也out了,成都人都去哪了?答案还得是骑行,最美的风景在路上。骑行真的很惬意舒畅快乐,要知道,在骑车这项运动上,成都……杜峰太能装了,篮球媒体人证实马尚已到达赛区,办完手续即可出战北京时间4月5日,根据知名篮球媒体人导演我躺那CBA的发文爆料,证实广东队外援马尚布鲁克斯已经在2号就到达江西南昌赛区了,并已经开始和球队进行合练,对于这个消息可谓是激起千层浪……为什么说鱼腥草是害人草?常吃鱼腥草会怎么样呢?一文告诉你鱼腥草是中国西南地区的一种草本植物,有鱼腥味,所以被称为鱼腥草,也叫老鸨。它在夏天和秋天被收集,清洗,在阳光下干燥,然后切成小块供生用,辛凉微寒,属肺肾经。具有清热解毒、……QRowTable表格控件重写表头排序支持第三次单击恢复默认一、原生表格开发客户端程序的方式越来越多了,现在很流行的libcef、electron等等都可以作为快速开发客户端软件的方案,但是如果需要一个好的用户体验,还是离不开原生……
冬游价格政策公布!这个冬天,总要去趟黄山!控油补水的护肤品在家自己就能让脸水油平衡西城蝶变春暖花开西城COHO时代广场举行招商发布会小米的智能家居实际体验如何,真实用户评价中国游泳年轻教练抱团训练见成效零售电商,高增长时代已经过去?企业竞争的三个层面我是一棵树假如你的股票突然涨停,你该持有还是卖出,才能保持收益最大化?淘宝店主经营之小店如何立足包子铺月入几万元的致富经何为家,何为爱情,何为幸福?
大暑上蒸下煮,孩子动不动满头大汗!推荐3款汤水,止渴又开胃高效减肥不可不知的7大常识浅议检察机关在侦查活动中使用指定居所监视居住措施三国笑话后主造句用后主造句大全美国不孕夫妇通过试管生下一对双胞胎,20年后又有三胞胎找上了公主和狼家什么是饭圈女孩?直击大咖观点追星本就是个伪命题春季减肥晚餐吃什么推荐8道食谱教你营养解馋的萝卜炖虾,好吃下饭,拿肉都不换,孩子嚷着吃不够杀蟑胶饵哪里有卖航天员刘伯明家穷腼腆,却娶了校长的女儿,父亲一度怀疑

友情链接:中准网聚热点快百科快传网快生活快软网快好知文好找菏泽德阳山西湖州宝鸡上海茂名内江三亚信阳长春北海西安安徽黄石烟台沧州湛江肇庆鹤壁六安韶关成都钦州