rocksdb/java/rocksjni/slice.cc
Radek Hubner 0bf9079d44 Change Java native methods to static (#11882)
Summary:
This should give us some performance benefit calling native C++ code.
Closes https://github.com/facebook/rocksdb/issues/4786
See https://github.com/evolvedbinary/jni-benchmarks/ for more info.

Pull Request resolved: https://github.com/facebook/rocksdb/pull/11882

Reviewed By: pdillinger

Differential Revision: D53066207

Pulled By: ajkr

fbshipit-source-id: daedef185215d0d8e791cd85bef598900bcb5bf2
2024-01-25 12:36:30 -08:00

375 lines
12 KiB
C++

// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
// This source code is licensed under both the GPLv2 (found in the
// COPYING file in the root directory) and Apache 2.0 License
// (found in the LICENSE.Apache file in the root directory).
//
// This file implements the "bridge" between Java and C++ for
// ROCKSDB_NAMESPACE::Slice.
#include "rocksdb/slice.h"
#include <jni.h>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include "include/org_rocksdb_AbstractSlice.h"
#include "include/org_rocksdb_DirectSlice.h"
#include "include/org_rocksdb_Slice.h"
#include "rocksjni/cplusplus_to_java_convert.h"
#include "rocksjni/portal.h"
// <editor-fold desc="org.rocksdb.AbstractSlice>
/*
* Class: org_rocksdb_AbstractSlice
* Method: createNewSliceFromString
* Signature: (Ljava/lang/String;)J
*/
jlong Java_org_rocksdb_AbstractSlice_createNewSliceFromString(JNIEnv* env,
jclass /*jcls*/,
jstring jstr) {
const auto* str = env->GetStringUTFChars(jstr, nullptr);
if (str == nullptr) {
// exception thrown: OutOfMemoryError
return 0;
}
const size_t len = strlen(str);
// NOTE: buf will be deleted in the
// Java_org_rocksdb_Slice_disposeInternalBuf or
// or Java_org_rocksdb_DirectSlice_disposeInternalBuf methods
char* buf = new char[len + 1];
memcpy(buf, str, len);
buf[len] = 0;
env->ReleaseStringUTFChars(jstr, str);
const auto* slice = new ROCKSDB_NAMESPACE::Slice(buf);
return GET_CPLUSPLUS_POINTER(slice);
}
/*
* Class: org_rocksdb_AbstractSlice
* Method: size0
* Signature: (J)I
*/
jint Java_org_rocksdb_AbstractSlice_size0(JNIEnv* /*env*/, jclass /*jcls*/,
jlong handle) {
const auto* slice = reinterpret_cast<ROCKSDB_NAMESPACE::Slice*>(handle);
return static_cast<jint>(slice->size());
}
/*
* Class: org_rocksdb_AbstractSlice
* Method: empty0
* Signature: (J)Z
*/
jboolean Java_org_rocksdb_AbstractSlice_empty0(JNIEnv* /*env*/, jclass /*jcls*/,
jlong handle) {
const auto* slice = reinterpret_cast<ROCKSDB_NAMESPACE::Slice*>(handle);
return slice->empty();
}
/*
* Class: org_rocksdb_AbstractSlice
* Method: toString0
* Signature: (JZ)Ljava/lang/String;
*/
jstring Java_org_rocksdb_AbstractSlice_toString0(JNIEnv* env, jclass /*jobj*/,
jlong handle, jboolean hex) {
const auto* slice = reinterpret_cast<ROCKSDB_NAMESPACE::Slice*>(handle);
const std::string s = slice->ToString(hex);
return env->NewStringUTF(s.c_str());
}
/*
* Class: org_rocksdb_AbstractSlice
* Method: compare0
* Signature: (JJ)I;
*/
jint Java_org_rocksdb_AbstractSlice_compare0(JNIEnv* /*env*/, jclass /*jcls*/,
jlong handle, jlong otherHandle) {
const auto* slice = reinterpret_cast<ROCKSDB_NAMESPACE::Slice*>(handle);
const auto* otherSlice =
reinterpret_cast<ROCKSDB_NAMESPACE::Slice*>(otherHandle);
return slice->compare(*otherSlice);
}
/*
* Class: org_rocksdb_AbstractSlice
* Method: startsWith0
* Signature: (JJ)Z;
*/
jboolean Java_org_rocksdb_AbstractSlice_startsWith0(JNIEnv* /*env*/,
jclass /*jcls*/,
jlong handle,
jlong otherHandle) {
const auto* slice = reinterpret_cast<ROCKSDB_NAMESPACE::Slice*>(handle);
const auto* otherSlice =
reinterpret_cast<ROCKSDB_NAMESPACE::Slice*>(otherHandle);
return slice->starts_with(*otherSlice);
}
/*
* Class: org_rocksdb_AbstractSlice
* Method: disposeInternal
* Signature: (J)V
*/
void Java_org_rocksdb_AbstractSlice_disposeInternalJni(JNIEnv* /*env*/,
jclass /*jcls*/,
jlong handle) {
delete reinterpret_cast<ROCKSDB_NAMESPACE::Slice*>(handle);
}
// </editor-fold>
// <editor-fold desc="org.rocksdb.Slice>
/*
* Class: org_rocksdb_Slice
* Method: createNewSlice0
* Signature: ([BI)J
*/
jlong Java_org_rocksdb_Slice_createNewSlice0(JNIEnv* env, jclass /*jcls*/,
jbyteArray data, jint offset) {
const jsize dataSize = env->GetArrayLength(data);
const int len = dataSize - offset;
// NOTE: buf will be deleted in the Java_org_rocksdb_Slice_disposeInternalBuf
// method
jbyte* buf = new jbyte[len];
env->GetByteArrayRegion(data, offset, len, buf);
if (env->ExceptionCheck()) {
// exception thrown: ArrayIndexOutOfBoundsException
return 0;
}
const auto* slice = new ROCKSDB_NAMESPACE::Slice((const char*)buf, len);
return GET_CPLUSPLUS_POINTER(slice);
}
/*
* Class: org_rocksdb_Slice
* Method: createNewSlice1
* Signature: ([B)J
*/
jlong Java_org_rocksdb_Slice_createNewSlice1(JNIEnv* env, jclass /*jcls*/,
jbyteArray data) {
jbyte* ptrData = env->GetByteArrayElements(data, nullptr);
if (ptrData == nullptr) {
// exception thrown: OutOfMemoryError
return 0;
}
const int len = env->GetArrayLength(data) + 1;
// NOTE: buf will be deleted in the Java_org_rocksdb_Slice_disposeInternalBuf
// method
char* buf = new char[len];
memcpy(buf, ptrData, len - 1);
buf[len - 1] = '\0';
const auto* slice = new ROCKSDB_NAMESPACE::Slice(buf, len - 1);
env->ReleaseByteArrayElements(data, ptrData, JNI_ABORT);
return GET_CPLUSPLUS_POINTER(slice);
}
/*
* Class: org_rocksdb_Slice
* Method: data0
* Signature: (J)[B
*/
jbyteArray Java_org_rocksdb_Slice_data0(JNIEnv* env, jobject /*jobj*/,
jlong handle) {
const auto* slice = reinterpret_cast<ROCKSDB_NAMESPACE::Slice*>(handle);
const jsize len = static_cast<jsize>(slice->size());
const jbyteArray data = env->NewByteArray(len);
if (data == nullptr) {
// exception thrown: OutOfMemoryError
return nullptr;
}
env->SetByteArrayRegion(
data, 0, len,
const_cast<jbyte*>(reinterpret_cast<const jbyte*>(slice->data())));
if (env->ExceptionCheck()) {
// exception thrown: ArrayIndexOutOfBoundsException
env->DeleteLocalRef(data);
return nullptr;
}
return data;
}
/*
* Class: org_rocksdb_Slice
* Method: clear0
* Signature: (JZJ)V
*/
void Java_org_rocksdb_Slice_clear0(JNIEnv* /*env*/, jclass /*jcls*/,
jlong handle, jboolean shouldRelease,
jlong internalBufferOffset) {
auto* slice = reinterpret_cast<ROCKSDB_NAMESPACE::Slice*>(handle);
if (shouldRelease == JNI_TRUE) {
const char* buf = slice->data_ - internalBufferOffset;
delete[] buf;
}
slice->clear();
}
/*
* Class: org_rocksdb_Slice
* Method: removePrefix0
* Signature: (JI)V
*/
void Java_org_rocksdb_Slice_removePrefix0(JNIEnv* /*env*/, jclass /*jcls*/,
jlong handle, jint length) {
auto* slice = reinterpret_cast<ROCKSDB_NAMESPACE::Slice*>(handle);
slice->remove_prefix(length);
}
/*
* Class: org_rocksdb_DirectSlice
* Method: setLength0
* Signature: (JI)V
*/
void Java_org_rocksdb_DirectSlice_setLength0(JNIEnv* /*env*/, jclass /*jcls*/,
jlong handle, jint length) {
auto* slice = reinterpret_cast<ROCKSDB_NAMESPACE::Slice*>(handle);
slice->size_ = length;
}
/*
* Class: org_rocksdb_Slice
* Method: disposeInternalBuf
* Signature: (JJ)V
*/
void Java_org_rocksdb_Slice_disposeInternalBuf(JNIEnv* /*env*/, jclass /*jcls*/,
jlong handle,
jlong internalBufferOffset) {
const auto* slice = reinterpret_cast<ROCKSDB_NAMESPACE::Slice*>(handle);
const char* buf = slice->data_ - internalBufferOffset;
delete[] buf;
}
// </editor-fold>
// <editor-fold desc="org.rocksdb.DirectSlice>
/*
* Class: org_rocksdb_DirectSlice
* Method: createNewDirectSlice0
* Signature: (Ljava/nio/ByteBuffer;I)J
*/
jlong Java_org_rocksdb_DirectSlice_createNewDirectSlice0(JNIEnv* env,
jclass /*jcls*/,
jobject data,
jint length) {
assert(data != nullptr);
void* data_addr = env->GetDirectBufferAddress(data);
if (data_addr == nullptr) {
// error: memory region is undefined, given object is not a direct
// java.nio.Buffer, or JNI access to direct buffers is not supported by JVM
ROCKSDB_NAMESPACE::IllegalArgumentExceptionJni::ThrowNew(
env, ROCKSDB_NAMESPACE::Status::InvalidArgument(
"Could not access DirectBuffer"));
return 0;
}
const auto* ptrData = reinterpret_cast<char*>(data_addr);
const auto* slice = new ROCKSDB_NAMESPACE::Slice(ptrData, length);
return GET_CPLUSPLUS_POINTER(slice);
}
/*
* Class: org_rocksdb_DirectSlice
* Method: createNewDirectSlice1
* Signature: (Ljava/nio/ByteBuffer;)J
*/
jlong Java_org_rocksdb_DirectSlice_createNewDirectSlice1(JNIEnv* env,
jclass /*jcls*/,
jobject data) {
void* data_addr = env->GetDirectBufferAddress(data);
if (data_addr == nullptr) {
// error: memory region is undefined, given object is not a direct
// java.nio.Buffer, or JNI access to direct buffers is not supported by JVM
ROCKSDB_NAMESPACE::IllegalArgumentExceptionJni::ThrowNew(
env, ROCKSDB_NAMESPACE::Status::InvalidArgument(
"Could not access DirectBuffer"));
return 0;
}
const auto* ptrData = reinterpret_cast<char*>(data_addr);
const auto* slice = new ROCKSDB_NAMESPACE::Slice(ptrData);
return GET_CPLUSPLUS_POINTER(slice);
}
/*
* Class: org_rocksdb_DirectSlice
* Method: data0
* Signature: (J)Ljava/lang/Object;
*/
jobject Java_org_rocksdb_DirectSlice_data0(JNIEnv* env, jobject /*jobj*/,
jlong handle) {
const auto* slice = reinterpret_cast<ROCKSDB_NAMESPACE::Slice*>(handle);
return env->NewDirectByteBuffer(const_cast<char*>(slice->data()),
slice->size());
}
/*
* Class: org_rocksdb_DirectSlice
* Method: get0
* Signature: (JI)B
*/
jbyte Java_org_rocksdb_DirectSlice_get0(JNIEnv* /*env*/, jclass /*jcls*/,
jlong handle, jint offset) {
const auto* slice = reinterpret_cast<ROCKSDB_NAMESPACE::Slice*>(handle);
return (*slice)[offset];
}
/*
* Class: org_rocksdb_DirectSlice
* Method: clear0
* Signature: (JZJ)V
*/
void Java_org_rocksdb_DirectSlice_clear0(JNIEnv* /*env*/, jclass /*jcls*/,
jlong handle, jboolean shouldRelease,
jlong internalBufferOffset) {
auto* slice = reinterpret_cast<ROCKSDB_NAMESPACE::Slice*>(handle);
if (shouldRelease == JNI_TRUE) {
const char* buf = slice->data_ - internalBufferOffset;
delete[] buf;
}
slice->clear();
}
/*
* Class: org_rocksdb_DirectSlice
* Method: removePrefix0
* Signature: (JI)V
*/
void Java_org_rocksdb_DirectSlice_removePrefix0(JNIEnv* /*env*/,
jclass /*jcls*/, jlong handle,
jint length) {
auto* slice = reinterpret_cast<ROCKSDB_NAMESPACE::Slice*>(handle);
slice->remove_prefix(length);
}
/*
* Class: org_rocksdb_DirectSlice
* Method: disposeInternalBuf
* Signature: (JJ)V
*/
void Java_org_rocksdb_DirectSlice_disposeInternalBuf(
JNIEnv* /*env*/, jclass /*jcls*/, jlong handle,
jlong internalBufferOffset) {
const auto* slice = reinterpret_cast<ROCKSDB_NAMESPACE::Slice*>(handle);
const char* buf = slice->data_ - internalBufferOffset;
delete[] buf;
}
// </editor-fold>