2017-10-24 16 views
15

Tôi có một ứng dụng Java 9 mà tôi đang cố gắng đóng gói cho Windows Store. Điều kỳ lạ là nó hoạt động như mong đợi khi tôi chạy exe-launcher trực tiếp, nhưng tôi nhận được lỗi lạ sau khi tôi chạy launcher qua gói phụ lục:"Swing-Shell" java.lang.InternalError: Không thể khởi tạo 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 nghĩa RPC_E_CHANGED_MODE mà tôi đoán phương tiện đó COM bằng cách nào đó đã được khởi tạo trong chế độ MTA. Nhưng tại sao đây chỉ là một vấn đề trong hộp cát Windows Bridge? Liệu Windows Bridge bằng cách nào đó pre-initialize COM bằng cách nào đó vì một số lý do?

Tôi không chắc đây có phải là vấn đề Java 9 hay vấn đề về Cầu nối trên Desktop hay cả hai. Có ai có bất kỳ ý tưởng về làm thế nào để xác định nguyên nhân của vấn đề hoặc workaround?

Tôi đã thực hiện một tối thiểu Sample Project để tạo lại lỗi

Ứng dụng này hoạt động khi thực hiện trực tiếp, nhưng không phải khi thực hiện thông qua các phóng phụ lục. Tại sao?

+0

Một kết xuất chuỗi có thể sẽ là một cái nhìn sâu sắc hơn và báo cáo điều này để mở danh sách gửi thư jdk, trình theo dõi lỗi vv cũng sẽ hữu ích. – nullpointer

+0

Không chắc chắn nếu chúng có liên quan, nhưng hãy xem [JDK-8189604] (https://bugs.openjdk.java.net/browse/JDK-8189604) – nullpointer

+0

Bạn có thể chưng cất điều này xuống một trường hợp thử nghiệm nhỏ mà tái tạo vấn đề sao cho nó có thể được đính kèm vào https://bugs.openjdk.java.net/browse/JDK-8189938. –

Trả lời

1

Phân tích

Các bộ phận JDK, dựa trên COM được khởi tạo (D3DPipeline, âm thanh và cửa sổ ShellFolder truy cập) tất cả làm theo cùng một khuôn mẫu:

  • chạy mã trong một thread riêng biệt
  • cho chủ đề này CoInitialize được gọi
  • ở phần cuối của mã mức người dùng CoUnitialize được gọi

Điều này phù hợp với tài liệu mà MSDN giữ cho COM và phân tích là chính xác, lỗi cho biết rằng hệ thống con COM đã được khởi tạo thành chuỗi MTA.

Vì vậy, tôi sửa đổi trình chạy java (jvm.dll) và chèn tuyên bố gỡ lỗi vào một số phương pháp có nguồn gốc trong os_windows.cpp. Tôi tập trung vào các phương pháp luồng. Những gì tôi thấy được điều này:

  • create_main_thread, create_os_thread, pd_start_thread tất cả chạy với COM chưa khởi
  • initializer chủ đề quê hương (thread_native_entry) đã chạy với COM khởi

Tôi nhìn nhiều hơn vào trong _beginthreadex và thực sự tôi cuối cùng đã tìm thấy một dẫn trên stackoverflow. Điều đó đã chỉ cho tôi mã nguồn của threadex.c, là một phần của cài đặt Visual Studio 2013 Express.

Ở đó bạn thấy rằng _beginthreadex không trực tiếp bắt đầu chức năng chuỗi được cung cấp, nhưng chạy bộ khởi tạo thư viện (_threadstartex) trước tiên.Một phần của initializer này lần đọc:

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

_callthreadstartex(); 

_crtIsPackagedApp phát hiện qua một hàm kernel nếu ứng dụng là chạy như là một "PackagedApp" (tức là gói phụ lục) và nếu như vậy, thì RoInitialize hàm được gọi, mà từ tôi sự hiểu biết hành vi như anh em lớn của CoInitialize.

Tóm tắt câu chuyện dài: Nếu ứng dụng của bạn được tạo bằng Visual Studio 2013 và chạy dưới dạng ứng dụng đóng gói, bạn sẽ gặp phải một môi trường bị hỏng.

Nó đã được xác nhận, rằng các phiên bản làm việc của Oracle JDK được xây dựng với VS2010 SP1 và phiên bản bị hỏng được xây dựng với VS2013SP4.

Cách giải quyết

Với các thông tin trên google cuối cùng tìm thấy một tài liệu tham khảo, hỗ trợ phân tích:

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

Trích dẫn từ bài viết rằng:

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.

Vì vậy, tôi thấy để lựa chọn để sửa các ứng dụng, sẽ được phân phối dưới dạng gói AppX:

  • hoặc buộc người sử dụng phải có bản cập nhật VC++ 12,0 mã nhị phân được cài đặt (bằng cách giới thiệu các phụ thuộc được trích dẫn trong các bài viết trên blog) hoặc
  • thay thế msvcr120.dll mà đi kèm với Java 9 (và tôi cũng giả Java 10) với phiên bản cố định từ gói cập nhật

Tôi sẽ sử dụng phiên bản thứ hai và tôi đã thử nghiệm điều này. Bắt đầu với một hệ thống Windows 10 sạch mới nhất, tôi đã cài đặt JDK 9.0.4, tôi nhân bản testcase được cung cấp, sửa đổi nó sử dụng JRE được cài đặt cục bộ (không phải là JDK!) Và xây dựng gói appx. Chạy này, tôi sao chép vấn đề. sau đó tôi thay thế msvcr120.dll 's trong thư mục JRE cài đặt hệ thống của tôi với một chứa trong các thùng chứa phụ lục từ:

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

Gợi ý: * .appx chỉ là file ZIP có chữ ký bổ sung, vì vậy bạn có thể chỉ cần đổi tên và trích xuất nội dung.

Tôi xây dựng lại testcase và nó hoạt động như bình thường (không có COM lỗi khởi tạo nữa).

Các vấn đề liên quan