1f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes/* 2f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * Copyright (C) 2008 The Android Open Source Project 3f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * 4f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License"); 5f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * you may not use this file except in compliance with the License. 6f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * You may obtain a copy of the License at 7f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * 8f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * http://www.apache.org/licenses/LICENSE-2.0 9f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * 10f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * Unless required by applicable law or agreed to in writing, software 11f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS, 12f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * See the License for the specific language governing permissions and 14f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * limitations under the License. 15f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes */ 16f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes 17277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe#include "org_apache_harmony_dalvik_ddmc_DdmVmInternal.h" 18277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe 1907ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include "base/logging.h" 2076b6167407c2b6f5d40ad895b2793a6b037f54b2Elliott Hughes#include "base/mutex.h" 21f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes#include "debugger.h" 22eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes#include "jni_internal.h" 2353b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers#include "scoped_fast_native_object_access.h" 2400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#include "ScopedLocalRef.h" 25eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes#include "ScopedPrimitiveArray.h" 26bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes#include "stack.h" 27bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes#include "thread_list.h" 28f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes 29f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughesnamespace art { 30f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes 311bac54ffa933fbe9b92b62437577f2f4583eff1aElliott Hughesstatic void DdmVmInternal_enableRecentAllocations(JNIEnv*, jclass, jboolean enable) { 32545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes Dbg::SetAllocTrackingEnabled(enable); 33f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes} 34f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes 3500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersstatic jbyteArray DdmVmInternal_getRecentAllocations(JNIEnv* env, jclass) { 3653b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers ScopedFastNativeObjectAccess soa(env); 37545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes return Dbg::GetRecentAllocations(); 38f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes} 39f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes 401bac54ffa933fbe9b92b62437577f2f4583eff1aElliott Hughesstatic jboolean DdmVmInternal_getRecentAllocationStatus(JNIEnv*, jclass) { 41545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes return Dbg::IsAllocTrackingEnabled(); 42f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes} 43f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes 44f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes/* 45f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * Get a stack trace as an array of StackTraceElement objects. Returns 462cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier * nullptr on failure, e.g. if the threadId couldn't be found. 47f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes */ 48bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughesstatic jobjectArray DdmVmInternal_getStackTraceById(JNIEnv* env, jclass, jint thin_lock_id) { 4953b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers jobjectArray trace = nullptr; 50970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz Thread* const self = Thread::Current(); 51970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz if (static_cast<uint32_t>(thin_lock_id) == self->GetThreadId()) { 52970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz // No need to suspend ourself to build stacktrace. 53970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz ScopedObjectAccess soa(env); 54ee1d79a603c77c0667b27c075a983579d5c51f7eSebastien Hertz jobject internal_trace = self->CreateInternalStackTrace<false>(soa); 55970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz trace = Thread::InternalStackTraceToStackTraceElementArray(soa, internal_trace); 5600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } else { 57970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz ThreadList* thread_list = Runtime::Current()->GetThreadList(); 58970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz bool timed_out; 5914e81447ebaa1d80aae0c53312d4ff238d3fd98aJohnnie Birch 6014e81447ebaa1d80aae0c53312d4ff238d3fd98aJohnnie Birch // Check for valid thread 6114e81447ebaa1d80aae0c53312d4ff238d3fd98aJohnnie Birch if (thin_lock_id == ThreadList::kInvalidThreadId) { 6214e81447ebaa1d80aae0c53312d4ff238d3fd98aJohnnie Birch return nullptr; 6314e81447ebaa1d80aae0c53312d4ff238d3fd98aJohnnie Birch } 6414e81447ebaa1d80aae0c53312d4ff238d3fd98aJohnnie Birch 6514e81447ebaa1d80aae0c53312d4ff238d3fd98aJohnnie Birch // Suspend thread to build stack trace. 664ad5cd3e7d519484559ef778d96fb3f0be8919faIan Rogers Thread* thread = thread_list->SuspendThreadByThreadId(thin_lock_id, false, &timed_out); 67970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz if (thread != nullptr) { 68970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz { 69970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz ScopedObjectAccess soa(env); 70ee1d79a603c77c0667b27c075a983579d5c51f7eSebastien Hertz jobject internal_trace = thread->CreateInternalStackTrace<false>(soa); 71970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz trace = Thread::InternalStackTraceToStackTraceElementArray(soa, internal_trace); 72970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz } 73970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz // Restart suspended thread. 74970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz thread_list->Resume(thread, false); 75970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz } else { 76970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz if (timed_out) { 77970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz LOG(ERROR) << "Trying to get thread's stack by id failed as the thread failed to suspend " 78970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz "within a generous timeout."; 79970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz } 8015bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers } 81bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes } 8253b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers return trace; 83bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes} 84bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes 85bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughesstatic void ThreadCountCallback(Thread*, void* context) { 86bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes uint16_t& count = *reinterpret_cast<uint16_t*>(context); 87bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes ++count; 88bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes} 89bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes 90bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughesstatic const int kThstBytesPerEntry = 18; 91bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughesstatic const int kThstHeaderLen = 4; 92bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes 93bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughesstatic void ThreadStatsGetterCallback(Thread* t, void* context) { 94bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes /* 95bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes * Generate the contents of a THST chunk. The data encompasses all known 96bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes * threads. 97bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes * 98bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes * Response has: 99bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes * (1b) header len 100bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes * (1b) bytes per entry 101bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes * (2b) thread count 102bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes * Then, for each thread: 10321f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes * (4b) thread id 104bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes * (1b) thread status 105bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes * (4b) tid 106bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes * (4b) utime 107bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes * (4b) stime 108bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes * (1b) is daemon? 109bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes * 110bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes * The length fields exist in anticipation of adding additional fields 111bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes * without wanting to break ddms or bump the full protocol version. I don't 112bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes * think it warrants full versioning. They might be extraneous and could 113bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes * be removed from a future version. 114bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes */ 115ba0b9c55adce3f533845ab1b25c552589e5b4118Elliott Hughes char native_thread_state; 1162921201dce37ba40c55b89c0deca3c34bf64168eBrian Carlstrom int utime; 1172921201dce37ba40c55b89c0deca3c34bf64168eBrian Carlstrom int stime; 1182921201dce37ba40c55b89c0deca3c34bf64168eBrian Carlstrom int task_cpu; 1192921201dce37ba40c55b89c0deca3c34bf64168eBrian Carlstrom GetTaskStats(t->GetTid(), &native_thread_state, &utime, &stime, &task_cpu); 120bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes 12121f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes std::vector<uint8_t>& bytes = *reinterpret_cast<std::vector<uint8_t>*>(context); 122d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers JDWP::Append4BE(bytes, t->GetThreadId()); 123920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao JDWP::Append1BE(bytes, Dbg::ToJdwpThreadStatus(t->GetState())); 12421f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes JDWP::Append4BE(bytes, t->GetTid()); 12521f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes JDWP::Append4BE(bytes, utime); 12621f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes JDWP::Append4BE(bytes, stime); 12721f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes JDWP::Append1BE(bytes, t->IsDaemon()); 128f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes} 129f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes 130f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughesstatic jbyteArray DdmVmInternal_getThreadStats(JNIEnv* env, jclass) { 131bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes std::vector<uint8_t> bytes; 13250b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers Thread* self = static_cast<JNIEnvExt*>(env)->self; 133bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes { 13450b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers MutexLock mu(self, *Locks::thread_list_lock_); 135bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes ThreadList* thread_list = Runtime::Current()->GetThreadList(); 136bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes 13721f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes uint16_t thread_count = 0; 138bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes thread_list->ForEach(ThreadCountCallback, &thread_count); 139bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes 14021f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes JDWP::Append1BE(bytes, kThstHeaderLen); 14121f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes JDWP::Append1BE(bytes, kThstBytesPerEntry); 14221f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes JDWP::Append2BE(bytes, thread_count); 143bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes 14421f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes thread_list->ForEach(ThreadStatsGetterCallback, &bytes); 145bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes } 146bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes 147bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes jbyteArray result = env->NewByteArray(bytes.size()); 1482cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier if (result != nullptr) { 149545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes env->SetByteArrayRegion(result, 0, bytes.size(), reinterpret_cast<const jbyte*>(&bytes[0])); 150545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes } 151bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes return result; 152f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes} 153f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes 15400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersstatic jint DdmVmInternal_heapInfoNotify(JNIEnv* env, jclass, jint when) { 15553b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers ScopedFastNativeObjectAccess soa(env); 156767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes return Dbg::DdmHandleHpifChunk(static_cast<Dbg::HpifWhen>(when)); 157f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes} 158f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes 1591bac54ffa933fbe9b92b62437577f2f4583eff1aElliott Hughesstatic jboolean DdmVmInternal_heapSegmentNotify(JNIEnv*, jclass, jint when, jint what, jboolean native) { 160767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes return Dbg::DdmHandleHpsgNhsgChunk(static_cast<Dbg::HpsgWhen>(when), static_cast<Dbg::HpsgWhat>(what), native); 161f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes} 162f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes 1631bac54ffa933fbe9b92b62437577f2f4583eff1aElliott Hughesstatic void DdmVmInternal_threadNotify(JNIEnv*, jclass, jboolean enable) { 16447fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes Dbg::DdmSetThreadNotification(enable); 165f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes} 166f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes 167f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughesstatic JNINativeMethod gMethods[] = { 168f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes NATIVE_METHOD(DdmVmInternal, enableRecentAllocations, "(Z)V"), 16953b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers NATIVE_METHOD(DdmVmInternal, getRecentAllocations, "!()[B"), 17053b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers NATIVE_METHOD(DdmVmInternal, getRecentAllocationStatus, "!()Z"), 171f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes NATIVE_METHOD(DdmVmInternal, getStackTraceById, "(I)[Ljava/lang/StackTraceElement;"), 172f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes NATIVE_METHOD(DdmVmInternal, getThreadStats, "()[B"), 17353b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers NATIVE_METHOD(DdmVmInternal, heapInfoNotify, "!(I)Z"), 174f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes NATIVE_METHOD(DdmVmInternal, heapSegmentNotify, "(IIZ)Z"), 175f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes NATIVE_METHOD(DdmVmInternal, threadNotify, "(Z)V"), 176f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes}; 177f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes 178f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughesvoid register_org_apache_harmony_dalvik_ddmc_DdmVmInternal(JNIEnv* env) { 179eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes REGISTER_NATIVE_METHODS("org/apache/harmony/dalvik/ddmc/DdmVmInternal"); 180f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes} 181f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes 182f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes} // namespace art 183