在不使用JNI的情况下从java调用本机函数(使用堆栈操作)

时间:2012-03-23 17:17:52

标签: java c jvm embedded

我目前正在制作一个在嵌入式devie(POS终端)上运行的java应用程序。 该设备具有特定于制造商的虚拟机。

与硬件交互的功能在此虚拟内的C文件中定义 机器的来源(在配置文件AFAIK中)。

,因为根据官方文档,虚拟机不支持既不JNI也不KNI我无法从我的Java代码调用这些函数,它仅支持“堆栈操作”作为接口C和Java代码的方法。< / p>

据我所知,本机函数的参数是使用堆栈传递的。在调用函数并在函数内部弹出它们之前推送参数(原型具有void参数)。 我想应该这样做以调用函数,也许是与调用堆栈相关的东西?

真正的问题是,如何使用“堆栈操作”来连接C和java?

更新:要调用的函数示例(C代码)它在设备的屏幕上打印一条消息。

void PrintAt(void)
{
    Array msg = popStackAsType(Array);
    int y = popStack();
    int x = popStack();
    NativePrint(x,y,msg->bdata);
}

2 个答案:

答案 0 :(得分:3)

由于您无法控制堆栈,因此无法实际期望这样做。 JVM控制堆栈,任何所谓的堆栈操作只是一个卑鄙的黑客攻击。如果没有JNI或类似的东西,您的最佳解决方案可能是在单独的流程中执行C代码,并使用某种形式的IPC与之通信。

答案 1 :(得分:1)

由于您说“原型具有void参数”,我假设您可以调用Java本机方法,但是它们使用堆栈的顶部元素作为参数而不实际使用它们。像这样:

class Native {
   native static void doSomething() {
      // do something with stack[sp] as an int and stack[sp - 1] as
      // an object reference, but do not modify sp.
   }
}

如果你写了原始字节码,你可以按下参数,然后执行invokestatic,然后弹出。如果你想要一种看起来像Java的方法,我认为这应该有效:

class Dummy {
   static void doSomething(int a, Object b) {
      Native.doSomething();
   }
}

然后ab已经从调用Dummy.doSomething()开始堆叠,并且可以通过本机方法进行检查。

修改

你真的是说这些论点正在里面本机函数中?在这种情况下,不应该从任何 Java或字节码代码中调用它们,因为字节码验证器会阻塞:它检查通过函数的每个执行路径是否使堆栈的大小与它相同开始了,它无法知道本机代码中直接修改堆栈的隐藏弹出窗口。