Android 调用 Java 动态代理方法时 JNI 崩溃
Android JNI Crash when invoking Java Dynamic Proxy method
出于某种原因,我想用 JNI
调用动态代理 class 的方法
步骤:
- 创建动态代理实例
- 调用本机方法并将代理实例作为参数传递
- 使用 jni 调用代理实例上的一些方法
应用代码:
val target = object : ProxyTest {
override fun testVoid() {
Log.e(TAG, "testVoid: ")
}
override fun testString(): String {
Log.e(TAG, "testString: ")
return "hello"
}
}
val proxy = Proxy.newProxyInstance(
classLoader, arrayOf(ProxyTest::class.java)
) { proxy, method, args ->
// if open code below, it will crash on all device
// if not open, it will crash only on android 6.0, mostly on Vivo Y67
//val myargs = args ?: emptyArray()
//method.invoke(target, *myargs)
} as ProxyTest
invokeProxyMethod(proxy)
interface ProxyTest {
fun testVoid()
fun testString(): String
}
本地代码:
extern "C"
JNIEXPORT void JNICALL
Java_com_aprz_mytestdemo_jni_JNIInvokeProxyMethodActivity_invokeProxyMethod(JNIEnv *env,
__unused jobject thiz,
jobject proxy) {
jclass proxy_class = env->GetObjectClass(proxy);
// jmethodID test_void_method_id = env->GetMethodID(proxy_class, "testString", "()Ljava/lang/String;");
jmethodID test_void_method_id = env->GetMethodID(proxy_class, "testVoid", "()V");
LOGD("jmethodId = %d", test_void_method_id == nullptr);
jvalue *args = {};
jobject obj = env->NewLocalRef(proxy);
env->CallVoidMethodA(obj, test_void_method_id, args);
}
这是 android M 预览中的错误,提交 ID:f015c2f4835a9985a8b31cfc810129b69865a6c4。
此外,android JNI 中还有一些错误。
例如:
bool CheckMethodAndSig(ScopedObjectAccess& soa, jobject jobj, jclass jc,
jmethodID mid, Primitive::Type type, InvokeType invoke)
{
...
// **this should be m->GetInterfaceMethodIfProxy(xx)->GetShorty(xxx);**
if (type != Primitive::GetType(m->GetShorty()[0])) {
...
}
出于某种原因,我想用 JNI
调用动态代理 class 的方法步骤:
- 创建动态代理实例
- 调用本机方法并将代理实例作为参数传递
- 使用 jni 调用代理实例上的一些方法
应用代码:
val target = object : ProxyTest {
override fun testVoid() {
Log.e(TAG, "testVoid: ")
}
override fun testString(): String {
Log.e(TAG, "testString: ")
return "hello"
}
}
val proxy = Proxy.newProxyInstance(
classLoader, arrayOf(ProxyTest::class.java)
) { proxy, method, args ->
// if open code below, it will crash on all device
// if not open, it will crash only on android 6.0, mostly on Vivo Y67
//val myargs = args ?: emptyArray()
//method.invoke(target, *myargs)
} as ProxyTest
invokeProxyMethod(proxy)
interface ProxyTest {
fun testVoid()
fun testString(): String
}
本地代码:
extern "C"
JNIEXPORT void JNICALL
Java_com_aprz_mytestdemo_jni_JNIInvokeProxyMethodActivity_invokeProxyMethod(JNIEnv *env,
__unused jobject thiz,
jobject proxy) {
jclass proxy_class = env->GetObjectClass(proxy);
// jmethodID test_void_method_id = env->GetMethodID(proxy_class, "testString", "()Ljava/lang/String;");
jmethodID test_void_method_id = env->GetMethodID(proxy_class, "testVoid", "()V");
LOGD("jmethodId = %d", test_void_method_id == nullptr);
jvalue *args = {};
jobject obj = env->NewLocalRef(proxy);
env->CallVoidMethodA(obj, test_void_method_id, args);
}
这是 android M 预览中的错误,提交 ID:f015c2f4835a9985a8b31cfc810129b69865a6c4。
此外,android JNI 中还有一些错误。 例如:
bool CheckMethodAndSig(ScopedObjectAccess& soa, jobject jobj, jclass jc,
jmethodID mid, Primitive::Type type, InvokeType invoke)
{
...
// **this should be m->GetInterfaceMethodIfProxy(xx)->GetShorty(xxx);**
if (type != Primitive::GetType(m->GetShorty()[0])) {
...
}