1 /* 2 * Copyright (C) 2008 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 "dalvik_system_VMRuntime.h" 18 19 #ifdef HAVE_ANDROID_OS 20 extern "C" void android_set_application_target_sdk_version(uint32_t version); 21 #endif 22 #include <limits.h> 23 #include <ScopedUtfChars.h> 24 25 #pragma GCC diagnostic push 26 #pragma GCC diagnostic ignored "-Wshadow" 27 #include "toStringArray.h" 28 #pragma GCC diagnostic pop 29 30 #include "art_method-inl.h" 31 #include "arch/instruction_set.h" 32 #include "class_linker-inl.h" 33 #include "common_throws.h" 34 #include "debugger.h" 35 #include "dex_file-inl.h" 36 #include "gc/accounting/card_table-inl.h" 37 #include "gc/allocator/dlmalloc.h" 38 #include "gc/heap.h" 39 #include "gc/space/dlmalloc_space.h" 40 #include "gc/space/image_space.h" 41 #include "gc/task_processor.h" 42 #include "intern_table.h" 43 #include "jni_internal.h" 44 #include "mirror/class-inl.h" 45 #include "mirror/dex_cache-inl.h" 46 #include "mirror/object-inl.h" 47 #include "runtime.h" 48 #include "scoped_fast_native_object_access.h" 49 #include "scoped_thread_state_change.h" 50 #include "thread.h" 51 #include "thread_list.h" 52 53 namespace art { 54 55 static jfloat VMRuntime_getTargetHeapUtilization(JNIEnv*, jobject) { 56 return Runtime::Current()->GetHeap()->GetTargetHeapUtilization(); 57 } 58 59 static void VMRuntime_nativeSetTargetHeapUtilization(JNIEnv*, jobject, jfloat target) { 60 Runtime::Current()->GetHeap()->SetTargetHeapUtilization(target); 61 } 62 63 static void VMRuntime_startJitCompilation(JNIEnv*, jobject) { 64 } 65 66 static void VMRuntime_disableJitCompilation(JNIEnv*, jobject) { 67 } 68 69 static jobject VMRuntime_newNonMovableArray(JNIEnv* env, jobject, jclass javaElementClass, 70 jint length) { 71 ScopedFastNativeObjectAccess soa(env); 72 if (UNLIKELY(length < 0)) { 73 ThrowNegativeArraySizeException(length); 74 return nullptr; 75 } 76 mirror::Class* element_class = soa.Decode<mirror::Class*>(javaElementClass); 77 if (UNLIKELY(element_class == nullptr)) { 78 ThrowNullPointerException("element class == null"); 79 return nullptr; 80 } 81 Runtime* runtime = Runtime::Current(); 82 mirror::Class* array_class = 83 runtime->GetClassLinker()->FindArrayClass(soa.Self(), &element_class); 84 if (UNLIKELY(array_class == nullptr)) { 85 return nullptr; 86 } 87 gc::AllocatorType allocator = runtime->GetHeap()->GetCurrentNonMovingAllocator(); 88 mirror::Array* result = mirror::Array::Alloc<true>(soa.Self(), array_class, length, 89 array_class->GetComponentSizeShift(), 90 allocator); 91 return soa.AddLocalReference<jobject>(result); 92 } 93 94 static jobject VMRuntime_newUnpaddedArray(JNIEnv* env, jobject, jclass javaElementClass, 95 jint length) { 96 ScopedFastNativeObjectAccess soa(env); 97 if (UNLIKELY(length < 0)) { 98 ThrowNegativeArraySizeException(length); 99 return nullptr; 100 } 101 mirror::Class* element_class = soa.Decode<mirror::Class*>(javaElementClass); 102 if (UNLIKELY(element_class == nullptr)) { 103 ThrowNullPointerException("element class == null"); 104 return nullptr; 105 } 106 Runtime* runtime = Runtime::Current(); 107 mirror::Class* array_class = runtime->GetClassLinker()->FindArrayClass(soa.Self(), 108 &element_class); 109 if (UNLIKELY(array_class == nullptr)) { 110 return nullptr; 111 } 112 gc::AllocatorType allocator = runtime->GetHeap()->GetCurrentAllocator(); 113 mirror::Array* result = mirror::Array::Alloc<true, true>(soa.Self(), array_class, length, 114 array_class->GetComponentSizeShift(), 115 allocator); 116 return soa.AddLocalReference<jobject>(result); 117 } 118 119 static jlong VMRuntime_addressOf(JNIEnv* env, jobject, jobject javaArray) { 120 if (javaArray == nullptr) { // Most likely allocation failed 121 return 0; 122 } 123 ScopedFastNativeObjectAccess soa(env); 124 mirror::Array* array = soa.Decode<mirror::Array*>(javaArray); 125 if (!array->IsArrayInstance()) { 126 ThrowIllegalArgumentException("not an array"); 127 return 0; 128 } 129 if (Runtime::Current()->GetHeap()->IsMovableObject(array)) { 130 ThrowRuntimeException("Trying to get address of movable array object"); 131 return 0; 132 } 133 return reinterpret_cast<uintptr_t>(array->GetRawData(array->GetClass()->GetComponentSize(), 0)); 134 } 135 136 static void VMRuntime_clearGrowthLimit(JNIEnv*, jobject) { 137 Runtime::Current()->GetHeap()->ClearGrowthLimit(); 138 } 139 140 static void VMRuntime_clampGrowthLimit(JNIEnv*, jobject) { 141 Runtime::Current()->GetHeap()->ClampGrowthLimit(); 142 } 143 144 static jboolean VMRuntime_isDebuggerActive(JNIEnv*, jobject) { 145 return Dbg::IsDebuggerActive(); 146 } 147 148 static jobjectArray VMRuntime_properties(JNIEnv* env, jobject) { 149 return toStringArray(env, Runtime::Current()->GetProperties()); 150 } 151 152 // This is for backward compatibility with dalvik which returned the 153 // meaningless "." when no boot classpath or classpath was 154 // specified. Unfortunately, some tests were using java.class.path to 155 // lookup relative file locations, so they are counting on this to be 156 // ".", presumably some applications or libraries could have as well. 157 static const char* DefaultToDot(const std::string& class_path) { 158 return class_path.empty() ? "." : class_path.c_str(); 159 } 160 161 static jstring VMRuntime_bootClassPath(JNIEnv* env, jobject) { 162 return env->NewStringUTF(DefaultToDot(Runtime::Current()->GetBootClassPathString())); 163 } 164 165 static jstring VMRuntime_classPath(JNIEnv* env, jobject) { 166 return env->NewStringUTF(DefaultToDot(Runtime::Current()->GetClassPathString())); 167 } 168 169 static jstring VMRuntime_vmVersion(JNIEnv* env, jobject) { 170 return env->NewStringUTF(Runtime::GetVersion()); 171 } 172 173 static jstring VMRuntime_vmLibrary(JNIEnv* env, jobject) { 174 return env->NewStringUTF(kIsDebugBuild ? "libartd.so" : "libart.so"); 175 } 176 177 static jstring VMRuntime_vmInstructionSet(JNIEnv* env, jobject) { 178 InstructionSet isa = Runtime::Current()->GetInstructionSet(); 179 const char* isa_string = GetInstructionSetString(isa); 180 return env->NewStringUTF(isa_string); 181 } 182 183 static jboolean VMRuntime_is64Bit(JNIEnv*, jobject) { 184 bool is64BitMode = (sizeof(void*) == sizeof(uint64_t)); 185 return is64BitMode ? JNI_TRUE : JNI_FALSE; 186 } 187 188 static jboolean VMRuntime_isCheckJniEnabled(JNIEnv* env, jobject) { 189 return down_cast<JNIEnvExt*>(env)->vm->IsCheckJniEnabled() ? JNI_TRUE : JNI_FALSE; 190 } 191 192 static void VMRuntime_setTargetSdkVersionNative(JNIEnv*, jobject, jint target_sdk_version) { 193 // This is the target SDK version of the app we're about to run. It is intended that this a place 194 // where workarounds can be enabled. 195 // Note that targetSdkVersion may be CUR_DEVELOPMENT (10000). 196 // Note that targetSdkVersion may be 0, meaning "current". 197 Runtime::Current()->SetTargetSdkVersion(target_sdk_version); 198 199 #ifdef HAVE_ANDROID_OS 200 // This part is letting libc/dynamic linker know about current app's 201 // target sdk version to enable compatibility workarounds. 202 android_set_application_target_sdk_version(static_cast<uint32_t>(target_sdk_version)); 203 #endif 204 } 205 206 static void VMRuntime_registerNativeAllocation(JNIEnv* env, jobject, jint bytes) { 207 if (UNLIKELY(bytes < 0)) { 208 ScopedObjectAccess soa(env); 209 ThrowRuntimeException("allocation size negative %d", bytes); 210 return; 211 } 212 Runtime::Current()->GetHeap()->RegisterNativeAllocation(env, static_cast<size_t>(bytes)); 213 } 214 215 static void VMRuntime_registerNativeFree(JNIEnv* env, jobject, jint bytes) { 216 if (UNLIKELY(bytes < 0)) { 217 ScopedObjectAccess soa(env); 218 ThrowRuntimeException("allocation size negative %d", bytes); 219 return; 220 } 221 Runtime::Current()->GetHeap()->RegisterNativeFree(env, static_cast<size_t>(bytes)); 222 } 223 224 static void VMRuntime_updateProcessState(JNIEnv*, jobject, jint process_state) { 225 Runtime* runtime = Runtime::Current(); 226 runtime->GetHeap()->UpdateProcessState(static_cast<gc::ProcessState>(process_state)); 227 runtime->UpdateProfilerState(process_state); 228 } 229 230 static void VMRuntime_trimHeap(JNIEnv* env, jobject) { 231 Runtime::Current()->GetHeap()->Trim(ThreadForEnv(env)); 232 } 233 234 static void VMRuntime_concurrentGC(JNIEnv* env, jobject) { 235 Runtime::Current()->GetHeap()->ConcurrentGC(ThreadForEnv(env), true); 236 } 237 238 static void VMRuntime_requestHeapTrim(JNIEnv* env, jobject) { 239 Runtime::Current()->GetHeap()->RequestTrim(ThreadForEnv(env)); 240 } 241 242 static void VMRuntime_requestConcurrentGC(JNIEnv* env, jobject) { 243 Runtime::Current()->GetHeap()->RequestConcurrentGC(ThreadForEnv(env), true); 244 } 245 246 static void VMRuntime_startHeapTaskProcessor(JNIEnv* env, jobject) { 247 Runtime::Current()->GetHeap()->GetTaskProcessor()->Start(ThreadForEnv(env)); 248 } 249 250 static void VMRuntime_stopHeapTaskProcessor(JNIEnv* env, jobject) { 251 Runtime::Current()->GetHeap()->GetTaskProcessor()->Stop(ThreadForEnv(env)); 252 } 253 254 static void VMRuntime_runHeapTasks(JNIEnv* env, jobject) { 255 Runtime::Current()->GetHeap()->GetTaskProcessor()->RunAllTasks(ThreadForEnv(env)); 256 } 257 258 typedef std::map<std::string, mirror::String*> StringTable; 259 260 class PreloadDexCachesStringsVisitor : public SingleRootVisitor { 261 public: 262 explicit PreloadDexCachesStringsVisitor(StringTable* table) : table_(table) { } 263 264 void VisitRoot(mirror::Object* root, const RootInfo& info ATTRIBUTE_UNUSED) 265 OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 266 mirror::String* string = root->AsString(); 267 table_->operator[](string->ToModifiedUtf8()) = string; 268 } 269 270 private: 271 StringTable* const table_; 272 }; 273 274 // Based on ClassLinker::ResolveString. 275 static void PreloadDexCachesResolveString( 276 Handle<mirror::DexCache> dex_cache, uint32_t string_idx, StringTable& strings) 277 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 278 mirror::String* string = dex_cache->GetResolvedString(string_idx); 279 if (string != nullptr) { 280 return; 281 } 282 const DexFile* dex_file = dex_cache->GetDexFile(); 283 const char* utf8 = dex_file->StringDataByIdx(string_idx); 284 string = strings[utf8]; 285 if (string == nullptr) { 286 return; 287 } 288 // LOG(INFO) << "VMRuntime.preloadDexCaches resolved string=" << utf8; 289 dex_cache->SetResolvedString(string_idx, string); 290 } 291 292 // Based on ClassLinker::ResolveType. 293 static void PreloadDexCachesResolveType( 294 Thread* self, mirror::DexCache* dex_cache, uint32_t type_idx) 295 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 296 mirror::Class* klass = dex_cache->GetResolvedType(type_idx); 297 if (klass != nullptr) { 298 return; 299 } 300 const DexFile* dex_file = dex_cache->GetDexFile(); 301 const char* class_name = dex_file->StringByTypeIdx(type_idx); 302 ClassLinker* linker = Runtime::Current()->GetClassLinker(); 303 if (class_name[1] == '\0') { 304 klass = linker->FindPrimitiveClass(class_name[0]); 305 } else { 306 klass = linker->LookupClass(self, class_name, ComputeModifiedUtf8Hash(class_name), nullptr); 307 } 308 if (klass == nullptr) { 309 return; 310 } 311 // LOG(INFO) << "VMRuntime.preloadDexCaches resolved klass=" << class_name; 312 dex_cache->SetResolvedType(type_idx, klass); 313 // Skip uninitialized classes because filled static storage entry implies it is initialized. 314 if (!klass->IsInitialized()) { 315 // LOG(INFO) << "VMRuntime.preloadDexCaches uninitialized klass=" << class_name; 316 return; 317 } 318 // LOG(INFO) << "VMRuntime.preloadDexCaches static storage klass=" << class_name; 319 } 320 321 // Based on ClassLinker::ResolveField. 322 static void PreloadDexCachesResolveField(Handle<mirror::DexCache> dex_cache, uint32_t field_idx, 323 bool is_static) 324 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 325 ArtField* field = dex_cache->GetResolvedField(field_idx, sizeof(void*)); 326 if (field != nullptr) { 327 return; 328 } 329 const DexFile* dex_file = dex_cache->GetDexFile(); 330 const DexFile::FieldId& field_id = dex_file->GetFieldId(field_idx); 331 Thread* const self = Thread::Current(); 332 StackHandleScope<1> hs(self); 333 Handle<mirror::Class> klass(hs.NewHandle(dex_cache->GetResolvedType(field_id.class_idx_))); 334 if (klass.Get() == nullptr) { 335 return; 336 } 337 if (is_static) { 338 field = mirror::Class::FindStaticField(self, klass, dex_cache.Get(), field_idx); 339 } else { 340 field = klass->FindInstanceField(dex_cache.Get(), field_idx); 341 } 342 if (field == nullptr) { 343 return; 344 } 345 // LOG(INFO) << "VMRuntime.preloadDexCaches resolved field " << PrettyField(field); 346 dex_cache->SetResolvedField(field_idx, field, sizeof(void*)); 347 } 348 349 // Based on ClassLinker::ResolveMethod. 350 static void PreloadDexCachesResolveMethod(Handle<mirror::DexCache> dex_cache, uint32_t method_idx, 351 InvokeType invoke_type) 352 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 353 ArtMethod* method = dex_cache->GetResolvedMethod(method_idx, sizeof(void*)); 354 if (method != nullptr) { 355 return; 356 } 357 const DexFile* dex_file = dex_cache->GetDexFile(); 358 const DexFile::MethodId& method_id = dex_file->GetMethodId(method_idx); 359 mirror::Class* klass = dex_cache->GetResolvedType(method_id.class_idx_); 360 if (klass == nullptr) { 361 return; 362 } 363 switch (invoke_type) { 364 case kDirect: 365 case kStatic: 366 method = klass->FindDirectMethod(dex_cache.Get(), method_idx, sizeof(void*)); 367 break; 368 case kInterface: 369 method = klass->FindInterfaceMethod(dex_cache.Get(), method_idx, sizeof(void*)); 370 break; 371 case kSuper: 372 case kVirtual: 373 method = klass->FindVirtualMethod(dex_cache.Get(), method_idx, sizeof(void*)); 374 break; 375 default: 376 LOG(FATAL) << "Unreachable - invocation type: " << invoke_type; 377 UNREACHABLE(); 378 } 379 if (method == nullptr) { 380 return; 381 } 382 // LOG(INFO) << "VMRuntime.preloadDexCaches resolved method " << PrettyMethod(method); 383 dex_cache->SetResolvedMethod(method_idx, method, sizeof(void*)); 384 } 385 386 struct DexCacheStats { 387 uint32_t num_strings; 388 uint32_t num_types; 389 uint32_t num_fields; 390 uint32_t num_methods; 391 DexCacheStats() : num_strings(0), 392 num_types(0), 393 num_fields(0), 394 num_methods(0) {} 395 }; 396 397 static const bool kPreloadDexCachesEnabled = true; 398 399 // Disabled because it takes a long time (extra half second) but 400 // gives almost no benefit in terms of saving private dirty pages. 401 static const bool kPreloadDexCachesStrings = false; 402 403 static const bool kPreloadDexCachesTypes = true; 404 static const bool kPreloadDexCachesFieldsAndMethods = true; 405 406 static const bool kPreloadDexCachesCollectStats = true; 407 408 static void PreloadDexCachesStatsTotal(DexCacheStats* total) { 409 if (!kPreloadDexCachesCollectStats) { 410 return; 411 } 412 413 ClassLinker* linker = Runtime::Current()->GetClassLinker(); 414 const std::vector<const DexFile*>& boot_class_path = linker->GetBootClassPath(); 415 for (size_t i = 0; i< boot_class_path.size(); i++) { 416 const DexFile* dex_file = boot_class_path[i]; 417 CHECK(dex_file != nullptr); 418 total->num_strings += dex_file->NumStringIds(); 419 total->num_fields += dex_file->NumFieldIds(); 420 total->num_methods += dex_file->NumMethodIds(); 421 total->num_types += dex_file->NumTypeIds(); 422 } 423 } 424 425 static void PreloadDexCachesStatsFilled(DexCacheStats* filled) 426 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 427 if (!kPreloadDexCachesCollectStats) { 428 return; 429 } 430 ClassLinker* linker = Runtime::Current()->GetClassLinker(); 431 const std::vector<const DexFile*>& boot_class_path = linker->GetBootClassPath(); 432 for (size_t i = 0; i< boot_class_path.size(); i++) { 433 const DexFile* dex_file = boot_class_path[i]; 434 CHECK(dex_file != nullptr); 435 mirror::DexCache* dex_cache = linker->FindDexCache(*dex_file); 436 for (size_t j = 0; j < dex_cache->NumStrings(); j++) { 437 mirror::String* string = dex_cache->GetResolvedString(j); 438 if (string != nullptr) { 439 filled->num_strings++; 440 } 441 } 442 for (size_t j = 0; j < dex_cache->NumResolvedTypes(); j++) { 443 mirror::Class* klass = dex_cache->GetResolvedType(j); 444 if (klass != nullptr) { 445 filled->num_types++; 446 } 447 } 448 for (size_t j = 0; j < dex_cache->NumResolvedFields(); j++) { 449 ArtField* field = linker->GetResolvedField(j, dex_cache); 450 if (field != nullptr) { 451 filled->num_fields++; 452 } 453 } 454 for (size_t j = 0; j < dex_cache->NumResolvedMethods(); j++) { 455 ArtMethod* method = dex_cache->GetResolvedMethod(j, sizeof(void*)); 456 if (method != nullptr) { 457 filled->num_methods++; 458 } 459 } 460 } 461 } 462 463 // TODO: http://b/11309598 This code was ported over based on the 464 // Dalvik version. However, ART has similar code in other places such 465 // as the CompilerDriver. This code could probably be refactored to 466 // serve both uses. 467 static void VMRuntime_preloadDexCaches(JNIEnv* env, jobject) { 468 if (!kPreloadDexCachesEnabled) { 469 return; 470 } 471 472 ScopedObjectAccess soa(env); 473 474 DexCacheStats total; 475 DexCacheStats before; 476 if (kPreloadDexCachesCollectStats) { 477 LOG(INFO) << "VMRuntime.preloadDexCaches starting"; 478 PreloadDexCachesStatsTotal(&total); 479 PreloadDexCachesStatsFilled(&before); 480 } 481 482 Runtime* runtime = Runtime::Current(); 483 ClassLinker* linker = runtime->GetClassLinker(); 484 485 // We use a std::map to avoid heap allocating StringObjects to lookup in gDvm.literalStrings 486 StringTable strings; 487 if (kPreloadDexCachesStrings) { 488 PreloadDexCachesStringsVisitor visitor(&strings); 489 runtime->GetInternTable()->VisitRoots(&visitor, kVisitRootFlagAllRoots); 490 } 491 492 const std::vector<const DexFile*>& boot_class_path = linker->GetBootClassPath(); 493 for (size_t i = 0; i< boot_class_path.size(); i++) { 494 const DexFile* dex_file = boot_class_path[i]; 495 CHECK(dex_file != nullptr); 496 StackHandleScope<1> hs(soa.Self()); 497 Handle<mirror::DexCache> dex_cache(hs.NewHandle(linker->FindDexCache(*dex_file))); 498 499 if (kPreloadDexCachesStrings) { 500 for (size_t j = 0; j < dex_cache->NumStrings(); j++) { 501 PreloadDexCachesResolveString(dex_cache, j, strings); 502 } 503 } 504 505 if (kPreloadDexCachesTypes) { 506 for (size_t j = 0; j < dex_cache->NumResolvedTypes(); j++) { 507 PreloadDexCachesResolveType(soa.Self(), dex_cache.Get(), j); 508 } 509 } 510 511 if (kPreloadDexCachesFieldsAndMethods) { 512 for (size_t class_def_index = 0; 513 class_def_index < dex_file->NumClassDefs(); 514 class_def_index++) { 515 const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index); 516 const uint8_t* class_data = dex_file->GetClassData(class_def); 517 if (class_data == nullptr) { 518 continue; 519 } 520 ClassDataItemIterator it(*dex_file, class_data); 521 for (; it.HasNextStaticField(); it.Next()) { 522 uint32_t field_idx = it.GetMemberIndex(); 523 PreloadDexCachesResolveField(dex_cache, field_idx, true); 524 } 525 for (; it.HasNextInstanceField(); it.Next()) { 526 uint32_t field_idx = it.GetMemberIndex(); 527 PreloadDexCachesResolveField(dex_cache, field_idx, false); 528 } 529 for (; it.HasNextDirectMethod(); it.Next()) { 530 uint32_t method_idx = it.GetMemberIndex(); 531 InvokeType invoke_type = it.GetMethodInvokeType(class_def); 532 PreloadDexCachesResolveMethod(dex_cache, method_idx, invoke_type); 533 } 534 for (; it.HasNextVirtualMethod(); it.Next()) { 535 uint32_t method_idx = it.GetMemberIndex(); 536 InvokeType invoke_type = it.GetMethodInvokeType(class_def); 537 PreloadDexCachesResolveMethod(dex_cache, method_idx, invoke_type); 538 } 539 } 540 } 541 } 542 543 if (kPreloadDexCachesCollectStats) { 544 DexCacheStats after; 545 PreloadDexCachesStatsFilled(&after); 546 LOG(INFO) << StringPrintf("VMRuntime.preloadDexCaches strings total=%d before=%d after=%d", 547 total.num_strings, before.num_strings, after.num_strings); 548 LOG(INFO) << StringPrintf("VMRuntime.preloadDexCaches types total=%d before=%d after=%d", 549 total.num_types, before.num_types, after.num_types); 550 LOG(INFO) << StringPrintf("VMRuntime.preloadDexCaches fields total=%d before=%d after=%d", 551 total.num_fields, before.num_fields, after.num_fields); 552 LOG(INFO) << StringPrintf("VMRuntime.preloadDexCaches methods total=%d before=%d after=%d", 553 total.num_methods, before.num_methods, after.num_methods); 554 LOG(INFO) << StringPrintf("VMRuntime.preloadDexCaches finished"); 555 } 556 } 557 558 559 /* 560 * This is called by the framework when it knows the application directory and 561 * process name. We use this information to start up the sampling profiler for 562 * for ART. 563 */ 564 static void VMRuntime_registerAppInfo(JNIEnv* env, jclass, jstring pkgName, 565 jstring appDir ATTRIBUTE_UNUSED, 566 jstring procName ATTRIBUTE_UNUSED) { 567 const char *pkgNameChars = env->GetStringUTFChars(pkgName, nullptr); 568 std::string profileFile = StringPrintf("/data/dalvik-cache/profiles/%s", pkgNameChars); 569 570 Runtime::Current()->StartProfiler(profileFile.c_str()); 571 572 env->ReleaseStringUTFChars(pkgName, pkgNameChars); 573 } 574 575 static jboolean VMRuntime_isBootClassPathOnDisk(JNIEnv* env, jclass, jstring java_instruction_set) { 576 ScopedUtfChars instruction_set(env, java_instruction_set); 577 if (instruction_set.c_str() == nullptr) { 578 return JNI_FALSE; 579 } 580 InstructionSet isa = GetInstructionSetFromString(instruction_set.c_str()); 581 if (isa == kNone) { 582 ScopedLocalRef<jclass> iae(env, env->FindClass("java/lang/IllegalArgumentException")); 583 std::string message(StringPrintf("Instruction set %s is invalid.", instruction_set.c_str())); 584 env->ThrowNew(iae.get(), message.c_str()); 585 return JNI_FALSE; 586 } 587 std::string error_msg; 588 std::unique_ptr<ImageHeader> image_header(gc::space::ImageSpace::ReadImageHeader( 589 Runtime::Current()->GetImageLocation().c_str(), isa, &error_msg)); 590 return image_header.get() != nullptr; 591 } 592 593 static jstring VMRuntime_getCurrentInstructionSet(JNIEnv* env, jclass) { 594 return env->NewStringUTF(GetInstructionSetString(kRuntimeISA)); 595 } 596 597 static JNINativeMethod gMethods[] = { 598 NATIVE_METHOD(VMRuntime, addressOf, "!(Ljava/lang/Object;)J"), 599 NATIVE_METHOD(VMRuntime, bootClassPath, "()Ljava/lang/String;"), 600 NATIVE_METHOD(VMRuntime, clampGrowthLimit, "()V"), 601 NATIVE_METHOD(VMRuntime, classPath, "()Ljava/lang/String;"), 602 NATIVE_METHOD(VMRuntime, clearGrowthLimit, "()V"), 603 NATIVE_METHOD(VMRuntime, concurrentGC, "()V"), 604 NATIVE_METHOD(VMRuntime, disableJitCompilation, "()V"), 605 NATIVE_METHOD(VMRuntime, getTargetHeapUtilization, "()F"), 606 NATIVE_METHOD(VMRuntime, isDebuggerActive, "!()Z"), 607 NATIVE_METHOD(VMRuntime, nativeSetTargetHeapUtilization, "(F)V"), 608 NATIVE_METHOD(VMRuntime, newNonMovableArray, "!(Ljava/lang/Class;I)Ljava/lang/Object;"), 609 NATIVE_METHOD(VMRuntime, newUnpaddedArray, "!(Ljava/lang/Class;I)Ljava/lang/Object;"), 610 NATIVE_METHOD(VMRuntime, properties, "()[Ljava/lang/String;"), 611 NATIVE_METHOD(VMRuntime, setTargetSdkVersionNative, "(I)V"), 612 NATIVE_METHOD(VMRuntime, registerNativeAllocation, "(I)V"), 613 NATIVE_METHOD(VMRuntime, registerNativeFree, "(I)V"), 614 NATIVE_METHOD(VMRuntime, requestConcurrentGC, "()V"), 615 NATIVE_METHOD(VMRuntime, requestHeapTrim, "()V"), 616 NATIVE_METHOD(VMRuntime, runHeapTasks, "()V"), 617 NATIVE_METHOD(VMRuntime, updateProcessState, "(I)V"), 618 NATIVE_METHOD(VMRuntime, startHeapTaskProcessor, "()V"), 619 NATIVE_METHOD(VMRuntime, startJitCompilation, "()V"), 620 NATIVE_METHOD(VMRuntime, stopHeapTaskProcessor, "()V"), 621 NATIVE_METHOD(VMRuntime, trimHeap, "()V"), 622 NATIVE_METHOD(VMRuntime, vmVersion, "()Ljava/lang/String;"), 623 NATIVE_METHOD(VMRuntime, vmLibrary, "()Ljava/lang/String;"), 624 NATIVE_METHOD(VMRuntime, vmInstructionSet, "()Ljava/lang/String;"), 625 NATIVE_METHOD(VMRuntime, is64Bit, "!()Z"), 626 NATIVE_METHOD(VMRuntime, isCheckJniEnabled, "!()Z"), 627 NATIVE_METHOD(VMRuntime, preloadDexCaches, "()V"), 628 NATIVE_METHOD(VMRuntime, registerAppInfo, 629 "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"), 630 NATIVE_METHOD(VMRuntime, isBootClassPathOnDisk, "(Ljava/lang/String;)Z"), 631 NATIVE_METHOD(VMRuntime, getCurrentInstructionSet, "()Ljava/lang/String;"), 632 }; 633 634 void register_dalvik_system_VMRuntime(JNIEnv* env) { 635 REGISTER_NATIVE_METHODS("dalvik/system/VMRuntime"); 636 } 637 638 } // namespace art 639