"Windows Error Reporting"可以用于非致命的Java问题吗?



我想知道是否有一种方法可以使用Windows错误报告从"内部"的Java程序?

换句话说,使用该机制将异常报告回中央位置,而不会导致实际的JVM崩溃(根据我的理解,JVM崩溃是首先触发异常的原因)。

这里的想法是让收集Windows用户的bug报告变得更容易。


我也想知道它是否可以作为受控关闭的一部分。也就是说,不是JVM崩溃,而是正常的、受控的退出Java程序。


在仔细考虑之后,我认为创建一组文本文件(或者只是在单个文本流中管道)到位于我们文件系统内的一个小Windows应用程序就足够了。该Windows应用程序随后明显崩溃,并导致发送报告,其中包括我们提供的文本。这样行吗?

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

从Java调用基于dll的函数的最好方法是使用积极开发的Java Native Access项目。

为了进行所需的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文档中拼凑了这些-如果它不完整或不正确,在JNA网站上有大量的示例和相当好的文档。

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

过去我必须编写Java和。net之间的互操作性,所以我开始做一些关于使用。net与WER交互的研究,目的是看看是否有可能在一个可以与Java交互的。net应用程序中与WER交互。有趣的是,我在soff上看到了这篇文章——是否有一个。net API用于Windows错误报告

那篇文章有一些关于与WER交互的好信息。

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

正如那篇文章中公认的答案所建议的那样,尽管如此,最好使用Windows质量在线服务,而不是编程一些东西来与WER交互,因为WER似乎不打算被其他应用程序使用。

您可以与本地的WER库函数进行互操作。

以下是相关的MSDN文档:

  1. 创建报告
  2. 提交报告

也许有更有java互操作经验的人可以为你提供代码示例,不幸的是,我更喜欢。net。

编辑:

我做了更多的研究,我认为你可以尝试使用GlueGen或SWIG来生成Java绑定。如果你想生成绑定,你必须下载Windows SDK来获取werapi头文件。

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

如果情况是1,那么显然你不能做得很整齐。您可能一直运行一个单独的守护进程来查找创建的hs_err_pid*.log ->使用外部库解释它->使用上面建议的WER api将其写入WER记录。

如果是第二种情况,那么你可能喜欢进行JNI调用,并调用WER api来在WER中编写内容。

相关内容

  • 没有找到相关文章

最新更新