summaryrefslogtreecommitdiffstats
path: root/runtime/native/dalvik_system_VMStack.cc
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/native/dalvik_system_VMStack.cc')
-rw-r--r--runtime/native/dalvik_system_VMStack.cc132
1 files changed, 132 insertions, 0 deletions
diff --git a/runtime/native/dalvik_system_VMStack.cc b/runtime/native/dalvik_system_VMStack.cc
new file mode 100644
index 0000000000..1a80d6286b
--- /dev/null
+++ b/runtime/native/dalvik_system_VMStack.cc
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "jni_internal.h"
+#include "nth_caller_visitor.h"
+#include "mirror/abstract_method-inl.h"
+#include "mirror/class-inl.h"
+#include "mirror/class_loader.h"
+#include "mirror/object-inl.h"
+#include "scoped_thread_state_change.h"
+#include "thread_list.h"
+
+namespace art {
+
+static jobject GetThreadStack(JNIEnv* env, jobject peer) {
+ {
+ ScopedObjectAccess soa(env);
+ if (soa.Decode<mirror::Object*>(peer) == soa.Self()->GetPeer()) {
+ return soa.Self()->CreateInternalStackTrace(soa);
+ }
+ }
+ // Suspend thread to build stack trace.
+ bool timed_out;
+ Thread* thread = Thread::SuspendForDebugger(peer, true, &timed_out);
+ if (thread != NULL) {
+ jobject trace;
+ {
+ ScopedObjectAccess soa(env);
+ trace = thread->CreateInternalStackTrace(soa);
+ }
+ // Restart suspended thread.
+ Runtime::Current()->GetThreadList()->Resume(thread, true);
+ return trace;
+ } else {
+ if (timed_out) {
+ LOG(ERROR) << "Trying to get thread's stack failed as the thread failed to suspend within a "
+ "generous timeout.";
+ }
+ return NULL;
+ }
+}
+
+static jint VMStack_fillStackTraceElements(JNIEnv* env, jclass, jobject javaThread,
+ jobjectArray javaSteArray) {
+ jobject trace = GetThreadStack(env, javaThread);
+ if (trace == NULL) {
+ return 0;
+ }
+ int32_t depth;
+ Thread::InternalStackTraceToStackTraceElementArray(env, trace, javaSteArray, &depth);
+ return depth;
+}
+
+// Returns the defining class loader of the caller's caller.
+static jobject VMStack_getCallingClassLoader(JNIEnv* env, jclass) {
+ ScopedObjectAccess soa(env);
+ NthCallerVisitor visitor(soa.Self(), 2);
+ visitor.WalkStack();
+ return soa.AddLocalReference<jobject>(visitor.caller->GetDeclaringClass()->GetClassLoader());
+}
+
+static jobject VMStack_getClosestUserClassLoader(JNIEnv* env, jclass, jobject javaBootstrap,
+ jobject javaSystem) {
+ struct ClosestUserClassLoaderVisitor : public StackVisitor {
+ ClosestUserClassLoaderVisitor(Thread* thread, mirror::Object* bootstrap, mirror::Object* system)
+ : StackVisitor(thread, NULL), bootstrap(bootstrap), system(system), class_loader(NULL) {}
+
+ bool VisitFrame() {
+ DCHECK(class_loader == NULL);
+ mirror::Class* c = GetMethod()->GetDeclaringClass();
+ mirror::Object* cl = c->GetClassLoader();
+ if (cl != NULL && cl != bootstrap && cl != system) {
+ class_loader = cl;
+ return false;
+ }
+ return true;
+ }
+
+ mirror::Object* bootstrap;
+ mirror::Object* system;
+ mirror::Object* class_loader;
+ };
+ ScopedObjectAccess soa(env);
+ mirror::Object* bootstrap = soa.Decode<mirror::Object*>(javaBootstrap);
+ mirror::Object* system = soa.Decode<mirror::Object*>(javaSystem);
+ ClosestUserClassLoaderVisitor visitor(soa.Self(), bootstrap, system);
+ visitor.WalkStack();
+ return soa.AddLocalReference<jobject>(visitor.class_loader);
+}
+
+// Returns the class of the caller's caller's caller.
+static jclass VMStack_getStackClass2(JNIEnv* env, jclass) {
+ ScopedObjectAccess soa(env);
+ NthCallerVisitor visitor(soa.Self(), 3);
+ visitor.WalkStack();
+ return soa.AddLocalReference<jclass>(visitor.caller->GetDeclaringClass());
+}
+
+static jobjectArray VMStack_getThreadStackTrace(JNIEnv* env, jclass, jobject javaThread) {
+ jobject trace = GetThreadStack(env, javaThread);
+ if (trace == NULL) {
+ return NULL;
+ }
+ return Thread::InternalStackTraceToStackTraceElementArray(env, trace);
+}
+
+static JNINativeMethod gMethods[] = {
+ NATIVE_METHOD(VMStack, fillStackTraceElements, "(Ljava/lang/Thread;[Ljava/lang/StackTraceElement;)I"),
+ NATIVE_METHOD(VMStack, getCallingClassLoader, "()Ljava/lang/ClassLoader;"),
+ NATIVE_METHOD(VMStack, getClosestUserClassLoader, "(Ljava/lang/ClassLoader;Ljava/lang/ClassLoader;)Ljava/lang/ClassLoader;"),
+ NATIVE_METHOD(VMStack, getStackClass2, "()Ljava/lang/Class;"),
+ NATIVE_METHOD(VMStack, getThreadStackTrace, "(Ljava/lang/Thread;)[Ljava/lang/StackTraceElement;"),
+};
+
+void register_dalvik_system_VMStack(JNIEnv* env) {
+ REGISTER_NATIVE_METHODS("dalvik/system/VMStack");
+}
+
+} // namespace art