32-bit Java loses the main maintainer... and Vavr gains one – JVM Weekly vol. 93
Today we have a regular edition, with some very interesting news from the community and a Release Radar. Enjoy!
1. jSpecify with stable version 1.0 - standard for NonNull annotations in Java is ready
Kotlin is not the only JVM language with "built-in" support for non-nullability, but it has built its identity around this concept, which is why it is strongly associated with it and serves as a reference point. Nicolas Fränkel published last year an article [Null safety: Kotlin vs. Java, in which he attempted to compare how the approaches to the concept of Null differ between these two languages. As part of his analysis, he summarized the existing null-related annotations on the market and listed eight(!) different variants, having different packages and (worse) slightly different behaviors.
Looking at the above, I am incredibly pleased with the jSpecify initiative (also mentioned in Nicolas's article). Participating players are working on defining a standardized set of annotations for static analysis, and their first goal is those related to nulls (considering the above - very rightly). The project is led by Google, with companies such as VMWare, Microsoft, Oracle, and JetBrains, the creators of many of the mentioned annotations, participating, so they have the power to organize all this mess.
Why do I mention it right now? Because its version 1.0 has been released - announced by David P. Baker from Java and Kotlin Ecosystem Team at Google - introducing @Nullable
, @NonNull
, @NullMarked
, and @NullUnmarked
. The latter are especially interesting - Marked
indicates that the marked element and the code inside it are marked as not accepting null values: types are considered to exclude null unless otherwise specified with the @Nullable
annotation. Using this annotation eliminates the need for multiple @NonNull
applications in the code.
jSpecify is an action at the level of static analysis, but the topic of nullability is also touched "under the hood" in Project Valhalla. This aims to introduce Value Types (or whatever they are called in the current iteration). One obvious difference between "reference types" (those currently existing in Java) and "value types" is that the latter cannot accept null values. Unlike Kotlin, this feature is not easily expressible in the language itself. Therefore, I want to remind you that the Valhalla designers intend to introduce new "nullness" annotations for objects.
So, in the end, as a bonus, I give you a freshly published airhacks.fm podcast episode, where Adam Bien talks to Paul Sandoz about Valhalla. The discussion about nullability starts at ~25 minutes, but the whole episode is worth listening to - it's a good opportunity to refresh Valhalla. This is worth doing from time to time considering the project's complexity.
2. Who really uses JPMS?
I remember when at the level of JDK 1.8 (yes, I'm old), everyone was eagerly waiting for Project Jigsaw, which was supposed to introduce a true module system to Java, ready to save us all from the chaotic growth of monolithic applications. Introduced in Java 9, it promised modularity, encapsulation, and a clearer, more organized future where dependencies wouldn't clash like children fighting over the last cookie (I’m a father, trust me). JPMS was a knight in shining armor, at least that's what we thought... especially knowing the alternatives.
JPMS appeared and its use in the JDK itself gave us such cool effects as the new release cycle or preview features. But there was a catch: adoption problems outside the JDK. The main problem? Complexity (and now those using the mentioned OSGI smile with pity), especially compared to solutions WITHOUT modularity. "Why bother?" they said, "Spring Boot works well enough, thank you very much." And since Spring itself doesn't use JPMS (initially worked in Spring Framework 6.0, but postponed those plans), the carrot became less tasty compared to the stick.
So the community complained, grumbled, and mostly ignored JPMS. Finally, rumors circulated in the community that no one was using it and it became a joke at Java conferences. And thanks to the gods of Java, some good soul (darenkster from /r/java) had the audacity to say: "Check!" and actually prepared a list so that we would talk about specifics.
As can be seen, many libraries have managed to adopt Automatic-Module-Name in their manifests, although full adoption of modularization is progressing slowly but steadily. For example, recently many Apache Commons libraries have been undergoing modularization. The methodology of the study involved downloading the latest stable version of the libraries and checking the jar file for the presence of a module descriptor or an Automatic-Module-Name entry in the manifest. No beta or pre-release versions were considered.
And what are my conclusions? It's better than I thought, but support is rather poor. Many projects (like Guava, Mockito, or the mentioned Spring Boot) are still not modularized, but the presence of RxJava on the list pleasantly surprised me (does anyone still remember this project? Because I intend to remind you of it soon 😉).
Well, I hope the author will update everything, and I will check from time to time. Great job that invoked great discussion on Reddit.
3. 32-bit Java loses the main maintainer (and Vavr gains one)
Aleksey Shipilev is a well-known software engineer specializing in JVM performance and OpenJDK development. He works as a Principal Engineer at AWS, and he is one of the authors of the Java Microbenchmarking Harness (JMH), a tool for examining Java code performance. He is also the creator of JCStress, a toolset for testing concurrent code in Java. I first heard about him while reading Java Memory Model Pragmatics, which is one of my favorite texts (despite being de facto a collection of slides) about Java ever. Seriously, a great thing, if you don't know it, read it and come back here after the 2-3 hours needed to delve into it.
Are you back? If so, Aleksey Shipilev had yet another role in the community: he was also the current maintainer of the 32-bit Java port for the x86 architecture. "Was" is the keyword here.
At the beginning of July, Aleksey announced that he is resigning from this role. This results from his belief that the costs of maintaining this port outweigh the benefits, and new features such as Loom or FFM are difficult to implement. Shipilev noted that current support for 32-bit platforms is minimal, and most of the industry has moved to 64-bit systems.
Shipilev pointed out several benefits of maintaining the port, such as ensuring compatibility with old platforms and helping keep the code clean for other 32-bit ports. However, these benefits do not justify the high costs and time needed to maintain the port. He proposes replacing it with the Zero interpreter, which, although slower, requires fewer resources.
In the context of Java, "Zero" refers to an implementation of the Java Virtual Machine (JVM) designed to run without any specific platform optimizations, making it slower compared to more optimized JVM versions. The Zero implementation does not use advanced just-in-time (JIT) compilation techniques and other optimizations. However, it is useful in situations where portability and compatibility between different platforms are needed, and performance is not a critical factor.
If no one takes over the role of port maintainer by August 9, 2024, the port will become formally unmaintained. Shipilev suggested housekeeping tasks such as disabling 32-bit builds in GHA and introducing deprecation warnings in the build system. This is an interesting case, as the decision to abandon the port may set a precedent and signify changes in how the OpenJDK community approaches support for older architectures.
And while we are writing about losing a maintainer here, I'll leave you with a note of optimism:
Vavr, a project we wrote about having recently lost its maintainer, is being revived under new leadership. Recently we wrote that its creator Daniel Dietrich decided to withdraw and was looking for a successor, and this weekend it was finally announced that it would be Grzegorz Piwowarek, Founding Engineer at Quesma, well-known in the Polish (and broader) Java community. His first goal is to release the long-promised version 1.0. Congratulations Grzesiek! I still remember your old talks about Vavr and I'm glad that my compatriot will develop the project - it is in very good hands.
4. Release Radar
Gradle 8.9
The main features of the new version Gradle 8.9 are improved error and warning reports, particularly regarding dependency management issues and configuration cache failures. This update makes it easier to understand and resolve problems in the build process, as messages for typical dependency variant issues now include clear suggestions for adding necessary attributes to resolve ambiguities or suggest appropriate values to resolve conflicts, offering clearer guidance.
In the context of IDE integration, Gradle has improved the reporting of compilation failures through the new Problems API, allowing IDEs to access detailed information about build problems. This improves the accuracy of error representation in popular IDEs, eliminating the need to parse compiler output text. Gradle also introduces detailed information about changes in files that invalidate the configuration cache. The console now indicates whether a file has been deleted or replaced, helping users understand why the cache cannot be reused.
Other significant updates include a detailed JVM Daemon information report, providing transparency about JVM configurations used by Gradle after running the gradle --version
command. Additionally, Gradle offers better control of parallelism in TestNG tests, supporting the configuration of suite ThreadPoolSize
, improving the management of parallel test execution. Other new features and improvements can be found in the release notes.
Graal Development Kit for Micronaut 4.5
First, a reminder: Graal Development Kit (GDK), previously known as Graal Cloud Native (GCN), is a version of the Micronaut framework developed by Oracle, offering a set of modules that simplify cloud application development, designed for ahead-of-time compilation using GraalVM Native Image, and fully supported by Oracle. GDK modules provide platform-independent APIs and libraries for several core cloud services, covering Oracle Cloud Infrastructure (OCI), Amazon Web Services (AWS), and Google Cloud Platform (GCP), with support for Microsoft Azure coming soon.
Graal Development Kit for Micronaut 4.5, announced by Sachin Pikle brings full support for Micronaut 4.5.0 (anyone surprised?). This version completes the renaming process of the project to GDK. All artifacts, including the bill of materials, launcher, CLI, IDE extensions, modules, guides, and code examples, have been renamed from GCN to GDK. The mentioned update to Micronaut brings improvements and fixes to several modules. The new version also includes a guide on Serverless OCI Functions and updates to GDK tools, including a new OCI Config Policy tool that facilitates working with Oracle Cloud. Other new features and improvements can be found in the release notes.
Mappie
And now I have a real curiosity. Mappie is a Kotlin compiler plugin that generates code simplifying the creation of object mapping code. Mappie generates all code at compile-time, allowing for quick mapping without the need for runtime reflection. It can generate mappers for objects and enums, aiming for ease of use, inferring as many mappings as possible ("by default"), and maintaining a consistent API and performance at the level of manually written mapping code.
Mappie is designed to be simple to use, supporting both implicit and explicit mappings. The plugin offers a consistent API and strives to provide the same runtime performance as manually written mapping code. The example code shows how Mappie can be used to map data from the Person
class to PersonDto
:
data class Person(
val firstname: String,
val age: Int,
val gender: Gender,
)
data class PersonDto(
val name: String,
val age: Int,
val gender: GenderDto,
)
object PersonMapper : ObjectMappie<Person, PersonDto>() {
override fun map(from: Person) = mapping {
to::name fromProperty from::firstname
}
}
In the above code, PersonMapper
defines the mapping rules between the respective objects and enums. We can then use PersonMapper
by calling the map
, mapList
, or mapSet
function to perform object mapping in the application.
The whole thing looks like a very useful small functionality, I will be following its development.
1JPM
1 Java Project Manager (1JPM) is an alternative to Maven/Gradle with a unique approach. Instead of using XML files (Maven) or Groovy (Gradle), the configuration file is written in Java itself. To build a project, simply download the JPM.java file to the project, open the terminal, and run the command java JPM.java jar
(or javac JPM.java && java -cp . JPM jar
for Java 8 to 10). The jar
command compiles and creates a JAR file from the project code. There is also an option to include dependencies - fatJar
. 1JPM works similarly to Gradle, but everything in 1JPM is a plugin, including all tasks. External plugins can be added simply by including their Java code in the ThirdPartyPlugins
class.
The main advantages of a single file are the ease of installation by drag and drop, direct access to the 1JPM source, and access to IDE auto-completion features when JPM.java
is in the project's root directory. You can also add JPM.java
to the ./src/main/java
directory, allowing the entire project easy access to data from the configuration file.
The 1JPM project is in early access/beta and does not contain all the functionality of other build tools like Maven and Gradle but provides basic and most commonly used features. For now, developing plugins is difficult because external dependencies cannot be used. However, the project is developing and we will see, maybe it will gain enough traction to become something more than a niche player.