mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 06:11:37 +00:00
1. Added ContextFactory.getApplicationClassLoader()/initApplicationClassLoader() for simpler class loader customization.
2. Context.getApplicationClassLoader() now uses ContextFactory.getApplicationClassLoader() and also tries ContextFactory subclass as the last resort of loader guessing.
This commit is contained in:
parent
58ff31852c
commit
01a323d63b
@ -2090,22 +2090,29 @@ public class Context
|
||||
public final ClassLoader getApplicationClassLoader()
|
||||
{
|
||||
if (applicationClassLoader == null) {
|
||||
// If Context was subclassed, the following gets the loader
|
||||
// for the subclass which can be different from Rhino loader,
|
||||
// but then proper Rhino classes should be accessible through it
|
||||
// in any case or JVM class loading is severely broken
|
||||
Class cxClass = this.getClass();
|
||||
ClassLoader loader = cxClass.getClassLoader();
|
||||
ClassLoader threadLoader
|
||||
= VMBridge.instance.getCurrentThreadClassLoader();
|
||||
if (threadLoader != null && threadLoader != loader) {
|
||||
if (testIfCanUseLoader(threadLoader, cxClass)) {
|
||||
ContextFactory f = getFactory();
|
||||
ClassLoader loader = f.getApplicationClassLoader();
|
||||
if (loader == null) {
|
||||
ClassLoader threadLoader
|
||||
= VMBridge.instance.getCurrentThreadClassLoader();
|
||||
if (threadLoader != null
|
||||
&& Kit.testIfCanLoadRhinoClasses(threadLoader))
|
||||
{
|
||||
// Thread.getContextClassLoader is not cached since
|
||||
// its caching prevents it from GC which may lead to
|
||||
// a memory leak and hides updates to
|
||||
// Thread.getContextClassLoader
|
||||
return threadLoader;
|
||||
}
|
||||
// Thread.getContextClassLoader can not load Rhino classes,
|
||||
// try to use the loader of ContextFactory or Context
|
||||
// subclasses.
|
||||
Class fClass = f.getClass();
|
||||
if (fClass != ScriptRuntime.ContextFactoryClass) {
|
||||
loader = fClass.getClassLoader();
|
||||
} else {
|
||||
loader = getClass().getClassLoader();
|
||||
}
|
||||
}
|
||||
applicationClassLoader = loader;
|
||||
}
|
||||
@ -2120,27 +2127,13 @@ public class Context
|
||||
applicationClassLoader = null;
|
||||
return;
|
||||
}
|
||||
if (!testIfCanUseLoader(loader, this.getClass())) {
|
||||
if (!Kit.testIfCanLoadRhinoClasses(loader)) {
|
||||
throw new IllegalArgumentException(
|
||||
"Loader can not resolve Rhino classes");
|
||||
}
|
||||
applicationClassLoader = loader;
|
||||
}
|
||||
|
||||
private static boolean testIfCanUseLoader(ClassLoader loader, Class cxClass)
|
||||
{
|
||||
// Check that Context or its suclass is accesible from this loader
|
||||
Class x = Kit.classOrNull(loader, cxClass.getName());
|
||||
if (x != cxClass) {
|
||||
// The check covers the case when x == null =>
|
||||
// loader does not know about Rhino or the case
|
||||
// when x != null && x != cxClass =>
|
||||
// loader loads unrelated Rhino instance
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/********** end of API **********/
|
||||
|
||||
/**
|
||||
|
@ -143,6 +143,7 @@ public class ContextFactory
|
||||
private final Object listenersLock = new Object();
|
||||
private volatile Object listeners;
|
||||
private boolean disabledListening;
|
||||
private ClassLoader applicationClassLoader;
|
||||
|
||||
/**
|
||||
* Listener of {@link Context} creation and release events.
|
||||
@ -290,6 +291,38 @@ public class ContextFactory
|
||||
return new DefiningClassLoader(parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get ClassLoader to use when searching for Java classes.
|
||||
* Unless it was explicitly initialized with
|
||||
* {@link #initApplicationClassLoader(ClassLoader)} the method returns
|
||||
* null to indicate that Thread.getContextClassLoader() should be used.
|
||||
*/
|
||||
public final ClassLoader getApplicationClassLoader()
|
||||
{
|
||||
return applicationClassLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set explicit class loader to use when searching for Java classes.
|
||||
*
|
||||
* @see #getApplicationClassLoader()
|
||||
*/
|
||||
public final void initApplicationClassLoader(ClassLoader loader)
|
||||
{
|
||||
if (loader == null)
|
||||
throw new IllegalArgumentException("loader is null");
|
||||
if (!Kit.testIfCanLoadRhinoClasses(loader))
|
||||
throw new IllegalArgumentException(
|
||||
"Loader can not resolve Rhino classes");
|
||||
|
||||
if (this.applicationClassLoader != null)
|
||||
throw new IllegalStateException(
|
||||
"applicationClassLoader can only be set once");
|
||||
checkNotSealed();
|
||||
|
||||
this.applicationClassLoader = loader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute top call to script or function.
|
||||
* When the runtime is about to execute a script or function that will
|
||||
|
@ -104,6 +104,23 @@ public class Kit
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that testClass is accesible from the given loader.
|
||||
*/
|
||||
static boolean testIfCanLoadRhinoClasses(ClassLoader loader)
|
||||
{
|
||||
Class testClass = ScriptRuntime.ContextFactoryClass;
|
||||
Class x = Kit.classOrNull(loader, testClass.getName());
|
||||
if (x != testClass) {
|
||||
// The check covers the case when x == null =>
|
||||
// loader does not know about testClass or the case
|
||||
// when x != null && x != testClass =>
|
||||
// loader loads a class unrelated to testClass
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* If initCause methods exists in Throwable, call
|
||||
* <tt>ex.initCause(cause)</tt> or otherwise do nothing.
|
||||
|
Loading…
Reference in New Issue
Block a user