DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Related

  • Javac and Java Katas, Part 2: Module Path
  • Java's Quiet Revolution: Thriving in the Serverless Kubernetes Era
  • Leverage Amazon BedRock Chat Model With Java and Spring AI
  • Using Spring AI to Generate Images With OpenAI's DALL-E 3

Trending

  • AWS to Azure Migration: A Cloudy Journey of Challenges and Triumphs
  • Memory Leak Due to Time-Taking finalize() Method
  • Developers Beware: Slopsquatting and Vibe Coding Can Increase Risk of AI-Powered Attacks
  • Infrastructure as Code (IaC) Beyond the Basics
  1. DZone
  2. Coding
  3. Java
  4. Javac and Java Katas, Part 1: Class Path

Javac and Java Katas, Part 1: Class Path

This article contains several exercises focused on using JDK tools such as javac, java, and jar to build and run Java applications.

By 
Maksim Kren user avatar
Maksim Kren
·
May. 02, 24 · Tutorial
Likes (9)
Comment
Save
Tweet
Share
4.4K Views

Join the DZone community and get the full member experience.

Join For Free

Here, I'd like to talk you through three Java katas, ranging from the simplest to the most complex. These exercises should help you gain experience working with JDK tools such as javac, java, and jar. By doing them, you'll get a good understanding of what goes on behind the scenes of your favorite IDE or build tools like Maven, Gradle, etc.

None of this denies the benefits of an IDE. But to be truly skilled at your craft, understand your essential tools and don’t let them get rusty.
- Gail Ollis, "Don’t hIDE Your Tools"

Getting Started

The source code can be found in the GitHub repository. All commands in the exercises below are executed inside a Docker container to avoid any particularities related to a specific environment.

Thus, to get started, clone the repository and run the command below from its java-javac-kata folder:

Shell
 
docker run --rm -it --name java_kata -v .:/java-javac-kata --entrypoint /bin/bash maven:3.9.6-amazoncorretto-17-debian


Kata 1: "Hello, World!" Warm Up

In this kata, we will be dealing with a simple Java application without any third-party dependencies. Let's navigate to the /class-path-part/kata-one-hello-world-warm-up folder and have a look at the directory structure.

/class-path-part/kata-one-hello-world-warm-up folder directory structure

Within this directory, we can see the Java project structure and two classes in the com.example.kata.one package.

Compilation

Shell
 
javac -d ./target/classes $(find -name '*.java')


Compiled Java classes appearing in the target/classes folder

The compiled Java classes should appear in the target/classes folder, as shown in the screenshot above. Try using the verbose option to see more details about the compilation process in the console output:

Shell
 
javac -verbose -d ./target/classes $(find -name '*.java')


With that covered, let's jump into the execution part.

Execution

Shell
 
java --class-path "./target/classes" com.example.kata.one.Main


As a result, you should see Hello World! in your console. 

Try using different verbose:[class|gc|jni] options to get more details on the execution process:

Shell
 
java -verbose:class --class-path "./target/classes" com.example.kata.one.Main


As an extra step, it's worth trying to remove classes or rename packages to see what happens during both the complication and execution stages. This will give you a better understanding of which problems result in particular errors.

Packaging

Building Jar

Shell
 
jar --create --file ./target/hello-world-warm-up.jar -C target/classes/ .


Built jar placed in the target folder

The built jar is placed in the target folder. Don't forget to use the verbose option as well to see more details:

Shell
 
jar --verbose --create --file ./target/hello-world-warm-up.jar -C target/classes/ .


You can view the structure of the built jar using the following command:

Shell
 
jar -tf ./target/hello-world-warm-up.jar


With that, let's proceed to run it:

Shell
 
java --class-path "./target/hello-world-warm-up.jar" com.example.kata.one.Main


Building Executable Jar

To build an executable jar, the main-class must be specified:

Shell
 
jar --create --file ./target/hello-world-warm-up.jar --main-class=com.example.kata.one.Main -C target/classes/ .


It can then be run via jar option:

Shell
 
java -jar ./target/hello-world-warm-up.jar


Kata 2: Third-Party Dependency

In this kata, you will follow the same steps as in the previous one. The main difference is that our Hello World! application uses guava-30.1-jre.jar as a third-party dependency. Also, remember to use the verbose option to get more details.

So, without further ado, let's get to the /class-path-part/kata-two-third-party-dependency folder and check out the directory's structure.

/class-path-part/kata-two-third-party-dependency folder directory structure

Compilation

Shell
 
javac --class-path "./lib/*" -d ./target/classes/ $(find -name '*.java')


The class-path option is used to specify the path to the lib folder where our dependency is stored.

Execution

Shell
 
java --class-path "./target/classes:./lib/*" com.example.kata.two.Main


Packaging

Building Jar

Shell
 
