Home | History | Annotate | Download | only in openjdkjvmti
      1 /* Copyright (C) 2017 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_phase.h"
     33 
     34 #include "art_jvmti.h"
     35 #include "base/macros.h"
     36 #include "events-inl.h"
     37 #include "nativehelper/scoped_local_ref.h"
     38 #include "runtime.h"
     39 #include "runtime_callbacks.h"
     40 #include "scoped_thread_state_change-inl.h"
     41 #include "thread-current-inl.h"
     42 #include "thread_list.h"
     43 #include "ti_thread.h"
     44 
     45 namespace openjdkjvmti {
     46 
     47 jvmtiPhase PhaseUtil::current_phase_ = static_cast<jvmtiPhase>(0);
     48 
     49 struct PhaseUtil::PhaseCallback : public art::RuntimePhaseCallback {
     50   inline static JNIEnv* GetJniEnv() {
     51     return reinterpret_cast<JNIEnv*>(art::Thread::Current()->GetJniEnv());
     52   }
     53 
     54   inline static jthread GetCurrentJThread() {
     55     art::ScopedObjectAccess soa(art::Thread::Current());
     56     return soa.AddLocalReference<jthread>(soa.Self()->GetPeer());
     57   }
     58 
     59   void NextRuntimePhase(RuntimePhase phase) REQUIRES_SHARED(art::Locks::mutator_lock_) OVERRIDE {
     60     art::Thread* self = art::Thread::Current();
     61     switch (phase) {
     62       case RuntimePhase::kInitialAgents:
     63         PhaseUtil::current_phase_ = JVMTI_PHASE_PRIMORDIAL;
     64         break;
     65       case RuntimePhase::kStart:
     66         {
     67           PhaseUtil::current_phase_ = JVMTI_PHASE_START;
     68           event_handler->DispatchEvent<ArtJvmtiEvent::kVmStart>(self, GetJniEnv());
     69         }
     70         break;
     71       case RuntimePhase::kInit:
     72         {
     73           ThreadUtil::CacheData();
     74           PhaseUtil::current_phase_ = JVMTI_PHASE_LIVE;
     75           {
     76             ScopedLocalRef<jthread> thread(GetJniEnv(), GetCurrentJThread());
     77             event_handler->DispatchEvent<ArtJvmtiEvent::kVmInit>(self, GetJniEnv(), thread.get());
     78           }
     79           // We need to have these events be ordered to match behavior expected by some real-world
     80           // agents. The spec does not really require this but compatibility is a useful property to
     81           // maintain.
     82           ThreadUtil::VMInitEventSent();
     83         }
     84         break;
     85       case RuntimePhase::kDeath:
     86         {
     87           event_handler->DispatchEvent<ArtJvmtiEvent::kVmDeath>(self, GetJniEnv());
     88           PhaseUtil::current_phase_ = JVMTI_PHASE_DEAD;
     89         }
     90         // TODO: Block events now.
     91         break;
     92     }
     93   }
     94 
     95   EventHandler* event_handler = nullptr;
     96 };
     97 
     98 PhaseUtil::PhaseCallback gPhaseCallback;
     99 
    100 jvmtiError PhaseUtil::GetPhase(jvmtiEnv* env ATTRIBUTE_UNUSED, jvmtiPhase* phase_ptr) {
    101   if (phase_ptr == nullptr) {
    102     return ERR(NULL_POINTER);
    103   }
    104   jvmtiPhase now = PhaseUtil::current_phase_;
    105   DCHECK(now == JVMTI_PHASE_ONLOAD ||
    106          now == JVMTI_PHASE_PRIMORDIAL ||
    107          now == JVMTI_PHASE_START ||
    108          now == JVMTI_PHASE_LIVE ||
    109          now == JVMTI_PHASE_DEAD);
    110   *phase_ptr = now;
    111   return ERR(NONE);
    112 }
    113 
    114 bool PhaseUtil::IsLivePhase() {
    115   jvmtiPhase now = PhaseUtil::current_phase_;
    116   DCHECK(now == JVMTI_PHASE_ONLOAD ||
    117          now == JVMTI_PHASE_PRIMORDIAL ||
    118          now == JVMTI_PHASE_START ||
    119          now == JVMTI_PHASE_LIVE ||
    120          now == JVMTI_PHASE_DEAD);
    121   return now == JVMTI_PHASE_LIVE;
    122 }
    123 
    124 void PhaseUtil::SetToOnLoad() {
    125   DCHECK_EQ(0u, static_cast<size_t>(PhaseUtil::current_phase_));
    126   PhaseUtil::current_phase_ = JVMTI_PHASE_ONLOAD;
    127 }
    128 
    129 void PhaseUtil::SetToPrimordial() {
    130   DCHECK_EQ(static_cast<size_t>(JVMTI_PHASE_ONLOAD), static_cast<size_t>(PhaseUtil::current_phase_));
    131   PhaseUtil::current_phase_ = JVMTI_PHASE_ONLOAD;
    132 }
    133 
    134 void PhaseUtil::SetToLive() {
    135   DCHECK_EQ(static_cast<size_t>(0), static_cast<size_t>(PhaseUtil::current_phase_));
    136   ThreadUtil::CacheData();
    137   PhaseUtil::current_phase_ = JVMTI_PHASE_LIVE;
    138 }
    139 
    140 void PhaseUtil::Register(EventHandler* handler) {
    141   gPhaseCallback.event_handler = handler;
    142   art::ScopedThreadStateChange stsc(art::Thread::Current(),
    143                                     art::ThreadState::kWaitingForDebuggerToAttach);
    144   art::ScopedSuspendAll ssa("Add phase callback");
    145   art::Runtime::Current()->GetRuntimeCallbacks()->AddRuntimePhaseCallback(&gPhaseCallback);
    146 }
    147 
    148 void PhaseUtil::Unregister() {
    149   art::ScopedThreadStateChange stsc(art::Thread::Current(),
    150                                     art::ThreadState::kWaitingForDebuggerToAttach);
    151   art::ScopedSuspendAll ssa("Remove phase callback");
    152   art::Runtime::Current()->GetRuntimeCallbacks()->RemoveRuntimePhaseCallback(&gPhaseCallback);
    153 }
    154 
    155 jvmtiPhase PhaseUtil::GetPhaseUnchecked() {
    156   return PhaseUtil::current_phase_;
    157 }
    158 
    159 }  // namespace openjdkjvmti
    160