user2991413
user2991413

Reputation: 551

Unable to load library in Maven project

I have a 3rd party native library (let's call it test.dylib) which I am trying to load through JNA in a Maven project. output of otool -L test.dylib is

/Library/Frameworks/test/Versions/A/test (compatibility version 1.0.0, current version 1.0.0)

   /System/Library/Frameworks/Cocoa.framework/Versions/A/Cocoa (compatibility version 1.0.0, current version 19.0.0)

   /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (compatibility version 300.0.0, current version 945.11.0)

   /usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)

   /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 65.1.0)

   /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 169.3.0)

   /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 744.1.0)

If I paste the test.dylib file at location "/Library/Frameworks/test/Versions/A/test " from otool -L output. And load the file through JNA, it works fine. But if I keep the test.dylib under resource folder, I get error.

java.io.IOException: Native library (darwin-x86-64/test.dylib) not found in resource path (/Users/username/Downloads/TestJNA/target/classes:

Even though I can see the dylib file present in /target/classes folder. Can someone suggest, how can I achieve calling dylib from resource folder? I don't want to paste the dylib file at this location "/Library/Frameworks/test/Versions/A/test".

This is how I am loading native library.

public class TestJNA {

     public interface Perception extends Library {
          Perception Instance = (Perception) Native.load("test",  Perception.class);

          void method1();
           int method2(int a, int b, int c);
     }
    public static void main(String[] args) { 
           Perception.Instance.method1();
           System.out.println(Perception.Instance.method2(1,2,3));
    }
}

Upvotes: 1

Views: 1268

Answers (1)

Daniel Widdis
Daniel Widdis

Reputation: 9121

While the error message you received only lists one search path, JNA actually checks multiple locations for your library. As documented in the NativeLibrary class javadocs:

A search for a given library will scan the following locations:

  1. jna.library.path User-customizable path
  2. jna.platform.library.path Platform-specific paths
  3. On OSX, ~/Library/Frameworks, /Library/Frameworks, and /System/Library/Frameworks will be searched for a framework with a name corresponding to that requested. Absolute paths to frameworks are also accepted, either ending at the framework name (sans ".framework") or the full path to the framework shared library (e.g. CoreServices.framework/CoreServices).
  4. Context class loader classpath. Deployed native libraries may be installed on the classpath under ${os-prefix}/LIBRARY_FILENAME, where ${os-prefix} is the OS/Arch prefix returned by Platform.getNativeLibraryResourcePrefix(). If bundled in a jar file, the resource will be extracted to jna.tmpdir for loading, and later removed (but only if jna.nounpack is false or not set).

You may set the system property jna.debug_load=true to make JNA print the steps of its library search to the console.

Note the os-prefix directory in item 4 above. You have included your library directly on the classpath (from the comments, /Users/username/Downloads/TestJNA/src/main/java/test.dylib). However, as the error message states, it needs to be in the darwin-x86-64/ directory on your classpath, e.g., /Users/username/Downloads/TestJNA/src/main/java/darwin-x86-64/test.dylib;

You may wish to use src/main/resources in preference to the java subdirectory for non-java code.

Your attempt to set the system library path to your raw source code directory doesn't work for the compiled code where it is looking in the target/classes directory structure.

Note that you can get further debugging information by setting the system property jna.debug_load=true.

Upvotes: 2

Related Questions