What is Jikes?
How do I use it? What options does it support?
Why must I define CLASSPATH
? What is JIKESPATH
?
How do I control the compiler listing?
What is incremental compilation?
How do I use Jikes to generate dependencies for make?
Why does Jikes reject a program that another compiler accepts, or accept one that it rejects?
Does Jikes follow the Unofficial Java Spec Report?
What can I do if I don't get the same results when using class files generated by Jikes?no
How do I report bugs?
Jikes is a Java compiler, written from scratch in C++, that translates Java source files as defined in The Java Language Specification (Addison-Wesley, 1996) and Inner Classes Specification (JavaSoft, Release 2/10/97) into the bytecoded instruction set and binary format defined in The Java Virtual Machine Specification (Addison-Wesley, 1996) .
You can use Jikes to see if your program conforms to the specification. It accepts the language as specified: not a subset, not a variant, not a superset.
You can use Jikes in the same way as your current compiler, since it accepts the usual command line options and arguments. You can use it to quickly compile part, or all, of your program.
Jikes can also compute the complete dependency relations of the files in your program, so that:
q
command
to end the compilation.
Jikes supports the 1.1 level of the language.
This is an upwards compatible extension
of the 1.0 level of the language (except that the character $
can no longer be used in
an identifier) so you can use Jikes to compile your old programs. You
can use the option +1.0
to direct the compiler to accept
only the 1.0 level of the language. You can also use the +$
option to allow the use
of $
in identifiers in 1.1 programs, though this is discouraged since names generated
by the compiler for inner classes and related methods and fields contain $
.
You can visit the Jikes Discussion Database . It contains recent problem reports and other topics, including suggestions and a discussion on the Clarification and Interpretation of the Java Language Specification.
Here are links to some articles in the press that mention Jikes:
Internet
Computing (April 1998): Java Tools Enrich the Bean Pool
PC Week (December
22, 1997): PCW Labs' top 10 tech trends: It was the best of information
technology
PC Week (September 22, 1997): IBM spreading its software wings
Infoworld (May 24, 1997): IBM to invest $100 million in Internet, networking
research center this year
Web Week (April 28, 1997): IBM Greases Java's Rails
PC Week (April 14, 1997): IBM, Netscape Up Web Ante
You can see recent comments about Jikes in the Usenet discussions by searching for "Jikes" in dejanews.
Invoke Jikes in the same way as your current compiler; it accepts the usual command line options and arguments.
Invoke Jikes with no arguments to see a short summary of the arguments. Here is a more complete description:
-g
LocalVariableTable
attribute
-O
LineNumberTable
attribute-debug
-depend
-deprecation
-nowarn
-verbose
-classpath path
-nowrite
-d dir
++
+$
+1.0
$
can be used in an identifier only if this option or the +$
option is specified.
+B
-nowrite
generates byte code but does
not write it out.
+E
+F
+M
+U
+V
+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.listwhere
file.list
is a file containing the lines:
Test.java x.java Test.java
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 versions 1.1 of the JDK
do not require that you 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:
CLASSPATH
; for example, in Win95 this takes the form
SET CLASSPATH=.;C:\JAVA\LIB\CLASSES.ZIPor for example, in Linux:
export CLASSPATH=.:/usr/local/jdk.1.1.6/lib/classes.zip (jdk) export CLASSPATH=.:/usr/local/jre1.1.6/lib/rt.jar (jre)
-classpath
option on the command line;
for example:
jikes -classpath .:$HOME/java/lib/classes.zip ...
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.
unzip532
from Info-ZIP, so we have 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 or Info-ZIP ftp site 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.
JIKESPATH
can be used when working with a 1.1 level JDK because this level
does not always require a definition of CLASSPATH
; indeed, we have observed some
problems when trying to specify CLASSPATH
using some 1.1 level JDK's.
JIKESPATH
can be used when working with a 1.0 level JDK to permit the used
of compressed class files. The CLASSES.ZIP
files shipped with 1.0 JDK's do not
use any compression. However, if you have any of the various zip file utilities such as
WinZip PKZIP or
Info-ZIP, then you can take the provided
CLASSES.ZIP
, unzip it, rezip using compression, and use the compressed
CLASSES.ZIP
in JIKESPATH
. This should speed up compilations on
systems with slow file systems. However, you must leave the uncompressed CLASSES.ZIP
in CLASSPATH
as 1.0 JVM's don't support compressed zip files.
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 +V
. 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 veracious option +V
is used to request a complete, veracious listing.
Just what is or is not veracious depends in part on
e-mail 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 +V
is selected:
This compilation unit contains no type declaration
An EmptyDeclaration is a deprecated feature that should not be used
private
access:
Note that the method ... in class ... does not override the corresponding method with private access in class ...
The method ... in class ... does not override the corresponding method with default access in class ...
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:
-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.
Most compilers appears to use the same behavior as provided by Jikes by default.
You should only need to use +F
and +U
for special situations.
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.
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:
jikes ++ Main.javawhere
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.)qin 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.
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 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. Indeed, were we to attempt to match a particular version of the JDK, then we would also have to match the bugs in that version. 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. See also Does Jikes follow the Unofficial Java Spec Report?
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 semicolonJikes 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 - ";" ignoredThe 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.
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
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:
Jikes rejects the program:
class X extends Y.Z {} class Y extends X.Z {}because Jikes checks for cycles by grouping types as follows:
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 membersW.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) ...
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.
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.
Please send mail to one of the authors: