Monday, 11 May 2015

java : The Java Interpreter

Overview

The Java runtime interpreter is a stand-alone version of the Java interpreter built into Java-compatible Web browsers, such as Netscape Navigator. The runtime interpreter provides the support to run Java executable programs in the compiled bytecode class format. Because the interpreter doesn't directly provide any means to view graphical output, you are limited to using it to execute purely textual Java programs and applications that manage their own graphics. If you want to run graphical Java applets, you need to use either the Java applet viewer or a Java-compatible Web browser. The Java applet viewer is covered in the next chapter, "Using the Applet Viewer."

You can think of the runtime interpreter as exposing the bare essentials of the Java runtime system. Even though I use the term "bare essentials," the interpreter actually lets you do quite a lot. Essentially, you can run any Java programs that don't rely on the Appletclass. In fact, the statement earlier about not being able to run graphical programs isn't entirely true; you can run graphical Java applications-you just can't run Java applets. The difference between a Java application and a Java applet is that an application is responsible for creating and maintaining its own window if it requires the need for graphical output, whereas an applet relies on a Web browser to provide a window on which to display graphics. So, the Java interpreter is capable of executing both textual Java programs and graphical Java applications.

Usage

The runtime interpreter is a command-line tool for running Java programs and applications; Java applets require the graphics and display support of a Web browser. The syntax for using the Java runtime interpreter follows:
java Options Classname Arguments
The Classname argument specifies the name of the class you want to execute. If the class resides in a package, you must fully qualify the name. For example, if you want to run a class called SolveItthat is located in a package called Equations, you would execute it in the interpreter like this:
java Equations.SolveIt
When the Java interpreter executes a class, what it is really doing is executing the mainmethod of the class. The interpreter exits when the mainmethod and any threads created by it are finished executing. The main method accepts a list of arguments that can be used to control the program. Following is the definition of the mainmethod as specified by the Java language:
class DoIt {
  public static void main(String argv[]) {
    // do something
  }
}
Notice that main has a single parameter, argv, which is an array of String objects. This brings us to the Arguments argument for the runtime interpreter, which specifies the arguments passed into the main method. Any arguments passed to the runtime interpreter by Argumentsare accessible from the argvparameter in main. The following interpreter call passes two numeric arguments to the mainmethod in the DoIt class:
java DoIt 8 24

Options

The Options argument specifies options related to how the runtime interpreter executes the Java program. Following is a list of the most important runtime interpreter options:
-debug
-checksource or -cs
-classpath Path
-mx x
-ms x
-noasyncgc
-noverify
-ss x
-oss x
-t
-verbose or -v
-verbosegc
-verify
-verifyremote
-DPropertyName=NewValue
The -debug option starts the interpreter in debugging mode, which enables you to use the Java debugger (jdb) in conjunction with the interpreter.

The -checksource option causes the interpreter to compare the modification dates of the source code files and executable class files. If the source file is more recent, the class is automatically recompiled and the new bytecode executable is loaded.

The Java interpreter uses an environment variable, CLASSPATH, to determine where to look for user-defined classes. The CLASSPATHvariable contains a semicolon-delimited list of system paths to user-defined Java classes. Actually, most of the Java tools use the CLASSPATH variable to know where to find user-defined classes. The -classpathoption informs the runtime interpreter to override CLASSPATHwith the path specified by Path.

The -mx option enables you to modify the maximum size of the memory allocation pool, or garbage collection heap, used by the interpreter. By default, the pool has a maximum size of 16 megabytes (-mx 16m). x specifies the new maximum size of the pool, and it is measured in bytes by default. You also can specify x in either kilobytes or megabytes by appending the letter kor m respectively onto the value. Also, x must be greater than 1,000 bytes, meaning that the pool must have a maximum size of at least 1,000 bytes.
The -ms option is similar to the -mx option, except that it enables you to modify the initial size of the memory allocation pool rather than the maximum size. By default, the size of the pool is initially set to 1 megabyte (-ms 1m). x specifies the new initial pool size and is measured in bytes by default. As with the -mx option, you also can specify x in either kilobytes or megabytes by appending the letter kor m respectively onto the value. Additionally, x must be greater than 1,000 bytes.

