std::vector<std::unique_ptr<
const
DexFile>> OatFileManager::OpenDexFilesFromOat(
const
char
* dex_location,
jobject class_loader,
jobjectArray dex_elements,
const
OatFile** out_oat_file,
std::vector<std::string>* error_msgs) {
ScopedTrace trace(__FUNCTION__);
CHECK(dex_location != nullptr);
CHECK(error_msgs != nullptr);
Thread*
const
self = Thread::Current();
Locks::mutator_lock_->AssertNotHeld(self);
Runtime*
const
runtime = Runtime::Current();
OatFileAssistant oat_file_assistant(dex_location,
kRuntimeISA,
!runtime->IsAotCompiler());
std::string error_msg;
if
(!oat_file_assistant.Lock(
&error_msg)) {
VLOG(class_linker) <<
"OatFileAssistant::Lock: "
<< error_msg;
}
const
OatFile* source_oat_file = nullptr;
if
(!oat_file_assistant.IsUpToDate()) {
switch
(oat_file_assistant.MakeUpToDate(
false
,
&error_msg)) {
case
OatFileAssistant::kUpdateFailed:
LOG(WARNING) << error_msg;
break
;
case
OatFileAssistant::kUpdateNotAttempted:
VLOG(oat) << error_msg;
break
;
case
OatFileAssistant::kUpdateSucceeded:
break
;
}
}
std::unique_ptr<
const
OatFile> oat_file(oat_file_assistant.GetBestOatFile().release());
if
(oat_file != nullptr) {
bool
accept_oat_file =
!HasCollisions(oat_file.get(), class_loader, dex_elements,
&error_msg);
if
(!accept_oat_file) {
if
(Runtime::Current()->IsDexFileFallbackEnabled()) {
if
(!oat_file_assistant.HasOriginalDexFiles()) {
accept_oat_file =
true
;
LOG(WARNING) <<
"Dex location "
<< dex_location <<
" does not seem to include dex file. "
<<
"Allow oat file use. This is potentially dangerous."
;
}
else
{
LOG(WARNING) <<
"Found duplicate classes, falling back to extracting from APK : "
<< dex_location;
LOG(WARNING) <<
"NOTE: This wastes RAM and hurts startup performance."
;
}
}
else
{
if
(!oat_file_assistant.HasOriginalDexFiles()) {
accept_oat_file =
true
;
}
LOG(WARNING) <<
"Found duplicate classes, dex-file-fallback disabled, will be failing to "
" load classes for "
<< dex_location;
}
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;
if
(source_oat_file != nullptr) {
bool
added_image_space =
false
;
if
(source_oat_file->IsExecutable()) {
std::unique_ptr<gc::space::ImageSpace> image_space =
kEnableAppImage ? oat_file_assistant.OpenImageSpace(source_oat_file) : nullptr;
if
(image_space != nullptr) {
ScopedObjectAccess soa(self);
StackHandleScope<1> hs(self);
Handle<mirror::ClassLoader> h_loader(
hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
if
(h_loader != nullptr) {
std::string temp_error_msg;
{
ScopedThreadSuspension sts(self, kSuspended);
gc::ScopedGCCriticalSection gcs(self,
gc::kGcCauseAddRemoveAppImageSpace,
gc::kCollectorTypeAddRemoveAppImageSpace);
ScopedSuspendAll ssa(
"Add image space"
);
runtime->GetHeap()->AddSpace(image_space.get());
}
{
ScopedTrace trace2(StringPrintf(
"Adding image space for location %s"
, dex_location));
added_image_space = runtime->GetClassLinker()->AddImageSpace(image_space.get(),
h_loader,
dex_elements,
dex_location,
&dex_files,
&temp_error_msg);
}
if
(added_image_space) {
image_space.release();
}
else
{
LOG(INFO) <<
"Failed to add image file "
<< temp_error_msg;
dex_files.clear();
{
ScopedThreadSuspension sts(self, kSuspended);
gc::ScopedGCCriticalSection gcs(self,
gc::kGcCauseAddRemoveAppImageSpace,
gc::kCollectorTypeAddRemoveAppImageSpace);
ScopedSuspendAll ssa(
"Remove image space"
);
runtime->GetHeap()->RemoveSpace(image_space.get());
}
}
}
}
}
if
(!added_image_space) {
DCHECK(dex_files.empty());
dex_files = oat_file_assistant.LoadDexFiles(*source_oat_file, dex_location);
}
if
(dex_files.empty()) {
error_msgs->push_back(
"Failed to open dex files from "
+ source_oat_file->GetLocation());
}
}
if
(dex_files.empty()) {
if
(oat_file_assistant.HasOriginalDexFiles()) {
if
(Runtime::Current()->IsDexFileFallbackEnabled()) {
static
constexpr
bool
kVerifyChecksum =
true
;
if
(!DexFile::Open(
dex_location, dex_location, kVerifyChecksum,
&error_msg, &dex_files)) {
LOG(WARNING) << error_msg;
error_msgs->push_back(
"Failed to open dex files from "
+ std::string(dex_location)
+
" because: "
+ error_msg);
}
}
else
{
error_msgs->push_back(
"Fallback mode disabled, skipping dex files."
);
}
}
else
{
error_msgs->push_back(
"No original dex files found for dex location "
+ std::string(dex_location));
}
}
return
dex_files;
}