An open API service indexing awesome lists of open source software.

https://github.com/sormuras/jdk-tools

๐Ÿ› ๏ธ JDK Tools and Where to Find Them
https://github.com/sormuras/jdk-tools

java jdk tools

Last synced: 12 months ago
JSON representation

๐Ÿ› ๏ธ JDK Tools and Where to Find Them

Awesome Lists containing this project

README

          

# JDK Tools and Where to Find Them

Java projects can be built using tools the Java Development Kit (JDK) provides.
Let's write a Java Scripting program that uses tools as primitives.

The JDK does not include a "build" tool.

Users resort to 3rd-party tools in order to transform Java source code into shippable products.

The JDK does include a set of foundation tools: javac, jar, ..., jlink.

This session explores ways how to make
the implicit connection between JDK tools and Java modules explicit
so that users are enabled to build Java projects more easily.

## Outline

This session starts with an overview of 28+ tools shipping with JDK 20.

After a short break (reading all linked man pages takes time),
a few tools are executed live on the command-line in order to
compile and link an example application.

In order to execute command-line tools programmatically,
the `ToolProvider` interface was introduced in Java 9.
It provides a way invoke tools without necessarily starting a new VM.

Leveraging the "Launch Single-File Source-Code Programs" feature
of JDK Enhancement Proposal (JEP) 330 a standalone tool-running
program called `Tool.java` is developed in seven steps.

Three abstractions are introduced along the way:

- `ToolFinder` A finder of tools. Similar to what `ModuleFinder` is to `ModuleReference`.
- `ToolRunner` A runner of tools. Uses `ToolFinder` and provides run time context.
- `ToolOperator` An extension of `ToolProvider` to run tools within a tool run.

## Tools, Options, Examples

