Java 9 有一个 Java 的读取-评估-打印循环,称为
jshell
。我已经看到它在命令行的基本模式下工作。它也可以用于远程进程吗?换句话说,我可以连接到另一个 Java 进程并输入代码片段以在该运行时运行吗?这将是更改应用程序服务器中的配置状态的好方法,而无需编写带有 UI 的管理工具。
简单的答案是否定的,没有办法将 jshell 附加到正在运行的 Java 进程。 jshell 是一个独立的应用程序,在自己的 JVM 中运行。
没有官方方法可以这样做。
然而,重新捆绑代码并通过 Java 代理在另一个虚拟机上运行它并不困难。然而,这不会像您期望的那样工作,因为不清楚 shell 应该使用什么类加载器以及它应该如何与正在运行的程序交互。
答案https://stackoverflow.com/a/48132747/1561345包括一个hacky解决方案和一个建议,干净的解决方案可能是什么。
另一个答案中建议 JShell 仅在其 VM 中运行代码的部分是错误的 - JShell 默认情况下启动一个单独的 JVM,并通过 JDI 进行传输(至少在 Linux 上)。但是,是的,我不知道如何做到这一点的官方方法。
Attaching JShell 是一个为此实现 JShell 扩展的项目。它使用 Java 代理与目标 JVM 进行通信。
我没有使用过它,所以我不能说它的效果如何。
使用
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=XXXhostname:XXXport
启动目标 JVM(根据需要更新 XXXhostname
和 XXXport
)并在使用 JShell 之前从该 JVM 调用 new uk.org.cinquin.attaching_jshell.ExistingVMRemoteExecutionControl()
。按如下方式调用 JShell:
java -cp lib/attaching_jshell.jar jdk.internal.jshell.tool.JShellToolProvider --execution "attachToExistingVM:hostname(XXXhostname),port(XXXport)"
使用与上面相同的 XXXhostname
和 XXXport
值在远程 JVM 中运行代码,如下所示:
import uk.org.cinquin.attaching_jshell.ExistingVMRemoteExecutionControl;
String s = ExistingVMRemoteExecutionControl.theGoodsForTesting
尝试arthas-mvel,它是一个像jshell一样的mvel REPL,并通过arthas实现attaching-another-jvm。
试试这个https://github.com/DavidKottas/remotejshell 这将让您通过 telnet 远程连接的 jshell 控制您的应用程序
import cz.kottas.remotejshell.TcpServer;
TcpServer tcpServer = new TcpServer(9876, null);
telnet 0 9876