blob: d5d091767cc3bb08ed36fed215af0c8b27ef481f [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"
20#include "ScopedUtfChars.h"
21#include "toStringArray.h"
22
23#include "JniConstants.h" // Last to avoid problems with LOG redefinition.
24
25#include <string.h>
26#include <unistd.h>
27
28namespace art {
29
30namespace {
31
32/*
33 * Return a set of strings describing available VM features (this is chiefly
34 * of interest to DDMS).
35 */
36jobjectArray VMDebug_getVmFeatureList(JNIEnv* env, jclass) {
37 std::vector<std::string> features;
Elliott Hughesf6a1e1e2011-10-25 16:28:04 -070038 // TODO: we might need to uncomment these to make them work.
Elliott Hughes9d5ccec2011-09-19 13:19:50 -070039 //features.push_back("method-trace-profiling");
40 //features.push_back("method-trace-profiling-streaming");
41 //features.push_back("hprof-heap-dump");
42 //features.push_back("hprof-heap-dump-streaming");
43 return toStringArray(env, features);
44}
45
46void VMDebug_startAllocCounting(JNIEnv*, jclass) {
47 Runtime::Current()->SetStatsEnabled(true);
48}
49
50void VMDebug_stopAllocCounting(JNIEnv*, jclass) {
51 Runtime::Current()->SetStatsEnabled(false);
52}
53
54jint VMDebug_getAllocCount(JNIEnv* env, jclass, jint kind) {
55 return Runtime::Current()->GetStat(kind);
56}
57
58void VMDebug_resetAllocCount(JNIEnv*, jclass, jint kinds) {
59 Runtime::Current()->ResetStats(kinds);
60}
61
62void VMDebug_startMethodTracingDdmsImpl(JNIEnv* env, jclass, jint bufferSize, jint flags) {
63 UNIMPLEMENTED(WARNING);
64 //dvmMethodTraceStart("[DDMS]", -1, bufferSize, flags, true);
65}
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 }
83 UNIMPLEMENTED(WARNING);
84 //dvmMethodTraceStart(traceFilename.c_str(), fd, bufferSize, flags, false);
85}
86
87void VMDebug_startMethodTracingFilename(JNIEnv* env, jclass, jstring javaTraceFilename, jint bufferSize, jint flags) {
88 ScopedUtfChars traceFilename(env, javaTraceFilename);
89 if (traceFilename.c_str() == NULL) {
90 return;
91 }
92 UNIMPLEMENTED(WARNING);
93 //dvmMethodTraceStart(traceFilename.c_str(), -1, bufferSize, flags, false);
94}
95
96jboolean VMDebug_isMethodTracingActive(JNIEnv*, jclass) {
97 UNIMPLEMENTED(WARNING);
98 return JNI_FALSE; //dvmIsMethodTraceActive();
99}
100
101void VMDebug_stopMethodTracing(JNIEnv*, jclass) {
102 UNIMPLEMENTED(WARNING);
103 //dvmMethodTraceStop();
104}
105
106void VMDebug_startEmulatorTracing(JNIEnv*, jclass) {
107 UNIMPLEMENTED(WARNING);
108 //dvmEmulatorTraceStart();
109}
110
111void VMDebug_stopEmulatorTracing(JNIEnv*, jclass) {
112 UNIMPLEMENTED(WARNING);
113 //dvmEmulatorTraceStop();
114}
115
116jboolean VMDebug_isDebuggerConnected(JNIEnv*, jclass) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700117 return Dbg::IsDebuggerConnected();
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700118}
119
120jboolean VMDebug_isDebuggingEnabled(JNIEnv*, jclass) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700121 return Dbg::IsDebuggingEnabled();
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700122}
123
124jlong VMDebug_lastDebuggerActivity(JNIEnv*, jclass) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700125 return Dbg::LastDebuggerActivity();
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700126}
127
128void VMDebug_startInstructionCounting(JNIEnv* env, jclass) {
129 jniThrowException(env, "java/lang/UnsupportedOperationException", NULL);
130}
131
132void VMDebug_stopInstructionCounting(JNIEnv* env, jclass) {
133 jniThrowException(env, "java/lang/UnsupportedOperationException", NULL);
134}
135
136void VMDebug_getInstructionCount(JNIEnv* env, jclass, jintArray javaCounts) {
137 jniThrowException(env, "java/lang/UnsupportedOperationException", NULL);
138}
139
140void VMDebug_resetInstructionCount(JNIEnv* env, jclass) {
141 jniThrowException(env, "java/lang/UnsupportedOperationException", NULL);
142}
143
144void VMDebug_printLoadedClasses(JNIEnv*, jclass, jint flags) {
145 return Runtime::Current()->GetClassLinker()->DumpAllClasses(flags);
146}
147
148jint VMDebug_getLoadedClassCount(JNIEnv*, jclass) {
149 return Runtime::Current()->GetClassLinker()->NumLoadedClasses();
150}
151
152/*
153 * Returns the thread-specific CPU-time clock value for the current thread,
154 * or -1 if the feature isn't supported.
155 */
156jlong VMDebug_threadCpuTimeNanos(JNIEnv*, jclass) {
157#ifdef HAVE_POSIX_CLOCKS
158 struct timespec now;
159 clock_gettime(CLOCK_THREAD_CPUTIME_ID, &now);
160 return static_cast<jlong>(now.tv_sec*1000000000LL + now.tv_nsec);
161#else
162 return -1LL;
163#endif
164}
165
166/*
167 * static void dumpHprofData(String fileName, FileDescriptor fd)
168 *
169 * Cause "hprof" data to be dumped. We can throw an IOException if an
170 * error occurs during file handling.
171 */
172void VMDebug_dumpHprofData(JNIEnv* env, jclass, jstring javaFilename, jobject javaFd) {
173 // Only one of these may be NULL.
174 if (javaFilename == NULL && javaFd == NULL) {
175 jniThrowNullPointerException(env, "fileName == null && fd == null");
176 return;
177 }
178
179 std::string filename;
180 if (javaFilename != NULL) {
181 ScopedUtfChars chars(env, javaFilename);
182 if (env->ExceptionCheck()) {
183 return;
184 }
185 filename = chars.c_str();
186 } else {
187 filename = "[fd]";
188 }
189
190 int fd = -1;
191 if (javaFd != NULL) {
192 fd = jniGetFDFromFileDescriptor(env, javaFd);
193 if (fd < 0) {
194 jniThrowException(env, "Ljava/lang/RuntimeException;", "Invalid file descriptor");
195 return;
196 }
197 }
198
199 UNIMPLEMENTED(WARNING);
200 int result = 0; //hprofDumpHeap(filename.c_str(), fd, false);
201 if (result != 0) {
202 // TODO: ideally we'd throw something more specific based on actual failure
203 jniThrowException(env, "Ljava/lang/RuntimeException;", "Failure during heap dump; check log output for details");
204 return;
205 }
206}
207
208void VMDebug_dumpHprofDataDdms(JNIEnv* env, jclass) {
209 UNIMPLEMENTED(WARNING);
210 int result = 0; //hprofDumpHeap("[DDMS]", -1, true);
211 if (result != 0) {
212 // TODO: ideally we'd throw something more specific based on actual failure
213 jniThrowException(env, "Ljava/lang/RuntimeException;", "Failure during heap dump; check log output for details");
214 return;
215 }
216}
217
218void VMDebug_dumpReferenceTables(JNIEnv* env, jclass) {
219 LOG(INFO) << "--- reference table dump ---";
220
221 JNIEnvExt* e = reinterpret_cast<JNIEnvExt*>(env);
222 e->DumpReferenceTables();
223 e->vm->DumpReferenceTables();
224
225 LOG(INFO) << "---";
226}
227
228/*
229 * Dump the current thread's interpreted stack and abort the VM. Useful
230 * for seeing both interpreted and native stack traces.
231 */
232void VMDebug_crash(JNIEnv*, jclass) {
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700233 std::ostringstream os;
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700234 os << "Crashing VM on request:\n";
235 Thread::Current()->Dump(os);
236 LOG(FATAL) << os.str();
237}
238
239/*
240 * Provide a hook for gdb to hang to so that the VM can be stopped when
241 * user-tagged source locations are being executed.
242 */
243void VMDebug_infopoint(JNIEnv*, jclass, jint id) {
244 LOG(INFO) << "VMDebug infopoint " << id << " hit";
245}
246
247jlong VMDebug_countInstancesOfClass(JNIEnv* env, jclass, jclass javaClass, jboolean countAssignable) {
248 Class* c = Decode<Class*>(env, javaClass);
249 if (c == NULL) {
250 return 0;
251 }
252 return Heap::CountInstances(c, countAssignable);
253}
254
255JNINativeMethod gMethods[] = {
256 NATIVE_METHOD(VMDebug, countInstancesOfClass, "(Ljava/lang/Class;Z)J"),
257 NATIVE_METHOD(VMDebug, crash, "()V"),
258 NATIVE_METHOD(VMDebug, dumpHprofData, "(Ljava/lang/String;Ljava/io/FileDescriptor;)V"),
259 NATIVE_METHOD(VMDebug, dumpHprofDataDdms, "()V"),
260 NATIVE_METHOD(VMDebug, dumpReferenceTables, "()V"),
261 NATIVE_METHOD(VMDebug, getAllocCount, "(I)I"),
262 NATIVE_METHOD(VMDebug, getInstructionCount, "([I)V"),
263 NATIVE_METHOD(VMDebug, getLoadedClassCount, "()I"),
264 NATIVE_METHOD(VMDebug, getVmFeatureList, "()[Ljava/lang/String;"),
265 NATIVE_METHOD(VMDebug, infopoint, "(I)V"),
266 NATIVE_METHOD(VMDebug, isDebuggerConnected, "()Z"),
267 NATIVE_METHOD(VMDebug, isDebuggingEnabled, "()Z"),
268 NATIVE_METHOD(VMDebug, isMethodTracingActive, "()Z"),
269 NATIVE_METHOD(VMDebug, lastDebuggerActivity, "()J"),
270 NATIVE_METHOD(VMDebug, printLoadedClasses, "(I)V"),
271 NATIVE_METHOD(VMDebug, resetAllocCount, "(I)V"),
272 NATIVE_METHOD(VMDebug, resetInstructionCount, "()V"),
273 NATIVE_METHOD(VMDebug, startAllocCounting, "()V"),
274 NATIVE_METHOD(VMDebug, startEmulatorTracing, "()V"),
275 NATIVE_METHOD(VMDebug, startInstructionCounting, "()V"),
276 NATIVE_METHOD(VMDebug, startMethodTracingDdmsImpl, "(II)V"),
277 NATIVE_METHOD(VMDebug, startMethodTracingFd, "(Ljava/lang/String;Ljava/io/FileDescriptor;II)V"),
278 NATIVE_METHOD(VMDebug, startMethodTracingFilename, "(Ljava/lang/String;II)V"),
279 NATIVE_METHOD(VMDebug, stopAllocCounting, "()V"),
280 NATIVE_METHOD(VMDebug, stopEmulatorTracing, "()V"),
281 NATIVE_METHOD(VMDebug, stopInstructionCounting, "()V"),
282 NATIVE_METHOD(VMDebug, stopMethodTracing, "()V"),
283 NATIVE_METHOD(VMDebug, threadCpuTimeNanos, "()J"),
284};
285
286} // namespace
287
288void register_dalvik_system_VMDebug(JNIEnv* env) {
289 jniRegisterNativeMethods(env, "dalvik/system/VMDebug", gMethods, NELEM(gMethods));
290}
291
292} // namespace art