Java Agent(五)OpenJdk/Instrument包源码分析

简介

在介绍instrument是什么之前,先来看几个定义:
JVMTI(JVM tool interface):它是JVM提供的一系列native编程接口。
Agent:与JVM进行通信的外部进程,它们通过调用JVMTI进行交互,可进行的操作包括设置JVM回调函数、获取当前虚拟机状态信息等
Instrument:Jdk提供的"java.lang.instrument"包,与JVM进行交互,可以看作为一个Instrument Agent。

https://www.ibm.com/developerworks/cn/java/j-lo-jpda2/index.html?ca=drs-

整体流程

接上文,当JVM接收到execute(“load”,“instrument”,“false”,options)命令之后,开始进行动态链接库的加载。

  • "load"命令——对应load_agent方法:
  1. 接收参数:op->arg(0)、 op->arg(1)、op->arg(2);(“instrument”、是否绝对路径、agentpath=args)
  2. 判断 if(arg(0)==“instrument”)先加载"java.instrument"模块,再load_agent_library
  • load_agent_library:
  1. 首先加载动态库:“libinstrument.so”,加载instrument Agent(JVM定义Linux系统中,加载的动态链接库名字是"lib"+args(0)+".so")
  2. 调用库中的Agent_OnAttach方法。

从Agent_OnAttach开始,是libinstrument.so中的内容:
在这里插入图片描述

关于libInstrument.so库,我认为可以当做是一个底层Agent。

它直接调用了JVMTI提供的回调方法,然后加载我们自定义的agent,避免了我们自己的agent与JVMTI直接通信。

源码分析

// Implementation of "load" command.
static jint load_agent(AttachOperation* op, outputStream* out) {
   
  // get agent name and options
  const char* agent = op->arg(0);
  const char* absParam = op->arg(1);
  const char* options = op->arg(2);

  // If loading a java agent then need to ensure that the java.instrument module is loaded
  if (strcmp(agent, "instrument") == 0) {
   
    Thread* THREAD = Thread::current();
    ResourceMark rm(THREAD);
    HandleMark hm(THREAD);
    JavaValue result(T_OBJECT);
    Handle h_module_name = java_lang_String::create_from_str("java.instrument", THREAD);
    JavaCalls::call_static(&result,
                           SystemDictionary::module_Modules_klass(),
                           vmSymbols::loadModule_name(),
                           vmSymbols::loadModule_signature(),
                           h_module_name,
                           THREAD);
    if (HAS_PENDING_EXCEPTION) {
   
      java_lang_Throwable::print(PENDING_EXCEPTION, out);
      CLEAR_PENDING_EXCEPTION;
      return JNI_ERR;
    }
  }

  return JvmtiExport::load_agent_library(agent, absParam, options, out);
}

接收到的三个参数对应我们发送命令时的三个:“instrument”、是否绝对路径、agentpath=args;
先加载java.instrument模块,再加载Agent,调用JvmtiExport::load_agent_library(agent, absParam, options, out),当成功时返回码为0.

jint JvmtiExport::load_agent_library(const char *agent, const char *absParam,
                                     const char *options, outputStream* st) {
   
  char ebuf[1024];
  char buffer[JVM_MAXPATHLEN];
  void* library = NULL;
  jint result = JNI_ERR;
  const char *on_attach_symbols[] = AGENT_ONATTACH_SYMBOLS;
  size_t num_symbol_entries = ARRAY_SIZE(on_attach_symbols);

  // The abs paramter should be "true" or "false"
  bool is_absolute_path = (absParam != NULL) && (strcmp(absParam,"true")==0);

  // Initially marked as invalid. It will be set to valid if we can find the agent
  AgentLibrary *agent_lib = new AgentLibrary(agent, options, is_absolute_path, NULL);

  // Check for statically linked in agent. If not found then if the path is
  // absolute we attempt to load the library. Otherwise we try to load it
  // from the standard dll directory.

  if (!os::find_builtin_agent(agent_lib, on_attach_symbols, num_symbol_entries)) {
   
    if (is_absolute_path) {
   
      library = os::dll_load(agent, ebuf, sizeof ebuf);
    } else {
   
      // Try to load the agent from the standard dll directory
      if (os::dll_locate_lib(buffer, sizeof(buffer), Arguments::get_dll_dir(),
                             agent)) {
   
        library = os::dll_load(buffer, ebuf, sizeof ebuf);
      }
      if (library == NULL) 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值