Python中使用jpype调用Jar包中的实现方法
scluis 人气:0使用jpype调用Jar包中的实现方法
安装
pip install jpype1(注意要加后边这个1)
使用
基本流程如下:
- 使用jpype开启jvm
- 加载java类
- 调用java方法
- 关闭jvm
说明
我这里是在Python中使用Java的第三方抽象语法树包JavaParser(Python中的javalang实在太难用了),实现得到一个类文件中的所有的方法的功能
代码
Python代码:
import jpype import os import json if __name__ == '__main__': # 加载jar包 jarpath = os.path.join(os.path.abspath('.'),'D:/study/hdu-cs-learning/Paper/TD/BuildDataset/target/BuildDataset.jar') # 获取jvm.dll的默认文件路径 jvmPath = jpype.getDefaultJVMPath() # 开启虚拟机 jpype.startJVM(jvmPath, '-ea', '-Djava.class.path=%s' % (jarpath)) # 加载java类(参数名是java的长类名) javaClass = jpype.JClass('scluis.API') # 调用类中的方法 class_file_path = 'D:/study/TD/OpenSourceProject/JFreeChart/source/org/jfree/chart/fx/ChartViewer.java' # 这里是调用scluis.API类的静态方法getMethods,如果调用实例方法,则需要先实例化java对象,即javaInstance = javaClass(),在使用实例调用 file_methods_str = javaClass.getMethods(class_file_path) # 解析返回值,这里的返回值是json数组 methods_list = "" if file_methods_str != "": methods_list = json.loads(str(file_methods_str)) # 关闭虚拟机 jpype.shutdownJVM()
API.java:
package scluis; import com.github.javaparser.ParseException; import java.io.IOException; import java.security.SecureRandom; import java.util.Random; public class API { public static void main(String[] args) { //main方法是为了测试Java代码即,getMethods,main方法不是必须的 String filePath="D:/study/OpenSourceProject/SQuirrel/app/src/net/sourceforge/squirrel_sql/client/gui/HelpViewerWindow.java"; String methods=getMethods(filePath); System.out.println(methods); } public static String getMethods(String filePath){ String res=""; try { Parser fileParser = new Parser(); res= fileParser.getFileMethods(filePath); } catch (ParseException | IOException e) { e.printStackTrace(); } return res; } }
Parser.java(内含Java返回值格式)
package scluis; import com.alibaba.fastjson.JSON; import com.github.javaparser.*; import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.ast.Node; import com.github.javaparser.ast.NodeList; import com.github.javaparser.ast.body.MethodDeclaration; import com.github.javaparser.ast.comments.Comment; import com.github.javaparser.ast.expr.*; import com.github.javaparser.ast.stmt.BlockStmt; import com.github.javaparser.ast.stmt.ExpressionStmt; import com.github.javaparser.ast.stmt.Statement; import com.github.javaparser.printer.DotPrinter; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.stream.Stream; public class Parser { private CompilationUnit m_CompilationUnit; public CompilationUnit getParsedFile() { return m_CompilationUnit; } public String getFileMethods(String filePath) throws ParseException, IOException { String methodJson = ""; try { m_CompilationUnit = StaticJavaParser.parse(new File(filePath)); FunctionVisitor functionVisitor = new FunctionVisitor(); functionVisitor.visit(m_CompilationUnit, null); ArrayList<MethodDeclaration> nodes = functionVisitor.getMethodDeclarations(); ArrayList<Method> methodList = new ArrayList<>(); for (int i = 0; i < nodes.size(); i++) { MethodDeclaration methodDeclaration = nodes.get(i); //起止行 int startLine = methodDeclaration.getRange().get().begin.line; int endLine = methodDeclaration.getRange().get().end.line; //方法代码 String method = methodDeclaration.removeComment().toString(); Method m = new Method(startLine, endLine, method); methodList.add(m); } methodJson = JSON.toJSONString(methodList); } catch (Exception e) { e.printStackTrace(); } return methodJson; } }
jpype调用jar包“Class xx not found“问题
环境
- Java 1.8 (64位)
- Python 2.7.9 (32位)
- Jpype 0.5.4.2
- Pycharm
代码
import jpype from jpype import * # 该目录下有需要调用的jar包 pak.jar jvmArg = "-Djava.ext.dirs=D:/1_Workspace/jpype_test/" if not jpype.isJVMStarted(): jvmPath = jpype.getDefaultJVMPath() jpype.startJVM(jvmPath,"-ea", jvmArg) # pak.jar中包含类com.abc.EFG jd = JClass("com.abc.EFG") instance = jd() print(instance.getName()) jpype.shutdownJVM()
问题
执行以上代码,报错如下。Class com.abc.EFG not found
检查点
1.在pak.jar包中有com.abc.EFG
类
2.EFG
依赖的jar包都在同级目录下
3.Jpype使用没有问题:调用System.out.println
可以打印
jprint = java.lang.System.out.println jprint("xxx") #输出xxx
试着从环境上找原因,也许和Java版本有关。
首先查找pak.jar包的编译jdk版本
使用以上方法获得输出是 52,即对应java 1.8,与本机Java版本相符。
但是回头一想其实在Pycharm中并没有配置过Java的版本。
那么打印一下jvmPath
,获得的路径是C:\Program Files (x86)\Java\jre6\bin\client\jvm.dll
,=> 使用的是 jre1.6(32位)。
此时去Java1.8目录找,发现server
目录下有jvm.dll
,不是在client
目录。管他的,尝试直接指定存在的jvm.dll路径。
# ... # jvmPath = jpype.getDefaultJVMPath() jvmPath = r'D:\java\jdk1.8\jre\bin\server\jvm.dll' jpype.startJVM(jvmPath,"-ea", jvmArg) # ...
到这里也许有人的问题可以解决了,但我的情况是还是报错…
解决
最后装了jdk1.8 32位!!!,发现在client
目录下有jvm.dll
文件了
再次修改代码,执行通过。
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持。
加载全部内容