Skip to content

Commit 2e3e9ae

Browse files
committed
ModuleAccess.getEVERYONE_MODULE & getALL_UNNAMED_MODULE
1 parent b09501d commit 2e3e9ae

File tree

12 files changed

+335
-15
lines changed

12 files changed

+335
-15
lines changed

api/src/main/java/io/github/karlatemp/unsafeaccessor/ModuleAccess.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,24 @@
1313
public interface ModuleAccess {
1414
boolean isSupport();
1515

16+
/**
17+
* special Module to mean "everyone"
18+
* <p>
19+
* Only used for {@link #addExports(Object, String, Object)}, {@link #addOpens(Object, String, Object)}
20+
*
21+
* @since 1.6.0
22+
*/
23+
Object getEVERYONE_MODULE();
24+
25+
/**
26+
* special Module to mean "all unnamed modules"
27+
* <p>
28+
* Only used for {@link #addExports(Object, String, Object)}, {@link #addOpens(Object, String, Object)}
29+
*
30+
* @since 1.6.0
31+
*/
32+
Object getALL_UNNAMED_MODULE();
33+
1634
/**
1735
* klass.getModule()
1836
*/

api/src/main/java/io/github/karlatemp/unsafeaccessor/ModuleAccessImpl.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,16 @@ public Object getModule(Class<?> klass) {
1616
throw new UnsupportedOperationException();
1717
}
1818

19+
@Override
20+
public Object getEVERYONE_MODULE() {
21+
throw new UnsupportedOperationException();
22+
}
23+
24+
@Override
25+
public Object getALL_UNNAMED_MODULE() {
26+
throw new UnsupportedOperationException();
27+
}
28+
1929
@Override
2030
public Package definePackage(ClassLoader cl, String name, Object module) {
2131
throw new UnsupportedOperationException();
@@ -83,6 +93,16 @@ public boolean isSupport() {
8393
return false;
8494
}
8595

96+
@Override
97+
public Object getEVERYONE_MODULE() {
98+
return null;
99+
}
100+
101+
@Override
102+
public Object getALL_UNNAMED_MODULE() {
103+
return null;
104+
}
105+
86106
@Override
87107
public Object getModule(Class<?> klass) {
88108
return null;

api/src/main/java/io/github/karlatemp/unsafeaccessor/Root.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import java.lang.invoke.MethodHandles;
77
import java.lang.reflect.AccessibleObject;
88
import java.lang.reflect.Field;
9+
import java.util.function.Consumer;
910

1011
/**
1112
* JVM Root Access.
@@ -177,4 +178,28 @@ public static ModuleAccess getModuleAccess() {
177178
getUnsafe();
178179
return Secret.MACCESS;
179180
}
181+
182+
static class ObjectInitializer {
183+
static Consumer<Object> initializer;
184+
185+
static Consumer<Object> initializer() {
186+
if (initializer != null) return initializer;
187+
synchronized (ObjectInitializer.class) {
188+
if (initializer != null) return initializer;
189+
initializer = UsfAccessor.allocateObjectInitializer();
190+
}
191+
return initializer;
192+
}
193+
}
194+
195+
/**
196+
* Do nothing
197+
*
198+
* @since 1.6.0
199+
*/
200+
public static void initializeObject(Object instance) {
201+
if (instance == null) return;
202+
Unsafe.getUnsafe0().ensureClassInitialized(instance.getClass());
203+
ObjectInitializer.initializer().accept(instance);
204+
}
180205
}
Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,37 @@
11
package io.github.karlatemp.unsafeaccessor;
22

3+
import java.util.function.Consumer;
4+
35
// internal
46
public class UsfAccessor {
7+
static abstract class UsfAccessorSpi {
8+
abstract Object allocateUnsafe();
9+
10+
abstract Consumer<Object> allocateObjectInitializer();
11+
}
12+
13+
static UsfAccessorSpi spi;
14+
15+
static UsfAccessorSpi spi() {
16+
if (spi != null) return spi;
17+
synchronized (UsfAccessorSpi.class) {
18+
if (spi != null) return spi;
19+
try {
20+
// in module :impl.loader
21+
Class<?> impl = Class.forName("io.github.karlatemp.unsafeaccessor.UsfAccessorImpl");
22+
return spi = impl.asSubclass(UsfAccessorSpi.class).getDeclaredConstructor().newInstance();
23+
} catch (Exception e) {
24+
throw new UnsupportedOperationException(e);
25+
}
26+
}
27+
}
528

629
// Internal service for load Unsafe.
730
protected static Object allocateUnsafe() {
8-
try {
9-
// in module :impl.loader
10-
Class<?> impl = Class.forName("io.github.karlatemp.unsafeaccessor.UsfAccessorImpl");
11-
return impl.getDeclaredMethod("allocateUnsafe").invoke(null);
12-
} catch (Exception e) {
13-
throw new UnsupportedOperationException(e);
14-
}
31+
return spi().allocateUnsafe();
32+
}
33+
34+
protected static Consumer<Object> allocateObjectInitializer() {
35+
return spi().allocateObjectInitializer();
1536
}
1637
}

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ description = "A bridge for access jdk.internal.misc.Unsafe"
77

88
allprojects {
99
group 'io.github.karlatemp'
10-
version '1.5.0'
10+
version '1.6.0'
1111
repositories {
1212
mavenCentral()
1313
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package io.github.karlatemp.unsafeaccessor.codegen;
2+
3+
import io.github.karlatemp.unsafeaccessor.CodeGenUtils;
4+
import org.objectweb.asm.MethodVisitor;
5+
import org.objectweb.asm.Opcodes;
6+
import org.objectweb.asm.tree.ClassNode;
7+
8+
import java.util.Base64;
9+
10+
public class GenObjectInitializer {
11+
public static void main(String[] args) throws Throwable {
12+
ClassNode newClass = new ClassNode();
13+
newClass.visit(
14+
Opcodes.V1_8,
15+
0,
16+
"io/github/karlatemp/unsafeaccessor/ObjectInitializerHolder",
17+
null,
18+
"java/lang/Object",
19+
null
20+
);
21+
CodeGenUtils.genCons(newClass);
22+
MethodVisitor code = newClass.visitMethod(Opcodes.ACC_STATIC, "code", "()[B", null, null);
23+
code.visitMethodInsn(Opcodes.INVOKESTATIC, "java/util/Base64", "getDecoder", "()Ljava/util/Base64$Decoder;", false);
24+
{
25+
ClassNode initializer = new ClassNode();
26+
initializer.visit(
27+
Opcodes.V1_8,
28+
0,
29+
"io/github/karlatemp/unsafeaccessor/ObjectInitializerImpl",
30+
null,
31+
"jdk/internal/reflect/MagicAccessorImpl",
32+
new String[]{"java/util/function/Consumer"}
33+
);
34+
CodeGenUtils.genCons(initializer);
35+
MethodVisitor accept = initializer.visitMethod(Opcodes.ACC_PUBLIC, "accept", "(Ljava/lang/Object;)V", null, null);
36+
accept.visitVarInsn(Opcodes.ALOAD, 0);
37+
accept.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
38+
accept.visitInsn(Opcodes.RETURN);
39+
accept.visitMaxs(2, 2);
40+
byte[] bytecode = CodeGenUtils.toBytecode(initializer);
41+
code.visitLdcInsn(Base64.getEncoder().encodeToString(bytecode));
42+
}
43+
code.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/util/Base64$Decoder", "decode", "(Ljava/lang/String;)[B", false);
44+
code.visitInsn(Opcodes.ARETURN);
45+
code.visitMaxs(3, 3);
46+
47+
CodeGenUtils.save(newClass);
48+
}
49+
}

impl/jdk9/src/main/java/io/github/karlatemp/unsafeaccessor/ModuleAccessImpl$JDK9.java

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,28 @@
99
import java.util.Iterator;
1010
import java.util.Set;
1111
import java.util.function.Consumer;
12+
import java.util.function.Supplier;
1213

13-
@SuppressWarnings("unchecked")
14+
@SuppressWarnings({"unchecked", "rawtypes"})
1415
class ModuleAccessImpl$JDK9 implements ModuleAccess {
16+
private static Object EVERYONE_MODULE;
17+
private static Object ALL_UNNAMED_MODULE;
18+
private static final Supplier<UnsafeAccess> SUPPLIER;
19+
20+
private static Object findModule(String name) {
21+
try {
22+
return (Module) SUPPLIER.get().getTrustedIn(Module.class)
23+
.findStaticGetter(Module.class, name, Module.class)
24+
.invoke();
25+
} catch (Throwable throwable) {
26+
return throwable;
27+
}
28+
}
29+
1530
static {
16-
((Consumer<Object>) ModuleAccessImpl$JDK9.class.getClassLoader())
17-
.accept(new ModuleAccessImpl$JDK9());
31+
ClassLoader classLoader = ModuleAccessImpl$JDK9.class.getClassLoader();
32+
SUPPLIER = (Supplier<UnsafeAccess>) ((Supplier) classLoader).get();
33+
((Consumer<Object>) classLoader).accept(new ModuleAccessImpl$JDK9());
1834
}
1935

2036
@Override
@@ -30,6 +46,26 @@ public Object getModule(Class<?> klass) {
3046
return klass.getModule();
3147
}
3248

49+
@Override
50+
public Object getALL_UNNAMED_MODULE() {
51+
if (ALL_UNNAMED_MODULE == null) {
52+
ALL_UNNAMED_MODULE = findModule("ALL_UNNAMED_MODULE");
53+
}
54+
if (ALL_UNNAMED_MODULE instanceof Throwable)
55+
throw new UnsupportedOperationException((Throwable) ALL_UNNAMED_MODULE);
56+
return ALL_UNNAMED_MODULE;
57+
}
58+
59+
@Override
60+
public Object getEVERYONE_MODULE() {
61+
if (EVERYONE_MODULE == null) {
62+
EVERYONE_MODULE = findModule("EVERYONE_MODULE");
63+
}
64+
if (EVERYONE_MODULE instanceof Throwable)
65+
throw new UnsupportedOperationException((Throwable) EVERYONE_MODULE);
66+
return EVERYONE_MODULE;
67+
}
68+
3369
@Override
3470
public Object newModuleBuilder(
3571
String mn,

impl/jdk9/src/main/java/io/github/karlatemp/unsafeaccessor/Open9.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ JLA, findSS(), findJLMA()
138138
data = replace(data, "Lio/github/karlatemp/unsafeaccessor/ModuleAccessImpl$JDK9;", "L" + targetJvmName + ";");
139139

140140
data = doRemap(data, ACCESS_CLASSES);
141+
env = (Supplier) () -> UnsafeAccess.INSTANCE;
141142

142143
Class.forName(loader.define(data).getName(), true, loader);
143144
Root.Secret.MACCESS = (ModuleAccess) env;

impl/loader/src/main/java/io/github/karlatemp/unsafeaccessor/UsfAccessorImpl.java

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
package io.github.karlatemp.unsafeaccessor;
22

3-
class UsfAccessorImpl {
4-
static Object allocateUnsafe() throws Exception {
3+
import java.lang.reflect.Constructor;
4+
import java.util.ArrayList;
5+
import java.util.List;
6+
import java.util.function.Consumer;
7+
8+
@SuppressWarnings("unchecked")
9+
class UsfAccessorImpl extends UsfAccessor.UsfAccessorSpi {
10+
Object allocateUnsafe() {
511
try {
612
Class.forName("java.lang.Module");
713
Root.Secret.MACCESS = new ModuleAccessImpl.PendingInit();
@@ -16,4 +22,50 @@ static Object allocateUnsafe() throws Exception {
1622
return new SunMiscUnsafeImpl();
1723
}
1824
}
25+
26+
static Class<?> findC(ClassLoader cl, String... names) {
27+
List<Throwable> throwables = new ArrayList<>();
28+
for (String n : names) {
29+
try {
30+
return Class.forName(n, false, cl);
31+
} catch (ClassNotFoundException e) {
32+
throwables.add(e);
33+
}
34+
}
35+
NoClassDefFoundError error = new NoClassDefFoundError();
36+
for (Throwable t : throwables) error.addSuppressed(t);
37+
throw error;
38+
}
39+
40+
@Override
41+
Consumer<Object> allocateObjectInitializer() {
42+
byte[] code = ObjectInitializerHolder.code();
43+
Class<?> MagicAccessorImpl = findC(
44+
null,
45+
"jdk.internal.reflect.MagicAccessorImpl",
46+
"sun.reflect.MagicAccessorImpl"
47+
);
48+
Class<? extends ClassLoader> DelegatingClassLoader = findC(
49+
null,
50+
"jdk.internal.reflect.DelegatingClassLoader",
51+
"sun.reflect.DelegatingClassLoader"
52+
).asSubclass(ClassLoader.class);
53+
if (!MagicAccessorImpl.getName().equals("jdk.internal.reflect.MagicAccessorImpl")) {
54+
code = BytecodeUtil.replace(code,
55+
"jdk/internal/reflect/MagicAccessorImpl",
56+
MagicAccessorImpl.getName().replace('.', '/')
57+
);
58+
}
59+
try {
60+
Constructor<? extends ClassLoader> constructor = DelegatingClassLoader.getDeclaredConstructor(ClassLoader.class);
61+
Root.OpenAccess.openAccess0(constructor, true);
62+
ClassLoader delegate = constructor.newInstance(ClassLoader.getSystemClassLoader());
63+
Class<?> klass = Unsafe.getUnsafe0().defineClass(null, code, 0, code.length, delegate, null);
64+
Constructor<?> constructor1 = klass.getDeclaredConstructor();
65+
Root.OpenAccess.openAccess0(constructor1, true);
66+
return (Consumer<Object>) constructor1.newInstance();
67+
} catch (Exception e) {
68+
throw new UnsupportedOperationException(e);
69+
}
70+
}
1971
}

0 commit comments

Comments
 (0)