45 ms·
Java Hello World, LLVM Edition
- jakozaur 11mo agoLLVM IR is quite fun to play with from many programming languages. The Java example is rather educational, but there are several practical example,s such as in Go Lang: https://github.com/llir/llvm https://github.com/llir/llvm
- znpy 11mo ago500 internal server error…
- zkmon 11mo agoWhat's wrong with using the standard JDK for Java code?
- throwaway150 11mo agoNothing wrong with it. Why would you assume the author is in anyway hinting that there's something wrong with using the standard JDK for Java code?
- zkmon 11mo agoOk. Let me ask differently. Why would I download and use LLVM for working with java code? Which usecases favor this?
- drzaiusx11 11mo agoThis is interop glue to cross language boundaries in the JVM without the problems that come with JNI. The natural goal/use-case being that you can call pre-existing code in other languages that target LLVM IR.
- TazeTSchnitzel 11mo agoThat's not what the article is about.
- connicpu 11mo agoThe article is presenting something different entirely. This is the precursor to what it would take to create a compiler written in java that produces native code.
- mands 11mo agoIt's more an fun educational overview of the new FFM API. I can't think of many actual use-cases where you'd want to use the LLVM JIT over those built-in to HotSpot. Interfacing with existing LLVM-based systems, writing a very tight inner loop using LLVM where you absolutely need LLVM-like performance, or creating a compiler that targets LLVM using Java would be the main "real-world" use-cases.
- almostgotcaught 11mo ago"why would I use a frying pan when I can use a flashlight" The two things have nothing to do with each other.
- kachapopopow 11mo agoLLVM is such an amazing piece of software, the amount of uses for it are unlimited especially when it comes to obfuscation. The IR is also really fun for compiling bytecode to native code since it's pretty trivial to translate it into IR (opposite of what is done in this article)
- troymc 11mo agoI made a poster showing how one might write a Hello World program in 39 different programming languages, and even different versions of some common languages like Java: https://troymcconaghy.blog/2025/01/13/39-hello-world-programs/ https://troymcconaghy.blog/2025/01/13/39-hello-world-program...
- throwaway150 11mo agoCool poster! If you don't mind me asking, would you share what tools you use to create this poster? You've got syntax highlighting going on there too. What did you use for that?
- iTokio 11mo agoYou just have to read his blog, it is short and he answered everything. > he used python and xelatex > https://github.com/ttmc/hello-world-ways https://github.com/ttmc/hello-world-ways
- troymc 11mo agoYep, and for syntax highlighting, I used the minted package [1]. Internally, minted uses the Pygments library [2]. [1] https://ctan.org/pkg/minted https://ctan.org/pkg/minted [2] https://pygments.org/ https://pygments.org/
- throwaway150 11mo agoThanks!
- pron 11mo agoNice, but as of JDK 25 (the preview JEP 445 has become the permanent JEP 512), the canonical Hello World in Java is: void main() { IO.println("Hello World"); }
- troymc 11mo ago
- Octoth0rpe 11mo agoI've been playing with a very basic compiler for a language that looks a bit like go -> llvm ir, but I'm finding myself constantly revising my AST implementation as I progressively add more things that it needs to represent. Is anyone aware of any kind of vaguely standardized AST implementation used by more than one project? I've been searching this morning for one and am coming up empty. My thinking is that if I can find some reasonably widely used implementation, then hopefully that implementation has thought out lots of the corner cases that I haven't gotten to yet.
- znkr 11mo agoLISP ;-)
- xnacly 11mo agoThis, lisp is perfect for representing arbitrary data, nesting is just another sexpr, easy to produce, easy to parse and easy to debug / reason about
- pjmlp 11mo agoWhen I did my degree, the years prior to mine had some flexibility choosing the implementation language for compilers class. Lisp and Prolog were forbidden due to how easy the whole exercise would be.
- Octoth0rpe 11mo agoI can appreciate this answer, but I don't think it's really what I'm asking. I think I'm more looking for some kind of standardized struct definition that translates easily to llvm IR and is flexible enough for a wide variety of languages to target. Something like this: https://gist.github.com/thomaswp/8c8ef19bd5203ce8b6cd4d6df5e3db44 https://gist.github.com/thomaswp/8c8ef19bd5203ce8b6cd4d6df5e... (Which doesn't meet my criteria because AFAICT isn't used by anything, but is reasonably close to what I want) or this: https://docs.rs/sap-ast/latest/src/ast/lib.rs.html#1-83 https://docs.rs/sap-ast/latest/src/ast/lib.rs.html#1-83 (which seems specific to SAP, I would like something more general)
- rendaw 11mo agoSelf plug, I put together this reference/example before+after (high and corresponding intermediate/low level) example gallery for for a couple languages: https://andrewbaxter.github.io/semicompiled/ https://andrewbaxter.github.io/semicompiled/ https://github.com/andrewbaxter/semicompiled?tab=readme-ov-file https://github.com/andrewbaxter/semicompiled?tab=readme-ov-f... I was using it while dabbling on compiler stuff, it was useful to have a set of concise compilation examples. I haven't touched it much lately, unfortunately, and I added the eBPF because the target was there but had no way to validate it (standalone eBPF validator where?) so I think it's probably somewhat wrong... or invalid at least, maybe that's a separate concern for people who would want this.
- tuhgdetzhh 11mo agoI'm always a bit shocked how casual people people wget and execute shell scripts as part of their install process. This is the equivalent of giving an author of a website remote code execution (RCE) on your computer. I get the idea that you can download the script first and carefully read it, but I think that 99% of people won't.
- balder1991 11mo agoEven assuming it’s not malicious, the script can mess up your environment configuration.
- exe34 11mo agoI'm so thankful for nixos for making it hard for me to give in to that temptation. you always think "oh just this once". but with nixos I either have to do it right or not bother.
- hombre_fatal 11mo agoNixOS gives you a place to configure things in a reproducible way, but it doesn’t require you do it.
- tombert 11mo agoIt sort of does actually, at least if you don't have nix-ld enabled. A lot of programs simply won't start if they're not static-linked, and so a lot of the time if you download a third-party script, or try to install it when the `curl somesite.blah | sh`, it actually will not work. Moreover, it also is likely that it won't be properly linked in your path unless you do it thr right way.
- exe34 11mo ago$ ./Downloads/tmp/xpack-riscv-none-elf-gcc-15.2.0-1/bin/riscv-none-elf-cpp Could not start dynamically linked executable: ./Downloads/tmp/xpack-riscv-none-elf-gcc-15.2.0-1/bin/riscv-none-elf-cpp NixOS cannot run dynamically linked executables intended for generic linux environments out of the box. For more information, see: https://nix.dev/permalink/stub-ld https://nix.dev/permalink/stub-ld You have to go out of your way to make something like that run in an fhs env. By that point, you've had enough time to think, even with ADHD.
- mands 11mo agoNice read up of the new FFM API. Recently saw a new FFM-based zero-copy transport and RPC framework using io_uring at https://www.mvp.express/ https://www.mvp.express/ An interesting time to be in the Java/JVM ecosystem, meanwhile, back to my Spring Boot app...tho least we're on Java 25
- pron 11mo agoTangential: The --enable-native-access option mentioned in the article is part of a large effort we call "Integrity by Default"[1]. The idea is that a library module can violate invariants established by another module (e.g. access to private fields and methods, mutation of final fields etc.) requires approval by the application, so that a library will not be able to have a global effect on the application without its knowledge, and the correctness of each module could be verfied in isolation. Now, --enable-native-access is also required to use JNI, but JNI can violate the integrity of Java invariants in a much more extensive way than FFM can. For example, JNI gives native code access to private fields of classes in arbitrary modules, while FFM does not. The only invariant FFM can break is freedom from undefined behaviour in the C sense. This is dangerous, but not nearly as dangerous as what JNI can do. For the time being, we decided to enable both FFM and JNI with the same flag, but, given how more dangerous JNI is, in the future we may introduce a more fine-grained flag that would allow the use of FFM but not of JNI. [1]: https://openjdk.org/jeps/8305968 https://openjdk.org/jeps/8305968
- tadfisher 11mo agoWhere does the "final means final" effort fit in? Can the JVM prevent modification of final fields via JNI, or is --enable-native-access also going to require (or imply) the flag which enables setAccessible() and friends?
- pron 11mo agoAh, that's a great question, and the answer is in the JEP (https://openjdk.org/jeps/500#Mutating-final-fields-from-native-code https://openjdk.org/jeps/500#Mutating-final-fields-from-nati...). When running with -Xcheck:jni, you'll get a warning when trying to mutate a final field with JNI. Now, enabling this check by default without harming JNI performance proved to be too much of an effort. However, mutating final fields with JNI even today can already lead to undefined behaviour, including horrible miscompilation, where different Java methods can read different values of the field, for final fields that the JVM already trusts to be immutable, such as static finals, record components, or a few other cases (indeed, there are non-final fields that the JVM trusts to be assigned only once, and mutating those with JNI is also undefined behaviour). As the compiler starts trusting more final fields after this change, mutating almost all final fields will lead to undefined behaviour. Then again, using JNI can lead to undefined behaviour in many ways. So to make sure your JNI code isn't mutating finals, test with -Xcheck:jni (as of JDK 26).
- namegulf 11mo agoWondering the benefits and how is this different from using GraalVM to build native images? For eg. we could use Spring + Graal VM and get the application into native binaries without worrying too much about the low level stuff. What are we missing?
- gavinray 11mo agoThis article specifically discusses calling external C ABI libraries via the FFM API. GraalVM is for compiling JVM bytecode to native, architecture-specific binaries. FFM is like "[DllImport]" in .NET, or "extern" definitions in other languages. The article shows how to auto-generate JVM bindings from C headers, and then allocate managed memory + interact with externally linked libs via the FFM API passing along said managed memory.
- fniephaus 11mo agoBTW: We (the GraalVM team) maintain a full-blown LLVM bitcode runtime that can be embedded in Spring or any other JVM application and compiled to native: https://github.com/oracle/graal/tree/master/sulong https://github.com/oracle/graal/tree/master/sulong
- gavinray 11mo agoMay as well throw the Native Image C API for FFM-like capabilities out there too https://www.graalvm.org/latest/reference-manual/native-image/native-code-interoperability/JNIInvocationAPI/ https://www.graalvm.org/latest/reference-manual/native-image... One of the neatest things I've been able to do is compile a .dll library "plugin" for an application which loads plug-ins by invoking a special exported symbol name like "int plugin_main()" using GraalVM and @CEntryPoint The entrypoint function starts a Graal isolate via annotation params and no native code was needed
- namegulf 11mo agoDon't we have JNI for that?
- 11mo ago