什么导致sun.awt.shell.Win32ShellFolder2.initSpecial()抛出InternalError错误?

4

我们的一些Windows用户在启动我们的应用程序后不久会得到此堆栈跟踪:

java.lang.InternalError: Could not bind shell folder to interface
  at sun.awt.shell.Win32ShellFolder2.initSpecial(Native Method) ~[na:1.7.0_25]
  at sun.awt.shell.Win32ShellFolder2.access$300(Unknown Source) ~[na:1.7.0_25]
  at sun.awt.shell.Win32ShellFolder2$1.call(Unknown Source) ~[na:1.7.0_25]
  at sun.awt.shell.Win32ShellFolder2$1.call(Unknown Source) ~[na:1.7.0_25]
  at sun.awt.shell.Win32ShellFolderManager2$ComInvoker.invoke(Unknown Source) ~[na:1.7.0_25]
  at sun.awt.shell.ShellFolder.invoke(Unknown Source) ~[na:1.7.0_25]
  at sun.awt.shell.Win32ShellFolder2.<init>(Unknown Source) ~[na:1.7.0_25]
  at sun.awt.shell.Win32ShellFolderManager2.getNetwork(Unknown Source) ~[na:1.7.0_25]
  at sun.awt.shell.Win32ShellFolder2.getFileSystemPath(Unknown Source) ~[na:1.7.0_25]
  at sun.awt.shell.Win32ShellFolder2.access$400(Unknown Source) ~[na:1.7.0_25]
  at sun.awt.shell.Win32ShellFolder2$10.call(Unknown Source) ~[na:1.7.0_25]
  at sun.awt.shell.Win32ShellFolder2$10.call(Unknown Source) ~[na:1.7.0_25]
  at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source) ~[na:1.7.0_25]
  at java.util.concurrent.FutureTask.run(Unknown Source) ~[na:1.7.0_25]
  at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) ~[na:1.7.0_25]
  at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) ~[na:1.7.0_25]
  at sun.awt.shell.Win32ShellFolderManager2$ComInvoker$3.run(Unknown Source) ~[na:1.7.0_25]
  at java.lang.Thread.run(Unknown Source) ~[na:1.7.0_25]

观察结果:
  • 堆栈跟踪中的每个帧都是JDK中的内容,而不是我们的代码。
  • 这只在Windows上发生,但我们已经收到了关于Vista和Windows 7上出现此问题的报告。
  • 这发生在各种版本的Java上:1.6.0_19、1.6.0_21、1.7.0_11、1.7.0_25。
  • 问题仅发生在少数用户身上,但对于这些用户来说,它是100%可重复的。不幸的是,除了出现此问题外,我们没有看到这些用户系统中有任何共同点,我们的开发人员也从未经历过这种情况。
  • 我搜索Oracle的错误数据库时,并没有发现具有相同或类似堆栈跟踪的错误。
  • 似乎有很多帖子在网上讨论这个特定的问题,但没有人知道是什么原因导致的。

如果这确实是一个JDK bug,我并不抱有Oracle修复问题的希望,但如果我们知道是什么触发了这个bug,我们至少可以帮助受到影响的用户。有人能解释一下这是什么原因吗?

编辑:相关的本地函数是这个,来自ShellFolder2.cpp:

JNIEXPORT void JNICALL Java_sun_awt_shell_Win32ShellFolder2_initSpecial
    (JNIEnv* env, jobject folder, jlong desktopIShellFolder, jint folderType)
{
    // Get desktop IShellFolder interface
    IShellFolder* pDesktop = (IShellFolder*)desktopIShellFolder;
    if (pDesktop == NULL) {
        JNU_ThrowInternalError(env, "Desktop shell folder missing");
        return;
    }
    // Get special folder relative PIDL
    LPITEMIDLIST relPIDL;
    HRESULT res = fn_SHGetSpecialFolderLocation(NULL, folderType,
        &relPIDL);
    if (res != S_OK) {
        JNU_ThrowIOException(env, "Could not get shell folder ID list");
        return;
    }
    // Set field ID for relative PIDL
    env->CallVoidMethod(folder, MID_relativePIDL, (jlong)relPIDL);
    // Get special folder IShellFolder interface
    IShellFolder* pFolder;
    res = pDesktop->BindToObject(relPIDL, NULL, IID_IShellFolder,
        (void**)&pFolder);
    if (res != S_OK) {
        JNU_ThrowInternalError(env,
            "Could not bind shell folder to interface");
        return;
    }
    // Set field ID for pIShellFolder
    env->CallVoidMethod(folder, MID_pIShellFolder, (jlong)pFolder);
}

为了触发“无法绑定”异常,看起来pDesktop!= NULL并且成功检索到relPIDL,但pDesktop->BindToObject()返回的不是S_OKpDesktop是一个IShellFolder*,显然在Windows的<shellapi.h>中定义。令人恼火的是,Java丢弃了由IShellFolder :: BindToObject返回的错误代码。
因此,我想问题归结为:什么会导致IShellFolder :: BindToObject失败? 编辑2:由于Win32ShellFolderManager2.getNetwork()调用了Win32ShellFolder2构造函数Win32ShellFolderManager2.java:181,我们可以看到Win32ShellFolder2.initSpecial的最后一个参数必须是Win32ShellFolder2.NETWORK。因此,用户的网络邻居文件夹可能出现了问题,是吗?

你的程序在崩溃时是否正在处理 JFileChooser?请查看 Bug ID 4879395。同时尝试以管理员身份运行受影响的安装程序。 - Anthony Accioly
我们确实使用了JFileChooser,但用户报告说这种情况发生在他们做任何事情之前。可能在异常发生时已经构造了一个JFileChooser或正在构造中,但由于异常发生在不同的线程上,我们无法确定。 (我在2010年搜索此问题时看到了您提到的错误 - 堆栈跟踪与我们的有很大不同,并且在Java 6或7中不存在用于解决问题的属性。) - uckelman
你弄清楚这个问题的底细了吗? - CodeBuddy
不,从来没有。我仍然想知道答案。(实际上,我希望Oracle修复这个bug...) - uckelman
2个回答

2
好的,有几份与您类似的报告(例如来自jEdit的这份报告,来自codenameone的这份报告以及这份报告 - 德语 - 看起来像是在Windows 7和Java 6中出现了一个JFileChooser错误,其堆栈跟踪与您的非常接近)。所有这些都似乎与JFileChooser和/或文件浏览有关。

因此,我会采用以下两种方法之一:

要么选择耗时的、非推测性的路线,使用工具(如jstackVisualVMJConsole)对受影响的安装进行转储,直到您能够确定问题的根本原因(可能是JFileChooser,也可能不是)。如果您选择这条路线,请记住,必须要远程访问其中一个受影响的安装或寻求技术熟练用户的帮助。

或者尝试走捷径,假设问题确实是JFileChooser(根据轶事证据显示),并发布一个自定义版本,用FileDialog替换JFileChooser。如果在受影响的机器上按预期运行,则问题解决了;否则请为自己的尝试自我鼓励,然后选择“漫长而曲折的道路”。


0

我曾经遇到过同样的问题,答案是java.awt.FileDialog

如果你在搜索 "Open File Dialog" 的 VbScript 解决方案时,似乎没有 COM 类能在大多数Windows平台上完成这项工作。


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