- 浏览: 141016 次
- 性别:
- 来自: 上海
文章分类
最新评论
-
zi_wu_xian:
docx格式的word文件虽然是zip格式的,也可以看到xml ...
用Java操作Office 2007 -
MyDreamNotDream:
看代码看到这里很不容易呢。
Java中HashMap的实现原理 -
四书五经:
to 楼上的 SonofGod :这个时候这样去获取:如果(值 ...
Java中HashMap的实现原理 -
SonofGod:
请问 楼主 在疑问3中。多个key的hash值一样的话,存储时 ...
Java中HashMap的实现原理 -
SonofGod:
请问 楼主 在疑问2中。多个可以的hash得到一样的hash值 ...
Java中HashMap的实现原理
所有这些解决方案都是有难度且容易出错的。另一个关键的JNA要素是它还能有效取代Java本地接口(JNI)。
例一中展示了一组笔者将要在本文中寻找的代码。笔者从Windows Kernel32 DLL中引用了GetTickCount()程序。GetTickCount()返回了系统启动后所产生的毫秒数量。
public interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary) Native.loadLibrary((Platform.isWindows() ? "kernel32" : "c"), CLibrary.class); int GetTickCount(); } public static void main(String[] args) { System.out.println("TickCount" + CLibrary.INSTANCE.GetTickCount()); } |
例1:简单的JNA示例
例一中有趣的一件事情是不再需要JNI代码。相反,你只需从Java代码中调用一个DLL符号。不需要映射和自动生成JNI标头文件。使用JNA你只需简单加载所需库,映射感兴趣的符合然后引用这些符号就可以了。
总之,毫无疑问,JNA解决方案可以节约成本。它能直接调用传统代码从而避免一切使用JNI的请求或是重写传统代码的需要。或许JNA最重要的一方面是它具备统一的代码环境。但是,其他与JNA相关的事物会干涉本地代码区域。其中之一就是要决定Java是否是所谓的系统语言。
Java:不是系统语言?
初期外界针对Java提出主要质疑是它并非是一个系统语言。与C或C++不同,Java存在于JVM之中,不能访问低级别的机器指定型细节信息只有通过高级别的API才能对其进行访问。Java这样的相对独立性带来的一大优点是其安全性,也就是说JVM死机的时候,整个系统不一定会死机。
JNA的出现改变了这一状况,因为现在Java代码可以访问C类型机制。例二展示了另一个通过Windows kernel32 DLL函数访问数据的Java代码示例。
Kernel32 lib = Kernel32.INSTANCE;
SYSTEMTIME time = new SYSTEMTIME(); lib.GetSystemTime(time); System.out.println("Today's integer value is " + time.wDay); |
例二:Kernel32.dll的系统时间
注意在例二中,Java代码对低级别平台的数据进行了访问。因此JNA意味着Java可以进行系统级别的存取。但是,另一个使用JNA的重要性是对传统代码的访问,因为主要的商业价值存在于传统代码中:例如用C/C++编写的复杂数学函数。也就是说,JNA可以起到技术性桥接作用。
JNA:桥接技术
从上述两个例子中,你可以看出JNA是一项能有效实现Java-本地-Java 的桥接技术。这使得JNA有别于JNI因为不再需要自动生成标头文件或执行特殊的C代码。相反,使用JNA你可以简单映射需要的库符号然后再引用它们。
现在,让我们再看一个创建DLL的复杂示例然后再用JNA代码对其进行调用。
使用JNA的实例
与单一使用JNA技术然后简单调用已有DLL不同之处在于你你好要将JNA调用映射到自己的DLL中。因此笔者想创建一个真正简单的DLL,然后通过JNA代码对其进行调用。笔者用微软VisualC++ 2005 Express Edition创建了一个DLL。当然你也可以使用更新的版本再使用相同的方法。例三截取了DLL代码的重要部分,其中大部分是自动生成。(下图为例三 DLL代码)
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call, LPVOID lpReserved) { return TRUE; } extern "C" __declspec(dllexport) DWORD helloWorld (DWORD divider) { return 77/divider; } |
让我们迅速了解helloWorld()函数的要点。首先,外部C用来避免C++名称装饰。这意味着函数可以作为helloWorld()从外部引用而不需要对名称添加特别性能。其次,_declspec(dllexport)标签用来从DLL中输出函数。函数定义的剩余部分就是返回值,函数名称和参数。
最后要注意的一件事是调用惯例。要确保它被设定为_cdecl。在Visual C++ Express Edition中,你要将调用惯例设定在C++高级部分的项目配置级别。
当上述所有步骤都完成后,你就可以创建制造DLL的项目了。在本文中,DLL被称为nativecode.dll。下面让我们通过JNA执行该DLL代码。
从Java中引用DLL代码
例四展示了引用DLL函数的代码。
public interface CLibrary extends Library {
CLibrary INSTANCE1 = (CLibrary) Native.loadLibrary((Platform.isWindows() ? "nativecode" : "c"), CLibrary.class); int helloWorld(int divider); } public static void main(String[] args) { CLibrary.INSTANCE1.helloWorld(77)); } |
例五展示了从例四代码中输出的程序
C:\jnacode>java HelloWorld
Value is 1
在例五中没有什么令人惊讶的地方——数值77被发送到函数中。参数(77)随后被函数中的77分割以生成答案:1。
当笔者尝试找出与调用惯例相关的DLL问题时,发现可以用Dependency Walker工具看到DLL。你只需下载免费的Dependency Walker副本,打开,并往里面加载DLL。与下图类似。
注意上图中的函数名称与DLL符号helloWorld()名称匹配。当你创建DLL时,如果你使用标准的调用惯例,函数名称看起来就和下图中的一样。
注意函数名称改变的方式。现在,如果你想尝试运行Java程序,你会得到下面的错误陈述。
C:\jnacode>java HelloWorld
Exception in thread "main" java.lang.UnsatisfiedLinkError: Error looking up function 'helloWorld': The specified procedure could not be found. at com.sun.jna.Function.(Function.java:129) at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:250) at com.sun.jna.Library$Handler.invoke(Library.java:191) at $Proxy0.helloWorld(Unknown Source) at HelloWorld.main(HelloWorld.java:31) |
告别JNI
在使用JNI来连接大型Java和C++代码库时,有时,Java和C++代码会一起被传送,但是每次都造成死机。在这样的情况下,Java和C++程序员往往开始互相指责。
解决这一纷争的一项方案是为两种代码运行一套清单目录。例如,在C代码中:
·数组越界了吗?
·空的指示针是否被废弃?
·动态内存是否被正确分配了?
JNA可以结束这一切疑问。
库许可证问题
JNA中有趣的一面在于它为Java访问DLL打通了一条捷径。这也同样可以应用于其他库技术,如共享Unix库。这对于授权的软件组件意味着什么呢?JNA的使用或许能有效访问授权库代码。该问题的另一个方面是JNA代码可能允许对安全限制库代码的访问。
除了上述情况的考虑,访问传统代码的能力也为Java和传统代码之间的接口例外开辟了其他可能性。请看下列代码:
重新调用例三中的代码,如果键入0,并引发 divide-by-zero异常,会发生什么?
public interface CLibrary extends Library {
CLibrary INSTANCE1 = (CLibrary) Native.loadLibrary((Platform.isWindows() ? "nativecode" : "c"), CLibrary.class); int helloWorld(int divider); } public static void main(String[] args) { CLibrary.INSTANCE1.helloWorld(77)); System.out.println("Value: " + CLibrary.INSTANCE1.helloWorld(0)); } |
当笔者指定上述代码时,系统给出了下列回复:
C:\jna_article\jnacode>java HelloWorld
Value is 1 # # An unexpected error has been detected by HotSpot Virtual Machine: # # EXCEPTION_INT_DIVIDE_BY_ZERO (0xc0000094) at pc=0x009b1365, pid=1768, tid=458 4 # # Java VM: Java HotSpot(TM) Client VM (1.5.0_17-b04 mixed mode) # Problematic frame: # C [nativecode.dll+0x11365] # # An error report file with more information is saved as hs_err_pid1768.log # # If you would like to submit a bug report, please visit: # http://java.sun.com/webapps/bugreport/crash.jsp |
结语
如果库代码的建立方式正确,你就不会遇到很多困难。JNA对于那些拥有庞大的,复杂的商业遗留代码的公司来说可以提供相当大的帮助。记住任何发送到本地库的数据都要经过仔细验证。
发表评论
-
微信收货地址共享接口-终极解决
2015-06-25 13:10 8305最近要接入微信的收货地址共享接口,总是不成功,折腾了好 ... -
Java中HashMap的实现原理
2011-04-28 14:30 2728昨天有人来公司面试,因为面试的地方和我坐的地方比较近,所以也听 ... -
java注解(annotation)简介
2010-06-13 10:10 1313[Java 5.0] Annotation – @Deprec ... -
quartz和spring-quartz
2010-06-13 10:03 873quartz和spring-quartz -
Java 线程实例讲解综述
2010-06-13 09:57 983Java 线程实例讲解综述 编写具有多线程能力的程序经常会用 ... -
Java Double 精度问题总结
2010-06-13 09:56 5250使用Java,double 进行运算时,经常出现精度丢失的问题 ... -
eXtremeComponents的eXtremeTable分页特性
2010-05-14 17:27 3281下面是我使用的例子: <ec:table ite ... -
java---final 关键字 和 static 用法
2010-03-17 13:58 842final 关键字 和 static 用法 一、final ... -
java版的escape和unescape方法
2010-03-17 09:21 2502其中unescape方法可以用来解开javascript的es ... -
StatSVN的使用说明
2010-03-04 10:27 1000一、 checkout 希望统计的版本或者分支到某个目录(不管 ... -
Velocity语法
2010-03-01 18:01 8371. 变量 (1)变量的 ... -
用KeyTool生成安全证书
2010-02-22 17:14 1095详细请见:Tomcat的帮助文档,:https://local ... -
Spring 注解学习手札
2010-02-10 10:02 780http://snowolf.iteye.com/blog/5 ... -
JDK、JRE、JVM的关系
2010-01-25 11:23 854JDK就是Java Development Kit.简单的说J ... -
类装载器学习
2010-01-22 12:54 773Java的类装载器(Class Loader)和命名空间(Na ... -
Tomcat发布项目方法
2010-01-22 10:46 2566第一种方法:在tomcat中的conf目录中,在server. ... -
理解Java ClassLoader机制
2010-01-21 16:20 849当JVM(Java虚拟机)启动时,会形成由三个类加载器组成的初 ... -
cookie和session的工作机制
2010-01-19 15:19 763转载自:http://hi.baidu.com/jmtbai/ ... -
如何设置Tomcat的JVM虚拟机内存大小
2010-01-18 14:25 925Tomcat本身不能直接在计算机上运行,需要依赖于硬件基础之上 ... -
浅谈设置JVM内存分配的几个妙招
2010-01-18 14:24 1567安装Java开发软件时,默 ...
相关推荐
JNA.docJNA.docJNA.docJNA.docJNA.docJNA.docJNA.docJna学习总结
本文原名《使用JNA 方便地调用原生函数》发表于2009 年3 月的“程序员”杂志上。 感谢程序员杂志的许可,使这篇文章能够成为免费的电子版,发布于网络上。 程序员杂志发表此文时,略有裁剪,因此本文比程序员上的...
JNA学习使用,java调用dll,JNA_demo
开源项目JNA-中文翻译版 帮助你更快的学习JNA
jna和jnative的一个简单示例工程,包含jna和jnative的jar包,还有jna的chm api文档以供参考。其中.dll是的函数是求两个数的较大值。这是我初入学习java访问.dll做的一个示例。
学习java调用c++时用到的JNA包,分享出来和大家一起学习
jna是基于JNI的基础上,简化了繁琐的连接过程,操作简单。里面附上所需jar和例子代码,供学习。
用于基于JNI基础上的JNA调用不可缺少的.jar包,大家相互学习交流
深入浅出JJNNAA——快速调用原生函数
java 通过jna调用c++ 推理方法 用c++ 做pytorch torch script 推理
JNA:演示了JNA的基本用法,使用Java调用C++代码。 博客目录 Java基础 Java基础学习(1)——引用 Java基础学习(2)——注解 Java基础学习(3)——泛型 Java基础学习(4)——动态代理 《Java多线程核心技术》读书笔记 ...
仅用JAVA实现全局键盘钩子的功能,很好很强大,学习下
解压之后双击AutoClick.jar即可运行,源代码也在压缩包内,程序短小精练,结构清晰。 由于是本人原创,所以意思意思收取要各位1分资源分。很适合JAVA初学者研究学习,未经本人同意,还望请勿转载!
该文档详细描述了,内存溢出各种问题和解决方案,适合学习!
CTP-API 是 C++版,程序员使用 JNA、JNI、COM 等技术转换很困难, 本程序基于上期 20160606_tradeapi_windows API 使用 bridj 纯 jni 技 术提供 JAVA-CTP-API。接口形式和使用流程基本等同 C++版本,学习 成本低,...
手写识别机器学习课程源码 原始码和视频教程 国际通用课程 国内知名 视频教程: : 课程目录 sklearn是一个强大的机器学习库,本套课程的目的就是在一周之内教会您使用机器学习技术。 第一章手写识别效果演示本课程...
Java监听键盘鼠标全局事件[定义].pdf
Java学习 本仓库记录了我的Java学习进阶之路,涵盖了Java基础,JDK源码,JVM中的重要知识,附有代码和博客讲解,... :演示了JNA的基本用法,使用Java调用C ++代码。 博客目录 Java基础 JDK原始码 虚拟机 联系作者
主要介绍了Java中枚举类型的一种使用方式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
它允许程序员在应用程序内部创建各种媒体处理管道,从简单的媒体播放到编码,实时流式传输,分析,机器学习, WebRTC等。 GStreamer被设计为跨平台的,并且为各种操作系统提供了二进制文件。 gst1-java-core已在...