2009-08-21 28 views
4

我正在開發一個新的Java桌面應用程序,並希望包括一個崩潰報告設施 - 你知道那種事情 - 程序崩潰,框彈出要求用戶點擊好的發送它等在Java中的崩潰報告的策略/技術

我很滿意如何將錯誤發送回我們的服務器 - 可能通過一個簡單的Web服務。我更不確定的是應該如何實現捕獲失敗的機制?我會歡迎任何實施類似的任何建議。

+0

還發現了一種很好的跟蹤JVM的方法:使用名爲Java-Monitor.com的東西。它不是免費的,但代碼已經足夠暴露,你可能能夠實現類似的東西。 – djangofan 2011-09-21 18:36:48

回答

2

我看到三種情況:

  1. 災難。 JVM本身不是已經死亡就是正在死亡。你不能假設你的任何代碼都能工作 - 例如你不能分配任何內存。因此,在這種情況下,您無法合理地希望能夠發送任何診斷信息。你可以期望的最好的方式是在死亡程序的灰燼中留下一些診斷信息,如核心轉儲。

    在這種情況下,您可以啓動一個新的運行查找這些碎片,並建議用戶收集它,或者更多努力嘗試自己組裝診斷包。

  2. 低級應用程序代碼不會捕獲異常,可能是運行時異常,例如NullPointer異常。在這種情況下,你可以在你的主(假設你有一個)你可以捕獲異常,並有一些希望你的崩潰記者代碼將工作。 將異常和堆棧跟蹤傳遞給Crash Reporter。

  3. 您的低級代碼捕獲了一些真正不健康的東西。不足以終止流程,但值得報告。在這裏你不僅有例外,而且還有其他上下文信息。我們有更多要發送給崩潰記者。

+0

桌面應用程序實際上沒有主要方法。顯示框架時主線程結束(以及其他任何操作直到方法結束)。 – Yishai 2009-08-21 17:12:45

+0

在大多數情況下,是的,這就是爲什麼我說「如果你有一個」,但有一些非UI桌面應用程序可以有一個主。無論如何,當沒有主力時,知道你會推薦什麼是很好的。 – djna 2009-08-21 20:12:52

0

我不知道這是否是Java目前所提供的最好的,但是這是我做的事而回。

首先所有有可能崩潰的有趣活動都是通過命令模式發出的。這個應用程序包括通過互聯網打擊應用程序服務器,所以很多人可能會出錯。命令調度程序捕獲異常並向用戶顯示適當的結果(通常顯示一個錯誤對話框,之後是關閉和發送有關崩潰的電子郵件)。

其次,在Swing中使用自定義事件隊列來捕獲發生在事件線程上的任何異常。我希望Java現在有更好的解決方案,但基本上當發生異常時,您必須檢查代碼是否涉及,否則某些Swing錯誤可能會導致應用程序崩潰,這並不令人愉快。當然,遞歸必須被檢查(當你嘗試向用戶顯示一條消息時,崩潰會一遍又一遍地重複)。順便說一句,大多數任何崩潰都會使JVM繼續運行,包括內存不足錯誤,足以在大多數情況下發送電子郵件,因爲在內存不足錯誤發生後,通常錯誤會釋放足夠的堆棧(因此堆)允許進一步的垃圾收集,並讓你的代碼生活。但在這樣的情況下,你應該很快退出。 IDEA會在內存不足錯誤後繼續運行,但通常運行不正常。國際海事組織最好退出。

您推送一個新的Queue,其中包含以下EventQueue子類並將其鏈接到您的行爲中。

Toolkit.getDefaultToolkit().getSystemEventQueue().push(newQueue); 
5

使用Thread.setUncaughtExceptionHandler和靜態Thread.setDefaultUncaughtExceptionHandler以(試圖)例外情況向您的日誌系統。

+0

正是我想要的! +1 – fury 2012-01-01 07:03:05

7

有一個命令行選項,您可以爲JVM在JVM崩潰後使用內存轉儲運行批處理文件。你所做的只是創建一個外部程序來執行錯誤報告,然後使用JVM選項使用你所做的實用程序在電子郵件中發送核心轉儲。

-XX:-HeapDumpOnOutOfMemoryError -XX:OnError="<cmd args>;<cmd args>" 
+0

當然,您可能希望將此方法與運行時錯誤報告功能結合使用... – djangofan 2009-08-23 17:53:35

0

一個選項是使用BugSense。它針對移動應用程序崩潰報告,但API聲明它可以用於任何類型的崩潰報告。從我讀過的內容看,這很簡單,所有需要做的就是創建一個包含所有值的簡單POST請求。

{ 
    "client": { 
     "name": "bugsense-android", // Obligatory 
     "version": "0.6" 
    }, 
    "request": { 
     "remote_ip": "10.0.0.1", 
     "custom_data": { 
     "key1": "value1", 
     "key2": "value2" 
     } 
    }, 
    "exception": { 
     "message": "java.lang.RuntimeException: exception requested", // Obligatory 
     "where": "MainActivity.java:47", // Obligatory 
     "klass": "java.lang.RuntimeException", // Type of exception 
     "backtrace": "java.lang.RuntimeException: exception requested\r\nat com.sfalma.trace.example.MainActivity$1.onClick(MainActivity.java:47)\r\nat android.view.View.performClick(View.java:2408)\r\nat android.view.View$PerformClick.run(View.java:8816)\r\nat android.os.Handler.handleCallback(Handler.java:587)\r\nat android.os.Handler.dispatchMessage(Handler.java:92)\r\nat android.os.Looper.loop(Looper.java:123)\r\nat android.app.ActivityThread.main(ActivityThread.java:4627)\r\nat java.lang.reflect.Method.invokeNative(Native Method)\r\nat java.lang.reflect.Method.invoke(Method.java:521)\r\nat com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)\r\nat com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)\r\nat dalvik.system.NativeStart.main(Native Method)\\n" // Obligatory 
    }, 
    "application_environment": { 
     "phone": "android", // Device model (could be PC or Max) Obligatory 
     "appver": "1.2", // Obligatory 
     "appname": "com.sfalma", // Obligatory 
     "osver": "2.3", // Obligatory 
     "wifi_on": "true", 
     "mobile_net_on": "true", 
     "gps_on": "true", 
     "screen_dpi(x:y)": "120.0:120.0", 
     "screen:width": "240", 
     "screen:height": "400", 
     "screen:orientation": "normal" 
    } 
} 

您可以read more about it here

2

使用日誌記錄。通用模式是這樣的:

  • 創建發送錯誤信息到服務器(即發送日誌通過郵件,甚至JDBC消息最日誌框架支持追加程序)一個appender。如果沒有現成的appender,他們會舉例說明如何做到這一點。
  • 將該appender添加到根記錄器並將其設置爲閾值ERROR
  • 當您發現異常時記錄錯誤。日誌框架將爲你做好準備。