Skip to content

Commit

Permalink
Support for Java 22+ (#91)
Browse files Browse the repository at this point in the history
Fix #80

Problem indeed introduced in this change. Despite code comment MagicAccessorImpl is not prevent bytecode verification anymore.

Also added separate build configuration for jdk 23
  • Loading branch information
lehvolk authored Jan 16, 2025
1 parent 22c7927 commit a1ea385
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 9 deletions.
4 changes: 1 addition & 3 deletions .github/workflows/build-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,7 @@ jobs:
strategy:
fail-fast: false
matrix:
jdk: [8, 11, 17, 19, 21]
env:
main_jdk: 8
jdk: [8, 11, 17, 19, 21, 23]

steps:
- uses: actions/checkout@v3
Expand Down
10 changes: 4 additions & 6 deletions src/one/nio/serial/gen/DelegateGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import one.nio.serial.NotSerial;
import one.nio.serial.Repository;
import one.nio.serial.SerializeWith;
import one.nio.util.Hex;
import one.nio.util.JavaFeatures;
import one.nio.util.JavaInternals;
import one.nio.util.MethodHandlesReflection;
Expand Down Expand Up @@ -59,7 +58,7 @@ public class DelegateGenerator extends BytecodeGenerator {
private static final AtomicInteger index = new AtomicInteger();

// Allows to bypass security checks when accessing private members of other classes
private static final String MAGIC_CLASS = "sun/reflect/MagicAccessorImpl";
static final String MAGIC_CLASS = "sun/reflect/MagicAccessorImpl";

// In JDK 9+ there is no more sun.reflect.MagicAccessorImpl class.
// Instead there is package private jdk.internal.reflect.MagicAccessorImpl, which is not visible
Expand All @@ -76,18 +75,17 @@ public class DelegateGenerator extends BytecodeGenerator {
}

// public jdk.internal.reflect.MagicAccessorBridge extends jdk.internal.reflect.MagicAccessorImpl
defineBootstrapClass(m, "cafebabe00000033000a0a000300070700080700090100063c696e69743e010003282956010004436f64650c000400050100286a646b2f696e7465726e616c2f7265666c6563742f4d616769634163636573736f724272696467650100266a646b2f696e7465726e616c2f7265666c6563742f4d616769634163636573736f72496d706c042100020003000000000001000100040005000100060000001100010001000000052ab70001b1000000000000");
defineBootstrapClass(m, MagicAccessor.magicAccessorBridge());
// public sun.reflect.MagicAccessorImpl extends jdk.internal.reflect.MagicAccessorBridge
defineBootstrapClass(m, "cafebabe00000033000a0a000300070700080700090100063c696e69743e010003282956010004436f64650c0004000501001d73756e2f7265666c6563742f4d616769634163636573736f72496d706c0100286a646b2f696e7465726e616c2f7265666c6563742f4d616769634163636573736f72427269646765042100020003000000000001000100040005000100060000001100010001000000052ab70001b1000000000000");
defineBootstrapClass(m, MagicAccessor.sunMagicAccessor());
} catch (Exception e) {
throw new IllegalStateException(e);
}
}
}

// Defines a new class by the bootstrap ClassLoader
private static void defineBootstrapClass(Method m, String classData) throws ReflectiveOperationException {
byte[] code = Hex.parseBytes(classData);
private static void defineBootstrapClass(Method m, byte[] code) throws ReflectiveOperationException {
m.invoke(null, null, null, code, 0, code.length, null, null);
}

Expand Down
60 changes: 60 additions & 0 deletions src/one/nio/serial/gen/MagicAccessor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright 2025 VK
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package one.nio.serial.gen;

import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

public class MagicAccessor {

public static byte[] magicAccessorBridge() {
String superClass;
if (useSerializationConstructorAccessor()) {
superClass = "jdk/internal/reflect/SerializationConstructorAccessorImpl";
} else {
superClass = "jdk/internal/reflect/MagicAccessorImpl";
}

return generateClass("jdk/internal/reflect/MagicAccessorBridge", superClass);
}

public static byte[] sunMagicAccessor() {
return generateClass(DelegateGenerator.MAGIC_CLASS, "jdk/internal/reflect/MagicAccessorBridge");
}

private static boolean useSerializationConstructorAccessor() {
String javaVersion = System.getProperty("java.version");
int majorVersion = Integer.parseInt(javaVersion.substring(0, javaVersion.indexOf(".")));
return majorVersion >= 22;
}

private static byte[] generateClass(String name, String superClass) {
ClassWriter cv = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
cv.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC, name, null, superClass, new String[]{});
MethodVisitor mv = cv.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);
mv.visitCode();

mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, superClass, "<init>", "()V", false);
mv.visitInsn(Opcodes.RETURN);
mv.visitEnd();
cv.visitEnd();
return cv.toByteArray();
}

}

0 comments on commit a1ea385

Please sign in to comment.