Skip to content

Commit

Permalink
Let JUTFString takes ownership
Browse files Browse the repository at this point in the history
  • Loading branch information
yujincheng08 committed Dec 7, 2023
1 parent 92a6a72 commit 1322920
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 42 deletions.
68 changes: 35 additions & 33 deletions lsplant/src/main/jni/include/utils/jni_helper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#include <jni.h>

#include <string>
#include <memory>
#include <functional>
#include <string_view>

#pragma clang diagnostic push
Expand All @@ -30,6 +32,7 @@ concept JObject = std::is_base_of_v<std::remove_pointer_t<_jobject>, std::remove

template <JObject T>
class ScopedLocalRef {
friend class JUTFString;
public:
using BaseType [[maybe_unused]] = T;

Expand Down Expand Up @@ -181,56 +184,55 @@ inline auto JNI_NewStringUTF(JNIEnv *env, std::string_view sv) {

class JUTFString {
public:
JUTFString(JNIEnv *env, jstring jstr) : JUTFString(env, jstr, nullptr) {}
JUTFString(JNIEnv *env, jstring jstr, const char *default_cstr = nullptr) : JUTFString(ScopedLocalRef<jstring>(env, (jstring) env->NewLocalRef(jstr)), default_cstr) {}

JUTFString(const ScopedLocalRef<jstring> &jstr)
: JUTFString(jstr.env_, jstr.local_ref_, nullptr) {}

JUTFString(JNIEnv *env, jstring jstr, const char *default_cstr)
: env_(env), jstr_(jstr) {
if (env_ && jstr_)
cstr_ = env_->GetStringUTFChars(jstr, nullptr);
else
cstr_ = default_cstr;
: JUTFString(jstr.clone(), nullptr) {}

JUTFString(ScopedLocalRef<jstring> &&jstr, const char *default_cstr = nullptr)
: jstr_(std::move(jstr)) {
if (jstr_)
jstr_.env_->GetStringUTFChars(jstr, nullptr);
else {
if (default_cstr) {
auto len = strlen(default_cstr);
auto str = new char[len + 1];
memcpy(str, default_cstr, len + 1);
str_.reset(str);
}
jstr_.reset();
}
}

operator const char *() const { return cstr_; }
operator const char *() const { return str_.get(); }

operator const std::string() const { return cstr_; }
operator const std::string() const { return str_ ? str_.get() : ""; }

operator const bool() const { return cstr_ != nullptr; }
operator const bool() const { return str_ != nullptr; }

auto get() const { return cstr_; }

~JUTFString() {
if (env_ && jstr_) env_->ReleaseStringUTFChars(jstr_, cstr_);
}
auto get() const { return str_.get(); }

JUTFString(JUTFString &&other)
: env_(std::move(other.env_)),
jstr_(std::move(other.jstr_)),
cstr_(std::move(other.cstr_)) {
other.cstr_ = nullptr;
: jstr_(std::move(other.jstr_)),
str_(std::move(other.str_)) {
}

JUTFString &operator=(JUTFString &&other) {
if (&other != this) {
env_ = std::move(other.env_);
jstr_ = std::move(other.jstr_);
cstr_ = std::move(other.cstr_);
other.cstr_ = nullptr;
}
jstr_ = std::move(other.jstr_);
str_ = std::move(other.str_);
return *this;
}

private:
JNIEnv *env_;
jstring jstr_;
const char *cstr_;

JUTFString(const JUTFString &) = delete;
ScopedLocalRef<jstring> jstr_;
std::unique_ptr<const char[], std::function<void(const char *)>> str_ {nullptr, [this](const char str[]) {
if (jstr_)
jstr_.env_->ReleaseStringUTFChars(jstr_, str);
else
std::default_delete<const char[]>()(str);
}};

JUTFString &operator=(const JUTFString &) = delete;
DISALLOW_COPY_AND_ASSIGN(JUTFString);
};

template <typename Func, typename... Args>
Expand Down
12 changes: 3 additions & 9 deletions lsplant/src/main/jni/lsplant.cc
Original file line number Diff line number Diff line change
Expand Up @@ -714,19 +714,13 @@ using ::lsplant::IsHooked;

ScopedLocalRef<jclass> built_class{env};
{
auto callback_name =
JNI_Cast<jstring>(JNI_CallObjectMethod(env, callback_method, method_get_name));
JUTFString callback_method_name(callback_name);
auto target_name =
JNI_Cast<jstring>(JNI_CallObjectMethod(env, target_method, method_get_name));
JUTFString target_method_name(target_name);
JUTFString callback_method_name(JNI_Cast<jstring>(JNI_CallObjectMethod(env, callback_method, method_get_name)));
JUTFString target_method_name(JNI_Cast<jstring>(JNI_CallObjectMethod(env, target_method, method_get_name)));
auto callback_class = JNI_Cast<jclass>(
JNI_CallObjectMethod(env, callback_method, method_get_declaring_class));
auto callback_class_loader =
JNI_CallObjectMethod(env, callback_class, class_get_class_loader);
auto callback_class_name =
JNI_Cast<jstring>(JNI_CallObjectMethod(env, callback_class, class_get_name));
JUTFString class_name(callback_class_name);
JUTFString class_name(JNI_Cast<jstring>(JNI_CallObjectMethod(env, callback_class, class_get_name)));
if (!JNI_IsInstanceOf(env, hooker_object, callback_class)) {
LOGE("callback_method is not a method of hooker_object");
return nullptr;
Expand Down

0 comments on commit 1322920

Please sign in to comment.