OSDN Git Service

Differentiate between native alloc and normal background GC
[android-x86/art.git] / runtime / runtime_callbacks_test.cc
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 "jni.h"
20 #include <signal.h>
21 #include <sys/types.h>
22 #include <unistd.h>
23
24 #include <initializer_list>
25 #include <memory>
26 #include <string>
27
28 #include "art_method-inl.h"
29 #include "base/mutex.h"
30 #include "class_linker.h"
31 #include "common_runtime_test.h"
32 #include "handle.h"
33 #include "handle_scope-inl.h"
34 #include "mem_map.h"
35 #include "mirror/class-inl.h"
36 #include "mirror/class_loader.h"
37 #include "obj_ptr.h"
38 #include "runtime.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"
44
45 namespace art {
46
47 class RuntimeCallbacksTest : public CommonRuntimeTest {
48  protected:
49   void SetUp() OVERRIDE {
50     CommonRuntimeTest::SetUp();
51
52     Thread* self = Thread::Current();
53     ScopedObjectAccess soa(self);
54     ScopedThreadSuspension sts(self, kWaitingForDebuggerToAttach);
55     ScopedSuspendAll ssa("RuntimeCallbacksTest SetUp");
56     AddListener();
57   }
58
59   void TearDown() OVERRIDE {
60     {
61       Thread* self = Thread::Current();
62       ScopedObjectAccess soa(self);
63       ScopedThreadSuspension sts(self, kWaitingForDebuggerToAttach);
64       ScopedSuspendAll ssa("RuntimeCallbacksTest TearDown");
65       RemoveListener();
66     }
67
68     CommonRuntimeTest::TearDown();
69   }
70
71   virtual void AddListener() REQUIRES(Locks::mutator_lock_) = 0;
72   virtual void RemoveListener() REQUIRES(Locks::mutator_lock_) = 0;
73
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);
80       }
81     }
82   }
83 };
84
85 class ThreadLifecycleCallbackRuntimeCallbacksTest : public RuntimeCallbacksTest {
86  public:
87   static void* PthreadsCallback(void* arg ATTRIBUTE_UNUSED) {
88     // Attach.
89     Runtime* runtime = Runtime::Current();
90     CHECK(runtime->AttachCurrentThread("ThreadLifecycle test thread", true, nullptr, false));
91
92     // Detach.
93     runtime->DetachCurrentThread();
94
95     // Die...
96     return nullptr;
97   }
98
99  protected:
100   void AddListener() OVERRIDE REQUIRES(Locks::mutator_lock_) {
101     Runtime::Current()->GetRuntimeCallbacks()->AddThreadLifecycleCallback(&cb_);
102   }
103   void RemoveListener() OVERRIDE REQUIRES(Locks::mutator_lock_) {
104     Runtime::Current()->GetRuntimeCallbacks()->RemoveThreadLifecycleCallback(&cb_);
105   }
106
107   enum CallbackState {
108     kBase,
109     kStarted,
110     kDied,
111     kWrongStart,
112     kWrongDeath,
113   };
114
115   struct Callback : public ThreadLifecycleCallback {
116     void ThreadStart(Thread* self) OVERRIDE {
117       if (state == CallbackState::kBase) {
118         state = CallbackState::kStarted;
119         stored_self = self;
120       } else {
121         state = CallbackState::kWrongStart;
122       }
123     }
124
125     void ThreadDeath(Thread* self) OVERRIDE {
126       if (state == CallbackState::kStarted && self == stored_self) {
127         state = CallbackState::kDied;
128       } else {
129         state = CallbackState::kWrongDeath;
130       }
131     }
132
133     Thread* stored_self;
134     CallbackState state = CallbackState::kBase;
135   };
136
137   Callback cb_;
138 };
139
140 TEST_F(ThreadLifecycleCallbackRuntimeCallbacksTest, ThreadLifecycleCallbackJava) {
141   Thread* self = Thread::Current();
142
143   self->TransitionFromSuspendedToRunnable();
144   bool started = runtime_->Start();
145   ASSERT_TRUE(started);
146
147   cb_.state = CallbackState::kBase;  // Ignore main thread attach.
148
149   {
150     ScopedObjectAccess soa(self);
151     MakeExecutable(soa.Decode<mirror::Class>(WellKnownClasses::java_lang_Thread));
152   }
153
154   JNIEnv* env = self->GetJniEnv();
155
156   ScopedLocalRef<jobject> thread_name(env,
157                                       env->NewStringUTF("ThreadLifecycleCallback test thread"));
158   ASSERT_TRUE(thread_name.get() != nullptr);
159
160   ScopedLocalRef<jobject> thread(env, env->AllocObject(WellKnownClasses::java_lang_Thread));
161   ASSERT_TRUE(thread.get() != nullptr);
162
163   env->CallNonvirtualVoidMethod(thread.get(),
164                                 WellKnownClasses::java_lang_Thread,
165                                 WellKnownClasses::java_lang_Thread_init,
166                                 runtime_->GetMainThreadGroup(),
167                                 thread_name.get(),
168                                 kMinThreadPriority,
169                                 JNI_FALSE);
170   ASSERT_FALSE(env->ExceptionCheck());
171
172   jmethodID start_id = env->GetMethodID(WellKnownClasses::java_lang_Thread, "start", "()V");
173   ASSERT_TRUE(start_id != nullptr);
174
175   env->CallVoidMethod(thread.get(), start_id);
176   ASSERT_FALSE(env->ExceptionCheck());
177
178   jmethodID join_id = env->GetMethodID(WellKnownClasses::java_lang_Thread, "join", "()V");
179   ASSERT_TRUE(join_id != nullptr);
180
181   env->CallVoidMethod(thread.get(), join_id);
182   ASSERT_FALSE(env->ExceptionCheck());
183
184   EXPECT_TRUE(cb_.state == CallbackState::kDied) << static_cast<int>(cb_.state);
185 }
186
187 TEST_F(ThreadLifecycleCallbackRuntimeCallbacksTest, ThreadLifecycleCallbackAttach) {
188   std::string error_msg;
189   std::unique_ptr<MemMap> stack(MemMap::MapAnonymous("ThreadLifecycleCallback Thread",
190                                                      nullptr,
191                                                      128 * kPageSize,  // Just some small stack.
192                                                      PROT_READ | PROT_WRITE,
193                                                      false,
194                                                      false,
195                                                      &error_msg));
196   ASSERT_FALSE(stack == nullptr) << error_msg;
197
198   const char* reason = "ThreadLifecycleCallback test thread";
199   pthread_attr_t attr;
200   CHECK_PTHREAD_CALL(pthread_attr_init, (&attr), reason);
201   CHECK_PTHREAD_CALL(pthread_attr_setstack, (&attr, stack->Begin(), stack->Size()), reason);
202   pthread_t pthread;
203   CHECK_PTHREAD_CALL(pthread_create,
204                      (&pthread,
205                          &attr,
206                          &ThreadLifecycleCallbackRuntimeCallbacksTest::PthreadsCallback,
207                          this),
208                          reason);
209   CHECK_PTHREAD_CALL(pthread_attr_destroy, (&attr), reason);
210
211   CHECK_PTHREAD_CALL(pthread_join, (pthread, nullptr), "ThreadLifecycleCallback test shutdown");
212
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);
215 }
216
217 class ClassLoadCallbackRuntimeCallbacksTest : public RuntimeCallbacksTest {
218  protected:
219   void AddListener() OVERRIDE REQUIRES(Locks::mutator_lock_) {
220     Runtime::Current()->GetRuntimeCallbacks()->AddClassLoadCallback(&cb_);
221   }
222   void RemoveListener() OVERRIDE REQUIRES(Locks::mutator_lock_) {
223     Runtime::Current()->GetRuntimeCallbacks()->RemoveClassLoadCallback(&cb_);
224   }
225
226   bool Expect(std::initializer_list<const char*> list) {
227     if (cb_.data.size() != list.size()) {
228       PrintError(list);
229       return false;
230     }
231
232     if (!std::equal(cb_.data.begin(), cb_.data.end(), list.begin())) {
233       PrintError(list);
234       return false;
235     }
236
237     return true;
238   }
239
240   void PrintError(std::initializer_list<const char*> list) {
241     LOG(ERROR) << "Expected:";
242     for (const char* expected : list) {
243       LOG(ERROR) << "  " << expected;
244     }
245     LOG(ERROR) << "Found:";
246     for (const auto& s : cb_.data) {
247       LOG(ERROR) << "  " << s;
248     }
249   }
250
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());
261       std::string event =
262           std::string("PreDefine:") + descriptor + " <" +
263           location.substr(location.rfind("/") + 1, location.size()) + ">";
264       data.push_back(event);
265     }
266
267     void ClassLoad(Handle<mirror::Class> klass) OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
268       std::string tmp;
269       std::string event = std::string("Load:") + klass->GetDescriptor(&tmp);
270       data.push_back(event);
271     }
272
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);
279     }
280
281     std::vector<std::string> data;
282   };
283
284   Callback cb_;
285 };
286
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)));
293
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);
298
299   bool expect1 = Expect({ "PreDefine:LY; <art-gtest-XandY.jar>",
300                           "PreDefine:LX; <art-gtest-XandY.jar>",
301                           "Load:LX;",
302                           "Prepare:LX;[LX;]",
303                           "Load:LY;",
304                           "Prepare:LY;[LY;]" });
305   EXPECT_TRUE(expect1);
306
307   cb_.data.clear();
308
309   ASSERT_TRUE(class_linker_->EnsureInitialized(Thread::Current(), h_Y, true, true));
310
311   bool expect2 = Expect({ "PreDefine:LY$Z; <art-gtest-XandY.jar>",
312                           "Load:LY$Z;",
313                           "Prepare:LY$Z;[LY$Z;]" });
314   EXPECT_TRUE(expect2);
315 }
316
317 class RuntimeSigQuitCallbackRuntimeCallbacksTest : public RuntimeCallbacksTest {
318  protected:
319   void AddListener() OVERRIDE REQUIRES(Locks::mutator_lock_) {
320     Runtime::Current()->GetRuntimeCallbacks()->AddRuntimeSigQuitCallback(&cb_);
321   }
322   void RemoveListener() OVERRIDE REQUIRES(Locks::mutator_lock_) {
323     Runtime::Current()->GetRuntimeCallbacks()->RemoveRuntimeSigQuitCallback(&cb_);
324   }
325
326   struct Callback : public RuntimeSigQuitCallback {
327     void SigQuit() OVERRIDE {
328       ++sigquit_count;
329     }
330
331     size_t sigquit_count = 0;
332   };
333
334   Callback cb_;
335 };
336
337 TEST_F(RuntimeSigQuitCallbackRuntimeCallbacksTest, SigQuit) {
338   // The runtime needs to be started for the signal handler.
339   Thread* self = Thread::Current();
340
341   self->TransitionFromSuspendedToRunnable();
342   bool started = runtime_->Start();
343   ASSERT_TRUE(started);
344
345   EXPECT_EQ(0u, cb_.sigquit_count);
346
347   kill(getpid(), SIGQUIT);
348
349   // Try a few times.
350   for (size_t i = 0; i != 30; ++i) {
351     if (cb_.sigquit_count == 0) {
352       sleep(1);
353     } else {
354       break;
355     }
356   }
357   EXPECT_EQ(1u, cb_.sigquit_count);
358 }
359
360 class RuntimePhaseCallbackRuntimeCallbacksTest : public RuntimeCallbacksTest {
361  protected:
362   void AddListener() OVERRIDE REQUIRES(Locks::mutator_lock_) {
363     Runtime::Current()->GetRuntimeCallbacks()->AddRuntimePhaseCallback(&cb_);
364   }
365   void RemoveListener() OVERRIDE REQUIRES(Locks::mutator_lock_) {
366     Runtime::Current()->GetRuntimeCallbacks()->RemoveRuntimePhaseCallback(&cb_);
367   }
368
369   void TearDown() OVERRIDE {
370     // Bypass RuntimeCallbacksTest::TearDown, as the runtime is already gone.
371     CommonRuntimeTest::TearDown();
372   }
373
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";
379         }
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.";
384         }
385         ++start_seen;
386       } else if (p == RuntimePhaseCallback::RuntimePhase::kInit) {
387         ++init_seen;
388       } else if (p == RuntimePhaseCallback::RuntimePhase::kDeath) {
389         ++death_seen;
390       } else {
391         LOG(FATAL) << "Unknown phase " << static_cast<uint32_t>(p);
392       }
393     }
394
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;
399   };
400
401   Callback cb_;
402 };
403
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);
409
410   // Start the runtime.
411   {
412     Thread* self = Thread::Current();
413     self->TransitionFromSuspendedToRunnable();
414     bool started = runtime_->Start();
415     ASSERT_TRUE(started);
416   }
417
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);
422
423   // Delete the runtime.
424   runtime_.reset();
425
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);
430 }
431
432 }  // namespace art