<!doctype html public "-//w3c//dtd html 4.0 transitional//en"> | |
<html> | |
<head> | |
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> | |
<meta name="GENERATOR" content="Mozilla/4.5 [en] (Win98; I) [Netscape]"> | |
<meta name="Author" content="Build"> | |
<title>JDT - Pluggable JDKs</title> | |
</head> | |
<body> | |
<h2> | |
Pluggable JDKs</h2> | |
Last revised 11:45 Friday October 19, 2001 | |
<p>Work item: pluggable JDKs | |
<p>Related work item: "Support for dealing with class files generated by | |
external Java compilers like javac and jikes from an Ant script." | |
<p>Related issue: remote builds | |
<p>Other IDEs can claim that when Sun or IBM releases a new JDK, a developer | |
can just "plug it in" to their IDE. We would like Eclipse to be similarly | |
flexible, and be able to make a similar claim. | |
<p>In practice, what does this mean? There are several different aspects. | |
<ol> | |
<li> | |
The ablility to run Java programs with the JDK's JRE.</li> | |
<li> | |
The ablility to compile Java source code against the JDK's class libraries.</li> | |
<li> | |
The ablility to compile Java source code with the JDK's javac compiler.</li> | |
<li> | |
The ablility to debug Java programs with the JDK's JDPA and JVM.</li> | |
<li> | |
The ablility to browse the JDK's class library API javadoc (or perhaps | |
other release doc).</li> | |
<li> | |
The ablility to run the JDK's utility programs like javap, javadoc, javah.</li> | |
</ol> | |
We will take the first four as the most important ones for Eclipse to address, | |
and look at each in turn. | |
<h3> | |
Pluggable JREs</h3> | |
This is supported in Eclipse 1.0. | |
<p>The org.eclipse.jdt.launching plug-in provides pluggable support ("vmInstallTypes" | |
extension point) for describing installed Java2-style Java runtime environments | |
and launching particular configurations of a Java virtual machine. | |
<p>JDT defines a workbench preference ("Installed Java Runtime Environments") | |
so that the user can create, remove, and edit JRE definitions (i.e., instances | |
of the known VM installed types). The user chooses which one of the JRE | |
definitions is the default. | |
<p>JDT also defines a JRE property for each Java project to control which | |
JRE is used to run programs in that project. By default, each project shares | |
the workspace-wide default. The user can elect to specify a JRE for that | |
project, which overrides the workspace-wide default. | |
<h3> | |
Pluggable JDK class libraries</h3> | |
This is supported in Eclipse 1.0. | |
<p>JDT Core provides a reserved build classpath variable, named "JRE_LIB", | |
which gets bound to the JAR library (and associated source code ZIP) of | |
the current workspace-wide default JRE (e.g., "D:\jdk1.4\jre\lib\rt.jar" | |
with source in "D:\jdk1.4\src.zip"). By default, a classpath entry is included | |
on the build classpath of a newly created project. This library would ordinarily | |
supply the compile-time definitions of the standard class libraries used | |
when browsing and building a Java project. | |
<p>The client that is not satisfied with this variable is free to remove | |
the classpath entry from the build classpath and replace it with something | |
else. The client could declare their own build classpath variable, bind | |
it to a suitable value, and include that on the build classpath instead | |
(For instance, VAME/WSDD declares a classpath variable named "IVJ_HOME" | |
and references various class libraries relative to it; e.g., "IVJ_HOME/lib/jclmax.jar".) | |
Or they could just hard-wire a library entry for a particular JRE library. | |
<p>While the basic mechanism is reasonable, it is unfortunate that it is | |
tied so tightly to the default JRE. It might be more convenient if selecting | |
a different workspace-wide default JRE definition would prompt the user | |
to change the JRE_LIB classpath variable as well. | |
<p>Paralleling the workbench JRE mechanism, we could consider allowing | |
the user to specify classpath variable bindings at the project level that | |
override the workspace-wide default. This would allow the user to change | |
the binding to affect just that project. Something similar can already | |
be achieved by using distinctly-named classpath variables for each project | |
(e.g., "P1_JRE_LIB" for project P1's "JRE_LIB"). So it's unclear whether | |
any interesting new usecases would be supported by this. | |
<h3> | |
Pluggable Java compilers</h3> | |
Java compilers can differ along many axes: | |
<ul> | |
<li> | |
supported Java language level</li> | |
<li> | |
Java bytecode version</li> | |
<li> | |
quality of generated code</li> | |
<li> | |
helpfulness of error messages</li> | |
<li> | |
performance</li> | |
<li> | |
robustness</li> | |
<li> | |
product support for compiler</li> | |
</ul> | |
In the simple world of the command line compiler, it's easy to use whatever | |
Java compiler you choose to use. The command lines are substantially the | |
same, and the overt compiler behavior of translating .java source files | |
to .class files is utterly standard. | |
<p>In additional to the basic compiler functionality, there are usually | |
a number of IDE features that also need to be "language aware" (to some | |
extent), including: | |
<ul> | |
<li> | |
source code editing (syntax highlighting)</li> | |
<li> | |
code assist (completion, selection)</li> | |
<li> | |
code reformatter</li> | |
<li> | |
search</li> | |
</ul> | |
The language aware features require compiler infrastructure (e.g., a scanner). | |
<p>The standard Sun Java compiler has no official APIs; the compiler infrastructure | |
is not available outside the compiler. This means that Java IDEs have no | |
choice but to reimplement whatever compiler infrastructure they might need. | |
Without standard Java compiler APIs, no Java IDE can be truely pluggable | |
in these regards. The best that a Java IDE can do in the circumstances | |
is to use a pluggable Java compiler for its basic compiler functionality. | |
<p>In Eclipse 1.0, the IDE's basic Java compiler functionality is provided | |
by the built-in Eclipse compiler. What would it take to make this part | |
pluggable? | |
<p>In Eclipse, the basic Java compiler functionality is provided through | |
the Java builder. The Java builder is activated when its build method is | |
called. This happens when (a) an explicit Build commands requested by the | |
user, (b) the workspace performs an auto build, or (c) some plug-in instigated | |
a build programmatically. | |
<p>So the first idea is that the Java builder's build method should invoke | |
a pluggable Java compiler to do a build. | |
<h4> | |
Calling a pluggable javac from within the Java builder</h4> | |
For a full build, this is clearly doable. The source folders mentioned | |
on the build classpath can be walked to identify all Java source files. | |
The corresponding class files in the output folder are deleted, and Java | |
problem markers are removed. The names of these source files are then passed | |
to javac as the ones to compile (large file sets perhaps broken up into | |
reasonable sized batches); the classpath passed is computed from the project's | |
build classpath; the output folder is passed as the target for the generated | |
class files. The compiler will generate class files into the target folder | |
and print text error messages to its output stream. Depending on how "standard" | |
the format of the output stream was, the Java builder might be able to | |
analyze the stream of text error messages and convert these into Java problem | |
markers associated with the offending source files (the complete stream | |
could also be saved and made available to user through some other mechanism). | |
Otherwise the net result is close to that of running the Eclipse compiler. | |
One other difference is that the Java builder would not be able to produce | |
anything resembling its current internal built state (i.e., no dependency | |
graph). | |
<p>For an incremental build, it is impossible to do anything more than | |
a cursory job without proper dependency information. The Java builder is | |
passed a resource delta for the project showing which source files have | |
changed. The delta would also show that the build classpath had changed | |
(the Java builder could easily remember some classpaths between builds). | |
<p>How to do an incremental build: | |
<ul> | |
<li> | |
delete a source file => identify and delete the corresponding class files</li> | |
<li> | |
add a source file => identify and delete corresponding class files (just | |
in case); include source file in list to be recompiled</li> | |
<li> | |
change a source file => identify and delete corresponding class files; | |
include source file in list to be recompiled</li> | |
</ul> | |
The compiler is called to recompile the identified list of source files. | |
The Java builder might be able to analyze the -verbose output stream to | |
discover which source files were actually compiled and update their Java | |
problem markers. | |
<p>This kind of simple-minded incremental build handles many simple cases | |
(e.g., changing the body of a method, fixing javadoc comments, reformatting). | |
The results would usually be less satisfactory when the principal structure | |
of class is changed because any dependent source files do not get recompiled, | |
which may lead to incompatible sets of binaries class files. The developer | |
would need to be educated about when to be asking for a full build. Many | |
will already be familiar with these rules from using other Java IDEs. With | |
a Java compiler that does not produce dependency information, it is hard | |
for an IDE with pluggable Java compilers to do any better. | |
<p>Autobuild is just an incremental build that is triggered automatically. | |
Note that the user may find it intolerable to run with autobuild enabled | |
if the overhead for invoking the pluggable compiler is high (which it is | |
likely to be if a separate JVM would need to be launched). | |
<p>The conclusion is that this is feasible, although autobuilding may be | |
intolerable. As long as the pluggable Java compiler was very javac-like | |
in terms of command line options and format of generated error messages, | |
it should be possible to use it to build a Java project. | |
<h4> | |
Calling an Ant script instead of the Java builder</h4> | |
An even more flexible approach would be to allow a Java project to be configured | |
with a generic Ant-based incremental project builder instead of the standard | |
Java builder. The Ant-based builder is described in a separate 2.0 Platform | |
Core feature proposal. | |
<p>All of the above considerations would still apply; the only real difference | |
is that everything is implemented in Ant terms. | |
<h3> | |
Pluggable JDPA Debuggers</h3> | |
Eclipse reimplements the JPDA debugger front end; it does not use the JDI | |
implementation supplied by Sun. Even if it did use Sun JDI, it still would | |
be work for the Eclipse debugger to capitalize on any new debugger functionality | |
thereby introduced. So the debugger front end is upgradeable, but not pluggable. | |
<p>The JDPA debugger back end is logically part of the Java runtime environment, | |
and ships with the IBM and Sun J2SE JDKs since 1.3. So this part is already | |
pluggable. | |
<br> | |
</body> | |
</html> |