我目前正在制作一个在嵌入式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);
}
答案 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();
}
}
然后a
和b
已经从调用Dummy.doSomething()
开始堆叠,并且可以通过本机方法进行检查。
修改强>
你真的是说这些论点正在里面本机函数中?在这种情况下,不应该从任何 Java或字节码代码中调用它们,因为字节码验证器会阻塞:它检查通过函数的每个执行路径是否使堆栈的大小与它相同开始了,它无法知道本机代码中直接修改堆栈的隐藏弹出窗口。