summaryrefslogtreecommitdiff
path: root/runtime/java_vm_ext.cc
diff options
context:
space:
mode:
author Alex Light <allight@google.com> 2016-08-11 10:48:03 -0700
committer Alex Light <allight@google.com> 2016-08-11 13:55:03 -0700
commit185d134a3b43ab7529053e965917e0fa74bceba4 (patch)
tree5d3d0cee3aa4c64fc5f36fd5f648e53f6df984ae /runtime/java_vm_ext.cc
parent7233c7e752c0d26387d143ee74420e9cd1f09390 (diff)
Add basic runtime-plugins support.
This allows one to pass shared-libraries on the command line that the runtime will load as plugins. They have access to runtime code and can install hooks to add functionality. Currently the only hook they can touch is JavaVMExt::AddEnvironmentHook to register a callback for GetEnv(). More hooks might be added in the future. Test: ./test/run-test 900 Change-Id: I852b4daf5a3fa71e9888722bc07794632c0e5010
Diffstat (limited to 'runtime/java_vm_ext.cc')
-rw-r--r--runtime/java_vm_ext.cc42
1 files changed, 28 insertions, 14 deletions
diff --git a/runtime/java_vm_ext.cc b/runtime/java_vm_ext.cc
index c644cde5db..2401bec9f3 100644
--- a/runtime/java_vm_ext.cc
+++ b/runtime/java_vm_ext.cc
@@ -48,7 +48,7 @@ static size_t gGlobalsMax = 51200; // Arbitrary sanity check. (Must fit in 16 b
static const size_t kWeakGlobalsInitial = 16; // Arbitrary.
static const size_t kWeakGlobalsMax = 51200; // Arbitrary sanity check. (Must fit in 16 bits.)
-static bool IsBadJniVersion(int version) {
+bool JavaVMExt::IsBadJniVersion(int version) {
// We don't support JNI_VERSION_1_1. These are the only other valid versions.
return version != JNI_VERSION_1_2 && version != JNI_VERSION_1_4 && version != JNI_VERSION_1_6;
}
@@ -344,13 +344,6 @@ class JII {
}
static jint GetEnv(JavaVM* vm, void** env, jint version) {
- // GetEnv always returns a JNIEnv* for the most current supported JNI version,
- // and unlike other calls that take a JNI version doesn't care if you supply
- // JNI_VERSION_1_1, which we don't otherwise support.
- if (IsBadJniVersion(version) && version != JNI_VERSION_1_1) {
- LOG(ERROR) << "Bad JNI version passed to GetEnv: " << version;
- return JNI_EVERSION;
- }
if (vm == nullptr || env == nullptr) {
return JNI_ERR;
}
@@ -359,8 +352,8 @@ class JII {
*env = nullptr;
return JNI_EDETACHED;
}
- *env = thread->GetJniEnv();
- return JNI_OK;
+ JavaVMExt* raw_vm = reinterpret_cast<JavaVMExt*>(vm);
+ return raw_vm->HandleGetEnv(env, version);
}
private:
@@ -388,7 +381,7 @@ class JII {
const char* thread_name = nullptr;
jobject thread_group = nullptr;
if (args != nullptr) {
- if (IsBadJniVersion(args->version)) {
+ if (JavaVMExt::IsBadJniVersion(args->version)) {
LOG(ERROR) << "Bad JNI version passed to "
<< (as_daemon ? "AttachCurrentThreadAsDaemon" : "AttachCurrentThread") << ": "
<< args->version;
@@ -436,7 +429,8 @@ JavaVMExt::JavaVMExt(Runtime* runtime, const RuntimeArgumentMap& runtime_options
weak_globals_lock_("JNI weak global reference table lock", kJniWeakGlobalsLock),
weak_globals_(kWeakGlobalsInitial, kWeakGlobalsMax, kWeakGlobal),
allow_accessing_weak_globals_(true),
- weak_globals_add_condition_("weak globals add condition", weak_globals_lock_) {
+ weak_globals_add_condition_("weak globals add condition", weak_globals_lock_),
+ env_hooks_() {
functions = unchecked_functions_;
SetCheckJniEnabled(runtime_options.Exists(RuntimeArgumentMap::CheckJni));
}
@@ -444,6 +438,26 @@ JavaVMExt::JavaVMExt(Runtime* runtime, const RuntimeArgumentMap& runtime_options
JavaVMExt::~JavaVMExt() {
}
+jint JavaVMExt::HandleGetEnv(/*out*/void** env, jint version) {
+ for (GetEnvHook hook : env_hooks_) {
+ jint res = hook(this, env, version);
+ if (res == JNI_OK) {
+ return JNI_OK;
+ } else if (res != JNI_EVERSION) {
+ LOG(ERROR) << "Error returned from a plugin GetEnv handler! " << res;
+ return res;
+ }
+ }
+ LOG(ERROR) << "Bad JNI version passed to GetEnv: " << version;
+ return JNI_EVERSION;
+}
+
+// Add a hook to handle getting environments from the GetEnv call.
+void JavaVMExt::AddEnvironmentHook(GetEnvHook hook) {
+ CHECK(hook != nullptr) << "environment hooks shouldn't be null!";
+ env_hooks_.push_back(hook);
+}
+
void JavaVMExt::JniAbort(const char* jni_function_name, const char* msg) {
Thread* self = Thread::Current();
ScopedObjectAccess soa(self);
@@ -866,7 +880,7 @@ bool JavaVMExt::LoadNativeLibrary(JNIEnv* env,
if (version == JNI_ERR) {
StringAppendF(error_msg, "JNI_ERR returned from JNI_OnLoad in \"%s\"", path.c_str());
- } else if (IsBadJniVersion(version)) {
+ } else if (JavaVMExt::IsBadJniVersion(version)) {
StringAppendF(error_msg, "Bad JNI version returned from JNI_OnLoad in \"%s\": %d",
path.c_str(), version);
// It's unwise to call dlclose() here, but we can mark it
@@ -939,7 +953,7 @@ void JavaVMExt::VisitRoots(RootVisitor* visitor) {
extern "C" jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {
ScopedTrace trace(__FUNCTION__);
const JavaVMInitArgs* args = static_cast<JavaVMInitArgs*>(vm_args);
- if (IsBadJniVersion(args->version)) {
+ if (JavaVMExt::IsBadJniVersion(args->version)) {
LOG(ERROR) << "Bad JNI version passed to CreateJavaVM: " << args->version;
return JNI_EVERSION;
}