From ce8852f6ba175b15e63fa9d80bc2c63e957600a7 Mon Sep 17 00:00:00 2001 From: lukaseder Date: Thu, 21 Jun 2018 12:47:31 +0200 Subject: [PATCH] [#7602] Upgrade jOOR dependency's Java 9 functionality --- .../java/org/jooq/tools/reflect/Compile.java | 76 +++++++++---------- .../java/org/jooq/tools/reflect/Reflect.java | 54 +++++-------- 2 files changed, 59 insertions(+), 71 deletions(-) diff --git a/jOOQ/src/main/java/org/jooq/tools/reflect/Compile.java b/jOOQ/src/main/java/org/jooq/tools/reflect/Compile.java index 28354c0f67..0970c5a872 100644 --- a/jOOQ/src/main/java/org/jooq/tools/reflect/Compile.java +++ b/jOOQ/src/main/java/org/jooq/tools/reflect/Compile.java @@ -15,6 +15,8 @@ package org.jooq.tools.reflect; +import static java.lang.StackWalker.Option.RETAIN_CLASS_REFERENCE; + import java.io.ByteArrayOutputStream; import java.io.OutputStream; import java.io.StringWriter; @@ -32,8 +34,6 @@ import javax.tools.SimpleJavaFileObject; import javax.tools.StandardJavaFileManager; import javax.tools.ToolProvider; -// import static java.lang.StackWalker.Option.RETAIN_CLASS_REFERENCE; - /** * A utility that simplifies in-memory compilation of new classes. @@ -58,7 +58,7 @@ class Compile { files.add(new CharSequenceJavaFileObject(className, content)); StringWriter out = new StringWriter(); - compiler.getTask(null, fileManager, null, null, null, files).call(); + compiler.getTask(out, fileManager, null, null, null, files).call(); if (fileManager.o == null) throw new ReflectException("Compilation error: " + out); @@ -66,48 +66,48 @@ class Compile { Class result = null; // This works if we have private-access to the interfaces in the class hierarchy - // if (Reflect.CACHED_LOOKUP_CONSTRUCTOR != null) { + if (Reflect.CACHED_LOOKUP_CONSTRUCTOR != null) { ClassLoader cl = lookup.lookupClass().getClassLoader(); byte[] b = fileManager.o.getBytes(); result = Reflect.on(cl).call("defineClass", className, b, 0, b.length).get(); - // } + } /* [java-9] */ // Lookup.defineClass() has only been introduced in Java 9. It is // required to get private-access to interfaces in the class hierarchy - // else { - // - // // This method is called by client code from two levels up the current stack frame - // // We need a private-access lookup from the class in that stack frame in order to get - // // private-access to any local interfaces at that location. - // Class caller = StackWalker - // .getInstance(RETAIN_CLASS_REFERENCE) - // .walk(s -> s - // .skip(2) - // .findFirst() - // .get() - // .getDeclaringClass()); - // - // // If the compiled class is in the same package as the caller class, then - // // we can use the private-access Lookup of the caller class - // if (className.startsWith(caller.getPackageName() + ".")) { - // result = MethodHandles - // .privateLookupIn(caller, lookup) - // .defineClass(fileManager.o.getBytes()); - // } - // - // // Otherwise, use an arbitrary class loader. This approach doesn't allow for - // // loading private-access interfaces in the compiled class's type hierarchy - // else { - // result = new ClassLoader() { - // @Override - // protected Class findClass(String name) throws ClassNotFoundException { - // byte[] b = fileManager.o.getBytes(); - // return defineClass(className, b, 0, b.length); - // } - // }.loadClass(className); - // } - // } + else { + + // This method is called by client code from two levels up the current stack frame + // We need a private-access lookup from the class in that stack frame in order to get + // private-access to any local interfaces at that location. + Class caller = StackWalker + .getInstance(RETAIN_CLASS_REFERENCE) + .walk(s -> s + .skip(2) + .findFirst() + .get() + .getDeclaringClass()); + + // If the compiled class is in the same package as the caller class, then + // we can use the private-access Lookup of the caller class + if (className.startsWith(caller.getPackageName() + ".")) { + result = MethodHandles + .privateLookupIn(caller, lookup) + .defineClass(fileManager.o.getBytes()); + } + + // Otherwise, use an arbitrary class loader. This approach doesn't allow for + // loading private-access interfaces in the compiled class's type hierarchy + else { + result = new ClassLoader() { + @Override + protected Class findClass(String name) throws ClassNotFoundException { + byte[] b = fileManager.o.getBytes(); + return defineClass(className, b, 0, b.length); + } + }.loadClass(className); + } + } /* [/java-9] */ return result; diff --git a/jOOQ/src/main/java/org/jooq/tools/reflect/Reflect.java b/jOOQ/src/main/java/org/jooq/tools/reflect/Reflect.java index 74a891d783..ee5d431db3 100644 --- a/jOOQ/src/main/java/org/jooq/tools/reflect/Reflect.java +++ b/jOOQ/src/main/java/org/jooq/tools/reflect/Reflect.java @@ -25,7 +25,6 @@ import java.lang.reflect.Proxy; import java.util.Arrays; import java.util.LinkedHashMap; import java.util.Map; -import java.util.Optional; /** * A wrapper for an {@link Object} or {@link Class} upon which reflective calls @@ -178,36 +177,25 @@ public class Reflect { static final Constructor CACHED_LOOKUP_CONSTRUCTOR; - static final boolean JAVA_9; static { + Constructor result; - // Runtime detection if we're on Java 9 - boolean java9; - + /* [java-9] */ + if (true) + result = null; + else + /* [/java-9] */ try { - Optional.class.getMethod("stream"); - java9 = true; - } - catch (NoSuchMethodException e) { - java9 = false; + result = MethodHandles.Lookup.class.getDeclaredConstructor(Class.class); + + if (!result.isAccessible()) + result.setAccessible(true); } - JAVA_9 = java9; - - Constructor result = null; - - if (!java9) { - try { - result = MethodHandles.Lookup.class.getDeclaredConstructor(Class.class); - - if (!result.isAccessible()) - result.setAccessible(true); - } - - // Can no longer access the above in JDK 9 - catch (Throwable ignore) { - } + // Can no longer access the above in JDK 9 + catch (Throwable ignore) { + result = null; } CACHED_LOOKUP_CONSTRUCTOR = result; @@ -659,14 +647,14 @@ public class Reflect { /* [java-9] */ // Java 9 version - // if (CACHED_LOOKUP_CONSTRUCTOR == null) { - // return MethodHandles - // .privateLookupIn(proxyType, MethodHandles.lookup()) - // .in(proxyType) - // .unreflectSpecial(method, proxyType) - // .bindTo(proxy) - // .invokeWithArguments(args); - // } + if (CACHED_LOOKUP_CONSTRUCTOR == null) { + return MethodHandles + .privateLookupIn(proxyType, MethodHandles.lookup()) + .in(proxyType) + .unreflectSpecial(method, proxyType) + .bindTo(proxy) + .invokeWithArguments(args); + } /* [/java-9] */ // Java 8 version