1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef LIBTEXTCLASSIFIER_UTIL_JAVA_SCOPED_GLOBAL_REF_H_ 18 #define LIBTEXTCLASSIFIER_UTIL_JAVA_SCOPED_GLOBAL_REF_H_ 19 20 #include <jni.h> 21 #include <memory> 22 #include <type_traits> 23 24 #include "util/base/logging.h" 25 26 namespace libtextclassifier2 { 27 28 // A deleter to be used with std::unique_ptr to delete JNI global references. 29 class GlobalRefDeleter { 30 public: 31 GlobalRefDeleter() : jvm_(nullptr) {} 32 33 // Style guide violating implicit constructor so that the GlobalRefDeleter 34 // is implicitly constructed from the second argument to ScopedGlobalRef. 35 GlobalRefDeleter(JavaVM* jvm) : jvm_(jvm) {} // NOLINT(runtime/explicit) 36 37 GlobalRefDeleter(const GlobalRefDeleter& orig) = default; 38 39 // Copy assignment to allow move semantics in ScopedGlobalRef. 40 GlobalRefDeleter& operator=(const GlobalRefDeleter& rhs) { 41 TC_CHECK_EQ(jvm_, rhs.jvm_); 42 return *this; 43 } 44 45 // The delete operator. 46 void operator()(jobject object) const { 47 JNIEnv* env; 48 if (object != nullptr && jvm_ != nullptr && 49 JNI_OK == 50 jvm_->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_4)) { 51 env->DeleteGlobalRef(object); 52 } 53 } 54 55 private: 56 // The jvm_ stashed to use for deletion. 57 JavaVM* const jvm_; 58 }; 59 60 // A smart pointer that deletes a JNI global reference when it goes out 61 // of scope. Usage is: 62 // ScopedGlobalRef<jobject> scoped_global(env->JniFunction(), jvm); 63 template <typename T> 64 using ScopedGlobalRef = 65 std::unique_ptr<typename std::remove_pointer<T>::type, GlobalRefDeleter>; 66 67 // A helper to create global references. 68 template <typename T> 69 ScopedGlobalRef<T> MakeGlobalRef(T object, JNIEnv* env, JavaVM* jvm) { 70 const jobject globalObject = env->NewGlobalRef(object); 71 return ScopedGlobalRef<T>(reinterpret_cast<T>(globalObject), jvm); 72 } 73 74 } // namespace libtextclassifier2 75 76 #endif // LIBTEXTCLASSIFIER_UTIL_JAVA_SCOPED_GLOBAL_REF_H_ 77