9 Replies Latest reply on Apr 1, 2005 4:26 AM by ramses

    Can not invoke a native method

    ramses

      Hi,

      I have found any topics for this problem, but all of them have no solution for it. Therefore a new topic.
      JBoss 4.0.1 and Java 1.4.2_02

      I have put a native library (xxx.dll) in the rar file (as the connector specification defines). During startup the RARDeployer (SubDeployerSupport) loads the library.
      But when the adaptor (which is loaded by an UnifiedClassLoader3) invokes the native method (e.g: Jni_ft_showdir), an UnsatisfiedLinkError is thrown.

      java.lang.UnsatisfiedLinkError: Jni_ft_showdir .....where Jni_ft_showdir is the name of the native method

      Maybe a ClassLoader Problem. But what is the solution?


      When I move the native library in a directory of the PATH and the adaptor calls System.loadLibrary then it works.

      BUT when I redeploy the adapter, the System.loadLibrary("xxx") throws an
      UnsatisfiedLinkError (Native Library xxx.dll already loaded in another classloader).
      When I ignore the error, and invoke the method, an
      UnsatisfiedLinkError: Jni_ft_showdir
      is thrown.

      Have anybody an idea?
      Thank you for your assistance
      Ramses


        • 1. Re: Can not invoke a native method
          starksm64

          Classpaths are not used to load native libraries. System specific paths are like PATH and LD_LIBRARY_PATH so that is where the lib needs to be. There is no way to reload a dynamic library in java.

          • 2. Re: Can not invoke a native method
            ramses

            Means that, that JBoss can not handle native librarys for an adapter!

            The Connector Architecture Specification Version 1.5 chapter 17.2 Packaging specifies to put an native library in the rar archive.

            1) JBoss loads the native library during the deployment (class SubDeployerSupport). But when a native method is invoked an
            UnsatisfiedLinkError with the method name is thrown.

            This occures, because the native library is loaded in a different classloader (NoAnnotationURLClassLoader) as the class which invokes the native method(UnifiedClassLoader3).

            2) JBoss loads the native library during redeployment once more and get an UnsatisfiedLinkError (already loaded in another classloader)


            How should I handle native libraries for an adapter.


            Thank you for your assistance
            Ramses

            • 3. Re: Can not invoke a native method

              This has nothing to do with the spec and everything to do with OS configuration
              and java limitations.

              1) You cannot load the library.
              This is because JBoss unpacks the dll to

              ${jboss.server.home.dir}/tmp/native
              

              which is not in your library path.

              We make no attempt to modify your library path.

              You can either:
              a) raise a feature request to add new behaviour
              http://jira.jboss.com/jira/browse/JBAS
              that allows this location to be overriden using a system property, e.g.
              run.bat -Djboss.native.dir=d:\some\other\place
              

              which is a location you can add to your library path, JBoss would then unpack
              the library to that location
              b) provide a patch that modifies run.bat to include that directory in the
              library path.

              2) Redeployment
              This has nothing todo with NoAnnotationURLClassLoader.
              Java does not even use classloading scope to load libraries.

              The problem is caused because the classloader (the unified classloader)
              is not garbage collected yet.
              Your Objects -> Class -> UCL3 -> native library
              Once the GC has figured out they are no longer used (they are undeployed)
              it will unload the library.

              UnsatisifiedLinkError
              Where the NoAnnotationURLClassLoader does cause a problem
              is that the GC will not even try to unload the library until this classloader
              is no longer referenced (which is never/shutdown).

              Bug Report:
              http://jira.jboss.com/jira/browse/JBAS-1619

              • 4. Re: Can not invoke a native method
                ramses

                @ 1)
                JBoss can load the native library. The SubDeployerSupport.class uses the method System.load with the full qualified filename (e.g: /home/rameder/jboss/server/sx/tmp/native/libopenFTjni.so) of the native library, therefore no java.library.path has to be set.

                I can see this in the loggings (no exception during first deployment).

                When the native method is invoked an
                UnsatisfiedLinkError with the method name is thrown.

                I can reproduce this behaviour in a small test example without JBoss.
                see http://forum.java.sun.com/thread.jspa?messageID=3366590

                Therfore my allegation, that the class which invokes the native method, and the native library has to be loaded by the same classloader.

                I have tested with your propsal (start JBoss with java.library.path) also, but with the same result

                @ 2) Bug Report
                How will you ensure, that the GC runs (unload a native library) between a redeployment.


                Thank you for your assistance
                Ramses

                • 5. Re: Can not invoke a native method

                   

                  "ramses" wrote:

                  @ 2) Bug Report
                  How will you ensure, that the GC runs (unload a native library) between a redeployment.


                  I/we do not control the GC. Hence Scott's comment about not being
                  able to redeploy native code.

                  • 6. Re: Can not invoke a native method

                     

                    "ramses" wrote:
                    @ 1)
                    JBoss can load the native library. The SubDeployerSupport.class uses the method System.load with the full qualified filename (e.g: /home/rameder/jboss/server/sx/tmp/native/libopenFTjni.so) of the native library, therefore no java.library.path has to be set.

                    I can see this in the loggings (no exception during first deployment).

                    When the native method is invoked an
                    UnsatisfiedLinkError with the method name is thrown.

                    I can reproduce this behaviour in a small test example without JBoss.
                    see http://forum.java.sun.com/thread.jspa?messageID=3366590

                    Therfore my allegation, that the class which invokes the native method, and the native library has to be loaded by the same classloader.

                    I have tested with your propsal (start JBoss with java.library.path) also, but with the same result


                    I do not write code to implementation details, that just makes for nonportable
                    code across jvms. The spec says any classloader scoping is not used for loading,
                    which makes sense since you can't scope dlls bound in the runtime.
                    In anycase, the fact that the deployer framework loads the library is wrong,
                    so the problem is mute.

                    • 7. Re: Can not invoke a native method
                      ramses

                      Excuse, if I bother you once again.

                      How the solution will be ?

                      The class(es) which invokes the native method, has also load the native library. JBoss will not any longer load the native libraries.

                      A redeployment with native libraries is not possible.

                      Is this correct?

                      br
                      Ramses

                      • 8. Re: Can not invoke a native method

                         

                        "ramses" wrote:
                        Excuse, if I bother you once again.

                        How the solution will be ?

                        The class(es) which invokes the native method, has also load the native library. JBoss will not any longer load the native libraries.

                        Correct


                        A redeployment with native libraries is not possible.


                        It will be possible if you wait long enough for the GC to unload the library
                        before redeploying. We could add a System.gc() to the undeploy to give it a hint
                        but we generally recommend you disable explicit gc to stop RMI killing your
                        performance.

                        • 9. Re: Can not invoke a native method
                          ramses

                          Hi,

                          Thank you very much for the fast correction.

                          Regards,
                          Ramses