incision: ManualSelfAttach permanently sets jdk.attach.allowAttachSelf=true, breaking agent attachment for other plugins (e.g. ByteBuddy users)
Body:
Summary
taboolib.module.incision.loader.attach.ManualSelfAttach.attach() unconditionally executes:
// 启用 self-attach(JDK 9+)
System.setProperty("jdk.attach.allowAttachSelf", "true")
|
System.setProperty("jdk.attach.allowAttachSelf", "true") |
This property write is process-global and is never reverted. It cannot achieve what the comment intends, and it silently breaks Java agent attachment for every other plugin in the same JVM that uses ByteBuddy (or any library that consults this property at runtime).
Why setting the property at runtime cannot work
HotSpot snapshots this property at JVM startup. sun.tools.attach.HotSpotVirtualMachine reads it via VM.getSavedProperty, not System.getProperty:
static {
String s = VM.getSavedProperty("jdk.attach.allowAttachSelf");
ALLOW_ATTACH_SELF = "".equals(s) || Boolean.parseBoolean(s);
}
...
if (!ALLOW_ATTACH_SELF && selfAttach) {
throw new IOException("Can not attach to current VM");
}
So unless -Djdk.attach.allowAttachSelf=true was passed on the command line, incision's own self-attach fails regardless of the setProperty call. Incision then falls back to its ASM-only path — but the poisoned property remains set for the lifetime of the process.
Why this breaks other plugins
net.bytebuddy.agent.ByteBuddyAgent chooses its attachment strategy from the live system property (ByteBuddyAgent$AttachmentTypeEvaluator$InstallationAction):
if (Boolean.getBoolean("jdk.attach.allowAttachSelf")) {
return Disabled.INSTANCE; // direct in-process self-attach
}
Normally (property unset), ByteBuddy detects a self-attach and transparently spawns an external helper process to perform the attach, which works fine without any JVM flags. After incision has set the property, ByteBuddy believes in-process self-attach is permitted, skips the external fallback, calls VirtualMachine.attach(<own pid>) directly — and the JDK rejects it with IOException: Can not attach to current VM, because the startup snapshot still says self-attach is disallowed.
Net effect: the JDK ignores the runtime value, ByteBuddy trusts it, and the setProperty call drives the two apart. Any plugin loading after a TabooLib plugin with the incision module can no longer install a Java agent.
TrChat 2.4.10 (TabooLib 6.3.0, incision installed) + Iris on Paper: Iris self-attaches its instrumentation agent via ByteBuddyAgent.attach(...) at startup. Without TrChat this works. With TrChat installed, Iris's attach fails with Can not attach to current VM and it reports its safeguard error, even though the server was started with -XX:+EnableDynamicAgentLoading. Removing TrChat (or adding -Djdk.attach.allowAttachSelf=true so the runtime property matches reality) resolves it.
PLEASE:
Remove the System.setProperty call entirely — it cannot enable self-attach on HotSpot. If there is a VM where it does help, at minimum snapshot the previous value and restore it (including clearing it if it was unset) when the attach attempt fails, so the failed experiment doesn't leak process-global state into unrelated plugins.
You can see my plugin here:
https://github.com/VolmitSoftware/Iris
Thank you
TRANSLATED:
标题:
incision: ManualSelfAttach 永久设置 jdk.attach.allowAttachSelf=true,破坏其他插件的 agent 附加(例如 ByteBuddy 用户)
正文:
摘要
taboolib.module.incision.loader.attach.ManualSelfAttach.attach() 无条件执行:
// 启用 self-attach(JDK 9+)
System.setProperty("jdk.attach.allowAttachSelf", "true")
|
System.setProperty("jdk.attach.allowAttachSelf", "true") |
此属性写入是进程全局的,且从未还原。它无法实现注释中的意图,并会静默破坏同一 JVM 中所有使用 ByteBuddy(或任何在运行时检查此属性的库)的其他插件的 Java agent 附加。
为什么在运行时设置该属性无效
HotSpot 在 JVM 启动时快照此属性。sun.tools.attach.HotSpotVirtualMachine 通过 VM.getSavedProperty 读取它,而不是 System.getProperty:
static {
String s = VM.getSavedProperty("jdk.attach.allowAttachSelf");
ALLOW_ATTACH_SELF = "".equals(s) || Boolean.parseBoolean(s);
}
...
if (!ALLOW_ATTACH_SELF && selfAttach) {
throw new IOException("Can not attach to current VM");
}
因此,除非启动时传入 -Djdk.attach.allowAttachSelf=true,否则 incision 自身的 self-attach 无论是否调用 setProperty 都会失败。Incision 随后回退到纯 ASM 路径,但被污染的属性会在进程生命周期内一直保留。
为什么这会破坏其他插件
net.bytebuddy.agent.ByteBuddyAgent 根据实时系统属性选择附加策略(ByteBuddyAgent$AttachmentTypeEvaluator$InstallationAction):
if (Boolean.getBoolean("jdk.attach.allowAttachSelf")) {
return Disabled.INSTANCE; // 直接进程内 self-attach
}
正常情况下(属性未设置),ByteBuddy 检测到 self-attach 后会透明地启动一个外部辅助进程来执行附加,无需任何 JVM 参数即可正常工作。当 incision 设置了该属性后,ByteBuddy 认为进程内 self-attach 已允许,跳过外部回退,直接调用 VirtualMachine.attach(<own pid>)——而 JDK 会因启动快照仍禁止 self-attach 而抛出 IOException: Can not attach to current VM。
最终结果:JDK 忽略运行时值,ByteBuddy 信任它,setProperty 调用使两者产生分歧。任何在带有 incision 模块的 TabooLib 插件之后加载的插件都无法再安装 Java agent。
TrChat 2.4.10(TabooLib 6.3.0,安装了 incision)+ Iris on Paper:Iris 在启动时通过 ByteBuddyAgent.attach(...) 自附加其 instrumentation agent。没有 TrChat 时正常。安装 TrChat 后,Iris 的附加失败并报 Can not attach to current VM,即使服务器启动时使用了 -XX:+EnableDynamicAgentLoading。移除 TrChat(或添加 -Djdk.attach.allowAttachSelf=true 使运行时属性与实际一致)即可解决。
请求:
请完全移除 System.setProperty 调用——它无法在 HotSpot 上启用 self-attach。如果有某些 VM 确实有效,至少应快照原值,并在附加失败时恢复(包括原未设置时清除),避免失败的实验泄漏进程全局状态到无关插件。
我的插件在此:
https://github.com/VolmitSoftware/Iris
谢谢
incision: ManualSelfAttach permanently sets jdk.attach.allowAttachSelf=true, breaking agent attachment for other plugins (e.g. ByteBuddy users)
Body:
Summary
taboolib.module.incision.loader.attach.ManualSelfAttach.attach()unconditionally executes:taboolib/module/incision/src/main/kotlin/taboolib/module/incision/loader/attach/ManualSelfAttach.kt
Line 37 in b848958
This property write is process-global and is never reverted. It cannot achieve what the comment intends, and it silently breaks Java agent attachment for every other plugin in the same JVM that uses ByteBuddy (or any library that consults this property at runtime).
Why setting the property at runtime cannot work
HotSpot snapshots this property at JVM startup.
sun.tools.attach.HotSpotVirtualMachinereads it viaVM.getSavedProperty, notSystem.getProperty:So unless
-Djdk.attach.allowAttachSelf=truewas passed on the command line, incision's own self-attach fails regardless of thesetPropertycall. Incision then falls back to its ASM-only path — but the poisoned property remains set for the lifetime of the process.Why this breaks other plugins
net.bytebuddy.agent.ByteBuddyAgentchooses its attachment strategy from the live system property (ByteBuddyAgent$AttachmentTypeEvaluator$InstallationAction):Normally (property unset), ByteBuddy detects a self-attach and transparently spawns an external helper process to perform the attach, which works fine without any JVM flags. After incision has set the property, ByteBuddy believes in-process self-attach is permitted, skips the external fallback, calls
VirtualMachine.attach(<own pid>)directly — and the JDK rejects it withIOException: Can not attach to current VM, because the startup snapshot still says self-attach is disallowed.Net effect: the JDK ignores the runtime value, ByteBuddy trusts it, and the
setPropertycall drives the two apart. Any plugin loading after a TabooLib plugin with theincisionmodule can no longer install a Java agent.TrChat 2.4.10 (TabooLib 6.3.0,
incisioninstalled) + Iris on Paper: Iris self-attaches its instrumentation agent viaByteBuddyAgent.attach(...)at startup. Without TrChat this works. With TrChat installed, Iris's attach fails withCan not attach to current VMand it reports its safeguard error, even though the server was started with-XX:+EnableDynamicAgentLoading. Removing TrChat (or adding-Djdk.attach.allowAttachSelf=trueso the runtime property matches reality) resolves it.PLEASE:
Remove the
System.setPropertycall entirely — it cannot enable self-attach on HotSpot. If there is a VM where it does help, at minimum snapshot the previous value and restore it (including clearing it if it was unset) when the attach attempt fails, so the failed experiment doesn't leak process-global state into unrelated plugins.You can see my plugin here:
https://github.com/VolmitSoftware/Iris
Thank you
TRANSLATED:
标题:
incision: ManualSelfAttach 永久设置 jdk.attach.allowAttachSelf=true,破坏其他插件的 agent 附加(例如 ByteBuddy 用户)
正文:
摘要
taboolib.module.incision.loader.attach.ManualSelfAttach.attach()无条件执行:taboolib/module/incision/src/main/kotlin/taboolib/module/incision/loader/attach/ManualSelfAttach.kt
Line 37 in b848958
此属性写入是进程全局的,且从未还原。它无法实现注释中的意图,并会静默破坏同一 JVM 中所有使用 ByteBuddy(或任何在运行时检查此属性的库)的其他插件的 Java agent 附加。
为什么在运行时设置该属性无效
HotSpot 在 JVM 启动时快照此属性。
sun.tools.attach.HotSpotVirtualMachine通过VM.getSavedProperty读取它,而不是System.getProperty:因此,除非启动时传入
-Djdk.attach.allowAttachSelf=true,否则 incision 自身的 self-attach 无论是否调用setProperty都会失败。Incision 随后回退到纯 ASM 路径,但被污染的属性会在进程生命周期内一直保留。为什么这会破坏其他插件
net.bytebuddy.agent.ByteBuddyAgent根据实时系统属性选择附加策略(ByteBuddyAgent$AttachmentTypeEvaluator$InstallationAction):正常情况下(属性未设置),ByteBuddy 检测到 self-attach 后会透明地启动一个外部辅助进程来执行附加,无需任何 JVM 参数即可正常工作。当 incision 设置了该属性后,ByteBuddy 认为进程内 self-attach 已允许,跳过外部回退,直接调用
VirtualMachine.attach(<own pid>)——而 JDK 会因启动快照仍禁止 self-attach 而抛出IOException: Can not attach to current VM。最终结果:JDK 忽略运行时值,ByteBuddy 信任它,
setProperty调用使两者产生分歧。任何在带有incision模块的 TabooLib 插件之后加载的插件都无法再安装 Java agent。TrChat 2.4.10(TabooLib 6.3.0,安装了
incision)+ Iris on Paper:Iris 在启动时通过ByteBuddyAgent.attach(...)自附加其 instrumentation agent。没有 TrChat 时正常。安装 TrChat 后,Iris 的附加失败并报Can not attach to current VM,即使服务器启动时使用了-XX:+EnableDynamicAgentLoading。移除 TrChat(或添加-Djdk.attach.allowAttachSelf=true使运行时属性与实际一致)即可解决。请求:
请完全移除
System.setProperty调用——它无法在 HotSpot 上启用 self-attach。如果有某些 VM 确实有效,至少应快照原值,并在附加失败时恢复(包括原未设置时清除),避免失败的实验泄漏进程全局状态到无关插件。我的插件在此:
https://github.com/VolmitSoftware/Iris
谢谢