2 * Copyright (C) 2017 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "runtime_callbacks.h"
21 #include <sys/types.h>
24 #include <initializer_list>
28 #include "art_method-inl.h"
29 #include "base/mutex.h"
30 #include "class_linker.h"
31 #include "common_runtime_test.h"
33 #include "handle_scope-inl.h"
35 #include "mirror/class-inl.h"
36 #include "mirror/class_loader.h"
39 #include "scoped_thread_state_change-inl.h"
40 #include "ScopedLocalRef.h"
41 #include "thread-inl.h"
42 #include "thread_list.h"
43 #include "well_known_classes.h"
47 class RuntimeCallbacksTest : public CommonRuntimeTest {
49 void SetUp() OVERRIDE {
50 CommonRuntimeTest::SetUp();
52 Thread* self = Thread::Current();
53 ScopedObjectAccess soa(self);
54 ScopedThreadSuspension sts(self, kWaitingForDebuggerToAttach);
55 ScopedSuspendAll ssa("RuntimeCallbacksTest SetUp");
59 void TearDown() OVERRIDE {
61 Thread* self = Thread::Current();
62 ScopedObjectAccess soa(self);
63 ScopedThreadSuspension sts(self, kWaitingForDebuggerToAttach);
64 ScopedSuspendAll ssa("RuntimeCallbacksTest TearDown");
68 CommonRuntimeTest::TearDown();
71 virtual void AddListener() REQUIRES(Locks::mutator_lock_) = 0;
72 virtual void RemoveListener() REQUIRES(Locks::mutator_lock_) = 0;
74 void MakeExecutable(ObjPtr<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_) {
75 CHECK(klass != nullptr);
76 PointerSize pointer_size = class_linker_->GetImagePointerSize();
77 for (auto& m : klass->GetMethods(pointer_size)) {
78 if (!m.IsAbstract()) {
79 class_linker_->SetEntryPointsToInterpreter(&m);
85 class ThreadLifecycleCallbackRuntimeCallbacksTest : public RuntimeCallbacksTest {
87 static void* PthreadsCallback(void* arg ATTRIBUTE_UNUSED) {
89 Runtime* runtime = Runtime::Current();
90 CHECK(runtime->AttachCurrentThread("ThreadLifecycle test thread", true, nullptr, false));
93 runtime->DetachCurrentThread();
100 void AddListener() OVERRIDE REQUIRES(Locks::mutator_lock_) {
101 Runtime::Current()->GetRuntimeCallbacks()->AddThreadLifecycleCallback(&cb_);
103 void RemoveListener() OVERRIDE REQUIRES(Locks::mutator_lock_) {
104 Runtime::Current()->GetRuntimeCallbacks()->RemoveThreadLifecycleCallback(&cb_);
115 struct Callback : public ThreadLifecycleCallback {
116 void ThreadStart(Thread* self) OVERRIDE {
117 if (state == CallbackState::kBase) {
118 state = CallbackState::kStarted;
121 state = CallbackState::kWrongStart;
125 void ThreadDeath(Thread* self) OVERRIDE {
126 if (state == CallbackState::kStarted && self == stored_self) {
127 state = CallbackState::kDied;
129 state = CallbackState::kWrongDeath;
134 CallbackState state = CallbackState::kBase;
140 TEST_F(ThreadLifecycleCallbackRuntimeCallbacksTest, ThreadLifecycleCallbackJava) {
141 Thread* self = Thread::Current();
143 self->TransitionFromSuspendedToRunnable();
144 bool started = runtime_->Start();
145 ASSERT_TRUE(started);
147 cb_.state = CallbackState::kBase; // Ignore main thread attach.
150 ScopedObjectAccess soa(self);
151 MakeExecutable(soa.Decode<mirror::Class>(WellKnownClasses::java_lang_Thread));
154 JNIEnv* env = self->GetJniEnv();
156 ScopedLocalRef<jobject> thread_name(env,
157 env->NewStringUTF("ThreadLifecycleCallback test thread"));
158 ASSERT_TRUE(thread_name.get() != nullptr);
160 ScopedLocalRef<jobject> thread(env, env->AllocObject(WellKnownClasses::java_lang_Thread));
161 ASSERT_TRUE(thread.get() != nullptr);
163 env->CallNonvirtualVoidMethod(thread.get(),
164 WellKnownClasses::java_lang_Thread,
165 WellKnownClasses::java_lang_Thread_init,
166 runtime_->GetMainThreadGroup(),
170 ASSERT_FALSE(env->ExceptionCheck());
172 jmethodID start_id = env->GetMethodID(WellKnownClasses::java_lang_Thread, "start", "()V");
173 ASSERT_TRUE(start_id != nullptr);
175 env->CallVoidMethod(thread.get(), start_id);
176 ASSERT_FALSE(env->ExceptionCheck());
178 jmethodID join_id = env->GetMethodID(WellKnownClasses::java_lang_Thread, "join", "()V");
179 ASSERT_TRUE(join_id != nullptr);
181 env->CallVoidMethod(thread.get(), join_id);
182 ASSERT_FALSE(env->ExceptionCheck());
184 EXPECT_TRUE(cb_.state == CallbackState::kDied) << static_cast<int>(cb_.state);
187 TEST_F(ThreadLifecycleCallbackRuntimeCallbacksTest, ThreadLifecycleCallbackAttach) {
188 std::string error_msg;
189 std::unique_ptr<MemMap> stack(MemMap::MapAnonymous("ThreadLifecycleCallback Thread",
191 128 * kPageSize, // Just some small stack.
192 PROT_READ | PROT_WRITE,
196 ASSERT_FALSE(stack == nullptr) << error_msg;
198 const char* reason = "ThreadLifecycleCallback test thread";
200 CHECK_PTHREAD_CALL(pthread_attr_init, (&attr), reason);
201 CHECK_PTHREAD_CALL(pthread_attr_setstack, (&attr, stack->Begin(), stack->Size()), reason);
203 CHECK_PTHREAD_CALL(pthread_create,
206 &ThreadLifecycleCallbackRuntimeCallbacksTest::PthreadsCallback,
209 CHECK_PTHREAD_CALL(pthread_attr_destroy, (&attr), reason);
211 CHECK_PTHREAD_CALL(pthread_join, (pthread, nullptr), "ThreadLifecycleCallback test shutdown");
213 // Detach is not a ThreadDeath event, so we expect to be in state Started.
214 EXPECT_TRUE(cb_.state == CallbackState::kStarted) << static_cast<int>(cb_.state);
217 class ClassLoadCallbackRuntimeCallbacksTest : public RuntimeCallbacksTest {
219 void AddListener() OVERRIDE REQUIRES(Locks::mutator_lock_) {
220 Runtime::Current()->GetRuntimeCallbacks()->AddClassLoadCallback(&cb_);
222 void RemoveListener() OVERRIDE REQUIRES(Locks::mutator_lock_) {
223 Runtime::Current()->GetRuntimeCallbacks()->RemoveClassLoadCallback(&cb_);
226 bool Expect(std::initializer_list<const char*> list) {
227 if (cb_.data.size() != list.size()) {
232 if (!std::equal(cb_.data.begin(), cb_.data.end(), list.begin())) {
240 void PrintError(std::initializer_list<const char*> list) {
241 LOG(ERROR) << "Expected:";
242 for (const char* expected : list) {
243 LOG(ERROR) << " " << expected;
245 LOG(ERROR) << "Found:";
246 for (const auto& s : cb_.data) {
247 LOG(ERROR) << " " << s;
251 struct Callback : public ClassLoadCallback {
252 virtual void ClassPreDefine(const char* descriptor,
253 Handle<mirror::Class> klass ATTRIBUTE_UNUSED,
254 Handle<mirror::ClassLoader> class_loader ATTRIBUTE_UNUSED,
255 const DexFile& initial_dex_file,
256 const DexFile::ClassDef& initial_class_def ATTRIBUTE_UNUSED,
257 /*out*/DexFile const** final_dex_file ATTRIBUTE_UNUSED,
258 /*out*/DexFile::ClassDef const** final_class_def ATTRIBUTE_UNUSED)
259 OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
260 std::string location(initial_dex_file.GetLocation());
262 std::string("PreDefine:") + descriptor + " <" +
263 location.substr(location.rfind("/") + 1, location.size()) + ">";
264 data.push_back(event);
267 void ClassLoad(Handle<mirror::Class> klass) OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
269 std::string event = std::string("Load:") + klass->GetDescriptor(&tmp);
270 data.push_back(event);
273 void ClassPrepare(Handle<mirror::Class> temp_klass,
274 Handle<mirror::Class> klass) OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
275 std::string tmp, tmp2;
276 std::string event = std::string("Prepare:") + klass->GetDescriptor(&tmp)
277 + "[" + temp_klass->GetDescriptor(&tmp2) + "]";
278 data.push_back(event);
281 std::vector<std::string> data;
287 TEST_F(ClassLoadCallbackRuntimeCallbacksTest, ClassLoadCallback) {
288 ScopedObjectAccess soa(Thread::Current());
289 jobject jclass_loader = LoadDex("XandY");
290 VariableSizedHandleScope hs(soa.Self());
291 Handle<mirror::ClassLoader> class_loader(hs.NewHandle(
292 soa.Decode<mirror::ClassLoader>(jclass_loader)));
294 const char* descriptor_y = "LY;";
295 Handle<mirror::Class> h_Y(
296 hs.NewHandle(class_linker_->FindClass(soa.Self(), descriptor_y, class_loader)));
297 ASSERT_TRUE(h_Y != nullptr);
299 bool expect1 = Expect({ "PreDefine:LY; <art-gtest-XandY.jar>",
300 "PreDefine:LX; <art-gtest-XandY.jar>",
304 "Prepare:LY;[LY;]" });
305 EXPECT_TRUE(expect1);
309 ASSERT_TRUE(class_linker_->EnsureInitialized(Thread::Current(), h_Y, true, true));
311 bool expect2 = Expect({ "PreDefine:LY$Z; <art-gtest-XandY.jar>",
313 "Prepare:LY$Z;[LY$Z;]" });
314 EXPECT_TRUE(expect2);
317 class RuntimeSigQuitCallbackRuntimeCallbacksTest : public RuntimeCallbacksTest {
319 void AddListener() OVERRIDE REQUIRES(Locks::mutator_lock_) {
320 Runtime::Current()->GetRuntimeCallbacks()->AddRuntimeSigQuitCallback(&cb_);
322 void RemoveListener() OVERRIDE REQUIRES(Locks::mutator_lock_) {
323 Runtime::Current()->GetRuntimeCallbacks()->RemoveRuntimeSigQuitCallback(&cb_);
326 struct Callback : public RuntimeSigQuitCallback {
327 void SigQuit() OVERRIDE {
331 size_t sigquit_count = 0;
337 TEST_F(RuntimeSigQuitCallbackRuntimeCallbacksTest, SigQuit) {
338 // The runtime needs to be started for the signal handler.
339 Thread* self = Thread::Current();
341 self->TransitionFromSuspendedToRunnable();
342 bool started = runtime_->Start();
343 ASSERT_TRUE(started);
345 EXPECT_EQ(0u, cb_.sigquit_count);
347 kill(getpid(), SIGQUIT);
350 for (size_t i = 0; i != 30; ++i) {
351 if (cb_.sigquit_count == 0) {
357 EXPECT_EQ(1u, cb_.sigquit_count);
360 class RuntimePhaseCallbackRuntimeCallbacksTest : public RuntimeCallbacksTest {
362 void AddListener() OVERRIDE REQUIRES(Locks::mutator_lock_) {
363 Runtime::Current()->GetRuntimeCallbacks()->AddRuntimePhaseCallback(&cb_);
365 void RemoveListener() OVERRIDE REQUIRES(Locks::mutator_lock_) {
366 Runtime::Current()->GetRuntimeCallbacks()->RemoveRuntimePhaseCallback(&cb_);
369 void TearDown() OVERRIDE {
370 // Bypass RuntimeCallbacksTest::TearDown, as the runtime is already gone.
371 CommonRuntimeTest::TearDown();
374 struct Callback : public RuntimePhaseCallback {
375 void NextRuntimePhase(RuntimePhaseCallback::RuntimePhase p) OVERRIDE {
376 if (p == RuntimePhaseCallback::RuntimePhase::kInitialAgents) {
377 if (start_seen > 0 || init_seen > 0 || death_seen > 0) {
378 LOG(FATAL) << "Unexpected order";
380 ++initial_agents_seen;
381 } else if (p == RuntimePhaseCallback::RuntimePhase::kStart) {
382 if (init_seen > 0 || death_seen > 0) {
383 LOG(FATAL) << "Init seen before start.";
386 } else if (p == RuntimePhaseCallback::RuntimePhase::kInit) {
388 } else if (p == RuntimePhaseCallback::RuntimePhase::kDeath) {
391 LOG(FATAL) << "Unknown phase " << static_cast<uint32_t>(p);
395 size_t initial_agents_seen = 0;
396 size_t start_seen = 0;
397 size_t init_seen = 0;
398 size_t death_seen = 0;
404 TEST_F(RuntimePhaseCallbackRuntimeCallbacksTest, Phases) {
405 ASSERT_EQ(0u, cb_.initial_agents_seen);
406 ASSERT_EQ(0u, cb_.start_seen);
407 ASSERT_EQ(0u, cb_.init_seen);
408 ASSERT_EQ(0u, cb_.death_seen);
410 // Start the runtime.
412 Thread* self = Thread::Current();
413 self->TransitionFromSuspendedToRunnable();
414 bool started = runtime_->Start();
415 ASSERT_TRUE(started);
418 ASSERT_EQ(0u, cb_.initial_agents_seen);
419 ASSERT_EQ(1u, cb_.start_seen);
420 ASSERT_EQ(1u, cb_.init_seen);
421 ASSERT_EQ(0u, cb_.death_seen);
423 // Delete the runtime.
426 ASSERT_EQ(0u, cb_.initial_agents_seen);
427 ASSERT_EQ(1u, cb_.start_seen);
428 ASSERT_EQ(1u, cb_.init_seen);
429 ASSERT_EQ(1u, cb_.death_seen);