快捷搜索:

KVM的扩展

KVM本身只带有cldc1.1的类库,功能十分简单,不能满意用户的需求,本篇先容若何对KVM进行扩展。

对KVM进行扩展,在Java层十分简单,只要向在编译Java代码时多加一个文件就可以,没什么要说的,麻烦的是假如在加入的Java类中有本地操作该怎么办?本地的C说话代码放在哪里编译才能够供KVM调用?

谜底是KNI。下面就以KNI为主要内容先容若何对KVM加以扩展,在着末附加一个详细的实现例子。

1. KNI的特征:

KNI(K Native Interface)是SUN的KVM(K Virtual Machine)所应用的本地措施调用机制。

JNI(Java Native Interface)是已经为我们所认识的Java本地措施调用机制,JNI一样平常应用在J2SE或J2EE平台上,本地措施被编进动态链接库,在运行时由Java虚拟机载入。

KVM中也必要本地调用,但JNI是“重量级”的本地调用要领,在应用时耗损的资本较多,以是针对KVM设计出了KNI,KNI被称为是JNI的一个简化版,是“轻量级”的本地调用要领。KVM不能加载动态链接库,以是在KNI机制下,本地措施不是写在库中,而是编入虚拟机内部。

以下是KNI与JNI最紧张的一些差别:

KNI是“实现层”的API,即它是虚拟机实现的一部分,改动KNI的API就要从新编译虚拟机,这些API的细节对付Java法度榜样员来说是弗成见的;而JNI的API是在运行时动态加载进来的,它的改动与虚拟机无关,JNI的API对付Java法度榜样员来说是可见的。

KNI的函数建在虚拟机内部,只能为此虚拟机所独享;而JNI的函数放在动态链接库中,可以为多个虚拟机共用。

因为在虚拟机内部,KNI的很多操作要领与虚拟机有关,在通报参数和节制工具的时刻都要先颠末一些特其余处置惩罚;JNI的调用要领对照直接,但可能会增添安然隐患。

KNI是JNI的简化版,功能也会弱一些,它不能创建工具,也不能调用Java层的措施。

总之,“在虚拟机内部”是KNI所有特征的根源,记得这一点,KNI的所有内容都异常轻易理解。

下文各节对KNI的各个方面做一下先容,只胪陈那些KNI所特有的内容,更周全的内容可以参考KVM附带的KNI specification。

2. 数据类型:

2.1 原始类型:

上表中心一列是KNI所供给的8种原始类型,它们的长度与所对应的Java原始类型的长度相同。

2.2 工具类型:

上图是KNI所支持的工具类型,着实所有工具都可作为jobject,只是对图中所示的这些object类的子类有特其余支持,比如为数组类供给了操作数组元素的措施。

2.3 返回类型:

“返回类型”也便是本地措施的返回值的类型,KNI对它们有专门的定义。

上表右边一列即本地措施的返回类型。

2.4 字符串类型、类描述符、字段描述符:

