diff --git a/.travis.yml b/.travis.yml index 58d2c3d..c003429 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,20 @@ sudo: false language: java -install: mvn install -DskipTests=true -Dgpg.skip=true -jdk: - - oraclejdk8 +install: mvn install -Dgpg.skip=true + +jobs: + include: + - stage: adoptopenjdk.net - Eclipse OpenJ9 + env: + - MAVEN_OPTS="--add-exports java.base/jdk.internal.misc=ALL-UNNAMED --add-exports java.base/jdk.internal.reflect=ALL-UNNAMED" + before_install: + - unset -v _JAVA_OPTIONS + - wget https://github.com/sormuras/bach/raw/master/install-jdk.sh + - source install-jdk.sh --url $(curl --silent https://api.adoptopenjdk.net/v2/binary/nightly/openjdk11\?openjdk_impl\=openj9\&os\=linux\&arch\=x64\&release\=latest\&type\=jdk | grep 'binary_link' | grep -Eo '(http|https)://[^"]+' | head -1) + - stage: jdk.java.net - OpenJDK - GPL + jdk: oraclejdk8 notifications: email: false diff --git a/pom.xml b/pom.xml index 7ead24d..f08f8d6 100644 --- a/pom.xml +++ b/pom.xml @@ -50,6 +50,17 @@ + + + + maven-surefire-plugin + 3.0.0-M3 + + 0 + + + + org.apache.maven.plugins @@ -108,7 +119,7 @@ org.jacoco jacoco-maven-plugin - 0.7.9 + 0.8.2 diff --git a/src/main/java/net/jodah/typetools/TypeResolver.java b/src/main/java/net/jodah/typetools/TypeResolver.java index 0b9f17d..1633164 100644 --- a/src/main/java/net/jodah/typetools/TypeResolver.java +++ b/src/main/java/net/jodah/typetools/TypeResolver.java @@ -17,7 +17,6 @@ import java.lang.ref.Reference; import java.lang.ref.WeakReference; -import java.lang.reflect.AccessibleObject; import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.Field; @@ -29,16 +28,12 @@ import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; import java.lang.reflect.WildcardType; -import java.security.AccessController; -import java.security.PrivilegedExceptionAction; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.WeakHashMap; -import sun.misc.Unsafe; - /** * Enhanced type resolution utilities. * @@ -54,6 +49,7 @@ public final class TypeResolver { private static Method GET_CONSTANT_POOL; private static Method GET_CONSTANT_POOL_SIZE; private static Method GET_CONSTANT_POOL_METHOD_AT; + private static Object JAVA_LANG_ACCESS; private static final Map OBJECT_METHODS = new HashMap(); private static final Map, Class> PRIMITIVE_WRAPPERS; private static final Double JAVA_VERSION; @@ -62,39 +58,49 @@ public final class TypeResolver { JAVA_VERSION = Double.parseDouble(System.getProperty("java.specification.version", "0")); try { - Unsafe unsafe = AccessController.doPrivileged(new PrivilegedExceptionAction() { - @Override - public Unsafe run() throws Exception { - final Field f = Unsafe.class.getDeclaredField("theUnsafe"); - f.setAccessible(true); - - return (Unsafe) f.get(null); - } - }); + String constantPoolName = null; + String sharedSecretName = null; + if (JAVA_VERSION < 9) { + constantPoolName = "sun.reflect.ConstantPool"; + sharedSecretName = "sun.misc.SharedSecrets"; + } else { + constantPoolName = "jdk.internal.reflect.ConstantPool"; + sharedSecretName = "jdk.internal.misc.SharedSecrets"; + } + + Class sharedSecretsClass = Class.forName(sharedSecretName); + Method getJavaLangAccessMethod = sharedSecretsClass.getDeclaredMethod("getJavaLangAccess"); + JAVA_LANG_ACCESS = getJavaLangAccessMethod.invoke(null); + + GET_CONSTANT_POOL = JAVA_LANG_ACCESS.getClass().getDeclaredMethod("getConstantPool", Class.class);; - GET_CONSTANT_POOL = Class.class.getDeclaredMethod("getConstantPool"); - String constantPoolName = JAVA_VERSION < 9 ? "sun.reflect.ConstantPool" : "jdk.internal.reflect.ConstantPool"; Class constantPoolClass = Class.forName(constantPoolName); GET_CONSTANT_POOL_SIZE = constantPoolClass.getDeclaredMethod("getSize"); GET_CONSTANT_POOL_METHOD_AT = constantPoolClass.getDeclaredMethod("getMethodAt", int.class); - // setting the methods as accessible - Field overrideField = AccessibleObject.class.getDeclaredField("override"); - long overrideFieldOffset = unsafe.objectFieldOffset(overrideField); - unsafe.putBoolean(GET_CONSTANT_POOL, overrideFieldOffset, true); - unsafe.putBoolean(GET_CONSTANT_POOL_SIZE, overrideFieldOffset, true); - unsafe.putBoolean(GET_CONSTANT_POOL_METHOD_AT, overrideFieldOffset, true); + GET_CONSTANT_POOL.setAccessible(true); + GET_CONSTANT_POOL_SIZE.setAccessible(true); + GET_CONSTANT_POOL_METHOD_AT.setAccessible(true); // additional checks - make sure we get a result when invoking the Class::getConstantPool and // ConstantPool::getSize on a class - Object constantPool = GET_CONSTANT_POOL.invoke(Object.class); + Object constantPool = GET_CONSTANT_POOL.invoke(JAVA_LANG_ACCESS, Object.class); GET_CONSTANT_POOL_SIZE.invoke(constantPool); for (Method method : Object.class.getDeclaredMethods()) OBJECT_METHODS.put(method.getName(), method); RESOLVES_LAMBDAS = true; - } catch (Exception ignore) { + } catch (Exception exception) { + if (JAVA_VERSION == 8) { + throw new IllegalStateException("Java 8 detected but lambda support initialization failed - Unsupported JDK?", exception); + } else if (JAVA_VERSION > 8) { + // TypeResolver can only work if JVM is started with parameters + // --add-exports java.base/jdk.internal.misc=ALL-UNNAMED --add-exports java.base/jdk.internal.reflect=ALL-UNNAMED + // which allow unnamed Java modules to access the jdk.internal.misc and jdk.internal.reflect packages, even if they + // are not exported by module java.base + throw new IllegalStateException("Java 9 or higher detected but internal access failed, did you remember to --add-exports?", exception); + } } Map, Class> types = new HashMap, Class>(); @@ -738,7 +744,7 @@ private static boolean isDefaultMethod(Method m) { private static Member getMemberRef(Class type) { Object constantPool; try { - constantPool = GET_CONSTANT_POOL.invoke(type); + constantPool = GET_CONSTANT_POOL.invoke(JAVA_LANG_ACCESS, type); } catch (Exception ignore) { return null; }