簡體   English   中英

為什么Tomcat無法顯示實際的堆棧跟蹤?

[英]Why is Tomcat unable to show the actual stack trace?

使用GWT ,我已將我的服務器部署到Tomcat中 這樣可以正常工作,但是當GWT拋出異常時,Popup會向客戶端顯示異常的堆棧跟蹤。

在開發模式下,這很好用。 在Tomcat中,我得到了下面的堆棧跟蹤。

為什么以及如何解決這個問題?

 Unknown.Le(StackTraceCreator.java:168) Unknown.Jd(StackTraceCreator.java:421) Unknown.NT(Exception_FieldSerializer.java:16) Unknown.g1(SerializerBase.java:55) Unknown.b1(SerializerBase.java:112) Unknown.D$(AbstractSerializationStreamReader.java:119) Unknown.uAc(CustomException_FieldSerializer.java:39) Unknown.uBc(ServerSideException_FieldSerializer.java:12) Unknown.f1(SerializerBase.java:46) Unknown._0(SerializerBase.java:92) Unknown.D$(AbstractSerializationStreamReader.java:119) Unknown.B_(RequestCallbackAdapter.java:216) Unknown._o(Request.java:287) 

在使用@Christian Kuetbach的回答后,這就是我現在得到的:

Unknown.com_google_gwt_core_client_impl_StackTraceCreator $ CollectorEmulated_ $ fillInStackTrace__Lcom_google_gwt_core_client_impl_StackTraceCreator $ CollectorEmulated_2Ljava_lang_Throwable_2V(StackTraceCreator.java:168)Unknown.java_lang_Throwable_Throwable__Ljava_lang_String_2Ljava_lang_Throwable_2V(StackTraceCreator.java:421)Unknown.com_google_gwt_user_client_rpc_StatusCodeException_StatusCodeException__ILjava_lang_String_2V(StatusCodeException.java:35)Unknown.com_google_gwt_user_client_rpc_impl_RequestCallbackAdapter_ $ onResponseReceived__Lcom_google_gwt_user_client_rpc_impl_RequestCallbackAdapter_2Lcom_google_gwt_http_client_Request_2Lcom_google_gwt_http_client_Response_2V(RequestCallbackAdapter.java:209)未知。 com_google_gwt_http_client_Request_ $ fireOnResponseReceived__Lcom_google_gwt_http_client_Request_2Lcom_google_gwt_http_client_RequestCallback_2V(Request.java:287)Unknown.net_google_gwt_http_client_RequestBuilder $ 1_onReadyStateChange__Lcom_google_gwt_xhr_client_XMLHttpRequest _2V(RequestBuilder.java:395)Unknown.anonymous(XMLHttpRequest.java:287)

請幫忙!

為什么?

正如Christian Kuetbach所說,這是在DevMode(你的代碼在Java中執行)和prod模式(你的代碼編譯成JavaScript並進行優化,包括重命名類和方法)之間的區別。

你是如何解決這個問題的?

你沒有。 一般來說,向用戶顯示堆棧跟蹤並不是一個好主意。 更好的方法是通過將異常發送到服務器來記錄異常(例如,使用java.util.logging進行記錄,以及SimpleRemoteLogHandler將日志發送到服務器,在那里使用java.util.logging記錄它)。

有一些方法可以對堆棧跟蹤進行反混淆處理,並且RemoteLoggingServiceImpl servlet可以配置為自動執行。
有關詳細信息,請參閱http://code.google.com/p/google-web-toolkit/wiki/WebModeExceptions

如果您不能或不想使用遠程日志記錄,那么您可以“手動”反混淆堆棧跟蹤:查看WEB-INF/deploy中的文件(默認位置,可以通過將-deploy傳遞給GWT來更改)編譯器)與排列相對應(與瀏覽器加載的*.cache.*文件*.cache.* ),它會告訴你Le方法源自哪種Java方法。
但是你已經擁有源文件名和行號,所以你真的不需要它,對吧?

在GWT文檔中找到所有信息有點困難,需要設置去混淆的日志記錄,所以這里是簡短的版本:

在模塊文件(.gwt.xml)中,添加:

<inherits name="com.google.gwt.logging.Logging"/>
<set-property name="gwt.logging.simpleRemoteHandler" value="ENABLED" />
<set-property name="compiler.stackMode" value="emulated" />
<set-configuration-property name="compiler.emulatedStack.recordLineNumbers" 
     value="true" />

在客戶端,使用類似的東西

import java.util.logging.Logger;

private static Logger rootLogger = Logger.getLogger("");
...
rootLogger.log(Level.SEVERE, "My message", e);

您不必在客戶端創建RemoteLoggingServiceAsync實例 - 它由記錄器自動使用,因為我們指定了<set-property name="gwt.logging.simpleRemoteHandler" value="ENABLED" />

在服務器端,配置RemoteLoggingServiceImpl。 您必須告訴它,它在哪里找到symbolMaps,它將在使用GWT編譯器參數-extra /path/to/myExtraDir編譯時生成。 我個人使用這種方法來覆蓋RemoteLoggingServiceImpl,允許從web.xml的<init-param> s [*]指定目錄

package mypackage.server;

public class ConfigurableRemoteLoggingServiceImpl extends RemoteLoggingServiceImpl {

  @Override
  public void init(final ServletConfig config) throws ServletException {
    super.init(config);

    final String symbolMapsDirectory = 
        config.getInitParameter("symbolMapsDirectory");
    setSymbolMapsDirectory(symbolMapsDirectory);
  }
}

web.xml ,將其注冊為

<servlet>
    <servlet-name>remoteLogging</servlet-name>
    <servlet-class>mypackage.server.ConfigurableRemoteLoggingServiceImpl</servlet-class>

  <init-param>
    <param-name>symbolMapsDirectory</param-name>
    <param-value>/path/to/myExtraDir/mymodulename/symbolMaps</param-value>
  </init-param>
</servlet>
<servlet-mapping>
    <servlet-name>remoteLogging</servlet-name>
    <url-pattern>/mymodulename/remote_logging</url-pattern>
</servlet-mapping>

用你自己的值替換/path/to/myExtraDirmymodulenamemypackage ,不要忘記用-extra參數調用GWT編譯器(注意你不必使用-style PRETTY或DETAILED,它也是適用於OBF)。 保留所有生成的symbolMaps:如果沒有它們,則反混淆將無效。 由於每個新版本都會自動獲得唯一名稱,因此您可以在構建時將它們全部收集在安全的中心位置。

[*]我真的非常想知道為什么RemoteLoggingServiceImpl本身並沒有實現它!

這可以按預期工作,因為optimaziation將刪除方法和類名。

您可以編譯為PRETTY或DETAILED,以獲得更好的可讀Stacktraces。

還可以模擬Stacktraces。

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

這對於生產使用來說是個壞主意,因為它會增加你的javascript的大小。

更新:我看到Exception_FieldSerializer異常。

你試圖序列化一些不可序列化的東西嗎?

沒有默認構造函數的類不可序列化,不在客戶端或共享包中的類。 如果您嘗試序列化異常,則可能是問題所在。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM