Command Line Changes
|
SDK Tools |
This file summarizes changes some changes to the way the Java 2 SDK's tools work as compared to the tools that ship with the JDK 1.1.x software. The changes described here are not changes between versions 1.2 and 1.3 of the Java 2 SDK.
CLASSPATH
and
-classpath
-Xbootclasspath
,
-bootclasspath
oldjava
CLASSPATH
-sourcepath
This document summarizes a few important changes in command line options between JDK1.1 and Java 2 SDK 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 Java 2 SDK 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
orrt.jar
. We also use the term "class path" to refer to the search path set byCLASSPATH
and-classpath
.Although the examples in this document are Solaris oriented, they apply equally to Windows, after the slashes and prompts have been appropriately changed.
In the Java 2 Platform, the value of the java.home property is the directory that houses the runtime environment. For the Java 2 SDK, this is the jdk1.3\jre directory. In the case of the Java 2 Runtime Environment, it is the top-level directory, usually C:\Program Files\JavaSoft\JRE\1.3.In JDK 1.1.x software, the java.home property value referred to the installation directory.
CLASSPATH
and -classpath
The class path has a default value and can be set by
-classpath
orCLASSPATH
. 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 (
classes.zip
orrt.jar
), and (2) the current working directory (".", read as "dot").CLASSPATH
- If the environment variableCLASSPATH
was set, then the class path would (1) continue to containclasses.zip
orrt.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
orrt.jar
and (2) application classes.-classpath
was unfortunate because it meant users had to spell out the path toclasses.zip
:% java -classpath /sdk-path/lib/classes.zip:/app/classes ApplicationWe say unfortunate because this is inherently error-prone; the onus is on the user to ensure that thejava
command and theclasses.zip
were from the same JDK version. We ourselves have spent time debugging problems where a 1.1.4java
was trying to run 1.1.3classes.zip
, and this does not work because the native methods do not match.The good news is that the
-classpath
option as used by the Java 2 SDK tools has taken on the same meaning as theCLASSPATH
environment variable in the Java 2 SDK, so you can now conveniently omit having to spell out the path to Java platform classes:% java -classpath /app/classes ApplicationSome developers like to temporarily modify individual Java platform classes such as
java/util/Vector.class
, for purposes such as addingprintln
statements to understand how the class works. In the Java 2 Platform, 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 the Java 2 SDK.Note 1 - Contrary to the bulleted statement above, we have seen users explicitly placing the path to
classes.zip
in theirCLASSPATH
environment 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
-classpath
option or theCLASSPATH
environment variable.In the Java 2 SDK, there are three search paths that are used to find classes:
- The first place where
java
looks for classes is the bootstrap classpath. The value of this path can be examined by callingSystem.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
java
looks for classes is the extension directories. The list of directories can be examined by callingSystem.getProperty("java.ext.dirs")
.- The third and last place where
java
looks for classes is the application classpath. The value of this path can be examined by callingSystem.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 the Java 2 SDK, 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 namedrt.jar
. This is discussed in the next section.
-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 inrt.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 MyApplicationIn 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 throughrt.jar
. If you wanted to add debugging statements tojava/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 the Java 2 SDK's 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 Java 2 Runtime Environment re-distribution license does not allow replacing parts of
rt.jar
. So the-Xbootclasspath
option may not be used override parts ofrt.jar
when you are re-distributing the Runtime Environment with an application. When re-distributing, if there is a need to place your application on the bootclasspath, we recommend using theoldjava
command. If you are not usingoldjava
, then make sure that unmodifiedrt.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.The Java 2 Platform introduced the notion of a parent classloader. A well-behaved classloader in the Java 2 SDK 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, thejava
command asks the application classloader (the one that uses the-classpath
value) to loadMyApplication
. 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 findMyApplication
(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
CLASSPATH
In the Java 2 SDK,
appletviewer
ignores yourCLASSPATH
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 the Java 2 SDK. Say you placed your
.html
file in a place different from your.class
files. In JDK 1.1, you could set yourCLASSPATH
at the.class
files, andappletviewer
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. % appletviewer /home/user/htmls/foo.html # ClassNotFoundException in the Java 2 SDK! % appletviewer /home/user/htmls/foo.htmlWhy 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 SDK'sappletviewer
does, you have the same problem that you have when using the Java 2 SDK. The classesreferred 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
codebase
.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
honoringCLASSPATH
was that you could grab a third party library (say amailx.jar
providing some email related functionality), place it on yourCLASSPATH
and your applet could refer to the classes inmailx.jar
. In order to get the same convenience in the Java 2 SDK, we recommend the use of The Extensions Framework, which, unlikeCLASSPATH
, is a deployment solution. (CLASSPATH
is only a development time solution.)
In the Java 2 SDK tooks, 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 ApplicationIn the Java 2 SDK, you should express the same option with a
-X
.% java -Xms10m ApplicationThe motivation here, as you probably guessed, is that the Java 2 SDK tools distinguishe 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 Java 2 SDK
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 -helpFor the current list of non-standard options, please type:
% java -X % javac -XA 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.
-sourcepath
In 1.1,javac
andjavadoc
would find both source files and class files in the paths specified in theCLASSPATH
environment variable. For example, suppose you compiledfoo/bar/FooBar.java
and the classFooBar
relied on aHelper
class, then javac would attempt to find the source fileHelper.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 % 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 % javac /tmp/foo/bar/FooBar.javaIn the Java 2 SDK, these tools still look inCLASSPATH
for source files unless the-sourcepath <path>
option is included -- then it looks only in<path>
for source files, and theCLASSPATH
is not searched for source files:% setenv CLASSPATH /tmp # This still works with the Java 2 SDK: % javac /tmp/foo/bar/FooBar.java # But it doesn't work if you use -sourcepath % javac -sourcepath . /tmp/foo/bar/FooBar.java /tmp/foo/bar/FooBar.java:3: Superclass foo.bar.Helper ... not found.