增加KVM中的系统调用API
大家都晓得KVM是不支持Native函数调用的,如果要增加一些系统调用的API,那么只能加到KVM内部。同时,不同的J2ME设备,也有不同的系统调用API以及它们的实现。我们从SUN那么下载到原始的KVM源代码,如何为其增加一个系统调用API呢?本文以具体实践的步骤一步一步来讲解增加KVM系统API的方法。
其实为KVM增加一个系统调用API比为Linux增加一个系统调用API还简单。大致就分成两步工作就完成。一步是在classes.zip中增加一个你自己新增的class,一步是在KVM的nativeCore.c中实现这个新增的class的native api函数。
下面以org.test.MiniTest这个新增的class为例来实现一个TestInt()系统调用函数。函数的功能很简单,就是返回一个整数9999。
1. 新增org.test.MiniTest类
从SUN那里下载到j2me_cldc 1.1版本的KVM代码后。在j2me_cldc/api目录下,增加org/test/MiniTest.java的包目录以及java文件。然后写上如下的代码:
package org.test;
public class MiniTest
{
public static native int TestInt();
}
2. 进行第一次编译
根据上一篇文章中的KVM编译方法,在命令提示符下,跳到目录j2me_cldc/build/win32下,输入make命令进行第一次整体编译。不过,这次编译过程在编译连接KVM中的*.o文件的时候,会提示一个找到_Java_org_test_MiniTest_TestInt符号的错误提示。
这是因为在我们只是在org.test.MiniTest中定义了这个native函数TestInt,但是并没有在KVM的任何一个c文件中实现其对应的函数。
首先编译过程是用javac来编译j2me_cldc/api里面的所有的*.java文件,然后将其class文件打包成一个classes.zip,然后JCC这个工具会默认根据classes.zip生成ROMJavaWin.c和nativeFunctionTableWin.c。而在ROMJavaWin.c声明这个native函数:
extern void Java_org_test_MiniTest_TestInt(void);
3. 实现Java_org_test_MiniTest_TestInt函数
从KVM中的代码可以看到,KVM默认都是把一些native函数放到了nativeCore.c这个文件里面。你也可以自己去新增一些C程序文件,不过本例就把这个Java_org_test_MiniTest_TestInt放在了nativeCore.c文件。
下面是代码:
void Java_org_test_MiniTest_TestInt(void)
{
pushStack(9999);
}
这里为什么把返回值使用pushStack这个宏来返回的原因就不好说了,关于JAVA运行的方式其实就是一个堆栈,Java的字节码其实就是一种栈式语言,这个在编译原理里面的中间代码生成那一章可以找到它的原型和其说明。再者,还可以看《Inside Java Virtual Machine》这本书。
4. 第二次编译
第二次编译就是可以生成真正的kvm.exe文件了。还是跟第一次编译以及上一篇编译KVM的方法一样,敲入make命令即可。
5. 测试MiniTest.TestInt这个API
自己写了一个Test的类,来测试这个API:
import org.test.*;
class Test {
public static void main(String[] args) {
System.out.println("Test Result = "+MiniTest.TestInt());
}
}
用javac编译的时候,需要把前面的j2me_cldc/classes.zip拷贝过来,执行:
javac -classpath classes.zip Test.java
kvm -classpath . Test
可以看到结果: