Alibaba开源的Arthas是一个十分有名的Java诊断工具,他能够解析JVM的运行资源占用,运行状况,能够查看类的加载过程,应用的类加载器等等。然而比拟惋惜的是,他没有对于OpenJ9做出额定的反对,因而当你的JVM抉择OpenJ9后,应用arthas可能会存在肯定问题。本文将从我的亲自应用登程,看看OpenJ9在应用Arthas时会遇到哪些问题?
dashboard
dashboard是arthas的指令之一,该指令用于展现以后零碎的实时面板。然而在理论应用中会发现,如果OpenJ9中启用-Xgcpolicy:balanced的gc策略,会报如下的谬误:
[arthas@73192]$ dashboardprocess dashboard failed: init argument cannot be less than -1
查看Arthas的日志文件,文件中有更加具体的日志:
java.lang.IllegalArgumentException: init argument cannot be less than -1 at java.lang.management.MemoryUsage.<init>(MemoryUsage.java:94) at com.ibm.java.lang.management.internal.MemoryPoolMXBeanImpl.getUsageImpl(Native Method) at com.ibm.java.lang.management.internal.MemoryPoolMXBeanImpl.getUsage(MemoryPoolMXBeanImpl.java:235) at com.taobao.arthas.core.command.monitor200.MemoryCommand.getUsage(MemoryCommand.java:82) at com.taobao.arthas.core.command.monitor200.MemoryCommand.memoryInfo(MemoryCommand.java:52) at com.taobao.arthas.core.command.monitor200.DashboardCommand$DashboardTimerTask.run(DashboardCommand.java:245) at java.util.TimerThread.mainLoop(Timer.java:555) at java.util.TimerThread.run(Timer.java:505)
原本认为是Arthas对于OpenJ9不兼容导致的,然而通过一番钻研发现事件并不是那么简略。
写一个最简略的程序来进行验证:
public static void main(String[] args) { List<MemoryPoolMXBean> memoryPoolMXBeans = ManagementFactory.getMemoryPoolMXBeans(); for (MemoryPoolMXBean memoryPoolMXBean : memoryPoolMXBeans) { memoryPoolMXBean.getUsage(); }}
这么简略一个demo竟然在OpenJ9 balanced gc策略下抛出了异样:
Exception in thread "main" java.lang.IllegalArgumentException: init argument cannot be less than -1 at java.management/java.lang.management.MemoryUsage.<init>(MemoryUsage.java:94) at java.management/com.ibm.java.lang.management.internal.MemoryPoolMXBeanImpl.getUsageImpl(Native Method) at java.management/com.ibm.java.lang.management.internal.MemoryPoolMXBeanImpl.getUsage(MemoryPoolMXBeanImpl.java:235) at org.example.openj9.Test.main(Test.java:12)
通过测试验证,确认了这个是OpenJ9的bug,错怪Arthas了!
通过和OpenJ9社区的沟通,发现这个bug会在闲暇的region
数小于Eden region
数时产生,此时的"reserved size"会小于0,并导致报错。遗憾的是,此bug目前还未修复,预计将在后续的7月份的版本中进行修复并公布。
trace
应用trace能够排查具体的类的加载时长,排查执行慢的起因。不过在OpenJ9场景下应用trace会呈现如下报错:
[arthas@22508]$ trace org.springframework* * '#cost > 1000'Affect(class count: 4180 , method count: 33388) cost in 28438 ms, listenerId: 1Enhance error! exception: java.lang.VerifyErrorerror happens when enhancing class: null, check arthas log: /Users/logs/arthas/arthas.log
查看日志发现如下报错:
java.lang.VerifyError: null at sun.instrument.InstrumentationImpl.retransformClasses0(Native Method) at sun.instrument.InstrumentationImpl.retransformClasses(InstrumentationImpl.java:156) at com.taobao.arthas.core.advisor.Enhancer.enhance(Enhancer.java:446) at com.taobao.arthas.core.command.monitor200.EnhancerCommand.enhance(EnhancerCommand.java:162) at com.taobao.arthas.core.command.monitor200.EnhancerCommand.process(EnhancerCommand.java:109) at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl.process(AnnotatedCommandImpl.java:82) at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl.access$100(AnnotatedCommandImpl.java:18) at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl$ProcessHandler.handle(AnnotatedCommandImpl.java:111) at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl$ProcessHandler.handle(AnnotatedCommandImpl.java:108) at com.taobao.arthas.core.shell.system.impl.ProcessImpl$CommandProcessTask.run(ProcessImpl.java:385) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:826)
这让我百思不得其解,没方法只好求助Arthas社区,可是失去的后果就是Arthas不反对OpenJ9。没方法,既然不反对,那么咱们就换种方法来排查问题。
火焰图
Arthas火焰图是基于开源我的项目async-profiler
实现的,async-profiler
应用C++实现。反对生成利用热点的火焰图。其也能够用于排查利用执行慢的问题。他实质上是通过一直的采样,而后把收集到的采样后果生成火焰图。
然而在理论的应用中,会发现火焰图也不反对OpenJ9。
没方法,又又又只能去社区寻找答案。最终通过排查,发现async-profiler
是做了OpenJ9的反对的,不过,这些反对在2.7+版本后才陆续合并入主分支,而Arthas的最新版本援用的是2.6.x的async-profiler
,因而不反对OpenJ9也是情理之中了。
于是咱们只好本人入手饥寒交迫。好在Arthas集成async-profiler
的办法十分粗犷,是间接应用的so文件,于是咱们间接替换Arthas的async-profiler
目录下的几个so文件,将之替换为最新版本的,果然火焰图能力就可能失常应用了。
后续在提了Issue之后,Arthas社区近期反馈曾经将async-profiler
降级至了高版本,因而只有下载最新版本就能让OpenJ9也能够应用Arthas的火焰图能力了。
总结
OpenJ9
尽管有其劣势,然而在理论中的用户远远不如HotSpot
,因而在各个开源我的项目中的反对还远远不够。在折腾Arthas的过程中遇到了有数的坑,而且很多还是无奈简略解决的,本文只是简略选取几个遇到的典型问题,心愿可能有雷同需要的敌人们可能一起来 踩坑 摸索。