The Java runtime system typically performs garbage collection automatically to make sure unneeded memory stays freed up. This takes place in an asynchronous thread that runs alongside other threads in the runtime system. The -noasyncgcoption alters this behavior by turning off asynchronous garbage collection. The result is that no garbage collection takes place unless it is explicitly called upon or the Java program runs out of memory. Incidentally, an explicit garbage collection can be forced by calling the gcmethod in the System class.

The -noverify option turns all code verification off, meaning that no bytecodes are processed by the bytecode verifier. Typically, the verifier verifies code loaded into the system using a class loader.
Every thread in the Java runtime system is given two stacks, one for Java code and one for C/C++ code. The presence of two stacks reflects the native code support in Java. The -ssoption enables you to alter the maximum stack size used by C code in a thread. The default C stack size is 128 kilobytes (-ss 128k). The xparameter specifies the new maximum size in bytes of the C stack, which must be greater than 1,000 bytes. You also can specify xin either kilobytes or megabytes by appending the letter kor m onto the value, respectively. Keep in mind that this option applies to all threads created during program execution.

Similar to the -ss option, the -oss option enables you to set the maximum stack size that can be used by the Java code in a thread. The default Java code stack size is 400 kilobytes (-oss 400k). The xparameter specifies the new maximum size in bytes of the Java stack, which must be greater than 1,000 bytes.

The -t option prints a trace of the bytecode instructions executed. This option works only with the non-optimized version of the Java interpreter, java_g. You learn about the non-optimized interpreter in a moment. The -t option generates a great deal of information that can give you a lot of insight into what is happening within a program. Of course, it would help if you had some understanding of Java bytecodes.
The -verbose option causes the interpreter to print a message to standard output each time a Java class is loaded. Similarly, the -verbosegcoption causes the interpreter to print a message each time a garbage collection is performed. A garbage collection is performed by the runtime system to clean up unneeded objects and to free memory.

The opposite of the -noverifyoption, the -verify option causes the interpreter to run the bytecode verifier on all code loaded into the runtime environment. The default function of the verifier is to only verify code loaded into the system using a class loader. This default behavior also can be explicitly specified using the -verifyremote option.

The -D option enables you to redefine property values. PropertyNamespecifies the name of the property you want to change, and NewValuespecifies the new value you want to assign to it.

The Non-Optimized Interpreter

Some distributions of the Java Developer's Kit include an alternate Java interpreter called java_g. This is a non-optimized version of the Java interpreter that executes Java bytecodes in a manner more suitable for debugging. If this interpreter is in your JDK distribution, be sure to use it when you are executing code within the Java debugger.

Bugs

The latest release of the Java Developer's Kit, which as of this writing is 1.02, contains some known bugs. More specifically, the following Java runtime interpreter bugs, which apply only to the Windows 95/NT platform, have been documented and acknowledged by the JavaSoft development team:
  • Programs using multiple threads never exit.
  • Ordered comparisons with NaNdon't return false.
  • Conversion from Double.MAX_VALUEto an integer doesn't produce Integer.MAX_VALUE.
  • Conversion from Double.MAX_VALUEto a long doesn't produce Long.MAX_VALUE.
The first bug is a pretty big problem and occurs whenever a program starts or creates multiple threads; any program that starts multiple threads will not exit. Fortunately, there is a workaround for this bug: either call System.exitwhen the last running thread is finished, or monitor the threads by calling Thread.join and force an exit yourself. Keep in mind that this problem, along with all the interpreter bugs, is apparent only on the Windows 95/NT platform.
The NaN constant defined in the Float and Doubleclasses represents a result that isn't a number. Because NaNisn't a number, any numeric comparisons made with it should always return false. However, the second bug causes the runtime interpreter to evaluate NaNas less than NEGATIVE_INFINITY, which allows for comparisons with it to return true.

The last two bugs listed deal with converting doubles to integer numbers. More specifically, Double.MAX_VALUEdoesn't result in Integer.MAX_VALUEor Long.MAX_VALUE when converted to an integer or long, respectively. 

No comments:

Post a Comment