Java 9 有一个用于 Java 的 read-eval-print 循环,称为jshell
. 我已经从命令行看到它在基本模式下工作。它也可以在远程进程中使用吗?换句话说,我可以连接到另一个 Java 进程并输入代码片段以在该运行时中运行吗?这将是在应用服务器中更改配置状态的好方法,而无需编写带有 UI 的管理工具。
5 回答
简单的答案是否定的,没有办法将 jshell 附加到正在运行的 Java 进程。jshell 是在自己的 JVM 中运行的独立应用程序。
没有这样做的官方方式。
然而,重新捆绑代码并通过 Java 代理在另一个 VM 上运行它并不难。然而,这不会像您期望的那样工作,因为不清楚 shell 应该使用什么类加载器以及它应该如何与正在运行的程序交互。
回答https://stackoverflow.com/a/48132747/1561345包括一个 hacky 解决方案和一个建议,干净的解决方案可能是什么。
另一个答案的一部分暗示 JShell 仅在其 VM 中运行代码是错误的 - JShell 默认情况下通过 JDI 启动一个单独的 JVM(至少在 Linux 上)。但是,是的,我不知道官方的方式如何做到这一点。
附加 JShell是一个为 JShell 实现扩展的项目。它使用 Java 代理与目标 JVM 进行通信。
我没有使用它,所以我不能说它的效果如何。
快速检查后的观察
- 自述文件看起来很专业。
- 代码看起来很小很简单,好像很久没有开发了。
- 错误跟踪器中没有票证,这表明它没有被太多使用。
项目自述文件中的示例
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=XXXhostname:XXXport
使用(更新XXXhostname
和XXXport
酌情)启动目标 JVM,并new uk.org.cinquin.attaching_jshell.ExistingVMRemoteExecutionControl()
在使用 JShell 之前从该 JVM 调用。调用 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。