1. 什么是Attach机制

简单点说就是jdk的一些工具类提供的一种jvm进程间通信的能力,能让一个进程传命令给另外一个进程,并让它执行内部的一些操作,比如说我们为了让另外一个jvm进程把线程dump出来,那么我们运行了一个jstack的进程,然后给它传了个pid的参数,告诉它要对哪个进程进行线程dump,既然是两个进程,那肯定涉及到进程间通信,以及传输协议的定义,比如要执行什么操作,传了什么参数等等。

Attach机制可以对目标进程收集很多信息,如内存dump,线程dump,类信息统计(比如加载的类及大小以及实例个数等),动态加载agent,动态设置vm flag(但是并不是所有的flag都可以设置的,因为有些flag是在jvm启动过程中使用的,是一次性的),打印vm flag,获取系统属性等等,这些对应的源码(AttachListener.cpp)。

2. Attach方法小结

2.1 继承Tool/HotSpotAgent.attach(采用Serviceability Agent,简称SA)

SA(Serviceability Agent)是一个用于分析HotSpot运行时进程和Core文件中数据的工具。它可以attach到Java进程或分析Core文件中的数据,了解加载的class,是一个包含大量Java API和工具的工具集,目前实现只支持“snapshot”式的使用方式。“snapshot”是指不支持在SA保持连接的同时让目标进程运行,就是说无论如何在SA进行attach的时候目标进程都要暂停的(SA在attatch到进程之后,会暂停当前进程的执行,拿到的是进程的一个snapshot,当前进程会在SA断开后继续执行),所以在线上使用这类工具进行dump时无论耗时长短必须要摘流量,否则可能会使服务不可用而带来一些不必要的影响。

SA 在JDK中是以Jar文件的形式提供的,位于JAVA_HOME/lib/sa-jdi.jar ,和一般的Jar文件执行一样。

TBJMap使用了hotspot源码的sa-jdi.jar的sun.jvm.hotspot.HotSpotAgent这个类(其中TBJMap继承了sun.jvm.hotspot.tools.Tool这个类,最终用到的也是HotSpotAgent作为代理agent,也就是使用的是SA)。

HotSpotAgent.attach方法过程分析(linux):

  1. 首先通过/proc/[pid]/maps读取elf文件,保存符号表(elf文件除了机器码外,还包含其它额外的信息,如段的加载地址,运行地址,重定位表,符号表等,比bin文件要大,通过gcc编译出来的可执行文件是elf文件);
  2. 接着通过保存的符号表读取HotSpotVM中localHotSpotVMStructs和localHotSpotVMTypes等变量的地址;
  3. 然后使用ptrace根据变量的地址读取SA需要用到的HotSpotVM中的数据的元信息(类型信息,字段offset,地址等);
  4. 最后根据这些元信息就可以读取到目标VM上这些数据的值。

在Linux平台上,attach方法最终是使用了/proc和ptrace来读取目标VM中的数据,ptrace提供了一种使父进程可以监视和控制其它进程的方式,它还能够改变子进程中的寄存器和内核映像,因而可以实现断点调试和系统调用的跟踪(ptrace会使内核暂停当前进程并将控制权交给跟踪进程,使跟踪进程得以察看或者修改被跟踪进程的寄存器,待收集完跟踪信息以后会把控制权交回给当前进程让其继续运行)。

SA工具的attach和detach分别对应的ptrace方法是:

ptrace(PT_ATTACH, pid, 0, 0);
ptrace(PT_DETACH, pid, 0, 0);

更具体源码分析见:HotSpotAgent.attach源码分析

2.2 VirtualMachine.attach(Attach到Attach Listener线程后执行有限命令)

jstack和jhipcup的attach使用的是VirtualMachine.attach。

VirtualMachine.attach方法过程分析(linux):

(1)信号机制

JVM启动的时候并不会马上创建Attach Listener线程,而是通过另外一个线程Signal Dispatcher在接收到信号处理请求(如jstack,jmap等)时创建临时socket文件/tmp/.java_pid并创建Attach Listener线程(external process会先发送一个SIGQUIT信号给target VM process,target VM会创建一个Attach Listener线程);

(2)Unix domain socket

