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_VMDebug.h" 18 19 #include <string.h> 20 #include <unistd.h> 21 22 #include <sstream> 23 24 #include "nativehelper/jni_macros.h" 25 26 #include "base/file_utils.h" 27 #include "base/histogram-inl.h" 28 #include "base/time_utils.h" 29 #include "class_linker.h" 30 #include "common_throws.h" 31 #include "debugger.h" 32 #include "gc/space/bump_pointer_space.h" 33 #include "gc/space/dlmalloc_space.h" 34 #include "gc/space/large_object_space.h" 35 #include "gc/space/space-inl.h" 36 #include "gc/space/zygote_space.h" 37 #include "handle_scope-inl.h" 38 #include "hprof/hprof.h" 39 #include "jni/java_vm_ext.h" 40 #include "jni/jni_internal.h" 41 #include "mirror/array-alloc-inl.h" 42 #include "mirror/array-inl.h" 43 #include "mirror/class.h" 44 #include "mirror/object_array-inl.h" 45 #include "native_util.h" 46 #include "nativehelper/scoped_local_ref.h" 47 #include "nativehelper/scoped_utf_chars.h" 48 #include "scoped_fast_native_object_access-inl.h" 49 #include "trace.h" 50 #include "well_known_classes.h" 51 52 namespace art { 53 54 static jobjectArray VMDebug_getVmFeatureList(JNIEnv* env, jclass) { 55 static const char* features[] = { 56 "method-trace-profiling", 57 "method-trace-profiling-streaming", 58 "method-sample-profiling", 59 "hprof-heap-dump", 60 "hprof-heap-dump-streaming", 61 }; 62 jobjectArray result = env->NewObjectArray(arraysize(features), 63 WellKnownClasses::java_lang_String, 64 nullptr); 65 if (result != nullptr) { 66 for (size_t i = 0; i < arraysize(features); ++i) { 67 ScopedLocalRef<jstring> jfeature(env, env->NewStringUTF(features[i])); 68 if (jfeature.get() == nullptr) { 69 return nullptr; 70 } 71 env->SetObjectArrayElement(result, i, jfeature.get()); 72 } 73 } 74 return result; 75 } 76 77 static void VMDebug_startAllocCounting(JNIEnv*, jclass) { 78 Runtime::Current()->SetStatsEnabled(true); 79 } 80 81 static void VMDebug_stopAllocCounting(JNIEnv*, jclass) { 82 Runtime::Current()->SetStatsEnabled(false); 83 } 84 85 static jint VMDebug_getAllocCount(JNIEnv*, jclass, jint kind) { 86 return Runtime::Current()->GetStat(kind); 87 } 88 89 static void VMDebug_resetAllocCount(JNIEnv*, jclass, jint kinds) { 90 Runtime::Current()->ResetStats(kinds); 91 } 92 93 static void VMDebug_startMethodTracingDdmsImpl(JNIEnv*, jclass, jint bufferSize, jint flags, 94 jboolean samplingEnabled, jint intervalUs) { 95 Trace::StartDDMS(bufferSize, 96 flags, 97 samplingEnabled ? Trace::TraceMode::kSampling : Trace::TraceMode::kMethodTracing, 98 intervalUs); 99 } 100 101 static void VMDebug_startMethodTracingFd(JNIEnv* env, 102 jclass, 103 jstring javaTraceFilename ATTRIBUTE_UNUSED, 104 jint javaFd, 105 jint bufferSize, 106 jint flags, 107 jboolean samplingEnabled, 108 jint intervalUs, 109 jboolean streamingOutput) { 110 int originalFd = javaFd; 111 if (originalFd < 0) { 112 ScopedObjectAccess soa(env); 113 soa.Self()->ThrowNewExceptionF("Ljava/lang/RuntimeException;", 114 "Trace fd is invalid: %d", 115 originalFd); 116 return; 117 } 118 119 int fd = DupCloexec(originalFd); 120 if (fd < 0) { 121 ScopedObjectAccess soa(env); 122 soa.Self()->ThrowNewExceptionF("Ljava/lang/RuntimeException;", 123 "dup(%d) failed: %s", 124 originalFd, 125 strerror(errno)); 126 return; 127 } 128 129 // Ignore the traceFilename. 130 Trace::TraceOutputMode outputMode = streamingOutput 131 ? Trace::TraceOutputMode::kStreaming 132 : Trace::TraceOutputMode::kFile; 133 Trace::Start(fd, 134 bufferSize, 135 flags, 136 outputMode, 137 samplingEnabled ? Trace::TraceMode::kSampling : Trace::TraceMode::kMethodTracing, 138 intervalUs); 139 } 140 141 static void VMDebug_startMethodTracingFilename(JNIEnv* env, jclass, jstring javaTraceFilename, 142 jint bufferSize, jint flags, 143 jboolean samplingEnabled, jint intervalUs) { 144 ScopedUtfChars traceFilename(env, javaTraceFilename); 145 if (traceFilename.c_str() == nullptr) { 146 return; 147 } 148 Trace::Start(traceFilename.c_str(), 149 bufferSize, 150 flags, 151 Trace::TraceOutputMode::kFile, 152 samplingEnabled ? Trace::TraceMode::kSampling : Trace::TraceMode::kMethodTracing, 153 intervalUs); 154 } 155 156 static jint VMDebug_getMethodTracingMode(JNIEnv*, jclass) { 157 return Trace::GetMethodTracingMode(); 158 } 159 160 static void VMDebug_stopMethodTracing(JNIEnv*, jclass) { 161 Trace::Stop(); 162 } 163 164 static void VMDebug_startEmulatorTracing(JNIEnv*, jclass) { 165 UNIMPLEMENTED(WARNING); 166 // dvmEmulatorTraceStart(); 167 } 168 169 static void VMDebug_stopEmulatorTracing(JNIEnv*, jclass) { 170 UNIMPLEMENTED(WARNING); 171 // dvmEmulatorTraceStop(); 172 } 173 174 static jboolean VMDebug_isDebuggerConnected(JNIEnv*, jclass) { 175 return Dbg::IsDebuggerActive(); 176 } 177 178 static jboolean VMDebug_isDebuggingEnabled(JNIEnv* env, jclass) { 179 ScopedObjectAccess soa(env); 180 return Runtime::Current()->GetRuntimeCallbacks()->IsDebuggerConfigured(); 181 } 182 183 static jlong VMDebug_lastDebuggerActivity(JNIEnv*, jclass) { 184 return Dbg::LastDebuggerActivity(); 185 } 186 187 static void ThrowUnsupportedOperationException(JNIEnv* env) { 188 ScopedObjectAccess soa(env); 189 soa.Self()->ThrowNewException("Ljava/lang/UnsupportedOperationException;", nullptr); 190 } 191 192 static void VMDebug_startInstructionCounting(JNIEnv* env, jclass) { 193 ThrowUnsupportedOperationException(env); 194 } 195 196 static void VMDebug_stopInstructionCounting(JNIEnv* env, jclass) { 197 ThrowUnsupportedOperationException(env); 198 } 199 200 static void VMDebug_getInstructionCount(JNIEnv* env, jclass, jintArray /*javaCounts*/) { 201 ThrowUnsupportedOperationException(env); 202 } 203 204 static void VMDebug_resetInstructionCount(JNIEnv* env, jclass) { 205 ThrowUnsupportedOperationException(env); 206 } 207 208 static void VMDebug_printLoadedClasses(JNIEnv* env, jclass, jint flags) { 209 class DumpClassVisitor : public ClassVisitor { 210 public: 211 explicit DumpClassVisitor(int dump_flags) : flags_(dump_flags) {} 212 213 bool operator()(ObjPtr<mirror::Class> klass) override REQUIRES_SHARED(Locks::mutator_lock_) { 214 klass->DumpClass(LOG_STREAM(ERROR), flags_); 215 return true; 216 } 217 218 private: 219 const int flags_; 220 }; 221 DumpClassVisitor visitor(flags); 222 223 ScopedFastNativeObjectAccess soa(env); 224 return Runtime::Current()->GetClassLinker()->VisitClasses(&visitor); 225 } 226 227 static jint VMDebug_getLoadedClassCount(JNIEnv* env, jclass) { 228 ScopedFastNativeObjectAccess soa(env); 229 return Runtime::Current()->GetClassLinker()->NumLoadedClasses(); 230 } 231 232 /* 233 * Returns the thread-specific CPU-time clock value for the current thread, 234 * or -1 if the feature isn't supported. 235 */ 236 static jlong VMDebug_threadCpuTimeNanos(JNIEnv*, jclass) { 237 return ThreadCpuNanoTime(); 238 } 239 240 /* 241 * static void dumpHprofData(String fileName, FileDescriptor fd) 242 * 243 * Cause "hprof" data to be dumped. We can throw an IOException if an 244 * error occurs during file handling. 245 */ 246 static void VMDebug_dumpHprofData(JNIEnv* env, jclass, jstring javaFilename, jint javaFd) { 247 // Only one of these may be null. 248 if (javaFilename == nullptr && javaFd < 0) { 249 ScopedObjectAccess soa(env); 250 ThrowNullPointerException("fileName == null && fd == null"); 251 return; 252 } 253 254 std::string filename; 255 if (javaFilename != nullptr) { 256 ScopedUtfChars chars(env, javaFilename); 257 if (env->ExceptionCheck()) { 258 return; 259 } 260 filename = chars.c_str(); 261 } else { 262 filename = "[fd]"; 263 } 264 265 int fd = javaFd; 266 267 hprof::DumpHeap(filename.c_str(), fd, false); 268 } 269 270 static void VMDebug_dumpHprofDataDdms(JNIEnv*, jclass) { 271 hprof::DumpHeap("[DDMS]", -1, true); 272 } 273 274 static void VMDebug_dumpReferenceTables(JNIEnv* env, jclass) { 275 ScopedObjectAccess soa(env); 276 LOG(INFO) << "--- reference table dump ---"; 277 278 soa.Env()->DumpReferenceTables(LOG_STREAM(INFO)); 279 soa.Vm()->DumpReferenceTables(LOG_STREAM(INFO)); 280 281 LOG(INFO) << "---"; 282 } 283 284 static void VMDebug_crash(JNIEnv*, jclass) { 285 LOG(FATAL) << "Crashing runtime on request"; 286 } 287 288 static void VMDebug_infopoint(JNIEnv*, jclass, jint id) { 289 LOG(INFO) << "VMDebug infopoint " << id << " hit"; 290 } 291 292 static jlong VMDebug_countInstancesOfClass(JNIEnv* env, 293 jclass, 294 jclass javaClass, 295 jboolean countAssignable) { 296 ScopedObjectAccess soa(env); 297 gc::Heap* const heap = Runtime::Current()->GetHeap(); 298 // Caller's responsibility to do GC if desired. 299 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(javaClass); 300 if (c == nullptr) { 301 return 0; 302 } 303 VariableSizedHandleScope hs(soa.Self()); 304 std::vector<Handle<mirror::Class>> classes {hs.NewHandle(c)}; 305 uint64_t count = 0; 306 heap->CountInstances(classes, countAssignable, &count); 307 return count; 308 } 309 310 static jlongArray VMDebug_countInstancesOfClasses(JNIEnv* env, 311 jclass, 312 jobjectArray javaClasses, 313 jboolean countAssignable) { 314 ScopedObjectAccess soa(env); 315 gc::Heap* const heap = Runtime::Current()->GetHeap(); 316 // Caller's responsibility to do GC if desired. 317 ObjPtr<mirror::ObjectArray<mirror::Class>> decoded_classes = 318 soa.Decode<mirror::ObjectArray<mirror::Class>>(javaClasses); 319 if (decoded_classes == nullptr) { 320 return nullptr; 321 } 322 VariableSizedHandleScope hs(soa.Self()); 323 std::vector<Handle<mirror::Class>> classes; 324 for (size_t i = 0, count = decoded_classes->GetLength(); i < count; ++i) { 325 classes.push_back(hs.NewHandle(decoded_classes->Get(i))); 326 } 327 std::vector<uint64_t> counts(classes.size(), 0u); 328 // Heap::CountInstances can handle null and will put 0 for these classes. 329 heap->CountInstances(classes, countAssignable, &counts[0]); 330 ObjPtr<mirror::LongArray> long_counts = mirror::LongArray::Alloc(soa.Self(), counts.size()); 331 if (long_counts == nullptr) { 332 soa.Self()->AssertPendingOOMException(); 333 return nullptr; 334 } 335 for (size_t i = 0; i < counts.size(); ++i) { 336 long_counts->Set(i, counts[i]); 337 } 338 return soa.AddLocalReference<jlongArray>(long_counts); 339 } 340 341 static jobjectArray VMDebug_getInstancesOfClasses(JNIEnv* env, 342 jclass, 343 jobjectArray javaClasses, 344 jboolean includeAssignable) { 345 ScopedObjectAccess soa(env); 346 StackHandleScope<2> hs(soa.Self()); 347 Handle<mirror::ObjectArray<mirror::Class>> classes = hs.NewHandle( 348 soa.Decode<mirror::ObjectArray<mirror::Class>>(javaClasses)); 349 if (classes == nullptr) { 350 return nullptr; 351 } 352 353 jclass object_array_class = env->FindClass("[Ljava/lang/Object;"); 354 if (env->ExceptionCheck() == JNI_TRUE) { 355 return nullptr; 356 } 357 CHECK(object_array_class != nullptr); 358 359 size_t num_classes = classes->GetLength(); 360 jobjectArray result = env->NewObjectArray(num_classes, object_array_class, nullptr); 361 if (env->ExceptionCheck() == JNI_TRUE) { 362 return nullptr; 363 } 364 365 gc::Heap* const heap = Runtime::Current()->GetHeap(); 366 MutableHandle<mirror::Class> h_class(hs.NewHandle<mirror::Class>(nullptr)); 367 for (size_t i = 0; i < num_classes; ++i) { 368 h_class.Assign(classes->Get(i)); 369 370 VariableSizedHandleScope hs2(soa.Self()); 371 std::vector<Handle<mirror::Object>> raw_instances; 372 heap->GetInstances(hs2, h_class, includeAssignable, /* max_count= */ 0, raw_instances); 373 jobjectArray array = env->NewObjectArray(raw_instances.size(), 374 WellKnownClasses::java_lang_Object, 375 nullptr); 376 if (env->ExceptionCheck() == JNI_TRUE) { 377 return nullptr; 378 } 379 380 for (size_t j = 0; j < raw_instances.size(); ++j) { 381 env->SetObjectArrayElement(array, j, raw_instances[j].ToJObject()); 382 } 383 env->SetObjectArrayElement(result, i, array); 384 } 385 return result; 386 } 387 388 // We export the VM internal per-heap-space size/alloc/free metrics 389 // for the zygote space, alloc space (application heap), and the large 390 // object space for dumpsys meminfo. The other memory region data such 391 // as PSS, private/shared dirty/shared data are available via 392 // /proc/<pid>/smaps. 393 static void VMDebug_getHeapSpaceStats(JNIEnv* env, jclass, jlongArray data) { 394 jlong* arr = reinterpret_cast<jlong*>(env->GetPrimitiveArrayCritical(data, nullptr)); 395 if (arr == nullptr || env->GetArrayLength(data) < 9) { 396 return; 397 } 398 399 size_t allocSize = 0; 400 size_t allocUsed = 0; 401 size_t zygoteSize = 0; 402 size_t zygoteUsed = 0; 403 size_t largeObjectsSize = 0; 404 size_t largeObjectsUsed = 0; 405 gc::Heap* heap = Runtime::Current()->GetHeap(); 406 { 407 ScopedObjectAccess soa(env); 408 for (gc::space::ContinuousSpace* space : heap->GetContinuousSpaces()) { 409 if (space->IsImageSpace()) { 410 // Currently don't include the image space. 411 } else if (space->IsZygoteSpace()) { 412 gc::space::ZygoteSpace* zygote_space = space->AsZygoteSpace(); 413 zygoteSize += zygote_space->Size(); 414 zygoteUsed += zygote_space->GetBytesAllocated(); 415 } else if (space->IsMallocSpace()) { 416 // This is a malloc space. 417 gc::space::MallocSpace* malloc_space = space->AsMallocSpace(); 418 allocSize += malloc_space->GetFootprint(); 419 allocUsed += malloc_space->GetBytesAllocated(); 420 } else if (space->IsBumpPointerSpace()) { 421 gc::space::BumpPointerSpace* bump_pointer_space = space->AsBumpPointerSpace(); 422 allocSize += bump_pointer_space->Size(); 423 allocUsed += bump_pointer_space->GetBytesAllocated(); 424 } 425 } 426 for (gc::space::DiscontinuousSpace* space : heap->GetDiscontinuousSpaces()) { 427 if (space->IsLargeObjectSpace()) { 428 largeObjectsSize += space->AsLargeObjectSpace()->GetBytesAllocated(); 429 largeObjectsUsed += largeObjectsSize; 430 } 431 } 432 } 433 size_t allocFree = allocSize - allocUsed; 434 size_t zygoteFree = zygoteSize - zygoteUsed; 435 size_t largeObjectsFree = largeObjectsSize - largeObjectsUsed; 436 437 int j = 0; 438 arr[j++] = allocSize; 439 arr[j++] = allocUsed; 440 arr[j++] = allocFree; 441 arr[j++] = zygoteSize; 442 arr[j++] = zygoteUsed; 443 arr[j++] = zygoteFree; 444 arr[j++] = largeObjectsSize; 445 arr[j++] = largeObjectsUsed; 446 arr[j++] = largeObjectsFree; 447 env->ReleasePrimitiveArrayCritical(data, arr, 0); 448 } 449 450 // The runtime stat names for VMDebug.getRuntimeStat(). 451 enum class VMDebugRuntimeStatId { 452 kArtGcGcCount = 0, 453 kArtGcGcTime, 454 kArtGcBytesAllocated, 455 kArtGcBytesFreed, 456 kArtGcBlockingGcCount, 457 kArtGcBlockingGcTime, 458 kArtGcGcCountRateHistogram, 459 kArtGcBlockingGcCountRateHistogram, 460 kNumRuntimeStats, 461 }; 462 463 static jstring VMDebug_getRuntimeStatInternal(JNIEnv* env, jclass, jint statId) { 464 gc::Heap* heap = Runtime::Current()->GetHeap(); 465 switch (static_cast<VMDebugRuntimeStatId>(statId)) { 466 case VMDebugRuntimeStatId::kArtGcGcCount: { 467 std::string output = std::to_string(heap->GetGcCount()); 468 return env->NewStringUTF(output.c_str()); 469 } 470 case VMDebugRuntimeStatId::kArtGcGcTime: { 471 std::string output = std::to_string(NsToMs(heap->GetGcTime())); 472 return env->NewStringUTF(output.c_str()); 473 } 474 case VMDebugRuntimeStatId::kArtGcBytesAllocated: { 475 std::string output = std::to_string(heap->GetBytesAllocatedEver()); 476 return env->NewStringUTF(output.c_str()); 477 } 478 case VMDebugRuntimeStatId::kArtGcBytesFreed: { 479 std::string output = std::to_string(heap->GetBytesFreedEver()); 480 return env->NewStringUTF(output.c_str()); 481 } 482 case VMDebugRuntimeStatId::kArtGcBlockingGcCount: { 483 std::string output = std::to_string(heap->GetBlockingGcCount()); 484 return env->NewStringUTF(output.c_str()); 485 } 486 case VMDebugRuntimeStatId::kArtGcBlockingGcTime: { 487 std::string output = std::to_string(NsToMs(heap->GetBlockingGcTime())); 488 return env->NewStringUTF(output.c_str()); 489 } 490 case VMDebugRuntimeStatId::kArtGcGcCountRateHistogram: { 491 std::ostringstream output; 492 heap->DumpGcCountRateHistogram(output); 493 return env->NewStringUTF(output.str().c_str()); 494 } 495 case VMDebugRuntimeStatId::kArtGcBlockingGcCountRateHistogram: { 496 std::ostringstream output; 497 heap->DumpBlockingGcCountRateHistogram(output); 498 return env->NewStringUTF(output.str().c_str()); 499 } 500 default: 501 return nullptr; 502 } 503 } 504 505 static bool SetRuntimeStatValue(JNIEnv* env, 506 jobjectArray result, 507 VMDebugRuntimeStatId id, 508 const std::string& value) { 509 ScopedLocalRef<jstring> jvalue(env, env->NewStringUTF(value.c_str())); 510 if (jvalue.get() == nullptr) { 511 return false; 512 } 513 env->SetObjectArrayElement(result, static_cast<jint>(id), jvalue.get()); 514 return true; 515 } 516 517 static jobjectArray VMDebug_getRuntimeStatsInternal(JNIEnv* env, jclass) { 518 jobjectArray result = env->NewObjectArray( 519 static_cast<jint>(VMDebugRuntimeStatId::kNumRuntimeStats), 520 WellKnownClasses::java_lang_String, 521 nullptr); 522 if (result == nullptr) { 523 return nullptr; 524 } 525 gc::Heap* heap = Runtime::Current()->GetHeap(); 526 if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcGcCount, 527 std::to_string(heap->GetGcCount()))) { 528 return nullptr; 529 } 530 if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcGcTime, 531 std::to_string(NsToMs(heap->GetGcTime())))) { 532 return nullptr; 533 } 534 if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcBytesAllocated, 535 std::to_string(heap->GetBytesAllocatedEver()))) { 536 return nullptr; 537 } 538 if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcBytesFreed, 539 std::to_string(heap->GetBytesFreedEver()))) { 540 return nullptr; 541 } 542 if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcBlockingGcCount, 543 std::to_string(heap->GetBlockingGcCount()))) { 544 return nullptr; 545 } 546 if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcBlockingGcTime, 547 std::to_string(NsToMs(heap->GetBlockingGcTime())))) { 548 return nullptr; 549 } 550 { 551 std::ostringstream output; 552 heap->DumpGcCountRateHistogram(output); 553 if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcGcCountRateHistogram, 554 output.str())) { 555 return nullptr; 556 } 557 } 558 { 559 std::ostringstream output; 560 heap->DumpBlockingGcCountRateHistogram(output); 561 if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcBlockingGcCountRateHistogram, 562 output.str())) { 563 return nullptr; 564 } 565 } 566 return result; 567 } 568 569 static void VMDebug_nativeAttachAgent(JNIEnv* env, jclass, jstring agent, jobject classloader) { 570 if (agent == nullptr) { 571 ScopedObjectAccess soa(env); 572 ThrowNullPointerException("agent is null"); 573 return; 574 } 575 576 if (!Dbg::IsJdwpAllowed()) { 577 ScopedObjectAccess soa(env); 578 ThrowSecurityException("Can't attach agent, process is not debuggable."); 579 return; 580 } 581 582 std::string filename; 583 { 584 ScopedUtfChars chars(env, agent); 585 if (env->ExceptionCheck()) { 586 return; 587 } 588 filename = chars.c_str(); 589 } 590 591 Runtime::Current()->AttachAgent(env, filename, classloader); 592 } 593 594 static void VMDebug_allowHiddenApiReflectionFrom(JNIEnv* env, jclass, jclass j_caller) { 595 Runtime* runtime = Runtime::Current(); 596 ScopedObjectAccess soa(env); 597 598 if (!runtime->IsJavaDebuggable()) { 599 ThrowSecurityException("Can't exempt class, process is not debuggable."); 600 return; 601 } 602 603 StackHandleScope<1> hs(soa.Self()); 604 Handle<mirror::Class> h_caller(hs.NewHandle(soa.Decode<mirror::Class>(j_caller))); 605 if (h_caller.IsNull()) { 606 ThrowNullPointerException("argument is null"); 607 return; 608 } 609 610 h_caller->SetSkipHiddenApiChecks(); 611 } 612 613 static void VMDebug_setAllocTrackerStackDepth(JNIEnv* env, jclass, jint stack_depth) { 614 Runtime* runtime = Runtime::Current(); 615 if (stack_depth < 0 || 616 static_cast<size_t>(stack_depth) > gc::AllocRecordObjectMap::kMaxSupportedStackDepth) { 617 ScopedObjectAccess soa(env); 618 soa.Self()->ThrowNewExceptionF("Ljava/lang/RuntimeException;", 619 "Stack depth is invalid: %d", 620 stack_depth); 621 } else { 622 runtime->GetHeap()->SetAllocTrackerStackDepth(static_cast<size_t>(stack_depth)); 623 } 624 } 625 626 static JNINativeMethod gMethods[] = { 627 NATIVE_METHOD(VMDebug, countInstancesOfClass, "(Ljava/lang/Class;Z)J"), 628 NATIVE_METHOD(VMDebug, countInstancesOfClasses, "([Ljava/lang/Class;Z)[J"), 629 NATIVE_METHOD(VMDebug, crash, "()V"), 630 NATIVE_METHOD(VMDebug, dumpHprofData, "(Ljava/lang/String;I)V"), 631 NATIVE_METHOD(VMDebug, dumpHprofDataDdms, "()V"), 632 NATIVE_METHOD(VMDebug, dumpReferenceTables, "()V"), 633 NATIVE_METHOD(VMDebug, getAllocCount, "(I)I"), 634 NATIVE_METHOD(VMDebug, getHeapSpaceStats, "([J)V"), 635 NATIVE_METHOD(VMDebug, getInstancesOfClasses, "([Ljava/lang/Class;Z)[[Ljava/lang/Object;"), 636 NATIVE_METHOD(VMDebug, getInstructionCount, "([I)V"), 637 FAST_NATIVE_METHOD(VMDebug, getLoadedClassCount, "()I"), 638 NATIVE_METHOD(VMDebug, getVmFeatureList, "()[Ljava/lang/String;"), 639 NATIVE_METHOD(VMDebug, infopoint, "(I)V"), 640 FAST_NATIVE_METHOD(VMDebug, isDebuggerConnected, "()Z"), 641 FAST_NATIVE_METHOD(VMDebug, isDebuggingEnabled, "()Z"), 642 NATIVE_METHOD(VMDebug, getMethodTracingMode, "()I"), 643 FAST_NATIVE_METHOD(VMDebug, lastDebuggerActivity, "()J"), 644 FAST_NATIVE_METHOD(VMDebug, printLoadedClasses, "(I)V"), 645 NATIVE_METHOD(VMDebug, resetAllocCount, "(I)V"), 646 NATIVE_METHOD(VMDebug, resetInstructionCount, "()V"), 647 NATIVE_METHOD(VMDebug, startAllocCounting, "()V"), 648 NATIVE_METHOD(VMDebug, startEmulatorTracing, "()V"), 649 NATIVE_METHOD(VMDebug, startInstructionCounting, "()V"), 650 NATIVE_METHOD(VMDebug, startMethodTracingDdmsImpl, "(IIZI)V"), 651 NATIVE_METHOD(VMDebug, startMethodTracingFd, "(Ljava/lang/String;IIIZIZ)V"), 652 NATIVE_METHOD(VMDebug, startMethodTracingFilename, "(Ljava/lang/String;IIZI)V"), 653 NATIVE_METHOD(VMDebug, stopAllocCounting, "()V"), 654 NATIVE_METHOD(VMDebug, stopEmulatorTracing, "()V"), 655 NATIVE_METHOD(VMDebug, stopInstructionCounting, "()V"), 656 NATIVE_METHOD(VMDebug, stopMethodTracing, "()V"), 657 FAST_NATIVE_METHOD(VMDebug, threadCpuTimeNanos, "()J"), 658 NATIVE_METHOD(VMDebug, getRuntimeStatInternal, "(I)Ljava/lang/String;"), 659 NATIVE_METHOD(VMDebug, getRuntimeStatsInternal, "()[Ljava/lang/String;"), 660 NATIVE_METHOD(VMDebug, nativeAttachAgent, "(Ljava/lang/String;Ljava/lang/ClassLoader;)V"), 661 NATIVE_METHOD(VMDebug, allowHiddenApiReflectionFrom, "(Ljava/lang/Class;)V"), 662 NATIVE_METHOD(VMDebug, setAllocTrackerStackDepth, "(I)V"), 663 }; 664 665 void register_dalvik_system_VMDebug(JNIEnv* env) { 666 REGISTER_NATIVE_METHODS("dalvik/system/VMDebug"); 667 } 668 669 } // namespace art 670