diff options
author | chibash <chiba@javassist.org> | 2018-09-07 01:04:04 +0900 |
---|---|---|
committer | chibash <chiba@javassist.org> | 2018-09-07 01:04:04 +0900 |
commit | 0958148acbb1b737ca90f78670a4d13c6f321416 (patch) | |
tree | 57f8a3d9b513a6a09452915b384be21b5e40733f | |
parent | e0439f8e0493b46f5e19de2f0972520f6a59bedd (diff) | |
download | javassist-0958148acbb1b737ca90f78670a4d13c6f321416.tar.gz javassist-0958148acbb1b737ca90f78670a4d13c6f321416.zip |
does refactoring for javassist.util.proxy.
-rw-r--r-- | javassist.jar | bin | 763837 -> 0 bytes | |||
-rw-r--r-- | src/main/javassist/util/proxy/DefineClassHelper.java | 293 | ||||
-rwxr-xr-x | src/main/javassist/util/proxy/SecurityActions.java | 10 |
3 files changed, 150 insertions, 153 deletions
diff --git a/javassist.jar b/javassist.jar Binary files differdeleted file mode 100644 index 4c72e547..00000000 --- a/javassist.jar +++ /dev/null diff --git a/src/main/javassist/util/proxy/DefineClassHelper.java b/src/main/javassist/util/proxy/DefineClassHelper.java index b367931a..bc6866ce 100644 --- a/src/main/javassist/util/proxy/DefineClassHelper.java +++ b/src/main/javassist/util/proxy/DefineClassHelper.java @@ -31,194 +31,191 @@ import javassist.bytecode.ClassFile; * * @since 3.22 */ -public class DefineClassHelper -{ +public class DefineClassHelper { - private static enum SecuredPrivileged - { - JAVA_9 { - final class ReferencedUnsafe - { - private final SecurityActions.TheUnsafe sunMiscUnsafeTheUnsafe; - private final MethodHandle defineClass; + private static abstract class Helper { + abstract Class<?> defineClass(String name, byte[] b, int off, int len, + ClassLoader loader, ProtectionDomain protectionDomain) + throws ClassFormatError; + } - ReferencedUnsafe(SecurityActions.TheUnsafe usf, MethodHandle meth) - { - this.sunMiscUnsafeTheUnsafe = usf; - this.defineClass = meth; - } + private static class Java9 extends Helper { + final class ReferencedUnsafe { + private final SecurityActions.TheUnsafe sunMiscUnsafeTheUnsafe; + private final MethodHandle defineClass; - Class<?> defineClass(String name, byte[] b, int off, int len, - ClassLoader loader, ProtectionDomain protectionDomain) - throws ClassFormatError { - try { - if (getCallerClass.invoke(stack) != SecuredPrivileged.JAVA_9.getClass()) - throw new IllegalAccessError("Access denied for caller."); - } catch (Exception e) { - throw new RuntimeException("cannot initialize", e); - } - try { - return (Class<?>) defineClass.invokeWithArguments( - sunMiscUnsafeTheUnsafe.theUnsafe, - name, b, off, len, loader, protectionDomain); - } catch (Throwable e) { - if (e instanceof RuntimeException) throw (RuntimeException) e; - if (e instanceof ClassFormatError) throw (ClassFormatError) e; - throw new ClassFormatError(e.getMessage()); - } - } + ReferencedUnsafe(SecurityActions.TheUnsafe usf, MethodHandle meth) { + this.sunMiscUnsafeTheUnsafe = usf; + this.defineClass = meth; } - private final Object stack; - private final Method getCallerClass; - { - Class<?> stackWalkerClass = null; - try { - stackWalkerClass = Class.forName("java.lang.StackWalker"); - } catch (ClassNotFoundException e) { - // Skip initialization when the class doesn't exist i.e. we are on JDK < 9 - } - if (stackWalkerClass != null) { - try { - Class<?> optionClass = Class.forName("java.lang.StackWalker$Option"); - stack = stackWalkerClass.getMethod("getInstance", optionClass) - // The first one is RETAIN_CLASS_REFERENCE - .invoke(null, optionClass.getEnumConstants()[0]); - getCallerClass = stackWalkerClass.getMethod("getCallerClass"); - } catch (Throwable e) { - throw new RuntimeException("cannot initialize", e); - } - } else { - stack = null; - getCallerClass = null; - } - } - private final ReferencedUnsafe sunMiscUnsafe = getReferencedUnsafe(); - private final ReferencedUnsafe getReferencedUnsafe() + + Class<?> defineClass(String name, byte[] b, int off, int len, + ClassLoader loader, ProtectionDomain protectionDomain) + throws ClassFormatError { try { - if (null != SecuredPrivileged.JAVA_9 - && getCallerClass.invoke(stack) != this.getClass()) + if (getCallerClass.invoke(stack) != Java9.class) throw new IllegalAccessError("Access denied for caller."); } catch (Exception e) { throw new RuntimeException("cannot initialize", e); } try { - SecurityActions.TheUnsafe usf = SecurityActions.getSunMiscUnsafeAnonymously(); - List<Method> defineClassMethod = usf.methods.get("defineClass"); - // On Java 11+ the defineClass method does not exist anymore - if (null == defineClassMethod) - return null; - MethodHandle meth = MethodHandles.lookup() - .unreflect(defineClassMethod.get(0)); - return new ReferencedUnsafe(usf, meth); + return (Class<?>) defineClass.invokeWithArguments( + sunMiscUnsafeTheUnsafe.theUnsafe, + name, b, off, len, loader, protectionDomain); } catch (Throwable e) { - throw new RuntimeException("cannot initialize", e); + if (e instanceof RuntimeException) throw (RuntimeException) e; + if (e instanceof ClassFormatError) throw (ClassFormatError) e; + throw new ClassFormatError(e.getMessage()); } } + } - @Override - public Class<?> defineClass(String name, byte[] b, int off, int len, - ClassLoader loader, ProtectionDomain protectionDomain) - throws ClassFormatError - { + private final Object stack; + private final Method getCallerClass; + private final ReferencedUnsafe sunMiscUnsafe = getReferencedUnsafe(); + + Java9 () { + Class<?> stackWalkerClass = null; + try { + stackWalkerClass = Class.forName("java.lang.StackWalker"); + } catch (ClassNotFoundException e) { + // Skip initialization when the class doesn't exist i.e. we are on JDK < 9 + } + if (stackWalkerClass != null) { try { - if (getCallerClass.invoke(stack) != DefineClassHelper.class) - throw new IllegalAccessError("Access denied for caller."); - } catch (Exception e) { + Class<?> optionClass = Class.forName("java.lang.StackWalker$Option"); + stack = stackWalkerClass.getMethod("getInstance", optionClass) + // The first one is RETAIN_CLASS_REFERENCE + .invoke(null, optionClass.getEnumConstants()[0]); + getCallerClass = stackWalkerClass.getMethod("getCallerClass"); + } catch (Throwable e) { throw new RuntimeException("cannot initialize", e); } - return sunMiscUnsafe.defineClass(name, b, off, len, loader, - protectionDomain); + } else { + stack = null; + getCallerClass = null; } - }, - JAVA_7 { - private final SecurityActions stack = SecurityActions.stack; - private final MethodHandle defineClass = getDefineClassMethodHandle(); - private final MethodHandle getDefineClassMethodHandle() - { - if (null != SecuredPrivileged.JAVA_7 - && stack.getCallerClass() != this.getClass()) + } + + private final ReferencedUnsafe getReferencedUnsafe() { + try { + if (privileged != null && getCallerClass.invoke(stack) != this.getClass()) throw new IllegalAccessError("Access denied for caller."); - try { - return SecurityActions.getMethodHandle(ClassLoader.class, - "defineClass", new Class[] { + } catch (Exception e) { + throw new RuntimeException("cannot initialize", e); + } + try { + SecurityActions.TheUnsafe usf = SecurityActions.getSunMiscUnsafeAnonymously(); + List<Method> defineClassMethod = usf.methods.get("defineClass"); + // On Java 11+ the defineClass method does not exist anymore + if (null == defineClassMethod) + return null; + MethodHandle meth = MethodHandles.lookup().unreflect(defineClassMethod.get(0)); + return new ReferencedUnsafe(usf, meth); + } catch (Throwable e) { + throw new RuntimeException("cannot initialize", e); + } + } + + @Override + Class<?> defineClass(String name, byte[] b, int off, int len, + ClassLoader loader, ProtectionDomain protectionDomain) + throws ClassFormatError + { + try { + if (getCallerClass.invoke(stack) != DefineClassHelper.class) + throw new IllegalAccessError("Access denied for caller."); + } catch (Exception e) { + throw new RuntimeException("cannot initialize", e); + } + return sunMiscUnsafe.defineClass(name, b, off, len, loader, + protectionDomain); + } + } + + private static class Java7 extends Helper { + private final SecurityActions stack = SecurityActions.stack; + private final MethodHandle defineClass = getDefineClassMethodHandle(); + private final MethodHandle getDefineClassMethodHandle() { + if (privileged != null && stack.getCallerClass() != this.getClass()) + throw new IllegalAccessError("Access denied for caller."); + try { + return SecurityActions.getMethodHandle(ClassLoader.class, "defineClass", + new Class[] { String.class, byte[].class, int.class, int.class, ProtectionDomain.class }); } catch (NoSuchMethodException e) { throw new RuntimeException("cannot initialize", e); } - } + } - @Override - protected Class<?> defineClass(String name, byte[] b, int off, int len, - ClassLoader loader, ProtectionDomain protectionDomain) throws ClassFormatError - { - if (stack.getCallerClass() != DefineClassHelper.class) - throw new IllegalAccessError("Access denied for caller."); - try { - return (Class<?>) defineClass.invokeWithArguments( + @Override + Class<?> defineClass(String name, byte[] b, int off, int len, + ClassLoader loader, ProtectionDomain protectionDomain) + throws ClassFormatError + { + if (stack.getCallerClass() != DefineClassHelper.class) + throw new IllegalAccessError("Access denied for caller."); + try { + return (Class<?>) defineClass.invokeWithArguments( loader, name, b, off, len, protectionDomain); - } catch (Throwable e) { - if (e instanceof RuntimeException) throw (RuntimeException) e; - if (e instanceof ClassFormatError) throw (ClassFormatError) e; - throw new ClassFormatError(e.getMessage()); - } + } catch (Throwable e) { + if (e instanceof RuntimeException) throw (RuntimeException) e; + if (e instanceof ClassFormatError) throw (ClassFormatError) e; + throw new ClassFormatError(e.getMessage()); } - }, - JAVA_OTHER { - private final Method defineClass = getDefineClassMethod(); - private final SecurityActions stack = SecurityActions.stack; - private final Method getDefineClassMethod() { - if (null != SecuredPrivileged.JAVA_OTHER - && stack.getCallerClass() != this.getClass()) - throw new IllegalAccessError("Access denied for caller."); - try { - return SecurityActions.getDeclaredMethod(ClassLoader.class, - "defineClass", new Class[] { + } + } + + private static class JavaOther extends Helper { + private final Method defineClass = getDefineClassMethod(); + private final SecurityActions stack = SecurityActions.stack; + + private final Method getDefineClassMethod() { + if (privileged != null && stack.getCallerClass() != this.getClass()) + throw new IllegalAccessError("Access denied for caller."); + try { + return SecurityActions.getDeclaredMethod(ClassLoader.class, "defineClass", + new Class[] { String.class, byte[].class, int.class, int.class, ProtectionDomain.class }); - } catch (NoSuchMethodException e) { - throw new RuntimeException("cannot initialize", e); - } + } catch (NoSuchMethodException e) { + throw new RuntimeException("cannot initialize", e); } + } - @Override - protected Class<?> defineClass(String name, byte[] b, int off, int len, - ClassLoader loader, ProtectionDomain protectionDomain) throws ClassFormatError - { - if (stack.getCallerClass() != DefineClassHelper.class) - throw new IllegalAccessError("Access denied for caller."); - try { - SecurityActions.setAccessible(defineClass, true); - return (Class<?>) defineClass.invoke(loader, new Object[] { + @Override + Class<?> defineClass(String name, byte[] b, int off, int len, + ClassLoader loader, ProtectionDomain protectionDomain) + throws ClassFormatError + { + if (stack.getCallerClass() != DefineClassHelper.class) + throw new IllegalAccessError("Access denied for caller."); + try { + SecurityActions.setAccessible(defineClass, true); + return (Class<?>) defineClass.invoke(loader, new Object[] { name, b, off, len, protectionDomain - }); - } catch (Throwable e) { - if (e instanceof ClassFormatError) throw (ClassFormatError) e; - if (e instanceof RuntimeException) throw (RuntimeException) e; - throw new ClassFormatError(e.getMessage()); - } - finally { - SecurityActions.setAccessible(defineClass, false); - } + }); + } catch (Throwable e) { + if (e instanceof ClassFormatError) throw (ClassFormatError) e; + if (e instanceof RuntimeException) throw (RuntimeException) e; + throw new ClassFormatError(e.getMessage()); } - - }; - - protected abstract Class<?> defineClass(String name, byte[] b, int off, int len, - ClassLoader loader, ProtectionDomain protectionDomain) throws ClassFormatError; + finally { + SecurityActions.setAccessible(defineClass, false); + } + } } // Java 11+ removed sun.misc.Unsafe.defineClass, so we fallback to invoking defineClass on // ClassLoader until we have an implementation that uses MethodHandles.Lookup.defineClass - private static final SecuredPrivileged privileged = ClassFile.MAJOR_VERSION > ClassFile.JAVA_10 - ? SecuredPrivileged.JAVA_OTHER + private static final Helper privileged = ClassFile.MAJOR_VERSION > ClassFile.JAVA_10 + ? new JavaOther() : ClassFile.MAJOR_VERSION >= ClassFile.JAVA_9 - ? SecuredPrivileged.JAVA_9 - : ClassFile.MAJOR_VERSION >= ClassFile.JAVA_7 - ? SecuredPrivileged.JAVA_7 - : SecuredPrivileged.JAVA_OTHER; + ? new Java9() + : ClassFile.MAJOR_VERSION >= ClassFile.JAVA_7 ? new Java7() : new JavaOther(); /** * Loads a class file by a given class loader. diff --git a/src/main/javassist/util/proxy/SecurityActions.java b/src/main/javassist/util/proxy/SecurityActions.java index acb89c8d..c940561b 100755 --- a/src/main/javassist/util/proxy/SecurityActions.java +++ b/src/main/javassist/util/proxy/SecurityActions.java @@ -36,6 +36,7 @@ import javassist.bytecode.ClassFile; class SecurityActions extends SecurityManager { public static final SecurityActions stack = new SecurityActions(); + /** * Since Java 9 abruptly removed <code>Reflection.getCallerClass()</code> * in favour of <code>StackWalker</code> we are left having to find a @@ -46,14 +47,13 @@ class SecurityActions extends SecurityManager * functional across all versions, for now. * * @return represents the declaring class of the method that invoked - * the method that called this or idx 2 on the stack trace. - * @since 3.23 */ - public Class<?> getCallerClass() - { + * the method that called this or index 2 on the stack trace. + * @since 3.23 + */ + public Class<?> getCallerClass() { return getClassContext()[2]; } - static Method[] getDeclaredMethods(final Class<?> clazz) { if (System.getSecurityManager() == null) |