Enhancing Productivity and Insight A Tour of JDK Tools Progress Beyond Java 17
AnaMariaMihalceanu1
270 views
55 slides
Oct 06, 2024
Slide 1 of 55
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
About This Presentation
As Java developers, staying at the forefront of technological advancements is vital to creating efficient and innovative applications. During this session, we will dive into the key changes that have taken place across essential JDK tools since the release of Java 17. From enhancements to javac to t...
As Java developers, staying at the forefront of technological advancements is vital to creating efficient and innovative applications. During this session, we will dive into the key changes that have taken place across essential JDK tools since the release of Java 17. From enhancements to javac to the powerful monitoring capabilities of JDK Flight Recorder (JFR) and JDK Mission Control (JMC), I’ll guide you through the key updates that matter in your daily developer journey.
Size: 3.18 MB
Language: en
Added: Oct 06, 2024
Slides: 55 pages
Slide Content
Enhancing Productivity and Insight
A Tour of JDK Tools Progress
Beyond Java 17
Hello! I am Ana
Goal
Learn about key enhancements on the JDK tools
since Java 17 so that you can efficiently code,
deploy and monitor your applications.
Source and Classfile Tools
Noticing Possible Lossy Conversions
public class Example {
public static void main(String[] args) {
long value = 5L;
long b = value + 0.1 * 3L;
}
}
// incompatible types: possible lossy conversion from double to long
public class Example {
public static void main(String[] args) {
long b = 5L;
b += 0.1 * 3L; // before JDK 20: no error
}
}
Warnings on Lossy Conversions
public class Example {
public static void main(String[] args) {
long b = 5L;
b += 0.1 * 3L;
}
}
$ javac Example.java -Xlint:[all|lossy-conversions} # since JDK 20
> Example.java:4: warning: [lossy-conversions] implicit cast from double to long in
> compound assignment is possibly lossy
> b += 0.1 * 3L;
^
[Warn compound assignment is possibly lossy —JDK-8244681]
Calling Overridable Methods in Constructors
public class Example {
public Example() {
System.out.println(this.hashCode());
}
public static void main(String[] args) {
new Example();
}
}
// Until JDK 21, javac says all good
Warnings About Possible this Escapes
public class Example {
public Example() {
System.out.println(this.hashCode());
}
public static void main(String[] args) {
new Example();
}
}
$ javac Example.java -Xlint:[all|this-escape] # since JDK 21
> Example.java 3: warning: [this-escape] possible 'this' escape before subclass is fully initialized
> System.out.println(this.hashCode());
^
[Add lint check for calling overridable methods from a constructor -JDK-8299995]
Compiling and Launching a Java Program
IDE
.java source file .class file Program running
javac java
Towards Enhanced Usability
// HelloWorld.java
class HelloWorld {
public static void main(String[] args) {
Helper.run();
}
}
// Helper.java
class Helper {
static void run() {
System.out.println("Hello, World!");
}
}
$ java HelloWorld.java
> Hello, World!
[Run a Java program supplied as multiple files - JEP 458 ㉒ ]
Bridge Code Execution
with Clear API Documentation
Goals for API Documentation
• Helps with product maintenance.
• Technical users can understand your APIs goals.
• Can increase awareness/adoption of your software.
• Third-party developers can start quickly by trying out API examples.
Words May Come Easy,
Yet Examples Require Extra Care.
Fragments of Source Code in Documentation
•Wrap code examples inside <pre> and {@code ...}.
•Automatically escape special characters with {@code ...}.
•No control over indentation.
•No code highlighting.
/**
* <p>Java class for user complex type.<p/>
* <p>The following schema fragment specifies the expected content for the User class.<p/>
* <pre> {@code
* <complexType name="user">
* <complexContent>
* <restriction base="{http://www.w3.org/2001/ XMLSchema}anyType">
* <sequence>
* <element name="id" type="{http://www.w3.org/2001/ XMLSchema}long" minOccurs="0"/>
* <element name="email" type="{http://www.w3.org/2001/ XMLSchema}string" minOccurs="0"/>
* <element name="firstName” type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
* <element name="lastName" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
* <element name="userName" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
* </sequence>
* </restriction>
* </complexContent>
* </complexType>
* }
* </pre>
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "user", propOrder = {"id", "email", "firstName", "lastName","userName”})
public class User {
/**
* <p>Java class for user complex type.<p/>
* <p>The following schema fragment specifies the expected content for the User class.<p/>
* <pre> {@code
* <complexType name="user">
* <complexContent>
* <restriction base="{http://www.w3.org/2001/ XMLSchema}anyType">
* <sequence>
* <element name="id" type="{http://www.w3.org/2001/ XMLSchema}long" minOccurs="0"/>
* <element name="email" type="{http://www.w3.org/2001/ XMLSchema}string" minOccurs="0"/>
* <element name="firstName” type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
* <element name="lastName" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
* <element name="userName" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
* </sequence>
* </restriction>
* </complexContent>
* </complexType>
* }
* </pre>
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "user", propOrder = {"id", "email", "firstName", "lastName","userName”})
public class User {
javadoc User.java
Elegant Inclusion of Code Examples
• JEP 413 introduced {@snippet ...} tag in JDK 18.
• A better presentation of the targeted code examples via regions.
• Control code via @highlight, @replace, @link tags and regions.
Example for Documenting a SOAP API resource
/**
* <p>Java class for user complex type.</p>
* <p>The following schema fragment specifies the expected content for the User class.</p>
* {@snippet lang=xml :
* //@start region="type"
* <complexType name="user">
* <complexContent>
* <restriction base="{http://www.w3.org/2001/ XMLSchema}anyType">
* <sequence>
* //@highlight region="element" regex="name=. \w+."
* <element name="id" type="{http://www.w3.org/2001/ XMLSchema}long" minOccurs="0"/>
* <element name="email" type="{http://www.w3.org/2001/ XMLSchema}string" minOccurs="0"/>
* <element name="firstName" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
* <element name="lastName" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
* <element name="userName" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
* //@end region="element"
* </sequence>
* </restriction>
* </complexContent>
* </complexType>
* //@end region="type"
* }
*/
Example for Documenting a SOAP API resource
•/**
* <p>Java class for user complex type.</p>
* <p>The following schema fragment specifies the expected content for the User class.</p>
* {@snippet lang=xml :
* //@start region="type"
* <complexType name="user">
* <complexContent>
* <restriction base="{http://www.w3.org/2001/ XMLSchema}anyType">
* <sequence>
* //@highlight region="element" regex="name=. \w+."
* <element name="id" type="{http://www.w3.org/2001/ XMLSchema}long" minOccurs="0"/>
* <element name="email" type="{http://www.w3.org/2001/ XMLSchema}string" minOccurs="0"/>
* <element name="firstName" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
* <element name="lastName" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
* <element name="userName" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
* //@end region="element"
* </sequence>
* </restriction>
* </complexContent>
* </complexType>
* //@end region="type"
* }
*/
Regenerated HTML Page
javadoc User.java
Extract the Snippet Content to Separate Files
$ javadoc --snippet-path ./src/xml User.java
/**
* <p>Java class for user complex type.
* </p>
* <p>The following schema fragment specifies the expected content for the User class.
* </p>
* {@snippet file="user.xml" lang=xml}
*
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "user", propOrder = {"id", "email", "firstName", "lastName","userName”})
public class User {
Markdown in Documentation Comments
• JDK 23 introduces Markdown in Java documentation comments.
• Enjoy a concise syntax for common constructs.
• Reduce the dependence on HTML markup and JavaDoc tags.
• Keep enabling the use of specialized tags when not available in Markdown.
• A new form of documentation comment: ///
Benefit of Interactive Documentation
• Since JDK 18, configure the --add-script <file> option of javadoc.
$ cat interact.js
> alert("Okey-dokey! Get ready to move your fingers!");
$ javadoc --add-script interact.js User.java
•Enjoy markdown documentation with syntax highlighting.
$ javadoc --add-script prism.js --add-stylesheet prism.css
[Add scripts to generated documentation—JDK-8275786]
Development and Deployment Tools
Fast Prototyping Java Code with jshell
•Quickly try, debug and learn Java and its APIs.
•Experiment with Java by bypassing the compile stage.
•Get immediate feedback on your code.
•Exposes a programmatic API.
Highlighting Deprecated Elements
jshell> var check = new Boolean("true");
| Warning:
| Boolean(java.lang.String) in java.lang.Boolean has been deprecated and marked for removal
| var check = new Boolean("true");
| ^-----------------^
check ==> true
jshell> Short number = new Short("12345");
| Warning:
| Short(java.lang.String) in java.lang.Short has been deprecated and marked for removal
| Short number = new Short("12345");
| ^----------------^
number ==> 12345
[jshell outlines deprecated elements ⑲—JDK-8274148]
JDK Tools Access in jshell
Predefined scriptsDescription
DEFAULT Loads the default entries, which are commonly used as imports.
JAVASE Imports all Java SE packages.
PRINTING Definesprint,println, andprintfasjshellmethods for use within the
tool.
TOOLING㉑ Definesjavac,jar, and other methods for running JDK tools via their
command-line interface within thejshelltool.
• jshell supports loading scripts with any valid code snippets or jshell commands.
• Scripts can be local files or one of the predefined scripts.
Load and Use TOOLING Script
• Load TOOLING when you start jshell
$ jshell TOOLING
• Open TOLLING inside a jshell session
jshell> /open TOOLING
• Check available tools
jshell> tools()
• Execute a tool command in a jshell session
jshell> run("javac", "-version")
javac 23
[JDK tools in jshell ㉑—JDK-8306560]
Easy Local Prototyping, Testing or
Debugging in a Client-Server Setup?
Overview of jwebserver
•Provides a minimal HTTP server, serving only static files.
•Supports only HTTP/1.1.
•Only HEAD and GET requests are served.
•Other requests receive 501-Not Implemented or 405-Not Allowedresponse.
Use Cases for jwebserver (1)
•Web development testing, to simulate locally a client-server setup.
$ jwebserver
> Binding to loopback by default. For all interfaces use " -b 0.0.0.0" > or "-b ::".
> Serving /cwd and subdirectories on 127.0.0.1 port 8000
> URL: http://127.0.0.1:8000/
•Use static files as API stubs for web-service prototyping or application testing.
$ jwebserver -p 9000
> Binding to loopback by default. For all interfaces use " -b 0.0.0.0" or "-b ::".
> Serving /example and subdirectories on 127.0.0.1 port 9000
> URL http://127.0.0.1:9000/
> 127.0.0.1 -- [09/Feb/2024:3:02:05 +0200] "GET /api/a1.json HTTP/1.1" 200
> 127.0.0.1 -- [09/Feb/2024:3:02:06 +0200] "GET /api/a2.json HTTP/1.1" 200
Use Cases for jwebserver (2)
•Great for learning purposes.
•Search a directory on a remote server from your local machine.
$ jwebserver -b 0.0.0.0
> Serving /work and subdirectories on 0.0.0.0 (all interfaces) port 8000
> URL http://192.168.178.41:8000/
•Can also be started via java launcher
$ java -m jdk.httpserver
> Binding to loopback by default. For all interfaces use " -b 0.0.0.0" or "-b ::".
> Serving /example and subdirectories on 127.0.0.1 port 8000
> URL http://127.0.0.1:8000/
Working with the Simple Web Server API
TheSimpleFileServerclass supports the creation of:
•file server
•file handler
•an output filter
$ jshell
jshell> var server = SimpleFileServer.createFileServer(new InetSocketAddress(8080),
...> Path.of("/some/path"), OutputLevel.VERBOSE);
jshell> server.start()
Packaging self-contained
Java applications
Introduction to jpackage
•Packages self-contained Java applications.
•Prior JDK 19, installing a jpackaged app was system-wide.
•For modular applications,jpackagewill automatically runjlinkand generate a
runtime with the modules needed.
A Closer Look to Running jpackage
jpackage --input target/ --name JDemoApp
--main-jar JDemoApp.jar
--main-class org.example.JDemoApp
--type app-image
JDemoApp.app/
Contents/
Info.plist
MacOS/ //Application launchers
JDemoApp
Resources/ // Icons, etc.
app/
JDemoApp.cfg //Configuration info, made by jpackage
JDemoApp.jar //JAR file, copied from --input directory
runtime/ //Java runtime image
Installation of a Packaged Application
After JDK 19, the application launcher will look up the .cfg file in user-specific folders.
Linux
~/.local/${PACKAGE_NAME}
~/.${PACKAGE_NAME}
macOS
~/Library/Application Support/${PACKAGE_NAME}
Windows
%LocalAppData%\%PACKAGE_NAME%
%AppData%\%PACKAGE_NAME%
# ${PACKAGE_NAME} and %PACKAGE_NAME% refer to jpackaged application name.
Installation of a Jpackaged Application
After JDK 19, application launcher will look up the .cfg file:
• In user-specific directories.
• From the installation directory if .cfg file is not found.
• From the application image directory if the application launcher is executed from
that location.
Security Tools
New –version Option for keytool &jarsigner
# Since JDK 18, you can check the version of keytool and jarsigner.
$ keytool -help -version
> keytool -version [OPTION]...
> Prints the program version
> Options:
> Use "keytool -?, -h, or --help" for this help message
$ keytool -version & jarsigner -version
> [1] 83711 jarsigner 21 keytool 21
Updated Options for keytool
# keytoolwarns you when using weak password-based encryption algorithms via -genseckeyand
-importpassoptions
$ keytool -genseckey -alias secret -keypass changeit \
-keyalg RC4 -keysize 128 -keystore example.p12 \
-storepass changeit -storetype PKCS12 -v
> Generated 128-bit ARCFOUR secret key [Storing example.p12]
> Warning: The generated secret key uses the ARCFOUR algorithm which is considered a
security risk.
[keytool warns about weak PBE algorithms ㉑—JDK-8286907]
Updated Options for jarsigner
•Specify the classpath for providers via –providerPath
$ jarsigner -keystore keystore -storetype CUSTOMKS \
-providerPath /path/to/test.myks \
-providerClass my.custom.AnotherProvider
signed.jar mykey
•The options-altsignerand-altsignerpathhave been removed in JDK 21.
[Add -providerPath option to jarsigner ⑲—JDK-8281175]
Profiling and Runtime Management
Tools
Technology Overview
Technology Goal
JDK Flight Recorder (JFR)Collects diagnostic and profiling data about a
running Java application.
JFR Event Streaming APIAPI for the continuous consumption of JFR data
on disk.
JDK Mission Control (JMC)A set of tools for managing, monitoring, profiling,
and troubleshooting Java applications.
The jfr scrub Command
•Filter data from the specified recording file.
jfr scrub [filters] [recording-file] [output-file]
•Supply which events to include.
jfr scrub --include-events jdk.FileRead,jdk.FileWrite
•Include a category and exclude events.
jfr scrub --include-categories GC* --exclude-events jdk.GCLocker
•Remove all events by category: jfr scrub --exclude-categories GC*
[JFR scrub recording data—JDK-8281175]
The jfr view Command
•Displays aggregated event data without the need to dump a recording file.
•Start JFR a recording via -XX:StartFlightRecording or jcmd.
$ java -XX:StartFlightRecording -jar imaging.jar
• Use the PID or jar name in the command.
• UsejpsJDK tool to list all running Java processes (PID).
[JFR view command㉑—JDK-8306704 ]
JMC Graph Views Updates
•JMC 9 requires JDK 17 or later!
•Since JMC 8.3, JMC Graph View was updated to allow limiting the number of
nodes displayed.
•Focus on most impactful nodes by using smart pruning.
•Example : focus on how often a specific method is ran based on sampling.
Open JFR Recording -> Method Profiling -> Select method -> Graph View
JMC Flame View Enhancements
•Flame View has options that limit the data displayed on the view.
•In Samples drop-down, select either Allocation Size, Sample Weight or TLAB Size.
•Example use case: visualize where your program is spending its memory.
Open JFR Recording -> Memory-> Flame View
•Starting with JMC 9, Flame Graph will now be rendered using Java Swing.
Stay Tuned For More!
Inside.javaDev.java youtube.com/java
Useful links
• Programmer’s Guide to Snippets: https://docs.oracle.com/en/java/javase/21/javadoc/programmers-guide-snippets.html
• Java 21 Tool Enhancements: Better Across the Board #RoadTo21 https://www.youtube.com/embed/nFJBVuaIsRg
• Using Jshell API https://inside.java/2022/11/21/jshell-java-source-browser/
• Advanced jshell usage article: https://dev.java/learn/jvm/tools/core/jshell-advanced/
• Christian Stein’s article on jshell tooling https://sormuras.github.io/blog/2023-03-09-jshell-tooling
• Julia Boes article on more advanced jwebserver usage https://inside.java/2021/12/06/working-with-the-simple-web-server/
• JEP 408 on jwebserver https://openjdk.org/jeps/408
• More on jpackage: https://dev.java/learn/jvm/tool/jpackage/
• Package a JavaFX application as a native executable https://inside.java/2023/11/14/package-javafx-native-exec/
• Stack Walker ep 2 on JFR https://inside.java/2023/05/14/stackwalker-02/
• Monitoring Java Application Security with JDK tools and JFR Events: https://dev.java/learn/security/monitor/
•JEP 467 on markdown documentation comments: https://openjdk.org/jeps/467