2

私は JNI を使用して学校のプロジェクトに取り組んでいます。簡単に言えば、最初の部分は共有ライブラリと JNI を使用して動作するようになりましたが、2 番目の部分 (同じライブラリを参照) では、コードを実行しようとするたびに UnsatisfiedLinkError が返されます。私の教授と TA は皆、この問題を理解することができず、私は 1 週間以上デバッグしようとしています。

最初の部分は、独立して実行される .java プログラムです。整数のファイルと周波数が与えられると、C のネイティブ コードを呼び出して、直接フーリエ変換を計算し、与えられた周波数の値を返す必要があります。Java では、これらの int を配列に格納し、その配列を JNI に渡して C で DFT を計算しました。これにより、単一の int 値が返され、魔法のように機能します。

2 番目の部分では、JNI ライブラリをロードし、.wav ファイルまたは独自の形式のファイルを取り込む GUI インターフェイスを作成しました。この GUI は、ファイル チューザーから選択されたときにファイルの頻度を計算するために必要です。.wav ファイル (およびその他のタイプ) には、最初の部分のように整数ではなく、ヘッダー情報とバイナリ データが含まれているため、私の戦略は、ファイル名を (文字列として) JNI に渡し、ネイティブ コードがint 値を配列自体に分解し、ファイルの頻度を計算します。私の GUI は完成しました。チューザーからファイルを選択するアクション イベントは、JNI コードを呼び出して、ファイルの頻度を返すことになっています。興味深いことに、コードは Linux でコンパイルされ、ライブラリを正常にロードしますが、このリンク エラーでクラッシュします。ファイルが選択され、ファイルチューザーを使用してネイティブコードが呼び出されることになっている場合。私は完全かつ完全に挫折した敗北を喫しています。何か案は?

JNI によって生成されたヘッダー ファイルは次のとおりです。

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class dft */

#ifndef _Included_dft
#define _Included_dft
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     dft
 * Method:    computeDFT
 * Signature: ([III)I
 */
JNIEXPORT jint JNICALL Java_dft_computeDFT
  (JNIEnv *, jobject, jintArray, jint, jint);

/*
 * Class:     dft
 * Method:    computeFileDFT
 * Signature: (Ljava/lang/String;)I
 */
JNIEXPORT jint JNICALL Java_dft_computeFileDFT
  (JNIEnv *, jobject, jstring);

#ifdef __cplusplus
}
#endif
#endif

これが機能するコードです

public class dft
{
private native int computeDFT(int[] nums, int count, int freq);
private native int computeFileDFT(String fileName);

static
{
    /* 
     * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
     * SYSTEM LOAD LIBRARY PATH BELOW
     * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
     */
    System.loadLibrary("dft");
}

/**
 * @param args
 * @throws IOException 
 */
public static void main(String[] args) throws IOException
{
    File infile;
    Scanner sc = null;
    dft dft = new dft();
    int count = 0;
    int[] data = new int[4096];

    //code that reads the file and puts the content into an array called 'data'
            //the args[1] below is the specified frequency to be calculated in JNI

    int dftValue = dft.computeDFT(data, count, Integer.parseInt(args[1]));
    System.out.println(dftValue);
}

ここに問題のコードがあります

private native int computeFileDFT(String fileName);

static
{
    /* 
     * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
     * SYSTEM LOAD LIBRARY PATH BELOW
     * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
     */
    System.loadLibrary("dft");
    System.out.println("loaded successfully");
}

    //imagine more code here creating a JPanel object,
    //adding a bunch of stuff to it, etc. 
    //One key item that is added is a button, 
    //which when pressed opens a JFileChooser object, 
    //below you will see my implementation of the 
    //ActionListener which listens to the button and is 
    //supposed to execute the native code when the file is chosen.

private class TunerButtonListener implements ActionListener
{
    //@Override
    public void actionPerformed(ActionEvent event)
    {
        int returnVal = dialog.showOpenDialog(fileButton);
        if(returnVal == JFileChooser.APPROVE_OPTION) 
        {
            currentFileName = dialog.getSelectedFile().getName();
            currentFilePath = dialog.getSelectedFile().getPath();
            message.setText(currentFileName);


            int val = computeFileDFT(currentFilePath);
                    //more code goes here that does more stuff

完全なエラー メッセージとスタック

Exception in thread "AWT-EventQueue-0" java.lang.UnsatisfiedLinkError: TunerPanel.computeFileDFT(Ljava/lang/String;)I
at TunerPanel.computeFileDFT(Native Method)
at TunerPanel$TunerButtonListener.actionPerformed(TunerPanel.java:167)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2012)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2335)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:404)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)
at java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:289)
at java.awt.Component.processMouseEvent(Component.java:6389)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3268)
at java.awt.Component.processEvent(Component.java:6154)
at java.awt.Container.processEvent(Container.java:2045)
at java.awt.Component.dispatchEventImpl(Component.java:4750)
at java.awt.Container.dispatchEventImpl(Container.java:2103)
at java.awt.Component.dispatchEvent(Component.java:4576)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4633)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4297)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4227)
at java.awt.Container.dispatchEventImpl(Container.java:2089)
at java.awt.Window.dispatchEventImpl(Window.java:2518)
at java.awt.Component.dispatchEvent(Component.java:4576)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:672)
at java.awt.EventQueue.access$400(EventQueue.java:96)
at java.awt.EventQueue$2.run(EventQueue.java:631)
at java.awt.EventQueue$2.run(EventQueue.java:629)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:105)
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:116)
at java.awt.EventQueue$3.run(EventQueue.java:645)
at java.awt.EventQueue$3.run(EventQueue.java:643)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:105)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:642)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:275)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:200)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:190)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:185)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:177)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:138)
4

1 に答える 1

2

SO JNI サブカルチャーのどこにでもいるスマートな人々の膨大なコメント スレッドを読んでいると、何かが足りないかもしれませんが、私にはバグが明らかです。

class に対してネイティブ JNI lib を作成したdftため、ネイティブ関数はJava_dft_*. dftインスタンスのスコープで呼び出されると、実際に機能します。

次に、別のクラスを作成しますTunerPanelJava_TunerPanel_*もちろん、同じネイティブ メソッド シグネチャを宣言しますが、関数を含むライブラリはありません。と同じ元のライブラリを引き続き使用していJava_dft_*ます。

からインスタンスdftにアクセスできるようにしTunerPanelます。2 つの異なるクラスのネイティブ メソッドに同じネイティブ ライブラリを使用することはできません。または、ネイティブ メソッドを静的にします。FFT に関する私の理解では、実行間で永続的なデータを保持する必要はありませんcompute*

于 2012-11-08T10:00:27.450 に答える