android: jni: Add IDCache to cache Java methods.

This commit is contained in:
bunnei 2019-08-24 15:50:19 -04:00
parent 991ec9f2b0
commit ebe77c59f2
6 changed files with 111 additions and 51 deletions

View File

@ -32,8 +32,6 @@ public final class NativeLibrary {
} catch (UnsatisfiedLinkError ex) {
Log.error("[NativeLibrary] " + ex.toString());
}
CacheClassesAndMethods();
}
private NativeLibrary() {
@ -268,13 +266,6 @@ public final class NativeLibrary {
**/
public static native double[] GetPerfStats();
/**
* The methods C++ uses to find references to Java classes and methods
* are really expensive. Rather than calling them every time we want to
* run them, do it once when we load the native library.
*/
private static native void CacheClassesAndMethods();
/**
* Notifies the core emulation that the orientation has changed.
*/

View File

@ -10,6 +10,8 @@ add_library(main SHARED
emu_window/emu_window.h
game_info.cpp
game_info.h
id_cache.cpp
id_cache.h
native.cpp
native.h
)

View File

@ -0,0 +1,93 @@
// Copyright 2019 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "common/common_paths.h"
#include "common/logging/backend.h"
#include "common/logging/filter.h"
#include "common/logging/log.h"
#include "core/settings.h"
#include "jni/id_cache.h"
#include <jni.h>
static constexpr jint JNI_VERSION = JNI_VERSION_1_6;
static JavaVM* s_java_vm;
static jclass s_native_library_class;
static jmethodID s_display_alert_msg;
namespace IDCache {
JNIEnv* GetEnvForThread() {
thread_local static struct OwnedEnv {
OwnedEnv() {
status = s_java_vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6);
if (status == JNI_EDETACHED)
s_java_vm->AttachCurrentThread(&env, nullptr);
}
~OwnedEnv() {
if (status == JNI_EDETACHED)
s_java_vm->DetachCurrentThread();
}
int status;
JNIEnv* env = nullptr;
} owned;
return owned.env;
}
jclass GetNativeLibraryClass() {
return s_native_library_class;
}
jmethodID GetDisplayAlertMsg() {
return s_display_alert_msg;
}
} // namespace IDCache
#ifdef __cplusplus
extern "C" {
#endif
jint JNI_OnLoad(JavaVM* vm, void* reserved) {
s_java_vm = vm;
JNIEnv* env;
if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION) != JNI_OK)
return JNI_ERR;
// Initialize Logger
Log::Filter log_filter;
log_filter.ParseFilterString(Settings::values.log_filter);
Log::SetGlobalFilter(log_filter);
Log::AddBackend(std::make_unique<Log::ColorConsoleBackend>());
FileUtil::CreateFullPath(FileUtil::GetUserPath(FileUtil::UserPath::LogDir));
Log::AddBackend(std::make_unique<Log::FileBackend>(
FileUtil::GetUserPath(FileUtil::UserPath::LogDir) + LOG_FILE));
LOG_INFO(Frontend, "Logging backend initialised");
// Initialize Java methods
const jclass native_library_class = env->FindClass("org/citra/citra_android/NativeLibrary");
s_native_library_class = reinterpret_cast<jclass>(env->NewGlobalRef(native_library_class));
s_display_alert_msg = env->GetStaticMethodID(s_native_library_class, "displayAlertMsg",
"(Ljava/lang/String;Ljava/lang/String;Z)Z");
return JNI_VERSION;
}
void JNI_OnUnload(JavaVM* vm, void* reserved) {
JNIEnv* env;
if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION) != JNI_OK) {
return;
}
env->DeleteGlobalRef(s_native_library_class);
}
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,15 @@
// Copyright 2019 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <jni.h>
namespace IDCache {
JNIEnv* GetEnvForThread();
jclass GetNativeLibraryClass();
jmethodID GetDisplayAlertMsg();
} // namespace IDCache

View File

@ -12,10 +12,7 @@
#include <android/native_window_jni.h>
#include <jni.h>
#include "common/common_paths.h"
#include "common/file_util.h"
#include "common/logging/backend.h"
#include "common/logging/filter.h"
#include "common/logging/log.h"
#include "common/scm_rev.h"
#include "common/scope_exit.h"
@ -32,13 +29,12 @@
#include "jni/config.h"
#include "jni/emu_window/emu_window.h"
#include "jni/game_info.h"
#include "jni/id_cache.h"
#include "jni/native.h"
#include "network/network.h"
#include "video_core/renderer_base.h"
#include "video_core/video_core.h"
JavaVM* g_java_vm;
namespace {
ANativeWindow* s_surf;
@ -56,27 +52,6 @@ std::condition_variable running_cv;
} // Anonymous namespace
/**
* Cache the JavaVM so that we can call into it later.
*/
jint JNI_OnLoad(JavaVM* vm, void* reserved) {
g_java_vm = vm;
// Initialise Logger
Log::Filter log_filter;
log_filter.ParseFilterString(Settings::values.log_filter);
Log::SetGlobalFilter(log_filter);
Log::AddBackend(std::make_unique<Log::ColorConsoleBackend>());
FileUtil::CreateFullPath(FileUtil::GetUserPath(FileUtil::UserPath::LogDir));
Log::AddBackend(std::make_unique<Log::FileBackend>(
FileUtil::GetUserPath(FileUtil::UserPath::LogDir) + LOG_FILE));
LOG_INFO(Frontend, "Logging backend initialised");
return JNI_VERSION_1_6;
}
static int RunCitra(const std::string& filepath) {
LOG_INFO(Frontend, "Citra is Starting");
@ -181,19 +156,6 @@ void Java_org_citra_citra_1android_NativeLibrary_SurfaceChanged(JNIEnv* env, job
void Java_org_citra_citra_1android_NativeLibrary_SurfaceDestroyed(JNIEnv* env, jobject obj) {}
void Java_org_citra_citra_1android_NativeLibrary_CacheClassesAndMethods(JNIEnv* env, jobject obj) {
// This class reference is only valid for the lifetime of this method.
jclass localClass = env->FindClass("org/citra/citra_android/NativeLibrary");
// This reference, however, is valid until we delete it.
s_jni_class = reinterpret_cast<jclass>(env->NewGlobalRef(localClass));
// Method signature taken from javap -s
// Source/Android/app/build/intermediates/classes/arm/debug/org/dolphinemu/dolphinemu/NativeLibrary.class
s_jni_method_alert = env->GetStaticMethodID(s_jni_class, "displayAlertMsg",
"(Ljava/lang/String;Ljava/lang/String;Z)Z");
}
void Java_org_citra_citra_1android_NativeLibrary_NotifyOrientationChange(
JNIEnv* env, jobject obj, jint layout_option, jboolean is_portrait_mode) {
Settings::values.layout_option = static_cast<Settings::LayoutOption>(layout_option);

View File

@ -136,9 +136,6 @@ JNIEXPORT void JNICALL Java_org_citra_citra_1android_NativeLibrary_SetProfiling(
JNIEXPORT void JNICALL Java_org_citra_citra_1android_NativeLibrary_WriteProfileResults(JNIEnv* env,
jobject obj);
JNIEXPORT void JNICALL
Java_org_citra_citra_1android_NativeLibrary_CacheClassesAndMethods(JNIEnv* env, jobject obj);
JNIEXPORT void JNICALL Java_org_citra_citra_1android_NativeLibrary_NotifyOrientationChange(
JNIEnv* env, jobject obj, jint layout_option, jboolean is_portrait_mode);