ART: Update for split native bridge initialization
Change-Id: I0b93da93251c6b4638de786bf98cf99df07c3fc2
diff --git a/runtime/native/dalvik_system_ZygoteHooks.cc b/runtime/native/dalvik_system_ZygoteHooks.cc
index c3c8c25..e469126 100644
--- a/runtime/native/dalvik_system_ZygoteHooks.cc
+++ b/runtime/native/dalvik_system_ZygoteHooks.cc
@@ -111,15 +111,17 @@
thread->InitAfterFork();
EnableDebugFeatures(debug_flags);
- Runtime::NativeBridgeAction action = Runtime::NativeBridgeAction::kUnload;
if (instruction_set != nullptr) {
ScopedUtfChars isa_string(env, instruction_set);
InstructionSet isa = GetInstructionSetFromString(isa_string.c_str());
+ Runtime::NativeBridgeAction action = Runtime::NativeBridgeAction::kUnload;
if (isa != kNone && isa != kRuntimeISA) {
action = Runtime::NativeBridgeAction::kInitialize;
}
+ Runtime::Current()->DidForkFromZygote(env, action, isa_string.c_str());
+ } else {
+ Runtime::Current()->DidForkFromZygote(env, Runtime::NativeBridgeAction::kUnload, nullptr);
}
- Runtime::Current()->DidForkFromZygote(action);
}
static JNINativeMethod gMethods[] = {
diff --git a/runtime/native_bridge_art_interface.cc b/runtime/native_bridge_art_interface.cc
index 453c92f..fcd11ed 100644
--- a/runtime/native_bridge_art_interface.cc
+++ b/runtime/native_bridge_art_interface.cc
@@ -16,6 +16,9 @@
#include "native_bridge_art_interface.h"
+#include "nativebridge/native_bridge.h"
+
+#include "base/logging.h"
#include "mirror/art_method-inl.h"
#include "mirror/class-inl.h"
#include "scoped_thread_state_change.h"
@@ -91,4 +94,40 @@
return count;
}
+// Native bridge library runtime callbacks. They represent the runtime interface to native bridge.
+//
+// The interface is expected to expose the following methods:
+// getMethodShorty(): in the case of native method calling JNI native function CallXXXXMethodY(),
+// native bridge calls back to VM for the shorty of the method so that it can prepare based on
+// host calling convention.
+// getNativeMethodCount() and getNativeMethods(): in case of JNI function UnregisterNatives(),
+// native bridge can call back to get all native methods of specified class so that all
+// corresponding trampolines can be destroyed.
+static android::NativeBridgeRuntimeCallbacks native_bridge_art_callbacks_ {
+ GetMethodShorty, GetNativeMethodCount, GetNativeMethods
+};
+
+void LoadNativeBridge(std::string& native_bridge_library_filename) {
+ android::LoadNativeBridge(native_bridge_library_filename.c_str(), &native_bridge_art_callbacks_);
+ VLOG(startup) << "Runtime::Setup native bridge library: "
+ << (native_bridge_library_filename.empty() ? "(empty)" : native_bridge_library_filename);
+}
+
+void PreInitializeNativeBridge(std::string dir) {
+ VLOG(startup) << "Runtime::Pre-initialize native bridge";
+ if (unshare(CLONE_NEWNS) == -1) {
+ LOG(WARNING) << "Could not create mount namespace.";
+ return;
+ }
+ android::PreInitializeNativeBridge(dir.c_str(), GetInstructionSetString(kRuntimeISA));
+}
+
+void InitializeNativeBridge(JNIEnv* env, const char* instruction_set) {
+ android::InitializeNativeBridge(env, instruction_set);
+}
+
+void UnloadNativeBridge() {
+ android::UnloadNativeBridge();
+}
+
}; // namespace art
diff --git a/runtime/native_bridge_art_interface.h b/runtime/native_bridge_art_interface.h
index 08735c8..42f0ed2 100644
--- a/runtime/native_bridge_art_interface.h
+++ b/runtime/native_bridge_art_interface.h
@@ -19,15 +19,21 @@
#include <jni.h>
#include <stdint.h>
+#include <string>
namespace art {
-const char* GetMethodShorty(JNIEnv* env, jmethodID mid);
+// Mirror libnativebridge interface. Done to have the ART callbacks out of line, and not require
+// the system/core header file in other files.
-uint32_t GetNativeMethodCount(JNIEnv* env, jclass clazz);
+void LoadNativeBridge(std::string& native_bridge_library_filename);
-uint32_t GetNativeMethods(JNIEnv* env, jclass clazz, JNINativeMethod* methods,
- uint32_t method_count);
+// This is mostly for testing purposes, as in a full system this is called by Zygote code.
+void PreInitializeNativeBridge(std::string dir);
+
+void InitializeNativeBridge(JNIEnv* env, const char* instruction_set);
+
+void UnloadNativeBridge();
}; // namespace art
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 9b24bec..0edf116 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -143,8 +143,7 @@
target_sdk_version_(0),
implicit_null_checks_(false),
implicit_so_checks_(false),
- implicit_suspend_checks_(false),
- native_bridge_art_callbacks_({GetMethodShorty, GetNativeMethodCount, GetNativeMethods}) {
+ implicit_suspend_checks_(false) {
}
Runtime::~Runtime() {
@@ -418,18 +417,23 @@
Thread::FinishStartup();
+ system_class_loader_ = CreateSystemClassLoader();
+
if (is_zygote_) {
if (!InitZygote()) {
return false;
}
} else {
- DidForkFromZygote(NativeBridgeAction::kInitialize);
+ bool have_native_bridge = !native_bridge_library_filename_.empty();
+ if (have_native_bridge) {
+ PreInitializeNativeBridge(".");
+ }
+ DidForkFromZygote(self->GetJniEnv(), have_native_bridge ? NativeBridgeAction::kInitialize :
+ NativeBridgeAction::kUnload, GetInstructionSetString(kRuntimeISA));
}
StartDaemonThreads();
- system_class_loader_ = CreateSystemClassLoader();
-
{
ScopedObjectAccess soa(self);
self->GetJniEnv()->locals.AssertEmpty();
@@ -501,16 +505,16 @@
#endif
}
-void Runtime::DidForkFromZygote(NativeBridgeAction action) {
+void Runtime::DidForkFromZygote(JNIEnv* env, NativeBridgeAction action, const char* isa) {
is_zygote_ = false;
switch (action) {
case NativeBridgeAction::kUnload:
- android::UnloadNativeBridge();
+ UnloadNativeBridge();
break;
case NativeBridgeAction::kInitialize:
- android::InitializeNativeBridge();
+ InitializeNativeBridge(env, isa);
break;
}
@@ -870,10 +874,7 @@
// DidForkFromZygote(kInitialize) -> try to initialize any native bridge given.
// No-op wrt native bridge.
native_bridge_library_filename_ = options->native_bridge_library_filename_;
- android::LoadNativeBridge(native_bridge_library_filename_.c_str(), &native_bridge_art_callbacks_);
- VLOG(startup) << "Runtime::Setup native bridge library: "
- << (native_bridge_library_filename_.empty() ?
- "(empty)" : native_bridge_library_filename_);
+ LoadNativeBridge(native_bridge_library_filename_);
VLOG(startup) << "Runtime::Init exiting";
return true;
diff --git a/runtime/runtime.h b/runtime/runtime.h
index cfb1abc..9a8235d 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -32,7 +32,6 @@
#include "instrumentation.h"
#include "instruction_set.h"
#include "jobject_comparator.h"
-#include "nativebridge/native_bridge.h"
#include "object_callbacks.h"
#include "offsets.h"
#include "profiler_options.h"
@@ -398,7 +397,7 @@
};
void PreZygoteFork();
bool InitZygote();
- void DidForkFromZygote(NativeBridgeAction action);
+ void DidForkFromZygote(JNIEnv* env, NativeBridgeAction action, const char* isa);
const instrumentation::Instrumentation* GetInstrumentation() const {
return &instrumentation_;
@@ -648,17 +647,6 @@
// the native bridge to load it and then gets the trampoline for the entry to native activity.
std::string native_bridge_library_filename_;
- // Native bridge library runtime callbacks. They represent the runtime interface to native bridge.
- //
- // The interface is expected to expose the following methods:
- // getMethodShorty(): in the case of native method calling JNI native function CallXXXXMethodY(),
- // native bridge calls back to VM for the shorty of the method so that it can prepare based on
- // host calling convention.
- // getNativeMethodCount() and getNativeMethods(): in case of JNI function UnregisterNatives(),
- // native bridge can call back to get all native methods of specified class so that all
- // corresponding trampolines can be destroyed.
- android::NativeBridgeRuntimeCallbacks native_bridge_art_callbacks_;
-
DISALLOW_COPY_AND_ASSIGN(Runtime);
};