blob: 2a5ab1186424122dba55c054955912a9f6ae787b [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
Andreas Gampedfcd82c2018-10-16 20:22:37 -070026#include "base/file_utils.h"
Hiroshi Yamauchia1c9f012015-04-02 10:18:12 -070027#include "base/histogram-inl.h"
Vladimir Marko80afd022015-05-19 18:08:00 +010028#include "base/time_utils.h"
Elliott Hugheseac76672012-05-24 21:56:51 -070029#include "class_linker.h"
Ian Rogers62d6c772013-02-27 08:32:07 -080030#include "common_throws.h"
Elliott Hugheseac76672012-05-24 21:56:51 -070031#include "debugger.h"
Mathieu Chartier7410f292013-11-24 13:17:35 -080032#include "gc/space/bump_pointer_space.h"
Hiroshi Yamauchi09b07a92013-07-15 13:17:06 -070033#include "gc/space/dlmalloc_space.h"
34#include "gc/space/large_object_space.h"
35#include "gc/space/space-inl.h"
Mathieu Chartier1f3b5352014-02-03 14:00:42 -080036#include "gc/space/zygote_space.h"
Andreas Gampec15a2f42017-04-21 12:09:39 -070037#include "handle_scope-inl.h"
Elliott Hugheseac76672012-05-24 21:56:51 -070038#include "hprof/hprof.h"
Vladimir Markoa3ad0cd2018-05-04 10:06:38 +010039#include "jni/java_vm_ext.h"
40#include "jni/jni_internal.h"
Andreas Gampe8e0f0432018-10-24 13:38:03 -070041#include "mirror/array-alloc-inl.h"
42#include "mirror/array-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080043#include "mirror/class.h"
Andreas Gampec15a2f42017-04-21 12:09:39 -070044#include "mirror/object_array-inl.h"
Andreas Gampe87583b32017-05-25 11:22:18 -070045#include "native_util.h"
Andreas Gampe373a9b52017-10-18 09:01:57 -070046#include "nativehelper/scoped_local_ref.h"
47#include "nativehelper/scoped_utf_chars.h"
Mathieu Chartier0795f232016-09-27 18:43:30 -070048#include "scoped_fast_native_object_access-inl.h"
Elliott Hugheseac76672012-05-24 21:56:51 -070049#include "trace.h"
Ian Rogersdd157d72014-05-15 14:47:50 -070050#include "well_known_classes.h"
Elliott Hugheseac76672012-05-24 21:56:51 -070051
Elliott Hughes9d5ccec2011-09-19 13:19:50 -070052namespace art {
53
Elliott Hughes0512f022012-03-15 22:10:52 -070054static jobjectArray VMDebug_getVmFeatureList(JNIEnv* env, jclass) {
Ian Rogersdd157d72014-05-15 14:47:50 -070055 static const char* features[] = {
56 "method-trace-profiling",
57 "method-trace-profiling-streaming",
58 "method-sample-profiling",
59 "hprof-heap-dump",
60 "hprof-heap-dump-streaming",
61 };
62 jobjectArray result = env->NewObjectArray(arraysize(features),
63 WellKnownClasses::java_lang_String,
64 nullptr);
65 if (result != nullptr) {
66 for (size_t i = 0; i < arraysize(features); ++i) {
67 ScopedLocalRef<jstring> jfeature(env, env->NewStringUTF(features[i]));
68 if (jfeature.get() == nullptr) {
69 return nullptr;
70 }
71 env->SetObjectArrayElement(result, i, jfeature.get());
72 }
73 }
74 return result;
Elliott Hughes9d5ccec2011-09-19 13:19:50 -070075}
76
Elliott Hughes0512f022012-03-15 22:10:52 -070077static void VMDebug_startAllocCounting(JNIEnv*, jclass) {
Mathieu Chartier9ef78b52014-09-25 17:03:12 -070078 Runtime::Current()->SetStatsEnabled(true);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -070079}
80
Elliott Hughes0512f022012-03-15 22:10:52 -070081static void VMDebug_stopAllocCounting(JNIEnv*, jclass) {
Mathieu Chartier9ef78b52014-09-25 17:03:12 -070082 Runtime::Current()->SetStatsEnabled(false);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -070083}
84
Elliott Hughes1bac54f2012-03-16 12:48:31 -070085static jint VMDebug_getAllocCount(JNIEnv*, jclass, jint kind) {
Andreas Gampe7ee607e2019-07-23 12:22:04 -070086 return static_cast<jint>(Runtime::Current()->GetStat(kind));
Elliott Hughes9d5ccec2011-09-19 13:19:50 -070087}
88
Elliott Hughes0512f022012-03-15 22:10:52 -070089static void VMDebug_resetAllocCount(JNIEnv*, jclass, jint kinds) {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -070090 Runtime::Current()->ResetStats(kinds);
91}
92
Jeff Hao23009dc2013-08-22 15:36:42 -070093static void VMDebug_startMethodTracingDdmsImpl(JNIEnv*, jclass, jint bufferSize, jint flags,
94 jboolean samplingEnabled, jint intervalUs) {
Andreas Gampe6ff3b372018-03-15 08:53:16 -070095 Trace::StartDDMS(bufferSize,
96 flags,
97 samplingEnabled ? Trace::TraceMode::kSampling : Trace::TraceMode::kMethodTracing,
98 intervalUs);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -070099}
100
Andreas Gampe6ff3b372018-03-15 08:53:16 -0700101static void VMDebug_startMethodTracingFd(JNIEnv* env,
102 jclass,
103 jstring javaTraceFilename ATTRIBUTE_UNUSED,
104 jint javaFd,
105 jint bufferSize,
106 jint flags,
107 jboolean samplingEnabled,
108 jint intervalUs,
Shukang Zhouca6e14e2017-01-25 00:35:21 -0800109 jboolean streamingOutput) {
Andreas Gampead5df102017-10-04 16:31:08 -0700110 int originalFd = javaFd;
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700111 if (originalFd < 0) {
Andreas Gampe6ff3b372018-03-15 08:53:16 -0700112 ScopedObjectAccess soa(env);
113 soa.Self()->ThrowNewExceptionF("Ljava/lang/RuntimeException;",
114 "Trace fd is invalid: %d",
115 originalFd);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700116 return;
117 }
118
Andreas Gampedfcd82c2018-10-16 20:22:37 -0700119 int fd = DupCloexec(originalFd);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700120 if (fd < 0) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700121 ScopedObjectAccess soa(env);
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000122 soa.Self()->ThrowNewExceptionF("Ljava/lang/RuntimeException;",
Andreas Gampe6ff3b372018-03-15 08:53:16 -0700123 "dup(%d) failed: %s",
124 originalFd,
125 strerror(errno));
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700126 return;
127 }
128
Andreas Gampe6ff3b372018-03-15 08:53:16 -0700129 // Ignore the traceFilename.
Shukang Zhouca6e14e2017-01-25 00:35:21 -0800130 Trace::TraceOutputMode outputMode = streamingOutput
131 ? Trace::TraceOutputMode::kStreaming
132 : Trace::TraceOutputMode::kFile;
Andreas Gampe6ff3b372018-03-15 08:53:16 -0700133 Trace::Start(fd,
134 bufferSize,
135 flags,
136 outputMode,
Andreas Gampe7e7e0f42015-03-29 15:26:23 -0700137 samplingEnabled ? Trace::TraceMode::kSampling : Trace::TraceMode::kMethodTracing,
138 intervalUs);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700139}
140
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700141static void VMDebug_startMethodTracingFilename(JNIEnv* env, jclass, jstring javaTraceFilename,
Jeff Hao4044bda2014-01-06 15:50:45 -0800142 jint bufferSize, jint flags,
143 jboolean samplingEnabled, jint intervalUs) {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700144 ScopedUtfChars traceFilename(env, javaTraceFilename);
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700145 if (traceFilename.c_str() == nullptr) {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700146 return;
147 }
Andreas Gampe6ff3b372018-03-15 08:53:16 -0700148 Trace::Start(traceFilename.c_str(),
149 bufferSize,
150 flags,
151 Trace::TraceOutputMode::kFile,
Andreas Gampe7e7e0f42015-03-29 15:26:23 -0700152 samplingEnabled ? Trace::TraceMode::kSampling : Trace::TraceMode::kMethodTracing,
153 intervalUs);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700154}
155
Jeff Hao64caa7d2013-08-29 11:18:01 -0700156static jint VMDebug_getMethodTracingMode(JNIEnv*, jclass) {
157 return Trace::GetMethodTracingMode();
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700158}
159
Elliott Hughes0512f022012-03-15 22:10:52 -0700160static void VMDebug_stopMethodTracing(JNIEnv*, jclass) {
jeffhaoe343b762011-12-05 16:36:44 -0800161 Trace::Stop();
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700162}
163
Elliott Hughes0512f022012-03-15 22:10:52 -0700164static void VMDebug_startEmulatorTracing(JNIEnv*, jclass) {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700165 UNIMPLEMENTED(WARNING);
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700166 // dvmEmulatorTraceStart();
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700167}
168
Elliott Hughes0512f022012-03-15 22:10:52 -0700169static void VMDebug_stopEmulatorTracing(JNIEnv*, jclass) {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700170 UNIMPLEMENTED(WARNING);
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700171 // dvmEmulatorTraceStop();
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700172}
173
Elliott Hughes0512f022012-03-15 22:10:52 -0700174static jboolean VMDebug_isDebuggerConnected(JNIEnv*, jclass) {
Elliott Hughesc0f09332012-03-26 13:27:06 -0700175 return Dbg::IsDebuggerActive();
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700176}
177
Alex Light40320712017-12-14 11:52:04 -0800178static jboolean VMDebug_isDebuggingEnabled(JNIEnv* env, jclass) {
179 ScopedObjectAccess soa(env);
180 return Runtime::Current()->GetRuntimeCallbacks()->IsDebuggerConfigured();
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700181}
182
Elliott Hughes0512f022012-03-15 22:10:52 -0700183static jlong VMDebug_lastDebuggerActivity(JNIEnv*, jclass) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700184 return Dbg::LastDebuggerActivity();
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700185}
186
Ian Rogers62d6c772013-02-27 08:32:07 -0800187static void ThrowUnsupportedOperationException(JNIEnv* env) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700188 ScopedObjectAccess soa(env);
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700189 soa.Self()->ThrowNewException("Ljava/lang/UnsupportedOperationException;", nullptr);
Ian Rogers62d6c772013-02-27 08:32:07 -0800190}
191
192static void VMDebug_startInstructionCounting(JNIEnv* env, jclass) {
193 ThrowUnsupportedOperationException(env);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700194}
195
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700196static void VMDebug_stopInstructionCounting(JNIEnv* env, jclass) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800197 ThrowUnsupportedOperationException(env);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700198}
199
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700200static void VMDebug_getInstructionCount(JNIEnv* env, jclass, jintArray /*javaCounts*/) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800201 ThrowUnsupportedOperationException(env);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700202}
203
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700204static void VMDebug_resetInstructionCount(JNIEnv* env, jclass) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800205 ThrowUnsupportedOperationException(env);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700206}
207
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700208static void VMDebug_printLoadedClasses(JNIEnv* env, jclass, jint flags) {
Andreas Gampecc1b5352016-12-01 16:58:38 -0800209 class DumpClassVisitor : public ClassVisitor {
210 public:
211 explicit DumpClassVisitor(int dump_flags) : flags_(dump_flags) {}
212
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100213 bool operator()(ObjPtr<mirror::Class> klass) override REQUIRES_SHARED(Locks::mutator_lock_) {
Andreas Gampecc1b5352016-12-01 16:58:38 -0800214 klass->DumpClass(LOG_STREAM(ERROR), flags_);
215 return true;
216 }
217
218 private:
219 const int flags_;
220 };
221 DumpClassVisitor visitor(flags);
222
Ian Rogers53b8b092014-03-13 23:45:53 -0700223 ScopedFastNativeObjectAccess soa(env);
Andreas Gampecc1b5352016-12-01 16:58:38 -0800224 return Runtime::Current()->GetClassLinker()->VisitClasses(&visitor);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700225}
226
Ian Rogers7dfb28c2013-08-22 08:18:36 -0700227static jint VMDebug_getLoadedClassCount(JNIEnv* env, jclass) {
Ian Rogers53b8b092014-03-13 23:45:53 -0700228 ScopedFastNativeObjectAccess soa(env);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700229 return Runtime::Current()->GetClassLinker()->NumLoadedClasses();
230}
231
232/*
233 * Returns the thread-specific CPU-time clock value for the current thread,
234 * or -1 if the feature isn't supported.
235 */
Elliott Hughes0512f022012-03-15 22:10:52 -0700236static jlong VMDebug_threadCpuTimeNanos(JNIEnv*, jclass) {
237 return ThreadCpuNanoTime();
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700238}
239
240/*
241 * static void dumpHprofData(String fileName, FileDescriptor fd)
242 *
243 * Cause "hprof" data to be dumped. We can throw an IOException if an
244 * error occurs during file handling.
245 */
Andreas Gampead5df102017-10-04 16:31:08 -0700246static void VMDebug_dumpHprofData(JNIEnv* env, jclass, jstring javaFilename, jint javaFd) {
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700247 // Only one of these may be null.
Andreas Gampead5df102017-10-04 16:31:08 -0700248 if (javaFilename == nullptr && javaFd < 0) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700249 ScopedObjectAccess soa(env);
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000250 ThrowNullPointerException("fileName == null && fd == null");
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700251 return;
252 }
253
254 std::string filename;
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700255 if (javaFilename != nullptr) {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700256 ScopedUtfChars chars(env, javaFilename);
257 if (env->ExceptionCheck()) {
258 return;
259 }
260 filename = chars.c_str();
261 } else {
262 filename = "[fd]";
263 }
264
Andreas Gampead5df102017-10-04 16:31:08 -0700265 int fd = javaFd;
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700266
Elliott Hughes622a6982012-06-08 17:58:54 -0700267 hprof::DumpHeap(filename.c_str(), fd, false);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700268}
269
Elliott Hugheseac76672012-05-24 21:56:51 -0700270static void VMDebug_dumpHprofDataDdms(JNIEnv*, jclass) {
Elliott Hughes622a6982012-06-08 17:58:54 -0700271 hprof::DumpHeap("[DDMS]", -1, true);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700272}
273
Elliott Hughes0512f022012-03-15 22:10:52 -0700274static void VMDebug_dumpReferenceTables(JNIEnv* env, jclass) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700275 ScopedObjectAccess soa(env);
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700276 LOG(INFO) << "--- reference table dump ---";
277
Andreas Gampe3fec9ac2016-09-13 10:47:28 -0700278 soa.Env()->DumpReferenceTables(LOG_STREAM(INFO));
279 soa.Vm()->DumpReferenceTables(LOG_STREAM(INFO));
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700280
281 LOG(INFO) << "---";
282}
283
Elliott Hughes0512f022012-03-15 22:10:52 -0700284static void VMDebug_crash(JNIEnv*, jclass) {
Elliott Hughes81ff3182012-03-23 20:35:56 -0700285 LOG(FATAL) << "Crashing runtime on request";
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700286}
287
Elliott Hughes0512f022012-03-15 22:10:52 -0700288static void VMDebug_infopoint(JNIEnv*, jclass, jint id) {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700289 LOG(INFO) << "VMDebug infopoint " << id << " hit";
290}
291
Mathieu Chartier9d156d52016-10-06 17:44:26 -0700292static jlong VMDebug_countInstancesOfClass(JNIEnv* env,
293 jclass,
294 jclass javaClass,
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700295 jboolean countAssignable) {
296 ScopedObjectAccess soa(env);
Mathieu Chartierf1820852015-07-10 13:19:51 -0700297 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::Class> c = soa.Decode<mirror::Class>(javaClass);
Mathieu Chartier412c7fc2014-02-07 12:18:39 -0800300 if (c == nullptr) {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700301 return 0;
302 }
Mathieu Chartiere8a3c572016-10-11 16:52:17 -0700303 VariableSizedHandleScope hs(soa.Self());
Mathieu Chartier9d156d52016-10-06 17:44:26 -0700304 std::vector<Handle<mirror::Class>> classes {hs.NewHandle(c)};
Elliott Hughesec0f83d2013-01-15 16:54:08 -0800305 uint64_t count = 0;
Mathieu Chartier412c7fc2014-02-07 12:18:39 -0800306 heap->CountInstances(classes, countAssignable, &count);
Elliott Hughesec0f83d2013-01-15 16:54:08 -0800307 return count;
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700308}
309
Mathieu Chartier9d156d52016-10-06 17:44:26 -0700310static jlongArray VMDebug_countInstancesOfClasses(JNIEnv* env,
311 jclass,
312 jobjectArray javaClasses,
Mathieu Chartierf1820852015-07-10 13:19:51 -0700313 jboolean countAssignable) {
314 ScopedObjectAccess soa(env);
315 gc::Heap* const heap = Runtime::Current()->GetHeap();
316 // Caller's responsibility to do GC if desired.
Mathieu Chartier0795f232016-09-27 18:43:30 -0700317 ObjPtr<mirror::ObjectArray<mirror::Class>> decoded_classes =
318 soa.Decode<mirror::ObjectArray<mirror::Class>>(javaClasses);
Mathieu Chartierf1820852015-07-10 13:19:51 -0700319 if (decoded_classes == nullptr) {
320 return nullptr;
321 }
Mathieu Chartiere8a3c572016-10-11 16:52:17 -0700322 VariableSizedHandleScope hs(soa.Self());
Mathieu Chartier9d156d52016-10-06 17:44:26 -0700323 std::vector<Handle<mirror::Class>> classes;
Mathieu Chartierf1820852015-07-10 13:19:51 -0700324 for (size_t i = 0, count = decoded_classes->GetLength(); i < count; ++i) {
Mathieu Chartier9d156d52016-10-06 17:44:26 -0700325 classes.push_back(hs.NewHandle(decoded_classes->Get(i)));
Mathieu Chartierf1820852015-07-10 13:19:51 -0700326 }
327 std::vector<uint64_t> counts(classes.size(), 0u);
328 // Heap::CountInstances can handle null and will put 0 for these classes.
329 heap->CountInstances(classes, countAssignable, &counts[0]);
Mathieu Chartier9d156d52016-10-06 17:44:26 -0700330 ObjPtr<mirror::LongArray> long_counts = mirror::LongArray::Alloc(soa.Self(), counts.size());
Mathieu Chartierf1820852015-07-10 13:19:51 -0700331 if (long_counts == nullptr) {
332 soa.Self()->AssertPendingOOMException();
333 return nullptr;
334 }
335 for (size_t i = 0; i < counts.size(); ++i) {
336 long_counts->Set(i, counts[i]);
337 }
338 return soa.AddLocalReference<jlongArray>(long_counts);
339}
340
Richard Uhler660be6f2017-11-22 16:12:29 +0000341static jobjectArray VMDebug_getInstancesOfClasses(JNIEnv* env,
342 jclass,
343 jobjectArray javaClasses,
344 jboolean includeAssignable) {
345 ScopedObjectAccess soa(env);
346 StackHandleScope<2> hs(soa.Self());
347 Handle<mirror::ObjectArray<mirror::Class>> classes = hs.NewHandle(
348 soa.Decode<mirror::ObjectArray<mirror::Class>>(javaClasses));
349 if (classes == nullptr) {
350 return nullptr;
351 }
352
353 jclass object_array_class = env->FindClass("[Ljava/lang/Object;");
354 if (env->ExceptionCheck() == JNI_TRUE) {
355 return nullptr;
356 }
357 CHECK(object_array_class != nullptr);
358
359 size_t num_classes = classes->GetLength();
360 jobjectArray result = env->NewObjectArray(num_classes, object_array_class, nullptr);
361 if (env->ExceptionCheck() == JNI_TRUE) {
362 return nullptr;
363 }
364
365 gc::Heap* const heap = Runtime::Current()->GetHeap();
366 MutableHandle<mirror::Class> h_class(hs.NewHandle<mirror::Class>(nullptr));
367 for (size_t i = 0; i < num_classes; ++i) {
368 h_class.Assign(classes->Get(i));
369
370 VariableSizedHandleScope hs2(soa.Self());
371 std::vector<Handle<mirror::Object>> raw_instances;
Andreas Gampe98ea9d92018-10-19 14:06:15 -0700372 heap->GetInstances(hs2, h_class, includeAssignable, /* max_count= */ 0, raw_instances);
Richard Uhler660be6f2017-11-22 16:12:29 +0000373 jobjectArray array = env->NewObjectArray(raw_instances.size(),
374 WellKnownClasses::java_lang_Object,
375 nullptr);
376 if (env->ExceptionCheck() == JNI_TRUE) {
377 return nullptr;
378 }
379
380 for (size_t j = 0; j < raw_instances.size(); ++j) {
381 env->SetObjectArrayElement(array, j, raw_instances[j].ToJObject());
382 }
383 env->SetObjectArrayElement(result, i, array);
384 }
385 return result;
386}
387
Hiroshi Yamauchi09b07a92013-07-15 13:17:06 -0700388// We export the VM internal per-heap-space size/alloc/free metrics
389// for the zygote space, alloc space (application heap), and the large
390// object space for dumpsys meminfo. The other memory region data such
391// as PSS, private/shared dirty/shared data are available via
392// /proc/<pid>/smaps.
393static void VMDebug_getHeapSpaceStats(JNIEnv* env, jclass, jlongArray data) {
Yi Kong4b22b342018-08-02 14:43:21 -0700394 jlong* arr = reinterpret_cast<jlong*>(env->GetPrimitiveArrayCritical(data, nullptr));
Mathieu Chartier7410f292013-11-24 13:17:35 -0800395 if (arr == nullptr || env->GetArrayLength(data) < 9) {
Hiroshi Yamauchi09b07a92013-07-15 13:17:06 -0700396 return;
397 }
398
399 size_t allocSize = 0;
400 size_t allocUsed = 0;
401 size_t zygoteSize = 0;
402 size_t zygoteUsed = 0;
403 size_t largeObjectsSize = 0;
404 size_t largeObjectsUsed = 0;
Hiroshi Yamauchi09b07a92013-07-15 13:17:06 -0700405 gc::Heap* heap = Runtime::Current()->GetHeap();
Mathieu Chartiera9d82fe2016-01-25 20:06:11 -0800406 {
407 ScopedObjectAccess soa(env);
408 for (gc::space::ContinuousSpace* space : heap->GetContinuousSpaces()) {
409 if (space->IsImageSpace()) {
410 // Currently don't include the image space.
411 } else if (space->IsZygoteSpace()) {
412 gc::space::ZygoteSpace* zygote_space = space->AsZygoteSpace();
413 zygoteSize += zygote_space->Size();
414 zygoteUsed += zygote_space->GetBytesAllocated();
415 } else if (space->IsMallocSpace()) {
416 // This is a malloc space.
417 gc::space::MallocSpace* malloc_space = space->AsMallocSpace();
418 allocSize += malloc_space->GetFootprint();
419 allocUsed += malloc_space->GetBytesAllocated();
420 } else if (space->IsBumpPointerSpace()) {
421 gc::space::BumpPointerSpace* bump_pointer_space = space->AsBumpPointerSpace();
422 allocSize += bump_pointer_space->Size();
423 allocUsed += bump_pointer_space->GetBytesAllocated();
424 }
425 }
426 for (gc::space::DiscontinuousSpace* space : heap->GetDiscontinuousSpaces()) {
427 if (space->IsLargeObjectSpace()) {
428 largeObjectsSize += space->AsLargeObjectSpace()->GetBytesAllocated();
429 largeObjectsUsed += largeObjectsSize;
430 }
Hiroshi Yamauchi09b07a92013-07-15 13:17:06 -0700431 }
432 }
Hiroshi Yamauchi09b07a92013-07-15 13:17:06 -0700433 size_t allocFree = allocSize - allocUsed;
434 size_t zygoteFree = zygoteSize - zygoteUsed;
435 size_t largeObjectsFree = largeObjectsSize - largeObjectsUsed;
436
437 int j = 0;
438 arr[j++] = allocSize;
439 arr[j++] = allocUsed;
440 arr[j++] = allocFree;
441 arr[j++] = zygoteSize;
442 arr[j++] = zygoteUsed;
443 arr[j++] = zygoteFree;
444 arr[j++] = largeObjectsSize;
445 arr[j++] = largeObjectsUsed;
446 arr[j++] = largeObjectsFree;
447 env->ReleasePrimitiveArrayCritical(data, arr, 0);
448}
449
Hiroshi Yamauchia1c9f012015-04-02 10:18:12 -0700450// The runtime stat names for VMDebug.getRuntimeStat().
451enum class VMDebugRuntimeStatId {
452 kArtGcGcCount = 0,
453 kArtGcGcTime,
454 kArtGcBytesAllocated,
455 kArtGcBytesFreed,
456 kArtGcBlockingGcCount,
457 kArtGcBlockingGcTime,
458 kArtGcGcCountRateHistogram,
459 kArtGcBlockingGcCountRateHistogram,
460 kNumRuntimeStats,
461};
462
Igor Murashkin06537f72018-02-22 15:03:05 -0800463static jstring VMDebug_getRuntimeStatInternal(JNIEnv* env, jclass, jint statId) {
Hiroshi Yamauchia1c9f012015-04-02 10:18:12 -0700464 gc::Heap* heap = Runtime::Current()->GetHeap();
465 switch (static_cast<VMDebugRuntimeStatId>(statId)) {
466 case VMDebugRuntimeStatId::kArtGcGcCount: {
467 std::string output = std::to_string(heap->GetGcCount());
468 return env->NewStringUTF(output.c_str());
469 }
470 case VMDebugRuntimeStatId::kArtGcGcTime: {
471 std::string output = std::to_string(NsToMs(heap->GetGcTime()));
472 return env->NewStringUTF(output.c_str());
473 }
474 case VMDebugRuntimeStatId::kArtGcBytesAllocated: {
475 std::string output = std::to_string(heap->GetBytesAllocatedEver());
476 return env->NewStringUTF(output.c_str());
477 }
478 case VMDebugRuntimeStatId::kArtGcBytesFreed: {
479 std::string output = std::to_string(heap->GetBytesFreedEver());
480 return env->NewStringUTF(output.c_str());
481 }
482 case VMDebugRuntimeStatId::kArtGcBlockingGcCount: {
483 std::string output = std::to_string(heap->GetBlockingGcCount());
484 return env->NewStringUTF(output.c_str());
485 }
486 case VMDebugRuntimeStatId::kArtGcBlockingGcTime: {
487 std::string output = std::to_string(NsToMs(heap->GetBlockingGcTime()));
488 return env->NewStringUTF(output.c_str());
489 }
490 case VMDebugRuntimeStatId::kArtGcGcCountRateHistogram: {
491 std::ostringstream output;
492 heap->DumpGcCountRateHistogram(output);
493 return env->NewStringUTF(output.str().c_str());
494 }
495 case VMDebugRuntimeStatId::kArtGcBlockingGcCountRateHistogram: {
496 std::ostringstream output;
497 heap->DumpBlockingGcCountRateHistogram(output);
498 return env->NewStringUTF(output.str().c_str());
499 }
500 default:
501 return nullptr;
502 }
503}
504
Andreas Gampeca620d72016-11-08 08:09:33 -0800505static bool SetRuntimeStatValue(JNIEnv* env,
506 jobjectArray result,
507 VMDebugRuntimeStatId id,
508 const std::string& value) {
Hiroshi Yamauchia1c9f012015-04-02 10:18:12 -0700509 ScopedLocalRef<jstring> jvalue(env, env->NewStringUTF(value.c_str()));
510 if (jvalue.get() == nullptr) {
511 return false;
512 }
513 env->SetObjectArrayElement(result, static_cast<jint>(id), jvalue.get());
514 return true;
515}
516
517static jobjectArray VMDebug_getRuntimeStatsInternal(JNIEnv* env, jclass) {
518 jobjectArray result = env->NewObjectArray(
519 static_cast<jint>(VMDebugRuntimeStatId::kNumRuntimeStats),
520 WellKnownClasses::java_lang_String,
521 nullptr);
522 if (result == nullptr) {
523 return nullptr;
524 }
525 gc::Heap* heap = Runtime::Current()->GetHeap();
526 if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcGcCount,
527 std::to_string(heap->GetGcCount()))) {
528 return nullptr;
529 }
530 if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcGcTime,
531 std::to_string(NsToMs(heap->GetGcTime())))) {
532 return nullptr;
533 }
534 if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcBytesAllocated,
535 std::to_string(heap->GetBytesAllocatedEver()))) {
536 return nullptr;
537 }
538 if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcBytesFreed,
539 std::to_string(heap->GetBytesFreedEver()))) {
540 return nullptr;
541 }
542 if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcBlockingGcCount,
543 std::to_string(heap->GetBlockingGcCount()))) {
544 return nullptr;
545 }
546 if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcBlockingGcTime,
547 std::to_string(NsToMs(heap->GetBlockingGcTime())))) {
548 return nullptr;
549 }
550 {
551 std::ostringstream output;
552 heap->DumpGcCountRateHistogram(output);
553 if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcGcCountRateHistogram,
554 output.str())) {
555 return nullptr;
556 }
557 }
558 {
559 std::ostringstream output;
560 heap->DumpBlockingGcCountRateHistogram(output);
561 if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcBlockingGcCountRateHistogram,
562 output.str())) {
563 return nullptr;
564 }
565 }
566 return result;
567}
568
Andreas Gampe7b38e692017-12-28 19:18:28 -0800569static void VMDebug_nativeAttachAgent(JNIEnv* env, jclass, jstring agent, jobject classloader) {
Leonard Mosescueb842212016-10-06 17:26:36 -0700570 if (agent == nullptr) {
571 ScopedObjectAccess soa(env);
572 ThrowNullPointerException("agent is null");
573 return;
574 }
575
576 if (!Dbg::IsJdwpAllowed()) {
577 ScopedObjectAccess soa(env);
578 ThrowSecurityException("Can't attach agent, process is not debuggable.");
579 return;
580 }
581
582 std::string filename;
583 {
584 ScopedUtfChars chars(env, agent);
585 if (env->ExceptionCheck()) {
586 return;
587 }
588 filename = chars.c_str();
589 }
590
Andreas Gampe7b38e692017-12-28 19:18:28 -0800591 Runtime::Current()->AttachAgent(env, filename, classloader);
Leonard Mosescueb842212016-10-06 17:26:36 -0700592}
593
David Brazdil59a49a62018-05-09 10:58:27 +0100594static void VMDebug_allowHiddenApiReflectionFrom(JNIEnv* env, jclass, jclass j_caller) {
595 Runtime* runtime = Runtime::Current();
596 ScopedObjectAccess soa(env);
597
598 if (!runtime->IsJavaDebuggable()) {
599 ThrowSecurityException("Can't exempt class, process is not debuggable.");
600 return;
601 }
602
603 StackHandleScope<1> hs(soa.Self());
604 Handle<mirror::Class> h_caller(hs.NewHandle(soa.Decode<mirror::Class>(j_caller)));
605 if (h_caller.IsNull()) {
606 ThrowNullPointerException("argument is null");
607 return;
608 }
609
610 h_caller->SetSkipHiddenApiChecks();
611}
612
Mathieu Chartier0a206072019-03-28 12:29:22 -0700613static void VMDebug_setAllocTrackerStackDepth(JNIEnv* env, jclass, jint stack_depth) {
614 Runtime* runtime = Runtime::Current();
615 if (stack_depth < 0 ||
616 static_cast<size_t>(stack_depth) > gc::AllocRecordObjectMap::kMaxSupportedStackDepth) {
617 ScopedObjectAccess soa(env);
618 soa.Self()->ThrowNewExceptionF("Ljava/lang/RuntimeException;",
619 "Stack depth is invalid: %d",
620 stack_depth);
621 } else {
622 runtime->GetHeap()->SetAllocTrackerStackDepth(static_cast<size_t>(stack_depth));
623 }
624}
625
Elliott Hughes0512f022012-03-15 22:10:52 -0700626static JNINativeMethod gMethods[] = {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700627 NATIVE_METHOD(VMDebug, countInstancesOfClass, "(Ljava/lang/Class;Z)J"),
Mathieu Chartierf1820852015-07-10 13:19:51 -0700628 NATIVE_METHOD(VMDebug, countInstancesOfClasses, "([Ljava/lang/Class;Z)[J"),
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700629 NATIVE_METHOD(VMDebug, crash, "()V"),
Andreas Gampead5df102017-10-04 16:31:08 -0700630 NATIVE_METHOD(VMDebug, dumpHprofData, "(Ljava/lang/String;I)V"),
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700631 NATIVE_METHOD(VMDebug, dumpHprofDataDdms, "()V"),
632 NATIVE_METHOD(VMDebug, dumpReferenceTables, "()V"),
633 NATIVE_METHOD(VMDebug, getAllocCount, "(I)I"),
Hiroshi Yamauchi09b07a92013-07-15 13:17:06 -0700634 NATIVE_METHOD(VMDebug, getHeapSpaceStats, "([J)V"),
Richard Uhler660be6f2017-11-22 16:12:29 +0000635 NATIVE_METHOD(VMDebug, getInstancesOfClasses, "([Ljava/lang/Class;Z)[[Ljava/lang/Object;"),
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700636 NATIVE_METHOD(VMDebug, getInstructionCount, "([I)V"),
Igor Murashkin3b6f4402017-02-16 16:13:17 -0800637 FAST_NATIVE_METHOD(VMDebug, getLoadedClassCount, "()I"),
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700638 NATIVE_METHOD(VMDebug, getVmFeatureList, "()[Ljava/lang/String;"),
639 NATIVE_METHOD(VMDebug, infopoint, "(I)V"),
Igor Murashkin3b6f4402017-02-16 16:13:17 -0800640 FAST_NATIVE_METHOD(VMDebug, isDebuggerConnected, "()Z"),
641 FAST_NATIVE_METHOD(VMDebug, isDebuggingEnabled, "()Z"),
Jeff Hao64caa7d2013-08-29 11:18:01 -0700642 NATIVE_METHOD(VMDebug, getMethodTracingMode, "()I"),
Igor Murashkin3b6f4402017-02-16 16:13:17 -0800643 FAST_NATIVE_METHOD(VMDebug, lastDebuggerActivity, "()J"),
644 FAST_NATIVE_METHOD(VMDebug, printLoadedClasses, "(I)V"),
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700645 NATIVE_METHOD(VMDebug, resetAllocCount, "(I)V"),
646 NATIVE_METHOD(VMDebug, resetInstructionCount, "()V"),
647 NATIVE_METHOD(VMDebug, startAllocCounting, "()V"),
648 NATIVE_METHOD(VMDebug, startEmulatorTracing, "()V"),
649 NATIVE_METHOD(VMDebug, startInstructionCounting, "()V"),
Jeff Hao23009dc2013-08-22 15:36:42 -0700650 NATIVE_METHOD(VMDebug, startMethodTracingDdmsImpl, "(IIZI)V"),
Andreas Gampead5df102017-10-04 16:31:08 -0700651 NATIVE_METHOD(VMDebug, startMethodTracingFd, "(Ljava/lang/String;IIIZIZ)V"),
Jeff Hao4044bda2014-01-06 15:50:45 -0800652 NATIVE_METHOD(VMDebug, startMethodTracingFilename, "(Ljava/lang/String;IIZI)V"),
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700653 NATIVE_METHOD(VMDebug, stopAllocCounting, "()V"),
654 NATIVE_METHOD(VMDebug, stopEmulatorTracing, "()V"),
655 NATIVE_METHOD(VMDebug, stopInstructionCounting, "()V"),
656 NATIVE_METHOD(VMDebug, stopMethodTracing, "()V"),
Igor Murashkin3b6f4402017-02-16 16:13:17 -0800657 FAST_NATIVE_METHOD(VMDebug, threadCpuTimeNanos, "()J"),
Hiroshi Yamauchia1c9f012015-04-02 10:18:12 -0700658 NATIVE_METHOD(VMDebug, getRuntimeStatInternal, "(I)Ljava/lang/String;"),
Leonard Mosescueb842212016-10-06 17:26:36 -0700659 NATIVE_METHOD(VMDebug, getRuntimeStatsInternal, "()[Ljava/lang/String;"),
Andreas Gampe7b38e692017-12-28 19:18:28 -0800660 NATIVE_METHOD(VMDebug, nativeAttachAgent, "(Ljava/lang/String;Ljava/lang/ClassLoader;)V"),
David Brazdil59a49a62018-05-09 10:58:27 +0100661 NATIVE_METHOD(VMDebug, allowHiddenApiReflectionFrom, "(Ljava/lang/Class;)V"),
Mathieu Chartier0a206072019-03-28 12:29:22 -0700662 NATIVE_METHOD(VMDebug, setAllocTrackerStackDepth, "(I)V"),
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700663};
664
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700665void register_dalvik_system_VMDebug(JNIEnv* env) {
Elliott Hugheseac76672012-05-24 21:56:51 -0700666 REGISTER_NATIVE_METHODS("dalvik/system/VMDebug");
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700667}
668
669} // namespace art