blob: 5f4b6d9ebfec405274e184584201c806ac0295c4 [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
32namespace {
33
34/*
35 * Return a set of strings describing available VM features (this is chiefly
36 * of interest to DDMS).
37 */
38jobjectArray VMDebug_getVmFeatureList(JNIEnv* env, jclass) {
39 std::vector<std::string> features;
jeffhaoe343b762011-12-05 16:36:44 -080040 features.push_back("method-trace-profiling");
41 features.push_back("method-trace-profiling-streaming");
Elliott Hughes767a1472011-10-26 18:49:02 -070042 features.push_back("hprof-heap-dump");
43 features.push_back("hprof-heap-dump-streaming");
Elliott Hughes9d5ccec2011-09-19 13:19:50 -070044 return toStringArray(env, features);
45}
46
47void VMDebug_startAllocCounting(JNIEnv*, jclass) {
48 Runtime::Current()->SetStatsEnabled(true);
49}
50
51void VMDebug_stopAllocCounting(JNIEnv*, jclass) {
52 Runtime::Current()->SetStatsEnabled(false);
53}
54
55jint VMDebug_getAllocCount(JNIEnv* env, jclass, jint kind) {
56 return Runtime::Current()->GetStat(kind);
57}
58
59void VMDebug_resetAllocCount(JNIEnv*, jclass, jint kinds) {
60 Runtime::Current()->ResetStats(kinds);
61}
62
63void VMDebug_startMethodTracingDdmsImpl(JNIEnv* env, jclass, jint bufferSize, jint flags) {
jeffhaoe343b762011-12-05 16:36:44 -080064 Trace::Start("[DDMS]", -1, bufferSize, flags, true);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -070065}
66
67void VMDebug_startMethodTracingFd(JNIEnv* env, jclass, jstring javaTraceFilename, jobject javaFd, jint bufferSize, jint flags) {
68 int originalFd = jniGetFDFromFileDescriptor(env, javaFd);
69 if (originalFd < 0) {
70 return;
71 }
72
73 int fd = dup(originalFd);
74 if (fd < 0) {
75 jniThrowExceptionFmt(env, "java/lang/RuntimeException", "dup(%d) failed: %s", originalFd, strerror(errno));
76 return;
77 }
78
79 ScopedUtfChars traceFilename(env, javaTraceFilename);
80 if (traceFilename.c_str() == NULL) {
81 return;
82 }
jeffhaoe343b762011-12-05 16:36:44 -080083 Trace::Start(traceFilename.c_str(), fd, bufferSize, flags, false);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -070084}
85
86void VMDebug_startMethodTracingFilename(JNIEnv* env, jclass, jstring javaTraceFilename, jint bufferSize, jint flags) {
87 ScopedUtfChars traceFilename(env, javaTraceFilename);
88 if (traceFilename.c_str() == NULL) {
89 return;
90 }
jeffhaoe343b762011-12-05 16:36:44 -080091 Trace::Start(traceFilename.c_str(), -1, bufferSize, flags, false);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -070092}
93
94jboolean VMDebug_isMethodTracingActive(JNIEnv*, jclass) {
jeffhao2692b572011-12-16 15:42:28 -080095 return Runtime::Current()->IsMethodTracingActive();
Elliott Hughes9d5ccec2011-09-19 13:19:50 -070096}
97
98void VMDebug_stopMethodTracing(JNIEnv*, jclass) {
jeffhaoe343b762011-12-05 16:36:44 -080099 Trace::Stop();
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700100}
101
102void VMDebug_startEmulatorTracing(JNIEnv*, jclass) {
103 UNIMPLEMENTED(WARNING);
104 //dvmEmulatorTraceStart();
105}
106
107void VMDebug_stopEmulatorTracing(JNIEnv*, jclass) {
108 UNIMPLEMENTED(WARNING);
109 //dvmEmulatorTraceStop();
110}
111
112jboolean VMDebug_isDebuggerConnected(JNIEnv*, jclass) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700113 return Dbg::IsDebuggerConnected();
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700114}
115
116jboolean VMDebug_isDebuggingEnabled(JNIEnv*, jclass) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700117 return Dbg::IsDebuggingEnabled();
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700118}
119
120jlong VMDebug_lastDebuggerActivity(JNIEnv*, jclass) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700121 return Dbg::LastDebuggerActivity();
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700122}
123
124void VMDebug_startInstructionCounting(JNIEnv* env, jclass) {
125 jniThrowException(env, "java/lang/UnsupportedOperationException", NULL);
126}
127
128void VMDebug_stopInstructionCounting(JNIEnv* env, jclass) {
129 jniThrowException(env, "java/lang/UnsupportedOperationException", NULL);
130}
131
132void VMDebug_getInstructionCount(JNIEnv* env, jclass, jintArray javaCounts) {
133 jniThrowException(env, "java/lang/UnsupportedOperationException", NULL);
134}
135
136void VMDebug_resetInstructionCount(JNIEnv* env, jclass) {
137 jniThrowException(env, "java/lang/UnsupportedOperationException", NULL);
138}
139
140void VMDebug_printLoadedClasses(JNIEnv*, jclass, jint flags) {
141 return Runtime::Current()->GetClassLinker()->DumpAllClasses(flags);
142}
143
144jint VMDebug_getLoadedClassCount(JNIEnv*, jclass) {
145 return Runtime::Current()->GetClassLinker()->NumLoadedClasses();
146}
147
148/*
149 * Returns the thread-specific CPU-time clock value for the current thread,
150 * or -1 if the feature isn't supported.
151 */
152jlong VMDebug_threadCpuTimeNanos(JNIEnv*, jclass) {
153#ifdef HAVE_POSIX_CLOCKS
154 struct timespec now;
155 clock_gettime(CLOCK_THREAD_CPUTIME_ID, &now);
156 return static_cast<jlong>(now.tv_sec*1000000000LL + now.tv_nsec);
157#else
158 return -1LL;
159#endif
160}
161
162/*
163 * static void dumpHprofData(String fileName, FileDescriptor fd)
164 *
165 * Cause "hprof" data to be dumped. We can throw an IOException if an
166 * error occurs during file handling.
167 */
168void VMDebug_dumpHprofData(JNIEnv* env, jclass, jstring javaFilename, jobject javaFd) {
169 // Only one of these may be NULL.
170 if (javaFilename == NULL && javaFd == NULL) {
171 jniThrowNullPointerException(env, "fileName == null && fd == null");
172 return;
173 }
174
175 std::string filename;
176 if (javaFilename != NULL) {
177 ScopedUtfChars chars(env, javaFilename);
178 if (env->ExceptionCheck()) {
179 return;
180 }
181 filename = chars.c_str();
182 } else {
183 filename = "[fd]";
184 }
185
186 int fd = -1;
187 if (javaFd != NULL) {
188 fd = jniGetFDFromFileDescriptor(env, javaFd);
189 if (fd < 0) {
190 jniThrowException(env, "Ljava/lang/RuntimeException;", "Invalid file descriptor");
191 return;
192 }
193 }
194
Elliott Hughesfbd84562011-11-07 18:56:13 -0800195 int result = hprof::DumpHeap(filename.c_str(), fd, false);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700196 if (result != 0) {
197 // TODO: ideally we'd throw something more specific based on actual failure
198 jniThrowException(env, "Ljava/lang/RuntimeException;", "Failure during heap dump; check log output for details");
199 return;
200 }
201}
202
203void VMDebug_dumpHprofDataDdms(JNIEnv* env, jclass) {
Elliott Hughesfbd84562011-11-07 18:56:13 -0800204 int result = hprof::DumpHeap("[DDMS]", -1, true);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700205 if (result != 0) {
206 // TODO: ideally we'd throw something more specific based on actual failure
207 jniThrowException(env, "Ljava/lang/RuntimeException;", "Failure during heap dump; check log output for details");
208 return;
209 }
210}
211
212void VMDebug_dumpReferenceTables(JNIEnv* env, jclass) {
213 LOG(INFO) << "--- reference table dump ---";
214
215 JNIEnvExt* e = reinterpret_cast<JNIEnvExt*>(env);
216 e->DumpReferenceTables();
217 e->vm->DumpReferenceTables();
218
219 LOG(INFO) << "---";
220}
221
222/*
223 * Dump the current thread's interpreted stack and abort the VM. Useful
224 * for seeing both interpreted and native stack traces.
225 */
226void VMDebug_crash(JNIEnv*, jclass) {
Elliott Hughes899e7892012-01-24 14:57:32 -0800227 LOG(FATAL) << "Crashing VM on request";
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700228}
229
230/*
231 * Provide a hook for gdb to hang to so that the VM can be stopped when
232 * user-tagged source locations are being executed.
233 */
234void VMDebug_infopoint(JNIEnv*, jclass, jint id) {
235 LOG(INFO) << "VMDebug infopoint " << id << " hit";
236}
237
238jlong VMDebug_countInstancesOfClass(JNIEnv* env, jclass, jclass javaClass, jboolean countAssignable) {
239 Class* c = Decode<Class*>(env, javaClass);
240 if (c == NULL) {
241 return 0;
242 }
243 return Heap::CountInstances(c, countAssignable);
244}
245
246JNINativeMethod gMethods[] = {
247 NATIVE_METHOD(VMDebug, countInstancesOfClass, "(Ljava/lang/Class;Z)J"),
248 NATIVE_METHOD(VMDebug, crash, "()V"),
249 NATIVE_METHOD(VMDebug, dumpHprofData, "(Ljava/lang/String;Ljava/io/FileDescriptor;)V"),
250 NATIVE_METHOD(VMDebug, dumpHprofDataDdms, "()V"),
251 NATIVE_METHOD(VMDebug, dumpReferenceTables, "()V"),
252 NATIVE_METHOD(VMDebug, getAllocCount, "(I)I"),
253 NATIVE_METHOD(VMDebug, getInstructionCount, "([I)V"),
254 NATIVE_METHOD(VMDebug, getLoadedClassCount, "()I"),
255 NATIVE_METHOD(VMDebug, getVmFeatureList, "()[Ljava/lang/String;"),
256 NATIVE_METHOD(VMDebug, infopoint, "(I)V"),
257 NATIVE_METHOD(VMDebug, isDebuggerConnected, "()Z"),
258 NATIVE_METHOD(VMDebug, isDebuggingEnabled, "()Z"),
259 NATIVE_METHOD(VMDebug, isMethodTracingActive, "()Z"),
260 NATIVE_METHOD(VMDebug, lastDebuggerActivity, "()J"),
261 NATIVE_METHOD(VMDebug, printLoadedClasses, "(I)V"),
262 NATIVE_METHOD(VMDebug, resetAllocCount, "(I)V"),
263 NATIVE_METHOD(VMDebug, resetInstructionCount, "()V"),
264 NATIVE_METHOD(VMDebug, startAllocCounting, "()V"),
265 NATIVE_METHOD(VMDebug, startEmulatorTracing, "()V"),
266 NATIVE_METHOD(VMDebug, startInstructionCounting, "()V"),
267 NATIVE_METHOD(VMDebug, startMethodTracingDdmsImpl, "(II)V"),
268 NATIVE_METHOD(VMDebug, startMethodTracingFd, "(Ljava/lang/String;Ljava/io/FileDescriptor;II)V"),
269 NATIVE_METHOD(VMDebug, startMethodTracingFilename, "(Ljava/lang/String;II)V"),
270 NATIVE_METHOD(VMDebug, stopAllocCounting, "()V"),
271 NATIVE_METHOD(VMDebug, stopEmulatorTracing, "()V"),
272 NATIVE_METHOD(VMDebug, stopInstructionCounting, "()V"),
273 NATIVE_METHOD(VMDebug, stopMethodTracing, "()V"),
274 NATIVE_METHOD(VMDebug, threadCpuTimeNanos, "()J"),
275};
276
277} // namespace
278
279void register_dalvik_system_VMDebug(JNIEnv* env) {
280 jniRegisterNativeMethods(env, "dalvik/system/VMDebug", gMethods, NELEM(gMethods));
281}
282
283} // namespace art