JNI参数类型类型对齐
JNI 参数类型对齐:Java 层的对象到了 native 层到底是什么
做 JNI 动态分析时,很多人只关注函数名和返回值,却忽略了最关键的一步:参数类型对齐。Java 层的 String、byte[]、int 到了 native 层会变成什么?如果没搞清楚这个,hook 时看到的参数可能完全对不上号。
先说结论:JNI 参数对齐是桥接层分析的基础
Java 和 native 的类型系统差异很大:
- Java 对象在 native 层是
jobject及其子类型 - 基本类型有对应的
jint、jlong、jboolean等 - 数组是
jarray及其子类型 - 字符串是
jstring,需要转换才能拿到原始字符
你不先对齐类型,后面看参数就是在猜。
JNI 参数对齐的核心,是把 Java 语义和 native 表示一一对应起来。
最常见的类型映射
| Java 类型 | JNI 类型 | 说明 |
|---|---|---|
| int | jint | 32 位有符号整数 |
| long | jlong | 64 位有符号整数 |
| boolean | jboolean | 无符号 8 位,0 或 1 |
| byte[] | jbyteArray | 需要 GetByteArrayElements 访问 |
| String | jstring | 需要 GetStringUTFChars 转换 |
| Object | jobject | Java 对象引用 |
为什么类型对齐这么重要?
因为:
- 同样的二进制值,按不同类型解释结果完全不同
- 数组和对象需要特定 API 才能访问内容
- 字符串有编码转换问题
- 对象字段需要通过 JNI 函数获取
你没对齐类型,hook 时看到的参数值可能完全不是你想象的那样。
动态分析时的对齐策略
- 先看 Java 层声明的签名
- 确认每个参数在 native 层的类型
- 对数组和字符串做必要的转换
- 对象类型需要进一步获取字段值
这套流程看着繁琐,但能让你看到的参数真正有意义。
最容易犯的错误
- 把 jint 当成指针
- 直接打印 jstring 而不是先转换
- 忽略数组长度,直接访问越界
- 对象类型不进一步展开字段
结尾
JNI 参数类型对齐不是繁琐的仪式感,而是让动态分析结果真正可靠的基础。你只要把类型映射搞清楚,很多原本看起来奇怪的现象都会变得合理。