1  Agent

Agent在java中本质是一个动态库,利用JVMTI暴露出来的一些接口实现逻辑的入侵,需要实现如下的一个或者多个函数:

JNIEXPORT jint JNICALL

Agent_OnLoad(JavaVM *vm, char *options, void *reserved);

JNIEXPORT jint JNICALL

Agent_OnAttach(JavaVM* vm, char* options, void* reserved);

JNIEXPORT void JNICALL

Agent_OnUnload(JavaVM *vm);

Agent_OnLoad    函数  加载agent后调用的函数

Agent_OnAttach     函数     当agent在启动时加载,所调用的Agent函数

Agent_OnUnload   函数     当agent卸载时调用

1.1 初始化Agent

目前常见的几个Agent

1.      以-agentlib: 或者-agentpath:为开头的格式,例如:常见的eclipse中的debug代码 -agentlib:jdwp=transport=dt_socket,suspend=y,address=localhost:xxxx,这种情况下的agent 是jdwp

2.      以-javaagent:为开头的默认为instrument的agent

JVM在启动的时候,读取参数 -agentlib  -agentpath  -javaagent 构建了AgentLibrary的链表

代码如下:

    if (match_option(option, "-agentlib:", &tail) ||(is_absolute_path = match_option(option, "-agentpath:", &tail))) {if(tail != NULL) {const char* pos = strchr(tail, '=');size_t len = (pos == NULL) ? strlen(tail) : pos - tail;char* name = strncpy(NEW_C_HEAP_ARRAY(char, len + 1), tail, len);name[len] = '\0';char *options = NULL;if(pos != NULL) {options = strcpy(NEW_C_HEAP_ARRAY(char, strlen(pos + 1) + 1), pos + 1);}
#ifdef JVMTI_KERNELif ((strcmp(name, "hprof") == 0) || (strcmp(name, "jdwp") == 0)) {warning("profiling and debugging agents are not supported with Kernel VM");} else#endif // JVMTI_KERNELadd_init_agent(name, options, is_absolute_path);}// -javaagent} else if (match_option(option, "-javaagent:", &tail)) {if(tail != NULL) {char *options = strcpy(NEW_C_HEAP_ARRAY(char, strlen(tail) + 1), tail);add_init_agent("instrument", options, false);}// -Xnoclassgc}</span>
1.2 加载Agent链接库

在启动JVM create_vm的时候会初始化agent的链表中的每个agent库,加载所指定的动态库, 并调用里面的Agent_OnLoad方法,对instrument的就是加载libinstrument的动态库instrument.so

// Create agents for -agentlib:  -agentpath:  and converted -Xrun
void Threads::create_vm_init_agents() {extern struct JavaVM_ main_vm;AgentLibrary* agent;JvmtiExport::enter_onload_phase();for (agent = Arguments::agents(); agent != NULL; agent = agent->next()) {OnLoadEntry_t  on_load_entry = lookup_agent_on_load(agent);  if (on_load_entry != NULL) {// Invoke the Agent_OnLoad functionjint err = (*on_load_entry)(&main_vm, agent->options(), NULL);if (err != JNI_OK) {vm_exit_during_initialization("agent library failed to init", agent->name());}} else {vm_exit_during_initialization("Could not find Agent_OnLoad function in the agent library", agent->name());}}JvmtiExport::enter_primordial_phase();
}</span>

在函数里,通过OnloadEntry方法来调用instruments动态库里的Onload方法

// Create agents for -agentlib:  -agentpath:  and converted -Xrun
void Threads::create_vm_init_agents() {extern struct JavaVM_ main_vm;AgentLibrary* agent;JvmtiExport::enter_onload_phase();for (agent = Arguments::agents(); agent != NULL; agent = agent->next()) {OnLoadEntry_t  on_load_entry = lookup_agent_on_load(agent);if (on_load_entry != NULL) {// Invoke the Agent_OnLoad functionjint err = (*on_load_entry)(&main_vm, agent->options(), NULL);if (err != JNI_OK) {vm_exit_during_initialization("agent library failed to init", agent->name());}} else {vm_exit_during_initialization("Could not find Agent_OnLoad function in the agent library", agent->name());}}JvmtiExport::enter_primordial_phase();
}
1.3 Instrument  JPLISAgent

在方法Agent_OnLoad中创建一个新的JPLISAgent(Java Programming Language Instrumentation Services Agent), 初始化了类和包里的配置文件,并且同时从Vm环境中获取了jvmtiEnv 的环境。

JNIEXPORT jint JNICALL
Agent_OnLoad(JavaVM *vm, char *tail, void * reserved) {JPLISInitializationError initerror  = JPLIS_INIT_ERROR_NONE;jint                     result     = JNI_OK;JPLISAgent *             agent      = NULL;initerror = createNewJPLISAgent(vm, &agent);if ( initerror == JPLIS_INIT_ERROR_NONE ) {if (parseArgumentTail(tail, &jarfile, &options) != 0) {fprintf(stderr, "-javaagent: memory allocation failure.\n");return JNI_ERR;}attributes = readAttributes(jarfile);if (attributes == NULL) {fprintf(stderr, "Error opening zip file or JAR manifest missing : %s\n", jarfile);free(jarfile);if (options != NULL) free(options);return JNI_ERR;}premainClass = getAttribute(attributes, "Premain-Class");if (premainClass == NULL) {fprintf(stderr, "Failed to find Premain-Class manifest attribute in %s\n",jarfile);free(jarfile);if (options != NULL) free(options);freeAttributes(attributes);return JNI_ERR;}/** Add to the jarfile*/appendClassPath(agent, jarfile);……}…..}

在代码中,可以看到在读取jar的配置文件MANIFEST 里Premain-Class,并且把jar文件追加到agent的class path中

Java Instrument(一) Java Agent相关推荐

  1. java入参为方法_Java命令注入原理结合Java Instrument技术(FreeBuf首发)

    一.前言 命令注入:恶意用户构造恶意请求,对一些执行系统命令的功能点进行构造注入,从而达到执行命令的效果. 二.演示环境搭建 这里采用springboot+swagger搭建一个模拟的web环境:启动 ...

  2. java动态修改class_Java Agent入门学习之动态修改代码

    前言 最近用了一下午总算把Java agent给跑通了,本篇文章记录一下具体的操作步骤,以免遗忘.下面话不多说,来一起看看详细的介绍: 通过java agent可以动态修改代码(替换.修改类的定义), ...

  3. 【转载】Java Instrument 功能使用及原理

    0 介绍 利用 java.lang.instrument 做动态 Instrumentation 是 Java SE 5 的新特性,它把 Java 的 instrument 功能从本地代码中解放出来, ...

  4. java instrument 初探

    java在1.5引入java.lang.instrument,你可以由此实现一个java agent,通过此agent来修改类的字节码即改变一个类.本文中,会通过java instrument 实现一 ...

  5. java怎么监听多个组件,java web(五):java web三大组件之另外两个和八大监听器

    java的三大组件指Servlet.Filter.Listener.八大监听器指八个接口.前面介绍了Servlet,现在介绍一下Filter拦截器以及拦截地址的设置, Listener监听那些事件. ...

  6. Atitti.java exp ast java表达式语法ast构造器

    Atitti.java exp ast java表达式语法ast构造器 /atiplat_cms/src/com/attilax/lang/AstParser.java 原理 分割tokens_sli ...

  7. java AST 表达式_Atitti.java exp ast java表达式语法ast构造器

    Atitti.java exp ast java表达式语法ast构造器 /atiplat_cms/src/com/attilax/lang/AstParser.java 原理 分割tokens_sli ...

  8. java从头再来--java

    java从头再来–java语言 第一站 java语言 一起学习进步,欢迎留言指正 文章目录 java从头再来--java语言 一.java是什么? 1.面向对象 2.强类型编程语言 3.跨平台 二.j ...

  9. java 读取txt,java读取大文件

    java 读取txt,java读取大文件 package com.bbcmart.util; import java.io.File; import java.io.RandomAccessFile; ...

  10. JAVA基础(JAVA 执行环境) 第一天

    JAVA程序有3中执行环境. (1)能够单独运行的程序,称为Java Application(Java应用程序). (2)在Internet浏览器中运行的程序,称为 Java Applet(JAVA小 ...

最新文章

  1. 怎么样让自己更加从容的面对生活
  2. Web前端三剑客之CSS基础
  3. 推荐系统炼丹笔记:阿里边缘计算+奉送20个推荐系统强特
  4. 求教PHP+oracle的开发
  5. 【转】Dicom 学习笔记-Dicom 消息服务(DIMSE-C/DIMSE-N)
  6. C++11 tuple的使用
  7. 详解MariaDB数据库的事务
  8. python mongodb 设置密码前一篇ok,csv文件存入mongodb
  9. RHEL5.X 重启网卡出现./network-functions: line 78: .: ifc
  10. react-native学习小结
  11. Euraka配置详解
  12. 三国历史上最不该被埋没的十大人才!
  13. 敏捷领导力2.0培训体会
  14. [IOS][已越狱]配合网易云音乐,使用Bridge快速免iTunes导入音乐到“音乐”
  15. NLP冻手之路(4)——pipeline管道函数的使用
  16. 字符串转换成数字的三种方法 js
  17. 25. 答疑 - SAP OData 框架处理 Metadata 元数据请求的实现细节,前后端组件部署在同一台物理服务器
  18. docker健康检查
  19. EC-Net: a Edge-aware Point set Consolidation Network
  20. js调用摄像头解析二维码

热门文章

  1. arcgis影像怎么去黑边_arcgis遥感图像去黑边林林种种(至少7种方法)
  2. SSM(Spring+SpringMVC+MyBatis)框架入门
  3. 沈海高速汕尾往深圳服务器维护报价,沈海高速收费
  4. 教妹学Java:深入浅出之美团技术团队解析过的 String.intern
  5. U盘文件夹变成.exe文件的解决方法
  6. 江苏省2021年高考成绩查询有分数吗,江苏省2021年普通高考录取分数线公布
  7. ubuntu shuru zhic
  8. Effective java读后感
  9. html中加分割线,多种HTML分割线
  10. 快恢复二极管工作原理、反向恢复时间详解