summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/gc/heap.cc12
-rw-r--r--runtime/gc/heap.h1
-rw-r--r--runtime/oat_file.h7
-rw-r--r--runtime/oat_file_assistant_test.cc4
-rw-r--r--runtime/oat_file_manager.cc31
-rw-r--r--test/2231-oat-require-app-image/expected.txt2
-rw-r--r--test/2231-oat-require-app-image/info.txt1
-rw-r--r--test/2231-oat-require-app-image/profile1
-rw-r--r--test/2231-oat-require-app-image/run18
-rw-r--r--test/2231-oat-require-app-image/src/Main.java31
-rw-r--r--test/common/runtime_state.cc8
11 files changed, 101 insertions, 15 deletions
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index b919cdda60..401394af6e 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -870,6 +870,18 @@ bool Heap::IsCompilingBoot() const {
return true;
}
+bool Heap::HasAppImageSpace() const {
+ for (const auto& space : GetContinuousSpaces()) {
+ if (space->IsImageSpace()) {
+ const gc::space::ImageSpace* image_space = space->AsImageSpace();
+ if (image_space->GetImageHeader().IsAppImage()) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
void Heap::IncrementDisableMovingGC(Thread* self) {
// Need to do this holding the lock to prevent races where the GC is about to run / running when
// we attempt to disable it.
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index 515dcb3a6d..9008c01a2b 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -783,6 +783,7 @@ class Heap {
bool HasBootImageSpace() const {
return !boot_image_spaces_.empty();
}
+ bool HasAppImageSpace() const REQUIRES_SHARED(Locks::mutator_lock_);
ReferenceProcessor* GetReferenceProcessor() {
return reference_processor_.get();
diff --git a/runtime/oat_file.h b/runtime/oat_file.h
index dce34d9728..75770d73f9 100644
--- a/runtime/oat_file.h
+++ b/runtime/oat_file.h
@@ -378,6 +378,13 @@ class OatFile {
return external_dex_files_.empty();
}
+ // Returns whether an image (e.g. app image) is required to safely execute this OAT file.
+ inline bool RequiresImage() const {
+ // We currently require images only for speed profile and everything profile.
+ return GetCompilerFilter() == CompilerFilter::Filter::kSpeedProfile ||
+ GetCompilerFilter() == CompilerFilter::Filter::kEverythingProfile;
+ }
+
protected:
OatFile(const std::string& filename, bool executable);
diff --git a/runtime/oat_file_assistant_test.cc b/runtime/oat_file_assistant_test.cc
index ed47ca3a6b..e8a7381296 100644
--- a/runtime/oat_file_assistant_test.cc
+++ b/runtime/oat_file_assistant_test.cc
@@ -1437,6 +1437,7 @@ TEST_F(OatFileAssistantTest, GetDexOptNeededWithOutOfDateContext) {
TEST_F(OatFileAssistantTest, GetDexLocation) {
std::string dex_location = GetScratchDir() + "/TestDex.jar";
std::string oat_location = GetOdexDir() + "/TestDex.odex";
+ std::string art_location = GetOdexDir() + "/TestDex.art";
// Start the runtime to initialize the system's class loader.
Thread::Current()->TransitionFromSuspendedToRunnable();
@@ -1463,6 +1464,7 @@ TEST_F(OatFileAssistantTest, GetDexLocation) {
args.push_back("--dex-file=" + dex_location);
args.push_back("--dex-location=TestDex.jar");
args.push_back("--oat-file=" + oat_location);
+ args.push_back("--app-image-file=" + art_location);
std::string error_msg;
ASSERT_TRUE(DexoptTest::Dex2Oat(args, &error_msg)) << error_msg;
}
@@ -1490,6 +1492,7 @@ TEST_F(OatFileAssistantTest, SystemFrameworkDir) {
odex_dir = odex_dir + std::string(GetInstructionSetString(kRuntimeISA));
mkdir(odex_dir.c_str(), 0700);
std::string oat_location = odex_dir + "/" + filebase + ".odex";
+ std::string art_location = odex_dir + "/" + filebase + ".art";
// Clean up in case previous run crashed.
remove(oat_location.c_str());
@@ -1527,6 +1530,7 @@ TEST_F(OatFileAssistantTest, SystemFrameworkDir) {
args.push_back("--dex-file=" + dex_location);
args.push_back("--dex-location=" + filebase + ".jar");
args.push_back("--oat-file=" + oat_location);
+ args.push_back("--app-image-file=" + art_location);
std::string error_msg;
ASSERT_TRUE(DexoptTest::Dex2Oat(args, &error_msg)) << error_msg;
}
diff --git a/runtime/oat_file_manager.cc b/runtime/oat_file_manager.cc
index ff743d5158..7101a23d43 100644
--- a/runtime/oat_file_manager.cc
+++ b/runtime/oat_file_manager.cc
@@ -492,13 +492,14 @@ std::vector<std::unique_ptr<const DexFile>> OatFileManager::OpenDexFilesFromOat(
const OatFile* source_oat_file = nullptr;
CheckCollisionResult check_collision_result = CheckCollisionResult::kPerformedHasCollisions;
std::string error_msg;
+ bool accept_oat_file = false;
if ((class_loader != nullptr || dex_elements != nullptr) && oat_file != nullptr) {
// Prevent oat files from being loaded if no class_loader or dex_elements are provided.
// This can happen when the deprecated DexFile.<init>(String) is called directly, and it
// could load oat files without checking the classpath, which would be incorrect.
// Take the file only if it has no collisions, or we must take it because of preopting.
check_collision_result = CheckCollision(oat_file.get(), context.get(), /*out*/ &error_msg);
- bool accept_oat_file = AcceptOatFile(check_collision_result);
+ accept_oat_file = AcceptOatFile(check_collision_result);
if (!accept_oat_file) {
// Failed the collision check. Print warning.
if (runtime->IsDexFileFallbackEnabled()) {
@@ -531,30 +532,24 @@ std::vector<std::unique_ptr<const DexFile>> OatFileManager::OpenDexFilesFromOat(
LOG(WARNING) << error_msg;
}
-
- if (accept_oat_file) {
- VLOG(class_linker) << "Registering " << oat_file->GetLocation();
- source_oat_file = RegisterOatFile(std::move(oat_file));
- *out_oat_file = source_oat_file;
- }
}
std::vector<std::unique_ptr<const DexFile>> dex_files;
// Load the dex files from the oat file.
- if (source_oat_file != nullptr) {
- bool added_image_space = false;
- if (source_oat_file->IsExecutable()) {
+ bool added_image_space = false;
+ if (accept_oat_file) {
+ if (oat_file->IsExecutable()) {
ScopedTrace app_image_timing("AppImage:Loading");
// We need to throw away the image space if we are debuggable but the oat-file source of the
// image is not otherwise we might get classes with inlined methods or other such things.
std::unique_ptr<gc::space::ImageSpace> image_space;
if (ShouldLoadAppImage(check_collision_result,
- source_oat_file,
+ oat_file.get(),
context.get(),
&error_msg)) {
- image_space = oat_file_assistant.OpenImageSpace(source_oat_file);
+ image_space = oat_file_assistant.OpenImageSpace(oat_file.get());
}
if (image_space != nullptr) {
ScopedObjectAccess soa(self);
@@ -606,9 +601,9 @@ std::vector<std::unique_ptr<const DexFile>> OatFileManager::OpenDexFilesFromOat(
}
}
}
- if (!added_image_space) {
+ if (!added_image_space && !oat_file->RequiresImage()) {
DCHECK(dex_files.empty());
- dex_files = oat_file_assistant.LoadDexFiles(*source_oat_file, dex_location);
+ dex_files = oat_file_assistant.LoadDexFiles(*oat_file.get(), dex_location);
// Register for tracking.
for (const auto& dex_file : dex_files) {
@@ -616,7 +611,7 @@ std::vector<std::unique_ptr<const DexFile>> OatFileManager::OpenDexFilesFromOat(
}
}
if (dex_files.empty()) {
- error_msgs->push_back("Failed to open dex files from " + source_oat_file->GetLocation());
+ error_msgs->push_back("Failed to open dex files from " + oat_file->GetLocation());
} else {
// Opened dex files from an oat file, madvise them to their loaded state.
for (const std::unique_ptr<const DexFile>& dex_file : dex_files) {
@@ -625,6 +620,12 @@ std::vector<std::unique_ptr<const DexFile>> OatFileManager::OpenDexFilesFromOat(
}
}
+ if (accept_oat_file && (added_image_space || !oat_file->RequiresImage())) {
+ VLOG(class_linker) << "Registering " << oat_file->GetLocation();
+ source_oat_file = RegisterOatFile(std::move(oat_file));
+ *out_oat_file = source_oat_file;
+ }
+
// Fall back to running out of the original dex file if we couldn't load any
// dex_files from the oat file.
if (dex_files.empty()) {
diff --git a/test/2231-oat-require-app-image/expected.txt b/test/2231-oat-require-app-image/expected.txt
new file mode 100644
index 0000000000..95d58e9d79
--- /dev/null
+++ b/test/2231-oat-require-app-image/expected.txt
@@ -0,0 +1,2 @@
+JNI_OnLoad called
+Test passed.
diff --git a/test/2231-oat-require-app-image/info.txt b/test/2231-oat-require-app-image/info.txt
new file mode 100644
index 0000000000..8e0b0693de
--- /dev/null
+++ b/test/2231-oat-require-app-image/info.txt
@@ -0,0 +1 @@
+Make sure speed-profile OAT files do not load without an AppImage \ No newline at end of file
diff --git a/test/2231-oat-require-app-image/profile b/test/2231-oat-require-app-image/profile
new file mode 100644
index 0000000000..36fb1bae49
--- /dev/null
+++ b/test/2231-oat-require-app-image/profile
@@ -0,0 +1 @@
+LMain; \ No newline at end of file
diff --git a/test/2231-oat-require-app-image/run b/test/2231-oat-require-app-image/run
new file mode 100644
index 0000000000..c258a0ef45
--- /dev/null
+++ b/test/2231-oat-require-app-image/run
@@ -0,0 +1,18 @@
+#!/bin/bash
+#
+# Copyright (C) 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# We need a profile to tell dex2oat to include classes in the final app image
+exec ${RUN} --no-app-image --profile $@
diff --git a/test/2231-oat-require-app-image/src/Main.java b/test/2231-oat-require-app-image/src/Main.java
new file mode 100644
index 0000000000..1bac2cba7e
--- /dev/null
+++ b/test/2231-oat-require-app-image/src/Main.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class Main {
+ public static void main(String[] args) {
+ System.loadLibrary(args[0]);
+
+ if ("speed-profile".equals(getCompilerFilter(Main.class)) && !hasAppImage() && hasOatFile()) {
+ System.out.println("Error: Loaded OAT file with no app image in speed-profile mode");
+ }
+
+ System.out.println("Test passed.");
+ }
+
+ private native static boolean hasAppImage();
+ private native static boolean hasOatFile();
+ private native static Object getCompilerFilter(Class c);
+}
diff --git a/test/common/runtime_state.cc b/test/common/runtime_state.cc
index 6c76288663..48158e28ba 100644
--- a/test/common/runtime_state.cc
+++ b/test/common/runtime_state.cc
@@ -102,6 +102,14 @@ extern "C" JNIEXPORT jboolean JNICALL Java_Main_hasImage(JNIEnv* env ATTRIBUTE_U
return Runtime::Current()->GetHeap()->HasBootImageSpace();
}
+// public static native boolean hasAppImage();
+
+extern "C" JNIEXPORT jboolean JNICALL Java_Main_hasAppImage(JNIEnv* env,
+ jclass cls ATTRIBUTE_UNUSED) {
+ ScopedObjectAccess soa(env);
+ return Runtime::Current()->GetHeap()->HasAppImageSpace();
+}
+
// public static native boolean isImageDex2OatEnabled();
extern "C" JNIEXPORT jboolean JNICALL Java_Main_isImageDex2OatEnabled(JNIEnv* env ATTRIBUTE_UNUSED,