ikvm icon indicating copy to clipboard operation
ikvm copied to clipboard

verify.dll conflicts with unique module name requirement of Windows

Open askids opened this issue 2 years ago • 38 comments

hi,

We have a .Net 6.0 console app that does batch processing and is targeted for Windows 64 bit. Within that process, I am invoking a custom Java library class using the IKVM library. This was working fine in the previous versions (8.4.x, 8.5.x upto 8.6.4). However after I upgraded from 8.6.4 to 8.7.1, the process fails to initialize, when the java class is called.

This is what I have captured from my logs. In the dependencies, I have 2 jars - one is my custom library and second is the jdbc db2 driver package (.csproj file info is given below).

For the time being, I have reverted back to 8.6.4.

Please let me know if you need any further details to investigate this further.

"System.TypeInitializationException: The type initializer for 'java.lang.Object' threw an exception. ---> System.TypeInitializationException: The type initializer for 'java.io.FileInputStream' threw an exception. ---> System.TypeInitializationException: The type initializer for 'IKVM.Runtime.LibJava' threw an exception. ---> System.TypeInitializationException: The type initializer for 'IKVM.Runtime.LibJvm' threw an exception. ---> IKVM.Runtime.InternalException: Could not load libjvm. at IKVM.Runtime.LibJvm..ctor() at IKVM.Runtime.LibJvm..cctor() --- End of inner exception stack trace --- at IKVM.Runtime.LibJava..ctor() at IKVM.Runtime.LibJava..cctor() --- End of inner exception stack trace --- at IKVM.Runtime.BootstrapClassLoader..ctor(RuntimeContext context) at IKVM.Runtime.RuntimeClassLoaderFactory.GetBootstrapClassLoader() at IKVM.Runtime.RuntimeClassLoaderFactory.GetClassLoaderWrapper(ClassLoader javaClassLoader) at IKVM.Runtime.JNI.JNIFrame.GetFuncPtr(CallerID callerID, String clazz, String name, String sig) at java.io.FileInputStream.initIDs() at java.io.FileInputStream..cctor() --- End of inner exception stack trace --- at java.io.FileInputStream.__<clinit>() at java.lang.System.initializeSystemClass() at __<MethodAccessor>__System__initializeSystemClass() at IKVM.Runtime.JVM.EnsureInitialized() at java.lang.Object..cctor() --- End of inner exception stack trace --- at java.lang.Object..ctor() at mynamespace.ZLoadRequest..ctor()

Project dependencies is as give below. `` <Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
	<TargetFramework>net6.0</TargetFramework>
	<AssemblyName>MyNamspace.ZLoader</AssemblyName>
	<PackageId>MyNamspace.ZLoader</PackageId>
	<RootNamespace>MyNamspace.ZLoader</RootNamespace>
	<ImplicitUsings>enable</ImplicitUsings>
	<Nullable>disable</Nullable>
	<PlatformTarget>x64</PlatformTarget>
</PropertyGroup>

<ItemGroup>
	<PackageReference Include="IKVM" Version="8.7.1" />
	<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.1" />
</ItemGroup>

<ItemGroup>
	<IkvmReference Include="db2jcc4.jar">
		<AssemblyName>com.ibm.db2</AssemblyName>
		<AssemblyVersion>11.5.8.0</AssemblyVersion>
		<AssemblyFileVersion>11.5.8.0</AssemblyFileVersion>
	</IkvmReference>
	<IkvmReference Include="myappnamespace.zload.jar">
		<AssemblyName>MyAppNamspace.ZLoad</AssemblyName>
		<AssemblyVersion>1.0.0.0</AssemblyVersion>
		<AssemblyFileVersion>1.0.0.0</AssemblyFileVersion>
		<References>db2jcc4.jar</References>
	</IkvmReference>
</ItemGroup>
`` Thanks!

askids avatar Dec 20 '23 02:12 askids

Please try the latest version.

wasabii avatar Dec 20 '23 02:12 wasabii

Please try the latest version.

