好好生活,努力工作,天天向上!

          BlogJava 首頁 新隨筆 聯(lián)系 聚合 管理
            46 Posts :: 1 Stories :: 178 Comments :: 0 Trackbacks
                JNA全稱是Java Native Access,Sun推出的一種調(diào)用本地方法技術(shù),比起它的同門師兄JNI,JNA大大簡化了調(diào)用本地方法的過程,使用也比較方便, JNA是在JNI的基礎(chǔ)上完善的,用青出于藍(lán)而勝于藍(lán)來形容一點(diǎn)不為過,下面看一下JNI的調(diào)用過程:    

                

                使用JNI你得完成上面這些步驟,比較麻煩,而是用JNA就省事多了,基本上不需要脫離Java環(huán)境就可以完成。
            
             JNA項(xiàng)目主頁是https://jna.dev.java.net/, 目前最新的版本是3.2.4 。下載時記得將自帶的Example.jar 也下載下來,這個里面提供了一些JNA的例子,通過這個能夠更快的了解JNA

              使用JNA的調(diào)用本地方法的時候需要自定義數(shù)據(jù)結(jié)構(gòu),下面我們通過調(diào)用Windows提供的的鎖定工作站方法來了解一下JNA

              1首先查詢Windows API知道鎖定工作站的方法在user32.dll中定義,接下來定義一個接口來繼承JNALibrary.java接口,用作聲明DLL庫文件,這里我們就把它命名為User32:      

           public interface User32 extends Library {}

              2查詢user32.dll提供的API得知鎖定工作方法是LockWorkStation,返回類型是boolean型,在User32.java中新增相應(yīng)的方法:

          boolean LockWorkStation();

                   這樣我們的User32.java這個類就定義好了。接下來我們寫測試程序進(jìn)行調(diào)用。

              3、編寫測試類比如LockWorkStation.java,首先通過JNANative類加載對應(yīng)的dll:     

          User32 user32 = (User32) Native.loadLibrary("user32", User32.class);

                  然后就可以調(diào)用LockWorkStation方法了,完整代碼如下:      

          public class LockWorkStation {
              
          public static void main(String[] args) {
                 User32 user32 
          = (User32) Native.loadLibrary("user32", User32.class);
                 user32.LockWorkStation();
              }
          }

            這里說明一下loadLibrary方法中第一個參數(shù)是需要加載的dll文件名稱,第二個參數(shù)的作用是讓JNA使用這個類的加載器去加載DLL文件,加載順序是,先從Users.class類的當(dāng)前文件夾找,如果沒有找到,再在工程當(dāng)前文件夾下面找win32/win64文件夾,找到后搜索對應(yīng)的dll文件,如果找不到再到WINDOWS下面去搜索,再找不到就會拋異常了。以TWAINDSM.dll將文件放到工程的根文件夾可以按照下面這個格式放:

             上面的User32定義的是dll庫文件,有時會碰到比如HANDLE、POINT、WORD和MSG等數(shù)據(jù)類型,有些數(shù)據(jù)類型JNA中沒有提供,需要自己定義,根據(jù)作用的不同,定義的時候繼承的父類也不一樣,比如HANDLE定義方法是:
           class HANDLE extends PointerType {
                  
          private boolean immutable;
                  
          public HANDLE() { }
                  
          public HANDLE(Pointer p) { setPointer(p); immutable = true; }
                 
          public Object fromNative(Object nativeValue, FromNativeContext context) {
                      Object o 
          = super.fromNative(nativeValue, context);
                      
          if (INVALID_HANDLE_VALUE.equals(o))
                          
          return INVALID_HANDLE_VALUE;
                      
          return o;
                  }
                  
          public void setPointer(Pointer p) {
                      
          if (immutable)
                          
          throw new UnsupportedOperationException("immutable reference");
                      
          super.setPointer(p);
                  }
              }
              HANDLE被定義為類型安全的指針。而POINT用作表示坐標(biāo),不需要這么復(fù)雜,定義方式為:
           class POINT extends Structure {
                  
          public int x, y;
                  
          public POINT() { }
                  
          public POINT(int x, int y) { this.x = x; this.y = y; }
            }
             
               使用JNA的過程中也不一定會一帆風(fēng)順,比如會拋出”非法內(nèi)存訪問”,這時候檢查一下變量是否==null。還有內(nèi)存對齊的問題,當(dāng)從內(nèi)存中獲取圖片信息進(jìn)行保存的時候,如果內(nèi)存對齊處理不好,就會拋出很嚴(yán)重的異常,導(dǎo)致JVM異常退出,JNA提供了四種內(nèi)存對齊的方式,分別是:ALIGN_DEFAULTALIGN_NONEALIGN_GNUCALIGN_MSVCALIGN_DEFAULT采用平臺默認(rèn)的對齊方式(推薦);ALIGN_NONE是不采用對齊方式;ALIGN_GNUC為針對linux/gcc操作系統(tǒng)的對齊方式。ALIGN_MSVC為針對win32/msvc架構(gòu)的內(nèi)存對齊方式。

               JNA也提供了一種保護(hù)機(jī)制.比如防止JNA出現(xiàn)異常不會導(dǎo)致JVM異常退出,默認(rèn)是開啟這個功能的,開啟方式為System.setProperty(“jna.protected”,”true”); 記得要在JNA加載dll文件之前調(diào)用,然后try {...} catch(Throwable e)異常,不過你也不要期望過高,不要以為加上這個就萬事大吉,出現(xiàn)”非法內(nèi)存訪問”的時候還是會束手無策。JNA也提供了一種保護(hù)機(jī)制.比如防止JNA出現(xiàn)異常不會導(dǎo)致JVM異常退出,默認(rèn)是開啟這個功能的,開啟方式為System.setProperty(“jna.protected”,”true”); 記得要在JNA加載dll文件之前調(diào)用,然后try {...} catch(Throwable e)異常,不過你也不要期望過高,不要以為加上這個就萬事大吉,出現(xiàn)”非法內(nèi)存訪問”的時候還是會束手無策。
              
          posted on 2010-05-06 22:35 VWPOLO 閱讀(7984) 評論(5)  編輯  收藏 所屬分類: Java 技術(shù)

          Feedback

          # re: 使用JNA替代JNI調(diào)用本地方法 2010-05-06 22:55 草屋主人
          非常實(shí)用  回復(fù)  更多評論
            

          # re: 使用JNA替代JNI調(diào)用本地方法 2010-05-07 01:13 隔葉黃鶯
          JNA 應(yīng)該是個不錯的東西,當(dāng)初研究 JNative 的時候關(guān)注過它。  回復(fù)  更多評論
            

          # re: 使用JNA替代JNI調(diào)用本地方法 2010-05-07 13:53 99書城
          圣誕節(jié)開發(fā)商空間的肌膚  回復(fù)  更多評論
            

          # re: 使用JNA替代JNI調(diào)用本地方法 2010-05-08 09:32 BeanSoft
          感謝分享!  回復(fù)  更多評論
            

          # re: 使用JNA替代JNI調(diào)用本地方法 2010-06-18 10:32 飛熊
          同感@草屋主人
            回復(fù)  更多評論
            

          主站蜘蛛池模板: 满洲里市| 元朗区| 义马市| 高陵县| 揭阳市| 葫芦岛市| 汤阴县| 四子王旗| 南乐县| 和田县| 沂水县| 罗平县| 朔州市| 香港| 大同市| 平南县| 扎囊县| 体育| 锦州市| 苏州市| 长兴县| 兴化市| 东丰县| 象山县| 曲周县| 乌恰县| 哈密市| 比如县| 乐陵市| 大名县| 鹤山市| 朝阳县| 北海市| 博野县| 通州市| 潢川县| 衡山县| 得荣县| 吉林省| 调兵山市| 于都县|