[Java] Add RocksObject, the base class of all java objects with a c++ pointer.

Summary:
Add RocksObject, the base class of all java objects which has a c++ pointer.
While the finalizer of a RocksObject will release its c++ resource, it is
suggested to call its RocksObject.dispose() to manually release its
c++ resource.

Existing RocksDB java classes are now extending RocksObject.

Test Plan:
make rocksdbjava
make jtest
make jdb_bench

Reviewers: haobo, dhruba, sdong, ankgup87, rsumbaly, swapnilghike, zzbennett

Reviewed By: haobo

CC: leveldb

Differential Revision: https://reviews.facebook.net/D18411
main
Yueh-Hsuan Chiang 11 years ago
parent 096f5be0ed
commit 61955a0dda
  1. 5
      java/RocksDBSample.java
  2. 8
      java/org/rocksdb/BackupableDB.java
  3. 14
      java/org/rocksdb/BackupableDBOptions.java
  4. 20
      java/org/rocksdb/Filter.java
  5. 22
      java/org/rocksdb/Iterator.java
  6. 15
      java/org/rocksdb/Options.java
  7. 12
      java/org/rocksdb/ReadOptions.java
  8. 22
      java/org/rocksdb/RocksDB.java
  9. 35
      java/org/rocksdb/RocksObject.java
  10. 14
      java/org/rocksdb/WriteBatch.java
  11. 14
      java/org/rocksdb/WriteOptions.java
  12. 8
      java/rocksjni/iterator.cc
  13. 12
      java/rocksjni/rocksjni.cc

@ -218,7 +218,7 @@ public class RocksDBSample {
System.out.println("iterator seek test passed."); System.out.println("iterator seek test passed.");
iterator.close(); iterator.dispose();
System.out.println("iterator tests passed."); System.out.println("iterator tests passed.");
iterator = db.newIterator(); iterator = db.newIterator();
@ -226,7 +226,7 @@ public class RocksDBSample {
for (iterator.seekToLast(); iterator.isValid(); iterator.prev()) { for (iterator.seekToLast(); iterator.isValid(); iterator.prev()) {
keys.add(iterator.key()); keys.add(iterator.key());
} }
iterator.close(); iterator.dispose();
Map<byte[], byte[]> values = db.multiGet(keys); Map<byte[], byte[]> values = db.multiGet(keys);
assert(values.size() == keys.size()); assert(values.size() == keys.size());
@ -248,5 +248,6 @@ public class RocksDBSample {
// be sure to dispose c++ pointers // be sure to dispose c++ pointers
options.dispose(); options.dispose();
readOptions.dispose(); readOptions.dispose();
filter.dispose();
} }
} }

@ -55,8 +55,8 @@ public class BackupableDB extends RocksDB {
* should be transparent to Java developers. * should be transparent to Java developers.
*/ */
@Override public synchronized void close() { @Override public synchronized void close() {
if (isOpened()) { if (isInitialized()) {
super.close0(); super.close();
} }
} }
@ -73,10 +73,6 @@ public class BackupableDB extends RocksDB {
close(); close();
} }
private boolean isOpened() {
return nativeHandle_ != 0;
}
protected native void open(long rocksDBHandle, long backupDBOptionsHandle); protected native void open(long rocksDBHandle, long backupDBOptionsHandle);
protected native void createNewBackup(long handle, boolean flag); protected native void createNewBackup(long handle, boolean flag);

