From 92ee53b460fcde5f8585780ccd829d5034889e71 Mon Sep 17 00:00:00 2001 From: Christian Beikov Date: Fri, 22 Jun 2018 09:03:55 +0200 Subject: [PATCH] [#171] Allow running on JDK 8 and possibly on JDK 7 as well. Fixes #171 --- .../util/proxy/DefineClassHelper.java | 52 +++++++++++++++---- 1 file changed, 43 insertions(+), 9 deletions(-) diff --git a/src/main/javassist/util/proxy/DefineClassHelper.java b/src/main/javassist/util/proxy/DefineClassHelper.java index 4d6c9f9d..38691118 100644 --- a/src/main/javassist/util/proxy/DefineClassHelper.java +++ b/src/main/javassist/util/proxy/DefineClassHelper.java @@ -51,8 +51,12 @@ public class DefineClassHelper Class defineClass(String name, byte[] b, int off, int len, ClassLoader loader, ProtectionDomain protectionDomain) throws ClassFormatError { - if (stack.getCallerClass() != SecuredPrivileged.JAVA_9.getClass()) - throw new IllegalAccessError("Access denied for caller."); + 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, @@ -64,14 +68,40 @@ public class DefineClassHelper } } } - private final StackWalker stack = StackWalker - .getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE); + 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() { - if (null != SecuredPrivileged.JAVA_9 - && stack.getCallerClass() != this.getClass()) - throw new IllegalAccessError("Access denied for caller."); + try { + if (null != SecuredPrivileged.JAVA_9 + && getCallerClass.invoke(stack) != this.getClass()) + throw new IllegalAccessError("Access denied for caller."); + } catch (Exception e) { + throw new RuntimeException("cannot initialize", e); + } try { SecurityActions.TheUnsafe usf = SecurityActions.getSunMiscUnsafeAnonymously(); List defineClassMethod = usf.methods.get("defineClass"); @@ -91,8 +121,12 @@ public class DefineClassHelper ClassLoader loader, ProtectionDomain protectionDomain) throws ClassFormatError { - if (stack.getCallerClass() != DefineClassHelper.class) - throw new IllegalAccessError("Access denied for caller."); + 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); } -- 2.39.5