Search in sources :

Example 1 with DefineClassResult

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;
}
Also used : ClassLoaderHook(org.eclipse.osgi.internal.hookregistry.ClassLoaderHook) DefineClassResult(org.eclipse.osgi.internal.loader.ModuleClassLoader.DefineClassResult)

Aggregations

ClassLoaderHook (org.eclipse.osgi.internal.hookregistry.ClassLoaderHook)1 DefineClassResult (org.eclipse.osgi.internal.loader.ModuleClassLoader.DefineClassResult)1