scoped_java_ref.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541
  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef BASE_ANDROID_SCOPED_JAVA_REF_H_
  5. #define BASE_ANDROID_SCOPED_JAVA_REF_H_
  6. #include <jni.h>
  7. #include <stddef.h>
  8. #include <type_traits>
  9. #include <utility>
  10. #include "base/base_export.h"
  11. #include "base/check_op.h"
  12. #include "base/macros.h"
  13. namespace base {
  14. namespace android {
  15. // Creates a new local reference frame, in which at least a given number of
  16. // local references can be created. Note that local references already created
  17. // in previous local frames are still valid in the current local frame.
  18. class BASE_EXPORT ScopedJavaLocalFrame {
  19. public:
  20. explicit ScopedJavaLocalFrame(JNIEnv* env);
  21. ScopedJavaLocalFrame(JNIEnv* env, int capacity);
  22. ~ScopedJavaLocalFrame();
  23. private:
  24. // This class is only good for use on the thread it was created on so
  25. // it's safe to cache the non-threadsafe JNIEnv* inside this object.
  26. JNIEnv* env_;
  27. DISALLOW_COPY_AND_ASSIGN(ScopedJavaLocalFrame);
  28. };
  29. // Forward declare the generic java reference template class.
  30. template <typename T>
  31. class JavaRef;
  32. // Template specialization of JavaRef, which acts as the base class for all
  33. // other JavaRef<> template types. This allows you to e.g. pass
  34. // ScopedJavaLocalRef<jstring> into a function taking const JavaRef<jobject>&
  35. template <>
  36. class BASE_EXPORT JavaRef<jobject> {
  37. public:
  38. // Initializes a null reference.
  39. constexpr JavaRef() {}
  40. // Allow nullptr to be converted to JavaRef. This avoids having to declare an
  41. // empty JavaRef just to pass null to a function, and makes C++ "nullptr" and
  42. // Java "null" equivalent.
  43. constexpr JavaRef(std::nullptr_t) {}
  44. // Public to allow destruction of null JavaRef objects.
  45. ~JavaRef() {}
  46. // TODO(torne): maybe rename this to get() for consistency with unique_ptr
  47. // once there's fewer unnecessary uses of it in the codebase.
  48. jobject obj() const { return obj_; }
  49. explicit operator bool() const { return obj_ != nullptr; }
  50. // Deprecated. Just use bool conversion.
  51. // TODO(torne): replace usage and remove this.
  52. bool is_null() const { return obj_ == nullptr; }
  53. protected:
  54. // Takes ownership of the |obj| reference passed; requires it to be a local
  55. // reference type.
  56. #if DCHECK_IS_ON()
  57. // Implementation contains a DCHECK; implement out-of-line when DCHECK_IS_ON.
  58. JavaRef(JNIEnv* env, jobject obj);
  59. #else
  60. JavaRef(JNIEnv* env, jobject obj) : obj_(obj) {}
  61. #endif
  62. // Used for move semantics. obj_ must have been released first if non-null.
  63. void steal(JavaRef&& other) {
  64. obj_ = other.obj_;
  65. other.obj_ = nullptr;
  66. }
  67. // The following are implementation detail convenience methods, for
  68. // use by the sub-classes.
  69. JNIEnv* SetNewLocalRef(JNIEnv* env, jobject obj);
  70. void SetNewGlobalRef(JNIEnv* env, jobject obj);
  71. void ResetLocalRef(JNIEnv* env);
  72. void ResetGlobalRef();
  73. jobject ReleaseInternal();
  74. private:
  75. jobject obj_ = nullptr;
  76. DISALLOW_COPY_AND_ASSIGN(JavaRef);
  77. };
  78. // Forward declare the object array reader for the convenience function.
  79. template <typename T>
  80. class JavaObjectArrayReader;
  81. // Generic base class for ScopedJavaLocalRef and ScopedJavaGlobalRef. Useful
  82. // for allowing functions to accept a reference without having to mandate
  83. // whether it is a local or global type.
  84. template <typename T>
  85. class JavaRef : public JavaRef<jobject> {
  86. public:
  87. constexpr JavaRef() {}
  88. constexpr JavaRef(std::nullptr_t) {}
  89. ~JavaRef() {}
  90. T obj() const { return static_cast<T>(JavaRef<jobject>::obj()); }
  91. // Get a JavaObjectArrayReader for the array pointed to by this reference.
  92. // Only defined for JavaRef<jobjectArray>.
  93. // You must pass the type of the array elements (usually jobject) as the
  94. // template parameter.
  95. template <typename ElementType,
  96. typename T_ = T,
  97. typename = std::enable_if_t<std::is_same<T_, jobjectArray>::value>>
  98. JavaObjectArrayReader<ElementType> ReadElements() const {
  99. return JavaObjectArrayReader<ElementType>(*this);
  100. }
  101. protected:
  102. JavaRef(JNIEnv* env, T obj) : JavaRef<jobject>(env, obj) {}
  103. private:
  104. DISALLOW_COPY_AND_ASSIGN(JavaRef);
  105. };
  106. // Holds a local reference to a JNI method parameter.
  107. // Method parameters should not be deleted, and so this class exists purely to
  108. // wrap them as a JavaRef<T> in the JNI binding generator. Do not create
  109. // instances manually.
  110. template <typename T>
  111. class JavaParamRef : public JavaRef<T> {
  112. public:
  113. // Assumes that |obj| is a parameter passed to a JNI method from Java.
  114. // Does not assume ownership as parameters should not be deleted.
  115. JavaParamRef(JNIEnv* env, T obj) : JavaRef<T>(env, obj) {}
  116. // Allow nullptr to be converted to JavaParamRef. Some unit tests call JNI
  117. // methods directly from C++ and pass null for objects which are not actually
  118. // used by the implementation (e.g. the caller object); allow this to keep
  119. // working.
  120. JavaParamRef(std::nullptr_t) {}
  121. ~JavaParamRef() {}
  122. // TODO(torne): remove this cast once we're using JavaRef consistently.
  123. // http://crbug.com/506850
  124. operator T() const { return JavaRef<T>::obj(); }
  125. private:
  126. DISALLOW_COPY_AND_ASSIGN(JavaParamRef);
  127. };
  128. // Holds a local reference to a Java object. The local reference is scoped
  129. // to the lifetime of this object.
  130. // Instances of this class may hold onto any JNIEnv passed into it until
  131. // destroyed. Therefore, since a JNIEnv is only suitable for use on a single
  132. // thread, objects of this class must be created, used, and destroyed, on a
  133. // single thread.
  134. // Therefore, this class should only be used as a stack-based object and from a
  135. // single thread. If you wish to have the reference outlive the current
  136. // callstack (e.g. as a class member) or you wish to pass it across threads,
  137. // use a ScopedJavaGlobalRef instead.
  138. template <typename T>
  139. class ScopedJavaLocalRef : public JavaRef<T> {
  140. public:
  141. // Take ownership of a bare jobject. This does not create a new reference.
  142. // This should only be used by JNI helper functions, or in cases where code
  143. // must call JNIEnv methods directly.
  144. static ScopedJavaLocalRef Adopt(JNIEnv* env, T obj) {
  145. return ScopedJavaLocalRef(env, obj);
  146. }
  147. constexpr ScopedJavaLocalRef() {}
  148. constexpr ScopedJavaLocalRef(std::nullptr_t) {}
  149. // Copy constructor. This is required in addition to the copy conversion
  150. // constructor below.
  151. ScopedJavaLocalRef(const ScopedJavaLocalRef& other) : env_(other.env_) {
  152. JavaRef<T>::SetNewLocalRef(env_, other.obj());
  153. }
  154. // Copy conversion constructor.
  155. template <typename U,
  156. typename = std::enable_if_t<std::is_convertible<U, T>::value>>
  157. ScopedJavaLocalRef(const ScopedJavaLocalRef<U>& other) : env_(other.env_) {
  158. JavaRef<T>::SetNewLocalRef(env_, other.obj());
  159. }
  160. // Move constructor. This is required in addition to the move conversion
  161. // constructor below.
  162. ScopedJavaLocalRef(ScopedJavaLocalRef&& other) : env_(other.env_) {
  163. JavaRef<T>::steal(std::move(other));
  164. }
  165. // Move conversion constructor.
  166. template <typename U,
  167. typename = std::enable_if_t<std::is_convertible<U, T>::value>>
  168. ScopedJavaLocalRef(ScopedJavaLocalRef<U>&& other) : env_(other.env_) {
  169. JavaRef<T>::steal(std::move(other));
  170. }
  171. // Constructor for other JavaRef types.
  172. explicit ScopedJavaLocalRef(const JavaRef<T>& other) { Reset(other); }
  173. // Assumes that |obj| is a local reference to a Java object and takes
  174. // ownership of this local reference.
  175. // TODO(torne): make legitimate uses call Adopt() instead, and make this
  176. // private.
  177. ScopedJavaLocalRef(JNIEnv* env, T obj) : JavaRef<T>(env, obj), env_(env) {}
  178. ~ScopedJavaLocalRef() { Reset(); }
  179. // Null assignment, for disambiguation.
  180. ScopedJavaLocalRef& operator=(std::nullptr_t) {
  181. Reset();
  182. return *this;
  183. }
  184. // Copy assignment.
  185. ScopedJavaLocalRef& operator=(const ScopedJavaLocalRef& other) {
  186. Reset(other);
  187. return *this;
  188. }
  189. // Copy conversion assignment.
  190. template <typename U,
  191. typename = std::enable_if_t<std::is_convertible<U, T>::value>>
  192. ScopedJavaLocalRef& operator=(const ScopedJavaLocalRef<U>& other) {
  193. Reset(other);
  194. return *this;
  195. }
  196. // Move assignment.
  197. template <typename U,
  198. typename = std::enable_if_t<std::is_convertible<U, T>::value>>
  199. ScopedJavaLocalRef& operator=(ScopedJavaLocalRef<U>&& other) {
  200. env_ = other.env_;
  201. Reset();
  202. JavaRef<T>::steal(std::move(other));
  203. return *this;
  204. }
  205. // Assignment for other JavaRef types.
  206. ScopedJavaLocalRef& operator=(const JavaRef<T>& other) {
  207. Reset(other);
  208. return *this;
  209. }
  210. void Reset() { JavaRef<T>::ResetLocalRef(env_); }
  211. template <typename U,
  212. typename = std::enable_if_t<std::is_convertible<U, T>::value>>
  213. void Reset(const ScopedJavaLocalRef<U>& other) {
  214. // We can copy over env_ here as |other| instance must be from the same
  215. // thread as |this| local ref. (See class comment for multi-threading
  216. // limitations, and alternatives).
  217. Reset(other.env_, other.obj());
  218. }
  219. void Reset(const JavaRef<T>& other) {
  220. // If |env_| was not yet set (is still null) it will be attached to the
  221. // current thread in SetNewLocalRef().
  222. Reset(env_, other.obj());
  223. }
  224. // Creates a new local reference to the Java object, unlike the constructor
  225. // with the same parameters that takes ownership of the existing reference.
  226. // Deprecated. Don't use bare jobjects; use a JavaRef as the input.
  227. // TODO(torne): fix existing usage and remove this.
  228. void Reset(JNIEnv* env, T obj) {
  229. env_ = JavaRef<T>::SetNewLocalRef(env, obj);
  230. }
  231. // Releases the local reference to the caller. The caller *must* delete the
  232. // local reference when it is done with it. Note that calling a Java method
  233. // is *not* a transfer of ownership and Release() should not be used.
  234. T Release() { return static_cast<T>(JavaRef<T>::ReleaseInternal()); }
  235. private:
  236. // This class is only good for use on the thread it was created on so
  237. // it's safe to cache the non-threadsafe JNIEnv* inside this object.
  238. JNIEnv* env_ = nullptr;
  239. // Prevent ScopedJavaLocalRef(JNIEnv*, T obj) from being used to take
  240. // ownership of a JavaParamRef's underlying object - parameters are not
  241. // allowed to be deleted and so should not be owned by ScopedJavaLocalRef.
  242. // TODO(torne): this can be removed once JavaParamRef no longer has an
  243. // implicit conversion back to T.
  244. ScopedJavaLocalRef(JNIEnv* env, const JavaParamRef<T>& other);
  245. // Friend required to get env_ from conversions.
  246. template <typename U>
  247. friend class ScopedJavaLocalRef;
  248. // Avoids JavaObjectArrayReader having to accept and store its own env.
  249. template <typename U>
  250. friend class JavaObjectArrayReader;
  251. };
  252. // Holds a global reference to a Java object. The global reference is scoped
  253. // to the lifetime of this object. This class does not hold onto any JNIEnv*
  254. // passed to it, hence it is safe to use across threads (within the constraints
  255. // imposed by the underlying Java object that it references).
  256. template <typename T>
  257. class ScopedJavaGlobalRef : public JavaRef<T> {
  258. public:
  259. constexpr ScopedJavaGlobalRef() {}
  260. constexpr ScopedJavaGlobalRef(std::nullptr_t) {}
  261. // Copy constructor. This is required in addition to the copy conversion
  262. // constructor below.
  263. ScopedJavaGlobalRef(const ScopedJavaGlobalRef& other) { Reset(other); }
  264. // Copy conversion constructor.
  265. template <typename U,
  266. typename = std::enable_if_t<std::is_convertible<U, T>::value>>
  267. ScopedJavaGlobalRef(const ScopedJavaGlobalRef<U>& other) {
  268. Reset(other);
  269. }
  270. // Move constructor. This is required in addition to the move conversion
  271. // constructor below.
  272. ScopedJavaGlobalRef(ScopedJavaGlobalRef&& other) {
  273. JavaRef<T>::steal(std::move(other));
  274. }
  275. // Move conversion constructor.
  276. template <typename U,
  277. typename = std::enable_if_t<std::is_convertible<U, T>::value>>
  278. ScopedJavaGlobalRef(ScopedJavaGlobalRef<U>&& other) {
  279. JavaRef<T>::steal(std::move(other));
  280. }
  281. // Conversion constructor for other JavaRef types.
  282. explicit ScopedJavaGlobalRef(const JavaRef<T>& other) { Reset(other); }
  283. // Create a new global reference to the object.
  284. // Deprecated. Don't use bare jobjects; use a JavaRef as the input.
  285. ScopedJavaGlobalRef(JNIEnv* env, T obj) { Reset(env, obj); }
  286. ~ScopedJavaGlobalRef() { Reset(); }
  287. // Null assignment, for disambiguation.
  288. ScopedJavaGlobalRef& operator=(std::nullptr_t) {
  289. Reset();
  290. return *this;
  291. }
  292. // Copy assignment.
  293. ScopedJavaGlobalRef& operator=(const ScopedJavaGlobalRef& other) {
  294. Reset(other);
  295. return *this;
  296. }
  297. // Copy conversion assignment.
  298. template <typename U,
  299. typename = std::enable_if_t<std::is_convertible<U, T>::value>>
  300. ScopedJavaGlobalRef& operator=(const ScopedJavaGlobalRef<U>& other) {
  301. Reset(other);
  302. return *this;
  303. }
  304. // Move assignment.
  305. template <typename U,
  306. typename = std::enable_if_t<std::is_convertible<U, T>::value>>
  307. ScopedJavaGlobalRef& operator=(ScopedJavaGlobalRef<U>&& other) {
  308. Reset();
  309. JavaRef<T>::steal(std::move(other));
  310. return *this;
  311. }
  312. // Assignment for other JavaRef types.
  313. ScopedJavaGlobalRef& operator=(const JavaRef<T>& other) {
  314. Reset(other);
  315. return *this;
  316. }
  317. void Reset() { JavaRef<T>::ResetGlobalRef(); }
  318. template <typename U,
  319. typename = std::enable_if_t<std::is_convertible<U, T>::value>>
  320. void Reset(const ScopedJavaGlobalRef<U>& other) {
  321. Reset(nullptr, other.obj());
  322. }
  323. void Reset(const JavaRef<T>& other) { Reset(nullptr, other.obj()); }
  324. // Deprecated. You can just use Reset(const JavaRef&).
  325. void Reset(JNIEnv* env, const JavaParamRef<T>& other) {
  326. Reset(env, other.obj());
  327. }
  328. // Deprecated. Don't use bare jobjects; use a JavaRef as the input.
  329. void Reset(JNIEnv* env, T obj) { JavaRef<T>::SetNewGlobalRef(env, obj); }
  330. // Releases the global reference to the caller. The caller *must* delete the
  331. // global reference when it is done with it. Note that calling a Java method
  332. // is *not* a transfer of ownership and Release() should not be used.
  333. T Release() { return static_cast<T>(JavaRef<T>::ReleaseInternal()); }
  334. };
  335. // Wrapper for a jobjectArray which supports input iteration, allowing Java
  336. // arrays to be iterated over with a range-based for loop, or used with
  337. // <algorithm> functions that accept input iterators.
  338. //
  339. // The iterator returns each object in the array in turn, wrapped in a
  340. // ScopedJavaLocalRef<T>. T will usually be jobject, but if you know that the
  341. // array contains a more specific type (such as jstring) you can use that
  342. // instead. This does not check the type at runtime!
  343. //
  344. // The wrapper holds a local reference to the array and only queries the size of
  345. // the array once, so must only be used as a stack-based object from the current
  346. // thread.
  347. //
  348. // Note that this does *not* update the contents of the array if you mutate the
  349. // returned ScopedJavaLocalRef.
  350. template <typename T>
  351. class JavaObjectArrayReader {
  352. public:
  353. class iterator {
  354. public:
  355. // We can only be an input iterator, as all richer iterator types must
  356. // implement the multipass guarantee (always returning the same object for
  357. // the same iterator position), which is not practical when returning
  358. // temporary objects.
  359. using iterator_category = std::input_iterator_tag;
  360. using difference_type = ptrdiff_t;
  361. using value_type = ScopedJavaLocalRef<T>;
  362. // It doesn't make sense to return a reference type as the iterator creates
  363. // temporary wrapper objects when dereferenced. Fortunately, it's not
  364. // required that input iterators actually use references, and defining it
  365. // as value_type is valid.
  366. using reference = value_type;
  367. // This exists to make operator-> work as expected: its return value must
  368. // resolve to an actual pointer (otherwise the compiler just keeps calling
  369. // operator-> on the return value until it does), so we need an extra level
  370. // of indirection. This is sometimes called an "arrow proxy" or similar, and
  371. // this version is adapted from base/value_iterators.h.
  372. class pointer {
  373. public:
  374. explicit pointer(const reference& ref) : ref_(ref) {}
  375. pointer(const pointer& ptr) = default;
  376. pointer& operator=(const pointer& ptr) = delete;
  377. reference* operator->() { return &ref_; }
  378. private:
  379. reference ref_;
  380. };
  381. iterator(const iterator&) = default;
  382. ~iterator() = default;
  383. iterator& operator=(const iterator&) = default;
  384. bool operator==(const iterator& other) const {
  385. DCHECK(reader_ == other.reader_);
  386. return i_ == other.i_;
  387. }
  388. bool operator!=(const iterator& other) const {
  389. DCHECK(reader_ == other.reader_);
  390. return i_ != other.i_;
  391. }
  392. reference operator*() const {
  393. DCHECK(i_ < reader_->size_);
  394. // JNIEnv functions return unowned local references; take ownership with
  395. // Adopt so that ~ScopedJavaLocalRef will release it automatically later.
  396. return value_type::Adopt(
  397. reader_->array_.env_,
  398. static_cast<T>(reader_->array_.env_->GetObjectArrayElement(
  399. reader_->array_.obj(), i_)));
  400. }
  401. pointer operator->() const { return pointer(operator*()); }
  402. iterator& operator++() {
  403. DCHECK(i_ < reader_->size_);
  404. ++i_;
  405. return *this;
  406. }
  407. iterator operator++(int) {
  408. iterator old = *this;
  409. ++*this;
  410. return old;
  411. }
  412. private:
  413. iterator(const JavaObjectArrayReader* reader, jsize i)
  414. : reader_(reader), i_(i) {}
  415. const JavaObjectArrayReader* reader_;
  416. jsize i_;
  417. friend JavaObjectArrayReader;
  418. };
  419. JavaObjectArrayReader(const JavaRef<jobjectArray>& array) : array_(array) {
  420. size_ = array_.env_->GetArrayLength(array_.obj());
  421. }
  422. // Copy constructor to allow returning it from JavaRef::ReadElements().
  423. JavaObjectArrayReader(const JavaObjectArrayReader& other) = default;
  424. // Assignment operator for consistency with copy constructor.
  425. JavaObjectArrayReader& operator=(const JavaObjectArrayReader& other) =
  426. default;
  427. // Allow move constructor and assignment since this owns a local ref.
  428. JavaObjectArrayReader(JavaObjectArrayReader&& other) = default;
  429. JavaObjectArrayReader& operator=(JavaObjectArrayReader&& other) = default;
  430. bool empty() const { return size_ == 0; }
  431. jsize size() const { return size_; }
  432. iterator begin() const { return iterator(this, 0); }
  433. iterator end() const { return iterator(this, size_); }
  434. private:
  435. ScopedJavaLocalRef<jobjectArray> array_;
  436. jsize size_;
  437. friend iterator;
  438. };
  439. } // namespace android
  440. } // namespace base
  441. #endif // BASE_ANDROID_SCOPED_JAVA_REF_H_