JPYPE用户手册小译
来源:互联网 发布:英雄无敌7 for mac 编辑:程序博客网 时间:2024/05/16 06:39
JPYPE用户手册小译
By Jetway from hdu_cloud
1、 概述
JPype是为了python程序能完全访问java类库而开发的。它并不是将像Jython/JPython那样重新用python实现java类库,而是通过两个虚拟机之间的接口实现的。
为什么要开发JPype呢?开发者认为尽管他自身对python编程非常深入,但他并不能否认java的市场占有率。比如sourceforge中就包含了3267个与python相关的项目和12126个与java相关的项目(没算上商业用途的项目)。并且在服务器端python的非常弱小的,就算是Zope,还是比不上java在服务器的应用上的地位。于是为了同时使用这两种语言,开发者搞了这个项目。
那么Jython又如何?Jython不错,但是有很多缺点,比如,它比CPython慢,并且不允许访问大部分Python扩展库。
看一个JPype使用的例子:
from jpype import *
startJVM("d:/tools/j2sdk/jre/bin/client/jvm.dll", "-ea")
java.lang.System.out.println("hello world")
shutdownJVM()
这是一个简单的helloworld程序,不过显示了最重要的两个调用:startJVM和shutdownJVM。下一节将详细介绍。
2、
线程
此处唯一的问题是保证java线程和python线程正确的交互,感谢上苍,这个实现起来不难。
Python线程。唯一要注意的只有调用线程内的jpype.attachThreadToJVM(),这样的话JVM就可用了。对于那些不是你自己启动的线程,你可以调用ThreadAttachedToJVM()来检测。
Java线程。因为没有回调机制,当前无法使用java创建的线程。
同步(一致性)。Java同步(一致性)机制可以分为两种:第一种,同步(一致)的关键字,诸如一个方法的前缀和一个方法内部的语句块;第二种,对象类中不同的方法(notify,notify all,wait)。为支持同步(一致性)功能,jpype定义了一个synchronized(O)方法,O必须是一个java对象或者java类或者相当于一个对象的java包(JString和JObject)。此方法的返回值是一个monitor对象,它将在对象O的整个生命周期中保持其一致性(同步)。
3、 性能
Jpype使用JNI,它并不是最有效的接口。并且Jpype桥接两个完全不同的实时环境,需要来回转换。这两个都可能引入巨大的性能瓶颈。
JNI是标准的适用于大部分JVM的本地化接口,要减少JNI负担只能将一部分代码转移到java中。
要减少转换负担,可以对那些给定(一个字符串,一个对象,一个数组等等)并且经常传入java的对象,你可以使用wrappers一次性预转换他们。
4、 内部类
大部分内部类可以像普通类一样使用,只是有以下区别:
在java中使用$来区分内部类和外部类。例如内部类Foo定义在Bar内部,在java中称为Bar.Foo,但此时其真正的名字为Bar$Foo。
由于上述名字变异,你不能使用标准的包访问方式来获取它们。使用JPackage的方法_getclass_来载入。
非静态内部类不能从python代码中实例化。但是可以完全没有问题地使用从java代码中接受到的实例。
5、 数组
Jpype完全支持接受java数组并传递java方法给这些数组。Java数组(打包成JArray包类),其行为很像python列表(list),当然了java数组大小是固定的,而python列表大小是可变的。多维数组也可以很好的在python中运行。
从python中创建java数组。创建java数组用的是JArray方法,代码形式如下:
JArray(type, num_dims)(sz or sequence)
Type是java(String或java对像)类或者包类型。Num_dims是数组大小,默认为1.。sz数组中元素的真实数目。Sequence是初始化数组的序列。JArray(type, ndims)返回的是一个数组类,可以通过此类来生成实例。
6、 类型转换
JPype这个桥接系统中最麻烦的应该是找到python类型和java类型之间的无缝转换。下表列出了转换明细。
其中:none表示无法转换;Explicit(E)表示JPype可以转换成想要的类型,但是只针对与Wrapper类。也就是wrapper类将作为一个参数方位此类型。Implicit(I)表示JPype可以按需转换。Exact>(X),类似implicit,但是当决定哪个方法负载时,exact比implicit具有更高的优先级。
其中:
(1) 如果Python值符合java本地值类型,转换就会发生。
(2) 如果python string或者unicode的长度是1,转化发生
(3) 所要求的对象必须与java.lang.String (java.lang.Object,java.util.Comparable)兼容。
(4) 维数必须能配对,并且类型必须兼容。
(5) 只有当所要求的类型为java.lang.Object
(6) 只有当JObject包的详细类型为一个可兼容的数组类。
(7) 只有当所要求的类型与包的详细类型兼容。实际的java对象并不考虑。
(8) 只有当所要求的类型与java对象的实际类型兼容
(9) 只有当所要求的类型是java.lang.Object或者java.lang.Class
(10)只有当值True和False明确的转换成boolean时。
从java转换到python:
Java的byte,short和int转换成python的int
Java的long转换成python的long
Java的float和double转换成python的float
Java的boolean转换成python int值0或1
Java 的char转换成python 中长度为1 的unicode
Java的String转换成python的unicode
Java的数组转换成JArray
所有的java对象转换成JavaObject
Java类转换成JavaClass
Java数组类转换成JavaArrayClass
7、 JProxy
JProxy的构造函数使用2个参数。第一个参数是一个或者一组(a sequence of)JClass对象,定义要实现的接口。第二个参数必须是一个关键字参数(keyword argument),并且必须是一个dict或者inst。如果dict指定,那么第二个参数必须是一个字典,带关键字的方法名为定义的接口,而且值为可调用的对象。如果inst是一个给定对象实例(定义的给接口修饰的方法)。
当然在python中子类别化java类是不一样的。
样例代码:
假设java接口如下:
public interface ITestInterface2
{
int testMethod();
String testMethod2();
}
你可以创建一个代理并实现此接口,有两种方法,第一种使用类:
class C :
def testMethod(self) :
return 42
def testMethod2(self) :
return "Bar"
c = C()
proxy = JProxy("ITestInterface2", inst=c)
第二种使用字典:
def _testMethod() :
return 32
def _testMethod2() :
return "Fooo!"
d = {
'testMethod' : _testMethod,
'testMethod2' : _testMethod2,
}
proxy = JProxy("ITestInterface2", dict=d
8、 java异常
python异常是扩展类,在表面上与java类差不多(常规类),但是python异常与常规python类完全不同,这导致了完全直接的捕获java异常是不可能的。
所有的抛出的java异常都会结束于抛出jpype.JavaException异常。你可以接下来使用message(), stackTrace() 和javaClass()来访问扩展信息。例子如下:
try :
# Code that throws a java.lang.RuntimeException
except JavaException, ex :
if JavaException.javaClass() is java.lang.RuntimeException :
print "Caught the runtime exception : ", JavaException.message()
print JavaException.stackTrace()
你可以直接使用JException来捕获真正的java异常:
try :
# Code that throws a java.lang.RuntimeException
except jpype.JException(java.lang.RuntimeException), ex :
print "Caught the runtime exception : ", JavaException.message()
print JavaException.stackTrace()
9、 已知的局限性
卸载JVM。JNI API中定义了destroyJVM()的方法,但是由于Sun公司的JVM不允许卸载,此方法形同虚设。所以当你在shutdownJVM()之后尝试着再次调用startJVM(),你将会受到一个不明确的(non-specific)异常。JPype中并没有出错。
方法依赖于现存的类。Java库中有一些方法依赖于寻找调用类时的信息。如果直接从python代码中调用会出错。JNI API没有提供类似的方法。
A. Module Reference
startJVM()方法。此方法必须必须在任何jpype features被使用前调用。返回值为None。异常,RuntimeException。参数:
vmPath jvm.dll或者jvm.so(这个看具体平台的)的路径。
misc arguments 可选,可以通过此参数将任何命令行参数传递给JVM。
shutdownJVM()方法。没有参数,返回值None。异常RuntimeException。
attachThreadToJVM方法。大部分情况下不用调用,jpype module会自动执行。没有参数,返回值None,异常为RuntimeException
isTreadAttachedToJVM方法。这个也是不大用调用的。参数没有,返回值None,异常RuntimeException。
detachThreadFromJVM方法。不太需要手动调用。参数没有,返回值None,异常RuntimeException
synchronized方法。不太需要手动调用。参数没有,返回值None,异常RuntimeException
JPackage类。此包允许结构化方位java包和类。只需要在JPackage中声明包树的根(the root of the package tree)。例如:
要导入w3c DOM包:Document = JPackage(‘arg’).w3c.dom.Document
Wrapper classes。封装java类和方法到python中的主要问题在于,java允许重载一个方法。大部分情况下是没什么问题的。大部分重载的方法有不一样的参数并且不会发生冲撞。
当jpype不能决定调用哪个重载的方法时,用户必须解决这个歧义。于是就可以引入wrapper类了。例子为java.io.PrintStream类,它有两种可变的方法print和println。
对于以下代码,Jpype会自动的选择println(int)方法。
from jpype import *
startJVM("d:/tools/j2sdk/jre/bin/client/jvm.dll", "-ea")
java.lang.System.out.println(1)
shutdownJVM()
改过之后:
from jpype import *
startJVM("d:/tools/j2sdk/jre/bin/client/jvm.dll", "-ea")
java.lang.System.out.println(JByte(1)) # <--- wrap the 1 in a JByte
shutdownJVM()
告诉jpype选择byte类型,但是这个wrappered类型要求必须与要求类型兼容,于是使用JByte wrapper来请求一个int会失败。
(到此为止吧,jetway水平有限,但是若要转载或使用此文,请挂上jetway的名字啊嘿嘿——原文地址:http://jpype.sourceforge.net/doc/user-guide/userguide.html)
- JPYPE用户手册小译
- Jpype
- JPype
- Jpype
- BTrace用户手册<译>
- 用户手册
- 用户手册
- 用户手册
- 用户手册
- 小飞计算器(小飞可编程复数计算器)用户手册
- 安装jpype及问题
- Jpype调用java 故障
- jpype安装问题
- python的jpype模块
- Jpype的使用
- jpype和HanLP
- jpype的安装
- JPype入门实例
- exp之compress到底在压缩什么
- navigationController视图间的跳转
- 图像叠加
- IHttpHander讲解
- complie and install open-iscsi
- JPYPE用户手册小译
- 自定义HTTPHandler实现数字水印效果
- Vertex Shader - 散射光照处理
- DataStage 与PowerCenter
- Struts target is null for setProperty(null, "x", [Ljava.lang.String;@179da9f)
- Ubuntu下搭建android NDK开发环境
- Coldfusion [Invalid token > found]
- 15位和18位身份证JS校验实例(jquery)和注意项
- FastReport打印TListView数据的实现