dalvik_system_VMDebug.cc revision 7e7e0f47628fb358da70c5e2766545c4f0596235
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
229d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes#include "class_linker.h"
2362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers#include "common_throws.h"
24872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include "debugger.h"
257410f29b4dae223befac036ea567d7f33351dad1Mathieu Chartier#include "gc/space/bump_pointer_space.h"
2609b07a96094086e205948717666025909a75163bHiroshi Yamauchi#include "gc/space/dlmalloc_space.h"
2709b07a96094086e205948717666025909a75163bHiroshi Yamauchi#include "gc/space/large_object_space.h"
2809b07a96094086e205948717666025909a75163bHiroshi Yamauchi#include "gc/space/space-inl.h"
291f3b5358b28a83f0929bdd8ce738f06908677fb7Mathieu Chartier#include "gc/space/zygote_space.h"
301121e0b619d0c9df36c57396b2234a9d570b4923Jesse Wilson#include "hprof/hprof.h"
31eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes#include "jni_internal.h"
322dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class.h"
33dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers#include "ScopedLocalRef.h"
349d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes#include "ScopedUtfChars.h"
3553b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers#include "scoped_fast_native_object_access.h"
36eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes#include "trace.h"
37dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers#include "well_known_classes.h"
389d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
399d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughesnamespace art {
409d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
410512f02dd6623c0870c11fbf3274d7462f732136Elliott Hughesstatic jobjectArray VMDebug_getVmFeatureList(JNIEnv* env, jclass) {
42dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers  static const char* features[] = {
43dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers    "method-trace-profiling",
44dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers    "method-trace-profiling-streaming",
45dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers    "method-sample-profiling",
46dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers    "hprof-heap-dump",
47dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers    "hprof-heap-dump-streaming",
48dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers  };
49dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers  jobjectArray result = env->NewObjectArray(arraysize(features),
50dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers                                            WellKnownClasses::java_lang_String,
51dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers                                            nullptr);
52dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers  if (result != nullptr) {
53dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers    for (size_t i = 0; i < arraysize(features); ++i) {
54dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers      ScopedLocalRef<jstring> jfeature(env, env->NewStringUTF(features[i]));
55dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers      if (jfeature.get() == nullptr) {
56dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers        return nullptr;
57dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers      }
58dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers      env->SetObjectArrayElement(result, i, jfeature.get());
59dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers    }
60dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers  }
61dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers  return result;
629d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
639d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
640512f02dd6623c0870c11fbf3274d7462f732136Elliott Hughesstatic void VMDebug_startAllocCounting(JNIEnv*, jclass) {
659ef78b59da51080882e47505896b420977fd79aeMathieu Chartier  Runtime::Current()->SetStatsEnabled(true);
669d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
679d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
680512f02dd6623c0870c11fbf3274d7462f732136Elliott Hughesstatic void VMDebug_stopAllocCounting(JNIEnv*, jclass) {
699ef78b59da51080882e47505896b420977fd79aeMathieu Chartier  Runtime::Current()->SetStatsEnabled(false);
709d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
719d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
721bac54ffa933fbe9b92b62437577f2f4583eff1aElliott Hughesstatic jint VMDebug_getAllocCount(JNIEnv*, jclass, jint kind) {
739d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  return Runtime::Current()->GetStat(kind);
749d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
759d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
760512f02dd6623c0870c11fbf3274d7462f732136Elliott Hughesstatic void VMDebug_resetAllocCount(JNIEnv*, jclass, jint kinds) {
779d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  Runtime::Current()->ResetStats(kinds);
789d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
799d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
8023009dca63c1699e28bfeaa8b45ca48fa0e86aceJeff Haostatic void VMDebug_startMethodTracingDdmsImpl(JNIEnv*, jclass, jint bufferSize, jint flags,
8123009dca63c1699e28bfeaa8b45ca48fa0e86aceJeff Hao                                               jboolean samplingEnabled, jint intervalUs) {
827e7e0f47628fb358da70c5e2766545c4f0596235Andreas Gampe  Trace::Start("[DDMS]", -1, bufferSize, flags, Trace::TraceOutputMode::kDDMS,
837e7e0f47628fb358da70c5e2766545c4f0596235Andreas Gampe               samplingEnabled ? Trace::TraceMode::kSampling : Trace::TraceMode::kMethodTracing,
847e7e0f47628fb358da70c5e2766545c4f0596235Andreas Gampe               intervalUs);
859d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
869d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
8700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersstatic void VMDebug_startMethodTracingFd(JNIEnv* env, jclass, jstring javaTraceFilename,
884044bdac490777cbc8a12d467bec675ef8aa6eb1Jeff Hao                                         jobject javaFd, jint bufferSize, jint flags,
894044bdac490777cbc8a12d467bec675ef8aa6eb1Jeff Hao                                         jboolean samplingEnabled, jint intervalUs) {
909d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  int originalFd = jniGetFDFromFileDescriptor(env, javaFd);
919d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  if (originalFd < 0) {
929d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return;
939d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  }
949d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
959d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  int fd = dup(originalFd);
969d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  if (fd < 0) {
9700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    ScopedObjectAccess soa(env);
980aa50ce2fb75bfc2e815a0c33adf9b049561923bNicolas Geoffray    soa.Self()->ThrowNewExceptionF("Ljava/lang/RuntimeException;",
9962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                                   "dup(%d) failed: %s", originalFd, strerror(errno));
1009d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return;
1019d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  }
1029d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
1039d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  ScopedUtfChars traceFilename(env, javaTraceFilename);
1049d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  if (traceFilename.c_str() == NULL) {
1059d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return;
1069d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  }
1077e7e0f47628fb358da70c5e2766545c4f0596235Andreas Gampe  Trace::Start(traceFilename.c_str(), fd, bufferSize, flags, Trace::TraceOutputMode::kFile,
1087e7e0f47628fb358da70c5e2766545c4f0596235Andreas Gampe               samplingEnabled ? Trace::TraceMode::kSampling : Trace::TraceMode::kMethodTracing,
1097e7e0f47628fb358da70c5e2766545c4f0596235Andreas Gampe               intervalUs);
1109d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
1119d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
11200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersstatic void VMDebug_startMethodTracingFilename(JNIEnv* env, jclass, jstring javaTraceFilename,
1134044bdac490777cbc8a12d467bec675ef8aa6eb1Jeff Hao                                               jint bufferSize, jint flags,
1144044bdac490777cbc8a12d467bec675ef8aa6eb1Jeff Hao                                               jboolean samplingEnabled, jint intervalUs) {
1159d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  ScopedUtfChars traceFilename(env, javaTraceFilename);
1169d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  if (traceFilename.c_str() == NULL) {
1179d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return;
1189d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  }
1197e7e0f47628fb358da70c5e2766545c4f0596235Andreas Gampe  Trace::Start(traceFilename.c_str(), -1, bufferSize, flags, Trace::TraceOutputMode::kFile,
1207e7e0f47628fb358da70c5e2766545c4f0596235Andreas Gampe               samplingEnabled ? Trace::TraceMode::kSampling : Trace::TraceMode::kMethodTracing,
1217e7e0f47628fb358da70c5e2766545c4f0596235Andreas Gampe               intervalUs);
1229d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
1239d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
12464caa7dcf46ed6139b766dbe77fbd7353899417fJeff Haostatic jint VMDebug_getMethodTracingMode(JNIEnv*, jclass) {
12564caa7dcf46ed6139b766dbe77fbd7353899417fJeff Hao  return Trace::GetMethodTracingMode();
1269d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
1279d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
1280512f02dd6623c0870c11fbf3274d7462f732136Elliott Hughesstatic void VMDebug_stopMethodTracing(JNIEnv*, jclass) {
129e343b76af81a005ef64f5e75a555389fd9147dabjeffhao  Trace::Stop();
1309d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
1319d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
1320512f02dd6623c0870c11fbf3274d7462f732136Elliott Hughesstatic void VMDebug_startEmulatorTracing(JNIEnv*, jclass) {
1339d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  UNIMPLEMENTED(WARNING);
1347934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom  // dvmEmulatorTraceStart();
1359d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
1369d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
1370512f02dd6623c0870c11fbf3274d7462f732136Elliott Hughesstatic void VMDebug_stopEmulatorTracing(JNIEnv*, jclass) {
1389d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  UNIMPLEMENTED(WARNING);
1397934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom  // dvmEmulatorTraceStop();
1409d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
1419d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
1420512f02dd6623c0870c11fbf3274d7462f732136Elliott Hughesstatic jboolean VMDebug_isDebuggerConnected(JNIEnv*, jclass) {
143c0f0933249cf516b37717faa766e1e9808f7c1f8Elliott Hughes  return Dbg::IsDebuggerActive();
1449d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
1459d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
1460512f02dd6623c0870c11fbf3274d7462f732136Elliott Hughesstatic jboolean VMDebug_isDebuggingEnabled(JNIEnv*, jclass) {
147c0f0933249cf516b37717faa766e1e9808f7c1f8Elliott Hughes  return Dbg::IsJdwpConfigured();
1489d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
1499d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
1500512f02dd6623c0870c11fbf3274d7462f732136Elliott Hughesstatic jlong VMDebug_lastDebuggerActivity(JNIEnv*, jclass) {
151872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return Dbg::LastDebuggerActivity();
1529d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
1539d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
15462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersstatic void ThrowUnsupportedOperationException(JNIEnv* env) {
15500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ScopedObjectAccess soa(env);
1560aa50ce2fb75bfc2e815a0c33adf9b049561923bNicolas Geoffray  soa.Self()->ThrowNewException("Ljava/lang/UnsupportedOperationException;", NULL);
15762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}
15862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
15962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersstatic void VMDebug_startInstructionCounting(JNIEnv* env, jclass) {
16062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  ThrowUnsupportedOperationException(env);
1619d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
1629d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
16300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersstatic void VMDebug_stopInstructionCounting(JNIEnv* env, jclass) {
16462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  ThrowUnsupportedOperationException(env);
1659d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
1669d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
16700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersstatic void VMDebug_getInstructionCount(JNIEnv* env, jclass, jintArray /*javaCounts*/) {
16862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  ThrowUnsupportedOperationException(env);
1699d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
1709d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
17100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersstatic void VMDebug_resetInstructionCount(JNIEnv* env, jclass) {
17262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  ThrowUnsupportedOperationException(env);
1739d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
1749d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
17500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersstatic void VMDebug_printLoadedClasses(JNIEnv* env, jclass, jint flags) {
17653b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers  ScopedFastNativeObjectAccess soa(env);
1779d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  return Runtime::Current()->GetClassLinker()->DumpAllClasses(flags);
1789d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
1799d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
1807dfb28c066159e6cde8181720f0c451a700ef966Ian Rogersstatic jint VMDebug_getLoadedClassCount(JNIEnv* env, jclass) {
18153b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers  ScopedFastNativeObjectAccess soa(env);
1829d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  return Runtime::Current()->GetClassLinker()->NumLoadedClasses();
1839d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
1849d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
1859d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes/*
1869d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes * Returns the thread-specific CPU-time clock value for the current thread,
1879d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes * or -1 if the feature isn't supported.
1889d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes */
1890512f02dd6623c0870c11fbf3274d7462f732136Elliott Hughesstatic jlong VMDebug_threadCpuTimeNanos(JNIEnv*, jclass) {
1900512f02dd6623c0870c11fbf3274d7462f732136Elliott Hughes  return ThreadCpuNanoTime();
1919d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
1929d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
1939d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes/*
1949d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes * static void dumpHprofData(String fileName, FileDescriptor fd)
1959d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes *
1969d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes * Cause "hprof" data to be dumped.  We can throw an IOException if an
1979d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes * error occurs during file handling.
1989d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes */
1990512f02dd6623c0870c11fbf3274d7462f732136Elliott Hughesstatic void VMDebug_dumpHprofData(JNIEnv* env, jclass, jstring javaFilename, jobject javaFd) {
2009d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  // Only one of these may be NULL.
2019d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  if (javaFilename == NULL && javaFd == NULL) {
20200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    ScopedObjectAccess soa(env);
2030aa50ce2fb75bfc2e815a0c33adf9b049561923bNicolas Geoffray    ThrowNullPointerException("fileName == null && fd == null");
2049d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return;
2059d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  }
2069d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
2079d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  std::string filename;
2089d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  if (javaFilename != NULL) {
2099d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    ScopedUtfChars chars(env, javaFilename);
2109d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    if (env->ExceptionCheck()) {
2119d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes      return;
2129d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    }
2139d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    filename = chars.c_str();
2149d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  } else {
2159d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    filename = "[fd]";
2169d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  }
2179d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
2189d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  int fd = -1;
2199d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  if (javaFd != NULL) {
2209d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    fd = jniGetFDFromFileDescriptor(env, javaFd);
2219d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    if (fd < 0) {
22200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers      ScopedObjectAccess soa(env);
22362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      ThrowRuntimeException("Invalid file descriptor");
2249d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes      return;
2259d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    }
2269d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  }
2279d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
228622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  hprof::DumpHeap(filename.c_str(), fd, false);
2299d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
2309d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
231eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughesstatic void VMDebug_dumpHprofDataDdms(JNIEnv*, jclass) {
232622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  hprof::DumpHeap("[DDMS]", -1, true);
2339d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
2349d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
2350512f02dd6623c0870c11fbf3274d7462f732136Elliott Hughesstatic void VMDebug_dumpReferenceTables(JNIEnv* env, jclass) {
23600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ScopedObjectAccess soa(env);
2379d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  LOG(INFO) << "--- reference table dump ---";
2389d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
23900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  soa.Env()->DumpReferenceTables(LOG(INFO));
24000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  soa.Vm()->DumpReferenceTables(LOG(INFO));
2419d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
2429d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  LOG(INFO) << "---";
2439d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
2449d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
2450512f02dd6623c0870c11fbf3274d7462f732136Elliott Hughesstatic void VMDebug_crash(JNIEnv*, jclass) {
24681ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes  LOG(FATAL) << "Crashing runtime on request";
2479d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
2489d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
2490512f02dd6623c0870c11fbf3274d7462f732136Elliott Hughesstatic void VMDebug_infopoint(JNIEnv*, jclass, jint id) {
2509d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  LOG(INFO) << "VMDebug infopoint " << id << " hit";
2519d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
2529d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
25300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersstatic jlong VMDebug_countInstancesOfClass(JNIEnv* env, jclass, jclass javaClass,
25400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers                                           jboolean countAssignable) {
25500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ScopedObjectAccess soa(env);
256412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier  gc::Heap* heap = Runtime::Current()->GetHeap();
25783c8ee000d525017ead8753fce6bc1020249b96aMathieu Chartier  // We only want reachable instances, so do a GC. Heap::VisitObjects visits all of the heap
25883c8ee000d525017ead8753fce6bc1020249b96aMathieu Chartier  // objects in the all spaces and the allocation stack.
259412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier  heap->CollectGarbage(false);
2602dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  mirror::Class* c = soa.Decode<mirror::Class*>(javaClass);
261412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier  if (c == nullptr) {
2629d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    return 0;
2639d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  }
2642dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  std::vector<mirror::Class*> classes;
265ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes  classes.push_back(c);
266ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes  uint64_t count = 0;
267412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier  heap->CountInstances(classes, countAssignable, &count);
268ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes  return count;
2699d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
2709d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
27109b07a96094086e205948717666025909a75163bHiroshi Yamauchi// We export the VM internal per-heap-space size/alloc/free metrics
27209b07a96094086e205948717666025909a75163bHiroshi Yamauchi// for the zygote space, alloc space (application heap), and the large
27309b07a96094086e205948717666025909a75163bHiroshi Yamauchi// object space for dumpsys meminfo. The other memory region data such
27409b07a96094086e205948717666025909a75163bHiroshi Yamauchi// as PSS, private/shared dirty/shared data are available via
27509b07a96094086e205948717666025909a75163bHiroshi Yamauchi// /proc/<pid>/smaps.
27609b07a96094086e205948717666025909a75163bHiroshi Yamauchistatic void VMDebug_getHeapSpaceStats(JNIEnv* env, jclass, jlongArray data) {
2776b99dd10d8a4869bbf7e9263a350185e5ebe32e4Ian Rogers  jlong* arr = reinterpret_cast<jlong*>(env->GetPrimitiveArrayCritical(data, 0));
2787410f29b4dae223befac036ea567d7f33351dad1Mathieu Chartier  if (arr == nullptr || env->GetArrayLength(data) < 9) {
27909b07a96094086e205948717666025909a75163bHiroshi Yamauchi    return;
28009b07a96094086e205948717666025909a75163bHiroshi Yamauchi  }
28109b07a96094086e205948717666025909a75163bHiroshi Yamauchi
28209b07a96094086e205948717666025909a75163bHiroshi Yamauchi  size_t allocSize = 0;
28309b07a96094086e205948717666025909a75163bHiroshi Yamauchi  size_t allocUsed = 0;
28409b07a96094086e205948717666025909a75163bHiroshi Yamauchi  size_t zygoteSize = 0;
28509b07a96094086e205948717666025909a75163bHiroshi Yamauchi  size_t zygoteUsed = 0;
28609b07a96094086e205948717666025909a75163bHiroshi Yamauchi  size_t largeObjectsSize = 0;
28709b07a96094086e205948717666025909a75163bHiroshi Yamauchi  size_t largeObjectsUsed = 0;
28809b07a96094086e205948717666025909a75163bHiroshi Yamauchi  gc::Heap* heap = Runtime::Current()->GetHeap();
2897410f29b4dae223befac036ea567d7f33351dad1Mathieu Chartier  for (gc::space::ContinuousSpace* space : heap->GetContinuousSpaces()) {
29009b07a96094086e205948717666025909a75163bHiroshi Yamauchi    if (space->IsImageSpace()) {
29109b07a96094086e205948717666025909a75163bHiroshi Yamauchi      // Currently don't include the image space.
29209b07a96094086e205948717666025909a75163bHiroshi Yamauchi    } else if (space->IsZygoteSpace()) {
2931f3b5358b28a83f0929bdd8ce738f06908677fb7Mathieu Chartier      gc::space::ZygoteSpace* zygote_space = space->AsZygoteSpace();
2941f3b5358b28a83f0929bdd8ce738f06908677fb7Mathieu Chartier      zygoteSize += zygote_space->Size();
2951f3b5358b28a83f0929bdd8ce738f06908677fb7Mathieu Chartier      zygoteUsed += zygote_space->GetBytesAllocated();
2967410f29b4dae223befac036ea567d7f33351dad1Mathieu Chartier    } else if (space->IsMallocSpace()) {
2977410f29b4dae223befac036ea567d7f33351dad1Mathieu Chartier      // This is a malloc space.
298cf58d4adf461eb9b8e84baa8019054c88cd8acc6Hiroshi Yamauchi      gc::space::MallocSpace* malloc_space = space->AsMallocSpace();
299cf58d4adf461eb9b8e84baa8019054c88cd8acc6Hiroshi Yamauchi      allocSize += malloc_space->GetFootprint();
300cf58d4adf461eb9b8e84baa8019054c88cd8acc6Hiroshi Yamauchi      allocUsed += malloc_space->GetBytesAllocated();
3017410f29b4dae223befac036ea567d7f33351dad1Mathieu Chartier    } else if (space->IsBumpPointerSpace()) {
302692fafd9778141fa6ef0048c9569abd7ee0253bfMathieu Chartier      ScopedObjectAccess soa(env);
3037410f29b4dae223befac036ea567d7f33351dad1Mathieu Chartier      gc::space::BumpPointerSpace* bump_pointer_space = space->AsBumpPointerSpace();
3047410f29b4dae223befac036ea567d7f33351dad1Mathieu Chartier      allocSize += bump_pointer_space->Size();
3057410f29b4dae223befac036ea567d7f33351dad1Mathieu Chartier      allocUsed += bump_pointer_space->GetBytesAllocated();
30609b07a96094086e205948717666025909a75163bHiroshi Yamauchi    }
30709b07a96094086e205948717666025909a75163bHiroshi Yamauchi  }
3087410f29b4dae223befac036ea567d7f33351dad1Mathieu Chartier  for (gc::space::DiscontinuousSpace* space : heap->GetDiscontinuousSpaces()) {
30909b07a96094086e205948717666025909a75163bHiroshi Yamauchi    if (space->IsLargeObjectSpace()) {
31009b07a96094086e205948717666025909a75163bHiroshi Yamauchi      largeObjectsSize += space->AsLargeObjectSpace()->GetBytesAllocated();
31109b07a96094086e205948717666025909a75163bHiroshi Yamauchi      largeObjectsUsed += largeObjectsSize;
31209b07a96094086e205948717666025909a75163bHiroshi Yamauchi    }
31309b07a96094086e205948717666025909a75163bHiroshi Yamauchi  }
31409b07a96094086e205948717666025909a75163bHiroshi Yamauchi
31509b07a96094086e205948717666025909a75163bHiroshi Yamauchi  size_t allocFree = allocSize - allocUsed;
31609b07a96094086e205948717666025909a75163bHiroshi Yamauchi  size_t zygoteFree = zygoteSize - zygoteUsed;
31709b07a96094086e205948717666025909a75163bHiroshi Yamauchi  size_t largeObjectsFree = largeObjectsSize - largeObjectsUsed;
31809b07a96094086e205948717666025909a75163bHiroshi Yamauchi
31909b07a96094086e205948717666025909a75163bHiroshi Yamauchi  int j = 0;
32009b07a96094086e205948717666025909a75163bHiroshi Yamauchi  arr[j++] = allocSize;
32109b07a96094086e205948717666025909a75163bHiroshi Yamauchi  arr[j++] = allocUsed;
32209b07a96094086e205948717666025909a75163bHiroshi Yamauchi  arr[j++] = allocFree;
32309b07a96094086e205948717666025909a75163bHiroshi Yamauchi  arr[j++] = zygoteSize;
32409b07a96094086e205948717666025909a75163bHiroshi Yamauchi  arr[j++] = zygoteUsed;
32509b07a96094086e205948717666025909a75163bHiroshi Yamauchi  arr[j++] = zygoteFree;
32609b07a96094086e205948717666025909a75163bHiroshi Yamauchi  arr[j++] = largeObjectsSize;
32709b07a96094086e205948717666025909a75163bHiroshi Yamauchi  arr[j++] = largeObjectsUsed;
32809b07a96094086e205948717666025909a75163bHiroshi Yamauchi  arr[j++] = largeObjectsFree;
32909b07a96094086e205948717666025909a75163bHiroshi Yamauchi  env->ReleasePrimitiveArrayCritical(data, arr, 0);
33009b07a96094086e205948717666025909a75163bHiroshi Yamauchi}
33109b07a96094086e205948717666025909a75163bHiroshi Yamauchi
3320512f02dd6623c0870c11fbf3274d7462f732136Elliott Hughesstatic JNINativeMethod gMethods[] = {
3339d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  NATIVE_METHOD(VMDebug, countInstancesOfClass, "(Ljava/lang/Class;Z)J"),
3349d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  NATIVE_METHOD(VMDebug, crash, "()V"),
3359d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  NATIVE_METHOD(VMDebug, dumpHprofData, "(Ljava/lang/String;Ljava/io/FileDescriptor;)V"),
3369d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  NATIVE_METHOD(VMDebug, dumpHprofDataDdms, "()V"),
3379d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  NATIVE_METHOD(VMDebug, dumpReferenceTables, "()V"),
3389d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  NATIVE_METHOD(VMDebug, getAllocCount, "(I)I"),
33909b07a96094086e205948717666025909a75163bHiroshi Yamauchi  NATIVE_METHOD(VMDebug, getHeapSpaceStats, "([J)V"),
3409d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  NATIVE_METHOD(VMDebug, getInstructionCount, "([I)V"),
34153b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers  NATIVE_METHOD(VMDebug, getLoadedClassCount, "!()I"),
3429d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  NATIVE_METHOD(VMDebug, getVmFeatureList, "()[Ljava/lang/String;"),
3439d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  NATIVE_METHOD(VMDebug, infopoint, "(I)V"),
34453b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers  NATIVE_METHOD(VMDebug, isDebuggerConnected, "!()Z"),
34553b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers  NATIVE_METHOD(VMDebug, isDebuggingEnabled, "!()Z"),
34664caa7dcf46ed6139b766dbe77fbd7353899417fJeff Hao  NATIVE_METHOD(VMDebug, getMethodTracingMode, "()I"),
34753b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers  NATIVE_METHOD(VMDebug, lastDebuggerActivity, "!()J"),
34853b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers  NATIVE_METHOD(VMDebug, printLoadedClasses, "!(I)V"),
3499d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  NATIVE_METHOD(VMDebug, resetAllocCount, "(I)V"),
3509d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  NATIVE_METHOD(VMDebug, resetInstructionCount, "()V"),
3519d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  NATIVE_METHOD(VMDebug, startAllocCounting, "()V"),
3529d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  NATIVE_METHOD(VMDebug, startEmulatorTracing, "()V"),
3539d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  NATIVE_METHOD(VMDebug, startInstructionCounting, "()V"),
35423009dca63c1699e28bfeaa8b45ca48fa0e86aceJeff Hao  NATIVE_METHOD(VMDebug, startMethodTracingDdmsImpl, "(IIZI)V"),
3554044bdac490777cbc8a12d467bec675ef8aa6eb1Jeff Hao  NATIVE_METHOD(VMDebug, startMethodTracingFd, "(Ljava/lang/String;Ljava/io/FileDescriptor;IIZI)V"),
3564044bdac490777cbc8a12d467bec675ef8aa6eb1Jeff Hao  NATIVE_METHOD(VMDebug, startMethodTracingFilename, "(Ljava/lang/String;IIZI)V"),
3579d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  NATIVE_METHOD(VMDebug, stopAllocCounting, "()V"),
3589d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  NATIVE_METHOD(VMDebug, stopEmulatorTracing, "()V"),
3599d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  NATIVE_METHOD(VMDebug, stopInstructionCounting, "()V"),
3609d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes  NATIVE_METHOD(VMDebug, stopMethodTracing, "()V"),
36153b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers  NATIVE_METHOD(VMDebug, threadCpuTimeNanos, "!()J"),
3629d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes};
3639d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
3649d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughesvoid register_dalvik_system_VMDebug(JNIEnv* env) {
365eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes  REGISTER_NATIVE_METHODS("dalvik/system/VMDebug");
3669d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}
3679d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
3689d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes}  // namespace art
369