1. btrace解析script,并生成相应的agent包
2. attach到jvm,并将相关agent包load进行,执行preMain或者agentMain方法,传入参数包括instrument
3. asm强化代码
4. instrument替换
attach到jvm,load agent
通过jvm TI api来获取jvmjvm TI启动方式:
A. 启动时通过参数直接载入共享库
B. 通过java attach实现,触发JVM源生线程Attach Listener来执行这个dynamic module的回调函数
方式A引入的回调函数如下: JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *vm, char *options, void *reserved) 方式B引入的回调函数如下: JNIEXPORT jint JNICALL Agent_OnAttach(JavaVM *jvm, char *options, void *reserved) { 卸载共享库时的回调函数(通用): JNIEXPORT void JNICALL Agent_OnUnload(JavaVM *vm) 我们可以看到,方式A和方式B提供的回调函数,参数是一样的。
instrumentation
"java.lang.instrument"包的具体实现,依赖于 JVMTI* * There are two ways to obtain an instance of the *
Instrumentation
interface: * * - *
- When a JVM is launched in a way that indicates an agent * class. In that case an
Instrumentation
instance * is passed to thepremain
method of the agent class. * * - When a JVM provides a mechanism to start agents sometime * after the JVM is launched. In that case an
Instrumentation
* instance is passed to theagentmain
method of the * agent code.
*
* * This method operates _disibledevent=>
- load到agent包之后通过回调函数执行agentMain函数,end
btrace中内容
在Main类中的入口方法:premain或者agentmain都会调用main方法public static void premain(String args, Instrumentation inst) { main(args, inst); } public static void agentmain(String args, Instrumentation inst) { main(args, inst); } private static synchronized void main(final String args, final Instrumentation inst)
main中的内容:
private static synchronized void main(final String args, final Instrumentation inst) { ... parseArgs(args); 注:解析传入的参数 String bootClassPath = argMap.get("bootClassPath"); ... inst.appendToBootstrapClassLoaderSearch(new JarFile(new File(path))); String systemClassPath = argMap.get("systemClassPath"); ... inst.appendToSystemClassLoaderSearch(new JarFile(new File(path))); 注:增加BootstrapClassLoader/SystemClassLoader的搜索路径 ... Thread agentThread = new Thread(new Runnable() { public void run() { BTraceRuntime.enter(); try { startServer(); } finally { BTraceRuntime.leave(); } } }); BTraceRuntime.enter(); ... agentThread.start(); ================================================== private static void startServer() { int port = BTRACE_DEFAULT_PORT; ... ServerSocket ss; try { System.setProperty("btrace.port", String.valueOf(port)); ... ss = new ServerSocket(port); 注:创建链接 } catch (IOException ioexp) { ... } Socket sock = ss.accept(); Client client = new RemoteClient(inst, sock); registerExitHook(client); 注:在Runtime.getRuntime()中添加shutdown的hook handleNewClient(client); 注: } ======================================================== private static void handleNewClient(final Client client) { serializedExecutor.submit(new Runnable() { public void run() { try { if (client.shouldAddTransformer()) { inst.addTransformer(client, true); Class[] classes = inst.getAllLoadedClasses(); 注:获取已加载的class ArrayList
最新评论