简单来说,Java 25(JDK 25)本身没有内置功能让你“直接”调用 Python 代码。JDK 25 是 Java 平台的最新 LTS(长期支持)版本,于 2025 年 9 月 16 日发布,主要聚焦于性能优化、语法简化(如紧凑源文件和模块导入)和工具增强(如 JFR 的 CPU 时间剖析),但没有引入任何针对 Python 的原生集成或 JEP(JDK Enhancement Proposal)。这意味着,你不能像调用 Java 方法那样无缝、无需额外依赖地执行 Python 脚本或导入 Python 模块。
不过,别失望!Java 和 Python 的互操作(interoperability)已经很成熟,通过第三方库或工具,你可以轻松实现“嵌入式”调用。Java 25 的向后兼容性确保这些工具在新版本上运行无压力。下面我一步步解释为什么没有直接支持、怎么实现调用,以及实际案例。目标是让你看完就能上手。
为什么 Java 25 没有“直接”支持 Python?
- 历史背景:Java 的 Scripting API(JSR-223,自 Java 6 起)允许通过引擎运行脚本语言,但 Python 支持依赖外部实现:Jython:这是 Java 平台的 Python 实现(Python 2.7 兼容),能直接在 JVM 上运行 Python 代码,像 Java 模块一样导入。但它不支持 Python 3.x 的现代特性(如 f-strings、async/await),且开发停滞(最后大更新在 2015 年左右)。在 Java 25 上,Jython 还能用,但不推荐用于新项目。没有新 JEP:JDK 25 的 18 个 JEP(如 JEP 511:紧凑源文件、JEP 519:紧凑对象头)都聚焦在 Java 生态内优化。没有涉及 Python 或其他语言的“桥接”。OpenJDK 官网和 InfoWorld 的发布笔记确认了这一点。
- 设计哲学:Java 强调“一次编写,到处运行”的纯 JVM 环境,直接嵌入 CPython(标准 Python 解释器)会引入复杂性(如线程安全、内存管理),Oracle 更倾向于让社区通过 JNI(Java Native Interface)或外部工具处理。
结果:如果你想“直接调用”,得靠桥接库。这些库在 Java 25 上无缝工作,由于 JDK 25 兼容旧版 API。
如何在 Java 25 中调用 Python?推荐方案
最实用的方式是使用 JEP(Java Embedded Python) 库。它通过 JNI 将 CPython 嵌入 JVM,让你从 Java 代码中执行 Python 脚本、调用函数,甚至访问 Python 库(如 NumPy、Pandas)。JEP 支持 Python 3.8+,性能高(接近原生 Python),跨平台(Windows/Linux/macOS)。
步骤 1:安装和配置
- 前提:安装 JDK 25(从 Oracle 或 Adoptium 下载)和 Python 3.x(确保 pip 可用)。
- 安装 JEP:
- pip install jep
- 这会编译 JEP,需要 JDK 和 Python 已安装。构建后,JEP 会生成 JAR 文件(jep-x.x.x.jar),放到你的项目 classpath 中。
- Maven/Gradle 集成(可选,但推荐): 在 pom.xml 添加:
<dependency>
<groupId>org.scijava</groupId>
<artifactId>jep</artifactId>
<version>4.2.0</version> <!-- 最新版,支持 Java 25 -->
</dependency>
- 注意:JEP 需要本地编译,所以 pip 安装后,手动将生成的 .so/.dll 和 JAR 复制到项目。
步骤 2:简单示例代码
假设你有个 Python 脚本 hello.py:
def greet(name):
return f"Hello, {name} from Python!"
print(greet("World"))
在 Java 25 中调用它(使用 try-with-resources 确保资源释放):
import jep.Interpreter;
import jep.JepException;
public class PythonCaller {
public static void main(String[] args) {
try (Interpreter interp = new Interpreter()) {
// 加载 Python 脚本
interp.exec("import hello"); // 假设 hello.py 在 Python path 中
// 调用 Python 函数,并传递参数
interp.set("name", "Grok"); // 从 Java 传字符串到 Python
interp.exec("result = hello.greet(name)"); // 执行函数
// 获取 Python 返回值到 Java
String result = (String) interp.getValue("result");
System.out.println(result); // 输出: Hello, Grok from Python!
} catch (JepException e) {
e.printStackTrace();
}
}
}
- 运行:编译 Java(javac PythonCaller.java),然后 java -Djava.library.path=/path/to/jep/lib PythonCaller(指定 JNI 库路径)。
- 输出:直接看到 Python 的执行结果。整个过程像调用 Java 方法,但底层是 Python 解释器。
高级用法:处理复杂数据和库
- 调用 NumPy(科学计算):
interp.exec("import numpy as np");
interp.set("data", new double[]{1, 2, 3});
interp.exec("mean_val = np.mean(data)");
double mean = interp.getValue("mean_val", Double.class); // 类型安全获取
System.out.println("Mean: " + mean); // 2.0
- 这让 Java 能用 Python 的数据科学库,而无需重写。
- 线程注意:JEP 要求同一个线程创建和使用 Interpreter(Python GIL 限制)。多线程用线程池管理。
- 性能:基准测试显示,JEP 的调用开销 <1ms,适合生产环境(如 ML 模型推理)。
其他备选方案
如果 JEP 不合适,这里有梯队: 1. ProcessBuilder(简单但低效):用 Java 启动 Python 进程。 java ProcessBuilder pb = new ProcessBuilder(“python”, “script.py”, “arg1”); Process p = pb.start(); // 读输出流 优点:零依赖。缺点:进程开销大,不适合高频调用。
- Py4J 或 JPype:反向桥接(从 Python 调 Java,或双向)。适合 Python 主导的项目。
- GraalVM 25:Oracle 的多语言 VM(基于 JDK 25),内置 GraalPy(Python 运行时)。你能用 Context API 直接 eval Python 代码:
import org.graalvm.polyglot.Context;
Context context = Context.newBuilder("python").allowAllAccess(true).build();
context.eval("python", "print('Hello from GraalPy!')");
- 优点:零 JNI,开销低,支持 Python 3.11+。缺点:需下载 GraalVM(~300MB)。
- Jython(遗留):如果你的 Python 是 2.7 代码,直接 ScriptEngine:
ScriptEngine engine = new ScriptEngineManager().getEngineByName("python");
engine.eval("print('Jython works!')");
- 但别用于新项目。
真实场景:为什么需要这个?
- 数据科学:Java 后端用 JEP 调用 Python 的 Scikit-learn 模型预测用户行为。
- AI 集成:如 Netflix,用类似桥接运行 Python ML 管道。
- Reddit 讨论:开发者反馈,JEP 是“最佳平衡”——稳定、快,且在 Java 25 上无问题。
潜在坑和提议
- 兼容:确保 Python 和 JDK 版本匹配(JEP 支持 JDK 8-25)。
- 错误处理:JepException 常因路径或 GIL 引起——用日志调试。
- 未来:JDK 26+ 可能加多语言支持(受 GraalVM 影响),但短期无 Python JEP。
- 资源:查 JEP GitHub(ninia/jep)或 Baeldung 教程。
总之,Java 25 没“魔法”直接调用 Python,但用 JEP 或 GraalVM,你能实现无缝集成。试试上面的代码,5 分钟上手!

