How to Use JPype

Date March 31, 2008 by Isaac

Background

I love Python and my personal experience has shown that testers are about 4x more productive when using Python than when using Java. However, at work I am a tester on a Java application. I've been looking for a way to bridge that gap and allow me to write my tests in Python but test a Java application.

I've looked into Jython and while it had many advantages it has one major drawback that I can't live with: Jython only implements Python 2.2. Most of the time this is fine, but there are times where I use Python 2.4 or 2.5 features and don't want to create a workaround just so I can use an older Python standard. If I had the money I would pay someone to bring Jython up to date. But, that's not a possibility.

I did find another alternative that so far seems to work great. It is still in development, but JPype seems to be working fairly well. JPype differs in philosophy from Jython in a fundamental way: Jython is a complete reimplementation of Python in Java, whereas JPype is a bridge between CPython and native Java.

Kicking The Tires

This article is a "how to," so let's get down to business. I'm going to create a Java class that I would like to access from Python. Here is Java class:

 
package org.wg3i.test;
 
class Test {
    private String msg;
 
    public Test() {
    }
 
    public void speak(String msg) {
	System.out.println(msg);
    }
 
    public void setString(String s) {
	msg = s;
    }
 
    public String getString() {
	return msg;
    }
}

The class is simple enough, but it will illustrate the basic JPype usage. For my testing I compiled this and placed it into a jar file. Feel free to leave it as a class file if you wish. I'll show you how to deal with both situations below.

For reference, here is my ant build file:

 
<project name="TestProject" basedir="." default="jar">
<property name="src.dir" value="src"></property>
<property name="build.dir" value="build"></property>
<property name="classes.dir" value="${build.dir}/classes"></property>
<property name="jar.dir" value="${build.dir}/jar"></property>
 
  <target name="clean">
    <delete dir="build">
  </delete>
 
  <target name="compile">
    <mkdir dir="${classes.dir}">
    <javac srcdir="${src.dir}" destdir="${classes.dir}">
  </javac>
 
  <target name="jar" depends="compile">
    <mkdir dir="${jar.dir}">
    <jar destfile="${jar.dir}/${ant.project.name}.jar" basedir="${classes.dir}">
  </jar>
 
  <target name="clean-build" depends="clean,jar">
</target>
</mkdir></target></mkdir></target></target></project>

After creating a jar file you are ready to go. Here is the Python code to utilize a jar file and create an instance of the Java class.

 
# Simple little JPype test.  Note: This test assumes
# that the jar file is in the build/jar directory
# relative to the current directory
import jpype
import os.path
 
jarpath = os.path.join(os.path.abspath('.'), 'build/jar')
jpype.startJVM(jpype.getDefaultJVMPath(), "-Djava.ext.dirs=%s" % jarpath)
Test = jpype.JClass('org.wg3i.test.Test')  # get the class
t = Test()  # create an instance of the class
t.speak("This is a test message")  # try to call one of the class methods
t.setString("Hello, World")  # set a string
s = t.getString()  # get the string back
print s
jpype.shutdownJVM()

In a nutshell that's it. I promised to show you how to initialize JPype when you have class files and not jar files. Here's a Python example that shows that This example also shows the use of the JPackage method, which gets a package, not a class.

 
import jpype
import os.path
 
classpath = os.path.join(os.path.abspath('.'), 'build/classes')
jpype.startJVM(jpype.getDefaultJVMPath(), "-Djava.class.path=%s" % classpath)
testPkg = jpype.JPackage('org').wg3i.test  # get the package
Test = testPkg.Test # get the class
t = Test()  # create an instance of the class
t.speak("This is a test message")  # try to call one of the class methods
t.setString("Hello, World")  # set a string
s = t.getString()  # get the string back
print s
jpype.shutdownJVM()

Conclusion

There are many things I have not covered, such as passing arrays back and forth, types other than strings, exceptions, etc. However, this should be enough to get you started using JPype. I'd be interested in hearing your own experiences or suggestions.

One Response to “How to Use JPype”

  1. AvatarKen
    1

    Thanks, this was a helpful introduction. The jpype.getDefaultJVMPath() call didn’t work properly on my Ubuntu Linux system, so I just hard-coded the path, which in my case is /usr/lib/jvm/java-1.5.0-sun/jre/lib/i386/client/libjvm.so

    Reply to this comment.

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>