Java探针技术-动态agent机制:在main函数启动之后运行agent

摘要:
premain是JavaSE5开始就提供的代理方式,由于其必须在命令行指定代理jar,并且代理类必须在main方法前启动。在有些场合下,premain代理方式不能满足需求。为解决运行时启动代理类的问题,JavaSE6开始提供了在应用程序的VM启动后在动态添加代理的方式,即agentmain方式。在manifest中指定Agent-Class属性,值为代理类全路径代理类需要提供publicstaticvoidagentmain或publicstaticvoidagentmain方法。args和inst和premain中的一致。由于agentmain方式无法向premain方式那样在命令行指定代理jar,因此需要借助AttachToolsAPI。

premain是Java SE5开始就提供的代理方式,由于其必须在命令行指定代理jar,并且代理类必须在main方法前启动。因此,要求开发者在应用前就必须确认代理的处理逻辑和参数内容等等。在有些场合下,premain代理方式不能满足需求。为解决运行时启动代理类的问题,Java SE6开始提供了在应用程序的VM启动后在动态添加代理的方式,即agentmain方式。

  • 在manifest中指定Agent-Class属性,值为代理类全路径
  • 代理类需要提供 public static void agentmain(String args, Instrumentation inst)public static void agentmain(String args)方法。并且再二者同时存在时以前者优先。args和inst和premain中的一致。
package aty.agent.after;
import java.lang.instrument.Instrumentation;
public class AgentAfterMain{
public static void agentmain(String args, Instrumentation inst){
  System.out.println("loadagent after main run.args=" + args);
  Class<?>[] classes = inst.getAllLoadedClasses();
  for (Class<?> cls : classes){
    System.out.println(cls.getName());
  }
  System.out.println("agent run completely.");
  }
}

将该代理类打成jar包,并修改MANIFEST.MF文件

Manifest-Version: 1.0
Agent-Class: aty.agent.after.AgentAfterMain

编写好agent jar之后,接下来需要将该jar挂接到目标进程的jvm中执行。由于agent main方式无法向pre main方式那样在命令行指定代理jar,因此需要借助Attach Tools API。使用com.sun.tools.attach包下的VirtualMachine类,使用attach pid 来得到相应的VirtumalMachine,使用loadAgent 方法指定AgentMain所在类并加载。其中com.sun.tools.attach.VirtualMachine的jar包是jdk下lib中的tools.jar

package aty.agent.after;
import com.sun.tools.attach.VirtualMachine;
public class RunAttach{
  public static void main(String[] args) throws Exception{
    // args[0]传入的是某个jvm进程的pid
    String targetPid = args[0];
    VirtualMachine vm = VirtualMachine.attach(targetPid);
    vm.loadAgent("F:/workspaces/j2se练习代码/jvm_high_api/agentmain.jar","toagent");
  }
}

免责声明:文章转载自《Java探针技术-动态agent机制:在main函数启动之后运行agent》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇【Linux】 源码安装make命令详解,避免踩坑利用LDAP操作AD域下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

GDB 命令行调试之路(全 19)

1: 基本命令. 2: 断点管理/多文件调试. 3: 函数基本调试. 4: 中级命令. 5: 监视内存. 6: 高级命令. 7: 类的调试. 8: 线程调试 9: 总结. 11.hello gdb!2.FAQ hello gdb! 首先准备好我们的调试文件test.cpp 如下 #include <iostr...

给新手看的 Micronaut 入门教程,10 分钟写出一个Micronaut程序

以下内容均选自 Micronaut 入门实战:基于 JVM 的微服务框架 。 Micronaut是什么? Micronaut 是一个现代化的基于 JVM 的全栈框架,用于构建模块化且易于测试的微服务或无服务程序。 同时,Micronaut 使用 Netty,并且对响应式编程提供一流的支持。对于 JVM 领域的全栈框架来说,Micronaut 是一个非常有前...

STM32 HAL库 UART使用printf

STM32 HAL库 UART使用printf // 添加这个函数 int fputc(int ch,FILE *f) { uint8_t temp[1]={ch}; HAL_UART_Transmit(&UartHandle,temp,1,2); } MDK设置:勾选Use Micro LIB 测试板子:STM32F746NG-...

NGINX----源码阅读一(main函数)

1、ngx_debug_init(); 初始化debug函数,一般为空。 2、ngx_strerror_init(); 将系统错误码+错误信息,以ngx_str_t数组保存。 3、ngx_get_options(int argc, char *const *argv) nginx启动函数选项, 4、ngx_show_version_info(); 如果上一...

Spring-AOP:开发准备、初识动态代理、使用步骤、

Aop场景 我们构建一个计算器场景进行学习 Calculator接口 (计算器) package com.jiang.inter; /** * @Title: * @author: JiangPeng * @Code: No Bug */ public interface Calculator { public int add(int a...

问题:C#控制台程序参数;结果:设置与读取C#控制台应用程序Main函数中的参数args

设置与读取C#控制台应用程序Main函数中的参数args在项目属性面版->调试->命令行参数设置。空格分隔。读取:string[] str = Environment.GetCommandLineArgs(); Main函数是C#应用程序的入口点,Main函数可以有四种签名,分别如下: static void Main() static vo...