报错invalid memory access — Java调用JNA

一、错误概述

“Invalid memory access”是Java中使用JNA(Java Native Access)调用本地库时可能出现的错误之一。

二、错误原因

  • 内存越界
    在访问本地内存时,如果超出了允许的范围,就会导致无效的内存访问。这可能是由于传递给本地函数的参数有误,或者在访问返回的数据时发生了错误。
  • 内存释放错误
    如果在使用本地内存之后,不正确地释放或管理内存,就可能导致无效的内存访问。确保在不再需要使用本地内存时,正确地释放它。
  • 数据类型不匹配
    JNA通过Java和本地代码之间的数据转换来实现交互,如果数据类型在转换过程中不匹配,就可能导致无效的内存访问。确保在声明和使用本地函数、结构体或指针时,数据类型是正确匹配的。

三、解决方法

1、数据类型不匹配

数据对应关系



建议使用对应的ByReference对象替代Pointer,使用Pointer有时可能会得到一个垃圾值(正常情况下两种方式结果一样),如果C中函数执行失败时没有对指针的值进行处理,使用Pointer就会得到一个垃圾值

将int*和 IntByReference对应的例子

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.ptr.IntByReference;

public interface MyLibrary extends Library {
    MyLibrary INSTANCE = Native.load("mylibrary", MyLibrary.class);

    void myFunction(IntByReference intValue);
}

public class Main {
    public static void main(String[] args) {
        MyLibrary myLibrary = MyLibrary.INSTANCE;

        IntByReference intValue = new IntByReference(0);
        myLibrary.myFunction(intValue);
        
        int result = intValue.getValue();
        System.out.println("Result: " + result);
    }
}

一个将double*和Pointer对应的例子

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;

public interface MyLibrary extends Library {
    MyLibrary INSTANCE = (MyLibrary) Native.load("mylibrary", MyLibrary.class);

    // 假设C语言中的函数原型为:void processDoubles(double* data, int length);
    void processDoubles(Pointer data, int length);
}

public class Main {
    public static void main(String[] args) {
        // 准备一些数据
        double[] inputData = {1.0, 2.0, 3.0, 4.0};
        int length = inputData.length;

        // 将数据拷贝到本地内存,并获取一个指向该内存块的指针
        Pointer pointer = new Memory(inputData.length * Native.getNativeSize(Double.TYPE));
        //Double[] doubles = new Double[]{};
        //将Double[]转换成double[]
        //double[] primitiveArray = Arrays.stream(doubles).mapToDouble(Double::doubleValue).toArray();
        pointer.write(0, inputData, 0, inputData.length);

        // 调用C语言函数
        MyLibrary.INSTANCE.processDoubles(pointer, length);
    }
}

2、内存错误

保在使用本地内存之前和之后,正确地分配和释放内存。可以使用JNA提供的内存管理方法来处理内存。
这个错误的地方无法预判,可以看下面文章,一次内存上的问题的解决方案
记一次JNA踩坑历程 – JNA

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
心中带点小风骚的头像心中带点小风骚普通用户
上一篇 2023年12月22日
下一篇 2023年12月22日

相关推荐