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 <gtest/gtest.h> 20 21 #include "android-base/strings.h" 22 #include "base/dchecked_vector.h" 23 #include "base/stl_util.h" 24 #include "class_linker.h" 25 #include "common_runtime_test.h" 26 #include "dex/dex_file.h" 27 #include "handle_scope-inl.h" 28 #include "mirror/class.h" 29 #include "mirror/class_loader.h" 30 #include "mirror/object-inl.h" 31 #include "oat_file_assistant.h" 32 #include "runtime.h" 33 #include "scoped_thread_state_change-inl.h" 34 #include "thread.h" 35 #include "well_known_classes.h" 36 37 namespace art { 38 39 class ClassLoaderContextTest : public CommonRuntimeTest { 40 public: 41 void VerifyContextSize(ClassLoaderContext* context, size_t expected_size) { 42 ASSERT_TRUE(context != nullptr); 43 ASSERT_EQ(expected_size, context->class_loader_chain_.size()); 44 } 45 46 void VerifyClassLoaderPCL(ClassLoaderContext* context, 47 size_t index, 48 const std::string& classpath) { 49 VerifyClassLoaderInfo( 50 context, index, ClassLoaderContext::kPathClassLoader, classpath); 51 } 52 53 void VerifyClassLoaderDLC(ClassLoaderContext* context, 54 size_t index, 55 const std::string& classpath) { 56 VerifyClassLoaderInfo( 57 context, index, ClassLoaderContext::kDelegateLastClassLoader, classpath); 58 } 59 60 void VerifyClassLoaderPCLFromTestDex(ClassLoaderContext* context, 61 size_t index, 62 const std::string& test_name) { 63 VerifyClassLoaderFromTestDex( 64 context, index, ClassLoaderContext::kPathClassLoader, test_name); 65 } 66 67 void VerifyClassLoaderDLCFromTestDex(ClassLoaderContext* context, 68 size_t index, 69 const std::string& test_name) { 70 VerifyClassLoaderFromTestDex( 71 context, index, ClassLoaderContext::kDelegateLastClassLoader, test_name); 72 } 73 74 enum class LocationCheck { 75 kEquals, 76 kEndsWith 77 }; 78 enum class BaseLocationCheck { 79 kEquals, 80 kEndsWith 81 }; 82 83 static bool IsAbsoluteLocation(const std::string& location) { 84 return !location.empty() && location[0] == '/'; 85 } 86 87 void VerifyOpenDexFiles( 88 ClassLoaderContext* context, 89 size_t index, 90 std::vector<std::unique_ptr<const DexFile>>* all_dex_files) { 91 ASSERT_TRUE(context != nullptr); 92 ASSERT_TRUE(context->dex_files_open_attempted_); 93 ASSERT_TRUE(context->dex_files_open_result_); 94 ClassLoaderContext::ClassLoaderInfo& info = context->class_loader_chain_[index]; 95 ASSERT_EQ(all_dex_files->size(), info.classpath.size()); 96 ASSERT_EQ(all_dex_files->size(), info.opened_dex_files.size()); 97 size_t cur_open_dex_index = 0; 98 for (size_t k = 0; k < all_dex_files->size(); k++) { 99 std::unique_ptr<const DexFile>& opened_dex_file = 100 info.opened_dex_files[cur_open_dex_index++]; 101 std::unique_ptr<const DexFile>& expected_dex_file = (*all_dex_files)[k]; 102 103 std::string expected_location = expected_dex_file->GetLocation(); 104 105 const std::string& opened_location = opened_dex_file->GetLocation(); 106 if (!IsAbsoluteLocation(opened_location)) { 107 // If the opened location is relative (it was open from a relative path without a 108 // classpath_dir) it might not match the expected location which is absolute in tests). 109 // So we compare the endings (the checksum will validate it's actually the same file). 110 ASSERT_EQ(0, expected_location.compare( 111 expected_location.length() - opened_location.length(), 112 opened_location.length(), 113 opened_location)); 114 } else { 115 ASSERT_EQ(expected_location, opened_location); 116 } 117 ASSERT_EQ(expected_dex_file->GetLocationChecksum(), opened_dex_file->GetLocationChecksum()); 118 ASSERT_EQ(info.classpath[k], opened_location); 119 } 120 } 121 122 std::unique_ptr<ClassLoaderContext> CreateContextForClassLoader(jobject class_loader) { 123 return ClassLoaderContext::CreateContextForClassLoader(class_loader, nullptr); 124 } 125 126 std::unique_ptr<ClassLoaderContext> ParseContextWithChecksums(const std::string& context_spec) { 127 std::unique_ptr<ClassLoaderContext> context(new ClassLoaderContext()); 128 if (!context->Parse(context_spec, /*parse_checksums*/ true)) { 129 return nullptr; 130 } 131 return context; 132 } 133 134 void VerifyContextForClassLoader(ClassLoaderContext* context) { 135 ASSERT_TRUE(context != nullptr); 136 ASSERT_TRUE(context->dex_files_open_attempted_); 137 ASSERT_TRUE(context->dex_files_open_result_); 138 ASSERT_FALSE(context->owns_the_dex_files_); 139 ASSERT_FALSE(context->special_shared_library_); 140 } 141 142 void VerifyClassLoaderDexFiles(ScopedObjectAccess& soa, 143 Handle<mirror::ClassLoader> class_loader, 144 jclass type, 145 std::vector<const DexFile*>& expected_dex_files) 146 REQUIRES_SHARED(Locks::mutator_lock_) { 147 ASSERT_TRUE(class_loader->GetClass() == soa.Decode<mirror::Class>(type)); 148 149 std::vector<const DexFile*> class_loader_dex_files = GetDexFiles(soa, class_loader); 150 ASSERT_EQ(expected_dex_files.size(), class_loader_dex_files.size()); 151 152 for (size_t i = 0; i < expected_dex_files.size(); i++) { 153 ASSERT_EQ(expected_dex_files[i]->GetLocation(), 154 class_loader_dex_files[i]->GetLocation()); 155 ASSERT_EQ(expected_dex_files[i]->GetLocationChecksum(), 156 class_loader_dex_files[i]->GetLocationChecksum()); 157 } 158 } 159 160 void PretendContextOpenedDexFiles(ClassLoaderContext* context) { 161 context->dex_files_open_attempted_ = true; 162 context->dex_files_open_result_ = true; 163 } 164 165 private: 166 void VerifyClassLoaderInfo(ClassLoaderContext* context, 167 size_t index, 168 ClassLoaderContext::ClassLoaderType type, 169 const std::string& classpath) { 170 ASSERT_TRUE(context != nullptr); 171 ASSERT_GT(context->class_loader_chain_.size(), index); 172 ClassLoaderContext::ClassLoaderInfo& info = context->class_loader_chain_[index]; 173 ASSERT_EQ(type, info.type); 174 std::vector<std::string> expected_classpath; 175 Split(classpath, ':', &expected_classpath); 176 ASSERT_EQ(expected_classpath, info.classpath); 177 } 178 179 void VerifyClassLoaderFromTestDex(ClassLoaderContext* context, 180 size_t index, 181 ClassLoaderContext::ClassLoaderType type, 182 const std::string& test_name) { 183 std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles(test_name.c_str()); 184 185 VerifyClassLoaderInfo(context, index, type, GetTestDexFileName(test_name.c_str())); 186 VerifyOpenDexFiles(context, index, &dex_files); 187 } 188 }; 189 190 TEST_F(ClassLoaderContextTest, ParseValidEmptyContext) { 191 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(""); 192 // An empty context should create a single empty PathClassLoader. 193 VerifyContextSize(context.get(), 1); 194 VerifyClassLoaderPCL(context.get(), 0, ""); 195 } 196 197 TEST_F(ClassLoaderContextTest, ParseValidSharedLibraryContext) { 198 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create("&"); 199 // An shared library context should have no class loader in the chain. 200 VerifyContextSize(context.get(), 0); 201 } 202 203 TEST_F(ClassLoaderContextTest, ParseValidContextPCL) { 204 std::unique_ptr<ClassLoaderContext> context = 205 ClassLoaderContext::Create("PCL[a.dex]"); 206 VerifyContextSize(context.get(), 1); 207 VerifyClassLoaderPCL(context.get(), 0, "a.dex"); 208 } 209 210 TEST_F(ClassLoaderContextTest, ParseValidContextDLC) { 211 std::unique_ptr<ClassLoaderContext> context = 212 ClassLoaderContext::Create("DLC[a.dex]"); 213 VerifyContextSize(context.get(), 1); 214 VerifyClassLoaderDLC(context.get(), 0, "a.dex"); 215 } 216 217 TEST_F(ClassLoaderContextTest, ParseValidContextChain) { 218 std::unique_ptr<ClassLoaderContext> context = 219 ClassLoaderContext::Create("PCL[a.dex:b.dex];DLC[c.dex:d.dex];PCL[e.dex]"); 220 VerifyContextSize(context.get(), 3); 221 VerifyClassLoaderPCL(context.get(), 0, "a.dex:b.dex"); 222 VerifyClassLoaderDLC(context.get(), 1, "c.dex:d.dex"); 223 VerifyClassLoaderPCL(context.get(), 2, "e.dex"); 224 } 225 226 TEST_F(ClassLoaderContextTest, ParseValidEmptyContextDLC) { 227 std::unique_ptr<ClassLoaderContext> context = 228 ClassLoaderContext::Create("DLC[]"); 229 VerifyContextSize(context.get(), 1); 230 VerifyClassLoaderDLC(context.get(), 0, ""); 231 } 232 233 TEST_F(ClassLoaderContextTest, ParseValidContextSpecialSymbol) { 234 std::unique_ptr<ClassLoaderContext> context = 235 ClassLoaderContext::Create(OatFile::kSpecialSharedLibrary); 236 VerifyContextSize(context.get(), 0); 237 } 238 239 TEST_F(ClassLoaderContextTest, ParseInvalidValidContexts) { 240 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("ABC[a.dex]")); 241 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL")); 242 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL[a.dex")); 243 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCLa.dex]")); 244 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL{a.dex}")); 245 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL[a.dex];DLC[b.dex")); 246 } 247 248 TEST_F(ClassLoaderContextTest, OpenInvalidDexFiles) { 249 std::unique_ptr<ClassLoaderContext> context = 250 ClassLoaderContext::Create("PCL[does_not_exist.dex]"); 251 VerifyContextSize(context.get(), 1); 252 ASSERT_FALSE(context->OpenDexFiles(InstructionSet::kArm, ".")); 253 } 254 255 TEST_F(ClassLoaderContextTest, OpenValidDexFiles) { 256 std::string multidex_name = GetTestDexFileName("MultiDex"); 257 std::string myclass_dex_name = GetTestDexFileName("MyClass"); 258 std::string dex_name = GetTestDexFileName("Main"); 259 260 261 std::unique_ptr<ClassLoaderContext> context = 262 ClassLoaderContext::Create( 263 "PCL[" + multidex_name + ":" + myclass_dex_name + "];" + 264 "DLC[" + dex_name + "]"); 265 266 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, /*classpath_dir*/ "")); 267 268 VerifyContextSize(context.get(), 2); 269 270 std::vector<std::unique_ptr<const DexFile>> all_dex_files0 = OpenTestDexFiles("MultiDex"); 271 std::vector<std::unique_ptr<const DexFile>> myclass_dex_files = OpenTestDexFiles("MyClass"); 272 for (size_t i = 0; i < myclass_dex_files.size(); i++) { 273 all_dex_files0.emplace_back(myclass_dex_files[i].release()); 274 } 275 VerifyOpenDexFiles(context.get(), 0, &all_dex_files0); 276 277 std::vector<std::unique_ptr<const DexFile>> all_dex_files1 = OpenTestDexFiles("Main"); 278 VerifyOpenDexFiles(context.get(), 1, &all_dex_files1); 279 } 280 281 // Creates a relative path from cwd to 'in'. Returns false if it cannot be done. 282 // TODO We should somehow support this in all situations. b/72042237. 283 static bool CreateRelativeString(const std::string& in, const char* cwd, std::string* out) { 284 int cwd_len = strlen(cwd); 285 if (!android::base::StartsWith(in, cwd) || (cwd_len < 1)) { 286 return false; 287 } 288 bool contains_trailing_slash = (cwd[cwd_len - 1] == '/'); 289 int start_position = cwd_len + (contains_trailing_slash ? 0 : 1); 290 *out = in.substr(start_position); 291 return true; 292 } 293 294 TEST_F(ClassLoaderContextTest, OpenValidDexFilesRelative) { 295 char cwd_buf[4096]; 296 if (getcwd(cwd_buf, arraysize(cwd_buf)) == nullptr) { 297 PLOG(FATAL) << "Could not get working directory"; 298 } 299 std::string multidex_name; 300 std::string myclass_dex_name; 301 std::string dex_name; 302 if (!CreateRelativeString(GetTestDexFileName("MultiDex"), cwd_buf, &multidex_name) || 303 !CreateRelativeString(GetTestDexFileName("MyClass"), cwd_buf, &myclass_dex_name) || 304 !CreateRelativeString(GetTestDexFileName("Main"), cwd_buf, &dex_name)) { 305 LOG(ERROR) << "Test OpenValidDexFilesRelative cannot be run because target dex files have no " 306 << "relative path."; 307 SUCCEED(); 308 return; 309 } 310 311 312 std::unique_ptr<ClassLoaderContext> context = 313 ClassLoaderContext::Create( 314 "PCL[" + multidex_name + ":" + myclass_dex_name + "];" + 315 "DLC[" + dex_name + "]"); 316 317 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, /*classpath_dir*/ "")); 318 319 std::vector<std::unique_ptr<const DexFile>> all_dex_files0 = OpenTestDexFiles("MultiDex"); 320 std::vector<std::unique_ptr<const DexFile>> myclass_dex_files = OpenTestDexFiles("MyClass"); 321 for (size_t i = 0; i < myclass_dex_files.size(); i++) { 322 all_dex_files0.emplace_back(myclass_dex_files[i].release()); 323 } 324 VerifyOpenDexFiles(context.get(), 0, &all_dex_files0); 325 326 std::vector<std::unique_ptr<const DexFile>> all_dex_files1 = OpenTestDexFiles("Main"); 327 VerifyOpenDexFiles(context.get(), 1, &all_dex_files1); 328 } 329 330 TEST_F(ClassLoaderContextTest, OpenValidDexFilesClasspathDir) { 331 char cwd_buf[4096]; 332 if (getcwd(cwd_buf, arraysize(cwd_buf)) == nullptr) { 333 PLOG(FATAL) << "Could not get working directory"; 334 } 335 std::string multidex_name; 336 std::string myclass_dex_name; 337 std::string dex_name; 338 if (!CreateRelativeString(GetTestDexFileName("MultiDex"), cwd_buf, &multidex_name) || 339 !CreateRelativeString(GetTestDexFileName("MyClass"), cwd_buf, &myclass_dex_name) || 340 !CreateRelativeString(GetTestDexFileName("Main"), cwd_buf, &dex_name)) { 341 LOG(ERROR) << "Test OpenValidDexFilesClasspathDir cannot be run because target dex files have " 342 << "no relative path."; 343 SUCCEED(); 344 return; 345 } 346 std::unique_ptr<ClassLoaderContext> context = 347 ClassLoaderContext::Create( 348 "PCL[" + multidex_name + ":" + myclass_dex_name + "];" + 349 "DLC[" + dex_name + "]"); 350 351 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, cwd_buf)); 352 353 VerifyContextSize(context.get(), 2); 354 std::vector<std::unique_ptr<const DexFile>> all_dex_files0 = OpenTestDexFiles("MultiDex"); 355 std::vector<std::unique_ptr<const DexFile>> myclass_dex_files = OpenTestDexFiles("MyClass"); 356 for (size_t i = 0; i < myclass_dex_files.size(); i++) { 357 all_dex_files0.emplace_back(myclass_dex_files[i].release()); 358 } 359 VerifyOpenDexFiles(context.get(), 0, &all_dex_files0); 360 361 std::vector<std::unique_ptr<const DexFile>> all_dex_files1 = OpenTestDexFiles("Main"); 362 VerifyOpenDexFiles(context.get(), 1, &all_dex_files1); 363 } 364 365 TEST_F(ClassLoaderContextTest, OpenInvalidDexFilesMix) { 366 std::string dex_name = GetTestDexFileName("Main"); 367 std::unique_ptr<ClassLoaderContext> context = 368 ClassLoaderContext::Create("PCL[does_not_exist.dex];DLC[" + dex_name + "]"); 369 ASSERT_FALSE(context->OpenDexFiles(InstructionSet::kArm, "")); 370 } 371 372 TEST_F(ClassLoaderContextTest, CreateClassLoader) { 373 std::string dex_name = GetTestDexFileName("Main"); 374 std::unique_ptr<ClassLoaderContext> context = 375 ClassLoaderContext::Create("PCL[" + dex_name + "]"); 376 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, "")); 377 378 std::vector<std::unique_ptr<const DexFile>> classpath_dex = OpenTestDexFiles("Main"); 379 std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex"); 380 381 std::vector<const DexFile*> compilation_sources_raw = 382 MakeNonOwningPointerVector(compilation_sources); 383 jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw); 384 ASSERT_TRUE(jclass_loader != nullptr); 385 386 ScopedObjectAccess soa(Thread::Current()); 387 388 StackHandleScope<1> hs(soa.Self()); 389 Handle<mirror::ClassLoader> class_loader = hs.NewHandle( 390 soa.Decode<mirror::ClassLoader>(jclass_loader)); 391 392 ASSERT_TRUE(class_loader->GetClass() == 393 soa.Decode<mirror::Class>(WellKnownClasses::dalvik_system_PathClassLoader)); 394 ASSERT_TRUE(class_loader->GetParent()->GetClass() == 395 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader)); 396 397 // For the first class loader the class path dex files must come first and then the 398 // compilation sources. 399 std::vector<const DexFile*> expected_classpath = MakeNonOwningPointerVector(classpath_dex); 400 for (auto& dex : compilation_sources_raw) { 401 expected_classpath.push_back(dex); 402 } 403 404 VerifyClassLoaderDexFiles(soa, 405 class_loader, 406 WellKnownClasses::dalvik_system_PathClassLoader, 407 expected_classpath); 408 } 409 410 TEST_F(ClassLoaderContextTest, CreateClassLoaderWithEmptyContext) { 411 std::unique_ptr<ClassLoaderContext> context = 412 ClassLoaderContext::Create(""); 413 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, "")); 414 415 std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex"); 416 417 std::vector<const DexFile*> compilation_sources_raw = 418 MakeNonOwningPointerVector(compilation_sources); 419 jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw); 420 ASSERT_TRUE(jclass_loader != nullptr); 421 422 ScopedObjectAccess soa(Thread::Current()); 423 424 StackHandleScope<1> hs(soa.Self()); 425 Handle<mirror::ClassLoader> class_loader = hs.NewHandle( 426 soa.Decode<mirror::ClassLoader>(jclass_loader)); 427 428 // An empty context should create a single PathClassLoader with only the compilation sources. 429 VerifyClassLoaderDexFiles(soa, 430 class_loader, 431 WellKnownClasses::dalvik_system_PathClassLoader, 432 compilation_sources_raw); 433 ASSERT_TRUE(class_loader->GetParent()->GetClass() == 434 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader)); 435 } 436 437 TEST_F(ClassLoaderContextTest, CreateClassLoaderWithSharedLibraryContext) { 438 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create("&"); 439 440 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, "")); 441 442 std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex"); 443 444 std::vector<const DexFile*> compilation_sources_raw = 445 MakeNonOwningPointerVector(compilation_sources); 446 jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw); 447 ASSERT_TRUE(jclass_loader != nullptr); 448 449 ScopedObjectAccess soa(Thread::Current()); 450 451 StackHandleScope<1> hs(soa.Self()); 452 Handle<mirror::ClassLoader> class_loader = hs.NewHandle( 453 soa.Decode<mirror::ClassLoader>(jclass_loader)); 454 455 // A shared library context should create a single PathClassLoader with only the compilation 456 // sources. 457 VerifyClassLoaderDexFiles(soa, 458 class_loader, 459 WellKnownClasses::dalvik_system_PathClassLoader, 460 compilation_sources_raw); 461 ASSERT_TRUE(class_loader->GetParent()->GetClass() == 462 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader)); 463 } 464 465 TEST_F(ClassLoaderContextTest, CreateClassLoaderWithComplexChain) { 466 // Setup the context. 467 std::vector<std::unique_ptr<const DexFile>> classpath_dex_a = OpenTestDexFiles("ForClassLoaderA"); 468 std::vector<std::unique_ptr<const DexFile>> classpath_dex_b = OpenTestDexFiles("ForClassLoaderB"); 469 std::vector<std::unique_ptr<const DexFile>> classpath_dex_c = OpenTestDexFiles("ForClassLoaderC"); 470 std::vector<std::unique_ptr<const DexFile>> classpath_dex_d = OpenTestDexFiles("ForClassLoaderD"); 471 472 std::string context_spec = 473 "PCL[" + CreateClassPath(classpath_dex_a) + ":" + CreateClassPath(classpath_dex_b) + "];" + 474 "DLC[" + CreateClassPath(classpath_dex_c) + "];" + 475 "PCL[" + CreateClassPath(classpath_dex_d) + "]"; 476 477 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_spec); 478 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, "")); 479 480 // Setup the compilation sources. 481 std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex"); 482 std::vector<const DexFile*> compilation_sources_raw = 483 MakeNonOwningPointerVector(compilation_sources); 484 485 // Create the class loader. 486 jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw); 487 ASSERT_TRUE(jclass_loader != nullptr); 488 489 // Verify the class loader. 490 ScopedObjectAccess soa(Thread::Current()); 491 492 StackHandleScope<3> hs(soa.Self()); 493 Handle<mirror::ClassLoader> class_loader_1 = hs.NewHandle( 494 soa.Decode<mirror::ClassLoader>(jclass_loader)); 495 496 // Verify the first class loader 497 498 // For the first class loader the class path dex files must come first and then the 499 // compilation sources. 500 std::vector<const DexFile*> class_loader_1_dex_files = 501 MakeNonOwningPointerVector(classpath_dex_a); 502 for (auto& dex : classpath_dex_b) { 503 class_loader_1_dex_files.push_back(dex.get()); 504 } 505 for (auto& dex : compilation_sources_raw) { 506 class_loader_1_dex_files.push_back(dex); 507 } 508 VerifyClassLoaderDexFiles(soa, 509 class_loader_1, 510 WellKnownClasses::dalvik_system_PathClassLoader, 511 class_loader_1_dex_files); 512 513 // Verify the second class loader 514 Handle<mirror::ClassLoader> class_loader_2 = hs.NewHandle(class_loader_1->GetParent()); 515 std::vector<const DexFile*> class_loader_2_dex_files = 516 MakeNonOwningPointerVector(classpath_dex_c); 517 VerifyClassLoaderDexFiles(soa, 518 class_loader_2, 519 WellKnownClasses::dalvik_system_DelegateLastClassLoader, 520 class_loader_2_dex_files); 521 522 // Verify the third class loader 523 Handle<mirror::ClassLoader> class_loader_3 = hs.NewHandle(class_loader_2->GetParent()); 524 std::vector<const DexFile*> class_loader_3_dex_files = 525 MakeNonOwningPointerVector(classpath_dex_d); 526 VerifyClassLoaderDexFiles(soa, 527 class_loader_3, 528 WellKnownClasses::dalvik_system_PathClassLoader, 529 class_loader_3_dex_files); 530 // The last class loader should have the BootClassLoader as a parent. 531 ASSERT_TRUE(class_loader_3->GetParent()->GetClass() == 532 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader)); 533 } 534 535 536 TEST_F(ClassLoaderContextTest, RemoveSourceLocations) { 537 std::unique_ptr<ClassLoaderContext> context = 538 ClassLoaderContext::Create("PCL[a.dex]"); 539 dchecked_vector<std::string> classpath_dex; 540 classpath_dex.push_back("a.dex"); 541 dchecked_vector<std::string> compilation_sources; 542 compilation_sources.push_back("src.dex"); 543 544 // Nothing should be removed. 545 ASSERT_FALSE(context->RemoveLocationsFromClassPaths(compilation_sources)); 546 VerifyClassLoaderPCL(context.get(), 0, "a.dex"); 547 // Classes should be removed. 548 ASSERT_TRUE(context->RemoveLocationsFromClassPaths(classpath_dex)); 549 VerifyClassLoaderPCL(context.get(), 0, ""); 550 } 551 552 TEST_F(ClassLoaderContextTest, EncodeInOatFile) { 553 std::string dex1_name = GetTestDexFileName("Main"); 554 std::string dex2_name = GetTestDexFileName("MyClass"); 555 std::unique_ptr<ClassLoaderContext> context = 556 ClassLoaderContext::Create("PCL[" + dex1_name + ":" + dex2_name + "]"); 557 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, "")); 558 559 std::vector<std::unique_ptr<const DexFile>> dex1 = OpenTestDexFiles("Main"); 560 std::vector<std::unique_ptr<const DexFile>> dex2 = OpenTestDexFiles("MyClass"); 561 std::string encoding = context->EncodeContextForOatFile(""); 562 std::string expected_encoding = "PCL[" + CreateClassPathWithChecksums(dex1) + ":" + 563 CreateClassPathWithChecksums(dex2) + "]"; 564 ASSERT_EQ(expected_encoding, context->EncodeContextForOatFile("")); 565 } 566 567 TEST_F(ClassLoaderContextTest, EncodeForDex2oat) { 568 std::string dex1_name = GetTestDexFileName("Main"); 569 std::string dex2_name = GetTestDexFileName("MultiDex"); 570 std::unique_ptr<ClassLoaderContext> context = 571 ClassLoaderContext::Create("PCL[" + dex1_name + ":" + dex2_name + "]"); 572 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, "")); 573 574 std::vector<std::unique_ptr<const DexFile>> dex1 = OpenTestDexFiles("Main"); 575 std::vector<std::unique_ptr<const DexFile>> dex2 = OpenTestDexFiles("MultiDex"); 576 std::string encoding = context->EncodeContextForDex2oat(""); 577 std::string expected_encoding = "PCL[" + dex1_name + ":" + dex2_name + "]"; 578 ASSERT_EQ(expected_encoding, context->EncodeContextForDex2oat("")); 579 } 580 581 // TODO(calin) add a test which creates the context for a class loader together with dex_elements. 582 TEST_F(ClassLoaderContextTest, CreateContextForClassLoader) { 583 // The chain is 584 // ClassLoaderA (PathClassLoader) 585 // ^ 586 // | 587 // ClassLoaderB (DelegateLastClassLoader) 588 // ^ 589 // | 590 // ClassLoaderC (PathClassLoader) 591 // ^ 592 // | 593 // ClassLoaderD (DelegateLastClassLoader) 594 595 jobject class_loader_a = LoadDexInPathClassLoader("ForClassLoaderA", nullptr); 596 jobject class_loader_b = LoadDexInDelegateLastClassLoader("ForClassLoaderB", class_loader_a); 597 jobject class_loader_c = LoadDexInPathClassLoader("ForClassLoaderC", class_loader_b); 598 jobject class_loader_d = LoadDexInDelegateLastClassLoader("ForClassLoaderD", class_loader_c); 599 600 std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader_d); 601 602 VerifyContextForClassLoader(context.get()); 603 VerifyContextSize(context.get(), 4); 604 605 VerifyClassLoaderDLCFromTestDex(context.get(), 0, "ForClassLoaderD"); 606 VerifyClassLoaderPCLFromTestDex(context.get(), 1, "ForClassLoaderC"); 607 VerifyClassLoaderDLCFromTestDex(context.get(), 2, "ForClassLoaderB"); 608 VerifyClassLoaderPCLFromTestDex(context.get(), 3, "ForClassLoaderA"); 609 } 610 611 TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextMatch) { 612 std::string context_spec = "PCL[a.dex*123:b.dex*456];DLC[c.dex*890]"; 613 std::unique_ptr<ClassLoaderContext> context = ParseContextWithChecksums(context_spec); 614 // Pretend that we successfully open the dex files to pass the DCHECKS. 615 // (as it's much easier to test all the corner cases without relying on actual dex files). 616 PretendContextOpenedDexFiles(context.get()); 617 618 VerifyContextSize(context.get(), 2); 619 VerifyClassLoaderPCL(context.get(), 0, "a.dex:b.dex"); 620 VerifyClassLoaderDLC(context.get(), 1, "c.dex"); 621 622 ASSERT_TRUE(context->VerifyClassLoaderContextMatch(context_spec)); 623 624 std::string wrong_class_loader_type = "PCL[a.dex*123:b.dex*456];PCL[c.dex*890]"; 625 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_class_loader_type)); 626 627 std::string wrong_class_loader_order = "DLC[c.dex*890];PCL[a.dex*123:b.dex*456]"; 628 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_class_loader_order)); 629 630 std::string wrong_classpath_order = "PCL[b.dex*456:a.dex*123];DLC[c.dex*890]"; 631 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_classpath_order)); 632 633 std::string wrong_checksum = "PCL[a.dex*999:b.dex*456];DLC[c.dex*890]"; 634 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_checksum)); 635 636 std::string wrong_extra_class_loader = "PCL[a.dex*123:b.dex*456];DLC[c.dex*890];PCL[d.dex*321]"; 637 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_extra_class_loader)); 638 639 std::string wrong_extra_classpath = "PCL[a.dex*123:b.dex*456];DLC[c.dex*890:d.dex*321]"; 640 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_extra_classpath)); 641 642 std::string wrong_spec = "PCL[a.dex*999:b.dex*456];DLC["; 643 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_spec)); 644 } 645 646 TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextMatchAfterEncoding) { 647 jobject class_loader_a = LoadDexInPathClassLoader("ForClassLoaderA", nullptr); 648 jobject class_loader_b = LoadDexInDelegateLastClassLoader("ForClassLoaderB", class_loader_a); 649 jobject class_loader_c = LoadDexInPathClassLoader("ForClassLoaderC", class_loader_b); 650 jobject class_loader_d = LoadDexInDelegateLastClassLoader("ForClassLoaderD", class_loader_c); 651 652 std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader_d); 653 654 std::string context_with_no_base_dir = context->EncodeContextForOatFile(""); 655 ASSERT_TRUE(context->VerifyClassLoaderContextMatch(context_with_no_base_dir)); 656 657 std::string dex_location = GetTestDexFileName("ForClassLoaderA"); 658 size_t pos = dex_location.rfind('/'); 659 ASSERT_NE(std::string::npos, pos); 660 std::string parent = dex_location.substr(0, pos); 661 662 std::string context_with_base_dir = context->EncodeContextForOatFile(parent); 663 ASSERT_NE(context_with_base_dir, context_with_no_base_dir); 664 ASSERT_TRUE(context->VerifyClassLoaderContextMatch(context_with_base_dir)); 665 } 666 667 TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextMatchAfterEncodingMultidex) { 668 jobject class_loader = LoadDexInPathClassLoader("MultiDex", nullptr); 669 670 std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader); 671 672 ASSERT_TRUE(context->VerifyClassLoaderContextMatch(context->EncodeContextForOatFile(""))); 673 } 674 675 } // namespace art 676