Android JNI GetMethodID 无法在发布版本中找到方法
Android JNI GetMethodID fails to find a method in release build
我正在 android 应用程序中从 C++ 调用 java 方法。在调试中工作正常,但 GetMethodID 在发布版本中失败。
// Java
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
//...
showKeyboard();
}
public void showKeyboard()
{
Log.i("my_app", "MainActivity::showKeyboard");
//...
}
}
// C++
JavaVM* gJvm; // Saved in JNI_OnLoad()
jobject gMainActivity; // Saved in call Java -> C++
// using JNIEnv->NewGlobalRef(mainActivity)
void my_thread_func() {
JNIEnv* jniEnv = nullptr;
gJvm->AttachCurrentThread(&jniEnv, nullptr);;
jclass activityClass = jniEnv->GetObjectClass(gMainActivity);
jmethodID methodId = jniEnv->GetMethodID(activityClass, "showKeyboard", "()V");
// Debug build: methodId is valid
// Release build: methodId is null
}
仅出于调试目的从 onCreate 调用 showKeyboard。我可以在输出中看到“MainActivity::showKeyboard”这一行。它在调试版本中也按预期工作。
我怀疑 java 优化启动并删除了发布中的方法。虽然它在 onCreate 中被调用,但它可能只是被内联。我试图添加 50 多行日志打印,希望阻止内联,但它没有改变任何东西。
有没有办法禁用此方法的 java 优化?或者我还能如何解决它?
是的,在发布模式下编译代码会启用 Proguard 缩小和混淆。如果你查看 documentation,你会发现几个选项:
- 在
showKeyboard
方法上使用 @Keep annotation。这将被默认的 proguard 规则集获取并防止该方法被重命名或删除。
- 编写自己的 Proguard 规则以保留方法。我认为这应该是这样的:
-keep public class com.example.MainActivity {
public void showKeyboard();
}
我正在 android 应用程序中从 C++ 调用 java 方法。在调试中工作正常,但 GetMethodID 在发布版本中失败。
// Java
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
//...
showKeyboard();
}
public void showKeyboard()
{
Log.i("my_app", "MainActivity::showKeyboard");
//...
}
}
// C++
JavaVM* gJvm; // Saved in JNI_OnLoad()
jobject gMainActivity; // Saved in call Java -> C++
// using JNIEnv->NewGlobalRef(mainActivity)
void my_thread_func() {
JNIEnv* jniEnv = nullptr;
gJvm->AttachCurrentThread(&jniEnv, nullptr);;
jclass activityClass = jniEnv->GetObjectClass(gMainActivity);
jmethodID methodId = jniEnv->GetMethodID(activityClass, "showKeyboard", "()V");
// Debug build: methodId is valid
// Release build: methodId is null
}
仅出于调试目的从 onCreate 调用 showKeyboard。我可以在输出中看到“MainActivity::showKeyboard”这一行。它在调试版本中也按预期工作。
我怀疑 java 优化启动并删除了发布中的方法。虽然它在 onCreate 中被调用,但它可能只是被内联。我试图添加 50 多行日志打印,希望阻止内联,但它没有改变任何东西。
有没有办法禁用此方法的 java 优化?或者我还能如何解决它?
是的,在发布模式下编译代码会启用 Proguard 缩小和混淆。如果你查看 documentation,你会发现几个选项:
- 在
showKeyboard
方法上使用 @Keep annotation。这将被默认的 proguard 规则集获取并防止该方法被重命名或删除。 - 编写自己的 Proguard 规则以保留方法。我认为这应该是这样的:
-keep public class com.example.MainActivity {
public void showKeyboard();
}