知识大全 用JNA保护你的传统代码

Posted 函数

篇首语:所谓的成熟、其实就是在不断看开狠多事情之后、更好的生活着。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 用JNA保护你的传统代码相关的知识,希望对你有一定的参考价值。

用JNA保护你的传统代码  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!

  Java 本地接入(JNA)主要是在Java世界和传统代码之间起到桥接作用 为什么JNA的存在如此重要呢?JNA可以有效避免重写传统代码 同样 JNA还意味着不再需要支付昂贵的桥接方案 后者包括代理安排 硬编码专有协议等 所有这些解决方案都是有难度且容易出错的 另一个关键的JNA要素是它还能有效取代Java本地接口(JNI)

  例一中展示了一组笔者将要在本文中寻找的代码 笔者从Windows Kernel DLL中引用了GetTickCount()程序 GetTickCount()返回了系统启动后所产生的毫秒数量        public interface CLibrary extends Library

  CLibrary INSTANCE = (CLibrary)

  Native loadLibrary((Platform isWindows() ? kernel : c )

  CLibrary class);

  int GetTickCount();

  

  public static void main(String[] args)

  System out println( TickCount + CLibrary INSTANCE GetTickCount());

  

  例 简单的JNA示例

  例一中有趣的一件事情是不再需要JNI代码 相反 你只需从Java代码中调用一个DLL符号 不需要映射和自动生成JNI标头文件 使用JNA你只需简单加载所需库 映射感兴趣的符合然后引用这些符号就可以了

  总之 毫无疑问 JNA解决方案可以节约成本 它能直接调用传统代码从而避免一切使用JNI的请求或是重写传统代码的需要 或许JNA最重要的一方面是它具备统一的代码环境 但是 其他与JNA相关的事物会干涉本地代码区域 其中之一就是要决定Java是否是所谓的系统语言

  Java 不是系统语言?

  初期外界针对Java提出主要质疑是它并非是一个系统语言 与C或C++不同 Java存在于JVM之中 不能访问低级别的机器指定型细节信息只有通过高级别的API才能对其进行访问 Java这样的相对独立性带来的一大优点是其安全性 也就是说JVM死机的时候 整个系统不一定会死机

  JNA的出现改变了这一状况 因为现在Java代码可以访问C类型机制 例二展示了另一个通过Windows kernel DLL函数访问数据的Java代码示例

        Kernel lib = Kernel INSTANCE;

  SYSTEMTIME time = new SYSTEMTIME();

  lib GetSystemTime(time);

  System out println( Today s integer value is + time wDay);

  例二 Kernel 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++ 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 /divider;

  

  不要担心例三中的细节 其中大部分都是自动生成 其中重要的部分是名为helloWorld()的函数 该函数通过整数参数来传递并将其划分为固定值 显然 这还不是标准结果 稍后 笔者会使用例三中的代码安排来模拟其分离过程以便看清楚JNA中发生的一切

  让我们迅速了解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 INSTANCE = (CLibrary)

  Native loadLibrary((Platform isWindows() ? nativecode : c )

  CLibrary class);

  int helloWorld(int divider);

  

  public static void main(String[] args)

  CLibrary INSTANCE helloWorld( ));

  

  在例四中 创建了一个Clibrary实例 该对象允许加载指定的DLL 参考下面的库加载过程 所需的库符号被映射了 在例四中 只有一个名为helloWorld()的符号

  例五展示了从例四代码中输出的程序

  C:\\jnacode>java HelloWorld

  Value is

  在例五中没有什么令人惊讶的地方——数值 被发送到函数中 参数( )随后被函数中的 分割以生成答案

  当笔者尝试找出与调用惯例相关的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 sun jna Function (Function java: )

  at sun jna NativeLibrary getFunction(NativeLibrary java: )

  at sun jna Library$Handler invoke(Library java: )

  at $Proxy helloWorld(Unknown Source)

  at HelloWorld main(HelloWorld java: )

  笔者之所以将这一情况列出来是因为自己也是突然遇到这一情况 因此这完全是一个证明JNA可行的例子 这与JNI有什么关系呢?

  告别JNI

  在使用JNI来连接大型Java和C++代码库时 有时 Java和C++代码会一起被传送 但是每次都造成死机 在这样的情况下 Java和C++程序员往往开始互相指责

  解决这一纷争的一项方案是为两种代码运行一套清单目录 例如 在C代码中

  ·数组越界了吗?

  ·空的指示针是否被废弃?

  ·动态内存是否被正确分配了?

  JNA可以结束这一切疑问

  库许可证问题

  JNA中有趣的一面在于它为Java访问DLL打通了一条捷径 这也同样可以应用于其他库技术 如共享Unix库 这对于授权的软件组件意味着什么呢?JNA的使用或许能有效访问授权库代码 该问题的另一个方面是JNA代码可能允许对安全限制库代码的访问

  除了上述情况的考虑 访问传统代码的能力也为Java和传统代码之间的接口例外开辟了其他可能性 请看下列代码

  重新调用例三中的代码 如果键入 并引发 divide by zero异常 会发生什么?

  

         public interface CLibrary extends Library

  CLibrary INSTANCE = (CLibrary)

  Native loadLibrary((Platform isWindows() ? nativecode : c )

  CLibrary class);

  int helloWorld(int divider);

  

  public static void main(String[] args)

  CLibrary INSTANCE helloWorld( ));

  System out println( Value: + CLibrary INSTANCE helloWorld( ));

  

  当笔者指定上述代码时 系统给出了下列回复

         C:\\jna_article\\jnacode>java HelloWorld

  Value is

  #

  # An unexpected error has been detected by HotSpot Virtual Machine:

  #

  # EXCEPTION_INT_DIVIDE_BY_ZERO ( xc ) at pc= x b pid= tid=

  

  #

  # Java VM: Java HotSpot(TM) Client VM ( _ b mixed mode)

  # Problematic frame:

  # C [nativecode dll+ x ]

  #

  # An error report file with more information is saved as hs_err_pid log

  #

  # If you would like to submit a bug report please visit:

  #

  或许这些并不好看 但是我们确实会获取一些追踪输出 但是将其扩展到真实世界的实例 想象一下如果继续在大型代码库中进行追踪会怎样?总之 JNA的功能是很强大的

  结语

