站内搜索: 请输入搜索关键词
当前页面: 在线文档首页 > JDK 5 Documentation v1.2.2, Java 2 SDK 英文文档

Command Line Changes From 1.1 to 1.2 - JDK 5 Documentation v1.2.2, Java 2 SDK 英文文档

Command Line Changes From 1.1 to 1.2

JDK Tools

Introduction

This document summarizes a few important changes in command line options between JDK1.1 and JDK1.2 tools. Its target audience is those already familiar with the command line options of JDK1.1 tools.

Please note that every effort has been made to keep the options in JDK1.2 backwards compatible with the options in JDK1.1, where possible. The purpose of this document is to provide you with a quick overview of what has changed, and to outline the motivation behind the changes. We hope that understanding our motivations will help you better use the new features.

Throughout this document we use the term "Java platform classes" to refer to classes that belong to the Java platform, as specified in the Java API Specification, such as ava.lang.String. These reside in classes.zip or rt.jar. We also use the term "class path" to refer to the search path set by CLASSPATH and -classpath (which has a different meaning in 1.1 and 1.2).

Although the examples in this document are Solaris oriented, they apply equally to Windows, after the slashes and prompts have been appropriately changed.

Changes to CLASSPATH and -classpath

The class path has a default value and can be set by -classpath or CLASSPATH. In 1.1, it worked as follows:

  • Class path default - The default value of the class path was (1) the path where Java platform classes resided (classes.zip or rt.jar), and (2) the current working directory (".", read as "dot").
  • CLASSPATH - If the environment variable CLASSPATH was set, then the class path would (1) continue to contain classes.zip or rt.jar just the like default plus (2) the newly set value instead of the current working directory. [See Note 1]
  • -classpath - If the option -classpath <path> was used, then <path> had to explicitly contain both (1) classes.zip or rt.jar and (2) application classes.
This behavior for -classpath was unfortunate because it meant users had to spell out the path to classes.zip:
 % java -classpath /jdk-path/lib/classes.zip:/app/classes Application
We say unfortunate because this is inherently error-prone; the onus is on the user to ensure that the java command and the classes.zip were from the same JDK version. We ourselves have spent time debugging problems where a 1.1.4 java was trying to run 1.1.3 classes.zip, and this does not work because the native methods do not match.

The good news is that the -classpath option in 1.2 has taken on the same meaning as the CLASSPATH environment variable in 1.2, so you can now conveniently omit having to spell out the path to Java platform classes:

 % java -classpath /app/classes Application

Some developers like to temporarily modify individual Java platform classes such as java/util/Vector.class, for purposes such as adding println statements to understand how the class works. In 1.2, these users would not be able to use the -classpath option to set the path to Java platform classes, as was possible in 1.1. For such uses, the -Xbootclasspath option must be used in 1.2.

Note 1 - Contrary to the bulleted statement above, we have seen users explicitly placing the path to classes.zip in their CLASSPATH environment variable, though this was not at all required.

New Class Search Paths

The earlier section showed that in JDK1.1, there was one search path used to find classes; its value could be set either through the -classpath option or the CLASSPATH environment variable.

In JDK 1.2, there are three search paths that are used to find classes:

  1. The first place where java looks for classes is the bootstrap classpath. The value of this path can be examined by calling System.getProperty("sun.boot.class.path"). Note that the prefix "sun." shows that, at least for now, this property is specific to Sun's implementation.
  2. The second place where java looks for classes is the extension directories. The list of directories can be examined by calling System.getProperty("java.ext.dirs").
  3. The third and last place where java looks for classes is the application classpath. The value of this path can be examined by calling System.getProperty("java.class.path").

For a discussion of the new "extension directories" feature mentioned in item 2, refer to javac and The Extensions Framework documentation.

In 1.2, the argument you specify with the -classpath option is the value of the application classpath; it should contain the path to classes that constitute your application. The bootstrap classpath contains the path to Java platform classes that are contained in a file named rt.jar. This is discussed in the next section.

New Options to Search for Boot Classes: -Xbootclasspath, -bootclasspath

