diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/func/FunctionPool.java b/hutool-core/src/main/java/cn/hutool/core/lang/func/FunctionPool.java index 02e611cc3..b235ad7d8 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/func/FunctionPool.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/func/FunctionPool.java @@ -16,13 +16,14 @@ public class FunctionPool { /** * 通过{@code String(char[] value, boolean share)}这个内部构造生成一个Lambda函数
- * 此函数通过传入char[],实现zero-copy的String创建,效率很高。但是要求传入的char[]不可以在其他地方修改。 + * 此函数通过传入char[],实现zero-copy的String创建,效率很高。但是要求传入的char[]不可以在其他地方修改。
+ * 此函数只支持JKDK8 */ - public static final BiFunction STRING_CREATOR; + public static final BiFunction STRING_CREATOR_JDK8; static { final Constructor constructor = ConstructorUtil.getConstructor(String.class, char[].class, boolean.class); - STRING_CREATOR = LambdaFactory.build(BiFunction.class, constructor); + STRING_CREATOR_JDK8 = LambdaFactory.build(BiFunction.class, constructor); } /** @@ -33,6 +34,6 @@ public class FunctionPool { * @return String */ public static String createString(final char[] value) { - return STRING_CREATOR.apply(value, true); + return STRING_CREATOR_JDK8.apply(value, true); } } diff --git a/hutool-core/src/main/java/cn/hutool/core/reflect/LookupFactory.java b/hutool-core/src/main/java/cn/hutool/core/reflect/LookupFactory.java index 5c284e18b..7afe7e6c9 100644 --- a/hutool-core/src/main/java/cn/hutool/core/reflect/LookupFactory.java +++ b/hutool-core/src/main/java/cn/hutool/core/reflect/LookupFactory.java @@ -1,6 +1,7 @@ package cn.hutool.core.reflect; import cn.hutool.core.exceptions.UtilException; +import cn.hutool.core.util.JdkUtil; import java.lang.invoke.MethodHandles; import java.lang.reflect.Constructor; @@ -24,30 +25,16 @@ public class LookupFactory { private static final int ALLOWED_MODES = MethodHandles.Lookup.PRIVATE | MethodHandles.Lookup.PROTECTED | MethodHandles.Lookup.PACKAGE | MethodHandles.Lookup.PUBLIC; - private static Constructor java8LookupConstructor; private static Method privateLookupInMethod; + private static Constructor jdk8LookupConstructor; static { - //先查询jdk9 开始提供的java.lang.invoke.MethodHandles.privateLookupIn方法, - //如果没有说明是jdk8的版本.(不考虑jdk8以下版本) - try { - //noinspection JavaReflectionMemberAccess - privateLookupInMethod = MethodHandles.class.getMethod("privateLookupIn", Class.class, MethodHandles.Lookup.class); - } catch (final NoSuchMethodException ignore) { - //ignore - } - - //jdk8 - //这种方式其实也适用于jdk9及以上的版本,但是上面优先,可以避免 jdk9 反射警告 - if (privateLookupInMethod == null) { - try { - java8LookupConstructor = MethodHandles.Lookup.class.getDeclaredConstructor(Class.class, int.class); - java8LookupConstructor.setAccessible(true); - } catch (final NoSuchMethodException e) { - //可能是jdk8 以下版本 - throw new IllegalStateException( - "There is neither 'privateLookupIn(Class, Lookup)' nor 'Lookup(Class, int)' method in java.lang.invoke.MethodHandles.", e); - } + if(JdkUtil.isJdk8()){ + // jdk8 这种方式其实也适用于jdk9及以上的版本,但是上面优先,可以避免 jdk9 反射警告 + jdk8LookupConstructor = createJdk8LookupConstructor(); + } else { + // jdk9+ 开始提供的java.lang.invoke.MethodHandles.privateLookupIn方法 + privateLookupInMethod = createJdk9PrivateLookupInMethod(); } } @@ -69,9 +56,33 @@ public class LookupFactory { } //jdk 8 try { - return java8LookupConstructor.newInstance(callerClass, ALLOWED_MODES); + return jdk8LookupConstructor.newInstance(callerClass, ALLOWED_MODES); } catch (final Exception e) { throw new IllegalStateException("no 'Lookup(Class, int)' method in java.lang.invoke.MethodHandles.", e); } } + + @SuppressWarnings("JavaReflectionMemberAccess") + private static Method createJdk9PrivateLookupInMethod(){ + try { + return MethodHandles.class.getMethod("privateLookupIn", Class.class, MethodHandles.Lookup.class); + } catch (final NoSuchMethodException e) { + //可能是jdk9 以下版本 + throw new IllegalStateException( + "There is no 'privateLookupIn(Class, Lookup)' method in java.lang.invoke.MethodHandles.", e); + } + } + + private static Constructor createJdk8LookupConstructor(){ + final Constructor constructor; + try { + constructor = MethodHandles.Lookup.class.getDeclaredConstructor(Class.class, int.class); + } catch (final NoSuchMethodException e) { + //可能是jdk8 以下版本 + throw new IllegalStateException( + "There is no 'Lookup(Class, int)' constructor in java.lang.invoke.MethodHandles.", e); + } + constructor.setAccessible(true); + return constructor; + } } diff --git a/hutool-core/src/main/java/cn/hutool/core/reflect/MethodHandleUtil.java b/hutool-core/src/main/java/cn/hutool/core/reflect/MethodHandleUtil.java index 6e7531bec..a0bad42b4 100644 --- a/hutool-core/src/main/java/cn/hutool/core/reflect/MethodHandleUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/reflect/MethodHandleUtil.java @@ -22,17 +22,6 @@ import java.lang.reflect.Method; */ public class MethodHandleUtil { - /** - * jdk8中如果直接调用{@link MethodHandles#lookup()}获取到的{@link MethodHandles.Lookup}在调用findSpecial和unreflectSpecial - * 时会出现权限不够问题,抛出"no private access for invokespecial"异常,因此针对JDK8及JDK9+分别封装lookup方法。 - * - * @param callerClass 被调用的类或接口 - * @return {@link MethodHandles.Lookup} - */ - public static MethodHandles.Lookup lookup(final Class callerClass) { - return LookupFactory.lookup(callerClass); - } - /** * 查找指定方法的方法句柄
* 此方法只会查找: @@ -53,7 +42,7 @@ public class MethodHandleUtil { } MethodHandle handle = null; - final MethodHandles.Lookup lookup = lookup(callerClass); + final MethodHandles.Lookup lookup = LookupFactory.lookup(callerClass); try { handle = lookup.findVirtual(callerClass, name, type); } catch (final IllegalAccessException | NoSuchMethodException ignore) { @@ -102,7 +91,7 @@ public class MethodHandleUtil { * @return 构造方法句柄 */ public static MethodHandle findConstructor(final Class callerClass, final MethodType type) { - final MethodHandles.Lookup lookup = lookup(callerClass); + final MethodHandles.Lookup lookup = LookupFactory.lookup(callerClass); try { return lookup.findConstructor(callerClass, type); } catch (final NoSuchMethodException e) { @@ -208,7 +197,7 @@ public class MethodHandleUtil { public static T invoke(final boolean isSpecial, final Object obj, final Method method, final Object... args) { Assert.notNull(method, "Method must be not null!"); final Class declaringClass = method.getDeclaringClass(); - final MethodHandles.Lookup lookup = lookup(declaringClass); + final MethodHandles.Lookup lookup = LookupFactory.lookup(declaringClass); try { MethodHandle handle = isSpecial ? lookup.unreflectSpecial(method, declaringClass) : lookup.unreflect(method); diff --git a/hutool-core/src/main/java/cn/hutool/core/util/JdkUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/JdkUtil.java new file mode 100755 index 000000000..51295aa8f --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/util/JdkUtil.java @@ -0,0 +1,50 @@ +package cn.hutool.core.util; + +import cn.hutool.core.text.StrUtil; + +/** + * JDK相关工具类,包括判断JDK版本等
+ * 工具部分方法来自fastjson2的JDKUtils + * + * @author fastjson, looly + */ +public class JdkUtil { + /** + * JDK版本 + */ + public static final int JVM_VERSION; + + static { + JVM_VERSION = _getJvmVersion(); + } + + /** + * 是否JDK8 + * + * @return 是否JDK8 + */ + public static boolean isJdk8() { + return 8 == JVM_VERSION; + } + + /** + * 根据{@code java.specification.version}属性值,获取版本号 + * + * @return 版本号 + */ + private static int _getJvmVersion() { + int jvmVersion = -1; + + String javaSpecVer = System.getProperty("java.specification.version"); + if (StrUtil.isNotBlank(javaSpecVer)) { + if (javaSpecVer.startsWith("1.")) { + javaSpecVer = javaSpecVer.substring(2); + } + if (javaSpecVer.indexOf('.') == -1) { + jvmVersion = Integer.parseInt(javaSpecVer); + } + } + + return jvmVersion; + } +} diff --git a/hutool-core/src/test/java/cn/hutool/core/util/JdkUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/JdkUtilTest.java new file mode 100755 index 000000000..f120c39d6 --- /dev/null +++ b/hutool-core/src/test/java/cn/hutool/core/util/JdkUtilTest.java @@ -0,0 +1,12 @@ +package cn.hutool.core.util; + +import org.junit.Assert; +import org.junit.Test; + +public class JdkUtilTest { + @Test + public void jvmVersionTest() { + final int jvmVersion = JdkUtil.JVM_VERSION; + Assert.assertTrue(jvmVersion >= 8); + } +} diff --git a/hutool-json/pom.xml b/hutool-json/pom.xml index 5bcec276f..bf9f00ae7 100755 --- a/hutool-json/pom.xml +++ b/hutool-json/pom.xml @@ -44,7 +44,7 @@ com.alibaba.fastjson2 fastjson2 - 2.0.24 + 2.0.25 test