diff --git a/docs-source/src/.vuepress/configs/template.ts b/docs-source/src/.vuepress/configs/template.ts
index 0e58016d..6d98c01d 100644
--- a/docs-source/src/.vuepress/configs/template.ts
+++ b/docs-source/src/.vuepress/configs/template.ts
@@ -56,6 +56,12 @@ const navigationLinks = {
baseApiPath + 'hook/core/finder/members/MethodFinder',
baseApiPath + 'hook/core/finder/members/ConstructorFinder',
baseApiPath + 'hook/core/finder/members/FieldFinder',
+ baseApiPath + 'hook/core/finder/classes/DexClassFinder',
+ baseApiPath + 'hook/core/finder/classes/rules/result/MemberRulesResult',
+ baseApiPath + 'hook/core/finder/classes/rules/MemberRules',
+ baseApiPath + 'hook/core/finder/classes/rules/FieldRules',
+ baseApiPath + 'hook/core/finder/classes/rules/MethodRules',
+ baseApiPath + 'hook/core/finder/classes/rules/ConstructorRules',
baseApiPath + 'hook/core/finder/base/BaseFinder',
baseApiPath + 'hook/core/finder/base/rules/CountRules',
baseApiPath + 'hook/core/finder/base/rules/ModifierRules',
@@ -63,6 +69,7 @@ const navigationLinks = {
baseApiPath + 'hook/bean/HookClass',
baseApiPath + 'hook/bean/VariousClass',
baseApiPath + 'hook/bean/CurrentClass',
+ baseApiPath + 'hook/bean/GenericClass',
baseApiPath + 'hook/bean/HookResources'
],
specialFeature: [
diff --git a/docs-source/src/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/DexClassFinder.md b/docs-source/src/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/DexClassFinder.md
new file mode 100644
index 00000000..dc80236b
--- /dev/null
+++ b/docs-source/src/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/DexClassFinder.md
@@ -0,0 +1,725 @@
+---
+pageClass: code-page
+---
+
+# DexClassFinder - class
+
+```kotlin:no-line-numbers
+class DexClassFinder internal constructor(
+ internal var name: String,
+ internal var async: Boolean,
+ override val loaderSet: ClassLoader?
+) : ClassBaseFinder
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> `Class` 查找类。
+
+可使用 `BaseDexClassLoader` 通过指定条件查找指定 `Class` 或一组 `Class`。
+
+::: warning
+
+此功能尚在试验阶段,性能与稳定性可能仍然存在问题,使用过程遇到问题请向我们报告并帮助我们改进。
+
+:::
+
+## companion object - object
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+### clearCache - method
+
+```kotlin:no-line-numbers
+fun clearCache(context: Context?, versionName: String?, versionCode: Long?)
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 清除当前 `DexClassFinder` 的 `Class` 缓存。
+
+适用于全部通过 [ClassLoader.searchClass](../../../factory/ReflectionFactory#classloader-searchclass-ext-method) 或 [PackageParam.searchClass](../../../param/PackageParam#searchclass-method) 获取的 `DexClassFinder`。
+
+## fullName - field
+
+```kotlin:no-line-numbers
+var fullName: String
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 设置 `Class` 完整名称。
+
+只会查询匹配到的 `Class.getName`。
+
+例如 `com.demo.Test` 需要填写 `com.demo.Test`。
+
+## simpleName - field
+
+```kotlin:no-line-numbers
+var simpleName: String
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 设置 `Class` 简单名称。
+
+只会查询匹配到的 `Class.getSimpleName`。
+
+例如 `com.demo.Test` 只需要填写 `Test`。
+
+对于匿名类例如 `com.demo.Test$InnerTest` 会为空,此时你可以使用 [singleName](#singlename-field)。
+
+## singleName - field
+
+```kotlin:no-line-numbers
+var singleName: String
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 设置 `Class` 独立名称。
+
+设置后将首先使用 `Class.getSimpleName`,若为空则会使用 `Class.getName` 进行处理。
+
+例如 `com.demo.Test` 只需要填写 `Test`。
+
+对于匿名类例如 `com.demo.Test$InnerTest` 只需要填写 `Test$InnerTest`。
+
+## from - method
+
+```kotlin:no-line-numbers
+fun from(vararg name: String): FromPackageRules
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 设置在指定包名范围查询当前 `Class`。
+
+设置后仅会在当前 `name` 开头匹配的包名路径下进行查询,可提升查询速度。
+
+例如 ↓
+
+`com.demo.test`
+
+`com.demo.test.demo`
+
+::: warning
+
+建议设置此参数指定查询范围,否则 **Class** 过多时将会非常慢。
+
+:::
+
+## modifiers - method
+
+```kotlin:no-line-numbers
+fun modifiers(conditions: ModifierConditions)
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 设置 `Class` 标识符筛选条件。
+
+可不设置筛选条件。
+
+## fullName - method
+
+```kotlin:no-line-numbers
+fun fullName(value: String): ClassNameRules
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 设置 `Class` 完整名称。
+
+只会查询匹配到的 `Class.getName`。
+
+例如 `com.demo.Test` 需要填写 `com.demo.Test`。
+
+## simpleName - method
+
+```kotlin:no-line-numbers
+fun simpleName(value: String): ClassNameRules
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 设置 `Class` 简单名称。
+
+只会查询匹配到的 `Class.getSimpleName`。
+
+例如 `com.demo.Test` 只需要填写 `Test`。
+
+对于匿名类例如 `com.demo.Test$InnerTest 会为空`,此时你可以使用 [singleName](#singlename-method)。
+
+## singleName - method
+
+```kotlin:no-line-numbers
+fun singleName(value: String): ClassNameRules
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 设置 `Class` 独立名称。
+
+设置后将首先使用 `Class.getSimpleName`,若为空则会使用 `Class.getName` 进行处理。
+
+例如 `com.demo.Test` 只需要填写 `Test`。
+
+对于匿名类例如 `com.demo.Test$InnerTest` 只需要填写 `Test$InnerTest`。
+
+## fullName - method
+
+```kotlin:no-line-numbers
+fun fullName(conditions: NameConditions)
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 设置 `Class` 完整名称条件。
+
+只会查询匹配到的 `Class.getName`。
+
+## simpleName - method
+
+```kotlin:no-line-numbers
+fun simpleName(conditions: NameConditions)
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 设置 `Class` 简单名称条件。
+
+只会查询匹配到的 `Class.getSimpleName`。
+
+## singleName - method
+
+```kotlin:no-line-numbers
+fun singleName(conditions: NameConditions)
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 设置 `Class` 独立名称条件。
+
+设置后将首先使用 `Class.getSimpleName`,若为空则会使用 `Class.getName` 进行处理。
+
+## extends - method
+
+```kotlin:no-line-numbers
+inline fun extends()
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 设置 `Class` 继承的父类。
+
+## extends - method
+
+```kotlin:no-line-numbers
+fun extends(vararg name: String)
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 设置 `Class` 继承的父类。
+
+会同时查询 `name` 中所有匹配的父类。
+
+## implements - method
+
+```kotlin:no-line-numbers
+inline fun implements()
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 设置 `Class` 实现的接口类。
+
+## implements - method
+
+```kotlin:no-line-numbers
+fun implements(vararg name: String)
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 设置 `Class` 实现的接口类。
+
+会同时查询 `name` 中所有匹配的接口类。
+
+## anonymous - method
+
+```kotlin:no-line-numbers
+fun anonymous()
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 标识 `Class` 为匿名类。
+
+例如 `com.demo.Test$1` 或 `com.demo.Test$InnerTest`。
+
+标识后你可以使用 [enclosing](#enclosing-method) 来进一步指定匿名类的 (封闭类) 主类。
+
+## noExtends - method
+
+```kotlin:no-line-numbers
+fun noExtends()
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 设置 `Class` 没有任何继承。
+
+此时 `Class` 只应该继承于 `Any`。
+
+::: warning
+
+设置此条件后 [extends](#extends-method) 将失效。
+
+:::
+
+## noImplements - method
+
+```kotlin:no-line-numbers
+fun noImplements()
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 设置 `Class` 没有任何接口。
+
+::: warning
+
+设置此条件后 [implements](#implements-method) 将失效。
+
+:::
+
+## noSuper - method
+
+```kotlin:no-line-numbers
+fun noSuper()
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 设置 `Class` 没有任何继承与接口。
+
+此时 `Class` 只应该继承于 `Any`。
+
+::: warning
+
+设置此条件后 [extends](#extends-method) 与 [implements](#implements-method) 将失效。
+
+:::
+
+## enclosing - method
+
+```kotlin:no-line-numbers
+inline fun enclosing()
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 设置 `Class` 匿名类的 (封闭类) 主类。
+
+## enclosing - method
+
+```kotlin:no-line-numbers
+fun enclosing(vararg name: String)
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 设置 `Class` 匿名类的 (封闭类) 主类。
+
+会同时查询 `name` 中所有匹配的 (封闭类) 主类。
+
+## FromPackageRules - class
+
+```kotlin:no-line-numbers
+inner class FromPackageRules internal constructor(private val packages: ArrayList)
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 包名范围名称过滤匹配条件实现类。
+
+### absolute - method
+
+```kotlin:no-line-numbers
+fun absolute()
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 设置包名绝对匹配。
+
+例如有如下包名 ↓
+
+`com.demo.test.a`
+
+`com.demo.test.a.b`
+
+`com.demo.test.active`
+
+若包名条件为 `com.demo.test.a` 则绝对匹配仅能匹配到第一个。
+
+相反地,不设置以上示例会全部匹配。
+
+## ClassNameRules - class
+
+```kotlin:no-line-numbers
+inner class ClassNameRules internal constructor(private val name: ClassRulesData.NameRulesData)
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 类名匹配条件实现类。
+
+### optional - method
+
+```kotlin:no-line-numbers
+fun optional()
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 设置类名可选。
+
+例如有如下类名 ↓
+
+`com.demo.Test` **fullName** / `Test` **simpleName**
+
+`defpackage.a` **fullName** / `a` **simpleName**
+
+这两个类名都是同一个类,但是在有些版本中被混淆有些版本没有。
+
+此时可设置类名为 `com.demo.Test` **fullName** / `Test` **simpleName**。
+
+这样就可在完全匹配类名情况下使用类名而忽略其它查询条件,否则忽略此条件继续使用其它查询条件。
+
+## member - method
+
+```kotlin:no-line-numbers
+inline fun member(initiate: MemberRules.() -> Unit): MemberRulesResult
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 设置 `Class` 满足的 `Member` 条件。
+
+## field - method
+
+```kotlin:no-line-numbers
+inline fun field(initiate: FieldRules.() -> Unit): MemberRulesResult
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 设置 `Class` 满足的 `Field` 条件。
+
+## method - method
+
+```kotlin:no-line-numbers
+inline fun method(initiate: MethodRules.() -> Unit): MemberRulesResult
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 设置 `Class` 满足的 `Method` 条件。
+
+## constructor - method
+
+```kotlin:no-line-numbers
+inline fun constructor(initiate: ConstructorRules.() -> Unit): MemberRulesResult
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 设置 `Class` 满足的 `Constructor` 条件。
+
+## Result - class
+
+```kotlin:no-line-numbers
+inner class Result internal constructor(internal var isNotFound: Boolean, internal var throwable: Throwable?) : BaseResult
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> `Class` 查找结果实现类。
+
+### result - method
+
+```kotlin:no-line-numbers
+inline fun result(initiate: Result.() -> Unit): Result
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 创建监听结果事件方法体。
+
+### get - method
+
+```kotlin:no-line-numbers
+fun get(): Class<*>?
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 得到 `Class` 本身。
+
+若有多个 `Class` 结果只会返回第一个。
+
+在查询条件找不到任何结果的时候将返回 `null`。
+
+若你设置了 `async` 请使用 [wait](#wait-method) 方法。
+
+### all - method
+
+```kotlin:no-line-numbers
+fun all(): HashSet>
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 得到 `Class` 本身数组。
+
+返回全部查询条件匹配的多个 `Class` 实例。
+
+在查询条件找不到任何结果的时候将返回空的 `HashSet`。
+
+若你设置了 `async` 请使用 [waitAll](#waitall-method) 方法。
+
+### all - method
+
+```kotlin:no-line-numbers
+fun all(result: (Class<*>) -> Unit): Result
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 得到 `Class` 本身数组 (依次遍历)。
+
+回调全部查询条件匹配的多个 `Class` 实例。
+
+在查询条件找不到任何结果的时候将不会执行。
+
+若你设置了 `async` 请使用 [waitAll](#waitall-method) 方法。
+
+### wait - method
+
+```kotlin:no-line-numbers
+fun wait(result: (Class<*>?) -> Unit): Result
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 得到 `Class` 本身 (异步)。
+
+若有多个 `Class` 结果只会回调第一个。
+
+在查询条件找不到任何结果的时候将回调 null。
+
+你需要设置 `async` 后此方法才会被回调,否则请使用 [get](#get-method) 方法。
+
+### waitAll - method
+
+```kotlin:no-line-numbers
+fun waitAll(result: (HashSet>) -> Unit): Result
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 得到 `Class` 本身数组 (异步)。
+
+回调全部查询条件匹配的多个 `Class` 实例。
+
+在查询条件找不到任何结果的时候将回调空的 `HashSet`。
+
+你需要设置 `async` 后此方法才会被回调,否则请使用 [all](#all-method) 方法。
+
+### onNoClassDefFoundError - method
+
+```kotlin:no-line-numbers
+fun onNoClassDefFoundError(result: (Throwable) -> Unit): Result
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 监听找不到 `Class` 时。
+
+### ignored - method
+
+```kotlin:no-line-numbers
+fun ignored(): Result
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 忽略异常并停止打印任何错误日志。
+
+此时若要监听异常结果,你需要手动实现 [onNoClassDefFoundError](#onnoclassdeffounderror-method) 方法。
\ No newline at end of file
diff --git a/docs-source/src/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/ConstructorRules.md b/docs-source/src/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/ConstructorRules.md
new file mode 100644
index 00000000..f801d1f0
--- /dev/null
+++ b/docs-source/src/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/ConstructorRules.md
@@ -0,0 +1,123 @@
+---
+pageClass: code-page
+---
+
+# ConstructorRules - class
+
+```kotlin:no-line-numbers
+class ConstructorRules internal constructor(internal val rulesData: ConstructorRulesData) : BaseRules
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> `Constructor` 查询条件实现类。
+
+## paramCount - field
+
+```kotlin:no-line-numbers
+var paramCount: Int
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 设置 `Constructor` 参数个数。
+
+你可以不使用 `param` 指定参数类型而是仅使用此变量指定参数个数。
+
+若参数个数小于零则忽略并使用 `param`。
+
+## modifiers - method
+
+```kotlin:no-line-numbers
+fun modifiers(conditions: ModifierConditions)
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 设置 `Constructor` 标识符筛选条件。
+
+可不设置筛选条件。
+
+## emptyParam - method
+
+```kotlin:no-line-numbers
+fun emptyParam()
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 设置 `Constructor` 空参数、无参数。
+
+## param - method
+
+```kotlin:no-line-numbers
+fun param(vararg paramType: Any)
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 设置 `Constructor` 参数。
+
+如果同时使用了 `paramCount` 则 `paramType` 的数量必须与 `paramCount` 完全匹配。
+
+如果 `Constructor` 中存在一些无意义又很长的类型,你可以使用 `VagueType` 来替代它。
+
+::: danger
+
+无参 **Constructor** 请使用 **emptyParam** 设置查询条件。
+
+有参 **Constructor** 必须使用此方法设定参数或使用 **paramCount** 指定个数。
+
+:::
+
+## paramCount - method
+
+```kotlin:no-line-numbers
+fun paramCount(numRange: IntRange)
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 设置 `Constructor` 参数个数范围。
+
+你可以不使用 `param` 指定参数类型而是仅使用此方法指定参数个数范围。
+
+## paramCount - method
+
+```kotlin:no-line-numbers
+fun paramCount(conditions: CountConditions)
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 设置 `Constructor` 参数个数条件。
+
+你可以不使用 `param` 指定参数类型而是仅使用此方法指定参数个数条件。
\ No newline at end of file
diff --git a/docs-source/src/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/FieldRules.md b/docs-source/src/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/FieldRules.md
new file mode 100644
index 00000000..48008a50
--- /dev/null
+++ b/docs-source/src/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/FieldRules.md
@@ -0,0 +1,77 @@
+---
+pageClass: code-page
+---
+
+# FieldRules - class
+
+```kotlin:no-line-numbers
+class FieldRules internal constructor(internal val rulesData: FieldRulesData) : BaseRules
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> `Field` 查询条件实现类。
+
+## name - field
+
+```kotlin:no-line-numbers
+var name: String
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 设置 `Field` 名称。
+
+## type - field
+
+```kotlin:no-line-numbers
+var type: Any?
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 设置 `Field` 类型。
+
+可不填写类型。
+
+## modifiers - method
+
+```kotlin:no-line-numbers
+fun modifiers(conditions: ModifierConditions)
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 设置 `Field` 标识符筛选条件。
+
+可不设置筛选条件。
+
+## name - method
+
+```kotlin:no-line-numbers
+fun name(conditions: NameConditions)
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 设置 `Field` 名称条件。
\ No newline at end of file
diff --git a/docs-source/src/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MemberRules.md b/docs-source/src/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MemberRules.md
new file mode 100644
index 00000000..da0149c6
--- /dev/null
+++ b/docs-source/src/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MemberRules.md
@@ -0,0 +1,33 @@
+---
+pageClass: code-page
+---
+
+# MemberRules - class
+
+```kotlin:no-line-numbers
+class MemberRules internal constructor(internal val rulesData: MemberRulesData) : BaseRules
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> `Member` 查询条件实现类。
+
+## modifiers - method
+
+```kotlin:no-line-numbers
+fun modifiers(conditions: ModifierConditions)
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 设置 `Member` 标识符筛选条件。
+
+可不设置筛选条件。
\ No newline at end of file
diff --git a/docs-source/src/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MethodRules.md b/docs-source/src/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MethodRules.md
new file mode 100644
index 00000000..24dcf3a6
--- /dev/null
+++ b/docs-source/src/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MethodRules.md
@@ -0,0 +1,167 @@
+---
+pageClass: code-page
+---
+
+# MethodRules - class
+
+```kotlin:no-line-numbers
+class MethodRules internal constructor(internal val rulesData: MethodRulesData) : BaseRules
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> `Method` 查询条件实现类。
+
+## name - field
+
+```kotlin:no-line-numbers
+var name: String
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 设置 `Method` 名称。
+
+## paramCount - field
+
+```kotlin:no-line-numbers
+var paramCount: Int
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 设置 `Method` 参数个数。
+
+你可以不使用 `param` 指定参数类型而是仅使用此变量指定参数个数。
+
+若参数个数小于零则忽略并使用 `param`。
+
+## returnType - field
+
+```kotlin:no-line-numbers
+var returnType: Any?
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 设置 `Method` 返回值。
+
+可不填写返回值。
+
+## modifiers - method
+
+```kotlin:no-line-numbers
+fun modifiers(conditions: ModifierConditions)
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 设置 `Method` 标识符筛选条件。
+
+可不设置筛选条件。
+
+## emptyParam - method
+
+```kotlin:no-line-numbers
+fun emptyParam()
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 设置 `Method` 空参数、无参数。
+
+## param - method
+
+```kotlin:no-line-numbers
+fun param(vararg paramType: Any)
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 设置 `Method` 参数。
+
+如果同时使用了 `paramCount` 则 `paramType` 的数量必须与 `paramCount` 完全匹配。
+
+如果 `Method` 中存在一些无意义又很长的类型,你可以使用 `VagueType` 来替代它。
+
+::: danger
+
+无参 **Method** 请使用 **emptyParam** 设置查询条件。
+
+有参 **Method** 必须使用此方法设定参数或使用 **paramCount** 指定个数。
+
+:::
+
+## name - method
+
+```kotlin:no-line-numbers
+fun name(conditions: NameConditions)
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 设置 `Method` 名称条件。
+
+## paramCount - method
+
+```kotlin:no-line-numbers
+fun paramCount(numRange: IntRange)
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 设置 `Method` 参数个数范围。
+
+你可以不使用 `param` 指定参数类型而是仅使用此方法指定参数个数范围。
+
+## paramCount - method
+
+```kotlin:no-line-numbers
+fun paramCount(conditions: CountConditions)
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 设置 `Method` 参数个数条件。
+
+你可以不使用 `param` 指定参数类型而是仅使用此方法指定参数个数条件。
\ No newline at end of file
diff --git a/docs-source/src/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/result/MemberRulesResult.md b/docs-source/src/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/result/MemberRulesResult.md
new file mode 100644
index 00000000..7789add3
--- /dev/null
+++ b/docs-source/src/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/result/MemberRulesResult.md
@@ -0,0 +1,73 @@
+---
+pageClass: code-page
+---
+
+# MemberRulesResult - class
+
+```kotlin:no-line-numbers
+class MemberRulesResult internal constructor(private val rulesData: MemberRulesData)
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 当前 `Member` 查询条件结果实现类。
+
+## none - method
+
+```kotlin:no-line-numbers
+fun none(): MemberRulesResult
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 设置当前 `Member` 在查询条件中个数为 `0`。
+
+## count - method
+
+```kotlin:no-line-numbers
+fun count(num: Int): MemberRulesResult
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 设置当前 `Member` 在查询条件中需要全部匹配的个数。
+
+## count - method
+
+```kotlin:no-line-numbers
+fun count(numRange: IntRange): MemberRulesResult
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 设置当前 `Member` 在查询条件中需要全部匹配的个数范围。
+
+## count - method
+
+```kotlin:no-line-numbers
+fun count(conditions: CountConditions): MemberRulesResult
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 设置当前 `Member` 在查询条件中需要全部匹配的个数条件。
\ No newline at end of file
diff --git a/docs-source/src/zh-cn/api/public/com/highcapable/yukihookapi/hook/factory/ReflectionFactory.md b/docs-source/src/zh-cn/api/public/com/highcapable/yukihookapi/hook/factory/ReflectionFactory.md
index 3ec9fed0..f5753efe 100644
--- a/docs-source/src/zh-cn/api/public/com/highcapable/yukihookapi/hook/factory/ReflectionFactory.md
+++ b/docs-source/src/zh-cn/api/public/com/highcapable/yukihookapi/hook/factory/ReflectionFactory.md
@@ -68,6 +68,30 @@ CONSTRUCTOR
> 全部 `Constructor`。
+## ClassLoader.searchClass - ext-method
+
+```kotlin:no-line-numbers
+inline fun ClassLoader.searchClass(name: String, async: Boolean, initiate: ClassConditions): DexClassFinder.Result
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 通过当前 `ClassLoader` 按指定条件查找并得到 **Dex** 中的 `Class`。
+
+::: danger
+
+此方法在 **Class** 数量过多及查找条件复杂时会非常耗时。
+
+建议启用 **async** 或设置 **name** 参数,**name** 参数将在 Hook APP (宿主) 不同版本中自动进行本地缓存以提升效率。
+
+此功能尚在试验阶段,性能与稳定性可能仍然存在问题,使用过程遇到问题请向我们报告并帮助我们改进。
+
+:::
+
## ClassLoader.onLoadClass - ext-method
```kotlin:no-line-numbers
diff --git a/docs-source/src/zh-cn/api/public/com/highcapable/yukihookapi/hook/param/PackageParam.md b/docs-source/src/zh-cn/api/public/com/highcapable/yukihookapi/hook/param/PackageParam.md
index f73ec3c8..1249f2f7 100644
--- a/docs-source/src/zh-cn/api/public/com/highcapable/yukihookapi/hook/param/PackageParam.md
+++ b/docs-source/src/zh-cn/api/public/com/highcapable/yukihookapi/hook/param/PackageParam.md
@@ -472,6 +472,30 @@ fun loadHooker(hooker: YukiBaseHooker)
你可以填入 `hooker` 在 Hooker 中继续装载 Hooker。
+## searchClass - method
+
+```kotlin:no-line-numbers
+inline fun searchClass(name: String, async: Boolean, initiate: ClassConditions): DexClassFinder.Result
+```
+
+**变更记录**
+
+`v1.1.0` `新增`
+
+**功能描述**
+
+> 通过 `appClassLoader` 按指定条件查找并得到当前 Hook APP **Dex** 中的 `Class`。
+
+::: danger
+
+此方法在 **Class** 数量过多及查找条件复杂时会非常耗时。
+
+建议启用 **async** 或设置 **name** 参数,**name** 参数将在 Hook APP (宿主) 不同版本中自动进行本地缓存以提升效率。
+
+此功能尚在试验阶段,性能与稳定性可能仍然存在问题,使用过程遇到问题请向我们报告并帮助我们改进。
+
+:::
+
String+VariousClass.clazz - i-ext-field
**变更记录**
diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/base/ClassBaseFinder.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/base/ClassBaseFinder.kt
new file mode 100644
index 00000000..19a528af
--- /dev/null
+++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/base/ClassBaseFinder.kt
@@ -0,0 +1,75 @@
+/*
+ * YukiHookAPI - An efficient Kotlin version of the Xposed Hook API.
+ * Copyright (C) 2019-2022 HighCapable
+ * https://github.com/fankes/YukiHookAPI
+ *
+ * MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * This file is Created by fankes on 2022/9/4.
+ */
+package com.highcapable.yukihookapi.hook.core.finder.base
+
+import com.highcapable.yukihookapi.YukiHookAPI
+import com.highcapable.yukihookapi.annotation.YukiPrivateApi
+import com.highcapable.yukihookapi.hook.log.yLoggerE
+import com.highcapable.yukihookapi.hook.log.yLoggerI
+import com.highcapable.yukihookapi.hook.xposed.bridge.YukiHookBridge
+
+/**
+ * 这是 [Class] 查找类功能的基本类实现
+ * @param loaderSet 当前使用的 [ClassLoader] 实例
+ */
+abstract class ClassBaseFinder internal constructor(internal open val loaderSet: ClassLoader? = null) : BaseFinder() {
+
+ /** 当前找到的 [Class] 数组 */
+ internal var classInstances = HashSet>()
+
+ /** 是否开启忽略错误警告功能 */
+ internal var isShutErrorPrinting = false
+
+ /**
+ * 将目标类型转换为可识别的兼容类型
+ * @param any 当前需要转换的实例
+ * @param tag 当前查找类的标识
+ * @return [Class] or null
+ */
+ internal fun compatType(any: Any?, tag: String) = any?.compat(tag, loaderSet)
+
+ /**
+ * 在开启 [YukiHookAPI.Configs.isDebug] 且在 [YukiHookBridge.hasXposedBridge] 情况下输出调试信息
+ * @param msg 调试日志内容
+ */
+ internal fun onDebuggingMsg(msg: String) {
+ if (YukiHookAPI.Configs.isDebug && YukiHookBridge.hasXposedBridge) yLoggerI(msg = msg)
+ }
+
+ /**
+ * 发生错误时输出日志
+ * @param throwable 错误
+ */
+ internal fun onFailureMsg(throwable: Throwable? = null) {
+ if (isShutErrorPrinting) return
+ yLoggerE(msg = "NoClassDefFound happend in [$loaderSet]", e = throwable)
+ }
+
+ @YukiPrivateApi
+ override fun failure(throwable: Throwable?) = error("DexClassFinder does not contain this usage")
+}
\ No newline at end of file
diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/classes/DexClassFinder.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/classes/DexClassFinder.kt
new file mode 100644
index 00000000..48e9524a
--- /dev/null
+++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/classes/DexClassFinder.kt
@@ -0,0 +1,620 @@
+/*
+ * YukiHookAPI - An efficient Kotlin version of the Xposed Hook API.
+ * Copyright (C) 2019-2022 HighCapable
+ * https://github.com/fankes/YukiHookAPI
+ *
+ * MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * This file is Created by fankes on 2022/9/4.
+ */
+@file:Suppress("unused", "MemberVisibilityCanBePrivate")
+
+package com.highcapable.yukihookapi.hook.core.finder.classes
+
+import android.content.Context
+import android.content.SharedPreferences
+import android.content.pm.PackageManager
+import android.os.SystemClock
+import androidx.core.content.pm.PackageInfoCompat
+import com.highcapable.yukihookapi.annotation.YukiPrivateApi
+import com.highcapable.yukihookapi.hook.core.finder.base.ClassBaseFinder
+import com.highcapable.yukihookapi.hook.core.finder.classes.data.ClassRulesData
+import com.highcapable.yukihookapi.hook.core.finder.classes.rules.ConstructorRules
+import com.highcapable.yukihookapi.hook.core.finder.classes.rules.FieldRules
+import com.highcapable.yukihookapi.hook.core.finder.classes.rules.MemberRules
+import com.highcapable.yukihookapi.hook.core.finder.classes.rules.MethodRules
+import com.highcapable.yukihookapi.hook.core.finder.classes.rules.base.BaseRules
+import com.highcapable.yukihookapi.hook.core.finder.classes.rules.result.MemberRulesResult
+import com.highcapable.yukihookapi.hook.core.finder.tools.ReflectionTool
+import com.highcapable.yukihookapi.hook.core.finder.type.factory.ModifierConditions
+import com.highcapable.yukihookapi.hook.core.finder.type.factory.NameConditions
+import com.highcapable.yukihookapi.hook.factory.hasClass
+import com.highcapable.yukihookapi.hook.factory.searchClass
+import com.highcapable.yukihookapi.hook.factory.toClass
+import com.highcapable.yukihookapi.hook.log.yLoggerW
+import com.highcapable.yukihookapi.hook.param.PackageParam
+import com.highcapable.yukihookapi.hook.utils.await
+import com.highcapable.yukihookapi.hook.utils.runBlocking
+import com.highcapable.yukihookapi.hook.xposed.helper.YukiHookAppHelper
+import dalvik.system.BaseDexClassLoader
+import java.lang.reflect.Constructor
+import java.lang.reflect.Field
+import java.lang.reflect.Member
+import java.lang.reflect.Method
+
+/**
+ * [Class] 查找类
+ *
+ * 可使用 [BaseDexClassLoader] 通过指定条件查找指定 [Class] 或一组 [Class]
+ *
+ * - ❗此功能尚在试验阶段 - 性能与稳定性可能仍然存在问题 - 使用过程遇到问题请向我们报告并帮助我们改进
+ * @param name 标识当前 [Class] 缓存的名称 - 不设置将不启用缓存 - 启用缓存必须启用 [async]
+ * @param async 是否启用异步
+ * @param loaderSet 当前使用的 [ClassLoader] 实例
+ */
+class DexClassFinder @PublishedApi internal constructor(
+ internal var name: String,
+ internal var async: Boolean,
+ override val loaderSet: ClassLoader?
+) : ClassBaseFinder(loaderSet) {
+
+ companion object {
+
+ /** 缓存的存储文件名 */
+ private const val CACHE_FILE_NAME = "config_yukihook_cache_obfuscate_classes"
+
+ /**
+ * 通过 [Context] 获取当前 [SharedPreferences]
+ * @param versionName 版本名称 - 默认空
+ * @param versionCode 版本号 - 默认空
+ * @return [SharedPreferences]
+ */
+ private fun Context.currentSp(versionName: String? = null, versionCode: Long? = null) =
+ getSharedPreferences(packageManager?.getPackageInfo(packageName, PackageManager.GET_META_DATA)
+ ?.let { "${CACHE_FILE_NAME}_${versionName ?: it.versionName}_${versionCode ?: PackageInfoCompat.getLongVersionCode(it)}" }
+ ?: "${CACHE_FILE_NAME}_unknown",
+ Context.MODE_PRIVATE)
+
+ /**
+ * 清除当前 [DexClassFinder] 的 [Class] 缓存
+ *
+ * 适用于全部通过 [ClassLoader.searchClass] or [PackageParam.searchClass] 获取的 [DexClassFinder]
+ * @param context 当前 [Context] - 不填默认获取 [YukiHookAppHelper.currentApplication]
+ * @param versionName 版本名称 - 默认空
+ * @param versionCode 版本号 - 默认空
+ */
+ fun clearCache(context: Context? = YukiHookAppHelper.currentApplication(), versionName: String? = null, versionCode: Long? = null) {
+ context?.currentSp(versionName, versionCode)?.edit()?.clear()?.apply()
+ ?: yLoggerW(msg = "Cannot clear cache for DexClassFinder because got null context instance")
+ }
+ }
+
+ @PublishedApi
+ override var rulesData = ClassRulesData()
+
+ /**
+ * 设置 [Class] 完整名称
+ *
+ * 只会查询匹配到的 [Class.getName]
+ *
+ * 例如 com.demo.Test 需要填写 com.demo.Test
+ * @return [String]
+ */
+ var fullName
+ get() = rulesData.fullName?.name ?: ""
+ set(value) {
+ rulesData.fullName = rulesData.createNameRulesData(value)
+ }
+
+ /**
+ * 设置 [Class] 简单名称
+ *
+ * 只会查询匹配到的 [Class.getSimpleName]
+ *
+ * 例如 com.demo.Test 只需要填写 Test
+ *
+ * 对于匿名类例如 com.demo.Test$InnerTest 会为空 - 此时你可以使用 [singleName]
+ * @return [String]
+ */
+ var simpleName
+ get() = rulesData.simpleName?.name ?: ""
+ set(value) {
+ rulesData.simpleName = rulesData.createNameRulesData(value)
+ }
+
+ /**
+ * 设置 [Class] 独立名称
+ *
+ * 设置后将首先使用 [Class.getSimpleName] - 若为空则会使用 [Class.getName] 进行处理
+ *
+ * 例如 com.demo.Test 只需要填写 Test
+ *
+ * 对于匿名类例如 com.demo.Test$InnerTest 只需要填写 Test$InnerTest
+ * @return [String]
+ */
+ var singleName
+ get() = rulesData.singleName?.name ?: ""
+ set(value) {
+ rulesData.singleName = rulesData.createNameRulesData(value)
+ }
+
+ /**
+ * 设置在指定包名范围查询当前 [Class]
+ *
+ * 设置后仅会在当前 [name] 开头匹配的包名路径下进行查询 - 可提升查询速度
+ *
+ * 例如 ↓
+ *
+ * com.demo.test
+ *
+ * com.demo.test.demo
+ *
+ * - ❗建议设置此参数指定查询范围 - 否则 [Class] 过多时将会非常慢
+ * @param name 指定包名
+ * @return [FromPackageRules] 可设置 [FromPackageRules.absolute] 标识包名绝对匹配
+ */
+ fun from(vararg name: String) = FromPackageRules(arrayListOf().also {
+ name.takeIf { e -> e.isNotEmpty() }?.forEach { e -> it.add(rulesData.createPackageRulesData(e)) }
+ if (it.isNotEmpty()) rulesData.fromPackages.addAll(it)
+ })
+
+ /**
+ * 设置 [Class] 标识符筛选条件
+ *
+ * - 可不设置筛选条件
+ * @param conditions 条件方法体
+ */
+ fun modifiers(conditions: ModifierConditions) {
+ rulesData.modifiers = conditions
+ }
+
+ /**
+ * 设置 [Class] 完整名称
+ *
+ * 只会查询匹配到的 [Class.getName]
+ *
+ * 例如 com.demo.Test 需要填写 com.demo.Test
+ * @param value 名称
+ * @return [ClassNameRules] 可设置 [ClassNameRules.optional] 标识类名可选
+ */
+ fun fullName(value: String) = rulesData.createNameRulesData(value).let {
+ rulesData.fullName = it
+ ClassNameRules(it)
+ }
+
+ /**
+ * 设置 [Class] 简单名称
+ *
+ * 只会查询匹配到的 [Class.getSimpleName]
+ *
+ * 例如 com.demo.Test 只需要填写 Test
+ *
+ * 对于匿名类例如 com.demo.Test$InnerTest 会为空 - 此时你可以使用 [singleName]
+ * @param value 名称
+ * @return [ClassNameRules] 可设置 [ClassNameRules.optional] 标识类名可选
+ */
+ fun simpleName(value: String) = rulesData.createNameRulesData(value).let {
+ rulesData.simpleName = it
+ ClassNameRules(it)
+ }
+
+ /**
+ * 设置 [Class] 独立名称
+ *
+ * 设置后将首先使用 [Class.getSimpleName] - 若为空则会使用 [Class.getName] 进行处理
+ *
+ * 例如 com.demo.Test 只需要填写 Test
+ *
+ * 对于匿名类例如 com.demo.Test$InnerTest 只需要填写 Test$InnerTest
+ * @param value 名称
+ * @return [ClassNameRules] 可设置 [ClassNameRules.optional] 标识类名可选
+ */
+ fun singleName(value: String) = rulesData.createNameRulesData(value).let {
+ rulesData.singleName = it
+ ClassNameRules(it)
+ }
+
+ /**
+ * 设置 [Class] 完整名称条件
+ *
+ * 只会查询匹配到的 [Class.getName]
+ * @param conditions 条件方法体
+ */
+ fun fullName(conditions: NameConditions) {
+ rulesData.fullNameConditions = conditions
+ }
+
+ /**
+ * 设置 [Class] 简单名称条件
+ *
+ * 只会查询匹配到的 [Class.getSimpleName]
+ * @param conditions 条件方法体
+ */
+ fun simpleName(conditions: NameConditions) {
+ rulesData.simpleNameConditions = conditions
+ }
+
+ /**
+ * 设置 [Class] 独立名称条件
+ *
+ * 设置后将首先使用 [Class.getSimpleName] - 若为空则会使用 [Class.getName] 进行处理
+ * @param conditions 条件方法体
+ */
+ fun singleName(conditions: NameConditions) {
+ rulesData.singleNameConditions = conditions
+ }
+
+ /** 设置 [Class] 继承的父类 */
+ inline fun extends() {
+ rulesData.extendsClass.add(T::class.java.name)
+ }
+
+ /**
+ * 设置 [Class] 继承的父类
+ *
+ * 会同时查询 [name] 中所有匹配的父类
+ * @param name [Class] 完整名称
+ */
+ fun extends(vararg name: String) {
+ rulesData.extendsClass.addAll(name.toList())
+ }
+
+ /** 设置 [Class] 实现的接口类 */
+ inline fun implements() {
+ rulesData.implementsClass.add(T::class.java.name)
+ }
+
+ /**
+ * 设置 [Class] 实现的接口类
+ *
+ * 会同时查询 [name] 中所有匹配的接口类
+ * @param name [Class] 完整名称
+ */
+ fun implements(vararg name: String) {
+ rulesData.implementsClass.addAll(name.toList())
+ }
+
+ /**
+ * 标识 [Class] 为匿名类
+ *
+ * 例如 com.demo.Test$1 或 com.demo.Test$InnerTest
+ *
+ * 标识后你可以使用 [enclosing] 来进一步指定匿名类的 (封闭类) 主类
+ */
+ fun anonymous() {
+ rulesData.isAnonymousClass = true
+ }
+
+ /**
+ * 设置 [Class] 没有任何继承
+ *
+ * 此时 [Class] 只应该继承于 [Any]
+ *
+ * - ❗设置此条件后 [extends] 将失效
+ */
+ fun noExtends() {
+ rulesData.isNoExtendsClass = true
+ }
+
+ /**
+ * 设置 [Class] 没有任何接口
+ *
+ * - ❗设置此条件后 [implements] 将失效
+ */
+ fun noImplements() {
+ rulesData.isNoImplementsClass = true
+ }
+
+ /**
+ * 设置 [Class] 没有任何继承与接口
+ *
+ * 此时 [Class] 只应该继承于 [Any]
+ *
+ * - ❗设置此条件后 [extends] 与 [implements] 将失效
+ */
+ fun noSuper() {
+ noExtends()
+ noImplements()
+ }
+
+ /** 设置 [Class] 匿名类的 (封闭类) 主类 */
+ inline fun enclosing() {
+ rulesData.enclosingClass.add(T::class.java.name)
+ }
+
+ /**
+ * 设置 [Class] 匿名类的 (封闭类) 主类
+ *
+ * 会同时查询 [name] 中所有匹配的 (封闭类) 主类
+ * @param name [Class] 完整名称
+ */
+ fun enclosing(vararg name: String) {
+ rulesData.enclosingClass.addAll(name.toList())
+ }
+
+ /**
+ * 包名范围名称过滤匹配条件实现类
+ * @param packages 包名数组
+ */
+ inner class FromPackageRules internal constructor(private val packages: ArrayList) {
+
+ /**
+ * 设置包名绝对匹配
+ *
+ * 例如有如下包名 ↓
+ *
+ * com.demo.test.a
+ *
+ * com.demo.test.a.b
+ *
+ * com.demo.test.active
+ *
+ * 若包名条件为 "com.demo.test.a" 则绝对匹配仅能匹配到第一个
+ *
+ * 相反地 - 不设置以上示例会全部匹配
+ */
+ fun absolute() = packages.takeIf { it.isNotEmpty() }?.forEach { it.isAbsolute = true }
+ }
+
+ /**
+ * 类名匹配条件实现类
+ * @param name 类名匹配实例
+ */
+ inner class ClassNameRules internal constructor(private val name: ClassRulesData.NameRulesData) {
+
+ /**
+ * 设置类名可选
+ *
+ * 例如有如下类名 ↓
+ *
+ * com.demo.Test (fullName) / Test (simpleName)
+ *
+ * defpackage.a (fullName) / a (simpleName)
+ *
+ * 这两个类名都是同一个类 - 但是在有些版本中被混淆有些版本没有
+ *
+ * 此时可设置类名为 "com.demo.Test" (fullName) / "Test" (simpleName)
+ *
+ * 这样就可在完全匹配类名情况下使用类名而忽略其它查询条件 - 否则忽略此条件继续使用其它查询条件
+ */
+ fun optional() {
+ name.isOptional = true
+ }
+ }
+
+ /**
+ * 设置 [Class] 满足的 [Member] 条件
+ * @param initiate 条件方法体
+ * @return [MemberRulesResult]
+ */
+ inline fun member(initiate: MemberRules.() -> Unit = {}) = BaseRules.createMemberRules(this).apply(initiate).build()
+
+ /**
+ * 设置 [Class] 满足的 [Field] 条件
+ * @param initiate 条件方法体
+ * @return [MemberRulesResult]
+ */
+ inline fun field(initiate: FieldRules.() -> Unit = {}) = BaseRules.createFieldRules(this).apply(initiate).build()
+
+ /**
+ * 设置 [Class] 满足的 [Method] 条件
+ * @param initiate 条件方法体
+ * @return [MemberRulesResult]
+ */
+ inline fun method(initiate: MethodRules.() -> Unit = {}) = BaseRules.createMethodRules(this).apply(initiate).build()
+
+ /**
+ * 设置 [Class] 满足的 [Constructor] 条件
+ * @param initiate 查找方法体
+ * @return [MemberRulesResult]
+ */
+ inline fun constructor(initiate: ConstructorRules.() -> Unit = {}) = BaseRules.createConstructorRules(this).apply(initiate).build()
+
+ /**
+ * 得到 [Class] 或一组 [Class]
+ * @return [HashSet]<[Class]>
+ * @throws NoClassDefFoundError 如果找不到 [Class]
+ */
+ private val result get() = ReflectionTool.findClasses(loaderSet, rulesData)
+
+ /**
+ * 从本地缓存读取 [Class] 数据
+ * @return [HashSet]<[Class]>
+ */
+ private fun readFromCache(): HashSet> =
+ if (async && name.isNotBlank()) YukiHookAppHelper.currentApplication()?.let {
+ hashSetOf>().also { classes ->
+ it.currentSp().getStringSet(name, emptySet())?.takeIf { it.isNotEmpty() }
+ ?.forEach { className -> if (className.hasClass(loaderSet)) classes.add(className.toClass(loaderSet)) }
+ }
+ } ?: let { SystemClock.sleep(1); readFromCache() } else hashSetOf()
+
+ /**
+ * 将当前 [Class] 数组名称保存到本地缓存
+ * @throws IllegalStateException 如果当前包名为 "android"
+ */
+ private fun HashSet>.saveToCache() {
+ if (name.isNotBlank() && isNotEmpty()) hashSetOf().also { names ->
+ takeIf { it.isNotEmpty() }?.forEach { names.add(it.name) }
+ YukiHookAppHelper.currentApplication()?.also {
+ if (it.packageName == "android") error("Cannot create classes cache for \"android\", please remove \"name\" param")
+ it.currentSp().edit().apply { putStringSet(name, names) }.apply()
+ }
+ }
+ }
+
+ /**
+ * 设置实例
+ * @param classes 当前找到的 [Class] 数组
+ */
+ private fun setInstance(classes: HashSet>) {
+ classInstances.clear()
+ classes.takeIf { it.isNotEmpty() }?.forEach { classInstances.add(it) }
+ }
+
+ @YukiPrivateApi
+ override fun build() = runCatching {
+ if (loaderSet != null) {
+ /** 开始任务 */
+ fun startProcess() {
+ runBlocking {
+ setInstance(readFromCache().takeIf { it.isNotEmpty() } ?: result)
+ }.result { ms -> classInstances.takeIf { it.isNotEmpty() }?.forEach { onDebuggingMsg(msg = "Find Class [$it] takes ${ms}ms") } }
+ }
+ Result().also { e ->
+ if (async) e.await {
+ runCatching {
+ startProcess()
+ it.waitResultCallback?.invoke(it.get())
+ it.waitAllResultCallback?.invoke(it.all())
+ classInstances.saveToCache()
+ }.onFailure { e ->
+ it.isNotFound = true
+ it.throwable = e
+ it.noClassDefFoundErrorCallback?.invoke()
+ onFailureMsg(throwable = e)
+ }
+ } else startProcess()
+ }
+ } else Result(isNotFound = true, Throwable("loaderSet is null")).await { onFailureMsg() }
+ }.getOrElse { e -> Result(isNotFound = true, e).await { onFailureMsg(throwable = e) } }
+
+ /**
+ * [Class] 查找结果实现类
+ * @param isNotFound 是否没有找到 [Class] - 默认否
+ * @param throwable 错误信息
+ */
+ inner class Result internal constructor(
+ @PublishedApi internal var isNotFound: Boolean = false,
+ @PublishedApi internal var throwable: Throwable? = null
+ ) : BaseResult {
+
+ /** 异步方法体回调结果 */
+ internal var waitResultCallback: ((Class<*>?) -> Unit)? = null
+
+ /** 异步方法体回调数组结果 */
+ internal var waitAllResultCallback: ((HashSet>) -> Unit)? = null
+
+ /** 异常结果重新回调方法体 */
+ internal var noClassDefFoundErrorCallback: (() -> Unit)? = null
+
+ /**
+ * 创建监听结果事件方法体
+ * @param initiate 方法体
+ * @return [Result] 可继续向下监听
+ */
+ inline fun result(initiate: Result.() -> Unit) = apply(initiate)
+
+ /**
+ * 得到 [Class] 本身
+ *
+ * - 若有多个 [Class] 结果只会返回第一个
+ *
+ * - 在查询条件找不到任何结果的时候将返回 null
+ *
+ * - ❗若你设置了 [async] 请使用 [wait] 方法
+ * @return [Class] or null
+ */
+ fun get() = all().takeIf { it.isNotEmpty() }?.first()
+
+ /**
+ * 得到 [Class] 本身数组
+ *
+ * - 返回全部查询条件匹配的多个 [Class] 实例
+ *
+ * - 在查询条件找不到任何结果的时候将返回空的 [HashSet]
+ *
+ * - ❗若你设置了 [async] 请使用 [waitAll] 方法
+ * @return [HashSet]<[Class]>
+ */
+ fun all() = classInstances
+
+ /**
+ * 得到 [Class] 本身数组 (依次遍历)
+ *
+ * - 回调全部查询条件匹配的多个 [Class] 实例
+ *
+ * - 在查询条件找不到任何结果的时候将不会执行
+ *
+ * - ❗若你设置了 [async] 请使用 [waitAll] 方法
+ * @param result 回调每个结果
+ * @return [Result] 可继续向下监听
+ */
+ fun all(result: (Class<*>) -> Unit): Result {
+ all().takeIf { it.isNotEmpty() }?.forEach(result)
+ return this
+ }
+
+ /**
+ * 得到 [Class] 本身 (异步)
+ *
+ * - 若有多个 [Class] 结果只会回调第一个
+ *
+ * - 在查询条件找不到任何结果的时候将回调 null
+ *
+ * - ❗你需要设置 [async] 后此方法才会被回调 - 否则请使用 [get] 方法
+ * @param result 回调 - ([Class] or null)
+ * @return [Result] 可继续向下监听
+ */
+ fun wait(result: (Class<*>?) -> Unit): Result {
+ waitResultCallback = result
+ return this
+ }
+
+ /**
+ * 得到 [Class] 本身数组 (异步)
+ *
+ * - 回调全部查询条件匹配的多个 [Class] 实例
+ *
+ * - 在查询条件找不到任何结果的时候将回调空的 [HashSet]
+ *
+ * - ❗你需要设置 [async] 后此方法才会被回调 - 否则请使用 [all] 方法
+ * @param result 回调 - ([HashSet]<[Class]>)
+ * @return [Result] 可继续向下监听
+ */
+ fun waitAll(result: (HashSet>) -> Unit): Result {
+ waitAllResultCallback = result
+ return this
+ }
+
+ /**
+ * 监听找不到 [Class] 时
+ * @param result 回调错误
+ * @return [Result] 可继续向下监听
+ */
+ fun onNoClassDefFoundError(result: (Throwable) -> Unit): Result {
+ noClassDefFoundErrorCallback = { if (isNotFound) result(throwable ?: Throwable("Initialization Error")) }
+ noClassDefFoundErrorCallback?.invoke()
+ return this
+ }
+
+ /**
+ * 忽略异常并停止打印任何错误日志
+ *
+ * - ❗此时若要监听异常结果 - 你需要手动实现 [onNoClassDefFoundError] 方法
+ * @return [Result] 可继续向下监听
+ */
+ fun ignored(): Result {
+ isShutErrorPrinting = true
+ return this
+ }
+ }
+}
\ No newline at end of file
diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/classes/data/ClassRulesData.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/classes/data/ClassRulesData.kt
new file mode 100644
index 00000000..b59ca99c
--- /dev/null
+++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/classes/data/ClassRulesData.kt
@@ -0,0 +1,183 @@
+/*
+ * YukiHookAPI - An efficient Kotlin version of the Xposed Hook API.
+ * Copyright (C) 2019-2022 HighCapable
+ * https://github.com/fankes/YukiHookAPI
+ *
+ * MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * This file is Created by fankes on 2022/9/5.
+ */
+@file:Suppress("PropertyName")
+
+package com.highcapable.yukihookapi.hook.core.finder.classes.data
+
+import com.highcapable.yukihookapi.hook.core.finder.base.data.BaseRulesData
+import com.highcapable.yukihookapi.hook.core.finder.base.rules.ModifierRules
+import com.highcapable.yukihookapi.hook.core.finder.members.data.ConstructorRulesData
+import com.highcapable.yukihookapi.hook.core.finder.members.data.FieldRulesData
+import com.highcapable.yukihookapi.hook.core.finder.members.data.MemberRulesData
+import com.highcapable.yukihookapi.hook.core.finder.members.data.MethodRulesData
+import com.highcapable.yukihookapi.hook.core.finder.type.factory.NameConditions
+import java.lang.reflect.Constructor
+import java.lang.reflect.Field
+import java.lang.reflect.Member
+import java.lang.reflect.Method
+
+/**
+ * [Class] 规则查询数据类
+ * @param fromPackages 指定包名范围名称数组
+ * @param fullName 完整名称
+ * @param simpleName 简单名称
+ * @param singleName 独立名称
+ * @param fullNameConditions 完整名称规则
+ * @param simpleNameConditions 简单名称规则
+ * @param singleNameConditions 独立名称规则
+ * @param isAnonymousClass 匿名类
+ * @param isNoExtendsClass 无继承的父类
+ * @param isNoImplementsClass 无继承的实现的接口类
+ * @param extendsClass 继承的父类名称数组
+ * @param implementsClass 实现的接口类名称数组
+ * @param enclosingClass 包含的封闭类 (主类) 名称数组
+ * @param memberRules [Member] 查询条件数据数组
+ * @param fieldRules [Field] 查询条件数据数组
+ * @param methodRules [Method] 查询条件数据数组
+ * @param constroctorRules [Constructor] 查询条件数据数组
+ */
+@PublishedApi
+internal class ClassRulesData internal constructor(
+ var fromPackages: ArrayList = arrayListOf(),
+ var fullName: NameRulesData? = null,
+ var simpleName: NameRulesData? = null,
+ var singleName: NameRulesData? = null,
+ var fullNameConditions: NameConditions? = null,
+ var simpleNameConditions: NameConditions? = null,
+ var singleNameConditions: NameConditions? = null,
+ var isAnonymousClass: Boolean? = null,
+ var isNoExtendsClass: Boolean? = null,
+ var isNoImplementsClass: Boolean? = null,
+ var extendsClass: ArrayList = arrayListOf(),
+ var implementsClass: ArrayList = arrayListOf(),
+ var enclosingClass: ArrayList = arrayListOf(),
+ var memberRules: ArrayList = arrayListOf(),
+ var fieldRules: ArrayList = arrayListOf(),
+ var methodRules: ArrayList = arrayListOf(),
+ var constroctorRules: ArrayList = arrayListOf()
+) : BaseRulesData() {
+
+ /**
+ * 创建类名匹配条件查询数据类
+ * @param name 包名
+ * @return [NameRulesData]
+ */
+ internal fun createNameRulesData(name: String) = NameRulesData(name)
+
+ /**
+ * 创建包名范围名称过滤匹配条件查询数据类
+ * @param name 包名
+ * @return [PackageRulesData]
+ */
+ internal fun createPackageRulesData(name: String) = PackageRulesData(name)
+
+ /**
+ * 获取 [Class.getSimpleName] 与 [Class.getName] 的独立名称
+ * @param instance 当前 [Class] 实例
+ * @return [String]
+ */
+ internal fun classSingleName(instance: Class<*>) = instance.simpleName.takeIf { it.isNotBlank() }
+ ?: instance.enclosingClass?.let { it.simpleName + instance.name.replace(it.name, newValue = "") } ?: ""
+
+ /**
+ * 类名匹配条件查询数据类
+ * @param name 包名
+ * @param isOptional 是否可选 - 默认否
+ */
+ inner class NameRulesData internal constructor(var name: String, var isOptional: Boolean = false) {
+
+ /** [Class.getName] */
+ internal val TYPE_NAME = 0
+
+ /** [Class.getSimpleName] */
+ internal val TYPE_SIMPLE_NAME = 1
+
+ /** [Class.getSimpleName] or [Class.getName] */
+ internal val TYPE_SINGLE_NAME = 2
+
+ /**
+ * 匹配当前 [Class] 实例
+ * @param instance 当前 [Class] 实例
+ * @param type 判断类型
+ * @return [Boolean]
+ */
+ internal fun equals(instance: Class<*>, type: Int) = when (type) {
+ TYPE_NAME -> instance.name == name
+ TYPE_SIMPLE_NAME -> instance.simpleName == name
+ TYPE_SINGLE_NAME -> classSingleName(instance) == name
+ else -> false
+ }
+
+ override fun toString() = "$name optional($isOptional)"
+ }
+
+ /**
+ * 包名范围名称过滤匹配条件查询数据类
+ * @param name 包名
+ * @param isAbsolute 是否绝对匹配 - 默认否
+ */
+ inner class PackageRulesData internal constructor(var name: String, var isAbsolute: Boolean = false) {
+ override fun toString() = "$name absolute($isAbsolute)"
+ }
+
+ override val templates
+ get() = arrayOf(
+ fromPackages.takeIf { it.isNotEmpty() }?.let { "from:$it" } ?: "",
+ fullName?.let { "fullName:[$it]" } ?: "",
+ simpleName?.let { "simpleName:[$it]" } ?: "",
+ singleName?.let { "singleName:[$it]" } ?: "",
+ fullNameConditions?.let { "fullNameConditions:[existed]" } ?: "",
+ simpleNameConditions?.let { "simpleNameConditions:[existed]" } ?: "",
+ singleNameConditions?.let { "singleNameConditions:[existed]" } ?: "",
+ modifiers?.let { "modifiers:${ModifierRules.templates(uniqueValue)}" } ?: "",
+ isAnonymousClass?.let { "isAnonymousClass:[$it]" } ?: "",
+ isNoExtendsClass?.let { "isNoExtendsClass:[$it]" } ?: "",
+ isNoImplementsClass?.let { "isNoImplementsClass:[$it]" } ?: "",
+ extendsClass.takeIf { it.isNotEmpty() }?.let { "extendsClass:$it" } ?: "",
+ implementsClass.takeIf { it.isNotEmpty() }?.let { "implementsClass:$it" } ?: "",
+ enclosingClass.takeIf { it.isNotEmpty() }?.let { "enclosingClass:$it" } ?: "",
+ memberRules.takeIf { it.isNotEmpty() }?.let { "memberRules:[${it.size} existed]" } ?: "",
+ fieldRules.takeIf { it.isNotEmpty() }?.let { "fieldRules:[${it.size} existed]" } ?: "",
+ methodRules.takeIf { it.isNotEmpty() }?.let { "methodRules:[${it.size} existed]" } ?: "",
+ constroctorRules.takeIf { it.isNotEmpty() }?.let { "constroctorRules:[${it.size} existed]" } ?: ""
+ )
+
+ override val objectName get() = "Class"
+
+ override val isInitialize
+ get() = super.isInitialize || fromPackages.isNotEmpty() || fullName != null || simpleName != null || singleName != null ||
+ fullNameConditions != null || simpleNameConditions != null || singleNameConditions != null || isAnonymousClass != null ||
+ isNoExtendsClass != null || isNoImplementsClass != null || extendsClass.isNotEmpty() || enclosingClass.isNotEmpty() ||
+ memberRules.isNotEmpty() || fieldRules.isNotEmpty() || methodRules.isNotEmpty() || constroctorRules.isNotEmpty()
+
+ override fun hashCode(other: Any?) = super.hashCode(other) + toString().hashCode()
+
+ override fun toString() = "[$fromPackages][$fullName][$simpleName][$singleName][$fullNameConditions][$simpleNameConditions]" +
+ "[$singleNameConditions][$modifiers][$isAnonymousClass][$isNoExtendsClass][$isNoImplementsClass][$extendsClass][$implementsClass]" +
+ "[$enclosingClass][$memberRules][$fieldRules][$methodRules][$constroctorRules]"
+}
\ No newline at end of file
diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/classes/rules/ConstructorRules.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/classes/rules/ConstructorRules.kt
new file mode 100644
index 00000000..6812e7e9
--- /dev/null
+++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/classes/rules/ConstructorRules.kt
@@ -0,0 +1,145 @@
+/*
+ * YukiHookAPI - An efficient Kotlin version of the Xposed Hook API.
+ * Copyright (C) 2019-2022 HighCapable
+ * https://github.com/fankes/YukiHookAPI
+ *
+ * MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * This file is Created by fankes on 2022/9/12.
+ */
+@file:Suppress("MemberVisibilityCanBePrivate")
+
+package com.highcapable.yukihookapi.hook.core.finder.classes.rules
+
+import com.highcapable.yukihookapi.hook.bean.VariousClass
+import com.highcapable.yukihookapi.hook.core.finder.classes.rules.base.BaseRules
+import com.highcapable.yukihookapi.hook.core.finder.classes.rules.result.MemberRulesResult
+import com.highcapable.yukihookapi.hook.core.finder.members.data.ConstructorRulesData
+import com.highcapable.yukihookapi.hook.core.finder.type.factory.CountConditions
+import com.highcapable.yukihookapi.hook.core.finder.type.factory.ModifierConditions
+import com.highcapable.yukihookapi.hook.type.defined.UndefinedType
+import com.highcapable.yukihookapi.hook.type.defined.VagueType
+import java.lang.reflect.Constructor
+
+/**
+ * [Constructor] 查询条件实现类
+ * @param rulesData 当前查询条件规则数据
+ */
+class ConstructorRules internal constructor(@PublishedApi internal val rulesData: ConstructorRulesData) : BaseRules() {
+
+ /**
+ * 设置 [Constructor] 参数个数
+ *
+ * 你可以不使用 [param] 指定参数类型而是仅使用此变量指定参数个数
+ *
+ * 若参数个数小于零则忽略并使用 [param]
+ * @return [Int]
+ */
+ var paramCount
+ get() = rulesData.paramCount
+ set(value) {
+ rulesData.paramCount = value
+ }
+
+ /**
+ * 设置 [Constructor] 标识符筛选条件
+ *
+ * - 可不设置筛选条件
+ * @param conditions 条件方法体
+ */
+ fun modifiers(conditions: ModifierConditions) {
+ rulesData.modifiers = conditions
+ }
+
+ /** 设置 [Constructor] 空参数、无参数 */
+ fun emptyParam() {
+ rulesData.paramCount = 0
+ }
+
+ /**
+ * 设置 [Constructor] 参数
+ *
+ * 如果同时使用了 [paramCount] 则 [paramType] 的数量必须与 [paramCount] 完全匹配
+ *
+ * 如果 [Constructor] 中存在一些无意义又很长的类型 - 你可以使用 [VagueType] 来替代它
+ *
+ * 例如下面这个参数结构 ↓
+ *
+ * ```java
+ * Foo(String var1, boolean var2, com.demo.Test var3, int var4)
+ * ```
+ *
+ * 此时就可以简单地写作 ↓
+ *
+ * ```kotlin
+ * param(StringType, BooleanType, VagueType, IntType)
+ * ```
+ *
+ * - ❗无参 [Constructor] 请使用 [emptyParam] 设置查询条件
+ *
+ * - ❗有参 [Constructor] 必须使用此方法设定参数或使用 [paramCount] 指定个数
+ * @param paramType 参数类型数组 - ❗只能是 [Class]、[String]、[VariousClass]
+ */
+ fun param(vararg paramType: Any) {
+ if (paramType.isEmpty()) error("paramTypes is empty, please use emptyParam() instead")
+ rulesData.paramTypes =
+ arrayListOf>().apply { paramType.forEach { add(it.compat(tag = "Constructor") ?: UndefinedType) } }.toTypedArray()
+ }
+
+ /**
+ * 设置 [Constructor] 参数个数范围
+ *
+ * 你可以不使用 [param] 指定参数类型而是仅使用此方法指定参数个数范围
+ *
+ * 使用示例如下 ↓
+ *
+ * ```kotlin
+ * paramCount(1..5)
+ * ```
+ * @param numRange 个数范围
+ */
+ fun paramCount(numRange: IntRange) {
+ rulesData.paramCountRange = numRange
+ }
+
+ /**
+ * 设置 [Constructor] 参数个数条件
+ *
+ * 你可以不使用 [param] 指定参数类型而是仅使用此方法指定参数个数条件
+ *
+ * 使用示例如下 ↓
+ *
+ * ```kotlin
+ * paramCount { it >= 5 || it.isZero() }
+ * ```
+ * @param conditions 条件方法体
+ */
+ fun paramCount(conditions: CountConditions) {
+ rulesData.paramCountConditions = conditions
+ }
+
+ /**
+ * 返回结果实现类
+ * @return [MemberRulesResult]
+ */
+ @PublishedApi
+ internal fun build() = MemberRulesResult(rulesData)
+}
\ No newline at end of file
diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/classes/rules/FieldRules.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/classes/rules/FieldRules.kt
new file mode 100644
index 00000000..4c570eb3
--- /dev/null
+++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/classes/rules/FieldRules.kt
@@ -0,0 +1,92 @@
+/*
+ * YukiHookAPI - An efficient Kotlin version of the Xposed Hook API.
+ * Copyright (C) 2019-2022 HighCapable
+ * https://github.com/fankes/YukiHookAPI
+ *
+ * MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * This file is Created by fankes on 2022/9/12.
+ */
+package com.highcapable.yukihookapi.hook.core.finder.classes.rules
+
+import com.highcapable.yukihookapi.hook.bean.VariousClass
+import com.highcapable.yukihookapi.hook.core.finder.classes.rules.base.BaseRules
+import com.highcapable.yukihookapi.hook.core.finder.classes.rules.result.MemberRulesResult
+import com.highcapable.yukihookapi.hook.core.finder.members.data.FieldRulesData
+import com.highcapable.yukihookapi.hook.core.finder.type.factory.ModifierConditions
+import com.highcapable.yukihookapi.hook.core.finder.type.factory.NameConditions
+import java.lang.reflect.Field
+
+/**
+ * [Field] 查询条件实现类
+ * @param rulesData 当前查询条件规则数据
+ */
+class FieldRules internal constructor(@PublishedApi internal val rulesData: FieldRulesData) : BaseRules() {
+
+ /**
+ * 设置 [Field] 名称
+ * @return [String]
+ */
+ var name
+ get() = rulesData.name
+ set(value) {
+ rulesData.name = value
+ }
+
+ /**
+ * 设置 [Field] 类型
+ *
+ * - ❗只能是 [Class]、[String]、[VariousClass]
+ *
+ * - 可不填写类型
+ * @return [Any] or null
+ */
+ var type
+ get() = rulesData.type
+ set(value) {
+ rulesData.type = value?.compat(tag = "Field")
+ }
+
+ /**
+ * 设置 [Field] 标识符筛选条件
+ *
+ * - 可不设置筛选条件
+ * @param conditions 条件方法体
+ */
+ fun modifiers(conditions: ModifierConditions) {
+ rulesData.modifiers = conditions
+ }
+
+ /**
+ * 设置 [Field] 名称条件
+ * @param conditions 条件方法体
+ */
+ fun name(conditions: NameConditions) {
+ rulesData.nameConditions = conditions
+ }
+
+ /**
+ * 返回结果实现类
+ * @return [MemberRulesResult]
+ */
+ @PublishedApi
+ internal fun build() = MemberRulesResult(rulesData)
+}
\ No newline at end of file
diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MemberRules.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MemberRules.kt
new file mode 100644
index 00000000..ef5e82a4
--- /dev/null
+++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MemberRules.kt
@@ -0,0 +1,58 @@
+/*
+ * YukiHookAPI - An efficient Kotlin version of the Xposed Hook API.
+ * Copyright (C) 2019-2022 HighCapable
+ * https://github.com/fankes/YukiHookAPI
+ *
+ * MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * This file is Created by fankes on 2022/9/12.
+ */
+package com.highcapable.yukihookapi.hook.core.finder.classes.rules
+
+import com.highcapable.yukihookapi.hook.core.finder.classes.rules.base.BaseRules
+import com.highcapable.yukihookapi.hook.core.finder.classes.rules.result.MemberRulesResult
+import com.highcapable.yukihookapi.hook.core.finder.members.data.MemberRulesData
+import com.highcapable.yukihookapi.hook.core.finder.type.factory.ModifierConditions
+import java.lang.reflect.Member
+
+/**
+ * [Member] 查询条件实现类
+ * @param rulesData 当前查询条件规则数据
+ */
+class MemberRules internal constructor(@PublishedApi internal val rulesData: MemberRulesData) : BaseRules() {
+
+ /**
+ * 设置 [Member] 标识符筛选条件
+ *
+ * - 可不设置筛选条件
+ * @param conditions 条件方法体
+ */
+ fun modifiers(conditions: ModifierConditions) {
+ rulesData.modifiers = conditions
+ }
+
+ /**
+ * 返回结果实现类
+ * @return [MemberRulesResult]
+ */
+ @PublishedApi
+ internal fun build() = MemberRulesResult(rulesData)
+}
\ No newline at end of file
diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MethodRules.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MethodRules.kt
new file mode 100644
index 00000000..7c32ebd3
--- /dev/null
+++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MethodRules.kt
@@ -0,0 +1,178 @@
+/*
+ * YukiHookAPI - An efficient Kotlin version of the Xposed Hook API.
+ * Copyright (C) 2019-2022 HighCapable
+ * https://github.com/fankes/YukiHookAPI
+ *
+ * MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * This file is Created by fankes on 2022/9/12.
+ */
+@file:Suppress("unused", "MemberVisibilityCanBePrivate")
+
+package com.highcapable.yukihookapi.hook.core.finder.classes.rules
+
+import com.highcapable.yukihookapi.hook.bean.VariousClass
+import com.highcapable.yukihookapi.hook.core.finder.classes.rules.base.BaseRules
+import com.highcapable.yukihookapi.hook.core.finder.classes.rules.result.MemberRulesResult
+import com.highcapable.yukihookapi.hook.core.finder.members.data.MethodRulesData
+import com.highcapable.yukihookapi.hook.core.finder.type.factory.CountConditions
+import com.highcapable.yukihookapi.hook.core.finder.type.factory.ModifierConditions
+import com.highcapable.yukihookapi.hook.core.finder.type.factory.NameConditions
+import com.highcapable.yukihookapi.hook.type.defined.UndefinedType
+import com.highcapable.yukihookapi.hook.type.defined.VagueType
+import java.lang.reflect.Method
+
+/**
+ * [Method] 查询条件实现类
+ * @param rulesData 当前查询条件规则数据
+ */
+class MethodRules internal constructor(@PublishedApi internal val rulesData: MethodRulesData) : BaseRules() {
+
+ /**
+ * 设置 [Method] 名称
+ * @return [String]
+ */
+ var name
+ get() = rulesData.name
+ set(value) {
+ rulesData.name = value
+ }
+
+ /**
+ * 设置 [Method] 参数个数
+ *
+ * 你可以不使用 [param] 指定参数类型而是仅使用此变量指定参数个数
+ *
+ * 若参数个数小于零则忽略并使用 [param]
+ * @return [Int]
+ */
+ var paramCount
+ get() = rulesData.paramCount
+ set(value) {
+ rulesData.paramCount = value
+ }
+
+ /**
+ * 设置 [Method] 返回值
+ *
+ * - ❗只能是 [Class]、[String]、[VariousClass]
+ *
+ * - 可不填写返回值
+ * @return [Any] or null
+ */
+ var returnType
+ get() = rulesData.returnType
+ set(value) {
+ rulesData.returnType = value.compat(tag = "Method")
+ }
+
+ /**
+ * 设置 [Method] 标识符筛选条件
+ *
+ * - 可不设置筛选条件
+ * @param conditions 条件方法体
+ */
+ fun modifiers(conditions: ModifierConditions) {
+ rulesData.modifiers = conditions
+ }
+
+ /** 设置 [Method] 空参数、无参数 */
+ fun emptyParam() {
+ rulesData.paramCount = 0
+ }
+
+ /**
+ * 设置 [Method] 参数
+ *
+ * 如果同时使用了 [paramCount] 则 [paramType] 的数量必须与 [paramCount] 完全匹配
+ *
+ * 如果 [Method] 中存在一些无意义又很长的类型 - 你可以使用 [VagueType] 来替代它
+ *
+ * 例如下面这个参数结构 ↓
+ *
+ * ```java
+ * void foo(String var1, boolean var2, com.demo.Test var3, int var4)
+ * ```
+ *
+ * 此时就可以简单地写作 ↓
+ *
+ * ```kotlin
+ * param(StringType, BooleanType, VagueType, IntType)
+ * ```
+ *
+ * - ❗无参 [Method] 请使用 [emptyParam] 设置查询条件
+ *
+ * - ❗有参 [Method] 必须使用此方法设定参数或使用 [paramCount] 指定个数
+ * @param paramType 参数类型数组 - ❗只能是 [Class]、[String]、[VariousClass]
+ */
+ fun param(vararg paramType: Any) {
+ if (paramType.isEmpty()) error("paramTypes is empty, please use emptyParam() instead")
+ rulesData.paramTypes =
+ arrayListOf>().apply { paramType.forEach { add(it.compat(tag = "Method") ?: UndefinedType) } }.toTypedArray()
+ }
+
+ /**
+ * 设置 [Method] 名称条件
+ * @param conditions 条件方法体
+ */
+ fun name(conditions: NameConditions) {
+ rulesData.nameConditions = conditions
+ }
+
+ /**
+ * 设置 [Method] 参数个数范围
+ *
+ * 你可以不使用 [param] 指定参数类型而是仅使用此方法指定参数个数范围
+ *
+ * 使用示例如下 ↓
+ *
+ * ```kotlin
+ * paramCount(1..5)
+ * ```
+ * @param numRange 个数范围
+ */
+ fun paramCount(numRange: IntRange) {
+ rulesData.paramCountRange = numRange
+ }
+
+ /**
+ * 设置 [Method] 参数个数条件
+ *
+ * 你可以不使用 [param] 指定参数类型而是仅使用此方法指定参数个数条件
+ *
+ * 使用示例如下 ↓
+ *
+ * ```kotlin
+ * paramCount { it >= 5 || it.isZero() }
+ * ```
+ * @param conditions 条件方法体
+ */
+ fun paramCount(conditions: CountConditions) {
+ rulesData.paramCountConditions = conditions
+ }
+
+ /**
+ * 返回结果实现类
+ * @return [MemberRulesResult]
+ */
+ @PublishedApi
+ internal fun build() = MemberRulesResult(rulesData)
+}
\ No newline at end of file
diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/classes/rules/base/BaseRules.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/classes/rules/base/BaseRules.kt
new file mode 100644
index 00000000..66561a70
--- /dev/null
+++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/classes/rules/base/BaseRules.kt
@@ -0,0 +1,90 @@
+/*
+ * YukiHookAPI - An efficient Kotlin version of the Xposed Hook API.
+ * Copyright (C) 2019-2022 HighCapable
+ * https://github.com/fankes/YukiHookAPI
+ *
+ * MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * This file is Created by fankes on 2022/9/12.
+ */
+package com.highcapable.yukihookapi.hook.core.finder.classes.rules.base
+
+import com.highcapable.yukihookapi.hook.core.finder.classes.DexClassFinder
+import com.highcapable.yukihookapi.hook.core.finder.classes.rules.ConstructorRules
+import com.highcapable.yukihookapi.hook.core.finder.classes.rules.FieldRules
+import com.highcapable.yukihookapi.hook.core.finder.classes.rules.MemberRules
+import com.highcapable.yukihookapi.hook.core.finder.classes.rules.MethodRules
+import com.highcapable.yukihookapi.hook.core.finder.members.data.ConstructorRulesData
+import com.highcapable.yukihookapi.hook.core.finder.members.data.FieldRulesData
+import com.highcapable.yukihookapi.hook.core.finder.members.data.MemberRulesData
+import com.highcapable.yukihookapi.hook.core.finder.members.data.MethodRulesData
+import java.lang.reflect.Member
+
+/**
+ * [Member] 查询条件实现父类
+ * @param instance 当前查找类实例
+ */
+open class BaseRules internal constructor(internal var instance: DexClassFinder? = null) {
+
+ @PublishedApi
+ internal companion object {
+
+ /**
+ * 创建查询条件规则数据
+ * @param instance 当前查找类实例
+ * @return [MemberRulesData]
+ */
+ @PublishedApi
+ internal fun createMemberRules(instance: DexClassFinder) =
+ MemberRules(MemberRulesData().apply { instance.rulesData.memberRules.add(this) }).apply { this.instance = instance }
+
+ /**
+ * 创建查询条件规则数据
+ * @return [FieldRulesData]
+ */
+ @PublishedApi
+ internal fun createFieldRules(instance: DexClassFinder) =
+ FieldRules(FieldRulesData().apply { instance.rulesData.fieldRules.add(this) }).apply { this.instance = instance }
+
+ /**
+ * 创建查询条件规则数据
+ * @return [MethodRulesData]
+ */
+ @PublishedApi
+ internal fun createMethodRules(instance: DexClassFinder) =
+ MethodRules(MethodRulesData().apply { instance.rulesData.methodRules.add(this) }).apply { this.instance = instance }
+
+ /**
+ * 创建查询条件规则数据
+ * @return [ConstructorRulesData]
+ */
+ @PublishedApi
+ internal fun createConstructorRules(instance: DexClassFinder) =
+ ConstructorRules(ConstructorRulesData().apply { instance.rulesData.constroctorRules.add(this) }).apply { this.instance = instance }
+ }
+
+ /**
+ * 将目标类型转换为可识别的兼容类型
+ * @param tag 当前查找类的标识
+ * @return [Class] or null
+ */
+ internal fun Any?.compat(tag: String) = instance?.compatType(any = this, tag)
+}
\ No newline at end of file
diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/classes/rules/result/MemberRulesResult.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/classes/rules/result/MemberRulesResult.kt
new file mode 100644
index 00000000..d8539299
--- /dev/null
+++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/classes/rules/result/MemberRulesResult.kt
@@ -0,0 +1,89 @@
+/*
+ * YukiHookAPI - An efficient Kotlin version of the Xposed Hook API.
+ * Copyright (C) 2019-2022 HighCapable
+ * https://github.com/fankes/YukiHookAPI
+ *
+ * MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * This file is Created by fankes on 2022/9/12.
+ */
+@file:Suppress("unused", "MemberVisibilityCanBePrivate")
+
+package com.highcapable.yukihookapi.hook.core.finder.classes.rules.result
+
+import com.highcapable.yukihookapi.hook.core.finder.members.data.MemberRulesData
+import com.highcapable.yukihookapi.hook.core.finder.type.factory.CountConditions
+import java.lang.reflect.Member
+
+/**
+ * 当前 [Member] 查询条件结果实现类
+ * @param rulesData 当前查询条件规则数据
+ */
+class MemberRulesResult internal constructor(private val rulesData: MemberRulesData) {
+
+ /**
+ * 设置当前 [Member] 在查询条件中个数为 0
+ * @return [MemberRulesResult] 可继续向下监听
+ */
+ fun none() = count(num = 0)
+
+ /**
+ * 设置当前 [Member] 在查询条件中需要全部匹配的个数
+ * @param num 个数
+ * @return [MemberRulesResult] 可继续向下监听
+ */
+ fun count(num: Int): MemberRulesResult {
+ rulesData.matchCount = num
+ return this
+ }
+
+ /**
+ * 设置当前 [Member] 在查询条件中需要全部匹配的个数范围
+ *
+ * 使用示例如下 ↓
+ *
+ * ```kotlin
+ * count(1..5)
+ * ```
+ * @param numRange 个数范围
+ * @return [MemberRulesResult] 可继续向下监听
+ */
+ fun count(numRange: IntRange): MemberRulesResult {
+ rulesData.matchCountRange = numRange
+ return this
+ }
+
+ /**
+ * 设置当前 [Member] 在查询条件中需要全部匹配的个数条件
+ *
+ * 使用示例如下 ↓
+ *
+ * ```kotlin
+ * count { it >= 5 || it.isZero() }
+ * ```
+ * @param conditions 条件方法体
+ * @return [MemberRulesResult] 可继续向下监听
+ */
+ fun count(conditions: CountConditions): MemberRulesResult {
+ rulesData.matchCountConditions = conditions
+ return this
+ }
+}
\ No newline at end of file
diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/tools/ReflectionTool.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/tools/ReflectionTool.kt
index ef3bde14..a61fc566 100644
--- a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/tools/ReflectionTool.kt
+++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/tools/ReflectionTool.kt
@@ -30,28 +30,34 @@
package com.highcapable.yukihookapi.hook.core.finder.tools
import com.highcapable.yukihookapi.hook.core.finder.base.data.BaseRulesData
+import com.highcapable.yukihookapi.hook.core.finder.base.rules.CountRules
+import com.highcapable.yukihookapi.hook.core.finder.classes.data.ClassRulesData
import com.highcapable.yukihookapi.hook.core.finder.members.data.ConstructorRulesData
import com.highcapable.yukihookapi.hook.core.finder.members.data.FieldRulesData
import com.highcapable.yukihookapi.hook.core.finder.members.data.MemberRulesData
import com.highcapable.yukihookapi.hook.core.finder.members.data.MethodRulesData
-import com.highcapable.yukihookapi.hook.factory.hasExtends
+import com.highcapable.yukihookapi.hook.factory.*
import com.highcapable.yukihookapi.hook.log.yLoggerW
import com.highcapable.yukihookapi.hook.store.ReflectsCacheStore
import com.highcapable.yukihookapi.hook.type.defined.UndefinedType
import com.highcapable.yukihookapi.hook.type.defined.VagueType
+import com.highcapable.yukihookapi.hook.type.java.DalvikBaseDexClassLoader
import com.highcapable.yukihookapi.hook.type.java.NoClassDefFoundErrorClass
import com.highcapable.yukihookapi.hook.type.java.NoSuchFieldErrorClass
import com.highcapable.yukihookapi.hook.type.java.NoSuchMethodErrorClass
import com.highcapable.yukihookapi.hook.utils.conditions
import com.highcapable.yukihookapi.hook.utils.let
import com.highcapable.yukihookapi.hook.utils.takeIf
+import com.highcapable.yukihookapi.hook.utils.value
import com.highcapable.yukihookapi.hook.xposed.bridge.YukiHookBridge
import com.highcapable.yukihookapi.hook.xposed.bridge.factory.YukiHookHelper
import com.highcapable.yukihookapi.hook.xposed.parasitic.AppParasitics
+import dalvik.system.BaseDexClassLoader
import java.lang.reflect.Constructor
import java.lang.reflect.Field
import java.lang.reflect.Member
import java.lang.reflect.Method
+import java.util.*
import kotlin.math.abs
/**
@@ -62,6 +68,23 @@ internal object ReflectionTool {
/** 当前工具类的标签 */
private const val TAG = "YukiHookAPI#ReflectionTool"
+ /**
+ * 写出当前 [ClassLoader] 下所有 [Class] 名称数组
+ * @param loader 当前使用的 [ClassLoader]
+ * @return [List]<[String]>
+ * @throws IllegalStateException 如果 [loader] 不是 [BaseDexClassLoader]
+ */
+ private fun findDexClassList(loader: ClassLoader?) = ReflectsCacheStore.findDexClassList(loader.hashCode())
+ ?: DalvikBaseDexClassLoader.field { name = "pathList" }.ignored().get(loader.value().let {
+ while (it.value !is BaseDexClassLoader) {
+ if (it.value?.parent != null) it.value = it.value?.parent
+ else error("ClassLoader [$loader] is not a DexClassLoader")
+ }; it.value ?: error("ClassLoader [$loader] load failed")
+ }).current(ignored = true)?.field { name = "dexElements" }?.array()?.flatMap { element ->
+ element.current(ignored = true).field { name = "dexFile" }.current(ignored = true)
+ ?.method { name = "entries" }?.invoke>()?.toList().orEmpty()
+ }.orEmpty().also { if (it.isNotEmpty()) ReflectsCacheStore.putDexClassList(loader.hashCode(), it) }
+
/**
* 使用字符串类名查询 [Class] 是否存在
* @param name [Class] 完整名称
@@ -89,6 +112,140 @@ internal object ReflectionTool {
}.getOrNull() ?: throw createException(loader ?: AppParasitics.baseClassLoader, name = "Class", "name:[$name]")
}
+ /**
+ * 查找任意 [Class] 或一组 [Class]
+ * @param loaderSet 类所在 [ClassLoader]
+ * @param rulesData 规则查询数据
+ * @return [HashSet]<[Class]>
+ * @throws IllegalStateException 如果 [loaderSet] 为 null 或未设置任何条件
+ * @throws NoClassDefFoundError 如果找不到 [Class]
+ */
+ internal fun findClasses(loaderSet: ClassLoader?, rulesData: ClassRulesData) = rulesData.createResult {
+ ReflectsCacheStore.findClasses(hashCode(loaderSet)) ?: hashSetOf>().also { classes ->
+ /**
+ * 开始查询作业
+ * @param instance 当前 [Class] 实例
+ */
+ fun startProcess(instance: Class<*>) {
+ conditions {
+ fromPackages.takeIf { it.isNotEmpty() }?.also { and(true) }
+ fullName?.also { it.equals(instance, it.TYPE_NAME).also { e -> if (it.isOptional) opt(e) else and(e) } }
+ simpleName?.also { it.equals(instance, it.TYPE_SIMPLE_NAME).also { e -> if (it.isOptional) opt(e) else and(e) } }
+ singleName?.also { it.equals(instance, it.TYPE_SINGLE_NAME).also { e -> if (it.isOptional) opt(e) else and(e) } }
+ fullNameConditions?.also { instance.name.also { n -> and(it(n.cast(), n)) } }
+ simpleNameConditions?.also { instance.simpleName.also { n -> and(it(n.cast(), n)) } }
+ singleNameConditions?.also { classSingleName(instance).also { n -> and(it(n.cast(), n)) } }
+ modifiers?.also { and(it(instance.cast())) }
+ extendsClass.takeIf { it.isNotEmpty() }?.also { and(instance.hasExtends && it.contains(instance.superclass.name)) }
+ implementsClass.takeIf { it.isNotEmpty() }
+ ?.also { and(instance.interfaces.isNotEmpty() && instance.interfaces.any { e -> it.contains(e.name) }) }
+ enclosingClass.takeIf { it.isNotEmpty() }
+ ?.also { and(instance.enclosingClass != null && it.contains(instance.enclosingClass.name)) }
+ isAnonymousClass?.also { and(instance.isAnonymousClass && it) }
+ isNoExtendsClass?.also { and(instance.hasExtends.not() && it) }
+ isNoImplementsClass?.also { and(instance.interfaces.isEmpty() && it) }
+ /**
+ * 匹配 [MemberRulesData]
+ * @param size [Member] 个数
+ * @param result 回调是否匹配
+ */
+ fun MemberRulesData.matchCount(size: Int, result: (Boolean) -> Unit) {
+ takeIf { it.isInitializeOfMatch }?.also { rule ->
+ rule.conditions {
+ value.matchCount.takeIf { it >= 0 }?.also { and(it == size) }
+ value.matchCountRange.takeIf { it.isEmpty().not() }?.also { and(size in it) }
+ value.matchCountConditions?.also { and(it(CountRules.with(size), size)) }
+ }.finally { result(true) }.without { result(false) }
+ } ?: result(true)
+ }
+
+ /**
+ * 检查类型中的 [Class] 是否存在 - 即不存在 [UndefinedType]
+ * @param type 类型
+ * @return [Boolean]
+ */
+ fun MemberRulesData.exists(vararg type: Any?): Boolean {
+ if (type.isEmpty()) return true
+ for (i in type.indices) if (type[i] == UndefinedType) {
+ yLoggerW(msg = "$objectName type[$i] mistake, it will be ignored in current conditions")
+ return false
+ }
+ return true
+ }
+ memberRules.takeIf { it.isNotEmpty() }?.forEach { rule ->
+ instance.existMembers?.apply {
+ var numberOfFound = 0
+ if (rule.isInitializeOfSuper) forEach { member ->
+ rule.conditions {
+ value.modifiers?.also { and(it(member.cast())) }
+ }.finally { numberOfFound++ }
+ }.run { rule.matchCount(numberOfFound) { and(it && numberOfFound > 0) } }
+ else rule.matchCount(size) { and(it) }
+ }
+ }
+ fieldRules.takeIf { it.isNotEmpty() }?.forEach { rule ->
+ instance.existFields?.apply {
+ var numberOfFound = 0
+ if (rule.isInitialize) forEach { field ->
+ rule.conditions {
+ value.type?.also { value.exists(it) and (it == field.type) }
+ value.name.takeIf { it.isNotBlank() }?.also { and(it == field.name) }
+ value.modifiers?.also { and(it(field.cast())) }
+ value.nameConditions?.also { field.name.also { n -> and(it(n.cast(), n)) } }
+ }.finally { numberOfFound++ }
+ }.run { rule.matchCount(numberOfFound) { and(it && numberOfFound > 0) } }
+ else rule.matchCount(size) { and(it) }
+ }
+ }
+ methodRules.takeIf { it.isNotEmpty() }?.forEach { rule ->
+ instance.existMethods?.apply {
+ var numberOfFound = 0
+ if (rule.isInitialize) forEach { method ->
+ rule.conditions {
+ value.name.takeIf { it.isNotBlank() }?.also { and(it == method.name) }
+ value.returnType?.also { value.exists(it) and (it == method.returnType) }
+ value.paramCount.takeIf { it >= 0 }?.also { and(method.parameterTypes.size == it) }
+ value.paramCountRange.takeIf { it.isEmpty().not() }?.also { and(method.parameterTypes.size in it) }
+ value.paramCountConditions?.also { method.parameterTypes.size.also { s -> and(it(s.cast(), s)) } }
+ value.paramTypes?.also { value.exists(*it) and (paramTypesEq(it, method.parameterTypes)) }
+ value.modifiers?.also { and(it(method.cast())) }
+ value.nameConditions?.also { method.name.also { n -> and(it(n.cast(), n)) } }
+ }.finally { numberOfFound++ }
+ }.run { rule.matchCount(numberOfFound) { and(it && numberOfFound > 0) } }
+ else rule.matchCount(size) { and(it) }
+ }
+ }
+ constroctorRules.takeIf { it.isNotEmpty() }?.forEach { rule ->
+ instance.existConstructors?.apply {
+ var numberOfFound = 0
+ if (rule.isInitialize) forEach { constructor ->
+ rule.conditions {
+ value.paramCount.takeIf { it >= 0 }?.also { and(constructor.parameterTypes.size == it) }
+ value.paramCountRange.takeIf { it.isEmpty().not() }?.also { and(constructor.parameterTypes.size in it) }
+ value.paramCountConditions?.also { constructor.parameterTypes.size.also { s -> and(it(s.cast(), s)) } }
+ value.paramTypes?.also { value.exists(*it) and (paramTypesEq(it, constructor.parameterTypes)) }
+ value.modifiers?.also { and(it(constructor.cast())) }
+ }.finally { numberOfFound++ }
+ }.run { rule.matchCount(numberOfFound) { and(it && numberOfFound > 0) } }
+ else rule.matchCount(size) { and(it) }
+ }
+ }
+ }.finally { classes.add(instance) }
+ }
+ findDexClassList(loaderSet).takeIf { it.isNotEmpty() }?.forEach { className ->
+ /** 分离包名 → com.demo.Test → com.demo (获取最后一个 "." + 简单类名的长度) → 由于末位存在 "." 最后要去掉 1 个长度 */
+ (if (className.contains(other = "."))
+ className.substring(0, className.length - className.split(".").let { it[it.lastIndex] }.length - 1)
+ else className).also { packageName ->
+ if ((fromPackages.isEmpty() || fromPackages.any {
+ if (it.isAbsolute) packageName == it.name else packageName.startsWith(it.name)
+ }) && className.hasClass(loaderSet)
+ ) startProcess(className.toClass(loaderSet))
+ }
+ }
+ }.takeIf { it.isNotEmpty() }?.also { ReflectsCacheStore.putClasses(hashCode(loaderSet), it) } ?: throwNotFoundError(loaderSet)
+ }
+
/**
* 查找任意 [Field] 或一组 [Field]
* @param classSet [Field] 所在类
@@ -333,6 +490,7 @@ internal object ReflectionTool {
is FieldRulesData -> isInitialize.not()
is MethodRulesData -> isInitialize.not()
is ConstructorRulesData -> isInitialize.not()
+ is ClassRulesData -> isInitialize.not()
else -> true
}.takeIf { it }?.also { error("You must set a condition when finding a $objectName") }
return result(this)
@@ -374,6 +532,7 @@ internal object ReflectionTool {
is FieldRulesData -> throw createException(instanceSet, objectName, *templates)
is MethodRulesData -> throw createException(instanceSet, objectName, *templates)
is ConstructorRulesData -> throw createException(instanceSet, objectName, *templates)
+ is ClassRulesData -> throw createException(instanceSet ?: AppParasitics.baseClassLoader, objectName, *templates)
else -> error("Type [$this] not allowed")
}
diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/type/factory/TypeAliasFactory.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/type/factory/TypeAliasFactory.kt
index 6c5f9999..f34b3d73 100644
--- a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/type/factory/TypeAliasFactory.kt
+++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/type/factory/TypeAliasFactory.kt
@@ -30,10 +30,14 @@ package com.highcapable.yukihookapi.hook.core.finder.type.factory
import com.highcapable.yukihookapi.hook.core.finder.base.rules.CountRules
import com.highcapable.yukihookapi.hook.core.finder.base.rules.ModifierRules
import com.highcapable.yukihookapi.hook.core.finder.base.rules.NameRules
+import com.highcapable.yukihookapi.hook.core.finder.classes.DexClassFinder
import com.highcapable.yukihookapi.hook.core.finder.members.ConstructorFinder
import com.highcapable.yukihookapi.hook.core.finder.members.FieldFinder
import com.highcapable.yukihookapi.hook.core.finder.members.MethodFinder
+/** 定义 [DexClassFinder] 方法体类型 */
+internal typealias ClassConditions = DexClassFinder.() -> Unit
+
/** 定义 [FieldFinder] 方法体类型 */
internal typealias FieldConditions = FieldFinder.() -> Unit
diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/factory/ReflectionFactory.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/factory/ReflectionFactory.kt
index b182ee7a..a64ebd7d 100644
--- a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/factory/ReflectionFactory.kt
+++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/factory/ReflectionFactory.kt
@@ -33,14 +33,12 @@ import com.highcapable.yukihookapi.YukiHookAPI
import com.highcapable.yukihookapi.hook.bean.CurrentClass
import com.highcapable.yukihookapi.hook.bean.GenericClass
import com.highcapable.yukihookapi.hook.core.finder.base.rules.ModifierRules
+import com.highcapable.yukihookapi.hook.core.finder.classes.DexClassFinder
import com.highcapable.yukihookapi.hook.core.finder.members.ConstructorFinder
import com.highcapable.yukihookapi.hook.core.finder.members.FieldFinder
import com.highcapable.yukihookapi.hook.core.finder.members.MethodFinder
import com.highcapable.yukihookapi.hook.core.finder.tools.ReflectionTool
-import com.highcapable.yukihookapi.hook.core.finder.type.factory.ConstructorConditions
-import com.highcapable.yukihookapi.hook.core.finder.type.factory.FieldConditions
-import com.highcapable.yukihookapi.hook.core.finder.type.factory.MethodConditions
-import com.highcapable.yukihookapi.hook.core.finder.type.factory.ModifierConditions
+import com.highcapable.yukihookapi.hook.core.finder.type.factory.*
import com.highcapable.yukihookapi.hook.xposed.bridge.status.YukiHookModuleStatus
import com.highcapable.yukihookapi.hook.xposed.parasitic.AppParasitics
import java.lang.reflect.*
@@ -59,6 +57,22 @@ enum class MembersType {
CONSTRUCTOR
}
+/**
+ * 通过当前 [ClassLoader] 按指定条件查找并得到 Dex 中的 [Class]
+ *
+ * - ❗此方法在 [Class] 数量过多及查找条件复杂时会非常耗时
+ *
+ * - ❗建议启用 [async] 或设置 [name] 参数 - [name] 参数将在 Hook APP (宿主) 不同版本中自动进行本地缓存以提升效率
+ *
+ * - ❗此功能尚在试验阶段 - 性能与稳定性可能仍然存在问题 - 使用过程遇到问题请向我们报告并帮助我们改进
+ * @param name 标识当前 [Class] 缓存的名称 - 不设置将不启用缓存 - 启用缓存自动启用 [async]
+ * @param async 是否启用异步 - 默认否
+ * @param initiate 方法体
+ * @return [DexClassFinder.Result]
+ */
+inline fun ClassLoader.searchClass(name: String = "", async: Boolean = false, initiate: ClassConditions) =
+ DexClassFinder(name, async = async || name.isNotBlank(), loaderSet = this).apply(initiate).build()
+
/**
* 监听当前 [ClassLoader] 的 [ClassLoader.loadClass] 方法装载
*
diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/param/PackageParam.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/param/PackageParam.kt
index 7953e01f..8be55a73 100644
--- a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/param/PackageParam.kt
+++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/param/PackageParam.kt
@@ -42,7 +42,9 @@ import com.highcapable.yukihookapi.hook.bean.HookResources
import com.highcapable.yukihookapi.hook.bean.VariousClass
import com.highcapable.yukihookapi.hook.core.YukiMemberHookCreator
import com.highcapable.yukihookapi.hook.core.YukiResourcesHookCreator
+import com.highcapable.yukihookapi.hook.core.finder.classes.DexClassFinder
import com.highcapable.yukihookapi.hook.core.finder.tools.ReflectionTool
+import com.highcapable.yukihookapi.hook.core.finder.type.factory.ClassConditions
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
import com.highcapable.yukihookapi.hook.param.type.HookEntryType
import com.highcapable.yukihookapi.hook.param.wrapper.PackageParamWrapper
@@ -292,6 +294,22 @@ open class PackageParam internal constructor(@PublishedApi internal var wrapper:
*/
fun loadHooker(hooker: YukiBaseHooker) = hooker.assignInstance(packageParam = this)
+ /**
+ * 通过 [appClassLoader] 按指定条件查找并得到当前 Hook APP Dex 中的 [Class]
+ *
+ * - ❗此方法在 [Class] 数量过多及查找条件复杂时会非常耗时
+ *
+ * - ❗建议启用 [async] 或设置 [name] 参数 - [name] 参数将在 Hook APP (宿主) 不同版本中自动进行本地缓存以提升效率
+ *
+ * - ❗此功能尚在试验阶段 - 性能与稳定性可能仍然存在问题 - 使用过程遇到问题请向我们报告并帮助我们改进
+ * @param name 标识当前 [Class] 缓存的名称 - 不设置将不启用缓存 - 启用缓存自动启用 [async]
+ * @param async 是否启用异步 - 默认否
+ * @param initiate 方法体
+ * @return [DexClassFinder.Result]
+ */
+ inline fun searchClass(name: String = "", async: Boolean = false, initiate: ClassConditions) =
+ DexClassFinder(name, async = async || name.isNotBlank(), appClassLoader).apply(initiate).build()
+
/**
* 通过字符串类名转换为当前 Hook APP 的实体类
*
diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/store/ReflectsCacheStore.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/store/ReflectsCacheStore.kt
index 8ef216f9..176ea651 100644
--- a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/store/ReflectsCacheStore.kt
+++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/store/ReflectsCacheStore.kt
@@ -38,13 +38,21 @@ import java.lang.reflect.Method
*
* 为防止 [Class]、[Member] 复用过高造成的系统 GC 问题
*
- * 查询后的 [Class]、[Member] 在 [YukiHookAPI.Configs.isEnableMemberCache] 启用后自动进入缓存
+ * 查找后的 [Class] 自动进入缓存 - 不受任何控制
+ *
+ * 查找后的 [Member] 在 [YukiHookAPI.Configs.isEnableMemberCache] 启用后自动进入缓存
*/
internal object ReflectsCacheStore {
- /** 缓存的 [Class] */
+ /** 缓存的 [Class] 列表 */
+ private val dexClassListData = HashMap>()
+
+ /** 缓存的 [Class] 对象 */
private val classData = HashMap?>()
+ /** 缓存的 [Class] 数组 */
+ private val classesData = HashMap>>()
+
/** 缓存的 [Method] 数组 */
private val methodsData = HashMap>()
@@ -54,6 +62,13 @@ internal object ReflectsCacheStore {
/** 缓存的 [Field] 数组 */
private val fieldsData = HashMap>()
+ /**
+ * 查找缓存中的 [Class] 列表
+ * @param hashCode 标识符
+ * @return [List]<[Class]>
+ */
+ internal fun findDexClassList(hashCode: Int) = dexClassListData[hashCode]
+
/**
* 查找缓存中的 [Class]
* @param hashCode 标识符
@@ -61,6 +76,13 @@ internal object ReflectsCacheStore {
*/
internal fun findClass(hashCode: Int) = classData[hashCode]
+ /**
+ * 查找缓存中的 [Class] 数组
+ * @param hashCode 标识符
+ * @return [HashSet]<[Class]> or null
+ */
+ internal fun findClasses(hashCode: Int) = classesData[hashCode]
+
/**
* 查找缓存中的 [Method] 数组
* @param hashCode 标识符
@@ -82,16 +104,33 @@ internal object ReflectsCacheStore {
*/
internal fun findFields(hashCode: Int) = fieldsData[hashCode]
+ /**
+ * 写入 [Class] 列表到缓存
+ * @param hashCode 标识符
+ * @param instance 实例
+ */
+ internal fun putDexClassList(hashCode: Int, instance: List) {
+ dexClassListData[hashCode] = instance
+ }
+
/**
* 写入 [Class] 到缓存
* @param hashCode 标识符
* @param instance 实例
*/
internal fun putClass(hashCode: Int, instance: Class<*>?) {
- if (YukiHookAPI.Configs.isEnableMemberCache.not()) return
classData[hashCode] = instance
}
+ /**
+ * 写入 [Class] 数组到缓存
+ * @param hashCode 标识符
+ * @param instance 实例
+ */
+ internal fun putClasses(hashCode: Int, instance: HashSet>) {
+ classesData[hashCode] = instance
+ }
+
/**
* 写入 [Method] 数组到缓存
* @param hashCode 标识符