如何从JVM外部调用对象中的方法?

时间:2008-12-15 15:57:11

标签: java jvm communication

我有一个非常简单的Java类,它使用输入验证有效地修饰了Map,使用了明显的void set()和String get()方法。

我希望能够有效地调用这些方法并处理来自JVM外部的返回值和异常,但仍然在同一台机器上更新:我想到的调用者不是另一个JVM;谢谢@Dave Ray

我的实施注意事项是典型的

  • 性能
  • 易于实施和维护(简单?)
  • 可靠性
  • 灵活性(即我可以从远程机器呼叫等)

有'正确的方法吗?'如果没有,我的选择是什么,每个人的利弊是什么?

(人们已经完成并且可以提供真实反馈的东西会很棒!)

11 个答案:

答案 0 :(得分:3)

您是从另一个基于JVM的系统调用,还是客户端语言是任意的?如果您从另一个JVM调用,最简单的方法之一是通过JMX将对象公开为MBean。规范的Hello World MBean显示为here。专业人士是:

  • 非常容易实施
  • 从其他JVM轻松调用
  • 支持远程计算机
  • jconsole允许您在不编写客户端的情况下手动测试MBean

缺点:

  • 客户端必须在JVM上(我认为)
  • 不适合更复杂的数据结构和交互。例如,我不认为MBean可以返回对另一个MBean的引用。它将序列化并返回一份副本。

答案 1 :(得分:3)

确定。这是另一个尝试,因为我知道客户端不是Java。由于您需要进程外访问以及可能的远程机器访问,因此我认为JNI不是您想要的,因为这是严格的进程(并且总是麻烦)。以下是其他一些选择:

原始套接字:只需在Java中设置一个侦听器套接字并接受连接。当您获得连接时,请阅读请求并发回响应。几乎每种语言都可以使用套接字,因此这是一个非常通用的解决方案。但是,您必须定义自己的编组方案,解析等。

XML-RPC :这些日子并不紧张,但它简单有效。大多数其他语言都有Java libraries和库。

CORBA :如上所述,CORBA是一个选项,但它非常复杂,专家越来越难以接受。

Web服务器:在您的应用中设置嵌入式Web服务器并处理请求。我听说过有关Jetty的好消息,或者您可以使用one provided with Java。我已成功地使用后者通过用Java编写的模拟将KML文件服务器连接到Google Earth。大多数其他语言都有用于发出HTTP请求的库。如何对数据(XML,文本等)进行编码取决于您。

Web服务:我认为这会更复杂,但您可以使用JAX-WS将对象公开为Web服务。 NetBeans有很好的工具来构建Web服务,但这可能有点过头了。

答案 2 :(得分:2)

由于您的呼叫者不是Java应用程序,并且您已经预见到网络呼叫者,RMI-IIOP (CORBA)可能是一种选择。虽然它绝对不容易实现,但它具有成为广泛认可的标准的优势。

答案 3 :(得分:2)

由于您的调用者不是基于JVM的,因此这是与JVM进行进程间通信的问题。我想到的选项是:

  1. 通过套接字进行通信:让您的JVM监听传入连接和呼叫者发送命令
  2. 使用共享文件进行通信(调用者写入文件,JVM轮询和更新)
  3. 使用JNI,在调用者进程内启动JVM,然后使用RMI / MBean与第一个(“服务器”)JVM进行通信。调用者可以使用JNI
  4. 访问结果

    选项3 IMO是执行此操作的最“Java”方式,并且是最复杂/容易出错的方式。 选项2很丑但很简单 选项1适度容易(java部分),否则确定。

答案 4 :(得分:1)

为了便于使用,我会使用Spring Remoting。如果您已经在项目中使用Spring,那就不用了。如果你不......那么你应该看看。

Spring提供了一个抽象,允许您轻松切换远程协议。它支持最广泛部署的协议(SOAP,Hessian,Burlap,RMI,......)。如果您使用非Java代码进行调用,Hessian支持许多其他语言,则称其比SOAP更有效,并且比CORBA更容易。

答案 5 :(得分:0)

JNI(Java Native Interface)允许从C或C ++访问java代码。

答案 6 :(得分:0)

我有一个Inno安装脚本(安装Java程序),它调用一些Java方法来执行某些操作或检查某些条件。
我(实际上是我的前任)只是在每次调用时实例化java.exe。显然,这是昂贵的,虽然在我的情况下并不重要(我认为Windows缓存开始了)。

另一种方法是使用一些语言间通信/消息传递,Java程序充当服务器。 Corba浮现在脑海中,因为它与语言无关。但也许有点沉重。你可以使用套接字。 RPC也是另一个流行语,但我在这个领域没有多少经验。

答案 7 :(得分:0)

你想要的是Java Native Interface(JNI),尽管它可能存在困难。没有其他同等技术可以轻松实施。

正如前面答案的评论中所提到的,JNI针对从Java调用本机代码进行了优化,但它也可以用于反向工作。在您的本机代码中,您需要实现JNI入口点 - 类似于SetMapPointer() - 然后在构建Map之后从Java代码调用该函数。 SetMapPointer()的实现应该保存Java对象指针在某处可访问,然后本机代码可以根据需要在其上调用Java方法。

您需要确保以正确的顺序发生这种情况(即本机代码在构建之前不会尝试访问Map并传递给本机代码),但这应该不是特别困难问题

答案 8 :(得分:0)

考虑另一个进程是否在同一台机器上并且操作系统符合POSIX(而不是Windows)的另一种选择是命名管道。

当Java应用程序从管道读取时,外部进程将操作(作为字符串或其他一致的字节编码)写入命名管道,解析传入操作并针对您的对象执行它们。

这与您用于套接字连接的策略相同,而不是您要从附加到命名管道的FileInputStream中读取的SocketInputStream。

答案 9 :(得分:0)

CORBA的替代方法是 ICE ,除非许可证有问题(它是GPL,但您也可以购买商业许可证)。

它具有CORBA的所有优点,但供应商ZeroC提供了许多不同语言的绑定。 CORBA供应商倾向于只提供一个或两个语言绑定,然后您开始发现兼容性问题。

文档也非常好。我不会说它特别容易拿起,但可能比CORBA更容易。

否则,我认为没有提到的另一个选项是思科开发的新中间件/ RPC框架,现在捐赠给Apache,名为 Etch 。它仍然很新,而且文档很少。

答案 10 :(得分:0)

Beanshell是一个类似shell的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();

这个小实用程序比JNI或RMI更容易进行远程java调用。

如需更多信息,请从:http://www.beanshell.org/manual/remotemode.html

开始