blob: f12527287600bfb1684c2210ae4b9a4e7ad3d881 [file] [log] [blame]
Elliott Hughes9d5ccec2011-09-19 13:19:50 -07001/*
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 "class_linker.h"
Elliott Hughes872d4ec2011-10-21 17:07:15 -070018#include "debugger.h"
Elliott Hughes9d5ccec2011-09-19 13:19:50 -070019#include "jni_internal.h"
jeffhaoe343b762011-12-05 16:36:44 -080020#include "trace.h"
Jesse Wilson1121e0b2011-11-07 15:37:42 -050021#include "hprof/hprof.h"
Elliott Hughes9d5ccec2011-09-19 13:19:50 -070022#include "ScopedUtfChars.h"
23#include "toStringArray.h"
24
25#include "JniConstants.h" // Last to avoid problems with LOG redefinition.
26
27#include <string.h>
28#include <unistd.h>
29
30namespace art {
31
Elliott Hughes0512f022012-03-15 22:10:52 -070032static jobjectArray VMDebug_getVmFeatureList(JNIEnv* env, jclass) {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -070033 std::vector<std::string> features;
jeffhaoe343b762011-12-05 16:36:44 -080034 features.push_back("method-trace-profiling");
35 features.push_back("method-trace-profiling-streaming");
Elliott Hughes767a1472011-10-26 18:49:02 -070036 features.push_back("hprof-heap-dump");
37 features.push_back("hprof-heap-dump-streaming");
Elliott Hughes9d5ccec2011-09-19 13:19:50 -070038 return toStringArray(env, features);
39}
40
Elliott Hughes0512f022012-03-15 22:10:52 -070041static void VMDebug_startAllocCounting(JNIEnv*, jclass) {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -070042 Runtime::Current()->SetStatsEnabled(true);
43}
44
Elliott Hughes0512f022012-03-15 22:10:52 -070045static void VMDebug_stopAllocCounting(JNIEnv*, jclass) {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -070046 Runtime::Current()->SetStatsEnabled(false);
47}
48
Elliott Hughes1bac54f2012-03-16 12:48:31 -070049static jint VMDebug_getAllocCount(JNIEnv*, jclass, jint kind) {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -070050 return Runtime::Current()->GetStat(kind);
51}
52
Elliott Hughes0512f022012-03-15 22:10:52 -070053static void VMDebug_resetAllocCount(JNIEnv*, jclass, jint kinds) {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -070054 Runtime::Current()->ResetStats(kinds);
55}
56
Elliott Hughes1bac54f2012-03-16 12:48:31 -070057static void VMDebug_startMethodTracingDdmsImpl(JNIEnv*, jclass, jint bufferSize, jint flags) {
jeffhaoe343b762011-12-05 16:36:44 -080058 Trace::Start("[DDMS]", -1, bufferSize, flags, true);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -070059}
60
Elliott Hughes0512f022012-03-15 22:10:52 -070061static void VMDebug_startMethodTracingFd(JNIEnv* env, jclass, jstring javaTraceFilename, jobject javaFd, jint bufferSize, jint flags) {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -070062 int originalFd = jniGetFDFromFileDescriptor(env, javaFd);
63 if (originalFd < 0) {
64 return;
65 }
66
67 int fd = dup(originalFd);
68 if (fd < 0) {
69 jniThrowExceptionFmt(env, "java/lang/RuntimeException", "dup(%d) failed: %s", originalFd, strerror(errno));
70 return;
71 }
72
73 ScopedUtfChars traceFilename(env, javaTraceFilename);
74 if (traceFilename.c_str() == NULL) {
75 return;
76 }
jeffhaoe343b762011-12-05 16:36:44 -080077 Trace::Start(traceFilename.c_str(), fd, bufferSize, flags, false);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -070078}
79
Elliott Hughes0512f022012-03-15 22:10:52 -070080static void VMDebug_startMethodTracingFilename(JNIEnv* env, jclass, jstring javaTraceFilename, jint bufferSize, jint flags) {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -070081 ScopedUtfChars traceFilename(env, javaTraceFilename);
82 if (traceFilename.c_str() == NULL) {
83 return;
84 }
jeffhaoe343b762011-12-05 16:36:44 -080085 Trace::Start(traceFilename.c_str(), -1, bufferSize, flags, false);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -070086}
87
Elliott Hughes0512f022012-03-15 22:10:52 -070088static jboolean VMDebug_isMethodTracingActive(JNIEnv*, jclass) {
jeffhao2692b572011-12-16 15:42:28 -080089 return Runtime::Current()->IsMethodTracingActive();
Elliott Hughes9d5ccec2011-09-19 13:19:50 -070090}
91
Elliott Hughes0512f022012-03-15 22:10:52 -070092static void VMDebug_stopMethodTracing(JNIEnv*, jclass) {
jeffhaoe343b762011-12-05 16:36:44 -080093 Trace::Stop();
Elliott Hughes9d5ccec2011-09-19 13:19:50 -070094}
95
Elliott Hughes0512f022012-03-15 22:10:52 -070096static void VMDebug_startEmulatorTracing(JNIEnv*, jclass) {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -070097 UNIMPLEMENTED(WARNING);
98 //dvmEmulatorTraceStart();
99}
100
Elliott Hughes0512f022012-03-15 22:10:52 -0700101static void VMDebug_stopEmulatorTracing(JNIEnv*, jclass) {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700102 UNIMPLEMENTED(WARNING);
103 //dvmEmulatorTraceStop();
104}
105
Elliott Hughes0512f022012-03-15 22:10:52 -0700106static jboolean VMDebug_isDebuggerConnected(JNIEnv*, jclass) {
Elliott Hughesc0f09332012-03-26 13:27:06 -0700107 return Dbg::IsDebuggerActive();
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700108}
109
Elliott Hughes0512f022012-03-15 22:10:52 -0700110static jboolean VMDebug_isDebuggingEnabled(JNIEnv*, jclass) {
Elliott Hughesc0f09332012-03-26 13:27:06 -0700111 return Dbg::IsJdwpConfigured();
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700112}
113
Elliott Hughes0512f022012-03-15 22:10:52 -0700114static jlong VMDebug_lastDebuggerActivity(JNIEnv*, jclass) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700115 return Dbg::LastDebuggerActivity();
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700116}
117
Elliott Hughes0512f022012-03-15 22:10:52 -0700118static void VMDebug_startInstructionCounting(JNIEnv* env, jclass) {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700119 jniThrowException(env, "java/lang/UnsupportedOperationException", NULL);
120}
121
Elliott Hughes0512f022012-03-15 22:10:52 -0700122static void VMDebug_stopInstructionCounting(JNIEnv* env, jclass) {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700123 jniThrowException(env, "java/lang/UnsupportedOperationException", NULL);
124}
125
Elliott Hughes1bac54f2012-03-16 12:48:31 -0700126static void VMDebug_getInstructionCount(JNIEnv* env, jclass, jintArray /*javaCounts*/) {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700127 jniThrowException(env, "java/lang/UnsupportedOperationException", NULL);
128}
129
Elliott Hughes0512f022012-03-15 22:10:52 -0700130static void VMDebug_resetInstructionCount(JNIEnv* env, jclass) {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700131 jniThrowException(env, "java/lang/UnsupportedOperationException", NULL);
132}
133
Elliott Hughes0512f022012-03-15 22:10:52 -0700134static void VMDebug_printLoadedClasses(JNIEnv*, jclass, jint flags) {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700135 return Runtime::Current()->GetClassLinker()->DumpAllClasses(flags);
136}
137
Elliott Hughes0512f022012-03-15 22:10:52 -0700138static jint VMDebug_getLoadedClassCount(JNIEnv*, jclass) {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700139 return Runtime::Current()->GetClassLinker()->NumLoadedClasses();
140}
141
142/*
143 * Returns the thread-specific CPU-time clock value for the current thread,
144 * or -1 if the feature isn't supported.
145 */
Elliott Hughes0512f022012-03-15 22:10:52 -0700146static jlong VMDebug_threadCpuTimeNanos(JNIEnv*, jclass) {
147 return ThreadCpuNanoTime();
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700148}
149
150/*
151 * static void dumpHprofData(String fileName, FileDescriptor fd)
152 *
153 * Cause "hprof" data to be dumped. We can throw an IOException if an
154 * error occurs during file handling.
155 */
Elliott Hughes0512f022012-03-15 22:10:52 -0700156static void VMDebug_dumpHprofData(JNIEnv* env, jclass, jstring javaFilename, jobject javaFd) {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700157 // Only one of these may be NULL.
158 if (javaFilename == NULL && javaFd == NULL) {
159 jniThrowNullPointerException(env, "fileName == null && fd == null");
160 return;
161 }
162
163 std::string filename;
164 if (javaFilename != NULL) {
165 ScopedUtfChars chars(env, javaFilename);
166 if (env->ExceptionCheck()) {
167 return;
168 }
169 filename = chars.c_str();
170 } else {
171 filename = "[fd]";
172 }
173
174 int fd = -1;
175 if (javaFd != NULL) {
176 fd = jniGetFDFromFileDescriptor(env, javaFd);
177 if (fd < 0) {
178 jniThrowException(env, "Ljava/lang/RuntimeException;", "Invalid file descriptor");
179 return;
180 }
181 }
182
Elliott Hughesfbd84562011-11-07 18:56:13 -0800183 int result = hprof::DumpHeap(filename.c_str(), fd, false);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700184 if (result != 0) {
185 // TODO: ideally we'd throw something more specific based on actual failure
186 jniThrowException(env, "Ljava/lang/RuntimeException;", "Failure during heap dump; check log output for details");
187 return;
188 }
189}
190
Elliott Hughes0512f022012-03-15 22:10:52 -0700191static void VMDebug_dumpHprofDataDdms(JNIEnv* env, jclass) {
Elliott Hughesfbd84562011-11-07 18:56:13 -0800192 int result = hprof::DumpHeap("[DDMS]", -1, true);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700193 if (result != 0) {
194 // TODO: ideally we'd throw something more specific based on actual failure
195 jniThrowException(env, "Ljava/lang/RuntimeException;", "Failure during heap dump; check log output for details");
196 return;
197 }
198}
199
Elliott Hughes0512f022012-03-15 22:10:52 -0700200static void VMDebug_dumpReferenceTables(JNIEnv* env, jclass) {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700201 LOG(INFO) << "--- reference table dump ---";
202
203 JNIEnvExt* e = reinterpret_cast<JNIEnvExt*>(env);
204 e->DumpReferenceTables();
205 e->vm->DumpReferenceTables();
206
207 LOG(INFO) << "---";
208}
209
Elliott Hughes0512f022012-03-15 22:10:52 -0700210static void VMDebug_crash(JNIEnv*, jclass) {
Elliott Hughes81ff3182012-03-23 20:35:56 -0700211 LOG(FATAL) << "Crashing runtime on request";
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700212}
213
Elliott Hughes0512f022012-03-15 22:10:52 -0700214static void VMDebug_infopoint(JNIEnv*, jclass, jint id) {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700215 LOG(INFO) << "VMDebug infopoint " << id << " hit";
216}
217
Elliott Hughes0512f022012-03-15 22:10:52 -0700218static jlong VMDebug_countInstancesOfClass(JNIEnv* env, jclass, jclass javaClass, jboolean countAssignable) {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700219 Class* c = Decode<Class*>(env, javaClass);
220 if (c == NULL) {
221 return 0;
222 }
Elliott Hughesb3bd5f02012-03-08 21:05:27 -0800223 return Runtime::Current()->GetHeap()->CountInstances(c, countAssignable);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700224}
225
Elliott Hughes0512f022012-03-15 22:10:52 -0700226static JNINativeMethod gMethods[] = {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700227 NATIVE_METHOD(VMDebug, countInstancesOfClass, "(Ljava/lang/Class;Z)J"),
228 NATIVE_METHOD(VMDebug, crash, "()V"),
229 NATIVE_METHOD(VMDebug, dumpHprofData, "(Ljava/lang/String;Ljava/io/FileDescriptor;)V"),
230 NATIVE_METHOD(VMDebug, dumpHprofDataDdms, "()V"),
231 NATIVE_METHOD(VMDebug, dumpReferenceTables, "()V"),
232 NATIVE_METHOD(VMDebug, getAllocCount, "(I)I"),
233 NATIVE_METHOD(VMDebug, getInstructionCount, "([I)V"),
234 NATIVE_METHOD(VMDebug, getLoadedClassCount, "()I"),
235 NATIVE_METHOD(VMDebug, getVmFeatureList, "()[Ljava/lang/String;"),
236 NATIVE_METHOD(VMDebug, infopoint, "(I)V"),
237 NATIVE_METHOD(VMDebug, isDebuggerConnected, "()Z"),
238 NATIVE_METHOD(VMDebug, isDebuggingEnabled, "()Z"),
239 NATIVE_METHOD(VMDebug, isMethodTracingActive, "()Z"),
240 NATIVE_METHOD(VMDebug, lastDebuggerActivity, "()J"),
241 NATIVE_METHOD(VMDebug, printLoadedClasses, "(I)V"),
242 NATIVE_METHOD(VMDebug, resetAllocCount, "(I)V"),
243 NATIVE_METHOD(VMDebug, resetInstructionCount, "()V"),
244 NATIVE_METHOD(VMDebug, startAllocCounting, "()V"),
245 NATIVE_METHOD(VMDebug, startEmulatorTracing, "()V"),
246 NATIVE_METHOD(VMDebug, startInstructionCounting, "()V"),
247 NATIVE_METHOD(VMDebug, startMethodTracingDdmsImpl, "(II)V"),
248 NATIVE_METHOD(VMDebug, startMethodTracingFd, "(Ljava/lang/String;Ljava/io/FileDescriptor;II)V"),
249 NATIVE_METHOD(VMDebug, startMethodTracingFilename, "(Ljava/lang/String;II)V"),
250 NATIVE_METHOD(VMDebug, stopAllocCounting, "()V"),
251 NATIVE_METHOD(VMDebug, stopEmulatorTracing, "()V"),
252 NATIVE_METHOD(VMDebug, stopInstructionCounting, "()V"),
253 NATIVE_METHOD(VMDebug, stopMethodTracing, "()V"),
254 NATIVE_METHOD(VMDebug, threadCpuTimeNanos, "()J"),
255};
256
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700257void register_dalvik_system_VMDebug(JNIEnv* env) {
258 jniRegisterNativeMethods(env, "dalvik/system/VMDebug", gMethods, NELEM(gMethods));
259}
260
261} // namespace art