blob: 67b2e1c503691ebf6fc33fcc2bfb694b05fec545 [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
Andreas Gampe277ccbd2014-11-03 21:36:10 -080017#include "dalvik_system_VMDebug.h"
18
Elliott Hughes9d5ccec2011-09-19 13:19:50 -070019#include <string.h>
20#include <unistd.h>
21
Hiroshi Yamauchia1c9f012015-04-02 10:18:12 -070022#include <sstream>
23
24#include "base/histogram-inl.h"
Vladimir Marko80afd022015-05-19 18:08:00 +010025#include "base/time_utils.h"
Elliott Hugheseac76672012-05-24 21:56:51 -070026#include "class_linker.h"
Ian Rogers62d6c772013-02-27 08:32:07 -080027#include "common_throws.h"
Elliott Hugheseac76672012-05-24 21:56:51 -070028#include "debugger.h"
Mathieu Chartier7410f292013-11-24 13:17:35 -080029#include "gc/space/bump_pointer_space.h"
Hiroshi Yamauchi09b07a92013-07-15 13:17:06 -070030#include "gc/space/dlmalloc_space.h"
31#include "gc/space/large_object_space.h"
32#include "gc/space/space-inl.h"
Mathieu Chartier1f3b5352014-02-03 14:00:42 -080033#include "gc/space/zygote_space.h"
Elliott Hugheseac76672012-05-24 21:56:51 -070034#include "hprof/hprof.h"
35#include "jni_internal.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080036#include "mirror/class.h"
Ian Rogersdd157d72014-05-15 14:47:50 -070037#include "ScopedLocalRef.h"
Elliott Hugheseac76672012-05-24 21:56:51 -070038#include "ScopedUtfChars.h"
Mathieu Chartier0795f232016-09-27 18:43:30 -070039#include "scoped_fast_native_object_access-inl.h"
Elliott Hugheseac76672012-05-24 21:56:51 -070040#include "trace.h"
Ian Rogersdd157d72014-05-15 14:47:50 -070041#include "well_known_classes.h"
Elliott Hugheseac76672012-05-24 21:56:51 -070042
Elliott Hughes9d5ccec2011-09-19 13:19:50 -070043namespace art {
44
Elliott Hughes0512f022012-03-15 22:10:52 -070045static jobjectArray VMDebug_getVmFeatureList(JNIEnv* env, jclass) {
Ian Rogersdd157d72014-05-15 14:47:50 -070046 static const char* features[] = {
47 "method-trace-profiling",
48 "method-trace-profiling-streaming",
49 "method-sample-profiling",
50 "hprof-heap-dump",
51 "hprof-heap-dump-streaming",
52 };
53 jobjectArray result = env->NewObjectArray(arraysize(features),
54 WellKnownClasses::java_lang_String,
55 nullptr);
56 if (result != nullptr) {
57 for (size_t i = 0; i < arraysize(features); ++i) {
58 ScopedLocalRef<jstring> jfeature(env, env->NewStringUTF(features[i]));
59 if (jfeature.get() == nullptr) {
60 return nullptr;
61 }
62 env->SetObjectArrayElement(result, i, jfeature.get());
63 }
64 }
65 return result;
Elliott Hughes9d5ccec2011-09-19 13:19:50 -070066}
67
Elliott Hughes0512f022012-03-15 22:10:52 -070068static void VMDebug_startAllocCounting(JNIEnv*, jclass) {
Mathieu Chartier9ef78b52014-09-25 17:03:12 -070069 Runtime::Current()->SetStatsEnabled(true);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -070070}
71
Elliott Hughes0512f022012-03-15 22:10:52 -070072static void VMDebug_stopAllocCounting(JNIEnv*, jclass) {
Mathieu Chartier9ef78b52014-09-25 17:03:12 -070073 Runtime::Current()->SetStatsEnabled(false);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -070074}
75
Elliott Hughes1bac54f2012-03-16 12:48:31 -070076static jint VMDebug_getAllocCount(JNIEnv*, jclass, jint kind) {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -070077 return Runtime::Current()->GetStat(kind);
78}
79
Elliott Hughes0512f022012-03-15 22:10:52 -070080static void VMDebug_resetAllocCount(JNIEnv*, jclass, jint kinds) {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -070081 Runtime::Current()->ResetStats(kinds);
82}
83
Jeff Hao23009dc2013-08-22 15:36:42 -070084static void VMDebug_startMethodTracingDdmsImpl(JNIEnv*, jclass, jint bufferSize, jint flags,
85 jboolean samplingEnabled, jint intervalUs) {
Andreas Gampe7e7e0f42015-03-29 15:26:23 -070086 Trace::Start("[DDMS]", -1, bufferSize, flags, Trace::TraceOutputMode::kDDMS,
87 samplingEnabled ? Trace::TraceMode::kSampling : Trace::TraceMode::kMethodTracing,
88 intervalUs);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -070089}
90
Ian Rogers00f7d0e2012-07-19 15:28:27 -070091static void VMDebug_startMethodTracingFd(JNIEnv* env, jclass, jstring javaTraceFilename,
Jeff Hao4044bda2014-01-06 15:50:45 -080092 jobject javaFd, jint bufferSize, jint flags,
93 jboolean samplingEnabled, jint intervalUs) {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -070094 int originalFd = jniGetFDFromFileDescriptor(env, javaFd);
95 if (originalFd < 0) {
96 return;
97 }
98
99 int fd = dup(originalFd);
100 if (fd < 0) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700101 ScopedObjectAccess soa(env);
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000102 soa.Self()->ThrowNewExceptionF("Ljava/lang/RuntimeException;",
Ian Rogers62d6c772013-02-27 08:32:07 -0800103 "dup(%d) failed: %s", originalFd, strerror(errno));
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700104 return;
105 }
106
107 ScopedUtfChars traceFilename(env, javaTraceFilename);
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700108 if (traceFilename.c_str() == nullptr) {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700109 return;
110 }
Andreas Gampe7e7e0f42015-03-29 15:26:23 -0700111 Trace::Start(traceFilename.c_str(), fd, bufferSize, flags, Trace::TraceOutputMode::kFile,
112 samplingEnabled ? Trace::TraceMode::kSampling : Trace::TraceMode::kMethodTracing,
113 intervalUs);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700114}
115
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700116static void VMDebug_startMethodTracingFilename(JNIEnv* env, jclass, jstring javaTraceFilename,
Jeff Hao4044bda2014-01-06 15:50:45 -0800117 jint bufferSize, jint flags,
118 jboolean samplingEnabled, jint intervalUs) {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700119 ScopedUtfChars traceFilename(env, javaTraceFilename);
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700120 if (traceFilename.c_str() == nullptr) {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700121 return;
122 }
Andreas Gampe7e7e0f42015-03-29 15:26:23 -0700123 Trace::Start(traceFilename.c_str(), -1, bufferSize, flags, Trace::TraceOutputMode::kFile,
124 samplingEnabled ? Trace::TraceMode::kSampling : Trace::TraceMode::kMethodTracing,
125 intervalUs);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700126}
127
Jeff Hao64caa7d2013-08-29 11:18:01 -0700128static jint VMDebug_getMethodTracingMode(JNIEnv*, jclass) {
129 return Trace::GetMethodTracingMode();
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700130}
131
Elliott Hughes0512f022012-03-15 22:10:52 -0700132static void VMDebug_stopMethodTracing(JNIEnv*, jclass) {
jeffhaoe343b762011-12-05 16:36:44 -0800133 Trace::Stop();
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700134}
135
Elliott Hughes0512f022012-03-15 22:10:52 -0700136static void VMDebug_startEmulatorTracing(JNIEnv*, jclass) {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700137 UNIMPLEMENTED(WARNING);
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700138 // dvmEmulatorTraceStart();
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700139}
140
Elliott Hughes0512f022012-03-15 22:10:52 -0700141static void VMDebug_stopEmulatorTracing(JNIEnv*, jclass) {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700142 UNIMPLEMENTED(WARNING);
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700143 // dvmEmulatorTraceStop();
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700144}
145
Elliott Hughes0512f022012-03-15 22:10:52 -0700146static jboolean VMDebug_isDebuggerConnected(JNIEnv*, jclass) {
Elliott Hughesc0f09332012-03-26 13:27:06 -0700147 return Dbg::IsDebuggerActive();
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700148}
149
Elliott Hughes0512f022012-03-15 22:10:52 -0700150static jboolean VMDebug_isDebuggingEnabled(JNIEnv*, jclass) {
Elliott Hughesc0f09332012-03-26 13:27:06 -0700151 return Dbg::IsJdwpConfigured();
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700152}
153
Elliott Hughes0512f022012-03-15 22:10:52 -0700154static jlong VMDebug_lastDebuggerActivity(JNIEnv*, jclass) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700155 return Dbg::LastDebuggerActivity();
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700156}
157
Ian Rogers62d6c772013-02-27 08:32:07 -0800158static void ThrowUnsupportedOperationException(JNIEnv* env) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700159 ScopedObjectAccess soa(env);
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700160 soa.Self()->ThrowNewException("Ljava/lang/UnsupportedOperationException;", nullptr);
Ian Rogers62d6c772013-02-27 08:32:07 -0800161}
162
163static void VMDebug_startInstructionCounting(JNIEnv* env, jclass) {
164 ThrowUnsupportedOperationException(env);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700165}
166
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700167static void VMDebug_stopInstructionCounting(JNIEnv* env, jclass) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800168 ThrowUnsupportedOperationException(env);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700169}
170
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700171static void VMDebug_getInstructionCount(JNIEnv* env, jclass, jintArray /*javaCounts*/) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800172 ThrowUnsupportedOperationException(env);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700173}
174
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700175static void VMDebug_resetInstructionCount(JNIEnv* env, jclass) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800176 ThrowUnsupportedOperationException(env);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700177}
178
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700179static void VMDebug_printLoadedClasses(JNIEnv* env, jclass, jint flags) {
Andreas Gampecc1b5352016-12-01 16:58:38 -0800180 class DumpClassVisitor : public ClassVisitor {
181 public:
182 explicit DumpClassVisitor(int dump_flags) : flags_(dump_flags) {}
183
184 bool operator()(ObjPtr<mirror::Class> klass) OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
185 klass->DumpClass(LOG_STREAM(ERROR), flags_);
186 return true;
187 }
188
189 private:
190 const int flags_;
191 };
192 DumpClassVisitor visitor(flags);
193
Ian Rogers53b8b092014-03-13 23:45:53 -0700194 ScopedFastNativeObjectAccess soa(env);
Andreas Gampecc1b5352016-12-01 16:58:38 -0800195 return Runtime::Current()->GetClassLinker()->VisitClasses(&visitor);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700196}
197
Ian Rogers7dfb28c2013-08-22 08:18:36 -0700198static jint VMDebug_getLoadedClassCount(JNIEnv* env, jclass) {
Ian Rogers53b8b092014-03-13 23:45:53 -0700199 ScopedFastNativeObjectAccess soa(env);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700200 return Runtime::Current()->GetClassLinker()->NumLoadedClasses();
201}
202
203/*
204 * Returns the thread-specific CPU-time clock value for the current thread,
205 * or -1 if the feature isn't supported.
206 */
Elliott Hughes0512f022012-03-15 22:10:52 -0700207static jlong VMDebug_threadCpuTimeNanos(JNIEnv*, jclass) {
208 return ThreadCpuNanoTime();
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700209}
210
211/*
212 * static void dumpHprofData(String fileName, FileDescriptor fd)
213 *
214 * Cause "hprof" data to be dumped. We can throw an IOException if an
215 * error occurs during file handling.
216 */
Elliott Hughes0512f022012-03-15 22:10:52 -0700217static void VMDebug_dumpHprofData(JNIEnv* env, jclass, jstring javaFilename, jobject javaFd) {
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700218 // Only one of these may be null.
219 if (javaFilename == nullptr && javaFd == nullptr) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700220 ScopedObjectAccess soa(env);
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000221 ThrowNullPointerException("fileName == null && fd == null");
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700222 return;
223 }
224
225 std::string filename;
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700226 if (javaFilename != nullptr) {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700227 ScopedUtfChars chars(env, javaFilename);
228 if (env->ExceptionCheck()) {
229 return;
230 }
231 filename = chars.c_str();
232 } else {
233 filename = "[fd]";
234 }
235
236 int fd = -1;
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700237 if (javaFd != nullptr) {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700238 fd = jniGetFDFromFileDescriptor(env, javaFd);
239 if (fd < 0) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700240 ScopedObjectAccess soa(env);
Ian Rogers62d6c772013-02-27 08:32:07 -0800241 ThrowRuntimeException("Invalid file descriptor");
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700242 return;
243 }
244 }
245
Elliott Hughes622a6982012-06-08 17:58:54 -0700246 hprof::DumpHeap(filename.c_str(), fd, false);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700247}
248
Elliott Hugheseac76672012-05-24 21:56:51 -0700249static void VMDebug_dumpHprofDataDdms(JNIEnv*, jclass) {
Elliott Hughes622a6982012-06-08 17:58:54 -0700250 hprof::DumpHeap("[DDMS]", -1, true);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700251}
252
Elliott Hughes0512f022012-03-15 22:10:52 -0700253static void VMDebug_dumpReferenceTables(JNIEnv* env, jclass) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700254 ScopedObjectAccess soa(env);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700255 LOG(INFO) << "--- reference table dump ---";
256
Andreas Gampe3fec9ac2016-09-13 10:47:28 -0700257 soa.Env()->DumpReferenceTables(LOG_STREAM(INFO));
258 soa.Vm()->DumpReferenceTables(LOG_STREAM(INFO));
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700259
260 LOG(INFO) << "---";
261}
262
Elliott Hughes0512f022012-03-15 22:10:52 -0700263static void VMDebug_crash(JNIEnv*, jclass) {
Elliott Hughes81ff3182012-03-23 20:35:56 -0700264 LOG(FATAL) << "Crashing runtime on request";
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700265}
266
Elliott Hughes0512f022012-03-15 22:10:52 -0700267static void VMDebug_infopoint(JNIEnv*, jclass, jint id) {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700268 LOG(INFO) << "VMDebug infopoint " << id << " hit";
269}
270
Mathieu Chartier9d156d52016-10-06 17:44:26 -0700271static jlong VMDebug_countInstancesOfClass(JNIEnv* env,
272 jclass,
273 jclass javaClass,
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700274 jboolean countAssignable) {
275 ScopedObjectAccess soa(env);
Mathieu Chartierf1820852015-07-10 13:19:51 -0700276 gc::Heap* const heap = Runtime::Current()->GetHeap();
277 // Caller's responsibility to do GC if desired.
Mathieu Chartier0795f232016-09-27 18:43:30 -0700278 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(javaClass);
Mathieu Chartier412c7fc2014-02-07 12:18:39 -0800279 if (c == nullptr) {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700280 return 0;
281 }
Mathieu Chartiere8a3c572016-10-11 16:52:17 -0700282 VariableSizedHandleScope hs(soa.Self());
Mathieu Chartier9d156d52016-10-06 17:44:26 -0700283 std::vector<Handle<mirror::Class>> classes {hs.NewHandle(c)};
Elliott Hughesec0f83d2013-01-15 16:54:08 -0800284 uint64_t count = 0;
Mathieu Chartier412c7fc2014-02-07 12:18:39 -0800285 heap->CountInstances(classes, countAssignable, &count);
Elliott Hughesec0f83d2013-01-15 16:54:08 -0800286 return count;
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700287}
288
Mathieu Chartier9d156d52016-10-06 17:44:26 -0700289static jlongArray VMDebug_countInstancesOfClasses(JNIEnv* env,
290 jclass,
291 jobjectArray javaClasses,
Mathieu Chartierf1820852015-07-10 13:19:51 -0700292 jboolean countAssignable) {
293 ScopedObjectAccess soa(env);
294 gc::Heap* const heap = Runtime::Current()->GetHeap();
295 // Caller's responsibility to do GC if desired.
Mathieu Chartier0795f232016-09-27 18:43:30 -0700296 ObjPtr<mirror::ObjectArray<mirror::Class>> decoded_classes =
297 soa.Decode<mirror::ObjectArray<mirror::Class>>(javaClasses);
Mathieu Chartierf1820852015-07-10 13:19:51 -0700298 if (decoded_classes == nullptr) {
299 return nullptr;
300 }
Mathieu Chartiere8a3c572016-10-11 16:52:17 -0700301 VariableSizedHandleScope hs(soa.Self());
Mathieu Chartier9d156d52016-10-06 17:44:26 -0700302 std::vector<Handle<mirror::Class>> classes;
Mathieu Chartierf1820852015-07-10 13:19:51 -0700303 for (size_t i = 0, count = decoded_classes->GetLength(); i < count; ++i) {
Mathieu Chartier9d156d52016-10-06 17:44:26 -0700304 classes.push_back(hs.NewHandle(decoded_classes->Get(i)));
Mathieu Chartierf1820852015-07-10 13:19:51 -0700305 }
306 std::vector<uint64_t> counts(classes.size(), 0u);
307 // Heap::CountInstances can handle null and will put 0 for these classes.
308 heap->CountInstances(classes, countAssignable, &counts[0]);
Mathieu Chartier9d156d52016-10-06 17:44:26 -0700309 ObjPtr<mirror::LongArray> long_counts = mirror::LongArray::Alloc(soa.Self(), counts.size());
Mathieu Chartierf1820852015-07-10 13:19:51 -0700310 if (long_counts == nullptr) {
311 soa.Self()->AssertPendingOOMException();
312 return nullptr;
313 }
314 for (size_t i = 0; i < counts.size(); ++i) {
315 long_counts->Set(i, counts[i]);
316 }
317 return soa.AddLocalReference<jlongArray>(long_counts);
318}
319
Hiroshi Yamauchi09b07a92013-07-15 13:17:06 -0700320// We export the VM internal per-heap-space size/alloc/free metrics
321// for the zygote space, alloc space (application heap), and the large
322// object space for dumpsys meminfo. The other memory region data such
323// as PSS, private/shared dirty/shared data are available via
324// /proc/<pid>/smaps.
325static void VMDebug_getHeapSpaceStats(JNIEnv* env, jclass, jlongArray data) {
Ian Rogers6b99dd12013-07-25 12:11:32 -0700326 jlong* arr = reinterpret_cast<jlong*>(env->GetPrimitiveArrayCritical(data, 0));
Mathieu Chartier7410f292013-11-24 13:17:35 -0800327 if (arr == nullptr || env->GetArrayLength(data) < 9) {
Hiroshi Yamauchi09b07a92013-07-15 13:17:06 -0700328 return;
329 }
330
331 size_t allocSize = 0;
332 size_t allocUsed = 0;
333 size_t zygoteSize = 0;
334 size_t zygoteUsed = 0;
335 size_t largeObjectsSize = 0;
336 size_t largeObjectsUsed = 0;
Hiroshi Yamauchi09b07a92013-07-15 13:17:06 -0700337 gc::Heap* heap = Runtime::Current()->GetHeap();
Mathieu Chartiera9d82fe2016-01-25 20:06:11 -0800338 {
339 ScopedObjectAccess soa(env);
340 for (gc::space::ContinuousSpace* space : heap->GetContinuousSpaces()) {
341 if (space->IsImageSpace()) {
342 // Currently don't include the image space.
343 } else if (space->IsZygoteSpace()) {
344 gc::space::ZygoteSpace* zygote_space = space->AsZygoteSpace();
345 zygoteSize += zygote_space->Size();
346 zygoteUsed += zygote_space->GetBytesAllocated();
347 } else if (space->IsMallocSpace()) {
348 // This is a malloc space.
349 gc::space::MallocSpace* malloc_space = space->AsMallocSpace();
350 allocSize += malloc_space->GetFootprint();
351 allocUsed += malloc_space->GetBytesAllocated();
352 } else if (space->IsBumpPointerSpace()) {
353 gc::space::BumpPointerSpace* bump_pointer_space = space->AsBumpPointerSpace();
354 allocSize += bump_pointer_space->Size();
355 allocUsed += bump_pointer_space->GetBytesAllocated();
356 }
357 }
358 for (gc::space::DiscontinuousSpace* space : heap->GetDiscontinuousSpaces()) {
359 if (space->IsLargeObjectSpace()) {
360 largeObjectsSize += space->AsLargeObjectSpace()->GetBytesAllocated();
361 largeObjectsUsed += largeObjectsSize;
362 }
Hiroshi Yamauchi09b07a92013-07-15 13:17:06 -0700363 }
364 }
Hiroshi Yamauchi09b07a92013-07-15 13:17:06 -0700365 size_t allocFree = allocSize - allocUsed;
366 size_t zygoteFree = zygoteSize - zygoteUsed;
367 size_t largeObjectsFree = largeObjectsSize - largeObjectsUsed;
368
369 int j = 0;
370 arr[j++] = allocSize;
371 arr[j++] = allocUsed;
372 arr[j++] = allocFree;
373 arr[j++] = zygoteSize;
374 arr[j++] = zygoteUsed;
375 arr[j++] = zygoteFree;
376 arr[j++] = largeObjectsSize;
377 arr[j++] = largeObjectsUsed;
378 arr[j++] = largeObjectsFree;
379 env->ReleasePrimitiveArrayCritical(data, arr, 0);
380}
381
Hiroshi Yamauchia1c9f012015-04-02 10:18:12 -0700382// The runtime stat names for VMDebug.getRuntimeStat().
383enum class VMDebugRuntimeStatId {
384 kArtGcGcCount = 0,
385 kArtGcGcTime,
386 kArtGcBytesAllocated,
387 kArtGcBytesFreed,
388 kArtGcBlockingGcCount,
389 kArtGcBlockingGcTime,
390 kArtGcGcCountRateHistogram,
391 kArtGcBlockingGcCountRateHistogram,
392 kNumRuntimeStats,
393};
394
395static jobject VMDebug_getRuntimeStatInternal(JNIEnv* env, jclass, jint statId) {
396 gc::Heap* heap = Runtime::Current()->GetHeap();
397 switch (static_cast<VMDebugRuntimeStatId>(statId)) {
398 case VMDebugRuntimeStatId::kArtGcGcCount: {
399 std::string output = std::to_string(heap->GetGcCount());
400 return env->NewStringUTF(output.c_str());
401 }
402 case VMDebugRuntimeStatId::kArtGcGcTime: {
403 std::string output = std::to_string(NsToMs(heap->GetGcTime()));
404 return env->NewStringUTF(output.c_str());
405 }
406 case VMDebugRuntimeStatId::kArtGcBytesAllocated: {
407 std::string output = std::to_string(heap->GetBytesAllocatedEver());
408 return env->NewStringUTF(output.c_str());
409 }
410 case VMDebugRuntimeStatId::kArtGcBytesFreed: {
411 std::string output = std::to_string(heap->GetBytesFreedEver());
412 return env->NewStringUTF(output.c_str());
413 }
414 case VMDebugRuntimeStatId::kArtGcBlockingGcCount: {
415 std::string output = std::to_string(heap->GetBlockingGcCount());
416 return env->NewStringUTF(output.c_str());
417 }
418 case VMDebugRuntimeStatId::kArtGcBlockingGcTime: {
419 std::string output = std::to_string(NsToMs(heap->GetBlockingGcTime()));
420 return env->NewStringUTF(output.c_str());
421 }
422 case VMDebugRuntimeStatId::kArtGcGcCountRateHistogram: {
423 std::ostringstream output;
424 heap->DumpGcCountRateHistogram(output);
425 return env->NewStringUTF(output.str().c_str());
426 }
427 case VMDebugRuntimeStatId::kArtGcBlockingGcCountRateHistogram: {
428 std::ostringstream output;
429 heap->DumpBlockingGcCountRateHistogram(output);
430 return env->NewStringUTF(output.str().c_str());
431 }
432 default:
433 return nullptr;
434 }
435}
436
Andreas Gampeca620d72016-11-08 08:09:33 -0800437static bool SetRuntimeStatValue(JNIEnv* env,
438 jobjectArray result,
439 VMDebugRuntimeStatId id,
440 const std::string& value) {
Hiroshi Yamauchia1c9f012015-04-02 10:18:12 -0700441 ScopedLocalRef<jstring> jvalue(env, env->NewStringUTF(value.c_str()));
442 if (jvalue.get() == nullptr) {
443 return false;
444 }
445 env->SetObjectArrayElement(result, static_cast<jint>(id), jvalue.get());
446 return true;
447}
448
449static jobjectArray VMDebug_getRuntimeStatsInternal(JNIEnv* env, jclass) {
450 jobjectArray result = env->NewObjectArray(
451 static_cast<jint>(VMDebugRuntimeStatId::kNumRuntimeStats),
452 WellKnownClasses::java_lang_String,
453 nullptr);
454 if (result == nullptr) {
455 return nullptr;
456 }
457 gc::Heap* heap = Runtime::Current()->GetHeap();
458 if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcGcCount,
459 std::to_string(heap->GetGcCount()))) {
460 return nullptr;
461 }
462 if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcGcTime,
463 std::to_string(NsToMs(heap->GetGcTime())))) {
464 return nullptr;
465 }
466 if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcBytesAllocated,
467 std::to_string(heap->GetBytesAllocatedEver()))) {
468 return nullptr;
469 }
470 if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcBytesFreed,
471 std::to_string(heap->GetBytesFreedEver()))) {
472 return nullptr;
473 }
474 if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcBlockingGcCount,
475 std::to_string(heap->GetBlockingGcCount()))) {
476 return nullptr;
477 }
478 if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcBlockingGcTime,
479 std::to_string(NsToMs(heap->GetBlockingGcTime())))) {
480 return nullptr;
481 }
482 {
483 std::ostringstream output;
484 heap->DumpGcCountRateHistogram(output);
485 if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcGcCountRateHistogram,
486 output.str())) {
487 return nullptr;
488 }
489 }
490 {
491 std::ostringstream output;
492 heap->DumpBlockingGcCountRateHistogram(output);
493 if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcBlockingGcCountRateHistogram,
494 output.str())) {
495 return nullptr;
496 }
497 }
498 return result;
499}
500
Leonard Mosescueb842212016-10-06 17:26:36 -0700501static void VMDebug_attachAgent(JNIEnv* env, jclass, jstring agent) {
502 if (agent == nullptr) {
503 ScopedObjectAccess soa(env);
504 ThrowNullPointerException("agent is null");
505 return;
506 }
507
508 if (!Dbg::IsJdwpAllowed()) {
509 ScopedObjectAccess soa(env);
510 ThrowSecurityException("Can't attach agent, process is not debuggable.");
511 return;
512 }
513
514 std::string filename;
515 {
516 ScopedUtfChars chars(env, agent);
517 if (env->ExceptionCheck()) {
518 return;
519 }
520 filename = chars.c_str();
521 }
522
523 Runtime::Current()->AttachAgent(filename);
524}
525
Elliott Hughes0512f022012-03-15 22:10:52 -0700526static JNINativeMethod gMethods[] = {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700527 NATIVE_METHOD(VMDebug, countInstancesOfClass, "(Ljava/lang/Class;Z)J"),
Mathieu Chartierf1820852015-07-10 13:19:51 -0700528 NATIVE_METHOD(VMDebug, countInstancesOfClasses, "([Ljava/lang/Class;Z)[J"),
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700529 NATIVE_METHOD(VMDebug, crash, "()V"),
530 NATIVE_METHOD(VMDebug, dumpHprofData, "(Ljava/lang/String;Ljava/io/FileDescriptor;)V"),
531 NATIVE_METHOD(VMDebug, dumpHprofDataDdms, "()V"),
532 NATIVE_METHOD(VMDebug, dumpReferenceTables, "()V"),
533 NATIVE_METHOD(VMDebug, getAllocCount, "(I)I"),
Hiroshi Yamauchi09b07a92013-07-15 13:17:06 -0700534 NATIVE_METHOD(VMDebug, getHeapSpaceStats, "([J)V"),
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700535 NATIVE_METHOD(VMDebug, getInstructionCount, "([I)V"),
Ian Rogers53b8b092014-03-13 23:45:53 -0700536 NATIVE_METHOD(VMDebug, getLoadedClassCount, "!()I"),
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700537 NATIVE_METHOD(VMDebug, getVmFeatureList, "()[Ljava/lang/String;"),
538 NATIVE_METHOD(VMDebug, infopoint, "(I)V"),
Ian Rogers53b8b092014-03-13 23:45:53 -0700539 NATIVE_METHOD(VMDebug, isDebuggerConnected, "!()Z"),
540 NATIVE_METHOD(VMDebug, isDebuggingEnabled, "!()Z"),
Jeff Hao64caa7d2013-08-29 11:18:01 -0700541 NATIVE_METHOD(VMDebug, getMethodTracingMode, "()I"),
Ian Rogers53b8b092014-03-13 23:45:53 -0700542 NATIVE_METHOD(VMDebug, lastDebuggerActivity, "!()J"),
543 NATIVE_METHOD(VMDebug, printLoadedClasses, "!(I)V"),
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700544 NATIVE_METHOD(VMDebug, resetAllocCount, "(I)V"),
545 NATIVE_METHOD(VMDebug, resetInstructionCount, "()V"),
546 NATIVE_METHOD(VMDebug, startAllocCounting, "()V"),
547 NATIVE_METHOD(VMDebug, startEmulatorTracing, "()V"),
548 NATIVE_METHOD(VMDebug, startInstructionCounting, "()V"),
Jeff Hao23009dc2013-08-22 15:36:42 -0700549 NATIVE_METHOD(VMDebug, startMethodTracingDdmsImpl, "(IIZI)V"),
Jeff Hao4044bda2014-01-06 15:50:45 -0800550 NATIVE_METHOD(VMDebug, startMethodTracingFd, "(Ljava/lang/String;Ljava/io/FileDescriptor;IIZI)V"),
551 NATIVE_METHOD(VMDebug, startMethodTracingFilename, "(Ljava/lang/String;IIZI)V"),
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700552 NATIVE_METHOD(VMDebug, stopAllocCounting, "()V"),
553 NATIVE_METHOD(VMDebug, stopEmulatorTracing, "()V"),
554 NATIVE_METHOD(VMDebug, stopInstructionCounting, "()V"),
555 NATIVE_METHOD(VMDebug, stopMethodTracing, "()V"),
Ian Rogers53b8b092014-03-13 23:45:53 -0700556 NATIVE_METHOD(VMDebug, threadCpuTimeNanos, "!()J"),
Hiroshi Yamauchia1c9f012015-04-02 10:18:12 -0700557 NATIVE_METHOD(VMDebug, getRuntimeStatInternal, "(I)Ljava/lang/String;"),
Leonard Mosescueb842212016-10-06 17:26:36 -0700558 NATIVE_METHOD(VMDebug, getRuntimeStatsInternal, "()[Ljava/lang/String;"),
559 NATIVE_METHOD(VMDebug, attachAgent, "(Ljava/lang/String;)V"),
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700560};
561
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700562void register_dalvik_system_VMDebug(JNIEnv* env) {
Elliott Hugheseac76672012-05-24 21:56:51 -0700563 REGISTER_NATIVE_METHODS("dalvik/system/VMDebug");
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700564}
565
566} // namespace art