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 "events-inl.h"
     33 
     34 #include "art_jvmti.h"
     35 #include "base/logging.h"
     36 #include "gc/allocation_listener.h"
     37 #include "gc/gc_pause_listener.h"
     38 #include "gc/heap.h"
     39 #include "handle_scope-inl.h"
     40 #include "instrumentation.h"
     41 #include "jni_env_ext-inl.h"
     42 #include "mirror/class.h"
     43 #include "mirror/object-inl.h"
     44 #include "runtime.h"
     45 #include "ScopedLocalRef.h"
     46 #include "scoped_thread_state_change-inl.h"
     47 #include "thread-inl.h"
     48 
     49 namespace openjdkjvmti {
     50 
     51 bool EventMasks::IsEnabledAnywhere(ArtJvmtiEvent event) {
     52   return global_event_mask.Test(event) || unioned_thread_event_mask.Test(event);
     53 }
     54 
     55 EventMask& EventMasks::GetEventMask(art::Thread* thread) {
     56   if (thread == nullptr) {
     57     return global_event_mask;
     58   }
     59 
     60   for (auto& pair : thread_event_masks) {
     61     const UniqueThread& unique_thread = pair.first;
     62     if (unique_thread.first == thread &&
     63         unique_thread.second == static_cast<uint32_t>(thread->GetTid())) {
     64       return pair.second;
     65     }
     66   }
     67 
     68   // TODO: Remove old UniqueThread with the same pointer, if exists.
     69 
     70   thread_event_masks.emplace_back(UniqueThread(thread, thread->GetTid()), EventMask());
     71   return thread_event_masks.back().second;
     72 }
     73 
     74 EventMask* EventMasks::GetEventMaskOrNull(art::Thread* thread) {
     75   if (thread == nullptr) {
     76     return &global_event_mask;
     77   }
     78 
     79   for (auto& pair : thread_event_masks) {
     80     const UniqueThread& unique_thread = pair.first;
     81     if (unique_thread.first == thread &&
     82         unique_thread.second == static_cast<uint32_t>(thread->GetTid())) {
     83       return &pair.second;
     84     }
     85   }
     86 
     87   return nullptr;
     88 }
     89 
     90 
     91 void EventMasks::EnableEvent(art::Thread* thread, ArtJvmtiEvent event) {
     92   DCHECK(EventMask::EventIsInRange(event));
     93   GetEventMask(thread).Set(event);
     94   if (thread != nullptr) {
     95     unioned_thread_event_mask.Set(event, true);
     96   }
     97 }
     98 
     99 void EventMasks::DisableEvent(art::Thread* thread, ArtJvmtiEvent event) {
    100   DCHECK(EventMask::EventIsInRange(event));
    101   GetEventMask(thread).Set(event, false);
    102   if (thread != nullptr) {
    103     // Regenerate union for the event.
    104     bool union_value = false;
    105     for (auto& pair : thread_event_masks) {
    106       union_value |= pair.second.Test(event);
    107       if (union_value) {
    108         break;
    109       }
    110     }
    111     unioned_thread_event_mask.Set(event, union_value);
    112   }
    113 }
    114 
    115 void EventMasks::HandleChangedCapabilities(const jvmtiCapabilities& caps, bool caps_added) {
    116   if (UNLIKELY(caps.can_retransform_classes == 1)) {
    117     // If we are giving this env the retransform classes cap we need to switch all events of
    118     // NonTransformable to Transformable and vice versa.
    119     ArtJvmtiEvent to_remove = caps_added ? ArtJvmtiEvent::kClassFileLoadHookNonRetransformable
    120                                          : ArtJvmtiEvent::kClassFileLoadHookRetransformable;
    121     ArtJvmtiEvent to_add = caps_added ? ArtJvmtiEvent::kClassFileLoadHookRetransformable
    122                                       : ArtJvmtiEvent::kClassFileLoadHookNonRetransformable;
    123     if (global_event_mask.Test(to_remove)) {
    124       CHECK(!global_event_mask.Test(to_add));
    125       global_event_mask.Set(to_remove, false);
    126       global_event_mask.Set(to_add, true);
    127     }
    128 
    129     if (unioned_thread_event_mask.Test(to_remove)) {
    130       CHECK(!unioned_thread_event_mask.Test(to_add));
    131       unioned_thread_event_mask.Set(to_remove, false);
    132       unioned_thread_event_mask.Set(to_add, true);
    133     }
    134     for (auto thread_mask : thread_event_masks) {
    135       if (thread_mask.second.Test(to_remove)) {
    136         CHECK(!thread_mask.second.Test(to_add));
    137         thread_mask.second.Set(to_remove, false);
    138         thread_mask.second.Set(to_add, true);
    139       }
    140     }
    141   }
    142 }
    143 
    144 void EventHandler::RegisterArtJvmTiEnv(ArtJvmTiEnv* env) {
    145   // Since we never shrink this array we might as well try to fill gaps.
    146   auto it = std::find(envs.begin(), envs.end(), nullptr);
    147   if (it != envs.end()) {
    148     *it = env;
    149   } else {
    150     envs.push_back(env);
    151   }
    152 }
    153 
    154 void EventHandler::RemoveArtJvmTiEnv(ArtJvmTiEnv* env) {
    155   // Since we might be currently iterating over the envs list we cannot actually erase elements.
    156   // Instead we will simply replace them with 'nullptr' and skip them manually.
    157   auto it = std::find(envs.begin(), envs.end(), env);
    158   if (it != envs.end()) {
    159     *it = nullptr;
    160     for (size_t i = static_cast<size_t>(ArtJvmtiEvent::kMinEventTypeVal);
    161          i <= static_cast<size_t>(ArtJvmtiEvent::kMaxEventTypeVal);
    162          ++i) {
    163       RecalculateGlobalEventMask(static_cast<ArtJvmtiEvent>(i));
    164     }
    165   }
    166 }
    167 
    168 static bool IsThreadControllable(ArtJvmtiEvent event) {
    169   switch (event) {
    170     case ArtJvmtiEvent::kVmInit:
    171     case ArtJvmtiEvent::kVmStart:
    172     case ArtJvmtiEvent::kVmDeath:
    173     case ArtJvmtiEvent::kThreadStart:
    174     case ArtJvmtiEvent::kCompiledMethodLoad:
    175     case ArtJvmtiEvent::kCompiledMethodUnload:
    176     case ArtJvmtiEvent::kDynamicCodeGenerated:
    177     case ArtJvmtiEvent::kDataDumpRequest:
    178       return false;
    179 
    180     default:
    181       return true;
    182   }
    183 }
    184 
    185 class JvmtiAllocationListener : public art::gc::AllocationListener {
    186  public:
    187   explicit JvmtiAllocationListener(EventHandler* handler) : handler_(handler) {}
    188 
    189   void ObjectAllocated(art::Thread* self, art::ObjPtr<art::mirror::Object>* obj, size_t byte_count)
    190       OVERRIDE REQUIRES_SHARED(art::Locks::mutator_lock_) {
    191     DCHECK_EQ(self, art::Thread::Current());
    192 
    193     if (handler_->IsEventEnabledAnywhere(ArtJvmtiEvent::kVmObjectAlloc)) {
    194       art::StackHandleScope<1> hs(self);
    195       auto h = hs.NewHandleWrapper(obj);
    196       // jvmtiEventVMObjectAlloc parameters:
    197       //      jvmtiEnv *jvmti_env,
    198       //      JNIEnv* jni_env,
    199       //      jthread thread,
    200       //      jobject object,
    201       //      jclass object_klass,
    202       //      jlong size
    203       art::JNIEnvExt* jni_env = self->GetJniEnv();
    204 
    205       jthread thread_peer;
    206       if (self->IsStillStarting()) {
    207         thread_peer = nullptr;
    208       } else {
    209         thread_peer = jni_env->AddLocalReference<jthread>(self->GetPeer());
    210       }
    211 
    212       ScopedLocalRef<jthread> thread(jni_env, thread_peer);
    213       ScopedLocalRef<jobject> object(
    214           jni_env, jni_env->AddLocalReference<jobject>(*obj));
    215       ScopedLocalRef<jclass> klass(
    216           jni_env, jni_env->AddLocalReference<jclass>(obj->Ptr()->GetClass()));
    217 
    218       handler_->DispatchEvent<ArtJvmtiEvent::kVmObjectAlloc>(self,
    219                                                              reinterpret_cast<JNIEnv*>(jni_env),
    220                                                              thread.get(),
    221                                                              object.get(),
    222                                                              klass.get(),
    223                                                              static_cast<jlong>(byte_count));
    224     }
    225   }
    226 
    227  private:
    228   EventHandler* handler_;
    229 };
    230 
    231 static void SetupObjectAllocationTracking(art::gc::AllocationListener* listener, bool enable) {
    232   // We must not hold the mutator lock here, but if we're in FastJNI, for example, we might. For
    233   // now, do a workaround: (possibly) acquire and release.
    234   art::ScopedObjectAccess soa(art::Thread::Current());
    235   art::ScopedThreadSuspension sts(soa.Self(), art::ThreadState::kSuspended);
    236   if (enable) {
    237     art::Runtime::Current()->GetHeap()->SetAllocationListener(listener);
    238   } else {
    239     art::Runtime::Current()->GetHeap()->RemoveAllocationListener();
    240   }
    241 }
    242 
    243 // Report GC pauses (see spec) as GARBAGE_COLLECTION_START and GARBAGE_COLLECTION_END.
    244 class JvmtiGcPauseListener : public art::gc::GcPauseListener {
    245  public:
    246   explicit JvmtiGcPauseListener(EventHandler* handler)
    247       : handler_(handler),
    248         start_enabled_(false),
    249         finish_enabled_(false) {}
    250 
    251   void StartPause() OVERRIDE {
    252     handler_->DispatchEvent<ArtJvmtiEvent::kGarbageCollectionStart>(nullptr);
    253   }
    254 
    255   void EndPause() OVERRIDE {
    256     handler_->DispatchEvent<ArtJvmtiEvent::kGarbageCollectionFinish>(nullptr);
    257   }
    258 
    259   bool IsEnabled() {
    260     return start_enabled_ || finish_enabled_;
    261   }
    262 
    263   void SetStartEnabled(bool e) {
    264     start_enabled_ = e;
    265   }
    266 
    267   void SetFinishEnabled(bool e) {
    268     finish_enabled_ = e;
    269   }
    270 
    271  private:
    272   EventHandler* handler_;
    273   bool start_enabled_;
    274   bool finish_enabled_;
    275 };
    276 
    277 static void SetupGcPauseTracking(JvmtiGcPauseListener* listener, ArtJvmtiEvent event, bool enable) {
    278   bool old_state = listener->IsEnabled();
    279 
    280   if (event == ArtJvmtiEvent::kGarbageCollectionStart) {
    281     listener->SetStartEnabled(enable);
    282   } else {
    283     listener->SetFinishEnabled(enable);
    284   }
    285 
    286   bool new_state = listener->IsEnabled();
    287 
    288   if (old_state != new_state) {
    289     if (new_state) {
    290       art::Runtime::Current()->GetHeap()->SetGcPauseListener(listener);
    291     } else {
    292       art::Runtime::Current()->GetHeap()->RemoveGcPauseListener();
    293     }
    294   }
    295 }
    296 
    297 // Handle special work for the given event type, if necessary.
    298 void EventHandler::HandleEventType(ArtJvmtiEvent event, bool enable) {
    299   switch (event) {
    300     case ArtJvmtiEvent::kVmObjectAlloc:
    301       SetupObjectAllocationTracking(alloc_listener_.get(), enable);
    302       return;
    303 
    304     case ArtJvmtiEvent::kGarbageCollectionStart:
    305     case ArtJvmtiEvent::kGarbageCollectionFinish:
    306       SetupGcPauseTracking(gc_pause_listener_.get(), event, enable);
    307       return;
    308 
    309     default:
    310       break;
    311   }
    312 }
    313 
    314 // Checks to see if the env has the capabilities associated with the given event.
    315 static bool HasAssociatedCapability(ArtJvmTiEnv* env,
    316                                     ArtJvmtiEvent event) {
    317   jvmtiCapabilities caps = env->capabilities;
    318   switch (event) {
    319     case ArtJvmtiEvent::kBreakpoint:
    320       return caps.can_generate_breakpoint_events == 1;
    321 
    322     case ArtJvmtiEvent::kCompiledMethodLoad:
    323     case ArtJvmtiEvent::kCompiledMethodUnload:
    324       return caps.can_generate_compiled_method_load_events == 1;
    325 
    326     case ArtJvmtiEvent::kException:
    327     case ArtJvmtiEvent::kExceptionCatch:
    328       return caps.can_generate_exception_events == 1;
    329 
    330     case ArtJvmtiEvent::kFieldAccess:
    331       return caps.can_generate_field_access_events == 1;
    332 
    333     case ArtJvmtiEvent::kFieldModification:
    334       return caps.can_generate_field_modification_events == 1;
    335 
    336     case ArtJvmtiEvent::kFramePop:
    337       return caps.can_generate_frame_pop_events == 1;
    338 
    339     case ArtJvmtiEvent::kGarbageCollectionStart:
    340     case ArtJvmtiEvent::kGarbageCollectionFinish:
    341       return caps.can_generate_garbage_collection_events == 1;
    342 
    343     case ArtJvmtiEvent::kMethodEntry:
    344       return caps.can_generate_method_entry_events == 1;
    345 
    346     case ArtJvmtiEvent::kMethodExit:
    347       return caps.can_generate_method_exit_events == 1;
    348 
    349     case ArtJvmtiEvent::kMonitorContendedEnter:
    350     case ArtJvmtiEvent::kMonitorContendedEntered:
    351     case ArtJvmtiEvent::kMonitorWait:
    352     case ArtJvmtiEvent::kMonitorWaited:
    353       return caps.can_generate_monitor_events == 1;
    354 
    355     case ArtJvmtiEvent::kNativeMethodBind:
    356       return caps.can_generate_native_method_bind_events == 1;
    357 
    358     case ArtJvmtiEvent::kObjectFree:
    359       return caps.can_generate_object_free_events == 1;
    360 
    361     case ArtJvmtiEvent::kSingleStep:
    362       return caps.can_generate_single_step_events == 1;
    363 
    364     case ArtJvmtiEvent::kVmObjectAlloc:
    365       return caps.can_generate_vm_object_alloc_events == 1;
    366 
    367     default:
    368       return true;
    369   }
    370 }
    371 
    372 jvmtiError EventHandler::SetEvent(ArtJvmTiEnv* env,
    373                                   art::Thread* thread,
    374                                   ArtJvmtiEvent event,
    375                                   jvmtiEventMode mode) {
    376   if (thread != nullptr) {
    377     art::ThreadState state = thread->GetState();
    378     if (state == art::ThreadState::kStarting ||
    379         state == art::ThreadState::kTerminated ||
    380         thread->IsStillStarting()) {
    381       return ERR(THREAD_NOT_ALIVE);
    382     }
    383     if (!IsThreadControllable(event)) {
    384       return ERR(ILLEGAL_ARGUMENT);
    385     }
    386   }
    387 
    388   if (mode != JVMTI_ENABLE && mode != JVMTI_DISABLE) {
    389     return ERR(ILLEGAL_ARGUMENT);
    390   }
    391 
    392   if (!EventMask::EventIsInRange(event)) {
    393     return ERR(INVALID_EVENT_TYPE);
    394   }
    395 
    396   if (!HasAssociatedCapability(env, event)) {
    397     return ERR(MUST_POSSESS_CAPABILITY);
    398   }
    399 
    400   bool old_state = global_mask.Test(event);
    401 
    402   if (mode == JVMTI_ENABLE) {
    403     env->event_masks.EnableEvent(thread, event);
    404     global_mask.Set(event);
    405   } else {
    406     DCHECK_EQ(mode, JVMTI_DISABLE);
    407 
    408     env->event_masks.DisableEvent(thread, event);
    409     RecalculateGlobalEventMask(event);
    410   }
    411 
    412   bool new_state = global_mask.Test(event);
    413 
    414   // Handle any special work required for the event type.
    415   if (new_state != old_state) {
    416     HandleEventType(event, mode == JVMTI_ENABLE);
    417   }
    418 
    419   return ERR(NONE);
    420 }
    421 
    422 EventHandler::EventHandler() {
    423   alloc_listener_.reset(new JvmtiAllocationListener(this));
    424   gc_pause_listener_.reset(new JvmtiGcPauseListener(this));
    425 }
    426 
    427 EventHandler::~EventHandler() {
    428 }
    429 
    430 }  // namespace openjdkjvmti
    431