I knew, you would say that :) I did see the later versions on GitHub. But we are in a restricted development environment and don't have access to direct nuget feed to pull latest version. Instead, we use some cached feed (post some scanning etc). So i will need to wait a few more days before the new version reflects in the internal nuget feed. BTW, was this a known issue in 8.7.1 which was fixed in subsequent release?

askids avatar Dec 20 '23 02:12 askids

Maybe. There's been a few issues with the new native library stuff in 8.7 that I've fixed in subsequent versions.

wasabii avatar Dec 20 '23 02:12 wasabii

Ok. Once I have the new version available, I will try it and report back if the issue is resolved or still happening.

Thanks

askids avatar Dec 20 '23 03:12 askids

I tried it with 8.7.3 and still getting same error as originally reported.

askids avatar Jan 04 '24 06:01 askids

I had a look into this. The folder from which IKVM tries to load all the native libaries looks like this:

image

The load that fails is done by LibJvm._JVM_LoadLibrary(...). I threw all the files into the method, and they produce seemingly valid handles, except for

iava.dll net.dll nio.dll unpack.dll

The failure to load iava.dll produces the error that we see.

Edit: Path prefix for me is net8.0\ikvm\win-x64\bin.

danielcweber avatar Jan 04 '24 22:01 danielcweber

So one of the issues I had found for 8.7.0 was that the default RID for Framework was win-x86. So, it would publish win-x86.

But then run 64-bit anyways.

So, I adjusted it so that if it publishes win-x86, and Prefer32Bit != 'true', then it includes both win-x86 and win-64 libraries. So, regardless what it happens to run as, the native libs should be available.

But, maybe this is a different issue.

I do think I probably need to see your project output at this point. Or some reproduction. To see what is where and what it's running as.

wasabii avatar Jan 05 '24 08:01 wasabii

I'll do my best to isolate something and test the latest SDK from Github packages. It might take me a while.

danielcweber avatar Jan 05 '24 08:01 danielcweber

I was able to strip things down to the likely culprit: https://github.com/danielcweber/IKVM_Repro

It's a xUnit test project with a library that references IKVM. The library itself contains no code, so the test project on it's own with a reference to IKVM is probably already sufficient.

It can be run simply with dotnet test or within Visual Studio. Tests start failing when code from the snapshot utility VerifyTests is loaded (AppDomains?!). Tests will succeed in isolation if no code from VerifyTests has run before. I can't tell yet whether there's something weird going on at runtime or whether the reference to VerifyTests already confuses the rids in IKVM....

I'd understand if you'd consider this an edge case due to some weird behaviour by a third party library. Maybe this can provide some insight though.

Thanks a lot!

danielcweber avatar Jan 05 '24 15:01 danielcweber

@danielcweber Is this a new thing for you, or related to the thing the OP is talking about?

wasabii avatar Jan 05 '24 16:01 wasabii

What's fun is to reverse the order of VerifySettings and new java.lang.Object.

I'm currently baffled.

wasabii avatar Jan 05 '24 16:01 wasabii

Okay. So, Verify. I've at least figured this much. Verify.dll has a ModuleInitializer that looks for Verify.*.dll for plugins, and loads them all. And the plugins all have module initializers themselves. And perhaps one of these loads IKVM.Java/IKVM.Runtime, and somehow enumerates something in it which causes a static ctor to be invoked before the JVM is initialized.

I think maybe the OP's issue is just that he needs to force the JVM to initialize before calling into it: by calling new java.lang.Object at the top of his program.

wasabii avatar Jan 05 '24 16:01 wasabii

@wasabii Wow. Thanks for investigating.

Is this a new thing for you, or related to the thing the OP is talking about?

I think it's pretty much the same thing, although it would be interesting if @askids could strip their repro to the minimal parts to see what else is causing such behaviour.

danielcweber avatar Jan 05 '24 23:01 danielcweber

Can you give 8.7.4-pre.16 a go?

wasabii avatar Jan 07 '24 17:01 wasabii

I will give it a try as soon as I am able to. Thank you very much for tackling this!

danielcweber avatar Jan 11 '24 20:01 danielcweber

@wasabii It works in the repro project, but not in my actual project. So I guess I will again carefully strip it down to the culprit.

