Static Java produces a statically compiled native executable targeting fast startup and small footprint, both on disk and with low metadata overhead at runtime. InfoQ spoke to Dan Heidinga, principal software engineer at Red Hat and long-time contributor to Static Java work, to understand how far from broad adoption we really are.
His involvement with Static Java has grown out of recognizing the need for Java to evolve to meet the changing ecosystem driven by new cloud-related practices. Besides his current involvement with CRiU (checkpoint/restore in userspace) both in OpenJDK’s Project CRaC and OpenJ9’s CRiU and his contribution to OpenJ9 JVM, Java Lambdas, bringing Method Handles to Java and currently with Project Valhalla, he has a front row seat on the journey towards Static Java.
InfoQ: Hello, Dan. Thank you for taking the time to respond to a couple of questions for our readers. Can you please give us a brief introduction about yourself, stating your day-to-day responsibilities and your involvement with Static Java?
Dan Heidinga: I’m a long time JVM developer and Java user. My day-to-day responsibilities are working on the Hotspot JVM (also project lead for OpenJ9 that JVM as well) and to the qbicc project: an experimental static compiler for Java programs, which acts as your playground to try out different approaches to Static Java to help explore the full design space in preparation for OpenJDK’s Project Leyden.
I’m also actively involved in CRiU (checkpoint/restore in userspace) investigations in both OpenJDK’s Project CRaC and OpenJ9’s CRiU project as I see a lot of overlap between the needs of checkpoint/restore and Static Java.
InfoQ: What are the benefits of Static Java? What are the use cases best suited for it?
Heidinga: Static Java produces a statically compiled native executable targeting fast startup and small footprint, both on disk and with low metadata overhead at runtime. Even though the potential scenarios where it could be used are many, microservices, CLI applications and serverless deployments are top candidates.
It’s composed of a small number of capabilities:
- Natively compile all the Java code that composes your application.
- The ability to "close the world" and prevent additional classes from being loaded. This allows dead code elimination to remove unused methods and fields resulting in a smaller binary.
- The ability to initialise parts of the application at build time to allow further optimisation, and to avoid redundant work at subsequent startups.
The primary benefit is faster startup from a small, single executable deployment package. The faster startup comes from being able to avoid the dynamic behaviours of Java such as loading and verifying classes and resolving each field and method on first use. And from using build time initialisation to move operations - such as class initialisation - from runtime to build time.
The footprint improvements at runtime are most evident for applications with small heaps as otherwise, the heap size completely dominates the smaller amount of memory needed for the class metadata.
InfoQ: What is required of developers to migrate from Java’s classic "dynamic VM" model to Static Java?
Heidinga: Even though guides and tools are available, developers should expect to spend a fair bit of effort on working through the challenges to transform their application into a static one.
Static Java, as the name suggests, is much less dynamic than regular Java and so use of many of Java’s dynamic capabilities such as Reflection, MethodHandles, class loading, bytecode generation, and JVMTI agents, can lead to problems. A good place to start is GraalVM’s tracing agent to create the configuration files required to support runtime use of these dynamic features. One of the requirements of Static Java - that dynamic capabilities become more limited and need to be explicitly opted into at build time.
Picking a framework that uses Static Java (e.g., Quarkus, Micronaut) will allow you to take advantage of its benefits without the hurdles of adoption.
InfoQ: Is Static Java already used in production systems?
Heidinga: The early adopters use it in production, but mainly on greenfield projects or non-critical use cases to allow them to build confidence and knowledge. I expect that OpenJDK’s Project Leyden standardization of the model will help the adoption. Right now, Static Java, apart from the frameworks that have smoothed the adoption path, is still hard to get started with.
While I expect adoption to continue to grow as cloud practices continue to take over the industry, and as users become more cost conscious with their cloud deployments, the growth will be slow as there’s a lot of software that will never be able to adapt to the requirements of Static Java (and that’s OK!). Users that need its characteristics are just starting to realize how important these capabilities are to their deployments.
To really drive mainstream adoption, Java needs to become aware of the phase changes (build time vs runtime and checkpoint vs restore) and give developers tools to say what they mean inside the language. I think this is coming but, given the timeframes for existing OpenJDK projects, is likely more than a year away.
With the perpetual move towards cloud and the need for faster startup times and smaller footprints, Static Java is just on the beginning of its journey, according to Heidinga. But the implementation of Project Leyden might speed up its adoption. Nevertheless, at this stage he recommends experimenting with it, pointing to the experiments led by Andrew Dinn, distinguished engineer at Red Hat. Heidinga also maintains that it is hard to say how much progress Project Leyden had made since its approval in 2020, but:
Lots of investigation and exploration is happening in OpenJDK and surrounding communities, and hopefully we'll see this come together in Project Leyden in the near future.
Several projects have overlaps with Leyden’s problem space like from Project CRaC, especially regarding "how to expose different phases of the Java programming model." Also, the GraalVM community has continued to improve SubstrateVM during this time.
For those that run into insurmountable issues adopting Static Java, or just don’t want to adapt their existing dynamic design, there is still hope for faster startup: the CRiU-related efforts, such as Project CRaC, to explore another point on the spectrum between static and dynamic Java.