2008-12-15 79 views
2

我有一個非常簡單的Java類,它使用輸入驗證有效地裝飾了一個Map,其中使用了顯而易見的void set()和String get()方法。如何從JVM外部調用對象中的方法?

我希望能夠有效地調用這些方法並處理來自JVM外部的返回值和異常,但仍然在同一臺機器上更新:我記住的調用者不是另一個JVM;感謝@戴夫雷

我的實現考慮是典型

  • 性能
  • 便於實施和維護(簡單?)
  • 可靠性的
  • 靈活性(即我可以從遠程設備呼叫等)

有沒有「正確的方法?如果不是,我的選擇是什麼,每個選項有哪些贊成/反對?

(東西的人實際上已經完成,可以提供真實的反饋意見將是巨大的!)

回答

3

好的。現在再試一次,我知道客戶端不是Java。既然你想進程外訪問和遠程機器訪問,我不認爲JNI是你想要的,因爲這是嚴格的過程中(和一個麻煩)。以下是一些其他選項:

原始套接字:只需在Java中設置一個偵聽套接字並接受連接。當你得到連接時,讀取請求併發送回應。幾乎所有的語言都可以使用套接字,所以這是一個非常通用的解決方案。但是,你必須定義自己的編組方案,解析等

XML-RPC:這是不是如髖關節,這些天,但它是簡單而有效的。有Java libraries以及大多數其他語言的圖書館。

CORBA:如上所述,CORBA是一種選擇,但它非常複雜,專家越來越難以得到。

Web服務器:在您的應用程序中設置嵌入式Web服務器並處理請求。我聽說過有關Jetty的好消息,或者您可以使用one provided with Java。我已經成功地將後者用於使用Java編寫的模擬服務器將KML文件服務到Google地球。大多數其他語言都有用於發出HTTP請求的庫。你如何編碼數據(XML,文本等)取決於你。

網絡服務:我認爲這會更復雜,但是您可以使用JAX-WS將對象公開爲Web服務。 NetBeans擁有用於構建Web服務的相當不錯的工具,但這可能是矯枉過正的。

3

你們會從其他基於JVM的系統調用,或者是客戶端語言任意?如果您從另一個JVM調用,最簡單的方法之一是通過JMX將對象作爲MBean公開。規範Hello World MBean顯示爲here。好處有:

  • 真的很容易實現
  • 真的很容易從其他JVM叫
  • 遠程機器支持
  • jconsole允許手動測試您的MBean,無需編寫客戶端

缺點:

  • 客戶有權爲O n一個JVM(我認爲)
  • 對於更復雜的數據結構和交互不太好。例如,我不認爲MBean可以返回對另一個MBean的引用。它會序列化並返回一份副本。
+0

感謝,呼叫者我心目中是不是另一個JVM,但很好的答案,我認爲我的 – Brabster 2008-12-15 16:26:03

0

JNI(Java Native Interface)允許從C或C++訪問Java代碼。

+0

類是在運行的JVM;我想從外面調用課堂上的方法。我認爲JNI是一種使Java本地代碼可用的方法,所以我不認爲這是我正在尋找的... – Brabster 2008-12-15 16:24:25

0

我有一個Inno Setup腳本(安裝Java程序),它調用一些Java方法來執行一些操作或檢查一些條件。
我(實際上是我的前任)在每次調用時只是實例化java.exe。這顯然是代價高昂的,雖然對我來說並不重要(我想也是Windows緩存)。

另一種方法是使用一些語言間通信/消息傳遞,您的Java程序充當服務器。考爾巴想到了,因爲它是語言不可知的。但也許有點沉重。你可以使用套接字。 RPC也是一個流行詞,但我在該領域沒有太多經驗。

2

由於您的呼叫者不是Java應用程序,並且您已經預見到網絡呼叫者,因此可能會提供RMI-IIOP (CORBA)選項。儘管實施起來並不容易,但它具有被廣泛認可的標準的優點。

2

由於您的來電者是不是JVM爲基礎的,這是JVM進程間通信的問題。我想到的選項是:

  1. 通信通過套接字:使你的JVM聽傳入連接和來電發送命令
  2. 通信使用共享文件(主叫方寫入文件,JVM投票和更新)
  3. 使用JNI,在調用者進程內啓動JVM,然後使用RMI/MBeans與第一個(「服務器」)JVM進行通信。來電者將有權訪問使用JNI的結果

選項3 IMO是這樣做的最「Java」方式,並且是最複雜/容易出錯的方式。 選項2很難看但很簡單 選項1非常容易(java部分),否則就ok了。

1

爲了方便使用,我會用Spring Remoting。如果你已經在你的項目中使用Spring,那是毫不費力的。如果你沒有...好,你應該看看。

Spring提供了一個抽象,讓您輕鬆切換遠程協議。它支持最廣泛部署的協議(SOAP,Hessian,Burlap,RMI等)。如果您使用非Java代碼進行調用,Hessian支持多種其他語言,已知它比SOAP更高效,比CORBA更容易。

0

你想要的是Java本地接口(JNI),儘管它可能出現的困難。沒有其他同等技術可以很容易實現。

至於在前面的答案的評論提到的,JNI是用於從Java調用本機代碼優化,但它也可以用於一點點的工作相反。在您的本地代碼中,您需要實現JNI入口點 - 類似於SetMapPointer() - 然後在構建Map之後從Java代碼中調用該函數。 SetMapPointer()的實現應該將Java對象指針保存在某個可訪問位置,然後本地代碼可以根據需要在其上調用Java方法。

你需要確保這種情況發生在正確的順序(即本地代碼不會嘗試訪問地圖,它已經建成並傳遞給本機代碼之前),但是這不應該是一個特別難題。

0

另一種方法來考慮,如果其他進程將是在同一臺機器上,並且操作系統是POSIX兼容的(而不是Windows)的命名管道。

當Java應用程序正在從管道中讀取數據時,外部進程將字符串或其他一致同意的字節編碼寫入命名管道,解析傳入操作並針對對象執行它們。

這是一個你想用套接字連接,只是代替一個SocketInputStream你會從附加到命名管道一個FileInputStream來讀的同樣的策略。

0

CORBA的替代品是ICE,除非許可證是問題(它是GPL,但您也可以購買商業許可證)。

它擁有幾乎所有的CORBA,但ZeroC,供應商的利益,許多不同的語言提供了綁定。 CORBA供應商往往只提供一種或兩種語言綁定,然後開始發現兼容性問題。

的文檔也很出色。我不會說這是特別容易拿起,但可能比CORBA更容易。

否則,另一種選擇,我不認爲已經提到是由思科,現在捐贈給Apache的開發出新的中間件/ RPC框架,稱爲Etch。儘管如此,它還是很新的,而且文檔很少。

0

BeanShell的是殼狀Java解釋器,可以通過網絡套接字被暴露。基本上你從Java這樣做:

i = new bsh.Interpreter(); 
i.set("myapp", this); // Provide a reference to your app 
i.eval("server(7000)"); 

,然後你從別的地方做:

telnet localhost 7001 
myapp.someMethod(); 

這個小工具更容易做遠程Java調用JNI比或RMI曾經擁有。

更多,開始在:http://www.beanshell.org/manual/remotemode.html