私は 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)