Popular Posts

Monday, February 23, 2009

Exercise 3.1: Write, Compile, and Run Hello Java Program

Introduction:

The goal of this exercise is to let you experience a complete development cycle - writing, compiling, and running a simplest possible Java program - using command line tools. If you have done any programming in the past using different programming languages such as C or C++, this is not that much different from it. (There is a slight difference, however. In Java, the compiler javac compiles the Java source code into what is called bytecode which can be run on any Java compliant platform, thus provides the portability of the Java programs. The bytecode is the same thing as Java class file, which is represented by *.class file notation.)

You will also get some exposure to the concept of the classpath. The classpath is the most basic but essential concept you will need to understand - it is basically a location where *.class files reside. If the classpath is not set up correctly, you will experience the infamous "java.lang.NoClassDefFoundError: " exception.

Steps to follow:

1. mkdir c:\myjavaprograms (to create a directory of your choice - this is the directory where you are going to write Java programs)
2. cd \myjavaprograms (this directory becomes the current directory)
3. Write Hello.java using your editor of choice (in this example, I am using jedit) as shown in Code-3.1-a below. You can cut and paste the code from the Code-3.1-a but I encourage you to write the code line by line yourself manually just to experience some compile errors.

* jedit Hello.java

public class Hello {

/**
* My first Java program
*/
public static void main( String[] args ){

// Print the string "Hello world" on screen
System.out.println("Hello world");

}

}
Code-3.1-a: Hello.java

4. Compile Hello.java using javac compiler. The javac compiler comes with J2SE SDK you've download. It resides in %JAVA_HOME%\bin (Windows) or $JAVA_HOME/bin (Solaris/Linux) directory. The result of compilation will be the creation of Hello.class file.

* javac Hello.java

Trouble-shooting 3.1.a: If you experience the following error condition, it means the %JAVA_HOME%\bin for Windows platform or $JAVA_HOME/bin for Solaris/Linux platform is not set in your path. You can try C:\Program Files\Java\jdk1.5.0_06\bin\javac Hello.java (for Windows) if you want to proceed without setting the path.

* C:\myjavaprograms>javac Hello.java
'javac' is not recognized as an internal or external command,
operable program or batch file.

