-
Notifications
You must be signed in to change notification settings - Fork 89
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: Object class will not be searched when searching for super class #55
base: master
Are you sure you want to change the base?
Conversation
If `hasExtend` of `Class<*>` returns false, it means that the current super class is the Object class. But should not stop searching for the super class at this time, because there are some classes that do not override the `String()`, `hash()`, and `equal()` methods.
|
因为在xposed环境下,就存在两个不同的 这里是我的 // origin 是被代理对象
internal class ProxyHandler(private val origin: Any) : InvocationHandler {
override fun invoke(proxy: Any?, method: Method, args: Array<out Any?>?): Any? {
// 查找被代理对象的方法
origin.javaClass.method {
superClass() // 包含父类的方法
name = method.name // 代理接口的方法名应该和被代理对象的方法名相同
param {
if (args.isNullOrEmpty() && it.isEmpty()) true // 两个方法参数都为 0
else if (args?.size != it.size) false // 两个方法参数不相同,说明不是同一个方法
else {
// 遍历所有参数判断是否符合能在origin对象中触发
it.forEachIndexed { index, clazz ->
if (args[index] != null && !clazz.isInstance(args[index])) {
return@param false
}
}
true
}
}
}.ignored().onNoSuchMethod {
// 问题出现在这,在调用 `toString()` 方法时居然提示origin对象不存在这个方法
// 于是加了下面这段,问题解决
Any::class.java.method {
name = method.name
}.ignored().onNoSuchMethod {
YLog.error("[ProxyUtils - ${origin.javaClass.simpleName}] is not found this method: $method")
YLog.error("[ProxyUtils] args: ${args?.asList()}")
YLog.error("${origin.javaClass.method{superClass()}.giveAll()}")
return null
}.get(origin).let {
return if (args.isNullOrEmpty()) it.call() else it.call(*args)
}
}.get(origin).let {
return if (args.isNullOrEmpty()) it.call() else it.call(*args)
}
}
} |
恕我没看懂这是在做什么,或者你可以把需要的内容发上来单独写个方法提交? |
这里是一个简单的例子,可以在任何包含依赖的地方执行这里的main方法测试 在第一个InvocationHandler 中哪怕我用到了 import com.highcapable.yukihookapi.hook.factory.method
import java.lang.reflect.InvocationHandler
import java.lang.reflect.Method
import java.lang.reflect.Proxy
/**
* 假设这个类是宿主中的一个类
*/
class A {
fun b(str: String) {
println("这里是业务内容:$str")
}
}
/**
* 下面这段代码写在模块上
*/
fun main() {
val a1: Any = A::class.java.newInstance() // 在模块中我们只能通过反射实例并且赋值成Any,我们没法完成 val a: A = A()的方式
// 但是我可以写一个接口 B,然后利用Proxy
val proxy = Proxy.newProxyInstance(
ClassLoader.getSystemClassLoader(), arrayOf(B::class.java),
object : InvocationHandler {
override fun invoke(proxy: Any?, method: Method, args: Array<out Any>?): Any? {
a1.javaClass.method {
superClass()
name = method.name // 这里只做简单的函数名匹配好了
}.ignored().onNoSuchMethod {
println("$a1 找不到 $method")
return null
}.get(a1).let {
return if (args.isNullOrEmpty()) it.call() else it.call(*args)
}
}
}
)
println("proxy 是否可以转型成 B:${proxy is B}")
if (proxy is B) {
proxy.b("这个是B")
proxy.b("这串代码正常执行")
proxy.b("我可以在模块上任意调用这段代码")
}
// 但是如果我调用 Any 类的方法
// 比如
runCatching { println("直接输出:${proxy.toString()}") }.onFailure { println("直接输出异常:$it") }
runCatching { println("hash值:${proxy.hashCode()}") }.onFailure { println("hash值异常: $it") }
runCatching { println("相等:${proxy.equals(1)}") }.onFailure { println("相等异常:$it") }
// 上面的代码就会异常,但如果能搜索到Any类的方法话,且 Any 肯定是 A 的父类
println("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++")
val proxy2 = Proxy.newProxyInstance(
ClassLoader.getSystemClassLoader(), arrayOf(B::class.java),
object : InvocationHandler {
override fun invoke(proxy: Any?, method: Method, args: Array<out Any>?): Any? {
a1.javaClass.method {
superClass()
name = method.name // 这里只做简单的函数名匹配好了
}.ignored().onNoSuchMethod {
Any::class.java.method {
name = method.name
}.ignored().onNoSuchMethod {
println("$a1 找不到 $method")
return null
}.get(a1).let {
return if (args.isNullOrEmpty()) it.call() else it.call(*args)
}
}.get(a1).let {
return if (args.isNullOrEmpty()) it.call() else it.call(*args)
}
}
}
)
println("proxy2 是否可以转型成 B:${proxy2 is B}")
if (proxy2 is B) {
proxy2.b("这个也是B")
proxy2.b("这串代码正常执行")
proxy2.b("我可以在模块上任意调用这段代码")
}
// 而且下面这段代码正常
runCatching { println("直接输出:${proxy2.toString()}") }.onFailure { println("直接输出异常:$it") }
runCatching { println("hash值:${proxy2.hashCode()}") }.onFailure { println("hash值异常: $it") }
runCatching { println("相等:${proxy2.equals(1)}") }.onFailure { println("相等异常:$it") }
}
interface B {
fun b(str: String)
}
下面是输出结果:
|
你说的对,第一次找不到时才会执行 但是如果第一次搜索是 |
我大概理解你的意思了,但是你这样修改并不严谨,你需要考虑到其它可能的情况,所以请先进行一次测试 |
确实,或许再添加一个 其实或者说压根不需要任何 |
还真不一定可能有奇怪的情况,所以最好是添加一个备用的方案 |
If
hasExtend
ofClass<*>
returns false, it means that the current super class is the Object class. But should not stop searching for the super class at this time, because there are some classes that do not override theString()
,hash()
, andequal()
methods.