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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了是什么导致sun.awt.shell.Win32ShellFolder2.initSpecial()抛出InternalError?相关的知识,希望对你有一定的参考价值。

我们的一些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的bug数据库的搜索没有出现相同或类似堆栈跟踪的错误。
  • 网上似乎有很多关于这个特定问题的帖子,没有人知道是什么原因引起的。

如果它确实是一个JDK错误的话,我并没有抱着甲骨文解决任何问题的希望,但如果我们知道是什么引发了这个错误,我们至少可以帮助受其影响的用户。任何人都可以了解导致这种情况发生的原因吗?

编辑:相关的原生函数就是这个,来自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 != NULLrelPIDL被成功检索,但pDesktop->BindToObject()返回的不是S_OKpDesktop是一个IShellFolder*,显然在Windows的<shellapi.h>中定义。加剧了,Java抛弃了IShellFolder::BindToObject返回的错误代码。

所以,我想这个问题简化为:什么会导致IShellFolder::BindToObject失败?

编辑2:由于Win32ShellFolderManager2.getNetwork()Win32ShellFolder2上称之为Win32ShellFolderManager2.java:181 ctor,我们可以看到Win32ShellFolder2.initSpecial的最后一个论点必须是Win32ShellFolder2.NETWORK。那么,用户的Network Neighborhood文件夹可能出现了问题吗?

答案

好吧,有几个类似于你的报告(如this one from jEditthis one from codenameonethis one - 德语 - 这似乎是一个JFileChooser错误,堆栈跟踪在Windows 7和Java 6中非常接近你的)。所有这些似乎都以某种方式与JFileChooser和/或文件浏览相关。

所以我会通过以下两种方式之一来解决这个问题:

要么花费时间/非投机性的道路,要使用jstackVisualVMJConsole等工具转移受影响的设施,直到你能够找出问题的根本原因(可能是也可能不是JFileChooser)。如果您选择该路径,请记住必须远程访问其中一个受影响的安装或技术精明的用户提供帮助。

或者尝试采取捷径,假设问题确实是JFileChooser(如轶事证据所示)并发布一个自定义版本替换JFileChooserFileDialog。如果它在受影响的机器上按预期运行,则关闭案例;否则就给自己轻拍一下尝试并采取“漫长而曲折的道路”。

另一答案

有同样的问题,答案是java.awt.FileDialog

如果你查找VbScript解决方案的“打开文件对话框”,似乎没有COM类为大多数Windows平台做这项工作

以上是关于是什么导致sun.awt.shell.Win32ShellFolder2.initSpecial()抛出InternalError?的主要内容,如果未能解决你的问题,请参考以下文章

什么会导致 WM_NCHITTEST lParam 溢出 32 位整数?

为什么用%s打印字符会导致分段错误?

底层原理C/C++内存对齐详解

是啥导致我的 s-s-rS 图表中的范围参数错误?

shell32.dll里没有扩展名的图标

R_X86_64_32S 和 R_X86_64_64 重定位是啥意思?