Tuesday, October 21, 2025

Effect of the omission of the symbolmap files on the stacktrace's line numbers

I have witnessed some - imo odd - GWT behavior regarding stacktrace accuracy that I cannot yet fully comprehend, so I am posting it here.

I have a GWT application of which the .gwt.xml file contains these three lines:

<set-property name="compiler.stackMode" value="emulated" />
<set-configuration-property name="compiler.emulatedStack.recordLineNumbers" value="true"/>
<set-configuration-property name="compiler.emulatedStack.recordFileNames" value="true"/>

Also, I ensured a StringOutOfBoundsException to occur on a distinct screen by doing this:

GWT.log("123".substring(65));

in SomePanel.java on line 195.

To conclude, I made two release builds: 'build A' and 'build B'. A and B are identical, except for B not having any symbol maps present in the resulting file structure (they are manually removed post-compilation) before a distributable zip file is made. The omission of the symbol map files is an attempt to no longer enable end users to be able to view deobfuscated stacktraces directly in the browser's console or to perform deobfuscation manually offline.

When navigating to the broken screen of build A, the stacktrace that is printed to the browser's console is deobfuscated (duh) and - more importantly - 100% correct regarding file names and line numbers. Therefore, it's straightforward to pinpoint where any issue did occur in the original Java code.

When navigating to the broken screen of build B, the stacktrace that is printed to the browser's console is obfuscated, but ... wrong in terms of file names and line numbers... This is the stacktrace that was printed out in the browser's console in this occasion:

java.lang.StringIndexOutOfBoundsException: Index: 65, Size: 4
    at Unknown.qXf(Throwable.java:66)
    at Unknown.CXf(Exception.java:29)
    at Unknown.H3f(RuntimeException.java:29)
    at Unknown.bop(IndexOutOfBoundsException.java:29)
    at Unknown.wrp(StringIndexOutOfBoundsException.java:30)
    at Unknown.OKp(InternalPreconditions.java:487)
    at Unknown.pwf(InternalPreconditions.java:475)
    at Unknown.hbe(NavigationManager.java:287)
    at Unknown.kbe(NavigationManager.java:118)
    at Unknown.RPe(MainPanel.java:604)
    at Unknown.Ung(ValueChangeEvent.java:128)
    at Unknown.hog(GwtEvent.java:76)
    at Unknown._ng(SimpleEventBus.java:88)
    at Unknown.Ntj(History.java:68)
    at Unknown.Vng(ValueChangeEvent.java:43)
    at Unknown.FPe(History.java:77)
    at Unknown.Qae(Application.java:273)
    at Unknown.cbe(Application.java:269)
    at Unknown.wke(TablesDataManager.java:43)
    at Unknown.MWf(JsonRequestBuilder.java:164)
    at Unknown.Pog(Request.java:227)
    at Unknown.cpg(RequestBuilder.java:412)
    at Unknown.anonymous(XMLHttpRequest.java:329)
    at Unknown.Wag(Impl.java:299)
    at Unknown.Zag(Impl.java:351)
    at Unknown.anonymous(Impl.java:78)

Using GWT's com.google.gwt.core.server.StackTraceDeobfuscator and the according symbol map, I was able to deobfuscate this to:

java.lang.Throwable: java.lang.StringIndexOutOfBoundsException: Index: 65, Size: 4
        at java.lang.Throwable.Throwable(Throwable.java:69)
        at java.lang.Exception.Exception(Exception.java:36)
        at java.lang.RuntimeException.RuntimeException(RuntimeException.java:32)
        at java.lang.ArithmeticException.ArithmeticException(ArithmeticException.java:27)
        at java.lang.StringBuilder.StringBuilder(StringBuilder.java:41)
        at javaemul.internal.InternalPreconditions.checkCriticalState(InternalPreconditions.java:379)
        at com.example.client.panels.SomePanel.someMethod(SomePanel.java:645)
        at  com.example.client.NavigationManager.hideAllPopupMenus(NavigationManager.java:372)
        at  com.example.client.NavigationManager.navigateAbsentRequests(NavigationManager.java:457)
        at  com.example.client.panels.main.MainPanel$1.MainPanel$1(MainPanel.java:312)
        at com.google.gwt.event.logical.shared.ValueChangeEvent.ValueChangeEvent(ValueChangeEvent.java:100)
        at com.google.web.bindery.event.shared.SimpleEventBus.$doAddNow(SimpleEventBus.java:168)
        at com.google.gwt.event.shared.HandlerManager.$addHandler(HandlerManager.java:98)
        at com.google.gwt.user.client.History$HistoryEventSource.History$HistoryEventSource(History.java:62)
        at com.google.gwt.event.logical.shared.ValueChangeEvent.dispatch(ValueChangeEvent.java:127)
        at com.example.client.panels.main.MainPanel.$lambda$2(MainPanel.java:252)
        at com.example.client.Application.$successLogin(Application.java:220)
        at com.example.client.Application.$lambda$6$Type.Application$lambda$6$Type(Application.java:299)
        at com.example.client.client.datamanager.SomeDataManager.getSomeData(SomeDataManager.java:100)
        at  com.example.jsonrpc.client.JsonRequestBuilder$2.JsonRequestBuilder$2(JsonRequestBuilder.java:377)
        at com.google.gwt.http.client.Request.$cancel(Request.java:151)
        at com.google.gwt.http.client.RequestBuilder$1.RequestBuilder$1(RequestBuilder.java:408)
        at Unknown.anonymous(XMLHttpRequest.java:329)
        at com.google.gwt.core.client.impl.Impl.enter(Impl.java:313)
        at com.google.gwt.core.client.impl.Impl.exit(Impl.java:373)
        at Unknown.anonymous(Impl.java:78)

So the exception's message is still correct, but the line number where the faulty line of code is present (195) is nowhere to be found in the deobfuscated stacktrace. Also worth noting is that the exception caused by the faulty line of code in SomePanel.java is reached after a few successive method invocations, although the deobfuscated stacktrace doesn't include those in the stack: I expected to have multiple stacktrace elements to exist between the one mentioning SomePanel:someMethod and the one showing the StringIndexOutOfBoundsException happening, but they simply aren't there for some reason.

Can someone shed a light on why all of this is happening in the way it does?

Kind regards,
Nick

When the 

--
You received this message because you are subscribed to the Google Groups "GWT Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-web-toolkit+unsubscribe@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/google-web-toolkit/66de6fea-89d3-489c-8667-c612224e7f59n%40googlegroups.com.

No comments:

Post a Comment