Jikes User FAQ
This FAQ is for users of Jikes, the high-performance Open Source
Java compiler. It covers common questions about setting up and
using binary versions of Jikes, especially where things are
different from Sun's javac compiler.
If you are looking for information about installing Jikes from
source, or would like to get involved in Jikes development,
please see the Jikes Developer
FAQ.
1.
Where to I get Jikes?
2.
How do I use it? What options does it support?
3.
Why must I define CLASSPATH ? What is
JIKESPATH ?
4.
How do I control the compiler listing?
5.
What is incremental compilation?
6.
How do I use Jikes to generate dependencies for make?
7.
Why does Jikes reject a program that another compiler accepts,
or accept one that it rejects?
8.
What can I do if I don't get the same results when using class
files generated by Jikes?
9.
How do I report bugs?
If you use Linux, check the
distributions page for a list of Linux distributions known
to include Jikes as a standard package. For other platforms,
go to the
downloads page and look for an official binary version of
Jikes. A Zip file is provided for Windows users, just unzip
it and place the bin directory on your PATH.
If there isn't an official version for your operating
system, join the
jikes mailing list and search the archives. There might be
an unofficial port available, or someone else might be working
on one. If you're still out of luck, why not download the
source and try compiling it yourself? The
Developer FAQ has a lot of
information about compiling Jikes. Join the the
jikes-dev mailing list where other developers can help you
out.
Back to top
Invoke Jikes in the form:
jikes options filename...
Invoke Jikes with no arguments to see a short summary of the
arguments. Allowed options are:
-
-classpath path
-
Set classpath.
-
-d dir
-
Write class files in specified directory.
-
-debug
-
No effect (recognized for compatibility with many compilers).
-
-depend
-
Recompile all used classes.
-
-deprecation
-
Report on use of deprecated features.
-
-g
-
Generate
LocalVariableTable attribute.
-
-nowarn
-
Suppress warning messages.
-
-nowrite
-
Do not write any class files.
-
-O
-
Do not generate
LineNumberTable attribute.
-
-verbose
-
List files read and written.
-
-Xstdout
-
Write error messages to standard output.
-
++
-
Compile in incremental mode.
-
+B
-
Do not generate bytecode. This is used primarily for debugging
the compiler. The
-nowrite option generates byte
code but does not write it out.
-
+OLDCSO
-
As of Jikes 1.12, the default classpath search order
has changed to be more like
javac . Jikes
now searches all directories for a class or
java file, and then compares their dates to
determine if recompilation is necessary. The
+OLDCSO option is provided for backward
compatibility and causes Jikes to follow the classpath
search order used by older version of Jikes.
-
+D
-
List errors immediately in Emacs-form without buffering. This
is only needed if Jikes is crashing and you want to see errors
as soon as they are detected; ordinarily errors are sorted and
listed at the end of the compilation.
-
+DR=filename
-
Write report of dependencies to specified file.
-
+E
-
List errors in a machine readilbe form commonly used by Emacs to scan
for errors. By default errors are listed in a more human readable
form.
-
+F
-
Do full dependence check except for Zip and Jar files.
-
+M
-
Generate makefiles with dependencies.
-
+P
-
Generate pedantic listing.
-
+Tnn
-
Set tab width for listing error messages.
-
+U
-
Do full dependence check including Zip and Jar files.
-
+Z
-
Treat cautions as errors.
Jikes can be used to compile more than one file at a time, causing
a class file to be created for each Java source file. It is
possible that compilation of a file named early on in the argument
list will force the compilation of a file that is also named later
on; however, no file will be compiled more than once. Jikes
allows the same file to be named more than once; however, such
files are only compiled once:
jikes Test.java x.java Test.java
Jikes also accepts arguments starting with an at-sign (@). Such
arguments are taken be the name of a file, each line of which is
then processed as though it were itself an argument, except that
lines so read that begin with an at-sign are not processed
recursively. For example, the above command could also be written
as:
jikes @file.list
where file.list is a file containing the lines:
Test.java
x.java
Test.java
Back to top
You must have some version of the JDK or JRE to run Jikes, so
the compiler can access the standard class files. Note that
from version 1.1 of the JDK, you are not required to provide a
definition of CLASSPATH to run javac
and java . However, Jikes doesn't know what
version of the JDK you are using and so must be told how to
find the standard library files. This can be done in three
ways:
-
Provide a definition of
CLASSPATH ; for example,
in Windows using Sun's JDK, this takes the form of one of the
following
set CLASSPATH=.;C:\Java\lib\classes.zip (JDK 1.1)
set CLASSPATH=.;C:\jdk1.2.2\jre\lib\rt.jar (JDK 1.2)
set CLASSPATH=.;C:\Program Files\JDK1.3\jre\lib\rt.jar (JDK 1.3)
or with the IBM Developer Kit 2.0 (compatible with Sun's J2SE
version 1.3)
set CLASSPATH=.;C:\Program Files\IBM\Java13\jre\lib\rt.jar
or with Microsoft's SDK for Java 4.0 (after running
"clspack -auto ")
set CLASSPATH=.;C:\WINNT\Java\Classes\classes.zip
In Linux you would use
export CLASSPATH=.:/usr/local/jdk1.1.6/lib/classes.zip (JDK 1.1)
export CLASSPATH=.:/usr/local/jre1.1.6/lib/rt.jar (JRE 1.1)
export CLASSPATH=.:/opt/jdk1.3/jre/lib/rt.jar (JDK 1.3)
or for csh
setenv CLASSPATH .:/usr/local/jdk1.1.6/lib/classes.zip (JDK 1.1)
setenv CLASSPATH .:/usr/local/jre1.1.6/lib/rt.jar (JRE 1.1)
setenv CLASSPATH .:/opt/jdk1.3/jre/lib/rt.jar (JDK 1.3)
-
Always specify a value for the
-classpath option
on the command line; for example:
jikes -classpath .:/opt/jdk1.3/jre/lib/rt.jar ...
-
Use
JIKESPATH as discussed below.
Jikes allows the use of JAR files, which have the
standard "zip" format, provided that any contained
class files are stored either using no compression or
the default "DeflatedN" compression (also known as "method 8" in
zip-speak). Indeed, any item in the class path that is a not a
directory is assumed to be a file in zip format. The code used to
do the the uncompression is based on that used in
unzip532 from Info-ZIP, so we need to make the
following statement:
Jikes incorporates compression code from the Info-ZIP group.
There are no extra charges or costs due to the use of this code,
and the original compression sources are freely available from
Info-ZIP
on the Internet.
Jikes looks for a definition of JIKESPATH in the
environment before it looks for a definition of
CLASSPATH . If JIKESPATH is defined,
then its value is used when looking for a class file.
You should almost always include "." in the classpath;
omit it only if you understand the implications.
The order in which the classpath is searched can also be
selected using the +OLDCSO (old classpath
search order) option. As of Jikes 1.12, by default the same
behavior as javac is followed:
-
Find the
java file which occurs leftmost in the
classpath.
-
Find the
class file which occurs leftmost in the
classpath.
-
Use the more recent of these for compilation purposes.
If the +OLDCSO option is specified, Jikes
operates in a backward-compatible mode:
-
Jikes searches the classpath from left to right.
-
In a given directory, it finds the most recent
java or class file.
-
Jikes then uses the
java/class found in the
leftmost classpath entry for compilation purposes.
Back to top
Jikes does not produce a compiler listing in the usual sense, but
only writes out warnings, cautions, and errors.
A caution is more severe than a warning, but normally does not
prevent the writing of the class file. The +Z option
can be used to prevent the writing of a class file if any cautions
are detected.
A number of options select the kind and volume of the information
produced. They are -nowarn , -verbose ,
+E and +P . The first two are found in
most Java compilers: -nowarn requests that warning
messages not be written, -verbose requests a report
on the files, including source and class files, read and written
by the compiler.
The error kind option +E is used to select how error
messages are formatted, By default, error messages are written in
a long form with the part of the text the compiler is complaining
about underlined, and with detailed explanatory text. The
+E option requests a terser form, suitable for
automatic parsing by editors such as
Emacs
and
Epsilon.
For example, consider the mis-typed "hello world" example:
class hello {
public static void main(String[] args) {
system.out.println("hi there"); // should be System...
}
}
When +E is not used, the error is reported as
Found 1 semantic error compiling "hello.java":
3. system.out.println("hi there"); // should be System...
<-------->
*** Semantic Error: "system/out" is either a misplaced package name
or a non-existent entity.
With +E is used, the error is reported as:
hello.java:3:6:3:15: Semantic:"system/out" is either a misplaced
package name or a non-existent entity.
The initial part of each line contains several fields, separated
by colons, giving in order the file name, the starting line in the
file, the starting column in the starting line, the ending line,
and the column number in the ending line.
The pedantic option +P is used to request a complete,
pedantic listing. Just what is or is not pedantic depends in part
on email we have received in which users have noted that Jikes
complains about constructs that other compilers accept. (It is an
open question whether the other compilers choose not to report
this information, or whether they do not even discover it.)
Select this option for a detailed listing. Currently, the
following are only reported if +P is selected:
-
No type declarations:
This compilation unit contains no type declaration
-
Empty declarations, typically the result of an extraneous
semicolon:
An EmptyDeclaration is a deprecated feature that should
not be used
-
Attempt to overwrite a method with private access:
Note that the method ... in class ... does not override
the corresponding method with private access in class ...
-
Attempt to overwrite a method with default access:
The method ... in class ... does not override the
corresponding method with default access in class ...
-
Access to a type defined in an unnamed package. This message
is issued in response to the comment in section 7.4.2 of
the specification that "It is recommended that a Java system
provide safeguards against unintended consequences in
situations where compiliation units of named packages import
types from unnamed packages."
The type associated with this construct is (or depends on)
the type ... which is contained in an unnamed package
We say C depends on D if and only if the
constant pool for C contains a reference to
D . Types so referenced may need to be incorporated
into the compilation, either by reading their class file or
compiling a source file to produce the needed class file.
Incorporation is done as follows:
-
If there is no class file and there is a source file, then the
source file is compiled.
-
If there is no source file and there is a class file, then the
class file is read.
-
If both a class file and a source file exist, then the class
file is read only if it is newer than the source file; otherwise
the source file is compiled.
-
If there is no class file and no source file, an error is
reported.
(The effect of the -depend option is to always
compile a source file if there is one.)
By default, Jikes does not incorporate D unless it
must.
If +F is specified, and C does not
belong to a Zip or Jar file, the type D is
incorporated. Otherwise, D is incorporated only if
it must be.
If +U is specified, then D is always
incorporated.
The option +F directs the compiler to load all other
types that are referenced within a class file, and causes
recompilation of such files if their source file is more
up-to-date than the class file. Normally, other types are loaded
only if required for the current compilation.
The option -depend (which can also be written
-Xdepend , for 1.2 compatibility) directs the compiler
to always compile a source file, if one exists, instead of loading
its class file, even if it exists and is up-to-date.
Consider the following example:
// file A.java:
class A {
static public void main(String[] args) {
System.out.println("enter A");
B.message();
}
}
// file B.java:
class B {
static void message() {
System.out.println("enter B");
C.message();
}
}
// file C.java:
class C {
static void message() {
System.out.println("enter C");
}
}
If no class files exist, then
jikes A.java
results in compilation of A , B and
C .
If C.java (but not B.java ) is updated,
then
jikes A.java
results in compilation only of A . javac
does the same thing.
However, if C.java (but not B.java ) is
updated, then
jikes +F A.java
results in compilation of A and C .
It is always the case, independent of time-stamps of files, that
jikes -depend A.java
results in compilation of A , B and
C .
Note that
jikes -depend +F ...
has the same effect as
jikes -depend ...
i.e., +F will cause no more files to be compiled than
will -depend .
You can use +F to get reports of errors and warnings
resulting from the use of out-of-date or non-existent classes, at
the expense of increasing compilation time. By default, Jikes
assumes that class files placed in Zip and Jar files do not
reference files not contained in Zip or Jar files; the
+U option should be used when this is not the case.
Back to top
Most Java compilers support at least some form of dependency
resolution, where we say that file A depends
on file B if a change to B implies that
A must be rebuilt. For example, A.class
depends on the source file defining A , usually
A.java . The make program is commonly used
to record the dependencies and keep files up to date.
Many Java compilers support a simple make-like function, as
follows: when compiling A check all classes referred
to by A and recompile any whose class file is older
than the source file. This approach can cause problems if this
implies recompiling B , and B is up to date, but uses
C which is out of date, in which case C
may not be recompiled.
Jikes supports the option -depend and interprets it
as a request to recompile all used classes whether or not they are
up to date with respect to their source file.
Jikes also supports the option +F to force a fuller
check of dependency. If compilation of A.java
requires B.class then B will be
recompiled if it is out of date. Once B.class is
available, it is read, and any classes it references are also
checked for dependencies. This fuller check is more expensive,
but will not cause the problems that can result using the simple
approach used by many compilers.
Jikes can also be run in an incremental mode that works
as follows:
-
Open a window and compile your program using
jikes ++ Main.java
where Main.java denotes your root source file.
Jikes will then compile Main.java and all the
files it references, building a complete set of dependencies,
and will then wait for input. (Note that ++
implies +F also.)
-
Modify your source files using your favorite editor until you
are ready to rebuild your program, and then type an empty line
in the window in which Jikes is waiting. Jikes will then
determine which source files have been changed, and will then
perform the minimum number of compilations needed to bring to
class files into a complete and consistent state. You can
repeat this cycle as you wish, until you
-
Terminate the compilation by typing a single line
q
in the window in which Jikes is waiting. Jikes will then
terminate.
By the way, you may notice a substantial delay after you type
q to end the incremental mode. This results from the
time needed to execute the destructors invoked to delete all the
nodes in the abstract syntax tree, all the symbols in the symbol
table, etc. This cost is also incurred whenever the compiler must
delete its current in-memory data structures before compiling a
changed file. We are aware of this cost and are looking at ways
to reduce it, but are making the compiler available with this
known performance limitation so you can try it and test it for
correctness.
Back to top
Most C and C++ compilers support the option -M to
generate dependency information for use with make. Jikes provides
the same function for Java using the option +M , which
requests that Jikes create a file X.u for each file
X.class that is compiled, and include in this file a
list of all the files that X.class depends on. Note
that use of the +M option turns on full dependency
checking (as is done by the +F option).
The contents of any zip files in CLASSPATH are
assumed to be fixed, and so are not included in the generated
makefiles, mainly to avoid cluttering up the dependency list with
voluminous dependencies on the contents of java.* .
You can also use the option +DR=filename to request
that a dependence report be written to the file
filename . The format is designed to allow the use of
the information as input to a tool; for example, it could be used
for a tool that determines the minimum set of class files that
must be included in a jar file.
Back to top
You may find that Jikes accepts a program that another compiler
rejects (or can't compile), or rejects programs that another
compiler accepts.
Each version of Jikes represents our best effort at the proper
interpretation of the language specification. Although Jikes is
designed to work with all but the earliest versions of the JDK, we
make no claim that any particular version supports precisely the
same language as any particular version of the JDK. Since some
products are designed to work with specific versions of the JDK,
the compilers associated with them may not always recognize the
same programs as Jikes.
This section contains some examples of issues related to
interpreting the specification.
The Java Language Specification does not allow class literals
to cause class initialization, even though javac has always
done it this way. Jikes used to also cause class initialization,
but starting with 1.17 it will not.
The following example demonstrates the difference in
behaviour between allowing class literals to cause class
initialization, and not
class Super {
static int i = 1;
static void m(Class c) {
System.out.println(i);
}
public static void main(String[] args) {
m(Sub.class);
}
}
class Sub extends Super {
static { i = 2; }
}
With old versions of jikes, or other buggy compilers,
executing Super will output 2 (since the class
initialization of Sub took place and changed
the value of i). But with jikes 1.17 and later, the
executing Super will correctly output 1.
To update your code to force class initialization
(and thus preserve the semantics you were used to), an
explicit call to Class.forName will help. In the above
example, rewriting Super.m() as shown below will give
the desired behavior of outputting 2.
static void m(Class c) {
// we aren't sure if c is initialized, hence this try-block
try {
if (c != null)
c.forName(c.getName());
} catch (Exception e) {
// shouldn't get here, and even if we do, we ignore it
}
System.out.println(i);
}
For additional details, see this
posting to jikes-dev.
Your program may contain extraneous semicolons that are silently
ignored by many compilers. For example, given
public class Test {
void f() {}; // first extra semicolon
}; // second extra semicolon
Jikes accepts the program but issues:
2. void f() {}; // first extra semicolon
*** Warning: An EmptyDeclaration is a deprecated feature that
should not be used - ";" ignored
3. }; // second extra semicolon
^
*** Warning: An EmptyDeclaration is a deprecated feature that
should not be used - ";" ignored
The first extra semicolon is erroneous, the second is allowed by
section 7.6. Jikes treats each as cause to issue a warning.
You can use the -nowarn option to suppress this (and
other) warnings, or, even better, you can use your editor to
delete those extra semicolons.
It is a compile-time error if a statement cannot be executed
because it is unreachable (section 14.19). When
Jikes first appeared, some other compilers didn't properly detect
unreachable statements, and accepted programs such as the
following:
class Test {
void method(boolean b) {
if (b) return;
else return;
b = !b;
}
}
Jikes rejected this program:
b = !b;
<----->
*** Semantic Error: This statement is unreachable
(This is the example referrred to in PC Week (April 14, 1997): IBM, Netscape Up Web Ante.)
Another example, and one that confused many users, is shown by the
following program:
class Test {
public static void main(String[] args) {
try {
}
catch (Exception e) {
System.out.println("caught");
}
}
}
Jikes accepts this program but issues the warning:
catch (Exception e) {
<--------->
*** Caution: This catch block is unreachable: there is no
exception whose type is assignable to
"java/lang/Exception" that can be thrown during
execution of the body of the try block
This was the most frequently reported problem when Jikes first
appeared. It took several months to confirm that Jikes was right
all along. See
Query #2 to Sun
for the full story.
Jikes rejects the program:
class X extends Y.Z {}
class Y extends X.Z {}
because Jikes checks for cycles by grouping types as follows:
-
Types that are package members form a group.
-
Within the body of a given type, all the inner types
immediately declared in it form a group. In other words, if
we look at the complete name of a type beginning with the name
of its outermost enclosing type, all types that share the same
prefix form a group.
When a type T "extends" or "implements" a type U, we find the
innermost enclosing group that contains an enclosing type Tx of T
(which may be T itself) and an enclosing type Ux of U (which may
be U itself) and add a dependence edge from Tx to Ux. We then
check for cycles in the graph induced by this relationship.
Consider the following example:
class Z {}
class W extends Z
{
class A
{
class x extends B {}
class y extends x {}
}
class B
{
class x extends A.x {}
}
class C extends B.x {}
}
Its dependence graph contains the following edges:
-
W->Z , since W and Z are
both package members
-
W.A->W.B , because type W.A.x extends
W.B
-
W.A.y->W.A.x , because type W.A.y
extends W.A.x
-
W.B->W.A , because type W.B.x extends
W.A.x
-
W.C->W.B , because type W.C extends
W.B.x
This graph has a cycle: W.A->W.B->W.A . So Jikes
rejects this program:
Found 3 semantic errors compiling "Z.java":
5. class A
^
*** Semantic Error: The class "W$A" is circularly defined with
its super type(s)
...
Another example of cyclic dependence is found in the following
code scheme used in some forms of the Swing package:
class C implements C.I {
...
interface I { ... }
}
This example is cyclic by Jikes's model of dependence. We asked
Sun about this usage:
Query #31 to Sun: Rules of inheritance of class members.
Their response agrees with our interpretation that this usage is
erroneous.
Here are some more examples of issues related to interpreting the
language specification:
Query #1 to Sun: Inner Static
Query #2 to Sun: Unreachable Statements
Query #3 to Sun: Dependence
Query #4 to Sun: Are block-level inner interface declarations
allowed?
Query #5 to Sun: String Concatenation Operator + and void
Query #6 to Sun: Getting a line on the LineNumberTable
Query #7 to Sun: Setting of InnerClasses_attribute inner_class_access_flags
Query #8 to Sun: Scope of Local Variable Declarations and Local
Classes
Query #9 to Sun: Qualifying new for static inner class
Query #10 to Sun: Can a class access its own private methods via a
subclass?
Query #11 to Sun: Access to members in anonymous classes
Query #12 to Sun: Anonymous inner classes should be final for
instanceof and casts
Query #13 to Sun: Access to inner classes
Query #14 to Sun: Unreachability and do-while
Query #15 to Sun: Access control bug with protected member of
sibling/outer classes
Query #16 to Sun: Floating point and bitwise operators
Query #17 to Sun: Compile-time evaluation of constant
expressions
Query #18 to Sun: Explicit versus implicit setting of attributes,
servialVersionUID algorithm
Query #19 to Sun: Octal escapes in string literals
Query #20 to Sun: What does "package-private method" mean?
Query #21 to Sun: Name resolution
Query #22 to Sun: Circularity problem?
Query #23 to Sun: Packages and non-existing directories
Query #24 to Sun: Protected
Query #25 to Sun: Can user-deifned package have a type named
"java"?
Query #26 to Sun: Acceptability of unreachable byte code
Query #27 to Sun: Representation of null value
Query #28 to Sun: Use of anonymous class in explicit constructor
invocation
Query #29 to Sun: When can the ConstantValue attribute be
used?
Query #30 to Sun: Labeled statements and nested classes
Query #31 to Sun: Rules of inheritance of class members
Query #32 to Sun: Verification problem
Query #33 to Sun: Field resolution for interfaces
Query #34 to Sun: Which checked exceptions need to be checked?
Query #35 to Sun: Clarification of White Space (3.6)
The Unofficial Java Spec Report
The Unofficial Java Spec Report
is an unofficial site that covers problems with the Java Language
Specification, the Java Virtual Machine Specification, and the
core API documents. It is maintained by Roly Perera and Peter
Bertelsen, and we wish to thank them for their service to the Java
community.
Starting with Jikes v0.28, we will attempt to track the
recommendations of the unofficial report, and implement them where
feasible. The current status for the 1.1 portion in Issue 9
(22 May 1998) is as follows:
-
No definition of cyclic scoping. Jikes has its definition, as
described earlier.
-
Resolution of ambiguous names. Implemented.
-
Access to protected members across nest siblings. Implemented.
-
Can nested interfaces redundantly be declared static? Yes.
-
Behavior of
new when qualified with an expression
that evalutes to null is undefined. Implemented.
-
Rule for making inacessible classes implicitly final is too lax.
Jikes does not make this transformation.
-
Reachability of instance initializers and constructors
undefined. Implemented.
-
Initialization requirements for blank final fields incorrect.
Implemented.
-
When qualified
new or super can be
used unspecified. Implemented.
-
Blank finals and interface fields. Implemented.
-
When may
this be used in an explicit constructor
invocation. Implemented.
-
New hiding rules for parameters and local variables.
Implemented.
-
Blank finals and
try statements. Implemented.
-
Blank finals and loops. Implemented.
-
Unclear whether forward referencing rule changes. Implemented.
-
Transformations for anonymous classes unspecified. Implemented.
-
Private methods implicitly final. Implemented.
Back to top
It is possible that your current compiler was miscompiling the
program and Jikes got it right. Jikes may have miscompiled your
program and we would appreciate your reporting the problem. Here
are some steps that may clarify the situation.
When you run your program using the Java virtual machine, run
java with the option -verify to enable
bytecode verification. If verification this shows one or more
class files are faulty, you've found a bug in Jikes. Please tell
us about it.
You should also to see if the Java virtual machine is using a JIT,
in which case you should try with the JIT disabled. We have seen
cases when JIT's fail with class files produced by Jikes, even
though these class files pass verification.
Otherwise build two sets of class files, one using your current
compiler and one using Jikes. Then, selectively substitute those
produced by Jikes until you find a class file generated by Jikes
whose use results in other than the expected output. If it
appears that Jikes is at fault, please tell us about it.
Back to top
This has been documented seperately.
Back to top
|