blob: 6b0e9c8488948dc773fa5608ae74f8afbdb3be54 [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
34#include <limits>
35
Andreas Gampe46ee31b2016-12-14 10:11:49 -080036#include "android-base/stringprintf.h"
37
Alex Lighta01de592016-11-15 10:43:06 -080038#include "art_jvmti.h"
39#include "base/logging.h"
Alex Light10f02fb2017-01-06 16:21:48 -080040#include "dex_file.h"
41#include "dex_file_types.h"
Alex Lighta01de592016-11-15 10:43:06 -080042#include "events-inl.h"
43#include "gc/allocation_listener.h"
Alex Light6abd5392017-01-05 17:53:00 -080044#include "gc/heap.h"
Alex Lighta01de592016-11-15 10:43:06 -080045#include "instrumentation.h"
Alex Lightdba61482016-12-21 08:20:29 -080046#include "jit/jit.h"
47#include "jit/jit_code_cache.h"
Alex Lighta01de592016-11-15 10:43:06 -080048#include "jni_env_ext-inl.h"
49#include "jvmti_allocator.h"
50#include "mirror/class.h"
51#include "mirror/class_ext.h"
52#include "mirror/object.h"
53#include "object_lock.h"
54#include "runtime.h"
55#include "ScopedLocalRef.h"
56
57namespace openjdkjvmti {
58
Andreas Gampe46ee31b2016-12-14 10:11:49 -080059using android::base::StringPrintf;
60
Alex Lightdba61482016-12-21 08:20:29 -080061// This visitor walks thread stacks and allocates and sets up the obsolete methods. It also does
62// some basic sanity checks that the obsolete method is sane.
63class ObsoleteMethodStackVisitor : public art::StackVisitor {
64 protected:
65 ObsoleteMethodStackVisitor(
66 art::Thread* thread,
67 art::LinearAlloc* allocator,
68 const std::unordered_set<art::ArtMethod*>& obsoleted_methods,
69 /*out*/std::unordered_map<art::ArtMethod*, art::ArtMethod*>* obsolete_maps,
70 /*out*/bool* success,
71 /*out*/std::string* error_msg)
72 : StackVisitor(thread,
73 /*context*/nullptr,
74 StackVisitor::StackWalkKind::kIncludeInlinedFrames),
75 allocator_(allocator),
76 obsoleted_methods_(obsoleted_methods),
77 obsolete_maps_(obsolete_maps),
78 success_(success),
79 is_runtime_frame_(false),
80 error_msg_(error_msg) {
81 *success_ = true;
82 }
83
84 ~ObsoleteMethodStackVisitor() OVERRIDE {}
85
86 public:
87 // Returns true if we successfully installed obsolete methods on this thread, filling
88 // obsolete_maps_ with the translations if needed. Returns false and fills error_msg if we fail.
89 // The stack is cleaned up when we fail.
90 static bool UpdateObsoleteFrames(
91 art::Thread* thread,
92 art::LinearAlloc* allocator,
93 const std::unordered_set<art::ArtMethod*>& obsoleted_methods,
94 /*out*/std::unordered_map<art::ArtMethod*, art::ArtMethod*>* obsolete_maps,
95 /*out*/std::string* error_msg) REQUIRES(art::Locks::mutator_lock_) {
96 bool success = true;
97 ObsoleteMethodStackVisitor visitor(thread,
98 allocator,
99 obsoleted_methods,
100 obsolete_maps,
101 &success,
102 error_msg);
103 visitor.WalkStack();
104 if (!success) {
105 RestoreFrames(thread, *obsolete_maps, error_msg);
106 return false;
107 } else {
108 return true;
109 }
110 }
111
112 static void RestoreFrames(
113 art::Thread* thread ATTRIBUTE_UNUSED,
114 const std::unordered_map<art::ArtMethod*, art::ArtMethod*>& obsolete_maps ATTRIBUTE_UNUSED,
115 std::string* error_msg)
116 REQUIRES(art::Locks::mutator_lock_) {
117 LOG(FATAL) << "Restoring stack frames is not yet supported. Error was: " << *error_msg;
118 }
119
120 bool VisitFrame() OVERRIDE REQUIRES(art::Locks::mutator_lock_) {
121 art::ArtMethod* old_method = GetMethod();
122 // TODO REMOVE once either current_method doesn't stick around through suspend points or deopt
123 // works through runtime methods.
124 bool prev_was_runtime_frame_ = is_runtime_frame_;
125 is_runtime_frame_ = old_method->IsRuntimeMethod();
126 if (obsoleted_methods_.find(old_method) != obsoleted_methods_.end()) {
127 // The check below works since when we deoptimize we set shadow frames for all frames until a
128 // native/runtime transition and for those set the return PC to a function that will complete
129 // the deoptimization. This does leave us with the unfortunate side-effect that frames just
130 // below runtime frames cannot be deoptimized at the moment.
131 // TODO REMOVE once either current_method doesn't stick around through suspend points or deopt
132 // works through runtime methods.
133 // TODO b/33616143
134 if (!IsShadowFrame() && prev_was_runtime_frame_) {
135 *error_msg_ = StringPrintf("Deoptimization failed due to runtime method in stack.");
136 *success_ = false;
137 return false;
138 }
139 // We cannot ensure that the right dex file is used in inlined frames so we don't support
140 // redefining them.
141 DCHECK(!IsInInlinedFrame()) << "Inlined frames are not supported when using redefinition";
142 // TODO We should really support intrinsic obsolete methods.
143 // TODO We should really support redefining intrinsics.
144 // We don't support intrinsics so check for them here.
145 DCHECK(!old_method->IsIntrinsic());
146 art::ArtMethod* new_obsolete_method = nullptr;
147 auto obsolete_method_pair = obsolete_maps_->find(old_method);
148 if (obsolete_method_pair == obsolete_maps_->end()) {
149 // Create a new Obsolete Method and put it in the list.
150 art::Runtime* runtime = art::Runtime::Current();
151 art::ClassLinker* cl = runtime->GetClassLinker();
152 auto ptr_size = cl->GetImagePointerSize();
153 const size_t method_size = art::ArtMethod::Size(ptr_size);
154 auto* method_storage = allocator_->Alloc(GetThread(), method_size);
155 if (method_storage == nullptr) {
156 *success_ = false;
157 *error_msg_ = StringPrintf("Unable to allocate storage for obsolete version of '%s'",
158 old_method->PrettyMethod().c_str());
159 return false;
160 }
161 new_obsolete_method = new (method_storage) art::ArtMethod();
162 new_obsolete_method->CopyFrom(old_method, ptr_size);
163 DCHECK_EQ(new_obsolete_method->GetDeclaringClass(), old_method->GetDeclaringClass());
164 new_obsolete_method->SetIsObsolete();
165 obsolete_maps_->insert({old_method, new_obsolete_method});
166 // Update JIT Data structures to point to the new method.
167 art::jit::Jit* jit = art::Runtime::Current()->GetJit();
168 if (jit != nullptr) {
169 // Notify the JIT we are making this obsolete method. It will update the jit's internal
170 // structures to keep track of the new obsolete method.
171 jit->GetCodeCache()->MoveObsoleteMethod(old_method, new_obsolete_method);
172 }
173 } else {
174 new_obsolete_method = obsolete_method_pair->second;
175 }
176 DCHECK(new_obsolete_method != nullptr);
177 SetMethod(new_obsolete_method);
178 }
179 return true;
180 }
181
182 private:
183 // The linear allocator we should use to make new methods.
184 art::LinearAlloc* allocator_;
185 // The set of all methods which could be obsoleted.
186 const std::unordered_set<art::ArtMethod*>& obsoleted_methods_;
187 // A map from the original to the newly allocated obsolete method for frames on this thread. The
188 // values in this map must be added to the obsolete_methods_ (and obsolete_dex_caches_) fields of
189 // the redefined classes ClassExt by the caller.
190 std::unordered_map<art::ArtMethod*, art::ArtMethod*>* obsolete_maps_;
191 bool* success_;
192 // TODO REMOVE once either current_method doesn't stick around through suspend points or deopt
193 // works through runtime methods.
194 bool is_runtime_frame_;
195 std::string* error_msg_;
196};
197
Alex Lighta01de592016-11-15 10:43:06 -0800198// Moves dex data to an anonymous, read-only mmap'd region.
199std::unique_ptr<art::MemMap> Redefiner::MoveDataToMemMap(const std::string& original_location,
200 jint data_len,
201 unsigned char* dex_data,
202 std::string* error_msg) {
203 std::unique_ptr<art::MemMap> map(art::MemMap::MapAnonymous(
Andreas Gampe46ee31b2016-12-14 10:11:49 -0800204 StringPrintf("%s-transformed", original_location.c_str()).c_str(),
Alex Lighta01de592016-11-15 10:43:06 -0800205 nullptr,
206 data_len,
207 PROT_READ|PROT_WRITE,
208 /*low_4gb*/false,
209 /*reuse*/false,
210 error_msg));
211 if (map == nullptr) {
212 return map;
213 }
214 memcpy(map->Begin(), dex_data, data_len);
Alex Light0b772572016-12-02 17:27:31 -0800215 // Make the dex files mmap read only. This matches how other DexFiles are mmaped and prevents
216 // programs from corrupting it.
Alex Lighta01de592016-11-15 10:43:06 -0800217 map->Protect(PROT_READ);
218 return map;
219}
220
Alex Lightdba61482016-12-21 08:20:29 -0800221// TODO This should handle doing multiple classes at once so we need to do less cleanup when things
222// go wrong.
Alex Lighta01de592016-11-15 10:43:06 -0800223jvmtiError Redefiner::RedefineClass(ArtJvmTiEnv* env,
224 art::Runtime* runtime,
225 art::Thread* self,
226 jclass klass,
227 const std::string& original_dex_location,
228 jint data_len,
229 unsigned char* dex_data,
230 std::string* error_msg) {
231 std::unique_ptr<art::MemMap> map(MoveDataToMemMap(original_dex_location,
232 data_len,
233 dex_data,
234 error_msg));
235 std::ostringstream os;
236 char* generic_ptr_unused = nullptr;
237 char* signature_ptr = nullptr;
238 if (env->GetClassSignature(klass, &signature_ptr, &generic_ptr_unused) != OK) {
239 signature_ptr = const_cast<char*>("<UNKNOWN CLASS>");
240 }
241 if (map.get() == nullptr) {
242 os << "Failed to create anonymous mmap for modified dex file of class " << signature_ptr
243 << "in dex file " << original_dex_location << " because: " << *error_msg;
244 *error_msg = os.str();
245 return ERR(OUT_OF_MEMORY);
246 }
247 if (map->Size() < sizeof(art::DexFile::Header)) {
248 *error_msg = "Could not read dex file header because dex_data was too short";
249 return ERR(INVALID_CLASS_FORMAT);
250 }
251 uint32_t checksum = reinterpret_cast<const art::DexFile::Header*>(map->Begin())->checksum_;
252 std::unique_ptr<const art::DexFile> dex_file(art::DexFile::Open(map->GetName(),
253 checksum,
254 std::move(map),
255 /*verify*/true,
256 /*verify_checksum*/true,
257 error_msg));
258 if (dex_file.get() == nullptr) {
259 os << "Unable to load modified dex file for " << signature_ptr << ": " << *error_msg;
260 *error_msg = os.str();
261 return ERR(INVALID_CLASS_FORMAT);
262 }
Alex Lightdba61482016-12-21 08:20:29 -0800263 // Stop JIT for the duration of this redefine since the JIT might concurrently compile a method we
264 // are going to redefine.
265 art::jit::ScopedJitSuspend suspend_jit;
Alex Lighta01de592016-11-15 10:43:06 -0800266 // Get shared mutator lock.
267 art::ScopedObjectAccess soa(self);
268 art::StackHandleScope<1> hs(self);
269 Redefiner r(runtime, self, klass, signature_ptr, dex_file, error_msg);
270 // Lock around this class to avoid races.
271 art::ObjectLock<art::mirror::Class> lock(self, hs.NewHandle(r.GetMirrorClass()));
272 return r.Run();
273}
274
275// TODO *MAJOR* This should return the actual source java.lang.DexFile object for the klass.
276// TODO Make mirror of DexFile and associated types to make this less hellish.
277// TODO Make mirror of BaseDexClassLoader and associated types to make this less hellish.
278art::mirror::Object* Redefiner::FindSourceDexFileObject(
279 art::Handle<art::mirror::ClassLoader> loader) {
280 const char* dex_path_list_element_array_name = "[Ldalvik/system/DexPathList$Element;";
281 const char* dex_path_list_element_name = "Ldalvik/system/DexPathList$Element;";
282 const char* dex_file_name = "Ldalvik/system/DexFile;";
283 const char* dex_path_list_name = "Ldalvik/system/DexPathList;";
284 const char* dex_class_loader_name = "Ldalvik/system/BaseDexClassLoader;";
285
286 CHECK(!self_->IsExceptionPending());
287 art::StackHandleScope<11> hs(self_);
288 art::ClassLinker* class_linker = runtime_->GetClassLinker();
289
290 art::Handle<art::mirror::ClassLoader> null_loader(hs.NewHandle<art::mirror::ClassLoader>(
291 nullptr));
292 art::Handle<art::mirror::Class> base_dex_loader_class(hs.NewHandle(class_linker->FindClass(
293 self_, dex_class_loader_name, null_loader)));
294
295 // Get all the ArtFields so we can look in the BaseDexClassLoader
296 art::ArtField* path_list_field = base_dex_loader_class->FindDeclaredInstanceField(
297 "pathList", dex_path_list_name);
298 CHECK(path_list_field != nullptr);
299
300 art::ArtField* dex_path_list_element_field =
301 class_linker->FindClass(self_, dex_path_list_name, null_loader)
302 ->FindDeclaredInstanceField("dexElements", dex_path_list_element_array_name);
303 CHECK(dex_path_list_element_field != nullptr);
304
305 art::ArtField* element_dex_file_field =
306 class_linker->FindClass(self_, dex_path_list_element_name, null_loader)
307 ->FindDeclaredInstanceField("dexFile", dex_file_name);
308 CHECK(element_dex_file_field != nullptr);
309
310 // Check if loader is a BaseDexClassLoader
311 art::Handle<art::mirror::Class> loader_class(hs.NewHandle(loader->GetClass()));
312 if (!loader_class->IsSubClass(base_dex_loader_class.Get())) {
313 LOG(ERROR) << "The classloader is not a BaseDexClassLoader which is currently the only "
314 << "supported class loader type!";
315 return nullptr;
316 }
317 // Start navigating the fields of the loader (now known to be a BaseDexClassLoader derivative)
318 art::Handle<art::mirror::Object> path_list(
319 hs.NewHandle(path_list_field->GetObject(loader.Get())));
320 CHECK(path_list.Get() != nullptr);
321 CHECK(!self_->IsExceptionPending());
322 art::Handle<art::mirror::ObjectArray<art::mirror::Object>> dex_elements_list(hs.NewHandle(
323 dex_path_list_element_field->GetObject(path_list.Get())->
324 AsObjectArray<art::mirror::Object>()));
325 CHECK(!self_->IsExceptionPending());
326 CHECK(dex_elements_list.Get() != nullptr);
327 size_t num_elements = dex_elements_list->GetLength();
328 art::MutableHandle<art::mirror::Object> current_element(
329 hs.NewHandle<art::mirror::Object>(nullptr));
330 art::MutableHandle<art::mirror::Object> first_dex_file(
331 hs.NewHandle<art::mirror::Object>(nullptr));
332 // Iterate over the DexPathList$Element to find the right one
333 // TODO Or not ATM just return the first one.
334 for (size_t i = 0; i < num_elements; i++) {
335 current_element.Assign(dex_elements_list->Get(i));
336 CHECK(current_element.Get() != nullptr);
337 CHECK(!self_->IsExceptionPending());
338 CHECK(dex_elements_list.Get() != nullptr);
339 CHECK_EQ(current_element->GetClass(), class_linker->FindClass(self_,
340 dex_path_list_element_name,
341 null_loader));
342 // TODO It would be cleaner to put the art::DexFile into the dalvik.system.DexFile the class
343 // comes from but it is more annoying because we would need to find this class. It is not
344 // necessary for proper function since we just need to be in front of the classes old dex file
345 // in the path.
346 first_dex_file.Assign(element_dex_file_field->GetObject(current_element.Get()));
347 if (first_dex_file.Get() != nullptr) {
348 return first_dex_file.Get();
349 }
350 }
351 return nullptr;
352}
353
354art::mirror::Class* Redefiner::GetMirrorClass() {
355 return self_->DecodeJObject(klass_)->AsClass();
356}
357
358art::mirror::ClassLoader* Redefiner::GetClassLoader() {
359 return GetMirrorClass()->GetClassLoader();
360}
361
362art::mirror::DexCache* Redefiner::CreateNewDexCache(art::Handle<art::mirror::ClassLoader> loader) {
363 return runtime_->GetClassLinker()->RegisterDexFile(*dex_file_, loader.Get());
364}
365
366// TODO Really wishing I had that mirror of java.lang.DexFile now.
367art::mirror::LongArray* Redefiner::AllocateDexFileCookie(
368 art::Handle<art::mirror::Object> java_dex_file_obj) {
369 art::StackHandleScope<2> hs(self_);
370 // mCookie is nulled out if the DexFile has been closed but mInternalCookie sticks around until
371 // the object is finalized. Since they always point to the same array if mCookie is not null we
372 // just use the mInternalCookie field. We will update one or both of these fields later.
373 // TODO Should I get the class from the classloader or directly?
374 art::ArtField* internal_cookie_field = java_dex_file_obj->GetClass()->FindDeclaredInstanceField(
375 "mInternalCookie", "Ljava/lang/Object;");
376 // TODO Add check that mCookie is either null or same as mInternalCookie
377 CHECK(internal_cookie_field != nullptr);
378 art::Handle<art::mirror::LongArray> cookie(
379 hs.NewHandle(internal_cookie_field->GetObject(java_dex_file_obj.Get())->AsLongArray()));
380 // TODO Maybe make these non-fatal.
381 CHECK(cookie.Get() != nullptr);
382 CHECK_GE(cookie->GetLength(), 1);
383 art::Handle<art::mirror::LongArray> new_cookie(
384 hs.NewHandle(art::mirror::LongArray::Alloc(self_, cookie->GetLength() + 1)));
385 if (new_cookie.Get() == nullptr) {
386 self_->AssertPendingOOMException();
387 return nullptr;
388 }
389 // Copy the oat-dex field at the start.
390 // TODO Should I clear this field?
391 // TODO This is a really crappy thing here with the first element being different.
392 new_cookie->SetWithoutChecks<false>(0, cookie->GetWithoutChecks(0));
393 new_cookie->SetWithoutChecks<false>(
394 1, static_cast<int64_t>(reinterpret_cast<intptr_t>(dex_file_.get())));
395 new_cookie->Memcpy(2, cookie.Get(), 1, cookie->GetLength() - 1);
396 return new_cookie.Get();
397}
398
399void Redefiner::RecordFailure(jvmtiError result, const std::string& error_msg) {
Andreas Gampe46ee31b2016-12-14 10:11:49 -0800400 *error_msg_ = StringPrintf("Unable to perform redefinition of '%s': %s",
401 class_sig_,
402 error_msg.c_str());
Alex Lighta01de592016-11-15 10:43:06 -0800403 result_ = result;
404}
405
406bool Redefiner::FinishRemainingAllocations(
407 /*out*/art::MutableHandle<art::mirror::ClassLoader>* source_class_loader,
408 /*out*/art::MutableHandle<art::mirror::Object>* java_dex_file_obj,
409 /*out*/art::MutableHandle<art::mirror::LongArray>* new_dex_file_cookie,
410 /*out*/art::MutableHandle<art::mirror::DexCache>* new_dex_cache) {
411 art::StackHandleScope<4> hs(self_);
412 // This shouldn't allocate
413 art::Handle<art::mirror::ClassLoader> loader(hs.NewHandle(GetClassLoader()));
414 if (loader.Get() == nullptr) {
415 // TODO Better error msg.
416 RecordFailure(ERR(INTERNAL), "Unable to find class loader!");
417 return false;
418 }
419 art::Handle<art::mirror::Object> dex_file_obj(hs.NewHandle(FindSourceDexFileObject(loader)));
420 if (dex_file_obj.Get() == nullptr) {
421 // TODO Better error msg.
422 RecordFailure(ERR(INTERNAL), "Unable to find class loader!");
423 return false;
424 }
425 art::Handle<art::mirror::LongArray> new_cookie(hs.NewHandle(AllocateDexFileCookie(dex_file_obj)));
426 if (new_cookie.Get() == nullptr) {
427 self_->AssertPendingOOMException();
428 self_->ClearException();
429 RecordFailure(ERR(OUT_OF_MEMORY), "Unable to allocate dex file array for class loader");
430 return false;
431 }
432 art::Handle<art::mirror::DexCache> dex_cache(hs.NewHandle(CreateNewDexCache(loader)));
433 if (dex_cache.Get() == nullptr) {
434 self_->AssertPendingOOMException();
435 self_->ClearException();
436 RecordFailure(ERR(OUT_OF_MEMORY), "Unable to allocate DexCache");
437 return false;
438 }
439 source_class_loader->Assign(loader.Get());
440 java_dex_file_obj->Assign(dex_file_obj.Get());
441 new_dex_file_cookie->Assign(new_cookie.Get());
442 new_dex_cache->Assign(dex_cache.Get());
443 return true;
444}
445
Alex Lightdba61482016-12-21 08:20:29 -0800446struct CallbackCtx {
447 Redefiner* const r;
448 art::LinearAlloc* allocator;
449 std::unordered_map<art::ArtMethod*, art::ArtMethod*> obsolete_map;
450 std::unordered_set<art::ArtMethod*> obsolete_methods;
451 bool success;
452 std::string* error_msg;
453
454 CallbackCtx(Redefiner* self, art::LinearAlloc* alloc, std::string* error)
455 : r(self), allocator(alloc), success(true), error_msg(error) {}
456};
457
458void DoRestoreObsoleteMethodsCallback(art::Thread* t, void* vdata) NO_THREAD_SAFETY_ANALYSIS {
459 CallbackCtx* data = reinterpret_cast<CallbackCtx*>(vdata);
460 ObsoleteMethodStackVisitor::RestoreFrames(t, data->obsolete_map, data->error_msg);
461}
462
463void DoAllocateObsoleteMethodsCallback(art::Thread* t, void* vdata) NO_THREAD_SAFETY_ANALYSIS {
464 CallbackCtx* data = reinterpret_cast<CallbackCtx*>(vdata);
465 if (data->success) {
466 // Don't do anything if we already failed once.
467 data->success = ObsoleteMethodStackVisitor::UpdateObsoleteFrames(t,
468 data->allocator,
469 data->obsolete_methods,
470 &data->obsolete_map,
471 data->error_msg);
472 }
473}
474
475// This creates any ArtMethod* structures needed for obsolete methods and ensures that the stack is
476// updated so they will be run.
477bool Redefiner::FindAndAllocateObsoleteMethods(art::mirror::Class* art_klass) {
478 art::ScopedAssertNoThreadSuspension ns("No thread suspension during thread stack walking");
479 art::mirror::ClassExt* ext = art_klass->GetExtData();
480 CHECK(ext->GetObsoleteMethods() != nullptr);
481 CallbackCtx ctx(this, art_klass->GetClassLoader()->GetAllocator(), error_msg_);
482 // Add all the declared methods to the map
483 for (auto& m : art_klass->GetDeclaredMethods(art::kRuntimePointerSize)) {
484 ctx.obsolete_methods.insert(&m);
485 }
486 for (art::ArtMethod* old_method : ctx.obsolete_methods) {
487 if (old_method->IsIntrinsic()) {
488 *error_msg_ = StringPrintf("Method '%s' is intrinsic and cannot be made obsolete!",
489 old_method->PrettyMethod().c_str());
490 return false;
491 }
492 }
493 {
494 art::MutexLock mu(self_, *art::Locks::thread_list_lock_);
495 art::ThreadList* list = art::Runtime::Current()->GetThreadList();
496 list->ForEach(DoAllocateObsoleteMethodsCallback, static_cast<void*>(&ctx));
497 if (!ctx.success) {
498 list->ForEach(DoRestoreObsoleteMethodsCallback, static_cast<void*>(&ctx));
499 return false;
500 }
501 }
502 FillObsoleteMethodMap(art_klass, ctx.obsolete_map);
503 return true;
504}
505
506// Fills the obsolete method map in the art_klass's extData. This is so obsolete methods are able to
507// figure out their DexCaches.
508void Redefiner::FillObsoleteMethodMap(
509 art::mirror::Class* art_klass,
510 const std::unordered_map<art::ArtMethod*, art::ArtMethod*>& obsoletes) {
511 int32_t index = 0;
512 art::mirror::ClassExt* ext_data = art_klass->GetExtData();
513 art::mirror::PointerArray* obsolete_methods = ext_data->GetObsoleteMethods();
514 art::mirror::ObjectArray<art::mirror::DexCache>* obsolete_dex_caches =
515 ext_data->GetObsoleteDexCaches();
516 int32_t num_method_slots = obsolete_methods->GetLength();
517 // Find the first empty index.
518 for (; index < num_method_slots; index++) {
519 if (obsolete_methods->GetElementPtrSize<art::ArtMethod*>(
520 index, art::kRuntimePointerSize) == nullptr) {
521 break;
522 }
523 }
524 // Make sure we have enough space.
525 CHECK_GT(num_method_slots, static_cast<int32_t>(obsoletes.size() + index));
526 CHECK(obsolete_dex_caches->Get(index) == nullptr);
527 // Fill in the map.
528 for (auto& obs : obsoletes) {
529 obsolete_methods->SetElementPtrSize(index, obs.second, art::kRuntimePointerSize);
530 obsolete_dex_caches->Set(index, art_klass->GetDexCache());
531 index++;
532 }
533}
534
535// TODO It should be possible to only deoptimize the specific obsolete methods.
536// TODO ReJitEverything can (sort of) fail. In certain cases it will skip deoptimizing some frames.
537// If one of these frames is an obsolete method we have a problem. b/33616143
538// TODO This shouldn't be necessary once we can ensure that the current method is not kept in
539// registers across suspend points.
540// TODO Pending b/33630159
541void Redefiner::EnsureObsoleteMethodsAreDeoptimized() {
542 art::ScopedAssertNoThreadSuspension nts("Deoptimizing everything!");
543 art::instrumentation::Instrumentation* i = runtime_->GetInstrumentation();
544 i->ReJitEverything("libOpenJkdJvmti - Class Redefinition");
545}
546
Alex Light10f02fb2017-01-06 16:21:48 -0800547bool Redefiner::CheckClass() {
548 // TODO Might just want to put it in a ObjPtr and NoSuspend assert.
549 art::StackHandleScope<1> hs(self_);
550 // Easy check that only 1 class def is present.
551 if (dex_file_->NumClassDefs() != 1) {
552 RecordFailure(ERR(ILLEGAL_ARGUMENT),
553 StringPrintf("Expected 1 class def in dex file but found %d",
554 dex_file_->NumClassDefs()));
555 return false;
556 }
557 // Get the ClassDef from the new DexFile.
558 // Since the dex file has only a single class def the index is always 0.
559 const art::DexFile::ClassDef& def = dex_file_->GetClassDef(0);
560 // Get the class as it is now.
561 art::Handle<art::mirror::Class> current_class(hs.NewHandle(GetMirrorClass()));
562
563 // Check the access flags didn't change.
564 if (def.GetJavaAccessFlags() != (current_class->GetAccessFlags() & art::kAccValidClassFlags)) {
565 RecordFailure(ERR(UNSUPPORTED_REDEFINITION_CLASS_MODIFIERS_CHANGED),
566 "Cannot change modifiers of class by redefinition");
567 return false;
568 }
569
570 // Check class name.
571 // These should have been checked by the dexfile verifier on load.
572 DCHECK_NE(def.class_idx_, art::dex::TypeIndex::Invalid()) << "Invalid type index";
573 const char* descriptor = dex_file_->StringByTypeIdx(def.class_idx_);
574 DCHECK(descriptor != nullptr) << "Invalid dex file structure!";
575 if (!current_class->DescriptorEquals(descriptor)) {
576 std::string storage;
577 RecordFailure(ERR(NAMES_DONT_MATCH),
578 StringPrintf("expected file to contain class called '%s' but found '%s'!",
579 current_class->GetDescriptor(&storage),
580 descriptor));
581 return false;
582 }
583 if (current_class->IsObjectClass()) {
584 if (def.superclass_idx_ != art::dex::TypeIndex::Invalid()) {
585 RecordFailure(ERR(UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED), "Superclass added!");
586 return false;
587 }
588 } else {
589 const char* super_descriptor = dex_file_->StringByTypeIdx(def.superclass_idx_);
590 DCHECK(descriptor != nullptr) << "Invalid dex file structure!";
591 if (!current_class->GetSuperClass()->DescriptorEquals(super_descriptor)) {
592 RecordFailure(ERR(UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED), "Superclass changed");
593 return false;
594 }
595 }
596 const art::DexFile::TypeList* interfaces = dex_file_->GetInterfacesList(def);
597 if (interfaces == nullptr) {
598 if (current_class->NumDirectInterfaces() != 0) {
599 RecordFailure(ERR(UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED), "Interfaces added");
600 return false;
601 }
602 } else {
603 DCHECK(!current_class->IsProxyClass());
604 const art::DexFile::TypeList* current_interfaces = current_class->GetInterfaceTypeList();
605 if (current_interfaces == nullptr || current_interfaces->Size() != interfaces->Size()) {
606 RecordFailure(ERR(UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED), "Interfaces added or removed");
607 return false;
608 }
609 // The order of interfaces is (barely) meaningful so we error if it changes.
610 const art::DexFile& orig_dex_file = current_class->GetDexFile();
611 for (uint32_t i = 0; i < interfaces->Size(); i++) {
612 if (strcmp(
613 dex_file_->StringByTypeIdx(interfaces->GetTypeItem(i).type_idx_),
614 orig_dex_file.StringByTypeIdx(current_interfaces->GetTypeItem(i).type_idx_)) != 0) {
615 RecordFailure(ERR(UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED),
616 "Interfaces changed or re-ordered");
617 return false;
618 }
619 }
620 }
621 LOG(WARNING) << "No verification is done on annotations of redefined classes.";
622
623 return true;
624}
625
626// TODO Move this to use IsRedefinable when that function is made.
627bool Redefiner::CheckRedefinable() {
628 art::ObjPtr<art::mirror::Class> klass(GetMirrorClass());
629 if (klass->IsPrimitive()) {
630 RecordFailure(ERR(UNMODIFIABLE_CLASS),
631 "Modification of primitive classes is not supported");
632 return false;
633 } else if (klass->IsInterface()) {
634 RecordFailure(ERR(UNMODIFIABLE_CLASS),
635 "Modification of Interface classes is currently not supported");
636 return false;
637 } else if (klass->IsArrayClass()) {
638 RecordFailure(ERR(UNMODIFIABLE_CLASS),
639 "Modification of Array classes is not supported");
640 return false;
641 } else if (klass->IsProxyClass()) {
642 RecordFailure(ERR(UNMODIFIABLE_CLASS),
643 "Modification of proxy classes is not supported");
644 return false;
645 }
646
647 // TODO We should check if the class has non-obsoletable methods on the stack
648 LOG(WARNING) << "presence of non-obsoletable methods on stacks is not currently checked";
649 return true;
650}
651
652bool Redefiner::CheckRedefinitionIsValid() {
653 return CheckRedefinable() &&
654 CheckClass() &&
655 CheckSameFields() &&
656 CheckSameMethods();
657}
658
Alex Lighta01de592016-11-15 10:43:06 -0800659jvmtiError Redefiner::Run() {
660 art::StackHandleScope<5> hs(self_);
661 // TODO We might want to have a global lock (or one based on the class being redefined at least)
662 // in order to make cleanup easier. Not a huge deal though.
663 //
664 // First we just allocate the ClassExt and its fields that we need. These can be updated
665 // atomically without any issues (since we allocate the map arrays as empty) so we don't bother
666 // doing a try loop. The other allocations we need to ensure that nothing has changed in the time
667 // between allocating them and pausing all threads before we can update them so we need to do a
668 // try loop.
Alex Light10f02fb2017-01-06 16:21:48 -0800669 if (!CheckRedefinitionIsValid() || !EnsureClassAllocationsFinished()) {
Alex Lighta01de592016-11-15 10:43:06 -0800670 return result_;
671 }
672 art::MutableHandle<art::mirror::ClassLoader> source_class_loader(
673 hs.NewHandle<art::mirror::ClassLoader>(nullptr));
674 art::MutableHandle<art::mirror::Object> java_dex_file(
675 hs.NewHandle<art::mirror::Object>(nullptr));
676 art::MutableHandle<art::mirror::LongArray> new_dex_file_cookie(
677 hs.NewHandle<art::mirror::LongArray>(nullptr));
678 art::MutableHandle<art::mirror::DexCache> new_dex_cache(
679 hs.NewHandle<art::mirror::DexCache>(nullptr));
680 if (!FinishRemainingAllocations(&source_class_loader,
681 &java_dex_file,
682 &new_dex_file_cookie,
683 &new_dex_cache)) {
684 // TODO Null out the ClassExt fields we allocated (if possible, might be racing with another
685 // redefineclass call which made it even bigger. Leak shouldn't be huge (2x array of size
686 // declared_methods_.length) but would be good to get rid of.
687 // new_dex_file_cookie & new_dex_cache should be cleaned up by the GC.
688 return result_;
689 }
690 // Get the mirror class now that we aren't allocating anymore.
691 art::Handle<art::mirror::Class> art_class(hs.NewHandle(GetMirrorClass()));
Alex Light6abd5392017-01-05 17:53:00 -0800692 // Disable GC and wait for it to be done if we are a moving GC. This is fine since we are done
693 // allocating so no deadlocks.
694 art::gc::Heap* heap = runtime_->GetHeap();
695 if (heap->IsGcConcurrentAndMoving()) {
696 // GC moving objects can cause deadlocks as we are deoptimizing the stack.
697 heap->IncrementDisableMovingGC(self_);
698 }
Alex Lighta01de592016-11-15 10:43:06 -0800699 // Enable assertion that this thread isn't interrupted during this installation.
700 // After this we will need to do real cleanup in case of failure. Prior to this we could simply
701 // return and would let everything get cleaned up or harmlessly leaked.
702 // Do transition to final suspension
703 // TODO We might want to give this its own suspended state!
704 // TODO This isn't right. We need to change state without any chance of suspend ideally!
705 self_->TransitionFromRunnableToSuspended(art::ThreadState::kNative);
706 runtime_->GetThreadList()->SuspendAll(
707 "Final installation of redefined Class!", /*long_suspend*/true);
Alex Lightdba61482016-12-21 08:20:29 -0800708 // TODO We need to invalidate all breakpoints in the redefined class with the debugger.
709 // TODO We need to deal with any instrumentation/debugger deoptimized_methods_.
710 // TODO We need to update all debugger MethodIDs so they note the method they point to is
711 // obsolete or implement some other well defined semantics.
712 // TODO We need to decide on & implement semantics for JNI jmethodids when we redefine methods.
Alex Lighta01de592016-11-15 10:43:06 -0800713 // TODO Might want to move this into a different type.
714 // Now we reach the part where we must do active cleanup if something fails.
715 // TODO We should really Retry if this fails instead of simply aborting.
716 // Set the new DexFileCookie returns the original so we can fix it back up if redefinition fails
717 art::ObjPtr<art::mirror::LongArray> original_dex_file_cookie(nullptr);
718 if (!UpdateJavaDexFile(java_dex_file.Get(),
719 new_dex_file_cookie.Get(),
Alex Lightdba61482016-12-21 08:20:29 -0800720 &original_dex_file_cookie) ||
721 !FindAndAllocateObsoleteMethods(art_class.Get())) {
Alex Lighta01de592016-11-15 10:43:06 -0800722 // Release suspendAll
723 runtime_->GetThreadList()->ResumeAll();
724 // Get back shared mutator lock as expected for return.
725 self_->TransitionFromSuspendedToRunnable();
Alex Light6abd5392017-01-05 17:53:00 -0800726 if (heap->IsGcConcurrentAndMoving()) {
727 heap->DecrementDisableMovingGC(self_);
728 }
Alex Lighta01de592016-11-15 10:43:06 -0800729 return result_;
730 }
731 if (!UpdateClass(art_class.Get(), new_dex_cache.Get())) {
732 // TODO Should have some form of scope to do this.
733 RestoreJavaDexFile(java_dex_file.Get(), original_dex_file_cookie);
734 // Release suspendAll
735 runtime_->GetThreadList()->ResumeAll();
736 // Get back shared mutator lock as expected for return.
737 self_->TransitionFromSuspendedToRunnable();
Alex Light6abd5392017-01-05 17:53:00 -0800738 if (heap->IsGcConcurrentAndMoving()) {
739 heap->DecrementDisableMovingGC(self_);
740 }
Alex Lighta01de592016-11-15 10:43:06 -0800741 return result_;
742 }
Alex Lightdba61482016-12-21 08:20:29 -0800743 // Ensure that obsolete methods are deoptimized. This is needed since optimized methods may have
744 // pointers to their ArtMethod's stashed in registers that they then use to attempt to hit the
745 // DexCache.
746 // TODO This can fail (leave some methods optimized) near runtime methods (including
747 // quick-to-interpreter transition function).
748 // TODO We probably don't need this at all once we have a way to ensure that the
749 // current_art_method is never stashed in a (physical) register by the JIT and lost to the
750 // stack-walker.
751 EnsureObsoleteMethodsAreDeoptimized();
752 // TODO Verify the new Class.
753 // TODO Failure then undo updates to class
754 // TODO Shrink the obsolete method maps if possible?
755 // TODO find appropriate class loader.
Alex Lighta01de592016-11-15 10:43:06 -0800756 // TODO Put this into a scoped thing.
757 runtime_->GetThreadList()->ResumeAll();
758 // Get back shared mutator lock as expected for return.
759 self_->TransitionFromSuspendedToRunnable();
Alex Lightdba61482016-12-21 08:20:29 -0800760 // TODO Do the dex_file_ release at a more reasonable place. This works but it muddles who really
761 // owns the DexFile.
Alex Lighta01de592016-11-15 10:43:06 -0800762 dex_file_.release();
Alex Light6abd5392017-01-05 17:53:00 -0800763 if (heap->IsGcConcurrentAndMoving()) {
764 heap->DecrementDisableMovingGC(self_);
765 }
Alex Lighta01de592016-11-15 10:43:06 -0800766 return OK;
767}
768
769void Redefiner::RestoreJavaDexFile(art::ObjPtr<art::mirror::Object> java_dex_file,
770 art::ObjPtr<art::mirror::LongArray> orig_cookie) {
771 art::ArtField* internal_cookie_field = java_dex_file->GetClass()->FindDeclaredInstanceField(
772 "mInternalCookie", "Ljava/lang/Object;");
773 art::ArtField* cookie_field = java_dex_file->GetClass()->FindDeclaredInstanceField(
774 "mCookie", "Ljava/lang/Object;");
775 art::ObjPtr<art::mirror::LongArray> new_cookie(
776 cookie_field->GetObject(java_dex_file)->AsLongArray());
777 internal_cookie_field->SetObject<false>(java_dex_file, orig_cookie);
778 if (!new_cookie.IsNull()) {
779 cookie_field->SetObject<false>(java_dex_file, orig_cookie);
780 }
781}
782
Alex Light200b9d72016-12-15 11:34:13 -0800783bool Redefiner::UpdateMethods(art::ObjPtr<art::mirror::Class> mclass,
784 art::ObjPtr<art::mirror::DexCache> new_dex_cache,
785 const art::DexFile::ClassDef& class_def) {
Alex Lighta01de592016-11-15 10:43:06 -0800786 art::ClassLinker* linker = runtime_->GetClassLinker();
787 art::PointerSize image_pointer_size = linker->GetImagePointerSize();
Alex Light200b9d72016-12-15 11:34:13 -0800788 const art::DexFile::TypeId& declaring_class_id = dex_file_->GetTypeId(class_def.class_idx_);
Alex Lighta01de592016-11-15 10:43:06 -0800789 const art::DexFile& old_dex_file = mclass->GetDexFile();
Alex Light200b9d72016-12-15 11:34:13 -0800790 // Update methods.
Alex Lighta01de592016-11-15 10:43:06 -0800791 for (art::ArtMethod& method : mclass->GetMethods(image_pointer_size)) {
792 const art::DexFile::StringId* new_name_id = dex_file_->FindStringId(method.GetName());
793 art::dex::TypeIndex method_return_idx =
794 dex_file_->GetIndexForTypeId(*dex_file_->FindTypeId(method.GetReturnTypeDescriptor()));
795 const auto* old_type_list = method.GetParameterTypeList();
796 std::vector<art::dex::TypeIndex> new_type_list;
797 for (uint32_t i = 0; old_type_list != nullptr && i < old_type_list->Size(); i++) {
798 new_type_list.push_back(
799 dex_file_->GetIndexForTypeId(
800 *dex_file_->FindTypeId(
801 old_dex_file.GetTypeDescriptor(
802 old_dex_file.GetTypeId(
803 old_type_list->GetTypeItem(i).type_idx_)))));
804 }
805 const art::DexFile::ProtoId* proto_id = dex_file_->FindProtoId(method_return_idx,
806 new_type_list);
Nicolas Geoffrayf6abcda2016-12-21 09:26:18 +0000807 // TODO Return false, cleanup.
Alex Lightdba61482016-12-21 08:20:29 -0800808 CHECK(proto_id != nullptr || old_type_list == nullptr);
Alex Lighta01de592016-11-15 10:43:06 -0800809 const art::DexFile::MethodId* method_id = dex_file_->FindMethodId(declaring_class_id,
810 *new_name_id,
811 *proto_id);
Nicolas Geoffrayf6abcda2016-12-21 09:26:18 +0000812 // TODO Return false, cleanup.
Alex Lightdba61482016-12-21 08:20:29 -0800813 CHECK(method_id != nullptr);
Alex Lighta01de592016-11-15 10:43:06 -0800814 uint32_t dex_method_idx = dex_file_->GetIndexForMethodId(*method_id);
815 method.SetDexMethodIndex(dex_method_idx);
816 linker->SetEntryPointsToInterpreter(&method);
Alex Light200b9d72016-12-15 11:34:13 -0800817 method.SetCodeItemOffset(dex_file_->FindCodeItemOffset(class_def, dex_method_idx));
Alex Lighta01de592016-11-15 10:43:06 -0800818 method.SetDexCacheResolvedMethods(new_dex_cache->GetResolvedMethods(), image_pointer_size);
819 method.SetDexCacheResolvedTypes(new_dex_cache->GetResolvedTypes(), image_pointer_size);
Alex Lightdba61482016-12-21 08:20:29 -0800820 // Notify the jit that this method is redefined.
821 art::jit::Jit* jit = runtime_->GetJit();
822 if (jit != nullptr) {
823 jit->GetCodeCache()->NotifyMethodRedefined(&method);
824 }
Alex Lighta01de592016-11-15 10:43:06 -0800825 }
Alex Light200b9d72016-12-15 11:34:13 -0800826 return true;
827}
828
829bool Redefiner::UpdateFields(art::ObjPtr<art::mirror::Class> mclass) {
830 // TODO The IFields & SFields pointers should be combined like the methods_ arrays were.
831 for (auto fields_iter : {mclass->GetIFields(), mclass->GetSFields()}) {
832 for (art::ArtField& field : fields_iter) {
833 std::string declaring_class_name;
834 const art::DexFile::TypeId* new_declaring_id =
835 dex_file_->FindTypeId(field.GetDeclaringClass()->GetDescriptor(&declaring_class_name));
836 const art::DexFile::StringId* new_name_id = dex_file_->FindStringId(field.GetName());
837 const art::DexFile::TypeId* new_type_id = dex_file_->FindTypeId(field.GetTypeDescriptor());
838 // TODO Handle error, cleanup.
839 CHECK(new_name_id != nullptr && new_type_id != nullptr && new_declaring_id != nullptr);
840 const art::DexFile::FieldId* new_field_id =
841 dex_file_->FindFieldId(*new_declaring_id, *new_name_id, *new_type_id);
842 CHECK(new_field_id != nullptr);
843 // We only need to update the index since the other data in the ArtField cannot be updated.
844 field.SetDexFieldIndex(dex_file_->GetIndexForFieldId(*new_field_id));
845 }
846 }
847 return true;
848}
849
850// Performs updates to class that will allow us to verify it.
851bool Redefiner::UpdateClass(art::ObjPtr<art::mirror::Class> mclass,
852 art::ObjPtr<art::mirror::DexCache> new_dex_cache) {
853 const art::DexFile::ClassDef* class_def = art::OatFile::OatDexFile::FindClassDef(
854 *dex_file_, class_sig_, art::ComputeModifiedUtf8Hash(class_sig_));
855 if (class_def == nullptr) {
856 RecordFailure(ERR(INVALID_CLASS_FORMAT), "Unable to find ClassDef!");
857 return false;
858 }
859 if (!UpdateMethods(mclass, new_dex_cache, *class_def)) {
860 // TODO Investigate appropriate error types.
861 RecordFailure(ERR(INTERNAL), "Unable to update class methods.");
862 return false;
863 }
864 if (!UpdateFields(mclass)) {
865 // TODO Investigate appropriate error types.
866 RecordFailure(ERR(INTERNAL), "Unable to update class fields.");
867 return false;
868 }
869
Alex Lighta01de592016-11-15 10:43:06 -0800870 // Update the class fields.
871 // Need to update class last since the ArtMethod gets its DexFile from the class (which is needed
872 // to call GetReturnTypeDescriptor and GetParameterTypeList above).
873 mclass->SetDexCache(new_dex_cache.Ptr());
Alex Lighta01de592016-11-15 10:43:06 -0800874 mclass->SetDexClassDefIndex(dex_file_->GetIndexForClassDef(*class_def));
875 mclass->SetDexTypeIndex(dex_file_->GetIndexForTypeId(*dex_file_->FindTypeId(class_sig_)));
876 return true;
877}
878
879bool Redefiner::UpdateJavaDexFile(art::ObjPtr<art::mirror::Object> java_dex_file,
880 art::ObjPtr<art::mirror::LongArray> new_cookie,
881 /*out*/art::ObjPtr<art::mirror::LongArray>* original_cookie) {
882 art::ArtField* internal_cookie_field = java_dex_file->GetClass()->FindDeclaredInstanceField(
883 "mInternalCookie", "Ljava/lang/Object;");
884 art::ArtField* cookie_field = java_dex_file->GetClass()->FindDeclaredInstanceField(
885 "mCookie", "Ljava/lang/Object;");
886 CHECK(internal_cookie_field != nullptr);
887 art::ObjPtr<art::mirror::LongArray> orig_internal_cookie(
888 internal_cookie_field->GetObject(java_dex_file)->AsLongArray());
889 art::ObjPtr<art::mirror::LongArray> orig_cookie(
890 cookie_field->GetObject(java_dex_file)->AsLongArray());
891 internal_cookie_field->SetObject<false>(java_dex_file, new_cookie);
892 *original_cookie = orig_internal_cookie;
893 if (!orig_cookie.IsNull()) {
894 cookie_field->SetObject<false>(java_dex_file, new_cookie);
895 }
896 return true;
897}
898
899// This function does all (java) allocations we need to do for the Class being redefined.
900// TODO Change this name maybe?
901bool Redefiner::EnsureClassAllocationsFinished() {
902 art::StackHandleScope<2> hs(self_);
903 art::Handle<art::mirror::Class> klass(hs.NewHandle(self_->DecodeJObject(klass_)->AsClass()));
904 if (klass.Get() == nullptr) {
905 RecordFailure(ERR(INVALID_CLASS), "Unable to decode class argument!");
906 return false;
907 }
908 // Allocate the classExt
909 art::Handle<art::mirror::ClassExt> ext(hs.NewHandle(klass->EnsureExtDataPresent(self_)));
910 if (ext.Get() == nullptr) {
911 // No memory. Clear exception (it's not useful) and return error.
912 // TODO This doesn't need to be fatal. We could just not support obsolete methods after hitting
913 // this case.
914 self_->AssertPendingOOMException();
915 self_->ClearException();
916 RecordFailure(ERR(OUT_OF_MEMORY), "Could not allocate ClassExt");
917 return false;
918 }
919 // Allocate the 2 arrays that make up the obsolete methods map. Since the contents of the arrays
920 // are only modified when all threads (other than the modifying one) are suspended we don't need
921 // to worry about missing the unsyncronized writes to the array. We do synchronize when setting it
922 // however, since that can happen at any time.
923 // TODO Clear these after we walk the stacks in order to free them in the (likely?) event there
924 // are no obsolete methods.
925 {
926 art::ObjectLock<art::mirror::ClassExt> lock(self_, ext);
927 if (!ext->ExtendObsoleteArrays(
928 self_, klass->GetDeclaredMethodsSlice(art::kRuntimePointerSize).size())) {
929 // OOM. Clear exception and return error.
930 self_->AssertPendingOOMException();
931 self_->ClearException();
932 RecordFailure(ERR(OUT_OF_MEMORY), "Unable to allocate/extend obsolete methods map");
933 return false;
934 }
935 }
936 return true;
937}
938
939} // namespace openjdkjvmti