1. 概述

R 语言是统计分析领域的主流工具,拥有海量的统计函数和扩展包。在实际开发中,我们经常需要在 Java 应用中调用 R 的计算能力,实现“Java 调 R”的混合编程。

本文将系统介绍几种主流的 Java 调用 R 的集成方案,帮助你在不同场景下做出合适的技术选型。

2. R 脚本准备

我们先准备一个简单的 R 脚本,实现向量求均值的功能。创建文件 script.R

customMean <- function(vector) {
    mean(vector)
}

在 Java 中,我们通过一个工具方法读取该脚本内容:

String getMeanScriptContent() throws IOException, URISyntaxException {
    URI rScriptUri = RUtils.class.getClassLoader().getResource("script.R").toURI();
    Path inputScript = Paths.get(rScriptUri);
    return Files.lines(inputScript).collect(Collectors.joining());
}

后续所有方案都将基于这个脚本进行调用演示。

3. RCaller:本地进程调用

RCaller 是一种简单直接的集成方式,其原理是 启动一个独立的 R 进程,通过标准输入输出与 Java 通信。

引入依赖

RCaller 已发布到 Maven Central,可直接引入:

<dependency>
    <groupId>com.github.jbytecode</groupId>
    <artifactId>RCaller</artifactId>
    <version>3.0</version>
</dependency>

调用示例

public double mean(int[] values) throws IOException, URISyntaxException {
    String fileContent = RUtils.getMeanScriptContent();
    RCode code = RCode.create();
    code.addRCode(fileContent);
    code.addIntArray("input", values);
    code.addRCode("result <- customMean(input)");
    RCaller caller = RCaller.create(code, RCallerOptions.create());
    caller.runAndReturnResult("result");
    return caller.getParser().getAsDoubleArray("result")[0];
}

关键对象说明

  • RCode:封装 R 脚本、变量和执行语句
  • RCaller:执行脚本并获取结果

注意事项 ⚠️

  • 不适合高频小计算:每次调用都要启动 R 进程,开销大
  • 强依赖本地 R 环境:目标机器必须安装 R
  • ✅ 适合离线批处理、计算密集型任务

4. Renjin:JVM 内嵌解释器

Renjin 是一个基于 JVM 的 R 语言解释器,无需外部 R 环境,运行在 JVM 内部。

配置仓库与依赖

Renjin 未发布到 Maven Central,需添加 Mulesoft 仓库:

<repositories>
    <repository>
        <id>mulesoft</id>
        <name>Mulesoft Repository</name>
        <url>https://repository.mulesoft.org/nexus/content/repositories/public/</url>
    </repository>
</repositories>

<dependencies>
    <dependency>
        <groupId>org.renjin</groupId>
        <artifactId>renjin-script-engine</artifactId>
        <version>RELEASE</version>
    </dependency>
</dependencies>

调用示例

public double mean(int[] values) throws IOException, URISyntaxException, ScriptException {
    RenjinScriptEngine engine = new RenjinScriptEngine();
    String meanScriptContent = RUtils.getMeanScriptContent();
    engine.put("input", values);
    engine.eval(meanScriptContent);
    DoubleArrayVector result = (DoubleArrayVector) engine.eval("customMean(input)");
    return result.asReal();
}

优势与限制

  • 无需安装 R:纯 Java 依赖,部署简单
  • 启动快:无进程开销,适合高频调用
  • ⚠️ 兼容性问题:并非 100% 兼容 GNU R,部分包可能无法使用
  • ✅ 提供企业支持,适合生产环境

5. Rserve:远程服务调用

当多个客户端需要共享 R 计算资源时,Rserve 是理想选择。它通过 TCP 提供 R 的远程调用能力,实现 R 服务化

启动 Rserve 服务

在 R 环境中安装并启动服务:

> install.packages("Rserve")
> library("Rserve")
> Rserve(args = "--RS-source ~/script.R")
Starting Rserve...

默认监听 127.0.0.1:6311

引入客户端依赖

<dependency>
    <groupId>org.rosuda.REngine</groupId>
    <artifactId>Rserve</artifactId>
    <version>1.8.1</version>
</dependency>

Java 调用代码

public double mean(int[] values) throws REngineException, REXPMismatchException {
    RConnection c = new RConnection();
    c.assign("input", values);
    return c.eval("customMean(input)").asDouble();
}

适用场景

  • ✅ 多 Java 应用共享 R 计算资源
  • ✅ R 脚本需要长期驻留内存(避免重复加载)
  • ✅ 集中管理 R 环境和依赖包

6. FastR:GraalVM 原生集成

FastR 是 Oracle 基于 GraalVM 实现的高性能 R 运行时,支持与 Java 深度互操作。

环境准备

  1. 安装 GraalVM
  2. 使用 gu 安装 FastR:
$ bin/gu install R
$ languages/R/bin/configure_fastr

⚠️ 当前仅支持 Linux 和 Darwin x64 系统。

Java 调用代码

public double mean(int[] values) {
    Context polyglot = Context.newBuilder().allowAllAccess(true).build();
    String meanScriptContent = RUtils.getMeanScriptContent(); 
    polyglot.eval("R", meanScriptContent);
    Value rBindings = polyglot.getBindings("R");
    Value rInput = rBindings.getMember("c").execute(values);
    return rBindings.getMember("customMean").execute(rInput).asDouble();
}

特点分析

  • 性能极佳:GraalVM JIT 优化,接近原生速度
  • 无缝互操作:Java 与 R 对象可直接传递
  • 强绑定 GraalVM:无法在普通 JVM 上运行
  • 平台限制:不支持 Windows 等系统

7. 总结与选型建议

方案 是否需 R 环境 部署复杂度 性能 适用场景
RCaller 低(启动慢) 离线批处理
Renjin 高频调用,轻量级计算
Rserve ✅(服务端) 多客户端共享,服务化部署
FastR ❌(GraalVM) 高性能要求,GraalVM 生态

简单粗暴的选型建议

  • 想快速验证?用 RCaller
  • 想省运维?用 Renjin
  • 想搞微服务?上 Rserve
  • 不差钱且用 GraalVM?闭眼选 FastR

所有示例代码已托管至 GitHub:https://github.com/baeldung/tutorials/tree/master/libraries


原始标题:Java-R Integration | Baeldung