diff --git a/yukihookapi-core/src/main/java/com/highcapable/yukihookapi/hook/core/finder/type/factory/TypeAliasFactory.kt b/yukihookapi-core/src/main/java/com/highcapable/yukihookapi/hook/core/finder/type/factory/TypeAliasFactory.kt index b33fde98..88e9426e 100644 --- a/yukihookapi-core/src/main/java/com/highcapable/yukihookapi/hook/core/finder/type/factory/TypeAliasFactory.kt +++ b/yukihookapi-core/src/main/java/com/highcapable/yukihookapi/hook/core/finder/type/factory/TypeAliasFactory.kt @@ -36,6 +36,9 @@ 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 +/** 定义 [ClassLoader] 装载实例方法体类型 */ +internal typealias ClassLoaderInitializer = () -> ClassLoader? + /** 定义 [DexClassFinder] 方法体类型 */ internal typealias ClassConditions = DexClassFinder.() -> Unit diff --git a/yukihookapi-core/src/main/java/com/highcapable/yukihookapi/hook/factory/ReflectionFactory.kt b/yukihookapi-core/src/main/java/com/highcapable/yukihookapi/hook/factory/ReflectionFactory.kt index c74c90b2..0fd49914 100644 --- a/yukihookapi-core/src/main/java/com/highcapable/yukihookapi/hook/factory/ReflectionFactory.kt +++ b/yukihookapi-core/src/main/java/com/highcapable/yukihookapi/hook/factory/ReflectionFactory.kt @@ -31,6 +31,7 @@ package com.highcapable.yukihookapi.hook.factory import com.highcapable.yukihookapi.hook.bean.CurrentClass import com.highcapable.yukihookapi.hook.bean.GenericClass +import com.highcapable.yukihookapi.hook.bean.VariousClass 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 @@ -38,6 +39,7 @@ 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.ClassConditions +import com.highcapable.yukihookapi.hook.core.finder.type.factory.ClassLoaderInitializer 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 @@ -68,6 +70,7 @@ import java.lang.reflect.Field import java.lang.reflect.Member import java.lang.reflect.Method import java.lang.reflect.ParameterizedType +import kotlin.reflect.KProperty /** * 定义一个 [Class] 中的 [Member] 类型 @@ -83,6 +86,78 @@ enum class MembersType { CONSTRUCTOR } +/** + * 懒装载 [Class] 实例 + * @param instance 当前实例 + * @param initialize 是否初始化 + * @param loader [ClassLoader] 装载实例 + */ +open class LazyClass internal constructor( + private val instance: Any, + private val initialize: Boolean, + private val loader: ClassLoaderInitializer?, +) { + + /** 当前实例 */ + private var baseInstance: Class? = null + + /** + * 获取非空实例 + * @return [Class]<[T]> + */ + internal val nonNull get(): Class { + if (baseInstance == null) baseInstance = when (instance) { + is String -> instance.toClass(loader?.invoke(), initialize) as Class + is VariousClass -> instance.get(loader?.invoke(), initialize) as Class + else -> error("Unknown lazy class type \"$instance\"") + } + return baseInstance ?: error("Exception has been thrown above") + } + + /** + * 获取可空实例 + * @return [Class]<[T]> or null + */ + internal val nullable get(): Class? { + if (baseInstance == null) baseInstance = when (instance) { + is String -> instance.toClassOrNull(loader?.invoke(), initialize) as? Class? + is VariousClass -> instance.getOrNull(loader?.invoke(), initialize) as? Class? + else -> error("Unknown lazy class type \"$instance\"") + } + return baseInstance + } + + /** + * 非空实例 + * @param instance 当前实例 + * @param initialize 是否初始化 + * @param loader [ClassLoader] 装载实例 + */ + class NonNull internal constructor( + instance: Any, + initialize: Boolean, + loader: ClassLoaderInitializer?, + ) : LazyClass(instance, initialize, loader) { + + operator fun getValue(thisRef: Any?, property: KProperty<*>) = nonNull + } + + /** + * 可空实例 + * @param instance 当前实例 + * @param initialize 是否初始化 + * @param loader [ClassLoader] 装载实例 + */ + class Nullable internal constructor( + instance: Any, + initialize: Boolean, + loader: ClassLoaderInitializer?, + ) : LazyClass(instance, initialize, loader) { + + operator fun getValue(thisRef: Any?, property: KProperty<*>) = nullable + } +} + /** * 写出当前 [ClassLoader] 下所有 [Class] 名称数组 * @@ -286,6 +361,68 @@ inline fun String.toClassOrNull(loader: ClassLoader? = null, initial inline fun classOf(loader: ClassLoader? = null, initialize: Boolean = false) = loader?.let { T::class.java.name.toClass(loader, initialize) as Class } ?: T::class.java +/** + * 懒装载 [Class] + * @param name 完整类名 + * @param initialize 是否初始化 [Class] 的静态方法块 - 默认否 + * @param loader [ClassLoader] 装载实例 - 默认空 - 不填使用默认 [ClassLoader] + * @return [LazyClass.NonNull] + */ +fun lazyClass(name: String, initialize: Boolean = false, loader: ClassLoaderInitializer? = null) = + lazyClass(name, initialize, loader) + +/** + * 懒装载 [Class]<[T]> + * @param name 完整类名 + * @param initialize 是否初始化 [Class] 的静态方法块 - 默认否 + * @param loader [ClassLoader] 装载实例 - 默认空 - 不填使用默认 [ClassLoader] + * @return [LazyClass.NonNull]<[T]> + */ +@JvmName("lazyClass_Generics") +inline fun lazyClass(name: String, initialize: Boolean = false, noinline loader: ClassLoaderInitializer? = null) = + LazyClass.NonNull(name, initialize, loader) + +/** + * 懒装载 [Class] + * @param variousClass [VariousClass] + * @param initialize 是否初始化 [Class] 的静态方法块 - 默认否 + * @param loader [ClassLoader] 装载实例 - 默认空 - 不填使用默认 [ClassLoader] + * @return [LazyClass.NonNull] + */ +fun lazyClass(variousClass: VariousClass, initialize: Boolean = false, loader: ClassLoaderInitializer? = null) = + LazyClass.NonNull(variousClass, initialize, loader) + +/** + * 懒装载 [Class] + * @param name 完整类名 + * @param initialize 是否初始化 [Class] 的静态方法块 - 默认否 + * @param loader [ClassLoader] 装载实例 - 默认空 - 不填使用默认 [ClassLoader] + * @return [LazyClass.Nullable] + */ +fun lazyClassOrNull(name: String, initialize: Boolean = false, loader: ClassLoaderInitializer? = null) = + lazyClassOrNull(name, initialize, loader) + +/** + * 懒装载 [Class]<[T]> + * @param name 完整类名 + * @param initialize 是否初始化 [Class] 的静态方法块 - 默认否 + * @param loader [ClassLoader] 装载实例 - 默认空 - 不填使用默认 [ClassLoader] + * @return [LazyClass.Nullable]<[T]> + */ +@JvmName("lazyClassOrNull_Generics") +inline fun lazyClassOrNull(name: String, initialize: Boolean = false, noinline loader: ClassLoaderInitializer? = null) = + LazyClass.Nullable(name, initialize, loader) + +/** + * 懒装载 [Class] + * @param variousClass [VariousClass] + * @param initialize 是否初始化 [Class] 的静态方法块 - 默认否 + * @param loader [ClassLoader] 装载实例 - 默认空 - 不填使用默认 [ClassLoader] + * @return [LazyClass.Nullable] + */ +fun lazyClassOrNull(variousClass: VariousClass, initialize: Boolean = false, loader: ClassLoaderInitializer? = null) = + LazyClass.Nullable(variousClass, initialize, loader) + /** * 通过字符串类名使用指定的 [ClassLoader] 查找是否存在 * @param loader [Class] 所在的 [ClassLoader] - 不填使用默认 [ClassLoader] diff --git a/yukihookapi-core/src/main/java/com/highcapable/yukihookapi/hook/param/PackageParam.kt b/yukihookapi-core/src/main/java/com/highcapable/yukihookapi/hook/param/PackageParam.kt index f6e49d9c..73bb1fd3 100644 --- a/yukihookapi-core/src/main/java/com/highcapable/yukihookapi/hook/param/PackageParam.kt +++ b/yukihookapi-core/src/main/java/com/highcapable/yukihookapi/hook/param/PackageParam.kt @@ -25,7 +25,7 @@ * * This file is created by fankes on 2022/2/2. */ -@file:Suppress("unused", "MemberVisibilityCanBePrivate", "UNCHECKED_CAST", "NON_PUBLIC_CALL_FROM_PUBLIC_INLINE") +@file:Suppress("unused", "MemberVisibilityCanBePrivate", "NON_PUBLIC_CALL_FROM_PUBLIC_INLINE") package com.highcapable.yukihookapi.hook.param @@ -50,9 +50,11 @@ import com.highcapable.yukihookapi.hook.core.finder.base.BaseFinder 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.MethodFinder -import com.highcapable.yukihookapi.hook.core.finder.tools.ReflectionTool import com.highcapable.yukihookapi.hook.core.finder.type.factory.ClassConditions +import com.highcapable.yukihookapi.hook.core.finder.type.factory.ClassLoaderInitializer import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker +import com.highcapable.yukihookapi.hook.factory.LazyClass +import com.highcapable.yukihookapi.hook.factory.hasClass import com.highcapable.yukihookapi.hook.log.YLog import com.highcapable.yukihookapi.hook.param.wrapper.PackageParamWrapper import com.highcapable.yukihookapi.hook.utils.factory.value @@ -66,6 +68,11 @@ import com.highcapable.yukihookapi.hook.xposed.prefs.YukiHookPrefsBridge import java.lang.reflect.Constructor import java.lang.reflect.Member import java.lang.reflect.Method +import com.highcapable.yukihookapi.hook.factory.hasClass as hasClassGlobal +import com.highcapable.yukihookapi.hook.factory.lazyClass as lazyClassGlobal +import com.highcapable.yukihookapi.hook.factory.lazyClassOrNull as lazyClassOrNullGlobal +import com.highcapable.yukihookapi.hook.factory.toClass as toClassGlobal +import com.highcapable.yukihookapi.hook.factory.toClassOrNull as toClassOrNullGlobal /** * 装载 Hook 的目标 APP 入口对象实现类 @@ -505,7 +512,7 @@ open class PackageParam internal constructor(internal var wrapper: PackageParamW * @throws NoClassDefFoundError 如果找不到 [Class] */ fun String.toClass(loader: ClassLoader? = appClassLoader, initialize: Boolean = false) = - ReflectionTool.findClassByName(name = this, loader, initialize) + toClassGlobal(loader, initialize) /** * 通过字符串类名转换为 [loader] 中的实体类 @@ -517,8 +524,7 @@ open class PackageParam internal constructor(internal var wrapper: PackageParamW */ @JvmName("toClass_Generics") inline fun String.toClass(loader: ClassLoader? = appClassLoader, initialize: Boolean = false) = - ReflectionTool.findClassByName(name = this, loader, initialize) as? Class? - ?: error("Target Class type cannot cast to ${T::class.java}") + toClassGlobal(loader, initialize) /** * 通过字符串类名转换为 [loader] 中的实体类 @@ -529,7 +535,7 @@ open class PackageParam internal constructor(internal var wrapper: PackageParamW * @return [Class] or null */ fun String.toClassOrNull(loader: ClassLoader? = appClassLoader, initialize: Boolean = false) = - runCatching { toClass(loader, initialize) }.getOrNull() + toClassOrNullGlobal(loader, initialize) /** * 通过字符串类名转换为 [loader] 中的实体类 @@ -541,7 +547,7 @@ open class PackageParam internal constructor(internal var wrapper: PackageParamW */ @JvmName("toClassOrNull_Generics") inline fun String.toClassOrNull(loader: ClassLoader? = appClassLoader, initialize: Boolean = false) = - runCatching { toClass(loader, initialize) }.getOrNull() + toClassOrNullGlobal(loader, initialize) /** * [VariousClass] 转换为 [loader] 中的实体类 @@ -562,12 +568,74 @@ open class PackageParam internal constructor(internal var wrapper: PackageParamW */ fun VariousClass.toClassOrNull(loader: ClassLoader? = appClassLoader, initialize: Boolean = false) = getOrNull(loader, initialize) + /** + * 懒装载 [Class] + * @param name 完整类名 + * @param initialize 是否初始化 [Class] 的静态方法块 - 默认否 + * @param loader [ClassLoader] 装载实例 - 不填使用 [appClassLoader] + * @return [LazyClass.NonNull] + */ + fun lazyClass(name: String, initialize: Boolean = false, loader: ClassLoaderInitializer? = { appClassLoader }) = + lazyClassGlobal(name, initialize, loader) + + /** + * 懒装载 [Class]<[T]> + * @param name 完整类名 + * @param initialize 是否初始化 [Class] 的静态方法块 - 默认否 + * @param loader [ClassLoader] 装载实例 - 不填使用 [appClassLoader] + * @return [LazyClass.NonNull]<[T]> + */ + @JvmName("lazyClass_Generics") + inline fun lazyClass(name: String, initialize: Boolean = false, noinline loader: ClassLoaderInitializer? = { appClassLoader }) = + lazyClassGlobal(name, initialize, loader) + + /** + * 懒装载 [Class] + * @param variousClass [VariousClass] + * @param initialize 是否初始化 [Class] 的静态方法块 - 默认否 + * @param loader [ClassLoader] 装载实例 - 不填使用 [appClassLoader] + * @return [LazyClass.NonNull] + */ + fun lazyClass(variousClass: VariousClass, initialize: Boolean = false, loader: ClassLoaderInitializer? = { appClassLoader }) = + lazyClassGlobal(variousClass, initialize, loader) + + /** + * 懒装载 [Class] + * @param name 完整类名 + * @param initialize 是否初始化 [Class] 的静态方法块 - 默认否 + * @param loader [ClassLoader] 装载实例 - 不填使用 [appClassLoader] + * @return [LazyClass.Nullable] + */ + fun lazyClassOrNull(name: String, initialize: Boolean = false, loader: ClassLoaderInitializer? = { appClassLoader }) = + lazyClassOrNullGlobal(name, initialize, loader) + + /** + * 懒装载 [Class]<[T]> + * @param name 完整类名 + * @param initialize 是否初始化 [Class] 的静态方法块 - 默认否 + * @param loader [ClassLoader] 装载实例 - 不填使用 [appClassLoader] + * @return [LazyClass.Nullable]<[T]> + */ + @JvmName("lazyClassOrNull_Generics") + inline fun lazyClassOrNull(name: String, initialize: Boolean = false, noinline loader: ClassLoaderInitializer? = { appClassLoader }) = + lazyClassOrNullGlobal(name, initialize, loader) + + /** + * 懒装载 [Class] + * @param variousClass [VariousClass] + * @param initialize 是否初始化 [Class] 的静态方法块 - 默认否 + * @param loader [ClassLoader] 装载实例 - 不填使用 [appClassLoader] + * @return [LazyClass.Nullable] + */ + fun lazyClassOrNull(variousClass: VariousClass, initialize: Boolean = false, loader: ClassLoaderInitializer? = { appClassLoader }) = + lazyClassOrNullGlobal(variousClass, initialize, loader) + /** * 通过字符串类名查找是否存在 * @param loader [Class] 所在的 [ClassLoader] - 不填使用 [appClassLoader] * @return [Boolean] 是否存在 */ - fun String.hasClass(loader: ClassLoader? = appClassLoader) = ReflectionTool.hasClassByName(name = this, loader) + fun String.hasClass(loader: ClassLoader? = appClassLoader) = hasClassGlobal(loader) /** * 查找并装载 [HookClass]