実行中のアプリケーションにJava 7を挿入した方法、およびCランタイム用に発明しなければならなかったこと

画像

寒い冬に、何年も前から正常に機能していた古いC ++アプリケーションで、完全に機能するJava 6の代わりに新しいJavaランタイム7を挿入する必要がありました。

コードは一般的に明白で単純です-少しJNI で、ここでは-悪い歯です。 Windows専用のコードを提供します。 ケシの下でバランスを取ることの不思議は必要ありませんでした。



どうでしたか


何年も前に、標準的な方法でjvm.dllにリンクされた簡単なDLLを作成し、その中の2つ半の関数をエクスポートし、動的に「引き出し」ました。 この耳のかすかなことは明らかです-Java自体がどこにあるのかを見つける必要があります。 この単純なプロキシは、このようなものと呼ばれていました

bool LoadJavaEngine(HANDLE& engHandle) { bool loadResult = false; do { ... // here we have auto variables, nothing interesting // first we need to find java CRegKey rk; if(rk.Open(HKEY_LOCAL_MACHINE, L"SOFTWARE\\JavaSoft\\Java Runtime Environment\\1.6", KEY_QUERY_VALUE) != ERROR_SUCCESS || rk.QueryValue(strBuf, L"RuntimeLib", &strBufSz) != ERROR_SUCCESS) break; WCHAR* backslashAddr = wcsrchr(strBuf, L'\\'); if(backslashAddr) BufLen = backslashAddr - strBuf; strBuf[BufLen] = L'\0'; // now C runtime knows where is jvm.dll located retnPWD = SetDllDirectoryW(strBuf); // ... nothing intersting - in the same manner we're looking for our proxy path in registry if((engHandle = LoadLibrary(strBuf))==NULL) break; // now try to initialize JVM by calling our proxy linked with jvm.dll CreateJavaVMFunPtr CreateJavaVM = (CreateJavaVMFunPtr)GetProcAddress(engHandle, "CreateJavaVM"); if(CreateJavaVM) loadResult = CreateJavaVM(needJNIProxy); } while(false); return loadResult; } 


思いがけないレーキ


ご覧のとおり、コードは非常にシンプルで、一般に3行もかかります

  SetDllDirectory LoadLibrary GetProcAddress 


そして今-私たちは複雑です。 Java 6では、Java 7に移行しています。楽観的な予測はこのようなものでした。1行変更するだけですべてが機能します。

変更
  if(rk.Open(HKEY_LOCAL_MACHINE, L"SOFTWARE\\JavaSoft\\Java Runtime Environment\\1.6", 


  if(rk.Open(HKEY_LOCAL_MACHINE, L"SOFTWARE\\JavaSoft\\Java Runtime Environment\\1.7", 

そして、有名なリトアニアの休日「オブロマイティス」は、パスが見つかりません。 彼は単純なプロキシをダウンロードしたくありません。

テレパシーセッション


手続きの1時間半の間、次のことが判明しました。

  1. メインプログラムの以前のバージョンとそのためのJavaプラグインは、2003〜2008年のビジュアルスタジオ(MSVCR80.dll、MSVCR90.dllなど)、およびJava 6でそれぞれコンパイルされ、MSVCR71.dllの希少性がありました。
  2. 新しいJavaはMSVCR100.dllを使用してコンパイルされます(ええ、ええ)。 そして、顧客のプログラムのバージョンはMSVCR90.dllを使用します。 ロードされません。


グーグルは機能しませんでした-マニフェストを処方および削除すると、重量ごとにゼロが得られ、同じ結果になりました。

タンバリン


画像
そして、大きなファイルがポケットから引き出され小道具の別のモンスターが生まれました。 そして、1つのSetDllDirectoryの代わりに、これが起こったのです。

  wcscat(strBuf, L"\\msvcr100.dll"); test = LoadLibraryW(strBuf); strBuf[BufLen] = L'\0'; wcscat(strBuf, L"\\client\\jvm.dll"); test = LoadLibraryW(strBuf); if(test == 0) { strBuf[BufLen] = L'\0'; wcscat(strBuf, L"\\server\\jvm.dll"); test = LoadLibraryW(strBuf); } strBuf[BufLen] = L'\0'; retnPWD = SetDllDirectoryW(strBuf); 

つまり、MSVCR100.dllから開始して依存関係を手動でロードすると、検出されて機能します。 そうでなければ、悲しいかな。

免責事項:「新しいバージョンを顧客に提供する」オプションは適切ではありません。 メインアプリケーションはAdobe InDesign Server CS5で、ライセンスあたり$ 7kです。

有刺鉄線の詳細は、このトピックに関する以前の出版物に記載されています。

http://habrahabr.ru/post/122746/
http://habrahabr.ru/post/127574/

Source: https://habr.com/ru/post/J148068/


All Articles