2、使用JVMTI实现应用性能监控(APM)
在微服务大行其道的环境下,分布式系统的逻辑结构变得越来越复杂 。这给系统性能分析和问题定位带来了非常大的挑战 。基于JVMTI的APM能够解决分布式架构和微服务带来的监控和运维上的挑战 。APM通过汇聚业务系统各处理环节的实时数据,分析业务系统各事务处理的交易路径和处理时间,实现对应用的全链路性能监测 。
相关的工具有:
(1)开源的Pinpoint、ZipKin、Hawkular
(2)商业的AppDynamics、OneAPM、google Dapper等都是个中好手 。
3、产品运行时错误监测及调试
想要看生产环境的异常,最原始的方式是登录到生产环境的机器查看日志 。稍微高级一点的方式是通过日志监控或者APM等工具将异常采集上来 。但是这些手段都有许多明显的缺点 。首先,不是所有的异常都会被打印到日志中,有些异常可能被代码吃掉了;其次,打印异常的时候通常只有异常堆栈信息,异常发生时上下文的变量值很难获取到(除非有经验的程序员将其打印出来了),而这些信息对定位异常的原因至关重要 。基于JVMTI可以开发出一款工具来时事监控生产环境的异常 。其基本的原理和如上实例的原理相同 。
相关的工具:商业软件OverOps
4、JAVA程序的调试(debug) 。
一般JAVA的IDE都自带了调试工具 。例如Eclipse的调试器相信大部分人都使用过 。它的调试器org.eclipse.jdt.debug插件底层就是调用的JVMTI来实现的 。经常使用eclipse等工具对java代码做调试,其实就利用了jre自带的jdwp agent来实现的,只是由于eclipse等工具在没让你察觉的情况下将相关参数(类似-agentlib:jdwp=transport=dt_socket,suspend=y,address=localhost:61349)给自动加到程序启动参数列表里了,其中agentlib参数就是用来跟要加载的agent的名字,比如这里的jdwp(不过这不是动态库的名字,而JVM是会做一些名称上的扩展,比如在linux下会去找libjdwp.so的动态库进行加载,也就是在名字的基础上加前缀lib,再加后缀.so),接下来会跟一堆相关的参数,会将这些参数传给Agent_OnLoad或者Agent_OnAttach函数里对应的options参数 。
随着服务云化的发展,google甚至推出了云端调试工具cloud debugger 。它时一个web应用,可以直接对生产环境进行远程调试,不需要重启或者中断服务 。阿里也有类似的工具Zdebugger 。
5、JAVA程序的诊断(profile) 。
当出现CPU使用率过高、线程死锁等问题时,需要使用一些JAVA性能剖析或者诊断工具来分析具体的原因 。例如Alibaba开源的Java诊断工具Arthas,深受开发者喜爱 。Arthas的功能十分强大,它可以查看或者动态修改某个变量的值、统计某个方法调用链上的耗时、拦截方法前后,打印参数值和返回值,以及异常信息等 。
6、热加载
热加载指的是在不重启虚拟机的情况下重新加载一些class 。热加载可以在本地调试代码或线上修改代码时不用频繁重启 。如spring-loaded,还有商业产品JRebel等 。
相关工具:
(1)spring-loaded https://github.com/spring-projects/spring-loaded
(2)JRebel https://www.jrebel.com/
8、Serviceability AgentSA是JDK提供的一个强大的调试工具集,可以用来调试运行着的Java进程、core文件和虚拟机crash以后的dump文件 。所以我们在遇到CPU飙高、内存泄漏、应用奔溃等问题时,可以借助SA技术实现的工具来查找问题 。在JDK自带的工具中,jmap、jstack、jinfo、HSDB等工具都在使用着SA 。SA 机制不需要与进程互动,通过直接分析目标进程的内存布局获取目标 JVM 进程的运行时数据,如呈现出类对象、能够识别出Java堆、堆边界、堆内对象、载入的类描述、栈内存、线程状态等信息,是不是感觉黑科技?其实原理也并没那么难,我们平时所说的Java堆栈等内存模型都是虚拟机层面概念,虚拟机最终还是跑在操作系统上的,所以可以使用SA直接读取目标进程的操作系统层面的内存数据 。
一般在使用jmap、jstack工具时,使用的是attach方式(之前介绍的JavaAgent和JVMTIAgent同样也使用了attach),这种方式就是与目标进程建立 socket 连接,目标进程处理后回传客户端,所以需要虚拟机本身代码的支持,但是SA不需要在目标 VM 中运行任何代码,SA 使用操作系统提供的符号查找和进程内存读取等原语实现 。所以当jmap、jstack等导不出堆栈数据时,可以采用SA的方式获取数据,例如jstack加上-F选项来解决 。有时候我们在运行这些工具时,会报如下错误:
Error attaching to process: sun.jvm.hotspot.debugger.DebuggerException: Can't attach to the process: ptrace(PTRACE_ATTACH, ..) failed for 6: Operation not permitted // ...
推荐阅读
- 使用Java读取、编写、确认Excel文档
- Pandas 28种常用方法使用总结
- 饵料|夏季钓鲤鱼常用的调漂技巧
- 鲫鱼|野钓鲫鱼的特殊窝料,钓王邓刚最常用的鲫鱼窝料
- 黑客必修:批处理常用网络命令和符号——网络命令
- 11 种糟糕的 JavaScript 编写方式
- JavaScript中的四种枚举方式
- JavaScript检测用户是否在线!
- 你必须知道的常用的足够简练的 11 个 Python代码
- JavaScript 的 Anti-Debugging 技術
