use of org.eclipse.osgi.internal.loader.ModuleClassLoader.DefineClassResult in project rt.equinox.framework by eclipse.
the class ClasspathManager method defineClass.
/**
* Defines the specified class. This method will first call all the configured class loader hooks
* {@link ClassLoadingHook#processClass(String, byte[], ClasspathEntry, BundleEntry, ClasspathManager)}
* methods. If any hook modifies the bytes the all configured hook
* {@link ClassLoaderHook#rejectTransformation(String, byte[], ClasspathEntry, BundleEntry, ClasspathManager)}
* methods are called. Then it will call the {@link ModuleClassLoader#defineClass(String, byte[], ClasspathEntry, BundleEntry)}
* method to define the class. After that, the class loader hooks are called to announce the class
* definition by calling {@link ClassLoaderHook#recordClassDefine(String, Class, byte[], ClasspathEntry, BundleEntry, ClasspathManager)}.
* @param name the name of the class to define
* @param classbytes the class bytes
* @param classpathEntry the classpath entry used to load the class bytes
* @param entry the BundleEntry used to load the class bytes
* @param hooks the class loader hooks
* @return the defined class
*/
private Class<?> defineClass(String name, byte[] classbytes, ClasspathEntry classpathEntry, BundleEntry entry, List<ClassLoaderHook> hooks) {
DefineClassResult result = null;
boolean recursionDetected = false;
try {
definePackage(name, classpathEntry);
DefineContext context = currentDefineContext.get();
if (context == null) {
context = new DefineContext();
currentDefineContext.set(context);
}
// First call the hooks that do not handle recursion themselves
if (!hookRegistry.getContainer().isProcessClassRecursionSupportedByAll()) {
// We need to detect recursions for this set of hooks.
if (context.currentlyProcessing.contains(name)) {
// Avoid recursion for the same class name for these hooks
recursionDetected = true;
// TODO consider thrown a ClassCircularityError here
return null;
}
context.currentlyProcessing.add(name);
try {
for (ClassLoaderHook hook : hooks) {
if (!hook.isProcessClassRecursionSupported()) {
classbytes = processClass(hook, name, classbytes, classpathEntry, entry, this, hooks);
}
}
} finally {
context.currentlyProcessing.remove(name);
}
}
// Now call the hooks that do support recursion without the check.
for (ClassLoaderHook hook : hooks) {
if (hook.isProcessClassRecursionSupported()) {
// Note if the hooks don't take protective measures for a recursive class load here
// it will result in a stack overflow.
classbytes = processClass(hook, name, classbytes, classpathEntry, entry, this, hooks);
}
}
if (context.currentlyDefining.contains(name)) {
// avoid recursive defines (bug 345500)
return null;
}
context.currentlyDefining.add(name);
try {
result = classloader.defineClass(name, classbytes, classpathEntry);
} finally {
context.currentlyDefining.remove(name);
}
} finally {
// only call hooks if we properly called processClass above
if (!recursionDetected) {
// only pass the newly defined class to the hook
Class<?> defined = result != null && result.defined ? result.clazz : null;
for (ClassLoaderHook hook : hooks) {
hook.recordClassDefine(name, defined, classbytes, classpathEntry, entry, this);
}
}
}
// return either the pre-loaded class or the newly defined class
return result == null ? null : result.clazz;
}
Aggregations