summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Gampe <agampe@google.com>2015-03-02 20:57:47 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2015-03-02 20:59:13 +0000
commit9924fd8f27e020e9336a085333ef7c68699b8c22 (patch)
tree0d68afb266795d2dfaf8ce152710e0b56cf2a2df
parent0b25c71ac93fb10c484dbacb9e23db505a8e2353 (diff)
parent324b9bb2f48be39e20077c1d7da45cf3dc47fe06 (diff)
downloadart-9924fd8f27e020e9336a085333ef7c68699b8c22.zip
art-9924fd8f27e020e9336a085333ef7c68699b8c22.tar.gz
art-9924fd8f27e020e9336a085333ef7c68699b8c22.tar.bz2
Merge "ART: Move DexFile vector to Java array"
-rw-r--r--runtime/class_linker.cc11
-rw-r--r--runtime/native/dalvik_system_DexFile.cc186
-rw-r--r--runtime/native/dalvik_system_DexFile.h2
-rw-r--r--runtime/well_known_classes.cc2
4 files changed, 134 insertions, 67 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index ee5eefb..03c5a11 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -2133,15 +2133,16 @@ mirror::Class* ClassLinker::FindClassInPathClassLoader(ScopedObjectAccessAlready
}
mirror::Object* dex_file = dex_file_field->GetObject(element);
if (dex_file != nullptr) {
- const uint64_t cookie = cookie_field->GetLong(dex_file);
- auto* dex_files =
- reinterpret_cast<std::vector<const DexFile*>*>(static_cast<uintptr_t>(cookie));
- if (dex_files == nullptr) {
+ mirror::LongArray* long_array = cookie_field->GetObject(dex_file)->AsLongArray();
+ if (long_array == nullptr) {
// This should never happen so log a warning.
LOG(WARNING) << "Null DexFile::mCookie for " << descriptor;
break;
}
- for (const DexFile* cp_dex_file : *dex_files) {
+ int32_t long_array_size = long_array->GetLength();
+ for (int32_t j = 0; j < long_array_size; ++j) {
+ const DexFile* cp_dex_file = reinterpret_cast<const DexFile*>(static_cast<uintptr_t>(
+ long_array->GetWithoutChecks(j)));
const DexFile::ClassDef* dex_class_def = cp_dex_file->FindClassDef(descriptor, hash);
if (dex_class_def != nullptr) {
RegisterDexFile(*cp_dex_file);
diff --git a/runtime/native/dalvik_system_DexFile.cc b/runtime/native/dalvik_system_DexFile.cc
index 037072d..e1fe3eb 100644
--- a/runtime/native/dalvik_system_DexFile.cc
+++ b/runtime/native/dalvik_system_DexFile.cc
@@ -58,6 +58,70 @@
namespace art {
+static std::unique_ptr<std::vector<const DexFile*>>
+ConvertJavaArrayToNative(JNIEnv* env, jobject arrayObject) {
+ jarray array = reinterpret_cast<jarray>(arrayObject);
+
+ jsize array_size = env->GetArrayLength(array);
+ if (env->ExceptionCheck() == JNI_TRUE) {
+ return std::unique_ptr<std::vector<const DexFile*>>();
+ }
+
+ // TODO: Optimize. On 32bit we can use an int array.
+ jboolean is_long_data_copied;
+ jlong* long_data = env->GetLongArrayElements(reinterpret_cast<jlongArray>(array),
+ &is_long_data_copied);
+ if (env->ExceptionCheck() == JNI_TRUE) {
+ return std::unique_ptr<std::vector<const DexFile*>>();
+ }
+
+ std::unique_ptr<std::vector<const DexFile*>> ret(new std::vector<const DexFile*>());
+ ret->reserve(array_size);
+ for (jsize i = 0; i < array_size; ++i) {
+ ret->push_back(reinterpret_cast<const DexFile*>(static_cast<uintptr_t>(*(long_data + i))));
+ }
+
+ env->ReleaseLongArrayElements(reinterpret_cast<jlongArray>(array), long_data, JNI_ABORT);
+ if (env->ExceptionCheck() == JNI_TRUE) {
+ return std::unique_ptr<std::vector<const DexFile*>>();
+ }
+
+ return ret;
+}
+
+static jlongArray ConvertNativeToJavaArray(JNIEnv* env,
+ std::vector<std::unique_ptr<const DexFile>>& vec) {
+ size_t vec_size = vec.size();
+ jlongArray long_array = env->NewLongArray(static_cast<jsize>(vec_size));
+ if (env->ExceptionCheck() == JNI_TRUE) {
+ return nullptr;
+ }
+
+ jboolean is_long_data_copied;
+ jlong* long_data = env->GetLongArrayElements(long_array, &is_long_data_copied);
+ if (env->ExceptionCheck() == JNI_TRUE) {
+ return nullptr;
+ }
+
+ jlong* tmp = long_data;
+ for (auto& dex_file : vec) {
+ *tmp = reinterpret_cast<uintptr_t>(dex_file.get());
+ tmp++;
+ }
+
+ env->ReleaseLongArrayElements(long_array, long_data, 0);
+ if (env->ExceptionCheck() == JNI_TRUE) {
+ return nullptr;
+ }
+
+ // Now release all the unique_ptrs.
+ for (auto& dex_file : vec) {
+ dex_file.release();
+ }
+
+ return long_array;
+}
+
// A smart pointer that provides read-only access to a Java string's UTF chars.
// Unlike libcore's NullableScopedUtfChars, this will *not* throw NullPointerException if
// passed a null jstring. The correct idiom is:
@@ -104,7 +168,7 @@ class NullableScopedUtfChars {
void operator=(const NullableScopedUtfChars&);
};
-static jlong DexFile_openDexFileNative(JNIEnv* env, jclass, jstring javaSourceName, jstring javaOutputName, jint) {
+static jobject DexFile_openDexFileNative(JNIEnv* env, jclass, jstring javaSourceName, jstring javaOutputName, jint) {
ScopedUtfChars sourceName(env, javaSourceName);
if (sourceName.c_str() == NULL) {
return 0;
@@ -115,20 +179,26 @@ static jlong DexFile_openDexFileNative(JNIEnv* env, jclass, jstring javaSourceNa
}
ClassLinker* linker = Runtime::Current()->GetClassLinker();
- std::unique_ptr<std::vector<std::unique_ptr<const DexFile>>> dex_files(
- new std::vector<std::unique_ptr<const DexFile>>());
+ std::vector<std::unique_ptr<const DexFile>> dex_files;
std::vector<std::string> error_msgs;
bool success = linker->OpenDexFilesFromOat(sourceName.c_str(), outputName.c_str(), &error_msgs,
- dex_files.get());
+ &dex_files);
- if (success || !dex_files->empty()) {
- // In the case of non-success, we have not found or could not generate the oat file.
- // But we may still have found a dex file that we can use.
- return static_cast<jlong>(reinterpret_cast<uintptr_t>(dex_files.release()));
+ if (success || !dex_files.empty()) {
+ jlongArray array = ConvertNativeToJavaArray(env, dex_files);
+ if (array == nullptr) {
+ ScopedObjectAccess soa(env);
+ for (auto& dex_file : dex_files) {
+ if (Runtime::Current()->GetClassLinker()->IsDexFileRegistered(*dex_file)) {
+ dex_file.release();
+ }
+ }
+ }
+ return array;
} else {
// The vector should be empty after a failed loading attempt.
- DCHECK_EQ(0U, dex_files->size());
+ DCHECK_EQ(0U, dex_files.size());
ScopedObjectAccess soa(env);
CHECK(!error_msgs.empty());
@@ -140,27 +210,17 @@ static jlong DexFile_openDexFileNative(JNIEnv* env, jclass, jstring javaSourceNa
ThrowWrappedIOException("%s", it->c_str());
}
- return 0;
+ return nullptr;
}
}
-static std::vector<std::unique_ptr<const DexFile>>*
-toDexFiles(jlong dex_file_address, JNIEnv* env) {
- std::vector<std::unique_ptr<const DexFile>>* dex_files
- = reinterpret_cast<std::vector<std::unique_ptr<const DexFile>>*>(
- static_cast<uintptr_t>(dex_file_address));
- if (UNLIKELY(dex_files == nullptr)) {
- ScopedObjectAccess soa(env);
- ThrowNullPointerException(NULL, "dex_file == null");
- }
- return dex_files;
-}
-
-static void DexFile_closeDexFile(JNIEnv* env, jclass, jlong cookie) {
- std::unique_ptr<std::vector<std::unique_ptr<const DexFile>>> dex_files(toDexFiles(cookie, env));
+static void DexFile_closeDexFile(JNIEnv* env, jclass, jobject cookie) {
+ std::unique_ptr<std::vector<const DexFile*>> dex_files = ConvertJavaArrayToNative(env, cookie);
if (dex_files.get() == nullptr) {
+ DCHECK(env->ExceptionCheck());
return;
}
+
ScopedObjectAccess soa(env);
// The Runtime currently never unloads classes, which means any registered
@@ -171,19 +231,21 @@ static void DexFile_closeDexFile(JNIEnv* env, jclass, jlong cookie) {
// TODO: The Runtime should support unloading of classes and freeing of the
// dex files for those unloaded classes rather than leaking dex files here.
for (auto& dex_file : *dex_files) {
- if (Runtime::Current()->GetClassLinker()->IsDexFileRegistered(*dex_file)) {
- dex_file.release();
+ if (!Runtime::Current()->GetClassLinker()->IsDexFileRegistered(*dex_file)) {
+ delete dex_file;
}
}
}
static jclass DexFile_defineClassNative(JNIEnv* env, jclass, jstring javaName, jobject javaLoader,
- jlong cookie) {
- std::vector<std::unique_ptr<const DexFile>>* dex_files = toDexFiles(cookie, env);
- if (dex_files == NULL) {
+ jobject cookie) {
+ std::unique_ptr<std::vector<const DexFile*>> dex_files = ConvertJavaArrayToNative(env, cookie);
+ if (dex_files.get() == nullptr) {
VLOG(class_linker) << "Failed to find dex_file";
- return NULL;
+ DCHECK(env->ExceptionCheck());
+ return nullptr;
}
+
ScopedUtfChars class_name(env, javaName);
if (class_name.c_str() == NULL) {
VLOG(class_linker) << "Failed to find class_name";
@@ -221,36 +283,38 @@ struct CharPointerComparator {
};
// Note: this can be an expensive call, as we sort out duplicates in MultiDex files.
-static jobjectArray DexFile_getClassNameList(JNIEnv* env, jclass, jlong cookie) {
- jobjectArray result = nullptr;
- std::vector<std::unique_ptr<const DexFile>>* dex_files = toDexFiles(cookie, env);
-
- if (dex_files != nullptr) {
- // Push all class descriptors into a set. Use set instead of unordered_set as we want to
- // retrieve all in the end.
- std::set<const char*, CharPointerComparator> descriptors;
- for (auto& dex_file : *dex_files) {
- for (size_t i = 0; i < dex_file->NumClassDefs(); ++i) {
- const DexFile::ClassDef& class_def = dex_file->GetClassDef(i);
- const char* descriptor = dex_file->GetClassDescriptor(class_def);
- descriptors.insert(descriptor);
- }
+static jobjectArray DexFile_getClassNameList(JNIEnv* env, jclass, jobject cookie) {
+ std::unique_ptr<std::vector<const DexFile*>> dex_files = ConvertJavaArrayToNative(env, cookie);
+ if (dex_files.get() == nullptr) {
+ DCHECK(env->ExceptionCheck());
+ return nullptr;
+ }
+
+ // Push all class descriptors into a set. Use set instead of unordered_set as we want to
+ // retrieve all in the end.
+ std::set<const char*, CharPointerComparator> descriptors;
+ for (auto& dex_file : *dex_files) {
+ for (size_t i = 0; i < dex_file->NumClassDefs(); ++i) {
+ const DexFile::ClassDef& class_def = dex_file->GetClassDef(i);
+ const char* descriptor = dex_file->GetClassDescriptor(class_def);
+ descriptors.insert(descriptor);
}
+ }
- // Now create output array and copy the set into it.
- result = env->NewObjectArray(descriptors.size(), WellKnownClasses::java_lang_String, nullptr);
- if (result != nullptr) {
- auto it = descriptors.begin();
- auto it_end = descriptors.end();
- jsize i = 0;
- for (; it != it_end; it++, ++i) {
- std::string descriptor(DescriptorToDot(*it));
- ScopedLocalRef<jstring> jdescriptor(env, env->NewStringUTF(descriptor.c_str()));
- if (jdescriptor.get() == nullptr) {
- return nullptr;
- }
- env->SetObjectArrayElement(result, i, jdescriptor.get());
+ // Now create output array and copy the set into it.
+ jobjectArray result = env->NewObjectArray(descriptors.size(), WellKnownClasses::java_lang_String,
+ nullptr);
+ if (result != nullptr) {
+ auto it = descriptors.begin();
+ auto it_end = descriptors.end();
+ jsize i = 0;
+ for (; it != it_end; it++, ++i) {
+ std::string descriptor(DescriptorToDot(*it));
+ ScopedLocalRef<jstring> jdescriptor(env, env->NewStringUTF(descriptor.c_str()));
+ if (jdescriptor.get() == nullptr) {
+ return nullptr;
}
+ env->SetObjectArrayElement(result, i, jdescriptor.get());
}
}
return result;
@@ -620,12 +684,12 @@ static jboolean DexFile_isDexOptNeeded(JNIEnv* env, jclass, jstring javaFilename
static JNINativeMethod gMethods[] = {
- NATIVE_METHOD(DexFile, closeDexFile, "(J)V"),
- NATIVE_METHOD(DexFile, defineClassNative, "(Ljava/lang/String;Ljava/lang/ClassLoader;J)Ljava/lang/Class;"),
- NATIVE_METHOD(DexFile, getClassNameList, "(J)[Ljava/lang/String;"),
+ NATIVE_METHOD(DexFile, closeDexFile, "(Ljava/lang/Object;)V"),
+ NATIVE_METHOD(DexFile, defineClassNative, "(Ljava/lang/String;Ljava/lang/ClassLoader;Ljava/lang/Object;)Ljava/lang/Class;"),
+ NATIVE_METHOD(DexFile, getClassNameList, "(Ljava/lang/Object;)[Ljava/lang/String;"),
NATIVE_METHOD(DexFile, isDexOptNeeded, "(Ljava/lang/String;)Z"),
NATIVE_METHOD(DexFile, isDexOptNeededInternal, "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)B"),
- NATIVE_METHOD(DexFile, openDexFileNative, "(Ljava/lang/String;Ljava/lang/String;I)J"),
+ NATIVE_METHOD(DexFile, openDexFileNative, "(Ljava/lang/String;Ljava/lang/String;I)Ljava/lang/Object;"),
};
void register_dalvik_system_DexFile(JNIEnv* env) {
diff --git a/runtime/native/dalvik_system_DexFile.h b/runtime/native/dalvik_system_DexFile.h
index 487df05..7585ab9 100644
--- a/runtime/native/dalvik_system_DexFile.h
+++ b/runtime/native/dalvik_system_DexFile.h
@@ -21,6 +21,8 @@
namespace art {
+class DexFile;
+
void register_dalvik_system_DexFile(JNIEnv* env);
} // namespace art
diff --git a/runtime/well_known_classes.cc b/runtime/well_known_classes.cc
index e368d2c..78185bf 100644
--- a/runtime/well_known_classes.cc
+++ b/runtime/well_known_classes.cc
@@ -222,7 +222,7 @@ void WellKnownClasses::Init(JNIEnv* env) {
org_apache_harmony_dalvik_ddmc_DdmServer_broadcast = CacheMethod(env, org_apache_harmony_dalvik_ddmc_DdmServer, true, "broadcast", "(I)V");
org_apache_harmony_dalvik_ddmc_DdmServer_dispatch = CacheMethod(env, org_apache_harmony_dalvik_ddmc_DdmServer, true, "dispatch", "(I[BII)Lorg/apache/harmony/dalvik/ddmc/Chunk;");
- dalvik_system_DexFile_cookie = CacheField(env, dalvik_system_DexFile, false, "mCookie", "J");
+ dalvik_system_DexFile_cookie = CacheField(env, dalvik_system_DexFile, false, "mCookie", "Ljava/lang/Object;");
dalvik_system_PathClassLoader_pathList = CacheField(env, dalvik_system_PathClassLoader, false, "pathList", "Ldalvik/system/DexPathList;");
dalvik_system_DexPathList_dexElements = CacheField(env, dalvik_system_DexPathList, false, "dexElements", "[Ldalvik/system/DexPathList$Element;");
dalvik_system_DexPathList__Element_dexFile = CacheField(env, dalvik_system_DexPathList__Element, false, "dexFile", "Ldalvik/system/DexFile;");