[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方法
```
![](https://img.kancloud.cn/b4/e6/b4e659568c42d292ae32a15ca9685ce8_969x516.png)
### 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差不多,如下图所示。
![](https://img.kancloud.cn/b9/6d/b96d6504a2eb9a6ffa636e31b0cd7ffd_1240x850.png)
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 性能优化
- 数据跨平台