2017-10-09 124 views
2

我在玩JDK9的JShell API。有沒有另外一種方法來啓動遠程jvm?

目前,JShell API在內部自動啓動遠程JVM。我不想自動啓動該過程,而是要分開這兩個過程。

注意:我知道我可以更改VM選項。但我想看看虛擬機是否可以在不同的機器上運行。

默認執行控制最終爲reaches this place in code

如果我指定啓動,它會自動使用com.sun.jdi.CommandLineLaunch連接器,它實際上按照定義啓動java程序。 如果我指定不啓動,它會像我所期望的那樣使用com.sun.jdi.SocketListen,一旦它啓動服務器套接字,它會自動starts a remote vm and connects to this socket。我認爲這是意想不到的。

其他的事情我試過,

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

我希望它可以失敗,或者被卡住,直到一個獨立的進程開始。

是否有替代方法來指定連接器或不啓動JVM? (我對「本地」不感興趣)

一些簡單的選項,例如能夠指定com.sun.jdi.RawCommandLineLaunch作爲接受自定義命令或能夠使用套接字偵聽連接器並等待其他進程連接的連接器。

謝謝。

回答

1

編輯:我發現這個錯誤 - 這不應該,因爲JDWP沒有附加到新的虛擬機。


是的,這可以用一個快速的黑客來完成。 my description的改編版本如下:

黑客依賴於替換由JShell啓動的VM中的代理。它可以通過remoteAgentexecution parameter注入。

新的虛擬代理必須以某種方式發出它應該連接的端口號。如果你不介意醜陋的黑客,它可以像寫入文件一樣簡單。您還可以利用命名管道。儘管如此,我不會推薦這件事。

一個簡單的代理:

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 -R "8000:localhost:$(cat /tmp/jshellargs)" ssh.example.org java jdk.jshell.execution.RemoteExecutionControl 8000 

一個more robust solution可能會涉及克隆JdiDefaultExecutionControlJdiInitiator實現,並與遠程連接能力擴展。

相關問題