“Windows错误报告”可以用于非致命的Java问题吗?

时间:2011-12-14 15:32:11

标签: java windows-error-reporting

我想知道是否有办法从Java程序的“内部”使用Windows错误报告?

换句话说,使用该机制将异常报告回中心位置而不会导致实际的JVM崩溃(据我所知,这首先触发了这一点)。

这里的想法是更容易从Windows用户收集错误报告。


我也想听听它是否可以成为受控关机的一部分。即不是JVM崩溃,而是从Java程序正常,受控制的退出。


在考虑完之后,我认为为我们的目的创建一组文本文件(或者可能只是在单个文本流中管道)到位于我们文件系统内部的小型Windows应用程序就足够了。然后,所述Windows应用程序突然崩溃并导致发送报告,包括我们提供的文本。那会有用吗?

4 个答案:

答案 0 :(得分:9)

您绝对可以使用wer.dll中附带的Windows错误报告API作为Win32 API的一部分。

从Java调用基于DLL的函数的最佳方法是使用积极开发的Java Native Access project

为了进行必要的Win32 API调用,我们需要向JNA讲授至少这些函数:

HRESULT WINAPI WerReportCreate(
  __in      PCWSTR pwzEventType,
  __in      WER_REPORT_TYPE repType,
  __in_opt  PWER_REPORT_INFORMATION pReportInformation,
  __out     HREPORT *phReportHandle
);

HRESULT WINAPI WerReportSubmit(
  __in       HREPORT hReportHandle,
  __in       WER_CONSENT consent,
  __in       DWORD dwFlags,
  __out_opt  PWER_SUBMIT_RESULT pSubmitResult
);

以及这个结构:

typedef struct _WER_REPORT_INFORMATION {
  DWORD  dwSize;
  HANDLE hProcess;
  WCHAR  wzConsentKey[64];
  WCHAR  wzFriendlyEventName[128];
  WCHAR  wzApplicationName[128];
  WCHAR  wzApplicationPath[MAX_PATH];
  WCHAR  wzDescription[512];
  HWND   hwndParent;
} WER_REPORT_INFORMATION, *PWER_REPORT_INFORMATION;

为此,我们将创建WER.java:

package com.sun.jna.platform.win32;

import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.platform.win32.WinNT.HANDLE;
import com.sun.jna.platform.win32.WinNT.HRESULT;
import com.sun.jna.ptr.PointerByReference;
import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.win32.W32APIOptions;

public interface Wer extends StdCallLibrary {
    Wer INSTANCE = (Wer) Native.loadLibrary("wer", Wer.class,
                                                W32APIOptions.DEFAULT_OPTIONS);

    public static class HREPORT extends HANDLE {
        public HREPORT() { }
        public HREPORT(Pointer p) { super(p); }
        public HREPORT(int value) { super(new Pointer(value)); }
    }

    public static class HREPORTByReference extends ByReference {
        public HREPORTByReference() {
            this(null);
        }

        public HREPORTByReference(HREPORT h) {
            super(Pointer.SIZE);
            setValue(h);
        }

        public void setValue(HREPORT h) {
            getPointer().setPointer(0, h != null ? h.getPointer() : null);
        }

        public HREPORT getValue() {
            Pointer p = getPointer().getPointer(0);
            if (p == null)
                return null;
            if (WinBase.INVALID_HANDLE_VALUE.getPointer().equals(p)) 
                return (HKEY) WinBase.INVALID_HANDLE_VALUE;
            HREPORT h = new HREPORT();
            h.setPointer(p);
            return h;
        }
    }

    public class WER_REPORT_INFORMATION extends Structure {
        public DWORD dwSize;
        public HANDLE hProcess;
        public char[] wzConsentKey = new char[64];
        public char[] wzFriendlyEventName = new char[128];
        public char[] wzApplicationName = new char[MAX_PATH];
        public char[] wzDescription = new char[512];
        public HWND hwndParent;

        dwSize = new DWORD(size());
    }

    public abstract class WER_REPORT_TYPE {
        public static final int WerReportNonCritical = 0;
        public static final int WerReportCritical = 1;
        public static final int WerReportApplicationCrash = 2;
        public static final int WerReportApplicationHang = 3;
        public static final int WerReportKernel = 4;
        public static final int WerReportInvalid = 5;
    }

    HRESULT WerReportCreate(String pwzEventType, int repType, WER_REPORT_INFORMATION pReportInformation, HREPORTByReference phReportHandle);
    HRESULT WerReportSubmit(HREPORT hReportHandle, int consent, DWORD dwFlags, WER_SUBMIT_RESULT.ByReference pSubmitResult);
}

我只是在几分钟内从MSDN dcoumentation中一起敲了 - 如果它不完整或不正确,JNA网站上有tons of examplespretty good documentation

要运行JNA,您需要jna.jarplatform.jar,您也可以从JNA网站上获取。

答案 1 :(得分:6)

过去我必须编写Java和.NET之间的互操作性,因此我开始研究如何使用.NET与WER进行交互,以便了解是否可以在WER中与WER进行交互。然后可以与Java交互的.NET应用程序。有趣的是,我在SOF上发现了这篇文章 - Is there a .Net API for Windows Error Reporting

该帖子提供了与WER交互相关的一些好信息。

我知道这篇文章围绕着使用.NET来对抗WER,但是当你尝试与本机Windows功能进行交互时,我建议使用.NET与它进行交互,因为使用本机Windows资源进行交互更加容易。 .NET比使用Java(它通常占用Java的一半代码)。然后,您可以使用Java与.NET应用程序(可能最好设置为Windows服务)连接(例如,您可以在.NET应用程序中使用临时“触发器”文件来指示.NET应用程序何时完成它处理; Java应用程序然后可以探测以查看何时创建了“触发器”文件并从那里继续......)。

正如该帖子中所接受的答案所建议的那样,最好使用Windows Quality Online Services而不是编写与WER交互的内容,因为看起来WER并不打算被其他应用程序使用。

答案 2 :(得分:4)

您可以与原生WER库函数互操作。

以下是相关的MSDN文档:

  1. Creating a report
  2. Submitting a report
  3. 也许拥有更多Java-interop经验的人可以为您提供代码示例,不幸的是,我更像是一个.NET人员。

    修改

    我做了更多的研究,我认为您可以尝试使用GlueGenSWIG来生成Java绑定。如果要生成绑定,则必须download the Windows SDK才能获取werapi头文件。

答案 3 :(得分:0)

你的意思是说,而不是创建hs_err_pid * .log文件WER应该用它记录日志吗?或者你打算记录任何可以在WER中的Java程序中处理的异常的详细异常消息?

如果案件是1那么显然你不能整齐地做到这一点。您可能有一个单独的守护程序一直在运行以查找hs_err_pid * .log created->使用外部库解释它 - >使用上面建议的WER API将其写入WER记录中。

如果案例是第二个案例,那么您可能希望进行JNI调用,并调用WER API来编写WER中的内容。