我们在这种形式的代码中占有一席之地:
void processParam(Object param)
{
wrapperForComplexNativeObject result = jniCallWhichMayCrash(param);
processResult(result);
}
processParam - 使用许多不同参数调用的方法。
jniCallWhichMayCrash - 一种本机方法,旨在对其参数进行一些复杂处理并创建一些复杂对象。在某些情况下它可能会崩溃。
wrapperForComplexNativeObject - SWIG生成的包装类型
processResult - 一个用纯Java编写的方法,它通过创建几种对象来处理它的参数(通过类型我不是类,有些像层次结构): 1 - 一些非唯一对象相互引用(来自同一层次结构),这些对象可以具有使用不同参数值的processParam()方法调用创建的重复项。由于保留所有重复数据的成本很高,因此需要对其进行缓存 2 - 一些相互引用的独特对象(来自同一层次结构)和一些第一类对象。
对某些集合中的每个参数执行processParam后,将同时处理processResult中创建的数据。问题是事实上jniCallWhichMayCrash方法可能会崩溃整个JVM,这将是非常糟糕的。崩溃的原因可能是一个参数值而不是另一个参数值。我们已经决定最好忽略JVM内部的崩溃,并在发生此类崩溃时跳过一些数据块。为了做到这一点,我们应该在单独的进程中运行processParam函数并以某种方式将结果传递给主进程(如何?这是一个问题),如果发生任何崩溃,我们只会丢失一些数据(没关系),而不会丢失其他所有数据。所以现在主要问题是在不同进程之间实现传输。我有哪些选择?我可以考虑通过流进行二进制数据的序列化和传输,但是由于对象的复杂性,序列化可能不是很快。也许我有其他一些实现这个的选择?
答案 0 :(得分:1)
让我们假设这些进程在同一台机器上。您的选择包括:
使用Process.exec()为每个请求启动一个新进程,将参数对象作为命令行参数传递,或者通过进程标准输入传递,并从thr进程标准输出中读取结果。该过程在完成单个请求后退出。
使用Process.exec()启动长时间运行的进程,使用Processes标准输入/输出发送请求和回复。流程实例处理多个请求。
使用“命名管道”将请求/回复发送到现有的本地(或可能是远程)进程。
使用原始TCP / IP套接字或Unix域套接字向现有本地(或可能是远程)进程发送请求/回复。
对于上述每一项,您需要设计自己的请求格式,并在双方处理参数/结果编码和解码。
将流程实现为Web服务,并使用JSON或XML(或其他)对参数和结果进行编码。根据您选择的编码方案,将有现有的库处理编码/解码和(可能)映射到Java类型。
SOAP / WSDL - 通常,您可以在更高的抽象级别设计应用程序协议,框架库负责编码/解码,调度请求等。
CORBA或类似ICE的等价物。这些选项类似于SOAP / WSDL,但使用更有效的线表示等
消息排队系统,如MQ系列。
请注意,最后四个通常用于客户端和服务器位于不同计算机上的系统中,但是当客户端和服务器位于同一位置时,它们也能正常工作(并且可能更快)。
我或许应该补充说,另一种方法是摆脱有问题的JNI代码。要么用纯Java代码替换它,要么在没有Java包装的情况下将其作为外部命令或服务运行。
答案 1 :(得分:0)
你有没有使用网络启发的方法?在您的情况下,通常,网络服务可以/将成为其多样性的解决方案:
答案 2 :(得分:0)
如果您可以隔离流程的职责,即P1是数据生产者而P2是消费者,那么最强大的答案是使用文件来传达您的数据。在serailization / deserialization中涉及开销(读取CPU周期),但是您的进程不会崩溃,并且调试/同步非常容易。