openwebbeans-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rmannibu...@apache.org
Subject svn commit: r1844973 - in /openwebbeans/trunk/webbeans-impl/src: main/java/org/apache/webbeans/proxy/ test/java/org/apache/webbeans/proxy/
Date Sat, 27 Oct 2018 14:27:42 GMT
Author: rmannibucau
Date: Sat Oct 27 14:27:41 2018
New Revision: 1844973

URL: http://svn.apache.org/viewvc?rev=1844973&view=rev
Log:
extracting unsafe proxy code in an Unsafe class - no fonctional change

Added:
    openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/Unsafe.java
    openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/proxy/
    openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/proxy/UnsafeTest.java
Modified:
    openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/AbstractProxyFactory.java
    openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/InterceptorDecoratorProxyFactory.java
    openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/NormalScopeProxyFactory.java

Modified: openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/AbstractProxyFactory.java
URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/AbstractProxyFactory.java?rev=1844973&r1=1844972&r2=1844973&view=diff
==============================================================================
--- openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/AbstractProxyFactory.java
(original)
+++ openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/AbstractProxyFactory.java
Sat Oct 27 14:27:41 2018
@@ -24,22 +24,14 @@ import static org.apache.xbean.asm7.Clas
 
 import java.io.InputStream;
 import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.security.ProtectionDomain;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.logging.Logger;
 
 import org.apache.webbeans.config.WebBeansContext;
 import org.apache.webbeans.exception.ProxyGenerationException;
 import org.apache.webbeans.exception.WebBeansException;
-import org.apache.webbeans.logger.WebBeansLoggerFacade;
 import org.apache.xbean.asm7.ClassReader;
 import org.apache.xbean.asm7.ClassWriter;
 import org.apache.xbean.asm7.MethodVisitor;
@@ -61,20 +53,10 @@ public abstract class AbstractProxyFacto
      */
     public static final int MODIFIER_VARARGS = 0x00000080;
 
-
-    private static final Logger logger = WebBeansLoggerFacade.getLogger(AbstractProxyFactory.class);
+    protected final Unsafe unsafe;
 
     protected WebBeansContext webBeansContext;
 
-    /**
-     * contains the instance of sun.misc.Unsafe.
-     * We use it for creating the proxy instance without fully
-     * initializing the class.
-     */
-    private Object unsafe;
-    private Method unsafeAllocateInstance;
-    private AtomicReference<Method> unsafeDefineClass;
-
     private final int javaVersion;
 
 
@@ -90,7 +72,7 @@ public abstract class AbstractProxyFacto
     {
         this.webBeansContext = webBeansContext;
         javaVersion = determineDefaultJavaVersion();
-        initializeUnsafe();
+        unsafe = new Unsafe();
     }
 
     private int determineDefaultJavaVersion()
@@ -264,7 +246,7 @@ public abstract class AbstractProxyFacto
                 sortOutDuplicateMethods(nonInterceptedMethods),
                 constructor);
 
-        return defineAndLoadClass(classLoader, proxyClassName, proxyBytes);
+        return unsafe.defineAndLoadClass(classLoader, proxyClassName, proxyBytes);
     }
 
     private Method[] sortOutDuplicateMethods(Method[] methods)
@@ -371,109 +353,6 @@ public abstract class AbstractProxyFacto
     }
 
 
