12 Replies Latest reply on May 15, 2003 8:31 AM by davidoevans

    How to invoke DLL via JNI with 3.06

    hanswurst33

      I am trying to connect to a DLL via JNI, but I always get an UnsatisfiedLinkException.

      If you unpack the attached files to your deploy directory and acces localhost:8080/servlet/olaf you can see my problem. The dll ist loaded (server.log) but I am not able to access it.

      Does anyone know how to do that or do you know another way? Is there a resource adapter available, or a good book or tutorial?

      Thanks
      Olaf

        • 1. Re: How to invoke DLL via JNI with 3.06
          andygodwin

          I assume you're trying to load the native DLL using
          System.loadLibrary(String libname).

          IIRC, native libraries must be somewhere on the
          system path in order for the JVM to find them. So
          you could either change your path environment
          variable to include your lib directory (where the DLL
          lives) or copy the DLL to somewhere already on the
          path.

          Don't think there's any other way round this.

          HTH

          • 2. Re: How to invoke DLL via JNI with 3.06
            hanswurst33

            Hi,

            getting the DLL in the Systempath ist the problem.

            I tried putting in lib, ear in deploy (it gets deployed, but I can't access it) and most other directories.

            Usually you can load the library with java -Djava.library.path=..path to dll, but JBoss ignores it.

            I think this is a Classloader issue, but I'm not sure.

            Bye
            Olaf

            • 3. Re: How to invoke DLL via JNI with 3.06
              andygodwin

              I tried your zip file. Just copying the contents into
              the deploy directory gives me the following:

              java.lang.UnsatisfiedLinkError: no olafdll1 in java.library.path
              at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1403)
              ...

              as you'd expect.

              If I then copy olafdll1.dll from sim.ear\sim.jar\lib to,
              say, c:\winnt\system32 I get:

              java.lang.UnsatisfiedLinkError: berechne
              at de.olafthiele.Simulation.berechne(Native Method)
              ...

              Alternatively, if I add the lib directory to the path, eg

              PATH=%PATH%;j:\jboss\server\default\deploy\sim.ear\sim.jar\lib

              then restart, I get the same error.

              So it looks like the library has been loaded but the
              linker can't resolve the berechne method in the DLL.
              Are you sure your native methods have the right
              signature, as generated by javah? You've got
              extern "C" wrapped around your function
              declarations if it's C++ to avoid name mangling?

              • 4. Re: How to invoke DLL via JNI with 3.06
                hanswurst33

                Hi Andy,
                thank you for your help.

                I have attached a zip-file containing the dll and the jar. Just pure JNI.

                Try calling start.bat and it works, thats why I figured that it is a JBoss Classloader Problem instead of JNI. Nevertheless I will investigate your comments.

                Bye
                Olaf

                • 5. Re: How to invoke DLL via JNI with 3.06
                  hanswurst33

                  Hi Andy,
                  thank you for your help.

                  I have attached a zip-file containing the dll and the jar. Just pure JNI.

                  Try calling start.bat and it works, thats why I figured that it is a JBoss Classloader Problem instead of JNI. Nevertheless I will investigate your comments.

                  Bye
                  Olaf

                  • 6. Re: How to invoke DLL via JNI with 3.06
                    andygodwin

                    You're quite right, Olaf ... it works just fine on the
                    command line. Plus if I run dumpbin on the dll to view
                    the exports section the output looks OK:

                    ordinal hint RVA name

                    1 0 00001005 _Java_de_olafthiele_Simulation_berechne@16

                    So not sure what to suggest. I've done a fair bit of
                    JNI with JBoss and not had any problems before, so
                    maybe something has changed in more recent
                    versions. I'm going to try some of my old code, see if
                    it still works, I'll let you know if I find anything.

                    • 7. Re: How to invoke DLL via JNI with 3.06
                      andygodwin

                      Just a couple of thoughts...

                      Don't think it's a good idea to try and load a native
                      library twice so, since JARDeployer calls
                      System.load(..) if it finds a native library, remove
                      the DLL completely from the deploy directory and
                      put it somewhere on the system path.

                      Also make sure you're loading the library inside the
                      class that defines the native methods
                      (de.olafthiele.Simulation) inside a static initialiser, ie

                      static {
                      System.loadLibrary("olafdll1");
                      }

                      I think this might make a difference in JBoss where
                      there's lots of ClassLoaders about.

                      • 8. Re: How to invoke DLL via JNI with 3.06
                        andygodwin

                        Scratch that, I'm talking rubbish (wouldn't be the first
                        time).

                        What I've suggested will probably work, Olaf, but it's
                        not the best way to do it. If you put your DLL back in
                        your jar, then DON'T call System.loadLibrary(..), it
                        should all just work.

                        Last time I tried this, it didn't work, but it seems to
                        work fine now. The JarDeployer also neatly gets
                        round the redploy problems using System.loadLibrary()
                        by redeploying the native library from a different temp
                        directory every time.

                        I should read the freakin source code more often,
                        that's what it's there for!

                        • 9. Re: How to invoke DLL via JNI with 3.06
                          jcoughlin

                          I have encountered a problem that appears to be the same as Olaf's. A class that belongs to a package invokes a method in a DLL via JNI. As in Olaf's case, a test program that is run on the command line will successfully invoke methods within the DLL. The JBOSS server logs indicate that the DLL is being loaded successfully. However, any attempt to invoke methods within the DLL results in UnsatisfiedLinkException.

                          Olaf, did you get this to work ? Andy, you indicated that in the past it didn't work, and now it does. Can you clarify ?

                          TIA for any help.

                          • 10. Re: How to invoke DLL via JNI with 3.06
                            andygodwin

                            > Andy, you indicated that in the past it didn't work,
                            > and now it does. Can you clarify ?

                            I'm still looking at this one ... I thought I'd got it
                            working but turns out I didn't (late night or
                            something :)

                            I think it's a ClassLoader issue (Olaf was right all
                            along), and there's something wierd going on with
                            JBoss deployers!

                            However, one definite way to get native libraries to
                            work is as I suggested first:

                            1. put the native library somewhere in the system
                            path (ie NOT in the jar or sar and NOT in the JBoss
                            deploy or lib directory)
                            2. call System.loadLibrary(...) in your class that has
                            the native methods (in a static initialiser block or
                            somewhere that's only going to be executed once).

                            The only problem with this approach is you can't hot
                            redeploy your jar/sar, you'll get a ULE when you do,
                            so you have to restart the server. There are ways
                            round this, tho, if it's a big problem.

                            • 11. Re: How to invoke DLL via JNI with 3.06
                              davidoevans

                              I was having a similar problem including a system dll. The dll in question is to connect to a C API for a proprietary vector database so goal is to write BMP to it.

                              For initial testing, I just have a standalone class accessing the dll. However, I had a jboss.xml and ejb-jar.xml that had errors in it. Since I wasn't using these yet, I removed them from my EAR and redeployed. It now recognizes the DLL from the System path.

                              I'm now moving my test code into an entity bean so will have to include the appropriate descriptors for it. Fingers crossed I can get these descriptors correct without screwing up the System.loadLibrary (that is happening somewhere unknown to me as yet)

                              Still looking forward to a more definitive post but if anything comes about on my part, will let you know.

                              Cheers,

                              Dave./

                              • 12. Re: How to invoke DLL via JNI with 3.06
                                davidoevans

                                Sorry...I think i'm wrong...my results are inconsistent. I thought I got thru but have noticed that it only seems to get to my next call after I refreshed my JUnitEE app. My first call when the system is started is not finding the dll. My next call; either after refreshing my web app or hot deploying returns a null exception.

                                Also, i'm testing on both:

                                jboss-3.0.4_tomcat-4.1.12
                                jboss-3.2.1_tomcat-4.1.24

                                Results seem consistent between the two versions.

                                I'll try and stay quiet until I actually get data back from dll.

                                Cheers,

                                Dave./