文章目录
- Jython 是将 Python 实现为 Java 字节码的解释器,允许 Python 代码直接调用 Java 类库。 适用场景: 已有 Java 系统需要嵌入 Python 脚本功能 希望复用 Java 生态中的成熟库
- # 安装:pip install jython from java.util import ArrayList # 创建 Java ArrayList java_list = ArrayList() java_list.add(“Java元素”) java_list.add(123) # 调用 Java 方法 print(java_list.size()) # 输出: 2 # 继承 Java 类 from javax.swing import JFrame class MyFrame(JFrame): def __init__(self): self.setTitle(“Jython 示例”) self.setSize(300, 200) self.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE) frame = MyFrame() frame.setVisible(True) 限制: 仅支持 Python 2.7 语法 无法使用基于 C 的 Python 扩展(如 NumPy)
- JPype 通过 JNI 桥接技术,让 Python 代码可以创建 JVM 并调用 Java 类。 适用场景: Python 主导的项目需要特定 Java 库功能 需要完整的 Java 8+ 支持
- # 安装:pip install JPype1 import jpype # 启动 JVM(指定 jvm.dll 路径) jpype.startJVM(jpype.getDefaultJVMPath(), “-ea”, “-Djava.class.path=/path/to/your.jar”) # 导入 Java 类 ArrayList = jpype.JClass(“java.util.ArrayList”) System = jpype.JClass(“java.lang.System”) # 使用 Java 对象 java_list = ArrayList() java_list.add(“测试数据”) System.out.println(java_list) # 输出: [测试数据] # 调用静态方法 Collections = jpype.JClass(“java.util.Collections”) Collections.sort(java_list) # 关闭 JVM(程序结束前调用) jpype.shutdownJVM() 性能提示: 避免频繁启动/关闭 JVM 使用 @JImplements 实现 Java 接口
- Py4J 在 Java 进程中运行网关服务器,Python 通过 socket 与之通信。 优势: 支持回调(Java 调用 Python) 独立的进程空间更稳定
- Java 服务端: // 添加 Maven 依赖 // <dependency> // <groupId>net.sf.py4j</groupId> // <artifactId>py4j</artifactId> // <version>0.10.9.5</version> // </dependency> import py4j.GatewayServer; public class MathService { public int add(int a, int b) { return a + b; } public static void main(String[] args) { GatewayServer server = new GatewayServer(new MathService()); server.start(); System.out.println(“Gateway Server Started”); } } Python 客户端: # 安装:pip install py4j from py4j.java_gateway import JavaGateway gateway = JavaGateway() # 连接默认网关 math_service = gateway.entry_point # 获取Java对象 result = math_service.add(10, 20) print(result) # 输出: 30 # 回调示例 class PythonListener: def __init__(self, gateway): self.gateway = gateway def notify(self, message): print(“Java回调:”, message) return “Python已处理” listener = PythonListener(gateway) gateway.jvm.System.setProperty(“python.listener”, gateway.jvm.py4j.GatewayServer.DEFAULT_PYTHON_PROXY_PORT)
- 基于 Protocol Buffers 的 IDL 支持流式通信 语言中立
- 步骤1:定义 proto 文件 syntax = “proto3”; service DataProcessor { rpc Process (DataRequest) returns (DataResponse); } message DataRequest { string content = 1; int32 priority = 2; } message DataResponse { bool success = 1; string result = 2; } 步骤2:生成代码 # Python 端 python -m grpc_tools.protoc -I. –python_out=. –grpc_python_out=. data.proto # Java 端(Maven配置) <build> <extensions> <extension> <groupId>kr.motd.maven</groupId> <artifactId>os-maven-plugin</artifactId> <version>1.6.2</version> </extension> </extensions> <plugins> <plugin> <groupId>org.xolstice.maven.plugins</groupId> <artifactId>protobuf-maven-plugin</artifactId> <version>0.6.1</version> <configuration> <protocArtifact>com.google.protobuf:protoc:3.19.2:exe:${os.detected.classifier}</protocArtifact> <pluginId>grpc-java</pluginId> <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.47.0:exe:${os.detected.classifier}</pluginArtifact> </configuration> <executions> <execution> <goals> <goal>compile</goal> <goal>compile-custom</goal> </goals> </execution> </executions> </plugin> </plugins> </build> 步骤3:Java 服务端实现 public class DataServiceImpl extends DataProcessorGrpc.DataProcessorImplBase { @Override public void process(DataRequest request, StreamObserver<DataResponse> responseObserver) { System.out.println(“收到请求: ” + request.getContent()); DataResponse response = DataResponse.newBuilder() .setSuccess(true) .setResult(“Processed: ” + request.getContent().toUpperCase()) .build(); responseObserver.onNext(response); responseObserver.onCompleted(); } } // 启动服务器 Server server = ServerBuilder.forPort(50051) .addService(new DataServiceImpl()) .build() .start(); 步骤4:Python 客户端调用 import grpc import data_pb2 import data_pb2_grpc channel = grpc.insecure_channel(‘localhost:50051’) stub = data_pb2_grpc.DataProcessorStub(channel) response = stub.Process(data_pb2.DataRequest( content=”hello grpc”, priority=1 )) print(response.result) # 输出: Processed: HELLO GRPC
- 图表 代码
- 步骤1:Java 端准备 native 方法 public class NativeBridge { static { System.loadLibrary(“nativebridge”); } public native String processData(String input); } 步骤2:生成 C 头文件 javac -h . NativeBridge.java 步骤3:实现 C 层逻辑 #include <jni.h> #include “NativeBridge.h” #include <Python.h> JNIEXPORT jstring JNICALL Java_NativeBridge_processData( JNIEnv *env, jobject obj, jstring input) { const char *str = (*env)->GetStringUTFChars(env, input, 0); // 初始化Python解释器 Py_Initialize(); PyObject *pModule = PyImport_ImportModule(“data_processor”); PyObject *pFunc = PyObject_GetAttrString(pModule, “process”); // 调用Python函数 PyObject *pArgs = PyTuple_Pack(1, PyUnicode_FromString(str)); PyObject *pResult = PyObject_CallObject(pFunc, pArgs); const char *result = PyUnicode_AsUTF8(pResult); // 清理资源 Py_DECREF(pArgs); Py_DECREF(pResult);share.aalatni.cn Py_Finalize(); return (*env)->NewStringUTF(env, result); } 步骤4:编译为动态库 # Linux示例 gcc -shared -fPIC -I${JAVA_HOME}/include -I${JAVA_HOME}/include/linux -I/usr/include/python3.8 -o libnativebridge.so NativeBridge.c -lpython3.8
- 对象池模式:重用Java对象避免重复创建 # JPype对象池示例 class ObjectPool:aiqiyi.aalatni.cn def __init__(self, j_class, size=10): self.pool = [j_class() for _ in range(size)] def acquire(self): return self.pool.pop() if self.pool else None def release(self, obj): self.pool.append(obj) 批量操作:减少跨语言调用次数 // Java端提供批量接口 public List<String> batchProcess(List<String> inputs) { return inputs.stream().map(this::process).collect(Collectors.toList()); }
- gRPC:启用TLS加密 # Python客户端 creds = grpc.ssl_channel_credentials()tenxun.aalatni.cn channel = grpc.secure_channel(‘localhost:50051’, creds) Py4J:设置白名单 GatewayServer server = new GatewayServer( new MathService(), GatewayServer.DEFAULT_PORT, GatewayServer.DEFAULT_CONNECT_TIMEOUT, GatewayServer.DEFAULT_READ_TIMEOUT, new String[] {“192.168.1.*”} // IP白名单 );
目录
- 前言
- 一、Jython:在 JVM 中运行 Python
- 1.1 基本概念
- 1.2 实战示例
- 二、JPype:在 Python 中调用 Java
- 2.1 核心机制
- 2.2 完整流程示例
- 三、Py4J:双向网关模式
- 3.1 架构原理
- 3.2 双向调用示例
- 四、gRPC 跨语言通信
- 4.1 方案特点
- 4.2 实现步骤
- 五、JNI 原生扩展(高级方案)
- 5.1 架构设计
- 5.2 实现示例
- 方案对比与选型建议
- 常见问题解决方案
- 问题1:内存泄漏处理
- 问题2:数据类型转换异常
- 问题3:调试技巧
- 进阶主题
- 性能优化技巧
- 安全注意事项
- 结语
在企业级应用开发中,Python 和 Java 常常需要协同工作——Python 擅长数据科学和快速原型开发,Java 则在大型系统和高性能后端方面表现优异。本指南将全面介绍 Python 与 Java 互操作的 5 种主流方式,涵盖从简单调用到深度集成的各种场景。
Jython 是将 Python 实现为 Java 字节码的解释器,允许 Python 代码直接调用 Java 类库。
适用场景:
- 已有 Java 系统需要嵌入 Python 脚本功能
- 希望复用 Java 生态中的成熟库
# 安装:pip install jython
from java.util import ArrayList
# 创建 Java ArrayList
java_list = ArrayList()
java_list.add("Java元素")
java_list.add(123)
# 调用 Java 方法
print(java_list.size()) # 输出: 2
# 继承 Java 类
from javax.swing import JFrame
class MyFrame(JFrame):
def __init__(self):
self.setTitle("Jython 示例")
self.setSize(300, 200)
self.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
frame = MyFrame()
frame.setVisible(True)
限制:
- 仅支持 Python 2.7 语法
- 无法使用基于 C 的 Python 扩展(如 NumPy)
JPype 通过 JNI 桥接技术,让 Python 代码可以创建 JVM 并调用 Java 类。
适用场景:
- Python 主导的项目需要特定 Java 库功能
- 需要完整的 Java 8+ 支持
# 安装:pip install JPype1
import jpype
# 启动 JVM(指定 jvm.dll 路径)
jpype.startJVM(jpype.getDefaultJVMPath(),
"-ea",
"-Djava.class.path=/path/to/your.jar")
# 导入 Java 类
ArrayList = jpype.JClass("java.util.ArrayList")
System = jpype.JClass("java.lang.System")
# 使用 Java 对象
java_list = ArrayList()
java_list.add("测试数据")
System.out.println(java_list) # 输出: [测试数据]
# 调用静态方法
Collections = jpype.JClass("java.util.Collections")
Collections.sort(java_list)
# 关闭 JVM(程序结束前调用)
jpype.shutdownJVM()
性能提示:
- 避免频繁启动/关闭 JVM
- 使用
@JImplements实现 Java 接口
Py4J 在 Java 进程中运行网关服务器,Python 通过 socket 与之通信。
优势:
- 支持回调(Java 调用 Python)
- 独立的进程空间更稳定
Java 服务端:
// 添加 Maven 依赖
// <dependency>
// <groupId>net.sf.py4j</groupId>
// <artifactId>py4j</artifactId>
// <version>0.10.9.5</version>
// </dependency>
import py4j.GatewayServer;
public class MathService {
public int add(int a, int b) {
return a + b;
}
public static void main(String[] args) {
GatewayServer server = new GatewayServer(new MathService());
server.start();
System.out.println("Gateway Server Started");
}
}
Python 客户端:
# 安装:pip install py4j
from py4j.java_gateway import JavaGateway
gateway = JavaGateway() # 连接默认网关
math_service = gateway.entry_point # 获取Java对象
result = math_service.add(10, 20)
print(result) # 输出: 30
# 回调示例
class PythonListener:
def __init__(self, gateway):
self.gateway = gateway
def notify(self, message):
print("Java回调:", message)
return "Python已处理"
listener = PythonListener(gateway)
gateway.jvm.System.setProperty("python.listener",
gateway.jvm.py4j.GatewayServer.DEFAULT_PYTHON_PROXY_PORT)
- 基于 Protocol Buffers 的 IDL
- 支持流式通信
- 语言中立
步骤1:定义 proto 文件
syntax = "proto3";
service DataProcessor {
rpc Process (DataRequest) returns (DataResponse);
}
message DataRequest {
string content = 1;
int32 priority = 2;
}
message DataResponse {
bool success = 1;
string result = 2;
}
步骤2:生成代码
# Python 端
python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. data.proto
# Java 端(Maven配置)
<build>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.6.2</version>
</extension>
</extensions>
<plugins>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.6.1</version>
<configuration>
<protocArtifact>com.google.protobuf:protoc:3.19.2:exe:${os.detected.classifier}</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.47.0:exe:${os.detected.classifier}</pluginArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
步骤3:Java 服务端实现
public class DataServiceImpl extends DataProcessorGrpc.DataProcessorImplBase {
@Override
public void process(DataRequest request,
StreamObserver<DataResponse> responseObserver) {
System.out.println("收到请求: " + request.getContent());
DataResponse response = DataResponse.newBuilder()
.setSuccess(true)
.setResult("Processed: " + request.getContent().toUpperCase())
.build();
responseObserver.onNext(response);
responseObserver.onCompleted();
}
}
// 启动服务器
Server server = ServerBuilder.forPort(50051)
.addService(new DataServiceImpl())
.build()
.start();
步骤4:Python 客户端调用
import grpc
import data_pb2
import data_pb2_grpc
channel = grpc.insecure_channel('localhost:50051')
stub = data_pb2_grpc.DataProcessorStub(channel)
response = stub.Process(data_pb2.DataRequest(
content="hello grpc",
priority=1
))
print(response.result) # 输出: Processed: HELLO GRPC
图表
代码
步骤1:Java 端准备 native 方法
public class NativeBridge {
static {
System.loadLibrary("nativebridge");
}
public native String processData(String input);
}
步骤2:生成 C 头文件
javac -h . NativeBridge.java
步骤3:实现 C 层逻辑
#include <jni.h>
#include "NativeBridge.h"
#include <Python.h>
JNIEXPORT jstring JNICALL Java_NativeBridge_processData(
JNIEnv *env, jobject obj, jstring input) {
const char *str = (*env)->GetStringUTFChars(env, input, 0);
// 初始化Python解释器
Py_Initialize();
PyObject *pModule = PyImport_ImportModule("data_processor");
PyObject *pFunc = PyObject_GetAttrString(pModule, "process");
// 调用Python函数
PyObject *pArgs = PyTuple_Pack(1, PyUnicode_FromString(str));
PyObject *pResult = PyObject_CallObject(pFunc, pArgs);
const char *result = PyUnicode_AsUTF8(pResult);
// 清理资源
Py_DECREF(pArgs);
Py_DECREF(pResult);share.aalatni.cn
Py_Finalize();
return (*env)->NewStringUTF(env, result);
}
步骤4:编译为动态库
# Linux示例
gcc -shared -fPIC -I${JAVA_HOME}/include
-I${JAVA_HOME}/include/linux
-I/usr/include/python3.8
-o libnativebridge.so NativeBridge.c
-lpython3.8
| 方案 | 适用场景 | 性能 | 复杂度 | 双向通信 |
|---|---|---|---|---|
| Jython | 嵌入Python到Java应用 | 中 | 低 | 否 |
| JPype | Python调用Java库 | 高 | 中 | 有限 |
| Py4J | 复杂双向交互 | 中 | 中 | 是 |
| gRPC | 跨网络服务调用 | 高 | 高 | 是 |
| JNI | 极致性能需求 | 最高 | 最高 | 是 |
决策树:
是否需要双向调用?
是 → Py4J 或 gRPC
否 → 进入2
是否主要从Python调用Java?
是 → JPype
否 → 进入3
是否需要嵌入Python到Java?
是 → Jython
否 → 考虑其他方案
- JPype:确保及时调用
jpype.shutdownJVM()
- Py4J:使用
gateway.close() 释放资源
- gRPC:实现
__del__ 方法关闭channel
jpype.shutdownJVM()gateway.close() 释放资源__del__ 方法关闭channel
- 数字类型:Java的
long 对应 Python 的 int
- 容器类型:使用
jpype.JArray 转换数组
- 日期类型:统一转为时间戳传输
long 对应 Python 的 intjpype.JArray 转换数组
开启JPype调试模式:
jpype.startJVM(..., "-Djpype.debug=True")
Py4J日志配置:
System.setProperty("py4j.logging", "py4j.logging.ConsoleLogger")
对象池模式:重用Java对象避免重复创建
# JPype对象池示例
class ObjectPool:aiqiyi.aalatni.cn
def __init__(self, j_class, size=10):
self.pool = [j_class() for _ in range(size)]
def acquire(self):
return self.pool.pop() if self.pool else None
def release(self, obj):
self.pool.append(obj)
批量操作:减少跨语言调用次数
// Java端提供批量接口
public List<String> batchProcess(List<String> inputs) {
return inputs.stream().map(this::process).collect(Collectors.toList());
}
gRPC:启用TLS加密
# Python客户端
creds = grpc.ssl_channel_credentials()tenxun.aalatni.cn
channel = grpc.secure_channel('localhost:50051', creds)
Py4J:设置白名单
GatewayServer server = new GatewayServer(
new MathService(),
GatewayServer.DEFAULT_PORT,
GatewayServer.DEFAULT_CONNECT_TIMEOUT,
GatewayServer.DEFAULT_READ_TIMEOUT,
new String[] {"192.168.1.*"} // IP白名单
);
Python 与 Java 的互操作虽然存在挑战,但通过选择合适的工具和模式,完全可以构建出高效稳定的跨语言系统。建议:xnj.gxglhxdec.com
- 从简单方案开始,逐步演进
- 做好接口抽象,降低耦合
- 建立完善的跨语言测试体系
- 监控性能关键指标
随着 GraalVM 等新技术的发展,未来两种语言的互操作将更加无缝。但当前这些成熟方案,已经足以支撑大多数企业级应用的需求。
以上就是Python与Java互操作的五种主流方式的详细内容,更多关于Python与Java互操作方式的资料请关注风君子博客其它相关文章!
您可能感兴趣的文章:
- Python与Java进行相互操作与调用的解决方案大全
- Python与Java进行交互操作的方法与性能对比
- 深入解析如何通过Py4J实现Python与Java交互
- Python调用Java接口实现互相SM2加签验签