19d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes/*
29d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes * Copyright (C) 2008 The Android Open Source Project
39d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes *
49d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
59d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes * you may not use this file except in compliance with the License.
69d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes * You may obtain a copy of the License at
79d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes *
89d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
99d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes *
109d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes * Unless required by applicable law or agreed to in writing, software
119d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
129d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes * See the License for the specific language governing permissions and
149d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes * limitations under the License.
159d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes */
169d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
17277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe#include "dalvik_system_VMDebug.h"
18277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe
19eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes#include <string.h>
20eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes#include <unistd.h>
21eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes
22a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi#include <sstream>
23a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi
24a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi#include "base/histogram-inl.h"
2580afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko#include "base/time_utils.h"
269d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes#include "class_linker.h"
2762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers#include "common_throws.h"
28872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include "debugger.h"
297410f29b4dae223befac036ea567d7f33351dad1Mathieu Chartier#include "gc/space/bump_pointer_space.h"
3009b07a96094086e205948717666025909a75163bHiroshi Yamauchi#include "gc/space/dlmalloc_space.h"
3109b07a96094086e205948717666025909a75163bHiroshi Yamauchi#include "gc/space/large_object_space.h"
3209b07a96094086e205948717666025909a75163bHiroshi Yamauchi#include "gc/space/space-inl.h"
331f3b5358b28a83f0929bdd8ce738f06908677fb7Mathieu Chartier#include "gc/space/zygote_space.h"
34c15a2f4f45661a7f5f542e406282c146ea1a968dAndreas Gampe#include "handle_scope-inl.h"
351121e0b619d0c9df36c57396b2234a9d570b4923Jesse Wilson#include "hprof/hprof.h"
36c15a2f4f45661a7f5f542e406282c146ea1a968dAndreas Gampe#include "java_vm_ext.h"
37eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes#include "jni_internal.h"
382dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class.h"
39c15a2f4f45661a7f5f542e406282c146ea1a968dAndreas Gampe#include "mirror/object_array-inl.h"
40dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers#include "ScopedLocalRef.h"
419d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes#include "ScopedUtfChars.h"
420795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier#include "scoped_fast_native_object_access-inl.h"
43eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes#include "trace.h"
44dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers#include "well_known_classes.h"
459d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
469d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughesnamespace art {
479d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
480512f02dd6623c0870c11fbf3274d7462f732136Elliott Hughesstatic jobjectArray VMDebug_getVmFeatureList(JNIEnv* env, jclass) {
49dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers  static const char* features[] = {
50dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers    "method-trace-profiling",
51dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers    "method-trace-profiling-streaming",
52dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers    "method-sample-profiling",
53dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers    "hprof-heap-dump",
54dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers    "hprof-heap-dump-streaming",
55dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers  };
56dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers  jobjectArray result = env->NewObjectArray(arraysize(features),
57dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers                                            WellKnownClasses::java_lang_String,
58dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers                                            nullptr);
59dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers  if (result != nullptr) {
60dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers    for (size_t i = 0; i < arraysize(features); ++i) {
61dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers      ScopedLocalRef<jstring> jfeature(env, env->NewStringUTF(features[i]));
62dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers      if (jfeature.get() == nullptr) {
63dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers        return nullptr;
64dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers      }
65dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers      env->SetObjectArrayElement(result, i, jfeature.get());
66dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers    }
67dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers  }
68dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers  return result;
699d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
709d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
710512f02dd6623c0870c11fbf3274d7462f732136Elliott Hughesstatic void VMDebug_startAllocCounting(JNIEnv*, jclass) {
729ef78b59da51080882e47505896b420977fd79aeMathieu Chartier  Runtime::Current()->SetStatsEnabled(true);
739d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
749d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
750512f02dd6623c0870c11fbf3274d7462f732136Elliott Hughesstatic void VMDebug_stopAllocCounting(JNIEnv*, jclass) {
769ef78b59da51080882e47505896b420977fd79aeMathieu Chartier  Runtime::Current()->SetStatsEnabled(false);
779d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
789d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
791bac54ffa933fbe9b92b62437577f2f4583eff1aElliott Hughesstatic jint VMDebug_getAllocCount(JNIEnv*, jclass, jint kind) {
809d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  return Runtime::Current()->GetStat(kind);
819d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
829d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
830512f02dd6623c0870c11fbf3274d7462f732136Elliott Hughesstatic void VMDebug_resetAllocCount(JNIEnv*, jclass, jint kinds) {
849d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  Runtime::Current()->ResetStats(kinds);
859d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
869d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
8723009dca63c1699e28bfeaa8b45ca48fa0e86aceJeff Haostatic void VMDebug_startMethodTracingDdmsImpl(JNIEnv*, jclass, jint bufferSize, jint flags,
8823009dca63c1699e28bfeaa8b45ca48fa0e86aceJeff Hao                                               jboolean samplingEnabled, jint intervalUs) {
897e7e0f47628fb358da70c5e2766545c4f0596235Andreas Gampe  Trace::Start("[DDMS]", -1, bufferSize, flags, Trace::TraceOutputMode::kDDMS,
907e7e0f47628fb358da70c5e2766545c4f0596235Andreas Gampe               samplingEnabled ? Trace::TraceMode::kSampling : Trace::TraceMode::kMethodTracing,
917e7e0f47628fb358da70c5e2766545c4f0596235Andreas Gampe               intervalUs);
929d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
939d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
9400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersstatic void VMDebug_startMethodTracingFd(JNIEnv* env, jclass, jstring javaTraceFilename,
954044bdac490777cbc8a12d467bec675ef8aa6eb1Jeff Hao                                         jobject javaFd, jint bufferSize, jint flags,
96ca6e14ebd19ab972e4962f18d99a882969d7bee1Shukang Zhou                                         jboolean samplingEnabled, jint intervalUs,
97ca6e14ebd19ab972e4962f18d99a882969d7bee1Shukang Zhou                                         jboolean streamingOutput) {
989d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  int originalFd = jniGetFDFromFileDescriptor(env, javaFd);
999d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  if (originalFd < 0) {
1009d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return;
1019d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  }
1029d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
1039d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  int fd = dup(originalFd);
1049d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  if (fd < 0) {
10500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    ScopedObjectAccess soa(env);
1060aa50ce2fb75bfc2e815a0c33adf9b049561923bNicolas Geoffray    soa.Self()->ThrowNewExceptionF("Ljava/lang/RuntimeException;",
10762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                                   "dup(%d) failed: %s", originalFd, strerror(errno));
1089d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return;
1099d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  }
1109d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
1119d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  ScopedUtfChars traceFilename(env, javaTraceFilename);
1122cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  if (traceFilename.c_str() == nullptr) {
1139d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return;
1149d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  }
115ca6e14ebd19ab972e4962f18d99a882969d7bee1Shukang Zhou  Trace::TraceOutputMode outputMode = streamingOutput
116ca6e14ebd19ab972e4962f18d99a882969d7bee1Shukang Zhou                                          ? Trace::TraceOutputMode::kStreaming
117ca6e14ebd19ab972e4962f18d99a882969d7bee1Shukang Zhou                                          : Trace::TraceOutputMode::kFile;
118ca6e14ebd19ab972e4962f18d99a882969d7bee1Shukang Zhou  Trace::Start(traceFilename.c_str(), fd, bufferSize, flags, outputMode,
1197e7e0f47628fb358da70c5e2766545c4f0596235Andreas Gampe               samplingEnabled ? Trace::TraceMode::kSampling : Trace::TraceMode::kMethodTracing,
1207e7e0f47628fb358da70c5e2766545c4f0596235Andreas Gampe               intervalUs);
1219d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
1229d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
12300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersstatic void VMDebug_startMethodTracingFilename(JNIEnv* env, jclass, jstring javaTraceFilename,
1244044bdac490777cbc8a12d467bec675ef8aa6eb1Jeff Hao                                               jint bufferSize, jint flags,
1254044bdac490777cbc8a12d467bec675ef8aa6eb1Jeff Hao                                               jboolean samplingEnabled, jint intervalUs) {
1269d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  ScopedUtfChars traceFilename(env, javaTraceFilename);
1272cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  if (traceFilename.c_str() == nullptr) {
1289d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return;
1299d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  }
1307e7e0f47628fb358da70c5e2766545c4f0596235Andreas Gampe  Trace::Start(traceFilename.c_str(), -1, bufferSize, flags, Trace::TraceOutputMode::kFile,
1317e7e0f47628fb358da70c5e2766545c4f0596235Andreas Gampe               samplingEnabled ? Trace::TraceMode::kSampling : Trace::TraceMode::kMethodTracing,
1327e7e0f47628fb358da70c5e2766545c4f0596235Andreas Gampe               intervalUs);
1339d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
1349d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
13564caa7dcf46ed6139b766dbe77fbd7353899417fJeff Haostatic jint VMDebug_getMethodTracingMode(JNIEnv*, jclass) {
13664caa7dcf46ed6139b766dbe77fbd7353899417fJeff Hao  return Trace::GetMethodTracingMode();
1379d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
1389d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
1390512f02dd6623c0870c11fbf3274d7462f732136Elliott Hughesstatic void VMDebug_stopMethodTracing(JNIEnv*, jclass) {
140e343b76af81a005ef64f5e75a555389fd9147dabjeffhao  Trace::Stop();
1419d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
1429d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
1430512f02dd6623c0870c11fbf3274d7462f732136Elliott Hughesstatic void VMDebug_startEmulatorTracing(JNIEnv*, jclass) {
1449d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  UNIMPLEMENTED(WARNING);
1457934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom  // dvmEmulatorTraceStart();
1469d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
1479d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
1480512f02dd6623c0870c11fbf3274d7462f732136Elliott Hughesstatic void VMDebug_stopEmulatorTracing(JNIEnv*, jclass) {
1499d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  UNIMPLEMENTED(WARNING);
1507934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom  // dvmEmulatorTraceStop();
1519d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
1529d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
1530512f02dd6623c0870c11fbf3274d7462f732136Elliott Hughesstatic jboolean VMDebug_isDebuggerConnected(JNIEnv*, jclass) {
154c0f0933249cf516b37717faa766e1e9808f7c1f8Elliott Hughes  return Dbg::IsDebuggerActive();
1559d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
1569d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
1570512f02dd6623c0870c11fbf3274d7462f732136Elliott Hughesstatic jboolean VMDebug_isDebuggingEnabled(JNIEnv*, jclass) {
158c0f0933249cf516b37717faa766e1e9808f7c1f8Elliott Hughes  return Dbg::IsJdwpConfigured();
1599d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
1609d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
1610512f02dd6623c0870c11fbf3274d7462f732136Elliott Hughesstatic jlong VMDebug_lastDebuggerActivity(JNIEnv*, jclass) {
162872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return Dbg::LastDebuggerActivity();
1639d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
1649d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
16562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersstatic void ThrowUnsupportedOperationException(JNIEnv* env) {
16600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ScopedObjectAccess soa(env);
1672cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  soa.Self()->ThrowNewException("Ljava/lang/UnsupportedOperationException;", nullptr);
16862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}
16962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
17062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersstatic void VMDebug_startInstructionCounting(JNIEnv* env, jclass) {
17162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  ThrowUnsupportedOperationException(env);
1729d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
1739d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
17400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersstatic void VMDebug_stopInstructionCounting(JNIEnv* env, jclass) {
17562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  ThrowUnsupportedOperationException(env);
1769d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
1779d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
17800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersstatic void VMDebug_getInstructionCount(JNIEnv* env, jclass, jintArray /*javaCounts*/) {
17962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  ThrowUnsupportedOperationException(env);
1809d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
1819d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
18200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersstatic void VMDebug_resetInstructionCount(JNIEnv* env, jclass) {
18362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  ThrowUnsupportedOperationException(env);
1849d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
1859d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
18600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersstatic void VMDebug_printLoadedClasses(JNIEnv* env, jclass, jint flags) {
187cc1b5357f83f0b787d51fbfde3fe870c8a2fa050Andreas Gampe  class DumpClassVisitor : public ClassVisitor {
188cc1b5357f83f0b787d51fbfde3fe870c8a2fa050Andreas Gampe   public:
189cc1b5357f83f0b787d51fbfde3fe870c8a2fa050Andreas Gampe    explicit DumpClassVisitor(int dump_flags) : flags_(dump_flags) {}
190cc1b5357f83f0b787d51fbfde3fe870c8a2fa050Andreas Gampe
191cc1b5357f83f0b787d51fbfde3fe870c8a2fa050Andreas Gampe    bool operator()(ObjPtr<mirror::Class> klass) OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
192cc1b5357f83f0b787d51fbfde3fe870c8a2fa050Andreas Gampe      klass->DumpClass(LOG_STREAM(ERROR), flags_);
193cc1b5357f83f0b787d51fbfde3fe870c8a2fa050Andreas Gampe      return true;
194cc1b5357f83f0b787d51fbfde3fe870c8a2fa050Andreas Gampe    }
195cc1b5357f83f0b787d51fbfde3fe870c8a2fa050Andreas Gampe
196cc1b5357f83f0b787d51fbfde3fe870c8a2fa050Andreas Gampe   private:
197cc1b5357f83f0b787d51fbfde3fe870c8a2fa050Andreas Gampe    const int flags_;
198cc1b5357f83f0b787d51fbfde3fe870c8a2fa050Andreas Gampe  };
199cc1b5357f83f0b787d51fbfde3fe870c8a2fa050Andreas Gampe  DumpClassVisitor visitor(flags);
200cc1b5357f83f0b787d51fbfde3fe870c8a2fa050Andreas Gampe
20153b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers  ScopedFastNativeObjectAccess soa(env);
202cc1b5357f83f0b787d51fbfde3fe870c8a2fa050Andreas Gampe  return Runtime::Current()->GetClassLinker()->VisitClasses(&visitor);
2039d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
2049d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
2057dfb28c066159e6cde8181720f0c451a700ef966Ian Rogersstatic jint VMDebug_getLoadedClassCount(JNIEnv* env, jclass) {
20653b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers  ScopedFastNativeObjectAccess soa(env);
2079d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  return Runtime::Current()->GetClassLinker()->NumLoadedClasses();
2089d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
2099d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
2109d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes/*
2119d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes * Returns the thread-specific CPU-time clock value for the current thread,
2129d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes * or -1 if the feature isn't supported.
2139d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes */
2140512f02dd6623c0870c11fbf3274d7462f732136Elliott Hughesstatic jlong VMDebug_threadCpuTimeNanos(JNIEnv*, jclass) {
2150512f02dd6623c0870c11fbf3274d7462f732136Elliott Hughes  return ThreadCpuNanoTime();
2169d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
2179d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
2189d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes/*
2199d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes * static void dumpHprofData(String fileName, FileDescriptor fd)
2209d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes *
2219d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes * Cause "hprof" data to be dumped.  We can throw an IOException if an
2229d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes * error occurs during file handling.
2239d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes */
2240512f02dd6623c0870c11fbf3274d7462f732136Elliott Hughesstatic void VMDebug_dumpHprofData(JNIEnv* env, jclass, jstring javaFilename, jobject javaFd) {
2252cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  // Only one of these may be null.
2262cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  if (javaFilename == nullptr && javaFd == nullptr) {
22700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    ScopedObjectAccess soa(env);
2280aa50ce2fb75bfc2e815a0c33adf9b049561923bNicolas Geoffray    ThrowNullPointerException("fileName == null && fd == null");
2299d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return;
2309d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  }
2319d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
2329d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  std::string filename;
2332cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  if (javaFilename != nullptr) {
2349d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    ScopedUtfChars chars(env, javaFilename);
2359d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    if (env->ExceptionCheck()) {
2369d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes      return;
2379d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    }
2389d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    filename = chars.c_str();
2399d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  } else {
2409d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    filename = "[fd]";
2419d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  }
2429d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
2439d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  int fd = -1;
2442cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  if (javaFd != nullptr) {
2459d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    fd = jniGetFDFromFileDescriptor(env, javaFd);
2469d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    if (fd < 0) {
24700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers      ScopedObjectAccess soa(env);
24862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      ThrowRuntimeException("Invalid file descriptor");
2499d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes      return;
2509d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    }
2519d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  }
2529d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
253622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  hprof::DumpHeap(filename.c_str(), fd, false);
2549d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
2559d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
256eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughesstatic void VMDebug_dumpHprofDataDdms(JNIEnv*, jclass) {
257622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  hprof::DumpHeap("[DDMS]", -1, true);
2589d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
2599d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
2600512f02dd6623c0870c11fbf3274d7462f732136Elliott Hughesstatic void VMDebug_dumpReferenceTables(JNIEnv* env, jclass) {
26100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ScopedObjectAccess soa(env);
2629d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  LOG(INFO) << "--- reference table dump ---";
2639d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
2643fec9ac0d5af1358d216eb2fdc2000ec0205f3f0Andreas Gampe  soa.Env()->DumpReferenceTables(LOG_STREAM(INFO));
2653fec9ac0d5af1358d216eb2fdc2000ec0205f3f0Andreas Gampe  soa.Vm()->DumpReferenceTables(LOG_STREAM(INFO));
2669d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
2679d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  LOG(INFO) << "---";
2689d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
2699d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
2700512f02dd6623c0870c11fbf3274d7462f732136Elliott Hughesstatic void VMDebug_crash(JNIEnv*, jclass) {
27181ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes  LOG(FATAL) << "Crashing runtime on request";
2729d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
2739d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
2740512f02dd6623c0870c11fbf3274d7462f732136Elliott Hughesstatic void VMDebug_infopoint(JNIEnv*, jclass, jint id) {
2759d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  LOG(INFO) << "VMDebug infopoint " << id << " hit";
2769d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
2779d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
2789d156d500801accee919b6d51e22d6ddcdcd4a05Mathieu Chartierstatic jlong VMDebug_countInstancesOfClass(JNIEnv* env,
2799d156d500801accee919b6d51e22d6ddcdcd4a05Mathieu Chartier                                           jclass,
2809d156d500801accee919b6d51e22d6ddcdcd4a05Mathieu Chartier                                           jclass javaClass,
28100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers                                           jboolean countAssignable) {
28200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ScopedObjectAccess soa(env);
283f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier  gc::Heap* const heap = Runtime::Current()->GetHeap();
284f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier  // Caller's responsibility to do GC if desired.
2850795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier  ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(javaClass);
286412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier  if (c == nullptr) {
2879d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return 0;
2889d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  }
289e8a3c576301fd531d5f73a65fc8b84a63619d580Mathieu Chartier  VariableSizedHandleScope hs(soa.Self());
2909d156d500801accee919b6d51e22d6ddcdcd4a05Mathieu Chartier  std::vector<Handle<mirror::Class>> classes {hs.NewHandle(c)};
291ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes  uint64_t count = 0;
292412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier  heap->CountInstances(classes, countAssignable, &count);
293ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes  return count;
2949d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
2959d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
2969d156d500801accee919b6d51e22d6ddcdcd4a05Mathieu Chartierstatic jlongArray VMDebug_countInstancesOfClasses(JNIEnv* env,
2979d156d500801accee919b6d51e22d6ddcdcd4a05Mathieu Chartier                                                  jclass,
2989d156d500801accee919b6d51e22d6ddcdcd4a05Mathieu Chartier                                                  jobjectArray javaClasses,
299f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier                                                  jboolean countAssignable) {
300f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier  ScopedObjectAccess soa(env);
301f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier  gc::Heap* const heap = Runtime::Current()->GetHeap();
302f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier  // Caller's responsibility to do GC if desired.
3030795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier  ObjPtr<mirror::ObjectArray<mirror::Class>> decoded_classes =
3040795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier      soa.Decode<mirror::ObjectArray<mirror::Class>>(javaClasses);
305f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier  if (decoded_classes == nullptr) {
306f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier    return nullptr;
307f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier  }
308e8a3c576301fd531d5f73a65fc8b84a63619d580Mathieu Chartier  VariableSizedHandleScope hs(soa.Self());
3099d156d500801accee919b6d51e22d6ddcdcd4a05Mathieu Chartier  std::vector<Handle<mirror::Class>> classes;
310f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier  for (size_t i = 0, count = decoded_classes->GetLength(); i < count; ++i) {
3119d156d500801accee919b6d51e22d6ddcdcd4a05Mathieu Chartier    classes.push_back(hs.NewHandle(decoded_classes->Get(i)));
312f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier  }
313f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier  std::vector<uint64_t> counts(classes.size(), 0u);
314f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier  // Heap::CountInstances can handle null and will put 0 for these classes.
315f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier  heap->CountInstances(classes, countAssignable, &counts[0]);
3169d156d500801accee919b6d51e22d6ddcdcd4a05Mathieu Chartier  ObjPtr<mirror::LongArray> long_counts = mirror::LongArray::Alloc(soa.Self(), counts.size());
317f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier  if (long_counts == nullptr) {
318f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier    soa.Self()->AssertPendingOOMException();
319f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier    return nullptr;
320f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier  }
321f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier  for (size_t i = 0; i < counts.size(); ++i) {
322f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier    long_counts->Set(i, counts[i]);
323f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier  }
324f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier  return soa.AddLocalReference<jlongArray>(long_counts);
325f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier}
326f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier
32709b07a96094086e205948717666025909a75163bHiroshi Yamauchi// We export the VM internal per-heap-space size/alloc/free metrics
32809b07a96094086e205948717666025909a75163bHiroshi Yamauchi// for the zygote space, alloc space (application heap), and the large
32909b07a96094086e205948717666025909a75163bHiroshi Yamauchi// object space for dumpsys meminfo. The other memory region data such
33009b07a96094086e205948717666025909a75163bHiroshi Yamauchi// as PSS, private/shared dirty/shared data are available via
33109b07a96094086e205948717666025909a75163bHiroshi Yamauchi// /proc/<pid>/smaps.
33209b07a96094086e205948717666025909a75163bHiroshi Yamauchistatic void VMDebug_getHeapSpaceStats(JNIEnv* env, jclass, jlongArray data) {
3336b99dd10d8a4869bbf7e9263a350185e5ebe32e4Ian Rogers  jlong* arr = reinterpret_cast<jlong*>(env->GetPrimitiveArrayCritical(data, 0));
3347410f29b4dae223befac036ea567d7f33351dad1Mathieu Chartier  if (arr == nullptr || env->GetArrayLength(data) < 9) {
33509b07a96094086e205948717666025909a75163bHiroshi Yamauchi    return;
33609b07a96094086e205948717666025909a75163bHiroshi Yamauchi  }
33709b07a96094086e205948717666025909a75163bHiroshi Yamauchi
33809b07a96094086e205948717666025909a75163bHiroshi Yamauchi  size_t allocSize = 0;
33909b07a96094086e205948717666025909a75163bHiroshi Yamauchi  size_t allocUsed = 0;
34009b07a96094086e205948717666025909a75163bHiroshi Yamauchi  size_t zygoteSize = 0;
34109b07a96094086e205948717666025909a75163bHiroshi Yamauchi  size_t zygoteUsed = 0;
34209b07a96094086e205948717666025909a75163bHiroshi Yamauchi  size_t largeObjectsSize = 0;
34309b07a96094086e205948717666025909a75163bHiroshi Yamauchi  size_t largeObjectsUsed = 0;
34409b07a96094086e205948717666025909a75163bHiroshi Yamauchi  gc::Heap* heap = Runtime::Current()->GetHeap();
345a9d82fe8bc6960b565245b920e99107a824ca515Mathieu Chartier  {
346a9d82fe8bc6960b565245b920e99107a824ca515Mathieu Chartier    ScopedObjectAccess soa(env);
347a9d82fe8bc6960b565245b920e99107a824ca515Mathieu Chartier    for (gc::space::ContinuousSpace* space : heap->GetContinuousSpaces()) {
348a9d82fe8bc6960b565245b920e99107a824ca515Mathieu Chartier      if (space->IsImageSpace()) {
349a9d82fe8bc6960b565245b920e99107a824ca515Mathieu Chartier        // Currently don't include the image space.
350a9d82fe8bc6960b565245b920e99107a824ca515Mathieu Chartier      } else if (space->IsZygoteSpace()) {
351a9d82fe8bc6960b565245b920e99107a824ca515Mathieu Chartier        gc::space::ZygoteSpace* zygote_space = space->AsZygoteSpace();
352a9d82fe8bc6960b565245b920e99107a824ca515Mathieu Chartier        zygoteSize += zygote_space->Size();
353a9d82fe8bc6960b565245b920e99107a824ca515Mathieu Chartier        zygoteUsed += zygote_space->GetBytesAllocated();
354a9d82fe8bc6960b565245b920e99107a824ca515Mathieu Chartier      } else if (space->IsMallocSpace()) {
355a9d82fe8bc6960b565245b920e99107a824ca515Mathieu Chartier        // This is a malloc space.
356a9d82fe8bc6960b565245b920e99107a824ca515Mathieu Chartier        gc::space::MallocSpace* malloc_space = space->AsMallocSpace();
357a9d82fe8bc6960b565245b920e99107a824ca515Mathieu Chartier        allocSize += malloc_space->GetFootprint();
358a9d82fe8bc6960b565245b920e99107a824ca515Mathieu Chartier        allocUsed += malloc_space->GetBytesAllocated();
359a9d82fe8bc6960b565245b920e99107a824ca515Mathieu Chartier      } else if (space->IsBumpPointerSpace()) {
360a9d82fe8bc6960b565245b920e99107a824ca515Mathieu Chartier        gc::space::BumpPointerSpace* bump_pointer_space = space->AsBumpPointerSpace();
361a9d82fe8bc6960b565245b920e99107a824ca515Mathieu Chartier        allocSize += bump_pointer_space->Size();
362a9d82fe8bc6960b565245b920e99107a824ca515Mathieu Chartier        allocUsed += bump_pointer_space->GetBytesAllocated();
363a9d82fe8bc6960b565245b920e99107a824ca515Mathieu Chartier      }
36409b07a96094086e205948717666025909a75163bHiroshi Yamauchi    }
365a9d82fe8bc6960b565245b920e99107a824ca515Mathieu Chartier    for (gc::space::DiscontinuousSpace* space : heap->GetDiscontinuousSpaces()) {
366a9d82fe8bc6960b565245b920e99107a824ca515Mathieu Chartier      if (space->IsLargeObjectSpace()) {
367a9d82fe8bc6960b565245b920e99107a824ca515Mathieu Chartier        largeObjectsSize += space->AsLargeObjectSpace()->GetBytesAllocated();
368a9d82fe8bc6960b565245b920e99107a824ca515Mathieu Chartier        largeObjectsUsed += largeObjectsSize;
369a9d82fe8bc6960b565245b920e99107a824ca515Mathieu Chartier      }
37009b07a96094086e205948717666025909a75163bHiroshi Yamauchi    }
37109b07a96094086e205948717666025909a75163bHiroshi Yamauchi  }
37209b07a96094086e205948717666025909a75163bHiroshi Yamauchi  size_t allocFree = allocSize - allocUsed;
37309b07a96094086e205948717666025909a75163bHiroshi Yamauchi  size_t zygoteFree = zygoteSize - zygoteUsed;
37409b07a96094086e205948717666025909a75163bHiroshi Yamauchi  size_t largeObjectsFree = largeObjectsSize - largeObjectsUsed;
37509b07a96094086e205948717666025909a75163bHiroshi Yamauchi
37609b07a96094086e205948717666025909a75163bHiroshi Yamauchi  int j = 0;
37709b07a96094086e205948717666025909a75163bHiroshi Yamauchi  arr[j++] = allocSize;
37809b07a96094086e205948717666025909a75163bHiroshi Yamauchi  arr[j++] = allocUsed;
37909b07a96094086e205948717666025909a75163bHiroshi Yamauchi  arr[j++] = allocFree;
38009b07a96094086e205948717666025909a75163bHiroshi Yamauchi  arr[j++] = zygoteSize;
38109b07a96094086e205948717666025909a75163bHiroshi Yamauchi  arr[j++] = zygoteUsed;
38209b07a96094086e205948717666025909a75163bHiroshi Yamauchi  arr[j++] = zygoteFree;
38309b07a96094086e205948717666025909a75163bHiroshi Yamauchi  arr[j++] = largeObjectsSize;
38409b07a96094086e205948717666025909a75163bHiroshi Yamauchi  arr[j++] = largeObjectsUsed;
38509b07a96094086e205948717666025909a75163bHiroshi Yamauchi  arr[j++] = largeObjectsFree;
38609b07a96094086e205948717666025909a75163bHiroshi Yamauchi  env->ReleasePrimitiveArrayCritical(data, arr, 0);
38709b07a96094086e205948717666025909a75163bHiroshi Yamauchi}
38809b07a96094086e205948717666025909a75163bHiroshi Yamauchi
389a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi// The runtime stat names for VMDebug.getRuntimeStat().
390a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchienum class VMDebugRuntimeStatId {
391a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi  kArtGcGcCount = 0,
392a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi  kArtGcGcTime,
393a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi  kArtGcBytesAllocated,
394a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi  kArtGcBytesFreed,
395a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi  kArtGcBlockingGcCount,
396a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi  kArtGcBlockingGcTime,
397a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi  kArtGcGcCountRateHistogram,
398a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi  kArtGcBlockingGcCountRateHistogram,
399a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi  kNumRuntimeStats,
400a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi};
401a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi
402a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchistatic jobject VMDebug_getRuntimeStatInternal(JNIEnv* env, jclass, jint statId) {
403a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi  gc::Heap* heap = Runtime::Current()->GetHeap();
404a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi  switch (static_cast<VMDebugRuntimeStatId>(statId)) {
405a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi    case VMDebugRuntimeStatId::kArtGcGcCount: {
406a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi      std::string output = std::to_string(heap->GetGcCount());
407a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi      return env->NewStringUTF(output.c_str());
408a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi    }
409a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi    case VMDebugRuntimeStatId::kArtGcGcTime: {
410a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi      std::string output = std::to_string(NsToMs(heap->GetGcTime()));
411a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi      return env->NewStringUTF(output.c_str());
412a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi    }
413a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi    case VMDebugRuntimeStatId::kArtGcBytesAllocated: {
414a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi      std::string output = std::to_string(heap->GetBytesAllocatedEver());
415a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi      return env->NewStringUTF(output.c_str());
416a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi    }
417a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi    case VMDebugRuntimeStatId::kArtGcBytesFreed: {
418a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi      std::string output = std::to_string(heap->GetBytesFreedEver());
419a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi      return env->NewStringUTF(output.c_str());
420a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi    }
421a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi    case VMDebugRuntimeStatId::kArtGcBlockingGcCount: {
422a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi      std::string output = std::to_string(heap->GetBlockingGcCount());
423a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi      return env->NewStringUTF(output.c_str());
424a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi    }
425a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi    case VMDebugRuntimeStatId::kArtGcBlockingGcTime: {
426a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi      std::string output = std::to_string(NsToMs(heap->GetBlockingGcTime()));
427a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi      return env->NewStringUTF(output.c_str());
428a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi    }
429a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi    case VMDebugRuntimeStatId::kArtGcGcCountRateHistogram: {
430a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi      std::ostringstream output;
431a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi      heap->DumpGcCountRateHistogram(output);
432a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi      return env->NewStringUTF(output.str().c_str());
433a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi    }
434a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi    case VMDebugRuntimeStatId::kArtGcBlockingGcCountRateHistogram: {
435a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi      std::ostringstream output;
436a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi      heap->DumpBlockingGcCountRateHistogram(output);
437a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi      return env->NewStringUTF(output.str().c_str());
438a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi    }
439a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi    default:
440a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi      return nullptr;
441a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi  }
442a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi}
443a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi
444ca620d7bc03b23a0bcf0ef58df58603ee000dca0Andreas Gampestatic bool SetRuntimeStatValue(JNIEnv* env,
445ca620d7bc03b23a0bcf0ef58df58603ee000dca0Andreas Gampe                                jobjectArray result,
446ca620d7bc03b23a0bcf0ef58df58603ee000dca0Andreas Gampe                                VMDebugRuntimeStatId id,
447ca620d7bc03b23a0bcf0ef58df58603ee000dca0Andreas Gampe                                const std::string& value) {
448a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi  ScopedLocalRef<jstring> jvalue(env, env->NewStringUTF(value.c_str()));
449a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi  if (jvalue.get() == nullptr) {
450a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi    return false;
451a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi  }
452a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi  env->SetObjectArrayElement(result, static_cast<jint>(id), jvalue.get());
453a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi  return true;
454a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi}
455a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi
456a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchistatic jobjectArray VMDebug_getRuntimeStatsInternal(JNIEnv* env, jclass) {
457a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi  jobjectArray result = env->NewObjectArray(
458a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi      static_cast<jint>(VMDebugRuntimeStatId::kNumRuntimeStats),
459a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi      WellKnownClasses::java_lang_String,
460a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi      nullptr);
461a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi  if (result == nullptr) {
462a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi    return nullptr;
463a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi  }
464a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi  gc::Heap* heap = Runtime::Current()->GetHeap();
465a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi  if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcGcCount,
466a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi                           std::to_string(heap->GetGcCount()))) {
467a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi    return nullptr;
468a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi  }
469a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi  if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcGcTime,
470a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi                           std::to_string(NsToMs(heap->GetGcTime())))) {
471a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi    return nullptr;
472a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi  }
473a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi  if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcBytesAllocated,
474a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi                           std::to_string(heap->GetBytesAllocatedEver()))) {
475a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi    return nullptr;
476a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi  }
477a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi  if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcBytesFreed,
478a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi                           std::to_string(heap->GetBytesFreedEver()))) {
479a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi    return nullptr;
480a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi  }
481a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi  if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcBlockingGcCount,
482a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi                           std::to_string(heap->GetBlockingGcCount()))) {
483a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi    return nullptr;
484a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi  }
485a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi  if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcBlockingGcTime,
486a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi                           std::to_string(NsToMs(heap->GetBlockingGcTime())))) {
487a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi    return nullptr;
488a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi  }
489a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi  {
490a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi    std::ostringstream output;
491a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi    heap->DumpGcCountRateHistogram(output);
492a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi    if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcGcCountRateHistogram,
493a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi                             output.str())) {
494a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi      return nullptr;
495a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi    }
496a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi  }
497a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi  {
498a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi    std::ostringstream output;
499a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi    heap->DumpBlockingGcCountRateHistogram(output);
500a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi    if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcBlockingGcCountRateHistogram,
501a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi                             output.str())) {
502a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi      return nullptr;
503a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi    }
504a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi  }
505a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi  return result;
506a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi}
507a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi
508eb84221ffc00357be6d69e2e461c7a45ee96334aLeonard Mosescustatic void VMDebug_attachAgent(JNIEnv* env, jclass, jstring agent) {
509eb84221ffc00357be6d69e2e461c7a45ee96334aLeonard Mosescu  if (agent == nullptr) {
510eb84221ffc00357be6d69e2e461c7a45ee96334aLeonard Mosescu    ScopedObjectAccess soa(env);
511eb84221ffc00357be6d69e2e461c7a45ee96334aLeonard Mosescu    ThrowNullPointerException("agent is null");
512eb84221ffc00357be6d69e2e461c7a45ee96334aLeonard Mosescu    return;
513eb84221ffc00357be6d69e2e461c7a45ee96334aLeonard Mosescu  }
514eb84221ffc00357be6d69e2e461c7a45ee96334aLeonard Mosescu
515eb84221ffc00357be6d69e2e461c7a45ee96334aLeonard Mosescu  if (!Dbg::IsJdwpAllowed()) {
516eb84221ffc00357be6d69e2e461c7a45ee96334aLeonard Mosescu    ScopedObjectAccess soa(env);
517eb84221ffc00357be6d69e2e461c7a45ee96334aLeonard Mosescu    ThrowSecurityException("Can't attach agent, process is not debuggable.");
518eb84221ffc00357be6d69e2e461c7a45ee96334aLeonard Mosescu    return;
519eb84221ffc00357be6d69e2e461c7a45ee96334aLeonard Mosescu  }
520eb84221ffc00357be6d69e2e461c7a45ee96334aLeonard Mosescu
521eb84221ffc00357be6d69e2e461c7a45ee96334aLeonard Mosescu  std::string filename;
522eb84221ffc00357be6d69e2e461c7a45ee96334aLeonard Mosescu  {
523eb84221ffc00357be6d69e2e461c7a45ee96334aLeonard Mosescu    ScopedUtfChars chars(env, agent);
524eb84221ffc00357be6d69e2e461c7a45ee96334aLeonard Mosescu    if (env->ExceptionCheck()) {
525eb84221ffc00357be6d69e2e461c7a45ee96334aLeonard Mosescu      return;
526eb84221ffc00357be6d69e2e461c7a45ee96334aLeonard Mosescu    }
527eb84221ffc00357be6d69e2e461c7a45ee96334aLeonard Mosescu    filename = chars.c_str();
528eb84221ffc00357be6d69e2e461c7a45ee96334aLeonard Mosescu  }
529eb84221ffc00357be6d69e2e461c7a45ee96334aLeonard Mosescu
530eb84221ffc00357be6d69e2e461c7a45ee96334aLeonard Mosescu  Runtime::Current()->AttachAgent(filename);
531eb84221ffc00357be6d69e2e461c7a45ee96334aLeonard Mosescu}
532eb84221ffc00357be6d69e2e461c7a45ee96334aLeonard Mosescu
5330512f02dd6623c0870c11fbf3274d7462f732136Elliott Hughesstatic JNINativeMethod gMethods[] = {
5349d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  NATIVE_METHOD(VMDebug, countInstancesOfClass, "(Ljava/lang/Class;Z)J"),
535f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier  NATIVE_METHOD(VMDebug, countInstancesOfClasses, "([Ljava/lang/Class;Z)[J"),
5369d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  NATIVE_METHOD(VMDebug, crash, "()V"),
5379d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  NATIVE_METHOD(VMDebug, dumpHprofData, "(Ljava/lang/String;Ljava/io/FileDescriptor;)V"),
5389d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  NATIVE_METHOD(VMDebug, dumpHprofDataDdms, "()V"),
5399d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  NATIVE_METHOD(VMDebug, dumpReferenceTables, "()V"),
5409d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  NATIVE_METHOD(VMDebug, getAllocCount, "(I)I"),
54109b07a96094086e205948717666025909a75163bHiroshi Yamauchi  NATIVE_METHOD(VMDebug, getHeapSpaceStats, "([J)V"),
5429d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  NATIVE_METHOD(VMDebug, getInstructionCount, "([I)V"),
5433b6f440dbd066f03a737da6d292074f47b3fbc29Igor Murashkin  FAST_NATIVE_METHOD(VMDebug, getLoadedClassCount, "()I"),
5449d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  NATIVE_METHOD(VMDebug, getVmFeatureList, "()[Ljava/lang/String;"),
5459d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  NATIVE_METHOD(VMDebug, infopoint, "(I)V"),
5463b6f440dbd066f03a737da6d292074f47b3fbc29Igor Murashkin  FAST_NATIVE_METHOD(VMDebug, isDebuggerConnected, "()Z"),
5473b6f440dbd066f03a737da6d292074f47b3fbc29Igor Murashkin  FAST_NATIVE_METHOD(VMDebug, isDebuggingEnabled, "()Z"),
54864caa7dcf46ed6139b766dbe77fbd7353899417fJeff Hao  NATIVE_METHOD(VMDebug, getMethodTracingMode, "()I"),
5493b6f440dbd066f03a737da6d292074f47b3fbc29Igor Murashkin  FAST_NATIVE_METHOD(VMDebug, lastDebuggerActivity, "()J"),
5503b6f440dbd066f03a737da6d292074f47b3fbc29Igor Murashkin  FAST_NATIVE_METHOD(VMDebug, printLoadedClasses, "(I)V"),
5519d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  NATIVE_METHOD(VMDebug, resetAllocCount, "(I)V"),
5529d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  NATIVE_METHOD(VMDebug, resetInstructionCount, "()V"),
5539d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  NATIVE_METHOD(VMDebug, startAllocCounting, "()V"),
5549d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  NATIVE_METHOD(VMDebug, startEmulatorTracing, "()V"),
5559d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  NATIVE_METHOD(VMDebug, startInstructionCounting, "()V"),
55623009dca63c1699e28bfeaa8b45ca48fa0e86aceJeff Hao  NATIVE_METHOD(VMDebug, startMethodTracingDdmsImpl, "(IIZI)V"),
557ca6e14ebd19ab972e4962f18d99a882969d7bee1Shukang Zhou  NATIVE_METHOD(VMDebug, startMethodTracingFd, "(Ljava/lang/String;Ljava/io/FileDescriptor;IIZIZ)V"),
5584044bdac490777cbc8a12d467bec675ef8aa6eb1Jeff Hao  NATIVE_METHOD(VMDebug, startMethodTracingFilename, "(Ljava/lang/String;IIZI)V"),
5599d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  NATIVE_METHOD(VMDebug, stopAllocCounting, "()V"),
5609d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  NATIVE_METHOD(VMDebug, stopEmulatorTracing, "()V"),
5619d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  NATIVE_METHOD(VMDebug, stopInstructionCounting, "()V"),
5629d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  NATIVE_METHOD(VMDebug, stopMethodTracing, "()V"),
5633b6f440dbd066f03a737da6d292074f47b3fbc29Igor Murashkin  FAST_NATIVE_METHOD(VMDebug, threadCpuTimeNanos, "()J"),
564a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi  NATIVE_METHOD(VMDebug, getRuntimeStatInternal, "(I)Ljava/lang/String;"),
565eb84221ffc00357be6d69e2e461c7a45ee96334aLeonard Mosescu  NATIVE_METHOD(VMDebug, getRuntimeStatsInternal, "()[Ljava/lang/String;"),
566eb84221ffc00357be6d69e2e461c7a45ee96334aLeonard Mosescu  NATIVE_METHOD(VMDebug, attachAgent, "(Ljava/lang/String;)V"),
5679d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes};
5689d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
5699d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughesvoid register_dalvik_system_VMDebug(JNIEnv* env) {
570eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes  REGISTER_NATIVE_METHODS("dalvik/system/VMDebug");
5719d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
5729d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
5739d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}  // namespace art
574