📜 ⬆️ ⬇️

How I inserted Java 7 into a running application, and what I had to invent for a C runtime

image

Once, in the icy winter season, one old C ++ application that had worked successfully for years had to insert a new Java runtime 7 instead of a well-run Java 6. Nothing boded, and suddenly.

The code is, in general, obvious and simple - a little JNI , and here it is - a bad tooth . I will give the code only for Windows, because Equilibrism miracles under poppy are not required.
')


How it was


Once, many years ago, we created a simple DLL linked to jvm.dll in the standard way, exported two and a half functions in it, and “pulled” it dynamically. This trick with ears is obvious - we still have to find where Java itself is located. This simple proxy was called something like this.

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; } 


Unexpected rake out of the blue


As you can see, the code is extremely simple and in general it occupies as many as three lines.

  SetDllDirectory LoadLibrary GetProcAddress 


And now - complicate. From Java 6 we turn to Java 7. The optimistic forecast was like that - we’ll change one line and everything works.

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

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

and comes the famous Lithuanian holiday "oblomaitis" Path not found. Do not want to download our simple proxy.

Telepathy session


During the one and a half hour proceedings, it turned out:

  1. The previous version of the main program and our plugin on java for it were compiled by visual studios from 2003 to 2008 (MSVCR80.dll, MSVCR90.dll, etc.), and Java 6, respectively, with a rare book with MSVCR71.dll.
  2. New Java compiled using MSVCR100.dll (yeah, yeah). And the version of the program at the customer - uses MSVCR90.dll. That does not load.


Googling options did not give - prescribing and deleting manifests gave zero to the mass with the same result.

Rumor on a tambourine


image
And then a large file was pulled out of his pocket, and they gave birth to another monster of props. And instead of one SetDllDirectory, this is what happened:

  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); 

That is, if you load dependencies from MSVCR100.dll with your hands, it finds and works. Otherwise, alas.

Disclaimer: the option “you put a newer version for the customer” is not appropriate. The main application is Adobe InDesign Server CS5, for $ 7k per license.

Details about the barbed wire can be found in previous publications on the topic.

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

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


All Articles