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