11 Replies Latest reply on Jul 7, 2004 4:21 AM by dannyyates

    unsatisfiedLinkError generated when trying to access JNI met

    jikramer

      There have been a number of posts on this subject but I have not seen a solution

      http://www.jboss.org/index.html?module=bb&op=viewtopic&t=49043
      http://www.jboss.org/index.html?module=bb&op=viewtopic&t=46561
      http://www.jboss.org/index.html?module=bb&op=viewtopic&t=46420
      http://www.jboss.org/index.html?module=bb&op=viewtopic&t=26432
      http://www.jboss.org/index.html?module=bb&op=viewtopic&t=25059

      Here's the issue: I'm loading a .dll with System.load("myAbsolutePath/myDll.dll"); It looks to load it fine ( no error thrown when wrapping the above in a try/catch block ), but when I make the call to a method in the .dll, I get unsatisifed link error. The .dll is in the bin. I have tried System.loadLibrary(dll) with the .dll in the java.library.path. No good. I have tried the call to loadLibrary in a static method and a non static method. No good. I have moved the .dll to the location of the MBean. No good. I looked in the .dll & matched up the name of the method I think i'm calling to the ascii name in the .dll. No good. UGH!

      I'm using jboss version 3.0.7_jakarta-tomcat-4.1.24. I downloaded a later version ( 3.2 and 4.0 beta ) which gave me some other deployment dependencies that only obscures the issue.

      If anyone has successfully called a JNI .dll from an mbean, please post!

      Thanks!


        • 1. Re: unsatisfiedLinkError generated when trying to access JNI
          dannyyates

          What you are trying to do is disallowed by the J2EE spec. Having said that, JBoss does nothing specific to prevent you from using JNI.

          Have you managed to make this work outside the JBoss environment? i.e. write a simple standalone Java program and try it. Note that the method name mangling used by JNI needs to be adhered to, and the method exported from the DLL.

          • 2. Re: unsatisfiedLinkError generated when trying to access JNI
            jikramer

            Thanks for your post.

            Yes, calling this .dll works fine outside jboss. I have also looked inside the .dll to match up the method name i'm calling. it is "aaBond_crv1_java", and I have found "aaBond_crv1" in the .dll. I have tried both with success in my test program, but both give me the same unsatisfiedLinkError(nativeMethod) when I build & deploy my .jar.

            Actually I also tried the javah -jni className which generated the following method name:

            JNIEXPORT jdoubleArray JNICALL Java_ShowBondcrv1_aaBond_1crv1_1java
            (JNIEnv *, jobject, jdouble, jobjectArray, jobjectArray, jobjectArray, jint, jint, jint, jobjectArray, jint);

            Interestingly this did not work in the standalone.

            Any ideas?

            Thanks!

            • 3. Re: unsatisfiedLinkError generated when trying to access JNI
              dannyyates

              Are you sure this is right? This would imply a method called 1java in a class called 1crv1 in a package called ShowBondcrv1.aaBond. Neither the package name nor the class name follow normal Java naming conventions, and the method name is simply illegal.

              If your method name has _ characters in it, firstly consider renaming your method in accordance with traditional Java coding conventions. Secondly, you'll have to look at the JNI spec for how to encode those method names in C because the _ character has a special meaning in the C signature.

              The hashCode() method in java.lang.Object is native. It would require a C++ method with signature Java_java_lang_Object_hashCode(...)

              Also, note that if your DLL is written in C++, you'll need an extern "C" directive:

              extern "C" JNIEXPORT void JNICALL Java_java_lang_Object_hashCode(JNIEnv* env, jobject self)

              • 4. Re: unsatisfiedLinkError generated when trying to access JNI
                jikramer

                All I can say about this generated method name is that it does not work in the sample or in jboss. I'm getting this .dll & sample calling program from a 3rd party, but it does run fine standalone.

                So my bigger question here is more about insuring the .dll(s) are getting loaded property when i'm running jboss. Is there more to it then dumping necessary .dll's in the JBOSS bin and then pointing to them with System.load?


                Thanks

                • 5. Re: unsatisfiedLinkError generated when trying to access JNI
                  dannyyates

                  If System.LoadLibrary returns without an exception, the library loaded OK (I think).

                  I can't conceive of any legal Java method signature which the JVM would map to the C method signature you've quoted.

                  Tell me the full package name, class name and method name of the Java native method, and I'll tell you what the C method should look like.

                  • 6. Re: unsatisfiedLinkError generated when trying to access JNI
                    jikramer

                    This sample app works, but the same thing does not work in jboss.

                    here's the method name:

                    /* Prototype for Java Native Interface wrapper function from CJavaWrap.dll */

                    public native double[] aaBond_crv1_java(double d_v, double[][] cash_crv, double[][] fut_crv, double[][] bond_crv, int method_boot, int rate_basis, int acc_rate, double[][] hl,
                    int method_gen);

                    No package name in the sample program

                    and the class name: ShowBondcrv1.java.

                    As I mentioned earlier, looking inside the .dll, there exists a method aaBond_crv1.

                    Thanks





                    • 7. Re: unsatisfiedLinkError generated when trying to access JNI
                      dannyyates

                      I guess that would map to a C method called Java_ShowBondcrv1_aaBond_crv1_java, except that I'm not sure how the _ characters in the method name are handled. Looking at your earlier example, it might turn _ into _1, which would leave the C method as Java_ShowBondcrv1_aaBond_1crv1_1java, which is exactly what you said!

                      However, given that your DLL isn't exporting this method, I'm a bit stuck how it's working.

                      Is your simple app a Java app? Or is it a C app which uses JNI to go out to the Java and back to the C? It is possible (from the C side) to tell the JVM to override its normal mapping of Java names to C names.

                      So if your simple app is working, I suspect it is working in one of two ways:

                      1) It is a C application (.exe) which loads a JVM through the JNI Invokation API, and then explicitly tells the JVM to use the C aaBond_crv1 method when it encounters the particular Java native method, or

                      2) It's a Java application that first makes a call to a native initialisation method in the DLL which sets up the same mapping from Java method to C method which I've described above.

                      The JVM maps Java method names to C method names using the algorithm I've already described, or by being told explicitly what the mapping is for a given Java method. But this explicit mapping can only happen from C code (using a method called JNI_RegisterNatives, or something similar).

                      Anyway, this is really outside the scope of JBoss.

                      Things to try:

                      1) Is the sample app a native exe? If so, you might be stuck.
                      2) Is there a native init method that needs to be called?
                      3) Are you sure you're looking at the right DLL?
                      4) Are you sure JBoss is loading it? Try removing it and seeing if you get an exception. Try replacing it with a corrupt file (e.g. type a few words into Notepad, and save the file with a .DLL extension). This will prove that it's finding the file and trying to load it.
                      5) Are you sure you're calling System.loadLibrary before you're calling the native method?

                      • 8. Re: unsatisfiedLinkError generated when trying to access JNI
                        jikramer

                        The sample app is a java app.

                        Thanks for your ideas - here's where I stand:

                        1) Is the sample app a native exe? If so, you might be stuck.

                        --> Sample app is a java app.

                        2) Is there a native init method that needs to be called?
                        --> native init? unsure what you mean here.. when I call the method in the sample app, it works. When I call it from my app in jboss, no workie.

                        3) Are you sure you're looking at the right DLL?
                        --> yes

                        4) Are you sure JBoss is loading it? Try removing it and seeing if you get an exception. Try replacing it with a corrupt file (e.g. type a few words into Notepad, and save the file with a .DLL extension). This will prove that it's finding the file and trying to load it.

                        --> yes. without this .dll, it gives me an unsatisfiedLinkError(CWrapJava.dll). When I include the .dll in the jboss/bin directory & point to it through System.load, it loads it fine but fails when I call the method.

                        5) Are you sure you're calling System.loadLibrary before you're calling the native method?

                        Yes. I've tried this in a static method which got called when the object was loaded (constructed ), and also put it in the constructor.


                        • 9. Re: unsatisfiedLinkError generated when trying to access JNI
                          jikramer

                          this should not be so hard.. is it not possible through JBOSS? I have seen posts elsewhere that possibly the library is getting loaded > 1 time?! any way to verify or protect against this?

                          thanks

                          • 10. Re: unsatisfiedLinkError generated when trying to access JNI
                            jikramer

                            SOLUTION:

                            The java project we were working on was in a package. The .dll header needs to contain a package name for the JNI process to bind to it, so it needed to be recompiled with package name embedded in the method.

                            • 11. Re: unsatisfiedLinkError generated when trying to access JNI
                              dannyyates

                              Hmm... see when I talked about JNI method name mangling, and package names (repeatedly?) And you also told me that your code wasn't in a package!

                              Oh well. Glad you got it sorted.