http://calvin1978.blogcn.com/articles/vjtools-tools4.html

jstat, jmap, btrace, jprofiler, vjtools都基于什么实现? 对围绕JVM的各种工具的外挂技术,运用大整理术,让大家从茫然,到轻摇纸扇,知道分子。

归拢一下,就是C 和 Java两种Agent,SA 和 VirtualMachine 两种 Attach,JMX和PerfData两种Data,两两之间很是混淆,网上好像少了篇简明扼要的科普,所以自己操刀补了一篇,作为上周的直播《VJTools如何利用佛性技术完全JVM》的续集。

1. 两种Agent

1.1 Native Agent

以 C/C++代码编写的Agent,用强大的JVMTI(JVM Tool Interface)接口与JVM进行通讯,订阅感兴趣的JVM事件(比如方法出入、线程始末等等),当这些事件发生时,会回调Agent的代码。 JVMTI 同时提供了众多的功能函数,查询和控制 Java 应用的运行状态,包括内存控制和对象获取,线程与锁等等,简直无所不能。

使用者,包括各种Profile工具,如Yourkit,JProfiler,Aysnc-Profiler, 还有动态Reload Class而不重启应用的JRebel。

使用方式 ,可以在启动命令里加入 -agentlib: 或 -agentpath: /path/to/agent.so,也可以用后面讲的VituralMachine.attach()动态加载。

1.2 Java Agent

Java Agent的底层也是JVMTI ,但后门能力就只剩一个AOP 代码植入了:在加载class文件之前做拦截并对字节码做修改。比如AspectJ,单元测试覆盖率的Jacoco,动态重载Class的Spring-Loaded。

典型代码如下:

public class MyAgent {
public static void premain(String args, Instrumentation instrumentation){
ClassFileTransformer transformer = new MyClassWeaving();
instrumentation.addTransformer(transformer);
}
}

另一种逍遥的用法,就是为了随时让 “一段代码” 与 “主应用” 在同一JVM中运行,而不用修改主应用的代码去显式调用。

比如JMX的agent,启动一条TCP侦听线程响应JMX 请求。
比如jolokia的agent,启动一条Http侦听线程,响应Restful版的JMX请求。
比如btrace,启动一条TCP线程与btrace client通信,接收client发过来的脚本字节码,进行加载并输出结果。

它有两种启动方式:

一种是在启动时命令行加入 -javaagent:/path/to/agent.jar,根据agent.jar中的MANIFEST.MF文件中的Premain-Class定义,JVM找到相应的MyAgent类,调用其premain函数。

一种是通过后面讲的VM.attach()技术,在任意时刻由外部程序来灵活加载,调用其agentmain函数。

2.两种Attach

两种截然不同方式实现的Attach,本质上都是在跟踪程序与目标JVM之间建立一个沟通的管道,然后在跟踪程序使用特定的API去操作目标JVM。

2.1 Vitural Machine.attach()

跟踪程序通过Unix Domain Socket 与目标JVM的Attach Listener线程进行交互。 Socket 文件为/tmp/.java_pid$PID。

API 接口是com.sun.tools.attach.VirtualMachine 及其子类sun.tools.attach.HotSpotVirtualMachine,在tools.jar中,运行时需要依赖,可以做下面的事情:

● dumpHeap: jmap -dump 效果
● heapHisto: jmap -histo效果
● threadDump: jstack效果
● dataDump: kill-3 效果(jstack + jmap -heap)
● loadAgent: 动态加载C/Java Agent
● agentProperties: 获得已加载Agent的属性
● sytemProperties: 获得System Properties
● setFlag: 动态设置可写的JVM参数(但没几个是可写的)
● printFlag: 打印JVM 参数的值
● jcmd: 执行jcmd命令,具体能干啥见jcmd $PID help

可见, jmap, jmap,jcmd 们默认就是基于这个机制来做事情的。

VJTools的vjmxcli的特色之一,如果应用的启动脚本忘了设定启动JMX,可以根据PID attach到应用里,动态的把JMX Agent启动起来,然后通Agent属性获得本地连接地址,嗯, jconsole也是这么干的。

2.2 SA.attach()

著名的SA(Serviceability Agent),用于分析JVM运行时进程的Snapshot数据。Snapshot的意思,就是当SA 开始分析时,整个目标JVM是停顿下来不工作的,让SA可以从容读取进程内存中的数据,直到断开后才会恢复。所以在生产上使用这类工具时,必须先摘除流量。

这个神奇的操作,主要是通过系统调用ptrace实现。ptrace会使内核暂停目标进程并将控制权交给跟踪进程,使跟踪进程得以察看目标进程的内存,详见ptrace的man,所以在容器环境下,需要打开ptrace的安全权限。

