1 // Copyright 2024 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "third_party/jni_zero/java_refs.h"
6
7 #include "third_party/jni_zero/jni_methods.h"
8
9 namespace jni_zero {
10 namespace {
11 const int kDefaultLocalFrameCapacity = 16;
12 }
13
ScopedJavaLocalFrame(JNIEnv * env)14 ScopedJavaLocalFrame::ScopedJavaLocalFrame(JNIEnv* env) : env_(env) {
15 int failed = env_->PushLocalFrame(kDefaultLocalFrameCapacity);
16 JNI_ZERO_DCHECK(!failed);
17 }
18
ScopedJavaLocalFrame(JNIEnv * env,int capacity)19 ScopedJavaLocalFrame::ScopedJavaLocalFrame(JNIEnv* env, int capacity)
20 : env_(env) {
21 int failed = env_->PushLocalFrame(capacity);
22 JNI_ZERO_DCHECK(!failed);
23 }
24
~ScopedJavaLocalFrame()25 ScopedJavaLocalFrame::~ScopedJavaLocalFrame() {
26 env_->PopLocalFrame(nullptr);
27 }
28
29 #if JNI_ZERO_DCHECK_IS_ON()
30 // This constructor is inlined when DCHECKs are disabled; don't add anything
31 // else here.
JavaRef(JNIEnv * env,jobject obj)32 JavaRef<jobject>::JavaRef(JNIEnv* env, jobject obj) : obj_(obj) {
33 if (obj) {
34 JNI_ZERO_DCHECK(env && env->GetObjectRefType(obj) == JNILocalRefType);
35 }
36 }
37 #endif
38
SetNewLocalRef(JNIEnv * env,jobject obj)39 JNIEnv* JavaRef<jobject>::SetNewLocalRef(JNIEnv* env, jobject obj) {
40 if (!env) {
41 env = AttachCurrentThread();
42 } else {
43 JNI_ZERO_DCHECK(env ==
44 AttachCurrentThread()); // Is |env| on correct thread.
45 }
46 if (obj) {
47 obj = env->NewLocalRef(obj);
48 }
49 if (obj_) {
50 env->DeleteLocalRef(obj_);
51 }
52 obj_ = obj;
53 return env;
54 }
55
SetNewGlobalRef(JNIEnv * env,jobject obj)56 void JavaRef<jobject>::SetNewGlobalRef(JNIEnv* env, jobject obj) {
57 if (!env) {
58 env = AttachCurrentThread();
59 } else {
60 JNI_ZERO_DCHECK(env ==
61 AttachCurrentThread()); // Is |env| on correct thread.
62 }
63 if (obj) {
64 obj = env->NewGlobalRef(obj);
65 }
66 if (obj_) {
67 env->DeleteGlobalRef(obj_);
68 }
69 obj_ = obj;
70 }
71
ResetLocalRef(JNIEnv * env)72 void JavaRef<jobject>::ResetLocalRef(JNIEnv* env) {
73 if (obj_) {
74 JNI_ZERO_DCHECK(env ==
75 AttachCurrentThread()); // Is |env| on correct thread.
76 env->DeleteLocalRef(obj_);
77 obj_ = nullptr;
78 }
79 }
80
ResetGlobalRef()81 void JavaRef<jobject>::ResetGlobalRef() {
82 if (obj_) {
83 AttachCurrentThread()->DeleteGlobalRef(obj_);
84 obj_ = nullptr;
85 }
86 }
87
ScopedJavaGlobalWeakRef(const ScopedJavaGlobalWeakRef & orig)88 ScopedJavaGlobalWeakRef::ScopedJavaGlobalWeakRef(
89 const ScopedJavaGlobalWeakRef& orig) {
90 Assign(orig);
91 }
92
ScopedJavaGlobalWeakRef(JNIEnv * env,const JavaRef<jobject> & obj)93 ScopedJavaGlobalWeakRef::ScopedJavaGlobalWeakRef(JNIEnv* env,
94 const JavaRef<jobject>& obj)
95 : obj_(env->NewWeakGlobalRef(obj.obj())) {}
96
reset()97 void ScopedJavaGlobalWeakRef::reset() {
98 if (obj_) {
99 AttachCurrentThread()->DeleteWeakGlobalRef(obj_);
100 obj_ = nullptr;
101 }
102 }
103
get(JNIEnv * env) const104 ScopedJavaLocalRef<jobject> ScopedJavaGlobalWeakRef::get(JNIEnv* env) const {
105 jobject real = obj_ ? real = env->NewLocalRef(obj_) : nullptr;
106 return ScopedJavaLocalRef<jobject>(env, real);
107 }
108
Assign(const ScopedJavaGlobalWeakRef & other)109 void ScopedJavaGlobalWeakRef::Assign(const ScopedJavaGlobalWeakRef& other) {
110 if (&other == this) {
111 return;
112 }
113
114 JNIEnv* env = AttachCurrentThread();
115 if (obj_) {
116 env->DeleteWeakGlobalRef(obj_);
117 }
118
119 obj_ = other.obj_ ? env->NewWeakGlobalRef(other.obj_) : nullptr;
120 }
121
122 } // namespace jni_zero
123