Rust-written JVM and Bytecode Transpiler: A Masterclass in Learning-by-Doing - JVM Weekly vol. 51
Man is only a week on vacation, and we were inundated with interesting information that begs for a summary - especially Release Radar is exceptionally stuffed today.
1. Rust-written JVM and Bytecode Transpiler: A Masterclass in Learning-by-Doing
The idea that we learn best through practice is well-known. However, some take this to heart more strongly than others. For example, Andrea Bergia, Principal Software Engineer at lastminute.com, decided to learn how JVM works internally by writing a simplified implementation of it. In addition, Andrea did it.... in Rust.
The project, called rjvm, although it does not support some features such as generics, threads, reflection, annotations, I/O, or JIT compilation, the author has successfully implemented several non-trivial components, including control instructions, object and primitive creation, virtual and static method support, exceptions, a garbage collector, and the ability to load classes from external .jar files. And to round out an already impressive whole, Andrea has developed a set of tests to illustrate the operation of rjvm based on a real rt.jar file from OpenJDK 7.
The author shared his experiences as part of a two-part (at least for now) blog post I have written a JVM in Rust. Andrea states he is most proud of a working garbage collector implementation, even in a relatively simple version. According to his announcements, we can expect in future more publications exploring in-depth aspects of rjvm.
However, this is not the end of educational projects around JVM. Jtcpp is a tool created in Rust, converting Java bytecode to C++ native calls (now that's a real combo). This allows programs written in languages such as Java and Kotlin to be compiled into native instructions, which in some cases supposedly improves performance, although the results do not encourage production use (as the author reports that from his experiments you can expect from 3x speedup to 50x slowdown of programs). The whole thing itself is supposedly quite complete in terms of language features, but the implementation of the standard Java library in C++ is very limited - the implemented classes are String, Object, System, and PrintStream, making it suitable for creating simple algorithms and console applications only. Yet, this entire endeavor is an intriguing experiment. What spurred its creation? Simply the possibility of its existence. And therein lies its beauty.
Even though Rust is the talk of the town, it's equally important to acknowledge comparable efforts in different languages. Jacobin, a project available on GitHub, is a more-than-minimal implementation of the JVM specification for Java 17, entirely written in Go. Striving to run most class files and JARs and deliver similar results to OpenJDK-based JVMs, Jacobin emphasizes a cohesive, extensively commented codebase with a broad test suite for professionals seeking to better understand JVM operations. Key to its lightweight nature, it leverages Go's built-in memory management for garbage collection, thus requiring no additional GC code. As of February 2023, the testing process included a test code 231% the size of the production code with more than 400 tests. While it has yet to reach a stage for packaged releases, future plans include running the OpenJDK test suites against it.
2. Kotlina Roadmap update
The last time we saw each other, we focused on Kotlin only due o share amount of announcements... But it turned out it is still not all that JetBrains had for us. Since then, Roadmap has appeared. And while it doesn't bring anything revolutionary on its own, it's worth a look.
The document primarily focuses on pivotal projects like the K2 compiler - a major improvement to the Kotlin compiler mentioned in the previous edition. Its aim is to boost speed, unify the codebase, and introduce fresh language features. In addition, efforts are being made to enhance the Kotlin plugin for IntelliJ, promising quicker completion, highlighting, and searching, as well as more reliable code analysis due to the language's transition to K2. Another significant goal is the production launch of Kotlin Multiplatform, which will be realized by enhancing the stability and documentation of the toolchain and offering compatibility assurances. Other enhancements include a new Kotlin/Native memory manager, klib
compatibility, and the capability to export Kotlin code to Objective-C.
The aim is also to enhance the experience for Kotlin library authors by providing comprehensive documentation and tools for the configuration, development, and publication of libraries. On the other hand, daily language users are expected to receive benefits such as improved Kotlin compilation reports, a better experience with Kotlin scripts, and enhancements in .gradle.kts
. The library ecosystem will be enriched with releases like kotlinx-io
, a new I/O library modeled on Square's okio. Other advancements will include the stabilization of kotlinx-kover
(the Code Coverage tool) and kotlinx-metadata-jvm
(a library for reading Kotlin compiler metadata).
3. Release Radar
Today in a truly a lavish way!
Micronaut 4.0
Let's begin with undoubtedly the most significant release in recent weeks. Micronaut, the pioneer among a new generation of modern Java frameworks, has seen a substantial new update.
The newly released Micronaut Framework 4.0 discontinues support for Java versions preceding JDK 17. This allows it to update the API to utilize new language syntaxes, such as Java Records, Sealed Classes, Switch Expressions, Text Blocks, and Pattern Matching for instanceof. Furthermore, the new version of the Micronaut HTTP Client is built on the Java HTTP Client that was first introduced in JDK 11. The decision to discard support for older versions has also led to improved performance outcomes.
Graeme Rocher, the mind behind Micronaut and formerly Grails, has been working for Oracle for a few years. It's no surprise then that Oracle has been a significant contributor to the new release, thereby implying Rocher's involvement in both Micronaut and Helidon. This partnership has resulted in a substantial overhaul of Micronaut's integration with GraalVM, which now leverages GraalVM's shared metadata. This improvement simplifies the compilation of Micronaut applications that rely on third-party libraries using GraalVM Native Image. Furthermore, Micronaut Serialization has now become the default module, providing fast, secure, and non-reflection-based JSON serialization/deserialization APIs. Other notable enhancements encompass better cloud support, inclusive of Oracle Cloud, and an increasingly modular architecture. This allows microservices to become even more micro by eliminating unnecessary features, positively impacting the overall startup time. Micronaut has also introduced preliminary support for VirtualThreads.
In terms of dependencies, Micronaut 4.0 no longer depends directly on SnakeYAML and Micronaut Jackson Databind, which gives developers the choice of using Micronaut Serialization or Micronaut Jackson Databind. In addition, the upgrade of javax
packages to jakarta
packages has been completed.
Arrow 1.2
To Java programmers, Kotlin may appear to have a slight edge in functional programming, but it still trails behind Scala. Whether this is a disadvantage or an advantage is subjective, but Kotlin Arrow, a functional programming library, seeks to narrow this gap by providing data types, type classes, and extensions for convenience. Recently, its latest version, Arrow 1.20, has been launched.
This release brings several significant additions. The Typed errors module presents a fresh way of handling error types, providing an alternative to the formerly used computation blocks and Effect/EagerEffect
types. Additionally, the resilience
the module now incorporates support for the so-called Saga (who knows - knows). Everything is bundled together with a new webpage that also features updated documentation and examples.
Ahead of the Arrow 2.0 release, certain features and types slated for removal have been flagged as @Deprecated
. Arrow 1.2.x is geared towards laying the groundwork for the impending 2.0 release by refining the APIs and incorporating community feedback. The release of Arrow 2.0 is expected to align with the launch of Kotlin 2.0. This synchronization would help maintain binary compatibility (given that Arrow generates a substantial amount of international bytecode) and facilitate a smoother transition to newer Kotlin versions.
Semantic Kernel for Java
No problem, Mr. Microsoft. We recently had an edition focusing on LLMs in Java, but the company's latest contribution is so intriguing that it warrants a mention.
Semantic Kernel (SK) is an SDK designed to facilitate the integration of large AI language models (LLMs) with standard programming languages. SK's adaptable programming model amalgamates natural language, conventional code, and embedding-based memory.
Microsoft has released the first version of the Semantic Kernel for Java, a library that enables Java developers to seamlessly integrate AI services (like Azure OpenAI) into their applications, using a structure of so-called skills. In practice, it looks more or less like this:
public class MyAppSkills {
@DefineSKFunction(name = "redactPassword", description = "Redacts passwords from a message")
public String redactPassword(@SKFunctionInputAttribute String input) {
System.out.println("[redactPassword] Redacting passwords from input: " + input);
return input.replaceAll("password.*", "******");
}
}
(...)
Kernel kernel = SKBuilders.kernel().withKernelConfig(config).build(); kernel.importSkill(new MyAppSkills(), "MyAppSkills");
Developers can then use the library to create intelligent plans using so-called Planners, combining the ability to perform complex actions with generative artificial intelligence.
SequentialPlanner planner = new SequentialPlanner(kernel, null, null);
Plan plan = planner.createPlanAsync(
"For any input with passwords, redact the passwords and send redacted input to sysadmin@corp.net").block();
System.out.println(plan.toPlanString());
String message = "Password changed to password.db=123456abc";
String result = plan.invokeAsync(message).block().getResult();
System.out.println(" === Result of the plan === ");
System.out.println(result);
Semantic Kernel for Java alpha version 0.2.6-alpha is available from Maven Central. to help developers get started and understand the potential of Semantic Kernel for Java, a collection of examples has been made available.
Microsoft Build of OpenJDK – July 2023 Release
While we're discussing Microsoft, the company has also unveiled the monthly release of security patches and updates for Microsoft Build OpenJDK. I typically do not cover such updates, but this time, the noteworthy enhancement is the escape analysis fix. It has attained such stability that Microsoft has decided to include it by default. For those who are not compiler experts, escape analysis in Java is an optimization strategy that determines the potential for objects in a program to be allocated on the stack instead of the heap. This key mechanism further allows for additional optimizations such as object scalarization (converting objects into a set of individual variables - scalars) or the elimination of thread synchronization. This improvement is already being utilized in production systems at Microsoft and LinkedIn, indicating its stability. Nonetheless, if users experience performance regression, they can disable this feature using the -XX:-ReduceAllocationMerges
flag.
For those who might be concerned, this isn't just a specific enhancement for the Microsoft JDK Build. This modification has already been integrated into the OpenJDK code and is accessible in the early versions of JDK 22.
Spring Web Flow 3.0
Spring Web Flow is a module of the Spring Framework aimed at assisting developers in crafting web applications with intricate page transitions. It offers a framework to organize navigation regulations using a declarative model. This allows developers to determine the application's "flow" as the name suggests.
Spring Web Flow 3.0.0 was recently released. The new version focuses on compatibility with Spring Framework 6 and Jakarta EE, ensuring that users can take advantage of the latest updates and enhancements to those platforms. However, this update required the removal of Apache Tiles (a templating framework), which was not migrated to Jakarta EE. As a replacement, the booking-mvc
sample application now uses Thymeleaf Layouts.
Scala Metals 1.0
The Language Server Protocol (LSP) is an open-source protocol based on JSON-RPC that facilitates interaction between an IDE editor and a so-called language server - a tool that provides language-specific functions such as autocomplete, navigating to definitions or finding all references within a codebase. With LSP, a once-created language server can be used with many other tools, so you don't have to do the same work repeatedly.
Metals is a mature language server for Scala. Its development is a collaborative effort by many members of the Scala community, and the Metals team is confident that the tool is ready for production use, which it confirms with the release of version 1.0, code-named Silver. In addition to the core features offered by Language Server Protocol, Metals 1.0 boasts several additional ones, such as support for projects with multiple roots, the ability to run specific Scalafix rules, and better support for the Scala CLI.
Metals v1.0.0 supports the latest versions of Scala (Scala 3.3.0, Scala 2.12.18 and Scala 2.13.11).