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.
Table of Contents
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?
Where do I get Jikes?
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.
How do I use it? What options does it support?
Invoke Jikes in the form:
jikes options filename...
Invoke Jikes with no arguments to see a short summary of the arguments. Allowed options are:
- Set classpath.
- Write class files in specified directory.
- No effect (recognized for compatibility with many compilers).
- Recompile all used classes.
- Report on use of deprecated features.
-
Generate
LocalVariableTable
attribute. - Suppress warning messages.
- Do not write any class files.
-
Do not generate
LineNumberTable
attribute. - List files read and written.
- Write error messages to standard output.
- Compile in incremental mode.
-
Do not generate bytecode. This is used primarily for debugging the compiler. The
-nowrite
option generates byte code but does not write it out. -
As of Jikes 1.12, the default classpath search order has changed to be more like
javac
. Jikes now searches all directories for aclass
orjava
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. - 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.
- Write report of dependencies to specified file.
- 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.
- Do full dependence check except for Zip and Jar files.
- Generate makefiles with dependencies.
- Generate pedantic listing.
- Set tab width for listing error messages.
- Do full dependence check including Zip and Jar files.
- Treat cautions as errors.
-classpath path
-d dir
-debug
-depend
-deprecation
-g
-nowarn
-nowrite
-O
-verbose
-Xstdout
++
+B
+OLDCSO
+D
+DR=filename
+E
+F
+M
+P
+Tnn
+U
+Z
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
Why must I define CLASSPATH
? What is JIKESPATH
?
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 followingset 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 useexport 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 forcsh
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
orclass
file. - Jikes then uses the
java/class
found in the leftmost classpath entry for compilation purposes.
How do I control the compiler listing?
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.
What is incremental compilation?
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
whereMain.java
denotes your root source file. Jikes will then compileMain.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.
How do I use Jikes to generate dependencies for make?
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.
Why does Jikes reject a program that another compiler accepts, or accept one that it rejects?
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.
Class Literal Semantics
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.
Extraneous Semicolons
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.
Unreachable Statements
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.
Cyclic Scoping
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
, sinceW
andZ
are both package membersW.A->W.B
, because typeW.A.x
extendsW.B
W.A.y->W.A.x
, because typeW.A.y
extendsW.A.x
W.B->W.A
, because typeW.B.x
extendsW.A.x
W.C->W.B
, because typeW.C
extendsW.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.
Queries to Sun
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 tonull
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
orsuper
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.
What can I do if I don't get the same results when using class files generated by Jikes?
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.
From : http://jikes.sourceforge.net/faq/user-index.shtml#jikespath