Pass the classpath to dex2oat.
This makes it possible to run applications that have multiple
dex files on the classpath.
Change-Id: I15264a001a46ddb253e87f2739e6b9644348f1be
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 3341d88..505f86f 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -577,6 +577,8 @@
execl(dex2oat.c_str(), dex2oat.c_str(),
"--runtime-arg", "-Xms64m",
"--runtime-arg", "-Xmx64m",
+ "--runtime-arg", "-classpath",
+ "--runtime-arg", Runtime::Current()->GetClassPath().c_str(),
boot_image_option.c_str(),
dex_file_option.c_str(),
oat_file_option.c_str(),
@@ -2621,19 +2623,9 @@
const char* descriptor = dex_file.StringByTypeIdx(type_idx);
resolved = FindClass(descriptor, class_loader);
if (resolved != NULL) {
- Class* check = resolved;
- while (check->IsArrayClass()) {
- check = check->GetComponentType();
- }
- if (dex_cache != check->GetDexCache()) {
- if (check->GetClassLoader() != NULL) {
- Thread::Current()->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
- "Class with type index %d resolved by unexpected .dex", type_idx);
- resolved = NULL;
- }
- }
- }
- if (resolved != NULL) {
+ // TODO: we used to throw here if resolved's class loader was not the
+ // boot class loader. This was to permit different classes with the
+ // same name to be loaded simultaneously by different loaders
dex_cache->SetResolvedType(type_idx, resolved);
} else {
DCHECK(Thread::Current()->IsExceptionPending());
diff --git a/src/compiler.cc b/src/compiler.cc
index 0a4117d..fabd8fd 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -82,13 +82,24 @@
}
}
-void Compiler::CompileAll(const ClassLoader* class_loader) {
+void Compiler::CompileAll(const ClassLoader* class_loader,
+ const std::vector<const DexFile*>& dex_files) {
DCHECK(!Runtime::Current()->IsStarted());
- Resolve(class_loader);
- Verify(class_loader);
- InitializeClassesWithoutClinit(class_loader);
- Compile(class_loader);
- SetCodeAndDirectMethods(class_loader);
+ for (size_t i = 0; i != dex_files.size(); ++i) {
+ ResolveDexFile(class_loader, *dex_files[i]);
+ }
+ for (size_t i = 0; i != dex_files.size(); ++i) {
+ VerifyDexFile(class_loader, *dex_files[i]);
+ }
+ for (size_t i = 0; i != dex_files.size(); ++i) {
+ InitializeClassesWithoutClinit(class_loader, *dex_files[i]);
+ }
+ for (size_t i = 0; i != dex_files.size(); ++i) {
+ CompileDexFile(class_loader, *dex_files[i]);
+ }
+ for (size_t i = 0; i != dex_files.size(); ++i) {
+ SetCodeAndDirectMethodsDexFile(*dex_files[i]);
+ }
}
void Compiler::CompileOne(const Method* method) {
diff --git a/src/compiler.h b/src/compiler.h
index c09e2c2..a8ea205 100644
--- a/src/compiler.h
+++ b/src/compiler.h
@@ -25,8 +25,8 @@
~Compiler();
- // Compile all Methods of all the Classes of all the DexFiles that are part of a ClassLoader.
- void CompileAll(const ClassLoader* class_loader);
+ void CompileAll(const ClassLoader* class_loader,
+ const std::vector<const DexFile*>& class_path);
// Compile a single Method
void CompileOne(const Method* method);
diff --git a/src/compiler_test.cc b/src/compiler_test.cc
index d1b377a..823aa48 100644
--- a/src/compiler_test.cc
+++ b/src/compiler_test.cc
@@ -19,7 +19,7 @@
protected:
void CompileAll(const ClassLoader* class_loader) {
- compiler_->CompileAll(class_loader);
+ compiler_->CompileAll(class_loader, ClassLoader::GetCompileTimeClassPath(class_loader));
MakeAllExecutable(class_loader);
}
diff --git a/src/dex2oat.cc b/src/dex2oat.cc
index 6cf6df6..231ca9c 100644
--- a/src/dex2oat.cc
+++ b/src/dex2oat.cc
@@ -94,6 +94,34 @@
bool do_unlink_;
};
+// Returns true if dex_files has a dex with the named location.
+bool DexFilesContains(const std::vector<const DexFile*>& dex_files, const std::string& location) {
+ for (size_t i = 0; i < dex_files.size(); ++i) {
+ if (dex_files[i]->GetLocation() == location) {
+ return true;
+ }
+ }
+ return false;
+}
+
+// Appends to dex_files any elements of class_path that it doesn't already
+// contain. This will open those dex files as necessary.
+void OpenClassPathFiles(const std::string& class_path, std::vector<const DexFile*>& dex_files) {
+ std::vector<std::string> parsed;
+ Split(class_path, ':', parsed);
+ for (size_t i = 0; i < parsed.size(); ++i) {
+ if (DexFilesContains(dex_files, parsed[i])) {
+ continue;
+ }
+ const DexFile* dex_file = DexFile::Open(parsed[i], Runtime::Current()->GetHostPrefix());
+ if (dex_file == NULL) {
+ LOG(WARNING) << "Failed to open dex file " << parsed[i];
+ } else {
+ dex_files.push_back(dex_file);
+ }
+ }
+}
+
int dex2oat(int argc, char** argv) {
// Skip over argv[0].
argv++;
@@ -272,13 +300,17 @@
// ClassLoader creation needs to come after Runtime::Create
SirtRef<ClassLoader> class_loader(NULL);
+ std::vector<const DexFile*> dex_files;
if (!boot_image_option.empty()) {
- std::vector<const DexFile*> dex_files;
DexFile::OpenDexFiles(dex_filenames, dex_files, host_prefix);
- for (size_t i = 0; i < dex_files.size(); i++) {
- class_linker->RegisterDexFile(*dex_files[i]);
+ std::vector<const DexFile*> class_path_files(dex_files);
+ OpenClassPathFiles(runtime->GetClassPath(), class_path_files);
+ for (size_t i = 0; i < class_path_files.size(); i++) {
+ class_linker->RegisterDexFile(*class_path_files[i]);
}
- class_loader.reset(PathClassLoader::AllocCompileTime(dex_files));
+ class_loader.reset(PathClassLoader::AllocCompileTime(class_path_files));
+ } else {
+ dex_files = runtime->GetClassLinker()->GetBootClassPath();
}
// if we loaded an existing image, we will reuse values from the image roots.
@@ -302,7 +334,7 @@
}
Compiler compiler(kThumb2, image_filename != NULL);
if (method_names.empty()) {
- compiler.CompileAll(class_loader.get());
+ compiler.CompileAll(class_loader.get(), dex_files);
} else {
for (size_t i = 0; i < method_names.size(); i++) {
// names are actually class_descriptor + name + signature.
diff --git a/src/oat_test.cc b/src/oat_test.cc
index e3186de..17a00e4 100644
--- a/src/oat_test.cc
+++ b/src/oat_test.cc
@@ -11,11 +11,12 @@
TEST_F(OatTest, WriteRead) {
const bool compile = false; // DISABLED_ due to the time to compile libcore
+ ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
SirtRef<ClassLoader> class_loader(NULL);
if (compile) {
compiler_.reset(new Compiler(kThumb2, false));
- compiler_->CompileAll(class_loader.get());
+ compiler_->CompileAll(class_loader.get(), class_linker->GetBootClassPath());
}
ScratchFile tmp;
@@ -23,15 +24,13 @@
ASSERT_TRUE(success);
if (compile) { // OatWriter strips the code, regenerate to compare
- compiler_->CompileAll(class_loader.get());
+ compiler_->CompileAll(class_loader.get(), class_linker->GetBootClassPath());
}
UniquePtr<OatFile> oat_file(OatFile::Open(std::string(tmp.GetFilename()), "", NULL));
ASSERT_TRUE(oat_file.get() != NULL);
const OatHeader& oat_header = oat_file->GetOatHeader();
ASSERT_EQ(1U, oat_header.GetDexFileCount());
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-
const DexFile& dex_file = *java_lang_dex_file_.get();
const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_file.GetLocation());
for (size_t i = 0; i < dex_file.NumClassDefs(); i++) {