cha138/Article/program/Java/hx/201311/26050

相关参考

知识大全 运用JNA保护你的遗留代码(二)

运用JNA保护你的遗留代码(二)  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  从Java中引用

知识大全 保护你的代码——谁动了我的组件

  摘要本文描述了如何用CodeAccessSecurity技术来保护代码使代码不致被恶意调用  作为一名NET开发人员你没日没夜地写代码你的组件运行在越来越多的机器上忽然有一天你发现你写的组件被引用

知识大全 JNA调用DLL一点小结

JNA调用DLL一点小结  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  &n

知识大全 需代码..

求高手指导~~如何做一个电子商务交易系统,要能用浏览器看到.谢谢啦!需代码..有时间可以处理你的问题我们可以根据你的需求提供一份适用于学生水平的程序为获取帮助,你需要提供有效的电子邮件地址。您可以凭借

知识大全 使用OracleWrap工具加密你的代码

使用OracleWrap工具加密你的代码  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  Orac

知识大全 六大代码问题检验你的Java知识

六大代码问题检验你的Java知识  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  你觉得自己是一个

知识大全 怎样保护你的.NET程序

怎样保护你的.NET程序  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  摘要阐述怎样保护用Mic

知识大全 利用DES加密算法保护Java源代码

利用DES加密算法保护Java源代码  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  Java语言

知识大全 使你的主页千变万化

不少网友发E-mail问我怎么每次去你的主页看到的图片都不一样难道你时时刻刻都在更换图片吗?天啊我哪有那么多钱支付电话费?我只不过用了JavaScript的小技巧做了个随机图片而已其HTML源代码为 

保护性耕作技术

一、保护区性耕作保护性耕作是相对于传统翻耕的一种新型耕作技术。它的定义是:“以机械化作业为主要手段,采取少耕或免耕方法,将耕作减少到只要能保证种子发牙即可,用农作物秸秆及残茬覆盖地表,并主要用农药来控