Attach Listener线程会通过Unix domain socket与external process建立连接,之后就可以基于这个socket进行通信了。

创建好的Attach Listener线程会负责执行这些命令(从队列里不断取AttachOperation,然后找到请求命令对应的方法进行执行,比如jstack命令,找到 { “threaddump”, thread_dump }的映射关系,然后执行thread_dump方法)并且把结果通过.java_pid文件返回给发送者。

整个过程中,会有两个文件被创建:

.attach_pid<pid>,external process会创建这个文件,为的是触发Attach Listener线程的创建,因为SIGQUIT信号不是只有external process才会发的,通过这个文件来告诉target VM,有attach请求过来了(如果.attach_pid创建好了,说明Attach Listener线程已经创建成功)。相关代码在LinuxVirtualMachine.java中;

.java_pid<pid>,target VM会创建这个文件,这个是因为Unix domain socket本身的实现机制需要去创建一个文件,通过这个文件来进行IPC。相关代码在attachListener_linux.cpp中。

其中的<pid>都是target VM的pid。

具体更详细的VirtualMachine.attach的源码分析见:VirtualMachine.attach源码分析

Attach Listener线程命令对应的源码(AttachListener.cpp)如下:

static AttachOperationFunctionInfo funcs[] = {{ "agentProperties",  get_agent_properties },{ "datadump",         data_dump },{ "dumpheap",         dump_heap },{ "load",             JvmtiExport::load_agent_library },{ "properties",       get_system_properties },{ "threaddump",       thread_dump },{ "inspectheap",      heap_inspection },{ "setflag",          set_flag },{ "printflag",        print_flag },{ "jcmd",             jcmd },{ NULL,               NULL }
};

Perf.getPerf().attach(通过PerfData文件获取信息)

用lsof -p 查看进程打开了哪些文件时,经常可以看到/tmp/hsperfdata_$username/$pid文件,如:

[root@ospdev-qxtjx]# lsof -p 32098 | grep perf
java 32098 root  mem    REG   252,1   32768  934145 /tmp/hsperfdata_root/32098

​该文件其实是一个mmap内存映射文件,JVM用来收集状态数据给其它进程使用的,可以使用-XX:+PerfDisableSharedMem来关闭它,当到达安全点时,JVM会把安全点的相关信息写入到这个文件中去,在使用jstack,jconsole等工具时会读取该文件获取内容来统计信息。

perf attach源码调用过程:

调用rt.jar包的sun.misc.Perf类的attach方法

--->调用对应的perf.cpp的Perf_Attach方法--->方法里再调用PerfMemory::attach

--->最后通过方法mmap_attach_shared将GC或其他状态相关的数据写入到该mmap内存映射文件(该mmap内存映射文件是在JVM启动时调用PerfMemory::create_memory_region就已经创建好的)。

jstat,sjk等工具通过访问该mmap内存映射文件,读取到相关的内容,显示在屏幕上。

几种命令工具的attach方式的比较

(1)几种attach方式的比较:

几种attach方式的比较

(2)命令工具以及它的所属系列及对应的代码入口:

命令工具以及它的所属系列及对应的代码入口

(3)命令工具以及它所对应的attach方式:

命令工具以及它所对应的attach方式

jmap和jstack的“-F”参数可以把原先VirtualMachine.attach方式强制改为SA attach方式,命令如下:

jmap -F -histo <pid>
jstack -F <pid>
jstack -F -l <pid>

