1 /*
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 "dalvik_system_VMDebug.h"
18
19 #include <string.h>
20 #include <unistd.h>
21
22 #include <sstream>
23
24 #include "base/histogram-inl.h"
25 #include "base/time_utils.h"
26 #include "class_linker.h"
27 #include "common_throws.h"
28 #include "debugger.h"
29 #include "gc/space/bump_pointer_space.h"
30 #include "gc/space/dlmalloc_space.h"
31 #include "gc/space/large_object_space.h"
32 #include "gc/space/space-inl.h"
33 #include "gc/space/zygote_space.h"
34 #include "handle_scope-inl.h"
35 #include "hprof/hprof.h"
36 #include "java_vm_ext.h"
37 #include "jni_internal.h"
38 #include "mirror/class.h"
39 #include "mirror/object_array-inl.h"
40 #include "ScopedLocalRef.h"
41 #include "ScopedUtfChars.h"
42 #include "scoped_fast_native_object_access-inl.h"
43 #include "trace.h"
44 #include "well_known_classes.h"
45
46 namespace art {
47
VMDebug_getVmFeatureList(JNIEnv * env,jclass)48 static jobjectArray VMDebug_getVmFeatureList(JNIEnv* env, jclass) {
49 static const char* features[] = {
50 "method-trace-profiling",
51 "method-trace-profiling-streaming",
52 "method-sample-profiling",
53 "hprof-heap-dump",
54 "hprof-heap-dump-streaming",
55 };
56 jobjectArray result = env->NewObjectArray(arraysize(features),
57 WellKnownClasses::java_lang_String,
58 nullptr);
59 if (result != nullptr) {
60 for (size_t i = 0; i < arraysize(features); ++i) {
61 ScopedLocalRef<jstring> jfeature(env, env->NewStringUTF(features[i]));
62 if (jfeature.get() == nullptr) {
63 return nullptr;
64 }
65 env->SetObjectArrayElement(result, i, jfeature.get());
66 }
67 }
68 return result;
69 }
70
VMDebug_startAllocCounting(JNIEnv *,jclass)71 static void VMDebug_startAllocCounting(JNIEnv*, jclass) {
72 Runtime::Current()->SetStatsEnabled(true);
73 }
74
VMDebug_stopAllocCounting(JNIEnv *,jclass)75 static void VMDebug_stopAllocCounting(JNIEnv*, jclass) {
76 Runtime::Current()->SetStatsEnabled(false);
77 }
78
VMDebug_getAllocCount(JNIEnv *,jclass,jint kind)79 static jint VMDebug_getAllocCount(JNIEnv*, jclass, jint kind) {
80 return Runtime::Current()->GetStat(kind);
81 }
82
VMDebug_resetAllocCount(JNIEnv *,jclass,jint kinds)83 static void VMDebug_resetAllocCount(JNIEnv*, jclass, jint kinds) {
84 Runtime::Current()->ResetStats(kinds);
85 }
86
VMDebug_startMethodTracingDdmsImpl(JNIEnv *,jclass,jint bufferSize,jint flags,jboolean samplingEnabled,jint intervalUs)87 static void VMDebug_startMethodTracingDdmsImpl(JNIEnv*, jclass, jint bufferSize, jint flags,
88 jboolean samplingEnabled, jint intervalUs) {
89 Trace::Start("[DDMS]", -1, bufferSize, flags, Trace::TraceOutputMode::kDDMS,
90 samplingEnabled ? Trace::TraceMode::kSampling : Trace::TraceMode::kMethodTracing,
91 intervalUs);
92 }
93
VMDebug_startMethodTracingFd(JNIEnv * env,jclass,jstring javaTraceFilename,jobject javaFd,jint bufferSize,jint flags,jboolean samplingEnabled,jint intervalUs,jboolean streamingOutput)94 static void VMDebug_startMethodTracingFd(JNIEnv* env, jclass, jstring javaTraceFilename,
95 jobject javaFd, jint bufferSize, jint flags,
96 jboolean samplingEnabled, jint intervalUs,
97 jboolean streamingOutput) {
98 int originalFd = jniGetFDFromFileDescriptor(env, javaFd);
99 if (originalFd < 0) {
100 return;
101 }
102
103 int fd = dup(originalFd);
104 if (fd < 0) {
105 ScopedObjectAccess soa(env);
106 soa.Self()->ThrowNewExceptionF("Ljava/lang/RuntimeException;",
107 "dup(%d) failed: %s", originalFd, strerror(errno));
108 return;
109 }
110
111 ScopedUtfChars traceFilename(env, javaTraceFilename);
112 if (traceFilename.c_str() == nullptr) {
113 return;
114 }
115 Trace::TraceOutputMode outputMode = streamingOutput
116 ? Trace::TraceOutputMode::kStreaming
117 : Trace::TraceOutputMode::kFile;
118 Trace::Start(traceFilename.c_str(), fd, bufferSize, flags, outputMode,
119 samplingEnabled ? Trace::TraceMode::kSampling : Trace::TraceMode::kMethodTracing,
120 intervalUs);
121 }
122
VMDebug_startMethodTracingFilename(JNIEnv * env,jclass,jstring javaTraceFilename,jint bufferSize,jint flags,jboolean samplingEnabled,jint intervalUs)123 static void VMDebug_startMethodTracingFilename(JNIEnv* env, jclass, jstring javaTraceFilename,
124 jint bufferSize, jint flags,
125 jboolean samplingEnabled, jint intervalUs) {
126 ScopedUtfChars traceFilename(env, javaTraceFilename);
127 if (traceFilename.c_str() == nullptr) {
128 return;
129 }
130 Trace::Start(traceFilename.c_str(), -1, bufferSize, flags, Trace::TraceOutputMode::kFile,
131 samplingEnabled ? Trace::TraceMode::kSampling : Trace::TraceMode::kMethodTracing,
132 intervalUs);
133 }
134
VMDebug_getMethodTracingMode(JNIEnv *,jclass)135 static jint VMDebug_getMethodTracingMode(JNIEnv*, jclass) {
136 return Trace::GetMethodTracingMode();
137 }
138
VMDebug_stopMethodTracing(JNIEnv *,jclass)139 static void VMDebug_stopMethodTracing(JNIEnv*, jclass) {
140 Trace::Stop();
141 }
142
VMDebug_startEmulatorTracing(JNIEnv *,jclass)143 static void VMDebug_startEmulatorTracing(JNIEnv*, jclass) {
144 UNIMPLEMENTED(WARNING);
145 // dvmEmulatorTraceStart();
146 }
147
VMDebug_stopEmulatorTracing(JNIEnv *,jclass)148 static void VMDebug_stopEmulatorTracing(JNIEnv*, jclass) {
149 UNIMPLEMENTED(WARNING);
150 // dvmEmulatorTraceStop();
151 }
152
VMDebug_isDebuggerConnected(JNIEnv *,jclass)153 static jboolean VMDebug_isDebuggerConnected(JNIEnv*, jclass) {
154 return Dbg::IsDebuggerActive();
155 }
156
VMDebug_isDebuggingEnabled(JNIEnv *,jclass)157 static jboolean VMDebug_isDebuggingEnabled(JNIEnv*, jclass) {
158 return Dbg::IsJdwpConfigured();
159 }
160
VMDebug_lastDebuggerActivity(JNIEnv *,jclass)161 static jlong VMDebug_lastDebuggerActivity(JNIEnv*, jclass) {
162 return Dbg::LastDebuggerActivity();
163 }
164
ThrowUnsupportedOperationException(JNIEnv * env)165 static void ThrowUnsupportedOperationException(JNIEnv* env) {
166 ScopedObjectAccess soa(env);
167 soa.Self()->ThrowNewException("Ljava/lang/UnsupportedOperationException;", nullptr);
168 }
169
VMDebug_startInstructionCounting(JNIEnv * env,jclass)170 static void VMDebug_startInstructionCounting(JNIEnv* env, jclass) {
171 ThrowUnsupportedOperationException(env);
172 }
173
VMDebug_stopInstructionCounting(JNIEnv * env,jclass)174 static void VMDebug_stopInstructionCounting(JNIEnv* env, jclass) {
175 ThrowUnsupportedOperationException(env);
176 }
177
VMDebug_getInstructionCount(JNIEnv * env,jclass,jintArray)178 static void VMDebug_getInstructionCount(JNIEnv* env, jclass, jintArray /*javaCounts*/) {
179 ThrowUnsupportedOperationException(env);
180 }
181
VMDebug_resetInstructionCount(JNIEnv * env,jclass)182 static void VMDebug_resetInstructionCount(JNIEnv* env, jclass) {
183 ThrowUnsupportedOperationException(env);
184 }
185
VMDebug_printLoadedClasses(JNIEnv * env,jclass,jint flags)186 static void VMDebug_printLoadedClasses(JNIEnv* env, jclass, jint flags) {
187 class DumpClassVisitor : public ClassVisitor {
188 public:
189 explicit DumpClassVisitor(int dump_flags) : flags_(dump_flags) {}
190
191 bool operator()(ObjPtr<mirror::Class> klass) OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
192 klass->DumpClass(LOG_STREAM(ERROR), flags_);
193 return true;
194 }
195
196 private:
197 const int flags_;
198 };
199 DumpClassVisitor visitor(flags);
200
201 ScopedFastNativeObjectAccess soa(env);
202 return Runtime::Current()->GetClassLinker()->VisitClasses(&visitor);
203 }
204
VMDebug_getLoadedClassCount(JNIEnv * env,jclass)205 static jint VMDebug_getLoadedClassCount(JNIEnv* env, jclass) {
206 ScopedFastNativeObjectAccess soa(env);
207 return Runtime::Current()->GetClassLinker()->NumLoadedClasses();
208 }
209
210 /*
211 * Returns the thread-specific CPU-time clock value for the current thread,
212 * or -1 if the feature isn't supported.
213 */
VMDebug_threadCpuTimeNanos(JNIEnv *,jclass)214 static jlong VMDebug_threadCpuTimeNanos(JNIEnv*, jclass) {
215 return ThreadCpuNanoTime();
216 }
217
218 /*
219 * static void dumpHprofData(String fileName, FileDescriptor fd)
220 *
221 * Cause "hprof" data to be dumped. We can throw an IOException if an
222 * error occurs during file handling.
223 */
VMDebug_dumpHprofData(JNIEnv * env,jclass,jstring javaFilename,jobject javaFd)224 static void VMDebug_dumpHprofData(JNIEnv* env, jclass, jstring javaFilename, jobject javaFd) {
225 // Only one of these may be null.
226 if (javaFilename == nullptr && javaFd == nullptr) {
227 ScopedObjectAccess soa(env);
228 ThrowNullPointerException("fileName == null && fd == null");
229 return;
230 }
231
232 std::string filename;
233 if (javaFilename != nullptr) {
234 ScopedUtfChars chars(env, javaFilename);
235 if (env->ExceptionCheck()) {
236 return;
237 }
238 filename = chars.c_str();
239 } else {
240 filename = "[fd]";
241 }
242
243 int fd = -1;
244 if (javaFd != nullptr) {
245 fd = jniGetFDFromFileDescriptor(env, javaFd);
246 if (fd < 0) {
247 ScopedObjectAccess soa(env);
248 ThrowRuntimeException("Invalid file descriptor");
249 return;
250 }
251 }
252
253 hprof::DumpHeap(filename.c_str(), fd, false);
254 }
255
VMDebug_dumpHprofDataDdms(JNIEnv *,jclass)256 static void VMDebug_dumpHprofDataDdms(JNIEnv*, jclass) {
257 hprof::DumpHeap("[DDMS]", -1, true);
258 }
259
VMDebug_dumpReferenceTables(JNIEnv * env,jclass)260 static void VMDebug_dumpReferenceTables(JNIEnv* env, jclass) {
261 ScopedObjectAccess soa(env);
262 LOG(INFO) << "--- reference table dump ---";
263
264 soa.Env()->DumpReferenceTables(LOG_STREAM(INFO));
265 soa.Vm()->DumpReferenceTables(LOG_STREAM(INFO));
266
267 LOG(INFO) << "---";
268 }
269
VMDebug_crash(JNIEnv *,jclass)270 static void VMDebug_crash(JNIEnv*, jclass) {
271 LOG(FATAL) << "Crashing runtime on request";
272 }
273
VMDebug_infopoint(JNIEnv *,jclass,jint id)274 static void VMDebug_infopoint(JNIEnv*, jclass, jint id) {
275 LOG(INFO) << "VMDebug infopoint " << id << " hit";
276 }
277
VMDebug_countInstancesOfClass(JNIEnv * env,jclass,jclass javaClass,jboolean countAssignable)278 static jlong VMDebug_countInstancesOfClass(JNIEnv* env,
279 jclass,
280 jclass javaClass,
281 jboolean countAssignable) {
282 ScopedObjectAccess soa(env);
283 gc::Heap* const heap = Runtime::Current()->GetHeap();
284 // Caller's responsibility to do GC if desired.
285 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(javaClass);
286 if (c == nullptr) {
287 return 0;
288 }
289 VariableSizedHandleScope hs(soa.Self());
290 std::vector<Handle<mirror::Class>> classes {hs.NewHandle(c)};
291 uint64_t count = 0;
292 heap->CountInstances(classes, countAssignable, &count);
293 return count;
294 }
295
VMDebug_countInstancesOfClasses(JNIEnv * env,jclass,jobjectArray javaClasses,jboolean countAssignable)296 static jlongArray VMDebug_countInstancesOfClasses(JNIEnv* env,
297 jclass,
298 jobjectArray javaClasses,
299 jboolean countAssignable) {
300 ScopedObjectAccess soa(env);
301 gc::Heap* const heap = Runtime::Current()->GetHeap();
302 // Caller's responsibility to do GC if desired.
303 ObjPtr<mirror::ObjectArray<mirror::Class>> decoded_classes =
304 soa.Decode<mirror::ObjectArray<mirror::Class>>(javaClasses);
305 if (decoded_classes == nullptr) {
306 return nullptr;
307 }
308 VariableSizedHandleScope hs(soa.Self());
309 std::vector<Handle<mirror::Class>> classes;
310 for (size_t i = 0, count = decoded_classes->GetLength(); i < count; ++i) {
311 classes.push_back(hs.NewHandle(decoded_classes->Get(i)));
312 }
313 std::vector<uint64_t> counts(classes.size(), 0u);
314 // Heap::CountInstances can handle null and will put 0 for these classes.
315 heap->CountInstances(classes, countAssignable, &counts[0]);
316 ObjPtr<mirror::LongArray> long_counts = mirror::LongArray::Alloc(soa.Self(), counts.size());
317 if (long_counts == nullptr) {
318 soa.Self()->AssertPendingOOMException();
319 return nullptr;
320 }
321 for (size_t i = 0; i < counts.size(); ++i) {
322 long_counts->Set(i, counts[i]);
323 }
324 return soa.AddLocalReference<jlongArray>(long_counts);
325 }
326
327 // We export the VM internal per-heap-space size/alloc/free metrics
328 // for the zygote space, alloc space (application heap), and the large
329 // object space for dumpsys meminfo. The other memory region data such
330 // as PSS, private/shared dirty/shared data are available via
331 // /proc/<pid>/smaps.
VMDebug_getHeapSpaceStats(JNIEnv * env,jclass,jlongArray data)332 static void VMDebug_getHeapSpaceStats(JNIEnv* env, jclass, jlongArray data) {
333 jlong* arr = reinterpret_cast<jlong*>(env->GetPrimitiveArrayCritical(data, 0));
334 if (arr == nullptr || env->GetArrayLength(data) < 9) {
335 return;
336 }
337
338 size_t allocSize = 0;
339 size_t allocUsed = 0;
340 size_t zygoteSize = 0;
341 size_t zygoteUsed = 0;
342 size_t largeObjectsSize = 0;
343 size_t largeObjectsUsed = 0;
344 gc::Heap* heap = Runtime::Current()->GetHeap();
345 {
346 ScopedObjectAccess soa(env);
347 for (gc::space::ContinuousSpace* space : heap->GetContinuousSpaces()) {
348 if (space->IsImageSpace()) {
349 // Currently don't include the image space.
350 } else if (space->IsZygoteSpace()) {
351 gc::space::ZygoteSpace* zygote_space = space->AsZygoteSpace();
352 zygoteSize += zygote_space->Size();
353 zygoteUsed += zygote_space->GetBytesAllocated();
354 } else if (space->IsMallocSpace()) {
355 // This is a malloc space.
356 gc::space::MallocSpace* malloc_space = space->AsMallocSpace();
357 allocSize += malloc_space->GetFootprint();
358 allocUsed += malloc_space->GetBytesAllocated();
359 } else if (space->IsBumpPointerSpace()) {
360 gc::space::BumpPointerSpace* bump_pointer_space = space->AsBumpPointerSpace();
361 allocSize += bump_pointer_space->Size();
362 allocUsed += bump_pointer_space->GetBytesAllocated();
363 }
364 }
365 for (gc::space::DiscontinuousSpace* space : heap->GetDiscontinuousSpaces()) {
366 if (space->IsLargeObjectSpace()) {
367 largeObjectsSize += space->AsLargeObjectSpace()->GetBytesAllocated();
368 largeObjectsUsed += largeObjectsSize;
369 }
370 }
371 }
372 size_t allocFree = allocSize - allocUsed;
373 size_t zygoteFree = zygoteSize - zygoteUsed;
374 size_t largeObjectsFree = largeObjectsSize - largeObjectsUsed;
375
376 int j = 0;
377 arr[j++] = allocSize;
378 arr[j++] = allocUsed;
379 arr[j++] = allocFree;
380 arr[j++] = zygoteSize;
381 arr[j++] = zygoteUsed;
382 arr[j++] = zygoteFree;
383 arr[j++] = largeObjectsSize;
384 arr[j++] = largeObjectsUsed;
385 arr[j++] = largeObjectsFree;
386 env->ReleasePrimitiveArrayCritical(data, arr, 0);
387 }
388
389 // The runtime stat names for VMDebug.getRuntimeStat().
390 enum class VMDebugRuntimeStatId {
391 kArtGcGcCount = 0,
392 kArtGcGcTime,
393 kArtGcBytesAllocated,
394 kArtGcBytesFreed,
395 kArtGcBlockingGcCount,
396 kArtGcBlockingGcTime,
397 kArtGcGcCountRateHistogram,
398 kArtGcBlockingGcCountRateHistogram,
399 kNumRuntimeStats,
400 };
401
VMDebug_getRuntimeStatInternal(JNIEnv * env,jclass,jint statId)402 static jobject VMDebug_getRuntimeStatInternal(JNIEnv* env, jclass, jint statId) {
403 gc::Heap* heap = Runtime::Current()->GetHeap();
404 switch (static_cast<VMDebugRuntimeStatId>(statId)) {
405 case VMDebugRuntimeStatId::kArtGcGcCount: {
406 std::string output = std::to_string(heap->GetGcCount());
407 return env->NewStringUTF(output.c_str());
408 }
409 case VMDebugRuntimeStatId::kArtGcGcTime: {
410 std::string output = std::to_string(NsToMs(heap->GetGcTime()));
411 return env->NewStringUTF(output.c_str());
412 }
413 case VMDebugRuntimeStatId::kArtGcBytesAllocated: {
414 std::string output = std::to_string(heap->GetBytesAllocatedEver());
415 return env->NewStringUTF(output.c_str());
416 }
417 case VMDebugRuntimeStatId::kArtGcBytesFreed: {
418 std::string output = std::to_string(heap->GetBytesFreedEver());
419 return env->NewStringUTF(output.c_str());
420 }
421 case VMDebugRuntimeStatId::kArtGcBlockingGcCount: {
422 std::string output = std::to_string(heap->GetBlockingGcCount());
423 return env->NewStringUTF(output.c_str());
424 }
425 case VMDebugRuntimeStatId::kArtGcBlockingGcTime: {
426 std::string output = std::to_string(NsToMs(heap->GetBlockingGcTime()));
427 return env->NewStringUTF(output.c_str());
428 }
429 case VMDebugRuntimeStatId::kArtGcGcCountRateHistogram: {
430 std::ostringstream output;
431 heap->DumpGcCountRateHistogram(output);
432 return env->NewStringUTF(output.str().c_str());
433 }
434 case VMDebugRuntimeStatId::kArtGcBlockingGcCountRateHistogram: {
435 std::ostringstream output;
436 heap->DumpBlockingGcCountRateHistogram(output);
437 return env->NewStringUTF(output.str().c_str());
438 }
439 default:
440 return nullptr;
441 }
442 }
443
SetRuntimeStatValue(JNIEnv * env,jobjectArray result,VMDebugRuntimeStatId id,const std::string & value)444 static bool SetRuntimeStatValue(JNIEnv* env,
445 jobjectArray result,
446 VMDebugRuntimeStatId id,
447 const std::string& value) {
448 ScopedLocalRef<jstring> jvalue(env, env->NewStringUTF(value.c_str()));
449 if (jvalue.get() == nullptr) {
450 return false;
451 }
452 env->SetObjectArrayElement(result, static_cast<jint>(id), jvalue.get());
453 return true;
454 }
455
VMDebug_getRuntimeStatsInternal(JNIEnv * env,jclass)456 static jobjectArray VMDebug_getRuntimeStatsInternal(JNIEnv* env, jclass) {
457 jobjectArray result = env->NewObjectArray(
458 static_cast<jint>(VMDebugRuntimeStatId::kNumRuntimeStats),
459 WellKnownClasses::java_lang_String,
460 nullptr);
461 if (result == nullptr) {
462 return nullptr;
463 }
464 gc::Heap* heap = Runtime::Current()->GetHeap();
465 if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcGcCount,
466 std::to_string(heap->GetGcCount()))) {
467 return nullptr;
468 }
469 if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcGcTime,
470 std::to_string(NsToMs(heap->GetGcTime())))) {
471 return nullptr;
472 }
473 if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcBytesAllocated,
474 std::to_string(heap->GetBytesAllocatedEver()))) {
475 return nullptr;
476 }
477 if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcBytesFreed,
478 std::to_string(heap->GetBytesFreedEver()))) {
479 return nullptr;
480 }
481 if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcBlockingGcCount,
482 std::to_string(heap->GetBlockingGcCount()))) {
483 return nullptr;
484 }
485 if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcBlockingGcTime,
486 std::to_string(NsToMs(heap->GetBlockingGcTime())))) {
487 return nullptr;
488 }
489 {
490 std::ostringstream output;
491 heap->DumpGcCountRateHistogram(output);
492 if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcGcCountRateHistogram,
493 output.str())) {
494 return nullptr;
495 }
496 }
497 {
498 std::ostringstream output;
499 heap->DumpBlockingGcCountRateHistogram(output);
500 if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcBlockingGcCountRateHistogram,
501 output.str())) {
502 return nullptr;
503 }
504 }
505 return result;
506 }
507
VMDebug_attachAgent(JNIEnv * env,jclass,jstring agent)508 static void VMDebug_attachAgent(JNIEnv* env, jclass, jstring agent) {
509 if (agent == nullptr) {
510 ScopedObjectAccess soa(env);
511 ThrowNullPointerException("agent is null");
512 return;
513 }
514
515 if (!Dbg::IsJdwpAllowed()) {
516 ScopedObjectAccess soa(env);
517 ThrowSecurityException("Can't attach agent, process is not debuggable.");
518 return;
519 }
520
521 std::string filename;
522 {
523 ScopedUtfChars chars(env, agent);
524 if (env->ExceptionCheck()) {
525 return;
526 }
527 filename = chars.c_str();
528 }
529
530 Runtime::Current()->AttachAgent(filename);
531 }
532
533 static JNINativeMethod gMethods[] = {
534 NATIVE_METHOD(VMDebug, countInstancesOfClass, "(Ljava/lang/Class;Z)J"),
535 NATIVE_METHOD(VMDebug, countInstancesOfClasses, "([Ljava/lang/Class;Z)[J"),
536 NATIVE_METHOD(VMDebug, crash, "()V"),
537 NATIVE_METHOD(VMDebug, dumpHprofData, "(Ljava/lang/String;Ljava/io/FileDescriptor;)V"),
538 NATIVE_METHOD(VMDebug, dumpHprofDataDdms, "()V"),
539 NATIVE_METHOD(VMDebug, dumpReferenceTables, "()V"),
540 NATIVE_METHOD(VMDebug, getAllocCount, "(I)I"),
541 NATIVE_METHOD(VMDebug, getHeapSpaceStats, "([J)V"),
542 NATIVE_METHOD(VMDebug, getInstructionCount, "([I)V"),
543 FAST_NATIVE_METHOD(VMDebug, getLoadedClassCount, "()I"),
544 NATIVE_METHOD(VMDebug, getVmFeatureList, "()[Ljava/lang/String;"),
545 NATIVE_METHOD(VMDebug, infopoint, "(I)V"),
546 FAST_NATIVE_METHOD(VMDebug, isDebuggerConnected, "()Z"),
547 FAST_NATIVE_METHOD(VMDebug, isDebuggingEnabled, "()Z"),
548 NATIVE_METHOD(VMDebug, getMethodTracingMode, "()I"),
549 FAST_NATIVE_METHOD(VMDebug, lastDebuggerActivity, "()J"),
550 FAST_NATIVE_METHOD(VMDebug, printLoadedClasses, "(I)V"),
551 NATIVE_METHOD(VMDebug, resetAllocCount, "(I)V"),
552 NATIVE_METHOD(VMDebug, resetInstructionCount, "()V"),
553 NATIVE_METHOD(VMDebug, startAllocCounting, "()V"),
554 NATIVE_METHOD(VMDebug, startEmulatorTracing, "()V"),
555 NATIVE_METHOD(VMDebug, startInstructionCounting, "()V"),
556 NATIVE_METHOD(VMDebug, startMethodTracingDdmsImpl, "(IIZI)V"),
557 NATIVE_METHOD(VMDebug, startMethodTracingFd, "(Ljava/lang/String;Ljava/io/FileDescriptor;IIZIZ)V"),
558 NATIVE_METHOD(VMDebug, startMethodTracingFilename, "(Ljava/lang/String;IIZI)V"),
559 NATIVE_METHOD(VMDebug, stopAllocCounting, "()V"),
560 NATIVE_METHOD(VMDebug, stopEmulatorTracing, "()V"),
561 NATIVE_METHOD(VMDebug, stopInstructionCounting, "()V"),
562 NATIVE_METHOD(VMDebug, stopMethodTracing, "()V"),
563 FAST_NATIVE_METHOD(VMDebug, threadCpuTimeNanos, "()J"),
564 NATIVE_METHOD(VMDebug, getRuntimeStatInternal, "(I)Ljava/lang/String;"),
565 NATIVE_METHOD(VMDebug, getRuntimeStatsInternal, "()[Ljava/lang/String;"),
566 NATIVE_METHOD(VMDebug, attachAgent, "(Ljava/lang/String;)V"),
567 };
568
register_dalvik_system_VMDebug(JNIEnv * env)569 void register_dalvik_system_VMDebug(JNIEnv* env) {
570 REGISTER_NATIVE_METHODS("dalvik/system/VMDebug");
571 }
572
573 } // namespace art
574