Agent第二種實(shí)現(xiàn)方式
上一部分第一種和本節(jié)基本相同,具體如下:
編寫java動(dòng)態(tài)執(zhí)行代碼
package abc;
import java.io.IOException;
import com.sun.tools.attach.VirtualMachine;
public class VMAttacher {
public static void main(String[] args) throws Exception {
// args[0]為java進(jìn)程id
System.out.println(args[0]);
VirtualMachine virtualMachine = com.sun.tools.attach.VirtualMachine.attach(args[0]);
System.out.println(virtualMachine.getClass());
System.out.println("==========contintue");
// args[1]為共享庫路徑
virtualMachine.loadAgentPath(args[1], null);
virtualMachine.detach();
}
}
編譯java程序生成class文件,指定額外的依賴
javac -Djava.ext.dirs=C:\jdk1.8.0_101\lib ./abc/VMAttacher.java
編寫cpp代碼打印加載的類信息
//如果引入失敗可以直接指定文件地址例如 "./jvm/jvmti.h"
#include <jvmti.h>
#include <string>
#include <cstring>
#include <iostream>
#include <list>
#include <map>
#include <set>
#include <stdlib.h>
#include <jni_md.h>
using namespace std;
JNIEXPORT jint JNICALL Agent_OnAttach(JavaVM* jvm, char* options,
void* reserved) {
jvmtiEnv* jvmti;
jint result = jvm->GetEnv((void**)&jvmti, JVMTI_VERSION_1_1);
if (result != JNI_OK) {
printf("ERROR: Unable to access JVMTI!\n");
}
jvmtiError err = (jvmtiError)0;
jclass* classes;
jint count;
err = jvmti->GetLoadedClasses(&count, &classes);
if (err) {
printf("ERROR: JVMTI GetLoadedClasses failed!\n");
}
for (int i = 0; i < count; i++) {
char* sig;
jvmti->GetClassSignature(classes[i], &sig, NULL);
printf("cls sig=%s\n", sig);
}
return err;
}
JNIEXPORT void JNICALL Agent_OnUnload(JavaVM* vm) {
cout << "Agent_OnUnload(" << vm << ")" << endl;
}
生成動(dòng)態(tài)鏈接庫:
cl /EHsc -I
{JAVA_HOME}/include/win32 -LD Agent2.cpp -FeAgent2.dll
用于 x64 的 Microsoft (R) C/C++ 優(yōu)化編譯器 19.24.28314 版
版權(quán)所有(C) Microsoft Corporation。保留所有權(quán)利。
Agent2.cpp
Microsoft (R) Incremental Linker Version 14.24.28314.0
Copyright (C) Microsoft Corporation. All rights reserved.
/dll
/implib:Agent2.lib
/out:Agent2.dll
Agent2.obj
正在創(chuàng)建庫 Agent2.lib 和對(duì)象 Agent2.exp
完成,后動(dòng)態(tài)啟動(dòng)加載該鏈接庫到對(duì)應(yīng)的jvm中
執(zhí)行
java -Djava.ext.dirs=./lib -cp ./ abc.VMAttacher 12345 /xx/Agent2.dll
- lib文件下是拷貝jdk lib下的tools.jar
執(zhí)行成功后钦幔,可以在對(duì)應(yīng)的進(jìn)程12345下看到下面jvmti打印的日志
class signature=Lorg/springframework/core/ReactiveAdapterRegistry$ReactorRegistrar$$Lambda$517/1273048940;
class signature=Lorg/springframework/core/ReactiveAdapterRegistry$ReactorRegistrar$$Lambda$516/375201108;
....
...
- 以上就是兩種實(shí)現(xiàn)方式了,具體可以根據(jù)需求實(shí)現(xiàn)具體的業(yè)務(wù)邏輯