是否有另一种方法来启动远程jvm? [英] Is there an alternate way to launch remote jvm?

查看:166
本文介绍了是否有另一种方法来启动远程jvm?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用JDK9的JShell API。



目前,JShell API在内部自动启动远程JVM。我不想自动启动流程,而是将两个流程分开。



注意:我知道我可以更改VM选项。但是我想知道VM是否可以在不同的机器上运行。



默认的执行控制最终在代码中到达这个地方



如果我指定启动,它会自动使用 com.sun.jdi.CommandLineLaunch 连接器,实际上按定义启动java程序。
如果我指定no-launch,它会按照我的预期使用 com.sun.jdi.SocketListen ,一旦启动服务器套接字,它会自动启动远程虚拟机并连接到此套接字。我认为这是出乎意料的。



我试过的其他事情,

  Shell jshell = JShell.builder()
.executionEngine(jdi:hostname(localhost),launch(false))
.build();
jshell.eval(1 + 2);

我希望这会失败或被卡住直到单独的流程开始。



是否有另一种指定连接器或不启动JVM的方法? (我对'本地'也不感兴趣)



一些简单的选项,比如能够指定 com.sun.jdi.RawCommandLineLaunch 作为接受自定义命令或能够使用套接字监听连接器并等待其他进程连接的连接器。



谢谢。

解决方案

编辑:我发现了一个错误 - 这应该不起作用,因为JDWP没有连接到新VM。 / p>




是的,这可以通过快速黑客来完成。
我的描述的改编版本如下:



hack依赖于替换JShell启动的VM中的代理。它可以通过 remoteAgent注入 执行参数

  CLASSPATH =< injectpath>  ./jshell --executionjdi:hostname(localhost),launch(false),remoteAgent(jshellhack.DumpPort),timeout(10000)

新的虚拟代理必须以某种方式给出它应该连接的端口号。如果你不介意丑陋的黑客,它可以像写入文件一样简单。您还可以利用命名管道。不过,对于任何严肃的事情我都不建议这样做。



一个简单的代理人:

  package jshellhack; 

import java.nio.file。*;
import java.lang。*;

import static java.nio.file.StandardOpenOption.CREATE;
import static java.nio.file.StandardOpenOption.WRITE;
import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING;

public class DumpPort {

public static void main(String [] args)throws Exception {
String str = args [0] +\ n ;
OpenOption [] opts = new OpenOption [] {CREATE,WRITE,TRUNCATE_EXISTING};
Files.write(Paths.get(/ tmp / jshellargs),str.getBytes(),opts);
}
}

计算机上的JShell是JDWP的监听端渠道。要重用现有的远程代理,您必须将所选端口反向转发到远程端。然后,您必须以远程端口作为参数在远程端运行原始代理。



使用SSH,它可能如下所示:

  ssh -R8000:localhost:$(cat / tmp / jshellargs)ssh.example.org java jdk.jshell.execution.RemoteExecutionControl 8000 

A 更强大的解决方案可能涉及克隆 JdiDefaultExecutionControl JdiInitiator 实现并使用远程连接功能扩展它们。


I am playing with the JDK9's JShell API.

At present, the JShell API automatically launches the remote JVM internally. Instead of starting the process automatically, I want to separate the two process.

Note: I understand I can change the VM options. But I want to see if the VM can even be run on a different machine.

The default execution control eventually reaches this place in code.

If I specify launch, it automatically uses com.sun.jdi.CommandLineLaunch connector, that actually launches the java program by definition. If I specify no-launch, it uses com.sun.jdi.SocketListen as I would expect, once it started the server socket, it automatically starts a remote vm and connects to this socket. This I think is unexpected.

Other things I tried,

Shell jshell = JShell.builder()
    .executionEngine("jdi:hostname(localhost),launch(false)")
    .build();
jshell.eval("1+2");

I would expect this to fail or be stuck until a separate process starts.

Is there an alternate way to specify the connectors, or not start a JVM? (I am not interested in 'local' either)

Some easy options like being able to specify com.sun.jdi.RawCommandLineLaunch as the connector that accepts the custom command or being able to use the socket listen connector and wait for the other process to connect.

Thanks.

解决方案

EDIT: I've found a bug in this - this shouldn't work, because the JDWP not attached to the new VM.


Yes, this can be accomplished with a quick hack. Adapted version of my description follows:

The hack relies on replacing the agent in the VM started by JShell. It can be injected through the remoteAgent execution parameter.

CLASSPATH="<injectpath>" ./jshell --execution "jdi:hostname(localhost),launch(false),remoteAgent(jshellhack.DumpPort),timeout(10000)"

The new dummy agent has to somehow give out the port number it was supposed to connect to. If you don't mind ugly hacks, it can be as simple as writing it to a file. You can also take advantage of a named pipe. I wouldn't recommend this for anything serious, though.

A simple agent:

package jshellhack;

import java.nio.file.*;
import java.lang.*;

import static java.nio.file.StandardOpenOption.CREATE;
import static java.nio.file.StandardOpenOption.WRITE;
import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING;

public class DumpPort {

    public static void main(String[] args) throws Exception {
        String str = args[0] + "\n";
        OpenOption[] opts = new OpenOption[] { CREATE, WRITE, TRUNCATE_EXISTING };
        Files.write(Paths.get("/tmp/jshellargs"), str.getBytes(), opts);
    }
}

JShell on your computer is the listening side of the JDWP channel. To reuse the existing remote agent, you have to reverse-forward a chosen port to the remote side. Then, you have to run the original agent on the remote side with the remote port as an argument.

Using SSH, it may look like this:

ssh -R "8000:localhost:$(cat /tmp/jshellargs)" ssh.example.org java jdk.jshell.execution.RemoteExecutionControl 8000

A more robust solution will probably involve cloning the JdiDefaultExecutionControl and JdiInitiator implementations and extending them with remote connection capability.

这篇关于是否有另一种方法来启动远程jvm?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