[TOC]
## jvmti
### 原理
本質是?JVMTI 本質上是在JVM內部的許多事件進行了埋點,包括內存申請、線程創建、類加載、GC信息、方法執行等,也可以控制JVM的某些行為
C/C++實現一個JVMTI Agent,在Agent里面注冊一些JVM事件的回調。當事件發生時JVMTI調用這些回調方法。Agent可以在回調方法里面實現自己的邏輯。
### 功能
1.重新定義類
2.跟蹤對象分配和垃圾回收過程
3.遵循對象的引用樹,遍歷堆中的所有對象
4.檢查 Java 調用堆棧
5.暫停(和恢復)所有線程
### 優點
1. Google自家推出,其穩定性和后續的維護更新可以得到保障,功能強大
### 缺點
1. Android9.0開放
2. Debug可用
3. 影響性能
### 實現
### java實現
```
//加載so
?System.load(agentPath);
//加載jvmti
Debug.attachJvmtiAgent(agentPath,null,getClassLoader());
//系統最終從加載的庫中尋找Agent\_xx方法,即回調so內部的Agent\_XX方法
```

### nativa實現
~~~
#include <jni.h>
#include <string>
#include "jvmti.h"
#include "utils.h"
jvmtiEnv *mJvmtiEnv = NULL;
jlong tag = 0;
//初始化工作
extern "C"
JNIEXPORT jint JNICALL Agent_OnAttach(JavaVM *vm, char *options, void *reserved) {
//準備jvmti環境
vm->GetEnv(reinterpret_cast<void **>(&mJvmtiEnv), JVMTI_VERSION_1_2);
//開啟jvmti的能力
jvmtiCapabilities caps;
//獲取所有的能力
mJvmtiEnv->GetPotentialCapabilities(&caps);
mJvmtiEnv->AddCapabilities(&caps);
return JNI_OK;
}
//調用System.Load()后會回調該方法
extern "C"
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
JNIEnv *env;
if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
return JNI_ERR;
}
return JNI_VERSION_1_6;
}
void JNICALL objectAlloc(jvmtiEnv *jvmti_env, JNIEnv *jni_env, jthread thread,
jobject object, jclass object_klass, jlong size) {
//對象創建
}
void JNICALL objectFree(jvmtiEnv *jvmti_env, jlong tag) {
//對象釋放
}
void JNICALL methodEntry(jvmtiEnv *jvmti_env,JNIEnv* jni_env,jthread thread,jmethodID method) {
//方法進入
}
void JNICALL methodExit(jvmtiEnv *jvmti_env,JNIEnv* jni_env,jthread thread,jmethodID method,jboolean was_popped_by_exception,
jvalue return_value) {
//方法退出
}
extern "C"
JNIEXPORT void JNICALL
Java_com_hly_memorymonitor_Monitor_agent_1init(JNIEnv *env, jclass jclazz) {
//開啟jvm事件監聽
jvmtiEventCallbacks callbacks;
memset(&callbacks, 0, sizeof(callbacks));
callbacks.MethodEntry = &methodEntry;
callbacks.MethodExit = &methodExit;
callbacks.VMObjectAlloc = &objectAlloc;
callbacks.ObjectFree = &objectFree;
//設置回調函數
mJvmtiEnv->SetEventCallbacks(&callbacks, sizeof(callbacks));
//開啟監聽
mJvmtiEnv->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_VM_OBJECT_ALLOC, NULL);
mJvmtiEnv->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_OBJECT_FREE, NULL);
mJvmtiEnv->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_METHOD_ENTRY, NULL);
mJvmtiEnv->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_METHOD_EXIT, NULL);
env->ReleaseStringUTFChars(_path, path);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_hly_memorymonitor_Monitor_agent_1release(JNIEnv *env, jclass clazz) {
mJvmtiEnv->SetEventNotificationMode(JVMTI_DISABLE, JVMTI_EVENT_VM_OBJECT_ALLOC, NULL);
mJvmtiEnv->SetEventNotificationMode(JVMTI_DISABLE, JVMTI_EVENT_OBJECT_FREE, NULL);
mJvmtiEnv->SetEventNotificationMode(JVMTI_DISABLE, JVMTI_EVENT_METHOD_ENTRY, NULL);
mJvmtiEnv->SetEventNotificationMode(JVMTI_DISABLE, JVMTI_EVENT_METHOD_EXIT, NULL);
}
~~~
1.在Agent\_OnAttach()內部初始化,準備jvmti環境,開啟及獲取能力;
2.在xx\_agent\_1init()內部,開啟jvmti事件監聽,設置需要關注的回調(該回調在jvmti.h內部有詳細的定義,設置需要關注的即可,本案例關注了JVMTI\_EVENT\_VM\_OBJECT\_ALLOC、JVMTI\_EVENT\_OBJECT\_FREE、JVMTI\_EVENT\_OBJECT\_FREE、JVMTI\_EVENT\_METHOD\_EXIT),執行SetEventNotificationMode JVMTI\_ENABLE 開啟監聽;
3.在xx\_agent\_1release()內部,執行SetEventNotificationMode JVMTI\_DISABLE 關閉監聽;
## epic
原理是通過修改ArtMethod的入口函數,把入口函數的前8個字節修改為一段跳轉指令,跳轉到執行hook操作的函數,原理跟阿里的熱修復框架AndFix差不多,如下圖所示。

