Open BiologyTools opened 1 year ago
Happen to have a projec/solution that demonstrates this?
I have prepared a project file and uploaded it to a google drive since the issue occurs with some whole-slide-images only which used to open up fine before. Unfortunately the file size is pretty big due to the size of the whole-slide-image. Here is the link: https://drive.google.com/file/d/1PyLNtq3TT_M1_5-xr7-ou1qZpCFnTF8Q/view?usp=sharing
@wasabii This issue seems to effect all NDPI whole-slide-images. Here BioformatsTest.zip is the project without an image since WSI's tend to be large. Here is a link to another NDPI image showing the same error: https://cytomine.com/collection/os-2/os-2-ndpi Have you had time to look into this error?
I've done enough work to understand the problem now. Now I just need to come up with a solution.
The issue is the JNI spec says this:
In the JDK, each class loader manages its own set of native libraries. The same JNI native library cannot be loaded into more than one class loader. Doing so causes UnsatisfiedLinkError to be thrown. For example, System.loadLibrary throws an UnsatisfiedLinkError when used to load a native library into two class loaders.
What's happening is the code loading the JNI library is different from the code trying to bind to it. There seems to be a common "native library loading capability" in a module named "org.scijava.nativelib". The jxrlib library takes it's native DLL, extracts it to a temporary directory, and then calls into org.scijava.nativelib to do the loading. At which point, it is org.scijava.nativelib that has loaded the library. And as such, it isn't available to the classloader with JXRLIB in it!
The thing here is that the org.scijava.nativelib functionality doesn't support the calling library being in a different classloader than itself.
And the way it's set up today, statically compiled DLLs each have their own unique class loader, so the class visibility can be restricted based on .NET reference visibility.
I consider this sort of a bug in org.scijava.nativelib or jxrlib. They should be passing the classloader down, or the loading class down, and using that passed classloader to do the native loading. But, they don't, so these two things have to be in the same clas loader.
Not yet sure of a solution on the IkvmReference side.
I'm surprised this used to work at all with IKVM 8.6.4. Should I get in touch with org.scijava.nativelib devs to get this fixed? I suspect this issue will happen with a lot more formats than just NDPI since it's related to JXRLIB. Thank you for your time this must have been a tough one to track down.
It works if you take all of the jar files and merge them into one assembly. Because IKVM loads each assembly into it's own class loader. But that's not how MavenReference works, and for good reason.
So, this will still work, for instance, if you use IkvmReference to merge all the jars together. But then you can't use MavenReference to get the JARs in the first place.
I'm not yet sure what the right answer is here.
In IKVM, each assembly gets it's own class loader. Because this means when you build assemblies like AssemblyA with a dependency to AssemblyB, the class loader hierarchy makes resources in AssemblyB visible to AssemblyA through delegation. But not resources in some random AssemblyC. The assembly dependencies form the class loader hierarchy, so it mirrors .NET, and you don't have resources or classes from random unexpected places being picked up.
And then MavenReference creates on IkvmReference per artifact, linking them together based on how Maven describes their references. So the Maven dependency tree ultimately informs the class loader hierarchy.
https://github.com/scijava/native-lib-loader/issues/49
It would obviously make the problem go away if this library just let you do the right thing, and then all the code got fixed. But I do feel like we should have a better answer.
Thank you for opening an issue with scijava hopefully this will be fixed by them and make it's way to the Bioformats library eventually. I'm glad this will hopefully help some scientists out in their work since IKVM Maven is now mentioned as a way to work with the Bioformats library in .NET in the bioformats documentation. https://bio-formats.readthedocs.io/en/stable/developers/dotnet-dev.html
I'm using IKVM 8.7.1 and I am getting this error when calling openBytes(). I know this can't be an error in the java code since I'm using the same version 7.0.1 as before back when I converted the jar to dll with ikvmc.exe it worked fine. I'm now using the IKVM Maven SDK instead of ikvmc.exe. Do you have any idea on what could be going on?