Open dlif-v opened 4 months ago
~Probably dependency issue with VCRT.~
~Check ABC.dll and XYZ.dll with Dependencies
for direct dependencies (i.e. msvcrt, vcruntime).~
copy both dlls to the exe's dir then it loads both dlls fine
scratch what I wrote.
Would probably need more details on the specific DLL or something. There's actually not much in this process that IKVM is responsible for. We call LoadLibraryExW(wfilename, 0, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR);
and present the error back as an exception. Everything that LoadLibraryExW does is up to Windows itself. We have very little control over how it goes about locating dependencies.
One thing I can sort of imagine is that maybe it depends on something else that is different in a native Java. But I can't know that without seeing it.
Thanks for the hint. I traced this issue back to a commit last June switching from LoadLibrary (which works fine in my case) to LoadLibraryEx with LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR, and then LOAD_LIBRARY_SEARCH_DEFAULT_DIRS was added later. Note the documentation for both options say "Directories in the standard search path are not searched" which is what's breaking things.
The commit mentions it's trying to fix loading libs from a given path so my suggestion would be to revert back to using the regular LoadLibrary and call AddDllDirectory at some point to add the extra given paths.
Ahhhhh. Okay, so, yeah, the PATH env is left out.
So we have a problem here. Because IKVM runs in process with .NET, and is loaded as an assembly, I'm a bit hesitent to change anything related to the process overall. For instance, by calling AddDllDirectory. That effects the search order of not just IKVM loaded JNI stuff, but also anything loaded by .NET (other P/Invoke calls) or other dlls, etc.
As to LoadLibrary: the reason I replaced it with LoadLibraryEx, is so dependent DLLs in the same folder as their parent are found. LoadLibrary doesn't allow this. But it was necessary because of the load order of some of the built in JVM DLLs (libiava, libjvm, etc). Since these load directly out of the executable path on a normal JVM (java.exe is located in the same dir as net.dll, etc), but in the .NET case, the process application path may differ (foo.exe using IKVM against a ikvm home dir located elsewhere).
So I need to come up with a better solution it seems. Something that makes the dependent search path for JDK DLLs work, regardless where the process is loaded form, but also doesn't override the user expectations that dependents can be on PATH.
Using IKVM 8.8.1 in a .NET 6.0 Windows Application, I have a jar that calls
System.loadLibrary("ABC");
where ABC depends on XYZ and each dll is in its own directory (eg C:\abc\ABC.dll and C:\xyz\XYZ.dll) and both directories are in PATH (and appear as expected in java.library.path). I get the following exception:If I use the jar in a java app then it loads both dlls fine. If I copy both dlls to the exe's dir then it loads both dlls fine (but that's not right or practical). If I DllImport any function from ABC and call the function in C# then it loads both dlls fine (but that is hacky, etc). If I add
System.loadLibrary("XYZ");
in the java first then it loads both dlls fine (but this is not a cross-platform solution since on Android XYZ is named something else so it will fail there).Expected: loading a lib from java should work the same as it does in java (and the regular .net app)