如果是单机的话, 确实可以使用 JNI.
不过如果是各个模块之间在不同的主机上的话, 那么就需要进行网络通信了.
下面我针对网络通信的方式来讲一下我的做法:
针对于同步调用模式
如果 Java 和 C++ 之间是相互调用关系的话, 例如 Java 调用 C++ 提供的服务, 那么一般可以看做是同步调用关系, 此时有如下几个方法:C++ 和 Java 之间使用 TCP 直接通信.
这个方法最直接也相对地不是很方便, 毕竟 Java 和 C++ 直接需要定义 TCP 通信协议, 无形中增加了负担, 如果不是必要的话, 最好不要使用这样的方法吧.
基于 HTTP 的 API 接口.
这个方法比直接使用 TCP 方式好很多. Java 可以使用 SpringMVC 或者 Netty 之类的框架或库提供 HTTP RESTful 接口, C++ 可以通过 HTTP 请求调用这些 api, 而且相对于直接写 TCP 交互来说, 编写调试过程都相对简单一些.
基于 Thrift 的 RPC 调用.
我推荐这个方法. 首先 Java 和 C++ 都有现成的 Thrift 库, 直接可以使用; 第二, 使用 Thrift 的话, 就不需要关系交互协议的问题了, Thrift 已经封装好了, 你直接写好各个服务调用接口即可; 第三, Thrift 实现了序列化功能, Java 和 C++ 之间可以直接交互结构化的数据, 不需要再次解析了; 而且使用了 Thrift 后, 还可以方便地将服务提供给更多的语言模块使用, 例如 Python, PHP 等.
针对异步交互模式
如果各个模块之间的交互不需要同步的话, 那么可以考虑使用队列的方式.
我原来做过一个项目, 也有类似的需求, 不过我的各个模块之间不需要强的同步性, 因此我选择了 ActiveMQ 和 Protobuf 的组合.
Protobuf 的作用是提供 Java 和 C++ 之间的数据对象的序列化, 方便它们之间的数据交互, 而 ActiveMQ 就是一个 Java 编写的著名的开源消息队列实现.
整个方案也不复杂, 即 Java 通过 Protobuf 将结构化的数据 序列化为二进制数据, 然后放到 ActiveMQ 消息队列中. C++ 模块呢, 就监听 ActiveMQ 队列中的消息, 当获取到一个消息时, 就使用 Protobuf 反序列化出来, 进而获取到 C++ 可以处理的数据.