NOTE - For a description of what the leading "X" means in an option, see Standard vs. Non-standard Options.
-Xbootclasspath - As mentioned, the bootstrap classpath contains the path to Java platform classes that are contained in rt.jar. If you need to override the location where Java platform classes are found, you must use the -Xbootclasspath option -- this is a big change from 1.1 where -classpath provided this functionality. Consider this example:
 % java -Xbootclasspath:/my/bootclasses:/jre/lib/rt.jar MyApplication 

In this example, the java command searches the paths provided by -Xbootclasspath to find the Java platform classes. It first searches the directory /my/bootclasses before searching through rt.jar. If you wanted to add debugging statements to java/util/Vector.class, you would place the modified class file under /my/bootclasses. This modified version would be found first, the search would then stop and this version would be loaded.

-bootclasspath - In addition, javac supports a similar option -bootclasspath which can be used to change the platform classes you are compiling against. This is most useful if you need to take advantage of the bug fixes in 1.2 javac to compile a 1.1 application. Please refer to that option for detailed instructions on how to do this.

Here are some relevant notes for both options:

  • Avoid overriding Java platform classes - The JRE re-distribution license does not allow replacing parts of rt.jar. So the -Xbootclasspath option may not be used override parts of rt.jar when you are re-distributing the JRE with an application. When re-distributing, if there is a need to place your application on the bootclasspath, we recommend using the oldjava command. If you are not using oldjava, then make sure that unmodified rt.jar and (the optional) i18n.jar, are placed first on -Xbootclasspath before your application classes. For example:
        # If app needs to be deployed on -Xbootclasspath, then use: 
        % java -Xbootclasspath:/jre/lib/rt.jar:/app/classes Application
    
        # instead of accidentally overriding rt.jar:
        % java -Xbootclasspath:/app/classes:/jre/lib/rt.jar Application
       
  • Our implementation of class path searching - The discerning reader is bound to ask "How are all these paths tied together by the implementation of java?" We'll resist the temptatation to say, "the answer is beyond the scope of this document," but instead present a short version of the story.

    1.2 introduces the notion of a parent classloader. A well-behaved classloader in 1.2 always checks to see if its parent can load the class before it uses its own mechanisms (such as paths it might have been asked to look at) to locate a class.

    The Java runtime has three classloaders, where a parent classloader is shown above its child:

          bootstrap classloader
                   |
          extension classloader
                   |
         application classloader
    
    The bootstrap classloader searches for classes only on the bootclasspath and on no other path. Likewise, the extension classloader searches in the extensions loaded from extdirs, and the application classloader searches only on the application class path.

    Say, you launch your application with the following command line:

       % java -classpath ~/classes MyApplication
    
    This command causes a sequence of steps, giving each classloader in turn a chance to load the application classes. First, the java command asks the application classloader (the one that uses the -classpath value) to load MyApplication. However, rather than trying to load this class, the application classloader asks its parent, the extension classloader, to load the class, which in turn, likewise asks its parent, the bootstrap classloader, to load the class. The bootstrap classloader is built into the virtual machine and has no parent; it attempts to load the class from the bootstrap classpath. Since the bootstrap classloader will not find MyApplication (we did not use -Xbootclasspath to disturb the default path), it allows the extension classloader to try to load the class, which also will not find the class (since we did not use -Djava.ext.dirs options to disturb the default path). Finally, the application classloader ends up finding and loading ~/classes/MyApplication.class.

    It is such parenting that produces the order "bootstrap first, extensions next, applications last" when searching for classes. For more information we again refer you to the The Extensions Framework documentation.

oldjava

oldjava

Appletviewer No Longer Uses CLASSPATH

In JDK 1.2, appletviewer ignores your CLASSPATH environment setting (which it did not ignore in 1.1). Though this sounds like a drastic change, this is the semantics you really want when testing your applets.

