diff options
Diffstat (limited to 'src/main/javassist/util')
-rw-r--r-- | src/main/javassist/util/proxy/DefineClassHelper.java | 139 | ||||
-rw-r--r-- | src/main/javassist/util/proxy/FactoryHelper.java | 60 | ||||
-rw-r--r-- | src/main/javassist/util/proxy/ProxyFactory.java | 5 |
3 files changed, 145 insertions, 59 deletions
diff --git a/src/main/javassist/util/proxy/DefineClassHelper.java b/src/main/javassist/util/proxy/DefineClassHelper.java new file mode 100644 index 00000000..c5749925 --- /dev/null +++ b/src/main/javassist/util/proxy/DefineClassHelper.java @@ -0,0 +1,139 @@ +/* + * Javassist, a Java-bytecode translator toolkit. + * Copyright (C) 1999- Shigeru Chiba. All Rights Reserved. + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. Alternatively, the contents of this file may be used under + * the terms of the GNU Lesser General Public License Version 2.1 or later, + * or the Apache License Version 2.0. + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + */ + +package javassist.util.proxy; + +import java.io.IOException; +import java.lang.reflect.Method; +import java.lang.reflect.Field; +import java.security.ProtectionDomain; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodHandles.Lookup; +import sun.misc.Unsafe; + +import javassist.CannotCompileException; +import javassist.bytecode.ClassFile; + +/** + * Helper class for invoking {@link ClassLoader#defineClass(String,byte[],int,int)}. + * + * @since 3.22 + */ +public class DefineClassHelper { + private static java.lang.reflect.Method defineClass1 = null; + private static java.lang.reflect.Method defineClass2 = null; + private static Unsafe sunMiscUnsafe = null; + + static { + if (ClassFile.MAJOR_VERSION < ClassFile.JAVA_9) + try { + Class<?> cl = Class.forName("java.lang.ClassLoader"); + defineClass1 = SecurityActions.getDeclaredMethod( + cl, + "defineClass", + new Class[] { String.class, byte[].class, + int.class, int.class }); + + defineClass2 = SecurityActions.getDeclaredMethod( + cl, + "defineClass", + new Class[] { String.class, byte[].class, + int.class, int.class, ProtectionDomain.class }); + } + catch (Exception e) { + throw new RuntimeException("cannot initialize"); + } + else + try { + Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); + theUnsafe.setAccessible(true); + sunMiscUnsafe = (sun.misc.Unsafe)theUnsafe.get(null); + } + catch (Throwable t) {} + } + + /** + * Loads a class file by a given class loader. + * + * @param domain if it is null, a default domain is used. + * @since 3.22 + */ + public static Class<?> toClass(String className, ClassLoader loader, + ProtectionDomain domain, byte[] bcode) + throws CannotCompileException + { + if (ClassFile.MAJOR_VERSION < ClassFile.JAVA_9) + return toClass2(className, loader, domain, bcode); + else { + if (sunMiscUnsafe != null) + try { + return sunMiscUnsafe.defineClass(className, bcode, 0, bcode.length, + loader, domain); + } + catch (Throwable t2) {} + + try { + Lookup lookup = MethodHandles.lookup(); + lookup = lookup.dropLookupMode(java.lang.invoke.MethodHandles.Lookup.PRIVATE); + return lookup.defineClass(bcode); + } + catch (Throwable t) { + throw new CannotCompileException(t); + } + } + } + + private static Class<?> toClass2(String cname, ClassLoader loader, + ProtectionDomain domain, byte[] bcode) + throws CannotCompileException + { + try { + Method method; + Object[] args; + if (domain == null) { + method = defineClass1; + args = new Object[] { cname, bcode, Integer.valueOf(0), + Integer.valueOf(bcode.length) }; + } + else { + method = defineClass2; + args = new Object[] { cname, bcode, Integer.valueOf(0), + Integer.valueOf(bcode.length), domain }; + } + + return toClass3(method, loader, args); + } + catch (RuntimeException e) { + throw e; + } + catch (java.lang.reflect.InvocationTargetException e) { + throw new CannotCompileException(e.getTargetException()); + } + catch (Exception e) { + throw new CannotCompileException(e); + } + } + + private static synchronized + Class<?> toClass3(Method method, ClassLoader loader, Object[] args) + throws Exception + { + SecurityActions.setAccessible(method, true); + Class<?> clazz = (Class<?>)method.invoke(loader, args); + SecurityActions.setAccessible(method, false); + return clazz; + } +} diff --git a/src/main/javassist/util/proxy/FactoryHelper.java b/src/main/javassist/util/proxy/FactoryHelper.java index b17b78ed..39114657 100644 --- a/src/main/javassist/util/proxy/FactoryHelper.java +++ b/src/main/javassist/util/proxy/FactoryHelper.java @@ -16,7 +16,6 @@ package javassist.util.proxy; -import java.lang.reflect.Method; import java.io.BufferedOutputStream; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; @@ -35,28 +34,6 @@ import javassist.bytecode.ClassFile; * @see ProxyFactory */ public class FactoryHelper { - private static java.lang.reflect.Method defineClass1, defineClass2; - - static { - try { - Class cl = Class.forName("java.lang.ClassLoader"); - defineClass1 = SecurityActions.getDeclaredMethod( - cl, - "defineClass", - new Class[] { String.class, byte[].class, - int.class, int.class }); - - defineClass2 = SecurityActions.getDeclaredMethod( - cl, - "defineClass", - new Class[] { String.class, byte[].class, - int.class, int.class, ProtectionDomain.class }); - } - catch (Exception e) { - throw new RuntimeException("cannot initialize"); - } - } - /** * Returns an index for accessing arrays in this class. * @@ -144,45 +121,16 @@ public class FactoryHelper { * @since 3.3 */ public static Class toClass(ClassFile cf, ClassLoader loader, ProtectionDomain domain) - throws CannotCompileException + throws CannotCompileException { try { byte[] b = toBytecode(cf); - Method method; - Object[] args; - if (domain == null) { - method = defineClass1; - args = new Object[] { cf.getName(), b, Integer.valueOf(0), - Integer.valueOf(b.length) }; - } - else { - method = defineClass2; - args = new Object[] { cf.getName(), b, Integer.valueOf(0), - Integer.valueOf(b.length), domain }; - } - - return toClass2(method, loader, args); + return DefineClassHelper.toClass(cf.getName(), loader, domain, b); } - catch (RuntimeException e) { - throw e; - } - catch (java.lang.reflect.InvocationTargetException e) { - throw new CannotCompileException(e.getTargetException()); - } - catch (Exception e) { + catch (IOException e) { throw new CannotCompileException(e); } - } - - private static synchronized Class toClass2(Method method, - ClassLoader loader, Object[] args) - throws Exception - { - SecurityActions.setAccessible(method, true); - Class clazz = (Class)method.invoke(loader, args); - SecurityActions.setAccessible(method, false); - return clazz; - } + } private static byte[] toBytecode(ClassFile cf) throws IOException { ByteArrayOutputStream barray = new ByteArrayOutputStream(); diff --git a/src/main/javassist/util/proxy/ProxyFactory.java b/src/main/javassist/util/proxy/ProxyFactory.java index a85e8de0..81792585 100644 --- a/src/main/javassist/util/proxy/ProxyFactory.java +++ b/src/main/javassist/util/proxy/ProxyFactory.java @@ -27,7 +27,6 @@ import java.util.*; import java.lang.ref.WeakReference; import javassist.CannotCompileException; -import javassist.NotFoundException; import javassist.bytecode.*; /* @@ -795,7 +794,7 @@ public class ProxyFactory { superClass = OBJECT_TYPE; superName = superClass.getName(); basename = interfaces.length == 0 ? superName - : interfaces[0].getName(); + : interfaces[0].getName(); } else { superName = superClass.getName(); basename = superName; @@ -805,7 +804,7 @@ public class ProxyFactory { throw new RuntimeException(superName + " is final"); if (basename.startsWith("java.")) - basename = "org.javassist.tmp." + basename; + basename = "javassist.util.proxy." + basename.replace('.', '_'); } private void allocateClassName() { |