无法反混淆GWT堆栈跟踪

16

我们正在尝试将未捕获的GWT异常(我们使用的是GWT 2.5 rc1版本)发送到服务器以进行日志记录和调试。我们希望对异常堆栈跟踪进行反混淆,否则它几乎没有用。

经过一些调查,我发现了 7个关于GWT异常处理的技巧WebModeExceptions 这两篇文章提供了有价值的信息。

因此,我们创建了一个GWT UncaughtExceptionHandler,使用自定义RPC服务传输异常及其堆栈跟踪。这工作得很好。

正如WebModeExceptions反混淆部分所述,我们在GWT模块中启用了堆栈跟踪仿真:

<set-property name="compiler.stackMode" value="emulated" />
<set-configuration-property name="compiler.emulatedStack.recordLineNumbers"
    value="true" />
现在我们的堆栈跟踪看起来像这样:

com.google.gwt.core.client.JavaScriptException: (TypeError) : Cannot call method 'pp' of null
    Unknown.aT(Unknown Source:174)
    Unknown.AVa(Unknown Source:501)
    Unknown.YF(Unknown Source:29)
    Unknown.Lqb(Unknown Source:138)
    ...

在我看来这个看起来没问题,因为它包含了混淆方法名和行号,这似乎是需要的,如WebModeExceptions deobfuscation section中所述。

然后我们使用-extra参数编译我们的GWT模块,以获取符号映射。

我们的自定义日志服务使用symbolMaps目录调用com.google.gwt.logging.server.StackTraceDeobfuscator。我们使用X-GWT-Permutation http头来调用deobfuscator。我进入deobfuscate方法,确保它可以加载符号映射。它可以。我验证了使用的symbolMap文件名与GWT模块的*.cache.js文件名匹配。它是匹配的。

所以基本上,该服务执行以下操作:

// Create the deobfuscator
String dir = getSymbolMapsDirPath();
StackTraceDeobfuscator deobfuscator = new StackTraceDeobfuscator(dir);

// request is the HttpServletRequest
String strongName = request.getHeader(RpcRequestBuilder.STRONG_NAME_HEADER);

// Deobfuscate the stack trace
exception.setStackTrace(
    deobfuscator.deobfuscateStackTrace(exception.getStackTrace(), strongName));

// Log the exception
logger.severe("Uncaught GWT exception", exception);

最终结果是堆栈跟踪未被反混淆。有时,一些行会用错误的类和方法名进行反混淆,但仅此而已。当查看symbolMap文件时,堆栈跟踪中的实际符号与symbolMap文件中的任何符号都不匹配。

不知道我们做错了什么?

编辑:我尝试了RemoteLoggingServiceImpl,得到了相同的结果。


出于好奇,你不使用RemoteLoggingServiceImpl有什么原因吗? - Thomas Broyer
我们已经标准化了客户端和服务器之间的所有通信方式(日志记录、安全性、错误处理),因此使用相同的机制将错误报告发送到我们的服务器似乎是显而易见的选择。不过,我们在开发解决方案时使用了RemoteLoggingServiceImpl源代码作为模型。 - Guillaume Duchesneau
@GuillaumeDuchesneau 或许你能帮我解决这个相关问题 https://dev59.com/FHzaa4cB1Zd3GeqPN0i3 - Michael
@GuillaumeDuchesneau,我正在实现相同的方案,但遇到了问题,您可能已经解决了。您能否就此主题提供一些指导?http://stackoverflow.com/questions/22049560/serialize-java-lang-throwable-along-with-stack-trace-causes-chain-and-related-s非常感谢! - Yuriy Nakonechnyy
@GuillaumeDuchesneau 给出了我的问题的答案 - 请忽略我之前的评论。 - Yuriy Nakonechnyy
请问您能否粘贴完整的代码?我也想实现相同的功能,需要Java和GWT.XML两者都要实现。 - virendrao
2个回答

9
经过进一步调查,我们发现使用新的GWT编译器选项-XenableClosureCompiler会生成代码,该代码不输出使用编译器生成的符号映射的堆栈跟踪。移除该选项后,可以成功反混淆堆栈跟踪。
另外需要注意的是,启用堆栈跟踪反混淆所需的编译器和GWT模块选项(如我在问题中描述的选项和删除闭包编译器选项)会使我们最终的js文件大小增加两倍。

2
这已被接受为GWT问题7803(http://code.google.com/p/google-web-toolkit/issues/detail?id=7803) - Roy Paterson
@RoyPaterson 这个问题已经被移动到 Github (https://github.com/gwtproject/gwt/issues/7800)。它也在2016年2月22日关闭,附带以下评论:"实验性的 Closure 编译器集成已从 GWT 2.8 中删除,因此关闭此问题。" - Attila Csipak

0

问题中的StackTraceDeobfuscator版本现已过时。这是新的方法(实际上并没有太大区别):

仍然在您的.gwt.xml文件中设置属性:

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

然后,一旦异常被传回到您的服务器的RemoteServiceServlet

import com.google.gwt.core.server.StackTraceDeobfuscator;
import com.google.gwt.user.client.rpc.RpcRequestBuilder;

String path = getServletConfig().getServletContext().getRealPath("/WEB-INF/deploy/<your module name>/symbolMaps/");
StackTraceDeobfuscator deobfuscator = StackTraceDeobfuscator.fromFileSystem(path);
String strongName = getThreadLocalRequest().getHeader(RpcRequestBuilder.STRONG_NAME_HEADER);

// Do the magic
deobfuscator.deobfuscateStackTrace(exception, strongName);

// Log it
logger.severe("Uncaught GWT exception", exception);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接