“Swing-Shell”java.lang.InternalError:无法初始化COM:HRESULT = 0x80010106

时间:2017-10-24 19:21:44

标签: windows-store java-9 desktop-bridge project-centennial

我有一个Java 9应用程序,我正在尝试为Windows应用商店打包。奇怪的是,当我直接运行exe-launcher时,它按预期工作,但是当我通过APPX包运行启动器时,我得到以下奇怪的错误:

Exception in thread "Swing-Shell" java.lang.InternalError: Could not 
initialize COM: HRESULT=0x80010106 
at java.desktop/sun.awt.shell.Win32ShellFolderManager2.initializeCom(Native Method) 
at java.desktop/sun.awt.shell.Win32ShellFolderManager2$ComInvoker$1.run(Unknown Source at java.base/java.lang.Thread.run(Unknown Source)

HRESULT=0x80010106表示RPC_E_CHANGED_MODE,我猜这意味着COM已经以某种方式在MTA模式下初始化。但为什么这只是Windows Bridge沙箱中的一个问题?由于某种原因,Windows桥以某种方式以某种方式pre-initialize COM吗?

我不确定这是Java 9问题,还是Desktop Bridge问题,或两者兼而有之。有没有人对如何确定问题的原因或解决方法有任何想法?

我已经制作了一个最小的Sample Project来重现问题

应用程序在直接执行时有效,但在通过APPX启动程序执行时无效。为什么呢?

1 个答案:

答案 0 :(得分:2)

分析

依赖于COM初始化的JDK部分(D3DPipeline,Sound和windows shellfolder访问)都遵循相同的模式:

  • 在单独的线程中运行代码
  • 表示此线程CoInitialize被称为
  • 在用户级代码CoUnitialize的末尾称为

这与MSDN为COM保存的文档一致,并且分析正确,错误表明COM子系统已初始化为MTA线程。

所以我修改了java启动器( jvm.dll )并插入 将语句调试到 os_windows.cpp 中的一些本机方法中。 我专注于线程方法。我发现的是:

  • create_main_threadcreate_os_threadpd_start_thread全部 运行COM尚未初始化
  • 原生线程初始值设定项(thread_native_entry)已经存在 使用COM初始化
  • 运行

我在_beginthreadex看了一下,确实我终于找到了领先优势 在stackoverflow上。这向我指出了 threadex.c 的源代码, 这是Visual Studio 2013 Express安装的一部分。

你发现,_beginthreadex没有直接启动 提供的线程函数,但运行库初始化程序 (_threadstartex)首先。该初始化程序的一部分内容为:

_ptd->_initapartment = __crtIsPackagedApp();
if (_ptd->_initapartment)
{
    _ptd->_initapartment = _initMTAoncurrentthread();
}

_callthreadstartex();
如果应用程序是,则

_crtIsPackagedApp通过内核函数检测到 作为" PackagedApp"运行(即AppX包),若然,那么 RoInitialize函数被调用,从我的理解就像大的一样 CoInitialize的兄弟。

长话短说:如果您的应用程序是使用Visual Studio 2013构建的 并且作为打包的应用程序运行,您将获得破碎的环境。

经证实,Oracle JDK的工作版本是使用VS2010 SP1构建的,破解版本是使用VS2013SP4构建的。

解决方法

通过上述信息,谷歌终于找到了一个支持分析的参考文献:

https://blogs.msdn.microsoft.com/vcblog/2016/07/07/using-visual-c-runtime-in-centennial-project/

引用那篇文章:

  

请注意,在此期间创建的现有VC ++ 12.0库   Windows 8时间帧有运行时检查以确定是否   应用程序是否在应用程序容器下运行。跑步时   桌面应用程序作为打包的应用程序,这些检查可能会限制   桌面应用程序的功能或使其表现得像UWA   (通用Windows应用程序)(有限的文件系统访问或   创建线程初始化MTA等)。我们已经修复了这种行为   在这些框架包中包含的VC ++库中   从而从您的桌面删除现代应用程序限制   应用

所以我看到修复应用程序的选项,应该作为AppX包分发:

  • 强制用户安装VC ++ 12.0二进制文件(通过引入博客文章中引用的依赖关系)或
  • 使用更新包中的固定版本替换与Java 9捆绑的msvcr120.dll(我也假设也是Java 10)

我会选择第二个版本,我测试了这个。从一个干净的最新Windows 10系统开始,我安装了JDK 9.0.4,我克隆了提供的测试用例,使用本地安装的JRE(而不是JDK!)修改它并构建appx包。运行这个,我重现了这个问题。然后,我将系统安装的JRE文件夹中的msvcr120.dll替换为APPX容器中包含的<span>

https://www.microsoft.com/en-us/download/details.aspx?id=53176

提示:* .appx只是带有其他签名的ZIP文件,所以你可以 只需重命名它们并提取内容。

我重建了测试用例,它正常工作(没有COM 初始化错误了。)