Jpype:“输入”;Can';t启动AWT,因为Java是在第一个线程上启动的。”;

Jpype:“输入”;Can';t启动AWT,因为Java是在第一个线程上启动的。”;,java,jpype,Java,Jpype,我使用Jpype将java类用于python脚本。 java类涉及AWT库的使用:这似乎就是问题所在 以下是python脚本: import jpype import os.path import threading jarpath = os.path.join(os.path.abspath('.'), 'build/jar') target=jpype.startJVM(jpype.getDefaultJVMPath(), "-Djava.ext.dirs=%s" % jarpath) C

我使用Jpype将java类用于python脚本。 java类涉及AWT库的使用:这似乎就是问题所在

以下是python脚本:

import jpype
import os.path
import threading

jarpath = os.path.join(os.path.abspath('.'), 'build/jar')
target=jpype.startJVM(jpype.getDefaultJVMPath(), "-Djava.ext.dirs=%s" % jarpath)
Capture = jpype.JClass('Capture')            # Capture is the class, contained in ./ folder
t = Capture(50,354,90,90,130,650,"num",36);  # create the instance
jpype.shutdownJVM()
所以我只是想实例化这个类,然后退出。 这是java类。我只报告导致错误的代码:

class Capture {

    public Capture(int x, int y, int width, int height, int mouseNextX, int mouseNextY, final String fnamestart, final int countmax) {
            //...
            images = new ArrayList<BufferedImage>();
            getImages(fnamestart,countmax);  //THIS is the problem
}

    // reference to getImages() method:
    public void getImages(String fname, int countmax) {

        images.clear();
        for(int i=0; i<=countmax; i++) {
            try {
                BufferedImage img = ImageIO.read(new File(fname+i+".bmp")); 
                images.add(img);
            } catch(IOException e) {
                images.add(null);
            }
         }
    }
}
 jpype._jexception.VirtualMachineErrorPyRaisable: java.lang.InternalError: Can't start
 the AWT because Java was started on the first thread.  Make sure StartOnFirstThread is
 not specified in your application's Info.plist or on the command line
长话短说,这是一个已知的问题:Eclipse有“自己的版本”,然后就解决了。不幸的是,没有人谈到这个与jpype相关的问题

我尝试了这些解决方案,但没有成功:

  • 在python脚本中,在启动JVM之前启动线程。然后在另一个线程中启动JVM

  • 在python脚本中,使用参数
    -XstartOnFirstThread
    启动JVM:

    target=jpype.startJVM(jpype.getDefaultJVMPath(), "-XStartOnFirstThread -Djava.ext.dirs=%s" % jarpath)
    
  • 在java代码中:使用AWT方法
    invokeLater
    ,在构造函数中:

    java.awt.EventQueue.invokeLater(new Runnable() {
        public void run() {
            images = new ArrayList<BufferedImage>();
            getImages(fnamestart,countmax);
        }
    });
    
    java.awt.EventQueue.invokeLater(new Runnable()){
    公开募捐{
    images=newarraylist();
    获取图像(fnamestart、countmax);
    }
    });
    
我真的不知道该怎么办,希望你能帮助我。 谢谢,


Giovanni

-XstartOnFirstThread
正是您必须确保在命令行上使用的。在python中启动线程没有什么区别,问题在于JVM的线程
invokeLater
也不会有什么不同——AWT运行循环必须在第一个线程上执行。这是一个只有可可豆的限制,所以我想你是在Mac电脑上运行的

现在,您应该通过查看用于启动JVM的确切命令行来搜索问题,然后尝试追溯根本原因——生成该命令行的代码。JVM是由您无法直接控制的方法启动的。

使用此参数:

jpype.startJVM(jpype.getDefaultJVMPath(), '-Djava.awt.headless=true')

在我看来,这是一个Jpype问题:我阅读了初始化JVM的代码,它在将其传递给python类之前运行java线程。这样,当我初始化AWT时,它会在第二个线程中进行初始化。尽管我将在Linux机器上运行我的代码,而不是像现在这样在MacOSX上运行。希望这能解决问题!谢谢,据我所知,AWT事件循环的初始化不在客户机代码的控制范围内,使用AWT对象的线程并不重要。所以这个错误的唯一原因是RunOnFirstThread。这听起来确实像是Jpype的问题。