Bug 44470 - Eclipse ignoring java extensions classloader
Summary: Eclipse ignoring java extensions classloader
Status: RESOLVED DUPLICATE of bug 30919
Alias: None
Product: Platform
Classification: Eclipse Project
Component: Resources (show other bugs)
Version: 2.1   Edit
Hardware: All All
: P3 critical (vote)
Target Milestone: ---   Edit
Assignee: Platform-Resources-Inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2003-10-08 12:12 EDT by Mel Martinez CLA
Modified: 2003-10-09 14:37 EDT (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Mel Martinez CLA 2003-10-08 12:12:03 EDT
One problem we have discovered with the Eclipse 2.1 classloader structure is
that it creates the root of the classloader tree with a parent of 'null' so that
the plugin class loaders will not look in the application class loader (who's
namespace is defined by -cp ) when it is mostly looking for plugin classes.  
This, I understand, is a performance optimization.  

Unfortunately, there is a rather bad side effect of this.  Because the way this
is done simply 'preempts' the parent search right before it would go to the
application class loader, they also end up preempting search of the _extensions_
class loader!   This has turned into a major problem for us because this
disables the Java 1.2+ standard extensions behavior.  The java extensions spec :

http://java.sun.com/j2se/1.3/docs/guide/extensions/index.html

requires that jars placed into the jre/lib/ext/ directory be treated as part of
the JRE.  This is important because this allows one to drop in 'javax' packages
into, say a 1.3.1 JRE and bring up the APIs to match 1.4.1 in an incremental
way.  In particular some of the java security features (SSE, JAAS & crypto, for
example) are not part of the standard 1.3.1 distribution.  In order for these
features to be added - and this is a requirement for our team - we need to be
able to use the Java Extension mechanism.

Personally, I am not convinced that the performance gain from skipping a search
of the application class loader is really all that significant.  Parents should
only be searched the first time a class is located and the search domain for the
application class loader is tiny (normally it only contains startup.jar).  
Normally, the proper thing to do before applying a spec changing optimization
(which is what this is) is to do measurements.  Has anybody actually done
measurements?

Giving the benefit of the doubt to this optimization of ignoring the application
class loader, nevertheless it is incorrect behavior to skip the extensions class
loader.   In the current eclipse 2.1 code, the offending line of code that
causes the problem is in
org.eclipse.platform/src/org/eclipse/core/launcher/Main.java :

public Class getBootLoader(URL[] path) throws Exception {
	URLClassLoader loader = new URLClassLoader(path, null);
	return loader.loadClass(BOOTLOADER);
}

The correct thing to do is change that to assign the extensions class loader
(which is the parent of the app class loader) as the parent.  A simple-minded
fix would be to change it to:


public Class getBootLoader(URL[] path) throws Exception {
	URLClassLoader loader = new URLClassLoader(path,
                     ClassLoader.getSystemClassLoader().getParent());
	return loader.loadClass(BOOTLOADER);
}

This fixes the behavior so far, from what we can tell so far.  However, I
suspect that a more rigorous thing to do would be to walk the chain and assign
the last non-null class loader as the parent:

public Class getBootLoader(URL[] path) throws Exception {
	ClassLoader cl = ClassLoader.getSystemClassLoader();
	ClassLoader parent = cl.getParent();
	while(parent!=null){
		cl=parent;
		parent=cl.getParent();
	}
	//last non-null classloader should be the java ExtLoader
	URLClassLoader loader = new URLClassLoader(path, cl);
	return loader.loadClass(BOOTLOADER);
}

This should protect against the case where a particular JRE implementation
returns a grandchild rather than a direct child of the EXT loader for the
getSystemClassLoader() call.

While my comments here address the Eclipse 2.1 codebase in hopes that this can
be fixed in Eclipse 2.1.2, I believe ths problem persists in the Eclipse HEAD
branch today as well and needs to be addressed in Eclipse 3.0.
Comment 1 Rafael Chaves CLA 2003-10-08 12:49:06 EDT
This has been considered before: bug 30919.
Comment 2 John Arthorne CLA 2003-10-08 13:49:50 EDT
This is a duplicate.

Note that this wasn't done as an optimization.  Plugins/Bundles in Eclipse
define their namespaces individually using a manifest file.  A "global"
namespace mechanism like the extension mechanism can be very problematic in a
system built on a loosely-coupled federation of independent plugins/bundles.  A
JAR added to "ext" to support plugin "A" can break plugin "B" that has
conflicting namespace requirements. You can add the libraries you need by
bundling them in a plugin and adding them to your plug-ins "requires" list.

*** This bug has been marked as a duplicate of 30919 ***
Comment 3 Jeff McAffer CLA 2003-10-08 14:02:17 EDT
This actually is not so much of a performance issue as on of maintaining the 
Eclipse component model.  Eclipse works because the various plugins have to 
identify the other function on which they rely.  Relying on function which may 
or may not be there in the JVM or on the classpath is problematic.  This kind 
of code is not version managed, is not updatable and, when loaded this way, 
does not support multiple implementations concurrently.  The choice to use null 
parentage in Eclipse has been there since the beginning in an attempt to 
support the above characteristics.  

An example of where the suggested approach would go wrong can be seen in our 
current problems with the JDK 1.4 support for endorsed libraries.  Endorsed 
libs are basically part of the boot classpath (not sure if there is another 
classloader for them).  As such, classloaders with null parents still see 
endorsed libs from the VM.  The major endorsed lib currently is the JAXP XML 
parser stuff.  

This directly conflicts with the Eclipse Xerces plugin function.  Further, some 
VMs include Xerces as their implementation but that version is different from 
the one provided with Eclipse.  It would be fine if the one in the VM was a 
complete cover for the one in the Xerces plugin but that is not the case and 
you end up with non-functioning XML parsing.  So currently Elcipse works on 
some 1.4 VMs and not others.

Alternaitves for extensions are to add plugins containing the relevant function 
and then setup the plugin requirements accordingly.

Alternatives for endorsed libs have been considered and basically amount to 
allowing plugins to state a preference to override/replace classes found in the 
system classloader.   This is techically possible but needs to be worked 
through.  Side note:  OSGi RFP44 contains an item which deals with this.

Comment 4 Mel Martinez CLA 2003-10-08 16:01:22 EDT
I would like to disagree with the resolution of WONTFIX for bug#30919 and
advocate that this bug be reopened and addressed for Eclipse 2.1.2.

I think the vulnerability to classpath polution from someone dropping a jar like
Xerces into the ext/ directory is overstated.  An eclipse-based application
deployment simply shouldn't make such an obvious mistake in general.   It is
important to note that technically one can STILL perform such a corruption even
now by using -XBootClasspath.  In a sense, this is analogous to the problem you
say is arrising on use of some 1.4 VMs and not others.

It is not the purpose in general of the Java Extension mechanism to add such
application-layer jars such as xerces.   The main purpose of the Ext mechanism
is to provide for modifications at the JRE level.   This mechanism is necessary
in order to add certain behavior to the JRE, especially in the security area.

Ultimately, I guess this comes down to whether one is going to design away a
whole major realm of functionality in order to avoid the possibility of someone
dropping an incompatible xml jar in.

If you make the change I advocate, I predict that the impact on existing
deployments should be negligible because, given the current behavior, it is
unlikely any existing deployments are even including extension jars in their
jre/lib/ext/.  And if they are, it is unlikely that they are including one that
actually going to be in conflict with a jar included in a plugin downstream.


This bug is a critical block for work that our team is doing.  We would like to
see it addressed for 2.1.2, even if with a switch at the command-line such as
'-enablejreext'.



Comment 5 Keith Kimball CLA 2003-10-09 11:31:07 EDT
It seems like a switch would be useful and could be added without effecting 
existing users.

In general, I concur with Pascal, that isolating plugins from random files in 
the extension's directory is a good thing. This is especially true if the 
required .jar files could have been included in a plugin.

However, there are use cases, where .jar files are required to be on the system 
classpath and can not be provided in a plugin. One of the cases Mel is worried 
about is using a 1.3 JRE and JAAS. His only alternative is to use -
Xboothclasspath with a long list of jar files.
Comment 6 John Arthorne CLA 2003-10-09 14:37:39 EDT

*** This bug has been marked as a duplicate of 30919 ***