-    /**
-     * The 'defineClass' method on the ClassLoader is protected, thus we need to invoke it
via reflection.
-     * @return the Class which got loaded in the classloader
-     */
-    private <T> Class<T> defineAndLoadClass(ClassLoader classLoader, String proxyName,
byte[] proxyBytes)
-            throws ProxyGenerationException
-    {
-        Class<?> clazz = classLoader.getClass();
-
-        Method defineClassMethod = null;
-        do
-        {
-            try
-            {
-                defineClassMethod = clazz.getDeclaredMethod("defineClass", String.class,
byte[].class, int.class, int.class);
-            }
-            catch (NoSuchMethodException e)
-            {
-                // do nothing, we need to search the superclass
-            }
-
-            clazz = clazz.getSuperclass();
-        } while (defineClassMethod == null && clazz != Object.class);
-
-        if (defineClassMethod != null && !defineClassMethod.isAccessible())
-        {
-            try
-            {
-                defineClassMethod.setAccessible(true);
-            }
-            catch (RuntimeException re) // likely j9, let's use unsafe
-            {
-                defineClassMethod = null;
-            }
-        }
-
-        try
-        {
-            Class<T> definedClass;
-
-            if (defineClassMethod != null)
-            {
-                definedClass = (Class<T>) defineClassMethod.invoke(classLoader, proxyName,
proxyBytes, 0, proxyBytes.length);
-            }
-            else
-            {
-
-                definedClass = (Class<T>) unsafeDefineClass().invoke(unsafe, proxyName,
proxyBytes, 0, proxyBytes.length, classLoader, null);
-            }
-
-            return (Class<T>) Class.forName(definedClass.getName(), true, classLoader);
-        }
-        catch (InvocationTargetException le) // if concurrent calls are done then ensure
to just reload the created one
-        {
-            if (LinkageError.class.isInstance(le.getCause()))
-            {
-                try
-                {
-                    return (Class<T>) Class.forName(proxyName.replace('/', '.'), true,
classLoader);
-                }
-                catch (ClassNotFoundException e)
-                {
-                    // default error handling
-                }
-            }
-            throw new ProxyGenerationException(le.getCause());
-        }
-        catch (Throwable e)
-        {
-            throw new ProxyGenerationException(e);
-        }
-    }
-
-    private Method unsafeDefineClass()
-    {
-        Method value = unsafeDefineClass.get();
-        if (value == null)
-        {
-            synchronized (this)
-            {
-                final Class<?> unsafeClass = getUnsafeClass();
-                value = AccessController.doPrivileged(new PrivilegedAction<Method>()
-                {
-                    @Override
-                    public Method run()
-                    {
-                        try
-                        {
-                            return unsafeClass.getDeclaredMethod("defineClass",
-                                    String.class, byte[].class, int.class, int.class, ClassLoader.class,
ProtectionDomain.class);
-                        }
-                        catch (final Exception e)
-                        {
-                            throw new IllegalStateException("Cannot get Unsafe.defineClass
or equivalent", e);
-                        }
-                    }
-                });
-                unsafeDefineClass.compareAndSet(null, value);
-            }
-        }
-        return value;
-    }
-
 
     protected boolean unproxyableMethod(Method delegatedMethod)
     {
@@ -736,121 +615,6 @@ public abstract class AbstractProxyFacto
         mv.visitInsn(getReturnInsn(returnType));
     }
 
-    protected <T> T unsafeNewInstance(Class<T> clazz)
-    {
-        try
-        {
-            if (unsafeAllocateInstance != null)
-            {
-                return (T) unsafeAllocateInstance.invoke(unsafe, clazz);
-            }
-            else
-            {
-                try
-                {
-                    return clazz.getConstructor().newInstance();
-                }
-                catch (final Exception e)
-                {
-                    throw new IllegalStateException("Failed to allocateInstance of Proxy
class " + clazz.getName(), e);
-                }
-            }
-        }
-        catch (IllegalAccessException e)
-        {
-            throw new IllegalStateException("Failed to allocateInstance of Proxy class "
+ clazz.getName(), e);
-        }
-        catch (InvocationTargetException e)
-        {
-            Throwable throwable = e.getTargetException() != null ? e.getTargetException()
: e;
-            throw new IllegalStateException("Failed to allocateInstance of Proxy class "
+ clazz.getName(),
-                    throwable);
-        }
-    }
-
-
-    private void initializeUnsafe()
-    {
-        final Class<?> unsafeClass = getUnsafeClass();
-
-        Object unsafe = AccessController.doPrivileged(new PrivilegedAction<Object>()
-        {
-            @Override
-            public Object run()
-            {
-                try
-                {
-                    Field field = unsafeClass.getDeclaredField("theUnsafe");
-                    field.setAccessible(true);
-                    return field.get(null);
-                }
-                catch (Exception e)
-                {
-                    logger.info("Cannot get sun.misc.Unsafe - will use newInstance() instead!");
-                    return null;
-                }
-            }
-        });
-
-        this.unsafe = unsafe;
-
-        if (unsafe != null)
-        {
-            unsafeAllocateInstance = AccessController.doPrivileged(new PrivilegedAction<Method>()
-            {
-                @Override
-                public Method run()
-                {
-                    try
-                    {
-                        Method mtd = unsafeClass.getDeclaredMethod("allocateInstance", Class.class);
-                        mtd.setAccessible(true);
-                        return mtd;
-                    }
-                    catch (Exception e)
-                    {
-                        return null; // use newInstance()
-                    }
-                }
-            });
-        }
-    }
-
-    private Class<?> getUnsafeClass()
-    {
-        Class<?> unsafeClass;
-        try
-        {
-            unsafeClass = AccessController.doPrivileged(new PrivilegedAction<Class<?>>()
-            {
-                @Override
-                public Class<?> run()
-                {
-                    try
-                    {
-                        return Thread.currentThread().getContextClassLoader().loadClass("sun.misc.Unsafe");
-                    }
-                    catch (Exception e)
-                    {
-                        try
-                        {
-                            return ClassLoader.getSystemClassLoader().loadClass("sun.misc.Unsafe");
-                        }
-                        catch (ClassNotFoundException e1)
-                        {
-                            throw new IllegalStateException("Cannot get sun.misc.Unsafe",
e);
-                        }
-                    }
-                }
-            });
-        }
-        catch (final Exception e)
-        {
-            throw new IllegalStateException("Cannot get sun.misc.Unsafe class", e);
-        }
-        return unsafeClass;
-    }
-
     /**
      * Create an Object[] parameter which contains all the parameters of the currently invoked
method
      * and store this array for use in the call stack.

Modified: openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/InterceptorDecoratorProxyFactory.java
URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/InterceptorDecoratorProxyFactory.java?rev=1844973&r1=1844972&r2=1844973&view=diff
==============================================================================
--- openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/InterceptorDecoratorProxyFactory.java
(original)
+++ openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/InterceptorDecoratorProxyFactory.java
Sat Oct 27 14:27:41 2018
@@ -87,7 +87,7 @@ public class InterceptorDecoratorProxyFa
 
         try
         {
-            T proxy = unsafeNewInstance(proxyClass);
+            T proxy = unsafe.unsafeNewInstance(proxyClass);
 
             Field delegateField = proxy.getClass().getDeclaredField(FIELD_PROXIED_INSTANCE);
             delegateField.setAccessible(true);

Modified: openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/NormalScopeProxyFactory.java
URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/NormalScopeProxyFactory.java?rev=1844973&r1=1844972&r2=1844973&view=diff
==============================================================================
--- openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/NormalScopeProxyFactory.java
(original)
+++ openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/NormalScopeProxyFactory.java
Sat Oct 27 14:27:41 2018
@@ -291,7 +291,7 @@ public class NormalScopeProxyFactory ext
     {
         try
         {
-            T proxy = unsafeNewInstance(proxyClass);
+            T proxy = unsafe.unsafeNewInstance(proxyClass);
 
             Field delegateField = proxy.getClass().getDeclaredField(FIELD_INSTANCE_PROVIDER);
             delegateField.setAccessible(true);

Added: openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/Unsafe.java
URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/Unsafe.java?rev=1844973&view=auto
==============================================================================
--- openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/Unsafe.java (added)
+++ openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/Unsafe.java Sat
Oct 27 14:27:41 2018
@@ -0,0 +1,238 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.webbeans.proxy;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.ProtectionDomain;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.apache.webbeans.exception.ProxyGenerationException;
+import org.apache.webbeans.logger.WebBeansLoggerFacade;
+
+public class Unsafe
+{
+    /**
+     * contains the instance of sun.misc.Unsafe.
+     * We use it for creating the proxy instance without fully
+     * initializing the class.
+     */
+    private Object unsafe;
+    private Method unsafeAllocateInstance;
+    private final AtomicReference<Method> unsafeDefineClass = new AtomicReference<>();
+
+    public Unsafe()
+    {
+        final Class<?> unsafeClass = getUnsafeClass();
+
+        this.unsafe = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
{
+            try
+            {
+                Field field = unsafeClass.getDeclaredField("theUnsafe");
+                field.setAccessible(true);
+                return field.get(null);
+            }
+            catch (Exception e)
+            {
+                WebBeansLoggerFacade.getLogger(Unsafe.class)
+                        .info("Cannot get sun.misc.Unsafe - will use newInstance() instead!");
+                return null;
+            }
+        });
+
+        if (unsafe != null)
+        {
+            unsafeAllocateInstance = AccessController.doPrivileged((PrivilegedAction<Method>)
() -> {
+                try
+                {
+                    Method mtd = unsafeClass.getDeclaredMethod("allocateInstance", Class.class);
+                    mtd.setAccessible(true);
+                    return mtd;
+                }
+                catch (Exception e)
+                {
+                    return null; // use newInstance()
+                }
+            });
+        }
+    }
+
+    /**
+     * The 'defineClass' method on the ClassLoader is protected, thus we need to invoke it
via reflection.
+     * @return the Class which got loaded in the classloader
+     */
+    public <T> Class<T> defineAndLoadClass(ClassLoader classLoader, String proxyName,
byte[] proxyBytes)
+            throws ProxyGenerationException
+    {
+        Class<?> clazz = classLoader.getClass();
+
+        Method defineClassMethod = null;
+        do
+        {
+            try
+            {
+                defineClassMethod = clazz.getDeclaredMethod("defineClass", String.class,
byte[].class, int.class, int.class);
+            }
+            catch (NoSuchMethodException e)
+            {
+                // do nothing, we need to search the superclass
+            }
+
+            clazz = clazz.getSuperclass();
+        } while (defineClassMethod == null && clazz != Object.class);
+
+        if (defineClassMethod != null && !defineClassMethod.isAccessible())
+        {
+            try
+            {
+                defineClassMethod.setAccessible(true);
+            }
+            catch (RuntimeException re) // likely j9, let's use unsafe
+            {
+                defineClassMethod = null;
+            }
+        }
+
+        try
+        {
+            Class<T> definedClass;
+
+            if (defineClassMethod != null)
+            {
+                definedClass = (Class<T>) defineClassMethod.invoke(classLoader, proxyName,
proxyBytes, 0, proxyBytes.length);
+            }
+            else
+            {
+
+                definedClass = (Class<T>) unsafeDefineClass().invoke(unsafe, proxyName,
proxyBytes, 0, proxyBytes.length, classLoader, null);
+            }
+
+            return (Class<T>) Class.forName(definedClass.getName(), true, classLoader);
+        }
+        catch (InvocationTargetException le) // if concurrent calls are done then ensure
to just reload the created one
+        {
+            if (LinkageError.class.isInstance(le.getCause()))
+            {
+                try
+                {
+                    return (Class<T>) Class.forName(proxyName.replace('/', '.'), true,
classLoader);
+                }
+                catch (ClassNotFoundException e)
+                {
+                    // default error handling
+                }
+            }
+            throw new ProxyGenerationException(le.getCause());
+        }
+        catch (Throwable e)
+        {
+            throw new ProxyGenerationException(e);
+        }
+    }
+
+    private Method unsafeDefineClass()
+    {
+        Method value = unsafeDefineClass.get();
+        if (value == null)
+        {
+            synchronized (this)
+            {
+                final Class<?> unsafeClass = getUnsafeClass();
+                value = AccessController.doPrivileged((PrivilegedAction<Method>) ()
-> {
+                    try
+                    {
+                        return unsafeClass.getDeclaredMethod("defineClass",
+                                String.class, byte[].class, int.class, int.class, ClassLoader.class,
ProtectionDomain.class);
+                    }
+                    catch (final Exception e)
+                    {
+                        throw new IllegalStateException("Cannot get Unsafe.defineClass or
equivalent", e);
+                    }
+                });
+                unsafeDefineClass.compareAndSet(null, value);
+            }
+        }
+        return value;
+    }
+
+    public <T> T unsafeNewInstance(Class<T> clazz)
+    {
+        try
+        {
+            if (unsafeAllocateInstance != null)
+            {
+                return (T) unsafeAllocateInstance.invoke(unsafe, clazz);
+            }
+            else
+            {
+                try
+                {
+                    return clazz.getConstructor().newInstance();
+                }
+                catch (final Exception e)
+                {
+                    throw new IllegalStateException("Failed to allocateInstance of Proxy
class " + clazz.getName(), e);
+                }
+            }
+        }
+        catch (IllegalAccessException e)
+        {
+            throw new IllegalStateException("Failed to allocateInstance of Proxy class "
+ clazz.getName(), e);
+        }
+        catch (InvocationTargetException e)
+        {
+            Throwable throwable = e.getTargetException() != null ? e.getTargetException()
: e;
+            throw new IllegalStateException("Failed to allocateInstance of Proxy class "
+ clazz.getName(),
+                    throwable);
+        }
+    }
+
+    private Class<?> getUnsafeClass()
+    {
+        Class<?> unsafeClass;
+        try
+        {
+            unsafeClass = AccessController.doPrivileged((PrivilegedAction<Class<?>>)
() -> {
+                try
+                {
+                    return Thread.currentThread().getContextClassLoader().loadClass("sun.misc.Unsafe");
+                }
+                catch (Exception e)
+                {
+                    try
+                    {
+                        return ClassLoader.getSystemClassLoader().loadClass("sun.misc.Unsafe");
+                    }
+                    catch (ClassNotFoundException e1)
+                    {
+                        throw new IllegalStateException("Cannot get sun.misc.Unsafe", e);
+                    }
+                }
+            });
+        }
+        catch (final Exception e)
+        {
+            throw new IllegalStateException("Cannot get sun.misc.Unsafe class", e);
+        }
+        return unsafeClass;
+    }
+}

Added: openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/proxy/UnsafeTest.java
URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/proxy/UnsafeTest.java?rev=1844973&view=auto
==============================================================================
--- openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/proxy/UnsafeTest.java
(added)
+++ openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/proxy/UnsafeTest.java
Sat Oct 27 14:27:41 2018
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.webbeans.proxy;
+
+import static org.apache.webbeans.util.Asserts.assertNotNull;
+import static org.junit.Assert.assertFalse;
+
+import org.junit.Test;
+
+public class UnsafeTest {
+    @Test
+    public void ensureUnsafeIsAvailable()
+    {
+        final Unsafe unsafe = new Unsafe();
+        final SpyConstructor obj = unsafe.unsafeNewInstance(SpyConstructor.class);
+        assertNotNull(obj);
+        assertFalse(obj.called);
+    }
+
+    public static class SpyConstructor
+    {
+        private boolean called;
+
+        public SpyConstructor()
+        {
+            called = true;
+        }
+    }
+}



Mime
View raw message