This chapter is an introduction to the software development tools contained in the Java Developer's Kit (JDK). It explains what each tool does and how it is used with the other tools in the toolkit, and shows you how to operate each tool and work with its command-line options. In the last section of this chapter, you'll learn how to run the demo applets included in the JDK.
This chapter has a dual purpose-it serves both as an initial introduction to the JDK and as a JDK reference manual. When reading this chapter for the first time, just try to understand how each of the JDK programs is used. Do not worry about learning all the options that are available to you. These options are illustrated via sample programs during the course of this book. Many of these options are useful only in special circumstances that you might never encounter. When you are working on later chapters, you can refer to this chapter for a full description of the options used in a programming example.
The purpose of the JDK is to provide a complete set of tools for
the development, testing, documentation, and execution of Java
programs and applets. The JDK provides tools that support each
of these activities, and more. It consists of the following seven
|javah||C header file generator|
Usually, you will write Java programs by using a text editor to develop Java source files. These files consist of source code packages that declare Java classes and interfaces. Source files use the .java extension.
The Java compiler, javac, is used to convert the source files into files that can be executed using the Java interpreter. These files are referred to as bytecode files and end with the .class extension.
The Java interpreter, java, executes classes from the bytecode (.class) files. It verifies the integrity, correct operation, and security of each class as it is loaded and executed, and interacts with the host operating system, windowing environment and communication facilities to produce the desired program behavior.
The debugger, jdb, is like the interpreter in that it executes Java classes that have been compiled into bytecode files, but it also provides special capabilities to stop program execution at selected breakpoints and to display the values of class variables. These capabilities are very useful in finding programming errors.
The disassembler takes the bytecode files and displays the classes, fields (variables), and methods that have been compiled into the bytecodes. It also identifies the bytecode instructions used to implement each method. The disassembler is a handy tool for recovering the source code design of those compiled Java classes for which no source code is available-for example, those that you would retrieve from the Web.
The applet viewer, appletviewer, displays Java applets contained within Web pages, located on your local file system, or at accessible websites. It is used to test applets that you develop.
The automated documentation tool, javadoc, is used to convert portions of Java source files into Hypertext Markup Language (HTML) files. HTML is the language used to write Web pages. The HTML files generated by javadoc document the classes, variables, methods, interfaces, and exceptions contained in Java source files based on special comments inserted into these files.
The C header file tool, javah, is used to generate C-language header and source files from a Java bytecode file. The files generated by javah are used to develop native methods-Java classes that are written in languages other than Java.
Figure 3.1 shows how each of these programs is used and how it interfaces with other programs within the JDK.
Figure 3.1 : How the programs of the JDK interact.
The Java compiler is used to translate Java source code files into bytecode files for execution by the Java interpreter. The source code files must end with the .java extension. They are translated into files with the same name, but with the .class extension.
For example, suppose the file test.java is located in
the c:\myfiles\source directory. To compile test.java,
change directories to c:\myfiles\source and enter the
command javac test.java. If your compilation is successful,
javac will create a file named test.class that
will contain the compiled bytecodes for test.java. If
your compile is unsuccessful, you will receive error messages
that will help you figure out what went wrong.
Set your PATH variable to the directory containing the JDK executable programs so that your operating system shell can find them. If you installed Java as described in the previous chapter, add c:\java\bin to your PATH.
In general, the Java compiler is executed as follows:
javac options java_source_file
Figure 3.2 illustrates the operation of the Java compiler. The compiler options are covered in the following sections. You get hands-on experience using javac to compile sample programs in Chapter 4, "First Programs: Hello World! to BlackJack."
Figure 3.2 : The operation of the Java compiler.
Every Java program uses classes that are defined outside of the program's source code file. Most often these external classes are contained in the Java API. However, you will also want to be able to reuse classes that you develop. The Java compiler must be able to locate these external classes in order to determine how to correctly compile code that references them. This section shows how the Java compiler and other programs in the JDK locate compiled classes. Understanding this information is important to using the JDK programs most effectively.
All Java declarations, such as classes, interfaces, and exceptions, are organized into logical units called packages. A class or interface must be identified as public to be used outside of its package. Only one public class or interface is allowed in a given source file. Interfaces are covered in Chapter 6, "Interfaces."
A compiled Java class is identified by its package name followed by a period (.) followed by its class name. For example, suppose you've developed and compiled a class called TestClass and it is contained in the TestAPI package. Your class would be identified by TestAPI.TestClass. The identifier, TestAPI.TestClass, is referred to as the fully qualified name or full name of the class TestClass. Figure 3.3 shows how package names are combined with class names to produce full class names.
Figure 3.3 : How class names are formed.
The full name of a class is used to locate the class with respect
to CLASSPATH. CLASSPATH is a system environment
variable containing a list of directories where Java packages
can be found. You convert the full name to a path offset by replacing
any periods in the name with backslashes (\) for Windows
95/NT systems and slashes (/) for UNIX systems. This
path offset is then combined with directories in CLASSPATH
to locate the bytecode (.class) files containing Java
Windows 95 and NT use backslashes (\) to indicate and separate directories. UNIX uses slashes (/). Because this book is oriented toward Windows 95, it uses the Windows 95 convention. Any other differences for UNIX systems are indicated as appropriate.
The package that contains a particular class is identified using the Java package statement. You'll learn how to use this statement in the next chapter. If no package is identified for a class, the class is put in a default package with no name. The full name for the class is then just the class name. Java assumes that the name of the bytecode file containing a class is the name of the class concatenated with the .class extension, as illustrated in Figure 3.4.
Figure 3.4 : The relationship between source code filenames, class names, and bytecode filenames.
CLASSPATH tells the JDK programs where to find Java classes. You must set the CLASSPATH to identify the location of your classes. You set CLASSPATH differently depending on your operating system. For Windows 95 and Windows NT, enter the following at the console command line to set your CLASSPATH:
A common CLASSPATH is .;c:\java;c:\java\lib\classes.zip. This tells the Java compiler and other JDK tools to use the current directory (.), the c:\java directory, and the file c:\java\lib\classes.zip as a base for finding Java class files. You would enter the following to set this CLASSPATH:
You can also put this statement in your AUTOEXEC.BAT file so that it will be set automatically each time you start a DOS shell. Windows NT users can use the System option in the Control Panel to set the CLASSPATH variable.
On UNIX systems that use the C shell, you set CLASSPATH using the setenv command. Java is typically installed under /usr/local on UNIX systems. Suppose that you want to set CLASSPATH to the current directory, your home directory, and the location of the JDK classes. You would enter the following at the shell prompt:
setenv CLASSPATH .:~:/usr/local/java/lib/classes.zip
For systems that use the Bourne Again shell (bash), you would enter the following at the shell prompt:
UNIX systems use the colon (:) to separate path elements. Windows 95 and NT use the semicolon (;).
CLASSPATH can also be set from the javac command line using the -classpath option. For example, to compile test.java with the .;c:\otherclasses path, you would use the following command line:
javac test.java classpath .;c:\otherclasses
The CLASSPATH set by the classpath option is temporary and only applies to the current file being compiled.
Normally, javac will put the .class bytecode file that it generates in the same directory as the .java source file that it compiles. You can change this using the d option. For example, to put the test.class file generated by compiling test.java in the c:\classes directory, you would use the following command:
javac d c:\classes test.java
The d option does not affect CLASSPATH.
The Java debugger needs additional information to be placed in .class files in order to support enhanced debugging operations. Normally, only information about line numbers is inserted in .class files. Additional information about local variables is produced as the result of using the g option. For example, the following produces the test.class file with additional debugging information included:
javac g test.java
The bytecode files produced by Java are usually not optimized for execution speed. Optimized files are generally larger, and this is undesirable for some applications, such as Java applets, which may be downloaded over slow Internet connections.
Optimization for execution speed can be turned on using the O option. This results in inline expansion of code, where possible, to reduce delays associated with loading and calling certain methods. Static, final, and private methods are optimized via inline expansion. For example, the following will optimize the test.class file for speedier execution:
javac O test.java
Sometimes your .java files will contain code that could lead to potential errors. The compiler will warn you about these problem areas. If you do not want to see these warnings, you can turn them off using the nowarn option. For example, the following command will suppress warnings from being generated when compiling test.java:
javac nowarn test.java
If you want more detailed information about the compiler's operation, verbose mode is for you. When verbose mode is turned on, the compiler identifies the source files that it compiles and the .class files that it loads in order to compile these files. Verbose mode is turned on using the verbose option. For example, the following will compile test.java and display information on what .class files are loaded during the compilation:
javac verbose test.java
The Java interpreter executes the bytecode files produced by the Java compiler. It is invoked using the java command, as follows:
java options class arguments
class is the full name of the compiled Java class generated by the Java compiler. In order for the compiler to locate and execute the class, the class must meet the following requirements:
The program arguments are optional parameters that are passed to the main method of the class that is executed. They are analogous to command-line arguments that are passed to C and C++ programs. The arguments are processed by the class's main method and not by the Java interpreter. For example, suppose that you developed a Java class called TestClass with a main method that merely displayed the arguments passed to it. Also, assume that TestClass is in the TestAPI package. The command
java TestAPI.TestClass 1 2 3
would merely print the numbers 1, 2, and 3.
Interpreter options are used to control different aspects of the interpreter's operation. These options are covered in the following subsections.
The Java interpreter has a classpath option that is identical to that of the compiler. It is used to temporarily change CLASSPATH for the duration of the class being executed. For example, the following will result in the execution of the main method of the compiled TestClass located in the file c:\other\TestAPI.TestClass.class:
java classpath c:\other TestAPI.TestClass
The Java interpreter has a useful option that checks to see if the source code file of the class to be executed has been modified since the last time that it was compiled. This option is the checksource option and is identified with cs or checksource. If the date/time of modification of the source code file is more recent than that of the bytecode file, then the source code file is recompiled before the specified class is executed.
For example, suppose you developed and compiled the TestClass class, and then later in the day made modifications to the TestClass.java file from which TestClass was compiled. You have the choice of recompiling TestClass.java and executing it using java or using the checksource option to accomplish compilation and execution with a single command. In the latter case, you could use
java cs TestAPI.TestClass
to perform both recompilation and execution.
The Java interpreter has three options to control the bytecode
verification of class files that it loads and executes:
|verify||Causes the interpreter to verify all code that it loads.|
|noverify||Causes the interpreter to skip all code verification.|
|verifyremote||Causes the interpreter to verify all code that is loaded via a classloader. This is the default operation of the interpreter.|
Bytecode verification is performed by the Java interpreter to ensure the security, integrity, and correctness of the code it executes. It consists of a series of tests that verify that the code can be safely executed. The advantage of verification is that it promotes security, safety, and reliability. The disadvantage is that it takes time to perform and, therefore, slows down overall program execution.
The default verifyremote option only applies verification to code that is loaded by a classloader. A classloader is a Java method that loads classes from remote systems into the local file system. The verifyremote option assumes that local classes are trustworthy and do not need to be verified, but remotely loaded classes are suspect and subject to verification.
Examples of using the verify options are
java verify TestAPI.TestClass
java noverify TestAPI.TestClass
java verifyremote TestAPI.TestClass
In the first case, all classes are verified as they are loaded. In the second case, no classes are verified. In the last case, only classes that are remotely loaded are verified.
The Java interpreter automatically allocates and deallocates memory resources as they are needed by Java programs. Memory is allocated as program objects are created and deallocated as the result of the Java garbage collector. The Java runtime system keeps track of objects that are created, monitors references to objects, and uses the garbage collector to free the memory associated with objects when no more references to the objects exist.
The garbage collector runs as a separate, low-priority background thread that executes when no other threads are active. It checks object references and frees those objects that are no longer in use. The garbage collector is not explicitly called by executing programs, but operates during periods of low activity. It is said to operate asynchronously with respect to program execution.
The noasyncgc option turns off asynchronous garbage collection. This prevents the garbage collector from being run except when a program calls it or the runtime system is out of memory. The noasyncgc option is generally used when a program calls the garbage collector directly. This only occurs in memory-intensive programs that require more direct control over memory resources.
The Java interpreter provides the verbosegc option for monitoring the operation of the garbage collector. This option instructs the garbage collector to display a message to the console window when it frees a previously allocated object. It is used to monitor the operation of the garbage collector and is generally limited to program testing and debugging.
The Java interpreter allows you to change the values of predefined system parameters, referred to as system properties. These properties are used to specify the default values of variables that control the overall behavior of the Java runtime system.
You change or add a property using the D option. If a property specified by the D option does not currently exist in the system properties, it will be added to the list of defined properties. For example, the following will change the predefined os.name property from Windows 95 to Windows 96:
java Dos.name="Windows 96" TestAPI.TestClass
The following example adds the myProperty property to the list of system properties and gives it the value 1234:
java DmyProperty=1234 TestAPI.TestClass
You will learn how to use properties in Chapter 12, "Portable Software and the java.lang Package," when you explore the java.lang.System class.
The Java interpreter uses three major memory data structures to execute Java classes. These are the memory allocation pool, the Java code stack, and the C code stack.
The memory allocation pool is used to create objects for use in Java programs. It is controlled by the Java runtime system and the garbage collector. It is initially 1MB in size and has a maximum size of 16MB. The ms and mx options can be used to change the startup size and maximum size of the memory allocation pool. The memory size may be specified in bytes (default), kilobytes (using the k suffix), or megabytes (using the m suffix). For example, each of the following set the startup size of the memory allocation pool to 2MB and the maximum size to 8MB for the execution of TestClass:
java ms 2097152 mx 8388608 TestAPI.TestClass
java ms 2048k mx 8192k TestAPI.TestClass
java ms 2m mx 8m TestAPI.TestClass
In general, you should not attempt to change the default memory allocation pool values unless you have a very memory-intensive program or a computer with a less-than-average amount of RAM. The memory allocation pool must be larger than 1,000 bytes, and the default sizeis 3MB.
A Java code stack is created for every thread of a Java program. It is used to execute the bytecodes that comprise the Java thread. Chapter 37, "The Java Virtual Machine," provides a detailed description of the operation of the Java virtual machine. By increasing the size of the Java code stack, you provide more room for program instructions. By decreasing its size, you lower the memory requirements for your program. The default maximum size of the stack is 400KB. It can be changed using the oss option. It specifies the stack size in bytes, kilobytes, and megabytes as previously described for the memory allocation pool. For example, the following command will execute TestClass with only 250KB of Java code stack by program thread:
java oss 250k TestAPI.TestClass
The Java code stack size should be changed only if you have a program with an unusually large number of Java bytecode instructions or a computer with significantly limited RAM.
The C code stack is similar to the Java code stack. It is used to execute C code for a given thread. Its default size is 128KB and can be changed using the ss option. Its size must be greater than 1,000 bytes. For example, the following command will execute TestClass with 256KB of C code stack per program thread:
java ss 256k TestAPI.TestClass
The code stack is used to pass parameters to methods and to return the results of a method's calculations. It is similar to the memory functions used in calculators. Unless you plan to use a large amount of C-language native methods in your Java programs, you should never have to change the C code stack size.
The Java interpreter provides a number of options that support the debugging and testing of Java classes. First and foremost, java lets you attach the Java debugger to an executing Java program. The debug option tells the interpreter that you may want to attach the debugger to a Java session. The interpreter responds by displaying an agent password to the console window. This password must be entered when you attach the debugger to the active session. Use of the Java debugger is covered in the next section.
The verbose option for the Java interpreter is similar to that used with the compiler. This option causes the interpreter to identify all classes that are loaded during a program's execution. The verbose option can also be identified using v. For example, the command
java verbose TestAPI.TestClass
will display all classes that are loaded during the execution of TestClass.
There is a special version of the Java interpreter, java_g, that is oriented toward debugging. It includes the t option for tracing the instructions executed during the course of a program's execution. Even for very short programs, the amount of data generated by this option can be overwhelming. For example, if you enter
java_g t TestAPI.TestClass
you will receive a seemingly endless stream of information concerning the methods and instructions executed.
The Java debugger is used to monitor the execution of Java programs in support of debugging and test activities. It supports debugging of both locally executing and remotely executing Java programs.
The debugger can be started in two ways. In the first way, the debugger is started with a fully qualified class name. The debugger then calls the interpreter with the name of the class to be debugged. For example, the following command line starts the debugger with TestAPI.TestClass:
The debugger then invokes the interpreter to load TestAPI.TestClass. The interpreter returns control to the debugger before executing any instructions of TestClass. Interpreter options can be passed to the interpreter via the debugger command line. For example, the following command passes the D option to the interpreter:
jdb DmyProperty=1234 TestAPI.TestClass
The second way of starting the debugger is to attach it to a Java program that has already been started and is still running. The Java program to be debugged must have been started using the debug option, as described in the previous section. The password displayed as the result of starting the program to be debugged is used when attaching the debugger. For example, suppose you initiate execution of TestClass using the following command:
java debug TestAPI.TestClass
The interpreter will display a password to be used to attach the debugger to this session:
You can then attach the debugger to the still-running program using the command
jdb password 424ee3
This command will attach the debugger to the execution of TestClass, which will result in TestClass being suspended and the debugger taking over control of the program's execution.
The debugger may also be used to attach to a program that is executing on a remote computer. Suppose the TestClass program is run on a computer named remote.host.com and you want to debug it from my.host.com. You can do so by entering the following command line:
jdb host remote.host.com password 424ee3
After starting jdb, it will announce that it is initializing, identify the class that it is debugging, and print a simple prompt.
Once you are up and running, using the debugger, you can enter a question mark (?) at the prompt (>) to receive a list of available debugging commands.
Chapter 9, "Using the Debugger," provides a detailed description of how the debugger is used to debug sample programs.
The Java disassembler, javap, is used to reproduce the
source code of a compiled Java class. It takes the full name of
a class as its input and identifies the variables and methods
that have been compiled into the class's bytecodes. It also identifies
the source bytecode instructions that implement the class methods.
The data components of a class are referred to as either variables, fields, or field variables.
For example, suppose you have the bytecode file of a class that you want to reverse engineer. You can use the disassembler to identify the public fields and methods of the class. With this information, you will be able to figure out how to create instances of the class and access their methods.
The debugger is executed as follows:
javap options class
class is the full name of a Java class created by the Java compiler. The options control the type of information displayed by the disassembler.
When no options are used, only the public fields and methods of the class are displayed. If the p option is specified, the class's private and protected fields and methods are also displayed.
The c option is used to display the source bytecode instructions for the class methods.
The classpath option is used in the same way as it is with the compiler and interpreter.
Chapter 37 describes the Java virtual machine, the bytecode instruction set, and the use of the disassembler to analyze compiled classes.
The applet viewer is used to run Java applets and test the applets that you develop. The applet viewer creates a window in which the applet can be viewed. It provides complete support for all applet functions, including networking and multimedia capabilities.
You use the applet viewer as follows:
appletviewer options URL
URL is the universal resource locator of an HTML document containing the applets to be viewed. It can be located on a local machine or on any accessible website. If you just want to view an applet in a local HTML file, you can use the file's name instead of the entire URL of the file.
The debug option is the only option supported by the applet viewer. It is used to run the applet viewer, using jdb, to test and debug the applets contained in the selected HTML document.
The applet viewer is covered in Part VI, "Programming the Web with Applets and Scripts." The last section in this chapter shows how to use it to display the demo applets included with the JDK.
The Java documentation generator, javadoc, is the tool that created the excellent Java API documentation. This documentation can (and should) be obtained from Sun's Java website. Make sure that you get the documentation that is applicable to your Java release. You can find it by pointing your browser at http://java.sun.com and then clicking on the documentation icon.
The documentation generator is executed using either the name of a Java source code file, a full class name, or a package name. If it is executed with a class name or package name, it will automatically load the source code associated with the class or with all the classes in the package. If it is executed with a source code file, it will generate documentation for all classes and interfaces defined in the file.
The javadoc command line is as follows:
javadoc options package
javadoc options class
javadoc options source_file
The javadoc options are classpath, d, and verbose. The classpath option is the same as with the compiler and interpreter. The d option is used to specify the directory to which the generated HTML files are to be stored. It is similar to the d option used with the compiler. The verbose option results in a comprehensive display of the files that are loaded during the documentation-generation process.
Chapter 10, "Automating Software Documentation," shows how to use javadoc to automatically generate Java software documentation.
The header file generation tool, javah, is used to produce the C files required to develop native methods. It produces both header and source files. The header files contain C-language definitions that map to Java class definitions. The source files contain the stubs for C functions that map to class methods.
The command line used to invoke javah is
javah options class(es)
where class(es) refers to the full class names of the classes for which header files are to be generated. The javah options control the way the header files are generated:
See Chapter 38, "Creating Native Methods," for more information on this process.
The JDK comes with 32 sample applets that demonstrate the capabilities of the Java language and API. These applets are located in the java\demo directory of the JDK. If you installed the JDK under your C: drive, the applets will be located under c:\java\demo. The demo directory has 22 subdirectories, each containing one or more sample applets. To execute any of the applets, open an MS-DOS window and change to the subdirectory of c:\java\demo where the applet is located. In the subdirectory are files named example1.html, example2.html, and so on that are the HTML files containing links to the demo applets. Most of the subdirectories contain only a single example file. To execute the applet, just run appletviewer with the name of the HTML file as a command-line argument.
I'll walk you through a few applets so that you can get the hang of it. First, open an MS-DOS window and change directories to c:\java\demo\Animator. If you do a directory listing, you will see that it contains the following files:
Volume in drive C is ATHOME
Volume Serial Number is 1CE3-2551
Directory of C:\java\demo\Animator
. <DIR> 01-24-96 6:50p .
.. <DIR> 01-24-96 6:50p ..
IMAGES <DIR> 01-24-96 6:50p images
ANIMAT~1 JAV 21,410 10-13-95 10:23a Animator.java
ANIMAT~1 CLA 14,873 10-13-95 1:54a Animator.class
IMAGEN~1 CLA 706 10-13-95 1:54a ImageNotFoundException.class
PARSEE~1 CLA 410 10-13-95 1:54a ParseException.class
INDEX~1 HTM 3,411 10-13-95 1:54a index.html
AUDIO <DIR> 01-24-96 6:50p audio
EXAMPL~1 HTM 428 10-13-95 1:54a example2.html
EXAMPL~2 HTM 466 10-13-95 1:54a example3.html
EXAMPL~3 HTM 419 10-13-95 1:54a example1.html
8 file(s) 42,123 bytes
4 dir(s) 357,564,416 bytes free
Entering the command appletviewer example1.html results in appletviewer being launched with the example1.html file. The applet viewer will then load and display any applets pointed to by the HTML file. (See Figure 3.5.)
Figure 3.5 : The applet viewer.
This applet displays an animation of the Duke, a kind of mascot of the Java project. As the Duke waves to you, an audio file is played in the background.
My favorite Duke applet is located in the UnderConstruction directory. Change to this directory using the command cd ..\UnderConstruction and run the applet using the command appletviewer example1.html. The applet shows the Duke operating a jackhammer and plays the sound of the jackhammer in the background. (See Figure 3.6.)
Figure 3.6 : Duke operating a jackhammer applet.
Now change to the BouncingHeads subdirectory and run the command appletviewer example1.html. You'll see images of a person's head bouncing around the screen, complete with background music and occasional grunting sounds. (See Figure 3.7.) This applet shows how Java can combine several multimedia features into a single applet with more than adequate runtime performance.
Figure 3.7 : The BouncingHeads applet.
Finally, change to the TicTacToe subdirectory and use the applet viewer to run the example1.html file. See if you can figure out how to beat the applet-it can be done! (See Figure 3.8.)
Figure 3.8 : The TicTacToe.
You can experiment with the rest of the demo applets by changing to the subdirectory containing the applet and running appletviewer with the appropriate HTML file.
You have covered a lot of information in this lesson. You have studied the tools of the Java Developer's Kit and learned what each tool does and how it is used with the other tools in the JDK. You have learned how to operate these tools and work with their command-line arguments. Finally, you have had a little fun by running the demo applets that come with the JDK. In Chapter 4 you'll start programming. You'll code, compile, and execute four simple programs that illustrate the basic elements of the Java language.