Skip to content

Commit 27a71fc

Browse files
committed
[Mono.Android] Java.Lang.Throwable overrides Exception.ToString()
Fixes: https://bugzilla.xamarin.com/show_bug.cgi?id=42366 A funny thing happened between Xamarin.Android 6.0 and 6.1: we bumped from Mono 4.2 to Mono 4.4, and Mono 4.4 now uses Microsoft's referencesource for `System.Exception`. In Mono 4.2, `System.Exception.ToString()` accesses the `System.Exception.StackTrace` property. Since `Java.Lang.Throwable` overrode the `Exception.StackTrace` property to append the Java-side stack trace, this was sufficient to cause `.ToString()` usage to likewise contain the java-side stack: var e = new Java.Lang.Throwable ("Boo!"); var s = e.ToString (); // s contains "... --- End of managed exception stack trace --- ..." This is *not* the case in Mono 4.4: `Exception.ToString()` *doesn't* use the `Exception.StackTrace` property, so the `Throwable.StackTrace` override is ignored, making for less-than-useful `.ToString()` value: // s == "Java.Lang.Throwable: Exception of type 'Java.Lang.Throwable' was thrown" // s does NOT contain the Java-side callstack! Update `Java.Lang.Throwable` to override `Exception.ToString()` so that the Java-side stack trace is always appended, if present. This allows `Exception.ToString()` to be far more useful: Java.Lang.Throwable: Exception of type 'Java.Lang.Throwable' was thrown. --- End of managed Java.Lang.Throwable stack trace --- java.lang.Throwable: Boo! at md5bb7ab8908f0a1e03a3f881aa9f8f5eef.MainActivity.n_onCreate(Native Method) at md5bb7ab8908f0a1e03a3f881aa9f8f5eef.MainActivity.onCreate(MainActivity.java:29) ...
1 parent 8aa18fc commit 27a71fc

File tree

1 file changed

+34
-10
lines changed

1 file changed

+34
-10
lines changed

src/Mono.Android/Java.Lang/Throwable.cs

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ public partial class Throwable : global::System.Exception, IJavaObject, IDisposa
1313
#endif // JAVA_INTEROP
1414
{
1515

16-
static IntPtr java_lang_Object_toString;
1716
protected bool is_generated;
1817
IntPtr handle;
1918

@@ -130,20 +129,45 @@ IntPtr IJavaObjectEx.ToLocalJniHandle ()
130129

131130
public override string StackTrace {
132131
get {
133-
if (string.IsNullOrEmpty (nativeStack) && handle != IntPtr.Zero) {
134-
using (var nativeStackWriter = new Java.IO.StringWriter ())
135-
using (var nativeStackPw = new Java.IO.PrintWriter (nativeStackWriter)) {
136-
PrintStackTrace (nativeStackPw);
137-
nativeStack = nativeStackWriter.ToString ();
138-
}
139-
nativeStack = base.StackTrace + Environment.NewLine +
140-
" --- End of managed exception stack trace ---" + Environment.NewLine +
141-
nativeStack;
132+
return base.StackTrace + ManagedStackTraceAddendum;
133+
}
134+
}
135+
136+
string ManagedStackTraceAddendum {
137+
get {
138+
var javaStack = JavaStackTrace;
139+
if (string.IsNullOrEmpty (javaStack))
140+
return "";
141+
return Environment.NewLine +
142+
" --- End of managed " +
143+
GetType ().FullName +
144+
" stack trace ---" + Environment.NewLine +
145+
javaStack;
146+
}
147+
}
148+
149+
string JavaStackTrace {
150+
get {
151+
if (!string.IsNullOrEmpty (nativeStack))
152+
return nativeStack;
153+
154+
if (handle == IntPtr.Zero)
155+
return null;
156+
157+
using (var nativeStackWriter = new Java.IO.StringWriter ())
158+
using (var nativeStackPw = new Java.IO.PrintWriter (nativeStackWriter)) {
159+
PrintStackTrace (nativeStackPw);
160+
nativeStack = nativeStackWriter.ToString ();
142161
}
143162
return nativeStack;
144163
}
145164
}
146165

166+
public override string ToString ()
167+
{
168+
return base.ToString () + ManagedStackTraceAddendum;
169+
}
170+
147171
#if JAVA_INTEROP
148172
public int JniIdentityHashCode {
149173
get {return (int) key_handle;}

0 commit comments

Comments
 (0)