| Index: base/android/scoped_java_ref.h
|
| diff --git a/base/android/scoped_java_ref.h b/base/android/scoped_java_ref.h
|
| index dd93b25f1542da677459472aeb42aa0c3e3e28d8..0d1e590f295f9caf7e4ee1a98f197323e705c24f 100644
|
| --- a/base/android/scoped_java_ref.h
|
| +++ b/base/android/scoped_java_ref.h
|
| @@ -22,7 +22,6 @@ template<typename T> class JavaRef;
|
| template<>
|
| class JavaRef<jobject> {
|
| public:
|
| - JNIEnv* env() const { return env_; }
|
| jobject obj() const { return obj_; }
|
|
|
| bool is_null() const { return obj_ == NULL; }
|
| @@ -39,14 +38,13 @@ class JavaRef<jobject> {
|
|
|
| // The following are implementation detail convenience methods, for
|
| // use by the sub-classes.
|
| - void SetNewLocalRef(JNIEnv* env, jobject obj);
|
| + JNIEnv* SetNewLocalRef(JNIEnv* env, jobject obj);
|
| void SetNewGlobalRef(JNIEnv* env, jobject obj);
|
| - void ResetLocalRef();
|
| + void ResetLocalRef(JNIEnv* env);
|
| void ResetGlobalRef();
|
| jobject ReleaseInternal();
|
|
|
| private:
|
| - JNIEnv* env_;
|
| jobject obj_;
|
|
|
| DISALLOW_COPY_AND_ASSIGN(JavaRef);
|
| @@ -71,31 +69,36 @@ class JavaRef : public JavaRef<jobject> {
|
| };
|
|
|
| // Holds a local reference to a Java object. The local reference is scoped
|
| -// to the lifetime of this object. Note that since a JNI Env is only suitable
|
| -// for use on a single thread, objects of this class must be created, used and
|
| -// destroyed on the same thread.
|
| -// In general, this class should only be used as a stack-based object. If you
|
| -// wish to have the reference outlive the current callstack (e.g. as a class
|
| -// member) use ScopedJavaGlobalRef instead.
|
| +// to the lifetime of this object.
|
| +// Instances of this class may hold onto any JNIEnv passed into it until
|
| +// destroyed. Therefore, since a JNIEnv is only suitable for use on a single
|
| +// thread, objects of this class must be created, used, and destroyed, on a
|
| +// single thread.
|
| +// Therefore, this class should only be used as a stack-based object and from a
|
| +// single thread. If you wish to have the reference outlive the current
|
| +// callstack (e.g. as a class member) or you wish to pass it across threads,
|
| +// use a ScopedJavaGlobalRef instead.
|
| template<typename T>
|
| class ScopedJavaLocalRef : public JavaRef<T> {
|
| public:
|
| - ScopedJavaLocalRef() {}
|
| + ScopedJavaLocalRef() : env_(NULL) {}
|
|
|
| // Non-explicit copy constructor, to allow ScopedJavaLocalRef to be returned
|
| // by value as this is the normal usage pattern.
|
| - ScopedJavaLocalRef(const ScopedJavaLocalRef<T>& other) {
|
| - this->Reset(other);
|
| + ScopedJavaLocalRef(const ScopedJavaLocalRef<T>& other)
|
| + : env_(other.env_) {
|
| + this->SetNewLocalRef(env_, other.obj());
|
| }
|
|
|
| template<typename U>
|
| - explicit ScopedJavaLocalRef(const U& other) {
|
| + explicit ScopedJavaLocalRef(const U& other)
|
| + : env_(NULL) {
|
| this->Reset(other);
|
| }
|
|
|
| // Assumes that |obj| is a local reference to a Java object and takes
|
| // ownership of this local reference.
|
| - ScopedJavaLocalRef(JNIEnv* env, T obj) : JavaRef<T>(env, obj) {}
|
| + ScopedJavaLocalRef(JNIEnv* env, T obj) : JavaRef<T>(env, obj), env_(env) {}
|
|
|
| ~ScopedJavaLocalRef() {
|
| this->Reset();
|
| @@ -108,18 +111,28 @@ class ScopedJavaLocalRef : public JavaRef<T> {
|
| }
|
|
|
| void Reset() {
|
| - this->ResetLocalRef();
|
| + this->ResetLocalRef(env_);
|
| + }
|
| +
|
| + template<typename U>
|
| + void Reset(const ScopedJavaLocalRef<U>& other) {
|
| + // We can copy over env_ here as |other| instance must be from the same
|
| + // thread as |this| local ref. (See class comment for multi-threading
|
| + // limitations, and alternatives).
|
| + this->Reset(other.env_, other.obj());
|
| }
|
|
|
| template<typename U>
|
| void Reset(const U& other) {
|
| - this->Reset(other.env(), other.obj());
|
| + // If |env_| was not yet set (is still NULL) it will be attached to the
|
| + // current thread in SetNewLocalRef().
|
| + this->Reset(env_, other.obj());
|
| }
|
|
|
| template<typename U>
|
| void Reset(JNIEnv* env, U obj) {
|
| implicit_cast<T>(obj); // Ensure U is assignable to T
|
| - this->SetNewLocalRef(env, obj);
|
| + env_ = this->SetNewLocalRef(env, obj);
|
| }
|
|
|
| // Releases the local reference to the caller. The caller *must* delete the
|
| @@ -127,12 +140,17 @@ class ScopedJavaLocalRef : public JavaRef<T> {
|
| T Release() {
|
| return static_cast<T>(this->ReleaseInternal());
|
| }
|
| +
|
| + private:
|
| + // This class is only good for use on the thread it was created on so
|
| + // it's safe to cache the non-threadsafe JNIEnv* inside this object.
|
| + JNIEnv* env_;
|
| };
|
|
|
| // Holds a global reference to a Java object. The global reference is scoped
|
| -// to the lifetime of this object. Note that since a JNI Env is only suitable
|
| -// for use on a single thread, objects of this class must be created, used and
|
| -// destroyed on the same thread.
|
| +// to the lifetime of this object. This class does not hold onto any JNIEnv*
|
| +// passed to it, hence it is safe to use across threads (within the constraints
|
| +// imposed by the underlying Java object that it references).
|
| template<typename T>
|
| class ScopedJavaGlobalRef : public JavaRef<T> {
|
| public:
|
| @@ -157,7 +175,7 @@ class ScopedJavaGlobalRef : public JavaRef<T> {
|
|
|
| template<typename U>
|
| void Reset(const U& other) {
|
| - this->Reset(other.env(), other.obj());
|
| + this->Reset(NULL, other.obj());
|
| }
|
|
|
| template<typename U>
|
|
|