BYO: Building a wc CLI Tool with Java and GraalVM 21
Senior Backend Engineer
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.readStringmethod 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 -PnativeRun 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!



