next up previous contents
Next: Basic Java syntax Up: Java Interlude 1 Quick Previous: Structure of a Java   Contents

Compiling and running Java programs

The java compiler is invoked using javac. Though our Java program may consist of several classes, it is sufficient to invoke javac on the class containing the static method main where we want the execution to begin. In the simple example above, we would write

  javac helloworld.java

Note that we have to supply the full filename, with the extension .java, to javac.

The Java compiler will automatically compile all additional classes that are invoked (transitively) by the current class being compiled. Each compiled class is stored in a file with the extension .java replaced by .class. In our simple example, we get a single new file called helloworld.class.

To get the full effect, try splitting the example into two classes (in two separate files), as follows, and see what happens when you compile helloworld.java:

  class helloworld{
    public static void main(String[] args){
      auxclass.printit("Hello world!");
    }
  }

  class auxclass{
    public static void printit(String s){
      System.out.println(s);
    }
  }

The Java compiler does not produce executable machine code for the underlying architecture, unlike, say, gcc. Instead, Java programs execute on a uniform underlying virtual machine called the Java Virtual Machine (JVM). The compiler produces JVM machine code, also called JVM bytecode.

To run the program, we need an interpreter--that is, an implementation of the JVM. This is invoked using the command java. We write

  java helloworld

to load the compiled file helloworld.class into the JVM interpreter and execute it. (Note that we should not give the extension .class in this case, unlike when we invoked the compiler javac!)

The fact that Java programs run under a uniform ``artificial'' environment (the JVM) on all architectures and operating systems makes it possible for Java to achieve a higher degree of standardization than most other programming languages--for instance, there is no ambiguity about the size of an int, unlike C. Moreover, since the JVM is in complete control, more exhaustive error reporting and handling is possible for runtime errors such as array bound overflows. Finally, dynamic storage management is significantly simplified by the incorporation of an automatic garbage collector in the JVM to reclaim freed memory, removing the peril of ``memory leaks''. Of course, there is a performance penalty, but that is another story.


next up previous contents
Next: Basic Java syntax Up: Java Interlude 1 Quick Previous: Structure of a Java   Contents
Madhavan Mukund 2004-04-29