Provides management of native library resources. One instance of this class corresponds to a single loaded native library. May also be used to map to the current process (see NativeLibrary#getProcess()). Library Search Paths A search for a given
| 85 | * @author twall |
| 86 | */ |
| 87 | public class NativeLibrary implements Closeable { |
| 88 | |
| 89 | private static final Logger LOG = Logger.getLogger(NativeLibrary.class.getName()); |
| 90 | private static final Level DEBUG_LOAD_LEVEL = DEBUG_LOAD ? Level.INFO : Level.FINE; |
| 91 | private static final SymbolProvider NATIVE_SYMBOL_PROVIDER = new SymbolProvider() { |
| 92 | @Override |
| 93 | public long getSymbolAddress(long handle, String name, SymbolProvider parent) { |
| 94 | return Native.findSymbol(handle, name); |
| 95 | } |
| 96 | }; |
| 97 | |
| 98 | private final Cleaner.Cleanable cleanable; |
| 99 | private volatile long handle; |
| 100 | private final String libraryName; |
| 101 | private final String libraryPath; |
| 102 | private final Map<String, Function> functions = new HashMap<>(); |
| 103 | private final SymbolProvider symbolProvider; |
| 104 | private final int callFlags; |
| 105 | private final String encoding; |
| 106 | private final Map<String, ?> options; |
| 107 | |
| 108 | private static final Map<String, Reference<NativeLibrary>> libraries = new HashMap<>(); |
| 109 | |
| 110 | private static final Map<String, List<String>> searchPaths = new ConcurrentHashMap<>(); |
| 111 | private static final LinkedHashSet<String> librarySearchPath = new LinkedHashSet<>(); |
| 112 | |
| 113 | static { |
| 114 | // Force initialization of native library |
| 115 | if (Native.POINTER_SIZE == 0) |
| 116 | throw new Error("Native library not initialized"); |
| 117 | } |
| 118 | |
| 119 | private static String functionKey(String name, int flags, String encoding) { |
| 120 | return name + "|" + flags + "|" + encoding; |
| 121 | } |
| 122 | |
| 123 | @SuppressWarnings("LeakingThisInConstructor") |
| 124 | private NativeLibrary(String libraryName, String libraryPath, long handle, Map<String, ?> options) { |
| 125 | this.libraryName = getLibraryName(libraryName); |
| 126 | this.libraryPath = libraryPath; |
| 127 | this.handle = handle; |
| 128 | this.cleanable = Cleaner.getCleaner().register(this, new NativeLibraryDisposer(handle)); |
| 129 | Object option = options.get(Library.OPTION_CALLING_CONVENTION); |
| 130 | int callingConvention = option instanceof Number ? ((Number)option).intValue() : Function.C_CONVENTION; |
| 131 | this.callFlags = callingConvention; |
| 132 | this.options = options; |
| 133 | SymbolProvider optionSymbolProvider = (SymbolProvider)options.get(Library.OPTION_SYMBOL_PROVIDER); |
| 134 | if (optionSymbolProvider == null) { |
| 135 | this.symbolProvider = NATIVE_SYMBOL_PROVIDER; |
| 136 | } else { |
| 137 | this.symbolProvider = optionSymbolProvider; |
| 138 | } |
| 139 | |
| 140 | String encodingValue = (String) options.get(Library.OPTION_STRING_ENCODING); |
| 141 | if (encodingValue == null) { |
| 142 | encodingValue = Native.getDefaultStringEncoding(); |
| 143 | } |
| 144 | this.encoding = encodingValue; |
nothing calls this directly
no test coverage detected
searching dependent graphs…