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