这三项内容都是在本地措施中对付Java层工具的描述,比如用”[Ljava/lang/String;”来描述String数组,这些内容与JNI规范以及Java虚拟机规范中所定义的都完全同等,以是这里不再多说。

3. KNI函数

本节分类简介各类KNI函数的功能。大年夜部分的函数功能对照轻易理解,只有“参数通报”和“句柄操作”是对照特其余内容,将作具体解说。

3.1 版本信息:

3.1.1 jint KNI_GetVersion()

获得KNI的版本号。

3.2 类和接口操作:

3.2.1 void KNI_FindClass(const char* name, jclass classHandle)

初始化一下指向某种工具的名柄,工签字字在name中。

3.2.2 void KNI_GetSuperClass(jclass classHandle, jclass superclassHandle)

取得超类的句柄。原类的句柄在classHandle中,调用后超类的名柄将被寄放在superclassHandle中。假如classHandle指向一个java.lang.Object工具,则superclassHandle应为NULL。

3.3.3 jboolean KNI_IsAssignableFrom(jclass classHandle1, jclass classHandle2)

判断classHandle1类的工具是否能安然转换为classHandle2类的工具。

3.3 非常:

3.3.1 jint KNI_ThrowNew(const char* name, const char* message)

抛非常,name长短常类的名字,message是所附带的信息。

3.3.2 void KNI_FatalError(const char* message)

呈现致命差错时应用,向标准输出打印掉足信息,并终止虚拟机。

3.4 工具操作

3.4.1 void KNI_GetObjectClass(jobject objectHandle, jclass classHandle)

取得某工具所对属的类,objectHandle是工具句柄,调用后,类句柄将被存入classHandle中。

3.4.2 jboolean KNI_IsInstanceOf(jobject objectHandle, jclass classHandle)

判断句柄objectHandle所指向的工具是否是句柄classHandle所指向的类的实例。

3.5 工具字段操作

3.5.1 jfieldID KNI_GetFieldID(jclass classHandle, const char* name, const char* signature)

取得类classHandle中由name和signature所指定的字段名。这个字段名的感化与JNI中的相同,是于在其它函数中读写字段的值。

3.5.2KNI_GetField(jobject objectHandle, jfieldID fieldID)

3.5.3 void KNI_SetField(jobject objectHandle, jfieldID fieldID,value)

上面两个措施分手用于读写类型字段的值,为基础类型。

3.5.4 void KNI_GetObjectField(jobject objectHandle, jfieldID fieldID, jobject toHandle)

3.5.5 void KNI_SetObjectField(jobject objectHandle, jfieldID fieldID, jobject fromHandle)

上面两个措施分手用于读写工具。

3.6 静态字段操作

3.6.1 jfieldID KNI_GetStaticFieldID(jclass classHandle, const char* name, const char* signature)

取得静态字段名。

3.6.2KNI_GetStaticField(jclass classHandle, jfield fieldID)

3.6.3 void KNI_SetStaticField(jclass classHandle, jfieldID fieldID, value)

上面两个措施分手用于读写类型静态字段的值,为基础类型。

3.6.4 void KNI_GetStaticObjectField(jclass classHandle, jfield fieldID, jobject toHandle)

3.6.5 void KNI_SetStaticObjectField(jclass classHandle, jfield fieldID, jobject fromHandle)

上面两个措施分手用于读写静态工具。

3.7 字符串操作

3.7.1 jsize KNI_GetStringLength(jstring stringHandle)

取得字符串长度。

3.7.2 void KNI_GetStringRegion(jstring stringHandle, jsize offset, jsize n, jchar* jcharbuf)

读取字符串内容。

3.7.3 void KNI_NewString(const jchar* uchars, jsize length, jstring stringHandle)

应用Unicode序列创建String。

3.7.4 void KNI_NewStringUTF(const char* utf8chars, jstring stringHandle)

应用UTF-8序列创建String。

3.8 数组操作

3.8.1 jsize KNI_GetArrayLength(jarray arrayHandle)

取得数组长度。

3.8.2KNI_GetArrayElement(http://www.sun.com/software/communitysource/j2me/cldc/download.xml下载KVM源法度榜样;

4.2 java类库源代码放在j2me_cldc/api/src,在此中增添类rayman.test.KNITest,源文件如下:/* rayman/test/KNITest.java */

package rayman.test;

public class KNITest {

public void println(String s) {

System.out.println(s);

}

public static native int nativeTest(int i, int j);

}

4.3 部分C层源文件放在j2me_cldc/kvm/VmCommon/src,新建文件nativeTest.c:/* nativeTest.c */

#include kni.h>

#include stdio.h>

KNIEXPORT KNI_RETURNTYPE_INT Java_rayman_test_KNITest_nativeTest() {

jint i1 = KNI_GetParameterAsInt(1);

jint i2 = KNI_GetParameterAsInt(2);

printf("in function Java_rayman_test_KNITest_nativeTest() ");

KNI_ReturnInt(i1+i2);

}

4.4 在j2me_cldc/kvm/VmUnix/build/Makefile中加入nativeTest.c。

4.5 在j2me_cldc/build/linux下履行make USE_KNI=true,编译好的可履行文件kvm就在j2me_cldc/kvm/VmUnix/build下。

4.6 编写测试类Hello:/* Hello.java */

import rayman.test.*;

public class Hello {

public static void main(String [] args) {

KNITest t=new KNITest();

t.println("Hello KVM ! " + t.nativeTest(1,2));

}

}

设置好classpath并履行,获得准期结果!

别的,在KNIspec.pdf文档中有很多例子可供参考。

您可能还会对下面的文章感兴趣: