2011-01-14 48 views
16

パート1

jarとしてリリースするJavaアプリケーションを開発しています。このプログラムは、JNIが呼び出すC++外部ライブラリに依存します。それらをロードするには、絶対パスでメソッドSystem.loadを使用します。これは正常に動作します。Java - 相対パスでdllをロードしてjarファイル内に隠す

しかし、私は本当にJARの中にそれらを隠したいので、それらを収集するパッケージを作成しました。これにより、相対パス、つまりパッケージパスがロードされます。このアプローチでは、DLLをリンクすることや以前のインストールプロセスに飽きることなく、任意のディレクトリでJARを実行できます。

これは、予想される例外をスロー:

Exception in thread "main" java.lang.UnsatisfiedLinkError: Expecting an absolute path of the library

は、どのように私はこの作業を得ることができますか?

PART 2

フォルダにDLLをコピーする方法は、私は日食の環境の下でそれを実行したときのみ動作します(後述)。エクスポートされたJARを実行して、DLLのバイナリがうまく作成されますが、JNI 1をロードしている、次の例外がスローされます。私は、これはアクセス権限の問題になることができると思い

public static void loadBinaries(){ 
     String os = System.getProperty("os.name").toLowerCase(); 

     if(os.indexOf("win") >= 0){ 
      ArrayList<String> bins = new ArrayList<String>(){{ 
       add("/nm/metadata/bin/dependence1.dll"); 
       add("/nm/metadata/bin/dependence2.dll"); 
       add("/nm/metadata/bin/dependence3.dll"); 
       add("/nm/metadata/bin/dependence4.dll"); 
       add("/nm/metadata/bin/jniBin.dll"); 
      }}; 

      File f = null; 
      for(String bin : bins){ 
       InputStream in = FileManager.class.getResourceAsStream(bin); 
       byte[] buffer = new byte[1024]; 
       int read = -1; 
       try { 
        String[] temp = bin.split("/"); 
        f = new File(TEMP_FOLDER, temp[temp.length-1]);  
        FileOutputStream fos = new FileOutputStream(f); 

        while((read = in.read(buffer)) != -1) { 
         fos.write(buffer, 0, read); 
        } 
        fos.close(); 
        in.close(); 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } 
      } 

      System.load(f.getAbsolutePath()); 
     } 
    } 

Exception in thread "main" java.lang.reflect.InvocationTargetException

at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:56) 
Caused by: java.lang.UnsatisfiedLinkError: C:\Users\Supertreta\Desktop\nm files\temp\jniBin.dll: Can't find dependent libraries at java.lang.ClassLoader$NativeLibrary.load(Native Method) 

私はこのロードメソッドを実行しかし、それを解決する方法を知らない。どう思いますか?

+0

なぜあなたはそれらを非表示にしたいですか? –

+0

清潔な瓶を提供するには – supertreta

答えて

21

JARからDLLを直接ロードすることはできません。 DLLをJARからコピーするための中間段階をとる必要があります。次のコードは、それを行う必要があります。

public static void loadJarDll(String name) throws IOException { 
    InputStream in = MyClass.class.getResourceAsStream(name); 
    byte[] buffer = new byte[1024]; 
    int read = -1; 
    File temp = File.createTempFile(name, ""); 
    FileOutputStream fos = new FileOutputStream(temp); 

    while((read = in.read(buffer)) != -1) { 
     fos.write(buffer, 0, read); 
    } 
    fos.close(); 
    in.close(); 

    System.load(temp.getAbsolutePath()); 
} 
+0

これは、この問題を解決するためのすばやく簡単な方法です。私は試してみましたが、問題があります:createTempFileメソッドはファイル名に数字を追加します。つまり、 "hello.dll"は "hello.dll4975093656535427331"になります。私の主要なJNI dllも他のDLLに依存しているので、私はその名前を知っておく必要があります。私はこれにどのように対処できるのか知っていますか? – supertreta

+0

はい、 'File temp'が初期化される方法を変更してください:' File temp = new File(new File(System.getProperty( "java.io.tmpdir"))、name) '; –

+0

すべてのdllファイルをコピーしますが、JNIをロードすると、次の例外が発生します。スレッド "main"の例外java.lang.UnsatisfiedLinkError:C:\ Documents and Settings \ Administrator \ Local Settings \ Temp \ hello.dll :アプリケーション構成が正しくないため、このアプリケーションの起動に失敗しました。アプリケーションを再インストールすると、この問題が解決する可能性があります。私はすべてのライブラリが一時フォルダにあることを確認しました... – supertreta

2

これは基本的に動作するはずです。これがJNAのやり方なので、単にダウンロードしてコードを勉強してください。あなたも、このプラットフォームには依存しないようにいくつかのヒントを持っている...

EDIT

JNAが、それはランタイムウント負荷で正しいバイナリを解凍し、瓶内に沿ってそのネイティブコードをもたらします。これは、私があなたの質問が正しい場合には、従うべき良いパターンかもしれません。

+3

申し訳ありませんが、あなたの答えに何かお見逃しですか? 「これ」では何を参照していますか?ありがとう – supertreta

-1

あなたが総理にDLLの場所とクラスローダを必要とする - それは瓶からそれを抽出することなく読み込むことができます。ロードコールが実行される前の単純なもので十分です。あなたのメインクラスでは、以下を追加してください:issue with JNA and OSGi's handling of how the DLLs are loaded

+0

私はそれを正しく実行すると思います。私はEclipse上でデバッグしているとき、これはうまく動作します。この問題は、jarをエクスポートして実行すると表示されます。私は私の読み込み方法で答えを更新しました。ありがとう! – supertreta

+0

@supertreta:JARにDLLをパックしていないと思います。 JARの名前をzipファイルの名前に変更して調べてみてください。 –

+0

フォルダにdllを作成しているjarファイルが見えます。私はそれを実行する前にそれらを削除することを確認した。私は今それをzipで変換したことを確認しました、そして、彼らはそこにいます。 – supertreta

関連する問題