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