Let us consider an example that worked in JDK 1.1, but will not work in JDK 1.2. Say you placed your .html file in a place different from your .class files. In JDK 1.1, you could set your CLASSPATH at the .class files, and appletviewer would pick them up.

   # Foo.class and foo.html are in different directories.
   % ls /home/user/htmls /home/user/classes 
   /home/user/classes:
   Foo.class
     
   /home/user/htmls:
   foo.html

   # Foo.class is NOT in applet's codebase:
   % cat /home/user/htmls/foo.html
   <applet code=Foo height=100 width=100></applet>

   # Can an applet use a class outside its codebase?
   % setenv CLASSPATH /home/user/classes

   # Works in 1.1.
   % /1.1.7/bin/appletviewer /home/user/htmls/foo.html

   # ClassNotFoundException in 1.2!
   % /1.2/bin/appletviewer /home/user/htmls/foo.html

Why did we change what looks like reasonable behavior? Look more closely. When an applet runs in a browser which does not honor CLASSPATH the way JDK's appletviewer does, you have the same problem that you have when using 1.2. The classes referred to by an applet must be either:

  • Java platform classes (such as java.lang.String) which are present in a browser, or,
  • classes that can be downloaded from the applet's codebase.
You cannot, and should not, expect a user of your applet to set their CLASSPATH, and even if they did, their browser might choose to ignore it. Consequently, appletviewer now does the same thing that a browser would.

One nice thing about 1.1 appletviewer honoring CLASSPATH was that you could grab a third party library (say a mailx.jar providing some email related functionality), place it on your CLASSPATH and your applet could refer to the classes in mailx.jar. In order to get the same convenience in JDK 1.2, we recommend the use of The Extensions Framework, which, unlike CLASSPATH, is a deployment solution. (CLASSPATH is only a development time solution.)

Standard vs. Non-standard Options

In 1.2 some options are prefixed with -X whereas others are not. In 1.1, if you needed to set the startup heap size of the virtual machine to 10MB, you would say:

    % java -ms10m Application

In 1.2, we recommend that you express the same option with a -X.

    % java -Xms10m Application

The motivation here, as you probably guessed, is that 1.2 distinguishes between options that can apply to all virtual machines, as opposed to options that are specific to a particular virtual machine's implementation. We expect all virtual machines will allow setting a classpath, but we can't expect all virtual machines to support initial heap size.

In the long run, as more compiler and virtual machine vendors support the same standard options, replacing a compiler won't require any changes to your makefiles, or replacing a virtual machine for a server application you launched through a script will need no modifications to the script.

Note however that for backwards compatibility, the 1.2 java launcher internally translates -ms10m to -Xms10m, so you could still use the old -ms10m option, but we recommend that you do use the newer syntax.

For the current list of standard options, please type:

    % java -help
    % javac -help

For the current list of non-standard options, please type:

    % java -X
    % javac -X

A note to vendors -- this separation of command line options into standard and non-standard ones is orthogonal to, and bears no relation with, conformance requirements. As stated earlier, we just hope that users' lives will be eased in the long run if standard options become a de facto standard for options that makes sense.

New Option to Search for Source Files: -sourcepath

In 1.1, javac and javadoc would find both source files and class files in the paths specified in the CLASSPATH environment variable. For example, suppose you compiled foo/bar/FooBar.java and the class FooBar relied on a Helper class, then javac would attempt to find the source file Helper.java in your CLASSPATH:
    % ls /tmp/foo/bar/*.java
    /tmp/foo/bar/FooBar.java   /tmp/foo/bar/Helper.java

    # Error because javac can't find Helper.class or Helper.java
    % /1.1.7/bin/javac /tmp/foo/bar/FooBar.java
    /tmp/foo/bar/FooBar.java:3: Superclass foo.bar.Helper of ... not found.

    % setenv CLASSPATH /tmp

    # Works because javac snooped in CLASSPATH for source files
    % /1.1.7/bin/javac /tmp/foo/bar/FooBar.java
In 1.2, these tools still look in CLASSPATH for source files unless the -sourcepath <path> option is included -- then it looks only in <path> for source files, and the CLASSPATH is not searched for source files:
    % setenv CLASSPATH /tmp

    # This still works in 1.2: 
    % /1.2/bin/javac /tmp/foo/bar/FooBar.java

    # But it doesn't work if you use -sourcepath
    % /1.2/bin/javac -sourcepath . /tmp/foo/bar/FooBar.java
    /tmp/foo/bar/FooBar.java:3: Superclass foo.bar.Helper ... not found.


Last modified: Thu Nov 19 10:23:16 PST