Command Line Changes From 1.1 to 1.2
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
rt.jar. We also use the term "class path" to refer to the search path set by
-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.
The class path has a default value and can be set by
CLASSPATH. In 1.1, it worked as follows:
This behavior for
- Class path default - The default value of the class path was (1) the path where Java platform classes resided (
rt.jar), and (2) the current working directory (".", read as "dot").
CLASSPATH- If the environment variable
CLASSPATHwas set, then the class path would (1) continue to contain
rt.jarjust 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)
rt.jarand (2) application classes.
-classpathwas unfortunate because it meant users had to spell out the path to
classes.zip:% java -classpath /jdk-path/lib/classes.zip:/app/classes ApplicationWe say unfortunate because this is inherently error-prone; the onus is on the user to ensure that the
javacommand and the
classes.zipwere from the same JDK version. We ourselves have spent time debugging problems where a 1.1.4
javawas 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
-classpathoption in 1.2 has taken on the same meaning as the
CLASSPATHenvironment 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
printlnstatements to understand how the class works. In 1.2, these users would not be able to use the
-classpathoption to set the path to Java platform classes, as was possible in 1.1. For such uses, the
-Xbootclasspathoption must be used in 1.2.
Note 1 - Contrary to the bulleted statement above, we have seen users explicitly placing the path to
CLASSPATHenvironment variable, though this was not at all required.
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
-classpathoption or the
In JDK 1.2, there are three search paths that are used to find classes:
- The first place where
javalooks 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.
- The second place where
javalooks for classes is the extension directories. The list of directories can be examined by calling
- The third and last place where
javalooks for classes is the application classpath. The value of this path can be examined by calling
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
-classpathoption 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.
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
-Xbootclasspathoption -- this is a big change from 1.1 where
-classpathprovided this functionality. Consider this example:% java -Xbootclasspath:/my/bootclasses:/jre/lib/rt.jar MyApplication
In this example, the
javacommand searches the paths provided by
-Xbootclasspathto find the Java platform classes. It first searches the directory
/my/bootclassesbefore 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,
javacsupports a similar option
-bootclasspathwhich 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
-Xbootclasspathoption may not be used override parts of
rt.jarwhen 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
oldjavacommand. If you are not using
oldjava, then make sure that unmodified
rt.jarand (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 classloaderThe 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 MyApplicationThis command causes a sequence of steps, giving each classloader in turn a chance to load the application classes. First, the
javacommand asks the application classloader (the one that uses the
-classpathvalue) 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
-Xbootclasspathto 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.dirsoptions to disturb the default path). Finally, the application classloader ends up finding and loading
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.
In JDK 1.2,
CLASSPATHenvironment 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
.htmlfile in a place different from your
.classfiles. In JDK 1.1, you could set your
appletviewerwould 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
CLASSPATHthe way JDK's
appletviewerdoes, you have the same problem that you have when using 1.2. The classes referred to by an applet must be either:
You cannot, and should not, expect a user of your applet to set their
- Java platform classes (such as
java.lang.String) which are present in a browser, or,
- classes that can be downloaded from the applet's
CLASSPATH, and even if they did, their browser might choose to ignore it. Consequently,
appletviewernow does the same thing that a browser would.
One nice thing about 1.1
CLASSPATHwas that you could grab a third party library (say a
mailx.jarproviding some email related functionality), place it on your
CLASSPATHand 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. (
CLASSPATHis only a development time solution.)
In 1.2 some options are prefixed with
-Xwhereas 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
javalauncher internally translates
-Xms10m, so you could still use the old
-ms10moption, 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.
javadocwould find both source files and class files in the paths specified in the
CLASSPATHenvironment variable. For example, suppose you compiled
foo/bar/FooBar.javaand the class
FooBarrelied on a
Helperclass, then javac would attempt to find the source file
Helper.javain 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.javaIn 1.2, these tools still look in
CLASSPATHfor source files unless the
-sourcepath <path>option is included -- then it looks only in
<path>for source files, and the
CLASSPATHis 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.