AgentMain与VirtualMachine
(2012-06-24 15:09:35)
标签:
agentmainjvmpidvirtualmachineattachloadagentit |
分类: JAVA |
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。具体需要参考《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 {
}
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的jar包是jdk下lib中的tools.jar
package attach;
import java.io.IOException;
import com.sun.tools.attach.AgentInitializationExcep
import com.sun.tools.attach.AgentLoadException;
import com.sun.tools.attach.AttachNotSupportedExcept
import com.sun.tools.attach.VirtualMachine;
public class AttachTest {
}