@ -12,8 +12,9 @@ package org.rocksdb;
* Note that dispose() must be called before an Options instance * Note that dispose() must be called before an Options instance
* become out-of-scope to release the allocated memory in c++. * become out-of-scope to release the allocated memory in c++.
*/ */
public class BackupableDBOptions { public class BackupableDBOptions extends RocksObject {
public BackupableDBOptions(String path) { public BackupableDBOptions(String path) {
super();
newBackupableDBOptions(path); newBackupableDBOptions(path);
} }
@ -31,22 +32,13 @@ public class BackupableDBOptions {
* Release the memory allocated for the current instance * Release the memory allocated for the current instance
* in the c++ side. * in the c++ side.
*/ */
public synchronized void dispose() { @Override public synchronized void dispose() {
if (isInitialized()) { if (isInitialized()) {
dispose(nativeHandle_); dispose(nativeHandle_);
} }
} }
@Override protected void finalize() {
dispose();
}
boolean isInitialized() {
return nativeHandle_ != 0;
}
private native void newBackupableDBOptions(String path); private native void newBackupableDBOptions(String path);
private native String backupDir(long handle); private native String backupDir(long handle);
private native void dispose(long handle); private native void dispose(long handle);
long nativeHandle_;
} }

@ -12,27 +12,21 @@ package org.rocksdb;
* number of disk seeks form a handful to a single disk seek per * number of disk seeks form a handful to a single disk seek per
* DB::Get() call. * DB::Get() call.
*/ */
public abstract class Filter { public abstract class Filter extends RocksObject {
protected long nativeHandle_ = 0;
protected abstract void createNewFilter(); protected abstract void createNewFilter();
/** /**
* Deletes underlying C++ filter pointer. * Deletes underlying C++ filter pointer.
*
* Note that this function should be called only after all
* RocksDB instances referencing the filter are closed.
* Otherwise an undefined behavior will occur.
*/ */
protected synchronized void dispose() { @Override public synchronized void dispose() {
if(nativeHandle_ != 0) { if (isInitialized()) {
dispose0(nativeHandle_); dispose0(nativeHandle_);
} }
} }
@Override protected void finalize() {
dispose();
}
protected boolean isInitialized() {
return (nativeHandle_ != 0);
}
private native void dispose0(long handle); private native void dispose0(long handle);
} }

@ -16,10 +16,9 @@ package org.rocksdb;
* non-const method, all threads accessing the same Iterator must use * non-const method, all threads accessing the same Iterator must use
* external synchronization. * external synchronization.
*/ */
public class Iterator { public class Iterator extends RocksObject {
private long nativeHandle_;
public Iterator(long nativeHandle) { public Iterator(long nativeHandle) {
super();
nativeHandle_ = nativeHandle; nativeHandle_ = nativeHandle;
} }
@ -119,22 +118,15 @@ public class Iterator {
/** /**
* Deletes underlying C++ iterator pointer. * Deletes underlying C++ iterator pointer.
*/ */
public synchronized void close() { @Override public synchronized void dispose() {
if(nativeHandle_ != 0) { if(isInitialized()) {
close0(nativeHandle_); dispose(nativeHandle_);
} nativeHandle_ = 0;
} }
@Override protected void finalize() {
close();
}
private boolean isInitialized() {
return (nativeHandle_ != 0);
} }
private native boolean isValid0(long handle); private native boolean isValid0(long handle);
private native void close0(long handle); private native void dispose(long handle);
private native void seekToFirst0(long handle); private native void seekToFirst0(long handle);
private native void seekToLast0(long handle); private native void seekToLast0(long handle);
private native void next0(long handle); private native void next0(long handle);

@ -12,7 +12,7 @@ package org.rocksdb;
* Note that dispose() must be called before an Options instance * Note that dispose() must be called before an Options instance
* become out-of-scope to release the allocated memory in c++. * become out-of-scope to release the allocated memory in c++.
*/ */
public class Options { public class Options extends RocksObject {
static final long DEFAULT_CACHE_SIZE = 8 << 20; static final long DEFAULT_CACHE_SIZE = 8 << 20;
/** /**
* Construct options for opening a RocksDB. * Construct options for opening a RocksDB.
@ -21,7 +21,7 @@ public class Options {
* an rocksdb::Options in the c++ side. * an rocksdb::Options in the c++ side.
*/ */
public Options() { public Options() {
nativeHandle_ = 0; super();
cacheSize_ = DEFAULT_CACHE_SIZE; cacheSize_ = DEFAULT_CACHE_SIZE;
newOptions(); newOptions();
} }
@ -2311,20 +2311,12 @@ public class Options {
* Release the memory allocated for the current instance * Release the memory allocated for the current instance
* in the c++ side. * in the c++ side.
*/ */
public synchronized void dispose() { @Override public synchronized void dispose() {
if (isInitialized()) { if (isInitialized()) {
dispose0(); dispose0();
} }
} }
@Override protected void finalize() {
dispose();
}
private boolean isInitialized() {
return (nativeHandle_ != 0);
}
static final int DEFAULT_PLAIN_TABLE_BLOOM_BITS_PER_KEY = 10; static final int DEFAULT_PLAIN_TABLE_BLOOM_BITS_PER_KEY = 10;
static final double DEFAULT_PLAIN_TABLE_HASH_TABLE_RATIO = 0.75; static final double DEFAULT_PLAIN_TABLE_HASH_TABLE_RATIO = 0.75;
static final int DEFAULT_PLAIN_TABLE_INDEX_SPARSENESS = 16; static final int DEFAULT_PLAIN_TABLE_INDEX_SPARSENESS = 16;
@ -2358,7 +2350,6 @@ public class Options {
private native void useFixedLengthPrefixExtractor( private native void useFixedLengthPrefixExtractor(
long handle, int prefixLength); long handle, int prefixLength);
long nativeHandle_;
long cacheSize_; long cacheSize_;
Filter filter_; Filter filter_;
} }

@ -11,9 +11,9 @@ package org.rocksdb;
* Note that dispose() must be called before an Options instance * Note that dispose() must be called before an Options instance
* become out-of-scope to release the allocated memory in c++. * become out-of-scope to release the allocated memory in c++.
*/ */
public class ReadOptions { public class ReadOptions extends RocksObject {
public ReadOptions() { public ReadOptions() {
nativeHandle_ = 0; super();
newReadOptions(); newReadOptions();
} }
private native void newReadOptions(); private native void newReadOptions();
@ -24,7 +24,7 @@ public class ReadOptions {
* *
* Calling other methods after dispose() leads to undefined behavior. * Calling other methods after dispose() leads to undefined behavior.
*/ */
public synchronized void dispose() { @Override public synchronized void dispose() {
if (isInitialized()) { if (isInitialized()) {
dispose(nativeHandle_); dispose(nativeHandle_);
} }
@ -127,10 +127,4 @@ public class ReadOptions {
} }
private native void setTailing( private native void setTailing(
long handle, boolean tailing); long handle, boolean tailing);
protected long nativeHandle_;
private boolean isInitialized() {
return nativeHandle_ != 0;
}
} }

@ -18,7 +18,7 @@ import org.rocksdb.util.Environment;
* All methods of this class could potentially throw RocksDBException, which * All methods of this class could potentially throw RocksDBException, which
* indicates sth wrong at the rocksdb library side and the call failed. * indicates sth wrong at the rocksdb library side and the call failed.
*/ */
public class RocksDB { public class RocksDB extends RocksObject {
public static final int NOT_FOUND = -1; public static final int NOT_FOUND = -1;
private static final String[] compressionLibs_ = { private static final String[] compressionLibs_ = {
"snappy", "zlib", "bzip2", "lz4", "lz4hc"}; "snappy", "zlib", "bzip2", "lz4", "lz4hc"};
@ -114,10 +114,19 @@ public class RocksDB {
return db; return db;
} }
public synchronized void close() { @Override public synchronized void dispose() {
if (nativeHandle_ != 0) { if (isInitialized()) {
close0(); dispose(nativeHandle_);
nativeHandle_ = 0;
}
} }
/**
* Close the RocksDB instance.
* This function is equivalent to dispose().
*/
public void close() {
dispose();
} }
/** /**
@ -314,7 +323,7 @@ public class RocksDB {
* Private constructor. * Private constructor.
*/ */
protected RocksDB() { protected RocksDB() {
nativeHandle_ = 0; super();
} }
/** /**
@ -361,8 +370,7 @@ public class RocksDB {
long handle, long writeOptHandle, long handle, long writeOptHandle,
byte[] key, int keyLen) throws RocksDBException; byte[] key, int keyLen) throws RocksDBException;
protected native long iterator0(long optHandle); protected native long iterator0(long optHandle);
protected native void close0(); protected native void dispose(long handle);
protected long nativeHandle_;
protected Filter filter_; protected Filter filter_;
} }

@ -0,0 +1,35 @@
// Copyright (c) 2014, Facebook, Inc. All rights reserved.
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
package org.rocksdb;
/**
* RocksObject is the base-class of all RocksDB related class that has
* a pointer to some c++ rocksdb object. Although RocksObject
* will release its c++ resource on its finalize() once it has been
* garbage-collected, it is suggested to call dispose() manually to
* release its c++ resource once an instance of RocksObject is no
* longer used.
*/
public abstract class RocksObject {
protected RocksObject() {
nativeHandle_ = 0;
}
/**
* Release the c++ object pointed by the native handle.
*/
public abstract void dispose();
protected boolean isInitialized() {
return (nativeHandle_ != 0);
}
@Override protected void finalize() {
dispose();
}
protected long nativeHandle_;
}

@ -24,9 +24,9 @@ import java.util.*;
* non-const method, all threads accessing the same WriteBatch must use * non-const method, all threads accessing the same WriteBatch must use
* external synchronization. * external synchronization.
*/ */
public class WriteBatch { public class WriteBatch extends RocksObject {
public WriteBatch() { public WriteBatch() {
nativeHandle_ = 0; super();
newWriteBatch(0); newWriteBatch(0);
} }
@ -86,16 +86,12 @@ public class WriteBatch {
/** /**
* Delete the c++ side pointer. * Delete the c++ side pointer.
*/ */
public synchronized void dispose() { @Override public synchronized void dispose() {
if (nativeHandle_ != 0) { if (isInitialized()) {
dispose0(); dispose0();
} }
} }
@Override protected void finalize() {
dispose();
}
private native void newWriteBatch(int reserved_bytes); private native void newWriteBatch(int reserved_bytes);
private native void put(byte[] key, int keyLen, private native void put(byte[] key, int keyLen,
byte[] value, int valueLen); byte[] value, int valueLen);
@ -104,8 +100,6 @@ public class WriteBatch {
private native void remove(byte[] key, int keyLen); private native void remove(byte[] key, int keyLen);
private native void putLogData(byte[] blob, int blobLen); private native void putLogData(byte[] blob, int blobLen);
private native void dispose0(); private native void dispose0();
long nativeHandle_;
} }
/** /**

@ -11,14 +11,14 @@ package org.rocksdb;
* Note that developers should call WriteOptions.dispose() to release the * Note that developers should call WriteOptions.dispose() to release the
* c++ side memory before a WriteOptions instance runs out of scope. * c++ side memory before a WriteOptions instance runs out of scope.
*/ */
public class WriteOptions { public class WriteOptions extends RocksObject {
public WriteOptions() { public WriteOptions() {
nativeHandle_ = 0; super();
newWriteOptions(); newWriteOptions();
} }
public synchronized void dispose() { @Override public synchronized void dispose() {
if (nativeHandle_ != 0) { if (isInitialized()) {
dispose0(nativeHandle_); dispose0(nativeHandle_);
} }
} }
@ -91,16 +91,10 @@ public class WriteOptions {
return disableWAL(nativeHandle_); return disableWAL(nativeHandle_);
} }
@Override protected void finalize() {
dispose();
}
private native void newWriteOptions(); private native void newWriteOptions();
private native void setSync(long handle, boolean flag); private native void setSync(long handle, boolean flag);
private native boolean sync(long handle); private native boolean sync(long handle);
private native void setDisableWAL(long handle, boolean flag); private native void setDisableWAL(long handle, boolean flag);
private native boolean disableWAL(long handle); private native boolean disableWAL(long handle);
private native void dispose0(long handle); private native void dispose0(long handle);
protected long nativeHandle_;
} }

@ -26,7 +26,7 @@ jboolean Java_org_rocksdb_Iterator_isValid0(
/* /*
* Class: org_rocksdb_Iterator * Class: org_rocksdb_Iterator
* Method: close0 * Method: seekToFirst0
* Signature: (J)V * Signature: (J)V
*/ */
void Java_org_rocksdb_Iterator_seekToFirst0( void Java_org_rocksdb_Iterator_seekToFirst0(
@ -135,13 +135,11 @@ void Java_org_rocksdb_Iterator_status0(
/* /*
* Class: org_rocksdb_Iterator * Class: org_rocksdb_Iterator
* Method: status0 * Method: dispose
* Signature: (J)V * Signature: (J)V
*/ */
void Java_org_rocksdb_Iterator_close0( void Java_org_rocksdb_Iterator_dispose(
JNIEnv* env, jobject jobj, jlong handle) { JNIEnv* env, jobject jobj, jlong handle) {
auto it = reinterpret_cast<rocksdb::Iterator*>(handle); auto it = reinterpret_cast<rocksdb::Iterator*>(handle);
delete it; delete it;
rocksdb::IteratorJni::setHandle(env, jobj, nullptr);
} }

@ -415,16 +415,14 @@ void Java_org_rocksdb_RocksDB_remove__JJ_3BI(
/* /*
* Class: org_rocksdb_RocksDB * Class: org_rocksdb_RocksDB
* Method: close0 * Method: dispose
* Signature: ()V * Signature: (J)V
*/ */
void Java_org_rocksdb_RocksDB_close0( void Java_org_rocksdb_RocksDB_dispose(
JNIEnv* env, jobject java_db) { JNIEnv* env, jobject java_db, jlong jhandle) {
rocksdb::DB* db = rocksdb::RocksDBJni::getHandle(env, java_db); auto db = reinterpret_cast<rocksdb::DB*>(jhandle);
assert(db != nullptr); assert(db != nullptr);
delete db; delete db;
rocksdb::RocksDBJni::setHandle(env, java_db, nullptr);
} }
/* /*

Loading…
Cancel
Save