xref: /aosp_15_r20/art/runtime/runtime_callbacks_test.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 
17 #include "runtime_callbacks.h"
18 
19 #include <signal.h>
20 #include <sys/types.h>
21 #include <unistd.h>
22 
23 #include <initializer_list>
24 #include <memory>
25 #include <mutex>
26 #include <string>
27 
28 #include "jni.h"
29 
30 #include "art_method-alloc-inl.h"
31 #include "base/mem_map.h"
32 #include "base/mutex.h"
33 #include "class_linker.h"
34 #include "common_runtime_test.h"
35 #include "dex/class_reference.h"
36 #include "handle.h"
37 #include "handle_scope-inl.h"
38 #include "mirror/class-alloc-inl.h"
39 #include "mirror/class_loader.h"
40 #include "monitor-inl.h"
41 #include "nativehelper/scoped_local_ref.h"
42 #include "obj_ptr-inl.h"
43 #include "runtime.h"
44 #include "scoped_thread_state_change-inl.h"
45 #include "thread-inl.h"
46 #include "thread_list.h"
47 #include "well_known_classes-inl.h"
48 
49 namespace art HIDDEN {
50 
51 class RuntimeCallbacksTest : public CommonRuntimeTest {
52  protected:
SetUp()53   void SetUp() override {
54     CommonRuntimeTest::SetUp();
55 
56     Thread* self = Thread::Current();
57     ScopedObjectAccess soa(self);
58     ScopedThreadSuspension sts(self, ThreadState::kWaitingForDebuggerToAttach);
59     ScopedSuspendAll ssa("RuntimeCallbacksTest SetUp");
60     AddListener();
61   }
62 
TearDown()63   void TearDown() override {
64     {
65       Thread* self = Thread::Current();
66       ScopedObjectAccess soa(self);
67       ScopedThreadSuspension sts(self, ThreadState::kWaitingForDebuggerToAttach);
68       ScopedSuspendAll ssa("RuntimeCallbacksTest TearDown");
69       RemoveListener();
70     }
71 
72     CommonRuntimeTest::TearDown();
73   }
74 
75   virtual void AddListener() REQUIRES(Locks::mutator_lock_) = 0;
76   virtual void RemoveListener() REQUIRES(Locks::mutator_lock_) = 0;
77 
MakeExecutable(ObjPtr<mirror::Class> klass)78   void MakeExecutable(ObjPtr<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_) {
79     CHECK(klass != nullptr);
80     PointerSize pointer_size = class_linker_->GetImagePointerSize();
81     for (auto& m : klass->GetMethods(pointer_size)) {
82       if (!m.IsAbstract()) {
83         Runtime::Current()->GetInstrumentation()->InitializeMethodsCode(&m, /*aot_code=*/ nullptr);
84       }
85     }
86   }
87 };
88 
89 class ThreadLifecycleCallbackRuntimeCallbacksTest : public RuntimeCallbacksTest {
90  public:
PthreadsCallback(void * arg)91   static void* PthreadsCallback([[maybe_unused]] void* arg) {
92     // Attach.
93     Runtime* runtime = Runtime::Current();
94     CHECK(runtime->AttachCurrentThread("ThreadLifecycle test thread", true, nullptr, false));
95 
96     // Detach.
97     runtime->DetachCurrentThread();
98 
99     // Die...
100     return nullptr;
101   }
102 
103  protected:
AddListener()104   void AddListener() override REQUIRES(Locks::mutator_lock_) {
105     Runtime::Current()->GetRuntimeCallbacks()->AddThreadLifecycleCallback(&cb_);
106   }
RemoveListener()107   void RemoveListener() override REQUIRES(Locks::mutator_lock_) {
108     Runtime::Current()->GetRuntimeCallbacks()->RemoveThreadLifecycleCallback(&cb_);
109   }
110 
111   enum CallbackState {
112     kBase,
113     kStarted,
114     kDied,
115     kWrongStart,
116     kWrongDeath,
117   };
118 
119   struct Callback : public ThreadLifecycleCallback {
ThreadStartart::ThreadLifecycleCallbackRuntimeCallbacksTest::Callback120     void ThreadStart(Thread* self) override {
121       {
122         ScopedObjectAccess soa(self);
123         LOG(DEBUG) << "ThreadStart callback for thread: " << self->GetThreadName();
124       }
125       if (state == CallbackState::kBase) {
126         state = CallbackState::kStarted;
127         stored_self = self;
128       } else {
129         state = CallbackState::kWrongStart;
130       }
131     }
132 
ThreadDeathart::ThreadLifecycleCallbackRuntimeCallbacksTest::Callback133     void ThreadDeath(Thread* self) override {
134       {
135         ScopedObjectAccess soa(self);
136         LOG(DEBUG) << "ThreadDeath callback for thread: " << self->GetThreadName();
137       }
138       if (state == CallbackState::kStarted && self == stored_self) {
139         state = CallbackState::kDied;
140       } else {
141         state = CallbackState::kWrongDeath;
142       }
143     }
144 
145     Thread* stored_self;
146     CallbackState state = CallbackState::kBase;
147   };
148 
149   Callback cb_;
150 };
151 
TEST_F(ThreadLifecycleCallbackRuntimeCallbacksTest,ThreadLifecycleCallbackJava)152 TEST_F(ThreadLifecycleCallbackRuntimeCallbacksTest, ThreadLifecycleCallbackJava) {
153   Thread* self = Thread::Current();
154 
155   self->TransitionFromSuspendedToRunnable();
156   bool started = runtime_->Start();
157   ASSERT_TRUE(started);
158   // Make sure the workers are done starting so we don't get callbacks for them.
159   runtime_->WaitForThreadPoolWorkersToStart();
160 
161   // The metrics reporting thread will sometimes be slow to start. Synchronously requesting a
162   // metrics report forces us to wait until the thread has started.
163   runtime_->RequestMetricsReport(/*synchronous=*/true);
164 
165   cb_.state = CallbackState::kBase;  // Ignore main thread attach.
166 
167   ScopedObjectAccess soa(self);
168   MakeExecutable(WellKnownClasses::java_lang_Thread.Get());
169 
170   StackHandleScope<3u> hs(self);
171   Handle<mirror::String> thread_name = hs.NewHandle(
172       mirror::String::AllocFromModifiedUtf8(self, "ThreadLifecycleCallback test thread"));
173   ASSERT_TRUE(thread_name != nullptr);
174 
175   Handle<mirror::Object> thread_group =
176       hs.NewHandle(soa.Decode<mirror::Object>(runtime_->GetMainThreadGroup()));
177   Handle<mirror::Object> thread =
178       WellKnownClasses::java_lang_Thread_init->NewObject<'L', 'L', 'I', 'Z'>(
179           hs, self, thread_group, thread_name, kMinThreadPriority, /*daemon=*/ false);
180   ASSERT_FALSE(self->IsExceptionPending());
181   ASSERT_TRUE(thread != nullptr);
182 
183   ArtMethod* start_method =
184       thread->GetClass()->FindClassMethod("start", "()V", kRuntimePointerSize);
185   ASSERT_TRUE(start_method != nullptr);
186 
187   start_method->InvokeVirtual<'V'>(self, thread.Get());
188   ASSERT_FALSE(self->IsExceptionPending());
189 
190   ArtMethod* join_method = thread->GetClass()->FindClassMethod("join", "()V", kRuntimePointerSize);
191   ASSERT_TRUE(join_method != nullptr);
192 
193   join_method->InvokeFinal<'V'>(self, thread.Get());
194   ASSERT_FALSE(self->IsExceptionPending());
195 
196   EXPECT_EQ(cb_.state, CallbackState::kDied);
197 }
198 
TEST_F(ThreadLifecycleCallbackRuntimeCallbacksTest,ThreadLifecycleCallbackAttach)199 TEST_F(ThreadLifecycleCallbackRuntimeCallbacksTest, ThreadLifecycleCallbackAttach) {
200   std::string error_msg;
201   MemMap stack = MemMap::MapAnonymous("ThreadLifecycleCallback Thread",
202                                       128 * gPageSize,  // Just some small stack.
203                                       PROT_READ | PROT_WRITE,
204                                       /*low_4gb=*/ false,
205                                       &error_msg);
206   ASSERT_TRUE(stack.IsValid()) << error_msg;
207 
208   const char* reason = "ThreadLifecycleCallback test thread";
209   pthread_attr_t attr;
210   CHECK_PTHREAD_CALL(pthread_attr_init, (&attr), reason);
211   CHECK_PTHREAD_CALL(pthread_attr_setstack, (&attr, stack.Begin(), stack.Size()), reason);
212   pthread_t pthread;
213   CHECK_PTHREAD_CALL(pthread_create,
214                      (&pthread,
215                          &attr,
216                          &ThreadLifecycleCallbackRuntimeCallbacksTest::PthreadsCallback,
217                          this),
218                          reason);
219   CHECK_PTHREAD_CALL(pthread_attr_destroy, (&attr), reason);
220 
221   CHECK_PTHREAD_CALL(pthread_join, (pthread, nullptr), "ThreadLifecycleCallback test shutdown");
222 
223   // Detach is not a ThreadDeath event, so we expect to be in state Started.
224   EXPECT_TRUE(cb_.state == CallbackState::kStarted) << static_cast<int>(cb_.state);
225 }
226 
227 class ClassLoadCallbackRuntimeCallbacksTest : public RuntimeCallbacksTest {
228  protected:
AddListener()229   void AddListener() override REQUIRES(Locks::mutator_lock_) {
230     Runtime::Current()->GetRuntimeCallbacks()->AddClassLoadCallback(&cb_);
231   }
RemoveListener()232   void RemoveListener() override REQUIRES(Locks::mutator_lock_) {
233     Runtime::Current()->GetRuntimeCallbacks()->RemoveClassLoadCallback(&cb_);
234   }
235 
Expect(std::initializer_list<const char * > list)236   bool Expect(std::initializer_list<const char*> list) {
237     if (cb_.data.size() != list.size()) {
238       PrintError(list);
239       return false;
240     }
241 
242     if (!std::equal(cb_.data.begin(), cb_.data.end(), list.begin())) {
243       PrintError(list);
244       return false;
245     }
246 
247     return true;
248   }
249 
PrintError(std::initializer_list<const char * > list)250   void PrintError(std::initializer_list<const char*> list) {
251     LOG(ERROR) << "Expected:";
252     for (const char* expected : list) {
253       LOG(ERROR) << "  " << expected;
254     }
255     LOG(ERROR) << "Found:";
256     for (const auto& s : cb_.data) {
257       LOG(ERROR) << "  " << s;
258     }
259   }
260 
261   struct Callback : public ClassLoadCallback {
ClassPreDefineart::ClassLoadCallbackRuntimeCallbacksTest::Callback262     void ClassPreDefine(const char* descriptor,
263                         [[maybe_unused]] Handle<mirror::Class> klass,
264                         [[maybe_unused]] Handle<mirror::ClassLoader> class_loader,
265                         const DexFile& initial_dex_file,
266                         [[maybe_unused]] const dex::ClassDef& initial_class_def,
267                         [[maybe_unused]] /*out*/ DexFile const** final_dex_file,
268                         [[maybe_unused]] /*out*/ dex::ClassDef const** final_class_def) override
269         REQUIRES_SHARED(Locks::mutator_lock_) {
270       const std::string& location = initial_dex_file.GetLocation();
271       std::string event =
272           std::string("PreDefine:") + descriptor + " <" +
273           location.substr(location.rfind('/') + 1, location.size()) + ">";
274       data.push_back(event);
275     }
276 
ClassLoadart::ClassLoadCallbackRuntimeCallbacksTest::Callback277     void ClassLoad(Handle<mirror::Class> klass) override REQUIRES_SHARED(Locks::mutator_lock_) {
278       std::string tmp;
279       std::string event = std::string("Load:") + klass->GetDescriptor(&tmp);
280       data.push_back(event);
281     }
282 
ClassPrepareart::ClassLoadCallbackRuntimeCallbacksTest::Callback283     void ClassPrepare(Handle<mirror::Class> temp_klass,
284                       Handle<mirror::Class> klass) override REQUIRES_SHARED(Locks::mutator_lock_) {
285       std::string tmp, tmp2;
286       std::string event = std::string("Prepare:") + klass->GetDescriptor(&tmp)
287           + "[" + temp_klass->GetDescriptor(&tmp2) + "]";
288       data.push_back(event);
289     }
290 
291     std::vector<std::string> data;
292   };
293 
294   Callback cb_;
295 };
296 
TEST_F(ClassLoadCallbackRuntimeCallbacksTest,ClassLoadCallback)297 TEST_F(ClassLoadCallbackRuntimeCallbacksTest, ClassLoadCallback) {
298   ScopedObjectAccess soa(Thread::Current());
299   jobject jclass_loader = LoadDex("XandY");
300   cb_.data.clear();  // Clear class loading records from `LoadDex()`, if any.
301   VariableSizedHandleScope hs(soa.Self());
302   Handle<mirror::ClassLoader> class_loader(hs.NewHandle(
303       soa.Decode<mirror::ClassLoader>(jclass_loader)));
304 
305   const char* descriptor_y = "LY;";
306   Handle<mirror::Class> h_Y = hs.NewHandle(FindClass(descriptor_y, class_loader));
307   ASSERT_TRUE(h_Y != nullptr);
308 
309   bool expect1 = Expect({ "PreDefine:LY; <art-gtest-jars-XandY.jar>",
310                           "PreDefine:LX; <art-gtest-jars-XandY.jar>",
311                           "Load:LX;",
312                           "Prepare:LX;[LX;]",
313                           "Load:LY;",
314                           "Prepare:LY;[LY;]" });
315   EXPECT_TRUE(expect1);
316 
317   cb_.data.clear();
318 
319   ASSERT_TRUE(class_linker_->EnsureInitialized(Thread::Current(), h_Y, true, true));
320 
321   bool expect2 = Expect({ "PreDefine:LY$Z; <art-gtest-jars-XandY.jar>",
322                           "Load:LY$Z;",
323                           "Prepare:LY$Z;[LY$Z;]" });
324   EXPECT_TRUE(expect2);
325 }
326 
327 class RuntimeSigQuitCallbackRuntimeCallbacksTest : public RuntimeCallbacksTest {
328  protected:
AddListener()329   void AddListener() override REQUIRES(Locks::mutator_lock_) {
330     Runtime::Current()->GetRuntimeCallbacks()->AddRuntimeSigQuitCallback(&cb_);
331   }
RemoveListener()332   void RemoveListener() override REQUIRES(Locks::mutator_lock_) {
333     Runtime::Current()->GetRuntimeCallbacks()->RemoveRuntimeSigQuitCallback(&cb_);
334   }
335 
336   struct Callback : public RuntimeSigQuitCallback {
SigQuitart::RuntimeSigQuitCallbackRuntimeCallbacksTest::Callback337     void SigQuit() override {
338       ++sigquit_count;
339     }
340 
341     size_t sigquit_count = 0;
342   };
343 
344   Callback cb_;
345 };
346 
TEST_F(RuntimeSigQuitCallbackRuntimeCallbacksTest,SigQuit)347 TEST_F(RuntimeSigQuitCallbackRuntimeCallbacksTest, SigQuit) {
348   // The runtime needs to be started for the signal handler.
349   Thread* self = Thread::Current();
350 
351   self->TransitionFromSuspendedToRunnable();
352   bool started = runtime_->Start();
353   ASSERT_TRUE(started);
354 
355   EXPECT_EQ(0u, cb_.sigquit_count);
356 
357   kill(getpid(), SIGQUIT);
358 
359   // Try a few times.
360   for (size_t i = 0; i != 30; ++i) {
361     if (cb_.sigquit_count == 0) {
362       sleep(1);
363     } else {
364       break;
365     }
366   }
367   EXPECT_EQ(1u, cb_.sigquit_count);
368 }
369 
370 class RuntimePhaseCallbackRuntimeCallbacksTest : public RuntimeCallbacksTest {
371  protected:
AddListener()372   void AddListener() override REQUIRES(Locks::mutator_lock_) {
373     Runtime::Current()->GetRuntimeCallbacks()->AddRuntimePhaseCallback(&cb_);
374   }
RemoveListener()375   void RemoveListener() override REQUIRES(Locks::mutator_lock_) {
376     Runtime::Current()->GetRuntimeCallbacks()->RemoveRuntimePhaseCallback(&cb_);
377   }
378 
TearDown()379   void TearDown() override {
380     // Bypass RuntimeCallbacksTest::TearDown, as the runtime is already gone.
381     CommonRuntimeTest::TearDown();
382   }
383 
384   struct Callback : public RuntimePhaseCallback {
NextRuntimePhaseart::RuntimePhaseCallbackRuntimeCallbacksTest::Callback385     void NextRuntimePhase(RuntimePhaseCallback::RuntimePhase p) override {
386       if (p == RuntimePhaseCallback::RuntimePhase::kInitialAgents) {
387         if (start_seen > 0 || init_seen > 0 || death_seen > 0) {
388           LOG(FATAL) << "Unexpected order";
389         }
390         ++initial_agents_seen;
391       } else if (p == RuntimePhaseCallback::RuntimePhase::kStart) {
392         if (init_seen > 0 || death_seen > 0) {
393           LOG(FATAL) << "Init seen before start.";
394         }
395         ++start_seen;
396       } else if (p == RuntimePhaseCallback::RuntimePhase::kInit) {
397         ++init_seen;
398       } else if (p == RuntimePhaseCallback::RuntimePhase::kDeath) {
399         ++death_seen;
400       } else {
401         LOG(FATAL) << "Unknown phase " << static_cast<uint32_t>(p);
402       }
403     }
404 
405     size_t initial_agents_seen = 0;
406     size_t start_seen = 0;
407     size_t init_seen = 0;
408     size_t death_seen = 0;
409   };
410 
411   Callback cb_;
412 };
413 
TEST_F(RuntimePhaseCallbackRuntimeCallbacksTest,Phases)414 TEST_F(RuntimePhaseCallbackRuntimeCallbacksTest, Phases) {
415   ASSERT_EQ(0u, cb_.initial_agents_seen);
416   ASSERT_EQ(0u, cb_.start_seen);
417   ASSERT_EQ(0u, cb_.init_seen);
418   ASSERT_EQ(0u, cb_.death_seen);
419 
420   // Start the runtime.
421   {
422     Thread* self = Thread::Current();
423     self->TransitionFromSuspendedToRunnable();
424     bool started = runtime_->Start();
425     ASSERT_TRUE(started);
426   }
427 
428   ASSERT_EQ(0u, cb_.initial_agents_seen);
429   ASSERT_EQ(1u, cb_.start_seen);
430   ASSERT_EQ(1u, cb_.init_seen);
431   ASSERT_EQ(0u, cb_.death_seen);
432 
433   // Delete the runtime.
434   runtime_.reset();
435 
436   ASSERT_EQ(0u, cb_.initial_agents_seen);
437   ASSERT_EQ(1u, cb_.start_seen);
438   ASSERT_EQ(1u, cb_.init_seen);
439   ASSERT_EQ(1u, cb_.death_seen);
440 }
441 
442 class MonitorWaitCallbacksTest : public RuntimeCallbacksTest {
443  protected:
AddListener()444   void AddListener() override REQUIRES(Locks::mutator_lock_) {
445     Runtime::Current()->GetRuntimeCallbacks()->AddMonitorCallback(&cb_);
446   }
RemoveListener()447   void RemoveListener() override REQUIRES(Locks::mutator_lock_) {
448     Runtime::Current()->GetRuntimeCallbacks()->RemoveMonitorCallback(&cb_);
449   }
450 
451   struct Callback : public MonitorCallback {
IsInterestingObjectart::MonitorWaitCallbacksTest::Callback452     bool IsInterestingObject(ObjPtr<mirror::Object> obj)
453         REQUIRES_SHARED(art::Locks::mutator_lock_) {
454       if (!obj->IsClass()) {
455         return false;
456       }
457       std::lock_guard<std::mutex> lock(ref_guard_);
458       ObjPtr<mirror::Class> k = obj->AsClass();
459       ClassReference test = { &k->GetDexFile(), k->GetDexClassDefIndex() };
460       return ref_ == test;
461     }
462 
SetInterestingObjectart::MonitorWaitCallbacksTest::Callback463     void SetInterestingObject(ObjPtr<mirror::Object> obj)
464         REQUIRES_SHARED(art::Locks::mutator_lock_) {
465       std::lock_guard<std::mutex> lock(ref_guard_);
466       ObjPtr<mirror::Class> k = obj->AsClass();
467       ref_ = { &k->GetDexFile(), k->GetDexClassDefIndex() };
468     }
469 
MonitorContendedLockingart::MonitorWaitCallbacksTest::Callback470     void MonitorContendedLocking([[maybe_unused]] Monitor* mon) override
471         REQUIRES_SHARED(Locks::mutator_lock_) {}
472 
MonitorContendedLockedart::MonitorWaitCallbacksTest::Callback473     void MonitorContendedLocked([[maybe_unused]] Monitor* mon) override
474         REQUIRES_SHARED(Locks::mutator_lock_) {}
475 
ObjectWaitStartart::MonitorWaitCallbacksTest::Callback476     void ObjectWaitStart(Handle<mirror::Object> obj, [[maybe_unused]] int64_t millis) override
477         REQUIRES_SHARED(Locks::mutator_lock_) {
478       if (IsInterestingObject(obj.Get())) {
479         saw_wait_start_ = true;
480       }
481     }
482 
MonitorWaitFinishedart::MonitorWaitCallbacksTest::Callback483     void MonitorWaitFinished(Monitor* m, [[maybe_unused]] bool timed_out) override
484         REQUIRES_SHARED(Locks::mutator_lock_) {
485       if (IsInterestingObject(m->GetObject())) {
486         saw_wait_finished_ = true;
487       }
488     }
489 
490     std::mutex ref_guard_;
491     ClassReference ref_ = {nullptr, 0};
492     bool saw_wait_start_ = false;
493     bool saw_wait_finished_ = false;
494   };
495 
496   Callback cb_;
497 };
498 
499 // TODO It would be good to have more tests for this but due to the multi-threaded nature of the
500 // callbacks this is difficult. For now the run-tests 1931 & 1932 should be sufficient.
TEST_F(MonitorWaitCallbacksTest,WaitUnlocked)501 TEST_F(MonitorWaitCallbacksTest, WaitUnlocked) {
502   ASSERT_FALSE(cb_.saw_wait_finished_);
503   ASSERT_FALSE(cb_.saw_wait_start_);
504   {
505     Thread* self = Thread::Current();
506     self->TransitionFromSuspendedToRunnable();
507     bool started = runtime_->Start();
508     ASSERT_TRUE(started);
509     {
510       ScopedObjectAccess soa(self);
511       cb_.SetInterestingObject(WellKnownClasses::java_util_Collections.Get());
512       Monitor::Wait(
513           self,
514           // Just a random class
515           WellKnownClasses::java_util_Collections.Get(),
516           /*ms=*/0,
517           /*ns=*/0,
518           /*interruptShouldThrow=*/false,
519           /*why=*/ThreadState::kWaiting);
520     }
521   }
522   ASSERT_TRUE(cb_.saw_wait_start_);
523   ASSERT_FALSE(cb_.saw_wait_finished_);
524 }
525 
526 }  // namespace art
527