API的接口,一个是 sun.jvm.hotspot.HotSpotAgent 负责attach, sun.jvm.hotspot.runtime.VM负责操作,在sa-jdi.jar中。

VM类从内存二进制信息中,提取出JVM内部数据结构,包括:

● 内存的getObjectHeap()/getUniverse()
● 处线程的getThreads()
● 永久代内容的getSymbolTable(),getStringTable(), getSystemDictionary()
● 还有很厉害的读内部Native对象值的getTypeDataBase()

jstack,jmap 们默认用前面的VM.attach()模式,与目标JVM的Attach Listener线程通信, 但如果目标JVM已经半死不活,Attach Listener线程无力响应请求时,就可以增加-F 参数,转而使用SA.attach 模式,用ptrace去暴力接管进程, 详细代码见sun.tools.jmap.JMap。看代码你还会发现,因为AttachListener支持的命令有限,所以jmap -heap 打印heap的总结信息时,也是以SA模式进去。

VJTools的vjmap是jmap的一个增强,能够独立各个分代中对象的数量大小统计,用以排除新生代对象的干扰,查找内存缓慢泄漏的问题,比如更直接找出Survior区里age>2的对象,里面就使用了VM类的观察者模式回调,和直接内存访问 两种方法来遍历。

SA模式比VM模式做相同事情时要慢一截,非必需时不要用它。还有,如果跟踪程序被kill-9 非正常退出,没有执行中断SA,目标JVM就会一直暂停在那里,Linux下可以执行kill -18 $PID 发送SIGCONT信号重新激活目标进程。

3. 两种Data

3.1 JMX

文章已太多,不再啰嗦。其中vjtools的vjtop,如何不停顿JVM的获得线程的CPU、内存信息,获得某条繁忙进程的StackTrace看看它在忙些什么,值得一看。

3.2 PerfData

很多人不知道的一个机制,JVM其实每秒都会将自己的大量统计数据,写入到 /tmp/hsperfdata_$username/$pid 文件中。

用下面指令可以感受下:

jcmd $PID PerfCounter.print

内容包括jvm的基本信息,内存,GC,线程数等等,还有一些JMX中没有暴露的数据,比如包含JVM中所有的停顿的SafePoint信息。

//线程的情况
java.threads.daemon=6
java.threads.live=7
...
// younggen的情况
sun.gc.generation.0.capacity=44695552
sun.gc.generation.0.maxCapacity=715784192
sun.gc.generation.0.minCapacity=44695552
....

jps,其实就是读取/tmp/hsperfdata_$username/ 目录下所有的文件。

jstat,同样是读取这个神秘的文件。一个很大的好处,就是它只默默读取文件,而不会像JMX那样要与应用程序交互,打扰应用程序的工作。

自己写代码也简单,使用 sun.management.counter.perf.PerfInstrumentation类即可,VJTools里的vjtop 从JMX,PerfData和/proc/pid 三处地方,综合打印JVM的概况和繁忙线程的情况,里面的PerfData类就是其使用的展示。

PerfData文件是mmap到内存中的,读写都很快,但每次写完还要更新磁盘上的文件元数据比如last modified time,如果遇上磁盘高IO,还是有概率造成JVM被锁定一段时间。所以我们以前通过-XX:+PerfDisableSharedMem禁止了perfdata的写入,不过现在又有点摇摆。

注意,perfdata 和 vm.attach 都需要在/tmp 目录读写文件,如果目标JVM的启动参数重新指定了临时目录,而跟踪程序依然去读取/tmp 目录,也会导致这些机制失效。

4. 小结

