3

I'm using Jpype to use a java class into a python script. The java class involves the use of AWT library: and this seems to be the problem.

This the python script:

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()

So I'm just trying to instantiate the class, and just exit. This the java class. I'm reporting only the code that is causing error:

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);
            }
         }
    }
}

This code, when running python script, raise me the following error:

 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

Long story short, this is a known problem: Eclipse had "its own version", then solved. Unfortunately no one spoke about this problem relating to jpype.

I tried these solutions, that didn't worked:

  • In python script, launching a thread before starting the JVM. And then starting the JVM in another thread.

  • In python script, starting the JVM with the parameter -XstartOnFirstThread:

    target=jpype.startJVM(jpype.getDefaultJVMPath(), "-XStartOnFirstThread -Djava.ext.dirs=%s" % jarpath)
    
  • In the java code: using the AWT method invokeLater, in the constructor:

    java.awt.EventQueue.invokeLater(new Runnable() {
        public void run() {
            images = new ArrayList<BufferedImage>();
            getImages(fnamestart,countmax);
        }
    });
    

I really don't know what to do, hoping that you will help me. Thank you,

Giovanni

TallTed
  • 9,069
  • 2
  • 22
  • 37
joker
  • 106
  • 1
  • 5

2 Answers2

1

Use this parameter:

jpype.startJVM(jpype.getDefaultJVMPath(), '-Djava.awt.headless=true')
Jorge
  • 2,156
  • 2
  • 22
  • 29
0

-XstartOnFirstThread is exactly what you must ensure not to have on the command line. Launching a thread in python makes no difference, the problem lies with JVM's threads. invokeLater will also not make a difference -- the AWT run loop must execute on the first thread. This is a Cocoa-only restriction, so I suppose you are running this on a Mac.

Now, you should search for your problem by seeing exactly what command line was used to start the JVM and then trying to trace back to the root cause -- the code that generated that command line. JVM is being launched by a method outside your immediate control.

Marko Topolnik
  • 195,646
  • 29
  • 319
  • 436
  • In my opinion it is a Jpype problem: i read the code which initializes the JVM, and it runs a java thread before passing it to a python class. This way, when I initialize AWT, it does it in a second thread. Although I will run my code on a Linux machine, and not on a MAC OSX as I've done since now. Hope that this will solve the problem! Thank you – joker Jul 11 '12 at 16:15
  • The initialization of the AWT event loop is outside the client code's control, as far as I know, and the thread where you use AWT objects is not important. So the only reason for this error would be RunOnFirstThread. It does sound like a problem with Jpype. – Marko Topolnik Jul 11 '12 at 17:50