diff options
author | 2022-02-23 10:50:31 +0000 | |
---|---|---|
committer | 2022-02-24 09:23:01 +0000 | |
commit | c858e5645e26983c63003c8c949aed578a720e38 (patch) | |
tree | ca60d2d1827bf451d0792599cb23b265126e5d12 | |
parent | e94a929c8e884edc007ad791178a23dbea431520 (diff) |
Remove obsolete code on lazy dequickening.
Test: m
Bug: 196414062
Change-Id: I2d5d0c5497a2ee438cad88c2090ae91626a64206
-rw-r--r-- | openjdkjvmti/Android.bp | 1 | ||||
-rw-r--r-- | openjdkjvmti/fixed_up_dex_file.cc | 136 | ||||
-rw-r--r-- | openjdkjvmti/fixed_up_dex_file.h | 83 | ||||
-rw-r--r-- | openjdkjvmti/ti_class.cc | 1 | ||||
-rw-r--r-- | openjdkjvmti/ti_class_definition.cc | 48 | ||||
-rw-r--r-- | openjdkjvmti/ti_class_definition.h | 29 | ||||
-rw-r--r-- | openjdkjvmti/transform.cc | 177 |
7 files changed, 1 insertions, 474 deletions
diff --git a/openjdkjvmti/Android.bp b/openjdkjvmti/Android.bp index 4f49ae5fcb..d01357f801 100644 --- a/openjdkjvmti/Android.bp +++ b/openjdkjvmti/Android.bp @@ -68,7 +68,6 @@ cc_defaults { "alloc_manager.cc", "deopt_manager.cc", "events.cc", - "fixed_up_dex_file.cc", "object_tagging.cc", "OpenjdkJvmTi.cc", "ti_allocator.cc", diff --git a/openjdkjvmti/fixed_up_dex_file.cc b/openjdkjvmti/fixed_up_dex_file.cc deleted file mode 100644 index 9d1fabfd4f..0000000000 --- a/openjdkjvmti/fixed_up_dex_file.cc +++ /dev/null @@ -1,136 +0,0 @@ -/* Copyright (C) 2017 The Android Open Source Project - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This file implements interfaces from the file jvmti.h. This implementation - * is licensed under the same terms as the file jvmti.h. The - * copyright and license information for the file jvmti.h follows. - * - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#include "base/leb128.h" -#include "fixed_up_dex_file.h" -#include "dex/class_accessor-inl.h" -#include "dex/dex_file-inl.h" -#include "dex/dex_file_loader.h" -#include "dex/dex_file_verifier.h" - -// Runtime includes. -#include "dex_container.h" -#include "dex/compact_dex_level.h" -#include "dexlayout.h" -#include "oat_file.h" -#include "vdex_file.h" - -namespace openjdkjvmti { - -static void RecomputeDexChecksum(art::DexFile* dex_file) { - reinterpret_cast<art::DexFile::Header*>(const_cast<uint8_t*>(dex_file->Begin()))->checksum_ = - dex_file->CalculateChecksum(); -} - -static void DCheckVerifyDexFile(const art::DexFile& dex) { - if (art::kIsDebugBuild) { - std::string error; - if (!art::dex::Verify(&dex, - dex.Begin(), - dex.Size(), - "FixedUpDexFile_Verification.dex", - /*verify_checksum=*/ true, - &error)) { - LOG(FATAL) << "Failed to verify de-quickened dex file: " << error; - } - } -} - -std::unique_ptr<FixedUpDexFile> FixedUpDexFile::Create(const art::DexFile& original, - const char* descriptor) { - // Copy the data into mutable memory. - std::vector<unsigned char> data; - std::unique_ptr<const art::DexFile> new_dex_file; - std::string error; - - // Do not use ArtDexFileLoader here. This code runs in a signal handler and - // its stack is too small to invoke the required LocationIsOnSystemFramework - // (b/76429651). Instead, we use DexFileLoader and copy the IsPlatformDexFile - // property from `original` to `new_dex_file`. - const art::DexFileLoader dex_file_loader; - - if (original.IsCompactDexFile() || original.HasHiddenapiClassData()) { - // Since we are supposed to return a standard dex, convert back using dexlayout. It's OK to do - // this before unquickening. - // We also do dex layout for dex files that have hidden API data, as we want to remove that - // data. - art::Options options; - options.compact_dex_level_ = art::CompactDexLevel::kCompactDexLevelNone; - // Add a filter to only include the class that has the matching descriptor. - static constexpr bool kFilterByDescriptor = true; - if (kFilterByDescriptor) { - options.class_filter_.insert(descriptor); - } - art::DexLayout dex_layout(options, - /*info=*/ nullptr, - /*out_file=*/ nullptr, - /*header=*/ nullptr); - std::unique_ptr<art::DexContainer> dex_container; - bool result = dex_layout.ProcessDexFile( - original.GetLocation().c_str(), - &original, - 0, - &dex_container, - &error); - CHECK(result) << "Failed to generate dex file " << error; - art::DexContainer::Section* main_section = dex_container->GetMainSection(); - CHECK_EQ(dex_container->GetDataSection()->Size(), 0u); - data.insert(data.end(), main_section->Begin(), main_section->End()); - } else { - data.resize(original.Size()); - memcpy(data.data(), original.Begin(), original.Size()); - } - - // Open the dex file in the buffer. - new_dex_file = dex_file_loader.Open( - data.data(), - data.size(), - /*location=*/"Unquickening_dexfile.dex", - /*location_checksum=*/0, - /*oat_dex_file=*/nullptr, - /*verify=*/false, - /*verify_checksum=*/false, - &error); - - if (new_dex_file == nullptr) { - LOG(ERROR) << "Unable to open dex file from memory for unquickening! error: " << error; - return nullptr; - } - - new_dex_file->SetHiddenapiDomain(original.GetHiddenapiDomain()); - - RecomputeDexChecksum(const_cast<art::DexFile*>(new_dex_file.get())); - DCheckVerifyDexFile(*new_dex_file); - std::unique_ptr<FixedUpDexFile> ret(new FixedUpDexFile(std::move(new_dex_file), std::move(data))); - return ret; -} - -} // namespace openjdkjvmti diff --git a/openjdkjvmti/fixed_up_dex_file.h b/openjdkjvmti/fixed_up_dex_file.h deleted file mode 100644 index 594e8a7358..0000000000 --- a/openjdkjvmti/fixed_up_dex_file.h +++ /dev/null @@ -1,83 +0,0 @@ -/* Copyright (C) 2017 The Android Open Source Project - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This file implements interfaces from the file jvmti.h. This implementation - * is licensed under the same terms as the file jvmti.h. The - * copyright and license information for the file jvmti.h follows. - * - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#ifndef ART_OPENJDKJVMTI_FIXED_UP_DEX_FILE_H_ -#define ART_OPENJDKJVMTI_FIXED_UP_DEX_FILE_H_ - -#include <memory> -#include <vector> - -#include "jni.h" -#include "jvmti.h" - -#include "base/mutex.h" -#include "dex/dex_file.h" - -namespace openjdkjvmti { - -// A holder for a DexFile that has been 'fixed up' to ensure it is fully compliant with the -// published standard (no internal/quick opcodes, all fields are the defined values, etc). This is -// used to ensure that agents get a consistent dex file regardless of what version of android they -// are running on. -class FixedUpDexFile { - public: - static std::unique_ptr<FixedUpDexFile> Create(const art::DexFile& original, - const char* descriptor); - - const art::DexFile& GetDexFile() { - return *dex_file_; - } - - const unsigned char* Begin() { - return data_.data(); - } - - size_t Size() { - return data_.size(); - } - - private: - explicit FixedUpDexFile(std::unique_ptr<const art::DexFile> fixed_up_dex_file, - std::vector<unsigned char> data) - : dex_file_(std::move(fixed_up_dex_file)), - data_(std::move(data)) {} - - // the fixed up DexFile - std::unique_ptr<const art::DexFile> dex_file_; - // The backing data for dex_file_. - const std::vector<unsigned char> data_; - - DISALLOW_COPY_AND_ASSIGN(FixedUpDexFile); -}; - -} // namespace openjdkjvmti - -#endif // ART_OPENJDKJVMTI_FIXED_UP_DEX_FILE_H_ diff --git a/openjdkjvmti/ti_class.cc b/openjdkjvmti/ti_class.cc index 334588348c..9752fb18d9 100644 --- a/openjdkjvmti/ti_class.cc +++ b/openjdkjvmti/ti_class.cc @@ -51,7 +51,6 @@ #include "dex/dex_file_loader.h" #include "dex/primitive.h" #include "events-inl.h" -#include "fixed_up_dex_file.h" #include "gc/heap-visit-objects-inl.h" #include "gc/heap.h" #include "gc_root.h" diff --git a/openjdkjvmti/ti_class_definition.cc b/openjdkjvmti/ti_class_definition.cc index 2c9cc1cfba..f1f559388d 100644 --- a/openjdkjvmti/ti_class_definition.cc +++ b/openjdkjvmti/ti_class_definition.cc @@ -37,7 +37,6 @@ #include "class_root-inl.h" #include "dex/dex_file.h" #include "dex/art_dex_file_loader.h" -#include "fixed_up_dex_file.h" #include "handle.h" #include "handle_scope-inl.h" #include "mirror/class-inl.h" @@ -48,32 +47,6 @@ namespace openjdkjvmti { -void ArtClassDefinition::InitializeMemory() const { - DCHECK(art::MemMap::kCanReplaceMapping); - VLOG(signals) << "Initializing de-quickened memory for dex file of " << name_; - CHECK(dex_data_mmap_.IsValid()); - CHECK(temp_mmap_.IsValid()); - CHECK_EQ(dex_data_mmap_.GetProtect(), PROT_NONE); - CHECK_EQ(temp_mmap_.GetProtect(), PROT_READ | PROT_WRITE); - - std::string desc = std::string("L") + name_ + ";"; - std::unique_ptr<FixedUpDexFile> - fixed_dex_file(FixedUpDexFile::Create(*initial_dex_file_unquickened_, desc.c_str())); - CHECK(fixed_dex_file.get() != nullptr); - CHECK_LE(fixed_dex_file->Size(), temp_mmap_.Size()); - CHECK_EQ(temp_mmap_.Size(), dex_data_mmap_.Size()); - // Copy the data to the temp mmap. - memcpy(temp_mmap_.Begin(), fixed_dex_file->Begin(), fixed_dex_file->Size()); - - // Move the mmap atomically. - art::MemMap source; - source.swap(temp_mmap_); - std::string error; - CHECK(dex_data_mmap_.ReplaceWith(&source, &error)) << "Failed to replace mmap for " - << name_ << " because " << error; - CHECK(dex_data_mmap_.Protect(PROT_READ)); -} - bool ArtClassDefinition::IsModified() const { // RedefineClasses calls always are 'modified' since they need to change the current_dex_file of // the class. @@ -87,27 +60,6 @@ bool ArtClassDefinition::IsModified() const { return false; } - // The dex_data_ was never touched by the agents. - if (dex_data_mmap_.IsValid() && dex_data_mmap_.GetProtect() == PROT_NONE) { - if (current_dex_file_.data() == dex_data_mmap_.Begin()) { - // the dex_data_ looks like it changed (not equal to current_dex_file_) but we never - // initialized the dex_data_mmap_. This means the new_dex_data was filled in without looking - // at the initial dex_data_. - return true; - } else if (dex_data_.data() == dex_data_mmap_.Begin()) { - // The dex file used to have modifications but they were not added again. - return true; - } else { - // It's not clear what happened. It's possible that the agent got the current dex file data - // from some other source so we need to initialize everything to see if it is the same. - VLOG(signals) << "Lazy dex file for " << name_ << " was never touched but the dex_data_ is " - << "changed! Need to initialize the memory to see if anything changed"; - InitializeMemory(); - } - } - - // We can definitely read current_dex_file_ and dex_file_ without causing page faults. - // Check if the dex file we want to set is the same as the current one. // Unfortunately we need to do this check even if no modifications have been done since it could // be that agents were removed in the mean-time so we still have a different dex file. The dex diff --git a/openjdkjvmti/ti_class_definition.h b/openjdkjvmti/ti_class_definition.h index 3caeed961c..3c1660eb6d 100644 --- a/openjdkjvmti/ti_class_definition.h +++ b/openjdkjvmti/ti_class_definition.h @@ -49,18 +49,12 @@ namespace openjdkjvmti { // redefinition/retransformation function that created it. class ArtClassDefinition { public: - // If we support doing a on-demand dex-dequickening using signal handlers. - static constexpr bool kEnableOnDemandDexDequicken = true; - ArtClassDefinition() : klass_(nullptr), loader_(nullptr), name_(), protection_domain_(nullptr), - dex_data_mmap_(), - temp_mmap_(), dex_data_memory_(), - initial_dex_file_unquickened_(nullptr), dex_data_(), current_dex_memory_(), current_dex_file_(), @@ -107,12 +101,6 @@ class ArtClassDefinition { } } - bool ContainsAddress(uintptr_t ptr) const { - return dex_data_mmap_.IsValid() && - reinterpret_cast<uintptr_t>(dex_data_mmap_.Begin()) <= ptr && - reinterpret_cast<uintptr_t>(dex_data_mmap_.End()) > ptr; - } - bool IsModified() const REQUIRES_SHARED(art::Locks::mutator_lock_); bool IsInitialized() const { @@ -134,13 +122,6 @@ class ArtClassDefinition { return name_; } - bool IsLazyDefinition() const { - DCHECK(IsInitialized()); - return dex_data_mmap_.IsValid() && - dex_data_.data() == dex_data_mmap_.Begin() && - dex_data_mmap_.GetProtect() == PROT_NONE; - } - jobject GetProtectionDomain() const { DCHECK(IsInitialized()); return protection_domain_; @@ -151,8 +132,6 @@ class ArtClassDefinition { return dex_data_; } - void InitializeMemory() const; - private: jvmtiError InitCommon(art::Thread* self, jclass klass); jvmtiError Init(const art::DexFile& dex_file); @@ -162,17 +141,9 @@ class ArtClassDefinition { std::string name_; jobject protection_domain_; - // Mmap that will be filled with the original-dex-file lazily if it needs to be de-quickened or - // de-compact-dex'd - mutable art::MemMap dex_data_mmap_; - // This is a temporary mmap we will use to be able to fill the dex file data atomically. - mutable art::MemMap temp_mmap_; - // A unique_ptr to the current dex_data if it needs to be cleaned up. std::vector<unsigned char> dex_data_memory_; - const art::DexFile* initial_dex_file_unquickened_; - // A ref to the current dex data. This is either dex_data_memory_, or current_dex_file_. This is // what the dex file will be turned into. art::ArrayRef<const unsigned char> dex_data_; diff --git a/openjdkjvmti/transform.cc b/openjdkjvmti/transform.cc index 9c440ef367..1f36da435a 100644 --- a/openjdkjvmti/transform.cc +++ b/openjdkjvmti/transform.cc @@ -70,185 +70,12 @@ namespace openjdkjvmti { -// A FaultHandler that will deal with initializing ClassDefinitions when they are actually needed. -class TransformationFaultHandler final : public art::FaultHandler { - public: - explicit TransformationFaultHandler(art::FaultManager* manager) - : art::FaultHandler(manager), - uninitialized_class_definitions_lock_("JVMTI Initialized class definitions lock", - art::LockLevel::kSignalHandlingLock), - class_definition_initialized_cond_("JVMTI Initialized class definitions condition", - uninitialized_class_definitions_lock_) { - manager->AddHandler(this, /* generated_code= */ false); - } - - ~TransformationFaultHandler() { - art::MutexLock mu(art::Thread::Current(), uninitialized_class_definitions_lock_); - uninitialized_class_definitions_.clear(); - } - - bool Action(int sig, siginfo_t* siginfo, void* context ATTRIBUTE_UNUSED) override { - DCHECK_EQ(sig, SIGSEGV); - art::Thread* self = art::Thread::Current(); - uintptr_t ptr = reinterpret_cast<uintptr_t>(siginfo->si_addr); - if (UNLIKELY(uninitialized_class_definitions_lock_.IsExclusiveHeld(self))) { - // It's possible this is just some other unrelated segv that should be - // handled separately, continue to later handlers. This is likely due to - // running out of memory somewhere along the FixedUpDexFile pipeline and - // is likely unrecoverable. By returning false here though we will get a - // better, more accurate, stack-trace later that points to the actual - // issue. - LOG(WARNING) << "Recursive SEGV occurred during Transformation dequickening at 0x" << std::hex - << ptr; - return false; - } - ArtClassDefinition* res = nullptr; - - { - // NB Technically using a mutex and condition variables here is non-posix compliant but - // everything should be fine since both glibc and bionic implementations of mutexs and - // condition variables work fine so long as the thread was not interrupted during a - // lock/unlock (which it wasn't) on all architectures we care about. - art::MutexLock mu(self, uninitialized_class_definitions_lock_); - auto it = std::find_if(uninitialized_class_definitions_.begin(), - uninitialized_class_definitions_.end(), - [&](const auto op) { return op->ContainsAddress(ptr); }); - if (it != uninitialized_class_definitions_.end()) { - res = *it; - // Remove the class definition. - uninitialized_class_definitions_.erase(it); - // Put it in the initializing list - initializing_class_definitions_.push_back(res); - } else { - // Wait for the ptr to be initialized (if it is currently initializing). - while (DefinitionIsInitializing(ptr)) { - WaitForClassInitializationToFinish(); - } - // Return true (continue with user code) if we find that the definition has been - // initialized. Return false (continue on to next signal handler) if the definition is not - // initialized or found. - return std::find_if(initialized_class_definitions_.begin(), - initialized_class_definitions_.end(), - [&](const auto op) { return op->ContainsAddress(ptr); }) != - initialized_class_definitions_.end(); - } - } - - if (LIKELY(self != nullptr)) { - CHECK_EQ(self->GetState(), art::ThreadState::kNative) - << "Transformation fault handler occurred outside of native mode"; - } - - VLOG(signals) << "Lazy initialization of dex file for transformation of " << res->GetName() - << " during SEGV"; - res->InitializeMemory(); - - { - art::MutexLock mu(self, uninitialized_class_definitions_lock_); - // Move to initialized state and notify waiters. - initializing_class_definitions_.erase(std::find(initializing_class_definitions_.begin(), - initializing_class_definitions_.end(), - res)); - initialized_class_definitions_.push_back(res); - class_definition_initialized_cond_.Broadcast(self); - } - - return true; - } - - void RemoveDefinition(ArtClassDefinition* def) REQUIRES(!uninitialized_class_definitions_lock_) { - art::MutexLock mu(art::Thread::Current(), uninitialized_class_definitions_lock_); - auto it = std::find(uninitialized_class_definitions_.begin(), - uninitialized_class_definitions_.end(), - def); - if (it != uninitialized_class_definitions_.end()) { - uninitialized_class_definitions_.erase(it); - return; - } - while (std::find(initializing_class_definitions_.begin(), - initializing_class_definitions_.end(), - def) != initializing_class_definitions_.end()) { - WaitForClassInitializationToFinish(); - } - it = std::find(initialized_class_definitions_.begin(), - initialized_class_definitions_.end(), - def); - CHECK(it != initialized_class_definitions_.end()) << "Could not find class definition for " - << def->GetName(); - initialized_class_definitions_.erase(it); - } - - void AddArtDefinition(ArtClassDefinition* def) REQUIRES(!uninitialized_class_definitions_lock_) { - DCHECK(def->IsLazyDefinition()); - art::MutexLock mu(art::Thread::Current(), uninitialized_class_definitions_lock_); - uninitialized_class_definitions_.push_back(def); - } - - private: - bool DefinitionIsInitializing(uintptr_t ptr) REQUIRES(uninitialized_class_definitions_lock_) { - return std::find_if(initializing_class_definitions_.begin(), - initializing_class_definitions_.end(), - [&](const auto op) { return op->ContainsAddress(ptr); }) != - initializing_class_definitions_.end(); - } - - void WaitForClassInitializationToFinish() REQUIRES(uninitialized_class_definitions_lock_) { - class_definition_initialized_cond_.Wait(art::Thread::Current()); - } - - art::Mutex uninitialized_class_definitions_lock_ ACQUIRED_BEFORE(art::Locks::abort_lock_); - art::ConditionVariable class_definition_initialized_cond_ - GUARDED_BY(uninitialized_class_definitions_lock_); - - // A list of the class definitions that have a non-readable map. - std::vector<ArtClassDefinition*> uninitialized_class_definitions_ - GUARDED_BY(uninitialized_class_definitions_lock_); - - // A list of class definitions that are currently undergoing unquickening. Threads should wait - // until the definition is no longer in this before returning. - std::vector<ArtClassDefinition*> initializing_class_definitions_ - GUARDED_BY(uninitialized_class_definitions_lock_); - - // A list of class definitions that are already unquickened. Threads should immediately return if - // it is here. - std::vector<ArtClassDefinition*> initialized_class_definitions_ - GUARDED_BY(uninitialized_class_definitions_lock_); -}; - -static TransformationFaultHandler* gTransformFaultHandler = nullptr; static EventHandler* gEventHandler = nullptr; - void Transformer::Register(EventHandler* eh) { - // Although we create this the fault handler is actually owned by the 'art::fault_manager' which - // will take care of destroying it. - if (art::MemMap::kCanReplaceMapping && ArtClassDefinition::kEnableOnDemandDexDequicken) { - gTransformFaultHandler = new TransformationFaultHandler(&art::fault_manager); - } gEventHandler = eh; } -// Simple helper to add and remove the class definition from the fault handler. -class ScopedDefinitionHandler { - public: - explicit ScopedDefinitionHandler(ArtClassDefinition* def) - : def_(def), is_lazy_(def_->IsLazyDefinition()) { - if (is_lazy_) { - gTransformFaultHandler->AddArtDefinition(def_); - } - } - - ~ScopedDefinitionHandler() { - if (is_lazy_) { - gTransformFaultHandler->RemoveDefinition(def_); - } - } - - private: - ArtClassDefinition* def_; - bool is_lazy_; -}; - // Initialize templates. template void Transformer::TransformSingleClassDirect<ArtJvmtiEvent::kClassFileLoadHookNonRetransformable>( @@ -269,10 +96,8 @@ void Transformer::TransformSingleClassDirect(EventHandler* event_handler, kEvent == ArtJvmtiEvent::kStructuralDexFileLoadHook, "bad event type"); // We don't want to do transitions between calling the event and setting the new data so change to - // native state early. This also avoids any problems that the FaultHandler might have in - // determining if an access to the dex_data is from generated code or not. + // native state early. art::ScopedThreadStateChange stsc(self, art::ThreadState::kNative); - ScopedDefinitionHandler handler(def); jint new_len = -1; unsigned char* new_data = nullptr; art::ArrayRef<const unsigned char> dex_data = def->GetDexData(); |