加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

AgentMain与VirtualMachine

(2012-06-24 15:09:35)
标签:

agent

main

jvm

pid

virtual

machine

attach

loadagent

it

分类: JAVA

agentmain方式

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

  1. 在manifest中指定Agent-Class属性,值为代理类全路径
  2. 代理类需要提供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。具体需要参考《Attach API》(http://docs.oracle.com/javase/6/docs/jdk/api/attach/spec/com/sun/tools/attach/VirtualMachine.html)


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.0

Agent-Class: loaded.LoadedAgent
Created-By: 1.6.0_29

绑定到目标VM

将agent类和MANIFEST.MF文件编译打成loadagent.jar后,由于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 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

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有