feat: support bypassJdkModule and Jakarta

This commit is contained in:
ReaJason
2024-11-29 02:02:04 +08:00
parent d0dcc8d56f
commit b6ce6581a0
40 changed files with 1167 additions and 686 deletions
@@ -0,0 +1,51 @@
package com.reajason.javaweb.buddy;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.asm.AsmVisitorWrapper;
import net.bytebuddy.description.modifier.Ownership;
import net.bytebuddy.description.modifier.Visibility;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.implementation.FixedValue;
import net.bytebuddy.implementation.MethodCall;
import net.bytebuddy.implementation.bytecode.assign.Assigner;
import java.lang.reflect.Field;
import static net.bytebuddy.matcher.ElementMatchers.isTypeInitializer;
import static net.bytebuddy.matcher.ElementMatchers.named;
/**
* @author ReaJason
*/
public class ByPassJdkModuleInterceptor {
@Advice.OnMethodExit
public static void enter(@Advice.Origin Class<?> clazz, @Advice.Return(readOnly = false, typing = Assigner.Typing.DYNAMIC) boolean returnValue) {
try {
Class<?> unsafeClass = Class.forName("sun.misc.Unsafe");
java.lang.reflect.Field unsafeField = unsafeClass.getDeclaredField("theUnsafe");
unsafeField.setAccessible(true);
Object unsafe = unsafeField.get(null);
java.lang.reflect.Method getModuleM = Class.class.getMethod("getModule");
Object module = getModuleM.invoke(Object.class, (Object[]) null);
java.lang.reflect.Method objectFieldOffsetM = unsafe.getClass().getMethod("objectFieldOffset", Field.class);
java.lang.reflect.Field moduleF = Class.class.getDeclaredField("module");
Long offset = (Long) objectFieldOffsetM.invoke(unsafe, moduleF);
java.lang.reflect.Method getAndSetObjectM = unsafe.getClass().getMethod("getAndSetObject", Object.class, long.class, Object.class);
getAndSetObjectM.invoke(unsafe, clazz, offset, module);
returnValue = true;
} catch (Exception ignored) {
}
}
public static DynamicType.Builder<?> extend(DynamicType.Builder<?> builder) {
return builder
.defineField("isBypassModule", boolean.class, Visibility.PUBLIC, Ownership.STATIC)
.invokable(isTypeInitializer())
.intercept(MethodCall.invoke(named("byPassJdkModule")))
.defineMethod("byPassJdkModule", Object.class, Visibility.PUBLIC, Ownership.STATIC)
.intercept(FixedValue.value(false))
.visit(new AsmVisitorWrapper.ForDeclaredMethods()
.method(named("byPassJdkModule"),
Advice.to(ByPassJdkModuleInterceptor.class)));
}
}
@@ -10,32 +10,35 @@ import net.bytebuddy.jar.asm.ClassVisitor;
import net.bytebuddy.jar.asm.commons.ClassRemapper;
import net.bytebuddy.jar.asm.commons.Remapper;
import net.bytebuddy.pool.TypePool;
import org.jetbrains.annotations.NotNull;
/**
* @author ReaJason
* @since 2024/11/23
*/
public class ServletRenameVisitorWrapper implements AsmVisitorWrapper {
public static ServletRenameVisitorWrapper INSTANCE = new ServletRenameVisitorWrapper();
@Override
public int mergeReader(int flags) {
return 0;
return flags;
}
@Override
public int mergeWriter(int flags) {
return 0;
return flags;
}
@NotNull
@Override
public ClassVisitor wrap(
TypeDescription instrumentedType,
ClassVisitor classVisitor,
Implementation.Context implementationContext,
TypePool typePool,
FieldList<FieldDescription.InDefinedShape> fields,
MethodList<?> methods,
int writerFlags,
int readerFlags) {
public ClassVisitor wrap(@NotNull TypeDescription instrumentedType,
@NotNull ClassVisitor classVisitor,
@NotNull Implementation.Context implementationContext,
@NotNull TypePool typePool,
@NotNull FieldList<FieldDescription.InDefinedShape> fields,
@NotNull MethodList<?> methods,
int writerFlags,
int readerFlags) {
return new ClassRemapper(
classVisitor,
new Remapper() {
@@ -0,0 +1,57 @@
package com.reajason.javaweb.buddy;
import com.reajason.javaweb.config.Constants;
import net.bytebuddy.asm.AsmVisitorWrapper;
import net.bytebuddy.description.field.FieldDescription;
import net.bytebuddy.description.field.FieldList;
import net.bytebuddy.description.method.MethodList;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.implementation.Implementation;
import net.bytebuddy.jar.asm.ClassVisitor;
import net.bytebuddy.jar.asm.Opcodes;
import net.bytebuddy.pool.TypePool;
import net.bytebuddy.utility.nullability.MaybeNull;
import org.jetbrains.annotations.NotNull;
/**
* @author ReaJason
*/
public class TargetJDKVersionVisitorWrapper implements AsmVisitorWrapper {
public static final TargetJDKVersionVisitorWrapper DEFAULT = new TargetJDKVersionVisitorWrapper();
private final int targetJdkVersion;
public TargetJDKVersionVisitorWrapper() {
targetJdkVersion = Constants.DEFAULT_VERSION;
}
public TargetJDKVersionVisitorWrapper(int targetJdkVersion) {
this.targetJdkVersion = targetJdkVersion;
}
@Override
public int mergeWriter(int flags) {
return flags;
}
@Override
public int mergeReader(int flags) {
return flags;
}
@NotNull
@Override
public ClassVisitor wrap(@NotNull TypeDescription instrumentedType,
@NotNull ClassVisitor classVisitor, @NotNull Implementation.Context implementationContext,
@NotNull TypePool typePool, @NotNull FieldList<FieldDescription.InDefinedShape> fields,
@NotNull MethodList<?> methods, int writerFlags, int readerFlags) {
return new ClassVisitor(Opcodes.ASM9, classVisitor) {
@Override
public void visit(int version, int modifiers, String name, @MaybeNull String signature, @MaybeNull String superClassName, @MaybeNull String[] interfaceName) {
super.visit(targetJdkVersion, modifiers, name, signature, superClassName, interfaceName);
}
};
}
}