参考文章《Jni 调试 : eclipse Vs 联合调试》发现jna也可以按类似的方法调试,方法如下:
1、复制dll到java工程
cp d:jna-cppbuildDebugdemojna.dll d:jna-javasrcmainresourceswin32-x86-64
然后切记要在eclipse中刷新工程
2、修改java代码
在Native.loadLibrary的调用前面增加:
System.setProperty("jna.debug_load", "true");
确保调试的时候能够看到尽可能多的信息
3、设置断点--java
就设置到System.setProperty("jna.debug_load", "true"); 或者任何调用jna前的代码
4、设置断点--c
在vs2015中设置断点到需要调试的代码上
5、调试
调试启动java程序,在断点断下来后,切换到vs2015中,选择调试-附加到进程-javaw.exe
然后跑到eclipse中继续运行程序,这个时候vs2015就可以断下来了
如果看到下面的图片,选择继续
注意:无论任何时候修改c代码,都需要重复第一步工作,否则可能断不下来了
6、错误处理:
Exception in thread "main" java.lang.IllegalStateException: Pointer native@0xdddddddddddddddd already mapped to Proxy interface to native function@0xdddddddddddddddd (com.tencent.evmc.demo.EvmcInterface$evmc_destroy_fn).
Native code may be re-using a default function pointer, in which case you may need to use a common Callback class wherever the function pointer is reused.
这个错误仅在debug版本的dll中存在,更改为release就没有了
7、需要注意的地方
char* 的数据如果是可以打印的,也就是不会中间存在0x00数据,java层就可以直接使用String接收,但是如果不可打印只能使用Point接收,否则会被0x00位置截断;
如果是java传递byte[]给c,那么使用string和Point都是可以的;
size_t 的数据用long或者NativeSize都可以接收,建议用NativeSize,如果用int一定得到错误的数据;
java调用c函数的返回值可以是结构体,但是c调用java函数,java函数的返回值如果是结构体总是空值,因此只能返回String,这块比较奇怪,没有搞明白
8、jna代码的自动生成
推荐使用jnaerator,下载最新版本,然后命令行执行:
java -jar jnaerator-0.12-SNAPSHOT-20130727.jar -runtime JNA -mode Maven -mavenGroupId com.test -mavenArtifactId myjna -o code -package com.test.myjna -f -library myjna.dll myjna.h
细节可以参考文章jnaerator:java调用动态库的神器,JNA代码自动生成工具