Added new function and fix a finding big

This commit is contained in:
2022-04-01 02:55:41 +08:00
parent 2a80e64ee0
commit 6efb90ca9d
4 changed files with 152 additions and 76 deletions

View File

@@ -65,6 +65,19 @@ class ConstructorFinder(
/** [ModifierRules] 实例 */ /** [ModifierRules] 实例 */
private var modifiers: ModifierRules? = null private var modifiers: ModifierRules? = null
/**
* [Constructor] 在当前类中的位置
*
* - 设置后将筛选 [Class.getDeclaredConstructors] 的数组下标
*
* - ❗受到字节码顺序影响 - 请勿完全依赖于此功能
*
* 若 index 小于零则忽略此条件 (等于 -2 为取最后一个)
*
* 可使用 [firstIndex] 和 [lastIndex] 设置首位和末位筛选条件
*/
var index = -1
/** /**
* [Constructor] 参数个数 * [Constructor] 参数个数
* *
@@ -74,6 +87,16 @@ class ConstructorFinder(
*/ */
var paramCount = -1 var paramCount = -1
/** 设置 [Constructor] 在当前类中的位置为首位 */
fun firstIndex() {
index = 0
}
/** 设置 [Constructor] 在当前类中的位置为末位 */
fun lastIndex() {
index = -2
}
/** /**
* [Constructor] 筛选条件 * [Constructor] 筛选条件
* *
@@ -105,7 +128,7 @@ class ConstructorFinder(
* @throws IllegalStateException 如果 [classSet] 为 null * @throws IllegalStateException 如果 [classSet] 为 null
* @throws NoSuchMethodError 如果找不到构造方法 * @throws NoSuchMethodError 如果找不到构造方法
*/ */
private val result get() = ReflectionTool.findConstructor(classSet, modifiers, paramCount, paramTypes) private val result get() = ReflectionTool.findConstructor(classSet, index, modifiers, paramCount, paramTypes)
/** /**
* 设置实例 * 设置实例

View File

@@ -34,7 +34,6 @@ import com.highcapable.yukihookapi.annotation.DoNotUseMethod
import com.highcapable.yukihookapi.hook.core.YukiHookCreater import com.highcapable.yukihookapi.hook.core.YukiHookCreater
import com.highcapable.yukihookapi.hook.core.finder.base.BaseFinder import com.highcapable.yukihookapi.hook.core.finder.base.BaseFinder
import com.highcapable.yukihookapi.hook.core.finder.type.ModifierRules import com.highcapable.yukihookapi.hook.core.finder.type.ModifierRules
import com.highcapable.yukihookapi.hook.log.yLoggerE
import com.highcapable.yukihookapi.hook.utils.ReflectionTool import com.highcapable.yukihookapi.hook.utils.ReflectionTool
import com.highcapable.yukihookapi.hook.utils.runBlocking import com.highcapable.yukihookapi.hook.utils.runBlocking
import java.lang.reflect.Field import java.lang.reflect.Field
@@ -54,10 +53,23 @@ class FieldFinder(
/** [ModifierRules] 实例 */ /** [ModifierRules] 实例 */
private var modifiers: ModifierRules? = null private var modifiers: ModifierRules? = null
/**
* [Field] 在当前类中的位置
*
* - 设置后将筛选 [Class.getDeclaredFields] 的数组下标
*
* - ❗受到字节码顺序影响 - 请勿完全依赖于此功能
*
* 若 index 小于零则忽略此条件 (等于 -2 为取最后一个)
*
* 可使用 [firstIndex] 和 [lastIndex] 设置首位和末位筛选条件
*/
var index = -1
/** /**
* [Field] 名称 * [Field] 名称
* *
* - ❗必须设置 * - ❗若不填写名称则必须存在一个其它条件 - 默认模糊查找并取第一个匹配的 [Field]
*/ */
var name = "" var name = ""
@@ -68,6 +80,16 @@ class FieldFinder(
*/ */
var type: Class<*>? = null var type: Class<*>? = null
/** 设置 [Field] 在当前类中的位置为首位 */
fun firstIndex() {
index = 0
}
/** 设置 [Field] 在当前类中的位置为末位 */
fun lastIndex() {
index = -2
}
/** /**
* [Field] 筛选条件 * [Field] 筛选条件
* *
@@ -87,14 +109,9 @@ class FieldFinder(
* @throws IllegalStateException 如果 [name] 没有被设置 * @throws IllegalStateException 如果 [name] 没有被设置
*/ */
@DoNotUseMethod @DoNotUseMethod
override fun build(isBind: Boolean) = when { override fun build(isBind: Boolean) = try {
name.isBlank() -> {
yLoggerE(msg = "Field name cannot be empty in Class [$classSet] [${hookTag}]")
Result(isNoSuch = true)
}
else -> try {
runBlocking { runBlocking {
memberInstance = ReflectionTool.findField(classSet, name, modifiers, type) memberInstance = ReflectionTool.findField(classSet, index, name, modifiers, type)
}.result { onHookLogMsg(msg = "Find Field [${memberInstance}] takes ${it}ms [${hookTag}]") } }.result { onHookLogMsg(msg = "Find Field [${memberInstance}] takes ${it}ms [${hookTag}]") }
Result() Result()
} catch (e: Throwable) { } catch (e: Throwable) {
@@ -104,7 +121,6 @@ class FieldFinder(
}.start() }.start()
Result(isNoSuch = true, e) Result(isNoSuch = true, e)
} }
}
/** /**
* 创建一个异常结果 * 创建一个异常结果

View File

@@ -36,7 +36,6 @@ import com.highcapable.yukihookapi.annotation.DoNotUseMethod
import com.highcapable.yukihookapi.hook.core.YukiHookCreater import com.highcapable.yukihookapi.hook.core.YukiHookCreater
import com.highcapable.yukihookapi.hook.core.finder.base.BaseFinder import com.highcapable.yukihookapi.hook.core.finder.base.BaseFinder
import com.highcapable.yukihookapi.hook.core.finder.type.ModifierRules import com.highcapable.yukihookapi.hook.core.finder.type.ModifierRules
import com.highcapable.yukihookapi.hook.log.yLoggerE
import com.highcapable.yukihookapi.hook.log.yLoggerW import com.highcapable.yukihookapi.hook.log.yLoggerW
import com.highcapable.yukihookapi.hook.utils.ReflectionTool import com.highcapable.yukihookapi.hook.utils.ReflectionTool
import com.highcapable.yukihookapi.hook.utils.runBlocking import com.highcapable.yukihookapi.hook.utils.runBlocking
@@ -66,10 +65,23 @@ class MethodFinder(
/** [ModifierRules] 实例 */ /** [ModifierRules] 实例 */
private var modifiers: ModifierRules? = null private var modifiers: ModifierRules? = null
/**
* [Method] 在当前类中的位置
*
* - 设置后将筛选 [Class.getDeclaredMethods] 的数组下标
*
* - ❗受到字节码顺序影响 - 请勿完全依赖于此功能
*
* 若 index 小于零则忽略此条件 (等于 -2 为取最后一个)
*
* 可使用 [firstIndex] 和 [lastIndex] 设置首位和末位筛选条件
*/
var index = -1
/** /**
* [Method] 名称 * [Method] 名称
* *
* - ❗必须设置 * - ❗若不填写名称则必须存在一个其它条件 - 默认模糊查找并取第一个匹配的 [Method]
*/ */
var name = "" var name = ""
@@ -89,6 +101,16 @@ class MethodFinder(
*/ */
var returnType: Class<*>? = null var returnType: Class<*>? = null
/** 设置 [Method] 在当前类中的位置为首位 */
fun firstIndex() {
index = 0
}
/** 设置 [Method] 在当前类中的位置为末位 */
fun lastIndex() {
index = -2
}
/** /**
* [Method] 筛选条件 * [Method] 筛选条件
* *
@@ -120,7 +142,7 @@ class MethodFinder(
* @throws IllegalStateException 如果 [classSet] 为 null * @throws IllegalStateException 如果 [classSet] 为 null
* @throws NoSuchMethodError 如果找不到方法 * @throws NoSuchMethodError 如果找不到方法
*/ */
private val result get() = ReflectionTool.findMethod(classSet, name, modifiers, returnType, paramCount, paramTypes) private val result get() = ReflectionTool.findMethod(classSet, index, name, modifiers, returnType, paramCount, paramTypes)
/** /**
* 设置实例 * 设置实例
@@ -140,12 +162,7 @@ class MethodFinder(
* @return [Result] * @return [Result]
*/ */
@DoNotUseMethod @DoNotUseMethod
override fun build(isBind: Boolean) = when { override fun build(isBind: Boolean) = try {
name.isBlank() -> {
yLoggerE(msg = "Method name cannot be empty in Class [$classSet] [${hookTag}]")
Result(isNoSuch = true)
}
else -> try {
runBlocking { runBlocking {
isBindToHooker = isBind isBindToHooker = isBind
setInstance(isBind, result) setInstance(isBind, result)
@@ -155,7 +172,6 @@ class MethodFinder(
onFailureMsg(throwable = e) onFailureMsg(throwable = e)
Result(isNoSuch = true, e) Result(isNoSuch = true, e)
} }
}
/** /**
* 创建一个异常结果 * 创建一个异常结果

View File

@@ -45,6 +45,7 @@ internal object ReflectionTool {
/** /**
* 查找任意变量 * 查找任意变量
* @param classSet 变量所在类 * @param classSet 变量所在类
* @param index 下标
* @param name 变量名称 * @param name 变量名称
* @param modifiers 变量描述 * @param modifiers 变量描述
* @param type 变量类型 * @param type 变量类型
@@ -52,26 +53,31 @@ internal object ReflectionTool {
* @throws IllegalStateException 如果 [classSet] 为 null * @throws IllegalStateException 如果 [classSet] 为 null
* @throws NoSuchFieldError 如果找不到变量 * @throws NoSuchFieldError 如果找不到变量
*/ */
internal fun findField(classSet: Class<*>?, name: String, modifiers: ModifierRules?, type: Class<*>?): Field { internal fun findField(classSet: Class<*>?, index: Int, name: String, modifiers: ModifierRules?, type: Class<*>?): Field {
val hashCode = ("[$name][$type][$modifiers][$classSet]").hashCode() val hashCode = ("[$index][$name][$type][$modifiers][$classSet]").hashCode()
return MemberCacheStore.findField(hashCode) ?: let { return MemberCacheStore.findField(hashCode) ?: let {
var field: Field? = null var field: Field? = null
run { classSet?.declaredFields?.apply {
classSet?.declaredFields?.forEach { forEachIndexed { p, it ->
var conditions = name == it.name var isMatched = false
if (type != null) conditions = conditions && it.type == type var conditions = true
if (modifiers != null) conditions = conditions && modifiers.contains(it) if (name.isNotBlank()) conditions = (name == it.name).also { isMatched = true }
if (conditions) { if (type != null) conditions = (conditions && it.type == type).also { isMatched = true }
if (modifiers != null) conditions = (conditions && modifiers.contains(it)).also { isMatched = true }
if (index == -2) conditions = (conditions && p == lastIndex).also { isMatched = true }
if (index >= 0) conditions = (conditions && p == index).also { isMatched = true }
if (conditions && isMatched) {
field = it.apply { isAccessible = true } field = it.apply { isAccessible = true }
return@run return@apply
}
} }
} ?: error("Can't find this Field [$name] because classSet is null") } ?: error("Can't find this Field [$name] because classSet is null")
}
field?.also { MemberCacheStore.putField(hashCode, field) } field?.also { MemberCacheStore.putField(hashCode, field) }
?: throw NoSuchFieldError( ?: throw NoSuchFieldError(
"Can't find this Field --> " + "Can't find this Field --> " +
"name:[$name] " + "index:[${index.takeIf { it >= 0 } ?: "unspecified"}] " +
"type:[$type] " + "name:[${name.takeIf { it.isNotBlank() } ?: "unspecified"}] " +
"type:[${type ?: "unspecified"}] " +
"modifiers:${modifiers ?: "[]"} " + "modifiers:${modifiers ?: "[]"} " +
"in Class [$classSet] " + "in Class [$classSet] " +
"by $TAG" "by $TAG"
@@ -82,6 +88,7 @@ internal object ReflectionTool {
/** /**
* 查找任意方法 * 查找任意方法
* @param classSet 方法所在类 * @param classSet 方法所在类
* @param index 下标
* @param name 方法名称 * @param name 方法名称
* @param modifiers 方法描述 * @param modifiers 方法描述
* @param returnType 方法返回值 * @param returnType 方法返回值
@@ -93,35 +100,42 @@ internal object ReflectionTool {
*/ */
internal fun findMethod( internal fun findMethod(
classSet: Class<*>?, classSet: Class<*>?,
index: Int,
name: String, name: String,
modifiers: ModifierRules?, modifiers: ModifierRules?,
returnType: Class<*>?, returnType: Class<*>?,
paramCount: Int, paramCount: Int,
paramTypes: Array<out Class<*>>? paramTypes: Array<out Class<*>>?
): Method { ): Method {
val hashCode = ("[$name][$paramCount][${paramTypes.typeOfString()}][$returnType][$modifiers][$classSet]").hashCode() val hashCode = ("[$index][$name][$paramCount][${paramTypes.typeOfString()}][$returnType][$modifiers][$classSet]").hashCode()
return MemberCacheStore.findMethod(hashCode) ?: let { return MemberCacheStore.findMethod(hashCode) ?: let {
var method: Method? = null var method: Method? = null
run { classSet?.declaredMethods?.apply {
classSet?.declaredMethods?.forEach { forEachIndexed { p, it ->
var conditions = name == it.name var isMatched = false
if (returnType != null) conditions = conditions && it.returnType == returnType var conditions = true
if (paramCount >= 0) conditions = conditions && it.parameterTypes.size == paramCount if (name.isNotBlank()) conditions = (name == it.name).also { isMatched = true }
if (paramTypes != null) conditions = conditions && arrayContentsEq(paramTypes, it.parameterTypes) if (returnType != null) conditions = (conditions && it.returnType == returnType).also { isMatched = true }
if (modifiers != null) conditions = conditions && modifiers.contains(it) if (paramCount >= 0) conditions = (conditions && it.parameterTypes.size == paramCount).also { isMatched = true }
if (conditions) { if (paramTypes != null) conditions =
(conditions && arrayContentsEq(paramTypes, it.parameterTypes)).also { isMatched = true }
if (modifiers != null) conditions = (conditions && modifiers.contains(it)).also { isMatched = true }
if (index == -2) conditions = (conditions && p == lastIndex).also { isMatched = true }
if (index >= 0) conditions = (conditions && p == index).also { isMatched = true }
if (conditions && isMatched) {
method = it.apply { isAccessible = true } method = it.apply { isAccessible = true }
return@run return@apply
}
} }
} ?: error("Can't find this Method [$name] because classSet is null") } ?: error("Can't find this Method [$name] because classSet is null")
}
method?.also { MemberCacheStore.putMethod(hashCode, method) } method?.also { MemberCacheStore.putMethod(hashCode, method) }
?: throw NoSuchMethodError( ?: throw NoSuchMethodError(
"Can't find this Method --> " + "Can't find this Method --> " +
"name:[$name] " + "index:[${index.takeIf { it >= 0 } ?: "unspecified"}] " +
"name:[${name.takeIf { it.isNotBlank() } ?: "unspecified"}] " +
"paramCount:[${paramCount.takeIf { it >= 0 } ?: "unspecified"}] " + "paramCount:[${paramCount.takeIf { it >= 0 } ?: "unspecified"}] " +
"paramTypes:[${paramTypes.typeOfString()}] " + "paramTypes:[${paramTypes.typeOfString()}] " +
"returnType:[$returnType] " + "returnType:[${returnType ?: "unspecified"}] " +
"modifiers:${modifiers ?: "[]"} " + "modifiers:${modifiers ?: "[]"} " +
"in Class [$classSet] " + "in Class [$classSet] " +
"by $TAG" "by $TAG"
@@ -132,6 +146,7 @@ internal object ReflectionTool {
/** /**
* 查找任意构造方法 * 查找任意构造方法
* @param classSet 构造方法所在类 * @param classSet 构造方法所在类
* @param index 下标
* @param modifiers 构造方法描述 * @param modifiers 构造方法描述
* @param paramCount 构造方法参数个数 * @param paramCount 构造方法参数个数
* @param paramTypes 构造方法参数类型 * @param paramTypes 构造方法参数类型
@@ -141,28 +156,34 @@ internal object ReflectionTool {
*/ */
internal fun findConstructor( internal fun findConstructor(
classSet: Class<*>?, classSet: Class<*>?,
index: Int,
modifiers: ModifierRules?, modifiers: ModifierRules?,
paramCount: Int, paramCount: Int,
paramTypes: Array<out Class<*>>? paramTypes: Array<out Class<*>>?
): Constructor<*> { ): Constructor<*> {
val hashCode = ("[$paramCount][${paramTypes.typeOfString()}][$modifiers][$classSet]").hashCode() val hashCode = ("[$index][$paramCount][${paramTypes.typeOfString()}][$modifiers][$classSet]").hashCode()
return MemberCacheStore.findConstructor(hashCode) ?: let { return MemberCacheStore.findConstructor(hashCode) ?: let {
var constructor: Constructor<*>? = null var constructor: Constructor<*>? = null
run { classSet?.declaredConstructors?.apply {
classSet?.declaredConstructors?.forEach { forEachIndexed { p, it ->
var conditions = false var isMatched = false
if (paramCount >= 0) conditions = it.parameterTypes.size == paramCount var conditions = true
if (paramTypes != null) conditions = arrayContentsEq(paramTypes, it.parameterTypes) if (paramCount >= 0) conditions = (it.parameterTypes.size == paramCount).also { isMatched = true }
if (modifiers != null) conditions = conditions && modifiers.contains(it) if (paramTypes != null) conditions =
if (conditions) { (conditions && arrayContentsEq(paramTypes, it.parameterTypes)).also { isMatched = true }
if (modifiers != null) conditions = (conditions && modifiers.contains(it)).also { isMatched = true }
if (index == -2) conditions = (conditions && p == lastIndex).also { isMatched = true }
if (index >= 0) conditions = (conditions && p == index).also { isMatched = true }
if (conditions && isMatched) {
constructor = it.apply { isAccessible = true } constructor = it.apply { isAccessible = true }
return@run return@apply
}
} }
} ?: error("Can't find this Constructor because classSet is null") } ?: error("Can't find this Constructor because classSet is null")
}
return constructor?.also { MemberCacheStore.putConstructor(hashCode, constructor) } return constructor?.also { MemberCacheStore.putConstructor(hashCode, constructor) }
?: throw NoSuchMethodError( ?: throw NoSuchMethodError(
"Can't find this Constructor --> " + "Can't find this Constructor --> " +
"index:[${index.takeIf { it >= 0 } ?: "unspecified"}] " +
"paramCount:[${paramCount.takeIf { it >= 0 } ?: "unspecified"}] " + "paramCount:[${paramCount.takeIf { it >= 0 } ?: "unspecified"}] " +
"paramTypes:[${paramTypes.typeOfString()}] " + "paramTypes:[${paramTypes.typeOfString()}] " +
"modifiers:${modifiers ?: "[]"} " + "modifiers:${modifiers ?: "[]"} " +