Fix stack trace for proxy methods and added test case.
Bug: 11861564
Change-Id: I9513359ff9e5d345ee71d84388afed02bd114ecf
(cherry picked from 228d6b8a4f0a21c1e9b2372c3104ce4ee19f65b4)
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 23cafe8..7d65f5a 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -1332,7 +1332,7 @@
return true; // Ignore runtime frames (in particular callee save).
}
method_trace_->Set(count_, m);
- dex_pc_trace_->Set(count_, GetDexPc());
+ dex_pc_trace_->Set(count_, m->IsProxyMethod() ? DexFile::kDexNoIndex : GetDexPc());
++count_;
return true;
}
@@ -1384,7 +1384,6 @@
mirror::ObjectArray<mirror::Object>* method_trace =
soa.Decode<mirror::ObjectArray<mirror::Object>*>(internal);
int32_t depth = method_trace->GetLength() - 1;
- mirror::IntArray* pc_trace = down_cast<mirror::IntArray*>(method_trace->Get(depth));
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
@@ -1413,19 +1412,32 @@
for (int32_t i = 0; i < depth; ++i) {
// Prepare parameters for StackTraceElement(String cls, String method, String file, int line)
mirror::ArtMethod* method = down_cast<mirror::ArtMethod*>(method_trace->Get(i));
- mh.ChangeMethod(method);
- uint32_t dex_pc = pc_trace->Get(i);
- int32_t line_number = mh.GetLineNumFromDexPC(dex_pc);
- // Allocate element, potentially triggering GC
- // TODO: reuse class_name_object via Class::name_?
- const char* descriptor = mh.GetDeclaringClassDescriptor();
- CHECK(descriptor != NULL);
- std::string class_name(PrettyDescriptor(descriptor));
- SirtRef<mirror::String> class_name_object(soa.Self(),
- mirror::String::AllocFromModifiedUtf8(soa.Self(),
- class_name.c_str()));
- if (class_name_object.get() == NULL) {
- return NULL;
+ MethodHelper mh(method);
+ int32_t line_number;
+ SirtRef<mirror::String> class_name_object(soa.Self(), NULL);
+ SirtRef<mirror::String> source_name_object(soa.Self(), NULL);
+ if (method->IsProxyMethod()) {
+ line_number = -1;
+ class_name_object.reset(method->GetDeclaringClass()->GetName());
+ // source_name_object intentionally left null for proxy methods
+ } else {
+ mirror::IntArray* pc_trace = down_cast<mirror::IntArray*>(method_trace->Get(depth));
+ uint32_t dex_pc = pc_trace->Get(i);
+ line_number = mh.GetLineNumFromDexPC(dex_pc);
+ // Allocate element, potentially triggering GC
+ // TODO: reuse class_name_object via Class::name_?
+ const char* descriptor = mh.GetDeclaringClassDescriptor();
+ CHECK(descriptor != NULL);
+ std::string class_name(PrettyDescriptor(descriptor));
+ class_name_object.reset(mirror::String::AllocFromModifiedUtf8(soa.Self(), class_name.c_str()));
+ if (class_name_object.get() == NULL) {
+ return NULL;
+ }
+ const char* source_file = mh.GetDeclaringClassSourceFile();
+ source_name_object.reset(mirror::String::AllocFromModifiedUtf8(soa.Self(), source_file));
+ if (source_name_object.get() == NULL) {
+ return NULL;
+ }
}
const char* method_name = mh.GetName();
CHECK(method_name != NULL);
@@ -1435,14 +1447,8 @@
if (method_name_object.get() == NULL) {
return NULL;
}
- const char* source_file = mh.GetDeclaringClassSourceFile();
- SirtRef<mirror::String> source_name_object(soa.Self(), mirror::String::AllocFromModifiedUtf8(soa.Self(),
- source_file));
mirror::StackTraceElement* obj = mirror::StackTraceElement::Alloc(soa.Self(),
- class_name_object.get(),
- method_name_object.get(),
- source_name_object.get(),
- line_number);
+ class_name_object.get(), method_name_object.get(), source_name_object.get(), line_number);
if (obj == NULL) {
return NULL;
}
diff --git a/test/044-proxy/expected.txt b/test/044-proxy/expected.txt
index eafaf1d..400a161 100644
--- a/test/044-proxy/expected.txt
+++ b/test/044-proxy/expected.txt
@@ -42,6 +42,7 @@
(no args)
--- blob
Success: method blob res=mix
+$Proxy1.getTrace null:-1
Invoke public abstract void Shapes.upChuck()
(no args)
Got expected ioobe
@@ -49,8 +50,8 @@
(no args)
Got expected ie
-Proxy interfaces: [interface Quads, interface Colors]
-Proxy methods: [public final java.lang.String $Proxy1.blob(), public final double $Proxy1.blue(int), public final R0a $Proxy1.checkMe(), public final R0aa $Proxy1.checkMe(), public final R0base $Proxy1.checkMe(), public final void $Proxy1.circle(int), public final boolean $Proxy1.equals(java.lang.Object), public final int $Proxy1.green(double), public final int $Proxy1.hashCode(), public final int $Proxy1.mauve(java.lang.String), public final int $Proxy1.rectangle(int,int), public final int $Proxy1.red(float), public final int $Proxy1.square(int,int), public final java.lang.String $Proxy1.toString(), public final int $Proxy1.trapezoid(int,double,int), public final void $Proxy1.upCheck() throws java.lang.InterruptedException, public final void $Proxy1.upChuck()]
+Proxy interfaces: [interface Quads, interface Colors, interface Trace]
+Proxy methods: [public final java.lang.String $Proxy1.blob(), public final double $Proxy1.blue(int), public final R0a $Proxy1.checkMe(), public final R0aa $Proxy1.checkMe(), public final R0base $Proxy1.checkMe(), public final void $Proxy1.circle(int), public final boolean $Proxy1.equals(java.lang.Object), public final void $Proxy1.getTrace(), public final int $Proxy1.green(double), public final int $Proxy1.hashCode(), public final int $Proxy1.mauve(java.lang.String), public final int $Proxy1.rectangle(int,int), public final int $Proxy1.red(float), public final int $Proxy1.square(int,int), public final java.lang.String $Proxy1.toString(), public final int $Proxy1.trapezoid(int,double,int), public final void $Proxy1.upCheck() throws java.lang.InterruptedException, public final void $Proxy1.upChuck()]
Decl annos: []
Param annos (0) : []
Dupe threw expected exception
diff --git a/test/044-proxy/src/BasicTest.java b/test/044-proxy/src/BasicTest.java
index 46aa3fe..ea46f49 100644
--- a/test/044-proxy/src/BasicTest.java
+++ b/test/044-proxy/src/BasicTest.java
@@ -51,6 +51,8 @@
colors.blue(777);
colors.mauve("sorry");
colors.blob();
+ Trace trace = (Trace) proxy;
+ trace.getTrace();
try {
shapes.upChuck();
@@ -96,7 +98,7 @@
/* create the proxy class */
Class proxyClass = Proxy.getProxyClass(Shapes.class.getClassLoader(),
- new Class[] { Quads.class, Colors.class });
+ new Class[] { Quads.class, Colors.class, Trace.class });
/* create a proxy object, passing the handler object in */
Object proxy = null;
@@ -156,6 +158,10 @@
public R0aa checkMe();
}
+interface Trace {
+ public void getTrace();
+}
+
/*
* Some return types.
*/
@@ -248,6 +254,20 @@
throw new RuntimeException("huh?");
}
+ if (method.getDeclaringClass() == Trace.class) {
+ if (method.getName().equals("getTrace")) {
+ StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
+ for (int i = 0; i < stackTrace.length; i++) {
+ StackTraceElement ste = stackTrace[i];
+ if (ste.getMethodName().equals("getTrace")) {
+ System.out.println(ste.getClassName() + "." + ste.getMethodName() + " " +
+ ste.getFileName() + ":" + ste.getLineNumber());
+ }
+ }
+ return null;
+ }
+ }
+
System.out.println("Invoke " + method);
if (args == null || args.length == 0) {
System.out.println(" (no args)");