不使用JNI(使用堆栈操作)从java调用本机函数

不使用JNI(使用堆栈操作)从java调用本机函数,java,c,jvm,embedded,Java,C,Jvm,Embedded,我目前正在制作一个运行在嵌入式设备(POS终端)上的java应用程序。 此设备具有特定于制造商的虚拟机 与硬件交互的函数在该虚拟机中的C文件中定义 机器的来源(在配置文件AFAIK中) 我不能从我的java代码中调用这些函数,因为根据官方文档,虚拟机既不支持JNI也不支持KNI,它只支持“堆栈操作”作为连接C和java代码的方法 就我所见,本机函数的参数是使用堆栈传递的。在调用函数之前推送参数,并将其放入函数中(原型具有无效参数)。 我想应该做类似的事情来调用函数,也许是与调用堆栈相关的事情 真

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

与硬件交互的函数在该虚拟机中的C文件中定义 机器的来源(在配置文件AFAIK中)

我不能从我的java代码中调用这些函数,因为根据官方文档,虚拟机既不支持JNI也不支持KNI,它只支持“堆栈操作”作为连接C和java代码的方法

就我所见,本机函数的参数是使用堆栈传递的。在调用函数之前推送参数,并将其放入函数中(原型具有无效参数)。 我想应该做类似的事情来调用函数,也许是与调用堆栈相关的事情

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

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

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

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

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

既然您说“原型有无效参数”,我假设您有可以调用的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();
   }
}
然后,调用
Dummy.doSomething()
时,
a
b
已经在堆栈上,并且可以通过本机方法进行检查

编辑:

你真的是说参数是在本机函数中弹出的吗?在这种情况下,不可能从任何Java或字节码代码调用它们,因为字节码验证器将阻塞:它检查通过函数的每个执行路径是否使堆栈保持与启动时相同的大小,并且它无法知道直接修改堆栈的本机代码中隐藏的POP“原型有无效参数”,我假设您有可以调用的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
,然后执行pop。如果您想要一种类似Java的方法,我认为应该这样做:

class Dummy {
   static void doSomething(int a, Object b) {
      Native.doSomething();
   }
}
然后,调用
Dummy.doSomething()
时,
a
b
已经在堆栈上,并且可以通过本机方法进行检查

编辑:


你真的是说参数是在本机函数中弹出的吗?在这种情况下,不可能从任何Java或字节码代码调用它们,因为字节码验证器会阻塞:它检查通过函数的每个执行路径是否使堆栈与启动时的大小相同,并且它无法知道堆栈的大小关于直接修改堆栈的本机代码中隐藏的POP。

制造商是否提供了示例?我很想看看。制造商是谁,设备的型号是什么。我试图找到一个,但遗憾的是没有包含任何示例。您能举一个本机函数原型的示例吗?以及comes?我将把它添加到主要问题中,因为它不能在这里格式化。我必须更改函数的名称,但C文件中的代码是这样的。我必须从java应用程序中调用PrintAt函数。为了实现这一点,JVM必须提供某种查找“PrintAt”位置的方法“并使程序计数器指向那里。制造商没有提供任何类来调用PrintAt?是否有任何特定于供应商的类可供查找和调用PrintAt?您是否可以访问JVM源代码或完整文档?制造商是否提供了示例?我很想看看。谁是制造商,设备的型号是什么。我试着找了一个,但遗憾的是没有包括在内。你能举一个本机功能原型的例子吗?还有随附的任何描述吗?我会把它添加到主要问题中,因为它不能在这里格式化。我不得不更改函数的名称,但是C文件中的代码是这样的。我必须从我的java应用程序中调用PrintAt函数。为了实现这一点,JVM必须提供某种方法来查找“PrintAt”的位置,并使程序计数器指向该位置。制造商没有提供任何类来调用PrintAt?是否有任何特定于供应商的类可供查找和调用PrintAt?您可以访问JVM源代码或完整的文档吗?感谢您的回答,文档明确地说是“堆栈操作”,如果java堆栈无法触摸,那么它可能是一个C堆栈吗?而且它使用的虚拟机既不是JVM也不是kvm,是一个制造商,对于堆栈修改可能有不同的规则。IPC方法可能是一个很好的替代解决方案,但我将把它作为最后的资源