diff options
| author | 2017-09-12 00:54:26 -0700 | |
|---|---|---|
| committer | 2017-11-01 08:47:23 -0700 | |
| commit | 20c46443ee06060838643abd7a2dcad339f71358 (patch) | |
| tree | 5b77f909c9bd2f9b4adbc4a3a47f39696f3583f0 | |
| parent | 4536a234e56aa7038198ab8c124fe117ef882192 (diff) | |
[art] Add classpath check to DexFile.getDexOptNeeded
Extend DexFile.getDexOptNeeded to factor into the decision the
expected class loader context. If the context does not match oat
file assistant and dexoptanalyzer will advise kDex2OatFromScratch.
(cherry picked from commit baafa55aede7cc43a27d76bd88ccc02152123ecf)
Bug: 62269291
Test: m test-art-host
Merged-In: I3a8e9321fe602712fac3595b790168b271918f10
Change-Id: I3a8e9321fe602712fac3595b790168b271918f10
| -rw-r--r-- | dexoptanalyzer/dexoptanalyzer.cc | 15 | ||||
| -rw-r--r-- | runtime/native/dalvik_system_DexFile.cc | 30 | ||||
| -rw-r--r-- | runtime/oat_file_assistant.cc | 7 | ||||
| -rw-r--r-- | runtime/oat_file_assistant_test.cc | 27 |
4 files changed, 70 insertions, 9 deletions
diff --git a/dexoptanalyzer/dexoptanalyzer.cc b/dexoptanalyzer/dexoptanalyzer.cc index 08d38d5925..3a2c7fc015 100644 --- a/dexoptanalyzer/dexoptanalyzer.cc +++ b/dexoptanalyzer/dexoptanalyzer.cc @@ -19,6 +19,7 @@ #include "android-base/stringprintf.h" #include "android-base/strings.h" #include "compiler_filter.h" +#include "class_loader_context.h" #include "dex_file.h" #include "noop_compiler_callbacks.h" #include "oat_file_assistant.h" @@ -175,7 +176,15 @@ class DexoptAnalyzer FINAL { oat_fd_ = std::stoi(option.substr(strlen("--oat-fd=")).ToString(), nullptr, 0); } else if (option.starts_with("--vdex-fd")) { vdex_fd_ = std::stoi(option.substr(strlen("--vdex-fd=")).ToString(), nullptr, 0); - } else { Usage("Unknown argument '%s'", option.data()); } + } else if (option.starts_with("--class-loader-context=")) { + std::string context_str = option.substr(strlen("--class-loader-context=")).ToString(); + class_loader_context_ = ClassLoaderContext::Create(context_str); + if (class_loader_context_ == nullptr) { + Usage("Invalid --class-loader-context '%s'", context_str.c_str()); + } + } else { + Usage("Unknown argument '%s'", option.data()); + } } if (image_.empty()) { @@ -255,9 +264,8 @@ class DexoptAnalyzer FINAL { return kNoDexOptNeeded; } - // TODO(calin): Pass the class loader context as an argument to dexoptanalyzer. b/62269291. int dexoptNeeded = oat_file_assistant->GetDexOptNeeded( - compiler_filter_, assume_profile_changed_, downgrade_); + compiler_filter_, assume_profile_changed_, downgrade_, class_loader_context_.get()); // Convert OatFileAssitant codes to dexoptanalyzer codes. switch (dexoptNeeded) { @@ -280,6 +288,7 @@ class DexoptAnalyzer FINAL { std::string dex_file_; InstructionSet isa_; CompilerFilter::Filter compiler_filter_; + std::unique_ptr<ClassLoaderContext> class_loader_context_; bool assume_profile_changed_; bool downgrade_; std::string image_; diff --git a/runtime/native/dalvik_system_DexFile.cc b/runtime/native/dalvik_system_DexFile.cc index 4ab8908ff3..451222715a 100644 --- a/runtime/native/dalvik_system_DexFile.cc +++ b/runtime/native/dalvik_system_DexFile.cc @@ -23,6 +23,7 @@ #include "base/logging.h" #include "base/stl_util.h" #include "class_linker.h" +#include <class_loader_context.h> #include "common_throws.h" #include "compiler_filter.h" #include "dex_file-inl.h" @@ -459,6 +460,7 @@ static jint GetDexOptNeeded(JNIEnv* env, const char* filename, const char* instruction_set, const char* compiler_filter_name, + const char* class_loader_context, bool profile_changed, bool downgrade) { if ((filename == nullptr) || !OS::FileExists(filename)) { @@ -485,6 +487,19 @@ static jint GetDexOptNeeded(JNIEnv* env, return -1; } + std::unique_ptr<ClassLoaderContext> context = nullptr; + if (class_loader_context != nullptr) { + context = ClassLoaderContext::Create(class_loader_context); + + if (context == nullptr) { + ScopedLocalRef<jclass> iae(env, env->FindClass("java/lang/IllegalArgumentException")); + std::string message(StringPrintf("Class loader context '%s' is invalid.", + class_loader_context)); + env->ThrowNew(iae.get(), message.c_str()); + return -1; + } + } + // TODO: Verify the dex location is well formed, and throw an IOException if // not? @@ -495,8 +510,10 @@ static jint GetDexOptNeeded(JNIEnv* env, return OatFileAssistant::kNoDexOptNeeded; } - // TODO(calin): Extend DexFile.getDexOptNeeded to accept the class loader context. b/62269291. - return oat_file_assistant.GetDexOptNeeded(filter, profile_changed, downgrade); + return oat_file_assistant.GetDexOptNeeded(filter, + profile_changed, + downgrade, + context.get()); } static jstring DexFile_getDexFileStatus(JNIEnv* env, @@ -532,6 +549,7 @@ static jint DexFile_getDexOptNeeded(JNIEnv* env, jstring javaFilename, jstring javaInstructionSet, jstring javaTargetCompilerFilter, + jstring javaClassLoaderContext, jboolean newProfile, jboolean downgrade) { ScopedUtfChars filename(env, javaFilename); @@ -549,10 +567,16 @@ static jint DexFile_getDexOptNeeded(JNIEnv* env, return -1; } + NullableScopedUtfChars class_loader_context(env, javaClassLoaderContext); + if (env->ExceptionCheck()) { + return -1; + } + return GetDexOptNeeded(env, filename.c_str(), instruction_set.c_str(), target_compiler_filter.c_str(), + class_loader_context.c_str(), newProfile == JNI_TRUE, downgrade == JNI_TRUE); } @@ -731,7 +755,7 @@ static JNINativeMethod gMethods[] = { NATIVE_METHOD(DexFile, getClassNameList, "(Ljava/lang/Object;)[Ljava/lang/String;"), NATIVE_METHOD(DexFile, isDexOptNeeded, "(Ljava/lang/String;)Z"), NATIVE_METHOD(DexFile, getDexOptNeeded, - "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZ)I"), + "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZ)I"), NATIVE_METHOD(DexFile, openDexFileNative, "(Ljava/lang/String;" "Ljava/lang/String;" diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc index a7fe9b1205..fb61228512 100644 --- a/runtime/oat_file_assistant.cc +++ b/runtime/oat_file_assistant.cc @@ -1168,12 +1168,13 @@ bool OatFileAssistant::OatFileInfo::ClassLoaderContextIsOkay(ClassLoaderContext* const OatFile* file = GetFile(); if (file == nullptr) { - return false; + // No oat file means we have nothing to verify. + return true; } - size_t dir_index = file->GetLocation().rfind('/'); + size_t dir_index = oat_file_assistant_->dex_location_.rfind('/'); std::string classpath_dir = (dir_index != std::string::npos) - ? file->GetLocation().substr(0, dir_index) + ? oat_file_assistant_->dex_location_.substr(0, dir_index) : ""; if (!context->OpenDexFiles(oat_file_assistant_->isa_, classpath_dir)) { diff --git a/runtime/oat_file_assistant_test.cc b/runtime/oat_file_assistant_test.cc index d99036df7e..6d14971179 100644 --- a/runtime/oat_file_assistant_test.cc +++ b/runtime/oat_file_assistant_test.cc @@ -1466,6 +1466,33 @@ TEST_F(OatFileAssistantTest, GetDexOptNeededWithOutOfDateContext) { default_filter, false, false, updated_context.get())); } +TEST_F(OatFileAssistantTest, GetDexOptNeededWithUpToDateContextRelative) { + std::string dex_location = GetScratchDir() + "/TestDex.jar"; + std::string context_location = GetScratchDir() + "/ContextDex.jar"; + Copy(GetDexSrc1(), dex_location); + Copy(GetDexSrc2(), context_location); + + OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false); + + const CompilerFilter::Filter default_filter = + OatFileAssistant::kDefaultCompilerFilterForDexLoading; + std::string error_msg; + std::string context_str = "PCL[" + context_location + "]"; + std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_str); + ASSERT_TRUE(context != nullptr); + ASSERT_TRUE(context->OpenDexFiles(kRuntimeISA, "")); + + int status = oat_file_assistant.MakeUpToDate(false, context.get(), &error_msg); + EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, status) << error_msg; + + // A relative context simulates a dependent split context. + std::unique_ptr<ClassLoaderContext> relative_context = + ClassLoaderContext::Create("PCL[ContextDex.jar]"); + EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded, + oat_file_assistant.GetDexOptNeeded( + default_filter, false, false, relative_context.get())); +} + // TODO: More Tests: // * Test class linker falls back to unquickened dex for DexNoOat // * Test class linker falls back to unquickened dex for MultiDexNoOat |