Flutter Engine
scoped_java_ref.h
Go to the documentation of this file.
1 // Copyright 2013 The Flutter 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 
5 #ifndef FLUTTER_FML_PLATFORM_ANDROID_SCOPED_JAVA_REF_H_
6 #define FLUTTER_FML_PLATFORM_ANDROID_SCOPED_JAVA_REF_H_
7 
8 #include <jni.h>
9 
10 #include <cstddef>
11 
12 #include "flutter/fml/macros.h"
13 
14 namespace fml {
15 namespace jni {
16 
17 // Creates a new local reference frame, in which at least a given number of
18 // local references can be created. Note that local references already created
19 // in previous local frames are still valid in the current local frame.
21  public:
22  explicit ScopedJavaLocalFrame(JNIEnv* env);
23  ScopedJavaLocalFrame(JNIEnv* env, int capacity);
25 
26  private:
27  // This class is only good for use on the thread it was created on so
28  // it's safe to cache the non-threadsafe JNIEnv* inside this object.
29  JNIEnv* env_;
30 
31  FML_DISALLOW_COPY_AND_ASSIGN(ScopedJavaLocalFrame);
32 };
33 
34 // Forward declare the generic java reference template class.
35 template <typename T>
36 class JavaRef;
37 
38 // Template specialization of JavaRef, which acts as the base class for all
39 // other JavaRef<> template types. This allows you to e.g. pass
40 // ScopedJavaLocalRef<jstring> into a function taking const JavaRef<jobject>&
41 template <>
42 class JavaRef<jobject> {
43  public:
44  jobject obj() const { return obj_; }
45 
46  bool is_null() const { return obj_ == NULL; }
47 
48  protected:
49  // Initializes a NULL reference.
50  JavaRef();
51 
52  // Takes ownership of the |obj| reference passed; requires it to be a local
53  // reference type.
54  JavaRef(JNIEnv* env, jobject obj);
55 
56  ~JavaRef();
57 
58  // The following are implementation detail convenience methods, for
59  // use by the sub-classes.
60  JNIEnv* SetNewLocalRef(JNIEnv* env, jobject obj);
61  void SetNewGlobalRef(JNIEnv* env, jobject obj);
62  void ResetLocalRef(JNIEnv* env);
63  void ResetGlobalRef();
64  jobject ReleaseInternal();
65 
66  private:
67  jobject obj_;
68 
70 };
71 
72 // Generic base class for ScopedJavaLocalRef and ScopedJavaGlobalRef. Useful
73 // for allowing functions to accept a reference without having to mandate
74 // whether it is a local or global type.
75 template <typename T>
76 class JavaRef : public JavaRef<jobject> {
77  public:
78  T obj() const { return static_cast<T>(JavaRef<jobject>::obj()); }
79 
80  protected:
81  JavaRef() {}
82  ~JavaRef() {}
83 
84  JavaRef(JNIEnv* env, T obj) : JavaRef<jobject>(env, obj) {}
85 
86  private:
88 };
89 
90 // Holds a local reference to a Java object. The local reference is scoped
91 // to the lifetime of this object.
92 // Instances of this class may hold onto any JNIEnv passed into it until
93 // destroyed. Therefore, since a JNIEnv is only suitable for use on a single
94 // thread, objects of this class must be created, used, and destroyed, on a
95 // single thread.
96 // Therefore, this class should only be used as a stack-based object and from a
97 // single thread. If you wish to have the reference outlive the current
98 // callstack (e.g. as a class member) or you wish to pass it across threads,
99 // use a ScopedJavaGlobalRef instead.
100 template <typename T>
101 class ScopedJavaLocalRef : public JavaRef<T> {
102  public:
103  ScopedJavaLocalRef() : env_(NULL) {}
104 
105  // Non-explicit copy constructor, to allow ScopedJavaLocalRef to be returned
106  // by value as this is the normal usage pattern.
107  ScopedJavaLocalRef(const ScopedJavaLocalRef<T>& other) : env_(other.env_) {
108  this->SetNewLocalRef(env_, other.obj());
109  }
110 
111  template <typename U>
112  explicit ScopedJavaLocalRef(const U& other) : env_(NULL) {
113  this->Reset(other);
114  }
115 
116  // Assumes that |obj| is a local reference to a Java object and takes
117  // ownership of this local reference.
118  ScopedJavaLocalRef(JNIEnv* env, T obj) : JavaRef<T>(env, obj), env_(env) {}
119 
120  ~ScopedJavaLocalRef() { this->Reset(); }
121 
122  // Overloaded assignment operator defined for consistency with the implicit
123  // copy constructor.
124  void operator=(const ScopedJavaLocalRef<T>& other) { this->Reset(other); }
125 
126  void Reset() { this->ResetLocalRef(env_); }
127 
128  template <typename U>
129  void Reset(const ScopedJavaLocalRef<U>& other) {
130  // We can copy over env_ here as |other| instance must be from the same
131  // thread as |this| local ref. (See class comment for multi-threading
132  // limitations, and alternatives).
133  this->Reset(other.env_, other.obj());
134  }
135 
136  template <typename U>
137  void Reset(const U& other) {
138  // If |env_| was not yet set (is still NULL) it will be attached to the
139  // current thread in SetNewLocalRef().
140  this->Reset(env_, other.obj());
141  }
142 
143  template <typename U>
144  void Reset(JNIEnv* env, U obj) {
145  env_ = this->SetNewLocalRef(env, obj);
146  }
147 
148  // Releases the local reference to the caller. The caller *must* delete the
149  // local reference when it is done with it.
150  T Release() { return static_cast<T>(this->ReleaseInternal()); }
151 
152  private:
153  // This class is only good for use on the thread it was created on so
154  // it's safe to cache the non-threadsafe JNIEnv* inside this object.
155  JNIEnv* env_;
156 };
157 
158 // Holds a global reference to a Java object. The global reference is scoped
159 // to the lifetime of this object. This class does not hold onto any JNIEnv*
160 // passed to it, hence it is safe to use across threads (within the constraints
161 // imposed by the underlying Java object that it references).
162 template <typename T>
163 class ScopedJavaGlobalRef : public JavaRef<T> {
164  public:
166 
168  this->Reset(other);
169  }
170 
171  ScopedJavaGlobalRef(JNIEnv* env, T obj) { this->Reset(env, obj); }
172 
173  template <typename U>
174  explicit ScopedJavaGlobalRef(const U& other) {
175  this->Reset(other);
176  }
177 
178  ~ScopedJavaGlobalRef() { this->Reset(); }
179 
180  void Reset() { this->ResetGlobalRef(); }
181 
182  template <typename U>
183  void Reset(const U& other) {
184  this->Reset(NULL, other.obj());
185  }
186 
187  template <typename U>
188  void Reset(JNIEnv* env, U obj) {
189  this->SetNewGlobalRef(env, obj);
190  }
191 
192  // Releases the global reference to the caller. The caller *must* delete the
193  // global reference when it is done with it.
194  T Release() { return static_cast<T>(this->ReleaseInternal()); }
195 };
196 
197 } // namespace jni
198 } // namespace fml
199 
200 #endif // FLUTTER_FML_PLATFORM_ANDROID_SCOPED_JAVA_REF_H_
ScopedJavaLocalRef(const ScopedJavaLocalRef< T > &other)
void Reset(const ScopedJavaLocalRef< U > &other)
void Reset(const U &other)
Definition: ascii_trie.cc:9
ScopedJavaLocalRef(JNIEnv *env, T obj)
ScopedJavaLocalRef(const U &other)
JavaRef(JNIEnv *env, T obj)
void Reset(JNIEnv *env, U obj)
ScopedJavaGlobalRef(JNIEnv *env, T obj)
void operator=(const ScopedJavaLocalRef< T > &other)
ScopedJavaGlobalRef(const ScopedJavaGlobalRef< T > &other)
void Reset(const U &other)
#define FML_DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition: macros.h:27
void Reset(JNIEnv *env, U obj)