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/ScopedLocalRef.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     switch (phase) {
     61       case RuntimePhase::kInitialAgents:
     62         PhaseUtil::current_phase_ = JVMTI_PHASE_PRIMORDIAL;
     63         break;
     64       case RuntimePhase::kStart:
     65         {
     66           art::ScopedThreadSuspension sts(art::Thread::Current(), art::ThreadState::kNative);
     67           event_handler->DispatchEvent<ArtJvmtiEvent::kVmStart>(nullptr, GetJniEnv());
     68           PhaseUtil::current_phase_ = JVMTI_PHASE_START;
     69         }
     70         break;
     71       case RuntimePhase::kInit:
     72         {
     73           ThreadUtil::CacheData();
     74           ScopedLocalRef<jthread> thread(GetJniEnv(), GetCurrentJThread());
     75           art::ScopedThreadSuspension sts(art::Thread::Current(), art::ThreadState::kNative);
     76           event_handler->DispatchEvent<ArtJvmtiEvent::kVmInit>(nullptr, GetJniEnv(), thread.get());
     77           PhaseUtil::current_phase_ = JVMTI_PHASE_LIVE;
     78         }
     79         break;
     80       case RuntimePhase::kDeath:
     81         {
     82           art::ScopedThreadSuspension sts(art::Thread::Current(), art::ThreadState::kNative);
     83           event_handler->DispatchEvent<ArtJvmtiEvent::kVmDeath>(nullptr, GetJniEnv());
     84           PhaseUtil::current_phase_ = JVMTI_PHASE_DEAD;
     85         }
     86         // TODO: Block events now.
     87         break;
     88     }
     89   }
     90 
     91   EventHandler* event_handler = nullptr;
     92 };
     93 
     94 PhaseUtil::PhaseCallback gPhaseCallback;
     95 
     96 jvmtiError PhaseUtil::GetPhase(jvmtiEnv* env ATTRIBUTE_UNUSED, jvmtiPhase* phase_ptr) {
     97   if (phase_ptr == nullptr) {
     98     return ERR(NULL_POINTER);
     99   }
    100   jvmtiPhase now = PhaseUtil::current_phase_;
    101   DCHECK(now == JVMTI_PHASE_ONLOAD ||
    102          now == JVMTI_PHASE_PRIMORDIAL ||
    103          now == JVMTI_PHASE_START ||
    104          now == JVMTI_PHASE_LIVE ||
    105          now == JVMTI_PHASE_DEAD);
    106   *phase_ptr = now;
    107   return ERR(NONE);
    108 }
    109 
    110 bool PhaseUtil::IsLivePhase() {
    111   jvmtiPhase now = PhaseUtil::current_phase_;
    112   DCHECK(now == JVMTI_PHASE_ONLOAD ||
    113          now == JVMTI_PHASE_PRIMORDIAL ||
    114          now == JVMTI_PHASE_START ||
    115          now == JVMTI_PHASE_LIVE ||
    116          now == JVMTI_PHASE_DEAD);
    117   return now == JVMTI_PHASE_LIVE;
    118 }
    119 
    120 void PhaseUtil::SetToOnLoad() {
    121   DCHECK_EQ(0u, static_cast<size_t>(PhaseUtil::current_phase_));
    122   PhaseUtil::current_phase_ = JVMTI_PHASE_ONLOAD;
    123 }
    124 
    125 void PhaseUtil::SetToPrimordial() {
    126   DCHECK_EQ(static_cast<size_t>(JVMTI_PHASE_ONLOAD), static_cast<size_t>(PhaseUtil::current_phase_));
    127   PhaseUtil::current_phase_ = JVMTI_PHASE_ONLOAD;
    128 }
    129 
    130 void PhaseUtil::SetToLive() {
    131   DCHECK_EQ(static_cast<size_t>(0), static_cast<size_t>(PhaseUtil::current_phase_));
    132   ThreadUtil::CacheData();
    133   PhaseUtil::current_phase_ = JVMTI_PHASE_LIVE;
    134 }
    135 
    136 void PhaseUtil::Register(EventHandler* handler) {
    137   gPhaseCallback.event_handler = handler;
    138   art::ScopedThreadStateChange stsc(art::Thread::Current(),
    139                                     art::ThreadState::kWaitingForDebuggerToAttach);
    140   art::ScopedSuspendAll ssa("Add phase callback");
    141   art::Runtime::Current()->GetRuntimeCallbacks()->AddRuntimePhaseCallback(&gPhaseCallback);
    142 }
    143 
    144 void PhaseUtil::Unregister() {
    145   art::ScopedThreadStateChange stsc(art::Thread::Current(),
    146                                     art::ThreadState::kWaitingForDebuggerToAttach);
    147   art::ScopedSuspendAll ssa("Remove phase callback");
    148   art::Runtime::Current()->GetRuntimeCallbacks()->RemoveRuntimePhaseCallback(&gPhaseCallback);
    149 }
    150 
    151 jvmtiPhase PhaseUtil::GetPhaseUnchecked() {
    152   return PhaseUtil::current_phase_;
    153 }
    154 
    155 }  // namespace openjdkjvmti
    156