用Delphi开发JNI(Java Native Interface)应用(二)

原创 2004年03月12日 13:55:00

要正确地访问类对象的成员属性(字段)及成员方法,最重要的一点是一定要给出正确的签名,在Java中对于数据类型和方法的签名有如下的约定:

数据类型/方法

签名

byte

B

char

C

double

D

float

F

int

I

long

J (注意:是J不是L)

short

S

void

V

boolean

Z(注意:是Z不是B

类类型

L跟完整类名,如Ljava/lang/String; (注意:以L开头,要包括包名,以斜杠分隔,最后有一个分号作为类型表达式的结束)

数组type[]

[type,例如 float[]的签名就是[float,如果是二维数组,如float[][],则签名为[[float,(注意:这里是两个 [ 符号)。

方法

(参数类型签名)返回值类型签名,例如方法: float fun(int a,int b),它的签名为(II)F(注意:两个I之间没有逗号!),而对于方法String toString(),则是()Ljava/lang/String;

通过上面的例子,我们了解了访问对象参数的成员属性或方法的基本步骤和多个Get方法的使用。TJNIEnv同时提供了多个Set方法,可以修改传入的对象参数的字段值,因为Java对象参数都是以传址的方式进行传递的,所以修改的结果可以在Java程序中得到反映。TJNIEnv提供的Get/Set方法,都需要两个基本参数:对象实例(JObject类型)和字段IDJField类型),就可以根据提供的对象和字段ID来获取或设置这个对象的这个字段的值。

现在我们了解了在Delphi代码中使用以及修改Java对象的操作步骤。进一步,如果需要在Delphi中从无到有地创建一个新的Java对象,可以吗?再来看一个例子,在Delphi中创建Java类的实例,操作方法其实也非常简单。

先在Java代码中增加一个本地方法,如下:

 public native Book findBook(String t);

然后,修改Delphi代码,增加一个函数(因为有返回值,所以不再是过程而是函数了):

function Java_HelloWorld_findBook(PEnv: PJNIEnv; Obj: JObject; t:JString):JObject; stdcall;

var

 JVM: TJNIEnv;

 c: JClass;

 fid:JFieldID;

 b:JObject;

 mid:JMethodID;

begin

  JVM := TJNIEnv.Create(PEnv);

 

  c:=JVM.FindClass('Book');

  mid:=JVM.GetMethodID(c,'<init>','()V');

  b:=JVM.NewObjectV(c,mid,nil);

  fid:=JVM.GetFieldID(c,'title','Ljava/lang/String;');

  JVM.SetObjectField(b,fid,t);

  fid:=JVM.GetFieldID(c,'price','D');

  JVM.SetDoubleField(b,fid,99.8);

  Result:=b;

 

  JVM.Free;

end;

这里先用FindClass方法根据类名查找到类,然后获取构造函数的方法ID,构造函数名称固定为“<init>”,注意签名为“()V”说明使用了Book类的一个空的构造函数。然后就是使用方法NewObjectV根据类和构造函数的方法ID来创建类的实例。创建了类实例,再对它进行操作就与前面的例子没有什么两样了。对于非空的构造函数,则略为复杂一点。需要设置它的参数表。还是上面的例子,在Book类中增加一个非空构造函数:

public Book(Strint t,double p){

 this.title=t;

this.price=p;

}

Delphi代码中,findBook函数修改获取方法ID的代码如下:

mid:=JVM.GetMethodID(c,'<init>','(Ljava/lang/String;D)V');

构造函数名称仍是“<init>”,方法签名表示它有两个参数,分别是Stringdouble。然后就是参数的传入了,在Delphi调用Java对象的方法如果需要传入参数,都需要构造出一个参数数组。在变量声明中加上:

args : array[0..1] of JValue;

注意!参数都是JValue类型,不管它是基本数据类型还是对象,都作为JValue的数组来处理。在代码实现中为参数设置值,并将数组的地址作为参数传给NewObjectA方法:

  args[0].l:=t; // t是传入的JString参数

  args[1].d:=9.8;

 

  b:=JVM.NewObjectA(c,mid,@args);

JValue类型的数据设置值的语句有点特殊,是吧?我们打开jni.pas,查看一下JValue的定义,原来它是一个packed record,已经包括了多种数据类型,JValue的定义如下:

  JValue = packed record

  case Integer of

    0: (z: JBoolean);

    1: (b: JByte   );

    2: (c: JChar   );

    3: (s: JShort  );

    4: (i: JInt    );

    5: (j: JLong   );

    6: (f: JFloat  );

    7: (d: JDouble );

    8: (l: JObject );

  end;

下面再来看一下错误处理,在调试前面的例子中,大家也许看到了一旦在Delphi的执行过程中发生了错误,控制台就会输出一大堆错误信息,如果想要屏蔽这些信息,也就是说希望在Delphi中捕获错误并直接处理它,应该怎么做?也很简单,在TJNIEnv中提供了两个方法可以方便地处理在访问Java对象时发生的错误。

var

… …

ae:JThrowable;

begin

… …

ae:=JVM.ExceptionOccurred;

  if ( ae<>nil ) then

   begin

    Writeln(Format('Exception handled in Main.cpp: %d', [longword(ae)]));

    JVM.ExceptionDescribe;

    JVM.ExceptionClear;

   end;

… …

用方法ExceptionOccurred可以捕获Java抛出的错误,并存入JThrowable类型的变量中。用ExceptionDescribe可以显示出Java的错误信息,而ExceptionClear显然就是清除错误,让它不再被抛出。

至此,我们已经把从Java代码通过JNI技术访问Delphi本地代码的步骤做了初步的探讨。在jni.pas中也提供了从Delphi中打开Java虚拟机执行Java代码的方法,有兴趣的读者不妨自己研究一下。

Java Native Interface(JNI)从零开始详细教程

==================================================================================== 首先声明:这边文章是我翻译的...
  • Baniel01
  • Baniel01
  • 2016年12月22日 13:37
  • 3061

java native interface JNI 简介、基本原理

JNI是Java Native Interface的缩写,中文为JAVA本地调用。从Java1.1开始,Java Native Interface(JNI)标准成为java平台的一部分,它允许Java...
  • rain_butterfly
  • rain_butterfly
  • 2014年05月05日 15:19
  • 18113

Jni:架起 Java 和 C/C++的桥梁,Java Native Interface

前言正如标题所说,Jni(Java Native Interface) 把 Java 和 C/C++之间联系起来了。这样的话,Java可以直接调用C/C++语言编写的代码。...
  • u013390476
  • u013390476
  • 2017年01月23日 15:56
  • 918

用Delphi开发JNI(Java Native Interface)应用(一)

JNI(Java Native Interface,Java本地接口)技术大家都不陌生,它可以帮助解决Java访问底层硬件的局限和执行效率的提高。关于JNI的开发,大多数资料讨论的都是如何用C/C++...
  • sharetop
  • sharetop
  • 2004年03月12日 13:57
  • 1908

用Delphi开发JNI(Java Native Interface)应用

JNI(Java Native Interface,Java本地接口)技术大家都不陌生,它可以帮助解决Java访问底层硬件的局限和执行效率的提高。关于JNI的开发,大多数资料讨论的都是如何用C/C++...
  • atomic_age
  • atomic_age
  • 2007年03月14日 12:21
  • 928

java native interface JNI 调用Java方法

在上一篇文章中介绍了JNI,以及java调用JNI,这篇讲一下 JNI调用java方法。       通过使用合适的JNI函数,你可以创建Java对象,get、set 静态(static)和...
  • rain_butterfly
  • rain_butterfly
  • 2014年05月06日 14:52
  • 12341

Java Native Interface Specification(JNI)

Java Native Interface Specification(JNI) 使用场景: 需要的功能,标准的java不能提供有了一个用其他的语言写好的工具包,希望用java去访问它当需要高...
  • luhuajcdd
  • luhuajcdd
  • 2013年07月22日 11:12
  • 1760

java开发第一个JNI示例程序(基于linux操作系统)--java调用native方法

大家都知道,通过jni可以实现java和c以及c++的交互,但是这对于新手来说,想实现自己的本地调用还是有一定困难,万事开头难,这里我将用一个最简单的程序向大家展示jni的真面目。项目的基本流程: ...
  • zhangmingbao2016
  • zhangmingbao2016
  • 2016年10月10日 16:38
  • 963

JNI - Java Native Interface

JavaTM Native Interface (JNI) is a standard programming interface for writing Java native methods an...
  • jasonchain
  • jasonchain
  • 2009年11月30日 22:32
  • 379

JNI:Java Native Interface

什么是 JNI JNI 是 Java Native Interface 的缩写,它提供了若干的 API 实现了 Java 和其他语言的通信(主要是C&C++)。从 Java1.1 开始,JNI 标准成...
  • SweetLoveFT
  • SweetLoveFT
  • 2015年10月14日 11:36
  • 540
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:用Delphi开发JNI(Java Native Interface)应用(二)
举报原因:
原因补充:

(最多只允许输入30个字)