6

JNIを使​​用しようとして、java.lang.UnsatisfiedLinkErrorを取得しています。これについて尋ねられた他の百万の質問とは異なり、私は自分の道にlibを持っており、それを削除すると例外の変化さえ見ました。作成したdllに問題があることは確かですが、何が原因かわかりません。

これが私のJavaクラスコードです:

package com;

public class Tune {
    static {
        System.loadLibrary("lala");
    }
    public static void main(String[] args) {
        Tune j = new Tune();
        System.out.println("2+6="+j.add(2, 6));
    }
    native public int add(int x,int y);
}

これが私のjavahで生成されたヘッダーファイルの要約部分です:

/*
 * Class:     com_Tune
 * Method:    add
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_com_Tune_add
  (JNIEnv *, jobject, jint, jint);

これが私のc++コードです:

#include <jni.h>
#include <com_Tune.h>

JNIEXPORT jint JNICALL Java_com_Tune_add
  (JNIEnv * env, jobject obj, jint x, jint y) {
    return x+y;
  }

Eclipseから取得するランタイム例外は次のとおりです。

Exception in thread "main" java.lang.UnsatisfiedLinkError: com.Tune.add(II)I
    at com.Tune.add(Native Method)
    at com.Tune.main(Tune.java:9)

上記の例外は、ライブラリ「lala」がDIDで検出されたことを意味しますが、メソッド「add」はまだ定義されていないことを読みました。プロジェクトとチュートリアルで異なるのは次のとおりです。

  • 私はデフォルトのパッケージの代わりにパッケージを使用しています(チュートリアルは実際にこれを行うべきではありませんか?!?!さあ、プロになりましょう)
    • 鉱山には戻り値があります。
    • 作成後にdllを移動しました(パスが構成されているため、これによってdllが破損することはないと思います)。

これはどのように可能ですか?

他の情報:

OS:Windows 7
JDK:1.6.0_31(x86、32ビットjvmの場合)
C ++ IDE:Code :: Blocks(dllはCode :: Blocks IDEによって自動的にコンパイルされました)
C ++コンパイラ:MinGW32-g ++(GNU C ++コンパイラ)

C:\ _ \ include
にjni.hとcom_Tune.hがあります。C:\ _\libにlala.dllがあります。

環境変数:
パス:C:\ Program Files(x86)\ NVIDIA Corporation \ PhysX \ Common;%CommonProgramFiles%\ Microsoft Shared \ Windows Live; C:\ Program Files(x86)\ AMD APP \ bin \ x86_64; C:\プログラムファイル(x86)\ AMD APP \ bin \ x86;%SystemRoot%\ system32;%SystemRoot%;%SystemRoot%\ System32 \ Wbem;%SYSTEMROOT%\ System32 \ WindowsPowerShell \ v1.0 \; C:\ Program Files( x86)\ ATI Technologies \ ATI.ACE \ Core-Static; C:\ Apps;%JAVA_HOME%\ bin; C:\ Program Files \ MySQL \ MySQL Server 5.5 \ bin;%MAVEN_HOME%\ bin;%HADOOP_INSTALL%\ bin ; c:\ Program Files(x86)\ Microsoft SQL Server \ 100 \ Tools \ Binn \; c:\ Program Files \ Microsoft SQL Server \ 100 \ Tools \ Binn \; c:\ Program Files \ Microsoft SQL Server \ 100 \ DTS \ Binn \; C:\ MinGW \ bin; C:\ Program Files(x86)\ GnuWin32 \ bin; C:_ \ path; C:\ _ \ lib; C:\ Program Files(x86)\ Microsoft Visual Studio 10.0 \ VC \ bin; C:\ _ \ include

4

5 に答える 5

4

問題は、コンパイラが生成した名前にあります。Java_com_Tune_add@16

2つのいずれかを使用します

gcc -Wl,-kill-at

または

gcc -Wl,--add-stdcall-alias

これにより、Java_com_Tune_addが確実に生成されます。

そして、メソッド呼び出しは成功します。

于 2012-10-03T11:40:12.530 に答える
2

問題の原因の1つとして、プレーンCとは異なる[呼び出し規約]を使用するC ++コンパイラを使用してコードをコンパイルしたことが考えられます。その場合、解決策は、メソッドのコードを次のextern "C"ようなブロックにラップすることです。これ:

#ifdef __cplusplus
extern "C" {
#endif

JNIEXPORT jint JNICALL Java_com_Tune_add
...

#ifdef __cplusplus
}
#endif
于 2012-02-20T20:19:10.690 に答える
1

推測するだけです...あなたのdllはパス上にない別のdllに依存していますか?MinGWモジュールは通常、特定のCランタイムライブラリに依存します。

于 2012-02-20T20:44:47.760 に答える
0

私は同じ問題を抱えていて、フラグ-Wl、-kill-atが私のために働いた。

于 2013-07-18T12:36:22.367 に答える
0

Windowsの次の例を試してください:(Javaクラス名は対応するファイル名と同じである必要があることに注意してください)

手順1.次のJavaファイル(P.java)を作成します。

class P
{
  static
  {
    // "P" is the name of DLL without ".dll"
    System.loadLibrary ("P");
  }

  public static native void f(int i);

  public static void main(String[] args)
  {
    f(1);
  }
}

ステップ2.javacP.java

ステップ3.javahP

次に、「javah」はヘッダーファイル「Ph」を生成します

ステップ4.次の2行を含むファイル「P.def」を作成します(このファイルは、エクスポートされたシンボル、この場合はC関数の名前を定義します)。

EXPORTS
Java_P_f

ステップ5.Cファイル(Pc)を作成します。

#include "P.h"

JNIEXPORT void JNICALL Java_P_f(JNIEnv *env, jclass c, jint i)
{
  printf("%i\n",i);
}

手順6.VisualStudioコマンドpromt内で、次の変数を定義します。

設定JAVA_HOME=JDKのパス

set include =%include%;%JAVA_HOME%\ include;%JAVA_HOME%\ include \ win32

ステップ7.DLLを生成します。

cl / LD Pc P.def

ステップ8.Javaプログラムを実行します。

java P

(注:P.dllとP.classは同じディレクトリにあります)

于 2013-11-26T16:35:55.227 に答える