diff --git a/docs-source/src/.vuepress/configs/template.ts b/docs-source/src/.vuepress/configs/template.ts
index 96992ae5..dbf77d05 100644
--- a/docs-source/src/.vuepress/configs/template.ts
+++ b/docs-source/src/.vuepress/configs/template.ts
@@ -38,6 +38,7 @@ const navigationLinks = {
baseApiPath + 'hook/xposed/parasitic/activity/base/ModuleAppActivity',
baseApiPath + 'hook/xposed/parasitic/activity/base/ModuleAppCompatActivity',
baseApiPath + 'hook/xposed/parasitic/context/wrapper/ModuleContextThemeWrapper',
+ baseApiPath + 'hook/xposed/parasitic/reference/ModuleClassLoader',
baseApiPath + 'hook/xposed/bridge/dummy/YukiModuleResources',
baseApiPath + 'hook/xposed/bridge/dummy/YukiResources',
baseApiPath + 'hook/xposed/bridge/dummy/YukiResForwarder',
diff --git a/docs-source/src/en/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/reference/ModuleClassLoader.md b/docs-source/src/en/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/reference/ModuleClassLoader.md
new file mode 100644
index 00000000..8500d322
--- /dev/null
+++ b/docs-source/src/en/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/reference/ModuleClassLoader.md
@@ -0,0 +1,75 @@
+---
+pageClass: code-page
+---
+
+::: warning
+
+The English translation of this page has not been completed, you are welcome to contribute translations to us.
+
+You can use the **Chrome Translation Plugin** to translate entire pages for reference.
+
+:::
+
+# ModuleClassLoader - class
+
+```kotlin:no-line-numbers
+class ModuleClassLoader private constructor() : ClassLoader
+```
+
+**Change Records**
+
+`v1.1.2` `added`
+
+**Function Illustrate**
+
+> 自动处理 (Xposed) 宿主环境与模块环境的 `ClassLoader`。
+
+## companion object - object
+
+**Change Records**
+
+`v1.1.2` `added`
+
+### excludeHostClasses - method
+
+```kotlin:no-line-numbers
+fun excludeHostClasses(vararg name: String)
+```
+
+**Change Records**
+
+`v1.1.2` `added`
+
+**Function Illustrate**
+
+> 添加到 Hook APP (宿主) `Class` 排除列表。
+
+排除列表中的 `Class` 将会使用宿主的 `ClassLoader` 进行装载。
+
+::: danger
+
+排除列表仅会在 (Xposed) 宿主环境生效。
+
+:::
+
+### excludeModuleClasses - method
+
+```kotlin:no-line-numbers
+fun excludeModuleClasses(vararg name: String)
+```
+
+**Change Records**
+
+`v1.1.2` `added`
+
+**Function Illustrate**
+
+> 添加到模块 `Class` 排除列表。
+
+排除列表中的 `Class` 将会使用模块 (当前宿主环境的模块注入进程) 的 `ClassLoader` 进行装载。
+
+::: danger
+
+排除列表仅会在 (Xposed) 宿主环境生效。
+
+:::
\ No newline at end of file
diff --git a/docs-source/src/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/reference/ModuleClassLoader.md b/docs-source/src/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/reference/ModuleClassLoader.md
new file mode 100644
index 00000000..ee8750c6
--- /dev/null
+++ b/docs-source/src/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/reference/ModuleClassLoader.md
@@ -0,0 +1,67 @@
+---
+pageClass: code-page
+---
+
+# ModuleClassLoader - class
+
+```kotlin:no-line-numbers
+class ModuleClassLoader private constructor() : ClassLoader
+```
+
+**变更记录**
+
+`v1.1.2` `新增`
+
+**功能描述**
+
+> 自动处理 (Xposed) 宿主环境与模块环境的 `ClassLoader`。
+
+## companion object - object
+
+**变更记录**
+
+`v1.1.2` `新增`
+
+### excludeHostClasses - method
+
+```kotlin:no-line-numbers
+fun excludeHostClasses(vararg name: String)
+```
+
+**变更记录**
+
+`v1.1.2` `新增`
+
+**功能描述**
+
+> 添加到 Hook APP (宿主) `Class` 排除列表。
+
+排除列表中的 `Class` 将会使用宿主的 `ClassLoader` 进行装载。
+
+::: danger
+
+排除列表仅会在 (Xposed) 宿主环境生效。
+
+:::
+
+### excludeModuleClasses - method
+
+```kotlin:no-line-numbers
+fun excludeModuleClasses(vararg name: String)
+```
+
+**变更记录**
+
+`v1.1.2` `新增`
+
+**功能描述**
+
+> 添加到模块 `Class` 排除列表。
+
+排除列表中的 `Class` 将会使用模块 (当前宿主环境的模块注入进程) 的 `ClassLoader` 进行装载。
+
+::: danger
+
+排除列表仅会在 (Xposed) 宿主环境生效。
+
+:::
\ No newline at end of file
diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/xposed/parasitic/reference/ModuleClassLoader.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/xposed/parasitic/reference/ModuleClassLoader.kt
index 4c5acf8f..ab6eb250 100644
--- a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/xposed/parasitic/reference/ModuleClassLoader.kt
+++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/xposed/parasitic/reference/ModuleClassLoader.kt
@@ -26,6 +26,8 @@
* This file is Created by fankes on 2022/8/8.
* Thanks for providing https://github.com/cinit/QAuxiliary/blob/main/app/src/main/java/io/github/qauxv/lifecycle/Parasitics.java
*/
+@file:Suppress("unused")
+
package com.highcapable.yukihookapi.hook.xposed.parasitic.reference
import com.highcapable.yukihookapi.hook.xposed.bridge.YukiHookBridge
@@ -35,26 +37,64 @@ import com.highcapable.yukihookapi.hook.xposed.parasitic.AppParasitics
/**
* 自动处理 (Xposed) 宿主环境与模块环境的 [ClassLoader]
*/
-internal class ModuleClassLoader private constructor() : ClassLoader(AppParasitics.baseClassLoader) {
+class ModuleClassLoader private constructor() : ClassLoader(AppParasitics.baseClassLoader) {
- internal companion object {
+ companion object {
/** 当前 [ModuleClassLoader] 单例 */
private var instance: ModuleClassLoader? = null
+ /** 排除的 Hook APP (宿主) [Class] 类名数组 */
+ private val excludeHostClasses = HashSet()
+
+ /** 排除的模块 [Class] 类名数组 */
+ private val excludeModuleClasses = HashSet()
+
/**
* 获取 [ModuleClassLoader] 单例
* @return [ModuleClassLoader]
*/
internal fun instance() = instance ?: ModuleClassLoader().apply { instance = this }
+
+ /**
+ * 添加到 Hook APP (宿主) [Class] 排除列表
+ *
+ * 排除列表中的 [Class] 将会使用宿主的 [ClassLoader] 进行装载
+ *
+ * - ❗排除列表仅会在 (Xposed) 宿主环境生效
+ * @param name 需要添加的 [Class] 完整类名
+ */
+ fun excludeHostClasses(vararg name: String) {
+ excludeHostClasses.addAll(name.toList())
+ }
+
+ /**
+ * 添加到模块 [Class] 排除列表
+ *
+ * 排除列表中的 [Class] 将会使用模块 (当前宿主环境的模块注入进程) 的 [ClassLoader] 进行装载
+ *
+ * - ❗排除列表仅会在 (Xposed) 宿主环境生效
+ * @param name 需要添加的 [Class] 完整类名
+ */
+ fun excludeModuleClasses(vararg name: String) {
+ excludeModuleClasses.addAll(name.toList())
+ }
+
+ init {
+ excludeHostClasses.add("androidx.lifecycle.ReportFragment")
+ }
}
+ /** 默认 [ClassLoader] */
+ private val baseLoader get() = AppParasitics.baseClassLoader
+
override fun loadClass(name: String, resolve: Boolean): Class<*> {
- if (YukiHookBridge.hasXposedBridge.not()) return AppParasitics.baseClassLoader.loadClass(name)
- return YukiHookAppHelper.currentApplication()?.classLoader?.let { loader ->
- runCatching { if (name == "androidx.lifecycle.ReportFragment") return@let loader.loadClass(name) }
- runCatching { return@let AppParasitics.baseClassLoader.loadClass(name) }
- runCatching { AppParasitics.baseClassLoader.loadClass(name) }.getOrNull() ?: loader.loadClass(name)
+ if (YukiHookBridge.hasXposedBridge.not()) return baseLoader.loadClass(name)
+ return YukiHookAppHelper.currentApplication()?.classLoader?.let { hostLoader ->
+ excludeHostClasses.takeIf { it.isNotEmpty() }?.forEach { runCatching { if (name == it) return@let hostLoader.loadClass(name) } }
+ excludeModuleClasses.takeIf { it.isNotEmpty() }?.forEach { runCatching { if (name == it) return@let baseLoader.loadClass(name) } }
+ runCatching { return@let baseLoader.loadClass(name) }
+ runCatching { baseLoader.loadClass(name) }.getOrNull() ?: hostLoader.loadClass(name)
} ?: super.loadClass(name, resolve)
}
}
\ No newline at end of file