在内存中创建一个函数并调用它

时间:2014-09-02 17:16:50

标签: java java-native-interface jna

我有一个简单的'功能',如果你甚至可以称之为,那只是存储在内存中的'NOP':

byte[] func = new byte[] {0x90}; // NOP

然后我分配了一块将要保存它的内存,并设置内容:

Memory mem = new Memory(func.length);
mem.write(0, code, 0, code.length); // Write all bytes from code, starting at mem + 0

现在,我想'调用'我刚刚创建的这个小函数。让我们试试:

Function function = Function.getFunction(mem, Function.C_CONVENTION);
function.invokeVoid(null); // I have tried other types of invokeXX too.

但这不起作用,反而抛出异常:

Exception in thread "main" java.lang.Error: Invalid memory access at com.sun.jna.Native.invokeVoid(Native Method) at com.sun.jna.Function.invoke(Function.java:367) at com.sun.jna.Function.invoke(Function.java:315) at com.sun.jna.Function.invoke(Function.java:268) at com.sun.jna.Function.invokeVoid(Function.java:727) at [my line calling invokeVoid]

我没想到会收到这个错误,因为它当然应该存在。我不知道什么可能出错。

我在这里缺少什么或(显然,但是什么?)做错了?

注意:我使用的是JNA 4.1.0。

2 个答案:

答案 0 :(得分:1)

我认为使用Memory对象并不是一个好主意。如果查看finalize方法,您会注意到它调用了本机free()函数,并且提供不受jvm管理的地址可能会导致分段错误。显然这里的问题出现得更早了。尝试向Function.getFunction提供Pointer对象,但不提供Memory。 你可以试试这个:

Pointer ptr = Pointer.createConstant(0x90);
Function f = Function.getFunction(ptr, Function.C_CONVENTION);

答案 1 :(得分:1)

事实证明,正如Peter Lawrey所建议的那样,页面确实受到了保护而无法执行。解决方案相当简单。

我必须从Win32 API映射VirtualProtectEx并使用值0x40调用它以允许执行。在那之后,它工作了!