jar --create --file ./target/third-party-dependency.jar -C target/classes/ .


And let us run it:

Shell
 
java --class-path "./target/third-party-dependency.jar:./lib/*" com.example.kata.two.Main


Building Executable Jar

Our first step here is to create a MANIFEST.FM file with the Class-Path specified:

Shell
 
echo 'Class-Path: ../lib/guava-30.1-jre.jar' > ./target/MANIFEST.FM


Next up, we build a jar with the provided manifest option:

Shell
 
jar --create \
    --file ./target/third-party-dependency.jar \
    --main-class=com.example.kata.two.Main \
    --manifest=./target/MANIFEST.FM \
    -C target/classes/ .


Finally, we execute it:

Shell
 
java -jar ./target/third-party-dependency.jar


Building Fat Jar

First of all, we need to unpack our guava-30.1-jre.jar into the ./target/classes/ folder (be patient, this can take some time):

Shell
 
cp lib/guava-30.1-jre.jar ./target/classes && \
cd ./target/classes && \
jar xf guava-30.1-jre.jar && \
rm ./guava-30.1-jre.jar && \
rm -r ./META-INF && \
cd ../../


With all the necessary classes in the ./target/classes folder, we can build our fat jar (again, be patient as this can take some time):

Shell
 
jar --create --file ./target/third-party-dependency-fat.jar --main-class=com.example.kata.two.Main -C target/classes/ .


Now,  we can run our built jar:

Shell
 
java -jar ./target/third-party-dependency-fat.jar


Kata 3: Spring Boot Application Conquest

In the /class-path-part/kata-three-spring-boot-app-conquest folder, you will find a Maven project for a simple Spring Boot application. The main goal here is to apply everything that we have learned so far to manage all its dependencies and run the application, including its test code.

As a starting point, let's run the following command:

Shell
 
mvn clean package && \
find ./target/ -mindepth 1 ! -regex '^./target/lib\(/.*\)?' -delete


This will leave only the source code and download all necessary dependencies into the ./target/lib folder.

Download all necessary dependencies into the ./target/lib folderCompilation

Shell
 
javac --class-path "./target/lib/compile/*" -d ./target/classes/ $(find -P ./src/main/ -name '*.java')


Execution

Shell
 
java --class-path "./target/classes:./target/lib/compile/*" com.example.kata.three.Main


As an extra step for both complication and execution, you can try specifying all necessary dependencies explicitly in the class-path. This will help you understand that not all artifacts in the ./target/lib/compile are needed to do that.

Packaging

Let's package our compiled code as a jar and try to run it. 

It won't be a Spring Boot jar because Spring Boot uses a non-standard approach to build fat jars, including its own class loader. See the documentation on The Executable Jar Format for more details. In this exercise, we will package our source code as we did before to demonstrate that everything can work in the same way with Spring Boot, too.

Shell
 
jar --create --file ./target/spring-boot-app-conquest.jar -C target/classes/ .


Now, let's run it to verify that it works:

Shell
 
java --class-path "./target/spring-boot-app-conquest.jar:./target/lib/compile/*" com.example.kata.three.Main


Test Compilation

Shell
 
javac --class-path "./target/classes:./target/lib/test/*:./target/lib/compile/*" -d ./target/test-classes/ $(find -P ./src/test/ -name '*.java')

Take notice that this time we are searching for source files in the ./src/test/ directory, and both the application source code and test dependencies are added to the class-path.

Test Execution

To be able to run code via java, we need an entry point (a class with the main method). Traditionally, tests are run via a Maven plugin or by an IDE, which have their own launchers to make this process comfortable for developers. To demonstrate test execution, the junit-platform-console-standalone dependency, which includes the org.junit.platform.console.ConsoleLauncher with the main method, is added to our pom.xml. Its artifact can also be seen in the ./target/lib/test/* folder.

Shell
 
java --class-path "./target/classes:./target/test-classes:./target/lib/compile/*:./target/lib/test/*" \
     org.junit.platform.console.ConsoleLauncher execute --scan-classpath --disable-ansi-colors


Wrapping Up

Gail's article, "Don’t hIDE Your Tools" quoted at the very beginning of this article, taken from 97 Things Every Java Programmer Should Know by Kevlin Henney and Trisha Gee, inspired me to start thinking in this direction and eventually led to the creation of this post.

Hopefully, by doing these katas and not just reading them, you have developed a better understanding of how the essential JDK tools work.

Javac JAR (file format) Java (programming language) Kata (programming) Spring Boot

Opinions expressed by DZone contributors are their own.

Related

  • Javac and Java Katas, Part 2: Module Path
  • Java's Quiet Revolution: Thriving in the Serverless Kubernetes Era
  • Leverage Amazon BedRock Chat Model With Java and Spring AI
  • Using Spring AI to Generate Images With OpenAI's DALL-E 3

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!