blob: fc9426650ea9b43321336fdf5136ecc90a3278bd [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
Andreas Gampea14100c2017-04-24 15:09:56 -070024#include "nativehelper/jni_macros.h"
25
Hiroshi Yamauchia1c9f012015-04-02 10:18:12 -070026#include "base/histogram-inl.h"
Vladimir Marko80afd022015-05-19 18:08:00 +010027#include "base/time_utils.h"
Elliott Hugheseac76672012-05-24 21:56:51 -070028#include "class_linker.h"
Ian Rogers62d6c772013-02-27 08:32:07 -080029#include "common_throws.h"
Elliott Hugheseac76672012-05-24 21:56:51 -070030#include "debugger.h"
Mathieu Chartier7410f292013-11-24 13:17:35 -080031#include "gc/space/bump_pointer_space.h"
Hiroshi Yamauchi09b07a92013-07-15 13:17:06 -070032#include "gc/space/dlmalloc_space.h"
33#include "gc/space/large_object_space.h"
34#include "gc/space/space-inl.h"
Mathieu Chartier1f3b5352014-02-03 14:00:42 -080035#include "gc/space/zygote_space.h"
Andreas Gampec15a2f42017-04-21 12:09:39 -070036#include "handle_scope-inl.h"
Elliott Hugheseac76672012-05-24 21:56:51 -070037#include "hprof/hprof.h"
Andreas Gampec15a2f42017-04-21 12:09:39 -070038#include "java_vm_ext.h"
Elliott Hugheseac76672012-05-24 21:56:51 -070039#include "jni_internal.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080040#include "mirror/class.h"
Andreas Gampec15a2f42017-04-21 12:09:39 -070041#include "mirror/object_array-inl.h"
Andreas Gampe87583b32017-05-25 11:22:18 -070042#include "native_util.h"
Andreas Gampe373a9b52017-10-18 09:01:57 -070043#include "nativehelper/scoped_local_ref.h"
44#include "nativehelper/scoped_utf_chars.h"
Mathieu Chartier0795f232016-09-27 18:43:30 -070045#include "scoped_fast_native_object_access-inl.h"
Elliott Hugheseac76672012-05-24 21:56:51 -070046#include "trace.h"
Ian Rogersdd157d72014-05-15 14:47:50 -070047#include "well_known_classes.h"
Elliott Hugheseac76672012-05-24 21:56:51 -070048
Elliott Hughes9d5ccec2011-09-19 13:19:50 -070049namespace art {
50
Elliott Hughes0512f022012-03-15 22:10:52 -070051static jobjectArray VMDebug_getVmFeatureList(JNIEnv* env, jclass) {
Ian Rogersdd157d72014-05-15 14:47:50 -070052 static const char* features[] = {
53 "method-trace-profiling",
54 "method-trace-profiling-streaming",
55 "method-sample-profiling",
56 "hprof-heap-dump",
57 "hprof-heap-dump-streaming",
58 };
59 jobjectArray result = env->NewObjectArray(arraysize(features),
60 WellKnownClasses::java_lang_String,
61 nullptr);
62 if (result != nullptr) {
63 for (size_t i = 0; i < arraysize(features); ++i) {
64 ScopedLocalRef<jstring> jfeature(env, env->NewStringUTF(features[i]));
65 if (jfeature.get() == nullptr) {
66 return nullptr;
67 }
68 env->SetObjectArrayElement(result, i, jfeature.get());
69 }
70 }
71 return result;
Elliott Hughes9d5ccec2011-09-19 13:19:50 -070072}
73
Elliott Hughes0512f022012-03-15 22:10:52 -070074static void VMDebug_startAllocCounting(JNIEnv*, jclass) {
Mathieu Chartier9ef78b52014-09-25 17:03:12 -070075 Runtime::Current()->SetStatsEnabled(true);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -070076}
77
Elliott Hughes0512f022012-03-15 22:10:52 -070078static void VMDebug_stopAllocCounting(JNIEnv*, jclass) {
Mathieu Chartier9ef78b52014-09-25 17:03:12 -070079 Runtime::Current()->SetStatsEnabled(false);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -070080}
81
Elliott Hughes1bac54f2012-03-16 12:48:31 -070082static jint VMDebug_getAllocCount(JNIEnv*, jclass, jint kind) {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -070083 return Runtime::Current()->GetStat(kind);
84}
85
Elliott Hughes0512f022012-03-15 22:10:52 -070086static void VMDebug_resetAllocCount(JNIEnv*, jclass, jint kinds) {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -070087 Runtime::Current()->ResetStats(kinds);
88}
89
Jeff Hao23009dc2013-08-22 15:36:42 -070090static void VMDebug_startMethodTracingDdmsImpl(JNIEnv*, jclass, jint bufferSize, jint flags,
91 jboolean samplingEnabled, jint intervalUs) {
Andreas Gampe7e7e0f42015-03-29 15:26:23 -070092 Trace::Start("[DDMS]", -1, bufferSize, flags, Trace::TraceOutputMode::kDDMS,
93 samplingEnabled ? Trace::TraceMode::kSampling : Trace::TraceMode::kMethodTracing,
94 intervalUs);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -070095}
96
Ian Rogers00f7d0e2012-07-19 15:28:27 -070097static void VMDebug_startMethodTracingFd(JNIEnv* env, jclass, jstring javaTraceFilename,
Andreas Gampead5df102017-10-04 16:31:08 -070098 jint javaFd, jint bufferSize, jint flags,
Shukang Zhouca6e14e2017-01-25 00:35:21 -080099 jboolean samplingEnabled, jint intervalUs,
100 jboolean streamingOutput) {
Andreas Gampead5df102017-10-04 16:31:08 -0700101 int originalFd = javaFd;
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700102 if (originalFd < 0) {
103 return;
104 }
105
106 int fd = dup(originalFd);
107 if (fd < 0) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700108 ScopedObjectAccess soa(env);
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000109 soa.Self()->ThrowNewExceptionF("Ljava/lang/RuntimeException;",
Ian Rogers62d6c772013-02-27 08:32:07 -0800110 "dup(%d) failed: %s", originalFd, strerror(errno));
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700111 return;
112 }
113
114 ScopedUtfChars traceFilename(env, javaTraceFilename);
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700115 if (traceFilename.c_str() == nullptr) {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700116 return;
117 }
Shukang Zhouca6e14e2017-01-25 00:35:21 -0800118 Trace::TraceOutputMode outputMode = streamingOutput
119 ? Trace::TraceOutputMode::kStreaming
120 : Trace::TraceOutputMode::kFile;
121 Trace::Start(traceFilename.c_str(), fd, bufferSize, flags, outputMode,
Andreas Gampe7e7e0f42015-03-29 15:26:23 -0700122 samplingEnabled ? Trace::TraceMode::kSampling : Trace::TraceMode::kMethodTracing,
123 intervalUs);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700124}
125
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700126static void VMDebug_startMethodTracingFilename(JNIEnv* env, jclass, jstring javaTraceFilename,
Jeff Hao4044bda2014-01-06 15:50:45 -0800127 jint bufferSize, jint flags,
128 jboolean samplingEnabled, jint intervalUs) {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700129 ScopedUtfChars traceFilename(env, javaTraceFilename);
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700130 if (traceFilename.c_str() == nullptr) {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700131 return;
132 }
Andreas Gampe7e7e0f42015-03-29 15:26:23 -0700133 Trace::Start(traceFilename.c_str(), -1, bufferSize, flags, Trace::TraceOutputMode::kFile,
134 samplingEnabled ? Trace::TraceMode::kSampling : Trace::TraceMode::kMethodTracing,
135 intervalUs);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700136}
137
Jeff Hao64caa7d2013-08-29 11:18:01 -0700138static jint VMDebug_getMethodTracingMode(JNIEnv*, jclass) {
139 return Trace::GetMethodTracingMode();
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700140}
141
Elliott Hughes0512f022012-03-15 22:10:52 -0700142static void VMDebug_stopMethodTracing(JNIEnv*, jclass) {
jeffhaoe343b762011-12-05 16:36:44 -0800143 Trace::Stop();
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700144}
145
Elliott Hughes0512f022012-03-15 22:10:52 -0700146static void VMDebug_startEmulatorTracing(JNIEnv*, jclass) {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700147 UNIMPLEMENTED(WARNING);
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700148 // dvmEmulatorTraceStart();
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700149}
150
Elliott Hughes0512f022012-03-15 22:10:52 -0700151static void VMDebug_stopEmulatorTracing(JNIEnv*, jclass) {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700152 UNIMPLEMENTED(WARNING);
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700153 // dvmEmulatorTraceStop();
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700154}
155
Elliott Hughes0512f022012-03-15 22:10:52 -0700156static jboolean VMDebug_isDebuggerConnected(JNIEnv*, jclass) {
Elliott Hughesc0f09332012-03-26 13:27:06 -0700157 return Dbg::IsDebuggerActive();
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700158}
159
Alex Light40320712017-12-14 11:52:04 -0800160static jboolean VMDebug_isDebuggingEnabled(JNIEnv* env, jclass) {
161 ScopedObjectAccess soa(env);
162 return Runtime::Current()->GetRuntimeCallbacks()->IsDebuggerConfigured();
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700163}
164
Elliott Hughes0512f022012-03-15 22:10:52 -0700165static jlong VMDebug_lastDebuggerActivity(JNIEnv*, jclass) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700166 return Dbg::LastDebuggerActivity();
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700167}
168
Ian Rogers62d6c772013-02-27 08:32:07 -0800169static void ThrowUnsupportedOperationException(JNIEnv* env) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700170 ScopedObjectAccess soa(env);
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700171 soa.Self()->ThrowNewException("Ljava/lang/UnsupportedOperationException;", nullptr);
Ian Rogers62d6c772013-02-27 08:32:07 -0800172}
173
174static void VMDebug_startInstructionCounting(JNIEnv* env, jclass) {
175 ThrowUnsupportedOperationException(env);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700176}
177
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700178static void VMDebug_stopInstructionCounting(JNIEnv* env, jclass) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800179 ThrowUnsupportedOperationException(env);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700180}
181
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700182static void VMDebug_getInstructionCount(JNIEnv* env, jclass, jintArray /*javaCounts*/) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800183 ThrowUnsupportedOperationException(env);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700184}
185
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700186static void VMDebug_resetInstructionCount(JNIEnv* env, jclass) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800187 ThrowUnsupportedOperationException(env);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700188}
189
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700190static void VMDebug_printLoadedClasses(JNIEnv* env, jclass, jint flags) {
Andreas Gampecc1b5352016-12-01 16:58:38 -0800191 class DumpClassVisitor : public ClassVisitor {
192 public:
193 explicit DumpClassVisitor(int dump_flags) : flags_(dump_flags) {}
194
195 bool operator()(ObjPtr<mirror::Class> klass) OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
196 klass->DumpClass(LOG_STREAM(ERROR), flags_);
197 return true;
198 }
199
200 private:
201 const int flags_;
202 };
203 DumpClassVisitor visitor(flags);
204
Ian Rogers53b8b092014-03-13 23:45:53 -0700205 ScopedFastNativeObjectAccess soa(env);
Andreas Gampecc1b5352016-12-01 16:58:38 -0800206 return Runtime::Current()->GetClassLinker()->VisitClasses(&visitor);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700207}
208
Ian Rogers7dfb28c2013-08-22 08:18:36 -0700209static jint VMDebug_getLoadedClassCount(JNIEnv* env, jclass) {
Ian Rogers53b8b092014-03-13 23:45:53 -0700210 ScopedFastNativeObjectAccess soa(env);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700211 return Runtime::Current()->GetClassLinker()->NumLoadedClasses();
212}
213
214/*
215 * Returns the thread-specific CPU-time clock value for the current thread,
216 * or -1 if the feature isn't supported.
217 */
Elliott Hughes0512f022012-03-15 22:10:52 -0700218static jlong VMDebug_threadCpuTimeNanos(JNIEnv*, jclass) {
219 return ThreadCpuNanoTime();
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700220}
221
222/*
223 * static void dumpHprofData(String fileName, FileDescriptor fd)
224 *
225 * Cause "hprof" data to be dumped. We can throw an IOException if an
226 * error occurs during file handling.
227 */
Andreas Gampead5df102017-10-04 16:31:08 -0700228static void VMDebug_dumpHprofData(JNIEnv* env, jclass, jstring javaFilename, jint javaFd) {
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700229 // Only one of these may be null.
Andreas Gampead5df102017-10-04 16:31:08 -0700230 if (javaFilename == nullptr && javaFd < 0) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700231 ScopedObjectAccess soa(env);
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000232 ThrowNullPointerException("fileName == null && fd == null");
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700233 return;
234 }
235
236 std::string filename;
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700237 if (javaFilename != nullptr) {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700238 ScopedUtfChars chars(env, javaFilename);
239 if (env->ExceptionCheck()) {
240 return;
241 }
242 filename = chars.c_str();
243 } else {
244 filename = "[fd]";
245 }
246
Andreas Gampead5df102017-10-04 16:31:08 -0700247 int fd = javaFd;
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700248
Elliott Hughes622a6982012-06-08 17:58:54 -0700249 hprof::DumpHeap(filename.c_str(), fd, false);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700250}
251
Elliott Hugheseac76672012-05-24 21:56:51 -0700252static void VMDebug_dumpHprofDataDdms(JNIEnv*, jclass) {
Elliott Hughes622a6982012-06-08 17:58:54 -0700253 hprof::DumpHeap("[DDMS]", -1, true);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700254}
255
Elliott Hughes0512f022012-03-15 22:10:52 -0700256static void VMDebug_dumpReferenceTables(JNIEnv* env, jclass) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700257 ScopedObjectAccess soa(env);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700258 LOG(INFO) << "--- reference table dump ---";
259
Andreas Gampe3fec9ac2016-09-13 10:47:28 -0700260 soa.Env()->DumpReferenceTables(LOG_STREAM(INFO));
261 soa.Vm()->DumpReferenceTables(LOG_STREAM(INFO));
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700262
263 LOG(INFO) << "---";
264}
265
Elliott Hughes0512f022012-03-15 22:10:52 -0700266static void VMDebug_crash(JNIEnv*, jclass) {
Elliott Hughes81ff3182012-03-23 20:35:56 -0700267 LOG(FATAL) << "Crashing runtime on request";
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700268}
269
Elliott Hughes0512f022012-03-15 22:10:52 -0700270static void VMDebug_infopoint(JNIEnv*, jclass, jint id) {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700271 LOG(INFO) << "VMDebug infopoint " << id << " hit";
272}
273
Mathieu Chartier9d156d52016-10-06 17:44:26 -0700274static jlong VMDebug_countInstancesOfClass(JNIEnv* env,
275 jclass,
276 jclass javaClass,
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700277 jboolean countAssignable) {
278 ScopedObjectAccess soa(env);
Mathieu Chartierf1820852015-07-10 13:19:51 -0700279 gc::Heap* const heap = Runtime::Current()->GetHeap();
280 // Caller's responsibility to do GC if desired.
Mathieu Chartier0795f232016-09-27 18:43:30 -0700281 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(javaClass);
Mathieu Chartier412c7fc2014-02-07 12:18:39 -0800282 if (c == nullptr) {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700283 return 0;
284 }
Mathieu Chartiere8a3c572016-10-11 16:52:17 -0700285 VariableSizedHandleScope hs(soa.Self());
Mathieu Chartier9d156d52016-10-06 17:44:26 -0700286 std::vector<Handle<mirror::Class>> classes {hs.NewHandle(c)};
Elliott Hughesec0f83d2013-01-15 16:54:08 -0800287 uint64_t count = 0;
Mathieu Chartier412c7fc2014-02-07 12:18:39 -0800288 heap->CountInstances(classes, countAssignable, &count);
Elliott Hughesec0f83d2013-01-15 16:54:08 -0800289 return count;
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700290}
291
Mathieu Chartier9d156d52016-10-06 17:44:26 -0700292static jlongArray VMDebug_countInstancesOfClasses(JNIEnv* env,
293 jclass,
294 jobjectArray javaClasses,
Mathieu Chartierf1820852015-07-10 13:19:51 -0700295 jboolean countAssignable) {
296 ScopedObjectAccess soa(env);
297 gc::Heap* const heap = Runtime::Current()->GetHeap();
298 // Caller's responsibility to do GC if desired.
Mathieu Chartier0795f232016-09-27 18:43:30 -0700299 ObjPtr<mirror::ObjectArray<mirror::Class>> decoded_classes =
300 soa.Decode<mirror::ObjectArray<mirror::Class>>(javaClasses);
Mathieu Chartierf1820852015-07-10 13:19:51 -0700301 if (decoded_classes == nullptr) {
302 return nullptr;
303 }
Mathieu Chartiere8a3c572016-10-11 16:52:17 -0700304 VariableSizedHandleScope hs(soa.Self());
Mathieu Chartier9d156d52016-10-06 17:44:26 -0700305 std::vector<Handle<mirror::Class>> classes;
Mathieu Chartierf1820852015-07-10 13:19:51 -0700306 for (size_t i = 0, count = decoded_classes->GetLength(); i < count; ++i) {
Mathieu Chartier9d156d52016-10-06 17:44:26 -0700307 classes.push_back(hs.NewHandle(decoded_classes->Get(i)));
Mathieu Chartierf1820852015-07-10 13:19:51 -0700308 }
309 std::vector<uint64_t> counts(classes.size(), 0u);
310 // Heap::CountInstances can handle null and will put 0 for these classes.
311 heap->CountInstances(classes, countAssignable, &counts[0]);
Mathieu Chartier9d156d52016-10-06 17:44:26 -0700312 ObjPtr<mirror::LongArray> long_counts = mirror::LongArray::Alloc(soa.Self(), counts.size());
Mathieu Chartierf1820852015-07-10 13:19:51 -0700313 if (long_counts == nullptr) {
314 soa.Self()->AssertPendingOOMException();
315 return nullptr;
316 }
317 for (size_t i = 0; i < counts.size(); ++i) {
318 long_counts->Set(i, counts[i]);
319 }
320 return soa.AddLocalReference<jlongArray>(long_counts);
321}
322
Richard Uhler660be6f2017-11-22 16:12:29 +0000323static jobjectArray VMDebug_getInstancesOfClasses(JNIEnv* env,
324 jclass,
325 jobjectArray javaClasses,
326 jboolean includeAssignable) {
327 ScopedObjectAccess soa(env);
328 StackHandleScope<2> hs(soa.Self());
329 Handle<mirror::ObjectArray<mirror::Class>> classes = hs.NewHandle(
330 soa.Decode<mirror::ObjectArray<mirror::Class>>(javaClasses));
331 if (classes == nullptr) {
332 return nullptr;
333 }
334
335 jclass object_array_class = env->FindClass("[Ljava/lang/Object;");
336 if (env->ExceptionCheck() == JNI_TRUE) {
337 return nullptr;
338 }
339 CHECK(object_array_class != nullptr);
340
341 size_t num_classes = classes->GetLength();
342 jobjectArray result = env->NewObjectArray(num_classes, object_array_class, nullptr);
343 if (env->ExceptionCheck() == JNI_TRUE) {
344 return nullptr;
345 }
346
347 gc::Heap* const heap = Runtime::Current()->GetHeap();
348 MutableHandle<mirror::Class> h_class(hs.NewHandle<mirror::Class>(nullptr));
349 for (size_t i = 0; i < num_classes; ++i) {
350 h_class.Assign(classes->Get(i));
351
352 VariableSizedHandleScope hs2(soa.Self());
353 std::vector<Handle<mirror::Object>> raw_instances;
354 heap->GetInstances(hs2, h_class, includeAssignable, /* max_count */ 0, raw_instances);
355 jobjectArray array = env->NewObjectArray(raw_instances.size(),
356 WellKnownClasses::java_lang_Object,
357 nullptr);
358 if (env->ExceptionCheck() == JNI_TRUE) {
359 return nullptr;
360 }
361
362 for (size_t j = 0; j < raw_instances.size(); ++j) {
363 env->SetObjectArrayElement(array, j, raw_instances[j].ToJObject());
364 }
365 env->SetObjectArrayElement(result, i, array);
366 }
367 return result;
368}
369
Hiroshi Yamauchi09b07a92013-07-15 13:17:06 -0700370// We export the VM internal per-heap-space size/alloc/free metrics
371// for the zygote space, alloc space (application heap), and the large
372// object space for dumpsys meminfo. The other memory region data such
373// as PSS, private/shared dirty/shared data are available via
374// /proc/<pid>/smaps.
375static void VMDebug_getHeapSpaceStats(JNIEnv* env, jclass, jlongArray data) {
Ian Rogers6b99dd12013-07-25 12:11:32 -0700376 jlong* arr = reinterpret_cast<jlong*>(env->GetPrimitiveArrayCritical(data, 0));
Mathieu Chartier7410f292013-11-24 13:17:35 -0800377 if (arr == nullptr || env->GetArrayLength(data) < 9) {
Hiroshi Yamauchi09b07a92013-07-15 13:17:06 -0700378 return;
379 }
380
381 size_t allocSize = 0;
382 size_t allocUsed = 0;
383 size_t zygoteSize = 0;
384 size_t zygoteUsed = 0;
385 size_t largeObjectsSize = 0;
386 size_t largeObjectsUsed = 0;
Hiroshi Yamauchi09b07a92013-07-15 13:17:06 -0700387 gc::Heap* heap = Runtime::Current()->GetHeap();
Mathieu Chartiera9d82fe2016-01-25 20:06:11 -0800388 {
389 ScopedObjectAccess soa(env);
390 for (gc::space::ContinuousSpace* space : heap->GetContinuousSpaces()) {
391 if (space->IsImageSpace()) {
392 // Currently don't include the image space.
393 } else if (space->IsZygoteSpace()) {
394 gc::space::ZygoteSpace* zygote_space = space->AsZygoteSpace();
395 zygoteSize += zygote_space->Size();
396 zygoteUsed += zygote_space->GetBytesAllocated();
397 } else if (space->IsMallocSpace()) {
398 // This is a malloc space.
399 gc::space::MallocSpace* malloc_space = space->AsMallocSpace();
400 allocSize += malloc_space->GetFootprint();
401 allocUsed += malloc_space->GetBytesAllocated();
402 } else if (space->IsBumpPointerSpace()) {
403 gc::space::BumpPointerSpace* bump_pointer_space = space->AsBumpPointerSpace();
404 allocSize += bump_pointer_space->Size();
405 allocUsed += bump_pointer_space->GetBytesAllocated();
406 }
407 }
408 for (gc::space::DiscontinuousSpace* space : heap->GetDiscontinuousSpaces()) {
409 if (space->IsLargeObjectSpace()) {
410 largeObjectsSize += space->AsLargeObjectSpace()->GetBytesAllocated();
411 largeObjectsUsed += largeObjectsSize;
412 }
Hiroshi Yamauchi09b07a92013-07-15 13:17:06 -0700413 }
414 }
Hiroshi Yamauchi09b07a92013-07-15 13:17:06 -0700415 size_t allocFree = allocSize - allocUsed;
416 size_t zygoteFree = zygoteSize - zygoteUsed;
417 size_t largeObjectsFree = largeObjectsSize - largeObjectsUsed;
418
419 int j = 0;
420 arr[j++] = allocSize;
421 arr[j++] = allocUsed;
422 arr[j++] = allocFree;
423 arr[j++] = zygoteSize;
424 arr[j++] = zygoteUsed;
425 arr[j++] = zygoteFree;
426 arr[j++] = largeObjectsSize;
427 arr[j++] = largeObjectsUsed;
428 arr[j++] = largeObjectsFree;
429 env->ReleasePrimitiveArrayCritical(data, arr, 0);
430}
431
Hiroshi Yamauchia1c9f012015-04-02 10:18:12 -0700432// The runtime stat names for VMDebug.getRuntimeStat().
433enum class VMDebugRuntimeStatId {
434 kArtGcGcCount = 0,
435 kArtGcGcTime,
436 kArtGcBytesAllocated,
437 kArtGcBytesFreed,
438 kArtGcBlockingGcCount,
439 kArtGcBlockingGcTime,
440 kArtGcGcCountRateHistogram,
441 kArtGcBlockingGcCountRateHistogram,
442 kNumRuntimeStats,
443};
444
Igor Murashkin06537f72018-02-22 15:03:05 -0800445static jstring VMDebug_getRuntimeStatInternal(JNIEnv* env, jclass, jint statId) {
Hiroshi Yamauchia1c9f012015-04-02 10:18:12 -0700446 gc::Heap* heap = Runtime::Current()->GetHeap();
447 switch (static_cast<VMDebugRuntimeStatId>(statId)) {
448 case VMDebugRuntimeStatId::kArtGcGcCount: {
449 std::string output = std::to_string(heap->GetGcCount());
450 return env->NewStringUTF(output.c_str());
451 }
452 case VMDebugRuntimeStatId::kArtGcGcTime: {
453 std::string output = std::to_string(NsToMs(heap->GetGcTime()));
454 return env->NewStringUTF(output.c_str());
455 }
456 case VMDebugRuntimeStatId::kArtGcBytesAllocated: {
457 std::string output = std::to_string(heap->GetBytesAllocatedEver());
458 return env->NewStringUTF(output.c_str());
459 }
460 case VMDebugRuntimeStatId::kArtGcBytesFreed: {
461 std::string output = std::to_string(heap->GetBytesFreedEver());
462 return env->NewStringUTF(output.c_str());
463 }
464 case VMDebugRuntimeStatId::kArtGcBlockingGcCount: {
465 std::string output = std::to_string(heap->GetBlockingGcCount());
466 return env->NewStringUTF(output.c_str());
467 }
468 case VMDebugRuntimeStatId::kArtGcBlockingGcTime: {
469 std::string output = std::to_string(NsToMs(heap->GetBlockingGcTime()));
470 return env->NewStringUTF(output.c_str());
471 }
472 case VMDebugRuntimeStatId::kArtGcGcCountRateHistogram: {
473 std::ostringstream output;
474 heap->DumpGcCountRateHistogram(output);
475 return env->NewStringUTF(output.str().c_str());
476 }
477 case VMDebugRuntimeStatId::kArtGcBlockingGcCountRateHistogram: {
478 std::ostringstream output;
479 heap->DumpBlockingGcCountRateHistogram(output);
480 return env->NewStringUTF(output.str().c_str());
481 }
482 default:
483 return nullptr;
484 }
485}
486
Andreas Gampeca620d72016-11-08 08:09:33 -0800487static bool SetRuntimeStatValue(JNIEnv* env,
488 jobjectArray result,
489 VMDebugRuntimeStatId id,
490 const std::string& value) {
Hiroshi Yamauchia1c9f012015-04-02 10:18:12 -0700491 ScopedLocalRef<jstring> jvalue(env, env->NewStringUTF(value.c_str()));
492 if (jvalue.get() == nullptr) {
493 return false;
494 }
495 env->SetObjectArrayElement(result, static_cast<jint>(id), jvalue.get());
496 return true;
497}
498
499static jobjectArray VMDebug_getRuntimeStatsInternal(JNIEnv* env, jclass) {
500 jobjectArray result = env->NewObjectArray(
501 static_cast<jint>(VMDebugRuntimeStatId::kNumRuntimeStats),
502 WellKnownClasses::java_lang_String,
503 nullptr);
504 if (result == nullptr) {
505 return nullptr;
506 }
507 gc::Heap* heap = Runtime::Current()->GetHeap();
508 if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcGcCount,
509 std::to_string(heap->GetGcCount()))) {
510 return nullptr;
511 }
512 if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcGcTime,
513 std::to_string(NsToMs(heap->GetGcTime())))) {
514 return nullptr;
515 }
516 if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcBytesAllocated,
517 std::to_string(heap->GetBytesAllocatedEver()))) {
518 return nullptr;
519 }
520 if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcBytesFreed,
521 std::to_string(heap->GetBytesFreedEver()))) {
522 return nullptr;
523 }
524 if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcBlockingGcCount,
525 std::to_string(heap->GetBlockingGcCount()))) {
526 return nullptr;
527 }
528 if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcBlockingGcTime,
529 std::to_string(NsToMs(heap->GetBlockingGcTime())))) {
530 return nullptr;
531 }
532 {
533 std::ostringstream output;
534 heap->DumpGcCountRateHistogram(output);
535 if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcGcCountRateHistogram,
536 output.str())) {
537 return nullptr;
538 }
539 }
540 {
541 std::ostringstream output;
542 heap->DumpBlockingGcCountRateHistogram(output);
543 if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcBlockingGcCountRateHistogram,
544 output.str())) {
545 return nullptr;
546 }
547 }
548 return result;
549}
550
Andreas Gampe7b38e692017-12-28 19:18:28 -0800551static void VMDebug_nativeAttachAgent(JNIEnv* env, jclass, jstring agent, jobject classloader) {
Leonard Mosescueb842212016-10-06 17:26:36 -0700552 if (agent == nullptr) {
553 ScopedObjectAccess soa(env);
554 ThrowNullPointerException("agent is null");
555 return;
556 }
557
558 if (!Dbg::IsJdwpAllowed()) {
559 ScopedObjectAccess soa(env);
560 ThrowSecurityException("Can't attach agent, process is not debuggable.");
561 return;
562 }
563
564 std::string filename;
565 {
566 ScopedUtfChars chars(env, agent);
567 if (env->ExceptionCheck()) {
568 return;
569 }
570 filename = chars.c_str();
571 }
572
Andreas Gampe7b38e692017-12-28 19:18:28 -0800573 Runtime::Current()->AttachAgent(env, filename, classloader);
Leonard Mosescueb842212016-10-06 17:26:36 -0700574}
575
Elliott Hughes0512f022012-03-15 22:10:52 -0700576static JNINativeMethod gMethods[] = {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700577 NATIVE_METHOD(VMDebug, countInstancesOfClass, "(Ljava/lang/Class;Z)J"),
Mathieu Chartierf1820852015-07-10 13:19:51 -0700578 NATIVE_METHOD(VMDebug, countInstancesOfClasses, "([Ljava/lang/Class;Z)[J"),
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700579 NATIVE_METHOD(VMDebug, crash, "()V"),
Andreas Gampead5df102017-10-04 16:31:08 -0700580 NATIVE_METHOD(VMDebug, dumpHprofData, "(Ljava/lang/String;I)V"),
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700581 NATIVE_METHOD(VMDebug, dumpHprofDataDdms, "()V"),
582 NATIVE_METHOD(VMDebug, dumpReferenceTables, "()V"),
583 NATIVE_METHOD(VMDebug, getAllocCount, "(I)I"),
Hiroshi Yamauchi09b07a92013-07-15 13:17:06 -0700584 NATIVE_METHOD(VMDebug, getHeapSpaceStats, "([J)V"),
Richard Uhler660be6f2017-11-22 16:12:29 +0000585 NATIVE_METHOD(VMDebug, getInstancesOfClasses, "([Ljava/lang/Class;Z)[[Ljava/lang/Object;"),
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700586 NATIVE_METHOD(VMDebug, getInstructionCount, "([I)V"),
Igor Murashkin3b6f4402017-02-16 16:13:17 -0800587 FAST_NATIVE_METHOD(VMDebug, getLoadedClassCount, "()I"),
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700588 NATIVE_METHOD(VMDebug, getVmFeatureList, "()[Ljava/lang/String;"),
589 NATIVE_METHOD(VMDebug, infopoint, "(I)V"),
Igor Murashkin3b6f4402017-02-16 16:13:17 -0800590 FAST_NATIVE_METHOD(VMDebug, isDebuggerConnected, "()Z"),
591 FAST_NATIVE_METHOD(VMDebug, isDebuggingEnabled, "()Z"),
Jeff Hao64caa7d2013-08-29 11:18:01 -0700592 NATIVE_METHOD(VMDebug, getMethodTracingMode, "()I"),
Igor Murashkin3b6f4402017-02-16 16:13:17 -0800593 FAST_NATIVE_METHOD(VMDebug, lastDebuggerActivity, "()J"),
594 FAST_NATIVE_METHOD(VMDebug, printLoadedClasses, "(I)V"),
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700595 NATIVE_METHOD(VMDebug, resetAllocCount, "(I)V"),
596 NATIVE_METHOD(VMDebug, resetInstructionCount, "()V"),
597 NATIVE_METHOD(VMDebug, startAllocCounting, "()V"),
598 NATIVE_METHOD(VMDebug, startEmulatorTracing, "()V"),
599 NATIVE_METHOD(VMDebug, startInstructionCounting, "()V"),
Jeff Hao23009dc2013-08-22 15:36:42 -0700600 NATIVE_METHOD(VMDebug, startMethodTracingDdmsImpl, "(IIZI)V"),
Andreas Gampead5df102017-10-04 16:31:08 -0700601 NATIVE_METHOD(VMDebug, startMethodTracingFd, "(Ljava/lang/String;IIIZIZ)V"),
Jeff Hao4044bda2014-01-06 15:50:45 -0800602 NATIVE_METHOD(VMDebug, startMethodTracingFilename, "(Ljava/lang/String;IIZI)V"),
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700603 NATIVE_METHOD(VMDebug, stopAllocCounting, "()V"),
604 NATIVE_METHOD(VMDebug, stopEmulatorTracing, "()V"),
605 NATIVE_METHOD(VMDebug, stopInstructionCounting, "()V"),
606 NATIVE_METHOD(VMDebug, stopMethodTracing, "()V"),
Igor Murashkin3b6f4402017-02-16 16:13:17 -0800607 FAST_NATIVE_METHOD(VMDebug, threadCpuTimeNanos, "()J"),
Hiroshi Yamauchia1c9f012015-04-02 10:18:12 -0700608 NATIVE_METHOD(VMDebug, getRuntimeStatInternal, "(I)Ljava/lang/String;"),
Leonard Mosescueb842212016-10-06 17:26:36 -0700609 NATIVE_METHOD(VMDebug, getRuntimeStatsInternal, "()[Ljava/lang/String;"),
Andreas Gampe7b38e692017-12-28 19:18:28 -0800610 NATIVE_METHOD(VMDebug, nativeAttachAgent, "(Ljava/lang/String;Ljava/lang/ClassLoader;)V"),
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700611};
612
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700613void register_dalvik_system_VMDebug(JNIEnv* env) {
Elliott Hugheseac76672012-05-24 21:56:51 -0700614 REGISTER_NATIVE_METHODS("dalvik/system/VMDebug");
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700615}
616
617} // namespace art