"Swing-Shell" java.lang.InternalError: Could not initialize COM: HRESULT=0x80010106
"Swing-Shell" java.lang.InternalError: Could not initialize COM: HRESULT=0x80010106
我有一个 Java 9 应用程序,我正在尝试为 Windows 商店打包。奇怪的是,当我直接 运行 exe 启动器时它按预期工作,但是当我通过 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.run(Unknown Source at java.base/java.lang.Thread.run(Unknown Source)
HRESULT=0x80010106
表示 RPC_E_CHANGED_MODE
,我猜这意味着 COM 已经以某种方式在 MTA 模式下进行了初始化。但为什么这只是 Windows Bridge 沙箱中的一个问题? Windows Bridge 是否出于某种原因以某种方式 pre-initialize
COM?
我不确定这是 Java 9 问题还是桌面桥问题,或者两者兼而有之。有人对如何确定问题的原因或解决方法有任何想法吗?
我做了一个最小的 Sample Project 来重现这个问题
该应用程序在直接执行时有效,但在通过 APPX 启动器执行时无效。为什么?
分析
依赖 COM 初始化的 JDK 部分(D3DPipeline、Sound 和 windows shellfolder 访问)都遵循相同的模式:
- 运行 单独线程中的代码
- 此线程
CoInitialize
被调用
- 在用户层结束时调用代码
CoUnitialize
这与 MSDN 为 COM 保留的文档一致,分析正确,错误表明 COM 子系统已经初始化为 MTA 线程。
所以我修改了java启动器(jvm.dll)并插入
将语句调试到 os_windows.cpp 中的某些本机方法中。
我专注于线程方法。我发现的是:
create_main_thread
、create_os_thread
、pd_start_thread
全部
运行 COM 尚未初始化
- 本机线程初始化程序 (
thread_native_entry
) 已经
运行 COM 已初始化
我在 _beginthreadex
中进行了更多研究,确实我终于找到了线索
在计算器上。这让我找到了 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 构建的。
解决方法
结合以上信息google终于找到了一个参考,支持分析:
https://blogs.msdn.microsoft.com/vcblog/2016/07/07/using-visual-c-runtime-in-centennial-project/
引用那篇文章:
Note that the existing VC++ 12.0 libraries created during the
Windows 8 timeframe have runtime checks to determine whether the
app is running under the app container or not. When running
desktop apps as a packaged app, these checks might limit the
functionality of the desktop app or cause it to behave like a UWA
(Universal Windows Application) (limited file system access or
create thread initializing MTA etc.). We have fixed this behavior
in the VC++ libraries contained in these framework packages and
thus removing the modern app limitations from your desktop
applications.
所以我看到了修复应用程序的选项,这些应用程序应作为 AppX 包分发:
- 强制用户安装更新 VC++ 12.0 二进制文件(通过引入博客 post 中引用的依赖项)或
- 用更新包
中的固定版本替换Java 9(我假设也是Java 10)捆绑的msvcr120.dll
我会选择第二个版本并且我测试了这个。从干净的 up-to-date Windows 10 系统开始,我安装了 JDK 9.0.4,我克隆了提供的测试用例,使用本地安装的 JRE(不是 JDK! ) 并构建 appx 包。 运行 这个,我复现了这个问题。然后,我将系统安装的 JRE 文件夹中的 msvcr120.dll
替换为 APPX 容器中包含的那个,来自:
https://www.microsoft.com/en-us/download/details.aspx?id=53176
提示:*.appx 只是带有附加签名的 ZIP 文件,因此您可以
只需重命名它们并提取内容即可。
我重建了测试用例并且它正常工作(没有 COM
初始化错误了)。
我有一个 Java 9 应用程序,我正在尝试为 Windows 商店打包。奇怪的是,当我直接 运行 exe 启动器时它按预期工作,但是当我通过 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.run(Unknown Source at java.base/java.lang.Thread.run(Unknown Source)
HRESULT=0x80010106
表示 RPC_E_CHANGED_MODE
,我猜这意味着 COM 已经以某种方式在 MTA 模式下进行了初始化。但为什么这只是 Windows Bridge 沙箱中的一个问题? Windows Bridge 是否出于某种原因以某种方式 pre-initialize
COM?
我不确定这是 Java 9 问题还是桌面桥问题,或者两者兼而有之。有人对如何确定问题的原因或解决方法有任何想法吗?
我做了一个最小的 Sample Project 来重现这个问题
该应用程序在直接执行时有效,但在通过 APPX 启动器执行时无效。为什么?
分析
依赖 COM 初始化的 JDK 部分(D3DPipeline、Sound 和 windows shellfolder 访问)都遵循相同的模式:
- 运行 单独线程中的代码
- 此线程
CoInitialize
被调用 - 在用户层结束时调用代码
CoUnitialize
这与 MSDN 为 COM 保留的文档一致,分析正确,错误表明 COM 子系统已经初始化为 MTA 线程。
所以我修改了java启动器(jvm.dll)并插入 将语句调试到 os_windows.cpp 中的某些本机方法中。 我专注于线程方法。我发现的是:
create_main_thread
、create_os_thread
、pd_start_thread
全部 运行 COM 尚未初始化- 本机线程初始化程序 (
thread_native_entry
) 已经 运行 COM 已初始化
我在 _beginthreadex
中进行了更多研究,确实我终于找到了线索
在计算器上。这让我找到了 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 构建的。
解决方法
结合以上信息google终于找到了一个参考,支持分析:
https://blogs.msdn.microsoft.com/vcblog/2016/07/07/using-visual-c-runtime-in-centennial-project/
引用那篇文章:
Note that the existing VC++ 12.0 libraries created during the Windows 8 timeframe have runtime checks to determine whether the app is running under the app container or not. When running desktop apps as a packaged app, these checks might limit the functionality of the desktop app or cause it to behave like a UWA (Universal Windows Application) (limited file system access or create thread initializing MTA etc.). We have fixed this behavior in the VC++ libraries contained in these framework packages and thus removing the modern app limitations from your desktop applications.
所以我看到了修复应用程序的选项,这些应用程序应作为 AppX 包分发:
- 强制用户安装更新 VC++ 12.0 二进制文件(通过引入博客 post 中引用的依赖项)或
- 用更新包 中的固定版本替换Java 9(我假设也是Java 10)捆绑的
msvcr120.dll
我会选择第二个版本并且我测试了这个。从干净的 up-to-date Windows 10 系统开始,我安装了 JDK 9.0.4,我克隆了提供的测试用例,使用本地安装的 JRE(不是 JDK! ) 并构建 appx 包。 运行 这个,我复现了这个问题。然后,我将系统安装的 JRE 文件夹中的 msvcr120.dll
替换为 APPX 容器中包含的那个,来自:
https://www.microsoft.com/en-us/download/details.aspx?id=53176
提示:*.appx 只是带有附加签名的 ZIP 文件,因此您可以 只需重命名它们并提取内容即可。
我重建了测试用例并且它正常工作(没有 COM 初始化错误了)。