class_loader_context.cc revision 1a509c8effc938ba3da0f90ad83abb124b296386
1/* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "class_loader_context.h" 18 19#include "art_field-inl.h" 20#include "base/dchecked_vector.h" 21#include "base/stl_util.h" 22#include "class_linker.h" 23#include "class_loader_utils.h" 24#include "dex_file.h" 25#include "handle_scope-inl.h" 26#include "jni_internal.h" 27#include "oat_file_assistant.h" 28#include "obj_ptr-inl.h" 29#include "runtime.h" 30#include "scoped_thread_state_change-inl.h" 31#include "thread.h" 32#include "well_known_classes.h" 33 34namespace art { 35 36static constexpr char kPathClassLoaderString[] = "PCL"; 37static constexpr char kDelegateLastClassLoaderString[] = "DLC"; 38static constexpr char kClassLoaderOpeningMark = '['; 39static constexpr char kClassLoaderClosingMark = ']'; 40static constexpr char kClassLoaderSeparator = ';'; 41static constexpr char kClasspathSeparator = ':'; 42static constexpr char kDexFileChecksumSeparator = '*'; 43 44ClassLoaderContext::ClassLoaderContext() 45 : special_shared_library_(false), 46 dex_files_open_attempted_(false), 47 dex_files_open_result_(false), 48 owns_the_dex_files_(true) {} 49 50ClassLoaderContext::ClassLoaderContext(bool owns_the_dex_files) 51 : special_shared_library_(false), 52 dex_files_open_attempted_(true), 53 dex_files_open_result_(true), 54 owns_the_dex_files_(owns_the_dex_files) {} 55 56ClassLoaderContext::~ClassLoaderContext() { 57 if (!owns_the_dex_files_) { 58 // If the context does not own the dex/oat files release the unique pointers to 59 // make sure we do not de-allocate them. 60 for (ClassLoaderInfo& info : class_loader_chain_) { 61 for (std::unique_ptr<OatFile>& oat_file : info.opened_oat_files) { 62 oat_file.release(); 63 } 64 for (std::unique_ptr<const DexFile>& dex_file : info.opened_dex_files) { 65 dex_file.release(); 66 } 67 } 68 } 69} 70 71std::unique_ptr<ClassLoaderContext> ClassLoaderContext::Create(const std::string& spec) { 72 std::unique_ptr<ClassLoaderContext> result(new ClassLoaderContext()); 73 if (result->Parse(spec)) { 74 return result; 75 } else { 76 return nullptr; 77 } 78} 79 80// The expected format is: "ClassLoaderType1[ClasspathElem1*Checksum1:ClasspathElem2*Checksum2...]". 81// The checksum part of the format is expected only if parse_cheksums is true. 82bool ClassLoaderContext::ParseClassLoaderSpec(const std::string& class_loader_spec, 83 ClassLoaderType class_loader_type, 84 bool parse_checksums) { 85 const char* class_loader_type_str = GetClassLoaderTypeName(class_loader_type); 86 size_t type_str_size = strlen(class_loader_type_str); 87 88 CHECK_EQ(0, class_loader_spec.compare(0, type_str_size, class_loader_type_str)); 89 90 // Check the opening and closing markers. 91 if (class_loader_spec[type_str_size] != kClassLoaderOpeningMark) { 92 return false; 93 } 94 if (class_loader_spec[class_loader_spec.length() - 1] != kClassLoaderClosingMark) { 95 return false; 96 } 97 98 // At this point we know the format is ok; continue and extract the classpath. 99 // Note that class loaders with an empty class path are allowed. 100 std::string classpath = class_loader_spec.substr(type_str_size + 1, 101 class_loader_spec.length() - type_str_size - 2); 102 103 class_loader_chain_.push_back(ClassLoaderInfo(class_loader_type)); 104 105 if (!parse_checksums) { 106 Split(classpath, kClasspathSeparator, &class_loader_chain_.back().classpath); 107 } else { 108 std::vector<std::string> classpath_elements; 109 Split(classpath, kClasspathSeparator, &classpath_elements); 110 for (const std::string& element : classpath_elements) { 111 std::vector<std::string> dex_file_with_checksum; 112 Split(element, kDexFileChecksumSeparator, &dex_file_with_checksum); 113 if (dex_file_with_checksum.size() != 2) { 114 return false; 115 } 116 uint32_t checksum = 0; 117 if (!ParseInt(dex_file_with_checksum[1].c_str(), &checksum)) { 118 return false; 119 } 120 class_loader_chain_.back().classpath.push_back(dex_file_with_checksum[0]); 121 class_loader_chain_.back().checksums.push_back(checksum); 122 } 123 } 124 125 return true; 126} 127 128// Extracts the class loader type from the given spec. 129// Return ClassLoaderContext::kInvalidClassLoader if the class loader type is not 130// recognized. 131ClassLoaderContext::ClassLoaderType 132ClassLoaderContext::ExtractClassLoaderType(const std::string& class_loader_spec) { 133 const ClassLoaderType kValidTypes[] = {kPathClassLoader, kDelegateLastClassLoader}; 134 for (const ClassLoaderType& type : kValidTypes) { 135 const char* type_str = GetClassLoaderTypeName(type); 136 if (class_loader_spec.compare(0, strlen(type_str), type_str) == 0) { 137 return type; 138 } 139 } 140 return kInvalidClassLoader; 141} 142 143// The format: ClassLoaderType1[ClasspathElem1:ClasspathElem2...];ClassLoaderType2[...]... 144// ClassLoaderType is either "PCL" (PathClassLoader) or "DLC" (DelegateLastClassLoader). 145// ClasspathElem is the path of dex/jar/apk file. 146bool ClassLoaderContext::Parse(const std::string& spec, bool parse_checksums) { 147 if (spec.empty()) { 148 // By default we load the dex files in a PathClassLoader. 149 // So an empty spec is equivalent to an empty PathClassLoader (this happens when running 150 // tests) 151 class_loader_chain_.push_back(ClassLoaderInfo(kPathClassLoader)); 152 return true; 153 } 154 155 // Stop early if we detect the special shared library, which may be passed as the classpath 156 // for dex2oat when we want to skip the shared libraries check. 157 if (spec == OatFile::kSpecialSharedLibrary) { 158 LOG(INFO) << "The ClassLoaderContext is a special shared library."; 159 special_shared_library_ = true; 160 return true; 161 } 162 163 std::vector<std::string> class_loaders; 164 Split(spec, kClassLoaderSeparator, &class_loaders); 165 166 for (const std::string& class_loader : class_loaders) { 167 ClassLoaderType type = ExtractClassLoaderType(class_loader); 168 if (type == kInvalidClassLoader) { 169 LOG(ERROR) << "Invalid class loader type: " << class_loader; 170 return false; 171 } 172 if (!ParseClassLoaderSpec(class_loader, type, parse_checksums)) { 173 LOG(ERROR) << "Invalid class loader spec: " << class_loader; 174 return false; 175 } 176 } 177 return true; 178} 179 180// Opens requested class path files and appends them to opened_dex_files. If the dex files have 181// been stripped, this opens them from their oat files (which get added to opened_oat_files). 182bool ClassLoaderContext::OpenDexFiles(InstructionSet isa, const std::string& classpath_dir) { 183 CHECK(!dex_files_open_attempted_) << "OpenDexFiles should not be called twice"; 184 185 dex_files_open_attempted_ = true; 186 // Assume we can open all dex files. If not, we will set this to false as we go. 187 dex_files_open_result_ = true; 188 189 if (special_shared_library_) { 190 // Nothing to open if the context is a special shared library. 191 return true; 192 } 193 194 // Note that we try to open all dex files even if some fail. 195 // We may get resource-only apks which we cannot load. 196 // TODO(calin): Refine the dex opening interface to be able to tell if an archive contains 197 // no dex files. So that we can distinguish the real failures... 198 for (ClassLoaderInfo& info : class_loader_chain_) { 199 for (const std::string& cp_elem : info.classpath) { 200 // If path is relative, append it to the provided base directory. 201 std::string location = cp_elem; 202 if (location[0] != '/') { 203 location = classpath_dir + '/' + location; 204 } 205 std::string error_msg; 206 // When opening the dex files from the context we expect their checksum to match their 207 // contents. So pass true to verify_checksum. 208 if (!DexFile::Open(location.c_str(), 209 location.c_str(), 210 /*verify_checksum*/ true, 211 &error_msg, 212 &info.opened_dex_files)) { 213 // If we fail to open the dex file because it's been stripped, try to open the dex file 214 // from its corresponding oat file. 215 // This could happen when we need to recompile a pre-build whose dex code has been stripped. 216 // (for example, if the pre-build is only quicken and we want to re-compile it 217 // speed-profile). 218 // TODO(calin): Use the vdex directly instead of going through the oat file. 219 OatFileAssistant oat_file_assistant(location.c_str(), isa, false); 220 std::unique_ptr<OatFile> oat_file(oat_file_assistant.GetBestOatFile()); 221 std::vector<std::unique_ptr<const DexFile>> oat_dex_files; 222 if (oat_file != nullptr && 223 OatFileAssistant::LoadDexFiles(*oat_file, location, &oat_dex_files)) { 224 info.opened_oat_files.push_back(std::move(oat_file)); 225 info.opened_dex_files.insert(info.opened_dex_files.end(), 226 std::make_move_iterator(oat_dex_files.begin()), 227 std::make_move_iterator(oat_dex_files.end())); 228 } else { 229 LOG(WARNING) << "Could not open dex files from location: " << location; 230 dex_files_open_result_ = false; 231 } 232 } 233 } 234 } 235 236 return dex_files_open_result_; 237} 238 239bool ClassLoaderContext::RemoveLocationsFromClassPaths( 240 const dchecked_vector<std::string>& locations) { 241 CHECK(!dex_files_open_attempted_) 242 << "RemoveLocationsFromClasspaths cannot be call after OpenDexFiles"; 243 244 std::set<std::string> canonical_locations; 245 for (const std::string& location : locations) { 246 canonical_locations.insert(DexFile::GetDexCanonicalLocation(location.c_str())); 247 } 248 bool removed_locations = false; 249 for (ClassLoaderInfo& info : class_loader_chain_) { 250 size_t initial_size = info.classpath.size(); 251 auto kept_it = std::remove_if( 252 info.classpath.begin(), 253 info.classpath.end(), 254 [canonical_locations](const std::string& location) { 255 return ContainsElement(canonical_locations, 256 DexFile::GetDexCanonicalLocation(location.c_str())); 257 }); 258 info.classpath.erase(kept_it, info.classpath.end()); 259 if (initial_size != info.classpath.size()) { 260 removed_locations = true; 261 } 262 } 263 return removed_locations; 264} 265 266std::string ClassLoaderContext::EncodeContextForOatFile(const std::string& base_dir) const { 267 CheckDexFilesOpened("EncodeContextForOatFile"); 268 if (special_shared_library_) { 269 return OatFile::kSpecialSharedLibrary; 270 } 271 272 std::ostringstream out; 273 if (class_loader_chain_.empty()) { 274 // We can get in this situation if the context was created with a class path containing the 275 // source dex files which were later removed (happens during run-tests). 276 out << GetClassLoaderTypeName(kPathClassLoader) 277 << kClassLoaderOpeningMark 278 << kClassLoaderClosingMark; 279 return out.str(); 280 } 281 282 for (size_t i = 0; i < class_loader_chain_.size(); i++) { 283 const ClassLoaderInfo& info = class_loader_chain_[i]; 284 if (i > 0) { 285 out << kClassLoaderSeparator; 286 } 287 out << GetClassLoaderTypeName(info.type); 288 out << kClassLoaderOpeningMark; 289 for (size_t k = 0; k < info.opened_dex_files.size(); k++) { 290 const std::unique_ptr<const DexFile>& dex_file = info.opened_dex_files[k]; 291 const std::string& location = dex_file->GetLocation(); 292 if (k > 0) { 293 out << kClasspathSeparator; 294 } 295 // Find paths that were relative and convert them back from absolute. 296 if (!base_dir.empty() && location.substr(0, base_dir.length()) == base_dir) { 297 out << location.substr(base_dir.length() + 1).c_str(); 298 } else { 299 out << dex_file->GetLocation().c_str(); 300 } 301 out << kDexFileChecksumSeparator; 302 out << dex_file->GetLocationChecksum(); 303 } 304 out << kClassLoaderClosingMark; 305 } 306 return out.str(); 307} 308 309jobject ClassLoaderContext::CreateClassLoader( 310 const std::vector<const DexFile*>& compilation_sources) const { 311 CheckDexFilesOpened("CreateClassLoader"); 312 313 Thread* self = Thread::Current(); 314 ScopedObjectAccess soa(self); 315 316 ClassLinker* const class_linker = Runtime::Current()->GetClassLinker(); 317 318 if (class_loader_chain_.empty()) { 319 return class_linker->CreatePathClassLoader(self, compilation_sources); 320 } 321 322 // Create the class loaders starting from the top most parent (the one on the last position 323 // in the chain) but omit the first class loader which will contain the compilation_sources and 324 // needs special handling. 325 jobject current_parent = nullptr; // the starting parent is the BootClassLoader. 326 for (size_t i = class_loader_chain_.size() - 1; i > 0; i--) { 327 std::vector<const DexFile*> class_path_files = MakeNonOwningPointerVector( 328 class_loader_chain_[i].opened_dex_files); 329 current_parent = class_linker->CreateWellKnownClassLoader( 330 self, 331 class_path_files, 332 GetClassLoaderClass(class_loader_chain_[i].type), 333 current_parent); 334 } 335 336 // We set up all the parents. Move on to create the first class loader. 337 // Its classpath comes first, followed by compilation sources. This ensures that whenever 338 // we need to resolve classes from it the classpath elements come first. 339 340 std::vector<const DexFile*> first_class_loader_classpath = MakeNonOwningPointerVector( 341 class_loader_chain_[0].opened_dex_files); 342 first_class_loader_classpath.insert(first_class_loader_classpath.end(), 343 compilation_sources.begin(), 344 compilation_sources.end()); 345 346 return class_linker->CreateWellKnownClassLoader( 347 self, 348 first_class_loader_classpath, 349 GetClassLoaderClass(class_loader_chain_[0].type), 350 current_parent); 351} 352 353std::vector<const DexFile*> ClassLoaderContext::FlattenOpenedDexFiles() const { 354 CheckDexFilesOpened("FlattenOpenedDexFiles"); 355 356 std::vector<const DexFile*> result; 357 for (const ClassLoaderInfo& info : class_loader_chain_) { 358 for (const std::unique_ptr<const DexFile>& dex_file : info.opened_dex_files) { 359 result.push_back(dex_file.get()); 360 } 361 } 362 return result; 363} 364 365const char* ClassLoaderContext::GetClassLoaderTypeName(ClassLoaderType type) { 366 switch (type) { 367 case kPathClassLoader: return kPathClassLoaderString; 368 case kDelegateLastClassLoader: return kDelegateLastClassLoaderString; 369 default: 370 LOG(FATAL) << "Invalid class loader type " << type; 371 UNREACHABLE(); 372 } 373} 374 375void ClassLoaderContext::CheckDexFilesOpened(const std::string& calling_method) const { 376 CHECK(dex_files_open_attempted_) 377 << "Dex files were not successfully opened before the call to " << calling_method 378 << "attempt=" << dex_files_open_attempted_ << ", result=" << dex_files_open_result_; 379} 380 381// Collects the dex files from the give Java dex_file object. Only the dex files with 382// at least 1 class are collected. If a null java_dex_file is passed this method does nothing. 383static bool CollectDexFilesFromJavaDexFile(ObjPtr<mirror::Object> java_dex_file, 384 ArtField* const cookie_field, 385 std::vector<const DexFile*>* out_dex_files) 386 REQUIRES_SHARED(Locks::mutator_lock_) { 387 if (java_dex_file == nullptr) { 388 return true; 389 } 390 // On the Java side, the dex files are stored in the cookie field. 391 mirror::LongArray* long_array = cookie_field->GetObject(java_dex_file)->AsLongArray(); 392 if (long_array == nullptr) { 393 // This should never happen so log a warning. 394 LOG(ERROR) << "Unexpected null cookie"; 395 return false; 396 } 397 int32_t long_array_size = long_array->GetLength(); 398 // Index 0 from the long array stores the oat file. The dex files start at index 1. 399 for (int32_t j = 1; j < long_array_size; ++j) { 400 const DexFile* cp_dex_file = reinterpret_cast<const DexFile*>(static_cast<uintptr_t>( 401 long_array->GetWithoutChecks(j))); 402 if (cp_dex_file != nullptr && cp_dex_file->NumClassDefs() > 0) { 403 // TODO(calin): It's unclear why the dex files with no classes are skipped here and when 404 // cp_dex_file can be null. 405 out_dex_files->push_back(cp_dex_file); 406 } 407 } 408 return true; 409} 410 411// Collects all the dex files loaded by the given class loader. 412// Returns true for success or false if an unexpected state is discovered (e.g. a null dex cookie, 413// a null list of dex elements or a null dex element). 414static bool CollectDexFilesFromSupportedClassLoader(ScopedObjectAccessAlreadyRunnable& soa, 415 Handle<mirror::ClassLoader> class_loader, 416 std::vector<const DexFile*>* out_dex_files) 417 REQUIRES_SHARED(Locks::mutator_lock_) { 418 CHECK(IsPathOrDexClassLoader(soa, class_loader) || IsDelegateLastClassLoader(soa, class_loader)); 419 420 // All supported class loaders inherit from BaseDexClassLoader. 421 // We need to get the DexPathList and loop through it. 422 ArtField* const cookie_field = 423 jni::DecodeArtField(WellKnownClasses::dalvik_system_DexFile_cookie); 424 ArtField* const dex_file_field = 425 jni::DecodeArtField(WellKnownClasses::dalvik_system_DexPathList__Element_dexFile); 426 ObjPtr<mirror::Object> dex_path_list = 427 jni::DecodeArtField(WellKnownClasses::dalvik_system_BaseDexClassLoader_pathList)-> 428 GetObject(class_loader.Get()); 429 CHECK(cookie_field != nullptr); 430 CHECK(dex_file_field != nullptr); 431 if (dex_path_list == nullptr) { 432 // This may be null if the current class loader is under construction and it does not 433 // have its fields setup yet. 434 return true; 435 } 436 // DexPathList has an array dexElements of Elements[] which each contain a dex file. 437 ObjPtr<mirror::Object> dex_elements_obj = 438 jni::DecodeArtField(WellKnownClasses::dalvik_system_DexPathList_dexElements)-> 439 GetObject(dex_path_list); 440 // Loop through each dalvik.system.DexPathList$Element's dalvik.system.DexFile and look 441 // at the mCookie which is a DexFile vector. 442 if (dex_elements_obj == nullptr) { 443 // TODO(calin): It's unclear if we should just assert here. For now be prepared for the worse 444 // and assume we have no elements. 445 return true; 446 } else { 447 StackHandleScope<1> hs(soa.Self()); 448 Handle<mirror::ObjectArray<mirror::Object>> dex_elements( 449 hs.NewHandle(dex_elements_obj->AsObjectArray<mirror::Object>())); 450 for (int32_t i = 0; i < dex_elements->GetLength(); ++i) { 451 mirror::Object* element = dex_elements->GetWithoutChecks(i); 452 if (element == nullptr) { 453 // Should never happen, log an error and break. 454 // TODO(calin): It's unclear if we should just assert here. 455 // This code was propagated to oat_file_manager from the class linker where it would 456 // throw a NPE. For now, return false which will mark this class loader as unsupported. 457 LOG(ERROR) << "Unexpected null in the dex element list"; 458 return false; 459 } 460 ObjPtr<mirror::Object> dex_file = dex_file_field->GetObject(element); 461 if (!CollectDexFilesFromJavaDexFile(dex_file, cookie_field, out_dex_files)) { 462 return false; 463 } 464 } 465 } 466 467 return true; 468} 469 470static bool GetDexFilesFromDexElementsArray( 471 ScopedObjectAccessAlreadyRunnable& soa, 472 Handle<mirror::ObjectArray<mirror::Object>> dex_elements, 473 std::vector<const DexFile*>* out_dex_files) REQUIRES_SHARED(Locks::mutator_lock_) { 474 DCHECK(dex_elements != nullptr); 475 476 ArtField* const cookie_field = 477 jni::DecodeArtField(WellKnownClasses::dalvik_system_DexFile_cookie); 478 ArtField* const dex_file_field = 479 jni::DecodeArtField(WellKnownClasses::dalvik_system_DexPathList__Element_dexFile); 480 ObjPtr<mirror::Class> const element_class = soa.Decode<mirror::Class>( 481 WellKnownClasses::dalvik_system_DexPathList__Element); 482 ObjPtr<mirror::Class> const dexfile_class = soa.Decode<mirror::Class>( 483 WellKnownClasses::dalvik_system_DexFile); 484 485 for (int32_t i = 0; i < dex_elements->GetLength(); ++i) { 486 mirror::Object* element = dex_elements->GetWithoutChecks(i); 487 // We can hit a null element here because this is invoked with a partially filled dex_elements 488 // array from DexPathList. DexPathList will open each dex sequentially, each time passing the 489 // list of dex files which were opened before. 490 if (element == nullptr) { 491 continue; 492 } 493 494 // We support this being dalvik.system.DexPathList$Element and dalvik.system.DexFile. 495 // TODO(calin): Code caried over oat_file_manager: supporting both classes seem to be 496 // a historical glitch. All the java code opens dex files using an array of Elements. 497 ObjPtr<mirror::Object> dex_file; 498 if (element_class == element->GetClass()) { 499 dex_file = dex_file_field->GetObject(element); 500 } else if (dexfile_class == element->GetClass()) { 501 dex_file = element; 502 } else { 503 LOG(ERROR) << "Unsupported element in dex_elements: " 504 << mirror::Class::PrettyClass(element->GetClass()); 505 return false; 506 } 507 508 if (!CollectDexFilesFromJavaDexFile(dex_file, cookie_field, out_dex_files)) { 509 return false; 510 } 511 } 512 return true; 513} 514 515// Adds the `class_loader` info to the `context`. 516// The dex file present in `dex_elements` array (if not null) will be added at the end of 517// the classpath. 518// This method is recursive (w.r.t. the class loader parent) and will stop once it reaches the 519// BootClassLoader. Note that the class loader chain is expected to be short. 520bool ClassLoaderContext::AddInfoToContextFromClassLoader( 521 ScopedObjectAccessAlreadyRunnable& soa, 522 Handle<mirror::ClassLoader> class_loader, 523 Handle<mirror::ObjectArray<mirror::Object>> dex_elements) 524 REQUIRES_SHARED(Locks::mutator_lock_) { 525 if (ClassLinker::IsBootClassLoader(soa, class_loader.Get())) { 526 // Nothing to do for the boot class loader as we don't add its dex files to the context. 527 return true; 528 } 529 530 ClassLoaderContext::ClassLoaderType type; 531 if (IsPathOrDexClassLoader(soa, class_loader)) { 532 type = kPathClassLoader; 533 } else if (IsDelegateLastClassLoader(soa, class_loader)) { 534 type = kDelegateLastClassLoader; 535 } else { 536 LOG(WARNING) << "Unsupported class loader"; 537 return false; 538 } 539 540 // Inspect the class loader for its dex files. 541 std::vector<const DexFile*> dex_files_loaded; 542 CollectDexFilesFromSupportedClassLoader(soa, class_loader, &dex_files_loaded); 543 544 // If we have a dex_elements array extract its dex elements now. 545 // This is used in two situations: 546 // 1) when a new ClassLoader is created DexPathList will open each dex file sequentially 547 // passing the list of already open dex files each time. This ensures that we see the 548 // correct context even if the ClassLoader under construction is not fully build. 549 // 2) when apk splits are loaded on the fly, the framework will load their dex files by 550 // appending them to the current class loader. When the new code paths are loaded in 551 // BaseDexClassLoader, the paths already present in the class loader will be passed 552 // in the dex_elements array. 553 if (dex_elements != nullptr) { 554 GetDexFilesFromDexElementsArray(soa, dex_elements, &dex_files_loaded); 555 } 556 557 class_loader_chain_.push_back(ClassLoaderContext::ClassLoaderInfo(type)); 558 ClassLoaderInfo& info = class_loader_chain_.back(); 559 for (const DexFile* dex_file : dex_files_loaded) { 560 info.classpath.push_back(dex_file->GetLocation()); 561 info.checksums.push_back(dex_file->GetLocationChecksum()); 562 info.opened_dex_files.emplace_back(dex_file); 563 } 564 565 // We created the ClassLoaderInfo for the current loader. Move on to its parent. 566 567 StackHandleScope<1> hs(Thread::Current()); 568 Handle<mirror::ClassLoader> parent = hs.NewHandle(class_loader->GetParent()); 569 570 // Note that dex_elements array is null here. The elements are considered to be part of the 571 // current class loader and are not passed to the parents. 572 ScopedNullHandle<mirror::ObjectArray<mirror::Object>> null_dex_elements; 573 return AddInfoToContextFromClassLoader(soa, parent, null_dex_elements); 574} 575 576std::unique_ptr<ClassLoaderContext> ClassLoaderContext::CreateContextForClassLoader( 577 jobject class_loader, 578 jobjectArray dex_elements) { 579 CHECK(class_loader != nullptr); 580 581 ScopedObjectAccess soa(Thread::Current()); 582 StackHandleScope<2> hs(soa.Self()); 583 Handle<mirror::ClassLoader> h_class_loader = 584 hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)); 585 Handle<mirror::ObjectArray<mirror::Object>> h_dex_elements = 586 hs.NewHandle(soa.Decode<mirror::ObjectArray<mirror::Object>>(dex_elements)); 587 588 std::unique_ptr<ClassLoaderContext> result(new ClassLoaderContext(/*owns_the_dex_files*/ false)); 589 if (result->AddInfoToContextFromClassLoader(soa, h_class_loader, h_dex_elements)) { 590 return result; 591 } else { 592 return nullptr; 593 } 594} 595 596bool ClassLoaderContext::VerifyClassLoaderContextMatch(const std::string& context_spec) { 597 ClassLoaderContext expected_context; 598 if (!expected_context.Parse(context_spec, /*parse_checksums*/ true)) { 599 LOG(WARNING) << "Invalid class loader context: " << context_spec; 600 return false; 601 } 602 603 if (expected_context.special_shared_library_) { 604 return true; 605 } 606 607 if (expected_context.class_loader_chain_.size() != class_loader_chain_.size()) { 608 LOG(WARNING) << "ClassLoaderContext size mismatch. expected=" 609 << expected_context.class_loader_chain_.size() 610 << ", actual=" << class_loader_chain_.size(); 611 return false; 612 } 613 614 for (size_t i = 0; i < class_loader_chain_.size(); i++) { 615 const ClassLoaderInfo& info = class_loader_chain_[i]; 616 const ClassLoaderInfo& expected_info = expected_context.class_loader_chain_[i]; 617 if (info.type != expected_info.type) { 618 LOG(WARNING) << "ClassLoaderContext type mismatch for position " << i 619 << ". expected=" << GetClassLoaderTypeName(expected_info.type) 620 << ", found=" << GetClassLoaderTypeName(info.type); 621 return false; 622 } 623 if (info.classpath.size() != expected_info.classpath.size()) { 624 LOG(WARNING) << "ClassLoaderContext classpath size mismatch for position " << i 625 << ". expected=" << expected_info.classpath.size() 626 << ", found=" << info.classpath.size(); 627 return false; 628 } 629 630 DCHECK_EQ(info.classpath.size(), info.checksums.size()); 631 DCHECK_EQ(expected_info.classpath.size(), expected_info.checksums.size()); 632 633 for (size_t k = 0; k < info.classpath.size(); k++) { 634 if (info.classpath[k] != expected_info.classpath[k]) { 635 LOG(WARNING) << "ClassLoaderContext classpath element mismatch for position " << i 636 << ". expected=" << expected_info.classpath[k] 637 << ", found=" << info.classpath[k]; 638 return false; 639 } 640 if (info.checksums[k] != expected_info.checksums[k]) { 641 LOG(WARNING) << "ClassLoaderContext classpath element checksum mismatch for position " << i 642 << ". expected=" << expected_info.checksums[k] 643 << ", found=" << info.checksums[k]; 644 return false; 645 } 646 } 647 } 648 return true; 649} 650 651jclass ClassLoaderContext::GetClassLoaderClass(ClassLoaderType type) { 652 switch (type) { 653 case kPathClassLoader: return WellKnownClasses::dalvik_system_PathClassLoader; 654 case kDelegateLastClassLoader: return WellKnownClasses::dalvik_system_DelegateLastClassLoader; 655 case kInvalidClassLoader: break; // will fail after the switch. 656 } 657 LOG(FATAL) << "Invalid class loader type " << type; 658 UNREACHABLE(); 659} 660 661} // namespace art 662 663