diff --git a/docs-source/src/en/api/public/com/highcapable/yukihookapi/YukiHookAPI.md b/docs-source/src/en/api/public/com/highcapable/yukihookapi/YukiHookAPI.md
index 8ec63842..1ba20531 100644
--- a/docs-source/src/en/api/public/com/highcapable/yukihookapi/YukiHookAPI.md
+++ b/docs-source/src/en/api/public/com/highcapable/yukihookapi/YukiHookAPI.md
@@ -512,29 +512,15 @@ var isEnableDataChannel: Boolean
此功能默认启用,关闭后将不会在功能初始化的时候装载 `YukiHookDataChannel`。
-### isEnableMemberCache - field
-
-```kotlin:no-line-numbers
-var isEnableMemberCache: Boolean
-```
+
isEnableMemberCache - field
**Change Records**
`v1.0.68` `added`
-**Function Illustrate**
+`v1.1.11` `deprecated`
-> 是否启用 `Member` 缓存功能。
-
-为防止 `Member` 复用过高造成的系统 GC 问题,此功能默认启用。
-
-启用后会缓存已经找到的 `Method`、`Constructor`、`Field`。
-
-缓存的 `Member` 都将处于 `ReflectsCacheStore` 的全局静态实例中。
-
-推荐使用 `MethodFinder`、`ConstructorFinder`、`FieldFinder` 来获取 `Member`。
-
-除非缓存的 `Member` 发生了混淆的问题,例如使用 R8 混淆后的 APP 的目标 `Member`,否则建议启用。
+`Member` 的直接缓存功能已被移除,因为其存在内存溢出 (OOM) 问题
## configs - method
@@ -578,7 +564,6 @@ object HookEntry : IYukiHookXposedInit {
isEnableHookModuleStatus = true
isEnableHookSharedPreferences = false
isEnableDataChannel = true
- isEnableMemberCache = true
}
}
@@ -607,7 +592,6 @@ object HookEntry : IYukiHookXposedInit {
isEnableHookModuleStatus = true
isEnableHookSharedPreferences = false
isEnableDataChannel = true
- isEnableMemberCache = true
}
override fun onHook() {
@@ -638,7 +622,6 @@ object HookEntry : IYukiHookXposedInit {
YukiHookAPI.Configs.isEnableHookModuleStatus = true
YukiHookAPI.Configs.isEnableHookSharedPreferences = false
YukiHookAPI.Configs.isEnableDataChannel = true
- YukiHookAPI.Configs.isEnableMemberCache = true
}
override fun onHook() {
diff --git a/docs-source/src/zh-cn/api/public/com/highcapable/yukihookapi/YukiHookAPI.md b/docs-source/src/zh-cn/api/public/com/highcapable/yukihookapi/YukiHookAPI.md
index 820e596a..ef140b7d 100644
--- a/docs-source/src/zh-cn/api/public/com/highcapable/yukihookapi/YukiHookAPI.md
+++ b/docs-source/src/zh-cn/api/public/com/highcapable/yukihookapi/YukiHookAPI.md
@@ -504,29 +504,15 @@ var isEnableDataChannel: Boolean
此功能默认启用,关闭后将不会在功能初始化的时候装载 `YukiHookDataChannel`。
-### isEnableMemberCache - field
-
-```kotlin:no-line-numbers
-var isEnableMemberCache: Boolean
-```
+isEnableMemberCache - field
**变更记录**
`v1.0.68` `新增`
-**功能描述**
+`v1.1.11` `作废`
-> 是否启用 `Member` 缓存功能。
-
-为防止 `Member` 复用过高造成的系统 GC 问题,此功能默认启用。
-
-启用后会缓存已经找到的 `Method`、`Constructor`、`Field`。
-
-缓存的 `Member` 都将处于 `ReflectsCacheStore` 的全局静态实例中。
-
-推荐使用 `MethodFinder`、`ConstructorFinder`、`FieldFinder` 来获取 `Member`。
-
-除非缓存的 `Member` 发生了混淆的问题,例如使用 R8 混淆后的 APP 的目标 `Member`,否则建议启用。
+`Member` 的直接缓存功能已被移除,因为其存在内存溢出 (OOM) 问题
## configs - method
@@ -570,7 +556,6 @@ object HookEntry : IYukiHookXposedInit {
isEnableHookModuleStatus = true
isEnableHookSharedPreferences = false
isEnableDataChannel = true
- isEnableMemberCache = true
}
}
@@ -599,7 +584,6 @@ object HookEntry : IYukiHookXposedInit {
isEnableHookModuleStatus = true
isEnableHookSharedPreferences = false
isEnableDataChannel = true
- isEnableMemberCache = true
}
override fun onHook() {
@@ -630,7 +614,6 @@ object HookEntry : IYukiHookXposedInit {
YukiHookAPI.Configs.isEnableHookModuleStatus = true
YukiHookAPI.Configs.isEnableHookSharedPreferences = false
YukiHookAPI.Configs.isEnableDataChannel = true
- YukiHookAPI.Configs.isEnableMemberCache = true
}
override fun onHook() {
diff --git a/yukihookapi/src/main/java/com/highcapable/yukihookapi/YukiHookAPI.kt b/yukihookapi/src/main/java/com/highcapable/yukihookapi/YukiHookAPI.kt
index c33d7f12..dba73525 100644
--- a/yukihookapi/src/main/java/com/highcapable/yukihookapi/YukiHookAPI.kt
+++ b/yukihookapi/src/main/java/com/highcapable/yukihookapi/YukiHookAPI.kt
@@ -40,10 +40,6 @@ import com.highcapable.yukihookapi.annotation.xposed.InjectYukiHookWithXposed
import com.highcapable.yukihookapi.hook.core.api.compat.HookApiCategoryHelper
import com.highcapable.yukihookapi.hook.core.api.compat.HookApiProperty
import com.highcapable.yukihookapi.hook.core.api.compat.type.ExecutorType
-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.store.ReflectsCacheStore
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
import com.highcapable.yukihookapi.hook.factory.isTaiChiModuleActive
import com.highcapable.yukihookapi.hook.factory.processName
@@ -58,10 +54,7 @@ import com.highcapable.yukihookapi.hook.xposed.bridge.status.YukiXposedModuleSta
import com.highcapable.yukihookapi.hook.xposed.bridge.type.HookEntryType
import com.highcapable.yukihookapi.hook.xposed.channel.YukiHookDataChannel
import com.highcapable.yukihookapi.hook.xposed.prefs.YukiHookPrefsBridge
-import java.lang.reflect.Constructor
-import java.lang.reflect.Field
import java.lang.reflect.Member
-import java.lang.reflect.Method
/**
* [YukiHookAPI] 的装载调用类
@@ -343,21 +336,12 @@ object YukiHookAPI {
/**
* 是否启用 [Member] 缓存功能
*
- * - 为防止 [Member] 复用过高造成的系统 GC 问题 - 此功能默认启用
+ * - ❗此方法及功能已被移除 - 在之后的版本中将直接被删除
*
- * 启用后会缓存已经找到的 [Method]、[Constructor]、[Field]
- *
- * 缓存的 [Member] 都将处于 [ReflectsCacheStore] 的全局静态实例中
- *
- * 推荐使用 [MethodFinder]、[ConstructorFinder]、[FieldFinder] 来获取 [Member]
- *
- * 详情请参考 [API 文档](https://fankes.github.io/YukiHookAPI/zh-cn/api/home)
- *
- * For English version, see [API Document](https://fankes.github.io/YukiHookAPI/en/api/home)
- *
- * 除非缓存的 [Member] 发生了混淆的问题 - 例如使用 R8 混淆后的 APP 的目标 [Member] - 否则建议启用
+ * - ❗[Member] 的直接缓存功能已被移除 - 因为其存在内存溢出 (OOM) 问题
*/
- var isEnableMemberCache = true
+ @Deprecated(message = "此方法及功能已被移除,请删除此方法")
+ var isEnableMemberCache = false
}
/**
diff --git a/yukihookapi/src/main/java/com/highcapable/yukihookapi/hook/core/finder/base/data/BaseRulesData.kt b/yukihookapi/src/main/java/com/highcapable/yukihookapi/hook/core/finder/base/data/BaseRulesData.kt
index 57d9d156..e6a61c98 100644
--- a/yukihookapi/src/main/java/com/highcapable/yukihookapi/hook/core/finder/base/data/BaseRulesData.kt
+++ b/yukihookapi/src/main/java/com/highcapable/yukihookapi/hook/core/finder/base/data/BaseRulesData.kt
@@ -139,10 +139,5 @@ internal abstract class BaseRulesData internal constructor(
*/
internal open val isInitialize get() = modifiers != null || orderIndex != null || matchIndex != null
- /**
- * 通过规则数据 [toString] 来得到一个 [Any.hashCode]
- * @param other 额外的数据 - 可选
- * @return [Int]
- */
- internal open fun hashCode(other: Any? = null) = "[$other][$modifiers][$orderIndex][$matchIndex]".hashCode()
+ override fun toString() = "[$modifiers][$orderIndex][$matchIndex]"
}
\ No newline at end of file
diff --git a/yukihookapi/src/main/java/com/highcapable/yukihookapi/hook/core/finder/classes/data/ClassRulesData.kt b/yukihookapi/src/main/java/com/highcapable/yukihookapi/hook/core/finder/classes/data/ClassRulesData.kt
index c45678b3..96706808 100644
--- a/yukihookapi/src/main/java/com/highcapable/yukihookapi/hook/core/finder/classes/data/ClassRulesData.kt
+++ b/yukihookapi/src/main/java/com/highcapable/yukihookapi/hook/core/finder/classes/data/ClassRulesData.kt
@@ -175,9 +175,7 @@ internal class ClassRulesData internal constructor(
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]"
+ "[$enclosingClass][$memberRules][$fieldRules][$methodRules][$constroctorRules]" + super.toString()
}
\ No newline at end of file
diff --git a/yukihookapi/src/main/java/com/highcapable/yukihookapi/hook/core/finder/members/data/ConstructorRulesData.kt b/yukihookapi/src/main/java/com/highcapable/yukihookapi/hook/core/finder/members/data/ConstructorRulesData.kt
index 53c88c04..a2c41e8f 100644
--- a/yukihookapi/src/main/java/com/highcapable/yukihookapi/hook/core/finder/members/data/ConstructorRulesData.kt
+++ b/yukihookapi/src/main/java/com/highcapable/yukihookapi/hook/core/finder/members/data/ConstructorRulesData.kt
@@ -63,7 +63,5 @@ internal class ConstructorRulesData internal constructor(
get() = super.isInitializeOfSuper || paramTypes != null || paramTypesConditions != null || paramCount >= 0 ||
paramCountRange.isEmpty().not() || paramCountConditions != null
- override fun hashCode(other: Any?) = super.hashCode(other) + toString().hashCode()
-
- override fun toString() = "[$paramTypes][$paramTypesConditions][$paramCount][$paramCountRange]"
+ override fun toString() = "[$paramTypes][$paramTypesConditions][$paramCount][$paramCountRange]" + super.toString()
}
\ No newline at end of file
diff --git a/yukihookapi/src/main/java/com/highcapable/yukihookapi/hook/core/finder/members/data/FieldRulesData.kt b/yukihookapi/src/main/java/com/highcapable/yukihookapi/hook/core/finder/members/data/FieldRulesData.kt
index 21bbee88..d2b89631 100644
--- a/yukihookapi/src/main/java/com/highcapable/yukihookapi/hook/core/finder/members/data/FieldRulesData.kt
+++ b/yukihookapi/src/main/java/com/highcapable/yukihookapi/hook/core/finder/members/data/FieldRulesData.kt
@@ -59,7 +59,5 @@ internal class FieldRulesData internal constructor(
override val isInitialize
get() = super.isInitializeOfSuper || name.isNotBlank() || nameConditions != null || type != null || typeConditions != null
- override fun hashCode(other: Any?) = super.hashCode(other) + toString().hashCode()
-
- override fun toString() = "[$name][$nameConditions][$type][$typeConditions]"
+ override fun toString() = "[$name][$nameConditions][$type][$typeConditions]" + super.toString()
}
\ No newline at end of file
diff --git a/yukihookapi/src/main/java/com/highcapable/yukihookapi/hook/core/finder/members/data/MemberRulesData.kt b/yukihookapi/src/main/java/com/highcapable/yukihookapi/hook/core/finder/members/data/MemberRulesData.kt
index 2dcfb843..d38e636a 100644
--- a/yukihookapi/src/main/java/com/highcapable/yukihookapi/hook/core/finder/members/data/MemberRulesData.kt
+++ b/yukihookapi/src/main/java/com/highcapable/yukihookapi/hook/core/finder/members/data/MemberRulesData.kt
@@ -70,7 +70,5 @@ internal open class MemberRulesData internal constructor(
override val isInitialize get() = isInitializeOfSuper || isInitializeOfMatch
- override fun hashCode(other: Any?) = super.hashCode(other) + toString().hashCode()
-
- override fun toString() = "[$isFindInSuper][$matchIndex][$matchCountRange]"
+ override fun toString() = "[$isFindInSuper][$matchIndex][$matchCountRange][$matchCountConditions]" + super.toString()
}
\ No newline at end of file
diff --git a/yukihookapi/src/main/java/com/highcapable/yukihookapi/hook/core/finder/members/data/MethodRulesData.kt b/yukihookapi/src/main/java/com/highcapable/yukihookapi/hook/core/finder/members/data/MethodRulesData.kt
index f1059e1e..aee3dc41 100644
--- a/yukihookapi/src/main/java/com/highcapable/yukihookapi/hook/core/finder/members/data/MethodRulesData.kt
+++ b/yukihookapi/src/main/java/com/highcapable/yukihookapi/hook/core/finder/members/data/MethodRulesData.kt
@@ -78,8 +78,6 @@ internal class MethodRulesData internal constructor(
paramCount >= 0 || paramCountRange.isEmpty().not() || paramCountConditions != null ||
returnType != null || returnTypeConditions != null
- override fun hashCode(other: Any?) = super.hashCode(other) + toString().hashCode()
-
override fun toString() = "[$name][$nameConditions][$paramTypes][$paramTypesConditions][$paramCount]" +
- "[$paramCountRange][$returnType][$returnTypeConditions]"
+ "[$paramCountRange][$returnType][$returnTypeConditions]" + super.toString()
}
\ No newline at end of file
diff --git a/yukihookapi/src/main/java/com/highcapable/yukihookapi/hook/core/finder/store/ReflectsCacheStore.kt b/yukihookapi/src/main/java/com/highcapable/yukihookapi/hook/core/finder/store/ReflectsCacheStore.kt
deleted file mode 100644
index c8a11b60..00000000
--- a/yukihookapi/src/main/java/com/highcapable/yukihookapi/hook/core/finder/store/ReflectsCacheStore.kt
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * YukiHookAPI - An efficient Hook API and Xposed Module solution built in Kotlin.
- * Copyright (C) 2019-2023 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/3/29.
- */
-package com.highcapable.yukihookapi.hook.core.finder.store
-
-import android.util.ArrayMap
-import com.highcapable.yukihookapi.YukiHookAPI
-import java.lang.reflect.Constructor
-import java.lang.reflect.Field
-import java.lang.reflect.Member
-import java.lang.reflect.Method
-
-/**
- * 这是一个全局静态的 [Class]、[Member] 缓存实例
- *
- * 为防止 [Class]、[Member] 复用过高造成的系统 GC 问题
- *
- * 查找后的 [Class] 自动进入缓存 - 不受任何控制
- *
- * 查找后的 [Member] 在 [YukiHookAPI.Configs.isEnableMemberCache] 启用后自动进入缓存
- */
-internal object ReflectsCacheStore {
-
- /** 缓存的 [Class] 列表 */
- private val dexClassListData = ArrayMap>()
-
- /** 缓存的 [Class] 对象 */
- private val classData = ArrayMap?>()
-
- /** 缓存的 [Class] 数组 */
- private val classesData = ArrayMap>>()
-
- /** 缓存的 [Method] 数组 */
- private val methodsData = ArrayMap>()
-
- /** 缓存的 [Constructor] 数组 */
- private val constructorsData = ArrayMap>>()
-
- /** 缓存的 [Field] 数组 */
- private val fieldsData = ArrayMap>()
-
- /**
- * 查找缓存中的 [Class] 列表
- * @param hashCode 标识符
- * @return [List]<[Class]>
- */
- internal fun findDexClassList(hashCode: Int) = dexClassListData[hashCode]
-
- /**
- * 查找缓存中的 [Class]
- * @param hashCode 标识符
- * @return [Class] or null
- */
- 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 标识符
- * @return [HashSet]<[Method]>
- */
- internal fun findMethods(hashCode: Int) = methodsData[hashCode]
-
- /**
- * 查找缓存中的 [Constructor] 数组
- * @param hashCode 标识符
- * @return [HashSet]<[Constructor]>
- */
- internal fun findConstructors(hashCode: Int) = constructorsData[hashCode]
-
- /**
- * 查找缓存中的 [Field] 数组
- * @param hashCode 标识符
- * @return [HashSet]<[Field]>
- */
- 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<*>?) {
- classData[hashCode] = instance
- }
-
- /**
- * 写入 [Class] 数组到缓存
- * @param hashCode 标识符
- * @param instance 实例
- */
- internal fun putClasses(hashCode: Int, instance: HashSet>) {
- classesData[hashCode] = instance
- }
-
- /**
- * 写入 [Method] 数组到缓存
- * @param hashCode 标识符
- * @param instances 实例数组
- */
- internal fun putMethods(hashCode: Int, instances: HashSet) {
- if (YukiHookAPI.Configs.isEnableMemberCache.not()) return
- methodsData[hashCode] = instances
- }
-
- /**
- * 写入 [Constructor] 数组到缓存
- * @param hashCode 标识符
- * @param instances 实例数组
- */
- internal fun putConstructors(hashCode: Int, instances: HashSet>) {
- if (YukiHookAPI.Configs.isEnableMemberCache.not()) return
- constructorsData[hashCode] = instances
- }
-
- /**
- * 写入 [Field] 数组到缓存
- * @param hashCode 标识符
- * @param instances 实例数组
- */
- internal fun putFields(hashCode: Int, instances: HashSet) {
- if (YukiHookAPI.Configs.isEnableMemberCache.not()) return
- fieldsData[hashCode] = instances
- }
-}
\ No newline at end of file
diff --git a/yukihookapi/src/main/java/com/highcapable/yukihookapi/hook/core/finder/tools/ReflectionTool.kt b/yukihookapi/src/main/java/com/highcapable/yukihookapi/hook/core/finder/tools/ReflectionTool.kt
index b4b3f5d1..d12d74f5 100644
--- a/yukihookapi/src/main/java/com/highcapable/yukihookapi/hook/core/finder/tools/ReflectionTool.kt
+++ b/yukihookapi/src/main/java/com/highcapable/yukihookapi/hook/core/finder/tools/ReflectionTool.kt
@@ -29,13 +29,13 @@
package com.highcapable.yukihookapi.hook.core.finder.tools
+import android.util.ArrayMap
import com.highcapable.yukihookapi.hook.core.finder.base.data.BaseRulesData
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.core.finder.store.ReflectsCacheStore
import com.highcapable.yukihookapi.hook.factory.*
import com.highcapable.yukihookapi.hook.log.yLoggerW
import com.highcapable.yukihookapi.hook.type.defined.UndefinedType
@@ -63,13 +63,31 @@ internal object ReflectionTool {
/** 当前工具类的标签 */
private const val TAG = "YukiHookAPI#ReflectionTool"
+ /**
+ * 当前工具类的 [ClassLoader]
+ * @return [ClassLoader]
+ */
+ private val currentClassLoader get() = AppParasitics.baseClassLoader
+
+ /**
+ * 内存缓存实例实现
+ */
+ private object MemoryCache {
+
+ /** 缓存的 [Class] 列表数组 */
+ val dexClassListData = ArrayMap>()
+
+ /** 缓存的 [Class] 对象数组 */
+ val classData = ArrayMap?>()
+ }
+
/**
* 写出当前 [ClassLoader] 下所有 [Class] 名称数组
* @param loader 当前使用的 [ClassLoader]
* @return [List]<[String]>
* @throws IllegalStateException 如果 [loader] 不是 [BaseDexClassLoader]
*/
- internal fun findDexClassList(loader: ClassLoader?) = ReflectsCacheStore.findDexClassList(loader.hashCode())
+ internal fun findDexClassList(loader: ClassLoader?) = MemoryCache.dexClassListData[loader.toString()]
?: DalvikBaseDexClassLoader.field { name = "pathList" }.ignored().get(loader.value().let {
while (it.value !is BaseDexClassLoader) {
if (it.value?.parent != null) it.value = it.value?.parent
@@ -78,7 +96,7 @@ internal object ReflectionTool {
}).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) }
+ }.orEmpty().also { if (it.isNotEmpty()) MemoryCache.dexClassListData[loader.toString()] = it }
/**
* 使用字符串类名查找 [Class] 是否存在
@@ -98,16 +116,16 @@ internal object ReflectionTool {
*/
@PublishedApi
internal fun findClassByName(name: String, loader: ClassLoader?, initialize: Boolean = false): Class<*> {
- val hashCode = ("[$name][$loader]").hashCode()
+ val uniqueCode = "[$name][$loader]"
/**
* 获取 [Class.forName] 的 [Class] 对象
* @param name [Class] 完整名称
* @param initialize 是否初始化 [Class] 的静态方法块
- * @param loader [Class] 所在的 [ClassLoader] - 默认为 [AppParasitics.baseClassLoader]
+ * @param loader [Class] 所在的 [ClassLoader] - 默认为 [currentClassLoader]
* @return [Class]
*/
- fun classForName(name: String, initialize: Boolean, loader: ClassLoader? = AppParasitics.baseClassLoader) =
+ fun classForName(name: String, initialize: Boolean, loader: ClassLoader? = currentClassLoader) =
Class.forName(name, initialize, loader)
/**
@@ -115,9 +133,9 @@ internal object ReflectionTool {
* @return [Class] or null
*/
fun loadWithDefaultClassLoader() = if (initialize.not()) loader?.loadClass(name) else classForName(name, initialize, loader)
- return ReflectsCacheStore.findClass(hashCode) ?: runCatching {
- (loadWithDefaultClassLoader() ?: classForName(name, initialize)).also { ReflectsCacheStore.putClass(hashCode, it) }
- }.getOrNull() ?: throw createException(loader ?: AppParasitics.baseClassLoader, name = "Class", "name:[$name]")
+ return MemoryCache.classData[uniqueCode] ?: runCatching {
+ (loadWithDefaultClassLoader() ?: classForName(name, initialize)).also { MemoryCache.classData[uniqueCode] = it }
+ }.getOrNull() ?: throw createException(loader ?: currentClassLoader, name = "Class", "name:[$name]")
}
/**
@@ -129,7 +147,7 @@ internal object ReflectionTool {
* @throws NoClassDefFoundError 如果找不到 [Class]
*/
internal fun findClasses(loaderSet: ClassLoader?, rulesData: ClassRulesData) = rulesData.createResult {
- ReflectsCacheStore.findClasses(hashCode(loaderSet)) ?: hashSetOf>().also { classes ->
+ hashSetOf>().also { classes ->
/**
* 开始查找作业
* @param instance 当前 [Class] 实例
@@ -188,7 +206,7 @@ internal object ReflectionTool {
value.modifiers?.also { runCatching { and(it(member.cast())) } }
}.finally { numberOfFound++ }
}.run { rule.matchCount(numberOfFound) { and(it && numberOfFound > 0) } }
- else rule.matchCount(size) { and(it) }
+ else rule.matchCount(count()) { and(it) }
}
}
fieldRules.takeIf { it.isNotEmpty() }?.forEach { rule ->
@@ -203,7 +221,7 @@ internal object ReflectionTool {
value.typeConditions?.also { field.also { t -> runCatching { and(it(t.type(), t.type)) } } }
}.finally { numberOfFound++ }
}.run { rule.matchCount(numberOfFound) { and(it && numberOfFound > 0) } }
- else rule.matchCount(size) { and(it) }
+ else rule.matchCount(count()) { and(it) }
}
}
methodRules.takeIf { it.isNotEmpty() }?.forEach { rule ->
@@ -226,7 +244,7 @@ internal object ReflectionTool {
value.nameConditions?.also { method.name.also { n -> runCatching { and(it(n.cast(), n)) } } }
}.finally { numberOfFound++ }
}.run { rule.matchCount(numberOfFound) { and(it && numberOfFound > 0) } }
- else rule.matchCount(size) { and(it) }
+ else rule.matchCount(count()) { and(it) }
}
}
constroctorRules.takeIf { it.isNotEmpty() }?.forEach { rule ->
@@ -244,7 +262,7 @@ internal object ReflectionTool {
value.modifiers?.also { runCatching { and(it(constructor.cast())) } }
}.finally { numberOfFound++ }
}.run { rule.matchCount(numberOfFound) { and(it && numberOfFound > 0) } }
- else rule.matchCount(size) { and(it) }
+ else rule.matchCount(count()) { and(it) }
}
}
}.finally { classes.add(instance) }
@@ -260,7 +278,7 @@ internal object ReflectionTool {
) startProcess(className.toClass(loaderSet))
}
}
- }.takeIf { it.isNotEmpty() }?.also { ReflectsCacheStore.putClasses(hashCode(loaderSet), it) } ?: throwNotFoundError(loaderSet)
+ }.takeIf { it.isNotEmpty() } ?: throwNotFoundError(loaderSet)
}
/**
@@ -274,19 +292,19 @@ internal object ReflectionTool {
internal fun findFields(classSet: Class<*>?, rulesData: FieldRulesData) = rulesData.createResult {
if (type == UndefinedType) error("Field match type class is not found")
if (classSet == null) return@createResult hashSetOf()
- ReflectsCacheStore.findFields(hashCode(classSet)) ?: hashSetOf().also { fields ->
+ hashSetOf().also { fields ->
classSet.existFields?.also { declares ->
var iType = -1
var iName = -1
var iModify = -1
var iNameCds = -1
var iTypeCds = -1
- val iLType = type?.let(matchIndex) { e -> declares.filter { e == it.type }.lastIndex } ?: -1
- val iLName = name.takeIf(matchIndex) { it.isNotBlank() }?.let { e -> declares.filter { e == it.name }.lastIndex } ?: -1
- val iLModify = modifiers?.let(matchIndex) { e -> declares.filter { runOrFalse { e(it.cast()) } }.lastIndex } ?: -1
+ val iLType = type?.let(matchIndex) { e -> declares.findLastIndex { e == it.type } } ?: -1
+ val iLName = name.takeIf(matchIndex) { it.isNotBlank() }?.let { e -> declares.findLastIndex { e == it.name } } ?: -1
+ val iLModify = modifiers?.let(matchIndex) { e -> declares.findLastIndex { runOrFalse { e(it.cast()) } } } ?: -1
val iLNameCds = nameConditions
- ?.let(matchIndex) { e -> declares.filter { it.name.let { n -> runOrFalse { e(n.cast(), n) } } }.lastIndex } ?: -1
- val iLTypeCds = typeConditions?.let(matchIndex) { e -> declares.filter { runOrFalse { e(it.type(), it.type) } }.lastIndex } ?: -1
+ ?.let(matchIndex) { e -> declares.findLastIndex { it.name.let { n -> runOrFalse { e(n.cast(), n) } } } } ?: -1
+ val iLTypeCds = typeConditions?.let(matchIndex) { e -> declares.findLastIndex { runOrFalse { e(it.type(), it.type) } } } ?: -1
declares.forEachIndexed { index, instance ->
conditions {
type?.also {
@@ -319,11 +337,11 @@ internal object ReflectionTool {
hold && matchIndex.compare(iTypeCds, iLTypeCds)
})
}
- orderIndex.compare(index, declares.lastIndex) { and(it) }
+ orderIndex.compare(index, declares.lastIndex()) { and(it) }
}.finally { fields.add(instance.apply { isAccessible = true }) }
}
}
- }.takeIf { it.isNotEmpty() }?.also { ReflectsCacheStore.putFields(hashCode(classSet), it) } ?: findSuperOrThrow(classSet)
+ }.takeIf { it.isNotEmpty() } ?: findSuperOrThrow(classSet)
}
/**
@@ -339,7 +357,7 @@ internal object ReflectionTool {
if (classSet == null) return@createResult hashSetOf()
paramTypes?.takeIf { it.isNotEmpty() }
?.forEachIndexed { p, it -> if (it == UndefinedType) error("Method match paramType[$p] class is not found") }
- ReflectsCacheStore.findMethods(hashCode(classSet)) ?: hashSetOf().also { methods ->
+ hashSetOf().also { methods ->
classSet.existMethods?.also { declares ->
var iReturnType = -1
var iReturnTypeCds = -1
@@ -351,23 +369,23 @@ internal object ReflectionTool {
var iName = -1
var iModify = -1
var iNameCds = -1
- val iLReturnType = returnType?.let(matchIndex) { e -> declares.filter { e == it.returnType }.lastIndex } ?: -1
+ val iLReturnType = returnType?.let(matchIndex) { e -> declares.findLastIndex { e == it.returnType } } ?: -1
val iLReturnTypeCds = returnTypeConditions
- ?.let(matchIndex) { e -> declares.filter { runOrFalse { e(it.returnType(), it.returnType) } }.lastIndex } ?: -1
+ ?.let(matchIndex) { e -> declares.findLastIndex { runOrFalse { e(it.returnType(), it.returnType) } } } ?: -1
val iLParamCount = paramCount.takeIf(matchIndex) { it >= 0 }
- ?.let { e -> declares.filter { e == it.parameterTypes.size }.lastIndex } ?: -1
+ ?.let { e -> declares.findLastIndex { e == it.parameterTypes.size } } ?: -1
val iLParamCountRange = paramCountRange.takeIf(matchIndex) { it.isEmpty().not() }
- ?.let { e -> declares.filter { it.parameterTypes.size in e }.lastIndex } ?: -1
+ ?.let { e -> declares.findLastIndex { it.parameterTypes.size in e } } ?: -1
val iLParamCountCds = paramCountConditions?.let(matchIndex) { e ->
- declares.filter { it.parameterTypes.size.let { s -> runOrFalse { e(s.cast(), s) } } }.lastIndex
+ declares.findLastIndex { it.parameterTypes.size.let { s -> runOrFalse { e(s.cast(), s) } } }
} ?: -1
- val iLParamTypes = paramTypes?.let(matchIndex) { e -> declares.filter { paramTypesEq(e, it.parameterTypes) }.lastIndex } ?: -1
+ val iLParamTypes = paramTypes?.let(matchIndex) { e -> declares.findLastIndex { paramTypesEq(e, it.parameterTypes) } } ?: -1
val iLParamTypesCds = paramTypesConditions
- ?.let(matchIndex) { e -> declares.filter { runOrFalse { e(it.paramTypes(), it.parameterTypes) } }.lastIndex } ?: -1
- val iLName = name.takeIf(matchIndex) { it.isNotBlank() }?.let { e -> declares.filter { e == it.name }.lastIndex } ?: -1
- val iLModify = modifiers?.let(matchIndex) { e -> declares.filter { runOrFalse { e(it.cast()) } }.lastIndex } ?: -1
+ ?.let(matchIndex) { e -> declares.findLastIndex { runOrFalse { e(it.paramTypes(), it.parameterTypes) } } } ?: -1
+ val iLName = name.takeIf(matchIndex) { it.isNotBlank() }?.let { e -> declares.findLastIndex { e == it.name } } ?: -1
+ val iLModify = modifiers?.let(matchIndex) { e -> declares.findLastIndex { runOrFalse { e(it.cast()) } } } ?: -1
val iLNameCds = nameConditions
- ?.let(matchIndex) { e -> declares.filter { it.name.let { n -> runOrFalse { e(n.cast(), n) } } }.lastIndex } ?: -1
+ ?.let(matchIndex) { e -> declares.findLastIndex { it.name.let { n -> runOrFalse { e(n.cast(), n) } } } } ?: -1
declares.forEachIndexed { index, instance ->
conditions {
name.takeIf { it.isNotBlank() }?.also {
@@ -430,11 +448,11 @@ internal object ReflectionTool {
hold && matchIndex.compare(iNameCds, iLNameCds)
})
}
- orderIndex.compare(index, declares.lastIndex) { and(it) }
+ orderIndex.compare(index, declares.lastIndex()) { and(it) }
}.finally { methods.add(instance.apply { isAccessible = true }) }
}
}
- }.takeIf { it.isNotEmpty() }?.also { ReflectsCacheStore.putMethods(hashCode(classSet), it) } ?: findSuperOrThrow(classSet)
+ }.takeIf { it.isNotEmpty() } ?: findSuperOrThrow(classSet)
}
/**
@@ -449,7 +467,7 @@ internal object ReflectionTool {
if (classSet == null) return@createResult hashSetOf()
paramTypes?.takeIf { it.isNotEmpty() }
?.forEachIndexed { p, it -> if (it == UndefinedType) error("Constructor match paramType[$p] class is not found") }
- ReflectsCacheStore.findConstructors(hashCode(classSet)) ?: hashSetOf>().also { constructors ->
+ hashSetOf>().also { constructors ->
classSet.existConstructors?.also { declares ->
var iParamTypes = -1
var iParamTypesCds = -1
@@ -458,16 +476,16 @@ internal object ReflectionTool {
var iParamCountCds = -1
var iModify = -1
val iLParamCount = paramCount.takeIf(matchIndex) { it >= 0 }
- ?.let { e -> declares.filter { e == it.parameterTypes.size }.lastIndex } ?: -1
+ ?.let { e -> declares.findLastIndex { e == it.parameterTypes.size } } ?: -1
val iLParamCountRange = paramCountRange.takeIf(matchIndex) { it.isEmpty().not() }
- ?.let { e -> declares.filter { it.parameterTypes.size in e }.lastIndex } ?: -1
+ ?.let { e -> declares.findLastIndex { it.parameterTypes.size in e } } ?: -1
val iLParamCountCds = paramCountConditions?.let(matchIndex) { e ->
- declares.filter { it.parameterTypes.size.let { s -> runOrFalse { e(s.cast(), s) } } }.lastIndex
+ declares.findLastIndex { it.parameterTypes.size.let { s -> runOrFalse { e(s.cast(), s) } } }
} ?: -1
- val iLParamTypes = paramTypes?.let(matchIndex) { e -> declares.filter { paramTypesEq(e, it.parameterTypes) }.lastIndex } ?: -1
+ val iLParamTypes = paramTypes?.let(matchIndex) { e -> declares.findLastIndex { paramTypesEq(e, it.parameterTypes) } } ?: -1
val iLParamTypesCds = paramTypesConditions
- ?.let(matchIndex) { e -> declares.filter { runOrFalse { e(it.paramTypes(), it.parameterTypes) } }.lastIndex } ?: -1
- val iLModify = modifiers?.let(matchIndex) { e -> declares.filter { runOrFalse { e(it.cast()) } }.lastIndex } ?: -1
+ ?.let(matchIndex) { e -> declares.findLastIndex { runOrFalse { e(it.paramTypes(), it.parameterTypes) } } } ?: -1
+ val iLModify = modifiers?.let(matchIndex) { e -> declares.findLastIndex { runOrFalse { e(it.cast()) } } } ?: -1
declares.forEachIndexed { index, instance ->
conditions {
paramCount.takeIf { it >= 0 }?.also {
@@ -506,11 +524,11 @@ internal object ReflectionTool {
hold && matchIndex.compare(iModify, iLModify)
})
}
- orderIndex.compare(index, declares.lastIndex) { and(it) }
+ orderIndex.compare(index, declares.lastIndex()) { and(it) }
}.finally { constructors.add(instance.apply { isAccessible = true }) }
}
}
- }.takeIf { it.isNotEmpty() }?.also { ReflectsCacheStore.putConstructors(hashCode(classSet), it) } ?: findSuperOrThrow(classSet)
+ }.takeIf { it.isNotEmpty() } ?: findSuperOrThrow(classSet)
}
/**
@@ -588,7 +606,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)
+ is ClassRulesData -> throw createException(instanceSet ?: currentClassLoader, objectName, *templates)
else -> error("Type [$this] not allowed")
}
@@ -629,7 +647,7 @@ internal object ReflectionTool {
/**
* 获取当前 [Class] 中存在的 [Member] 数组
- * @return [Array]<[Member]>
+ * @return [Sequence]<[Member]> or null
*/
private val Class<*>.existMembers
get() = runCatching {
@@ -637,35 +655,35 @@ internal object ReflectionTool {
addAll(declaredFields.toList())
addAll(declaredMethods.toList())
addAll(declaredConstructors.toList())
- }.toTypedArray()
+ }.asSequence()
}.onFailure {
yLoggerW(msg = "Failed to get the declared Members in [$this] because got an exception\n$it")
}.getOrNull()
/**
* 获取当前 [Class] 中存在的 [Field] 数组
- * @return [Array]<[Field]>
+ * @return [Sequence]<[Field]> or null
*/
private val Class<*>.existFields
- get() = runCatching { declaredFields }.onFailure {
+ get() = runCatching { declaredFields.asSequence() }.onFailure {
yLoggerW(msg = "Failed to get the declared Fields in [$this] because got an exception\n$it")
}.getOrNull()
/**
* 获取当前 [Class] 中存在的 [Method] 数组
- * @return [Array]<[Method]>
+ * @return [Sequence]<[Method]> or null
*/
private val Class<*>.existMethods
- get() = runCatching { declaredMethods }.onFailure {
+ get() = runCatching { declaredMethods.asSequence() }.onFailure {
yLoggerW(msg = "Failed to get the declared Methods in [$this] because got an exception\n$it")
}.getOrNull()
/**
* 获取当前 [Class] 中存在的 [Constructor] 数组
- * @return [Array]<[Constructor]>
+ * @return [Sequence]<[Constructor]> or null
*/
private val Class<*>.existConstructors
- get() = runCatching { declaredConstructors }.onFailure {
+ get() = runCatching { declaredConstructors.asSequence() }.onFailure {
yLoggerW(msg = "Failed to get the declared Constructors in [$this] because got an exception\n$it")
}.getOrNull()
diff --git a/yukihookapi/src/main/java/com/highcapable/yukihookapi/hook/utils/memory/LruCacheMemory.kt b/yukihookapi/src/main/java/com/highcapable/yukihookapi/hook/utils/memory/LruCacheMemory.kt
deleted file mode 100644
index fd28fd93..00000000
--- a/yukihookapi/src/main/java/com/highcapable/yukihookapi/hook/utils/memory/LruCacheMemory.kt
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * YukiHookAPI - An efficient Hook API and Xposed Module solution built in Kotlin.
- * Copyright (C) 2019-2023 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 2023/4/20.
- */
-package com.highcapable.yukihookapi.hook.utils.memory
-
-import android.util.LruCache
-
-/**
- * [LruCache] 内存定义类
- */
-internal object LruCacheMemory {
-
- /** 当前最大内存压缩倍数 */
- private const val MAX_COMPRESSION_FACTOR = 16
-
- /** 当前可用内存大小 (KB) */
- private val maxMemorySize = (Runtime.getRuntime().maxMemory() / 1024).toInt()
-
- /** 当前可用缓存大小 (KB) */
- internal val maxCacheSize = maxMemorySize / MAX_COMPRESSION_FACTOR
-}
\ No newline at end of file
diff --git a/yukihookapi/src/main/java/com/highcapable/yukihookapi/hook/utils/memory/factory/LruCacheFactory.kt b/yukihookapi/src/main/java/com/highcapable/yukihookapi/hook/utils/memory/factory/LruCacheFactory.kt
deleted file mode 100644
index 75cd5bab..00000000
--- a/yukihookapi/src/main/java/com/highcapable/yukihookapi/hook/utils/memory/factory/LruCacheFactory.kt
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * YukiHookAPI - An efficient Hook API and Xposed Module solution built in Kotlin.
- * Copyright (C) 2019-2023 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 2023/4/20.
- */
-package com.highcapable.yukihookapi.hook.utils.memory.factory
-
-import android.util.LruCache
-import com.highcapable.yukihookapi.hook.utils.memory.LruCacheMemory
-
-/**
- * 创建 [LruCache]<[K], [V]>
- * @param sizeOf 回调自定义缓存大小计算数值 - 默认不设置
- * @return [LruCache]<[K], [V]>
- */
-internal fun createLruCache(sizeOf: (() -> Int)? = null) = object : LruCache(LruCacheMemory.maxCacheSize) {
- override fun sizeOf(key: K?, value: V?) = when {
- sizeOf != null -> sizeOf()
- value is Array<*> -> {
- var allLengths = 0
- if (value.isNotEmpty()) value.forEach { allLengths += it.toString().length }
- allLengths / 1024
- }
- value is Map<*, *> -> {
- var allLengths = 0
- if (value.isNotEmpty()) value.forEach { allLengths += it.toString().length }
- allLengths / 1024
- }
- value is List<*> -> {
- var allLengths = 0
- if (value.isNotEmpty()) value.forEach { allLengths += it.toString().length }
- allLengths / 1024
- }
- value is Set<*> -> {
- var allLengths = 0
- if (value.isNotEmpty()) value.forEach { allLengths += it.toString().length }
- allLengths / 1024
- }
- value is String -> value.length / 1024
- else -> value.toString().length / 1024
- }
-}
\ No newline at end of file