VJTools (https://github.com/vipshop/vjtools) 的三个工具,是上面的两种Attach, 两种Data的使用样本,大家可以直接阅读源码来加深印象,再顺手点个Star。

有关的...

  • 2018-08-06 -- 快速,低成本,低扰动地运行一段Java代码
  • 2018-07-25 -- 《唯品会Java开发手册》-与阿里手册的比较文学
  • 2018-07-20 -- 关键业务系统的JVM参数推荐(2018仲夏版)
  • 2018-06-06 -- 唯品会Java核心项目VJTools开源了

转载于:https://www.cnblogs.com/davidwang456/articles/9553939.html

入门科普,围绕JVM的各种外挂技术相关推荐

  1. 通俗易懂的5G 入门科普!

    通俗易懂的5G 入门科普! 转自:鲜枣课堂(ID:xzclasscom) 一个简单且神奇的公式    今天的故事,从一个公式开始讲起. 这是一个既简单又神奇的公式.说它简单,是因为它一共只有3个字母. ...

  2. 存储快速入门——【1】网络存储主要技术(NAS、SAN、SCSI、CIFS、zone)

    存储快速入门--[1]网络存储主要技术 1 NAS简介(网络) 在20世纪80年代初,英国纽卡斯尔大学布赖恩.兰德尔教授 ( Brian Randell)和同事通过"纽卡斯尔连接" ...

  3. bat 等待输入_打碟使用的音频输入渠道总结和相关入门科普

    太多乐迷至今还是不太了解打碟,以热情的心态去打击假打故事是好事,那很多人对假打总是有太多误解.比如说前段时间一直有很多人传播"U盘打碟就是假打"的说法,显然随便哪位略懂打碟的朋友看 ...

  4. NLP入门:word2vec self-attention transformer diffusion的技术演变

    这一段时间大模型的相关进展如火如荼,吸引了很多人的目光:本文从nlp领域入门的角度来总结相关的技术路线演变路线. 1.introduction 自然语言处理(Natural Language Proc ...

  5. OpenStack入门科普,看这一篇就够啦

    OpenStack入门科普,看这一篇就够啦 科技百分百 2019-07-06 10:06:00 作者 | 小枣君 来源 | 鲜枣课堂 大家好,我是小枣君. 最近几年,OpenStack这个词开始频繁出 ...

  6. 游戏反外挂技术首次公开

    万字长文!inlinehook看这一篇足够了! 远程线程+hook=监控? 硬件断点 硬件断点hook 实战!谁动了我的代码! 前面的文章,我们介绍了inline hook.硬件断点hook.远程线程 ...

  7. 最简单安全有效的防盗技术和防脱机外挂技术。研发部门可以借鉴使用。

    最简单安全有效的防盗技术和防脱机外挂技术.研发部门可以借鉴使用. 最简单安全有效的防盗技术和防脱机外挂技术.研发部门可以借鉴使用. 服务所控制的图片式软键盘. 做了几年的数据转换工作,也玩了几年游戏. ...

  8. 游戏外挂反外挂技术简介

    1.游戏外挂分类: ⑴按实现方式 ㈠脱机式: 完全脱离游戏客户端程序,可以与游戏服务器自由通讯的外挂程序,开发难度最大, 普通的100多开,对游戏的危害最大 ,严重破坏游戏市场.影响玩家正常游戏.缩短 ...

  9. 机器学习入门科普篇--系列二

    机器学习入门科普篇--系列二 前言 python程序语言与机器学习实践可以称得上是"珠联璧合".因为使用python编程技巧,接触甚至掌握机器学习的经典学习算法至少有以下四个优势. ...

最新文章

  1. python编程if语法-二、python 语法之变量赋值与if(if else)
  2. Ubuntu 16.04 下安装Firefox的Flash插件
  3. 前端实现数字快速递增_艾默生新型超声波发生器的数字控制功能可实现快速设置和准确操作...
  4. android左右旋转动画效果图,Android新姿势:3D翻转效果原理
  5. 背完这442句英语,你的口语绝对不成问题了
  6. 服务器开机提示修复,电脑开机提示自动修复怎么办?win10电脑开机提示自动修复教程...
  7. 2019春季学期进度报告(十四)
  8. Python 安装pythoncom库和pyHook
  9. EM算法的形式化推导
  10. 【python】编程语言入门经典100例--30
  11. spring-第四篇之让bean获取所在的spring容器
  12. 尚硅谷大数据技术之Hadoop(入门)
  13. 《数字电子技术基础》5.3/4/5 电平/脉冲/边沿触发的触发器
  14. 如何压缩ppt文件,这个方法你该知道
  15. 大中型 UGC 平台的反垃圾(anti-spam)工作
  16. href传中文参数乱码问题
  17. js实现点击切换checkbox背景图片
  18. lpfs存储服务器怎样维护,ipfs云节点存储服务器
  19. 移动硬盘,U盘出现USBC病毒乱码恢复的可能性分析
  20. java类农夫过河问题_Java简单实现农夫过河问题示例

热门文章

  1. 主板19针接口_【新品上市】D4双通道还能组RAID!华南B365D4主板6/7/8/9代全兼容!...
  2. php pdo bind,PHPPDOStatement对象bindpram()、bindvalue()和bindcolumn之间的区别_php技巧
  3. 命令解释器的设计及实现
  4. 改变跳转页面 英文_如何高效阅读英文文献?你可以试试它 | 知云文献翻译
  5. linux安装mysql字符_Linux下MySQL的彻底卸载和安装配置字符集
  6. Android:Socket客户端开发,Android 的Socket客户端优化,Android非UI线程修改控件程序崩溃的问题
  7. 正版七日杀服务器存档,七日杀网吧怎么存档 七日杀网吧存档读档方法介绍-游侠网...
  8. 深入浅出C++虚函数的vptr与vtable
  9. php中target用法,Yii使用DbTarget实现日志功能的示例代码
  10. 行代码入门python_新浪微博Android客户端开发视频教程(36讲)