Java Attach机制相关推荐

  1. 一分钟了解Java Attach机制

    场景 在JVM运行时,我们经常需要获取目标JVM运行时的相关信息,jstack,jmap等常用工具的主要原理都和attach机制有关. 用法 默认不开启 可通过-XX:+StartAttachList ...

  2. JVM Attach机制实现

    Attach是什么   在讲这个之前,我们先来点大家都知道的东西,当我们感觉线程一直卡在某个地方,想知道卡在哪里,首先想到的是进行线程dump,而常用的命令是jstack ,我们就可以看到如下线程栈了 ...

  3. JVM源码分析之Attach机制实现完全解读

    本文来自: PerfMa技术社区 PerfMa(笨马网络)官网 Attach是什么 在讲这个之前,我们先来点大家都知道的东西,当我们感觉线程一直卡在某个地方,想知道卡在哪里,首先想到的是进行线程dum ...

  4. JAVA探针机制—Agent(一)

    JAVA探针机制-Agent(一) agent机制首次出现在JDK5版本,在JDK6版本得到升级并且正式被官方定义为agent原理. 首先要明确JavaAgent是一个JVM层面的插件,他可以利用JD ...

  5. java事件处理模型_从零开始理解JAVA事件处理机制(3)

    我们连续写了两小节的教师-学生的例子,必然觉得无聊死了,这样的例子我们就是玩上100遍,还是不知道该怎么写真实的代码.那从本节开始,我们开始往真实代码上面去靠拢. 事件最容易理解的例子是鼠标事件:我们 ...

  6. 两道面试题,带你解析Java类加载机制

    2019独角兽企业重金招聘Python工程师标准>>> 在许多Java面试中,我们经常会看到关于Java类加载机制的考察,例如下面这道题: class Grandpa {static ...

  7. Java类加载机制详解【java面试题】

    Java类加载机制详解[java面试题] (1)问题分析: Class文件由类装载器装载后,在JVM中将形成一份描述Class结构的元信息对象,通过该元信息对象可以获知Class的结构信息:如构造函数 ...

  8. 利用java反射机制 读取配置文件 实现动态类载入以及动态类型转换

    作者:54dabang 在spring的学习过程之中,我们能够看出通过配置文件来动态管理bean对象的优点(松耦合 能够让零散部分组成一个总体,而这些总体并不在意之间彼此的细节,从而达到了真正的物理上 ...

  9. Struts2中action接收参数的三种方法及ModelDriven跟Preparable接口结合JAVA反射机制的灵活用法...

    Struts2中action接收参数的三种方法及ModelDriven跟Preparable接口结合JAVA反射机制的灵活用法 www.MyException.Cn   发布于:2012-09-15 ...

  10. 谈谈 Java 类加载机制

    点击上方"方志朋",选择"置顶或者星标" 你的关注意义重大! 来源:Rainstorm , github.com/c-rainstorm/blog/blob/m ...

最新文章

  1. iptables时区_iptables time 时间匹配规则
  2. 使用clang将C/C++代码编译成LLVM的中间代码(LLVM ir bitcode),并反汇编LLVM bitcode
  3. electron 利用 electron-builder实现自动更新
  4. [转] linux下查看nginx,apache,mysql,php的编译参数
  5. 后台执行UNIX/Linux命令和脚本的五种方法
  6. wordcloud python3.7_[原创]win7/64位系统+python3.7.2下安装wordcloud库失败之解决——一个莫名其妙的方法...
  7. 分支结构定义java_[Android-Java]2.分支结构-(4-7)
  8. vue 深度拷贝数组_前端深拷贝和浅拷贝
  9. Android 四大组件学习之Activity一
  10. 7款可视化工具,提高开发效率必备
  11. 贪心算法之猴子吃香蕉(Monkeys and Bananas)
  12. 第三方支付接口有哪些?怎么申请?
  13. [zt]再谈QQ自动登陆器:提供C#源码下载(下)
  14. 威马D轮敲定,「造车新势力」四小龙已定
  15. [Abandoned connection cleanup thread] but has failed to stop it.
  16. 与虎宝假期可玩地方一览
  17. Unity变换矩阵之如何构建变换矩阵
  18. 遵从自己的内心就永远不会迷失前进的方向
  19. Kubernetes 1.6新特性系列 | 动态配置和存储类
  20. TVS 和压敏电阻区别

热门文章

  1. 为什么计算机能读懂 1 和 0 ?
  2. 【Flutter小记3】Android打开前置或广角摄像头的同时打开闪光灯方案
  3. Combating the Elsagate Phenomenon: Deep Learning Architectures for Disturbing Cartoons
  4. Tic Tac Toe
  5. Excel 下拉列表数据有效性智能匹配筛选
  6. 德鲁克《管理的实践》读后感-总结
  7. 阿里史上最大规模校招,进大厂的机会来啦!!!
  8. 银河麒麟设置静态IP
  9. 百度地图实现marker显示数字
  10. win8删除计算机管理员权限,win8.1系统如何删除administrator账户