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