ikvmnet / ikvm

A Java Virtual Machine and Bytecode-to-IL Converter for .NET
Other
1.17k stars 110 forks source link

SpringBoot built jar support #386

Closed anchurcn closed 1 year ago

anchurcn commented 1 year ago

I want to reflect the class metadata in jar, so I followed AssemblyClassLoaderTests but doesn't work correctly.

The main reason is standard JVM class loader does not support SpringBoot built jar. SpringBoot built jar structure:

example.jar
 |
 +-META-INF
 |  +-MANIFEST.MF
 +-org
 |  +-springframework
 |     +-boot
 |        +-loader
 |           +-<spring boot loader classes>
 +-BOOT-INF
    +-classes
    |  +-mycompany
    |     +-project
    |        +-YourClasses.class
    +-lib
       +-dependency1.jar
       +-dependency2.jar

How can I specify a custom class loader for loading the SpringBoot-built jar? Thanks for your reply.

wasabii commented 1 year ago

I can't figure out what you're asking here. There's not enough information about what you're trying to do or what is wrong.

anchurcn commented 1 year ago

@wasabii Sorry, I will provide more information here. I want to compile a jar to a .NET assembly using ikvm (Demo followed AssemblyClassLoaderTests ) but got some warning: IKVMC0135: Unable to compile "BOOT-INF .classes.com.mycompany.project.YourClasses.class" (wrong name: "com.mycompany.project.YourClasses")

Finally, it generates the .NET assembly containing just types in namespace org.springframework.xxx, the types in namespace com.mycompany.xxx are missing.

The jar is built from a spring boot project, and I search on the Internet and get some key info: The jar built from spring boot project can not load by default JVM class loader.

wasabii commented 1 year ago

I...

Did you read the README?

anchurcn commented 1 year ago

Yes... Is there something I missing?

wasabii commented 1 year ago

That's not a demo. That's a unit test. Why aren't you using IkvmReference?

wasabii commented 1 year ago

And is it a standard JDK 8 jar?

anchurcn commented 1 year ago

Thanks, I will try IkvmReference. I don't know what is standard JDK 8 jar, I just know it is compiled on JDK 8 and runnable on JDK8. But this jar has its own class loader. The jar package structure:

example.jar
 |
 +-META-INF
 |  +-MANIFEST.MF
 +-org
 |  +-springframework
 |     +-boot
 |        +-loader
 |           +-<spring boot loader classes>
 +-BOOT-INF
    +-classes
    |  +-mycompany
    |     +-project
    |        +-YourClasses.class
    +-lib
       +-dependency1.jar
       +-dependency2.jar

The META-INF/MANIFEST.MF content:

Main-Class: org.springframework.boot.loader.JarLauncher
Start-Class: com.mycompany.project.MyApplication

The launcher class is set to org.springframework.boot.loader.JarLauncher because the jar cannot load correctly by the standard JVM class loader, use the JarLauncher to replace the default class loader.

wasabii commented 1 year ago

Yeah that's definitely not a standard JAR. It has other JARs inside of it. You will not be able to convert that to an assembly.

You may be able to run it dynamically.

anchurcn commented 1 year ago

My main purpose is to get the class definition (Entities, Enums) in Java code, I don't know if running it dynamically is a good idea. Thank you for your patience.

wasabii commented 1 year ago

Yeah, so, I did some reading. It's a non-standard kinda weird hack to get a full application into a single JAR file. Nothing about how it loads is part of the Java Specification.

The only class inside that JAR that IKVM's static compiler could be aware of is the stuff outside of BOOT-INF: because that's the standard classpath for a JAR file. So, IKVM can probably compile THAT into the assembly. The nested JARs, and the rest of the stuff in BOOT-INFO, however, the best it can do with that is put them into the assembly as resources. Because that's what they are, according to the standard Java spec. Resources.

I would half expect it to be able to run though. Because it'll do what it says to do: compile the stuff outside BOOT-INF into .NET code. Which you can then run. Including the classloader. Which will read the resources and dynamically compile those as additional classes at runtime.

But it isn't going to magically probe into that logic on it's own.

wasabii commented 1 year ago

That said, the nested JARs and classes are right there, inside that JAR file. You can pull them out yourself.

wasabii commented 1 year ago

I'm going to go ahead and close this, because I don't think we've found any sort of issue with IKVM itself.