开发者

Python中使用jpype调用Jar包中的实现方法

开发者 https://www.devze.com 2022-12-09 09:20 出处:网络 作者: scluis
目录使用jpype调用Jar包中的实现方法安装使用说明代码jpype调用jar包“Class xx not found“问题环境代码问题检查点解决总结使用jpype调用Jar包中的实现方法
目录
  • 使用jpype调用Jar包中的实现方法
    • 安装
    • 使用
    • 说明
    • 代码
  • jpype调用jar包“Class xx not found“问题
    • 环境
    • 代码
    • 问题
    • 检查点
    • 解决
  • 总结

    使用jpype调用Jar包中的实现方法

    安装

    pip install jpype1(注意要加后边这个1)

    使用

    基本流程如下python

    • 使用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.fas开发者_JAVAtjson.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));
          Fwww.devze.comunctionVisitor functionVisitor = new FunctionVisitor();
    
          functionVisitor.visit(m_CompilationUnit, null);
          ArrayList<MethodDeclaration> nodes = functionVisitor.getMethodDeclarations()android;
          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.getRan编程客栈ge().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

    Python中使用jpype调用Jar包中的实现方法

    检查点

    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文件了

    再次修改代码,执行通过。

    Python中使用jpype调用Jar包中的实现方法

    总结

    以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

    0

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    关注公众号