Problem in connecting Java and CUDA

Hi all,

I am having problem in connecting Java and CUDA using JNI. The dll has been generated and copied to the PATH; and the JAVA interface can be displayed correctly. But as soon as I evoke the action to call the native method, a “source not found” error shows in the debug perspective in eclipse. When I clicked on the Resume button, the following errors are shown:

Exception in thread “AWT-EventQueue-0” java.lang.UnsatisfiedLinkError: pt.PTMainPanel.run(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V

at pt.PTMainPanel.run(Native Method)

at pt.PTMainPanel$ComponentListener.actionPerformed(PTMain.java:317)

at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)

at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)

at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)

at javax.swing.DefaultButtonModel.setPressed(Unknown Source)

at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)

at java.awt.Component.processMouseEvent(Unknown Source)

at javax.swing.JComponent.processMouseEvent(Unknown Source)

at java.awt.Component.processEvent(Unknown Source)

at java.awt.Container.processEvent(Unknown Source)

at java.awt.Component.dispatchEventImpl(Unknown Source)

at java.awt.Container.dispatchEventImpl(Unknown Source)

at java.awt.Component.dispatchEvent(Unknown Source)

at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)

at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)

at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)

at java.awt.Container.dispatchEventImpl(Unknown Source)

at java.awt.Window.dispatchEventImpl(Unknown Source)

at java.awt.Component.dispatchEvent(Unknown Source)

at java.awt.EventQueue.dispatchEvent(Unknown Source)

at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)

at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)

at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)

at java.awt.EventDispatchThread.pumpEvents(Unknown Source)

at java.awt.EventDispatchThread.pumpEvents(Unknown Source)

at java.awt.EventDispatchThread.run(Unknown Source)

public class PTMain {

   static {

        System.out.println(System.getProperty("java.library.path"));

        System.loadLibrary("SW2D_JNI");

    }

   public static void main(String args[]) {

        PTMainFrame frame = new PTMainFrame();

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.show();

    }

}

class PTMainFrame extends JFrame {

   class PTMainPanel extends JPanel {

   ...

       public native void run(String s1, String s2, String s3, String s4, int type);

      

       private class ComponentListener implements ActionListener {

       ...

          public void actionPerformed(ActionEvent event) {

          ...

            (line 317) run(SEQ1_TXT.getText(), SEQ2_TXT.getText(), SEQ3_TXT.getText(), SEQ4_TXT.getText(), 1);

           ...

           }

        }

    }

}      
JNIEXPORT jstring JNICALL Java_pt_PTMainPanel_run

  (JNIEnv *env, jobject obj, jstring s1, jstring s2, jstring s3, jstring s4, jint type)

   //jsize (JNICALL *GetStringLength)

   //   (JNIEnv *env, jstring str);

   int targetSize=env->GetStringLength(s1);

   int querySize=env->GetStringLength(s2);

   if(targetSize==0 || querySize==0){

     printf("File error!\n");

     exit(1);

   }

   targetSize +=1;

   querySize +=1;

  char *targetSeq,*querySeq,*targetTemp,*queryTemp;

   targetSeq = (char*)malloc(targetSize*sizeof(char));

   memset(targetSeq,'\0',targetSize*sizeof(char));

   querySeq = (char*)malloc(querySize*sizeof(char)); 

   memset(querySeq,'\0',querySize*sizeof(char));

   targetTemp = (char*)malloc((targetSize-1)*sizeof(char));

   memset((targetTemp-1),'\0',targetSize*sizeof(char));

   queryTemp = (char*)malloc((querySize-1)*sizeof(char)); 

   memset(queryTemp,'\0',querySize*sizeof(char));

   int i;

   env->GetStringUTFRegion(s1,i-1,1,targetTemp);

   env->GetStringUTFRegion(s2,i-1,1,queryTemp);

   for(i=targetSize-1; i>0; i--){

      *(targetSeq+i) = *(targetTemp+(i-1));

   }

   targetSeq[0] = 'a'; 

   for(i=querySize-1; i>0; i--){

      *(querySeq+i) = *(queryTemp+(i-1));

   }  

   querySeq[0] = 'a'; 

  char *res = runMain(type,targetSeq,targetSize,querySeq,querySize);

   return env->NewStringUTF(res);

}

Is it because the dll not found? How should I solve it?

Any idea will be appreciated!

Thanks a lot!!

  1. Your PTMainPanel class is internal, this may cause the problem. Make it a usual public class.
  2. If you placed sources in “project/src” directory, then (If you run application from eclipse) your dll should be named “project/SW2D_JNI.dll”. Also, check the name of exported function in dll - search for word Java_pt_PTMainPanel_run in .dll file and check that there aren’t any preficies and sufficies.

i recommend that you split your program up a little bit

a) first an util class which provides the native methods

now you write some simple junit tests, to make sure it always works

B) once your utility class is done you can write you stuff around it like JFrames and so on.

This approach makes lives much easier.

so back to the beginning this gives us now something like:

Util Class

public class PTUtil {

  static {

       System.out.println(System.getProperty("java.library.path"));

       System.loadLibrary("SW2D_JNI");

   }

   public native void run(String s1, String s2, String s3, String s4, int type);

}

A simple test class

public class PTUtilTest {

   @Test

    public void runTest(){

        

        String s1 = ....;

        String s2 = ....;

        String s3 = ....;

        String s4 = ....;

        int type = 0;

       new PTUtil().run(s1,s2,s3,s4,type);

    }

}

Now your Frame

class PTMainFrame extends JFrame {

...

  class PTMainPanel extends JPanel {

  ...

     

      private class ComponentListener implements ActionListener {

      ...

         public void actionPerformed(ActionEvent event) {

         ...

           new PTUtil().run(SEQ1_TXT.getText(), SEQ2_TXT.getText(), SEQ3_TXT.getText(), SEQ4_TXT.getText(), 1);

          ...

          }

       }

   }

}

i guess you also need to make your method “static”

at least if I look at some code i did with java/jni/C i always had to use static. An example would be here

link to a jacuda class

Thanks a bunch for all you replies.

I read the dll file and found the native method’s name is odd. Instead of being something like Java_pt_PTMainPanel_run (Ordinal: 2, Entry Point RVA: 11d0h (4,560)), it is ?Java_pt_PTMainPanel_run@@YGPAV_jstring@@PAUJNIEnv_@@PAV_jobject@@PAV1@222H@Z (Ordinal: 1, Entry Point RVA: 1030h (4,144)).

How should I create a correct dll file? BTW, do I need to copy the cuda’s DLLs to the PATH?

Thanks!!!

You forgot to include the .h file created by javah and thus your compiler created a C++ function instead of a C function. JNI only supports C functions!

And the snarky comment I can’t resist: using C++ does not mean you can get away without learning all the low-level C stuff, you just have to learn a lot more in addition :P

so true…

Thanks for your reply, Reimar. But I do have included the .h created by javah. Any other possibility that occurs this problem?

Your function declaration must completely match the one in the .h file, you did not copy the extern “C” part.

I missed this because I am used to C where the compiler can and will warn you about such mistakes.