With most Java programmers used to coding within the boundaries of an Integrated Development Environment (Eclipse, IntelliJ, etc.), when it comes to executing a simple Java code on a JVM, many falter. Below, we explore how to execute a simple Java program using the CLI.
The Java Code
We have two classes – AwesomeClass and SuperAwesomeClass; and one resource file – app.config. Note that both the classes are in different packages.
AwesomeClass contains the main method. The main method expects a command line argument, and passes on the same to an instance of SuperAwesomeClass.
Finally, SuperAwesomeClass prints two lines, one containing the argument it received, and the second displays the contents of the app.config resource file.
Step 1 – Compilation
The first step to execute the above code would be compiling it, i.e., converting to Java bytecode. The bytecode can then be run on any JVM.
I have created a new folder in my Desktop (~/Desktop/project/) and copied both the source files (AwesomeClass.java and SuperAwesomeClass.java) into it. The resource file resides in the Desktop (~/Desktop/app.config).
Now, one possible way to generate the bytecode (.class files) is to do the following:
javac -d “.” -cp “/Users/rnirvan/.m2/repository/commons-io/commons-io/1.3.2/commons-io-1.3.2.jar” *.java
This command will result in the creation of two .class files. To understand how this happens, lets first understand this command. It consists of three parts:
The d option signifies that the generated class files, AwesomeClass.class and SuperAwesomeClass.class (note: extension is .class and not .java), will be placed in the appropriate folder structure with respect to the current directory. The folder structure (which will be created by javac) is determined by the packaging of the Java files.
Therefore, for our two Java files, com.rudrnirvan.cli.package1.AwesomeClass.java and com.rudrnirvan.cli.package2.SuperAwesomeClass.java, two class files are generated: ./com/rudranirvan/cli/package1/AwesomeClass.class and ./com/rudranirvan/cli/package2/SuperAwesomeClass.class.
Using the cp option overrides the system classpath with provided one. We have provided the location of the commons-io jar. This is needed to support the org.apache.commons.io.IOUtils class needed by the SuperAwesomeClass. (Try running this command without the “cp” option, and you will encounter a “missing symbol” error.)
This simply tells javac to compile all the files with a .java extension in the current directory. Consequently, AwesomeClass.java and SuperAwesomeClass.java will be compiled.
Step 2 – Execution
In this step, we will run the class files generated in the previous phase on the JVM. We can do this using the following:
java -cp “/Users/rnirvan/.m2/repository/commons-io/commons-io/1.3.2/commons-io-1.3.2.jar:/Users/rnirvan/Desktop/:.” com.rudranirvan.cli.package1.AwesomeClass 1234
This commands consists of the following three parts:
Same as with the javac command, the cp option specifies the classpath to use. In unix-like systems, multiple classpath entries are separated by a colon. In Windows, the separator is a semi-colon.
Our classpath consists of three entries:
- /Users/rnirvan/.m2/repository/commons-io/commons-io/1.3.2/commons-io-1.3.2.jar: As with the previous javac command, the jar entry is included to support the IOUtils class.
- /Users/rnirvan/Desktop/: Included as this is where the resource file (app.config) is stored. ClassLoader.getResourceAsStream(String name) requires this file to be present in the classpath.
- . (current directory): Inclusion of the current directory ensures that the two class files generated by the javac command get included in our classpath.
This provides the class whose main method needs to be run. (If you provide a class with a missing “main” method, you will encounter a “could not load or find main class” error.)
This is the command line argument which is passed to the main method.
Running this java command will provide an output similar to the following:
I am the output from the app.config file.
At this point, it should now be clear why the classpath is so vital. You should hopefully be able to figure out how adding the commons-io jar to the classpath helps with the compilation process (hint: try listing the jar’s contents).
The method described here for executing Java files is just one of the multiple strategies you could apply. There is a lot of room to play around with just these two commands. Here is a fun exercise: try running javac without the d option and try to figure out how you could then use the java command.