diff --git a/java/src/main/java/org/rocksdb/FlushOptions.java b/java/src/main/java/org/rocksdb/FlushOptions.java index 4931b5d85..ce54a528b 100644 --- a/java/src/main/java/org/rocksdb/FlushOptions.java +++ b/java/src/main/java/org/rocksdb/FlushOptions.java @@ -5,6 +5,9 @@ package org.rocksdb; * {@link org.rocksdb.RocksDB}. */ public class FlushOptions extends RocksObject { + static { + RocksDB.loadLibrary(); + } /** * Construct a new instance of FlushOptions. diff --git a/java/src/main/java/org/rocksdb/RocksDB.java b/java/src/main/java/org/rocksdb/RocksDB.java index d16ae0435..64c05afc1 100644 --- a/java/src/main/java/org/rocksdb/RocksDB.java +++ b/java/src/main/java/org/rocksdb/RocksDB.java @@ -7,6 +7,9 @@ package org.rocksdb; import java.util.*; import java.io.IOException; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; + import org.rocksdb.util.Environment; /** @@ -19,6 +22,15 @@ public class RocksDB extends RocksObject { public static final byte[] DEFAULT_COLUMN_FAMILY = "default".getBytes(); public static final int NOT_FOUND = -1; + private enum LibraryState { + NOT_LOADED, + LOADING, + LOADED + } + + private static AtomicReference libraryLoaded + = new AtomicReference<>(LibraryState.NOT_LOADED); + static { RocksDB.loadLibrary(); } @@ -30,26 +42,42 @@ public class RocksDB extends RocksObject { * java.io.tmpdir, however, you can override this temporary location by * setting the environment variable ROCKSDB_SHAREDLIB_DIR. */ - public static synchronized void loadLibrary() { - String tmpDir = System.getenv("ROCKSDB_SHAREDLIB_DIR"); - // loading possibly necessary libraries. - for (CompressionType compressionType : CompressionType.values()) { - try { - if (compressionType.getLibraryName() != null) { - System.loadLibrary(compressionType.getLibraryName()); + public static void loadLibrary() { + if (libraryLoaded.get() == LibraryState.LOADED) { + return; + } + + if (libraryLoaded.compareAndSet(LibraryState.NOT_LOADED, + LibraryState.LOADING)) { + final String tmpDir = System.getenv("ROCKSDB_SHAREDLIB_DIR"); + // loading possibly necessary libraries. + for (final CompressionType compressionType : CompressionType.values()) { + try { + if (compressionType.getLibraryName() != null) { + System.loadLibrary(compressionType.getLibraryName()); + } + } catch (UnsatisfiedLinkError e) { + // since it may be optional, we ignore its loading failure here. } - } catch (UnsatisfiedLinkError e) { - // since it may be optional, we ignore its loading failure here. } + try { + NativeLibraryLoader.getInstance().loadLibrary(tmpDir); + } catch (IOException e) { + libraryLoaded.set(LibraryState.NOT_LOADED); + throw new RuntimeException("Unable to load the RocksDB shared library" + + e); + } + + libraryLoaded.set(LibraryState.LOADED); + return; } - try - { - NativeLibraryLoader.getInstance().loadLibrary(tmpDir); - } - catch (IOException e) - { - throw new RuntimeException("Unable to load the RocksDB shared library" - + e); + + while (libraryLoaded.get() == LibraryState.LOADING) { + try { + Thread.sleep(10); + } catch(final InterruptedException e) { + //ignore + } } } @@ -60,36 +88,55 @@ public class RocksDB extends RocksObject { * @param paths a list of strings where each describes a directory * of a library. */ - public static synchronized void loadLibrary(final List paths) { - for (CompressionType compressionType : CompressionType.values()) { - if (compressionType.equals(CompressionType.NO_COMPRESSION)) { - continue; + public static void loadLibrary(final List paths) { + if (libraryLoaded.get() == LibraryState.LOADED) { + return; + } + + if (libraryLoaded.compareAndSet(LibraryState.NOT_LOADED, + LibraryState.LOADING)) { + for (final CompressionType compressionType : CompressionType.values()) { + if (compressionType.equals(CompressionType.NO_COMPRESSION)) { + continue; + } + for (final String path : paths) { + try { + System.load(path + "/" + Environment.getSharedLibraryFileName( + compressionType.getLibraryName())); + break; + } catch (UnsatisfiedLinkError e) { + // since they are optional, we ignore loading fails. + } + } } - for (String path : paths) { + boolean success = false; + UnsatisfiedLinkError err = null; + for (final String path : paths) { try { - System.load(path + "/" + Environment.getSharedLibraryFileName( - compressionType.getLibraryName())); + System.load(path + "/" + + Environment.getJniLibraryFileName("rocksdbjni")); + success = true; break; } catch (UnsatisfiedLinkError e) { - // since they are optional, we ignore loading fails. + err = e; } } + if (!success) { + libraryLoaded.set(LibraryState.NOT_LOADED); + throw err; + } + + libraryLoaded.set(LibraryState.LOADED); + return; } - boolean success = false; - UnsatisfiedLinkError err = null; - for (String path : paths) { + + while (libraryLoaded.get() == LibraryState.LOADING) { try { - System.load(path + "/" + - Environment.getJniLibraryFileName("rocksdbjni")); - success = true; - break; - } catch (UnsatisfiedLinkError e) { - err = e; + Thread.sleep(10); + } catch(final InterruptedException e) { + //ignore } } - if (!success) { - throw err; - } } /**