blob: 15cb6de64715caf00d095540dc2cf390d32822ba [file] [log] [blame]
Alex Lighta01de592016-11-15 10:43:06 -08001/* Copyright (C) 2016 The Android Open Source Project
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3 *
4 * This file implements interfaces from the file jvmti.h. This implementation
5 * is licensed under the same terms as the file jvmti.h. The
6 * copyright and license information for the file jvmti.h follows.
7 *
8 * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
9 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
10 *
11 * This code is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License version 2 only, as
13 * published by the Free Software Foundation. Oracle designates this
14 * particular file as subject to the "Classpath" exception as provided
15 * by Oracle in the LICENSE file that accompanied this code.
16 *
17 * This code is distributed in the hope that it will be useful, but WITHOUT
18 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 * version 2 for more details (a copy is included in the LICENSE file that
21 * accompanied this code).
22 *
23 * You should have received a copy of the GNU General Public License version
24 * 2 along with this work; if not, write to the Free Software Foundation,
25 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
26 *
27 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
28 * or visit www.oracle.com if you need additional information or have any
29 * questions.
30 */
31
32#include "ti_redefine.h"
33
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +000034#include <algorithm>
35#include <atomic>
Alex Lighte7a33542019-04-10 14:22:49 -070036#include <iterator>
Alex Lighta01de592016-11-15 10:43:06 -080037#include <limits>
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +000038#include <sstream>
Vladimir Markoeb37ba52019-02-05 14:10:38 +000039#include <string_view>
Alex Lighte7a33542019-04-10 14:22:49 -070040#include <unordered_map>
Alex Lighta01de592016-11-15 10:43:06 -080041
Andreas Gampe57943812017-12-06 21:39:13 -080042#include <android-base/logging.h>
43#include <android-base/stringprintf.h>
Andreas Gampe46ee31b2016-12-14 10:11:49 -080044
Alex Light986914b2019-11-19 01:12:25 +000045#include "alloc_manager.h"
46#include "android-base/macros.h"
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +000047#include "android-base/thread_annotations.h"
Andreas Gampea1d2f952017-04-20 22:53:58 -070048#include "art_field-inl.h"
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +000049#include "art_field.h"
Alex Lighta01de592016-11-15 10:43:06 -080050#include "art_jvmti.h"
Steven Morelande431e272017-07-18 16:53:49 -070051#include "art_method-inl.h"
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +000052#include "art_method.h"
Vladimir Markoe1993c72017-06-14 17:01:38 +010053#include "base/array_ref.h"
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +000054#include "base/casts.h"
55#include "base/enums.h"
56#include "base/globals.h"
Alex Light270db1c2019-12-03 12:20:01 +000057#include "base/iteration_range.h"
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +000058#include "base/length_prefixed_array.h"
Alex Light270db1c2019-12-03 12:20:01 +000059#include "base/locks.h"
60#include "base/stl_util.h"
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +000061#include "base/utils.h"
Andreas Gampec6ea7d02017-02-01 16:46:28 -080062#include "class_linker-inl.h"
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +000063#include "class_linker.h"
Vladimir Marko5868ada2020-05-12 11:50:34 +010064#include "class_root-inl.h"
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +000065#include "class_status.h"
Alex Light5643caf2017-02-08 11:39:07 -080066#include "debugger.h"
David Sehr013fd802018-01-11 22:55:24 -080067#include "dex/art_dex_file_loader.h"
Mathieu Chartier4ac9ade2018-07-24 10:27:21 -070068#include "dex/class_accessor-inl.h"
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +000069#include "dex/class_accessor.h"
David Sehr9e734c72018-01-04 17:56:19 -080070#include "dex/dex_file.h"
71#include "dex/dex_file_loader.h"
72#include "dex/dex_file_types.h"
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +000073#include "dex/primitive.h"
Andreas Gampead1aa632019-01-02 10:30:54 -080074#include "dex/signature-inl.h"
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +000075#include "dex/signature.h"
Alex Lighta01de592016-11-15 10:43:06 -080076#include "events-inl.h"
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +000077#include "events.h"
Alex Lighta01de592016-11-15 10:43:06 -080078#include "gc/allocation_listener.h"
Alex Light6abd5392017-01-05 17:53:00 -080079#include "gc/heap.h"
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +000080#include "gc/heap-inl.h"
81#include "gc/heap-visit-objects-inl.h"
82#include "handle.h"
83#include "handle_scope.h"
Alex Lighta01de592016-11-15 10:43:06 -080084#include "instrumentation.h"
Alex Light07f06212017-06-01 14:01:43 -070085#include "intern_table.h"
Alex Lightdba61482016-12-21 08:20:29 -080086#include "jit/jit.h"
87#include "jit/jit_code_cache.h"
Vladimir Markoa3ad0cd2018-05-04 10:06:38 +010088#include "jni/jni_env_ext-inl.h"
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +000089#include "jni/jni_id_manager.h"
90#include "jvmti.h"
Alex Lighta01de592016-11-15 10:43:06 -080091#include "jvmti_allocator.h"
Vladimir Marko5924a4a2018-05-29 17:40:41 +010092#include "linear_alloc.h"
Andreas Gampe8e0f0432018-10-24 13:38:03 -070093#include "mirror/array-alloc-inl.h"
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +000094#include "mirror/array.h"
Andreas Gampe70f5fd02018-10-24 19:58:37 -070095#include "mirror/class-alloc-inl.h"
Alex Light6161f132017-01-25 10:30:20 -080096#include "mirror/class-inl.h"
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +000097#include "mirror/class-refvisitor-inl.h"
98#include "mirror/class.h"
Vladimir Markobb206de2019-03-28 10:30:32 +000099#include "mirror/class_ext-inl.h"
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000100#include "mirror/dex_cache-inl.h"
101#include "mirror/dex_cache.h"
102#include "mirror/executable-inl.h"
103#include "mirror/field-inl.h"
Alex Light163652e2020-01-08 15:18:25 -0800104#include "mirror/field.h"
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000105#include "mirror/method.h"
106#include "mirror/method_handle_impl-inl.h"
Alex Lighta01de592016-11-15 10:43:06 -0800107#include "mirror/object.h"
Andreas Gampe52ecb652018-10-24 15:18:21 -0700108#include "mirror/object_array-alloc-inl.h"
109#include "mirror/object_array-inl.h"
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000110#include "mirror/object_array.h"
111#include "mirror/string.h"
Alex Lightc18eba32019-09-24 14:36:27 -0700112#include "mirror/var_handle.h"
Andreas Gampe373a9b52017-10-18 09:01:57 -0700113#include "nativehelper/scoped_local_ref.h"
Alex Lighte77b48b2017-02-22 11:08:06 -0800114#include "non_debuggable_classes.h"
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000115#include "obj_ptr.h"
Alex Lighta01de592016-11-15 10:43:06 -0800116#include "object_lock.h"
Alex Light24627892019-11-06 10:28:21 -0800117#include "reflective_value_visitor.h"
Alex Lighta01de592016-11-15 10:43:06 -0800118#include "runtime.h"
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000119#include "runtime_globals.h"
Alex Light986914b2019-11-19 01:12:25 +0000120#include "scoped_thread_state_change.h"
Vladimir Marko5924a4a2018-05-29 17:40:41 +0100121#include "stack.h"
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000122#include "thread.h"
Vladimir Marko5924a4a2018-05-29 17:40:41 +0100123#include "thread_list.h"
Alex Lighta26e3492017-06-27 17:55:37 -0700124#include "ti_breakpoint.h"
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000125#include "ti_class_definition.h"
Alex Lighteb98b082017-01-25 13:02:32 -0800126#include "ti_class_loader.h"
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000127#include "ti_heap.h"
128#include "ti_logging.h"
129#include "ti_thread.h"
Alex Light0e692732017-01-10 15:00:05 -0800130#include "transform.h"
Andreas Gampea43ba3d2019-03-13 15:49:20 -0700131#include "verifier/class_verifier.h"
Andreas Gampe6d7abbd2017-04-24 13:19:09 -0700132#include "verifier/verifier_enums.h"
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000133#include "well_known_classes.h"
134#include "write_barrier.h"
Alex Lighta01de592016-11-15 10:43:06 -0800135
136namespace openjdkjvmti {
137
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000138// Debug check to force us to directly check we saw all methods and fields exactly once directly.
139// Normally we don't need to do this since if any are missing the count will be different
140constexpr bool kCheckAllMethodsSeenOnce = art::kIsDebugBuild;
141
Andreas Gampe46ee31b2016-12-14 10:11:49 -0800142using android::base::StringPrintf;
143
Alex Lighteee0bd42017-02-14 15:31:45 +0000144// A helper that fills in a classes obsolete_methods_ and obsolete_dex_caches_ classExt fields as
145// they are created. This ensures that we can always call any method of an obsolete ArtMethod object
146// almost as soon as they are created since the GetObsoleteDexCache method will succeed.
147class ObsoleteMap {
148 public:
Alex Lighte7a33542019-04-10 14:22:49 -0700149 art::ArtMethod* FindObsoleteVersion(art::ArtMethod* original) const
Alex Lighteee0bd42017-02-14 15:31:45 +0000150 REQUIRES(art::Locks::mutator_lock_, art::Roles::uninterruptible_) {
151 auto method_pair = id_map_.find(original);
152 if (method_pair != id_map_.end()) {
153 art::ArtMethod* res = obsolete_methods_->GetElementPtrSize<art::ArtMethod*>(
154 method_pair->second, art::kRuntimePointerSize);
155 DCHECK(res != nullptr);
Alex Lighteee0bd42017-02-14 15:31:45 +0000156 return res;
157 } else {
158 return nullptr;
159 }
160 }
161
162 void RecordObsolete(art::ArtMethod* original, art::ArtMethod* obsolete)
163 REQUIRES(art::Locks::mutator_lock_, art::Roles::uninterruptible_) {
164 DCHECK(original != nullptr);
165 DCHECK(obsolete != nullptr);
166 int32_t slot = next_free_slot_++;
167 DCHECK_LT(slot, obsolete_methods_->GetLength());
168 DCHECK(nullptr ==
169 obsolete_methods_->GetElementPtrSize<art::ArtMethod*>(slot, art::kRuntimePointerSize));
170 DCHECK(nullptr == obsolete_dex_caches_->Get(slot));
171 obsolete_methods_->SetElementPtrSize(slot, obsolete, art::kRuntimePointerSize);
172 obsolete_dex_caches_->Set(slot, original_dex_cache_);
173 id_map_.insert({original, slot});
174 }
175
176 ObsoleteMap(art::ObjPtr<art::mirror::PointerArray> obsolete_methods,
177 art::ObjPtr<art::mirror::ObjectArray<art::mirror::DexCache>> obsolete_dex_caches,
178 art::ObjPtr<art::mirror::DexCache> original_dex_cache)
179 : next_free_slot_(0),
180 obsolete_methods_(obsolete_methods),
181 obsolete_dex_caches_(obsolete_dex_caches),
182 original_dex_cache_(original_dex_cache) {
183 // Figure out where the first unused slot in the obsolete_methods_ array is.
184 while (obsolete_methods_->GetElementPtrSize<art::ArtMethod*>(
185 next_free_slot_, art::kRuntimePointerSize) != nullptr) {
186 DCHECK(obsolete_dex_caches_->Get(next_free_slot_) != nullptr);
187 next_free_slot_++;
188 }
Orion Hodsonaacf9772020-07-22 21:51:00 +0100189 // Check that the same slot in obsolete_dex_caches_ is free.
Alex Lighteee0bd42017-02-14 15:31:45 +0000190 DCHECK(obsolete_dex_caches_->Get(next_free_slot_) == nullptr);
191 }
192
Alex Lighte7a33542019-04-10 14:22:49 -0700193 struct ObsoleteMethodPair {
194 art::ArtMethod* old_method;
195 art::ArtMethod* obsolete_method;
196 };
197
Vladimir Markoeab02482019-05-09 10:28:17 +0100198 class ObsoleteMapIter {
Alex Lighte7a33542019-04-10 14:22:49 -0700199 public:
Vladimir Markoeab02482019-05-09 10:28:17 +0100200 using iterator_category = std::forward_iterator_tag;
201 using value_type = ObsoleteMethodPair;
202 using difference_type = ptrdiff_t;
203 using pointer = void; // Unsupported.
204 using reference = void; // Unsupported.
205
Alex Lighte7a33542019-04-10 14:22:49 -0700206 ObsoleteMethodPair operator*() const
207 REQUIRES(art::Locks::mutator_lock_, art::Roles::uninterruptible_) {
Vladimir Markoeab02482019-05-09 10:28:17 +0100208 art::ArtMethod* obsolete = map_->obsolete_methods_->GetElementPtrSize<art::ArtMethod*>(
209 iter_->second, art::kRuntimePointerSize);
Alex Lighte7a33542019-04-10 14:22:49 -0700210 DCHECK(obsolete != nullptr);
211 return { iter_->first, obsolete };
212 }
213
214 bool operator==(ObsoleteMapIter other) const {
215 return map_ == other.map_ && iter_ == other.iter_;
216 }
217
218 bool operator!=(ObsoleteMapIter other) const {
219 return !(*this == other);
220 }
221
Vladimir Markoeab02482019-05-09 10:28:17 +0100222 ObsoleteMapIter operator++(int) {
Alex Lighte7a33542019-04-10 14:22:49 -0700223 ObsoleteMapIter retval = *this;
224 ++(*this);
225 return retval;
226 }
227
Vladimir Markoeab02482019-05-09 10:28:17 +0100228 ObsoleteMapIter operator++() {
Alex Lighte7a33542019-04-10 14:22:49 -0700229 ++iter_;
230 return *this;
231 }
232
233 private:
234 ObsoleteMapIter(const ObsoleteMap* map,
235 std::unordered_map<art::ArtMethod*, int32_t>::const_iterator iter)
236 : map_(map), iter_(iter) {}
237
238 const ObsoleteMap* map_;
Vladimir Markoeab02482019-05-09 10:28:17 +0100239 std::unordered_map<art::ArtMethod*, int32_t>::const_iterator iter_;
Alex Lighte7a33542019-04-10 14:22:49 -0700240
241 friend class ObsoleteMap;
242 };
243
244 ObsoleteMapIter end() const {
245 return ObsoleteMapIter(this, id_map_.cend());
246 }
247
248 ObsoleteMapIter begin() const {
249 return ObsoleteMapIter(this, id_map_.cbegin());
250 }
251
Alex Lighteee0bd42017-02-14 15:31:45 +0000252 private:
253 int32_t next_free_slot_;
254 std::unordered_map<art::ArtMethod*, int32_t> id_map_;
255 // Pointers to the fields in mirror::ClassExt. These can be held as ObjPtr since this is only used
256 // when we have an exclusive mutator_lock_ (i.e. all threads are suspended).
257 art::ObjPtr<art::mirror::PointerArray> obsolete_methods_;
258 art::ObjPtr<art::mirror::ObjectArray<art::mirror::DexCache>> obsolete_dex_caches_;
259 art::ObjPtr<art::mirror::DexCache> original_dex_cache_;
260};
261
Alex Lightdba61482016-12-21 08:20:29 -0800262// This visitor walks thread stacks and allocates and sets up the obsolete methods. It also does
Orion Hodsonaacf9772020-07-22 21:51:00 +0100263// some basic soundness checks that the obsolete method is valid.
Alex Lightdba61482016-12-21 08:20:29 -0800264class ObsoleteMethodStackVisitor : public art::StackVisitor {
265 protected:
266 ObsoleteMethodStackVisitor(
267 art::Thread* thread,
268 art::LinearAlloc* allocator,
269 const std::unordered_set<art::ArtMethod*>& obsoleted_methods,
Alex Lighteee0bd42017-02-14 15:31:45 +0000270 ObsoleteMap* obsolete_maps)
Alex Lightdba61482016-12-21 08:20:29 -0800271 : StackVisitor(thread,
Andreas Gampe6e897762018-10-16 13:09:32 -0700272 /*context=*/nullptr,
Alex Lightdba61482016-12-21 08:20:29 -0800273 StackVisitor::StackWalkKind::kIncludeInlinedFrames),
274 allocator_(allocator),
275 obsoleted_methods_(obsoleted_methods),
Alex Light4ba388a2017-01-27 10:26:49 -0800276 obsolete_maps_(obsolete_maps) { }
Alex Lightdba61482016-12-21 08:20:29 -0800277
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100278 ~ObsoleteMethodStackVisitor() override {}
Alex Lightdba61482016-12-21 08:20:29 -0800279
280 public:
281 // Returns true if we successfully installed obsolete methods on this thread, filling
282 // obsolete_maps_ with the translations if needed. Returns false and fills error_msg if we fail.
283 // The stack is cleaned up when we fail.
Alex Light007ada22017-01-10 13:33:56 -0800284 static void UpdateObsoleteFrames(
Alex Lightdba61482016-12-21 08:20:29 -0800285 art::Thread* thread,
286 art::LinearAlloc* allocator,
287 const std::unordered_set<art::ArtMethod*>& obsoleted_methods,
Alex Lighteee0bd42017-02-14 15:31:45 +0000288 ObsoleteMap* obsolete_maps)
Alex Light007ada22017-01-10 13:33:56 -0800289 REQUIRES(art::Locks::mutator_lock_) {
Alex Lightdba61482016-12-21 08:20:29 -0800290 ObsoleteMethodStackVisitor visitor(thread,
291 allocator,
292 obsoleted_methods,
Alex Light007ada22017-01-10 13:33:56 -0800293 obsolete_maps);
Alex Lightdba61482016-12-21 08:20:29 -0800294 visitor.WalkStack();
Alex Lightdba61482016-12-21 08:20:29 -0800295 }
296
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100297 bool VisitFrame() override REQUIRES(art::Locks::mutator_lock_) {
Alex Lighteee0bd42017-02-14 15:31:45 +0000298 art::ScopedAssertNoThreadSuspension snts("Fixing up the stack for obsolete methods.");
Alex Lightdba61482016-12-21 08:20:29 -0800299 art::ArtMethod* old_method = GetMethod();
Alex Lightdba61482016-12-21 08:20:29 -0800300 if (obsoleted_methods_.find(old_method) != obsoleted_methods_.end()) {
Alex Lightdba61482016-12-21 08:20:29 -0800301 // We cannot ensure that the right dex file is used in inlined frames so we don't support
302 // redefining them.
Nicolas Geoffray226805d2018-12-14 10:59:02 +0000303 DCHECK(!IsInInlinedFrame()) << "Inlined frames are not supported when using redefinition: "
304 << old_method->PrettyMethod() << " is inlined into "
305 << GetOuterMethod()->PrettyMethod();
Alex Lighteee0bd42017-02-14 15:31:45 +0000306 art::ArtMethod* new_obsolete_method = obsolete_maps_->FindObsoleteVersion(old_method);
307 if (new_obsolete_method == nullptr) {
Alex Lightdba61482016-12-21 08:20:29 -0800308 // Create a new Obsolete Method and put it in the list.
309 art::Runtime* runtime = art::Runtime::Current();
310 art::ClassLinker* cl = runtime->GetClassLinker();
311 auto ptr_size = cl->GetImagePointerSize();
312 const size_t method_size = art::ArtMethod::Size(ptr_size);
Alex Light5c11a792017-03-10 14:29:22 -0800313 auto* method_storage = allocator_->Alloc(art::Thread::Current(), method_size);
Alex Light007ada22017-01-10 13:33:56 -0800314 CHECK(method_storage != nullptr) << "Unable to allocate storage for obsolete version of '"
315 << old_method->PrettyMethod() << "'";
Alex Lightdba61482016-12-21 08:20:29 -0800316 new_obsolete_method = new (method_storage) art::ArtMethod();
317 new_obsolete_method->CopyFrom(old_method, ptr_size);
318 DCHECK_EQ(new_obsolete_method->GetDeclaringClass(), old_method->GetDeclaringClass());
319 new_obsolete_method->SetIsObsolete();
Alex Lightfcbafb32017-02-02 15:09:54 -0800320 new_obsolete_method->SetDontCompile();
Alex Lightdb01a092017-04-03 15:39:55 -0700321 cl->SetEntryPointsForObsoleteMethod(new_obsolete_method);
Alex Lighteee0bd42017-02-14 15:31:45 +0000322 obsolete_maps_->RecordObsolete(old_method, new_obsolete_method);
Alex Lightdba61482016-12-21 08:20:29 -0800323 }
324 DCHECK(new_obsolete_method != nullptr);
325 SetMethod(new_obsolete_method);
326 }
327 return true;
328 }
329
330 private:
331 // The linear allocator we should use to make new methods.
332 art::LinearAlloc* allocator_;
333 // The set of all methods which could be obsoleted.
334 const std::unordered_set<art::ArtMethod*>& obsoleted_methods_;
335 // A map from the original to the newly allocated obsolete method for frames on this thread. The
Alex Lighteee0bd42017-02-14 15:31:45 +0000336 // values in this map are added to the obsolete_methods_ (and obsolete_dex_caches_) fields of
337 // the redefined classes ClassExt as it is filled.
338 ObsoleteMap* obsolete_maps_;
Alex Lightdba61482016-12-21 08:20:29 -0800339};
340
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000341template <RedefinitionType kType>
342jvmtiError
343Redefiner::IsModifiableClassGeneric(jvmtiEnv* env, jclass klass, jboolean* is_redefinable) {
344 if (env == nullptr) {
345 return ERR(INVALID_ENVIRONMENT);
346 }
Alex Lighte4a88632017-01-10 07:41:24 -0800347 art::Thread* self = art::Thread::Current();
348 art::ScopedObjectAccess soa(self);
349 art::StackHandleScope<1> hs(self);
350 art::ObjPtr<art::mirror::Object> obj(self->DecodeJObject(klass));
Alex Light413a8ad2019-02-14 10:19:44 -0800351 if (obj.IsNull() || !obj->IsClass()) {
Alex Lighte4a88632017-01-10 07:41:24 -0800352 return ERR(INVALID_CLASS);
353 }
354 art::Handle<art::mirror::Class> h_klass(hs.NewHandle(obj->AsClass()));
355 std::string err_unused;
356 *is_redefinable =
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000357 Redefiner::GetClassRedefinitionError<kType>(h_klass, &err_unused) != ERR(UNMODIFIABLE_CLASS)
358 ? JNI_TRUE
359 : JNI_FALSE;
Alex Lighte4a88632017-01-10 07:41:24 -0800360 return OK;
361}
362
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000363jvmtiError
364Redefiner::IsStructurallyModifiableClass(jvmtiEnv* env, jclass klass, jboolean* is_redefinable) {
365 return Redefiner::IsModifiableClassGeneric<RedefinitionType::kStructural>(
366 env, klass, is_redefinable);
367}
368
369jvmtiError Redefiner::IsModifiableClass(jvmtiEnv* env, jclass klass, jboolean* is_redefinable) {
370 return Redefiner::IsModifiableClassGeneric<RedefinitionType::kNormal>(env, klass, is_redefinable);
371}
372
373template <RedefinitionType kType>
374jvmtiError Redefiner::GetClassRedefinitionError(jclass klass, /*out*/ std::string* error_msg) {
Alex Light9e7859c2018-04-05 13:49:43 -0700375 art::Thread* self = art::Thread::Current();
376 art::ScopedObjectAccess soa(self);
377 art::StackHandleScope<1> hs(self);
378 art::ObjPtr<art::mirror::Object> obj(self->DecodeJObject(klass));
Alex Light413a8ad2019-02-14 10:19:44 -0800379 if (obj.IsNull() || !obj->IsClass()) {
Alex Light9e7859c2018-04-05 13:49:43 -0700380 return ERR(INVALID_CLASS);
381 }
382 art::Handle<art::mirror::Class> h_klass(hs.NewHandle(obj->AsClass()));
Alex Lightd55b8442019-10-15 15:46:07 -0700383 return Redefiner::GetClassRedefinitionError<kType>(h_klass, error_msg);
Alex Light9e7859c2018-04-05 13:49:43 -0700384}
385
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000386template <RedefinitionType kType>
Alex Lighte4a88632017-01-10 07:41:24 -0800387jvmtiError Redefiner::GetClassRedefinitionError(art::Handle<art::mirror::Class> klass,
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000388 /*out*/ std::string* error_msg) {
389 art::Thread* self = art::Thread::Current();
Alex Light9e7859c2018-04-05 13:49:43 -0700390 if (!klass->IsResolved()) {
391 // It's only a problem to try to retransform/redefine a unprepared class if it's happening on
392 // the same thread as the class-linking process. If it's on another thread we will be able to
393 // wait for the preparation to finish and continue from there.
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000394 if (klass->GetLockOwnerThreadId() == self->GetThreadId()) {
Alex Light9e7859c2018-04-05 13:49:43 -0700395 *error_msg = "Modification of class " + klass->PrettyClass() +
396 " from within the classes ClassLoad callback is not supported to prevent deadlocks." +
397 " Please use ClassFileLoadHook directly instead.";
398 return ERR(INTERNAL);
399 } else {
400 LOG(WARNING) << klass->PrettyClass() << " is not yet resolved. Attempting to transform "
401 << "it could cause arbitrary length waits as the class is being resolved.";
402 }
403 }
Alex Lighte4a88632017-01-10 07:41:24 -0800404 if (klass->IsPrimitive()) {
405 *error_msg = "Modification of primitive classes is not supported";
406 return ERR(UNMODIFIABLE_CLASS);
407 } else if (klass->IsInterface()) {
408 *error_msg = "Modification of Interface classes is currently not supported";
409 return ERR(UNMODIFIABLE_CLASS);
Alex Light09f274f2017-02-21 15:00:48 -0800410 } else if (klass->IsStringClass()) {
411 *error_msg = "Modification of String class is not supported";
412 return ERR(UNMODIFIABLE_CLASS);
Alex Lighte4a88632017-01-10 07:41:24 -0800413 } else if (klass->IsArrayClass()) {
414 *error_msg = "Modification of Array classes is not supported";
415 return ERR(UNMODIFIABLE_CLASS);
416 } else if (klass->IsProxyClass()) {
417 *error_msg = "Modification of proxy classes is not supported";
418 return ERR(UNMODIFIABLE_CLASS);
419 }
420
Alex Lighte77b48b2017-02-22 11:08:06 -0800421 for (jclass c : art::NonDebuggableClasses::GetNonDebuggableClasses()) {
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000422 if (klass.Get() == self->DecodeJObject(c)->AsClass()) {
Alex Lighte77b48b2017-02-22 11:08:06 -0800423 *error_msg = "Class might have stack frames that cannot be made obsolete";
424 return ERR(UNMODIFIABLE_CLASS);
425 }
426 }
427
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000428 if (kType == RedefinitionType::kStructural) {
Alex Lightfb119572019-09-18 15:04:53 -0700429 // Class initialization interacts really badly with structural redefinition since we need to
430 // make the old class obsolete. We currently just blanket don't allow it.
431 // TODO It might be nice to allow this at some point.
432 if (klass->IsInitializing() &&
433 !klass->IsInitialized() &&
434 klass->GetClinitThreadId() == self->GetTid()) {
435 // We are in the class-init running on this thread.
436 *error_msg = "Modification of class " + klass->PrettyClass() + " during class" +
437 " initialization is not allowed.";
438 return ERR(INTERNAL);
439 }
440 if (!art::Runtime::Current()->GetClassLinker()->EnsureInitialized(
441 self, klass, /*can_init_fields=*/true, /*can_init_parents=*/true)) {
442 self->AssertPendingException();
443 *error_msg = "Class " + klass->PrettyClass() + " failed initialization. Structural" +
444 " redefinition of erroneous classes is not allowed. Failure was: " +
445 self->GetException()->Dump();
446 self->ClearException();
447 return ERR(INVALID_CLASS);
448 }
Alex Lightf1b18fa2019-11-11 14:22:00 -0800449 if (klass->IsMirrored()) {
450 std::string pc(klass->PrettyClass());
451 *error_msg = StringPrintf("Class %s is a mirror class and cannot be structurally redefined.",
452 pc.c_str());
453 return ERR(UNMODIFIABLE_CLASS);
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000454 }
455 // Check Thread specifically since it's not a root but too many things reach into it with Unsafe
456 // too allow structural redefinition.
457 if (klass->IsAssignableFrom(
458 self->DecodeJObject(art::WellKnownClasses::java_lang_Thread)->AsClass())) {
459 *error_msg =
460 "java.lang.Thread has fields accessed using sun.misc.unsafe directly. It is not "
461 "safe to structurally redefine it.";
462 return ERR(UNMODIFIABLE_CLASS);
463 }
Alex Light3f0dca12020-01-27 17:20:28 -0800464 auto has_pointer_marker =
465 [](art::ObjPtr<art::mirror::Class> k) REQUIRES_SHARED(art::Locks::mutator_lock_) {
466 // Check for fields/methods which were returned before moving to index jni id type.
467 // TODO We might want to rework how this is done. Once full redefinition is implemented we
468 // will need to check any subtypes too.
469 art::ObjPtr<art::mirror::ClassExt> ext(k->GetExtData());
470 if (!ext.IsNull()) {
471 if (ext->HasInstanceFieldPointerIdMarker() || ext->HasMethodPointerIdMarker() ||
472 ext->HasStaticFieldPointerIdMarker()) {
473 return true;
474 }
475 }
476 return false;
477 };
478 if (has_pointer_marker(klass.Get())) {
479 *error_msg =
480 StringPrintf("%s has active pointer jni-ids and cannot be redefined structurally",
481 klass->PrettyClass().c_str());
482 return ERR(UNMODIFIABLE_CLASS);
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000483 }
Alex Light3f0dca12020-01-27 17:20:28 -0800484 jvmtiError res = OK;
485 art::ClassFuncVisitor cfv(
486 [&](art::ObjPtr<art::mirror::Class> k) REQUIRES_SHARED(art::Locks::mutator_lock_) {
487 // if there is any class 'K' that is a subtype (i.e. extends) klass and has pointer-jni-ids
488 // we cannot structurally redefine the class 'k' since we would structurally redefine the
489 // subtype.
490 if (k->IsLoaded() && klass->IsAssignableFrom(k) && has_pointer_marker(k)) {
491 *error_msg = StringPrintf(
492 "%s has active pointer jni-ids from subtype %s and cannot be redefined structurally",
493 klass->PrettyClass().c_str(),
494 k->PrettyClass().c_str());
495 res = ERR(UNMODIFIABLE_CLASS);
496 return false;
497 }
498 return true;
499 });
500 art::Runtime::Current()->GetClassLinker()->VisitClasses(&cfv);
501 return res;
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000502 }
Alex Lighte4a88632017-01-10 07:41:24 -0800503 return OK;
504}
505
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000506template jvmtiError Redefiner::GetClassRedefinitionError<RedefinitionType::kNormal>(
507 art::Handle<art::mirror::Class> klass, /*out*/ std::string* error_msg);
508template jvmtiError Redefiner::GetClassRedefinitionError<RedefinitionType::kStructural>(
509 art::Handle<art::mirror::Class> klass, /*out*/ std::string* error_msg);
510
Alex Lighta01de592016-11-15 10:43:06 -0800511// Moves dex data to an anonymous, read-only mmap'd region.
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100512art::MemMap Redefiner::MoveDataToMemMap(const std::string& original_location,
513 art::ArrayRef<const unsigned char> data,
514 std::string* error_msg) {
515 art::MemMap map = art::MemMap::MapAnonymous(
Andreas Gampe46ee31b2016-12-14 10:11:49 -0800516 StringPrintf("%s-transformed", original_location.c_str()).c_str(),
Alex Lightb7354d52017-03-30 15:17:01 -0700517 data.size(),
Alex Lighta01de592016-11-15 10:43:06 -0800518 PROT_READ|PROT_WRITE,
Andreas Gampe6e897762018-10-16 13:09:32 -0700519 /*low_4gb=*/ false,
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100520 error_msg);
521 if (LIKELY(map.IsValid())) {
522 memcpy(map.Begin(), data.data(), data.size());
523 // Make the dex files mmap read only. This matches how other DexFiles are mmaped and prevents
524 // programs from corrupting it.
525 map.Protect(PROT_READ);
Alex Lighta01de592016-11-15 10:43:06 -0800526 }
Alex Lighta01de592016-11-15 10:43:06 -0800527 return map;
528}
529
Alex Lighta7e38d82017-01-19 14:57:28 -0800530Redefiner::ClassRedefinition::ClassRedefinition(
531 Redefiner* driver,
532 jclass klass,
533 const art::DexFile* redefined_dex_file,
534 const char* class_sig,
Vladimir Markoe1993c72017-06-14 17:01:38 +0100535 art::ArrayRef<const unsigned char> orig_dex_file) :
Alex Lighta7e38d82017-01-19 14:57:28 -0800536 driver_(driver),
537 klass_(klass),
538 dex_file_(redefined_dex_file),
539 class_sig_(class_sig),
540 original_dex_file_(orig_dex_file) {
ShuJieWangb087bb22021-11-24 11:46:16 +0800541 lock_acquired_ = GetMirrorClass()->MonitorTryEnter(driver_->self_) != nullptr;
Alex Light0e692732017-01-10 15:00:05 -0800542}
543
544Redefiner::ClassRedefinition::~ClassRedefinition() {
ShuJieWangb087bb22021-11-24 11:46:16 +0800545 if (driver_ != nullptr && lock_acquired_) {
Alex Light0e692732017-01-10 15:00:05 -0800546 GetMirrorClass()->MonitorExit(driver_->self_);
547 }
548}
549
Alex Lightd55b8442019-10-15 15:46:07 -0700550template<RedefinitionType kType>
551jvmtiError Redefiner::RedefineClassesGeneric(jvmtiEnv* jenv,
552 jint class_count,
553 const jvmtiClassDefinition* definitions) {
Alex Light3732beb2019-10-04 13:35:34 -0700554 art::Runtime* runtime = art::Runtime::Current();
555 art::Thread* self = art::Thread::Current();
556 ArtJvmTiEnv* env = ArtJvmTiEnv::AsArtJvmTiEnv(jenv);
Alex Light0e692732017-01-10 15:00:05 -0800557 if (env == nullptr) {
Alex Light3732beb2019-10-04 13:35:34 -0700558 JVMTI_LOG(WARNING, env) << "FAILURE TO REDEFINE env was null!";
Alex Light0e692732017-01-10 15:00:05 -0800559 return ERR(INVALID_ENVIRONMENT);
560 } else if (class_count < 0) {
Alex Light3732beb2019-10-04 13:35:34 -0700561 JVMTI_LOG(WARNING, env) << "FAILURE TO REDEFINE class_count was less then 0";
Alex Light0e692732017-01-10 15:00:05 -0800562 return ERR(ILLEGAL_ARGUMENT);
563 } else if (class_count == 0) {
564 // We don't actually need to do anything. Just return OK.
565 return OK;
566 } else if (definitions == nullptr) {
Alex Light3732beb2019-10-04 13:35:34 -0700567 JVMTI_LOG(WARNING, env) << "FAILURE TO REDEFINE null definitions!";
Alex Light0e692732017-01-10 15:00:05 -0800568 return ERR(NULL_POINTER);
569 }
Alex Light3732beb2019-10-04 13:35:34 -0700570 std::string error_msg;
Alex Light6ac57502017-01-19 15:05:06 -0800571 std::vector<ArtClassDefinition> def_vector;
572 def_vector.reserve(class_count);
573 for (jint i = 0; i < class_count; i++) {
Alex Lightd55b8442019-10-15 15:46:07 -0700574 jvmtiError res = Redefiner::GetClassRedefinitionError<RedefinitionType::kNormal>(
575 definitions[i].klass, &error_msg);
Alex Lightce6ee702017-03-06 15:46:43 -0800576 if (res != OK) {
Alex Light3732beb2019-10-04 13:35:34 -0700577 JVMTI_LOG(WARNING, env) << "FAILURE TO REDEFINE " << error_msg;
Alex Lightce6ee702017-03-06 15:46:43 -0800578 return res;
Alex Lightce6ee702017-03-06 15:46:43 -0800579 }
Alex Light6ac57502017-01-19 15:05:06 -0800580 ArtClassDefinition def;
Alex Light64e4c142018-01-30 13:46:37 -0800581 res = def.Init(self, definitions[i]);
Alex Light6ac57502017-01-19 15:05:06 -0800582 if (res != OK) {
Alex Light3732beb2019-10-04 13:35:34 -0700583 JVMTI_LOG(WARNING, env) << "FAILURE TO REDEFINE bad definition " << i;
Alex Light6ac57502017-01-19 15:05:06 -0800584 return res;
585 }
586 def_vector.push_back(std::move(def));
587 }
588 // Call all the transformation events.
Alex Lightd55b8442019-10-15 15:46:07 -0700589 Transformer::RetransformClassesDirect<kType>(self, &def_vector);
590 if (kType == RedefinitionType::kStructural) {
591 Transformer::RetransformClassesDirect<RedefinitionType::kNormal>(self, &def_vector);
592 }
593 jvmtiError res = RedefineClassesDirect(env, runtime, self, def_vector, kType, &error_msg);
Alex Light3732beb2019-10-04 13:35:34 -0700594 if (res != OK) {
595 JVMTI_LOG(WARNING, env) << "FAILURE TO REDEFINE " << error_msg;
596 }
597 return res;
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000598}
599
Alex Lightd55b8442019-10-15 15:46:07 -0700600jvmtiError Redefiner::StructurallyRedefineClasses(jvmtiEnv* jenv,
601 jint class_count,
602 const jvmtiClassDefinition* definitions) {
603 ArtJvmTiEnv* art_env = ArtJvmTiEnv::AsArtJvmTiEnv(jenv);
604 if (art_env == nullptr) {
605 return ERR(INVALID_ENVIRONMENT);
606 } else if (art_env->capabilities.can_redefine_classes != 1) {
607 return ERR(MUST_POSSESS_CAPABILITY);
608 }
609 return RedefineClassesGeneric<RedefinitionType::kStructural>(jenv, class_count, definitions);
610}
611
612jvmtiError Redefiner::RedefineClasses(jvmtiEnv* jenv,
613 jint class_count,
614 const jvmtiClassDefinition* definitions) {
615 return RedefineClassesGeneric<RedefinitionType::kNormal>(jenv, class_count, definitions);
616}
617
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000618jvmtiError Redefiner::StructurallyRedefineClassDirect(jvmtiEnv* env,
619 jclass klass,
620 const unsigned char* data,
621 jint data_size) {
622 if (env == nullptr) {
623 return ERR(INVALID_ENVIRONMENT);
624 } else if (ArtJvmTiEnv::AsArtJvmTiEnv(env)->capabilities.can_redefine_classes != 1) {
625 JVMTI_LOG(INFO, env) << "Does not have can_redefine_classes cap!";
626 return ERR(MUST_POSSESS_CAPABILITY);
627 }
628 std::vector<ArtClassDefinition> acds;
629 ArtClassDefinition acd;
630 jvmtiError err = acd.Init(
631 art::Thread::Current(),
632 jvmtiClassDefinition{ .klass = klass, .class_byte_count = data_size, .class_bytes = data });
633 if (err != OK) {
634 return err;
635 }
636 acds.push_back(std::move(acd));
637 std::string err_msg;
638 err = RedefineClassesDirect(ArtJvmTiEnv::AsArtJvmTiEnv(env),
639 art::Runtime::Current(),
640 art::Thread::Current(),
641 acds,
642 RedefinitionType::kStructural,
643 &err_msg);
644 if (err != OK) {
645 JVMTI_LOG(WARNING, env) << "Failed structural redefinition: " << err_msg;
646 }
647 return err;
Alex Light6ac57502017-01-19 15:05:06 -0800648}
649
650jvmtiError Redefiner::RedefineClassesDirect(ArtJvmTiEnv* env,
651 art::Runtime* runtime,
652 art::Thread* self,
653 const std::vector<ArtClassDefinition>& definitions,
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000654 RedefinitionType type,
Alex Light6ac57502017-01-19 15:05:06 -0800655 std::string* error_msg) {
656 DCHECK(env != nullptr);
657 if (definitions.size() == 0) {
658 // We don't actually need to do anything. Just return OK.
659 return OK;
660 }
Alex Lightc2d0c962019-10-23 14:14:25 -0700661 // We need to fiddle with the verification class flags. To do this we need to make sure there are
662 // no concurrent redefinitions of the same class at the same time. For simplicity and because
663 // this is not expected to be a common occurrence we will just wrap the whole thing in a TOP-level
664 // lock.
665
Alex Light0e692732017-01-10 15:00:05 -0800666 // Stop JIT for the duration of this redefine since the JIT might concurrently compile a method we
667 // are going to redefine.
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000668 // TODO We should prevent user-code suspensions to make sure this isn't held for too long.
Alex Light0e692732017-01-10 15:00:05 -0800669 art::jit::ScopedJitSuspend suspend_jit;
670 // Get shared mutator lock so we can lock all the classes.
671 art::ScopedObjectAccess soa(self);
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000672 Redefiner r(env, runtime, self, type, error_msg);
Alex Light6ac57502017-01-19 15:05:06 -0800673 for (const ArtClassDefinition& def : definitions) {
674 // Only try to transform classes that have been modified.
Alex Light40528472017-03-28 09:07:36 -0700675 if (def.IsModified()) {
Alex Light6ac57502017-01-19 15:05:06 -0800676 jvmtiError res = r.AddRedefinition(env, def);
677 if (res != OK) {
678 return res;
679 }
Alex Light0e692732017-01-10 15:00:05 -0800680 }
681 }
682 return r.Run();
683}
684
Alex Light6ac57502017-01-19 15:05:06 -0800685jvmtiError Redefiner::AddRedefinition(ArtJvmTiEnv* env, const ArtClassDefinition& def) {
Alex Light0e692732017-01-10 15:00:05 -0800686 std::string original_dex_location;
687 jvmtiError ret = OK;
Alex Lightb7354d52017-03-30 15:17:01 -0700688 if ((ret = GetClassLocation(env, def.GetClass(), &original_dex_location))) {
Alex Light0e692732017-01-10 15:00:05 -0800689 *error_msg_ = "Unable to get original dex file location!";
690 return ret;
691 }
Alex Light52a2db52017-01-19 23:00:21 +0000692 char* generic_ptr_unused = nullptr;
693 char* signature_ptr = nullptr;
Alex Lightb7354d52017-03-30 15:17:01 -0700694 if ((ret = env->GetClassSignature(def.GetClass(), &signature_ptr, &generic_ptr_unused)) != OK) {
Alex Light6ac57502017-01-19 15:05:06 -0800695 *error_msg_ = "Unable to get class signature!";
696 return ret;
Alex Light52a2db52017-01-19 23:00:21 +0000697 }
Andreas Gampe54711412017-02-21 12:41:43 -0800698 JvmtiUniquePtr<char> generic_unique_ptr(MakeJvmtiUniquePtr(env, generic_ptr_unused));
699 JvmtiUniquePtr<char> signature_unique_ptr(MakeJvmtiUniquePtr(env, signature_ptr));
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100700 art::MemMap map = MoveDataToMemMap(original_dex_location, def.GetDexData(), error_msg_);
Alex Light6ac57502017-01-19 15:05:06 -0800701 std::ostringstream os;
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100702 if (!map.IsValid()) {
Alex Lightb7354d52017-03-30 15:17:01 -0700703 os << "Failed to create anonymous mmap for modified dex file of class " << def.GetName()
Alex Light0e692732017-01-10 15:00:05 -0800704 << "in dex file " << original_dex_location << " because: " << *error_msg_;
705 *error_msg_ = os.str();
Alex Lighta01de592016-11-15 10:43:06 -0800706 return ERR(OUT_OF_MEMORY);
707 }
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100708 if (map.Size() < sizeof(art::DexFile::Header)) {
Alex Light0e692732017-01-10 15:00:05 -0800709 *error_msg_ = "Could not read dex file header because dex_data was too short";
Alex Lighta01de592016-11-15 10:43:06 -0800710 return ERR(INVALID_CLASS_FORMAT);
711 }
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100712 std::string name = map.GetName();
713 uint32_t checksum = reinterpret_cast<const art::DexFile::Header*>(map.Begin())->checksum_;
David Sehr013fd802018-01-11 22:55:24 -0800714 const art::ArtDexFileLoader dex_file_loader;
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100715 std::unique_ptr<const art::DexFile> dex_file(dex_file_loader.Open(name,
David Sehr013fd802018-01-11 22:55:24 -0800716 checksum,
717 std::move(map),
Andreas Gampe6e897762018-10-16 13:09:32 -0700718 /*verify=*/true,
719 /*verify_checksum=*/true,
David Sehr013fd802018-01-11 22:55:24 -0800720 error_msg_));
Alex Lighta01de592016-11-15 10:43:06 -0800721 if (dex_file.get() == nullptr) {
Alex Lightb7354d52017-03-30 15:17:01 -0700722 os << "Unable to load modified dex file for " << def.GetName() << ": " << *error_msg_;
Alex Light0e692732017-01-10 15:00:05 -0800723 *error_msg_ = os.str();
Alex Lighta01de592016-11-15 10:43:06 -0800724 return ERR(INVALID_CLASS_FORMAT);
725 }
Alex Light0e692732017-01-10 15:00:05 -0800726 redefinitions_.push_back(
Alex Lighta7e38d82017-01-19 14:57:28 -0800727 Redefiner::ClassRedefinition(this,
Alex Lightb7354d52017-03-30 15:17:01 -0700728 def.GetClass(),
Alex Lighta7e38d82017-01-19 14:57:28 -0800729 dex_file.release(),
730 signature_ptr,
Alex Light40528472017-03-28 09:07:36 -0700731 def.GetNewOriginalDexFile()));
Alex Light0e692732017-01-10 15:00:05 -0800732 return OK;
Alex Lighta01de592016-11-15 10:43:06 -0800733}
734
Vladimir Marko4617d582019-03-28 13:48:31 +0000735art::ObjPtr<art::mirror::Class> Redefiner::ClassRedefinition::GetMirrorClass() {
Alex Light0e692732017-01-10 15:00:05 -0800736 return driver_->self_->DecodeJObject(klass_)->AsClass();
Alex Lighta01de592016-11-15 10:43:06 -0800737}
738
Vladimir Markoc524e9e2019-03-26 10:54:50 +0000739art::ObjPtr<art::mirror::ClassLoader> Redefiner::ClassRedefinition::GetClassLoader() {
Alex Lighta01de592016-11-15 10:43:06 -0800740 return GetMirrorClass()->GetClassLoader();
741}
742
Alex Light0e692732017-01-10 15:00:05 -0800743art::mirror::DexCache* Redefiner::ClassRedefinition::CreateNewDexCache(
744 art::Handle<art::mirror::ClassLoader> loader) {
Alex Light07f06212017-06-01 14:01:43 -0700745 art::StackHandleScope<2> hs(driver_->self_);
746 art::ClassLinker* cl = driver_->runtime_->GetClassLinker();
747 art::Handle<art::mirror::DexCache> cache(hs.NewHandle(
748 art::ObjPtr<art::mirror::DexCache>::DownCast(
Vladimir Markob4eb1b12018-05-24 11:09:38 +0100749 art::GetClassRoot<art::mirror::DexCache>(cl)->AllocObject(driver_->self_))));
Alex Light07f06212017-06-01 14:01:43 -0700750 if (cache.IsNull()) {
751 driver_->self_->AssertPendingOOMException();
752 return nullptr;
753 }
754 art::Handle<art::mirror::String> location(hs.NewHandle(
755 cl->GetInternTable()->InternStrong(dex_file_->GetLocation().c_str())));
756 if (location.IsNull()) {
757 driver_->self_->AssertPendingOOMException();
758 return nullptr;
759 }
760 art::WriterMutexLock mu(driver_->self_, *art::Locks::dex_lock_);
David Srbecky86d6cd52020-12-02 18:13:10 +0000761 cache->SetLocation(location.Get());
David Srbecky33df0e32021-09-30 14:36:32 +0000762 cache->Initialize(dex_file_.get(), loader.Get());
Alex Light07f06212017-06-01 14:01:43 -0700763 return cache.Get();
Alex Lighta01de592016-11-15 10:43:06 -0800764}
765
Alex Light0e692732017-01-10 15:00:05 -0800766void Redefiner::RecordFailure(jvmtiError result,
767 const std::string& class_sig,
768 const std::string& error_msg) {
Andreas Gampe46ee31b2016-12-14 10:11:49 -0800769 *error_msg_ = StringPrintf("Unable to perform redefinition of '%s': %s",
Alex Light0e692732017-01-10 15:00:05 -0800770 class_sig.c_str(),
Andreas Gampe46ee31b2016-12-14 10:11:49 -0800771 error_msg.c_str());
Alex Lighta01de592016-11-15 10:43:06 -0800772 result_ = result;
773}
774
Alex Light2f814aa2017-03-24 15:21:34 +0000775art::mirror::Object* Redefiner::ClassRedefinition::AllocateOrGetOriginalDexFile() {
Alex Lighta7e38d82017-01-19 14:57:28 -0800776 // If we have been specifically given a new set of bytes use that
777 if (original_dex_file_.size() != 0) {
Alex Light440b5d92017-01-24 15:32:25 -0800778 return art::mirror::ByteArray::AllocateAndFill(
779 driver_->self_,
Vladimir Markoe1993c72017-06-14 17:01:38 +0100780 reinterpret_cast<const signed char*>(original_dex_file_.data()),
Vladimir Markobcf17522018-06-01 13:14:32 +0100781 original_dex_file_.size()).Ptr();
Alex Lighta01de592016-11-15 10:43:06 -0800782 }
Alex Lighta7e38d82017-01-19 14:57:28 -0800783
784 // See if we already have one set.
785 art::ObjPtr<art::mirror::ClassExt> ext(GetMirrorClass()->GetExtData());
786 if (!ext.IsNull()) {
Alex Light2f814aa2017-03-24 15:21:34 +0000787 art::ObjPtr<art::mirror::Object> old_original_dex_file(ext->GetOriginalDexFile());
788 if (!old_original_dex_file.IsNull()) {
Alex Lighta7e38d82017-01-19 14:57:28 -0800789 // We do. Use it.
Alex Light2f814aa2017-03-24 15:21:34 +0000790 return old_original_dex_file.Ptr();
Alex Lighta7e38d82017-01-19 14:57:28 -0800791 }
Alex Lighta01de592016-11-15 10:43:06 -0800792 }
Alex Lighta7e38d82017-01-19 14:57:28 -0800793
Alex Light2f814aa2017-03-24 15:21:34 +0000794 // return the current dex_cache which has the dex file in it.
795 art::ObjPtr<art::mirror::DexCache> current_dex_cache(GetMirrorClass()->GetDexCache());
Alex Lighta7e38d82017-01-19 14:57:28 -0800796 // TODO Handle this or make it so it cannot happen.
Alex Light2f814aa2017-03-24 15:21:34 +0000797 if (current_dex_cache->GetDexFile()->NumClassDefs() != 1) {
Alex Lighta7e38d82017-01-19 14:57:28 -0800798 LOG(WARNING) << "Current dex file has more than one class in it. Calling RetransformClasses "
799 << "on this class might fail if no transformations are applied to it!";
Alex Lighta01de592016-11-15 10:43:06 -0800800 }
Alex Light2f814aa2017-03-24 15:21:34 +0000801 return current_dex_cache.Ptr();
Alex Lighta01de592016-11-15 10:43:06 -0800802}
803
Alex Lightdba61482016-12-21 08:20:29 -0800804struct CallbackCtx {
Alex Lighteee0bd42017-02-14 15:31:45 +0000805 ObsoleteMap* obsolete_map;
Alex Lightdba61482016-12-21 08:20:29 -0800806 art::LinearAlloc* allocator;
Alex Lightdba61482016-12-21 08:20:29 -0800807 std::unordered_set<art::ArtMethod*> obsolete_methods;
Alex Lightdba61482016-12-21 08:20:29 -0800808
Alex Lighteee0bd42017-02-14 15:31:45 +0000809 explicit CallbackCtx(ObsoleteMap* map, art::LinearAlloc* alloc)
810 : obsolete_map(map), allocator(alloc) {}
Alex Lightdba61482016-12-21 08:20:29 -0800811};
812
Alex Lightdba61482016-12-21 08:20:29 -0800813void DoAllocateObsoleteMethodsCallback(art::Thread* t, void* vdata) NO_THREAD_SAFETY_ANALYSIS {
814 CallbackCtx* data = reinterpret_cast<CallbackCtx*>(vdata);
Alex Light007ada22017-01-10 13:33:56 -0800815 ObsoleteMethodStackVisitor::UpdateObsoleteFrames(t,
816 data->allocator,
817 data->obsolete_methods,
Alex Lighteee0bd42017-02-14 15:31:45 +0000818 data->obsolete_map);
Alex Lightdba61482016-12-21 08:20:29 -0800819}
820
821// This creates any ArtMethod* structures needed for obsolete methods and ensures that the stack is
822// updated so they will be run.
Alex Light0e692732017-01-10 15:00:05 -0800823// TODO Rewrite so we can do this only once regardless of how many redefinitions there are.
Vladimir Markod93e3742018-07-18 10:58:13 +0100824void Redefiner::ClassRedefinition::FindAndAllocateObsoleteMethods(
825 art::ObjPtr<art::mirror::Class> art_klass) {
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000826 DCHECK(!IsStructuralRedefinition());
Alex Lightdba61482016-12-21 08:20:29 -0800827 art::ScopedAssertNoThreadSuspension ns("No thread suspension during thread stack walking");
Vladimir Markod93e3742018-07-18 10:58:13 +0100828 art::ObjPtr<art::mirror::ClassExt> ext = art_klass->GetExtData();
Alex Lightdba61482016-12-21 08:20:29 -0800829 CHECK(ext->GetObsoleteMethods() != nullptr);
Alex Light7916f202017-01-27 09:00:15 -0800830 art::ClassLinker* linker = driver_->runtime_->GetClassLinker();
Alex Lighteee0bd42017-02-14 15:31:45 +0000831 // This holds pointers to the obsolete methods map fields which are updated as needed.
832 ObsoleteMap map(ext->GetObsoleteMethods(), ext->GetObsoleteDexCaches(), art_klass->GetDexCache());
833 CallbackCtx ctx(&map, linker->GetAllocatorForClassLoader(art_klass->GetClassLoader()));
Alex Lightdba61482016-12-21 08:20:29 -0800834 // Add all the declared methods to the map
835 for (auto& m : art_klass->GetDeclaredMethods(art::kRuntimePointerSize)) {
Alex Light7532d582017-02-13 16:36:06 -0800836 if (m.IsIntrinsic()) {
837 LOG(WARNING) << "Redefining intrinsic method " << m.PrettyMethod() << ". This may cause the "
838 << "unexpected use of the original definition of " << m.PrettyMethod() << "in "
839 << "methods that have already been compiled.";
840 }
Alex Lighteee0bd42017-02-14 15:31:45 +0000841 // It is possible to simply filter out some methods where they cannot really become obsolete,
842 // such as native methods and keep their original (possibly optimized) implementations. We don't
843 // do this, however, since we would need to mark these functions (still in the classes
844 // declared_methods array) as obsolete so we will find the correct dex file to get meta-data
845 // from (for example about stack-frame size). Furthermore we would be unable to get some useful
846 // error checking from the interpreter which ensure we don't try to start executing obsolete
847 // methods.
Nicolas Geoffray7558d272017-02-10 10:01:47 +0000848 ctx.obsolete_methods.insert(&m);
Alex Lightdba61482016-12-21 08:20:29 -0800849 }
850 {
Alex Light0e692732017-01-10 15:00:05 -0800851 art::MutexLock mu(driver_->self_, *art::Locks::thread_list_lock_);
Alex Lightdba61482016-12-21 08:20:29 -0800852 art::ThreadList* list = art::Runtime::Current()->GetThreadList();
853 list->ForEach(DoAllocateObsoleteMethodsCallback, static_cast<void*>(&ctx));
Vladimir Markoeab02482019-05-09 10:28:17 +0100854 // After we've done walking all threads' stacks and updating method pointers on them,
855 // update JIT data structures (used by the stack walk above) to point to the new methods.
Alex Lighte7a33542019-04-10 14:22:49 -0700856 art::jit::Jit* jit = art::Runtime::Current()->GetJit();
857 if (jit != nullptr) {
858 for (const ObsoleteMap::ObsoleteMethodPair& it : *ctx.obsolete_map) {
859 // Notify the JIT we are making this obsolete method. It will update the jit's internal
860 // structures to keep track of the new obsolete method.
861 jit->GetCodeCache()->MoveObsoleteMethod(it.old_method, it.obsolete_method);
862 }
863 }
Alex Lightdba61482016-12-21 08:20:29 -0800864 }
Alex Lightdba61482016-12-21 08:20:29 -0800865}
866
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000867namespace {
868template <typename T> struct SignatureType {};
869template <> struct SignatureType<art::ArtField> { using type = std::string_view; };
870template <> struct SignatureType<art::ArtMethod> { using type = art::Signature; };
871
872template <typename T> struct NameAndSignature {
873 public:
874 using SigType = typename SignatureType<T>::type;
875
876 NameAndSignature(const art::DexFile* dex_file, uint32_t id);
877
878 NameAndSignature(const std::string_view& name, const SigType& sig) : name_(name), sig_(sig) {}
879
880 bool operator==(const NameAndSignature<T>& o) {
881 return name_ == o.name_ && sig_ == o.sig_;
Alex Light6161f132017-01-25 10:30:20 -0800882 }
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000883
884 std::ostream& dump(std::ostream& os) const {
885 return os << "'" << name_ << "' (sig: " << sig_ << ")";
886 }
887
888 std::string ToString() const {
889 std::ostringstream os;
890 os << *this;
891 return os.str();
892 }
893
894 std::string_view name_;
895 SigType sig_;
896};
897
898template <typename T>
899std::ostream& operator<<(std::ostream& os, const NameAndSignature<T>& nas) {
900 return nas.dump(os);
Alex Light6161f132017-01-25 10:30:20 -0800901}
902
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000903using FieldNameAndSignature = NameAndSignature<art::ArtField>;
904template <>
905FieldNameAndSignature::NameAndSignature(const art::DexFile* dex_file, uint32_t id)
906 : FieldNameAndSignature(dex_file->GetFieldName(dex_file->GetFieldId(id)),
907 dex_file->GetFieldTypeDescriptor(dex_file->GetFieldId(id))) {}
908
909using MethodNameAndSignature = NameAndSignature<art::ArtMethod>;
910template <>
911MethodNameAndSignature::NameAndSignature(const art::DexFile* dex_file, uint32_t id)
912 : MethodNameAndSignature(dex_file->GetMethodName(dex_file->GetMethodId(id)),
913 dex_file->GetMethodSignature(dex_file->GetMethodId(id))) {}
914
915} // namespace
916
917void Redefiner::ClassRedefinition::RecordNewMethodAdded() {
918 DCHECK(driver_->IsStructuralRedefinition());
919 added_methods_ = true;
920}
921void Redefiner::ClassRedefinition::RecordNewFieldAdded() {
922 DCHECK(driver_->IsStructuralRedefinition());
923 added_fields_ = true;
924}
925
926bool Redefiner::ClassRedefinition::CheckMethods() {
Alex Light6161f132017-01-25 10:30:20 -0800927 art::StackHandleScope<1> hs(driver_->self_);
928 art::Handle<art::mirror::Class> h_klass(hs.NewHandle(GetMirrorClass()));
929 DCHECK_EQ(dex_file_->NumClassDefs(), 1u);
930
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000931 // Make sure we have the same number of methods (or the same or greater if we're structural).
Mathieu Chartier4ac9ade2018-07-24 10:27:21 -0700932 art::ClassAccessor accessor(*dex_file_, dex_file_->GetClassDef(0));
933 uint32_t num_new_method = accessor.NumMethods();
Alex Light6161f132017-01-25 10:30:20 -0800934 uint32_t num_old_method = h_klass->GetDeclaredMethodsSlice(art::kRuntimePointerSize).size();
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000935 const bool is_structural = driver_->IsStructuralRedefinition();
936 if (!is_structural && num_new_method != num_old_method) {
Alex Light6161f132017-01-25 10:30:20 -0800937 bool bigger = num_new_method > num_old_method;
938 RecordFailure(bigger ? ERR(UNSUPPORTED_REDEFINITION_METHOD_ADDED)
939 : ERR(UNSUPPORTED_REDEFINITION_METHOD_DELETED),
940 StringPrintf("Total number of declared methods changed from %d to %d",
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000941 num_old_method,
942 num_new_method));
Alex Light6161f132017-01-25 10:30:20 -0800943 return false;
944 }
945
946 // Skip all of the fields. We should have already checked this.
Alex Light6161f132017-01-25 10:30:20 -0800947 // Check each of the methods. NB we don't need to specifically check for removals since the 2 dex
948 // files have the same number of methods, which means there must be an equal amount of additions
Mathieu Chartier4ac9ade2018-07-24 10:27:21 -0700949 // and removals. We should have already checked the fields.
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000950 const art::DexFile& old_dex_file = h_klass->GetDexFile();
951 art::ClassAccessor old_accessor(old_dex_file, *h_klass->GetClassDef());
952 // We need this to check for methods going missing in structural cases.
953 std::vector<bool> seen_old_methods(
954 (kCheckAllMethodsSeenOnce || is_structural) ? old_accessor.NumMethods() : 0, false);
955 const auto old_methods = old_accessor.GetMethods();
956 for (const art::ClassAccessor::Method& new_method : accessor.GetMethods()) {
Alex Light6161f132017-01-25 10:30:20 -0800957 // Get the data on the method we are searching for
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000958 MethodNameAndSignature new_method_id(dex_file_.get(), new_method.GetIndex());
959 const auto old_iter =
960 std::find_if(old_methods.cbegin(), old_methods.cend(), [&](const auto& current_old_method) {
961 MethodNameAndSignature old_method_id(&old_dex_file, current_old_method.GetIndex());
962 return old_method_id == new_method_id;
963 });
964
Alex Light986914b2019-11-19 01:12:25 +0000965 if (!new_method.IsStaticOrDirect()) {
966 RecordHasVirtualMembers();
967 }
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000968 if (old_iter == old_methods.cend()) {
Alex Light270db1c2019-12-03 12:20:01 +0000969 if (is_structural) {
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000970 RecordNewMethodAdded();
971 } else {
972 RecordFailure(
973 ERR(UNSUPPORTED_REDEFINITION_METHOD_ADDED),
974 StringPrintf("Unknown virtual method %s was added!", new_method_id.ToString().c_str()));
975 return false;
976 }
977 } else if (new_method.GetAccessFlags() != old_iter->GetAccessFlags()) {
978 RecordFailure(
979 ERR(UNSUPPORTED_REDEFINITION_METHOD_MODIFIERS_CHANGED),
980 StringPrintf("method %s had different access flags", new_method_id.ToString().c_str()));
Alex Light6161f132017-01-25 10:30:20 -0800981 return false;
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000982 } else if (kCheckAllMethodsSeenOnce || is_structural) {
983 // We only need this if we are structural.
984 size_t off = std::distance(old_methods.cbegin(), old_iter);
985 DCHECK(!seen_old_methods[off])
986 << "field at " << off << "("
987 << MethodNameAndSignature(&old_dex_file, old_iter->GetIndex()) << ") already seen?";
988 seen_old_methods[off] = true;
Alex Light6161f132017-01-25 10:30:20 -0800989 }
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000990 }
991 if ((kCheckAllMethodsSeenOnce || is_structural) &&
992 !std::all_of(seen_old_methods.cbegin(), seen_old_methods.cend(), [](auto x) { return x; })) {
993 DCHECK(is_structural) << "We should have hit an earlier failure before getting here!";
994 auto first_fail =
995 std::find_if(seen_old_methods.cbegin(), seen_old_methods.cend(), [](auto x) { return !x; });
996 auto off = std::distance(seen_old_methods.cbegin(), first_fail);
997 auto fail = old_methods.cbegin();
998 std::advance(fail, off);
999 RecordFailure(
1000 ERR(UNSUPPORTED_REDEFINITION_METHOD_DELETED),
1001 StringPrintf("Method %s missing!",
Alex Lightdaad67f2019-12-16 13:01:46 -08001002 MethodNameAndSignature(&old_dex_file, fail->GetIndex()).ToString().c_str()));
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001003 return false;
Alex Light6161f132017-01-25 10:30:20 -08001004 }
1005 return true;
1006}
1007
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001008bool Redefiner::ClassRedefinition::CheckFields() {
Alex Light6161f132017-01-25 10:30:20 -08001009 art::StackHandleScope<1> hs(driver_->self_);
1010 art::Handle<art::mirror::Class> h_klass(hs.NewHandle(GetMirrorClass()));
1011 DCHECK_EQ(dex_file_->NumClassDefs(), 1u);
Mathieu Chartier4ac9ade2018-07-24 10:27:21 -07001012 art::ClassAccessor new_accessor(*dex_file_, dex_file_->GetClassDef(0));
1013
Alex Light6161f132017-01-25 10:30:20 -08001014 const art::DexFile& old_dex_file = h_klass->GetDexFile();
Mathieu Chartier4ac9ade2018-07-24 10:27:21 -07001015 art::ClassAccessor old_accessor(old_dex_file, *h_klass->GetClassDef());
Alex Light6161f132017-01-25 10:30:20 -08001016 // Instance and static fields can be differentiated by their flags so no need to check them
1017 // separately.
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001018 std::vector<bool> seen_old_fields(old_accessor.NumFields(), false);
1019 const auto old_fields = old_accessor.GetFields();
Mathieu Chartier4ac9ade2018-07-24 10:27:21 -07001020 for (const art::ClassAccessor::Field& new_field : new_accessor.GetFields()) {
Alex Light6161f132017-01-25 10:30:20 -08001021 // Get the data on the method we are searching for
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001022 FieldNameAndSignature new_field_id(dex_file_.get(), new_field.GetIndex());
1023 const auto old_iter =
1024 std::find_if(old_fields.cbegin(), old_fields.cend(), [&](const auto& old_iter) {
1025 FieldNameAndSignature old_field_id(&old_dex_file, old_iter.GetIndex());
1026 return old_field_id == new_field_id;
1027 });
Alex Light986914b2019-11-19 01:12:25 +00001028 if (!new_field.IsStatic()) {
1029 RecordHasVirtualMembers();
1030 }
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001031 if (old_iter == old_fields.cend()) {
Alex Light270db1c2019-12-03 12:20:01 +00001032 if (driver_->IsStructuralRedefinition()) {
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001033 RecordNewFieldAdded();
1034 } else {
1035 RecordFailure(ERR(UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED),
1036 StringPrintf("Unknown field %s added!", new_field_id.ToString().c_str()));
1037 return false;
1038 }
1039 } else if (new_field.GetAccessFlags() != old_iter->GetAccessFlags()) {
1040 RecordFailure(
1041 ERR(UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED),
1042 StringPrintf("Field %s had different access flags", new_field_id.ToString().c_str()));
Alex Light6161f132017-01-25 10:30:20 -08001043 return false;
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001044 } else {
1045 size_t off = std::distance(old_fields.cbegin(), old_iter);
1046 DCHECK(!seen_old_fields[off])
1047 << "field at " << off << "(" << FieldNameAndSignature(&old_dex_file, old_iter->GetIndex())
1048 << ") already seen?";
1049 seen_old_fields[off] = true;
Alex Light6161f132017-01-25 10:30:20 -08001050 }
Alex Light6161f132017-01-25 10:30:20 -08001051 }
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001052 if (!std::all_of(seen_old_fields.cbegin(), seen_old_fields.cend(), [](auto x) { return x; })) {
1053 auto first_fail =
1054 std::find_if(seen_old_fields.cbegin(), seen_old_fields.cend(), [](auto x) { return !x; });
1055 auto off = std::distance(seen_old_fields.cbegin(), first_fail);
1056 auto fail = old_fields.cbegin();
1057 std::advance(fail, off);
1058 RecordFailure(
1059 ERR(UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED),
1060 StringPrintf("Field %s is missing!",
1061 FieldNameAndSignature(&old_dex_file, fail->GetIndex()).ToString().c_str()));
Alex Light6161f132017-01-25 10:30:20 -08001062 return false;
1063 }
1064 return true;
1065}
1066
Alex Light0e692732017-01-10 15:00:05 -08001067bool Redefiner::ClassRedefinition::CheckClass() {
Alex Light0e692732017-01-10 15:00:05 -08001068 art::StackHandleScope<1> hs(driver_->self_);
Alex Light460d1b42017-01-10 15:37:17 +00001069 // Easy check that only 1 class def is present.
1070 if (dex_file_->NumClassDefs() != 1) {
1071 RecordFailure(ERR(ILLEGAL_ARGUMENT),
1072 StringPrintf("Expected 1 class def in dex file but found %d",
1073 dex_file_->NumClassDefs()));
1074 return false;
1075 }
1076 // Get the ClassDef from the new DexFile.
1077 // Since the dex file has only a single class def the index is always 0.
Andreas Gampe3f1dcd32018-12-28 09:39:56 -08001078 const art::dex::ClassDef& def = dex_file_->GetClassDef(0);
Alex Light460d1b42017-01-10 15:37:17 +00001079 // Get the class as it is now.
1080 art::Handle<art::mirror::Class> current_class(hs.NewHandle(GetMirrorClass()));
1081
ShuJieWangb087bb22021-11-24 11:46:16 +08001082 // Check whether the class object has been successfully acquired.
1083 if (!lock_acquired_) {
1084 std::string storage;
1085 RecordFailure(ERR(INTERNAL),
1086 StringPrintf("Failed to lock class object '%s'",
1087 current_class->GetDescriptor(&storage)));
1088 return false;
1089 }
1090
Alex Light460d1b42017-01-10 15:37:17 +00001091 // Check the access flags didn't change.
1092 if (def.GetJavaAccessFlags() != (current_class->GetAccessFlags() & art::kAccValidClassFlags)) {
1093 RecordFailure(ERR(UNSUPPORTED_REDEFINITION_CLASS_MODIFIERS_CHANGED),
1094 "Cannot change modifiers of class by redefinition");
1095 return false;
1096 }
1097
1098 // Check class name.
1099 // These should have been checked by the dexfile verifier on load.
1100 DCHECK_NE(def.class_idx_, art::dex::TypeIndex::Invalid()) << "Invalid type index";
1101 const char* descriptor = dex_file_->StringByTypeIdx(def.class_idx_);
1102 DCHECK(descriptor != nullptr) << "Invalid dex file structure!";
1103 if (!current_class->DescriptorEquals(descriptor)) {
1104 std::string storage;
1105 RecordFailure(ERR(NAMES_DONT_MATCH),
1106 StringPrintf("expected file to contain class called '%s' but found '%s'!",
1107 current_class->GetDescriptor(&storage),
1108 descriptor));
1109 return false;
1110 }
1111 if (current_class->IsObjectClass()) {
1112 if (def.superclass_idx_ != art::dex::TypeIndex::Invalid()) {
1113 RecordFailure(ERR(UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED), "Superclass added!");
1114 return false;
1115 }
1116 } else {
1117 const char* super_descriptor = dex_file_->StringByTypeIdx(def.superclass_idx_);
1118 DCHECK(descriptor != nullptr) << "Invalid dex file structure!";
1119 if (!current_class->GetSuperClass()->DescriptorEquals(super_descriptor)) {
1120 RecordFailure(ERR(UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED), "Superclass changed");
1121 return false;
1122 }
1123 }
Andreas Gampe3f1dcd32018-12-28 09:39:56 -08001124 const art::dex::TypeList* interfaces = dex_file_->GetInterfacesList(def);
Alex Light460d1b42017-01-10 15:37:17 +00001125 if (interfaces == nullptr) {
1126 if (current_class->NumDirectInterfaces() != 0) {
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001127 // TODO Support this for kStructural.
Alex Light460d1b42017-01-10 15:37:17 +00001128 RecordFailure(ERR(UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED), "Interfaces added");
1129 return false;
1130 }
1131 } else {
1132 DCHECK(!current_class->IsProxyClass());
Andreas Gampe3f1dcd32018-12-28 09:39:56 -08001133 const art::dex::TypeList* current_interfaces = current_class->GetInterfaceTypeList();
Alex Light460d1b42017-01-10 15:37:17 +00001134 if (current_interfaces == nullptr || current_interfaces->Size() != interfaces->Size()) {
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001135 // TODO Support this for kStructural.
Alex Light460d1b42017-01-10 15:37:17 +00001136 RecordFailure(ERR(UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED), "Interfaces added or removed");
1137 return false;
1138 }
1139 // The order of interfaces is (barely) meaningful so we error if it changes.
1140 const art::DexFile& orig_dex_file = current_class->GetDexFile();
1141 for (uint32_t i = 0; i < interfaces->Size(); i++) {
1142 if (strcmp(
1143 dex_file_->StringByTypeIdx(interfaces->GetTypeItem(i).type_idx_),
1144 orig_dex_file.StringByTypeIdx(current_interfaces->GetTypeItem(i).type_idx_)) != 0) {
1145 RecordFailure(ERR(UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED),
1146 "Interfaces changed or re-ordered");
1147 return false;
1148 }
1149 }
1150 }
Alex Light460d1b42017-01-10 15:37:17 +00001151 return true;
1152}
1153
Alex Light0e692732017-01-10 15:00:05 -08001154bool Redefiner::ClassRedefinition::CheckRedefinable() {
Alex Lighte4a88632017-01-10 07:41:24 -08001155 std::string err;
Alex Light0e692732017-01-10 15:00:05 -08001156 art::StackHandleScope<1> hs(driver_->self_);
Alex Light460d1b42017-01-10 15:37:17 +00001157
Alex Lighte4a88632017-01-10 07:41:24 -08001158 art::Handle<art::mirror::Class> h_klass(hs.NewHandle(GetMirrorClass()));
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001159 jvmtiError res;
Alex Lightd55b8442019-10-15 15:46:07 -07001160 if (driver_->type_ == RedefinitionType::kStructural && this->IsStructuralRedefinition()) {
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001161 res = Redefiner::GetClassRedefinitionError<RedefinitionType::kStructural>(h_klass, &err);
Alex Lightd55b8442019-10-15 15:46:07 -07001162 } else {
1163 res = Redefiner::GetClassRedefinitionError<RedefinitionType::kNormal>(h_klass, &err);
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001164 }
Alex Lighte4a88632017-01-10 07:41:24 -08001165 if (res != OK) {
1166 RecordFailure(res, err);
1167 return false;
1168 } else {
1169 return true;
1170 }
Alex Light460d1b42017-01-10 15:37:17 +00001171}
1172
Alex Light0e692732017-01-10 15:00:05 -08001173bool Redefiner::ClassRedefinition::CheckRedefinitionIsValid() {
Alex Lightd55b8442019-10-15 15:46:07 -07001174 return CheckClass() && CheckFields() && CheckMethods() && CheckRedefinable();
Alex Light460d1b42017-01-10 15:37:17 +00001175}
1176
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001177class RedefinitionDataIter;
1178
Alex Light0e692732017-01-10 15:00:05 -08001179// A wrapper that lets us hold onto the arbitrary sized data needed for redefinitions in a
Orion Hodsonaacf9772020-07-22 21:51:00 +01001180// reasonable way. This adds no fields to the normal ObjectArray. By doing this we can avoid
Alex Light0e692732017-01-10 15:00:05 -08001181// having to deal with the fact that we need to hold an arbitrary number of references live.
1182class RedefinitionDataHolder {
1183 public:
1184 enum DataSlot : int32_t {
1185 kSlotSourceClassLoader = 0,
1186 kSlotJavaDexFile = 1,
1187 kSlotNewDexFileCookie = 2,
1188 kSlotNewDexCache = 3,
1189 kSlotMirrorClass = 4,
Alex Lighta7e38d82017-01-19 14:57:28 -08001190 kSlotOrigDexFile = 5,
Alex Light1e3926a2017-04-07 10:38:06 -07001191 kSlotOldObsoleteMethods = 6,
1192 kSlotOldDexCaches = 7,
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001193 kSlotNewClassObject = 8,
Alex Light986914b2019-11-19 01:12:25 +00001194 kSlotOldInstanceObjects = 9,
1195 kSlotNewInstanceObjects = 10,
Alex Light270db1c2019-12-03 12:20:01 +00001196 kSlotOldClasses = 11,
1197 kSlotNewClasses = 12,
Alex Light0e692732017-01-10 15:00:05 -08001198
1199 // Must be last one.
Alex Light270db1c2019-12-03 12:20:01 +00001200 kNumSlots = 13,
Alex Light0e692732017-01-10 15:00:05 -08001201 };
1202
1203 // This needs to have a HandleScope passed in that is capable of creating a new Handle without
1204 // overflowing. Only one handle will be created. This object has a lifetime identical to that of
1205 // the passed in handle-scope.
1206 RedefinitionDataHolder(art::StackHandleScope<1>* hs,
1207 art::Runtime* runtime,
1208 art::Thread* self,
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001209 std::vector<Redefiner::ClassRedefinition>* redefinitions)
1210 REQUIRES_SHARED(art::Locks::mutator_lock_) :
Vladimir Markob4eb1b12018-05-24 11:09:38 +01001211 arr_(hs->NewHandle(art::mirror::ObjectArray<art::mirror::Object>::Alloc(
1212 self,
1213 art::GetClassRoot<art::mirror::ObjectArray<art::mirror::Object>>(runtime->GetClassLinker()),
1214 redefinitions->size() * kNumSlots))),
Alex Lightfb537082019-12-10 14:38:34 -08001215 redefinitions_(redefinitions),
1216 initialized_(redefinitions_->size(), false),
1217 actually_structural_(redefinitions_->size(), false),
1218 initial_structural_(redefinitions_->size(), false) {}
Alex Light0e692732017-01-10 15:00:05 -08001219
1220 bool IsNull() const REQUIRES_SHARED(art::Locks::mutator_lock_) {
1221 return arr_.IsNull();
1222 }
1223
Vladimir Markod93e3742018-07-18 10:58:13 +01001224 art::ObjPtr<art::mirror::ClassLoader> GetSourceClassLoader(jint klass_index) const
Alex Light0e692732017-01-10 15:00:05 -08001225 REQUIRES_SHARED(art::Locks::mutator_lock_) {
Vladimir Markod93e3742018-07-18 10:58:13 +01001226 return art::ObjPtr<art::mirror::ClassLoader>::DownCast(
1227 GetSlot(klass_index, kSlotSourceClassLoader));
Alex Light0e692732017-01-10 15:00:05 -08001228 }
Vladimir Markod93e3742018-07-18 10:58:13 +01001229 art::ObjPtr<art::mirror::Object> GetJavaDexFile(jint klass_index) const
Alex Light8c889d22017-02-06 13:58:27 -08001230 REQUIRES_SHARED(art::Locks::mutator_lock_) {
Alex Light0e692732017-01-10 15:00:05 -08001231 return GetSlot(klass_index, kSlotJavaDexFile);
1232 }
Vladimir Markod93e3742018-07-18 10:58:13 +01001233 art::ObjPtr<art::mirror::LongArray> GetNewDexFileCookie(jint klass_index) const
Alex Light0e692732017-01-10 15:00:05 -08001234 REQUIRES_SHARED(art::Locks::mutator_lock_) {
Vladimir Markod93e3742018-07-18 10:58:13 +01001235 return art::ObjPtr<art::mirror::LongArray>::DownCast(
1236 GetSlot(klass_index, kSlotNewDexFileCookie));
Alex Light0e692732017-01-10 15:00:05 -08001237 }
Vladimir Markod93e3742018-07-18 10:58:13 +01001238 art::ObjPtr<art::mirror::DexCache> GetNewDexCache(jint klass_index) const
Alex Light0e692732017-01-10 15:00:05 -08001239 REQUIRES_SHARED(art::Locks::mutator_lock_) {
Vladimir Markod93e3742018-07-18 10:58:13 +01001240 return art::ObjPtr<art::mirror::DexCache>::DownCast(GetSlot(klass_index, kSlotNewDexCache));
Alex Light0e692732017-01-10 15:00:05 -08001241 }
Vladimir Markod93e3742018-07-18 10:58:13 +01001242 art::ObjPtr<art::mirror::Class> GetMirrorClass(jint klass_index) const
Alex Light8c889d22017-02-06 13:58:27 -08001243 REQUIRES_SHARED(art::Locks::mutator_lock_) {
Vladimir Markod93e3742018-07-18 10:58:13 +01001244 return art::ObjPtr<art::mirror::Class>::DownCast(GetSlot(klass_index, kSlotMirrorClass));
Alex Light0e692732017-01-10 15:00:05 -08001245 }
1246
Vladimir Markod93e3742018-07-18 10:58:13 +01001247 art::ObjPtr<art::mirror::Object> GetOriginalDexFile(jint klass_index) const
Alex Lighta7e38d82017-01-19 14:57:28 -08001248 REQUIRES_SHARED(art::Locks::mutator_lock_) {
Vladimir Markod93e3742018-07-18 10:58:13 +01001249 return art::ObjPtr<art::mirror::Object>::DownCast(GetSlot(klass_index, kSlotOrigDexFile));
Alex Lighta7e38d82017-01-19 14:57:28 -08001250 }
1251
Vladimir Markod93e3742018-07-18 10:58:13 +01001252 art::ObjPtr<art::mirror::PointerArray> GetOldObsoleteMethods(jint klass_index) const
Alex Light1e3926a2017-04-07 10:38:06 -07001253 REQUIRES_SHARED(art::Locks::mutator_lock_) {
Vladimir Markod93e3742018-07-18 10:58:13 +01001254 return art::ObjPtr<art::mirror::PointerArray>::DownCast(
Alex Light1e3926a2017-04-07 10:38:06 -07001255 GetSlot(klass_index, kSlotOldObsoleteMethods));
1256 }
1257
Vladimir Markod93e3742018-07-18 10:58:13 +01001258 art::ObjPtr<art::mirror::ObjectArray<art::mirror::DexCache>> GetOldDexCaches(
1259 jint klass_index) const REQUIRES_SHARED(art::Locks::mutator_lock_) {
1260 return art::ObjPtr<art::mirror::ObjectArray<art::mirror::DexCache>>::DownCast(
Alex Light1e3926a2017-04-07 10:38:06 -07001261 GetSlot(klass_index, kSlotOldDexCaches));
1262 }
1263
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001264 art::ObjPtr<art::mirror::Class> GetNewClassObject(jint klass_index) const
1265 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1266 return art::ObjPtr<art::mirror::Class>::DownCast(GetSlot(klass_index, kSlotNewClassObject));
1267 }
1268
Alex Light986914b2019-11-19 01:12:25 +00001269 art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>> GetOldInstanceObjects(
1270 jint klass_index) const REQUIRES_SHARED(art::Locks::mutator_lock_) {
1271 return art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>>::DownCast(
1272 GetSlot(klass_index, kSlotOldInstanceObjects));
1273 }
1274
1275 art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>> GetNewInstanceObjects(
1276 jint klass_index) const REQUIRES_SHARED(art::Locks::mutator_lock_) {
1277 return art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>>::DownCast(
1278 GetSlot(klass_index, kSlotNewInstanceObjects));
1279 }
Alex Light270db1c2019-12-03 12:20:01 +00001280 art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>> GetOldClasses(jint klass_index) const
1281 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1282 return art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>>::DownCast(
1283 GetSlot(klass_index, kSlotOldClasses));
1284 }
1285 art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>> GetNewClasses(jint klass_index) const
1286 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1287 return art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>>::DownCast(
1288 GetSlot(klass_index, kSlotNewClasses));
1289 }
Alex Lightfb537082019-12-10 14:38:34 -08001290 bool IsInitialized(jint klass_index) REQUIRES_SHARED(art::Locks::mutator_lock_) {
1291 return initialized_[klass_index];
1292 }
1293 bool IsActuallyStructural(jint klass_index) REQUIRES_SHARED(art::Locks::mutator_lock_) {
1294 return actually_structural_[klass_index];
1295 }
1296
1297 bool IsInitialStructural(jint klass_index) REQUIRES_SHARED(art::Locks::mutator_lock_) {
1298 return initial_structural_[klass_index];
1299 }
Alex Light986914b2019-11-19 01:12:25 +00001300
Vladimir Markod93e3742018-07-18 10:58:13 +01001301 void SetSourceClassLoader(jint klass_index, art::ObjPtr<art::mirror::ClassLoader> loader)
Alex Light0e692732017-01-10 15:00:05 -08001302 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1303 SetSlot(klass_index, kSlotSourceClassLoader, loader);
1304 }
Vladimir Markod93e3742018-07-18 10:58:13 +01001305 void SetJavaDexFile(jint klass_index, art::ObjPtr<art::mirror::Object> dexfile)
Alex Light0e692732017-01-10 15:00:05 -08001306 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1307 SetSlot(klass_index, kSlotJavaDexFile, dexfile);
1308 }
Vladimir Markod93e3742018-07-18 10:58:13 +01001309 void SetNewDexFileCookie(jint klass_index, art::ObjPtr<art::mirror::LongArray> cookie)
Alex Light0e692732017-01-10 15:00:05 -08001310 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1311 SetSlot(klass_index, kSlotNewDexFileCookie, cookie);
1312 }
Vladimir Markod93e3742018-07-18 10:58:13 +01001313 void SetNewDexCache(jint klass_index, art::ObjPtr<art::mirror::DexCache> cache)
Alex Light0e692732017-01-10 15:00:05 -08001314 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1315 SetSlot(klass_index, kSlotNewDexCache, cache);
1316 }
Vladimir Markod93e3742018-07-18 10:58:13 +01001317 void SetMirrorClass(jint klass_index, art::ObjPtr<art::mirror::Class> klass)
Alex Light0e692732017-01-10 15:00:05 -08001318 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1319 SetSlot(klass_index, kSlotMirrorClass, klass);
1320 }
Vladimir Markod93e3742018-07-18 10:58:13 +01001321 void SetOriginalDexFile(jint klass_index, art::ObjPtr<art::mirror::Object> bytes)
Alex Lighta7e38d82017-01-19 14:57:28 -08001322 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1323 SetSlot(klass_index, kSlotOrigDexFile, bytes);
1324 }
Vladimir Markod93e3742018-07-18 10:58:13 +01001325 void SetOldObsoleteMethods(jint klass_index, art::ObjPtr<art::mirror::PointerArray> methods)
Alex Light1e3926a2017-04-07 10:38:06 -07001326 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1327 SetSlot(klass_index, kSlotOldObsoleteMethods, methods);
1328 }
Vladimir Markod93e3742018-07-18 10:58:13 +01001329 void SetOldDexCaches(jint klass_index,
1330 art::ObjPtr<art::mirror::ObjectArray<art::mirror::DexCache>> caches)
Alex Light1e3926a2017-04-07 10:38:06 -07001331 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1332 SetSlot(klass_index, kSlotOldDexCaches, caches);
1333 }
Alex Light0e692732017-01-10 15:00:05 -08001334
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001335 void SetNewClassObject(jint klass_index, art::ObjPtr<art::mirror::Class> klass)
1336 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1337 SetSlot(klass_index, kSlotNewClassObject, klass);
1338 }
1339
Alex Light986914b2019-11-19 01:12:25 +00001340 void SetOldInstanceObjects(jint klass_index,
1341 art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>> objs)
1342 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1343 SetSlot(klass_index, kSlotOldInstanceObjects, objs);
1344 }
1345 void SetNewInstanceObjects(jint klass_index,
1346 art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>> objs)
1347 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1348 SetSlot(klass_index, kSlotNewInstanceObjects, objs);
1349 }
Alex Light270db1c2019-12-03 12:20:01 +00001350 void SetOldClasses(jint klass_index,
1351 art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>> klasses)
1352 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1353 SetSlot(klass_index, kSlotOldClasses, klasses);
1354 }
1355 void SetNewClasses(jint klass_index,
1356 art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>> klasses)
1357 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1358 SetSlot(klass_index, kSlotNewClasses, klasses);
1359 }
Alex Lightfb537082019-12-10 14:38:34 -08001360 void SetInitialized(jint klass_index) REQUIRES_SHARED(art::Locks::mutator_lock_) {
1361 initialized_[klass_index] = true;
1362 }
1363 void SetActuallyStructural(jint klass_index) REQUIRES_SHARED(art::Locks::mutator_lock_) {
1364 actually_structural_[klass_index] = true;
1365 }
1366 void SetInitialStructural(jint klass_index) REQUIRES_SHARED(art::Locks::mutator_lock_) {
1367 initial_structural_[klass_index] = true;
1368 }
Alex Light8c889d22017-02-06 13:58:27 -08001369 int32_t Length() const REQUIRES_SHARED(art::Locks::mutator_lock_) {
Alex Light0e692732017-01-10 15:00:05 -08001370 return arr_->GetLength() / kNumSlots;
1371 }
1372
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001373 std::vector<Redefiner::ClassRedefinition>* GetRedefinitions()
1374 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1375 return redefinitions_;
1376 }
1377
1378 bool operator==(const RedefinitionDataHolder& other) const
1379 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1380 return arr_.Get() == other.arr_.Get();
1381 }
1382
1383 bool operator!=(const RedefinitionDataHolder& other) const
1384 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1385 return !(*this == other);
1386 }
1387
1388 RedefinitionDataIter begin() REQUIRES_SHARED(art::Locks::mutator_lock_);
1389 RedefinitionDataIter end() REQUIRES_SHARED(art::Locks::mutator_lock_);
1390
Alex Light0e692732017-01-10 15:00:05 -08001391 private:
Alex Light8c889d22017-02-06 13:58:27 -08001392 mutable art::Handle<art::mirror::ObjectArray<art::mirror::Object>> arr_;
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001393 std::vector<Redefiner::ClassRedefinition>* redefinitions_;
Alex Lightfb537082019-12-10 14:38:34 -08001394 // Used to mark a particular redefinition as fully initialized.
1395 std::vector<bool> initialized_;
1396 // Used to mark a redefinition as 'actually' structural. That is either the redefinition is
1397 // structural or a superclass is.
1398 std::vector<bool> actually_structural_;
1399 // Used to mark a redefinition as the initial structural redefinition. This redefinition will take
1400 // care of updating all of its subtypes.
1401 std::vector<bool> initial_structural_;
Alex Light0e692732017-01-10 15:00:05 -08001402
Vladimir Markod93e3742018-07-18 10:58:13 +01001403 art::ObjPtr<art::mirror::Object> GetSlot(jint klass_index, DataSlot slot) const
1404 REQUIRES_SHARED(art::Locks::mutator_lock_) {
Alex Light0e692732017-01-10 15:00:05 -08001405 DCHECK_LT(klass_index, Length());
1406 return arr_->Get((kNumSlots * klass_index) + slot);
1407 }
1408
1409 void SetSlot(jint klass_index,
1410 DataSlot slot,
1411 art::ObjPtr<art::mirror::Object> obj) REQUIRES_SHARED(art::Locks::mutator_lock_) {
1412 DCHECK(!art::Runtime::Current()->IsActiveTransaction());
1413 DCHECK_LT(klass_index, Length());
1414 arr_->Set<false>((kNumSlots * klass_index) + slot, obj);
1415 }
1416
1417 DISALLOW_COPY_AND_ASSIGN(RedefinitionDataHolder);
1418};
1419
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001420class RedefinitionDataIter {
1421 public:
1422 RedefinitionDataIter(int32_t idx, RedefinitionDataHolder& holder) : idx_(idx), holder_(holder) {}
1423
1424 RedefinitionDataIter(const RedefinitionDataIter&) = default;
1425 RedefinitionDataIter(RedefinitionDataIter&&) = default;
1426 RedefinitionDataIter& operator=(const RedefinitionDataIter&) = default;
1427 RedefinitionDataIter& operator=(RedefinitionDataIter&&) = default;
1428
1429 bool operator==(const RedefinitionDataIter& other) const
1430 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1431 return idx_ == other.idx_ && holder_ == other.holder_;
1432 }
1433
1434 bool operator!=(const RedefinitionDataIter& other) const
1435 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1436 return !(*this == other);
1437 }
1438
1439 RedefinitionDataIter operator++() { // Value after modification.
1440 idx_++;
1441 return *this;
1442 }
1443
1444 RedefinitionDataIter operator++(int) {
1445 RedefinitionDataIter temp = *this;
1446 idx_++;
1447 return temp;
1448 }
1449
1450 RedefinitionDataIter operator+(ssize_t delta) const {
1451 RedefinitionDataIter temp = *this;
1452 temp += delta;
1453 return temp;
1454 }
1455
1456 RedefinitionDataIter& operator+=(ssize_t delta) {
1457 idx_ += delta;
1458 return *this;
1459 }
1460
Alex Light986914b2019-11-19 01:12:25 +00001461 // Compat for STL iterators.
1462 RedefinitionDataIter& operator*() {
1463 return *this;
1464 }
1465
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001466 Redefiner::ClassRedefinition& GetRedefinition() REQUIRES_SHARED(art::Locks::mutator_lock_) {
1467 return (*holder_.GetRedefinitions())[idx_];
1468 }
1469
1470 RedefinitionDataHolder& GetHolder() {
1471 return holder_;
1472 }
1473
Vladimir Markod93e3742018-07-18 10:58:13 +01001474 art::ObjPtr<art::mirror::ClassLoader> GetSourceClassLoader() const
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001475 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1476 return holder_.GetSourceClassLoader(idx_);
1477 }
Vladimir Markod93e3742018-07-18 10:58:13 +01001478 art::ObjPtr<art::mirror::Object> GetJavaDexFile() const
1479 REQUIRES_SHARED(art::Locks::mutator_lock_) {
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001480 return holder_.GetJavaDexFile(idx_);
1481 }
Vladimir Markod93e3742018-07-18 10:58:13 +01001482 art::ObjPtr<art::mirror::LongArray> GetNewDexFileCookie() const
1483 REQUIRES_SHARED(art::Locks::mutator_lock_) {
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001484 return holder_.GetNewDexFileCookie(idx_);
1485 }
Vladimir Markod93e3742018-07-18 10:58:13 +01001486 art::ObjPtr<art::mirror::DexCache> GetNewDexCache() const
1487 REQUIRES_SHARED(art::Locks::mutator_lock_) {
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001488 return holder_.GetNewDexCache(idx_);
1489 }
Vladimir Markod93e3742018-07-18 10:58:13 +01001490 art::ObjPtr<art::mirror::Class> GetMirrorClass() const
1491 REQUIRES_SHARED(art::Locks::mutator_lock_) {
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001492 return holder_.GetMirrorClass(idx_);
1493 }
Vladimir Markod93e3742018-07-18 10:58:13 +01001494 art::ObjPtr<art::mirror::Object> GetOriginalDexFile() const
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001495 REQUIRES_SHARED(art::Locks::mutator_lock_) {
Alex Light2f814aa2017-03-24 15:21:34 +00001496 return holder_.GetOriginalDexFile(idx_);
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001497 }
Vladimir Markod93e3742018-07-18 10:58:13 +01001498 art::ObjPtr<art::mirror::PointerArray> GetOldObsoleteMethods() const
Alex Light1e3926a2017-04-07 10:38:06 -07001499 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1500 return holder_.GetOldObsoleteMethods(idx_);
1501 }
Vladimir Markod93e3742018-07-18 10:58:13 +01001502 art::ObjPtr<art::mirror::ObjectArray<art::mirror::DexCache>> GetOldDexCaches() const
Alex Light1e3926a2017-04-07 10:38:06 -07001503 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1504 return holder_.GetOldDexCaches(idx_);
1505 }
1506
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001507 art::ObjPtr<art::mirror::Class> GetNewClassObject() const
1508 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1509 return holder_.GetNewClassObject(idx_);
1510 }
1511
Alex Light986914b2019-11-19 01:12:25 +00001512 art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>> GetOldInstanceObjects() const
1513 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1514 return holder_.GetOldInstanceObjects(idx_);
1515 }
1516 art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>> GetNewInstanceObjects() const
1517 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1518 return holder_.GetNewInstanceObjects(idx_);
1519 }
Alex Light270db1c2019-12-03 12:20:01 +00001520 art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>> GetOldClasses() const
1521 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1522 return holder_.GetOldClasses(idx_);
1523 }
1524 art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>> GetNewClasses() const
1525 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1526 return holder_.GetNewClasses(idx_);
1527 }
Alex Lightfb537082019-12-10 14:38:34 -08001528 bool IsInitialized() const REQUIRES_SHARED(art::Locks::mutator_lock_) {
1529 return holder_.IsInitialized(idx_);
1530 }
1531 bool IsActuallyStructural() const REQUIRES_SHARED(art::Locks::mutator_lock_) {
1532 return holder_.IsActuallyStructural(idx_);
1533 }
1534 bool IsInitialStructural() const REQUIRES_SHARED(art::Locks::mutator_lock_) {
1535 return holder_.IsInitialStructural(idx_);
1536 }
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001537 int32_t GetIndex() const {
1538 return idx_;
1539 }
1540
1541 void SetSourceClassLoader(art::mirror::ClassLoader* loader)
1542 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1543 holder_.SetSourceClassLoader(idx_, loader);
1544 }
Vladimir Markod93e3742018-07-18 10:58:13 +01001545 void SetJavaDexFile(art::ObjPtr<art::mirror::Object> dexfile)
1546 REQUIRES_SHARED(art::Locks::mutator_lock_) {
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001547 holder_.SetJavaDexFile(idx_, dexfile);
1548 }
Vladimir Markod93e3742018-07-18 10:58:13 +01001549 void SetNewDexFileCookie(art::ObjPtr<art::mirror::LongArray> cookie)
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001550 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1551 holder_.SetNewDexFileCookie(idx_, cookie);
1552 }
Vladimir Markod93e3742018-07-18 10:58:13 +01001553 void SetNewDexCache(art::ObjPtr<art::mirror::DexCache> cache)
1554 REQUIRES_SHARED(art::Locks::mutator_lock_) {
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001555 holder_.SetNewDexCache(idx_, cache);
1556 }
Vladimir Markod93e3742018-07-18 10:58:13 +01001557 void SetMirrorClass(art::ObjPtr<art::mirror::Class> klass)
1558 REQUIRES_SHARED(art::Locks::mutator_lock_) {
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001559 holder_.SetMirrorClass(idx_, klass);
1560 }
Vladimir Markod93e3742018-07-18 10:58:13 +01001561 void SetOriginalDexFile(art::ObjPtr<art::mirror::Object> bytes)
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001562 REQUIRES_SHARED(art::Locks::mutator_lock_) {
Alex Light2f814aa2017-03-24 15:21:34 +00001563 holder_.SetOriginalDexFile(idx_, bytes);
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001564 }
Vladimir Markod93e3742018-07-18 10:58:13 +01001565 void SetOldObsoleteMethods(art::ObjPtr<art::mirror::PointerArray> methods)
Alex Light1e3926a2017-04-07 10:38:06 -07001566 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1567 holder_.SetOldObsoleteMethods(idx_, methods);
1568 }
Vladimir Markod93e3742018-07-18 10:58:13 +01001569 void SetOldDexCaches(art::ObjPtr<art::mirror::ObjectArray<art::mirror::DexCache>> caches)
Alex Light1e3926a2017-04-07 10:38:06 -07001570 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1571 holder_.SetOldDexCaches(idx_, caches);
1572 }
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001573 void SetNewClassObject(art::ObjPtr<art::mirror::Class> klass)
1574 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1575 holder_.SetNewClassObject(idx_, klass);
1576 }
Alex Light986914b2019-11-19 01:12:25 +00001577 void SetOldInstanceObjects(art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>> objs)
1578 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1579 holder_.SetOldInstanceObjects(idx_, objs);
1580 }
1581 void SetNewInstanceObjects(art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>> objs)
1582 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1583 holder_.SetNewInstanceObjects(idx_, objs);
1584 }
Alex Light270db1c2019-12-03 12:20:01 +00001585 void SetOldClasses(art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>> klasses)
1586 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1587 holder_.SetOldClasses(idx_, klasses);
1588 }
1589 void SetNewClasses(art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>> klasses)
1590 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1591 holder_.SetNewClasses(idx_, klasses);
1592 }
Alex Lightfb537082019-12-10 14:38:34 -08001593 void SetInitialized() REQUIRES_SHARED(art::Locks::mutator_lock_) {
1594 holder_.SetInitialized(idx_);
1595 }
1596 void SetActuallyStructural() REQUIRES_SHARED(art::Locks::mutator_lock_) {
1597 holder_.SetActuallyStructural(idx_);
1598 }
1599 void SetInitialStructural() REQUIRES_SHARED(art::Locks::mutator_lock_) {
1600 holder_.SetInitialStructural(idx_);
1601 }
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001602
1603 private:
1604 int32_t idx_;
1605 RedefinitionDataHolder& holder_;
1606};
1607
1608RedefinitionDataIter RedefinitionDataHolder::begin() {
1609 return RedefinitionDataIter(0, *this);
1610}
1611
1612RedefinitionDataIter RedefinitionDataHolder::end() {
1613 return RedefinitionDataIter(Length(), *this);
1614}
1615
1616bool Redefiner::ClassRedefinition::CheckVerification(const RedefinitionDataIter& iter) {
Alex Light8c889d22017-02-06 13:58:27 -08001617 DCHECK_EQ(dex_file_->NumClassDefs(), 1u);
Nicolas Geoffray7744b692021-07-06 16:19:32 +01001618 art::StackHandleScope<3> hs(driver_->self_);
Alex Light8c889d22017-02-06 13:58:27 -08001619 std::string error;
1620 // TODO Make verification log level lower
Andreas Gampe6d7abbd2017-04-24 13:19:09 -07001621 art::verifier::FailureKind failure =
Andreas Gampea43ba3d2019-03-13 15:49:20 -07001622 art::verifier::ClassVerifier::VerifyClass(driver_->self_,
Nicolas Geoffray5b0b2e12021-03-19 14:48:40 +00001623 /*verifier_deps=*/nullptr,
Andreas Gampea43ba3d2019-03-13 15:49:20 -07001624 dex_file_.get(),
Nicolas Geoffray7744b692021-07-06 16:19:32 +01001625 hs.NewHandle(iter.GetNewClassObject() != nullptr
1626 ? iter.GetNewClassObject()
1627 : iter.GetMirrorClass()),
Andreas Gampea43ba3d2019-03-13 15:49:20 -07001628 hs.NewHandle(iter.GetNewDexCache()),
1629 hs.NewHandle(GetClassLoader()),
1630 /*class_def=*/ dex_file_->GetClassDef(0),
1631 /*callbacks=*/ nullptr,
Andreas Gampea43ba3d2019-03-13 15:49:20 -07001632 /*log_level=*/
1633 art::verifier::HardFailLogMode::kLogWarning,
1634 art::Runtime::Current()->GetTargetSdkVersion(),
1635 &error);
Nicolas Geoffray7744b692021-07-06 16:19:32 +01001636 if (failure == art::verifier::FailureKind::kHardFailure) {
1637 RecordFailure(ERR(FAILS_VERIFICATION), "Failed to verify class. Error was: " + error);
1638 return false;
Alex Light8c889d22017-02-06 13:58:27 -08001639 }
Nicolas Geoffray7744b692021-07-06 16:19:32 +01001640 return true;
Alex Light8c889d22017-02-06 13:58:27 -08001641}
1642
Alex Light1babae02017-02-01 15:35:34 -08001643// Looks through the previously allocated cookies to see if we need to update them with another new
1644// dexfile. This is so that even if multiple classes with the same classloader are redefined at
1645// once they are all added to the classloader.
1646bool Redefiner::ClassRedefinition::AllocateAndRememberNewDexFileCookie(
Alex Light1babae02017-02-01 15:35:34 -08001647 art::Handle<art::mirror::ClassLoader> source_class_loader,
1648 art::Handle<art::mirror::Object> dex_file_obj,
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001649 /*out*/RedefinitionDataIter* cur_data) {
Alex Light1babae02017-02-01 15:35:34 -08001650 art::StackHandleScope<2> hs(driver_->self_);
1651 art::MutableHandle<art::mirror::LongArray> old_cookie(
1652 hs.NewHandle<art::mirror::LongArray>(nullptr));
1653 bool has_older_cookie = false;
1654 // See if we already have a cookie that a previous redefinition got from the same classloader.
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001655 for (auto old_data = cur_data->GetHolder().begin(); old_data != *cur_data; ++old_data) {
1656 if (old_data.GetSourceClassLoader() == source_class_loader.Get()) {
Alex Light1babae02017-02-01 15:35:34 -08001657 // Since every instance of this classloader should have the same cookie associated with it we
1658 // can stop looking here.
1659 has_older_cookie = true;
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001660 old_cookie.Assign(old_data.GetNewDexFileCookie());
Alex Light1babae02017-02-01 15:35:34 -08001661 break;
1662 }
1663 }
1664 if (old_cookie.IsNull()) {
1665 // No older cookie. Get it directly from the dex_file_obj
1666 // We should not have seen this classloader elsewhere.
1667 CHECK(!has_older_cookie);
1668 old_cookie.Assign(ClassLoaderHelper::GetDexFileCookie(dex_file_obj));
1669 }
1670 // Use the old cookie to generate the new one with the new DexFile* added in.
1671 art::Handle<art::mirror::LongArray>
1672 new_cookie(hs.NewHandle(ClassLoaderHelper::AllocateNewDexFileCookie(driver_->self_,
1673 old_cookie,
1674 dex_file_.get())));
1675 // Make sure the allocation worked.
1676 if (new_cookie.IsNull()) {
1677 return false;
1678 }
1679
1680 // Save the cookie.
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001681 cur_data->SetNewDexFileCookie(new_cookie.Get());
Alex Light1babae02017-02-01 15:35:34 -08001682 // If there are other copies of this same classloader we need to make sure that we all have the
1683 // same cookie.
1684 if (has_older_cookie) {
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001685 for (auto old_data = cur_data->GetHolder().begin(); old_data != *cur_data; ++old_data) {
Alex Light1babae02017-02-01 15:35:34 -08001686 // We will let the GC take care of the cookie we allocated for this one.
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001687 if (old_data.GetSourceClassLoader() == source_class_loader.Get()) {
1688 old_data.SetNewDexFileCookie(new_cookie.Get());
Alex Light1babae02017-02-01 15:35:34 -08001689 }
1690 }
1691 }
1692
1693 return true;
1694}
1695
Alex Lightfb537082019-12-10 14:38:34 -08001696bool CompareClasses(art::ObjPtr<art::mirror::Class> l, art::ObjPtr<art::mirror::Class> r)
1697 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1698 auto parents = [](art::ObjPtr<art::mirror::Class> c) REQUIRES_SHARED(art::Locks::mutator_lock_) {
1699 uint32_t res = 0;
1700 while (!c->IsObjectClass()) {
1701 res++;
1702 c = c->GetSuperClass();
1703 }
1704 return res;
1705 };
1706 return parents(l.Ptr()) < parents(r.Ptr());
1707}
1708
Alex Light986914b2019-11-19 01:12:25 +00001709bool Redefiner::ClassRedefinition::CollectAndCreateNewInstances(
1710 /*out*/ RedefinitionDataIter* cur_data) {
Alex Lightfb537082019-12-10 14:38:34 -08001711 if (!cur_data->IsInitialStructural()) {
1712 // An earlier structural redefinition already remade all the instances.
Alex Light986914b2019-11-19 01:12:25 +00001713 return true;
1714 }
Alex Lightfb537082019-12-10 14:38:34 -08001715 art::gc::Heap* heap = driver_->runtime_->GetHeap();
Alex Light986914b2019-11-19 01:12:25 +00001716 art::VariableSizedHandleScope hs(driver_->self_);
1717 art::Handle<art::mirror::Class> old_klass(hs.NewHandle(cur_data->GetMirrorClass()));
1718 std::vector<art::Handle<art::mirror::Object>> old_instances;
Alex Light986914b2019-11-19 01:12:25 +00001719 auto is_instance = [&](art::mirror::Object* obj) REQUIRES_SHARED(art::Locks::mutator_lock_) {
Alex Light270db1c2019-12-03 12:20:01 +00001720 return obj->InstanceOf(old_klass.Get());
Alex Light986914b2019-11-19 01:12:25 +00001721 };
1722 heap->VisitObjects([&](art::mirror::Object* obj) REQUIRES_SHARED(art::Locks::mutator_lock_) {
1723 if (is_instance(obj)) {
Alex Light986914b2019-11-19 01:12:25 +00001724 old_instances.push_back(hs.NewHandle(obj));
1725 }
1726 });
1727 VLOG(plugin) << "Collected " << old_instances.size() << " instances to recreate!";
Alex Light270db1c2019-12-03 12:20:01 +00001728 art::Handle<art::mirror::ObjectArray<art::mirror::Class>> old_classes_arr(
Alex Lightfb537082019-12-10 14:38:34 -08001729 hs.NewHandle(cur_data->GetOldClasses()));
Alex Light270db1c2019-12-03 12:20:01 +00001730 art::Handle<art::mirror::ObjectArray<art::mirror::Class>> new_classes_arr(
Alex Lightfb537082019-12-10 14:38:34 -08001731 hs.NewHandle(cur_data->GetNewClasses()));
Alex Light3f4041b2020-01-09 12:59:22 -08001732 DCHECK_EQ(old_classes_arr->GetLength(), new_classes_arr->GetLength());
Alex Lightbaf938f2020-01-10 10:40:46 -08001733 DCHECK_GT(old_classes_arr->GetLength(), 0);
Alex Light986914b2019-11-19 01:12:25 +00001734 art::Handle<art::mirror::Class> obj_array_class(
1735 hs.NewHandle(art::GetClassRoot<art::mirror::ObjectArray<art::mirror::Object>>(
1736 driver_->runtime_->GetClassLinker())));
1737 art::Handle<art::mirror::ObjectArray<art::mirror::Object>> old_instances_arr(
1738 hs.NewHandle(art::mirror::ObjectArray<art::mirror::Object>::Alloc(
1739 driver_->self_, obj_array_class.Get(), old_instances.size())));
1740 if (old_instances_arr.IsNull()) {
1741 driver_->self_->AssertPendingOOMException();
1742 driver_->self_->ClearException();
1743 RecordFailure(ERR(OUT_OF_MEMORY), "Could not allocate old_instance arrays!");
1744 return false;
1745 }
1746 for (uint32_t i = 0; i < old_instances.size(); ++i) {
1747 old_instances_arr->Set(i, old_instances[i].Get());
1748 }
1749 cur_data->SetOldInstanceObjects(old_instances_arr.Get());
1750
1751 art::Handle<art::mirror::ObjectArray<art::mirror::Object>> new_instances_arr(
1752 hs.NewHandle(art::mirror::ObjectArray<art::mirror::Object>::Alloc(
1753 driver_->self_, obj_array_class.Get(), old_instances.size())));
1754 if (new_instances_arr.IsNull()) {
1755 driver_->self_->AssertPendingOOMException();
1756 driver_->self_->ClearException();
1757 RecordFailure(ERR(OUT_OF_MEMORY), "Could not allocate new_instance arrays!");
1758 return false;
1759 }
Alex Light270db1c2019-12-03 12:20:01 +00001760 for (auto pair : art::ZipCount(art::IterationRange(old_instances.begin(), old_instances.end()))) {
1761 art::Handle<art::mirror::Object> hinstance(pair.first);
1762 int32_t i = pair.second;
1763 auto iterator = art::ZipLeft(old_classes_arr.Iterate<art::mirror::Class>(),
1764 new_classes_arr.Iterate<art::mirror::Class>());
Alex Lightbaf938f2020-01-10 10:40:46 -08001765 auto it = std::find_if(iterator.begin(),
1766 iterator.end(),
1767 [&](auto class_pair) REQUIRES_SHARED(art::Locks::mutator_lock_) {
1768 return class_pair.first == hinstance->GetClass();
1769 });
1770 DCHECK(it != iterator.end()) << "Unable to find class pair for "
1771 << hinstance->GetClass()->PrettyClass() << " (instance " << i
1772 << ")";
1773 auto [_, new_type] = *it;
Alex Light2f494282020-01-07 22:53:09 +00001774 // Make sure when allocating the new instance we don't add it's finalizer since we will directly
1775 // replace the old object in the finalizer reference. If we added it here to we would call
1776 // finalize twice.
1777 // NB If a type is changed from being non-finalizable to finalizable the finalizers on any
1778 // objects created before the redefine will never be called. This is (sort of) allowable by
1779 // the spec and greatly simplifies implementation.
1780 // TODO Make it so we will always call all finalizers, even if the object when it was created
1781 // wasn't finalizable. To do this we need to be careful of handling failure correctly and making
1782 // sure that objects aren't finalized multiple times and that instances of failed redefinitions
1783 // aren't finalized.
1784 art::ObjPtr<art::mirror::Object> new_instance(
1785 new_type->Alloc</*kIsInstrumented=*/true,
1786 art::mirror::Class::AddFinalizer::kNoAddFinalizer,
1787 /*kCheckAddFinalizer=*/false>(
1788 driver_->self_, driver_->runtime_->GetHeap()->GetCurrentAllocator()));
Alex Light986914b2019-11-19 01:12:25 +00001789 if (new_instance.IsNull()) {
1790 driver_->self_->AssertPendingOOMException();
1791 driver_->self_->ClearException();
1792 std::string msg(
1793 StringPrintf("Could not allocate instance %d of %zu", i, old_instances.size()));
1794 RecordFailure(ERR(OUT_OF_MEMORY), msg);
1795 return false;
1796 }
1797 new_instances_arr->Set(i, new_instance);
1798 }
1799 cur_data->SetNewInstanceObjects(new_instances_arr.Get());
1800 return true;
1801}
1802
Alex Lightfb537082019-12-10 14:38:34 -08001803bool Redefiner::ClassRedefinition::FinishRemainingCommonAllocations(
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001804 /*out*/RedefinitionDataIter* cur_data) {
Alex Light7916f202017-01-27 09:00:15 -08001805 art::ScopedObjectAccessUnchecked soa(driver_->self_);
Alex Lightfb537082019-12-10 14:38:34 -08001806 art::StackHandleScope<2> hs(driver_->self_);
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001807 cur_data->SetMirrorClass(GetMirrorClass());
Alex Lighta7e38d82017-01-19 14:57:28 -08001808 // This shouldn't allocate
1809 art::Handle<art::mirror::ClassLoader> loader(hs.NewHandle(GetClassLoader()));
Alex Light7916f202017-01-27 09:00:15 -08001810 // The bootclasspath is handled specially so it doesn't have a j.l.DexFile.
1811 if (!art::ClassLinker::IsBootClassLoader(soa, loader.Get())) {
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001812 cur_data->SetSourceClassLoader(loader.Get());
Alex Light7916f202017-01-27 09:00:15 -08001813 art::Handle<art::mirror::Object> dex_file_obj(hs.NewHandle(
1814 ClassLoaderHelper::FindSourceDexFileObject(driver_->self_, loader)));
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001815 cur_data->SetJavaDexFile(dex_file_obj.Get());
Andreas Gampefa4333d2017-02-14 11:10:34 -08001816 if (dex_file_obj == nullptr) {
Alex Light7916f202017-01-27 09:00:15 -08001817 RecordFailure(ERR(INTERNAL), "Unable to find dex file!");
1818 return false;
1819 }
Alex Light1babae02017-02-01 15:35:34 -08001820 // Allocate the new dex file cookie.
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001821 if (!AllocateAndRememberNewDexFileCookie(loader, dex_file_obj, cur_data)) {
Alex Light7916f202017-01-27 09:00:15 -08001822 driver_->self_->AssertPendingOOMException();
1823 driver_->self_->ClearException();
1824 RecordFailure(ERR(OUT_OF_MEMORY), "Unable to allocate dex file array for class loader");
1825 return false;
1826 }
Alex Lighta7e38d82017-01-19 14:57:28 -08001827 }
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001828 cur_data->SetNewDexCache(CreateNewDexCache(loader));
1829 if (cur_data->GetNewDexCache() == nullptr) {
Vladimir Markocd556b02017-02-03 11:47:34 +00001830 driver_->self_->AssertPendingException();
Alex Lighta7e38d82017-01-19 14:57:28 -08001831 driver_->self_->ClearException();
1832 RecordFailure(ERR(OUT_OF_MEMORY), "Unable to allocate DexCache");
1833 return false;
1834 }
1835
1836 // We won't always need to set this field.
Alex Light2f814aa2017-03-24 15:21:34 +00001837 cur_data->SetOriginalDexFile(AllocateOrGetOriginalDexFile());
1838 if (cur_data->GetOriginalDexFile() == nullptr) {
Alex Lighta7e38d82017-01-19 14:57:28 -08001839 driver_->self_->AssertPendingOOMException();
1840 driver_->self_->ClearException();
1841 RecordFailure(ERR(OUT_OF_MEMORY), "Unable to allocate array for original dex file");
1842 return false;
1843 }
Alex Lightfb537082019-12-10 14:38:34 -08001844 return true;
1845}
1846
1847bool Redefiner::ClassRedefinition::FinishNewClassAllocations(RedefinitionDataHolder &holder,
1848 RedefinitionDataIter *cur_data) {
1849 if (cur_data->IsInitialized() || !cur_data->IsActuallyStructural()) {
1850 cur_data->SetInitialized();
1851 return true;
1852 }
1853
1854 art::VariableSizedHandleScope hs(driver_->self_);
1855 // If we weren't the lowest structural redef the superclass would have already initialized us.
1856 CHECK(IsStructuralRedefinition());
1857 CHECK(cur_data->IsInitialStructural()) << "Should have already been initialized by supertype";
1858 auto setup_single_redefinition =
1859 [this](RedefinitionDataIter* data, art::Handle<art::mirror::Class> super_class)
1860 REQUIRES_SHARED(art::Locks::mutator_lock_) -> art::ObjPtr<art::mirror::Class> {
1861 art::StackHandleScope<3> chs(driver_->self_);
1862 art::Handle<art::mirror::Class> nc(
1863 chs.NewHandle(AllocateNewClassObject(chs.NewHandle(data->GetMirrorClass()),
1864 super_class,
1865 chs.NewHandle(data->GetNewDexCache()),
1866 /*dex_class_def_index*/ 0)));
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001867 if (nc.IsNull()) {
Alex Lightfb537082019-12-10 14:38:34 -08001868 return nullptr;
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001869 }
1870
Alex Lightfb537082019-12-10 14:38:34 -08001871 data->SetNewClassObject(nc.Get());
Alex Lightfb537082019-12-10 14:38:34 -08001872 data->SetInitialized();
1873 return nc.Get();
1874 };
1875
1876 std::vector<art::Handle<art::mirror::Class>> old_types;
1877 {
1878 art::gc::Heap* heap = driver_->runtime_->GetHeap();
1879 art::Handle<art::mirror::Class>
1880 old_klass(hs.NewHandle(cur_data->GetMirrorClass()));
1881 if (setup_single_redefinition(cur_data, hs.NewHandle(old_klass->GetSuperClass())).IsNull()) {
1882 return false;
1883 }
1884 auto is_subtype = [&](art::mirror::Object* obj) REQUIRES_SHARED(art::Locks::mutator_lock_) {
1885 // We've already waited for class defines to be finished and paused them. All classes should be
1886 // either resolved or error. We don't need to do anything with error classes, since they cannot
1887 // be accessed in any observable way.
1888 return obj->IsClass() && obj->AsClass()->IsResolved() &&
1889 old_klass->IsAssignableFrom(obj->AsClass());
1890 };
1891 heap->VisitObjects([&](art::mirror::Object* obj) REQUIRES_SHARED(art::Locks::mutator_lock_) {
1892 if (is_subtype(obj)) {
1893 old_types.push_back(hs.NewHandle(obj->AsClass()));
1894 }
1895 });
Alex Lightbaf938f2020-01-10 10:40:46 -08001896 DCHECK_GT(old_types.size(), 0u) << "Expected to find at least old_klass!";
Alex Lightfb537082019-12-10 14:38:34 -08001897 VLOG(plugin) << "Found " << old_types.size() << " types that are/are subtypes of "
1898 << old_klass->PrettyClass();
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001899 }
Alex Lightfb537082019-12-10 14:38:34 -08001900
1901 art::Handle<art::mirror::Class> cls_array_class(
1902 hs.NewHandle(art::GetClassRoot<art::mirror::ObjectArray<art::mirror::Class>>(
1903 driver_->runtime_->GetClassLinker())));
1904 art::Handle<art::mirror::ObjectArray<art::mirror::Class>> old_classes_arr(
1905 hs.NewHandle(art::mirror::ObjectArray<art::mirror::Class>::Alloc(
1906 driver_->self_, cls_array_class.Get(), old_types.size())));
1907 if (old_classes_arr.IsNull()) {
1908 driver_->self_->AssertPendingOOMException();
1909 driver_->self_->ClearException();
1910 RecordFailure(ERR(OUT_OF_MEMORY), "Could not allocate old_classes arrays!");
1911 return false;
1912 }
1913 // Sort the old_types topologically.
1914 {
1915 art::ScopedAssertNoThreadSuspension sants("Sort classes");
1916 // Sort them by the distance to the base-class. This ensures that any class occurs before any of
1917 // its subtypes.
1918 std::sort(old_types.begin(),
1919 old_types.end(),
1920 [](auto& l, auto& r) REQUIRES_SHARED(art::Locks::mutator_lock_) {
1921 return CompareClasses(l.Get(), r.Get());
1922 });
1923 }
1924 for (uint32_t i = 0; i < old_types.size(); ++i) {
Alex Lightbaf938f2020-01-10 10:40:46 -08001925 DCHECK(!old_types[i].IsNull()) << i;
Alex Lightfb537082019-12-10 14:38:34 -08001926 old_classes_arr->Set(i, old_types[i].Get());
1927 }
1928 cur_data->SetOldClasses(old_classes_arr.Get());
Alex Lightbaf938f2020-01-10 10:40:46 -08001929 DCHECK_GT(old_classes_arr->GetLength(), 0);
Alex Lightfb537082019-12-10 14:38:34 -08001930
1931 art::Handle<art::mirror::ObjectArray<art::mirror::Class>> new_classes_arr(
1932 hs.NewHandle(art::mirror::ObjectArray<art::mirror::Class>::Alloc(
1933 driver_->self_, cls_array_class.Get(), old_types.size())));
1934 if (new_classes_arr.IsNull()) {
1935 driver_->self_->AssertPendingOOMException();
1936 driver_->self_->ClearException();
1937 RecordFailure(ERR(OUT_OF_MEMORY), "Could not allocate new_classes arrays!");
1938 return false;
1939 }
1940
1941 art::MutableHandle<art::mirror::DexCache> dch(hs.NewHandle<art::mirror::DexCache>(nullptr));
1942 art::MutableHandle<art::mirror::Class> superclass(hs.NewHandle<art::mirror::Class>(nullptr));
1943 for (size_t i = 0; i < old_types.size(); i++) {
1944 art::Handle<art::mirror::Class>& old_type = old_types[i];
1945 if (old_type.Get() == cur_data->GetMirrorClass()) {
1946 CHECK_EQ(i, 0u) << "original class not at index 0. Bad sort!";
1947 new_classes_arr->Set(i, cur_data->GetNewClassObject());
1948 continue;
1949 } else {
1950 auto old_super = std::find_if(old_types.begin(),
1951 old_types.begin() + i,
1952 [&](art::Handle<art::mirror::Class>& v)
1953 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1954 return v.Get() == old_type->GetSuperClass();
1955 });
1956 // Only the GetMirrorClass should not be in this list.
1957 CHECK(old_super != old_types.begin() + i)
1958 << "from first " << i << " could not find super of " << old_type->PrettyClass()
1959 << " expected to find " << old_type->GetSuperClass()->PrettyClass();
1960 superclass.Assign(new_classes_arr->Get(std::distance(old_types.begin(), old_super)));
1961 auto new_redef = std::find_if(
1962 *cur_data + 1, holder.end(), [&](auto it) REQUIRES_SHARED(art::Locks::mutator_lock_) {
1963 return it.GetMirrorClass() == old_type.Get();
1964 });
1965 art::ObjPtr<art::mirror::Class> new_type;
1966 if (new_redef == holder.end()) {
1967 // We aren't also redefining this subclass. Just allocate a new class and continue.
1968 dch.Assign(old_type->GetDexCache());
1969 new_type =
1970 AllocateNewClassObject(old_type, superclass, dch, old_type->GetDexClassDefIndex());
1971 } else {
1972 // This subclass is also being redefined. We need to use its new dex-file to load the new
1973 // class.
1974 CHECK(new_redef.IsActuallyStructural());
1975 CHECK(!new_redef.IsInitialStructural());
1976 new_type = setup_single_redefinition(&new_redef, superclass);
1977 }
1978 if (new_type == nullptr) {
1979 VLOG(plugin) << "Failed to load new version of class " << old_type->PrettyClass()
1980 << " for structural redefinition!";
1981 return false;
1982 }
1983 new_classes_arr->Set(i, new_type);
1984 }
1985 }
1986 cur_data->SetNewClasses(new_classes_arr.Get());
Alex Lighta7e38d82017-01-19 14:57:28 -08001987 return true;
1988}
1989
Alex Light270db1c2019-12-03 12:20:01 +00001990uint32_t Redefiner::ClassRedefinition::GetNewClassSize(art::ClassAccessor& accessor) {
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001991 uint32_t num_8bit_static_fields = 0;
1992 uint32_t num_16bit_static_fields = 0;
1993 uint32_t num_32bit_static_fields = 0;
1994 uint32_t num_64bit_static_fields = 0;
1995 uint32_t num_ref_static_fields = 0;
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001996 for (const art::ClassAccessor::Field& f : accessor.GetStaticFields()) {
Alex Light270db1c2019-12-03 12:20:01 +00001997 std::string_view desc(accessor.GetDexFile().GetFieldTypeDescriptor(
1998 accessor.GetDexFile().GetFieldId(f.GetIndex())));
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001999 if (desc[0] == 'L' || desc[0] == '[') {
2000 num_ref_static_fields++;
2001 } else if (desc == "Z" || desc == "B") {
2002 num_8bit_static_fields++;
2003 } else if (desc == "C" || desc == "S") {
2004 num_16bit_static_fields++;
2005 } else if (desc == "I" || desc == "F") {
2006 num_32bit_static_fields++;
2007 } else if (desc == "J" || desc == "D") {
2008 num_64bit_static_fields++;
2009 } else {
2010 LOG(FATAL) << "Unknown type descriptor! " << desc;
2011 }
2012 }
2013
Alex Light270db1c2019-12-03 12:20:01 +00002014 return art::mirror::Class::ComputeClassSize(/*has_embedded_vtable=*/ false,
2015 /*num_vtable_entries=*/ 0,
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002016 num_8bit_static_fields,
2017 num_16bit_static_fields,
2018 num_32bit_static_fields,
2019 num_64bit_static_fields,
2020 num_ref_static_fields,
2021 art::kRuntimePointerSize);
2022}
2023
2024art::ObjPtr<art::mirror::Class>
2025Redefiner::ClassRedefinition::AllocateNewClassObject(art::Handle<art::mirror::DexCache> cache) {
Alex Light270db1c2019-12-03 12:20:01 +00002026 art::StackHandleScope<2> hs(driver_->self_);
2027 art::Handle<art::mirror::Class> old_class(hs.NewHandle(GetMirrorClass()));
2028 art::Handle<art::mirror::Class> super_class(hs.NewHandle(old_class->GetSuperClass()));
2029 return AllocateNewClassObject(old_class, super_class, cache, /*dex_class_def_index*/0);
2030}
2031
2032art::ObjPtr<art::mirror::Class> Redefiner::ClassRedefinition::AllocateNewClassObject(
2033 art::Handle<art::mirror::Class> old_class,
2034 art::Handle<art::mirror::Class> super_class,
2035 art::Handle<art::mirror::DexCache> cache,
2036 uint16_t dex_class_def_index) {
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002037 // This is a stripped down DefineClass. We don't want to use DefineClass directly because it needs
2038 // to perform a lot of extra steps to tell the ClassTable and the jit and everything about a new
2039 // class. For now we will need to rely on our tests catching any issues caused by changes in how
2040 // class_linker sets up classes.
2041 // TODO Unify/move this into ClassLinker maybe.
Alex Light270db1c2019-12-03 12:20:01 +00002042 art::StackHandleScope<3> hs(driver_->self_);
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002043 art::ClassLinker* linker = driver_->runtime_->GetClassLinker();
Alex Light270db1c2019-12-03 12:20:01 +00002044 const art::DexFile* dex_file = cache->GetDexFile();
2045 art::ClassAccessor accessor(*dex_file, dex_class_def_index);
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002046 art::Handle<art::mirror::Class> new_class(hs.NewHandle(linker->AllocClass(
Alex Light270db1c2019-12-03 12:20:01 +00002047 driver_->self_, GetNewClassSize(accessor))));
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002048 if (new_class.IsNull()) {
2049 driver_->self_->AssertPendingOOMException();
Alex Light270db1c2019-12-03 12:20:01 +00002050 RecordFailure(
2051 ERR(OUT_OF_MEMORY),
2052 "Unable to allocate class object for redefinition of " + old_class->PrettyClass());
2053 driver_->self_->ClearException();
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002054 return nullptr;
2055 }
2056 new_class->SetDexCache(cache.Get());
Alex Light270db1c2019-12-03 12:20:01 +00002057 linker->SetupClass(*dex_file,
2058 dex_file->GetClassDef(dex_class_def_index),
2059 new_class,
2060 old_class->GetClassLoader());
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002061
2062 // Make sure we are ready for linking. The lock isn't really needed since this isn't visible to
2063 // other threads but the linker expects it.
2064 art::ObjectLock<art::mirror::Class> lock(driver_->self_, new_class);
2065 new_class->SetClinitThreadId(driver_->self_->GetTid());
2066 // Make sure we have a valid empty iftable even if there are errors.
2067 new_class->SetIfTable(art::GetClassRoot<art::mirror::Object>(linker)->GetIfTable());
Alex Light270db1c2019-12-03 12:20:01 +00002068 linker->LoadClass(
2069 driver_->self_, *dex_file, dex_file->GetClassDef(dex_class_def_index), new_class);
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002070 // NB. We know the interfaces and supers didn't change! :)
2071 art::MutableHandle<art::mirror::Class> linked_class(hs.NewHandle<art::mirror::Class>(nullptr));
2072 art::Handle<art::mirror::ObjectArray<art::mirror::Class>> proxy_ifaces(
2073 hs.NewHandle<art::mirror::ObjectArray<art::mirror::Class>>(nullptr));
2074 // No changing hierarchy so everything is loaded.
Alex Light270db1c2019-12-03 12:20:01 +00002075 new_class->SetSuperClass(super_class.Get());
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002076 art::mirror::Class::SetStatus(new_class, art::ClassStatus::kLoaded, nullptr);
2077 if (!linker->LinkClass(driver_->self_, nullptr, new_class, proxy_ifaces, &linked_class)) {
Alex Light270db1c2019-12-03 12:20:01 +00002078 std::ostringstream oss;
2079 oss << "failed to link class due to "
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002080 << (driver_->self_->IsExceptionPending() ? driver_->self_->GetException()->Dump()
2081 : " unknown");
Alex Light270db1c2019-12-03 12:20:01 +00002082 RecordFailure(ERR(INTERNAL), oss.str());
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002083 driver_->self_->ClearException();
2084 return nullptr;
2085 }
Alex Light270db1c2019-12-03 12:20:01 +00002086 // Everything is already resolved.
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002087 art::ObjectLock<art::mirror::Class> objlock(driver_->self_, linked_class);
Alex Lightfb119572019-09-18 15:04:53 -07002088 // Mark the class as initialized.
Alex Light270db1c2019-12-03 12:20:01 +00002089 CHECK(old_class->IsResolved())
2090 << "Attempting to redefine an unresolved class " << old_class->PrettyClass()
Alex Lightfb119572019-09-18 15:04:53 -07002091 << " status=" << old_class->GetStatus();
Alex Light270db1c2019-12-03 12:20:01 +00002092 CHECK(linked_class->IsResolved());
Alex Light270db1c2019-12-03 12:20:01 +00002093 if (old_class->ShouldSkipHiddenApiChecks()) {
2094 // Match skip hiddenapi flag
2095 linked_class->SetSkipHiddenApiChecks();
2096 }
2097 if (old_class->IsInitialized()) {
2098 // We already verified the class earlier. No need to do it again.
2099 linker->ForceClassInitialized(driver_->self_, linked_class);
2100 } else if (old_class->GetStatus() > linked_class->GetStatus()) {
2101 // We want to match the old status.
2102 art::mirror::Class::SetStatus(linked_class, old_class->GetStatus(), driver_->self_);
2103 }
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002104 // Make sure we have ext-data space for method & field ids. We won't know if we need them until
2105 // it's too late to create them.
2106 // TODO We might want to remove these arrays if they're not needed.
Alex Lightbc19b752019-12-02 18:54:13 +00002107 if (!art::mirror::Class::EnsureInstanceFieldIds(linked_class) ||
2108 !art::mirror::Class::EnsureStaticFieldIds(linked_class) ||
2109 !art::mirror::Class::EnsureMethodIds(linked_class)) {
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002110 driver_->self_->AssertPendingOOMException();
2111 driver_->self_->ClearException();
Alex Light270db1c2019-12-03 12:20:01 +00002112 RecordFailure(
2113 ERR(OUT_OF_MEMORY),
2114 "Unable to allocate jni-id arrays for redefinition of " + old_class->PrettyClass());
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002115 return nullptr;
2116 }
2117 // Finish setting up methods.
2118 linked_class->VisitMethods([&](art::ArtMethod* m) REQUIRES_SHARED(art::Locks::mutator_lock_) {
Nicolas Geoffrayc8a694d2022-01-17 17:12:38 +00002119 driver_->runtime_->GetInstrumentation()->InitializeMethodsCode(m, /* aot_code= */ nullptr);
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002120 m->SetNotIntrinsic();
2121 DCHECK(m->IsCopied() || m->GetDeclaringClass() == linked_class.Get())
2122 << m->PrettyMethod()
2123 << " m->GetDeclaringClass(): " << m->GetDeclaringClass()->PrettyClass()
2124 << " != linked_class.Get(): " << linked_class->PrettyClass();
2125 }, art::kRuntimePointerSize);
2126 if (art::kIsDebugBuild) {
2127 linked_class->VisitFields([&](art::ArtField* f) REQUIRES_SHARED(art::Locks::mutator_lock_) {
2128 DCHECK_EQ(f->GetDeclaringClass(), linked_class.Get());
2129 });
2130 }
Alex Light270db1c2019-12-03 12:20:01 +00002131 // Reset ClinitThreadId back to the thread that loaded the old class. This is needed if we are in
2132 // the middle of initializing a class.
2133 linked_class->SetClinitThreadId(old_class->GetClinitThreadId());
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002134 return linked_class.Get();
2135}
2136
Alex Lighta26e3492017-06-27 17:55:37 -07002137void Redefiner::ClassRedefinition::UnregisterJvmtiBreakpoints() {
Vladimir Marko4617d582019-03-28 13:48:31 +00002138 BreakpointUtil::RemoveBreakpointsInClass(driver_->env_, GetMirrorClass().Ptr());
Alex Lighta26e3492017-06-27 17:55:37 -07002139}
2140
Alex Light5643caf2017-02-08 11:39:07 -08002141void Redefiner::UnregisterAllBreakpoints() {
Alex Light5643caf2017-02-08 11:39:07 -08002142 for (Redefiner::ClassRedefinition& redef : redefinitions_) {
Alex Lighte34fe442018-02-21 17:35:55 -08002143 redef.UnregisterJvmtiBreakpoints();
Alex Light5643caf2017-02-08 11:39:07 -08002144 }
2145}
2146
Alex Light0e692732017-01-10 15:00:05 -08002147bool Redefiner::CheckAllRedefinitionAreValid() {
2148 for (Redefiner::ClassRedefinition& redef : redefinitions_) {
2149 if (!redef.CheckRedefinitionIsValid()) {
2150 return false;
2151 }
2152 }
2153 return true;
2154}
2155
Alex Light1e3926a2017-04-07 10:38:06 -07002156void Redefiner::RestoreObsoleteMethodMapsIfUnneeded(RedefinitionDataHolder& holder) {
2157 for (RedefinitionDataIter data = holder.begin(); data != holder.end(); ++data) {
2158 data.GetRedefinition().RestoreObsoleteMethodMapsIfUnneeded(&data);
2159 }
2160}
2161
Alex Lightfb537082019-12-10 14:38:34 -08002162void Redefiner::MarkStructuralChanges(RedefinitionDataHolder& holder) {
2163 for (RedefinitionDataIter data = holder.begin(); data != holder.end(); ++data) {
2164 if (data.IsActuallyStructural()) {
2165 // A superclass was structural and it marked all subclasses already. No need to do anything.
2166 CHECK(!data.IsInitialStructural());
2167 } else if (data.GetRedefinition().IsStructuralRedefinition()) {
2168 data.SetActuallyStructural();
2169 data.SetInitialStructural();
2170 // Go over all potential subtypes and mark any that are actually subclasses as structural.
2171 for (RedefinitionDataIter sub_data = data + 1; sub_data != holder.end(); ++sub_data) {
2172 if (sub_data.GetRedefinition().GetMirrorClass()->IsSubClass(
2173 data.GetRedefinition().GetMirrorClass())) {
2174 sub_data.SetActuallyStructural();
2175 }
2176 }
2177 }
2178 }
2179}
2180
Alex Light1e3926a2017-04-07 10:38:06 -07002181bool Redefiner::EnsureAllClassAllocationsFinished(RedefinitionDataHolder& holder) {
2182 for (RedefinitionDataIter data = holder.begin(); data != holder.end(); ++data) {
2183 if (!data.GetRedefinition().EnsureClassAllocationsFinished(&data)) {
Alex Light0e692732017-01-10 15:00:05 -08002184 return false;
2185 }
2186 }
2187 return true;
2188}
2189
Alex Light986914b2019-11-19 01:12:25 +00002190bool Redefiner::CollectAndCreateNewInstances(RedefinitionDataHolder& holder) {
2191 for (RedefinitionDataIter data = holder.begin(); data != holder.end(); ++data) {
2192 // Allocate the data this redefinition requires.
2193 if (!data.GetRedefinition().CollectAndCreateNewInstances(&data)) {
2194 return false;
2195 }
2196 }
2197 return true;
2198}
2199
Alex Lightfb537082019-12-10 14:38:34 -08002200bool Redefiner::FinishAllNewClassAllocations(RedefinitionDataHolder& holder) {
Alex Lightc5f5a6e2017-03-01 16:57:08 -08002201 for (RedefinitionDataIter data = holder.begin(); data != holder.end(); ++data) {
Alex Light0e692732017-01-10 15:00:05 -08002202 // Allocate the data this redefinition requires.
Alex Lightfb537082019-12-10 14:38:34 -08002203 if (!data.GetRedefinition().FinishNewClassAllocations(holder, &data)) {
2204 return false;
2205 }
2206 }
2207 return true;
2208}
2209
2210bool Redefiner::FinishAllRemainingCommonAllocations(RedefinitionDataHolder& holder) {
2211 for (RedefinitionDataIter data = holder.begin(); data != holder.end(); ++data) {
2212 // Allocate the data this redefinition requires.
2213 if (!data.GetRedefinition().FinishRemainingCommonAllocations(&data)) {
Alex Light0e692732017-01-10 15:00:05 -08002214 return false;
2215 }
Alex Light0e692732017-01-10 15:00:05 -08002216 }
2217 return true;
2218}
2219
2220void Redefiner::ClassRedefinition::ReleaseDexFile() {
Andreas Gampeafaf7f82018-10-16 11:32:38 -07002221 dex_file_.release(); // NOLINT b/117926937
Alex Light0e692732017-01-10 15:00:05 -08002222}
2223
2224void Redefiner::ReleaseAllDexFiles() {
2225 for (Redefiner::ClassRedefinition& redef : redefinitions_) {
2226 redef.ReleaseDexFile();
2227 }
2228}
2229
Alex Lightc5f5a6e2017-03-01 16:57:08 -08002230bool Redefiner::CheckAllClassesAreVerified(RedefinitionDataHolder& holder) {
2231 for (RedefinitionDataIter data = holder.begin(); data != holder.end(); ++data) {
2232 if (!data.GetRedefinition().CheckVerification(data)) {
Alex Light8c889d22017-02-06 13:58:27 -08002233 return false;
2234 }
Alex Light8c889d22017-02-06 13:58:27 -08002235 }
2236 return true;
2237}
2238
Alex Lightc5f5a6e2017-03-01 16:57:08 -08002239class ScopedDisableConcurrentAndMovingGc {
2240 public:
2241 ScopedDisableConcurrentAndMovingGc(art::gc::Heap* heap, art::Thread* self)
2242 : heap_(heap), self_(self) {
2243 if (heap_->IsGcConcurrentAndMoving()) {
2244 heap_->IncrementDisableMovingGC(self_);
2245 }
2246 }
2247
2248 ~ScopedDisableConcurrentAndMovingGc() {
2249 if (heap_->IsGcConcurrentAndMoving()) {
2250 heap_->DecrementDisableMovingGC(self_);
2251 }
2252 }
2253 private:
2254 art::gc::Heap* heap_;
2255 art::Thread* self_;
2256};
2257
Alex Light270db1c2019-12-03 12:20:01 +00002258class ClassDefinitionPauser : public art::ClassLoadCallback {
2259 public:
2260 explicit ClassDefinitionPauser(art::Thread* self) REQUIRES_SHARED(art::Locks::mutator_lock_)
2261 : self_(self),
2262 is_running_(false),
2263 barrier_(0),
2264 release_mu_("SuspendClassDefinition lock", art::kGenericBottomLock),
2265 release_barrier_(0),
2266 release_cond_("SuspendClassDefinition condvar", release_mu_),
2267 count_(0),
2268 release_(false) {
2269 art::Locks::mutator_lock_->AssertSharedHeld(self_);
2270 }
2271 ~ClassDefinitionPauser() REQUIRES_SHARED(art::Locks::mutator_lock_) {
2272 art::Locks::mutator_lock_->AssertSharedHeld(self_);
Alex Lightf6c69e52020-01-17 15:30:40 -08002273 CHECK(release_) << "Must call Release()";
2274 }
2275 void Release() REQUIRES(art::Locks::mutator_lock_) {
Alex Light270db1c2019-12-03 12:20:01 +00002276 if (is_running_) {
Alex Lightf6c69e52020-01-17 15:30:40 -08002277 art::Locks::mutator_lock_->AssertExclusiveHeld(self_);
Alex Light270db1c2019-12-03 12:20:01 +00002278 uint32_t count;
2279 // Wake up everything.
2280 {
2281 art::MutexLock mu(self_, release_mu_);
2282 release_ = true;
Alex Lightf6c69e52020-01-17 15:30:40 -08002283 // We have an exclusive mutator so all threads must be suspended and therefore they've
2284 // either already incremented this count_ or they are stuck somewhere before it.
Alex Light270db1c2019-12-03 12:20:01 +00002285 count = count_;
2286 release_cond_.Broadcast(self_);
2287 }
2288 // Wait for all threads to leave this structs code.
Alex Light270db1c2019-12-03 12:20:01 +00002289 VLOG(plugin) << "Resuming " << count << " threads paused before class-allocation!";
Alex Lightf6c69e52020-01-17 15:30:40 -08002290 release_barrier_.Increment</*locks=*/art::Barrier::kAllowHoldingLocks>(self_, count);
2291 } else {
2292 release_ = true;
Alex Light270db1c2019-12-03 12:20:01 +00002293 }
2294 }
2295 void BeginDefineClass() override REQUIRES_SHARED(art::Locks::mutator_lock_) {
2296 art::Thread* this_thread = art::Thread::Current();
2297 if (this_thread == self_) {
2298 // Allow the redefining thread to do whatever.
2299 return;
2300 }
2301 if (this_thread->GetDefineClassCount() != 0) {
2302 // We are in the middle of a recursive define-class. Don't suspend now allow it to finish.
2303 VLOG(plugin) << "Recursive DefineClass in " << *this_thread
2304 << " allowed to proceed despite class-def pause initiated by " << *self_;
2305 return;
2306 }
Alex Lightf6c69e52020-01-17 15:30:40 -08002307 // If we are suspended (no mutator-lock) then the pausing thread could do everything before the
2308 // count_++ including destroying this object, causing UAF/deadlock.
2309 art::Locks::mutator_lock_->AssertSharedHeld(this_thread);
2310 ++count_;
Alex Light270db1c2019-12-03 12:20:01 +00002311 art::ScopedThreadSuspension sts(this_thread, art::ThreadState::kSuspended);
2312 {
2313 art::MutexLock mu(this_thread, release_mu_);
Alex Light270db1c2019-12-03 12:20:01 +00002314 VLOG(plugin) << "Suspending " << *this_thread << " due to class definition. class-def pause "
2315 << "initiated by " << *self_;
Alex Light270db1c2019-12-03 12:20:01 +00002316 while (!release_) {
2317 release_cond_.Wait(this_thread);
2318 }
2319 }
2320 release_barrier_.Pass(this_thread);
2321 }
Alex Lightf6c69e52020-01-17 15:30:40 -08002322
Alex Light270db1c2019-12-03 12:20:01 +00002323 void EndDefineClass() override REQUIRES_SHARED(art::Locks::mutator_lock_) {
2324 art::Thread* this_thread = art::Thread::Current();
2325 if (this_thread == self_) {
2326 // Allow the redefining thread to do whatever.
2327 return;
2328 }
2329 if (this_thread->GetDefineClassCount() == 0) {
2330 // We are done with defining classes.
2331 barrier_.Pass(this_thread);
2332 }
2333 }
2334
2335 void ClassLoad(art::Handle<art::mirror::Class> klass ATTRIBUTE_UNUSED) override {}
2336 void ClassPrepare(art::Handle<art::mirror::Class> klass1 ATTRIBUTE_UNUSED,
2337 art::Handle<art::mirror::Class> klass2 ATTRIBUTE_UNUSED) override {}
2338
2339 void SetRunning() {
2340 is_running_ = true;
2341 }
2342 void WaitFor(uint32_t t) REQUIRES(!art::Locks::mutator_lock_) {
2343 barrier_.Increment(self_, t);
2344 }
2345
2346 private:
2347 art::Thread* self_;
2348 bool is_running_;
2349 art::Barrier barrier_;
2350 art::Mutex release_mu_;
2351 art::Barrier release_barrier_;
2352 art::ConditionVariable release_cond_;
Alex Lightf6c69e52020-01-17 15:30:40 -08002353 std::atomic<uint32_t> count_;
Alex Light270db1c2019-12-03 12:20:01 +00002354 bool release_;
2355};
2356
2357class ScopedSuspendClassLoading {
2358 public:
2359 ScopedSuspendClassLoading(art::Thread* self, art::Runtime* runtime, RedefinitionDataHolder& h)
2360 REQUIRES_SHARED(art::Locks::mutator_lock_)
Alex Lightf6c69e52020-01-17 15:30:40 -08002361 : self_(self), runtime_(runtime), pauser_() {
Alex Light270db1c2019-12-03 12:20:01 +00002362 if (std::any_of(h.begin(), h.end(), [](auto r) REQUIRES_SHARED(art::Locks::mutator_lock_) {
2363 return r.GetRedefinition().IsStructuralRedefinition();
2364 })) {
2365 VLOG(plugin) << "Pausing Class loading for structural redefinition.";
Alex Lightf6c69e52020-01-17 15:30:40 -08002366 pauser_.emplace(self);
Alex Light270db1c2019-12-03 12:20:01 +00002367 {
2368 art::ScopedThreadSuspension sts(self_, art::ThreadState::kNative);
2369 uint32_t in_progress_defines = 0;
2370 {
2371 art::ScopedSuspendAll ssa(__FUNCTION__);
Alex Lightf6c69e52020-01-17 15:30:40 -08002372 pauser_->SetRunning();
2373 runtime_->GetRuntimeCallbacks()->AddClassLoadCallback(&pauser_.value());
Alex Light270db1c2019-12-03 12:20:01 +00002374 art::MutexLock mu(self_, *art::Locks::thread_list_lock_);
2375 runtime_->GetThreadList()->ForEach([&](art::Thread* t) {
2376 if (t != self_ && t->GetDefineClassCount() != 0) {
2377 in_progress_defines++;
2378 }
2379 });
Alex Lightf6c69e52020-01-17 15:30:40 -08002380 VLOG(plugin) << "Waiting for " << in_progress_defines
2381 << " in progress class-loads to finish";
Alex Light270db1c2019-12-03 12:20:01 +00002382 }
Alex Lightf6c69e52020-01-17 15:30:40 -08002383 pauser_->WaitFor(in_progress_defines);
Alex Light270db1c2019-12-03 12:20:01 +00002384 }
2385 }
2386 }
2387 ~ScopedSuspendClassLoading() {
Alex Lightf6c69e52020-01-17 15:30:40 -08002388 if (pauser_.has_value()) {
Alex Light270db1c2019-12-03 12:20:01 +00002389 art::ScopedThreadSuspension sts(self_, art::ThreadState::kNative);
2390 art::ScopedSuspendAll ssa(__FUNCTION__);
Alex Lightf6c69e52020-01-17 15:30:40 -08002391 pauser_->Release();
2392 runtime_->GetRuntimeCallbacks()->RemoveClassLoadCallback(&pauser_.value());
Alex Light270db1c2019-12-03 12:20:01 +00002393 }
2394 }
2395
2396 private:
2397 art::Thread* self_;
2398 art::Runtime* runtime_;
Alex Lightf6c69e52020-01-17 15:30:40 -08002399 std::optional<ClassDefinitionPauser> pauser_;
Alex Light270db1c2019-12-03 12:20:01 +00002400};
2401
Alex Light986914b2019-11-19 01:12:25 +00002402class ScopedSuspendAllocations {
2403 public:
2404 ScopedSuspendAllocations(art::Runtime* runtime, RedefinitionDataHolder& h)
2405 REQUIRES_SHARED(art::Locks::mutator_lock_)
2406 : paused_(false) {
2407 if (std::any_of(h.begin(),
2408 h.end(),
2409 [](auto r) REQUIRES_SHARED(art::Locks::mutator_lock_) {
2410 return r.GetRedefinition().IsStructuralRedefinition();
2411 })) {
2412 VLOG(plugin) << "Pausing allocations for structural redefinition.";
2413 paused_ = true;
2414 AllocationManager::Get()->PauseAllocations(art::Thread::Current());
2415 // Collect garbage so we don't need to recreate as much.
2416 runtime->GetHeap()->CollectGarbage(/*clear_soft_references=*/false);
2417 }
2418 }
2419
2420 ~ScopedSuspendAllocations() REQUIRES_SHARED(art::Locks::mutator_lock_) {
2421 if (paused_) {
2422 AllocationManager::Get()->ResumeAllocations(art::Thread::Current());
2423 }
2424 }
2425
2426 private:
2427 bool paused_;
2428
2429 DISALLOW_COPY_AND_ASSIGN(ScopedSuspendAllocations);
2430};
2431
Alex Lighta01de592016-11-15 10:43:06 -08002432jvmtiError Redefiner::Run() {
Alex Light0e692732017-01-10 15:00:05 -08002433 art::StackHandleScope<1> hs(self_);
Alex Lightfb537082019-12-10 14:38:34 -08002434 // Sort the redefinitions_ array topologically by class. This makes later steps easier since we
2435 // know that every class precedes all of its supertypes.
2436 std::sort(redefinitions_.begin(),
2437 redefinitions_.end(),
2438 [&](auto& l, auto& r) REQUIRES_SHARED(art::Locks::mutator_lock_) {
2439 return CompareClasses(l.GetMirrorClass(), r.GetMirrorClass());
2440 });
2441 // Allocate an array to hold onto all java temporary objects associated with this
2442 // redefinition. We will let this be collected after the end of this function.
Alex Lightc5f5a6e2017-03-01 16:57:08 -08002443 RedefinitionDataHolder holder(&hs, runtime_, self_, &redefinitions_);
Alex Light0e692732017-01-10 15:00:05 -08002444 if (holder.IsNull()) {
2445 self_->AssertPendingOOMException();
2446 self_->ClearException();
2447 RecordFailure(ERR(OUT_OF_MEMORY), "Could not allocate storage for temporaries");
2448 return result_;
2449 }
2450
Alex Lighta01de592016-11-15 10:43:06 -08002451 // First we just allocate the ClassExt and its fields that we need. These can be updated
Alex Lightfb537082019-12-10 14:38:34 -08002452 // atomically without any issues (since we allocate the map arrays as empty).
2453 if (!CheckAllRedefinitionAreValid()) {
2454 return result_;
2455 }
2456 // Mark structural changes.
2457 MarkStructuralChanges(holder);
2458 // Now we pause class loading. If we are doing a structural redefinition we will need to get an
2459 // accurate picture of the classes loaded and having loads in the middle would make that
2460 // impossible. This only pauses class-loading if we actually have at least one structural
2461 // redefinition.
2462 ScopedSuspendClassLoading suspend_class_load(self_, runtime_, holder);
2463 if (!EnsureAllClassAllocationsFinished(holder) ||
2464 !FinishAllRemainingCommonAllocations(holder) ||
2465 !FinishAllNewClassAllocations(holder) ||
Alex Light8c889d22017-02-06 13:58:27 -08002466 !CheckAllClassesAreVerified(holder)) {
Alex Lighta01de592016-11-15 10:43:06 -08002467 return result_;
2468 }
Alex Lightc5f5a6e2017-03-01 16:57:08 -08002469
Alex Light986914b2019-11-19 01:12:25 +00002470 ScopedSuspendAllocations suspend_alloc(runtime_, holder);
2471 if (!CollectAndCreateNewInstances(holder)) {
2472 return result_;
2473 }
2474
Alex Light5643caf2017-02-08 11:39:07 -08002475 // At this point we can no longer fail without corrupting the runtime state.
Alex Lightc5f5a6e2017-03-01 16:57:08 -08002476 for (RedefinitionDataIter data = holder.begin(); data != holder.end(); ++data) {
Alex Light07f06212017-06-01 14:01:43 -07002477 art::ClassLinker* cl = runtime_->GetClassLinker();
Alex Lightc5f5a6e2017-03-01 16:57:08 -08002478 if (data.GetSourceClassLoader() == nullptr) {
David Srbecky11943fc2021-02-23 22:45:33 +00002479 // AppendToBootClassPath includes dex file registration.
Nicolas Geoffray7913cf32022-02-16 09:28:21 +00002480 cl->AppendToBootClassPath(&data.GetRedefinition().GetDexFile(), data.GetNewDexCache());
David Srbecky11943fc2021-02-23 22:45:33 +00002481 } else {
2482 cl->RegisterExistingDexCache(data.GetNewDexCache(), data.GetSourceClassLoader());
Alex Light7916f202017-01-27 09:00:15 -08002483 }
Nicolas Geoffray7913cf32022-02-16 09:28:21 +00002484 DCHECK_EQ(cl->FindDexCache(self_, data.GetRedefinition().GetDexFile()), data.GetNewDexCache());
Alex Light7916f202017-01-27 09:00:15 -08002485 }
Alex Light5643caf2017-02-08 11:39:07 -08002486 UnregisterAllBreakpoints();
Alex Lightc5f5a6e2017-03-01 16:57:08 -08002487
Alex Lightc2d0c962019-10-23 14:14:25 -07002488 {
2489 // Disable GC and wait for it to be done if we are a moving GC. This is fine since we are done
2490 // allocating so no deadlocks.
2491 ScopedDisableConcurrentAndMovingGc sdcamgc(runtime_->GetHeap(), self_);
Alex Lightc5f5a6e2017-03-01 16:57:08 -08002492
Alex Lightc2d0c962019-10-23 14:14:25 -07002493 // Do transition to final suspension
2494 // TODO We might want to give this its own suspended state!
2495 // TODO This isn't right. We need to change state without any chance of suspend ideally!
2496 art::ScopedThreadSuspension sts(self_, art::ThreadState::kNative);
2497 art::ScopedSuspendAll ssa("Final installation of redefined Classes!", /*long_suspend=*/true);
2498 for (RedefinitionDataIter data = holder.begin(); data != holder.end(); ++data) {
2499 art::ScopedAssertNoThreadSuspension nts("Updating runtime objects for redefinition");
2500 ClassRedefinition& redef = data.GetRedefinition();
2501 if (data.GetSourceClassLoader() != nullptr) {
2502 ClassLoaderHelper::UpdateJavaDexFile(data.GetJavaDexFile(), data.GetNewDexFileCookie());
2503 }
2504 redef.UpdateClass(data);
Alex Light7916f202017-01-27 09:00:15 -08002505 }
Alex Lightc2d0c962019-10-23 14:14:25 -07002506 RestoreObsoleteMethodMapsIfUnneeded(holder);
2507 // TODO We should check for if any of the redefined methods are intrinsic methods here and, if
2508 // any are, force a full-world deoptimization before finishing redefinition. If we don't do this
2509 // then methods that have been jitted prior to the current redefinition being applied might
2510 // continue to use the old versions of the intrinsics!
2511 // TODO Do the dex_file release at a more reasonable place. This works but it muddles who really
2512 // owns the DexFile and when ownership is transferred.
2513 ReleaseAllDexFiles();
Alex Light0e692732017-01-10 15:00:05 -08002514 }
Alex Lighta01de592016-11-15 10:43:06 -08002515 return OK;
2516}
2517
Alex Light0e692732017-01-10 15:00:05 -08002518void Redefiner::ClassRedefinition::UpdateMethods(art::ObjPtr<art::mirror::Class> mclass,
Andreas Gampe3f1dcd32018-12-28 09:39:56 -08002519 const art::dex::ClassDef& class_def) {
Alex Light0e692732017-01-10 15:00:05 -08002520 art::ClassLinker* linker = driver_->runtime_->GetClassLinker();
Alex Lighta01de592016-11-15 10:43:06 -08002521 art::PointerSize image_pointer_size = linker->GetImagePointerSize();
Andreas Gampe3f1dcd32018-12-28 09:39:56 -08002522 const art::dex::TypeId& declaring_class_id = dex_file_->GetTypeId(class_def.class_idx_);
Alex Lighta01de592016-11-15 10:43:06 -08002523 const art::DexFile& old_dex_file = mclass->GetDexFile();
Alex Light200b9d72016-12-15 11:34:13 -08002524 // Update methods.
Alex Light00e475c2017-07-19 16:36:23 -07002525 for (art::ArtMethod& method : mclass->GetDeclaredMethods(image_pointer_size)) {
Andreas Gampe3f1dcd32018-12-28 09:39:56 -08002526 const art::dex::StringId* new_name_id = dex_file_->FindStringId(method.GetName());
Alex Lighta01de592016-11-15 10:43:06 -08002527 art::dex::TypeIndex method_return_idx =
2528 dex_file_->GetIndexForTypeId(*dex_file_->FindTypeId(method.GetReturnTypeDescriptor()));
2529 const auto* old_type_list = method.GetParameterTypeList();
2530 std::vector<art::dex::TypeIndex> new_type_list;
2531 for (uint32_t i = 0; old_type_list != nullptr && i < old_type_list->Size(); i++) {
2532 new_type_list.push_back(
2533 dex_file_->GetIndexForTypeId(
2534 *dex_file_->FindTypeId(
2535 old_dex_file.GetTypeDescriptor(
2536 old_dex_file.GetTypeId(
2537 old_type_list->GetTypeItem(i).type_idx_)))));
2538 }
Andreas Gampe3f1dcd32018-12-28 09:39:56 -08002539 const art::dex::ProtoId* proto_id = dex_file_->FindProtoId(method_return_idx, new_type_list);
Alex Lightdba61482016-12-21 08:20:29 -08002540 CHECK(proto_id != nullptr || old_type_list == nullptr);
Andreas Gampe3f1dcd32018-12-28 09:39:56 -08002541 const art::dex::MethodId* method_id = dex_file_->FindMethodId(declaring_class_id,
2542 *new_name_id,
2543 *proto_id);
Alex Lightdba61482016-12-21 08:20:29 -08002544 CHECK(method_id != nullptr);
Alex Lighta01de592016-11-15 10:43:06 -08002545 uint32_t dex_method_idx = dex_file_->GetIndexForMethodId(*method_id);
2546 method.SetDexMethodIndex(dex_method_idx);
Nicolas Geoffrayc8a694d2022-01-17 17:12:38 +00002547 driver_->runtime_->GetInstrumentation()->InitializeMethodsCode(&method, /*aot_code=*/ nullptr);
Nicolas Geoffray47171752020-08-31 15:03:20 +01002548 if (method.HasCodeItem()) {
2549 method.SetCodeItem(
zhaoxuyang7156ea22022-01-10 13:58:11 +08002550 dex_file_->GetCodeItem(dex_file_->FindCodeItemOffset(class_def, dex_method_idx)),
2551 dex_file_->IsCompactDexFile());
Nicolas Geoffray47171752020-08-31 15:03:20 +01002552 }
Alex Light7532d582017-02-13 16:36:06 -08002553 // Clear all the intrinsics related flags.
Orion Hodsoncfcc9cf2017-09-29 15:07:27 +01002554 method.SetNotIntrinsic();
Alex Lighta01de592016-11-15 10:43:06 -08002555 }
Alex Light200b9d72016-12-15 11:34:13 -08002556}
2557
Alex Light0e692732017-01-10 15:00:05 -08002558void Redefiner::ClassRedefinition::UpdateFields(art::ObjPtr<art::mirror::Class> mclass) {
Alex Light200b9d72016-12-15 11:34:13 -08002559 // TODO The IFields & SFields pointers should be combined like the methods_ arrays were.
2560 for (auto fields_iter : {mclass->GetIFields(), mclass->GetSFields()}) {
2561 for (art::ArtField& field : fields_iter) {
2562 std::string declaring_class_name;
Andreas Gampe3f1dcd32018-12-28 09:39:56 -08002563 const art::dex::TypeId* new_declaring_id =
Alex Light200b9d72016-12-15 11:34:13 -08002564 dex_file_->FindTypeId(field.GetDeclaringClass()->GetDescriptor(&declaring_class_name));
Andreas Gampe3f1dcd32018-12-28 09:39:56 -08002565 const art::dex::StringId* new_name_id = dex_file_->FindStringId(field.GetName());
2566 const art::dex::TypeId* new_type_id = dex_file_->FindTypeId(field.GetTypeDescriptor());
Alex Light200b9d72016-12-15 11:34:13 -08002567 CHECK(new_name_id != nullptr && new_type_id != nullptr && new_declaring_id != nullptr);
Andreas Gampe3f1dcd32018-12-28 09:39:56 -08002568 const art::dex::FieldId* new_field_id =
Alex Light200b9d72016-12-15 11:34:13 -08002569 dex_file_->FindFieldId(*new_declaring_id, *new_name_id, *new_type_id);
2570 CHECK(new_field_id != nullptr);
Alex Light163652e2020-01-08 15:18:25 -08002571 uint32_t new_field_index = dex_file_->GetIndexForFieldId(*new_field_id);
Alex Light200b9d72016-12-15 11:34:13 -08002572 // We only need to update the index since the other data in the ArtField cannot be updated.
Alex Light163652e2020-01-08 15:18:25 -08002573 field.SetDexFieldIndex(new_field_index);
Alex Light200b9d72016-12-15 11:34:13 -08002574 }
2575 }
Alex Light200b9d72016-12-15 11:34:13 -08002576}
2577
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002578void Redefiner::ClassRedefinition::CollectNewFieldAndMethodMappings(
2579 const RedefinitionDataIter& data,
2580 std::map<art::ArtMethod*, art::ArtMethod*>* method_map,
2581 std::map<art::ArtField*, art::ArtField*>* field_map) {
Alex Light270db1c2019-12-03 12:20:01 +00002582 for (auto [new_cls, old_cls] :
2583 art::ZipLeft(data.GetNewClasses()->Iterate(), data.GetOldClasses()->Iterate())) {
2584 for (art::ArtField& f : old_cls->GetSFields()) {
2585 (*field_map)[&f] = new_cls->FindDeclaredStaticField(f.GetName(), f.GetTypeDescriptor());
2586 }
2587 for (art::ArtField& f : old_cls->GetIFields()) {
2588 (*field_map)[&f] = new_cls->FindDeclaredInstanceField(f.GetName(), f.GetTypeDescriptor());
2589 }
2590 auto new_methods = new_cls->GetMethods(art::kRuntimePointerSize);
2591 for (art::ArtMethod& m : old_cls->GetMethods(art::kRuntimePointerSize)) {
2592 // No support for finding methods in this way since it's generally not needed. Just do it the
2593 // easy way.
2594 auto nm_iter = std::find_if(
2595 new_methods.begin(),
2596 new_methods.end(),
2597 [&](art::ArtMethod& cand) REQUIRES_SHARED(art::Locks::mutator_lock_) {
2598 return cand.GetNameView() == m.GetNameView() && cand.GetSignature() == m.GetSignature();
2599 });
2600 CHECK(nm_iter != new_methods.end())
2601 << "Could not find redefined version of " << m.PrettyMethod();
2602 (*method_map)[&m] = &(*nm_iter);
2603 }
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002604 }
2605}
2606
Alex Light986914b2019-11-19 01:12:25 +00002607static void CopyField(art::ObjPtr<art::mirror::Object> target,
2608 art::ArtField* new_field,
2609 art::ObjPtr<art::mirror::Object> source,
2610 art::ArtField& old_field) REQUIRES(art::Locks::mutator_lock_) {
2611 art::Primitive::Type ftype = old_field.GetTypeAsPrimitiveType();
2612 CHECK_EQ(ftype, new_field->GetTypeAsPrimitiveType())
2613 << old_field.PrettyField() << " vs " << new_field->PrettyField();
2614 if (ftype == art::Primitive::kPrimNot) {
2615 new_field->SetObject<false>(target, old_field.GetObject(source));
2616 } else {
2617 switch (ftype) {
2618#define UPDATE_FIELD(TYPE) \
2619 case art::Primitive::kPrim##TYPE: \
2620 new_field->Set##TYPE<false>(target, old_field.Get##TYPE(source)); \
2621 break
2622 UPDATE_FIELD(Int);
2623 UPDATE_FIELD(Float);
2624 UPDATE_FIELD(Long);
2625 UPDATE_FIELD(Double);
2626 UPDATE_FIELD(Short);
2627 UPDATE_FIELD(Char);
2628 UPDATE_FIELD(Byte);
2629 UPDATE_FIELD(Boolean);
2630 case art::Primitive::kPrimNot:
2631 case art::Primitive::kPrimVoid:
2632 LOG(FATAL) << "Unexpected field with type " << ftype << " found!";
2633 UNREACHABLE();
2634#undef UPDATE_FIELD
2635 }
2636 }
2637}
2638
2639static void CopyFields(bool is_static,
2640 art::ObjPtr<art::mirror::Object> target,
2641 art::ObjPtr<art::mirror::Class> target_class,
2642 art::ObjPtr<art::mirror::Object> source,
2643 art::ObjPtr<art::mirror::Class> source_class)
2644 REQUIRES(art::Locks::mutator_lock_) {
2645 DCHECK(!source_class->IsObjectClass() && !target_class->IsObjectClass())
2646 << "Should not be overriding object class fields. Target: " << target_class->PrettyClass()
2647 << " Source: " << source_class->PrettyClass();
2648 for (art::ArtField& f : (is_static ? source_class->GetSFields() : source_class->GetIFields())) {
2649 art::ArtField* new_field =
2650 (is_static ? target_class->FindDeclaredStaticField(f.GetName(), f.GetTypeDescriptor())
2651 : target_class->FindDeclaredInstanceField(f.GetName(), f.GetTypeDescriptor()));
2652 CHECK(new_field != nullptr) << "could not find new version of " << f.PrettyField();
2653 CopyField(target, new_field, source, f);
2654 }
2655 if (!is_static && !target_class->GetSuperClass()->IsObjectClass()) {
2656 CopyFields(
2657 is_static, target, target_class->GetSuperClass(), source, source_class->GetSuperClass());
2658 }
2659}
2660
2661static void ClearField(art::ObjPtr<art::mirror::Object> target, art::ArtField& field)
2662 REQUIRES(art::Locks::mutator_lock_) {
2663 art::Primitive::Type ftype = field.GetTypeAsPrimitiveType();
2664 if (ftype == art::Primitive::kPrimNot) {
2665 field.SetObject<false>(target, nullptr);
2666 } else {
2667 switch (ftype) {
2668#define UPDATE_FIELD(TYPE) \
2669 case art::Primitive::kPrim##TYPE: \
2670 field.Set##TYPE<false>(target, 0); \
2671 break
2672 UPDATE_FIELD(Int);
2673 UPDATE_FIELD(Float);
2674 UPDATE_FIELD(Long);
2675 UPDATE_FIELD(Double);
2676 UPDATE_FIELD(Short);
2677 UPDATE_FIELD(Char);
2678 UPDATE_FIELD(Byte);
2679 UPDATE_FIELD(Boolean);
2680 case art::Primitive::kPrimNot:
2681 case art::Primitive::kPrimVoid:
2682 LOG(FATAL) << "Unexpected field with type " << ftype << " found!";
2683 UNREACHABLE();
2684#undef UPDATE_FIELD
2685 }
2686 }
2687}
2688
2689static void ClearFields(bool is_static,
2690 art::ObjPtr<art::mirror::Object> target,
2691 art::ObjPtr<art::mirror::Class> target_class)
2692 REQUIRES(art::Locks::mutator_lock_) {
2693 DCHECK(!target_class->IsObjectClass());
2694 for (art::ArtField& f : (is_static ? target_class->GetSFields() : target_class->GetIFields())) {
2695 ClearField(target, f);
2696 }
2697 if (!is_static && !target_class->GetSuperClass()->IsObjectClass()) {
2698 ClearFields(is_static, target, target_class->GetSuperClass());
2699 }
2700}
2701
2702static void CopyAndClearFields(bool is_static,
2703 art::ObjPtr<art::mirror::Object> target,
2704 art::ObjPtr<art::mirror::Class> target_class,
2705 art::ObjPtr<art::mirror::Object> source,
2706 art::ObjPtr<art::mirror::Class> source_class)
2707 REQUIRES(art::Locks::mutator_lock_) {
2708 // Copy all non-j.l.Object fields
2709 CopyFields(is_static, target, target_class, source, source_class);
2710 // Copy the lock-word.
2711 target->SetLockWord(source->GetLockWord(false), false);
2712 // Clear (reset) the old one.
2713 source->SetLockWord(art::LockWord::Default(), false);
2714 art::WriteBarrier::ForEveryFieldWrite(target);
2715
2716 // Clear the fields from the old class. We don't need it anymore.
2717 ClearFields(is_static, source, source_class);
2718 art::WriteBarrier::ForEveryFieldWrite(source);
2719}
2720
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002721void Redefiner::ClassRedefinition::UpdateClassStructurally(const RedefinitionDataIter& holder) {
Alex Lightfb537082019-12-10 14:38:34 -08002722 DCHECK(holder.IsActuallyStructural());
2723 DCHECK(holder.IsInitialStructural());
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002724 // LETS GO. We've got all new class structures so no need to do all the updating of the stacks.
2725 // Instead we need to update everything else.
2726 // Just replace the class and be done with it.
2727 art::Locks::mutator_lock_->AssertExclusiveHeld(driver_->self_);
Alex Light16527e82020-06-08 09:21:12 -07002728 art::ClassLinker* cl = driver_->runtime_->GetClassLinker();
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002729 art::ScopedAssertNoThreadSuspension sants(__FUNCTION__);
Alex Light270db1c2019-12-03 12:20:01 +00002730 art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>> new_classes(holder.GetNewClasses());
2731 art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>> old_classes(holder.GetOldClasses());
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002732 // Collect mappings from old to new fields/methods
2733 std::map<art::ArtMethod*, art::ArtMethod*> method_map;
2734 std::map<art::ArtField*, art::ArtField*> field_map;
2735 CollectNewFieldAndMethodMappings(holder, &method_map, &field_map);
Alex Light986914b2019-11-19 01:12:25 +00002736 art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>> new_instances(
2737 holder.GetNewInstanceObjects());
2738 art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>> old_instances(
2739 holder.GetOldInstanceObjects());
Alex Light270db1c2019-12-03 12:20:01 +00002740 // Once we do the ReplaceReferences old_classes will have the new_classes in it. We want to keep
2741 // ahold of the old classes so copy them now.
2742 std::vector<art::ObjPtr<art::mirror::Class>> old_classes_vec(old_classes->Iterate().begin(),
2743 old_classes->Iterate().end());
Alex Light986914b2019-11-19 01:12:25 +00002744 // Copy over the static fields of the class and all the instance fields.
Alex Light270db1c2019-12-03 12:20:01 +00002745 for (auto [new_class, old_class] : art::ZipLeft(new_classes->Iterate(), old_classes->Iterate())) {
2746 CHECK(!new_class.IsNull());
2747 CHECK(!old_class.IsNull());
2748 CHECK(!old_class->IsErroneous());
2749 if (old_class->GetStatus() > new_class->GetStatus()) {
2750 // Some verification/initialization step happened during interval between
2751 // creating the new class and now. Just copy the new status.
2752 new_class->SetStatusLocked(old_class->GetStatus());
2753 }
2754 CopyAndClearFields(true, new_class, new_class, old_class, old_class);
2755 }
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002756
Alex Light986914b2019-11-19 01:12:25 +00002757 // Copy and clear the fields of the old-instances.
Alex Light270db1c2019-12-03 12:20:01 +00002758 for (auto [new_instance, old_instance] :
2759 art::ZipLeft(new_instances->Iterate(), old_instances->Iterate())) {
Alex Light986914b2019-11-19 01:12:25 +00002760 CopyAndClearFields(/*is_static=*/false,
2761 new_instance,
2762 new_instance->GetClass(),
2763 old_instance,
2764 old_instance->GetClass());
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002765 }
Alex Light16527e82020-06-08 09:21:12 -07002766 // Mark old class and methods obsolete. Copy over any native implementation as well.
2767 for (auto [old_class, new_class] : art::ZipLeft(old_classes->Iterate(), new_classes->Iterate())) {
Alex Light270db1c2019-12-03 12:20:01 +00002768 old_class->SetObsoleteObject();
Alex Light16527e82020-06-08 09:21:12 -07002769 // Mark methods obsolete and copy native implementation. We need to wait
2770 // until later to actually clear the jit data. We copy the native
2771 // implementation here since we don't want to race with any threads doing
2772 // RegisterNatives.
Alex Light270db1c2019-12-03 12:20:01 +00002773 for (art::ArtMethod& m : old_class->GetMethods(art::kRuntimePointerSize)) {
Alex Light16527e82020-06-08 09:21:12 -07002774 if (m.IsNative()) {
2775 art::ArtMethod* new_method =
2776 new_class->FindClassMethod(m.GetNameView(), m.GetSignature(), art::kRuntimePointerSize);
2777 DCHECK(new_class->GetMethodsSlice(art::kRuntimePointerSize).Contains(new_method))
2778 << "Could not find method " << m.PrettyMethod() << " declared in new class!";
2779 DCHECK(new_method->IsNative());
2780 new_method->SetEntryPointFromJni(m.GetEntryPointFromJni());
2781 }
Alex Light270db1c2019-12-03 12:20:01 +00002782 m.SetIsObsolete();
Alex Light16527e82020-06-08 09:21:12 -07002783 cl->SetEntryPointsForObsoleteMethod(&m);
Alex Light270db1c2019-12-03 12:20:01 +00002784 if (m.IsInvokable()) {
2785 m.SetDontCompile();
2786 }
2787 }
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002788 }
Alex Lightc18eba32019-09-24 14:36:27 -07002789 // Update live pointers in ART code.
Alex Light24627892019-11-06 10:28:21 -08002790 auto could_change_resolution_of = [&](auto* field_or_method,
2791 const auto& info) REQUIRES(art::Locks::mutator_lock_) {
2792 constexpr bool is_method = std::is_same_v<art::ArtMethod*, decltype(field_or_method)>;
2793 static_assert(is_method || std::is_same_v<art::ArtField*, decltype(field_or_method)>,
2794 "Input is not field or method!");
2795 // Only dex-cache is used for resolution
2796 if (LIKELY(info.GetType() != art::ReflectionSourceType::kSourceDexCacheResolvedField &&
2797 info.GetType() != art::ReflectionSourceType::kSourceDexCacheResolvedMethod)) {
2798 return false;
2799 }
2800 if constexpr (is_method) {
2801 // Only direct methods are used without further indirection through a vtable/IFTable.
2802 // Constructors cannot be shadowed.
2803 if (LIKELY(!field_or_method->IsDirect() || field_or_method->IsConstructor())) {
2804 return false;
2805 }
2806 } else {
2807 // Only non-private fields can be shadowed in a manner that's visible.
2808 if (LIKELY(field_or_method->IsPrivate())) {
2809 return false;
2810 }
2811 }
2812 // We can only shadow things from our superclasses
Alex Lightbf6498e2020-07-21 17:03:26 -07002813 auto orig_classes_iter = old_classes->Iterate();
2814 auto replacement_classes_iter = new_classes->Iterate();
2815 art::ObjPtr<art::mirror::Class> f_or_m_class = field_or_method->GetDeclaringClass();
2816 if (LIKELY(!f_or_m_class->IsAssignableFrom(holder.GetMirrorClass()) &&
2817 std::find(orig_classes_iter.begin(), orig_classes_iter.end(), f_or_m_class) ==
2818 orig_classes_iter.end())) {
Alex Light24627892019-11-06 10:28:21 -08002819 return false;
2820 }
2821 if constexpr (is_method) {
Alex Lightbf6498e2020-07-21 17:03:26 -07002822 return std::any_of(
2823 replacement_classes_iter.begin(),
2824 replacement_classes_iter.end(),
2825 [&](art::ObjPtr<art::mirror::Class> cand) REQUIRES(art::Locks::mutator_lock_) {
2826 auto direct_methods = cand->GetDirectMethods(art::kRuntimePointerSize);
2827 return std::find_if(direct_methods.begin(),
2828 direct_methods.end(),
2829 [&](art::ArtMethod& m) REQUIRES(art::Locks::mutator_lock_) {
2830 return UNLIKELY(m.HasSameNameAndSignature(field_or_method));
2831 }) != direct_methods.end();
2832 });
Alex Light24627892019-11-06 10:28:21 -08002833 } else {
2834 auto pred = [&](art::ArtField& f) REQUIRES(art::Locks::mutator_lock_) {
2835 return std::string_view(f.GetName()) == std::string_view(field_or_method->GetName()) &&
2836 std::string_view(f.GetTypeDescriptor()) ==
2837 std::string_view(field_or_method->GetTypeDescriptor());
2838 };
2839 if (field_or_method->IsStatic()) {
Alex Lightbf6498e2020-07-21 17:03:26 -07002840 return std::any_of(
2841 replacement_classes_iter.begin(),
2842 replacement_classes_iter.end(),
2843 [&](art::ObjPtr<art::mirror::Class> cand) REQUIRES(art::Locks::mutator_lock_) {
2844 auto sfields = cand->GetSFields();
2845 return std::find_if(sfields.begin(), sfields.end(), pred) != sfields.end();
2846 });
Alex Light24627892019-11-06 10:28:21 -08002847 } else {
Alex Lightbf6498e2020-07-21 17:03:26 -07002848 return std::any_of(
2849 replacement_classes_iter.begin(),
2850 replacement_classes_iter.end(),
2851 [&](art::ObjPtr<art::mirror::Class> cand) REQUIRES(art::Locks::mutator_lock_) {
2852 auto ifields = cand->GetIFields();
2853 return std::find_if(ifields.begin(), ifields.end(), pred) != ifields.end();
2854 });
Alex Light24627892019-11-06 10:28:21 -08002855 }
2856 }
2857 };
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002858 // TODO Performing 2 stack-walks back to back isn't the greatest. We might want to try to combine
2859 // it with the one ReplaceReferences does. Doing so would be rather complicated though.
Alex Lightc18eba32019-09-24 14:36:27 -07002860 driver_->runtime_->VisitReflectiveTargets(
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002861 [&](art::ArtField* f, const auto& info) REQUIRES(art::Locks::mutator_lock_) {
Alex Light28b6efe2019-11-06 12:49:41 -08002862 DCHECK(f != nullptr) << info;
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002863 auto it = field_map.find(f);
Alex Lightbf6498e2020-07-21 17:03:26 -07002864 if (UNLIKELY(could_change_resolution_of(f, info))) {
2865 // Dex-cache Resolution might change. Just clear the resolved value.
2866 VLOG(plugin) << "Clearing resolution " << info << " for (field) " << f->PrettyField();
2867 return static_cast<art::ArtField*>(nullptr);
2868 } else if (it != field_map.end()) {
Alex Light24627892019-11-06 10:28:21 -08002869 VLOG(plugin) << "Updating " << info << " object for (field) "
2870 << it->second->PrettyField();
2871 return it->second;
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002872 }
Alex Light24627892019-11-06 10:28:21 -08002873 return f;
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002874 },
2875 [&](art::ArtMethod* m, const auto& info) REQUIRES(art::Locks::mutator_lock_) {
Alex Light28b6efe2019-11-06 12:49:41 -08002876 DCHECK(m != nullptr) << info;
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002877 auto it = method_map.find(m);
Alex Lightbf6498e2020-07-21 17:03:26 -07002878 if (UNLIKELY(could_change_resolution_of(m, info))) {
2879 // Dex-cache Resolution might change. Just clear the resolved value.
2880 VLOG(plugin) << "Clearing resolution " << info << " for (method) " << m->PrettyMethod();
2881 return static_cast<art::ArtMethod*>(nullptr);
2882 } else if (it != method_map.end()) {
Alex Light24627892019-11-06 10:28:21 -08002883 VLOG(plugin) << "Updating " << info << " object for (method) "
2884 << it->second->PrettyMethod();
2885 return it->second;
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002886 }
Alex Light24627892019-11-06 10:28:21 -08002887 return m;
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002888 });
2889
2890 // Force every frame of every thread to deoptimize (any frame might have eg offsets compiled in).
2891 driver_->runtime_->GetInstrumentation()->DeoptimizeAllThreadFrames();
2892
Alex Light986914b2019-11-19 01:12:25 +00002893 std::unordered_map<art::ObjPtr<art::mirror::Object>,
2894 art::ObjPtr<art::mirror::Object>,
2895 art::HashObjPtr> map;
Alex Light270db1c2019-12-03 12:20:01 +00002896 for (auto [new_class, old_class] : art::ZipLeft(new_classes->Iterate(), old_classes->Iterate())) {
2897 map.emplace(old_class, new_class);
2898 }
2899 for (auto [new_instance, old_instance] :
2900 art::ZipLeft(new_instances->Iterate(), old_instances->Iterate())) {
2901 map.emplace(old_instance, new_instance);
2902 // Bare-bones check that the mapping is correct.
2903 CHECK(new_instance->GetClass() == map[old_instance->GetClass()]->AsClass())
2904 << new_instance->GetClass()->PrettyClass() << " vs "
2905 << map[old_instance->GetClass()]->AsClass()->PrettyClass();
Alex Light986914b2019-11-19 01:12:25 +00002906 }
2907
2908 // Actually perform the general replacement. This doesn't affect ArtMethod/ArtFields. It does
2909 // affect the declaring_class field of all the obsolete objects, which is unfortunate and needs to
2910 // be undone. This replaces the mirror::Class in 'holder' as well. It's magic!
2911 HeapExtensions::ReplaceReferences(driver_->self_, map);
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002912
2913 // Save the old class so that the JIT gc doesn't get confused by it being collected before the
2914 // jit code. This is also needed to keep the dex-caches of any obsolete methods live.
Alex Light270db1c2019-12-03 12:20:01 +00002915 for (auto [new_class, old_class] :
2916 art::ZipLeft(new_classes->Iterate(), art::MakeIterationRange(old_classes_vec))) {
2917 new_class->GetExtData()->SetObsoleteClass(old_class);
2918 }
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002919
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002920 art::jit::Jit* jit = driver_->runtime_->GetJit();
2921 if (jit != nullptr) {
2922 // Clear jit.
2923 // TODO We might want to have some way to tell the JIT not to wait the kJitSamplesBatchSize
2924 // invokes to start compiling things again.
2925 jit->GetCodeCache()->InvalidateAllCompiledCode();
2926 }
2927
2928 // Clear thread caches
2929 {
2930 // TODO We might be able to avoid doing this but given the rather unstructured nature of the
2931 // interpreter cache it's probably not worth the effort.
2932 art::MutexLock mu(driver_->self_, *art::Locks::thread_list_lock_);
2933 driver_->runtime_->GetThreadList()->ForEach(
Hans Boehm3d2f1482022-01-17 01:32:55 +00002934 [](art::Thread* t) { t->GetInterpreterCache()->Clear(t); });
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002935 }
2936
2937 if (art::kIsDebugBuild) {
2938 // Just make sure we didn't screw up any of the now obsolete methods or fields. We need their
2939 // declaring-class to still be the obolete class
Alex Lightbf6498e2020-07-21 17:03:26 -07002940 std::for_each(
2941 old_classes_vec.cbegin(),
2942 old_classes_vec.cend(),
2943 [](art::ObjPtr<art::mirror::Class> orig) REQUIRES_SHARED(art::Locks::mutator_lock_) {
2944 orig->VisitMethods(
2945 [&](art::ArtMethod* method) REQUIRES_SHARED(art::Locks::mutator_lock_) {
2946 if (method->IsCopied()) {
2947 // Copied methods have interfaces as their declaring class.
2948 return;
2949 }
2950 DCHECK_EQ(method->GetDeclaringClass(), orig)
2951 << method->GetDeclaringClass()->PrettyClass() << " vs " << orig->PrettyClass();
2952 },
2953 art::kRuntimePointerSize);
2954 orig->VisitFields([&](art::ArtField* field) REQUIRES_SHARED(art::Locks::mutator_lock_) {
2955 DCHECK_EQ(field->GetDeclaringClass(), orig)
2956 << field->GetDeclaringClass()->PrettyClass() << " vs " << orig->PrettyClass();
2957 });
2958 });
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002959 }
2960}
2961
2962// Redefines the class in place
2963void Redefiner::ClassRedefinition::UpdateClassInPlace(const RedefinitionDataIter& holder) {
2964 art::ObjPtr<art::mirror::Class> mclass(holder.GetMirrorClass());
2965 // TODO Rewrite so we don't do a stack walk for each and every class.
2966 FindAndAllocateObsoleteMethods(mclass);
2967 art::ObjPtr<art::mirror::DexCache> new_dex_cache(holder.GetNewDexCache());
2968 art::ObjPtr<art::mirror::Object> original_dex_file(holder.GetOriginalDexFile());
Alex Light6ac57502017-01-19 15:05:06 -08002969 DCHECK_EQ(dex_file_->NumClassDefs(), 1u);
Andreas Gampe3f1dcd32018-12-28 09:39:56 -08002970 const art::dex::ClassDef& class_def = dex_file_->GetClassDef(0);
Vladimir Marko5122e6b2017-08-17 16:10:09 +01002971 UpdateMethods(mclass, class_def);
Alex Light007ada22017-01-10 13:33:56 -08002972 UpdateFields(mclass);
Alex Light200b9d72016-12-15 11:34:13 -08002973
David Brazdil1a658632018-12-01 17:54:26 +00002974 art::ObjPtr<art::mirror::ClassExt> ext(mclass->GetExtData());
2975 CHECK(!ext.IsNull());
2976 ext->SetOriginalDexFile(original_dex_file);
2977
2978 // If this is the first time the class is being redefined, store
2979 // the native DexFile pointer and initial ClassDef index in ClassExt.
2980 // This preserves the pointer for hiddenapi access checks which need
2981 // to read access flags from the initial DexFile.
2982 if (ext->GetPreRedefineDexFile() == nullptr) {
2983 ext->SetPreRedefineDexFile(&mclass->GetDexFile());
2984 ext->SetPreRedefineClassDefIndex(mclass->GetDexClassDefIndex());
2985 }
2986
Alex Lighta01de592016-11-15 10:43:06 -08002987 // Update the class fields.
2988 // Need to update class last since the ArtMethod gets its DexFile from the class (which is needed
2989 // to call GetReturnTypeDescriptor and GetParameterTypeList above).
2990 mclass->SetDexCache(new_dex_cache.Ptr());
Alex Light6ac57502017-01-19 15:05:06 -08002991 mclass->SetDexClassDefIndex(dex_file_->GetIndexForClassDef(class_def));
Alex Light0e692732017-01-10 15:00:05 -08002992 mclass->SetDexTypeIndex(dex_file_->GetIndexForTypeId(*dex_file_->FindTypeId(class_sig_.c_str())));
Alex Light035105f2018-03-05 17:48:48 -08002993
2994 // Notify the jit that all the methods in this class were redefined. Need to do this last since
2995 // the jit relies on the dex_file_ being correct (for native methods at least) to find the method
2996 // meta-data.
2997 art::jit::Jit* jit = driver_->runtime_->GetJit();
2998 if (jit != nullptr) {
2999 art::PointerSize image_pointer_size =
3000 driver_->runtime_->GetClassLinker()->GetImagePointerSize();
3001 auto code_cache = jit->GetCodeCache();
3002 // Non-invokable methods don't have any JIT data associated with them so we don't need to tell
3003 // the jit about them.
3004 for (art::ArtMethod& method : mclass->GetDeclaredMethods(image_pointer_size)) {
3005 if (method.IsInvokable()) {
3006 code_cache->NotifyMethodRedefined(&method);
3007 }
3008 }
3009 }
Alex Lighta01de592016-11-15 10:43:06 -08003010}
3011
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00003012// Performs final updates to class for redefinition.
3013void Redefiner::ClassRedefinition::UpdateClass(const RedefinitionDataIter& holder) {
Alex Lightfb537082019-12-10 14:38:34 -08003014 CHECK(holder.IsInitialized());
3015 if (holder.IsInitialStructural()) {
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00003016 UpdateClassStructurally(holder);
Alex Lightfb537082019-12-10 14:38:34 -08003017 } else if (!holder.IsActuallyStructural()) {
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00003018 UpdateClassInPlace(holder);
3019 }
3020}
3021
Alex Light1e3926a2017-04-07 10:38:06 -07003022// Restores the old obsolete methods maps if it turns out they weren't needed (ie there were no new
3023// obsolete methods).
3024void Redefiner::ClassRedefinition::RestoreObsoleteMethodMapsIfUnneeded(
3025 const RedefinitionDataIter* cur_data) {
Alex Lightfb537082019-12-10 14:38:34 -08003026 if (cur_data->IsActuallyStructural()) {
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00003027 // We didn't touch these in this case.
3028 return;
3029 }
Vladimir Markod93e3742018-07-18 10:58:13 +01003030 art::ObjPtr<art::mirror::Class> klass = GetMirrorClass();
3031 art::ObjPtr<art::mirror::ClassExt> ext = klass->GetExtData();
3032 art::ObjPtr<art::mirror::PointerArray> methods = ext->GetObsoleteMethods();
3033 art::ObjPtr<art::mirror::PointerArray> old_methods = cur_data->GetOldObsoleteMethods();
Alex Light70713df2017-04-18 13:03:31 -07003034 int32_t old_length = old_methods == nullptr ? 0 : old_methods->GetLength();
Alex Light1e3926a2017-04-07 10:38:06 -07003035 int32_t expected_length =
3036 old_length + klass->NumDirectMethods() + klass->NumDeclaredVirtualMethods();
3037 // Check to make sure we are only undoing this one.
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00003038 if (methods.IsNull()) {
3039 // No new obsolete methods! We can get rid of the maps.
3040 ext->SetObsoleteArrays(cur_data->GetOldObsoleteMethods(), cur_data->GetOldDexCaches());
3041 } else if (expected_length == methods->GetLength()) {
Alex Light70713df2017-04-18 13:03:31 -07003042 for (int32_t i = 0; i < expected_length; i++) {
3043 art::ArtMethod* expected = nullptr;
3044 if (i < old_length) {
3045 expected = old_methods->GetElementPtrSize<art::ArtMethod*>(i, art::kRuntimePointerSize);
3046 }
3047 if (methods->GetElementPtrSize<art::ArtMethod*>(i, art::kRuntimePointerSize) != expected) {
Alex Light1e3926a2017-04-07 10:38:06 -07003048 // We actually have some new obsolete methods. Just abort since we cannot safely shrink the
3049 // obsolete methods array.
3050 return;
3051 }
3052 }
3053 // No new obsolete methods! We can get rid of the maps.
3054 ext->SetObsoleteArrays(cur_data->GetOldObsoleteMethods(), cur_data->GetOldDexCaches());
3055 }
3056}
3057
Alex Lighta01de592016-11-15 10:43:06 -08003058// This function does all (java) allocations we need to do for the Class being redefined.
3059// TODO Change this name maybe?
Alex Light1e3926a2017-04-07 10:38:06 -07003060bool Redefiner::ClassRedefinition::EnsureClassAllocationsFinished(
3061 /*out*/RedefinitionDataIter* cur_data) {
Alex Light0e692732017-01-10 15:00:05 -08003062 art::StackHandleScope<2> hs(driver_->self_);
3063 art::Handle<art::mirror::Class> klass(hs.NewHandle(
3064 driver_->self_->DecodeJObject(klass_)->AsClass()));
Andreas Gampefa4333d2017-02-14 11:10:34 -08003065 if (klass == nullptr) {
Alex Lighta01de592016-11-15 10:43:06 -08003066 RecordFailure(ERR(INVALID_CLASS), "Unable to decode class argument!");
3067 return false;
3068 }
3069 // Allocate the classExt
Vladimir Marko3068d582019-05-28 16:39:29 +01003070 art::Handle<art::mirror::ClassExt> ext =
3071 hs.NewHandle(art::mirror::Class::EnsureExtDataPresent(klass, driver_->self_));
Andreas Gampefa4333d2017-02-14 11:10:34 -08003072 if (ext == nullptr) {
Alex Lighta01de592016-11-15 10:43:06 -08003073 // No memory. Clear exception (it's not useful) and return error.
Alex Light0e692732017-01-10 15:00:05 -08003074 driver_->self_->AssertPendingOOMException();
3075 driver_->self_->ClearException();
Alex Lighta01de592016-11-15 10:43:06 -08003076 RecordFailure(ERR(OUT_OF_MEMORY), "Could not allocate ClassExt");
3077 return false;
3078 }
Alex Lightfb537082019-12-10 14:38:34 -08003079 if (!cur_data->IsActuallyStructural()) {
3080 CHECK(!IsStructuralRedefinition());
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00003081 // First save the old values of the 2 arrays that make up the obsolete methods maps. Then
3082 // allocate the 2 arrays that make up the obsolete methods map. Since the contents of the arrays
3083 // are only modified when all threads (other than the modifying one) are suspended we don't need
3084 // to worry about missing the unsyncronized writes to the array. We do synchronize when setting
3085 // it however, since that can happen at any time.
3086 cur_data->SetOldObsoleteMethods(ext->GetObsoleteMethods());
3087 cur_data->SetOldDexCaches(ext->GetObsoleteDexCaches());
3088 if (!art::mirror::ClassExt::ExtendObsoleteArrays(
3089 ext, driver_->self_, klass->GetDeclaredMethodsSlice(art::kRuntimePointerSize).size())) {
3090 // OOM. Clear exception and return error.
3091 driver_->self_->AssertPendingOOMException();
3092 driver_->self_->ClearException();
3093 RecordFailure(ERR(OUT_OF_MEMORY), "Unable to allocate/extend obsolete methods map");
3094 return false;
3095 }
Alex Lighta01de592016-11-15 10:43:06 -08003096 }
3097 return true;
3098}
3099
3100} // namespace openjdkjvmti