[JDK 20 Documentation](https://docs.oracle.com/en/java/javase/20/)

[Javaยฎ Platform, Standard Edition & Java Development Kit Specifications Version 20](https://docs.oracle.com/en/java/javase/20/docs/specs)

[Javaยฎ Development Kit Version 20 Tool Specifications](https://docs.oracle.com/en/java/javase/20/docs/specs/man)

### Java Development Kit Version 20 Tool Specifications

**All Platforms**

* `jar` - create an archive for classes and resources, and manipulate or restore individual classes or resources from an archive
* `jarsigner` - sign and verify Java Archive (JAR) files
* `java` - launch a Java application
* `javac` - read Java class and interface definitions and compile them into bytecode and class files
* `javadoc` - generate HTML pages of API documentation from Java source files
* `javap` - disassemble one or more class files
* `jcmd` - send diagnostic command requests to a running Java Virtual Machine (JVM)
* `jconsole` - start a graphical console to monitor and manage Java applications
* `jdb` - find and fix bugs in Java platform programs
* `jdeprscan` - static analysis tool that scans a jar file (or some other aggregation of class files) for uses of deprecated API elements
* `jdeps` - launch the Java class dependency analyzer
* `jfr` - parse and print Flight Recorder files
* `jhsdb` - attach to a Java process or launch a postmortem debugger to analyze the content of a core dump from a crashed Java Virtual Machine (JVM)
* `jinfo` - generate Java configuration information for a specified Java process
* `jlink` - assemble and optimize a set of modules and their dependencies into a custom runtime image
* `jmap` - print details of a specified process
* `jmod` - create JMOD files and list the content of existing JMOD files
* `jpackage` - package a self-contained Java application
* `jps` - list the instrumented JVMs on the target system
* `jrunscript` - run a command-line script shell that supports interactive and batch modes
* `jshell` - interactively evaluate declarations, statements, and expressions of the Java programming language in a read-eval-print loop (REPL)
* `jstack` - print Java stack traces of Java threads for a specified Java process
* `jstat` - monitor JVM statistics
* `jstatd` - monitor the creation and termination of instrumented Java HotSpot VMs
* `jwebserver` - launch the Java Simple Web Server
* `keytool` - manage a keystore (database) of cryptographic keys, X.509 certificate chains, and trusted certificates
* `rmiregistry` - create and start a remote object registry on the specified port on the current host
* `serialver` - return the `serialVersionUID` for one or more classes in a form suitable for copying into an evolving class

**Windows Only**

* `jabswitch` - enable or disable Java Access Bridge
* `jaccessinspector` - examine accessible information about the objects in the Java Virtual Machine using the Java Accessibility Utilities API
* `jaccesswalker` - navigate through the component trees in a particular Java Virtual Machine and present the hierarchy in a tree view
* `javaw` - launch a Java application without a console window
* `kinit` - obtain and cache Kerberos ticket-granting tickets
* `klist` - display the entries in the local credentials cache and key table
* `ktab` - manage the principal names and service keys stored in a local key table

## An Example Project

```text
โ”œโ”€โ”€โ”€org.example
โ”‚ module-info.java
โ”‚
โ”œโ”€โ”€โ”€org.example.app
โ”‚ โ”‚ module-info.java
โ”‚ โ”‚
โ”‚ โ””โ”€โ”€โ”€org
โ”‚ โ””โ”€โ”€โ”€example
โ”‚ โ””โ”€โ”€โ”€app
โ”‚ Main.java
โ”‚
โ””โ”€โ”€โ”€org.example.lib
โ”‚ module-info.java
โ”‚
โ””โ”€โ”€โ”€org
โ””โ”€โ”€โ”€example
โ””โ”€โ”€โ”€lib
โ”‚ ExampleStringSupport.java
โ”‚
โ””โ”€โ”€โ”€internal
EchoToolProvider.java
```

### javac

> Read Java class and interface definitions and compile them into bytecode and class files.

```shell
javac
--module org.example,org.example.app,org.example.lib
--module-source-path .
-d out/classes
```

Here, compile 3 modules, namely...

- `org.example`,
- `org.example.app`, and
- `org.example.lib`.

Search source files in subdirectories of the current working directory `.`
named like the modules, and store class files in `out/classes`,
creating a subdirectory for each module

```text
โ”œโ”€โ”€โ”€org.example
โ”‚ module-info.class
โ”‚
โ”œโ”€โ”€โ”€org.example.app
โ”‚ โ”‚ module-info.class
โ”‚ โ”‚
โ”‚ โ””โ”€โ”€โ”€org
โ”‚ โ””โ”€โ”€โ”€example
โ”‚ โ””โ”€โ”€โ”€app
โ”‚ Main.class
โ”‚
โ””โ”€โ”€โ”€org.example.lib
โ”‚ module-info.class
โ”‚
โ””โ”€โ”€โ”€org
โ””โ”€โ”€โ”€example
โ””โ”€โ”€โ”€lib
โ”‚ ExampleStringSupport.class
โ”‚
โ””โ”€โ”€โ”€internal
EchoToolProvider.class
```

### java (exploded modules)

> Launch Java application

```shell
java
--module-path out/classes
--module org.example.app/org.example.app.Main
```

### jar

> Create an archive for classes and resources.

Three time's a charm, one call per module.

```shell
jar
--create
--file out/modules/org.example.jar
-C out/classes/org.example .
```

```shell
jar
--create
--file out/modules/org.example.app.jar
-C out/classes/org.example.app .
```

```shell
jar
--create
--file out/modules/org.example.lib.jar
-C out/classes/org.example.lib .
```

Here, create a modular JAR file named `org.example[.[app|lib]].jar`.

### java (archived modules)

> Launch Java application

```shell
java
--module-path out/modules
--module org.example.app/org.example.app.Main
```

### jlink

> Create custom runtime image

```shell
jlink
--verbose
--output out/image
--module-path out/modules
--add-modules org.example
--launcher example=org.example.app/org.example.app.Main
```

### java (custom launcher)

> Launch Java application in a custom runtime image

* Linux/Mac
```shell
out/image/bin/example
```

* Windows
```shell
out\image\bin\example
```

## Seven Steps to Find, Load, and Run Tools

### Step 0

Use `ToolProvider` (from `java.base/java.util.spi`) to find, load, and run `javac` tool.

```shell
java src/Tool0.java
```

* Launch single-file source-code Java program (JEP 330)
* Run: `java src/Tool0.java`
* TODO Pass non-empty main args arrays as tool's arguments
* Run: `java src/Tool0.java --version`

```text
// === DONE ===
// [x] Used ToolProvider SPI
// [x] Ignored result of the tool execution

// === HINT ===
// [ ] args.length != 0 ? args : new String[] {"--version"}
// [ ] Run: java src/Tool0.java --help-extra
// [ ] Run: java src/Tool0.java --help-lint

// === NEXT ===
// ? Run: java src/Tool0.java jar --version
// --> Transform into an application running an arbitrary tool
```

### Step 1

An application running an arbitrary tool.

```shell
java src/Tool1.java jar --version
```

* Show usage message on empty args array
* Create `ToolRunner` interface with run method
* Move find and run code into default implementation
* TODO Print tool name and its args on run

```text
// DONE
// [x] Let args[0] be the name of the tool to run and args[1..n] its arguments
// [x] Added an abstraction for running a tool, throwing on non-zero exit code

// HINT
// [ ] System.out.println("// name = " + name + ", args = " + Arrays.deepToString(args));
// [ ] Run with well-known system tools: javac, jar, jlink

// NEXT
// ? Run with: jfr
// --> Implement a `--list-tools` option showing all observable tools and exit
// --> By introducing a configurable `ToolFinder` abstraction
```

### Step 2

Introduce ToolFinder to list observable tools.

* Create ToolFinder interface with abstract `List findAll()` method
* Add default `Optional find(NAME)` method to ToolFinder
* Add `ToolFinder.ofEmpty()` factory
* In `ToolRunner`, replace `ToolProvider.findFirst(NAME)` usage with `ToolFinder.find(NAME)`
* TODO Implement `ToolFinder.ofSystem()` by looking into `ToolProvider.findFirst(NAME)`

```shell
java src/Tool2.java --list-tools
```

```text
// HINT:
// [x] Run: java --limit-modules java.base src/Tool2.java

// NEXT:
// ? Run: java src/Tool2.java banner hello world
// [ ] Implement a custom tool: `record Banner(String name) implements ToolProvider {...}`
// [ ] Implement a tool finder that accepts instances of `ToolProvider`
```

### Step 3

Local tool Banner and finder of tool instances.

```shell
java src/Tool3.java banner hello world
```

```text
// Next step:
// [ ] Implement a tool finder that is composed of other finders
// [ ] Compose application's tool finder
```

### Step 4

Composing tool finders.

```shell
java src/Tool4.java --list-tools
```

```text
// Next step:
// [ ] How to implement a tool that runs other tools?
// [ ] Add an abstraction for tool running tool: an operator
```

### Step 5

A tool operator runs other tools.

```shell
java src/Tool5.java chain banner banner
```

```text
// Next step:
// [ ] Implement tool operators: Compile and Link
```

### Step 6

```shell
java src/Tool6.java chain compile link
```

```text
// Next step:
// [ ] GOTO Tool.java
// More ToolFinder...
```

## `Tool.java`

Putting it all together to access all tools the JDK provides.

```shell
java src/Tool.java chain compile link run
```

* `ToolFinder.ofNativeTools(Path directory)`
* Leveraging `ProcessBuilder` and `Process` API.
* Example: `ofNativeTools(Path.of(System.getProperty("java.home"), "bin"))`

Explore more tool finders:

* `ToolFinder.ofJavaPrograms(Path directory)`
* Single-File Source-Code Program `java Program.java ARGS...`
* Executable JAR file `java -jar program.jar ARGS...`

* `ToolFinder.of(ModuleFinder)` and `ToolFinder.of(ModuleLayer)`
* Example: `of(ModuleFinder.of(Path.of("out", "modules")))`

## Talk-Related Links

* JDK Tool Specifications

* Project Jigsaw: Module System Quick-Start Guide

## More Tool-Related Links

* List of Unix commands

* Unix philosophy

* JEP 293: Guidelines for JDK Command-Line Tool Options

* JDK-8275072: Enhance java.util.spi.ToolProvider

* ARGument harVESTER - a simple command line parser written with Love and Java 15

## More Tools, More Options, More Examples

### jpackage

### jtreg (7+)

### jextract (?)

### junit (external)

### jreleaser (external)