Java CLI Template
This is a template repository for building CLI applications with Java. It leverages Picocli for bootstrapping the CLI execution and GraalVM native-image for building a native image executable.
- JDK Version:
17
- GraalVM Version:
21.3.0
Build
Maven
For the native-image
build, see instructions at bottom for tooling pre-requisites. Your
JAVA_HOME
will need to be set with GraalVM
installation.
./mvnw clean install # Build executable JAR
./mvnw clean install -D nativeImage # Build native image
Gradle
./gradlew clean build # Build executable JAR
./gradlew clean nativeImage # Build native image
Docker
An external build is first required since the Dockerfile
needs to ADD
the executable JAR.
By default, the JAR used is from maven build.
docker build -t java-cli-template .
To use the gradle build output:
docker build -t java-cli-template --build-arg "JAR=build/libs/java-cli-template-*.jar" .
Run
Maven
Executable JAR
java -jar target/java-cli-template-*.jar --help
java -jar target/java-cli-template-*.jar hello-world
java -jar target/java-cli-template-*.jar hello-world Brian
echo "Brian" | java -jar target/java-cli-template-*.jar hello-world -
Native Image
./target/app --help
./target/app hello-world
./target/app hello-world Brian
echo "Brian" | ./target/app hello-world -
Gradle
Executable JAR
java -jar build/libs/java-cli-template-*.jar --help
java -jar build/libs/java-cli-template-*.jar hello-world
java -jar build/libs/java-cli-template-*.jar hello-world Brian
echo "Brian" | java -jar build/libs/java-cli-template-*.jar hello-world -
Native Image
./build/graal/app --help
./build/graal/app hello-world
./build/graal/app hello-world Brian
echo "Brian" | ./build/graal/app hello-world -
Docker
docker run java-cli-template --help
docker run java-cli-template hello-world
docker run java-cli-template hello-world Brian
echo "Brian" | docker run -i java-cli-template hello-world -
Reflection in Native Image
Runtime reflection in a native image is tricky. GraalVM can detect basic usage of class loading with reflection, however it cannot determine classes loaded dynamically. To allow it to work, some configuration needs to be done.
See Reflect.java
for how the class is loaded "dynamically".
This Will Work
./app reflect java.lang.String
This is because it has been configured in reflect-config.json
.
This Will Not Work
./app reflect java.util.List
This is because it is not included in reflect-config.json
Native Image Prerequisites When Using Maven
The maven build requires that GraalVM and native-image
tooling already be available on the machine.
- GraalVM CE
- GraalVM CE
native-image
zlib
/xcode
GraalVM Installation
./install-graalvm.sh
If you are using Gradle or Docker, you do not need to perform this installation.