public Class defineAndLoadClass()

in webbeans-impl/src/main/java/org/apache/webbeans/proxy/Unsafe.java [175:313]


    public <T> Class<T> defineAndLoadClass(ClassLoader classLoader, String proxyName, byte[] proxyBytes,
                                           Class<?> parent)
            throws ProxyGenerationException
    {
        Class<?> definedClass = null;
        try
        {
            // CHECKSTYLE:OFF
            switch (defineClassImpl) {
                case 0: // unset
                case 1: // classloader
                {
                    if (defineClassMethod == null)
                    {
                        Method defineClassMethodTmp;
                        try
                        {
                            // defineClass is a final method on the abstract base ClassLoader
                            // thus we need to cache it only once
                            defineClassMethodTmp = ClassLoader.class.getDeclaredMethod(
                                    "defineClass", String.class, byte[].class, int.class, int.class);
                            if (!defineClassMethodTmp.isAccessible())
                            {
                                try
                                {
                                    defineClassMethodTmp.setAccessible(true);
                                    defineClassMethod = defineClassMethodTmp;
                                }
                                catch (final RuntimeException re)
                                {
                                    // likely j9 or not accessible via security, let's use unsafe or MethodHandle as fallbacks
                                }
                            }
                        }
                        catch (final NoSuchMethodException e)
                        {
                            // all fine, we just skip over from here
                        }
                    }

                    if (defineClassMethod != null)
                    {
                        try
                        {
                            definedClass = Class.class.cast(defineClassMethod.invoke(
                                    classLoader, proxyName, proxyBytes, 0, proxyBytes.length));
                            defineClassImpl = 1;
                            break;
                        }
                        catch (final Throwable t)
                        {
                            definedClass = handleLinkageError(t, proxyName, classLoader);
                            if (definedClass != null)
                            {
                                defineClassImpl = 1;
                                break;
                            }
                        }
                    }
                }
                case 2: // lookup
                {
                    if (privateLookup == null)
                    {
                        synchronized (this)
                        {
                            if (privateLookup == null)
                            {
                                try
                                {
                                    lookup = MethodHandles.lookup();
                                    defineClass = lookup.getClass().getMethod("defineClass", byte[].class);
                                    privateLookup = MethodHandles.class.getDeclaredMethod(
                                            "privateLookupIn", Class.class, MethodHandles.Lookup.class);
                                }
                                catch (final Exception re)
                                {
                                    // no-op
                                }
                            }
                        }
                    }

                    if (privateLookup != null)
                    {
                        try
                        {
                            final MethodHandles.Lookup lookupInstance = MethodHandles.Lookup.class.cast(
                                    privateLookup.invoke(
                                            null,
                                            proxyName.startsWith("org.apache.webbeans.custom.signed.") ?
                                                    CustomSignedProxyPackageMarker.class :
                                                    proxyName.startsWith("org.apache.webbeans.custom.") ?
                                                            CustomProxyPackageMarker.class : parent,
                                            lookup));
                            definedClass = (Class<T>) defineClass.invoke(lookupInstance, proxyBytes);
                            defineClassImpl = 2;
                            break;
                        }
                        catch (final Exception e)
                        {
                            definedClass = handleLinkageError(e, proxyName, classLoader);
                            if (definedClass != null)
                            {
                                defineClassImpl = 2;
                                break;
                            }
                        }
                    }
                }
                case 3: // unlikely - unsafe
                    try
                    {
                        definedClass = Class.class.cast(unsafeDefineClass().invoke(
                                internalUnsafe, proxyName, proxyBytes, 0, proxyBytes.length, classLoader, null));
                        defineClassImpl = 3;
                    }
                    catch (final Throwable t)
                    {
                        definedClass = handleLinkageError(t, proxyName, classLoader);
                    }
                    break;
                default:
                    throw new IllegalAccessError("Unknown defineClass impl: " + defineClassImpl);
            }

            // CHECKSTYLE:ON
            if (definedClass == null)
            {
                throw new IllegalStateException("Can't define proxy " + proxyName);
            }

            return (Class<T>) Class.forName(definedClass.getName(), true, classLoader);
        }
        catch (final Throwable e)
        {
            return onProxyGenerationError(e, proxyName, classLoader);
        }
    }