xref: /aosp_15_r20/art/runtime/native/dalvik_system_VMDebug.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2008 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #include "dalvik_system_VMDebug.h"
18*795d594fSAndroid Build Coastguard Worker 
19*795d594fSAndroid Build Coastguard Worker #include <string.h>
20*795d594fSAndroid Build Coastguard Worker #include <unistd.h>
21*795d594fSAndroid Build Coastguard Worker 
22*795d594fSAndroid Build Coastguard Worker #include <sstream>
23*795d594fSAndroid Build Coastguard Worker 
24*795d594fSAndroid Build Coastguard Worker #include "base/file_utils.h"
25*795d594fSAndroid Build Coastguard Worker #include "base/histogram-inl.h"
26*795d594fSAndroid Build Coastguard Worker #include "base/time_utils.h"
27*795d594fSAndroid Build Coastguard Worker #include "class_linker.h"
28*795d594fSAndroid Build Coastguard Worker #include "class_root-inl.h"
29*795d594fSAndroid Build Coastguard Worker #include "common_throws.h"
30*795d594fSAndroid Build Coastguard Worker #include "debugger.h"
31*795d594fSAndroid Build Coastguard Worker #include "dex/class_accessor-inl.h"
32*795d594fSAndroid Build Coastguard Worker #include "dex/descriptors_names.h"
33*795d594fSAndroid Build Coastguard Worker #include "gc/space/bump_pointer_space.h"
34*795d594fSAndroid Build Coastguard Worker #include "gc/space/dlmalloc_space.h"
35*795d594fSAndroid Build Coastguard Worker #include "gc/space/large_object_space.h"
36*795d594fSAndroid Build Coastguard Worker #include "gc/space/space-inl.h"
37*795d594fSAndroid Build Coastguard Worker #include "gc/space/zygote_space.h"
38*795d594fSAndroid Build Coastguard Worker #include "handle_scope-inl.h"
39*795d594fSAndroid Build Coastguard Worker #include "hprof/hprof.h"
40*795d594fSAndroid Build Coastguard Worker #include "jni/java_vm_ext.h"
41*795d594fSAndroid Build Coastguard Worker #include "jni/jni_internal.h"
42*795d594fSAndroid Build Coastguard Worker #include "mirror/array-alloc-inl.h"
43*795d594fSAndroid Build Coastguard Worker #include "mirror/array-inl.h"
44*795d594fSAndroid Build Coastguard Worker #include "mirror/class.h"
45*795d594fSAndroid Build Coastguard Worker #include "mirror/executable-inl.h"
46*795d594fSAndroid Build Coastguard Worker #include "mirror/object_array-alloc-inl.h"
47*795d594fSAndroid Build Coastguard Worker #include "native_util.h"
48*795d594fSAndroid Build Coastguard Worker #include "nativehelper/jni_macros.h"
49*795d594fSAndroid Build Coastguard Worker #include "nativehelper/scoped_local_ref.h"
50*795d594fSAndroid Build Coastguard Worker #include "nativehelper/scoped_utf_chars.h"
51*795d594fSAndroid Build Coastguard Worker #include "nativehelper/utils.h"
52*795d594fSAndroid Build Coastguard Worker #include "oat/oat_quick_method_header.h"
53*795d594fSAndroid Build Coastguard Worker #include "scoped_fast_native_object_access-inl.h"
54*795d594fSAndroid Build Coastguard Worker #include "string_array_utils.h"
55*795d594fSAndroid Build Coastguard Worker #include "thread-inl.h"
56*795d594fSAndroid Build Coastguard Worker #include "trace.h"
57*795d594fSAndroid Build Coastguard Worker #include "trace_profile.h"
58*795d594fSAndroid Build Coastguard Worker 
59*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
60*795d594fSAndroid Build Coastguard Worker 
VMDebug_getVmFeatureList(JNIEnv * env,jclass)61*795d594fSAndroid Build Coastguard Worker static jobjectArray VMDebug_getVmFeatureList(JNIEnv* env, jclass) {
62*795d594fSAndroid Build Coastguard Worker   ScopedObjectAccess soa(Thread::ForEnv(env));
63*795d594fSAndroid Build Coastguard Worker   return soa.AddLocalReference<jobjectArray>(
64*795d594fSAndroid Build Coastguard Worker       CreateStringArray(soa.Self(),
65*795d594fSAndroid Build Coastguard Worker                         {
66*795d594fSAndroid Build Coastguard Worker                             "method-trace-profiling",
67*795d594fSAndroid Build Coastguard Worker                             "method-trace-profiling-streaming",
68*795d594fSAndroid Build Coastguard Worker                             "method-sample-profiling",
69*795d594fSAndroid Build Coastguard Worker                             "hprof-heap-dump",
70*795d594fSAndroid Build Coastguard Worker                             "hprof-heap-dump-streaming",
71*795d594fSAndroid Build Coastguard Worker                             "app_info",
72*795d594fSAndroid Build Coastguard Worker                         }));
73*795d594fSAndroid Build Coastguard Worker }
74*795d594fSAndroid Build Coastguard Worker 
VMDebug_startAllocCounting(JNIEnv *,jclass)75*795d594fSAndroid Build Coastguard Worker static void VMDebug_startAllocCounting(JNIEnv*, jclass) {
76*795d594fSAndroid Build Coastguard Worker   Runtime::Current()->SetStatsEnabled(true);
77*795d594fSAndroid Build Coastguard Worker }
78*795d594fSAndroid Build Coastguard Worker 
VMDebug_stopAllocCounting(JNIEnv *,jclass)79*795d594fSAndroid Build Coastguard Worker static void VMDebug_stopAllocCounting(JNIEnv*, jclass) {
80*795d594fSAndroid Build Coastguard Worker   Runtime::Current()->SetStatsEnabled(false);
81*795d594fSAndroid Build Coastguard Worker }
82*795d594fSAndroid Build Coastguard Worker 
VMDebug_getAllocCount(JNIEnv *,jclass,jint kind)83*795d594fSAndroid Build Coastguard Worker static jint VMDebug_getAllocCount(JNIEnv*, jclass, jint kind) {
84*795d594fSAndroid Build Coastguard Worker   return static_cast<jint>(Runtime::Current()->GetStat(kind));
85*795d594fSAndroid Build Coastguard Worker }
86*795d594fSAndroid Build Coastguard Worker 
VMDebug_resetAllocCount(JNIEnv *,jclass,jint kinds)87*795d594fSAndroid Build Coastguard Worker static void VMDebug_resetAllocCount(JNIEnv*, jclass, jint kinds) {
88*795d594fSAndroid Build Coastguard Worker   Runtime::Current()->ResetStats(kinds);
89*795d594fSAndroid Build Coastguard Worker }
90*795d594fSAndroid Build Coastguard Worker 
VMDebug_startMethodTracingDdmsImpl(JNIEnv *,jclass,jint bufferSize,jint flags,jboolean samplingEnabled,jint intervalUs)91*795d594fSAndroid Build Coastguard Worker static void VMDebug_startMethodTracingDdmsImpl(JNIEnv*, jclass, jint bufferSize, jint flags,
92*795d594fSAndroid Build Coastguard Worker                                                jboolean samplingEnabled, jint intervalUs) {
93*795d594fSAndroid Build Coastguard Worker   Trace::StartDDMS(bufferSize,
94*795d594fSAndroid Build Coastguard Worker                    flags,
95*795d594fSAndroid Build Coastguard Worker                    samplingEnabled ? Trace::TraceMode::kSampling : Trace::TraceMode::kMethodTracing,
96*795d594fSAndroid Build Coastguard Worker                    intervalUs);
97*795d594fSAndroid Build Coastguard Worker }
98*795d594fSAndroid Build Coastguard Worker 
VMDebug_startMethodTracingFd(JNIEnv * env,jclass,jstring javaTraceFilename,jint javaFd,jint bufferSize,jint flags,jboolean samplingEnabled,jint intervalUs,jboolean streamingOutput)99*795d594fSAndroid Build Coastguard Worker static void VMDebug_startMethodTracingFd(JNIEnv* env,
100*795d594fSAndroid Build Coastguard Worker                                          jclass,
101*795d594fSAndroid Build Coastguard Worker                                          [[maybe_unused]] jstring javaTraceFilename,
102*795d594fSAndroid Build Coastguard Worker                                          jint javaFd,
103*795d594fSAndroid Build Coastguard Worker                                          jint bufferSize,
104*795d594fSAndroid Build Coastguard Worker                                          jint flags,
105*795d594fSAndroid Build Coastguard Worker                                          jboolean samplingEnabled,
106*795d594fSAndroid Build Coastguard Worker                                          jint intervalUs,
107*795d594fSAndroid Build Coastguard Worker                                          jboolean streamingOutput) {
108*795d594fSAndroid Build Coastguard Worker   int originalFd = javaFd;
109*795d594fSAndroid Build Coastguard Worker   if (originalFd < 0) {
110*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
111*795d594fSAndroid Build Coastguard Worker     soa.Self()->ThrowNewExceptionF("Ljava/lang/RuntimeException;",
112*795d594fSAndroid Build Coastguard Worker                                    "Trace fd is invalid: %d",
113*795d594fSAndroid Build Coastguard Worker                                    originalFd);
114*795d594fSAndroid Build Coastguard Worker     return;
115*795d594fSAndroid Build Coastguard Worker   }
116*795d594fSAndroid Build Coastguard Worker 
117*795d594fSAndroid Build Coastguard Worker   int fd = DupCloexec(originalFd);
118*795d594fSAndroid Build Coastguard Worker   if (fd < 0) {
119*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
120*795d594fSAndroid Build Coastguard Worker     soa.Self()->ThrowNewExceptionF("Ljava/lang/RuntimeException;",
121*795d594fSAndroid Build Coastguard Worker                                    "dup(%d) failed: %s",
122*795d594fSAndroid Build Coastguard Worker                                    originalFd,
123*795d594fSAndroid Build Coastguard Worker                                    strerror(errno));
124*795d594fSAndroid Build Coastguard Worker     return;
125*795d594fSAndroid Build Coastguard Worker   }
126*795d594fSAndroid Build Coastguard Worker 
127*795d594fSAndroid Build Coastguard Worker   // Ignore the traceFilename.
128*795d594fSAndroid Build Coastguard Worker   TraceOutputMode outputMode =
129*795d594fSAndroid Build Coastguard Worker       streamingOutput ? TraceOutputMode::kStreaming : TraceOutputMode::kFile;
130*795d594fSAndroid Build Coastguard Worker   Trace::Start(fd,
131*795d594fSAndroid Build Coastguard Worker                bufferSize,
132*795d594fSAndroid Build Coastguard Worker                flags,
133*795d594fSAndroid Build Coastguard Worker                outputMode,
134*795d594fSAndroid Build Coastguard Worker                samplingEnabled ? Trace::TraceMode::kSampling : Trace::TraceMode::kMethodTracing,
135*795d594fSAndroid Build Coastguard Worker                intervalUs);
136*795d594fSAndroid Build Coastguard Worker }
137*795d594fSAndroid Build Coastguard Worker 
VMDebug_startMethodTracingFilename(JNIEnv * env,jclass,jstring javaTraceFilename,jint bufferSize,jint flags,jboolean samplingEnabled,jint intervalUs)138*795d594fSAndroid Build Coastguard Worker static void VMDebug_startMethodTracingFilename(JNIEnv* env, jclass, jstring javaTraceFilename,
139*795d594fSAndroid Build Coastguard Worker                                                jint bufferSize, jint flags,
140*795d594fSAndroid Build Coastguard Worker                                                jboolean samplingEnabled, jint intervalUs) {
141*795d594fSAndroid Build Coastguard Worker   ScopedUtfChars traceFilename(env, javaTraceFilename);
142*795d594fSAndroid Build Coastguard Worker   if (traceFilename.c_str() == nullptr) {
143*795d594fSAndroid Build Coastguard Worker     return;
144*795d594fSAndroid Build Coastguard Worker   }
145*795d594fSAndroid Build Coastguard Worker   Trace::Start(traceFilename.c_str(),
146*795d594fSAndroid Build Coastguard Worker                bufferSize,
147*795d594fSAndroid Build Coastguard Worker                flags,
148*795d594fSAndroid Build Coastguard Worker                TraceOutputMode::kFile,
149*795d594fSAndroid Build Coastguard Worker                samplingEnabled ? Trace::TraceMode::kSampling : Trace::TraceMode::kMethodTracing,
150*795d594fSAndroid Build Coastguard Worker                intervalUs);
151*795d594fSAndroid Build Coastguard Worker }
152*795d594fSAndroid Build Coastguard Worker 
VMDebug_getMethodTracingMode(JNIEnv *,jclass)153*795d594fSAndroid Build Coastguard Worker static jint VMDebug_getMethodTracingMode(JNIEnv*, jclass) {
154*795d594fSAndroid Build Coastguard Worker   return Trace::GetMethodTracingMode();
155*795d594fSAndroid Build Coastguard Worker }
156*795d594fSAndroid Build Coastguard Worker 
VMDebug_stopMethodTracing(JNIEnv *,jclass)157*795d594fSAndroid Build Coastguard Worker static void VMDebug_stopMethodTracing(JNIEnv*, jclass) {
158*795d594fSAndroid Build Coastguard Worker   Trace::Stop();
159*795d594fSAndroid Build Coastguard Worker }
160*795d594fSAndroid Build Coastguard Worker 
VMDebug_stopLowOverheadTraceImpl(JNIEnv *,jclass)161*795d594fSAndroid Build Coastguard Worker static void VMDebug_stopLowOverheadTraceImpl(JNIEnv*, jclass) {
162*795d594fSAndroid Build Coastguard Worker   TraceProfiler::Stop();
163*795d594fSAndroid Build Coastguard Worker }
164*795d594fSAndroid Build Coastguard Worker 
VMDebug_dumpLowOverheadTraceImpl(JNIEnv * env,jclass,jstring javaProfileFileName)165*795d594fSAndroid Build Coastguard Worker static void VMDebug_dumpLowOverheadTraceImpl(JNIEnv* env, jclass, jstring javaProfileFileName) {
166*795d594fSAndroid Build Coastguard Worker   ScopedUtfChars profileFileName(env, javaProfileFileName);
167*795d594fSAndroid Build Coastguard Worker   if (profileFileName.c_str() == nullptr) {
168*795d594fSAndroid Build Coastguard Worker     LOG(ERROR) << "Filename not provided, ignoring the request to dump low-overhead trace";
169*795d594fSAndroid Build Coastguard Worker     return;
170*795d594fSAndroid Build Coastguard Worker   }
171*795d594fSAndroid Build Coastguard Worker   TraceProfiler::Dump(profileFileName.c_str());
172*795d594fSAndroid Build Coastguard Worker }
173*795d594fSAndroid Build Coastguard Worker 
VMDebug_dumpLowOverheadTraceFdImpl(JNIEnv *,jclass,jint originalFd)174*795d594fSAndroid Build Coastguard Worker static void VMDebug_dumpLowOverheadTraceFdImpl(JNIEnv*, jclass, jint originalFd) {
175*795d594fSAndroid Build Coastguard Worker   if (originalFd < 0) {
176*795d594fSAndroid Build Coastguard Worker     LOG(ERROR) << "Invalid file descriptor, ignoring the request to dump low-overhead trace";
177*795d594fSAndroid Build Coastguard Worker     return;
178*795d594fSAndroid Build Coastguard Worker   }
179*795d594fSAndroid Build Coastguard Worker 
180*795d594fSAndroid Build Coastguard Worker   // Set the O_CLOEXEC flag atomically here, so the file gets closed when a new process is forked.
181*795d594fSAndroid Build Coastguard Worker   int fd = DupCloexec(originalFd);
182*795d594fSAndroid Build Coastguard Worker   if (fd < 0) {
183*795d594fSAndroid Build Coastguard Worker     LOG(ERROR)
184*795d594fSAndroid Build Coastguard Worker         << "Unable to dup the file descriptor, ignoring the request to dump low-overhead trace";
185*795d594fSAndroid Build Coastguard Worker     return;
186*795d594fSAndroid Build Coastguard Worker   }
187*795d594fSAndroid Build Coastguard Worker 
188*795d594fSAndroid Build Coastguard Worker   TraceProfiler::Dump(fd);
189*795d594fSAndroid Build Coastguard Worker }
190*795d594fSAndroid Build Coastguard Worker 
VMDebug_startLowOverheadTraceImpl(JNIEnv *,jclass)191*795d594fSAndroid Build Coastguard Worker static void VMDebug_startLowOverheadTraceImpl(JNIEnv*, jclass) {
192*795d594fSAndroid Build Coastguard Worker   TraceProfiler::Start();
193*795d594fSAndroid Build Coastguard Worker }
194*795d594fSAndroid Build Coastguard Worker 
VMDebug_isDebuggerConnected(JNIEnv *,jclass)195*795d594fSAndroid Build Coastguard Worker static jboolean VMDebug_isDebuggerConnected(JNIEnv*, jclass) {
196*795d594fSAndroid Build Coastguard Worker   // This function will be replaced by the debugger when it's connected. See
197*795d594fSAndroid Build Coastguard Worker   // external/oj-libjdwp/src/share/vmDebug.c for implementation when debugger is connected.
198*795d594fSAndroid Build Coastguard Worker   return false;
199*795d594fSAndroid Build Coastguard Worker }
200*795d594fSAndroid Build Coastguard Worker 
VMDebug_isDebuggingEnabled(JNIEnv * env,jclass)201*795d594fSAndroid Build Coastguard Worker static jboolean VMDebug_isDebuggingEnabled(JNIEnv* env, jclass) {
202*795d594fSAndroid Build Coastguard Worker   ScopedObjectAccess soa(env);
203*795d594fSAndroid Build Coastguard Worker   return Runtime::Current()->GetRuntimeCallbacks()->IsDebuggerConfigured();
204*795d594fSAndroid Build Coastguard Worker }
205*795d594fSAndroid Build Coastguard Worker 
VMDebug_lastDebuggerActivity(JNIEnv *,jclass)206*795d594fSAndroid Build Coastguard Worker static jlong VMDebug_lastDebuggerActivity(JNIEnv*, jclass) {
207*795d594fSAndroid Build Coastguard Worker   // This function will be replaced by the debugger when it's connected. See
208*795d594fSAndroid Build Coastguard Worker   // external/oj-libjdwp/src/share/vmDebug.c for implementation when debugger is connected.
209*795d594fSAndroid Build Coastguard Worker   return -1;
210*795d594fSAndroid Build Coastguard Worker }
211*795d594fSAndroid Build Coastguard Worker 
VMDebug_suspendAllAndSendVmStart(JNIEnv *,jclass)212*795d594fSAndroid Build Coastguard Worker static void VMDebug_suspendAllAndSendVmStart(JNIEnv*, jclass)
213*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_) {
214*795d594fSAndroid Build Coastguard Worker   // This function will be replaced by the debugger when it's connected. See
215*795d594fSAndroid Build Coastguard Worker   // external/oj-libjdwp/src/share/vmDebug.c for implementation when debugger is connected.
216*795d594fSAndroid Build Coastguard Worker   ThrowRuntimeException("ART's suspendAllAndSendVmStart is not implemented");
217*795d594fSAndroid Build Coastguard Worker }
218*795d594fSAndroid Build Coastguard Worker 
VMDebug_printLoadedClasses(JNIEnv * env,jclass,jint flags)219*795d594fSAndroid Build Coastguard Worker static void VMDebug_printLoadedClasses(JNIEnv* env, jclass, jint flags) {
220*795d594fSAndroid Build Coastguard Worker   class DumpClassVisitor : public ClassVisitor {
221*795d594fSAndroid Build Coastguard Worker    public:
222*795d594fSAndroid Build Coastguard Worker     explicit DumpClassVisitor(int dump_flags) : flags_(dump_flags) {}
223*795d594fSAndroid Build Coastguard Worker 
224*795d594fSAndroid Build Coastguard Worker     bool operator()(ObjPtr<mirror::Class> klass) override REQUIRES_SHARED(Locks::mutator_lock_) {
225*795d594fSAndroid Build Coastguard Worker       klass->DumpClass(LOG_STREAM(ERROR), flags_);
226*795d594fSAndroid Build Coastguard Worker       return true;
227*795d594fSAndroid Build Coastguard Worker     }
228*795d594fSAndroid Build Coastguard Worker 
229*795d594fSAndroid Build Coastguard Worker    private:
230*795d594fSAndroid Build Coastguard Worker     const int flags_;
231*795d594fSAndroid Build Coastguard Worker   };
232*795d594fSAndroid Build Coastguard Worker   DumpClassVisitor visitor(flags);
233*795d594fSAndroid Build Coastguard Worker 
234*795d594fSAndroid Build Coastguard Worker   ScopedFastNativeObjectAccess soa(env);
235*795d594fSAndroid Build Coastguard Worker   return Runtime::Current()->GetClassLinker()->VisitClasses(&visitor);
236*795d594fSAndroid Build Coastguard Worker }
237*795d594fSAndroid Build Coastguard Worker 
VMDebug_getLoadedClassCount(JNIEnv * env,jclass)238*795d594fSAndroid Build Coastguard Worker static jint VMDebug_getLoadedClassCount(JNIEnv* env, jclass) {
239*795d594fSAndroid Build Coastguard Worker   ScopedFastNativeObjectAccess soa(env);
240*795d594fSAndroid Build Coastguard Worker   return Runtime::Current()->GetClassLinker()->NumLoadedClasses();
241*795d594fSAndroid Build Coastguard Worker }
242*795d594fSAndroid Build Coastguard Worker 
243*795d594fSAndroid Build Coastguard Worker /*
244*795d594fSAndroid Build Coastguard Worker  * Returns the thread-specific CPU-time clock value for the current thread,
245*795d594fSAndroid Build Coastguard Worker  * or -1 if the feature isn't supported.
246*795d594fSAndroid Build Coastguard Worker  */
VMDebug_threadCpuTimeNanos(JNIEnv *,jclass)247*795d594fSAndroid Build Coastguard Worker static jlong VMDebug_threadCpuTimeNanos(JNIEnv*, jclass) {
248*795d594fSAndroid Build Coastguard Worker   return ThreadCpuNanoTime();
249*795d594fSAndroid Build Coastguard Worker }
250*795d594fSAndroid Build Coastguard Worker 
251*795d594fSAndroid Build Coastguard Worker /*
252*795d594fSAndroid Build Coastguard Worker  * static void dumpHprofData(String fileName, FileDescriptor fd)
253*795d594fSAndroid Build Coastguard Worker  *
254*795d594fSAndroid Build Coastguard Worker  * Cause "hprof" data to be dumped.  We can throw an IOException if an
255*795d594fSAndroid Build Coastguard Worker  * error occurs during file handling.
256*795d594fSAndroid Build Coastguard Worker  */
VMDebug_dumpHprofData(JNIEnv * env,jclass,jstring javaFilename,jint javaFd)257*795d594fSAndroid Build Coastguard Worker static void VMDebug_dumpHprofData(JNIEnv* env, jclass, jstring javaFilename, jint javaFd) {
258*795d594fSAndroid Build Coastguard Worker   // Only one of these may be null.
259*795d594fSAndroid Build Coastguard Worker   if (javaFilename == nullptr && javaFd < 0) {
260*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
261*795d594fSAndroid Build Coastguard Worker     ThrowNullPointerException("fileName == null && fd == null");
262*795d594fSAndroid Build Coastguard Worker     return;
263*795d594fSAndroid Build Coastguard Worker   }
264*795d594fSAndroid Build Coastguard Worker 
265*795d594fSAndroid Build Coastguard Worker   std::string filename;
266*795d594fSAndroid Build Coastguard Worker   if (javaFilename != nullptr) {
267*795d594fSAndroid Build Coastguard Worker     ScopedUtfChars chars(env, javaFilename);
268*795d594fSAndroid Build Coastguard Worker     if (env->ExceptionCheck()) {
269*795d594fSAndroid Build Coastguard Worker       return;
270*795d594fSAndroid Build Coastguard Worker     }
271*795d594fSAndroid Build Coastguard Worker     filename = chars.c_str();
272*795d594fSAndroid Build Coastguard Worker   } else {
273*795d594fSAndroid Build Coastguard Worker     filename = "[fd]";
274*795d594fSAndroid Build Coastguard Worker   }
275*795d594fSAndroid Build Coastguard Worker 
276*795d594fSAndroid Build Coastguard Worker   int fd = javaFd;
277*795d594fSAndroid Build Coastguard Worker 
278*795d594fSAndroid Build Coastguard Worker   hprof::DumpHeap(filename.c_str(), fd, false);
279*795d594fSAndroid Build Coastguard Worker }
280*795d594fSAndroid Build Coastguard Worker 
VMDebug_dumpHprofDataDdms(JNIEnv *,jclass)281*795d594fSAndroid Build Coastguard Worker static void VMDebug_dumpHprofDataDdms(JNIEnv*, jclass) {
282*795d594fSAndroid Build Coastguard Worker   hprof::DumpHeap("[DDMS]", -1, true);
283*795d594fSAndroid Build Coastguard Worker }
284*795d594fSAndroid Build Coastguard Worker 
VMDebug_dumpReferenceTables(JNIEnv * env,jclass)285*795d594fSAndroid Build Coastguard Worker static void VMDebug_dumpReferenceTables(JNIEnv* env, jclass) {
286*795d594fSAndroid Build Coastguard Worker   ScopedObjectAccess soa(env);
287*795d594fSAndroid Build Coastguard Worker   LOG(INFO) << "--- reference table dump ---";
288*795d594fSAndroid Build Coastguard Worker 
289*795d594fSAndroid Build Coastguard Worker   soa.Env()->DumpReferenceTables(LOG_STREAM(INFO));
290*795d594fSAndroid Build Coastguard Worker   soa.Vm()->DumpReferenceTables(LOG_STREAM(INFO));
291*795d594fSAndroid Build Coastguard Worker 
292*795d594fSAndroid Build Coastguard Worker   LOG(INFO) << "---";
293*795d594fSAndroid Build Coastguard Worker }
294*795d594fSAndroid Build Coastguard Worker 
VMDebug_countInstancesOfClass(JNIEnv * env,jclass,jclass javaClass,jboolean countAssignable)295*795d594fSAndroid Build Coastguard Worker static jlong VMDebug_countInstancesOfClass(JNIEnv* env,
296*795d594fSAndroid Build Coastguard Worker                                            jclass,
297*795d594fSAndroid Build Coastguard Worker                                            jclass javaClass,
298*795d594fSAndroid Build Coastguard Worker                                            jboolean countAssignable) {
299*795d594fSAndroid Build Coastguard Worker   ScopedObjectAccess soa(env);
300*795d594fSAndroid Build Coastguard Worker   gc::Heap* const heap = Runtime::Current()->GetHeap();
301*795d594fSAndroid Build Coastguard Worker   // Caller's responsibility to do GC if desired.
302*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(javaClass);
303*795d594fSAndroid Build Coastguard Worker   if (c == nullptr) {
304*795d594fSAndroid Build Coastguard Worker     return 0;
305*795d594fSAndroid Build Coastguard Worker   }
306*795d594fSAndroid Build Coastguard Worker   VariableSizedHandleScope hs(soa.Self());
307*795d594fSAndroid Build Coastguard Worker   std::vector<Handle<mirror::Class>> classes {hs.NewHandle(c)};
308*795d594fSAndroid Build Coastguard Worker   uint64_t count = 0;
309*795d594fSAndroid Build Coastguard Worker   heap->CountInstances(classes, countAssignable, &count);
310*795d594fSAndroid Build Coastguard Worker   return count;
311*795d594fSAndroid Build Coastguard Worker }
312*795d594fSAndroid Build Coastguard Worker 
VMDebug_getExecutableMethodFileOffsetsNative(JNIEnv * env,jclass,jobject javaMethod)313*795d594fSAndroid Build Coastguard Worker static jobject VMDebug_getExecutableMethodFileOffsetsNative(JNIEnv* env,
314*795d594fSAndroid Build Coastguard Worker                                                             jclass,
315*795d594fSAndroid Build Coastguard Worker                                                             jobject javaMethod) {
316*795d594fSAndroid Build Coastguard Worker   ScopedObjectAccess soa(env);
317*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::Executable> m = soa.Decode<mirror::Executable>(javaMethod);
318*795d594fSAndroid Build Coastguard Worker   if (m == nullptr) {
319*795d594fSAndroid Build Coastguard Worker     soa.Self()->ThrowNewExceptionF("Ljava/lang/RuntimeException;",
320*795d594fSAndroid Build Coastguard Worker                                    "Could not find mirror::Executable for supplied jobject");
321*795d594fSAndroid Build Coastguard Worker     return nullptr;
322*795d594fSAndroid Build Coastguard Worker   }
323*795d594fSAndroid Build Coastguard Worker 
324*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::Class> c = m->GetDeclaringClass();
325*795d594fSAndroid Build Coastguard Worker   if (c == nullptr) {
326*795d594fSAndroid Build Coastguard Worker     soa.Self()->ThrowNewExceptionF("Ljava/lang/RuntimeException;",
327*795d594fSAndroid Build Coastguard Worker                                    "Could not find mirror::Class for supplied jobject");
328*795d594fSAndroid Build Coastguard Worker     return nullptr;
329*795d594fSAndroid Build Coastguard Worker   }
330*795d594fSAndroid Build Coastguard Worker 
331*795d594fSAndroid Build Coastguard Worker   ArtMethod* art_method = m->GetArtMethod();
332*795d594fSAndroid Build Coastguard Worker   auto oat_method_quick_code =
333*795d594fSAndroid Build Coastguard Worker       reinterpret_cast<const uint8_t*>(art_method->GetOatMethodQuickCode(kRuntimePointerSize));
334*795d594fSAndroid Build Coastguard Worker 
335*795d594fSAndroid Build Coastguard Worker   if (oat_method_quick_code == nullptr) {
336*795d594fSAndroid Build Coastguard Worker     LOG(ERROR) << "No OatMethodQuickCode for method " << art_method->PrettyMethod();
337*795d594fSAndroid Build Coastguard Worker     return nullptr;
338*795d594fSAndroid Build Coastguard Worker   }
339*795d594fSAndroid Build Coastguard Worker 
340*795d594fSAndroid Build Coastguard Worker   const OatDexFile* oat_dex_file = c->GetDexFile().GetOatDexFile();
341*795d594fSAndroid Build Coastguard Worker   if (oat_dex_file == nullptr) {
342*795d594fSAndroid Build Coastguard Worker     soa.Self()->ThrowNewExceptionF("Ljava/lang/RuntimeException;", "Could not find oat_dex_file");
343*795d594fSAndroid Build Coastguard Worker     return nullptr;
344*795d594fSAndroid Build Coastguard Worker   }
345*795d594fSAndroid Build Coastguard Worker 
346*795d594fSAndroid Build Coastguard Worker   const OatFile* oat_file = oat_dex_file->GetOatFile();
347*795d594fSAndroid Build Coastguard Worker   if (oat_file == nullptr) {
348*795d594fSAndroid Build Coastguard Worker     soa.Self()->ThrowNewExceptionF("Ljava/lang/RuntimeException;", "Could not find oat_file");
349*795d594fSAndroid Build Coastguard Worker     return nullptr;
350*795d594fSAndroid Build Coastguard Worker   }
351*795d594fSAndroid Build Coastguard Worker 
352*795d594fSAndroid Build Coastguard Worker   std::string error_msg;
353*795d594fSAndroid Build Coastguard Worker   const uint8_t* elf_begin = oat_file->ComputeElfBegin(&error_msg);
354*795d594fSAndroid Build Coastguard Worker   if (elf_begin == nullptr) {
355*795d594fSAndroid Build Coastguard Worker     soa.Self()->ThrowNewExceptionF(
356*795d594fSAndroid Build Coastguard Worker         "Ljava/lang/RuntimeException;", "Could not find elf_begin: %s", error_msg.c_str());
357*795d594fSAndroid Build Coastguard Worker     return nullptr;
358*795d594fSAndroid Build Coastguard Worker   }
359*795d594fSAndroid Build Coastguard Worker 
360*795d594fSAndroid Build Coastguard Worker   size_t adjusted_offset = oat_method_quick_code - elf_begin;
361*795d594fSAndroid Build Coastguard Worker 
362*795d594fSAndroid Build Coastguard Worker   ScopedLocalRef<jstring> odex_path = CREATE_UTF_OR_RETURN(env, oat_file->GetLocation());
363*795d594fSAndroid Build Coastguard Worker   auto odex_offset = reinterpret_cast64<jlong>(elf_begin);
364*795d594fSAndroid Build Coastguard Worker   auto method_offset = static_cast<jlong>(adjusted_offset);
365*795d594fSAndroid Build Coastguard Worker 
366*795d594fSAndroid Build Coastguard Worker   ScopedLocalRef<jclass> clazz(env,
367*795d594fSAndroid Build Coastguard Worker                                env->FindClass("dalvik/system/VMDebug$ExecutableMethodFileOffsets"));
368*795d594fSAndroid Build Coastguard Worker   if (clazz == nullptr) {
369*795d594fSAndroid Build Coastguard Worker     soa.Self()->ThrowNewExceptionF(
370*795d594fSAndroid Build Coastguard Worker         "Ljava/lang/RuntimeException;",
371*795d594fSAndroid Build Coastguard Worker         "Could not find dalvik/system/VMDebug$ExecutableMethodFileOffsets");
372*795d594fSAndroid Build Coastguard Worker     return nullptr;
373*795d594fSAndroid Build Coastguard Worker   }
374*795d594fSAndroid Build Coastguard Worker 
375*795d594fSAndroid Build Coastguard Worker   jmethodID constructor_id = env->GetMethodID(clazz.get(), "<init>", "(Ljava/lang/String;JJ)V");
376*795d594fSAndroid Build Coastguard Worker   return env->NewObject(clazz.get(), constructor_id, odex_path.get(), odex_offset, method_offset);
377*795d594fSAndroid Build Coastguard Worker }
378*795d594fSAndroid Build Coastguard Worker 
VMDebug_countInstancesOfClasses(JNIEnv * env,jclass,jobjectArray javaClasses,jboolean countAssignable)379*795d594fSAndroid Build Coastguard Worker static jlongArray VMDebug_countInstancesOfClasses(JNIEnv* env,
380*795d594fSAndroid Build Coastguard Worker                                                   jclass,
381*795d594fSAndroid Build Coastguard Worker                                                   jobjectArray javaClasses,
382*795d594fSAndroid Build Coastguard Worker                                                   jboolean countAssignable) {
383*795d594fSAndroid Build Coastguard Worker   ScopedObjectAccess soa(env);
384*795d594fSAndroid Build Coastguard Worker   gc::Heap* const heap = Runtime::Current()->GetHeap();
385*795d594fSAndroid Build Coastguard Worker   // Caller's responsibility to do GC if desired.
386*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::ObjectArray<mirror::Class>> decoded_classes =
387*795d594fSAndroid Build Coastguard Worker       soa.Decode<mirror::ObjectArray<mirror::Class>>(javaClasses);
388*795d594fSAndroid Build Coastguard Worker   if (decoded_classes == nullptr) {
389*795d594fSAndroid Build Coastguard Worker     return nullptr;
390*795d594fSAndroid Build Coastguard Worker   }
391*795d594fSAndroid Build Coastguard Worker   VariableSizedHandleScope hs(soa.Self());
392*795d594fSAndroid Build Coastguard Worker   std::vector<Handle<mirror::Class>> classes;
393*795d594fSAndroid Build Coastguard Worker   for (size_t i = 0, count = decoded_classes->GetLength(); i < count; ++i) {
394*795d594fSAndroid Build Coastguard Worker     classes.push_back(hs.NewHandle(decoded_classes->Get(i)));
395*795d594fSAndroid Build Coastguard Worker   }
396*795d594fSAndroid Build Coastguard Worker   std::vector<uint64_t> counts(classes.size(), 0u);
397*795d594fSAndroid Build Coastguard Worker   // Heap::CountInstances can handle null and will put 0 for these classes.
398*795d594fSAndroid Build Coastguard Worker   heap->CountInstances(classes, countAssignable, &counts[0]);
399*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::LongArray> long_counts = mirror::LongArray::Alloc(soa.Self(), counts.size());
400*795d594fSAndroid Build Coastguard Worker   if (long_counts == nullptr) {
401*795d594fSAndroid Build Coastguard Worker     soa.Self()->AssertPendingOOMException();
402*795d594fSAndroid Build Coastguard Worker     return nullptr;
403*795d594fSAndroid Build Coastguard Worker   }
404*795d594fSAndroid Build Coastguard Worker   for (size_t i = 0; i < counts.size(); ++i) {
405*795d594fSAndroid Build Coastguard Worker     long_counts->Set(i, counts[i]);
406*795d594fSAndroid Build Coastguard Worker   }
407*795d594fSAndroid Build Coastguard Worker   return soa.AddLocalReference<jlongArray>(long_counts);
408*795d594fSAndroid Build Coastguard Worker }
409*795d594fSAndroid Build Coastguard Worker 
410*795d594fSAndroid Build Coastguard Worker // The runtime stat names for VMDebug.getRuntimeStat().
411*795d594fSAndroid Build Coastguard Worker enum class VMDebugRuntimeStatId {
412*795d594fSAndroid Build Coastguard Worker   kArtGcGcCount = 0,
413*795d594fSAndroid Build Coastguard Worker   kArtGcGcTime,
414*795d594fSAndroid Build Coastguard Worker   kArtGcBytesAllocated,
415*795d594fSAndroid Build Coastguard Worker   kArtGcBytesFreed,
416*795d594fSAndroid Build Coastguard Worker   kArtGcBlockingGcCount,
417*795d594fSAndroid Build Coastguard Worker   kArtGcBlockingGcTime,
418*795d594fSAndroid Build Coastguard Worker   kArtGcGcCountRateHistogram,
419*795d594fSAndroid Build Coastguard Worker   kArtGcBlockingGcCountRateHistogram,
420*795d594fSAndroid Build Coastguard Worker   kArtGcObjectsAllocated,
421*795d594fSAndroid Build Coastguard Worker   kArtGcTotalTimeWaitingForGc,
422*795d594fSAndroid Build Coastguard Worker   kArtGcPreOomeGcCount,
423*795d594fSAndroid Build Coastguard Worker   kNumRuntimeStats,
424*795d594fSAndroid Build Coastguard Worker };
425*795d594fSAndroid Build Coastguard Worker 
VMDebug_getRuntimeStatInternal(JNIEnv * env,jclass,jint statId)426*795d594fSAndroid Build Coastguard Worker static jstring VMDebug_getRuntimeStatInternal(JNIEnv* env, jclass, jint statId) {
427*795d594fSAndroid Build Coastguard Worker   gc::Heap* heap = Runtime::Current()->GetHeap();
428*795d594fSAndroid Build Coastguard Worker   switch (static_cast<VMDebugRuntimeStatId>(statId)) {
429*795d594fSAndroid Build Coastguard Worker     case VMDebugRuntimeStatId::kArtGcGcCount: {
430*795d594fSAndroid Build Coastguard Worker       std::string output = std::to_string(heap->GetGcCount());
431*795d594fSAndroid Build Coastguard Worker       return env->NewStringUTF(output.c_str());
432*795d594fSAndroid Build Coastguard Worker     }
433*795d594fSAndroid Build Coastguard Worker     case VMDebugRuntimeStatId::kArtGcGcTime: {
434*795d594fSAndroid Build Coastguard Worker       std::string output = std::to_string(NsToMs(heap->GetGcTime()));
435*795d594fSAndroid Build Coastguard Worker       return env->NewStringUTF(output.c_str());
436*795d594fSAndroid Build Coastguard Worker     }
437*795d594fSAndroid Build Coastguard Worker     case VMDebugRuntimeStatId::kArtGcBytesAllocated: {
438*795d594fSAndroid Build Coastguard Worker       std::string output = std::to_string(heap->GetBytesAllocatedEver());
439*795d594fSAndroid Build Coastguard Worker       return env->NewStringUTF(output.c_str());
440*795d594fSAndroid Build Coastguard Worker     }
441*795d594fSAndroid Build Coastguard Worker     case VMDebugRuntimeStatId::kArtGcBytesFreed: {
442*795d594fSAndroid Build Coastguard Worker       std::string output = std::to_string(heap->GetBytesFreedEver());
443*795d594fSAndroid Build Coastguard Worker       return env->NewStringUTF(output.c_str());
444*795d594fSAndroid Build Coastguard Worker     }
445*795d594fSAndroid Build Coastguard Worker     case VMDebugRuntimeStatId::kArtGcBlockingGcCount: {
446*795d594fSAndroid Build Coastguard Worker       std::string output = std::to_string(heap->GetBlockingGcCount());
447*795d594fSAndroid Build Coastguard Worker       return env->NewStringUTF(output.c_str());
448*795d594fSAndroid Build Coastguard Worker     }
449*795d594fSAndroid Build Coastguard Worker     case VMDebugRuntimeStatId::kArtGcBlockingGcTime: {
450*795d594fSAndroid Build Coastguard Worker       std::string output = std::to_string(NsToMs(heap->GetBlockingGcTime()));
451*795d594fSAndroid Build Coastguard Worker       return env->NewStringUTF(output.c_str());
452*795d594fSAndroid Build Coastguard Worker     }
453*795d594fSAndroid Build Coastguard Worker     case VMDebugRuntimeStatId::kArtGcGcCountRateHistogram: {
454*795d594fSAndroid Build Coastguard Worker       std::ostringstream output;
455*795d594fSAndroid Build Coastguard Worker       heap->DumpGcCountRateHistogram(output);
456*795d594fSAndroid Build Coastguard Worker       return env->NewStringUTF(output.str().c_str());
457*795d594fSAndroid Build Coastguard Worker     }
458*795d594fSAndroid Build Coastguard Worker     case VMDebugRuntimeStatId::kArtGcBlockingGcCountRateHistogram: {
459*795d594fSAndroid Build Coastguard Worker       std::ostringstream output;
460*795d594fSAndroid Build Coastguard Worker       heap->DumpBlockingGcCountRateHistogram(output);
461*795d594fSAndroid Build Coastguard Worker       return env->NewStringUTF(output.str().c_str());
462*795d594fSAndroid Build Coastguard Worker     }
463*795d594fSAndroid Build Coastguard Worker     case VMDebugRuntimeStatId::kArtGcObjectsAllocated: {
464*795d594fSAndroid Build Coastguard Worker       std::string output = std::to_string(heap->GetObjectsAllocated());
465*795d594fSAndroid Build Coastguard Worker       return env->NewStringUTF(output.c_str());
466*795d594fSAndroid Build Coastguard Worker     }
467*795d594fSAndroid Build Coastguard Worker     case VMDebugRuntimeStatId::kArtGcTotalTimeWaitingForGc: {
468*795d594fSAndroid Build Coastguard Worker       std::string output = std::to_string(heap->GetTotalTimeWaitingForGC());
469*795d594fSAndroid Build Coastguard Worker       return env->NewStringUTF(output.c_str());
470*795d594fSAndroid Build Coastguard Worker     }
471*795d594fSAndroid Build Coastguard Worker     case VMDebugRuntimeStatId::kArtGcPreOomeGcCount: {
472*795d594fSAndroid Build Coastguard Worker       std::string output = std::to_string(heap->GetPreOomeGcCount());
473*795d594fSAndroid Build Coastguard Worker       return env->NewStringUTF(output.c_str());
474*795d594fSAndroid Build Coastguard Worker     }
475*795d594fSAndroid Build Coastguard Worker     default:
476*795d594fSAndroid Build Coastguard Worker       return nullptr;
477*795d594fSAndroid Build Coastguard Worker   }
478*795d594fSAndroid Build Coastguard Worker }
479*795d594fSAndroid Build Coastguard Worker 
SetRuntimeStatValue(Thread * self,Handle<mirror::ObjectArray<mirror::String>> array,VMDebugRuntimeStatId id,const std::string & value)480*795d594fSAndroid Build Coastguard Worker static bool SetRuntimeStatValue(Thread* self,
481*795d594fSAndroid Build Coastguard Worker                                 Handle<mirror::ObjectArray<mirror::String>> array,
482*795d594fSAndroid Build Coastguard Worker                                 VMDebugRuntimeStatId id,
483*795d594fSAndroid Build Coastguard Worker                                 const std::string& value) REQUIRES_SHARED(Locks::mutator_lock_) {
484*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::String> ovalue = mirror::String::AllocFromModifiedUtf8(self, value.c_str());
485*795d594fSAndroid Build Coastguard Worker   if (ovalue == nullptr) {
486*795d594fSAndroid Build Coastguard Worker     DCHECK(self->IsExceptionPending());
487*795d594fSAndroid Build Coastguard Worker     return false;
488*795d594fSAndroid Build Coastguard Worker   }
489*795d594fSAndroid Build Coastguard Worker   // We're initializing a newly allocated array object, so we do not need to record that under
490*795d594fSAndroid Build Coastguard Worker   // a transaction. If the transaction is aborted, the whole object shall be unreachable.
491*795d594fSAndroid Build Coastguard Worker   array->SetWithoutChecks</*kTransactionActive=*/ false, /*kCheckTransaction=*/ false>(
492*795d594fSAndroid Build Coastguard Worker       static_cast<int32_t>(id), ovalue);
493*795d594fSAndroid Build Coastguard Worker   return true;
494*795d594fSAndroid Build Coastguard Worker }
495*795d594fSAndroid Build Coastguard Worker 
VMDebug_getRuntimeStatsInternal(JNIEnv * env,jclass)496*795d594fSAndroid Build Coastguard Worker static jobjectArray VMDebug_getRuntimeStatsInternal(JNIEnv* env, jclass) {
497*795d594fSAndroid Build Coastguard Worker   Thread* self = Thread::ForEnv(env);
498*795d594fSAndroid Build Coastguard Worker   ScopedObjectAccess soa(self);
499*795d594fSAndroid Build Coastguard Worker   StackHandleScope<1u> hs(self);
500*795d594fSAndroid Build Coastguard Worker   int32_t size = enum_cast<int32_t>(VMDebugRuntimeStatId::kNumRuntimeStats);
501*795d594fSAndroid Build Coastguard Worker   Handle<mirror::ObjectArray<mirror::String>> array = hs.NewHandle(
502*795d594fSAndroid Build Coastguard Worker       mirror::ObjectArray<mirror::String>::Alloc(
503*795d594fSAndroid Build Coastguard Worker           self, GetClassRoot<mirror::ObjectArray<mirror::String>>(), size));
504*795d594fSAndroid Build Coastguard Worker   if (array == nullptr) {
505*795d594fSAndroid Build Coastguard Worker     DCHECK(self->IsExceptionPending());
506*795d594fSAndroid Build Coastguard Worker     return nullptr;
507*795d594fSAndroid Build Coastguard Worker   }
508*795d594fSAndroid Build Coastguard Worker   gc::Heap* heap = Runtime::Current()->GetHeap();
509*795d594fSAndroid Build Coastguard Worker   if (!SetRuntimeStatValue(self,
510*795d594fSAndroid Build Coastguard Worker                            array,
511*795d594fSAndroid Build Coastguard Worker                            VMDebugRuntimeStatId::kArtGcGcCount,
512*795d594fSAndroid Build Coastguard Worker                            std::to_string(heap->GetGcCount()))) {
513*795d594fSAndroid Build Coastguard Worker     return nullptr;
514*795d594fSAndroid Build Coastguard Worker   }
515*795d594fSAndroid Build Coastguard Worker   if (!SetRuntimeStatValue(self,
516*795d594fSAndroid Build Coastguard Worker                            array,
517*795d594fSAndroid Build Coastguard Worker                            VMDebugRuntimeStatId::kArtGcGcTime,
518*795d594fSAndroid Build Coastguard Worker                            std::to_string(NsToMs(heap->GetGcTime())))) {
519*795d594fSAndroid Build Coastguard Worker     return nullptr;
520*795d594fSAndroid Build Coastguard Worker   }
521*795d594fSAndroid Build Coastguard Worker   if (!SetRuntimeStatValue(self,
522*795d594fSAndroid Build Coastguard Worker                            array,
523*795d594fSAndroid Build Coastguard Worker                            VMDebugRuntimeStatId::kArtGcBytesAllocated,
524*795d594fSAndroid Build Coastguard Worker                            std::to_string(heap->GetBytesAllocatedEver()))) {
525*795d594fSAndroid Build Coastguard Worker     return nullptr;
526*795d594fSAndroid Build Coastguard Worker   }
527*795d594fSAndroid Build Coastguard Worker   if (!SetRuntimeStatValue(self,
528*795d594fSAndroid Build Coastguard Worker                            array,
529*795d594fSAndroid Build Coastguard Worker                            VMDebugRuntimeStatId::kArtGcBytesFreed,
530*795d594fSAndroid Build Coastguard Worker                            std::to_string(heap->GetBytesFreedEver()))) {
531*795d594fSAndroid Build Coastguard Worker     return nullptr;
532*795d594fSAndroid Build Coastguard Worker   }
533*795d594fSAndroid Build Coastguard Worker   if (!SetRuntimeStatValue(self,
534*795d594fSAndroid Build Coastguard Worker                            array,
535*795d594fSAndroid Build Coastguard Worker                            VMDebugRuntimeStatId::kArtGcBlockingGcCount,
536*795d594fSAndroid Build Coastguard Worker                            std::to_string(heap->GetBlockingGcCount()))) {
537*795d594fSAndroid Build Coastguard Worker     return nullptr;
538*795d594fSAndroid Build Coastguard Worker   }
539*795d594fSAndroid Build Coastguard Worker   if (!SetRuntimeStatValue(self,
540*795d594fSAndroid Build Coastguard Worker                            array,
541*795d594fSAndroid Build Coastguard Worker                            VMDebugRuntimeStatId::kArtGcBlockingGcTime,
542*795d594fSAndroid Build Coastguard Worker                            std::to_string(NsToMs(heap->GetBlockingGcTime())))) {
543*795d594fSAndroid Build Coastguard Worker     return nullptr;
544*795d594fSAndroid Build Coastguard Worker   }
545*795d594fSAndroid Build Coastguard Worker   {
546*795d594fSAndroid Build Coastguard Worker     std::ostringstream output;
547*795d594fSAndroid Build Coastguard Worker     heap->DumpGcCountRateHistogram(output);
548*795d594fSAndroid Build Coastguard Worker     if (!SetRuntimeStatValue(self,
549*795d594fSAndroid Build Coastguard Worker                              array,
550*795d594fSAndroid Build Coastguard Worker                              VMDebugRuntimeStatId::kArtGcGcCountRateHistogram,
551*795d594fSAndroid Build Coastguard Worker                              output.str())) {
552*795d594fSAndroid Build Coastguard Worker       return nullptr;
553*795d594fSAndroid Build Coastguard Worker     }
554*795d594fSAndroid Build Coastguard Worker   }
555*795d594fSAndroid Build Coastguard Worker   {
556*795d594fSAndroid Build Coastguard Worker     std::ostringstream output;
557*795d594fSAndroid Build Coastguard Worker     heap->DumpBlockingGcCountRateHistogram(output);
558*795d594fSAndroid Build Coastguard Worker     if (!SetRuntimeStatValue(self,
559*795d594fSAndroid Build Coastguard Worker                              array,
560*795d594fSAndroid Build Coastguard Worker                              VMDebugRuntimeStatId::kArtGcBlockingGcCountRateHistogram,
561*795d594fSAndroid Build Coastguard Worker                              output.str())) {
562*795d594fSAndroid Build Coastguard Worker       return nullptr;
563*795d594fSAndroid Build Coastguard Worker     }
564*795d594fSAndroid Build Coastguard Worker   }
565*795d594fSAndroid Build Coastguard Worker   return soa.AddLocalReference<jobjectArray>(array.Get());
566*795d594fSAndroid Build Coastguard Worker }
567*795d594fSAndroid Build Coastguard Worker 
VMDebug_nativeAttachAgent(JNIEnv * env,jclass,jstring agent,jobject classloader)568*795d594fSAndroid Build Coastguard Worker static void VMDebug_nativeAttachAgent(JNIEnv* env, jclass, jstring agent, jobject classloader) {
569*795d594fSAndroid Build Coastguard Worker   if (agent == nullptr) {
570*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
571*795d594fSAndroid Build Coastguard Worker     ThrowNullPointerException("agent is null");
572*795d594fSAndroid Build Coastguard Worker     return;
573*795d594fSAndroid Build Coastguard Worker   }
574*795d594fSAndroid Build Coastguard Worker 
575*795d594fSAndroid Build Coastguard Worker   if (!Dbg::IsJdwpAllowed()) {
576*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
577*795d594fSAndroid Build Coastguard Worker     ThrowSecurityException("Can't attach agent, process is not debuggable.");
578*795d594fSAndroid Build Coastguard Worker     return;
579*795d594fSAndroid Build Coastguard Worker   }
580*795d594fSAndroid Build Coastguard Worker 
581*795d594fSAndroid Build Coastguard Worker   std::string filename;
582*795d594fSAndroid Build Coastguard Worker   {
583*795d594fSAndroid Build Coastguard Worker     ScopedUtfChars chars(env, agent);
584*795d594fSAndroid Build Coastguard Worker     if (env->ExceptionCheck()) {
585*795d594fSAndroid Build Coastguard Worker       return;
586*795d594fSAndroid Build Coastguard Worker     }
587*795d594fSAndroid Build Coastguard Worker     filename = chars.c_str();
588*795d594fSAndroid Build Coastguard Worker   }
589*795d594fSAndroid Build Coastguard Worker 
590*795d594fSAndroid Build Coastguard Worker   Runtime::Current()->AttachAgent(env, filename, classloader);
591*795d594fSAndroid Build Coastguard Worker }
592*795d594fSAndroid Build Coastguard Worker 
VMDebug_allowHiddenApiReflectionFrom(JNIEnv * env,jclass,jclass j_caller)593*795d594fSAndroid Build Coastguard Worker static void VMDebug_allowHiddenApiReflectionFrom(JNIEnv* env, jclass, jclass j_caller) {
594*795d594fSAndroid Build Coastguard Worker   Runtime* runtime = Runtime::Current();
595*795d594fSAndroid Build Coastguard Worker   ScopedObjectAccess soa(env);
596*795d594fSAndroid Build Coastguard Worker 
597*795d594fSAndroid Build Coastguard Worker   if (!runtime->IsJavaDebuggableAtInit()) {
598*795d594fSAndroid Build Coastguard Worker     ThrowSecurityException("Can't exempt class, process is not debuggable.");
599*795d594fSAndroid Build Coastguard Worker     return;
600*795d594fSAndroid Build Coastguard Worker   }
601*795d594fSAndroid Build Coastguard Worker 
602*795d594fSAndroid Build Coastguard Worker   StackHandleScope<1> hs(soa.Self());
603*795d594fSAndroid Build Coastguard Worker   Handle<mirror::Class> h_caller(hs.NewHandle(soa.Decode<mirror::Class>(j_caller)));
604*795d594fSAndroid Build Coastguard Worker   if (h_caller.IsNull()) {
605*795d594fSAndroid Build Coastguard Worker     ThrowNullPointerException("argument is null");
606*795d594fSAndroid Build Coastguard Worker     return;
607*795d594fSAndroid Build Coastguard Worker   }
608*795d594fSAndroid Build Coastguard Worker 
609*795d594fSAndroid Build Coastguard Worker   h_caller->SetSkipHiddenApiChecks();
610*795d594fSAndroid Build Coastguard Worker }
611*795d594fSAndroid Build Coastguard Worker 
VMDebug_setAllocTrackerStackDepth(JNIEnv * env,jclass,jint stack_depth)612*795d594fSAndroid Build Coastguard Worker static void VMDebug_setAllocTrackerStackDepth(JNIEnv* env, jclass, jint stack_depth) {
613*795d594fSAndroid Build Coastguard Worker   Runtime* runtime = Runtime::Current();
614*795d594fSAndroid Build Coastguard Worker   if (stack_depth < 0 ||
615*795d594fSAndroid Build Coastguard Worker       static_cast<size_t>(stack_depth) > gc::AllocRecordObjectMap::kMaxSupportedStackDepth) {
616*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
617*795d594fSAndroid Build Coastguard Worker     soa.Self()->ThrowNewExceptionF("Ljava/lang/RuntimeException;",
618*795d594fSAndroid Build Coastguard Worker                                    "Stack depth is invalid: %d",
619*795d594fSAndroid Build Coastguard Worker                                    stack_depth);
620*795d594fSAndroid Build Coastguard Worker   } else {
621*795d594fSAndroid Build Coastguard Worker     runtime->GetHeap()->SetAllocTrackerStackDepth(static_cast<size_t>(stack_depth));
622*795d594fSAndroid Build Coastguard Worker   }
623*795d594fSAndroid Build Coastguard Worker }
624*795d594fSAndroid Build Coastguard Worker 
VMDebug_setCurrentProcessName(JNIEnv * env,jclass,jstring process_name)625*795d594fSAndroid Build Coastguard Worker static void VMDebug_setCurrentProcessName(JNIEnv* env, jclass, jstring process_name) {
626*795d594fSAndroid Build Coastguard Worker   ScopedObjectAccess soa(env);
627*795d594fSAndroid Build Coastguard Worker 
628*795d594fSAndroid Build Coastguard Worker   // Android application ID naming convention states:
629*795d594fSAndroid Build Coastguard Worker   // "The name can contain uppercase or lowercase letters, numbers, and underscores ('_')"
630*795d594fSAndroid Build Coastguard Worker   // This is fine to convert to std::string
631*795d594fSAndroid Build Coastguard Worker   const char* c_process_name = env->GetStringUTFChars(process_name, NULL);
632*795d594fSAndroid Build Coastguard Worker   Runtime::Current()->GetRuntimeCallbacks()->SetCurrentProcessName(std::string(c_process_name));
633*795d594fSAndroid Build Coastguard Worker   env->ReleaseStringUTFChars(process_name, c_process_name);
634*795d594fSAndroid Build Coastguard Worker }
635*795d594fSAndroid Build Coastguard Worker 
VMDebug_addApplication(JNIEnv * env,jclass,jstring package_name)636*795d594fSAndroid Build Coastguard Worker static void VMDebug_addApplication(JNIEnv* env, jclass, jstring package_name) {
637*795d594fSAndroid Build Coastguard Worker   ScopedObjectAccess soa(env);
638*795d594fSAndroid Build Coastguard Worker 
639*795d594fSAndroid Build Coastguard Worker   // Android application ID naming convention states:
640*795d594fSAndroid Build Coastguard Worker   // "The name can contain uppercase or lowercase letters, numbers, and underscores ('_')"
641*795d594fSAndroid Build Coastguard Worker   // This is fine to convert to std::string
642*795d594fSAndroid Build Coastguard Worker   const char* c_package_name = env->GetStringUTFChars(package_name, NULL);
643*795d594fSAndroid Build Coastguard Worker   Runtime::Current()->GetRuntimeCallbacks()->AddApplication(std::string(c_package_name));
644*795d594fSAndroid Build Coastguard Worker   env->ReleaseStringUTFChars(package_name, c_package_name);
645*795d594fSAndroid Build Coastguard Worker }
646*795d594fSAndroid Build Coastguard Worker 
VMDebug_removeApplication(JNIEnv * env,jclass,jstring package_name)647*795d594fSAndroid Build Coastguard Worker static void VMDebug_removeApplication(JNIEnv* env, jclass, jstring package_name) {
648*795d594fSAndroid Build Coastguard Worker   ScopedObjectAccess soa(env);
649*795d594fSAndroid Build Coastguard Worker 
650*795d594fSAndroid Build Coastguard Worker   // Android application ID naming convention states:
651*795d594fSAndroid Build Coastguard Worker   // "The name can contain uppercase or lowercase letters, numbers, and underscores ('_')"
652*795d594fSAndroid Build Coastguard Worker   // This is fine to convert to std::string
653*795d594fSAndroid Build Coastguard Worker   const char* c_package_name = env->GetStringUTFChars(package_name, NULL);
654*795d594fSAndroid Build Coastguard Worker   Runtime::Current()->GetRuntimeCallbacks()->RemoveApplication(std::string(c_package_name));
655*795d594fSAndroid Build Coastguard Worker   env->ReleaseStringUTFChars(package_name, c_package_name);
656*795d594fSAndroid Build Coastguard Worker }
657*795d594fSAndroid Build Coastguard Worker 
VMDebug_setWaitingForDebugger(JNIEnv * env,jclass,jboolean waiting)658*795d594fSAndroid Build Coastguard Worker static void VMDebug_setWaitingForDebugger(JNIEnv* env, jclass, jboolean waiting) {
659*795d594fSAndroid Build Coastguard Worker   ScopedObjectAccess soa(env);
660*795d594fSAndroid Build Coastguard Worker   Runtime::Current()->GetRuntimeCallbacks()->SetWaitingForDebugger(waiting);
661*795d594fSAndroid Build Coastguard Worker }
662*795d594fSAndroid Build Coastguard Worker 
VMDebug_setUserId(JNIEnv * env,jclass,jint user_id)663*795d594fSAndroid Build Coastguard Worker static void VMDebug_setUserId(JNIEnv* env, jclass, jint user_id) {
664*795d594fSAndroid Build Coastguard Worker   ScopedObjectAccess soa(env);
665*795d594fSAndroid Build Coastguard Worker   Runtime::Current()->GetRuntimeCallbacks()->SetUserId(user_id);
666*795d594fSAndroid Build Coastguard Worker }
667*795d594fSAndroid Build Coastguard Worker 
668*795d594fSAndroid Build Coastguard Worker static JNINativeMethod gMethods[] = {
669*795d594fSAndroid Build Coastguard Worker     NATIVE_METHOD(VMDebug, countInstancesOfClass, "(Ljava/lang/Class;Z)J"),
670*795d594fSAndroid Build Coastguard Worker     NATIVE_METHOD(VMDebug, countInstancesOfClasses, "([Ljava/lang/Class;Z)[J"),
671*795d594fSAndroid Build Coastguard Worker     NATIVE_METHOD(VMDebug, dumpHprofData, "(Ljava/lang/String;I)V"),
672*795d594fSAndroid Build Coastguard Worker     NATIVE_METHOD(VMDebug, dumpHprofDataDdms, "()V"),
673*795d594fSAndroid Build Coastguard Worker     NATIVE_METHOD(VMDebug, dumpReferenceTables, "()V"),
674*795d594fSAndroid Build Coastguard Worker     NATIVE_METHOD(VMDebug, getAllocCount, "(I)I"),
675*795d594fSAndroid Build Coastguard Worker     FAST_NATIVE_METHOD(VMDebug, getLoadedClassCount, "()I"),
676*795d594fSAndroid Build Coastguard Worker     NATIVE_METHOD(VMDebug, getVmFeatureList, "()[Ljava/lang/String;"),
677*795d594fSAndroid Build Coastguard Worker     FAST_NATIVE_METHOD(VMDebug, isDebuggerConnected, "()Z"),
678*795d594fSAndroid Build Coastguard Worker     FAST_NATIVE_METHOD(VMDebug, isDebuggingEnabled, "()Z"),
679*795d594fSAndroid Build Coastguard Worker     NATIVE_METHOD(VMDebug, suspendAllAndSendVmStart, "()V"),
680*795d594fSAndroid Build Coastguard Worker     NATIVE_METHOD(VMDebug, getMethodTracingMode, "()I"),
681*795d594fSAndroid Build Coastguard Worker     FAST_NATIVE_METHOD(VMDebug, lastDebuggerActivity, "()J"),
682*795d594fSAndroid Build Coastguard Worker     FAST_NATIVE_METHOD(VMDebug, printLoadedClasses, "(I)V"),
683*795d594fSAndroid Build Coastguard Worker     NATIVE_METHOD(VMDebug, resetAllocCount, "(I)V"),
684*795d594fSAndroid Build Coastguard Worker     NATIVE_METHOD(VMDebug, startAllocCounting, "()V"),
685*795d594fSAndroid Build Coastguard Worker     NATIVE_METHOD(VMDebug, startMethodTracingDdmsImpl, "(IIZI)V"),
686*795d594fSAndroid Build Coastguard Worker     NATIVE_METHOD(VMDebug, startMethodTracingFd, "(Ljava/lang/String;IIIZIZ)V"),
687*795d594fSAndroid Build Coastguard Worker     NATIVE_METHOD(VMDebug, startMethodTracingFilename, "(Ljava/lang/String;IIZI)V"),
688*795d594fSAndroid Build Coastguard Worker     NATIVE_METHOD(VMDebug, stopAllocCounting, "()V"),
689*795d594fSAndroid Build Coastguard Worker     NATIVE_METHOD(VMDebug, stopMethodTracing, "()V"),
690*795d594fSAndroid Build Coastguard Worker     FAST_NATIVE_METHOD(VMDebug, threadCpuTimeNanos, "()J"),
691*795d594fSAndroid Build Coastguard Worker     NATIVE_METHOD(VMDebug, getRuntimeStatInternal, "(I)Ljava/lang/String;"),
692*795d594fSAndroid Build Coastguard Worker     NATIVE_METHOD(VMDebug, getRuntimeStatsInternal, "()[Ljava/lang/String;"),
693*795d594fSAndroid Build Coastguard Worker     NATIVE_METHOD(VMDebug, nativeAttachAgent, "(Ljava/lang/String;Ljava/lang/ClassLoader;)V"),
694*795d594fSAndroid Build Coastguard Worker     NATIVE_METHOD(VMDebug, allowHiddenApiReflectionFrom, "(Ljava/lang/Class;)V"),
695*795d594fSAndroid Build Coastguard Worker     NATIVE_METHOD(VMDebug, setAllocTrackerStackDepth, "(I)V"),
696*795d594fSAndroid Build Coastguard Worker     NATIVE_METHOD(VMDebug, setCurrentProcessName, "(Ljava/lang/String;)V"),
697*795d594fSAndroid Build Coastguard Worker     NATIVE_METHOD(VMDebug, setWaitingForDebugger, "(Z)V"),
698*795d594fSAndroid Build Coastguard Worker     NATIVE_METHOD(VMDebug, addApplication, "(Ljava/lang/String;)V"),
699*795d594fSAndroid Build Coastguard Worker     NATIVE_METHOD(VMDebug, removeApplication, "(Ljava/lang/String;)V"),
700*795d594fSAndroid Build Coastguard Worker     NATIVE_METHOD(VMDebug, setUserId, "(I)V"),
701*795d594fSAndroid Build Coastguard Worker     NATIVE_METHOD(VMDebug, startLowOverheadTraceImpl, "()V"),
702*795d594fSAndroid Build Coastguard Worker     NATIVE_METHOD(VMDebug, stopLowOverheadTraceImpl, "()V"),
703*795d594fSAndroid Build Coastguard Worker     NATIVE_METHOD(VMDebug, dumpLowOverheadTraceImpl, "(Ljava/lang/String;)V"),
704*795d594fSAndroid Build Coastguard Worker     NATIVE_METHOD(VMDebug, dumpLowOverheadTraceFdImpl, "(I)V"),
705*795d594fSAndroid Build Coastguard Worker     NATIVE_METHOD(
706*795d594fSAndroid Build Coastguard Worker         VMDebug,
707*795d594fSAndroid Build Coastguard Worker         getExecutableMethodFileOffsetsNative,
708*795d594fSAndroid Build Coastguard Worker         "(Ljava/lang/reflect/Method;)Ldalvik/system/VMDebug$ExecutableMethodFileOffsets;"),
709*795d594fSAndroid Build Coastguard Worker };
710*795d594fSAndroid Build Coastguard Worker 
register_dalvik_system_VMDebug(JNIEnv * env)711*795d594fSAndroid Build Coastguard Worker void register_dalvik_system_VMDebug(JNIEnv* env) {
712*795d594fSAndroid Build Coastguard Worker   REGISTER_NATIVE_METHODS("dalvik/system/VMDebug");
713*795d594fSAndroid Build Coastguard Worker }
714*795d594fSAndroid Build Coastguard Worker 
715*795d594fSAndroid Build Coastguard Worker }  // namespace art
716