Skip to content

Commit 6a8dbe3

Browse files
committed
fix: method body write failed with jakarta renamed
ByteBuddy Advice cache the class method list at first, the method signature will be changed when use jakarta rename, if follow advice need enhance the javax method, it will not find method signature. because ByteBuddy cached javax method, but follow advice need find the jakarta method, boom~
1 parent a8403aa commit 6a8dbe3

6 files changed

Lines changed: 54 additions & 57 deletions

File tree

generator/src/main/java/com/reajason/javaweb/memshell/generator/ProcessorRegistry.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@ public final class ProcessorRegistry {
1717
private static final List<Processor<DynamicType.Builder<?>>> BUILDER_PROCESSORS = Arrays.asList(
1818
new ListenerBuilderModifier(),
1919
new ValveBuilderModifier(),
20-
new JakartaBuilderModifier(),
2120
new DebugOffBuilderModifier()
2221
);
2322

2423
private static final List<Processor<byte[]>> BYTE_PROCESSORS = Arrays.asList(
24+
new JakartaPostProcessor(),
2525
new JettyHandlerPostProcessor(),
2626
new ShrinkPostProcessor()
2727
);

generator/src/main/java/com/reajason/javaweb/memshell/generator/processors/JakartaBuilderModifier.java

Lines changed: 0 additions & 22 deletions
This file was deleted.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.reajason.javaweb.memshell.generator.processors;
2+
3+
import com.reajason.javaweb.asm.ClassRenameUtils;
4+
import com.reajason.javaweb.memshell.config.ShellConfig;
5+
import com.reajason.javaweb.memshell.config.ShellToolConfig;
6+
import com.reajason.javaweb.memshell.generator.Processor;
7+
8+
public class JakartaPostProcessor implements Processor<byte[]> {
9+
@Override
10+
public byte[] process(byte[] input, ShellConfig shellConfig, ShellToolConfig shellToolConfig) {
11+
if (shellConfig.isJakarta()) {
12+
return ClassRenameUtils.relocateJakarta(input);
13+
}
14+
return input;
15+
}
16+
}

generator/src/main/java/com/reajason/javaweb/memshell/generator/processors/ListenerBuilderModifier.java

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import net.bytebuddy.description.type.TypeDescription;
1818
import net.bytebuddy.dynamic.DynamicType;
1919
import net.bytebuddy.implementation.FixedValue;
20+
import net.bytebuddy.implementation.StubMethod;
2021
import net.bytebuddy.matcher.ElementMatchers;
2122

2223
import static net.bytebuddy.matcher.ElementMatchers.named;
@@ -46,26 +47,21 @@ public static DynamicType.Builder<?> modifier(DynamicType.Builder<?> builder, Cl
4647
TypeDescription typeDefinition, String newClassName) {
4748
MethodList<MethodDescription.InDefinedShape> methods = typeDefinition.getDeclaredMethods();
4849

49-
if (methods.filter(ElementMatchers.named("getResponseFromRequest")
50-
.and(ElementMatchers.takesArguments(Object.class))
51-
.and(ElementMatchers.returns(Object.class)))
52-
.isEmpty()) {
53-
throw new GenerationException("[public Object getResponseFromRequest(Object request)] method not found" +
54-
" make sure arg and return type is Object.class");
50+
if (methods.filter(named("getResponseFromRequest").and(takesArguments(1))).isEmpty()) {
51+
throw new GenerationException("please add [getResponseFromRequest(Object request)] method," +
52+
" the method body will be auto adapted for multi server");
5553
} else {
5654
builder = builder
5755
.visit(MethodCallReplaceVisitorWrapper.newInstance(
5856
"getResponseFromRequest", newClassName, ShellCommonUtil.class.getName()))
5957
.visit(Advice.to(implInterceptor).on(named("getResponseFromRequest")));
6058
}
6159

62-
if (methods.filter(named("getFieldValue")
63-
.and(takesArguments(Object.class, String.class)))
64-
.isEmpty()) {
60+
if (methods.filter(named("getFieldValue").and(takesArguments(Object.class, String.class))).isEmpty()) {
6561
builder = builder.defineMethod("getFieldValue", Object.class, Visibility.PUBLIC, Ownership.STATIC)
6662
.withParameters(Object.class, String.class)
6763
.throwing(Exception.class)
68-
.intercept(FixedValue.nullValue())
64+
.intercept(StubMethod.INSTANCE)
6965
.visit(Advice.to(ShellCommonUtil.GetFieldValueInterceptor.class).on(named("getFieldValue")));
7066
}
7167
return builder;

generator/src/test/java/com/reajason/javaweb/memshell/generator/ListenerGeneratorTest.java

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,6 @@ public Object getResponseFromRequest(Object request) {
2828
}
2929
}
3030

31-
public static class J {
32-
public HttpServletResponse getResponseFromRequest(HttpServletRequest request) {
33-
return null;
34-
}
35-
}
36-
3731
public static class FakeRequest {
3832
public Object response = "i'm a good boy";
3933
}
@@ -44,12 +38,6 @@ void testNoGetResponseFromRequest() {
4438
Assertions.assertThrows(GenerationException.class, () -> ListenerBuilderModifier.modifier(builder, Tomcat.ListenerInterceptor.class, TypeDescription.ForLoadedType.of(Object.class), "hello.world"));
4539
}
4640

47-
@Test
48-
void testGetResponseFromRequestSignatureError() {
49-
DynamicType.Builder<?> builder = new ByteBuddy().redefine(J.class);
50-
Assertions.assertThrows(GenerationException.class, () -> ListenerBuilderModifier.modifier(builder, Tomcat.ListenerInterceptor.class, TypeDescription.ForLoadedType.of(J.class), "hello.world"));
51-
}
52-
5341
@Test
5442
@SneakyThrows
5543
void test() {

memshell-party-common/src/main/java/com/reajason/javaweb/asm/ClassRenameUtils.java

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.reajason.javaweb.asm;
22

3+
import org.jetbrains.annotations.NotNull;
34
import org.objectweb.asm.ClassReader;
45
import org.objectweb.asm.ClassWriter;
56
import org.objectweb.asm.Opcodes;
@@ -14,12 +15,7 @@
1415
public class ClassRenameUtils {
1516

1617
public static byte[] renameClass(byte[] classBytes, String newName) {
17-
ClassReader reader = null;
18-
try {
19-
reader = new ClassReader(classBytes);
20-
} catch (Exception e) {
21-
throw new RuntimeException("invalid class bytes");
22-
}
18+
ClassReader reader = getClassReader(classBytes);
2319
String oldClassName = reader.getClassName();
2420
String newClassName = newName.replace('.', '/');
2521
ClassWriter writer = new ClassWriter(reader, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
@@ -29,12 +25,7 @@ public static byte[] renameClass(byte[] classBytes, String newName) {
2925
}
3026

3127
public static byte[] relocateClass(byte[] classBytes, String relocateClassPackage, String relocatePrefix) {
32-
ClassReader reader = null;
33-
try {
34-
reader = new ClassReader(classBytes);
35-
} catch (Exception e) {
36-
throw new RuntimeException("invalid class bytes");
37-
}
28+
ClassReader reader = getClassReader(classBytes);
3829
String oldClassName = relocateClassPackage.replace('.', '/');
3930
String newClassName = relocatePrefix.replace('.', '/');
4031
ClassWriter writer = new ClassWriter(reader, ClassWriter.COMPUTE_MAXS);
@@ -51,4 +42,32 @@ public String map(String typeName) {
5142
reader.accept(adapter, 0);
5243
return writer.toByteArray();
5344
}
45+
46+
public static byte[] relocateJakarta(byte[] classBytes) {
47+
ClassReader reader = getClassReader(classBytes);
48+
ClassWriter writer = new ClassWriter(reader, ClassWriter.COMPUTE_MAXS);
49+
ClassRemapper adapter = new ClassRemapper(writer, new Remapper(Opcodes.ASM9) {
50+
@Override
51+
public String map(String typeName) {
52+
if (typeName.startsWith("javax/servlet/")
53+
|| typeName.startsWith("javax/websocket/")) {
54+
return typeName.replaceFirst("javax", "jakarta");
55+
} else {
56+
return typeName;
57+
}
58+
}
59+
});
60+
reader.accept(adapter, 0);
61+
return writer.toByteArray();
62+
}
63+
64+
private static @NotNull ClassReader getClassReader(byte[] classBytes) {
65+
ClassReader reader = null;
66+
try {
67+
reader = new ClassReader(classBytes);
68+
} catch (Exception e) {
69+
throw new RuntimeException("invalid class bytes");
70+
}
71+
return reader;
72+
}
5473
}

0 commit comments

Comments
 (0)