BYO: Building a wc CLI Tool with Java and GraalVM 21

Building a wc
CLI Tool with Java and GraalVM 21
Creating command-line tools with Java can be both powerful and efficient, especially when paired with GraalVM's ability to compile Java applications into native executables. In this blog post, we’ll build a simple wc
(word count) CLI tool in Java that counts lines, words, and characters in a file. We’ll then use GraalVM 21 to compile it into a native executable for faster startup and lower memory usage.
Overview of the wc
Tool
The wc
command in Unix-like systems outputs the number of lines, words, and characters in a file. Our Java implementation will replicate this functionality and support file input.
Step 1: Writing the Java Code
Here’s the complete Java code for the wc
tool:
package com.arpitrathore.byo;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
/**
* Word count
*/
public class App {
public static void main(String[] args) {
if (args.length < 1) {
System.out.println("Usage: java WC <filename>");
System.exit(1);
}
String filePath = args[0];
try {
String content = Files.readString(Paths.get(filePath));
long lineCount = content.lines().count() - 1; //wc actually counts number of new line character
long wordCount = Arrays.stream(content.split("\\s+")).filter(word -> !word.isBlank()).count();
long charCount = content.length();
System.out.printf("%7d %7d %7d %s%n", lineCount, wordCount, charCount, filePath);
} catch (IOException e) {
System.err.println("Error reading file: " + e.getMessage());
System.exit(1);
}
}
}
Key Features of the Code
File Reading: The
Files.readString
method reads the file content as a single string.Line Count: The
content.lines()
method streams the lines and counts them.Word Count: Splits the content by whitespace and filters out empty strings.
Character Count: Simply uses the
length()
method on the string.Unix-like Output: Outputs results in the format:
lines words characters filename
.
Step 2: Compiling and Running the Program with Maven
We’ll use Maven for dependency management and to build the project. Additionally, we’ll use the native-maven-plugin
to create a native executable.
Maven Project Setup
Create a pom.xml
file for your project:
<?xml version="1.0" encoding="UTF-8"?>
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>com.arpitrathore.byo</groupId>
<artifactId>02-wc</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<native-maven-plugin.version>0.10.4</native-maven-plugin.version>
<main.class>com.arpitrathore.byo.App</main.class>
<image.name>ar-wc</image.name>
</properties>
<profiles>
<profile>
<id>native</id>
<build>
<plugins>
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
<version>${native-maven-plugin.version}</version>
<extensions>true</extensions>
<executions>
<execution>
<id>build-native</id>
<phase>package</phase>
<goals>
<goal>compile-no-fork</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>${main.class}</mainClass>
<imageName>${image.name}</imageName>
<agent>
<enabled>true</enabled>
</agent>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
Building and Running the Project
Compile the Java Code:
$ mvn clean package -Pnative
Run the Program and compare it with linux
wc
:$ ./target/ar-wc pom.xml main main 49 51 1626 pom.xml $ wc pom.xml main main 49 51 1626 pom.xml
Source Code
Entire source code used in this blog can be found here: link
Conclusion
Building CLI tools with Java and GraalVM opens up a world of possibilities for efficient and portable applications. This wc
tool is a simple example that demonstrates how you can leverage GraalVM to enhance Java’s capabilities. Try extending the tool with additional features, such as flag-based options (-l
for lines, -w
for words, etc.) or support for multiple files.
Let me know how you’ve used GraalVM for your projects!
Subscribe to my newsletter
Read articles from Arpit Rathore directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Arpit Rathore
Arpit Rathore
Senior Backend Engineer