Trouble-shooting 3.1.b: If your Hello.java program contains a problem such as a typo or missing semi-colon after each statement, you will experience compile errors like an example compile error below (I misspelled it - it should have been System.out.println("Hello world"); instead of Syste.out.println("Hello world");.

* C:\myjavaprograms>javac Hello.java
Hello.java:9: package Syste does not exist
Syste.out.println("Hello world");
^
1 error

Trouble-shooting 3.1.c: If you name your file as hello.java (instead of Hello.java), you will experience the following problem. It is because the file name, hello.java, and the class name inside the code does not match. Inside the code, you use Hello in "public class Hello" statement and you name your file as hello.java. They have to match. And Java is case sensitive. hello.java and Hello.java are different files as far as Java is concerned. So rename the file to Hello.java and do the compilation again.

* C:\myjavaprograms>javac hello.javahello.java:1: class Hello is public, should be declared in a file named Hello.java
public class Hello {
^
1 error


Experimentation 3.1.d: Try "javac -verbose Hello.java" to see what is happening when you run javac. You really don't need to understand what is happening underneath at this point, however, except that it reads Hello.java file and then created Hello.class at the end.

* C:\myjavaprograms>javac -verbose Hello.java
[parsing started Hello.java]
[parsing completed 31ms]
[search path for source files: [C:\Program Files\Java\jre1.5.0_05\lib\ext\QTJava.zip]]
[search path for class files: [C:\Program Files\Java\jdk1.5.0_06\jre\lib\rt.jar,C:\Program Files\Java\jdk1.5.0_06\jre\lib\jsse.jar, C:\Program Files\Java\jdk1.5.0_06\jre\lib\jce.jar, C:\Program Files\Java\jdk1.5.0_06\jre\lib\charsets.jar, C:\Program Files\Java\jdk1.5.0_06\jre\lib\ext\dnsns.jar, C:\Program Files\Java\jdk1.5.0_06\jre\lib\ext\localedata.jar, C:\Program Files\Java\jdk1.5.0_06\jre\lib\ext\sunjce_provider.jar, C:\Program Files\Java\jdk1.5.0_06\jre\lib\ext\sunpkcs11.jar, C:\Program Files\Java\jre1.5.0_05\lib\ext\QTJava.zip]]
[loading C:\Program Files\Java\jdk1.5.0_06\jre\lib\rt.jar(java/lang/Object.class)]
[loading C:\Program Files\Java\jdk1.5.0_06\jre\lib\rt.jar(java/lang/String.class)]
[checking Hello]
[loading C:\Program Files\Java\jdk1.5.0_06\jre\lib\rt.jar(java/lang/System.class)]
[loading C:\Program Files\Java\jdk1.5.0_06\jre\lib\rt.jar(java/io/PrintStream.class)]
[loading C:\Program Files\Java\jdk1.5.0_06\jre\lib\rt.jar(java/io/FilterOutputStream.class)]
[loading C:\Program Files\Java\jdk1.5.0_06\jre\lib\rt.jar(java/io/OutputStream.class)]
[wrote Hello.class]
[total 266ms]

Experimentation 3.1.e: Try "javac -help" to see what options you can specify when you compile Java code using javac compiler. You don't need to understand every option right now but the important options are "-classpath ", "-cp ", "-sourcepath ", "-d ". Please feel free to play around with these options. Among these four, "-classpath ", "-cp " are more important to understand. By the way, "-classpath ", "-cp " are the same thing.

* C:\myjavaprograms>javac -help
Usage: javac
where possible options include:
-g Generate all debugging info
-g:none Generate no debugging info
-g:{lines,vars,source} Generate only some debugging info
-nowarn Generate no warnings
-verbose Output messages about what the compiler is doing
-deprecation Output source locations where deprecated APIs are used
-classpath Specify where to find user class files
-cp Specify where to find user class files
-sourcepath Specify where to find input source files
-bootclasspath Override location of bootstrap class files
-extdirs Override location of installed extensions
-endorseddirs Override location of endorsed standards path
-d Specify where to place generated class files
-encoding Specify character encoding used by source files
-source Provide source compatibility with specified release

-target Generate class files for specific VM version
-version Version information
-help Print a synopsis of standard options
-X Print a synopsis of nonstandard options
-J Pass directly to the runtime system


5. Make sure Hello.class file has been created. The Hello.class file contains bytecode representation of the Hello class.

* dir Hello.class

6. Run the Hello program using java command. The java command starts the Java Virtual Machine and runs the Hello program in this example. A Java program can be made of multiple Java classes and and a set of libraries. In this example, the Hello program just contains a single class called Hello.class. You can regard the java command as Java interpreter.

* java Hello

You should see either of the following results.

* C:\myjavaprograms>java Hello
Hello world

or

* C:\myjavaprograms>java Hello
Exception in thread "main" java.lang.NoClassDefFoundError: Hello

Trouble-shooting 3.1.g: If you experience the "Exception in thread "main" java.lang.NoClassDefFoundError: Hello" exception as shown above, it is highly likely because you are using predefined or wrong (at least for running this program) CLASSPATH environment variable. You can find out whether CLASSPATH environment variable is set or not as following - in the example below, the CLASSPATH is set to C:\Program Files\Java\jre1.5.0_05\lib\ext\QTJava.zip. (You can type jar tvf "C:\Program Files\Java\jre1.5.0_05\lib\ext\QTJava.zip" at the command line to see what Java classes make up the zip file.)

* C:\myjavaprograms>set CLASSPATH
CLASSPATH=C:\Program Files\Java\jre1.5.0_05\lib\ext\QTJava.zip

The "Exception in thread "main" java.lang.NoClassDefFoundError: Hello" means that the Java interpreter, java, could not find the Hello.class file in the classpath. (Please be warned this will be the most frequently encountered error condition you will be experiencing the first time you learn Java programming using command line tools such as javac and java. The NetBeans IDE handles all this for you.)

One way to solve the problem is unsetting the CLASSPATH environment variable for now as described below and run the Hello program again as following. (In this case, the classpath is the current directory which contains the Hello.class file. I will explain how Java interpreter finds which classpath to use shortly.)

* C:\myjavaprograms>java Hello
Exception in thread "main" java.lang.NoClassDefFoundError: Hello
* C:\myjavaprograms>set CLASSPATH=
* C:\myjavaprograms>set CLASSPATH
Environment variable CLASSPATH not defined
* C:\myjavaprograms>java Hello
Hello world

Experimentation 3.1.h: You can also explicitly specify the classpath by using -classpath and -cp option. Try "java -classpath . Hello" and "java -cp . Hello" as shown below. (There is a dot . between -classpath and Hello and -cp and Hello.) It should work as following. What you did is basically specifying that the current directory, which is represented by the dot ., is the classpath you want to use.

* C:\myjavaprograms>java -classpath . Hello
Hello world
* C:\myjavaprograms>java -cp . Hello
Hello world

Experimentation 3.1.i: Try to set the classpath with full directory path, C:\myjavaprograms in this example. It should work as well.

* C:\myjavaprograms>java -classpath C:\myjavaprograms Hello
Hello world
* C:\myjavaprograms>java -cp C:\myjavaprograms Hello
Hello world

Important: The "-classpath " or "-cp " option specifies the location where the class files (in this example, we have only a single class file called Hello.class) reside. When you don't specify the classpath option, the Java interpreter tries to find the class files in the directories specified in the CLASSPATH environment variables or in a current directory. In fact, the Java interpreter tries to find the class files in the following order.

1. In the directories you specify with -classpath or -cp option.
2. In the directories that are specified in the CLASSPATH environment variable (If you have not specified the -classpath or -cp option)
3. In the currently directory (If you have not specified the -classpath or -cp option and the environment variable CLASSPATH is not set)

Online resource: For more detailed description on classpath, please see "Setting the class path" from java.sun.com.

Experimentation 3.1.j: Try "java -classpath .. Hello" to see if it still works. (Instead of single dot ., you specify double dots .. between -classpath and Hello. The double dot .. specifies a parent directory, C:\ in this example while single dot . specifies the current directory, c:\myjavaprograms in this example.) It should fail as following. It is because you set the classpath to a parent directory, C:\, which does not contain Hello.class file.

* C:\myjavaprograms>java -classpath .. Hello (this should fail because you are the parent directory C:\ as classpath here)
Exception in thread "main" java.lang.NoClassDefFoundError: Hello

Now try to copy the Hello.class file to the parent directory and try the above command again. You should see the following result. Try to think why this works.

* C:\myjavaprograms>move Hello.class .. (move the Hello.class to parent directory)
C:\myjavaprograms>java -classpath .. Hello (run the program using the classpath set to the parent directory)
Hello world
C:\myjavaprograms>java -classpath C:\ Hello (same as above, you the classpath explicitly)
Hello world
C:\myjavaprograms>java -classpath . Hello (this should fail because you no longer have Hello.class in the current directory)
Exception in thread "main" java.lang.NoClassDefFoundError: Hello

Important: As is mentioned above, you can set system wide classpath via CLASSPATH environment variable. This classpath gets applied system-widely meaning it gets applied to all Java programs running on that platform. Of course, you can override it via -classpath or -cp option when you run a particular program.

Experimentation 3.1.k: Try to set the environment variable CLASSPATH first to the directory that contains Hello.class file and then run the program as following. It should work.

* C:\myjavaprograms>set CLASSPATH=c:\myjavaprograms
C:\myjavaprograms>java Hello (You are going to experience the following Exception because you don't have Hello.class in the currently anymore since you moved it to a parent directory in the previous experimentation)
Exception in thread "main" java.lang.NoClassDefFoundError: Hello
C:\myjavaprograms>move ..\Hello.class . (So move the Hello.class back to the currently directory)
C:\myjavaprograms>java Hello
Hello world

Experimentation 3.1.l: Try to set the environment variable CLASSPATH to a bogus directory and then run the program as following:

* C:\myjavaprograms>set CLASSPATH=c:\tmp (set the CLASSPATH environment variable to a bogus directory, c:\tmp)
C:\myjavaprograms>java Hello (should fail since the c:\tmp directory does not contain Hello.class file)
Exception in thread "main" java.lang.NoClassDefFoundError: Hello
C:\myjavaprograms>java -cp . Hello (now you are overriding the CLASSPATH with your own classpath)
Hello world

Experimentation 3.1.m: Try to set the environment variable CLASSPATH to a set of directories and then run the program as following:

* C:\myjavaprograms>set CLASSPATH=c:\tmp;c:\myjavaprograms
C:\myjavaprograms>java Hello
Hello world

Important: As you've seen above, you can set the environment variable CLASSPATH to a set of directories. For Windows, you use semi-colon ; while on Solaris/Linux platform, you use colon : as a delimiter. You can also specify multiple directories when you specify -classpath or -cp option as following:

* C:\myjavaprograms>java -classpath c:\tmp Hello (this should fail since c:\tmp does not contain Hello.class file)
Exception in thread "main" java.lang.NoClassDefFoundError: Hello
C:\myjavaprograms>java -classpath c:\tmp;c:\myjavaprograms Hello (the classpath is set to two directories c:\tmp and c:\myjavaprograms - they will be searched in sequence)
Hello world
C:\myjavaprograms>java -classpath c:\tmp;. Hello
Hello world

Homework:

1. Modify, compile, and run the Hello program so that it prints the following

* "This is my first Java program" (instead of "Hello world")

2. Please play around with the classpath settings with -classpath or -cp option and CLASSPATH environment variable.

No comments:

Post a Comment