ClassLoaderRepositorySupportpublic final class ClassLoaderRepositorySupport extends Object implements ModifiableClassLoaderRepositoryThis class keeps the list of Class Loaders registered in the MBean Server.
It provides the necessary methods to load classes using the
registered Class Loaders. |
Fields Summary |
---|
private static final LoaderEntry[] | EMPTY_LOADER_ARRAY | private LoaderEntry[] | loadersList of class loaders
Only read-only actions should be performed on this object.
We do O(n) operations on this array, e.g. when removing
a ClassLoader. The assumption is that the number of elements
is small, probably less than ten, and that the vast majority
of operations are searches (loadClass) which are by definition
linear. | private final Map | searchList of valid search | private final Map | loadersWithNamesList of named class loaders. | private static final String | dbgTag |
Methods Summary |
---|
private synchronized boolean | add(javax.management.ObjectName name, java.lang.ClassLoader cl)Same behavior as add(Object o) in {@link java.util.List}.
Replace the loader list with a new one in which the new
loader has been added.
List<LoaderEntry> l =
new ArrayList<LoaderEntry>(Arrays.asList(loaders));
l.add(new LoaderEntry(name, cl));
loaders = l.toArray(EMPTY_LOADER_ARRAY);
return true;
| public final synchronized void | addClassLoader(javax.management.ObjectName name, java.lang.ClassLoader loader)
loadersWithNames.put(name, loader);
if (!(loader instanceof PrivateClassLoader))
add(name, loader);
| public final void | addClassLoader(java.lang.ClassLoader loader)
add(null, loader);
| private static void | debug(java.lang.String clz, java.lang.String func, java.lang.String info)
Trace.send(Trace.LEVEL_DEBUG, Trace.INFO_MBEANSERVER,clz,func,info);
| private static void | debug(java.lang.String func, java.lang.String info)
debug(dbgTag, func, info);
| public final java.lang.ClassLoader | getClassLoader(javax.management.ObjectName name)
return loadersWithNames.get(name);
| private static boolean | isDebugOn()
return Trace.isSelected(Trace.LEVEL_DEBUG, Trace.INFO_MBEANSERVER);
| private static boolean | isTraceOn()
return Trace.isSelected(Trace.LEVEL_TRACE, Trace.INFO_MBEANSERVER);
| public final java.lang.Class | loadClass(java.lang.String className)
// from javax.management.loading.DefaultLoaderRepository
return loadClass(loaders, className, null, null);
| private java.lang.Class | loadClass(com.sun.jmx.mbeanserver.ClassLoaderRepositorySupport$LoaderEntry[] list, java.lang.String className, java.lang.ClassLoader without, java.lang.ClassLoader stop)
final int size = list.length;
for(int i=0; i<size; i++) {
try {
final ClassLoader cl = list[i].loader;
if (cl == null) // bootstrap class loader
return Class.forName(className, false, null);
if (cl == without)
continue;
if (cl == stop)
break;
if (isTraceOn()) {
trace("loadClass", "trying loader = " + cl);
}
/* We used to have a special case for "instanceof
MLet" here, where we invoked the method
loadClass(className, null) to prevent infinite
recursion. But the rule whereby the MLet only
consults loaders that precede it in the CLR (via
loadClassBefore) means that the recursion can't
happen, and the test here caused some legitimate
classloading to fail. For example, if you have
dependencies C->D->E with loaders {E D C} in the
CLR in that order, you would expect to be able to
load C. The problem is that while resolving D, CLR
delegation is disabled, so it can't find E. */
return Class.forName(className, false, cl);
} catch (ClassNotFoundException e) {
// OK: continue with next class
}
}
throw new ClassNotFoundException(className);
| public final java.lang.Class | loadClassBefore(java.lang.ClassLoader stop, java.lang.String className)
if (isTraceOn())
trace("loadClassBefore", className + "\tbefore " + stop);
if (stop == null)
return loadClass(loaders, className, null, null);
startValidSearch(stop, className);
try {
return loadClass(loaders, className, null, stop);
} finally {
stopValidSearch(stop, className);
}
| public final java.lang.Class | loadClassWithout(java.lang.ClassLoader without, java.lang.String className)
if (isTraceOn()) {
trace("loadClassWithout", className + "\twithout " + without);
}
// without is null => just behave as loadClass
//
if (without == null)
return loadClass(loaders, className, null, null);
// We must try to load the class without the given loader.
//
startValidSearch(without, className);
try {
return loadClass(loaders, className, without, null);
} finally {
stopValidSearch(without, className);
}
| private synchronized boolean | remove(javax.management.ObjectName name, java.lang.ClassLoader cl)Same behavior as remove(Object o) in {@link java.util.List}.
Replace the loader list with a new one in which the old loader
has been removed.
The ObjectName may be null, in which case the entry to
be removed must also have a null ObjectName and the ClassLoader
values must match. If the ObjectName is not null, then
the first entry with a matching ObjectName is removed,
regardless of whether ClassLoader values match. (In fact,
the ClassLoader parameter will usually be null in this case.)
final int size = loaders.length;
for (int i = 0; i < size; i++) {
LoaderEntry entry = loaders[i];
boolean match =
(name == null) ?
cl == entry.loader :
name.equals(entry.name);
if (match) {
LoaderEntry[] newloaders = new LoaderEntry[size - 1];
System.arraycopy(loaders, 0, newloaders, 0, i);
System.arraycopy(loaders, i + 1, newloaders, i,
size - 1 - i);
loaders = newloaders;
return true;
}
}
return false;
| public final void | removeClassLoader(java.lang.ClassLoader loader)
remove(null, loader);
| public final synchronized void | removeClassLoader(javax.management.ObjectName name)
ClassLoader loader = loadersWithNames.remove(name);
if (!(loader instanceof PrivateClassLoader))
remove(name, loader);
| private synchronized void | startValidSearch(java.lang.ClassLoader aloader, java.lang.String className)
// Check if we have such a current search
//
List<ClassLoader> excluded = search.get(className);
if ((excluded!= null) && (excluded.contains(aloader))) {
if (isTraceOn()) {
trace("startValidSearch", "already requested loader=" +
aloader + " class= " + className);
}
throw new ClassNotFoundException(className);
}
// Add an entry
//
if (excluded == null) {
excluded = new ArrayList<ClassLoader>(1);
search.put(className, excluded);
}
excluded.add(aloader);
if (isTraceOn()) {
trace("startValidSearch", "loader=" + aloader + " class= " +
className);
}
| private synchronized void | stopValidSearch(java.lang.ClassLoader aloader, java.lang.String className)
// Retrieve the search.
//
List<ClassLoader> excluded = search.get(className);
if (excluded != null) {
excluded.remove(aloader);
if (isTraceOn()) {
trace("stopValidSearch", "loader=" + aloader +
" class= " + className);
}
}
| private static void | trace(java.lang.String clz, java.lang.String func, java.lang.String info)
Trace.send(Trace.LEVEL_TRACE, Trace.INFO_MBEANSERVER,clz,func,info);
| private static void | trace(java.lang.String func, java.lang.String info)
trace(dbgTag, func, info);
|
|