Home | History | Annotate | Download | only in openjdkjvmti
      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 
     46 namespace openjdkjvmti {
     47 
     48 bool 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 
     62 jvmtiError 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.
     83 static 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 
    133 jvmtiError 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 
    165 jvmtiError 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