r/javahelp • • 5d ago

Having difficulty in converting a jar file into native files

I am confused in this part where jar file can be converted into native fil like exe, dll, executable and so file. There are other languages like c++, rust and go and we have lot of different compilation support like exe, dll, so etc and also wasm. Does java have any way to compile jar or class files into any format whichever i would like? I am talking about true cross platform in here like what can be done in c++ or rust and also I am talking about the static and dynamic library generation part as well.

Please help me in this topic as I was learning java and currently confused in this part.

0 Upvotes

16 comments sorted by

1

u/AutoModerator 5d ago
Moderator Announcement Read More »

10

u/BassRecorder 5d ago

Usually every Java program runs under the Java Virtual Machine - that is what makes Java easily portable.

Ahead of time compilation is the process to convert a Java program into a native executable. This is used in cases where startup time is a critical factor. See https://www.baeldung.com/ahead-of-time-compilation for an introduction to this topic. There is no way to convert a jar into a native shared library.

3

u/barcodez 5d ago

-5

u/KakashiHatake0085 5d ago

Graalvm doesn't work properly. It is not capable of cross compilation like c++, ruat and go. It doesn't support extending the toolchain or changing compiler etc with something that supports i.e. clang, mingw gcc etc.

→ More replies (1)

6

u/MenschenToaster 5d ago

Thats the neat part, you dont. Your .jar is the binary, making it extremely portable to everything that has java installed.

You can build wrappers (and there are plenty preexisting wrappers) that ship java with your jar file and make it seem like you just run a normal exe, whilst all that it does is java -jar file.jar

-5

u/KakashiHatake0085 5d ago

Then it's a dead end? No way to create dll/so/dylibs with java?

7

u/MenschenToaster 5d ago

Maybe graalvm can do something, but Java's usecase is beeing a extremely portable higher level language. Don't use the wrong tools for the job.

You can use java to interact with native libraries, but I dont really know a way to do it the other way around

6

u/mikaball 5d ago

You want to use Java to create shared libraries to be used in other languages? Yhe, not a good use-case for Java.

5

u/vegan_antitheist 5d ago

java.exe is already compiled. You just use that. The jar files contain the bytecde that java executes. You can always deploy your application as a single package with all dependencies, including a JVM. Having a single executable file doesn't really make things easier.

3

u/bowbahdoe 5d ago edited 5d ago

There is one way, but currently it doesn't do everything you'd want.

Fundamentally you need to bundle your code + the JVM. A problem is that the JVM (currently) doesn't work as a self contained exe. It needs to be a folder of files. They are working on this, Google has done it internally for years, its just a slow moving project. (priorities at big companies are a bit silly)

What you can do is use a tool called jlink to bundle your code with the JVM. Think of it like making a special version of Java that comes with your code. It will be a folder, but you can "cross compile" this way so long as you have the "jmod" files for the platforms you want to cross compile to.

This is mechanically easy, but because so much of the Java world is built around "make big jar! share big jar!" the tooling is more than a bit annoying to set up/you won't find online tutorials suggesting it.

But if you go this route, eventually jlink will be able to output a single exe. This path won't have the same restrictions as graalvm. (which because it makes a single exe kinda breaks peoples brains. They wish it solved the problem in generality and not just for relatively specific use cases.)

There are other ways (jpackage, launch4j, etc.), but to my knowledge none let you easily cross-compile like you'd want.

But that is for exe's. For dlls its just not a thing that would make sense, at least yet. WASM is an interesting target, but the JVM is designed in such a way that it is a little weird to use it for that.

The way the JVM executes your code is first via a bytecode interpreter (think Python). Then if some code runs enough it "compiles" it at runtime to machine code. Then if it runs even more it will "compile" it further, putting in effort to optimize it. These are the C1/C2/C3 "just in time" compilers.

C1/C2/C3 are extremely platform specific. They will output machine code specific to your exact CPU architecture. So not just "intel x86," if your CPU has a niche instruction on that exact chip it can make use of it.

In WASM world that...makes less sense. You can compile the JDK with the interpreter only (OpenJDK Zero) which should make it really easy to cross compile to WASM, but there are other things in the base java libraries (like sockets) which won't work there. A product called CheerpJ tackles this specific problem, but mostly so old Java applets can keep running in modern browsers. It won't let you take your code and run a command to get a blob of wasm like Rust and C.

If nothing else, all of this could stand to be better communicated.

1

u/Kadabrium 4d ago

I got to the point where i could run jvm fully memory mapped with all the tls and stuff, but its windows ntdll version dependent

2

u/bowbahdoe 4d ago

Have you tried the OpenJDK zero builds? Also why were you trying to do that?

1

u/Kadabrium 4d ago

TLS mapping on windows is hello hell

1

u/awidesky 4d ago

If you "compiled" it into dll/exe, that kills whole purpose of Java.
The best thing of Java is "build once, run everywhere", you build a jar, deploy it, and every other people with JVM can run regardless of their OS.
When it's an exe, your program will not run on Linux, macOS, or even a few outdated Windows.
That is NOT a cross platform.
Also a jar file can be library or runnable application, so you don't build separate dll/so/a/dylibs stuff.

If you want your app to work where there's no JVM, you can embed the JVM inside of your package and ship as whole.
For packaged exe there's launch4j, for installer there's jpackager.

But let me ask; what's the actual problem you want to solve?
Why made you think it's a good idea to build separate dll/dylib/so/a/exe instead of using a single jar file?

1

u/Mindless-Resort-7548 4d ago

As others have said you've got the wrong frame of mind. Consider a truck/lorry (articulated/18 wheeler). The trailer is our JAR file, it's where the money is made and the bit the clients care about. The trailer can be hauled/pulled by various different tractors (the JRE) so long as they have the correct hitch. Most of the time we developers like this flexibility, we can connect our trailer (jar) to a Windows tractor, a Linux one, a lightweight special one, etc, without having to modify our payload (trailer/jar). The engine changes but we don't need to worry about it, the specialist (trucker/jre developer) does.

Now you can permanently attach your trailer to a fixed tractor (compile your Jar with a JRE - GraalVM, Mandrel, etc.). You get a startup speed increase (you don't need to find the trailer and hitch it) and it can be more lightweight (occupy a smaller space/turning circle) but once at highway speeds any benefit is negligible (maybe a to y but better fuel consumption [resource usage]) and if you need to change the environment you run (go off-road) you need to do some serious work to swap out the cab + engine, whereas our traditional separate trailer/cab would just unhitch and swap in a different tractor.

I've done GraalVM/Mandrel builds and maintain one for a quarkus native application still. It's "fine", smaller container image is nice, but there are lots of quirks to ensure that the "compiler" knows every JVM feature and class required (it's crawling is good but not 100% accurate). My team need to know more things for little gain and traditional debugging tools for java applications don't apply. Can't say I'd rush into doing it again over a normal jre swtup