2017-10-24 15 views
15

Windows Store 용으로 패키지하려는 Java 9 응용 프로그램이 있습니다. 이상한 것은 내가 직접 EXE-실행 프로그램을 실행할 때 예상대로 작동한다는 것입니다,하지만 난 APPX 패키지를 통해 실행 프로그램을 실행할 때 나는 다음과 같은 이상한 오류가 발생합니다 :"Swing-Shell"java.lang.InternalError : COM을 초기화 할 수 없습니다 : HRESULT = 0x80010106

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 Bridge가 어떻게 든 어쨌든 pre-initialize COM을 어떻게 여깁니까?

Java 9 문제인지, Desktop Bridge 문제인지 또는 둘 다 확실하지 않습니다. 문제 또는 해결 방법의 원인을 식별하는 방법에 대한 아이디어가 있습니까?

내가 직접 실행할 때,하지만 APPX 런처를 통해 실행하지 않을 경우 응용 프로그램이 작동 문제

을 재현하는 최소한의 Sample Project을 만들었습니다. 왜?

+0

가능한 스레드 덤프가 더 나은 통찰력이 될 것이고 jdk 메일 링리스트를 여는 것이보고되면 버그 추적기 등도 도움이됩니다. – nullpointer

+0

관련이 있는지는 잘 모르겠지만 [JDK-8189604] (https://bugs.openjdk.java.net/browse/JDK-8189604) – nullpointer

+0

을 살펴보십시오.이 테스트 케이스를 문제가 재현되어 https://bugs.openjdk.java.net/browse/JDK-8189938에 첨부 할 수 있습니다. –

답변

1

분석

COM에 의존 JDK 부품, 초기화되고

은 (D3DPipeline는, 사운드 및 창문의 ShellFolder 액세스) 모두 같은 패턴을 따르

  • 실행 별도의 스레드에서 코드를
  • 사용자 수준 코드 CoUnitialize의 말에
  • 라고 CoInitialize이 스레드에 대한
,536라고

이것은 MSDN에서 COM에 대해 보유하고있는 설명서와 일치하며 COM 하위 시스템이 이미 MTA 스레드로 초기화되었음을 나타내는 오류가 나타납니다.

그래서 나는 자바 실행 ( jvm.dll을를) 수정 os_windows.cpp 네이티브 몇 가지 방법으로 디버깅 문을 삽입. 스레딩 방법에 중점을 두었습니다. 내가 발견 한 것은이 있었다 :

  • create_main_thread, create_os_thread는, pd_start_thread 아직 COM 실행
  • 네이티브 스레드 초기화 (thread_native_entry가) 이미 을 초기화되지 COM 모든 실행이 초기화

나는 보았다 _beginthreadex에 대한 자세한 내용 및 실제로 드디어 leadwall을 찾았습니다 on stackoverflow. 저의 소스 코드는 입니다. threadex.c, Visual Studio 2013 Express 설치의 일부입니다. 당신이 찾을 수 있습니다

, 그 _beginthreadex 직접 공급 스레드 기능을 시작하지만, 먼저 라이브러리 초기화 (_threadstartex)를 실행하지 않습니다.이 초기화의 일부는 읽기 : 응용 프로그램이 "PackagedApp"(즉, AppX 패키지)와 같은 실행되는 경우

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

_callthreadstartex(); 

_crtIsPackagedApp

는 커널 함수를 통해 감지 그렇다면, 다음 RoInitialize 함수 호출에서하는 내 이해는 CoInitialize의 큰 형제 형처럼 작용합니다.

짧은 이야기 : 응용 프로그램이 Visual Studio 2013 으로 빌드되어 패키지 응용 프로그램으로 실행되는 경우 깨진 환경이 발생합니다.

Oracle JDK의 작업 버전은 VS2010 SP1로 빌드되었고 깨진 버전은 VS2013SP4로 빌드 되었음이 확인되었습니다.

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.

그래서 내가 옵션 참조 : 그 기사에서

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

인용구 :

구글이 마침내 참조를 발견 위의 정보와 해결 방법

, 즉 분석을 지원합니다 응용 프로그램을 수정하려면 AppX 패키지로 배포해야합니다 :

(210)
  • 중 자바 (9)와 함께 번들로 제공되는 msvcr120.dll 교체 (그리고 나는 또한 자바 10 가정) 또는
  • 합니다 (블로그 게시물에 인용 된 의존성을 도입하여) VC++ 12.0 바이너리가 설치 업데이트를하는 사용자를 강제로 업데이트 패키지의 수정 된 버전

두 번째 버전으로 이동하고 테스트했습니다. 최신 Windows 10 System으로 시작하여 JDK 9.0.4를 설치하고 제공된 테스트 케이스를 복제하고 JDK가 아닌 로컬에 설치된 JRE를 수정하여 appx 패키지를 작성했습니다. 이걸 실행하면 문제가 재현됩니다. 그때로부터 APPX 컨테이너에 보관 한 내 시스템 설치의 JRE 폴더에 msvcr120.dll 's을 (를) 대체 :

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

힌트 : * 단지 추가 서명 파일을 ZIP하는 .appx, 당신 때문에 이름을 바꿀 수 있으며 내용을 추출 할 수 있습니다.

테스트 케이스를 다시 작성하고 정상적으로 작동합니다 (COM 초기화 오류가 발생하지 않음).