diff --git a/api/src/main/java/io/github/karlatemp/unsafeaccessor/Unsafe.java b/api/src/main/java/io/github/karlatemp/unsafeaccessor/Unsafe.java index 90f0566..ce6092e 100644 --- a/api/src/main/java/io/github/karlatemp/unsafeaccessor/Unsafe.java +++ b/api/src/main/java/io/github/karlatemp/unsafeaccessor/Unsafe.java @@ -52,7 +52,8 @@ */ @SuppressWarnings({"unused", "BooleanMethodIsAlwaysInverted", "RedundantSuppression", "Since15", "DefaultAnnotationParam", "JavaDoc"}) public abstract class Unsafe { - private static Unsafe theUnsafe; + static Unsafe theUnsafe; + static final Unsafe INSTANCE = getUnsafe0(); /** * is Java9+ @@ -92,12 +93,12 @@ public boolean isJava9() { @Contract(pure = false) public static Unsafe getUnsafe() { SecurityCheck.LIMITER.preGetUnsafe(); - return getUnsafe0(); + return INSTANCE; } static Unsafe getUnsafe0() { if (theUnsafe == null) { - return theUnsafe = (Unsafe) UsfAccessor.allocateUnsafe(); + UsfAccessor.initialize(); } return theUnsafe; } diff --git a/api/src/main/java/io/github/karlatemp/unsafeaccessor/UsfAccessor.java b/api/src/main/java/io/github/karlatemp/unsafeaccessor/UsfAccessor.java index 7ab4667..ecec1f9 100644 --- a/api/src/main/java/io/github/karlatemp/unsafeaccessor/UsfAccessor.java +++ b/api/src/main/java/io/github/karlatemp/unsafeaccessor/UsfAccessor.java @@ -5,7 +5,7 @@ // internal public class UsfAccessor { static abstract class UsfAccessorSpi { - abstract Object allocateUnsafe(); + abstract void initialize(); abstract Consumer allocateObjectInitializer(); } @@ -27,8 +27,8 @@ static UsfAccessorSpi spi() { } // Internal service for load Unsafe. - protected static Object allocateUnsafe() { - return spi().allocateUnsafe(); + protected static void initialize() { + spi().initialize(); } protected static Consumer allocateObjectInitializer() { diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 1c728b8..f08e1fa 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,12 +1,4 @@ -# -# Copyright 2019-2021 Mamoe Technologies and contributors. -# -# 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. -# Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link. -# -# https://github.com/mamoe/mirai/blob/master/LICENSE -# -distributionUrl=https\://services.gradle.org/distributions/gradle-6.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.1-all.zip distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStorePath=wrapper/dists diff --git a/impl/codegen/build.gradle b/impl/codegen/build.gradle index 96e669c..5c2d79b 100644 --- a/impl/codegen/build.gradle +++ b/impl/codegen/build.gradle @@ -6,16 +6,17 @@ dependencies { implementation(project(':api')) // https://mvnrepository.com/artifact/org.ow2.asm/asm - testCompile group: 'org.ow2.asm', name: 'asm', version: '9.1' - testCompile group: 'org.ow2.asm', name: 'asm-commons', version: '9.1' - testCompile group: 'org.ow2.asm', name: 'asm-util', version: '9.1' - testCompile group: 'org.ow2.asm', name: 'asm-tree', version: '9.1' + testImplementation group: 'org.ow2.asm', name: 'asm', version: '9.2' + testImplementation group: 'org.ow2.asm', name: 'asm-commons', version: '9.2' + testImplementation group: 'org.ow2.asm', name: 'asm-util', version: '9.2' + testImplementation group: 'org.ow2.asm', name: 'asm-tree', version: '9.2' } task runCodeGen(type: JavaExec) { dependsOn(':impl.jdk8:classes') dependsOn(':impl.jdk9:classes') + dependsOn(':impl.jdk17:classes') classpath = sourceSets.test.runtimeClasspath main = 'io.github.karlatemp.unsafeaccessor.RunCodeGen' diff --git a/impl/jdk17/build.gradle b/impl/jdk17/build.gradle new file mode 100644 index 0000000..96a1e7b --- /dev/null +++ b/impl/jdk17/build.gradle @@ -0,0 +1,21 @@ +plugins { + id 'java' + id 'java-library' +} + +println("JDK 17") + +ext.set('versionOverrided', true) + +compileJava { + sourceCompatibility = JavaVersion.VERSION_16 + targetCompatibility = JavaVersion.VERSION_16 + options.compilerArgs.addAll([ + '--add-exports', 'java.base/jdk.internal.misc=ALL-UNNAMED', + '--add-exports', 'java.base/jdk.internal.access=ALL-UNNAMED' + ]) +} + +dependencies { + api(project(':impl.jdk9')) +} diff --git a/impl/jdk17/src/main/java/io/github/karlatemp/unsafeaccessor/UsfAllocImpl17.java b/impl/jdk17/src/main/java/io/github/karlatemp/unsafeaccessor/UsfAllocImpl17.java new file mode 100644 index 0000000..6063432 --- /dev/null +++ b/impl/jdk17/src/main/java/io/github/karlatemp/unsafeaccessor/UsfAllocImpl17.java @@ -0,0 +1,19 @@ +package io.github.karlatemp.unsafeaccessor; + +class UsfAllocImpl17 extends UsfAllocImpl9 { + @SuppressWarnings("JavaReflectionMemberAccess") + @Override + UsfAlloc checkSelectedRequirement() throws Exception { + try { + Class.forName("jdk.internal.misc.Unsafe").getMethod( + "defineAnonymousClass", + Class.class, + byte[].class, + Object[].class + ); + } catch (NoSuchMethodException ignore) { + return this; + } + return null; + } +} diff --git a/impl/jdk17/src/main/java/io/github/karlatemp/unsafeaccessor/UsfImpl17.java b/impl/jdk17/src/main/java/io/github/karlatemp/unsafeaccessor/UsfImpl17.java new file mode 100644 index 0000000..ada6b3b --- /dev/null +++ b/impl/jdk17/src/main/java/io/github/karlatemp/unsafeaccessor/UsfImpl17.java @@ -0,0 +1,18 @@ +package io.github.karlatemp.unsafeaccessor; + +import java.lang.invoke.MethodHandles; + +class UsfImpl17 extends Impl9 { + @Override + public Class defineAnonymousClass(Class hostClass, byte[] data, Object[] cpPatches) { + try { + MethodHandles.Lookup lookup = Root.RootLookupHolder.trustedIn(hostClass).in(hostClass); + if (cpPatches == null) { + return lookup.defineHiddenClass(data, false).lookupClass(); + } + return lookup.defineHiddenClassWithClassData(data, cpPatches, false).lookupClass(); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } +} diff --git a/impl/jdk8/build.gradle b/impl/jdk8/build.gradle index 97cac3e..6a55150 100644 --- a/impl/jdk8/build.gradle +++ b/impl/jdk8/build.gradle @@ -1,7 +1,8 @@ plugins { id 'java' + id 'java-library' } dependencies { - implementation(project(':api')) + api(project(':api')) } diff --git a/api/src/main/java/io/github/karlatemp/unsafeaccessor/ModuleAccessImpl.java b/impl/jdk8/src/main/java/io/github/karlatemp/unsafeaccessor/ModuleAccessImpl.java similarity index 100% rename from api/src/main/java/io/github/karlatemp/unsafeaccessor/ModuleAccessImpl.java rename to impl/jdk8/src/main/java/io/github/karlatemp/unsafeaccessor/ModuleAccessImpl.java diff --git a/impl/jdk8/src/main/java/io/github/karlatemp/unsafeaccessor/UsfAlloc.java b/impl/jdk8/src/main/java/io/github/karlatemp/unsafeaccessor/UsfAlloc.java new file mode 100644 index 0000000..911fc00 --- /dev/null +++ b/impl/jdk8/src/main/java/io/github/karlatemp/unsafeaccessor/UsfAlloc.java @@ -0,0 +1,25 @@ +package io.github.karlatemp.unsafeaccessor; + +abstract class UsfAlloc { + + Unsafe newUnsafe(UsfAllocCtx ctx) throws Exception { + return ctx.newUsfImpl(this); + } + + void prepare(UsfAllocCtx ctx) throws Exception { + } + + void destroyLimit(UsfAllocCtx ctx) throws Exception { + } + + void completed(UsfAllocCtx ctx) throws Exception { + } + + ModuleAccess newModuleAccess(UsfAllocCtx ctx) throws Exception { + return new ModuleAccessImpl.Noop(); + } + + UsfAlloc checkSelectedRequirement() throws Exception { + return this; + } +} diff --git a/impl/jdk8/src/main/java/io/github/karlatemp/unsafeaccessor/UsfAllocCtx.java b/impl/jdk8/src/main/java/io/github/karlatemp/unsafeaccessor/UsfAllocCtx.java new file mode 100644 index 0000000..65df81e --- /dev/null +++ b/impl/jdk8/src/main/java/io/github/karlatemp/unsafeaccessor/UsfAllocCtx.java @@ -0,0 +1,56 @@ +package io.github.karlatemp.unsafeaccessor; + +import java.util.function.Consumer; +import java.util.function.Supplier; + +class UsfAllocCtx { + private DynClassLoader loader; + + void putUnsafeInstance(Unsafe usf) { + Unsafe.theUnsafe = usf; + } + + void putModuleAccess(ModuleAccess ma) { + Root.Secret.MACCESS = ma; + } + + DynClassLoader loader() { + if (loader == null) + return loader = new DynClassLoader(); + return loader; + } + + @SuppressWarnings("rawtypes") + static class DynClassLoader extends ClassLoader implements Supplier, Consumer { + Object env; + + DynClassLoader() { + super(DynClassLoader.class.getClassLoader()); + } + + @Override + public Object get() { + return env; + } + + @Override + public void accept(Object o) { + env = o; + } + + Class define(byte[] code) { + return defineClass(null, code, 0, code.length, null); + } + + Class defineAndLoad(byte[] data) throws ClassNotFoundException { + return Class.forName(define(data).getName(), true, this); + } + } + + String namespace; + Class[] ACCESS_C; + + Unsafe newUsfImpl(UsfAlloc thiz) throws Exception { + throw new UnsupportedOperationException(); + } +} diff --git a/impl/jdk8/src/main/java/io/github/karlatemp/unsafeaccessor/UsfAllocImpl8.java b/impl/jdk8/src/main/java/io/github/karlatemp/unsafeaccessor/UsfAllocImpl8.java new file mode 100644 index 0000000..479aa07 --- /dev/null +++ b/impl/jdk8/src/main/java/io/github/karlatemp/unsafeaccessor/UsfAllocImpl8.java @@ -0,0 +1,4 @@ +package io.github.karlatemp.unsafeaccessor; + +class UsfAllocImpl8 extends UsfAlloc { +} diff --git a/impl/jdk9/build.gradle b/impl/jdk9/build.gradle index 5e49ca4..556ec12 100644 --- a/impl/jdk9/build.gradle +++ b/impl/jdk9/build.gradle @@ -1,5 +1,6 @@ plugins { id 'java' + id 'java-library' } println("JDK 9") @@ -16,5 +17,5 @@ compileJava { } dependencies { - implementation(project(':api')) + api(project(':impl.jdk8')) } diff --git a/impl/jdk9/src/main/java/io/github/karlatemp/unsafeaccessor/ModuleAccessImpl$JDK9.java b/impl/jdk9/src/main/java/io/github/karlatemp/unsafeaccessor/ModuleAccessImpl$JDK9.java index c4c13f2..e6fa107 100644 --- a/impl/jdk9/src/main/java/io/github/karlatemp/unsafeaccessor/ModuleAccessImpl$JDK9.java +++ b/impl/jdk9/src/main/java/io/github/karlatemp/unsafeaccessor/ModuleAccessImpl$JDK9.java @@ -124,7 +124,9 @@ public void addOpensToAllUnnamed(Object m, String pkg) { @Override public void addOpensToAllUnnamed(Object m, Iterator packages) { - JLA.addOpensToAllUnnamed((Module) m, packages); + while (packages.hasNext()) { + JLA.addOpensToAllUnnamed((Module) m, packages.next()); + } } @Override diff --git a/impl/jdk9/src/main/java/io/github/karlatemp/unsafeaccessor/Open9.java b/impl/jdk9/src/main/java/io/github/karlatemp/unsafeaccessor/Open9.java deleted file mode 100644 index 7222977..0000000 --- a/impl/jdk9/src/main/java/io/github/karlatemp/unsafeaccessor/Open9.java +++ /dev/null @@ -1,154 +0,0 @@ -package io.github.karlatemp.unsafeaccessor; - -import jdk.internal.access.JavaLangAccess; -import jdk.internal.access.SharedSecrets; - -import java.io.InputStream; -import java.lang.reflect.Proxy; -import java.security.AllPermission; -import java.security.ProtectionDomain; -import java.util.function.Consumer; -import java.util.function.Supplier; - -import static io.github.karlatemp.unsafeaccessor.BytecodeUtil.replace; - -class Open9 extends ClassLoader implements Supplier, Consumer { - private static Object env = null; - - @Override - public void accept(Object o) { - env = o; - } - - @Override - public Object get() { - return env; - } - - private Open9() { - super(Open9.class.getClassLoader()); - } - - static class Injector { - static { - Class klass = Injector.class; - Module module = klass.getModule(); - Module open = klass.getClassLoader().getClass().getModule(); - module.addExports(klass.getPackageName(), open); - module.addOpens(klass.getPackageName(), open); - JavaLangAccess javaLangAccess = SharedSecrets.getJavaLangAccess(); - javaLangAccess.addExports(Object.class.getModule(), "jdk.internal.misc", open); - javaLangAccess.addExports(open, "io.github.karlatemp.unsafeaccessor", module); - javaLangAccess.addReads(module, open); - } - } - - Class define(byte[] code) { - ProtectionDomain domain = new ProtectionDomain(null, - new AllPermission().newPermissionCollection() - ); - return defineClass(null, code, 0, code.length, domain); - } - - static Class findSS() throws ClassNotFoundException { - String[] classpath = { - "jdk.internal.access.SharedSecrets", - "jdk.internal.misc.SharedSecrets", - }; - return findClass(classpath); - } - - static Class findClass(String[] classpath) throws ClassNotFoundException { - ClassNotFoundException cnfe = null; - ClassLoader loader = ClassLoader.getSystemClassLoader(); - for (String s : classpath) { - try { - return Class.forName(s, true, loader); - } catch (ClassNotFoundException ce) { - if (cnfe == null) cnfe = ce; - else cnfe.addSuppressed(ce); - } - } - assert cnfe != null; - throw cnfe; - } - - static Class findJLA() throws ClassNotFoundException { - String[] classpath = { - "jdk.internal.access.JavaLangAccess", - "jdk.internal.misc.JavaLangAccess", - }; - return findClass(classpath); - } - - static Class findJLMA() throws ClassNotFoundException { - String[] classpath = { - "jdk.internal.access.JavaLangModuleAccess", - "jdk.internal.misc.JavaLangModuleAccess", - }; - return findClass(classpath); - } - - static byte[] doRemap( - byte[] data, - Class... accessClasses - ) { - - for (Class c : accessClasses) { - data = replace(data, "jdk/internal/access/" + c.getSimpleName(), c.getName().replace('.', '/')); - data = replace(data, "Ljdk/internal/access/" + c.getSimpleName() + ";", "L" + c.getName().replace('.', '/') + ";"); - data = replace(data, "()Ljdk/internal/access/" + c.getSimpleName() + ";", "()L" + c.getName().replace('.', '/') + ";"); - } - return data; - } - - - @SuppressWarnings("UnnecessarySemicolon") - static Unsafe open() throws NoSuchMethodException { - Open9 loader = new Open9(); - try (InputStream source = Open9.class.getResourceAsStream("Open9$Injector.class"); - InputStream mai9 = Open9.class.getResourceAsStream("ModuleAccessImpl$JDK9.class"); - ) { - byte[] data; - Class JLA = findJLA(); - Class[] ACCESS_CLASSES = { - JLA, findSS(), findJLMA() - }; - - Object proxy = Proxy.newProxyInstance(loader, new Class[]{JLA}, (proxy0, method, args) -> null); - String namespace = proxy.getClass().getPackageName(); - { - data = source.readAllBytes(); - String targetName = namespace + ".Injector", - targetJvmName = targetName.replace('.', '/'); - data = replace(data, "io/github/karlatemp/unsafeaccessor/Open9$Injector", targetJvmName); - data = replace(data, "Lio/github/karlatemp/unsafeaccessor/Open9$Injector;", "L" + targetJvmName + ";"); - - data = doRemap(data, ACCESS_CLASSES); - - Class injectorClass = loader.define(data); - Class.forName(injectorClass.getName(), true, loader); - } - { - String targetName = namespace + ".ModuleAccessImpl$JDK9", - targetJvmName = targetName.replace('.', '/'); - - data = mai9.readAllBytes(); - data = replace(data, "io/github/karlatemp/unsafeaccessor/ModuleAccessImpl$JDK9", targetJvmName); - data = replace(data, "Lio/github/karlatemp/unsafeaccessor/ModuleAccessImpl$JDK9;", "L" + targetJvmName + ";"); - - data = doRemap(data, ACCESS_CLASSES); - env = (Supplier) () -> UnsafeAccess.INSTANCE; - - Class.forName(loader.define(data).getName(), true, loader); - Root.Secret.MACCESS = (ModuleAccess) env; - env = null; - } - } catch (Exception exception) { - throw new ExceptionInInitializerError(exception); - } - //noinspection ResultOfMethodCallIgnored - jdk.internal.misc.Unsafe.class.getDeclaredMethod("getReference", Object.class, long.class); - return new Impl9(); - } -} diff --git a/impl/jdk9/src/main/java/io/github/karlatemp/unsafeaccessor/UsfAllocImpl9.java b/impl/jdk9/src/main/java/io/github/karlatemp/unsafeaccessor/UsfAllocImpl9.java new file mode 100644 index 0000000..ace4b97 --- /dev/null +++ b/impl/jdk9/src/main/java/io/github/karlatemp/unsafeaccessor/UsfAllocImpl9.java @@ -0,0 +1,131 @@ +package io.github.karlatemp.unsafeaccessor; + +import jdk.internal.access.JavaLangAccess; +import jdk.internal.access.SharedSecrets; + +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Proxy; +import java.util.function.Supplier; + +import static io.github.karlatemp.unsafeaccessor.BytecodeUtil.replace; + +class UsfAllocImpl9 extends UsfAlloc { + Class usfClass() { + return jdk.internal.misc.Unsafe.class; + } + + static class Injector { + static { + Class klass = Injector.class; + Module module = klass.getModule(); + Module open = klass.getClassLoader().getClass().getModule(); + module.addExports(klass.getPackageName(), open); + module.addOpens(klass.getPackageName(), open); + JavaLangAccess javaLangAccess = SharedSecrets.getJavaLangAccess(); + javaLangAccess.addExports(Object.class.getModule(), "jdk.internal.misc", open); + javaLangAccess.addExports(open, "io.github.karlatemp.unsafeaccessor", module); + javaLangAccess.addReads(module, open); + } + } + + static byte[] doRemap( + byte[] data, + Class... accessClasses + ) { + for (Class c : accessClasses) { + data = replace(data, "jdk/internal/access/" + c.getSimpleName(), c.getName().replace('.', '/')); + data = replace(data, "Ljdk/internal/access/" + c.getSimpleName() + ";", "L" + c.getName().replace('.', '/') + ";"); + data = replace(data, "()Ljdk/internal/access/" + c.getSimpleName() + ";", "()L" + c.getName().replace('.', '/') + ";"); + } + return data; + } + + static byte[] inNamespace(byte[] data, String name, String namespace) { + String targetJvmName = namespace.replace('.', '/') + "/UsfI_" + name; + data = BytecodeUtil.replace(data, "io/github/karlatemp/unsafeaccessor/" + name, targetJvmName); + data = BytecodeUtil.replace(data, "Lio/github/karlatemp/unsafeaccessor/" + name + ";", "L" + targetJvmName + ";"); + return data; + } + + static Class findSS() throws ClassNotFoundException { + String[] classpath = { + "jdk.internal.access.SharedSecrets", + "jdk.internal.misc.SharedSecrets", + }; + return findClass(classpath); + } + + static Class findClass(String[] classpath) throws ClassNotFoundException { + ClassNotFoundException cnfe = null; + ClassLoader loader = ClassLoader.getSystemClassLoader(); + for (String s : classpath) { + try { + return Class.forName(s, true, loader); + } catch (ClassNotFoundException ce) { + if (cnfe == null) cnfe = ce; + else cnfe.addSuppressed(ce); + } + } + assert cnfe != null; + throw cnfe; + } + + static Class findJLA() throws ClassNotFoundException { + String[] classpath = { + "jdk.internal.access.JavaLangAccess", + "jdk.internal.misc.JavaLangAccess", + }; + return findClass(classpath); + } + + static Class findJLMA() throws ClassNotFoundException { + String[] classpath = { + "jdk.internal.access.JavaLangModuleAccess", + "jdk.internal.misc.JavaLangModuleAccess", + }; + return findClass(classpath); + } + + static byte[] readC(String name) throws IOException { + try (InputStream is = UsfAllocImpl9.class.getResourceAsStream(name)) { + return is.readAllBytes(); + } + } + + @Override + void destroyLimit(UsfAllocCtx ctx) throws Exception { + Class[] ACCESS_CLASSES = { + findJLA(), findSS(), findJLMA() + }; + Object proxy = Proxy.newProxyInstance( + ctx.loader(), + new Class[]{ACCESS_CLASSES[0]}, + (proxy1, method, args) -> null + ); + String namespace = ctx.namespace = proxy.getClass().getPackageName(); + ctx.ACCESS_C = ACCESS_CLASSES; + + { // Injector + byte[] data = readC("UsfAllocImpl9$Injector.class"); + data = inNamespace(data, "UsfAllocImpl9$Injector", namespace); + data = doRemap(data, ACCESS_CLASSES); + ctx.loader().defineAndLoad(data); + } + } + + @Override + Unsafe newUnsafe(UsfAllocCtx ctx) throws Exception { + return ctx.newUsfImpl(this); + } + + @Override + ModuleAccess newModuleAccess(UsfAllocCtx ctx) throws Exception { + byte[] data = readC("ModuleAccessImpl$JDK9.class"); + data = inNamespace(data, "ModuleAccessImpl$JDK9", ctx.namespace); + data = doRemap(data, ctx.ACCESS_C); + ctx.loader().env = ((Supplier) () -> UnsafeAccess.INSTANCE); + ctx.loader().defineAndLoad(data); + return (ModuleAccess) ctx.loader().env; + } +} diff --git a/impl/loader/build.gradle b/impl/loader/build.gradle index cee76f0..f893228 100644 --- a/impl/loader/build.gradle +++ b/impl/loader/build.gradle @@ -17,21 +17,23 @@ task sourcesJar(type: Jar) { from(project(':api').sourceSets.main.allSource) from(project(':impl.jdk8').sourceSets.main.allSource) from(project(':impl.jdk9').sourceSets.main.allSource) + from(project(':impl.jdk17').sourceSets.main.allSource) from(project.sourceSets.main.allSource) } dependencies { implementation(project(':api')) - implementation(project(':impl.jdk8')) + implementation(files(new File(project(':impl.jdk8').buildDir, "classes/java/main"))) implementation(files(new File(project(':impl.jdk9').buildDir, "classes/java/main"))) + implementation(files(new File(project(':impl.jdk17').buildDir, "classes/java/main"))) implementation(files("generated")) // https://mvnrepository.com/artifact/org.ow2.asm/asm - testCompile group: 'org.ow2.asm', name: 'asm', version: '9.1' - testCompile group: 'org.ow2.asm', name: 'asm-commons', version: '9.1' - testCompile group: 'org.ow2.asm', name: 'asm-util', version: '9.1' - testCompile group: 'org.ow2.asm', name: 'asm-tree', version: '9.1' + testImplementation group: 'org.ow2.asm', name: 'asm', version: '9.2' + testImplementation group: 'org.ow2.asm', name: 'asm-commons', version: '9.2' + testImplementation group: 'org.ow2.asm', name: 'asm-util', version: '9.2' + testImplementation group: 'org.ow2.asm', name: 'asm-tree', version: '9.2' } diff --git a/impl/loader/src/main/java/io/github/karlatemp/unsafeaccessor/UsfAccessorImpl.java b/impl/loader/src/main/java/io/github/karlatemp/unsafeaccessor/UsfAccessorImpl.java index cbd7d64..1f0a367 100644 --- a/impl/loader/src/main/java/io/github/karlatemp/unsafeaccessor/UsfAccessorImpl.java +++ b/impl/loader/src/main/java/io/github/karlatemp/unsafeaccessor/UsfAccessorImpl.java @@ -7,19 +7,83 @@ @SuppressWarnings("unchecked") class UsfAccessorImpl extends UsfAccessor.UsfAccessorSpi { - Object allocateUnsafe() { - try { - Class.forName("java.lang.Module"); - Root.Secret.MACCESS = new ModuleAccessImpl.PendingInit(); + static class UsfACtxImpl extends UsfAllocCtx { + @Override + Unsafe newUsfImpl(UsfAlloc alloc) throws Exception { + return (Unsafe) newUsf(alloc); + } + + Object newUsf(UsfAlloc alloc) throws Exception { + if (alloc instanceof UsfAllocImpl8) { + return new SunMiscUnsafeImpl(); + } + return newUsf9(alloc); + } + + @SuppressWarnings("SwitchStatementWithTooFewBranches") + Object newUsf9(UsfAlloc $$$$$$$$$$$$$$$$) throws Exception { + UsfAllocImpl9 alloc = (UsfAllocImpl9) $$$$$$$$$$$$$$$$; + boolean isGetObj; try { - return Open9.open(); + alloc.usfClass().getMethod("getObject", Object.class, long.class); + isGetObj = true; } catch (NoSuchMethodException ignored) { - return new Impl9Obj(); + isGetObj = false; + } + + String cname = alloc.getClass().getSimpleName(); + String sname = null; + switch (cname) { + case "UsfAllocImpl17": + return new UsfImpl17(); + default: + return isGetObj ? new Impl9Obj() : new Impl9(); + } + } + + } + + static UsfAlloc findImpl9() { + ExceptionInInitializerError e = new ExceptionInInitializerError("no any provider found"); + for (String k : new String[]{ + "17", + "9", + "8", + }) { + try { + UsfAlloc alloc = Class.forName("io.github.karlatemp.unsafeaccessor.UsfAllocImpl" + k) + .asSubclass(UsfAlloc.class) + .getDeclaredConstructor() + .newInstance() + .checkSelectedRequirement(); + if (alloc != null) return alloc; + } catch (Throwable ex) { + e.addSuppressed(ex); } + } + throw e; + } + + void initialize() { + Root.Secret.MACCESS = new ModuleAccessImpl.PendingInit(); + UsfAlloc alloc; + try { + Class.forName("java.lang.Module"); + alloc = findImpl9(); } catch (ClassNotFoundException ignored) { - Root.Secret.MACCESS = new ModuleAccessImpl.Noop(); - return new SunMiscUnsafeImpl(); + alloc = new UsfAllocImpl8(); + } + try { + UsfAllocCtx ctx = new UsfACtxImpl(); + alloc.prepare(ctx); + alloc.destroyLimit(ctx); + + ctx.putUnsafeInstance(alloc.newUnsafe(ctx)); + + ctx.putModuleAccess(alloc.newModuleAccess(ctx)); + } catch (Throwable throwable) { + throw new ExceptionInInitializerError(throwable); } } diff --git a/impl/testunit/build.gradle b/impl/testunit/build.gradle index ab921e5..4ae26df 100644 --- a/impl/testunit/build.gradle +++ b/impl/testunit/build.gradle @@ -2,20 +2,21 @@ plugins { id 'java' id 'io.github.karlatemp.publication-sign' id("maven-publish") + id 'java-library' } dependencies { compileOnly(project(':api')) - compile group: 'org.ow2.asm', name: 'asm', version: '9.1' - compile group: 'org.ow2.asm', name: 'asm-commons', version: '9.1' - compile group: 'org.ow2.asm', name: 'asm-util', version: '9.1' - compile group: 'org.ow2.asm', name: 'asm-tree', version: '9.1' - compile 'com.google.code.gson:gson:2.8.8' - compile 'org.apache.commons:commons-lang3:3.12.0' - compile'org.apache.commons:commons-text:1.9' + api group: 'org.ow2.asm', name: 'asm', version: '9.2' + api group: 'org.ow2.asm', name: 'asm-commons', version: '9.2' + api group: 'org.ow2.asm', name: 'asm-util', version: '9.2' + api group: 'org.ow2.asm', name: 'asm-tree', version: '9.2' + api 'com.google.code.gson:gson:2.8.8' + api 'org.apache.commons:commons-lang3:3.12.0' + api 'org.apache.commons:commons-text:1.9' - compile 'org.junit.jupiter:junit-jupiter-api:5.6.0' + api 'org.junit.jupiter:junit-jupiter-api:5.6.0' } diff --git a/settings.gradle b/settings.gradle index 660b985..3d0390e 100644 --- a/settings.gradle +++ b/settings.gradle @@ -12,6 +12,7 @@ include(':api') importImpl('jdk8') importImpl('jdk9') +importImpl('jdk17') importImpl('codegen')