Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

verify.dll conflicts with unique module name requirement of Windows #462

Open
askids opened this issue Dec 20, 2023 · 37 comments
Open

verify.dll conflicts with unique module name requirement of Windows #462

askids opened this issue Dec 20, 2023 · 37 comments

Comments

@askids
Copy link

askids commented Dec 20, 2023

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.
``

<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!
@wasabii
Copy link
Contributor

wasabii commented Dec 20, 2023

Please try the latest version.

@askids
Copy link
Author

askids commented Dec 20, 2023

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?

@wasabii
Copy link
Contributor

wasabii commented Dec 20, 2023

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

@askids
Copy link
Author

askids commented Dec 20, 2023

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
Copy link
Author

askids commented Jan 4, 2024

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

@danielcweber
Copy link

danielcweber commented Jan 4, 2024

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.

@wasabii
Copy link
Contributor

wasabii commented Jan 5, 2024

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.

@danielcweber
Copy link

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

@danielcweber
Copy link

danielcweber commented Jan 5, 2024

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!

@wasabii
Copy link
Contributor

wasabii commented Jan 5, 2024

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

@wasabii
Copy link
Contributor

wasabii commented Jan 5, 2024

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

I'm currently baffled.

@wasabii
Copy link
Contributor

wasabii commented Jan 5, 2024

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.

@danielcweber
Copy link

@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.

@wasabii
Copy link
Contributor

wasabii commented Jan 7, 2024

Can you give 8.7.4-pre.16 a go?

@danielcweber
Copy link

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

@danielcweber
Copy link

@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
Copy link

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.

@askids
Copy link
Author

askids commented Jan 21, 2024

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
Copy link
Author

askids commented Feb 7, 2024

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

@wasabii
Copy link
Contributor

wasabii commented Feb 7, 2024

@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
Copy link
Contributor

wasabii commented Feb 7, 2024

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.

@askids
Copy link
Author

askids commented Feb 7, 2024

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
Copy link
Author

askids commented Feb 7, 2024

@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

@wasabii
Copy link
Contributor

wasabii commented Feb 7, 2024

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?

@askids
Copy link
Author

askids commented Feb 7, 2024

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.

@wasabii
Copy link
Contributor

wasabii commented Feb 7, 2024

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. =/

@askids
Copy link
Author

askids commented Feb 7, 2024

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.

@danielcweber
Copy link

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.

@askids
Copy link
Author

askids commented Feb 7, 2024

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.

@wasabii
Copy link
Contributor

wasabii commented Feb 7, 2024

@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.

@askids
Copy link
Author

askids commented Feb 7, 2024

I have 3 level projects in the solution. In all 3 projects, I had platformtarget set to x64. Top level project is a console app with exe output, which references the 2nd level library project, which in turn references the 3rd level library project which has the IKVM and jar reference. I removed platformTarget only from the 3rd library that has IKVM reference. Console app and 2nd library still has X64 platformtarget. So generated app is still a x64 exeutable.

I had manually checked the ikvm folders, when the error was earlier occurring. The jvm.dll was present in both win-x86 and win-x64 bin folders under ikvm folder. This is still the case, after I removed the platformtarget from the 3rd library.

@wasabii
Copy link
Contributor

wasabii commented Feb 8, 2024

May I ask why you are setting PlatformTarget? No combination of default options for Windows apps for Core that I can find in Visual Studio seems to add that Property.

@danielcweber
Copy link

@wasabii I updated the repro project to the latest IKVM internal preview/stable Maven SDK but the failure persists.

@danielcweber
Copy link

@wasabii I again gave it a try and updated the repro project. I observed that the error message changes from "Could not load libjava" to "Could not load libiava"...maybe this piece of information renders helpful.

Unfortunately, I haven't found a proper workaround (early loading of code in static initializers, etc.) yet.

@danielcweber
Copy link

I added some more tests that show that it's apparently not even about the order that ModuleInitializers are called, but about when the code is jitted. Just a guess though.

@wasabii
Copy link
Contributor

wasabii commented Apr 3, 2024

Ok. Yeah, I can reproduce this. I'm not yet sure why it isn't and to load. I'm pushing some changes to get better logging for it though so I'll know soon.

@wasabii
Copy link
Contributor

wasabii commented Apr 16, 2024

So, @danielcweber, I figured out an issue I believe. Still coming up with a solution.

It's because the managed assembly is named verify.dll. Which conflicts with verify.dll. If the native library loads second, the managed library is already loaded and confuses it.

@wasabii wasabii changed the title Unable to run process due to initialization failure after upgrade from 8.6.4 to 8.7.1 verify.dll conflicts with unique module name requirement of Windows May 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants