python调用.jar文件 —— 安装openjdk,而无需配置JAVA环境
文章目录
一、什么是 .jar 文件 ?
.jar(Java ARchive,Java归档)文件
:一种用于分发 Java 类文件(.class 文件)、Java 应用程序和相关资源(如:图像、音频文件、配置文件等)的文件格式。
.jar 文件的主要特点
压缩格式:使用 ZIP 格式进行压缩,能够减少文件大小,并将多个文件打包成一个易于分发的单一文件。 清单文件:每个 .jar 文件包含一个名为 MANIFEST.MF
的清单文件,位于 META-INF 目录中。提供了关于 .jar 文件的元数据信息,如:版本信息、类路径、主类(入口点)等。主类(Main-Class):指定 .jar 文件的主类,即应用程序的入口点。 类路径(Class-Path):指定 .jar 文件依赖的其他 .jar 文件或目录的路径。它允许 .jar 文件引用外部库。 可执行 JAR 文件:如果 .jar 文件中包含一个 Main-Class 入口在 MANIFEST.MF 中定义,.jar 文件可以被直接执行。
.jar 文件的主要用途
分发 Java 应用程序:.jar 文件可以打包整个 Java 应用程序,包括编译后的类文件和所有必需的资源。 创建 Java 库:可以将 Java 类库打包到 .jar 文件中,供其他 Java 应用程序使用。 便捷的部署:.jar 文件使得分发和部署 Java 应用程序变得更加方便。 简化项目管理:使用 .jar 文件可以将多个类文件和资源组织在一起,简化项目的管理和配置。
1.1、.jar 文件结构
MyApp.jar
|
|-- META-INF/
| |-- MANIFEST.MF
| |-- other-metadata-file (可选的其他元数据文件,如签名文件)
|
|-- com/
| |-- example/
| |-- MyClass.class (主要的类文件)
| |-- AnotherClass.class (其他类文件)
| |
| |-- utils/
| |-- HelperClass.class (工具类文件)
|
|-- resources/ (资源文件,如配置文件、图像等)
| |-- config.properties
| |-- logo.png
|
|-- lib/ (可能的依赖库,包含其他 JAR 文件)
| |-- external-library-1.jar
| |-- external-library-2.jar
|
|-- doc/ (文档目录,包含项目文档)
| |-- README.md
| |-- LICENSE.txt
| |-- API_Documentation.html
1.2、.jar 清单文件(MANIFEST.MF)
Manifest-Version: 1.0 清单文件的版本号
Main-Class: com.example.MainClass 指定 JAR 文件的主类
Class-Path: lib/library1.jar lib/library2.jar 指定其他 JAR 文件的路径
Created-By: 1.6.0_45 (Sun Microsystems Inc.) 表示创建 JAR 文件所用的 Java 运行时环境(JRE)或 Java 开发工具包(JDK)的版本和供应商信息。
1.6.0_45 表示 Java 版本 6 更新 45。
Sun Microsystems Inc. 表示这个 JRE 或 JDK 是由 Sun Microsystems(现在是 Oracle 的一部分)开发的。
二、python 调用 .jar
在 python 中,调用 .jar 文件的方法主要有两种:
Py4J
:适合在 Python 中通过 TCP/IP 连接到 Java 程序。你需要编写一个 Java 程序来启动 GatewayServer 并暴露接口。Python 客户端通过 JavaGateway 连接到这个服务器。JPype
:直接在 Python 中调用 Java 类,不需要单独的 Java 程序。你可以启动 JVM,并通过 JPype 导入和使用 Java 类。只学习并打通了JPype,适用于我的需求。
2.1、使用 Py4J 库
Py4J 允许 Python 程序调用 Java 代码。它需要一个 Java 程序来启动一个 GatewayServer,然后 Python 客户端连接到这个服务器。
2.1.1、Py4J 环境配置 —— OpenJDK 开源免费库
(1)安装 Py4J 库: pip install py4j
(2)配置 Java 环境 方法一:在Windows系统中安装 JDK 工具 + 手动配置环境变量 JAVA_HOME 安装 JDK:从 Oracle 或 OpenJDK 网站下载并安装 JDK。 配置环境变量: (1)此电脑 – 鼠标右击 – 属性 – 高级系统设置 – 环境变量; (2)在系统变量中 – 新建 – 变量名(JAVA_HOME)
:变量值(C:\Program Files\Java\jdk-22)
(3)在系统变量中 – Path – 添加: (%JAVA_HOME%\bin;)
和(%JAVA_HOME%\jre\bin)
方法二:无需在系统中安装 JDK + 无需手动配置环境变量 JAVA_HOME 在 Python 中,安装 OpenJDK 开源免费库 :
conda install openjdk=11 -y
考虑到部分用户在本机上安装过 JDK,则可能出现以下两种情况:
(1)已安装 JDK + 环境变量配置成功,则正常运行; (2)已安装 JDK + 环境变量配置异常,则删除环境变量JAVA_HOME,并重启 IDE(如 PyCharm)以避免错误。 否则可能提示:未检测到 jvm.dll —— No JVM shared library file (jvm.dll) found. Try setting up the JAVA_HOME environment variable properly.
2.1.2、创建 Java 程序
编写一个 Java 程序,启动 GatewayServer 并暴露 Java 对象。
//ImarisServer.java
import py4j.GatewayServer;
public class ImarisServer {
private ImarisClass imaris;
public ImarisServer() {
this.imaris = new ImarisClass(); // 初始化你的 Java 类
}
public void callSomeMethod() {
imaris.someMethod(); // 调用 Java 类中的方法
}
public static void main(String[] args) {
ImarisServer app = new ImarisServer();
GatewayServer server = new GatewayServer(app);
server.start();
System.out.println("Gateway Server Started");
}
}
2.1.3、编译和运行 Java 程序
javac -cp path/to/py4j.jar ImarisServer.java
java -cp .:path/to/py4j.jar:path/to/Imaris.jar ImarisServer
参数:
path/to/py4j.jar
:是 Py4J 的 JAR 文件
path/to/Imaris.jar
:是包含你的 Java 类的 JAR 文件。
2.1.4、编写 Python 客户端
from py4j.java_gateway import JavaGateway
gateway = JavaGateway() # 连接到 Java Gateway(默认连接到 localhost:25333)
imaris_server = gateway.entry_point # 获取 Java 对象
imaris_server.callSomeMethod() # 调用 Java 方法
2.2、使用 JPype 库(亲测有效)
在 python 中,使用 JPype 启动一个 JVM(Java Virtual Machine)
,并允许 Python 直接调用 Java 类和方法。
2.2.1、JPype 环境配置 —— OpenJDK 开源免费库
确保 Java 与 JPype 版本兼容 —— JPype 支持 Java 6 到 Java 17 版本。
(1)安装 JPype 库: pip install jpype1
(2)配置 Java 环境 方法一:在Windows系统中安装 JDK 工具 + 手动配置环境变量 JAVA_HOME 安装 JDK:从 Oracle 或 OpenJDK 网站下载并安装 JDK。 配置环境变量: (1)此电脑 – 鼠标右击 – 属性 – 高级系统设置 – 环境变量; (2)在系统变量中 – 新建 – 变量名(JAVA_HOME)
:变量值(C:\Program Files\Java\jdk-22)
(3)在系统变量中 – Path – 添加: (%JAVA_HOME%\bin;)
和(%JAVA_HOME%\jre\bin)
方法二:无需在系统中安装 JDK + 无需手动配置环境变量 JAVA_HOME 在 Python 中,安装 OpenJDK 开源免费库 :
conda install openjdk=11 -y
考虑到部分用户在本机上安装过 JDK,则可能出现以下两种情况:
(1)已安装 JDK + 环境变量配置成功,则正常运行; (2)已安装 JDK + 环境变量配置异常,则删除环境变量JAVA_HOME,并重启 IDE(如 PyCharm)以避免错误。 否则可能提示:未检测到 jvm.dll —— No JVM shared library file (jvm.dll) found. Try setting up the JAVA_HOME environment variable properly.
2.2.2、启动 JVM 并调用 Java 类
实战一:(JPype)python 调用 helloworld.jar
【helloworld.jar】下载地址:https://github.com/jarirajari/helloworld
HelloWorld.class
:打印信息
Python 命令,用于测试和验证 JPype(Java-Python Bridge)与 JVM(Java 虚拟机)是否正确安装和配置:python -c "import jpype; print(jpype.getDefaultJVMPath()); jpype.startJVM(jpype.getDefaultJVMPath()); print(jpype.isJVMStarted()); jpype.shutdownJVM()"
import jpype
import jpype.imports
# (1)检查JVM是否已经启动,如果没有启动,则启动JVM。在同一个 Python 进程中,只能启动一次 JVM
if not jpype.isJVMStarted():
# 使用jpype1启动JVM,并指定JAR文件的类路径 ———— classpath参数是一个包含JAR文件路径的列表
jpype.startJVM(classpath=[r"F:\py\helloworld.jar"])
# (2)使用JClass获取指定的Java类 ———— jar文件路径:io\github\javaf\HelloWorld.class
HelloWorld = jpype.JClass('HelloWorld')
print("Methods in HelloWorld class:", dir(HelloWorld))
# (3)调用 Java 类的方法
HelloWorld.main([])
# (4)# 关闭 JVM
jpype.shutdownJVM()
"""Hello world from HelloWorld.jar!"""
实战二:(JPype)python 调用 hello-world-1.1.11.jar
【hello-world-1.1.11.jar】下载地址:https://mavenlibs.com/jar/file/io.github.javaf/hello-world
HelloWorld.class
:创建一个简单的命令行程序,提示用户输入一个问题的答案。
import jpype
import jpype.imports
if not jpype.isJVMStarted():
"""#############################################################################################
# 函数功能:检查 Java 虚拟机(JVM)是否已经启动。
# 函数说明:jpype.isJVMStarted()
# 参数说明:
# 无参数。
# 返回值:
# 布尔值:如果 JVM 已经启动,则返回 True;否则返回 False。
#############################################################################################"""
jpype.startJVM(classpath=[r"F:\py\hello-world-1.1.11.jar"])
"""#############################################################################################
# 函数功能:启动 Java 虚拟机(JVM),使 Python 程序可以调用 Java 类和方法。
# 函数说明:jpype.startJVM(jvm, *args, **kwargs)
# 参数说明:
# jvm:字符串,表示要使用的 JVM 的路径。通常为 Java 安装目录中的 'jvm.dll' 或 'libjvm.so'。
# *args:可选参数,传递给 JVM 的其他参数,如类路径(-Djava.class.path=路径)或 JVM 选项(如 -Xmx512m)。
# **kwargs:可选参数,额外的关键字参数,包括:
# classpath:字符串或列表,指定 Java 类的类路径。
# ignoreUnrecognized:布尔值,默认为 False。如果为 True,则忽略 JVM 不识别的参数。
# 返回值:
# 无返回值。
# 注意事项:
# - 只能启动一次 JVM,在同一个 Python 进程中不能再次启动。
# - JVM 一旦启动,就无法停止或重新启动。
#############################################################################################"""
# (1)使用JPackage访问指定的Java包下的所有类类 ———— jar文件夹路径:io\github\javaf
package = jpype.JPackage('io.github.javaf')
print("Classes in package:", dir(package))
"""#############################################################################################
# 类功能:用于从 Java 包中动态加载类,可以用于访问 Java 包下的所有类。
# 类说明:jpype.JPackage(package_name)
# 参数说明:
# package_name:字符串,表示 Java 包的名称。
# 返回值:
# 返回一个 JPackage 对象,可以用于访问指定包下的类。
#############################################################################################"""
# (2)使用JClass获取指定的Java类 ———— jar文件路径:io\github\javaf\HelloWorld.class
HelloWorld = jpype.JClass('io.github.javaf.HelloWorld')
print("Methods in HelloWorld class:", dir(HelloWorld))
"""#############################################################################################
# 类功能:从 Java 类的完全限定名创建一个 Python 类,用于调用 Java 类的静态方法、静态字段以及创建实例。
# 类说明:jpype.JClass(name, loader=None)
# 参数说明:
# name:字符串,表示 Java 类的完全限定名(包括包名)。
# loader:可选参数,表示类加载器,可以是 Java 类加载器实例或类加载器名称。默认为 None,表示使用默认类加载器。
# 返回值:
# 返回一个 Python 类,可以用于调用对应的 Java 类中的方法、字段以及实例化对象。
# 使用示例:
# MyClass = jpype.JClass('com.example.MyClass')
# my_instance = MyClass() # 创建 Java 类的实例
# MyClass.staticMethod() # 调用 Java 类的静态方法
# print(MyClass.staticField) # 访问 Java 类的静态字段
#############################################################################################"""
# (3)调用 Java 类的方法
HelloWorld.main([])
jpype.shutdownJVM()
"""#############################################################################################
# 函数功能:关闭已经启动的 Java 虚拟机(JVM)。
# 函数说明:jpype.shutdownJVM()
# 参数说明:
# 无参数。
# 返回值:
# 无返回值。
# 注意事项:
# - 关闭 JVM 后,不能再次启动。同一进程中只能启动和关闭一次 JVM。
# - 在关闭 JVM 前,确保所有的 Java 资源已经被释放,以防止资源泄漏。
# - 如果 JVM 尚未启动,调用此函数不会有任何效果。
#############################################################################################"""
实战三:(JPype)python 调用 ImarisLib.jar + 获取 Imaris 版本号
【ImarisLib.jar】下载地址:https://github.com/bleach1by1/BIRDS_plugin
BPImarisLib.class
:定义了一个名为 BPImarisLib 的类,主要用于与 Imaris 服务器进行交互。
import jpype
import jpype.imports
from jpype.types import *
def get_object_id(v_imaris_lib):
try:
v_server = v_imaris_lib.GetServer()
v_number_of_objects = v_server.GetNumberOfObjects()
for v_index in range(v_number_of_objects):
v_object_id = v_server.GetObjectID(v_index)
return v_object_id # 返回第一个对象 ID
except Exception as e:
print(f"Error: {str(e)}")
print("Please reload image to Imaris")
return -1 # 无效的 ID
if __name__ == '__main__':
jpype.startJVM(classpath=[r"F:\py\pyinstaller\BIRDSpyd\BIRDS\code\cache\ImarisLib.jar"]) # 启动 JVM 并指定 JAR 文件路径
# from com.bitplane.xt import BPImarisLib # 导入 Java 包
BPImarisLib = jpype.JClass('com.bitplane.xt.BPImarisLib') # jar压缩包文件路径:com\bitplane\xt\BPImarisLib.class
print("Methods in HelloWorld class:", dir(BPImarisLib))
# 若没有Imaris软件或不需要获取Imaris版本号,则直接调用 ImarisLib.jar 即可。
if False:
v_imaris_lib = BPImarisLib() # 创建 Java 对象
imaris_id = get_object_id(v_imaris_lib) # 调用获取对象 ID 的函数
print(f"Imaris_ID={imaris_id}") # Imaris_ID=1(测试版本号:Imaris9.0.1)
jpype.shutdownJVM() # 关闭 JVM
"""##################################################################
# (0)classpath路径不存在或不正确
TypeError: Class com.bitplane.xt.BPImarisLib is not found
# (1)若Imaris软件没有打开
Error: 'NoneType' object has no attribute 'GetNumberOfObjects'
Please reload image to Imaris
Imaris_ID=-1
# (2)若Imaris软件已经打开
Imaris_ID=0
##################################################################"""
ImarisLib.jar
:是 Imaris 软件的 Java API 库,通常包含在 Imaris 安装包中。Imaris
:Imaris 是一个(商业)图像分析和处理软件,由 Bitplane 开发
。由于 Imaris 是商业软件,你需要从 官方渠道 购买以获得软件的使用权。
作者:胖墩会武术