1、业务背景对于分布式架构中的文件服务,由于涉及到大量的IO流操作,容易引发JVM相关异常,尤其是内存溢出问题;在最新的版本迭代中,真正的业务处理场景和上面差不多。由于在文件服务中加入了批处理,直接唤醒了隐藏已久的bug,也就是最常见的内存溢出;问题原因:word文档内容识别完成后,转成pdf文件,然后进行分页,转成一组图片。在这个复杂而漫长的过程中,有一个数组容器没有被销毁;解决方案:分析JVM的dump文件,定位OOM问题根源,分析文件服务异常日志,增加资源释放动作解决问题;2.Jdk-Bin目录对于相当一部分新手来说,看到JVM的问题都是Bug引起的,一头雾水。其实,这种心态是大可不必的。从职场几年的开发经验来看,JVM问题大致可以分为两种:开发容易解决:可以通过升级内存资源或者调整分配,或者优化程序来完成相关资源的管理和释放。这是最常用的方法;轻松解决开发:由于经验不足,程序出现重大bug导致JVM异常,进而引发一系列连锁反应。这不会从绝地反弹,地上只有一根羽毛;在解决常规的JVM异常时,通常依赖于JDK中的基础工具,即可以完成问题的定位,从而分析解决,但是这些都需要熟练使用基础工具,很多JDK的自己的能力往往被忽视;在jdk的bin目录下,有很多内置的工具可以用于JVM的分析;以上是基于jdk1.8的目录,里面有很多开发中经常用到的命令。下面重点介绍一个微服务的启动和运行,看看基于JDK的JVM工具的使用;三、命令行工具1、jps命令jps:虚拟机进程状态工具,该命令常用于Java环境部署和服务启动检查,先在本地启动一个门面微服务,然后在命令行执行查询;jps:command默认输出的是进程ID和应用程序的主类名称;-l:输出进程ID和应用程序主类的完整路径;-v:输出传递给jvm的参数,这里显示为idea中显式配置的VM-options参数,其他内容自行查看;-m:输出传递给main方法的参数,可以在服务启动前在idea的Program-arguments中配置;$jps1281FacadeApp$jps-l1281com.explore.facade.FacadeApp$jps-v1281FacadeApp-xms128m-Xmx256m-XX:MaxNewSize=256m-XX:MaxPermSize=256m$jps-m1281FacadeApphello,main-method2,jinfo命令jinfo:命令后带pid进程号,可以输出指定进程的配置信息。应用程序启动时通常不要指定过多的配置参数,可以使用该命令查询很多参数的默认值;该命令还可以在运行时动态调整一些参数,但很少使用;$jinfo1281#PasteonlyindividualparametersJavaSystemProperties:#Systemparameterjava.runtime.versinotallow=1.8.0_144-b01file.encoding=UTF-8sun.java.command=com.explore.facade.FacadeApp你好,main-methodVMFlags:#虚拟机参数-XX:InitialHeapSize=134217728-XX:MaxHeapSize=268435456-XX:MaxNewSize=267911168VMArguments:#runtimeparametersjvm_args:-Xms128m-Xmx256m-XX:MaxNewSize=256m-XX:MaxPermSize=256mjava_command.fac.command:comhello,main-method$jinfo-sysprops1281#只输出【JavaSystemProperties】参数$jinfo-flags1281#只输出【VMFlags】参数3.jstat命令jstat:输出JVM监控指标在指定频率,如下命令输出内存使用和GC相关信息,每3秒输出一次,连续打??印5次;由于这里启动了一个简单的微服务,没有执行任何业务逻辑,所以指标比较稳定;$jstat-gcutil128130005S0S1EOMCCSYGCYGCTFGCFGCTCGCCGCTGCT0.000.0057.9764.1692.8288.7530.02890.516--0.5440.000.0057.9764.1692.8288.7530.02890.516--sun_options包中相对路径下的tools文件中有参考工具包--/tools/jstat/resources/目录;optiongcutil{column{header"^S0^"/*Survivor0Space-使用百分比*/data(1-((sun.gc.generation.0.space.1.capacity-sun.gc.generation.0.space.1.used)/sun.gc.generation.0.space.1.capacity))*100}column{header"^S1^"/*Survivor1Space-PercentUsed*/data(1-((sun.gc.generation.0.space.2.capacity-sun.gc.generation.0.space.2.used)/sun.gc.generation.0.space.2.capacity))*100}......}4.jstack命令jstack:输出JVM中指定进程当前时刻的线程信息,为了清楚显示其结果,服务启动时产生线程死锁,然后死锁的线程会通过这个命令打印出来,通过输出可以查到两个线程相互等待的信息;$jstack1281发现一个Java级别的死锁:==============================="test-thread-02":waitingfor拥有的e同步器0x00000007b00a35d0,(一个java.util.concurrent.locks.ReentrantLock$NonfairSync),由“test-thread-01”“test-thread-01”持有:等待可拥有的同步器0x00000007b00a35a0,(一个java.util.concurrent.locks.ReentrantLock$NonfairSync),由上面列出的线程的“test-thread-02”Java堆栈信息保存:========================================================"test-thread-02":在sun.misc.Unsafe。park(NativeMethod)-停车等待<0x00000007b00a35d0>(ajava.util.concurrent.locks.ReentrantLock$NonfairSync)"test-thread-01":atsun.misc.Unsafe.park(NativeMethod)-停车到waitfor<0x00000007b00a35a0>(ajava.util.concurrent.locks.ReentrantLock$NonfairSync)Found1deadlock.5、jmap命令jmap:可以输出指定进程内存中的对象映射信息,或者堆的key信息,内存使用统计,GC算法,配置,类实例信息和内存使用等。这个命令经常用到解决JVM问题时;$jmap1281$jmap-heap1281Heap配置:MinHeapFreeRatio=0MaxHeapFreeRatio=100MaxHeapSize=536870912(512.0MB)HeapUsage:PSYoungGenerationEdenSpace:FromSpace:ToSpace:PSOldGeneration$jmap-histo:live1281num#instances#bytes类名----------------------------------------------1311:132com.explore.facade.FacadeApp$$EnhancerBySpringCGLIB$$313d9e3四、可视化工具1.jconsoleJava内置的JVM性能监控工具。熟悉了上述命令行工具之后,对于这个可视化工具的使用就不会太陌生了。您可以在命令中查看默认参数或应用自定义配置,也可以在这个工具中找到,并以图形方式呈现;$jconsole#此命令将唤起jconsole界面。这里选择线程一栏,可以直观的看到线程数的变化曲线,也可以在下方查看某个线程的每个线程的具体信息,并且通过死锁检测功能,两个线程test-thread-01可以找到服务中创建的test-thread-02;2、visualvmVisualVM是解决JVM问题的常用工具,集成的功能比较丰富。而且强大,这里通过Idea插件启动FacadeApp微服务,在进程首页可以看到自定义配置,thread栏会直接给出异常提示,因为检测到死锁;在监控栏中,可以通过[heapdump]查看详细信息,可以查看类实例的数量和大小,完成结果排序和占用统计;这里的信息在定位和解决JVM问题时非常重要;对于JVM监控工具来说,其能力与常用的命令相当,行语法差异很小,这些命令也可以在jdk中的tools.jar包中找到对应的类。对于一些更高级的监控平台,比如Kuboard、Skywalking等,这些底层能力也是集成的。原理应该是一样的。5.参考源码编程文档:https://gitee.com/cicadasmile/butte-java-note应用仓库:https://gitee.com/cicadasmile/butte-flyer-parent
