6. February 2024 By Merlin Bögershausen
Hidden Heros in Java 21
The Java language and JDK ecosystem are full of hidden gems. In order to find them, you have to take a closer look at different JDK Enhancement Proposals (JEPs). In this blog post, I will take you on a journey of discovery where you will learn about code snippets in javadoc and find out how to make an application start more quickly with the help of AppCDS.
Java snippets in javadoc
In most cases, we develop programs that also have to be maintained for years to come. These require high-quality documentation, especially if the programs are to be used again in other contexts. To meet this need, the javadoc tool, which allows you to convert comments in the source code into searchable HTML interface documentation, was introduced in the first version of the JDK,.
In technical documents like this, it makes sense to roughly outline the intended use of the interface. The @code tag, which highlights the source code, is often used for this purpose. Unfortunately, this tag is not well suited for multi-line code passages. This has changed since Java 18 thanks to the new @snippet tag. The following listing demonstrates how the @snippet tag can be used for the VATCalculator class. The formatting is retained in the finished documentation. Multi-line comments are not permitted, however.
/**
* Calculation of VAT for a private customer when making a purchase of 1055
* {@snippet :
* var customer = new private_customer("Merlin", "");
* var value = 1055d;
* // ...
* var VAT = VATCalculator.PlainOOP.calculateVAT(customer, value);
* }
*/
Unfortunately, the code cannot be tested and may contain syntax errors. To solve this problem, parts of Java files can be integrated using the @snippet tag. Beyond that, transformations can also be defined within the underlying files to improve readability and relevance. Examples of this include:
- Replacing one text with another one
- Highlighting through the use of regex expressions
- Defining areas
For a full list, please refer to JEP 412 [1]. The following listing shows a full example of how a snippet from the snippet-files/SwitchExpressionsSnippets.java file can be integrated into the javadoc document of another class.
/ File: VATCalculator.java'
/**
* Calculation of VAT for a private customer when making a purchase of 1055
*@snippet file="SwitchExpressionsSnippets.java" region="example"}
*/
// File: snippet-files/SwitchExpressionsSnippets.java
class Snippets {
void snippet01() {
// @start region="example"
// @replace region="replace" regex='(= new.*;)|(= [0-9]*d;)' replacement="= ..."
// @highlight region="highlight" regex=”\bVATCalculator\b"
var customer = new private customer("Merlin", "test@other.de"); // @replace regex="var" replacement="customer"
var value = 1055d; // @replace regex="var" replacement="double"
/* .. */
var VAT = VATCalculator.PlainOOP.calculateVAT(customer, value); // @link substring=”PlainOOP.calculateVAT" target="VATCalculatorPlainOOP#calculateVAT"
// @end @end @end
}
}
I have replaced and highlighted certain areas in this example. The final output provides a good overview of how it is used and can be tested at regular intervals. This lesser-known but powerful tool in the Java ecosystem makes it very easy to add examples to the clearly structured UI documentation.
Dynamic App Class Data Sharing
The Java Virtual Machine (JVM) was developed at a time when the peak performance of applications that were in long-term operation was much more relevant than in today’s microservice-driven world. Some of the best heuristics at the time now have a negative impact on the performance of microservices. To give one example, they are the reason for the comparatively poor start performance of the JVM.
To improve the start performance of a JVM application, you will need to speed up the initial classloading process. In this step in the JVM start process, information about the classes used is loaded and analysed. The JVM has been extended to include class data sharing (CDS) to avoid having to repeat this step. With it, the information collected from classloading is persisted in a CDS archive and can be used again at a later time.
The JVM already includes an archive that contains the Java standard library. This archive is available as a ‘classes.jsa’ file in some of the supplied JVMs and was created with a JVM configured for G1 with a 128 MB heap space. A separate archive will have to be created if a different heap configuration is needed or additional classes are required. Application Class-Data Sharing, also known as AppCDS for short, can be used to transfer the classpath of an application to the CDS archives that were generated, making it possible to significantly reduce the JVM’s start time. If you run the same application on multiple JVMs or restart it frequently, the time required to start the JVMs will be much lower.
You will need information regarding the classes that are used in an application at runtime in order to create a CDS archive. This information can be retrieved by the JVM itself:
- A training run in which the application is launched with additional parameters.
- 1. The application is launched with -Xshare:off -XX:DumpLoadedClassList=clazzes.cls, and a list of the loaded classes is generated as the clazzes.cls file.
- 2. A CDS archive of the application is created in the file ‘MyApp.jsa’ using -Xshare:dump -XX:SharedArchiveFile=MyApp.jsa -XX:SharedClassListFile=clazzes.cls -cp app.jar’.
- A CDS archive in production can be defined using JCMD.
- 1. The application must be started with the parameter -XX: RecordDynamicDumpInfo.
- 2. The command jcmd <pid> VM.cds dynamic_dump my_dynamic_archive.jsa d creates a ‘VM.cds’ CDS archive for the specified PID.
- The JVM can automatically generate a CDS archive after it is closed. To this end, the parameter -XX:ArchiveClassesAtExit=MyApp.jsa is specified at start.
To start an application with the generated CDS archive and be able to make use of the collected information, the JVM must be launched with the parameter -XX:SharedArchiveFile=MyApp.jsa. These few additional steps can significantly improve the start-up performance of a JVM application. At the same time, you can also achieve high peak performance earlier on. By making these changes, the JVM is also well suited for use in environments in which the JVM has to be restarted.
Summary
In this blog post, I have introduced two lesser-known tools from the Java ecosystem that can be used to develop fast-starting, resource-saving applications with elegant, well-documented interfaces. Among the many other things I do, I give talks on this topic at conferences and write other posts for the adesso blog. If you have any questions or problems, I or one of our experts at adesso would be happy to assist you.
Would you like to learn more about exciting topics from the world of adesso? Then check out our latest blog posts.