Set parent namespace for linker-namespaces

This change allows applications to share RTLD_GLOBAL
native libraries between namespaces associated with
different classloaders.

The rule is - if a library is GLOBAL within namespace
associated with parent classloader, it is shared
with namespace associated with this classloader

Note that the sharing happens on create_namespace
event, which is tied to createClassloader in case of
application classloaders created by the framework, for
custom application classloaders it is tied to first
loadLibrary() event.

Bug: http://b/28560538
Bug: https://code.google.com/p/android/issues/detail?id=208458
Change-Id: I7ee701166f8ec5eff033b7acc0f80c7aa4ec5bda
This commit is contained in:
Dimitry Ivanov 2016-05-12 15:34:41 -07:00
parent a214a769f9
commit 24db75c1ce
2 changed files with 29 additions and 2 deletions

View File

@ -83,7 +83,8 @@ extern struct android_namespace_t* android_create_namespace(const char* name,
const char* ld_library_path,
const char* default_library_path,
uint64_t type,
const char* permitted_when_isolated_path);
const char* permitted_when_isolated_path,
android_namespace_t* parent);
__END_DECLS

View File

@ -95,11 +95,14 @@ class LibraryNamespaces {
namespace_type |= ANDROID_NAMESPACE_TYPE_SHARED;
}
android_namespace_t* parent_ns = FindParentNamespaceByClassLoader(env, class_loader);
ns = android_create_namespace("classloader-namespace",
nullptr,
library_path.c_str(),
namespace_type,
permitted_path.c_str());
permitted_path.c_str(),
parent_ns);
if (ns != nullptr) {
namespaces_.push_back(std::make_pair(env->NewWeakGlobalRef(class_loader), ns));
@ -200,6 +203,29 @@ class LibraryNamespaces {
return initialized_;
}
jobject GetParentClassLoader(JNIEnv* env, jobject class_loader) {
jclass class_loader_class = env->FindClass("java/lang/ClassLoader");
jmethodID get_parent = env->GetMethodID(class_loader_class,
"getParent",
"()Ljava/lang/ClassLoader;");
return env->CallObjectMethod(class_loader, get_parent);
}
android_namespace_t* FindParentNamespaceByClassLoader(JNIEnv* env, jobject class_loader) {
jobject parent_class_loader = GetParentClassLoader(env, class_loader);
while (parent_class_loader != nullptr) {
android_namespace_t* ns = FindNamespaceByClassLoader(env, parent_class_loader);
if (ns != nullptr) {
return ns;
}
parent_class_loader = GetParentClassLoader(env, parent_class_loader);
}
return nullptr;
}
bool initialized_;
std::vector<std::pair<jweak, android_namespace_t*>> namespaces_;
std::string public_libraries_;