# DEX 索引与 descriptor

DEX 的三个特性会直接影响你怎么写查询。

### 一个 APK 里有多个 dex

APK 通常包含多个 `classes*.dex`。DexSQL 把它们放进同一组 SQL 关系，用 `file_id` 区分。由此有三条规则：

- **所有 `*_idx` 索引只在单个 dex 内有效。** `method_idx = 42` 在不同 dex 里是不同的方法。**join 时必须带上 `file_id`**，否则会跨 dex 串行。
- **同一个实体会在多个 dex 中各出现一次。** 一个被 5 个 dex 引用的方法在 `methods` 里有 5 行。要按实体计数，用 `DISTINCT descriptor`。
- **字符串是例外：它的作用域是「池」，不是 dex。** 键为 `(string_pool_id, string_idx)`，从 `file_id` 经 `dex_files.string_pool_id` 到达。DEX 041 容器中多个逻辑 dex 共享一个池；041 之前每个 dex 各有一个自己的池。

### descriptor 是什么

descriptor 是 DEX 用来指认一个实体的字符串，也是本 schema 中最常用的检索键：

| 实体 | 形式 | 例子 |
| --- | --- | --- |
| 类型 | `L<包路径>;` | `Ljava/lang/String;` |
| 方法 | `<类><code>-></code><名>(<参数…>)<返回>` | `Lpkg/Cls;->name(I)V` |
| 字段 | `<类><code>-></code><名>:<类型>` | `Lpkg/Cls;->field:I` |

基本类型是单字母：`V` void、`Z` boolean、`B` byte、`S` short、`C` char、`I` int、`J` long、`F` float、`D` double。数组加前缀 `[`，如 `[Ljava/lang/String;`。方法参数之间没有分隔符。

DEX 本身只存类型 descriptor；方法和字段的 descriptor 由 DexSQL 从各部分拼出来。

### 引用与定义

DEX 的 id 段（`method_ids`、`field_ids`、`type_ids`）登记的是当前 dex **引用**到的实体，无论它在何处定义；成员的实际定义在 class-data 中，是另一份数据。DexSQL 保留这个区别：

| 关系 | 一行是 |
| --- | --- |
| `methods`、`fields`、`types` | 一条**引用** |
| `class_methods`、`class_fields`、`classes` | 一条**定义** |

只被引用的方法在 `methods` 中，其定义相关的列为 `NULL`。这些列的具体行为见 [`methods`](schema.zh.md#methods) 条目。

---

Copyright (c) 2026 LSPosed Developers。本文档采用 [MIT 许可证](../license.md)。
