1/* 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_class_definition.h" 33 34#include "base/array_slice.h" 35#include "class_linker-inl.h" 36#include "dex_file.h" 37#include "fixed_up_dex_file.h" 38#include "handle_scope-inl.h" 39#include "handle.h" 40#include "mirror/class_ext.h" 41#include "mirror/class-inl.h" 42#include "mirror/object-inl.h" 43#include "reflection.h" 44#include "thread.h" 45 46namespace openjdkjvmti { 47 48bool ArtClassDefinition::IsModified() const { 49 // RedefineClasses calls always are 'modified' since they need to change the original_dex_file of 50 // the class. 51 if (redefined_) { 52 return true; 53 } 54 // Check if the dex file we want to set is the same as the current one. 55 // Unfortunately we need to do this check even if no modifications have been done since it could 56 // be that agents were removed in the mean-time so we still have a different dex file. The dex 57 // checksum means this is likely to be fairly fast. 58 return static_cast<jint>(original_dex_file_.size()) != dex_len_ || 59 memcmp(&original_dex_file_.At(0), dex_data_.get(), dex_len_) != 0; 60} 61 62jvmtiError ArtClassDefinition::InitCommon(ArtJvmTiEnv* env, jclass klass) { 63 JNIEnv* jni_env = GetJniEnv(env); 64 if (jni_env == nullptr) { 65 return ERR(INTERNAL); 66 } 67 art::ScopedObjectAccess soa(jni_env); 68 art::ObjPtr<art::mirror::Class> m_klass(soa.Decode<art::mirror::Class>(klass)); 69 if (m_klass.IsNull()) { 70 return ERR(INVALID_CLASS); 71 } 72 klass_ = klass; 73 loader_ = soa.AddLocalReference<jobject>(m_klass->GetClassLoader()); 74 std::string descriptor_store; 75 std::string descriptor(m_klass->GetDescriptor(&descriptor_store)); 76 name_ = descriptor.substr(1, descriptor.size() - 2); 77 // Android doesn't really have protection domains. 78 protection_domain_ = nullptr; 79 return OK; 80} 81 82// Gets the data surrounding the given class. 83static jvmtiError GetDexDataForRetransformation(ArtJvmTiEnv* env, 84 art::Handle<art::mirror::Class> klass, 85 /*out*/jint* dex_data_len, 86 /*out*/unsigned char** dex_data) 87 REQUIRES_SHARED(art::Locks::mutator_lock_) { 88 art::StackHandleScope<3> hs(art::Thread::Current()); 89 art::Handle<art::mirror::ClassExt> ext(hs.NewHandle(klass->GetExtData())); 90 const art::DexFile* dex_file = nullptr; 91 if (!ext.IsNull()) { 92 art::Handle<art::mirror::Object> orig_dex(hs.NewHandle(ext->GetOriginalDexFile())); 93 if (!orig_dex.IsNull()) { 94 if (orig_dex->IsArrayInstance()) { 95 DCHECK(orig_dex->GetClass()->GetComponentType()->IsPrimitiveByte()); 96 art::Handle<art::mirror::ByteArray> orig_dex_bytes( 97 hs.NewHandle(art::down_cast<art::mirror::ByteArray*>(orig_dex->AsArray()))); 98 *dex_data_len = static_cast<jint>(orig_dex_bytes->GetLength()); 99 return CopyDataIntoJvmtiBuffer( 100 env, 101 reinterpret_cast<const unsigned char*>(orig_dex_bytes->GetData()), 102 *dex_data_len, 103 /*out*/dex_data); 104 } else if (orig_dex->IsDexCache()) { 105 dex_file = orig_dex->AsDexCache()->GetDexFile(); 106 } else { 107 DCHECK(orig_dex->GetClass()->DescriptorEquals("Ljava/lang/Long;")) 108 << "Expected java/lang/Long but found object of type " 109 << orig_dex->GetClass()->PrettyClass(); 110 art::ObjPtr<art::mirror::Class> prim_long_class( 111 art::Runtime::Current()->GetClassLinker()->GetClassRoot( 112 art::ClassLinker::kPrimitiveLong)); 113 art::JValue val; 114 if (!art::UnboxPrimitiveForResult(orig_dex.Get(), prim_long_class, &val)) { 115 // This should never happen. 116 return ERR(INTERNAL); 117 } 118 dex_file = reinterpret_cast<const art::DexFile*>(static_cast<uintptr_t>(val.GetJ())); 119 } 120 } 121 } 122 if (dex_file == nullptr) { 123 dex_file = &klass->GetDexFile(); 124 } 125 std::unique_ptr<FixedUpDexFile> fixed_dex_file(FixedUpDexFile::Create(*dex_file)); 126 *dex_data_len = static_cast<jint>(fixed_dex_file->Size()); 127 return CopyDataIntoJvmtiBuffer(env, 128 fixed_dex_file->Begin(), 129 fixed_dex_file->Size(), 130 /*out*/dex_data); 131} 132 133jvmtiError ArtClassDefinition::Init(ArtJvmTiEnv* env, jclass klass) { 134 jvmtiError res = InitCommon(env, klass); 135 if (res != OK) { 136 return res; 137 } 138 unsigned char* new_data = nullptr; 139 art::Thread* self = art::Thread::Current(); 140 art::ScopedObjectAccess soa(self); 141 art::StackHandleScope<1> hs(self); 142 art::Handle<art::mirror::Class> m_klass(hs.NewHandle(self->DecodeJObject(klass)->AsClass())); 143 res = GetDexDataForRetransformation(env, m_klass, &dex_len_, &new_data); 144 if (res != OK) { 145 return res; 146 } 147 dex_data_ = MakeJvmtiUniquePtr(env, new_data); 148 if (m_klass->GetExtData() == nullptr || m_klass->GetExtData()->GetOriginalDexFile() == nullptr) { 149 // We have never redefined class this yet. Keep track of what the (de-quickened) dex file looks 150 // like so we can tell if anything has changed. Really we would like to just always do the 151 // 'else' block but the fact that we de-quickened stuff screws us over. 152 unsigned char* original_data_memory = nullptr; 153 res = CopyDataIntoJvmtiBuffer(env, dex_data_.get(), dex_len_, &original_data_memory); 154 original_dex_file_memory_ = MakeJvmtiUniquePtr(env, original_data_memory); 155 original_dex_file_ = art::ArraySlice<const unsigned char>(original_data_memory, dex_len_); 156 } else { 157 // We know that we have been redefined at least once (there is an original_dex_file set in 158 // the class) so we can just use the current dex file directly. 159 const art::DexFile& dex_file = m_klass->GetDexFile(); 160 original_dex_file_ = art::ArraySlice<const unsigned char>(dex_file.Begin(), dex_file.Size()); 161 } 162 return res; 163} 164 165jvmtiError ArtClassDefinition::Init(ArtJvmTiEnv* env, const jvmtiClassDefinition& def) { 166 jvmtiError res = InitCommon(env, def.klass); 167 if (res != OK) { 168 return res; 169 } 170 unsigned char* new_data = nullptr; 171 original_dex_file_ = art::ArraySlice<const unsigned char>(def.class_bytes, def.class_byte_count); 172 redefined_ = true; 173 dex_len_ = def.class_byte_count; 174 res = CopyDataIntoJvmtiBuffer(env, def.class_bytes, def.class_byte_count, /*out*/ &new_data); 175 dex_data_ = MakeJvmtiUniquePtr(env, new_data); 176 return res; 177} 178 179} // namespace openjdkjvmti 180