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