blob: 170887e397f57eb98a0633d42597cc97f2214869 [file] [log] [blame]
Elliott Hughes64f574f2013-02-20 14:57:12 -08001/*
2 * Copyright (C) 2013 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#include "object_registry.h"
18
Sebastien Hertze2d628b2014-10-23 15:39:33 +020019#include "handle_scope-inl.h"
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070020#include "jni_internal.h"
Ian Rogerse63db272014-07-15 15:36:11 -070021#include "mirror/class.h"
Mathieu Chartier3398c782016-09-30 10:27:43 -070022#include "obj_ptr-inl.h"
Mathieu Chartier0795f232016-09-27 18:43:30 -070023#include "scoped_thread_state_change-inl.h"
Elliott Hughes64f574f2013-02-20 14:57:12 -080024
25namespace art {
26
Elliott Hughes64f574f2013-02-20 14:57:12 -080027std::ostream& operator<<(std::ostream& os, const ObjectRegistryEntry& rhs) {
28 os << "ObjectRegistryEntry[" << rhs.jni_reference_type
29 << ",reference=" << rhs.jni_reference
30 << ",count=" << rhs.reference_count
31 << ",id=" << rhs.id << "]";
32 return os;
33}
34
Elliott Hughes0f827162013-02-26 12:12:58 -080035ObjectRegistry::ObjectRegistry()
Hiroshi Yamauchib5a9e3d2014-06-09 12:11:20 -070036 : lock_("ObjectRegistry lock", kJdwpObjectRegistryLock), next_id_(1) {
Elliott Hughes64f574f2013-02-20 14:57:12 -080037}
38
Mathieu Chartier3398c782016-09-30 10:27:43 -070039JDWP::RefTypeId ObjectRegistry::AddRefType(ObjPtr<mirror::Class> c) {
Sebastien Hertz261bc042015-04-08 09:36:07 +020040 return Add(c);
41}
42
43JDWP::RefTypeId ObjectRegistry::AddRefType(Handle<mirror::Class> c_h) {
44 return Add(c_h);
Elliott Hughes64f574f2013-02-20 14:57:12 -080045}
46
Mathieu Chartier3398c782016-09-30 10:27:43 -070047JDWP::ObjectId ObjectRegistry::Add(ObjPtr<mirror::Object> o) {
Hiroshi Yamauchib5a9e3d2014-06-09 12:11:20 -070048 if (o == nullptr) {
Elliott Hughes64f574f2013-02-20 14:57:12 -080049 return 0;
50 }
Sebastien Hertz261bc042015-04-08 09:36:07 +020051 Thread* const self = Thread::Current();
52 StackHandleScope<1> hs(self);
53 return InternalAdd(hs.NewHandle(o));
54}
55
56// Template instantiations must be declared below.
57template<class T>
58JDWP::ObjectId ObjectRegistry::Add(Handle<T> obj_h) {
59 if (obj_h.Get() == nullptr) {
60 return 0;
61 }
62 return InternalAdd(obj_h);
63}
64
65// Explicit template instantiation.
66template
Andreas Gampebdf7f1c2016-08-30 16:38:47 -070067REQUIRES_SHARED(Locks::mutator_lock_)
Mathieu Chartier90443472015-07-16 20:32:27 -070068REQUIRES(!Locks::thread_list_lock_, !Locks::thread_suspend_count_lock_)
Sebastien Hertz261bc042015-04-08 09:36:07 +020069JDWP::ObjectId ObjectRegistry::Add(Handle<mirror::Object> obj_h);
70
71template
Andreas Gampebdf7f1c2016-08-30 16:38:47 -070072REQUIRES_SHARED(Locks::mutator_lock_)
Mathieu Chartier90443472015-07-16 20:32:27 -070073REQUIRES(!Locks::thread_list_lock_, !Locks::thread_suspend_count_lock_)
Sebastien Hertz261bc042015-04-08 09:36:07 +020074JDWP::ObjectId ObjectRegistry::Add(Handle<mirror::Throwable> obj_h);
75
76template<class T>
77JDWP::ObjectId ObjectRegistry::InternalAdd(Handle<T> obj_h) {
78 CHECK(obj_h.Get() != nullptr);
Elliott Hughes64f574f2013-02-20 14:57:12 -080079
Sebastien Hertze2d628b2014-10-23 15:39:33 +020080 Thread* const self = Thread::Current();
Sebastien Hertze4266c52014-10-29 12:06:51 +010081 self->AssertNoPendingException();
Sebastien Hertz69206392015-04-07 15:54:25 +020082 // Object::IdentityHashCode may cause these locks to be held so check we do not already
83 // hold them.
84 Locks::thread_list_lock_->AssertNotHeld(self);
85 Locks::thread_suspend_count_lock_->AssertNotHeld(self);
Sebastien Hertze4266c52014-10-29 12:06:51 +010086
Hiroshi Yamauchib5a9e3d2014-06-09 12:11:20 -070087 // Call IdentityHashCode here to avoid a lock level violation between lock_ and monitor_lock.
Sebastien Hertze2d628b2014-10-23 15:39:33 +020088 int32_t identity_hash_code = obj_h->IdentityHashCode();
89
90 ScopedObjectAccessUnchecked soa(self);
Elliott Hughes64f574f2013-02-20 14:57:12 -080091 MutexLock mu(soa.Self(), lock_);
Hiroshi Yamauchib5a9e3d2014-06-09 12:11:20 -070092 ObjectRegistryEntry* entry = nullptr;
Sebastien Hertze2d628b2014-10-23 15:39:33 +020093 if (ContainsLocked(soa.Self(), obj_h.Get(), identity_hash_code, &entry)) {
Mathieu Chartier412c7fc2014-02-07 12:18:39 -080094 // This object was already in our map.
Mathieu Chartier412c7fc2014-02-07 12:18:39 -080095 ++entry->reference_count;
96 } else {
97 entry = new ObjectRegistryEntry;
98 entry->jni_reference_type = JNIWeakGlobalRefType;
99 entry->jni_reference = nullptr;
100 entry->reference_count = 0;
101 entry->id = 0;
Hiroshi Yamauchib5a9e3d2014-06-09 12:11:20 -0700102 entry->identity_hash_code = identity_hash_code;
103 object_to_entry_.insert(std::make_pair(identity_hash_code, entry));
Elliott Hughes64f574f2013-02-20 14:57:12 -0800104
Mathieu Chartier412c7fc2014-02-07 12:18:39 -0800105 // This object isn't in the registry yet, so add it.
106 JNIEnv* env = soa.Env();
Elliott Hughes64f574f2013-02-20 14:57:12 -0800107
Sebastien Hertze2d628b2014-10-23 15:39:33 +0200108 jobject local_reference = soa.AddLocalReference<jobject>(obj_h.Get());
Elliott Hughes64f574f2013-02-20 14:57:12 -0800109
Mathieu Chartier412c7fc2014-02-07 12:18:39 -0800110 entry->jni_reference_type = JNIWeakGlobalRefType;
111 entry->jni_reference = env->NewWeakGlobalRef(local_reference);
112 entry->reference_count = 1;
113 entry->id = next_id_++;
Elliott Hughes64f574f2013-02-20 14:57:12 -0800114
Mathieu Chartier412c7fc2014-02-07 12:18:39 -0800115 id_to_entry_.Put(entry->id, entry);
Elliott Hughes64f574f2013-02-20 14:57:12 -0800116
Mathieu Chartier412c7fc2014-02-07 12:18:39 -0800117 env->DeleteLocalRef(local_reference);
118 }
119 return entry->id;
Elliott Hughes64f574f2013-02-20 14:57:12 -0800120}
121
Mathieu Chartier3398c782016-09-30 10:27:43 -0700122bool ObjectRegistry::ContainsLocked(Thread* self,
123 ObjPtr<mirror::Object> o,
124 int32_t identity_hash_code,
Hiroshi Yamauchib5a9e3d2014-06-09 12:11:20 -0700125 ObjectRegistryEntry** out_entry) {
126 DCHECK(o != nullptr);
127 for (auto it = object_to_entry_.lower_bound(identity_hash_code), end = object_to_entry_.end();
128 it != end && it->first == identity_hash_code; ++it) {
129 ObjectRegistryEntry* entry = it->second;
130 if (o == self->DecodeJObject(entry->jni_reference)) {
131 if (out_entry != nullptr) {
132 *out_entry = entry;
133 }
134 return true;
135 }
136 }
137 return false;
Elliott Hughes64f574f2013-02-20 14:57:12 -0800138}
139
140void ObjectRegistry::Clear() {
Sebastien Hertz55f65342015-01-13 22:48:34 +0100141 Thread* const self = Thread::Current();
142
143 // We must not hold the mutator lock exclusively if we want to delete weak global
144 // references. Otherwise this can lead to a deadlock with a running GC:
145 // 1. GC thread disables access to weak global references, then releases
146 // mutator lock.
147 // 2. JDWP thread takes mutator lock exclusively after suspending all
148 // threads.
149 // 3. GC thread waits for shared mutator lock which is held by JDWP
150 // thread.
151 // 4. JDWP thread clears weak global references but need to wait for GC
152 // thread to re-enable access to them.
153 Locks::mutator_lock_->AssertNotExclusiveHeld(self);
154
Elliott Hughes64f574f2013-02-20 14:57:12 -0800155 MutexLock mu(self, lock_);
156 VLOG(jdwp) << "Object registry contained " << object_to_entry_.size() << " entries";
Elliott Hughes64f574f2013-02-20 14:57:12 -0800157 // Delete all the JNI references.
158 JNIEnv* env = self->GetJniEnv();
Mathieu Chartier412c7fc2014-02-07 12:18:39 -0800159 for (const auto& pair : object_to_entry_) {
Sebastien Hertza0328702014-06-25 22:06:12 +0200160 const ObjectRegistryEntry* entry = pair.second;
161 if (entry->jni_reference_type == JNIWeakGlobalRefType) {
162 env->DeleteWeakGlobalRef(entry->jni_reference);
Elliott Hughes64f574f2013-02-20 14:57:12 -0800163 } else {
Sebastien Hertza0328702014-06-25 22:06:12 +0200164 env->DeleteGlobalRef(entry->jni_reference);
Elliott Hughes64f574f2013-02-20 14:57:12 -0800165 }
Sebastien Hertza0328702014-06-25 22:06:12 +0200166 delete entry;
Elliott Hughes64f574f2013-02-20 14:57:12 -0800167 }
Elliott Hughes64f574f2013-02-20 14:57:12 -0800168 // Clear the maps.
169 object_to_entry_.clear();
170 id_to_entry_.clear();
171}
172
Ian Rogersc0542af2014-09-03 16:16:56 -0700173mirror::Object* ObjectRegistry::InternalGet(JDWP::ObjectId id, JDWP::JdwpError* error) {
Elliott Hughes64f574f2013-02-20 14:57:12 -0800174 Thread* self = Thread::Current();
175 MutexLock mu(self, lock_);
Mathieu Chartier412c7fc2014-02-07 12:18:39 -0800176 auto it = id_to_entry_.find(id);
Elliott Hughes64f574f2013-02-20 14:57:12 -0800177 if (it == id_to_entry_.end()) {
Ian Rogersc0542af2014-09-03 16:16:56 -0700178 *error = JDWP::ERR_INVALID_OBJECT;
179 return nullptr;
Elliott Hughes64f574f2013-02-20 14:57:12 -0800180 }
Mathieu Chartier412c7fc2014-02-07 12:18:39 -0800181 ObjectRegistryEntry& entry = *it->second;
Ian Rogersc0542af2014-09-03 16:16:56 -0700182 *error = JDWP::ERR_NONE;
Mathieu Chartierc4f39252016-10-05 18:32:08 -0700183 return self->DecodeJObject(entry.jni_reference).Ptr();
Elliott Hughes64f574f2013-02-20 14:57:12 -0800184}
185
Jeff Hao449db332013-04-12 18:30:52 -0700186jobject ObjectRegistry::GetJObject(JDWP::ObjectId id) {
Sebastien Hertz0630ab52013-11-28 18:53:35 +0100187 if (id == 0) {
Sebastien Hertz7d955652014-10-22 10:57:10 +0200188 return nullptr;
Sebastien Hertz0630ab52013-11-28 18:53:35 +0100189 }
Jeff Hao449db332013-04-12 18:30:52 -0700190 Thread* self = Thread::Current();
191 MutexLock mu(self, lock_);
Mathieu Chartier412c7fc2014-02-07 12:18:39 -0800192 auto it = id_to_entry_.find(id);
Jeff Hao449db332013-04-12 18:30:52 -0700193 CHECK(it != id_to_entry_.end()) << id;
Mathieu Chartier412c7fc2014-02-07 12:18:39 -0800194 ObjectRegistryEntry& entry = *it->second;
Jeff Hao449db332013-04-12 18:30:52 -0700195 return entry.jni_reference;
196}
197
Elliott Hughes64f574f2013-02-20 14:57:12 -0800198void ObjectRegistry::DisableCollection(JDWP::ObjectId id) {
199 Thread* self = Thread::Current();
200 MutexLock mu(self, lock_);
Mathieu Chartier412c7fc2014-02-07 12:18:39 -0800201 auto it = id_to_entry_.find(id);
Sebastien Hertze96060a2013-12-11 12:06:28 +0100202 CHECK(it != id_to_entry_.end());
Mathieu Chartier412c7fc2014-02-07 12:18:39 -0800203 Promote(*it->second);
Elliott Hughes64f574f2013-02-20 14:57:12 -0800204}
205
206void ObjectRegistry::EnableCollection(JDWP::ObjectId id) {
207 Thread* self = Thread::Current();
208 MutexLock mu(self, lock_);
Mathieu Chartier412c7fc2014-02-07 12:18:39 -0800209 auto it = id_to_entry_.find(id);
Sebastien Hertze96060a2013-12-11 12:06:28 +0100210 CHECK(it != id_to_entry_.end());
Mathieu Chartier412c7fc2014-02-07 12:18:39 -0800211 Demote(*it->second);
Elliott Hughes64f574f2013-02-20 14:57:12 -0800212}
213
214void ObjectRegistry::Demote(ObjectRegistryEntry& entry) {
215 if (entry.jni_reference_type == JNIGlobalRefType) {
216 Thread* self = Thread::Current();
217 JNIEnv* env = self->GetJniEnv();
218 jobject global = entry.jni_reference;
219 entry.jni_reference = env->NewWeakGlobalRef(entry.jni_reference);
220 entry.jni_reference_type = JNIWeakGlobalRefType;
221 env->DeleteGlobalRef(global);
222 }
223}
224
225void ObjectRegistry::Promote(ObjectRegistryEntry& entry) {
226 if (entry.jni_reference_type == JNIWeakGlobalRefType) {
227 Thread* self = Thread::Current();
228 JNIEnv* env = self->GetJniEnv();
229 jobject weak = entry.jni_reference;
230 entry.jni_reference = env->NewGlobalRef(entry.jni_reference);
231 entry.jni_reference_type = JNIGlobalRefType;
232 env->DeleteWeakGlobalRef(weak);
233 }
234}
235
236bool ObjectRegistry::IsCollected(JDWP::ObjectId id) {
237 Thread* self = Thread::Current();
238 MutexLock mu(self, lock_);
Mathieu Chartier412c7fc2014-02-07 12:18:39 -0800239 auto it = id_to_entry_.find(id);
Sebastien Hertze96060a2013-12-11 12:06:28 +0100240 CHECK(it != id_to_entry_.end());
Mathieu Chartier412c7fc2014-02-07 12:18:39 -0800241 ObjectRegistryEntry& entry = *it->second;
Elliott Hughes64f574f2013-02-20 14:57:12 -0800242 if (entry.jni_reference_type == JNIWeakGlobalRefType) {
243 JNIEnv* env = self->GetJniEnv();
Sebastien Hertz7d955652014-10-22 10:57:10 +0200244 return env->IsSameObject(entry.jni_reference, nullptr); // Has the jweak been collected?
Elliott Hughes64f574f2013-02-20 14:57:12 -0800245 } else {
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700246 return false; // We hold a strong reference, so we know this is live.
Elliott Hughes64f574f2013-02-20 14:57:12 -0800247 }
248}
249
250void ObjectRegistry::DisposeObject(JDWP::ObjectId id, uint32_t reference_count) {
251 Thread* self = Thread::Current();
252 MutexLock mu(self, lock_);
Mathieu Chartier412c7fc2014-02-07 12:18:39 -0800253 auto it = id_to_entry_.find(id);
Elliott Hughes64f574f2013-02-20 14:57:12 -0800254 if (it == id_to_entry_.end()) {
255 return;
256 }
Mathieu Chartier412c7fc2014-02-07 12:18:39 -0800257 ObjectRegistryEntry* entry = it->second;
258 entry->reference_count -= reference_count;
259 if (entry->reference_count <= 0) {
Elliott Hughes64f574f2013-02-20 14:57:12 -0800260 JNIEnv* env = self->GetJniEnv();
Hiroshi Yamauchib5a9e3d2014-06-09 12:11:20 -0700261 // Erase the object from the maps. Note object may be null if it's
262 // a weak ref and the GC has cleared it.
263 int32_t hash_code = entry->identity_hash_code;
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800264 for (auto inner_it = object_to_entry_.lower_bound(hash_code), end = object_to_entry_.end();
265 inner_it != end && inner_it->first == hash_code; ++inner_it) {
266 if (entry == inner_it->second) {
267 object_to_entry_.erase(inner_it);
Hiroshi Yamauchib5a9e3d2014-06-09 12:11:20 -0700268 break;
269 }
270 }
Mathieu Chartier412c7fc2014-02-07 12:18:39 -0800271 if (entry->jni_reference_type == JNIWeakGlobalRefType) {
272 env->DeleteWeakGlobalRef(entry->jni_reference);
Elliott Hughes64f574f2013-02-20 14:57:12 -0800273 } else {
Mathieu Chartier412c7fc2014-02-07 12:18:39 -0800274 env->DeleteGlobalRef(entry->jni_reference);
Elliott Hughes64f574f2013-02-20 14:57:12 -0800275 }
Elliott Hughes64f574f2013-02-20 14:57:12 -0800276 id_to_entry_.erase(id);
Mathieu Chartier412c7fc2014-02-07 12:18:39 -0800277 delete entry;
Elliott Hughes64f574f2013-02-20 14:57:12 -0800278 }
279}
280
Elliott Hughes64f574f2013-02-20 14:57:12 -0800281} // namespace art