blob: 68061d88b61e16c96ba649a36f0b205f84ca6246 [file] [log] [blame]
<!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&nbsp; 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>&nbsp;
</body>
</html>