Is there an alternative way to start remote jvm?

I play with the JDK9 JShell API.

Currently, the JShell API automatically starts a remote JVM. Instead of starting the process automatically, I want to separate the two processes.

Note. I understand that I can change the parameters of a virtual machine. But I want to see if it is possible to run the virtual machine on another machine.

By default, execution control reaches this place in the code .

If I specify a start, it automatically uses the com.sun.jdi.CommandLineLaunch connector, which actually launches a java program by definition. If I specify no-launch, it uses com.sun.jdi.SocketListen , as I would expect, as soon as it starts the server socket, it automatically starts the remote vm and connects to this socket . I find this unexpected.

Other things I've tried

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

I expect this to fail or get stuck until a separate process begins.

Is there an alternative way to specify connectors or not start the JVM? (I'm also not interested in "local")

Some simple options, such as the ability to specify com.sun.jdi.RawCommandLineLaunch as a connector that accepts a user command or can use the socket listen socket, and wait for another process to connect.

Thanks.

+3
java java-9 jshell
source share
1 answer

EDIT: I found an error in this - this should not work because JDWP is not connected to the new virtual machine.


Yes, this can be achieved with a quick hack. An adapted version of my description follows:

Hack relies on agent replacement in a virtual machine running JShell. It can be entered through the remoteAgent parameter.

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

The new dummy agent must somehow give out the port number to which it was supposed to connect. If you don't mind ugly hacks, it can be as simple as writing it to a file. You can also use a named pipe. I would not recommend this for anything serious.

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 an existing remote agent, you need to flip the selected port to the remote side. Then you need to start the source agent on the remote side with the remote port as an argument.

Using SSH, it might look like this:

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

A more robust solution is probably related to the cloning of JdiDefaultExecutionControl and JdiInitiator and extends them with remote connectivity.

+2
source share

All Articles