Last updated: August 31, 2005
Here is the obligatory "hello world" application:
public class T { public static void main(String[] args) { System.out.println("Salut, Le Monde"); } }
which I have placed in ~/USF/CS601/code/tools/T.java.
Jumping into ~/USF/CS601/code/tools, I can compile T.java with the javac tool:
$ cd ~/USF/CS601/code/tools $ javac T.java
which leaves T.class in the current directory.
To run the T.main() method, use the java interpreter/run-time-compiler tool:
$ java T Salut, Le Monde $
where java takes the name of a Java class, T, not the name of the file it is in, T.java. The java interpreter looks for T.class and then begins execution at the main() method within. Assume for now that java looks for T.class and any other class files in the current directory.
Now, lets use two Java files; one, U.java:
public class U { public static void main(String[] args) { Hello.speak(); } }
that refers to a method in the new file, Hello.java:
public class Hello { public static void speak() { System.out.println("hello"); } }
To compile these two files, use
$ javac U.java Hello.java
or, more generally:
$ javac *.java $ ls | more Hello.class Hello.java T.class T.java U.class U.java
Now you can run U's main() method via:
$ java U hello $
Jump into /tmp and now try to run U:
$ cd /tmp $ java U Exception in thread "main" java.lang.NoClassDefFoundError: U
The problem is that the Java interpreter does not know where to find U.class. You can specify where to look directly:
$ java -classpath ~/USF/CS601/code/tools T Salut, Le Monde $ java -classpath ~/USF/CS601/code/tools U hello
The notion of a class path is similar to the UNIX and DOS PATH environment variable that tells the command line where to find applications and tools.
In general, however, you will not want to repeat the path each time. Java looks for a CLASSPATH environment variable and uses it as a colon-separated (on UNIX; PC's use semicolon I think) list of directories. These directories are understood to potentially contain your code. For example, I could set my CLASSPATH to include directory ~/USF/CS601/code/tools:
$ echo $CLASSPATH # what is it set to currently? .:/home/parrt/lib/antlr-2.7.2.jar:/home/parrt/lib/jguru.util.jar:... $ export CLASSPATH="$CLASSPATH:/home/parrt/tmp" # append $ echo $CLASSPATH # what is it now? .:/home/parrt/lib/antlr-2.7.2.jar:/home/parrt/lib/jguru.util.jar:...:~/USF/CS601/code/tools
Note that you should generally include dot ('.'), the current directory, in your CLASSPATH.
Anyway, now from /tmp, you can run your programs without the explicit java option:
$ cd /tmp $ java T Salut, Le Monde $ java U hello $
Most of the time, Java code is organized into packages just like you organize your general files in your home directory. In fact, there is a prefix convention that is the reversal of your domain as the root package. For example, my ANTLR research code uses package org.antlr and jGuru uses com.jguru. For our purposes here, we will use a single package and move our test files into it.
Modify the above code to live in package foo:
$ cd ~/USF/CS601/code/tools $ mkdir foo $ cp *.java foo $ cd foo $ vi *.java
Where, with your editor, you have added
package foo;
as the first line of every file. Also add "foo: " to the strings so that we can tell which version of our code is executing. So Hello.java looks like:
package foo; public class Hello { public static void speak() { System.out.println("foo: hello"); } }
Note the obvious correlation between package and directory: if your class T is in package a.b.c then it must be in file a/b/c/T.java.
Compile as before (except you are in the foo) subdirectory:
$ javac *.java
Now, try to run the simplest class T:
$ java T Exception in thread "main" java.lang.NoClassDefFoundError: T (wrong name: foo/T) at java.lang.ClassLoader.defineClass0(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:502) ...
Java started looking for class T, which it knows will be in T.class. It found T.class in the current directory (remember '.' is in your CLASSPATH first), but the compiled code showed that it is actually class foo.T not T.
Besides, you want to run the new class which is foo.T not T. Try that:
$ cd ~/USF/CS601/code/tools/foo $ java foo.T Exception in thread "main" java.lang.NoClassDefFoundError: foo/T
Now, java is looking for foo.T in a file called foo/T.class. You are in foo, which has no foo subdirectory. If you move up a directory, then file foo/T.class will be found when you ask for class foo.T:
$ cd .. $ pwd # print working directory /Users/parrt/tmp $ java foo.T foo: Salut, Le Monde $ java foo.U foo: hello
To execute foo.T, java uses the following algorithm:
Tool jar (java archive) is analogous the UNIX tar utility and packs a bunch of Java source, Java .class files, resources etc... into a single file for easy deployment.
To make a jar of the simple test files in ~/USF/CS601/code/tools, jump inside and say
$ jar cvf /tmp/tools.jar *.class added manifest adding: Hello.class(in = 385) (out= 271)(deflated 29%) adding: T.class(in = 411) (out= 286)(deflated 30%) adding: U.class(in = 283) (out= 220)(deflated 22%)
This "cvf /tmp/tools.jar" (create, verbose, filename ...) option jars up all the .class files and puts the jar file in /tmp/tools.jar. To see what is inside, use tvf:
$ jar tvf /tmp/tools.jar 0 Tue Sep 02 14:44:44 PDT 2003 META-INF/ 70 Tue Sep 02 14:44:44 PDT 2003 META-INF/MANIFEST.MF 385 Tue Sep 02 14:05:50 PDT 2003 Hello.class 411 Tue Sep 02 13:55:06 PDT 2003 T.class 283 Tue Sep 02 14:05:50 PDT 2003 U.class
When you have packages, you must be careful what directory you are in. Recall that class foo.T must be in file foo/T.class. So to ja up the second round of packaged examples, you would jar everything up for the same directory as before (that is, the directory containing foo):
$ jar cvf /tmp/foo.jar foo added manifest adding: foo/(in = 0) (out= 0)(stored 0%) adding: foo/Hello.class(in = 389) (out= 276)(deflated 29%) adding: foo/Hello.java(in = 106) (out= 94)(deflated 11%) adding: foo/T.class(in = 415) (out= 290)(deflated 30%) adding: foo/T.java(in = 124) (out= 113)(deflated 8%) adding: foo/U.class(in = 291) (out= 227)(deflated 21%) adding: foo/U.java(in = 100) (out= 90)(deflated 10%) $ jar tvf /tmp/foo.jar 0 Tue Sep 02 14:47:44 PDT 2003 META-INF/ 70 Tue Sep 02 14:47:44 PDT 2003 META-INF/MANIFEST.MF 0 Tue Sep 02 14:34:38 PDT 2003 foo/ 389 Tue Sep 02 14:34:50 PDT 2003 foo/Hello.class 106 Tue Sep 02 14:34:30 PDT 2003 foo/Hello.java 415 Tue Sep 02 14:34:50 PDT 2003 foo/T.class 124 Tue Sep 02 14:34:32 PDT 2003 foo/T.java 291 Tue Sep 02 14:34:50 PDT 2003 foo/U.class 100 Tue Sep 02 14:34:36 PDT 2003 foo/U.java
To execute code from within a jar, make sure the jar file is in your class path (either explicitly from the command line as shown here or from your CLASSPATH environment variable).
$ cd some-random-directory $ java -classpath /tmp/tools.jar T foo: Salut, Le Monde $ java -classpath /tmp/tools.jar U foo: hello
To access the code in a package, the same syntax is used:
$ java -classpath /tmp/foo.jar foo.T foo: Salut, Le Monde ~/USF/CS601/code/tools $ java -classpath /tmp/foo.jar foo.U foo: hello
In essence, a jar file is simply mimicking file system directory structure.