JAVA AgentMain开发示例

来源:互联网 发布:自然灾害数据库 编辑:程序博客网 时间:2024/05/29 08:35

agentmain方式

        premain是Java SE5开始就提供的代理方式,给了开发者诸多惊喜,不过也有些须不便,由于其必须在命令行指定代理jar,并且代理类必须在main方法前启动。因此,要求开发者在应用前就必须确认代理的处理逻辑和参数内容等等,在有些场合下,这是比较困难的。比如正常的生产环境下,一般不会开启代理功能,但是在发生问题时,我们不希望停止应用就能够动态的去修改一些类的行为,以帮助排查问题,这在应用启动前是无法确定的。 为解决运行时启动代理类的问题,Java SE6开始,提供了在应用程序的VM启动后在动态添加代理的方式,即agentmain方式。 与Permain类似,agent方式同样需要提供一个agent jar,并且这个jar需要满足:

         在manifest中指定Agent-Class属性,值为代理类全路径代理类需要提供

    public static void agentmain(String args, Instrumentation inst)
  public static void agentmain(String args)

方法。并且在二者同时存在时以前者优先。args和inst与premain中的一致。

        不过如此设计的在运行时进行代理有个问题——如何在应用程序启动之后再开启代理程序呢? JDK6中提供了Java Tools API,其中Attach API可以满足这个需求。

        Attach API中的VirtualMachine代表一个运行中的VM。其提供了loadAgent()方法,可以在运行时动态加载一个代理jar。
agentmain实例-打印当前已加载的类

构造agent类

agentmain方式的代理类必须提供agentmain方法:

package loaded;import java.lang.instrument.Instrumentation;public class LoadedAgent {     public static void agentmain(String args, Instrumentation inst){        Class[] classes = inst.getAllLoadedClasses();        for(Class cls :classes){            System.out.println(cls.getName());        }    }}

agentmain方法通过传入的Instrumentation实例获取当前系统中已加载的类。

设置MANNIFEST.MF

        设置MANIFEST.MF文件,指定Agent-Class:

Manifest-Version: 1.0Agent-Class: loaded.LoadedAgentCreated-By: 1.6.0_29

绑定到目标VM

将agent类和MANIFEST.MF文件编译打包成loadagent.jar后,由于agent main方式无法向premain方式那样在命令行指定代理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 attach;import java.io.IOException;import com.sun.tools.attach.AgentInitializationException;import com.sun.tools.attach.AgentLoadException;import com.sun.tools.attach.AttachNotSupportedException;import com.sun.tools.attach.VirtualMachine;public class AttachTest {    public static void main(String[] args) throws AttachNotSupportedException,            IOException, AgentLoadException, AgentInitializationException {        VirtualMachine vm = VirtualMachine.attach(args[0]);//args[0]传入的是jvm的pid号     //   vm.loadAgent("/Users/jiangbo/Workspace/code/java/javaagent/loadagent.jar");         vm.loadAgent("F:\\workspace_aging_rejuvenate\\AgentMain\\agent.jar");    }}
0 0
原创粉丝点击