Pragma Pack使用C库导致jvm崩溃

时间:2016-01-22 06:49:05

标签: java c memory-management jvm jna

我在使用JNA的Java代码中使用了C库。我有这些C结构,我需要用Java打印其成员。由于内存对齐和填充,大小与我实际期望的大小不同。因此我使用了pragma pack,这就是结构现在的样子。

#define PACK( __Declaration__ ) __pragma( pack(push, 1) ) __Declaration__ __pragma( pack(pop) )

PACK(
typedef struct 
{
    size_t size;
    uint8_t bytes[48];
} ipj_tid_t);


PACK(
typedef struct 
{
    bool has_epc; //1
    ipj_epc_t epc; //64+8
    bool has_tid; //1
    ipj_tid_t tid; //48+8
    bool has_pc; //1
    uint32_t pc; //4
    bool has_xpc; //1
    uint32_t xpc; //4
    bool has_crc; //1
    uint32_t crc; //4
    bool has_timestamp; //1
    uint64_t timestamp; //8
    bool has_rssi; //1
    int32_t rssi; //4
    bool has_phase; //1
    int32_t phase; //4
    bool has_channel; //1
    uint32_t channel; //4
    bool has_antenna; //1
    uint32_t antenna; //4
} ipj_tag); //total size= 174


PACK(
typedef struct 
{
    bool has_error;
    ipj_error error;
    bool has_test_id;
    uint32_t test_id;
    bool has_result_1;
    uint32_t result_1;
    bool has_result_2;
    uint32_t result_2;
    bool has_result_3;
    uint32_t result_3;
    size_t data_count;
    uint32_t data[16];
    bool has_timestamp;
    uint64_t timestamp;
    size_t lt_buffer_count;
    uint32_t lt_buffer[21];
} ipj_test_report);


PACK(
typedef struct
{
    size_t size;
    uint8_t bytes[64];
} ipj_tag_operation_data_t);


PACK(
typedef  struct
{
    bool has_error;  //1
    ipj_error error; //4
    bool has_tag; //1
    ipj_tag tag; //174
    bool has_tag_operation_type; //1
    ipj_tag_operation_type tag_operation_type; //4
    bool has_tag_operation_data; //1
    ipj_tag_operation_data_t tag_operation_data; //72
    bool has_retries; //1
    uint32_t retries; //4
    bool has_diagnostic; //1
    uint32_t diagnostic; //4
    bool has_timestamp; //1
    uint64_t timestamp; //8
    size_t lt_buffer_count; //8
    uint32_t lt_buffer[30]; //120
} ipj_tag_operation_report); //405

当我从Visual Studio运行代码时,我没有收到任何错误,异常或崩溃。但是当我从Java调用它时,jvm崩溃了。为什么会这样? C代码中还有其他结构没有打包。这可能是一个原因吗?请指教。

上面显示的结构在C中使用。从C代码返回的是在所有处理之后的结构。

#define RX_MAX_SIZE     405
#pragma pack(push, 1)
typedef struct _report
{
    ipj_report_id report_id;
    uint32_t data_size;
    uint32_t data[RX_MAX_SIZE];
 } report;
 #pragma pack(pop)

已使用的等效JNA结构如下。

public class _report extends Structure {

    public static class ByValue extends _report implements Structure.ByValue {

    }

    public _report() {
        super();
        setAlignType(ALIGN_NONE);
    }

    public _ipj_report_id reportid;
    public int data_size;
    public int[] data = new int[405]; 

    @Override
    protected List getFieldOrder() {
        return Arrays.asList("reportid", "data_size", "data");
    }

}

public class _ipj_report_id extends Structure {

    public int ipj_report_id;

    public _ipj_report_id() {
        super();
        setAlignType(ALIGN_NONE);
    }

    @Override
    protected List getFieldOrder() {
        return Arrays.asList("ipj_report_id");
    }

}

以下是调试JNA代码时得到的结构。

    _report$ByValue(auto-allocated@0x18918cc0 (1628 bytes)) {
   _ipj_report_id reportid@0=_ipj_report_id(allocated@0x18918cc0 (4 bytes) (shared from auto-allocated@0x18918cc0 (1628 bytes))) {
    int ipj_report_id@0=0
   }
   int data_size@4=195
   int data[405]@8=[I@78bb0ecb
 }

以下是我在JNA中调用此方法的方法。

 rfidlib rlib = (rfidlib) Native.loadLibrary("rfidlib", rfidlib.class);
_report.ByValue report = new _report.ByValue();
 report = rlib.get_next_reports();

1 个答案:

答案 0 :(得分:0)

JNA假定当前目标平台(在本例中为MS编译器)的默认结构布局。

在使用 var mytrack = document.getElementById("sound"); var play = document.getElementById("play"); var currentTime = document.getElementById("current-time"); var totalTime = document.getElementById("total-time"); var defaultBar = document.getElementById("default-bar"); var progressBar = document.getElementById("progress-bar"); var barSize; defaultBar.addEventListener('click', clickedBar, false); mytrack.addEventListener('loadedmetadata', function () { mytrack.play(); updateTime = setInterval(update, 500); play.innerHTML = "<i class='fa fa-pause'></i>"; var minutes = parseInt(mytrack.duration / 60); var seconds = parseInt(mytrack.duration % 60); if (seconds < 10) { totalTime.innerHTML = minutes + ":0" + seconds; } else { totalTime.innerHTML = minutes + ":" + seconds; } }); function playOrPause() { if (!mytrack.paused && !mytrack.ended) { mytrack.pause(); play.innerHTML = "<i class='fa fa-play'></i>"; window.clearInterval(updateTime); } else { mytrack.play(); play.innerHTML = "<i class='fa fa-pause'></i>"; updateTime = setInterval(update, 500); } } function update() { if(!mytrack.ended) { // CURRENT TIME TO READABLE TIME var minutes = parseInt(mytrack.currentTime / 60); var seconds = parseInt(mytrack.currentTime % 60); if (seconds < 10) { currentTime.innerHTML = minutes + ":0" + seconds; } else { currentTime.innerHTML = minutes + ":" + seconds; } // BAR var progressBarSize = parseInt(mytrack.currentTime * barSize /mytrack.duration); progressBar.style.width = progressBarSize + "px"; barSize = defaultBar.offsetWidth; } else { currentTime.innerHTML = "0:00"; play.innerHTML = "<i class='fa fa-play'></i>"; // Bar progressBar.style.width = "0px"; // TIMER window.clearInterval(updateTime); } } function clickedBar(e) { if(!mytrack.ended) { var mouseX = e.pageX - defaultBar.offsetLeft; var newTime = mouseX * mytrack.duration/barSize; mytrack.currentTime = newTime; progressBar.style.width = mouseX + "px"; } } 调用JVM后,可以通过调用Structure.toString()来打印JNA生成的内存布局的布局。

然后,您可以将所需的结构布局与JNA生成的实际布局进行比较,以查找差异。如果您通常在Java结构中使用-Djna.dump_memory=true,则默认情况下是分配本机boolean,因此如果与原始int的大小不同,则需要使用{{ 1}}在Java端或明确地向bool提供byte以表明TypeMapper应转换为与原生Structure兼容的尺寸(请注意尺寸本地boolean的内容未由C标准定义。

除非您明确需要,否则我建议您在代码中使用bool not

请使用您的Java bool实现及其调试输出更新您的问题。