1. 受限于 inline hook 本身,短方法 (Thumb-2 下指令小于 8 個字節,ARM64 小于 16 字節) 無法支持。
2. 被完全內聯的方法不支持。
# 參考資料
[ASM hook隱私方法調用,防止App被下架](https://juejin.cn/post/7043399520486424612)
[我為Dexposed續一秒——論ART上運行時 Method AOP實現](https://weishu.me/2017/11/23/dexposed-on-art/)
[Android JVMTI實現應用內存動態檢測](https://www.jianshu.com/p/ab7bbc319dd9)
- Android
- 四大組件
- Activity
- Fragment
- Service
- 序列化
- Handler
- Hander介紹
- MessageQueue詳細
- 啟動流程
- 系統啟動流程
- 應用啟動流程
- Activity啟動流程
- View
- view繪制
- view事件傳遞
- choreographer
- LayoutInflater
- UI渲染概念
- Binder
- Binder原理
- Binder最大數據
- Binder小結
- Android組件
- ListView原理
- RecyclerView原理
- SharePreferences
- AsyncTask
- Sqlite
- SQLCipher加密
- 遷移與修復
- Sqlite內核
- Sqlite優化v2
- sqlite索引
- sqlite之wal
- sqlite之鎖機制
- 網絡
- 基礎
- TCP
- HTTP
- HTTP1.1
- HTTP2.0
- HTTPS
- HTTP3.0
- HTTP進化圖
- HTTP小結
- 實踐
- 網絡優化
- Json
- ProtoBuffer
- 斷點續傳
- 性能
- 卡頓
- 卡頓監控
- ANR
- ANR監控
- 內存
- 內存問題與優化
- 圖片內存優化
- 線下內存監控
- 線上內存監控
- 啟動優化
- 死鎖監控
- 崩潰監控
- 包體積優化
- UI渲染優化
- UI常規優化
- I/O監控
- 電量監控
- 第三方框架
- 網絡框架
- Volley
- Okhttp
- 網絡框架n問
- OkHttp原理N問
- 設計模式
- EventBus
- Rxjava
- 圖片
- ImageWoker
- Gilde的優化
- APT
- 依賴注入
- APT
- ARouter
- ButterKnife
- MMKV
- Jetpack
- 協程
- MVI
- Startup
- DataBinder
- 黑科技
- hook
- 運行期Java-hook技術
- 編譯期hook
- ASM
- Transform增量編譯
- 運行期Native-hook技術
- 熱修復
- 插件化
- AAB
- Shadow
- 虛擬機
- 其他
- UI自動化
- JavaParser
- Android Line
- 編譯
- 疑難雜癥
- Android11滑動異常
- 方案
- 工業化
- 模塊化
- 隱私合規
- 動態化
- 項目管理
- 業務啟動優化
- 業務架構設計
- 性能優化case
- 性能優化-排查思路
- 性能優化-現有方案
- 登錄
- 搜索
- C++
- NDK入門
- 跨平臺
- H5
- Flutter
- Flutter 性能優化
- 數據跨平臺