danielcweber avatar Jan 12 '24 16:01 danielcweber

Made the repro fail again. Creating something from a Maven dependency makes it fail. That's maybe only because the Maven SDK is from Nuget.org and has not received any experimental fixes.

danielcweber avatar Jan 15 '24 13:01 danielcweber

Made the repro fail again. Creating something from a Maven dependency makes it fail. That's maybe only because the Maven SDK is from Nuget.org and has not received any experimental fixes.

In my case, I am not using maven reference. Its a local jar reference to both jars (one my custom jar and 2nd from IBM).

askids avatar Jan 21 '24 08:01 askids

Tried it on recent 8.7.5 release and still seeing same issue.

askids avatar Feb 07 '24 19:02 askids

@askids In your case do you have all the folders and libraries in the right spot for the architecture you're trying to run on?

wasabii avatar Feb 07 '24 19:02 wasabii

And have you tried the workaround of forcing the JVM to initialize before VerifySettings by ... doing anything with it really, but new java.lang.Object() is the easiest.

wasabii avatar Feb 07 '24 19:02 wasabii

And have you tried the workaround of forcing the JVM to initialize before VerifySettings by ... doing anything with it really, but new java.lang.Object() is the easiest.

Tried add a dummy line before call to my actual java class. But the error is still generated from the old line of code only.

var dummy = new java.lang.Object();
var zLoadRunner = new ZLoadRunner(GetZLoadRequest(request));
var response = zLoadRunner.Load(); // ---------> error is generated pointing to this line in stacktrace.

askids avatar Feb 07 '24 21:02 askids

@askids In your case do you have all the folders and libraries in the right spot for the architecture you're trying to run on?

Didn't get what you mean by this? I haven't setup anything specifically. Its same as how it was before in 8,6.4. Target project is x64 on .Net 6.0

askids avatar Feb 07 '24 21:02 askids

And have you tried the workaround of forcing the JVM to initialize before VerifySettings by ... doing anything with it really, but new java.lang.Object() is the easiest.

Tried add a dummy line before call to my actual java class. But the error is still generated from the old line of code only.

var dummy = new java.lang.Object();
var zLoadRunner = new ZLoadRunner(GetZLoadRequest(request));
var response = zLoadRunner.Load(); // ---------> error is generated pointing to this line in stacktrace.

The same error?

wasabii avatar Feb 07 '24 22:02 wasabii

There is one small difference. The type initializer for '<Module>' threw an exception. . Previously, it was pointing to java.lang.Object. Rest of the details in stack trace is same...says could not load libjvm.

askids avatar Feb 07 '24 22:02 askids

So, anyway you can get a repro that mirrors this?

I'm not able to. Anything related to libjvm should have broken in the first access to IKVM.Runtime, which would happen on new java.lang.Object. Except you're passed that. =/

wasabii avatar Feb 07 '24 22:02 wasabii

I am on a restricted client environment. It will take some time for me to share just the full stack trace :). Have requested the information to be shared. Let me try to see if I can create a stripped down version of the code, if possible.

askids avatar Feb 07 '24 22:02 askids

Made the repro fail again. Creating something from a Maven dependency makes it fail. That's maybe only because the Maven SDK is from Nuget.org and has not received any experimental fixes.

I will give it a try the v8.7.5 and the latest Maven SDK.

danielcweber avatar Feb 07 '24 22:02 danielcweber

ok. I somehow got it working. The cs project which had the IKVM reference had PlatformTarget set to x64. When I removed the platform target and did a clean build, the process worked fine. With 8.6.4, it still works, when my project has PlatformTarget set to x64.

askids avatar Feb 07 '24 22:02 askids

@askids Okay. That's a hint then. What I would check is whether, if you add PlatformTarget, what happens to the output and stuff?

Does it generate a .exe file in the win-x86 folder? And yet, when running that exe, does it run as 64 bit? if so, it'll need 64 bit libraries. Do the 64 bit libraries get copied to the output regardless of the exe being win-x86? Etc.

I need to dig into PlatformTarget and figure out wtf it's supposed to mean.

wasabii avatar Feb 07 '24 23:02 wasabii