1 /*
2  * Copyright (C) 2014 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 "transaction.h"
18 
19 #include "art_field-inl.h"
20 #include "art_method-inl.h"
21 #include "class_linker-inl.h"
22 #include "common_runtime_test.h"
23 #include "dex/dex_file.h"
24 #include "mirror/array-alloc-inl.h"
25 #include "mirror/class-alloc-inl.h"
26 #include "scoped_thread_state_change-inl.h"
27 
28 namespace art {
29 
30 class TransactionTest : public CommonRuntimeTest {
31  protected:
SetUpRuntimeOptions(RuntimeOptions * options)32   void SetUpRuntimeOptions(/*out*/RuntimeOptions* options) override {
33     // Set up the image location.
34     options->emplace_back("-Ximage:" + GetImageLocation(), nullptr);
35   }
36 
37   // Tests failing class initialization due to native call with transaction rollback.
testTransactionAbort(const char * tested_class_signature)38   void testTransactionAbort(const char* tested_class_signature) {
39     ScopedObjectAccess soa(Thread::Current());
40     jobject jclass_loader = LoadDex("Transaction");
41     StackHandleScope<2> hs(soa.Self());
42     Handle<mirror::ClassLoader> class_loader(
43         hs.NewHandle(soa.Decode<mirror::ClassLoader>(jclass_loader)));
44     ASSERT_TRUE(class_loader != nullptr);
45 
46     // Load and initialize java.lang.ExceptionInInitializerError and the exception class used
47     // to abort transaction so they can be thrown during class initialization if the transaction
48     // aborts.
49     MutableHandle<mirror::Class> h_klass(
50         hs.NewHandle(class_linker_->FindSystemClass(soa.Self(),
51                                                     "Ljava/lang/ExceptionInInitializerError;")));
52     ASSERT_TRUE(h_klass != nullptr);
53     class_linker_->EnsureInitialized(soa.Self(), h_klass, true, true);
54     ASSERT_TRUE(h_klass->IsInitialized());
55 
56     h_klass.Assign(class_linker_->FindSystemClass(soa.Self(),
57                                                   Transaction::kAbortExceptionSignature));
58     ASSERT_TRUE(h_klass != nullptr);
59     class_linker_->EnsureInitialized(soa.Self(), h_klass, true, true);
60     ASSERT_TRUE(h_klass->IsInitialized());
61 
62     // Load and verify utility class.
63     h_klass.Assign(class_linker_->FindClass(soa.Self(), "LTransaction$AbortHelperClass;",
64                                             class_loader));
65     ASSERT_TRUE(h_klass != nullptr);
66     class_linker_->VerifyClass(soa.Self(), h_klass);
67     ASSERT_TRUE(h_klass->IsVerified());
68 
69     // Load and verify tested class.
70     h_klass.Assign(class_linker_->FindClass(soa.Self(), tested_class_signature, class_loader));
71     ASSERT_TRUE(h_klass != nullptr);
72     class_linker_->VerifyClass(soa.Self(), h_klass);
73     ASSERT_TRUE(h_klass->IsVerified());
74 
75     ClassStatus old_status = h_klass->GetStatus();
76     LockWord old_lock_word = h_klass->GetLockWord(false);
77 
78     EnterTransactionMode();
79     bool success = class_linker_->EnsureInitialized(soa.Self(), h_klass, true, true);
80     ASSERT_TRUE(IsTransactionAborted());
81     ASSERT_FALSE(success);
82     ASSERT_TRUE(h_klass->IsErroneous());
83     ASSERT_TRUE(soa.Self()->IsExceptionPending());
84 
85     // Check class's monitor get back to its original state without rolling back changes.
86     LockWord new_lock_word = h_klass->GetLockWord(false);
87     EXPECT_TRUE(LockWord::Equal<false>(old_lock_word, new_lock_word));
88 
89     // Check class status is rolled back properly.
90     soa.Self()->ClearException();
91     RollbackAndExitTransactionMode();
92     ASSERT_EQ(old_status, h_klass->GetStatus());
93   }
94 };
95 
96 // Tests object's class is preserved after transaction rollback.
TEST_F(TransactionTest,Object_class)97 TEST_F(TransactionTest, Object_class) {
98   ScopedObjectAccess soa(Thread::Current());
99   StackHandleScope<2> hs(soa.Self());
100   Handle<mirror::Class> h_klass(
101       hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;")));
102   ASSERT_TRUE(h_klass != nullptr);
103 
104   EnterTransactionMode();
105   Handle<mirror::Object> h_obj(hs.NewHandle(h_klass->AllocObject(soa.Self())));
106   ASSERT_TRUE(h_obj != nullptr);
107   ASSERT_OBJ_PTR_EQ(h_obj->GetClass(), h_klass.Get());
108   // Rolling back transaction's changes must not clear the Object::class field.
109   RollbackAndExitTransactionMode();
110   EXPECT_OBJ_PTR_EQ(h_obj->GetClass(), h_klass.Get());
111 }
112 
113 // Tests object's monitor state is preserved after transaction rollback.
TEST_F(TransactionTest,Object_monitor)114 TEST_F(TransactionTest, Object_monitor) {
115   ScopedObjectAccess soa(Thread::Current());
116   StackHandleScope<2> hs(soa.Self());
117   Handle<mirror::Class> h_klass(
118       hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;")));
119   ASSERT_TRUE(h_klass != nullptr);
120   Handle<mirror::Object> h_obj(hs.NewHandle(h_klass->AllocObject(soa.Self())));
121   ASSERT_TRUE(h_obj != nullptr);
122   ASSERT_OBJ_PTR_EQ(h_obj->GetClass(), h_klass.Get());
123 
124   // Lock object's monitor outside the transaction.
125   h_obj->MonitorEnter(soa.Self());
126   LockWord old_lock_word = h_obj->GetLockWord(false);
127 
128   EnterTransactionMode();
129   // Unlock object's monitor inside the transaction.
130   h_obj->MonitorExit(soa.Self());
131   LockWord new_lock_word = h_obj->GetLockWord(false);
132   // Rolling back transaction's changes must not change monitor's state.
133   RollbackAndExitTransactionMode();
134 
135   LockWord aborted_lock_word = h_obj->GetLockWord(false);
136   EXPECT_FALSE(LockWord::Equal<false>(old_lock_word, new_lock_word));
137   EXPECT_TRUE(LockWord::Equal<false>(aborted_lock_word, new_lock_word));
138 }
139 
140 // Tests array's length is preserved after transaction rollback.
TEST_F(TransactionTest,Array_length)141 TEST_F(TransactionTest, Array_length) {
142   ScopedObjectAccess soa(Thread::Current());
143   StackHandleScope<2> hs(soa.Self());
144   Handle<mirror::Class> h_klass(
145       hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "[Ljava/lang/Object;")));
146   ASSERT_TRUE(h_klass != nullptr);
147 
148   constexpr int32_t kArraySize = 2;
149 
150   EnterTransactionMode();
151 
152   // Allocate an array during transaction.
153   Handle<mirror::Array> h_obj = hs.NewHandle(
154       mirror::Array::Alloc(soa.Self(),
155                            h_klass.Get(),
156                            kArraySize,
157                            h_klass->GetComponentSizeShift(),
158                            Runtime::Current()->GetHeap()->GetCurrentAllocator()));
159   ASSERT_TRUE(h_obj != nullptr);
160   ASSERT_OBJ_PTR_EQ(h_obj->GetClass(), h_klass.Get());
161   RollbackAndExitTransactionMode();
162 
163   // Rolling back transaction's changes must not reset array's length.
164   EXPECT_EQ(h_obj->GetLength(), kArraySize);
165 }
166 
167 // Tests static fields are reset to their default value after transaction rollback.
TEST_F(TransactionTest,StaticFieldsTest)168 TEST_F(TransactionTest, StaticFieldsTest) {
169   ScopedObjectAccess soa(Thread::Current());
170   StackHandleScope<4> hs(soa.Self());
171   Handle<mirror::ClassLoader> class_loader(
172       hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("Transaction"))));
173   ASSERT_TRUE(class_loader != nullptr);
174 
175   Handle<mirror::Class> h_klass(
176       hs.NewHandle(class_linker_->FindClass(soa.Self(), "LStaticFieldsTest;", class_loader)));
177   ASSERT_TRUE(h_klass != nullptr);
178   bool success = class_linker_->EnsureInitialized(soa.Self(), h_klass, true, true);
179   ASSERT_TRUE(success);
180   ASSERT_TRUE(h_klass->IsInitialized());
181   ASSERT_FALSE(soa.Self()->IsExceptionPending());
182 
183   // Lookup fields.
184   ArtField* booleanField = h_klass->FindDeclaredStaticField("booleanField", "Z");
185   ASSERT_TRUE(booleanField != nullptr);
186   ASSERT_EQ(booleanField->GetTypeAsPrimitiveType(), Primitive::kPrimBoolean);
187   ASSERT_EQ(booleanField->GetBoolean(h_klass.Get()), false);
188 
189   ArtField* byteField = h_klass->FindDeclaredStaticField("byteField", "B");
190   ASSERT_TRUE(byteField != nullptr);
191   ASSERT_EQ(byteField->GetTypeAsPrimitiveType(), Primitive::kPrimByte);
192   ASSERT_EQ(byteField->GetByte(h_klass.Get()), 0);
193 
194   ArtField* charField = h_klass->FindDeclaredStaticField("charField", "C");
195   ASSERT_TRUE(charField != nullptr);
196   ASSERT_EQ(charField->GetTypeAsPrimitiveType(), Primitive::kPrimChar);
197   ASSERT_EQ(charField->GetChar(h_klass.Get()), 0u);
198 
199   ArtField* shortField = h_klass->FindDeclaredStaticField("shortField", "S");
200   ASSERT_TRUE(shortField != nullptr);
201   ASSERT_EQ(shortField->GetTypeAsPrimitiveType(), Primitive::kPrimShort);
202   ASSERT_EQ(shortField->GetShort(h_klass.Get()), 0);
203 
204   ArtField* intField = h_klass->FindDeclaredStaticField("intField", "I");
205   ASSERT_TRUE(intField != nullptr);
206   ASSERT_EQ(intField->GetTypeAsPrimitiveType(), Primitive::kPrimInt);
207   ASSERT_EQ(intField->GetInt(h_klass.Get()), 0);
208 
209   ArtField* longField = h_klass->FindDeclaredStaticField("longField", "J");
210   ASSERT_TRUE(longField != nullptr);
211   ASSERT_EQ(longField->GetTypeAsPrimitiveType(), Primitive::kPrimLong);
212   ASSERT_EQ(longField->GetLong(h_klass.Get()), static_cast<int64_t>(0));
213 
214   ArtField* floatField = h_klass->FindDeclaredStaticField("floatField", "F");
215   ASSERT_TRUE(floatField != nullptr);
216   ASSERT_EQ(floatField->GetTypeAsPrimitiveType(), Primitive::kPrimFloat);
217   ASSERT_FLOAT_EQ(floatField->GetFloat(h_klass.Get()), static_cast<float>(0.0f));
218 
219   ArtField* doubleField = h_klass->FindDeclaredStaticField("doubleField", "D");
220   ASSERT_TRUE(doubleField != nullptr);
221   ASSERT_EQ(doubleField->GetTypeAsPrimitiveType(), Primitive::kPrimDouble);
222   ASSERT_DOUBLE_EQ(doubleField->GetDouble(h_klass.Get()), static_cast<double>(0.0));
223 
224   ArtField* objectField = h_klass->FindDeclaredStaticField("objectField",
225                                                                    "Ljava/lang/Object;");
226   ASSERT_TRUE(objectField != nullptr);
227   ASSERT_EQ(objectField->GetTypeAsPrimitiveType(), Primitive::kPrimNot);
228   ASSERT_EQ(objectField->GetObject(h_klass.Get()), nullptr);
229 
230   // Create a java.lang.Object instance to set objectField.
231   Handle<mirror::Class> object_klass(
232       hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;")));
233   ASSERT_TRUE(object_klass != nullptr);
234   Handle<mirror::Object> h_obj(hs.NewHandle(h_klass->AllocObject(soa.Self())));
235   ASSERT_TRUE(h_obj != nullptr);
236   ASSERT_OBJ_PTR_EQ(h_obj->GetClass(), h_klass.Get());
237 
238   // Modify fields inside transaction then rollback changes.
239   EnterTransactionMode();
240   booleanField->SetBoolean<true>(h_klass.Get(), true);
241   byteField->SetByte<true>(h_klass.Get(), 1);
242   charField->SetChar<true>(h_klass.Get(), 1u);
243   shortField->SetShort<true>(h_klass.Get(), 1);
244   intField->SetInt<true>(h_klass.Get(), 1);
245   longField->SetLong<true>(h_klass.Get(), 1);
246   floatField->SetFloat<true>(h_klass.Get(), 1.0);
247   doubleField->SetDouble<true>(h_klass.Get(), 1.0);
248   objectField->SetObject<true>(h_klass.Get(), h_obj.Get());
249   RollbackAndExitTransactionMode();
250 
251   // Check values have properly been restored to their original (default) value.
252   EXPECT_EQ(booleanField->GetBoolean(h_klass.Get()), false);
253   EXPECT_EQ(byteField->GetByte(h_klass.Get()), 0);
254   EXPECT_EQ(charField->GetChar(h_klass.Get()), 0u);
255   EXPECT_EQ(shortField->GetShort(h_klass.Get()), 0);
256   EXPECT_EQ(intField->GetInt(h_klass.Get()), 0);
257   EXPECT_EQ(longField->GetLong(h_klass.Get()), static_cast<int64_t>(0));
258   EXPECT_FLOAT_EQ(floatField->GetFloat(h_klass.Get()), static_cast<float>(0.0f));
259   EXPECT_DOUBLE_EQ(doubleField->GetDouble(h_klass.Get()), static_cast<double>(0.0));
260   EXPECT_EQ(objectField->GetObject(h_klass.Get()), nullptr);
261 }
262 
263 // Tests instance fields are reset to their default value after transaction rollback.
TEST_F(TransactionTest,InstanceFieldsTest)264 TEST_F(TransactionTest, InstanceFieldsTest) {
265   ScopedObjectAccess soa(Thread::Current());
266   StackHandleScope<5> hs(soa.Self());
267   Handle<mirror::ClassLoader> class_loader(
268       hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("Transaction"))));
269   ASSERT_TRUE(class_loader != nullptr);
270 
271   Handle<mirror::Class> h_klass(
272       hs.NewHandle(class_linker_->FindClass(soa.Self(), "LInstanceFieldsTest;", class_loader)));
273   ASSERT_TRUE(h_klass != nullptr);
274   bool success = class_linker_->EnsureInitialized(soa.Self(), h_klass, true, true);
275   ASSERT_TRUE(success);
276   ASSERT_TRUE(h_klass->IsInitialized());
277   ASSERT_FALSE(soa.Self()->IsExceptionPending());
278 
279   // Allocate an InstanceFieldTest object.
280   Handle<mirror::Object> h_instance(hs.NewHandle(h_klass->AllocObject(soa.Self())));
281   ASSERT_TRUE(h_instance != nullptr);
282 
283   // Lookup fields.
284   ArtField* booleanField = h_klass->FindDeclaredInstanceField("booleanField", "Z");
285   ASSERT_TRUE(booleanField != nullptr);
286   ASSERT_EQ(booleanField->GetTypeAsPrimitiveType(), Primitive::kPrimBoolean);
287   ASSERT_EQ(booleanField->GetBoolean(h_instance.Get()), false);
288 
289   ArtField* byteField = h_klass->FindDeclaredInstanceField("byteField", "B");
290   ASSERT_TRUE(byteField != nullptr);
291   ASSERT_EQ(byteField->GetTypeAsPrimitiveType(), Primitive::kPrimByte);
292   ASSERT_EQ(byteField->GetByte(h_instance.Get()), 0);
293 
294   ArtField* charField = h_klass->FindDeclaredInstanceField("charField", "C");
295   ASSERT_TRUE(charField != nullptr);
296   ASSERT_EQ(charField->GetTypeAsPrimitiveType(), Primitive::kPrimChar);
297   ASSERT_EQ(charField->GetChar(h_instance.Get()), 0u);
298 
299   ArtField* shortField = h_klass->FindDeclaredInstanceField("shortField", "S");
300   ASSERT_TRUE(shortField != nullptr);
301   ASSERT_EQ(shortField->GetTypeAsPrimitiveType(), Primitive::kPrimShort);
302   ASSERT_EQ(shortField->GetShort(h_instance.Get()), 0);
303 
304   ArtField* intField = h_klass->FindDeclaredInstanceField("intField", "I");
305   ASSERT_TRUE(intField != nullptr);
306   ASSERT_EQ(intField->GetTypeAsPrimitiveType(), Primitive::kPrimInt);
307   ASSERT_EQ(intField->GetInt(h_instance.Get()), 0);
308 
309   ArtField* longField = h_klass->FindDeclaredInstanceField("longField", "J");
310   ASSERT_TRUE(longField != nullptr);
311   ASSERT_EQ(longField->GetTypeAsPrimitiveType(), Primitive::kPrimLong);
312   ASSERT_EQ(longField->GetLong(h_instance.Get()), static_cast<int64_t>(0));
313 
314   ArtField* floatField = h_klass->FindDeclaredInstanceField("floatField", "F");
315   ASSERT_TRUE(floatField != nullptr);
316   ASSERT_EQ(floatField->GetTypeAsPrimitiveType(), Primitive::kPrimFloat);
317   ASSERT_FLOAT_EQ(floatField->GetFloat(h_instance.Get()), static_cast<float>(0.0f));
318 
319   ArtField* doubleField = h_klass->FindDeclaredInstanceField("doubleField", "D");
320   ASSERT_TRUE(doubleField != nullptr);
321   ASSERT_EQ(doubleField->GetTypeAsPrimitiveType(), Primitive::kPrimDouble);
322   ASSERT_DOUBLE_EQ(doubleField->GetDouble(h_instance.Get()), static_cast<double>(0.0));
323 
324   ArtField* objectField = h_klass->FindDeclaredInstanceField("objectField",
325                                                                         "Ljava/lang/Object;");
326   ASSERT_TRUE(objectField != nullptr);
327   ASSERT_EQ(objectField->GetTypeAsPrimitiveType(), Primitive::kPrimNot);
328   ASSERT_EQ(objectField->GetObject(h_instance.Get()), nullptr);
329 
330   // Create a java.lang.Object instance to set objectField.
331   Handle<mirror::Class> object_klass(
332       hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;")));
333   ASSERT_TRUE(object_klass != nullptr);
334   Handle<mirror::Object> h_obj(hs.NewHandle(h_klass->AllocObject(soa.Self())));
335   ASSERT_TRUE(h_obj != nullptr);
336   ASSERT_OBJ_PTR_EQ(h_obj->GetClass(), h_klass.Get());
337 
338   // Modify fields inside transaction then rollback changes.
339   EnterTransactionMode();
340   booleanField->SetBoolean<true>(h_instance.Get(), true);
341   byteField->SetByte<true>(h_instance.Get(), 1);
342   charField->SetChar<true>(h_instance.Get(), 1u);
343   shortField->SetShort<true>(h_instance.Get(), 1);
344   intField->SetInt<true>(h_instance.Get(), 1);
345   longField->SetLong<true>(h_instance.Get(), 1);
346   floatField->SetFloat<true>(h_instance.Get(), 1.0);
347   doubleField->SetDouble<true>(h_instance.Get(), 1.0);
348   objectField->SetObject<true>(h_instance.Get(), h_obj.Get());
349   RollbackAndExitTransactionMode();
350 
351   // Check values have properly been restored to their original (default) value.
352   EXPECT_EQ(booleanField->GetBoolean(h_instance.Get()), false);
353   EXPECT_EQ(byteField->GetByte(h_instance.Get()), 0);
354   EXPECT_EQ(charField->GetChar(h_instance.Get()), 0u);
355   EXPECT_EQ(shortField->GetShort(h_instance.Get()), 0);
356   EXPECT_EQ(intField->GetInt(h_instance.Get()), 0);
357   EXPECT_EQ(longField->GetLong(h_instance.Get()), static_cast<int64_t>(0));
358   EXPECT_FLOAT_EQ(floatField->GetFloat(h_instance.Get()), static_cast<float>(0.0f));
359   EXPECT_DOUBLE_EQ(doubleField->GetDouble(h_instance.Get()), static_cast<double>(0.0));
360   EXPECT_EQ(objectField->GetObject(h_instance.Get()), nullptr);
361 }
362 
363 // Tests static array fields are reset to their default value after transaction rollback.
TEST_F(TransactionTest,StaticArrayFieldsTest)364 TEST_F(TransactionTest, StaticArrayFieldsTest) {
365   ScopedObjectAccess soa(Thread::Current());
366   StackHandleScope<13> hs(soa.Self());
367   Handle<mirror::ClassLoader> class_loader(
368       hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("Transaction"))));
369   ASSERT_TRUE(class_loader != nullptr);
370 
371   Handle<mirror::Class> h_klass(
372       hs.NewHandle(class_linker_->FindClass(soa.Self(), "LStaticArrayFieldsTest;", class_loader)));
373   ASSERT_TRUE(h_klass != nullptr);
374   bool success = class_linker_->EnsureInitialized(soa.Self(), h_klass, true, true);
375   ASSERT_TRUE(success);
376   ASSERT_TRUE(h_klass->IsInitialized());
377   ASSERT_FALSE(soa.Self()->IsExceptionPending());
378 
379   // Lookup fields.
380   ArtField* booleanArrayField = h_klass->FindDeclaredStaticField("booleanArrayField", "[Z");
381   ASSERT_TRUE(booleanArrayField != nullptr);
382   Handle<mirror::BooleanArray> booleanArray = hs.NewHandle(
383       booleanArrayField->GetObject(h_klass.Get())->AsBooleanArray());
384   ASSERT_TRUE(booleanArray != nullptr);
385   ASSERT_EQ(booleanArray->GetLength(), 1);
386   ASSERT_EQ(booleanArray->GetWithoutChecks(0), false);
387 
388   ArtField* byteArrayField = h_klass->FindDeclaredStaticField("byteArrayField", "[B");
389   ASSERT_TRUE(byteArrayField != nullptr);
390   Handle<mirror::ByteArray> byteArray =
391       hs.NewHandle(byteArrayField->GetObject(h_klass.Get())->AsByteArray());
392   ASSERT_TRUE(byteArray != nullptr);
393   ASSERT_EQ(byteArray->GetLength(), 1);
394   ASSERT_EQ(byteArray->GetWithoutChecks(0), 0);
395 
396   ArtField* charArrayField = h_klass->FindDeclaredStaticField("charArrayField", "[C");
397   ASSERT_TRUE(charArrayField != nullptr);
398   Handle<mirror::CharArray> charArray =
399       hs.NewHandle(charArrayField->GetObject(h_klass.Get())->AsCharArray());
400   ASSERT_TRUE(charArray != nullptr);
401   ASSERT_EQ(charArray->GetLength(), 1);
402   ASSERT_EQ(charArray->GetWithoutChecks(0), 0u);
403 
404   ArtField* shortArrayField = h_klass->FindDeclaredStaticField("shortArrayField", "[S");
405   ASSERT_TRUE(shortArrayField != nullptr);
406   Handle<mirror::ShortArray> shortArray =
407       hs.NewHandle(shortArrayField->GetObject(h_klass.Get())->AsShortArray());
408   ASSERT_TRUE(shortArray != nullptr);
409   ASSERT_EQ(shortArray->GetLength(), 1);
410   ASSERT_EQ(shortArray->GetWithoutChecks(0), 0);
411 
412   ArtField* intArrayField = h_klass->FindDeclaredStaticField("intArrayField", "[I");
413   ASSERT_TRUE(intArrayField != nullptr);
414   Handle<mirror::IntArray> intArray =
415       hs.NewHandle(intArrayField->GetObject(h_klass.Get())->AsIntArray());
416   ASSERT_TRUE(intArray != nullptr);
417   ASSERT_EQ(intArray->GetLength(), 1);
418   ASSERT_EQ(intArray->GetWithoutChecks(0), 0);
419 
420   ArtField* longArrayField = h_klass->FindDeclaredStaticField("longArrayField", "[J");
421   ASSERT_TRUE(longArrayField != nullptr);
422   Handle<mirror::LongArray> longArray =
423       hs.NewHandle(longArrayField->GetObject(h_klass.Get())->AsLongArray());
424   ASSERT_TRUE(longArray != nullptr);
425   ASSERT_EQ(longArray->GetLength(), 1);
426   ASSERT_EQ(longArray->GetWithoutChecks(0), static_cast<int64_t>(0));
427 
428   ArtField* floatArrayField = h_klass->FindDeclaredStaticField("floatArrayField", "[F");
429   ASSERT_TRUE(floatArrayField != nullptr);
430   Handle<mirror::FloatArray> floatArray =
431       hs.NewHandle(floatArrayField->GetObject(h_klass.Get())->AsFloatArray());
432   ASSERT_TRUE(floatArray != nullptr);
433   ASSERT_EQ(floatArray->GetLength(), 1);
434   ASSERT_FLOAT_EQ(floatArray->GetWithoutChecks(0), static_cast<float>(0.0f));
435 
436   ArtField* doubleArrayField = h_klass->FindDeclaredStaticField("doubleArrayField", "[D");
437   ASSERT_TRUE(doubleArrayField != nullptr);
438   Handle<mirror::DoubleArray> doubleArray =
439       hs.NewHandle(doubleArrayField->GetObject(h_klass.Get())->AsDoubleArray());
440   ASSERT_TRUE(doubleArray != nullptr);
441   ASSERT_EQ(doubleArray->GetLength(), 1);
442   ASSERT_DOUBLE_EQ(doubleArray->GetWithoutChecks(0), static_cast<double>(0.0f));
443 
444   ArtField* objectArrayField =
445       h_klass->FindDeclaredStaticField("objectArrayField", "[Ljava/lang/Object;");
446   ASSERT_TRUE(objectArrayField != nullptr);
447   Handle<mirror::ObjectArray<mirror::Object>> objectArray =
448       hs.NewHandle(objectArrayField->GetObject(h_klass.Get())->AsObjectArray<mirror::Object>());
449   ASSERT_TRUE(objectArray != nullptr);
450   ASSERT_EQ(objectArray->GetLength(), 1);
451   ASSERT_EQ(objectArray->GetWithoutChecks(0), nullptr);
452 
453   // Create a java.lang.Object instance to set objectField.
454   Handle<mirror::Class> object_klass(
455       hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;")));
456   ASSERT_TRUE(object_klass != nullptr);
457   Handle<mirror::Object> h_obj(hs.NewHandle(h_klass->AllocObject(soa.Self())));
458   ASSERT_TRUE(h_obj != nullptr);
459   ASSERT_OBJ_PTR_EQ(h_obj->GetClass(), h_klass.Get());
460 
461   // Modify fields inside transaction then rollback changes.
462   EnterTransactionMode();
463   booleanArray->SetWithoutChecks<true>(0, true);
464   byteArray->SetWithoutChecks<true>(0, 1);
465   charArray->SetWithoutChecks<true>(0, 1u);
466   shortArray->SetWithoutChecks<true>(0, 1);
467   intArray->SetWithoutChecks<true>(0, 1);
468   longArray->SetWithoutChecks<true>(0, 1);
469   floatArray->SetWithoutChecks<true>(0, 1.0);
470   doubleArray->SetWithoutChecks<true>(0, 1.0);
471   objectArray->SetWithoutChecks<true>(0, h_obj.Get());
472   RollbackAndExitTransactionMode();
473 
474   // Check values have properly been restored to their original (default) value.
475   EXPECT_EQ(booleanArray->GetWithoutChecks(0), false);
476   EXPECT_EQ(byteArray->GetWithoutChecks(0), 0);
477   EXPECT_EQ(charArray->GetWithoutChecks(0), 0u);
478   EXPECT_EQ(shortArray->GetWithoutChecks(0), 0);
479   EXPECT_EQ(intArray->GetWithoutChecks(0), 0);
480   EXPECT_EQ(longArray->GetWithoutChecks(0), static_cast<int64_t>(0));
481   EXPECT_FLOAT_EQ(floatArray->GetWithoutChecks(0), static_cast<float>(0.0f));
482   EXPECT_DOUBLE_EQ(doubleArray->GetWithoutChecks(0), static_cast<double>(0.0f));
483   EXPECT_EQ(objectArray->GetWithoutChecks(0), nullptr);
484 }
485 
486 // Tests rolling back interned strings and resolved strings.
TEST_F(TransactionTest,ResolveString)487 TEST_F(TransactionTest, ResolveString) {
488   ScopedObjectAccess soa(Thread::Current());
489   StackHandleScope<3> hs(soa.Self());
490   Handle<mirror::ClassLoader> class_loader(
491       hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("Transaction"))));
492   ASSERT_TRUE(class_loader != nullptr);
493 
494   Handle<mirror::Class> h_klass(
495       hs.NewHandle(class_linker_->FindClass(soa.Self(), "LTransaction$ResolveString;",
496                                             class_loader)));
497   ASSERT_TRUE(h_klass != nullptr);
498 
499   Handle<mirror::DexCache> h_dex_cache(hs.NewHandle(h_klass->GetDexCache()));
500   ASSERT_TRUE(h_dex_cache != nullptr);
501   const DexFile* const dex_file = h_dex_cache->GetDexFile();
502   ASSERT_TRUE(dex_file != nullptr);
503 
504   // Go search the dex file to find the string id of our string.
505   static const char* kResolvedString = "ResolvedString";
506   const dex::StringId* string_id = dex_file->FindStringId(kResolvedString);
507   ASSERT_TRUE(string_id != nullptr);
508   dex::StringIndex string_idx = dex_file->GetIndexForStringId(*string_id);
509   ASSERT_TRUE(string_idx.IsValid());
510   // String should only get resolved by the initializer.
511   EXPECT_TRUE(class_linker_->LookupString(string_idx, h_dex_cache.Get()) == nullptr);
512   EXPECT_TRUE(h_dex_cache->GetResolvedString(string_idx) == nullptr);
513   // Do the transaction, then roll back.
514   EnterTransactionMode();
515   bool success = class_linker_->EnsureInitialized(soa.Self(), h_klass, true, true);
516   ASSERT_TRUE(success);
517   ASSERT_TRUE(h_klass->IsInitialized());
518   // Make sure the string got resolved by the transaction.
519   {
520     ObjPtr<mirror::String> s =
521         class_linker_->LookupString(string_idx, h_dex_cache.Get());
522     ASSERT_TRUE(s != nullptr);
523     EXPECT_STREQ(s->ToModifiedUtf8().c_str(), kResolvedString);
524     EXPECT_OBJ_PTR_EQ(s, h_dex_cache->GetResolvedString(string_idx));
525   }
526   RollbackAndExitTransactionMode();
527   // Check that the string did not stay resolved.
528   EXPECT_TRUE(class_linker_->LookupString(string_idx, h_dex_cache.Get()) == nullptr);
529   EXPECT_TRUE(h_dex_cache->GetResolvedString(string_idx) == nullptr);
530   ASSERT_FALSE(h_klass->IsInitialized());
531   ASSERT_FALSE(soa.Self()->IsExceptionPending());
532 }
533 
534 // Tests successful class initialization without class initializer.
TEST_F(TransactionTest,EmptyClass)535 TEST_F(TransactionTest, EmptyClass) {
536   ScopedObjectAccess soa(Thread::Current());
537   StackHandleScope<2> hs(soa.Self());
538   Handle<mirror::ClassLoader> class_loader(
539       hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("Transaction"))));
540   ASSERT_TRUE(class_loader != nullptr);
541 
542   Handle<mirror::Class> h_klass(
543       hs.NewHandle(class_linker_->FindClass(soa.Self(), "LTransaction$EmptyStatic;",
544                                             class_loader)));
545   ASSERT_TRUE(h_klass != nullptr);
546   class_linker_->VerifyClass(soa.Self(), h_klass);
547   ASSERT_TRUE(h_klass->IsVerified());
548 
549   EnterTransactionMode();
550   bool success = class_linker_->EnsureInitialized(soa.Self(), h_klass, true, true);
551   ExitTransactionMode();
552   ASSERT_TRUE(success);
553   ASSERT_TRUE(h_klass->IsInitialized());
554   ASSERT_FALSE(soa.Self()->IsExceptionPending());
555 }
556 
557 // Tests successful class initialization with class initializer.
TEST_F(TransactionTest,StaticFieldClass)558 TEST_F(TransactionTest, StaticFieldClass) {
559   ScopedObjectAccess soa(Thread::Current());
560   StackHandleScope<2> hs(soa.Self());
561   Handle<mirror::ClassLoader> class_loader(
562       hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("Transaction"))));
563   ASSERT_TRUE(class_loader != nullptr);
564 
565   Handle<mirror::Class> h_klass(
566       hs.NewHandle(class_linker_->FindClass(soa.Self(), "LTransaction$StaticFieldClass;",
567                                             class_loader)));
568   ASSERT_TRUE(h_klass != nullptr);
569   class_linker_->VerifyClass(soa.Self(), h_klass);
570   ASSERT_TRUE(h_klass->IsVerified());
571 
572   EnterTransactionMode();
573   bool success = class_linker_->EnsureInitialized(soa.Self(), h_klass, true, true);
574   ExitTransactionMode();
575   ASSERT_TRUE(success);
576   ASSERT_TRUE(h_klass->IsInitialized());
577   ASSERT_FALSE(soa.Self()->IsExceptionPending());
578 }
579 
580 // Tests failing class initialization due to native call.
TEST_F(TransactionTest,NativeCallAbortClass)581 TEST_F(TransactionTest, NativeCallAbortClass) {
582   testTransactionAbort("LTransaction$NativeCallAbortClass;");
583 }
584 
585 // Tests failing class initialization due to native call in a "synchronized" statement
586 // (which must catch any exception, do the monitor-exit then re-throw the caught exception).
TEST_F(TransactionTest,SynchronizedNativeCallAbortClass)587 TEST_F(TransactionTest, SynchronizedNativeCallAbortClass) {
588   testTransactionAbort("LTransaction$SynchronizedNativeCallAbortClass;");
589 }
590 
591 // Tests failing class initialization due to native call, even if an "all" catch handler
592 // catches the exception thrown when aborting the transaction.
TEST_F(TransactionTest,CatchNativeCallAbortClass)593 TEST_F(TransactionTest, CatchNativeCallAbortClass) {
594   testTransactionAbort("LTransaction$CatchNativeCallAbortClass;");
595 }
596 
597 // Tests failing class initialization with multiple transaction aborts.
TEST_F(TransactionTest,MultipleNativeCallAbortClass)598 TEST_F(TransactionTest, MultipleNativeCallAbortClass) {
599   testTransactionAbort("LTransaction$MultipleNativeCallAbortClass;");
600 }
601 
602 // Tests failing class initialization due to allocating instance of finalizable class.
TEST_F(TransactionTest,FinalizableAbortClass)603 TEST_F(TransactionTest, FinalizableAbortClass) {
604   testTransactionAbort("LTransaction$FinalizableAbortClass;");
605 }
606 
TEST_F(TransactionTest,Constraints)607 TEST_F(TransactionTest, Constraints) {
608   ScopedObjectAccess soa(Thread::Current());
609   StackHandleScope<11> hs(soa.Self());
610   Handle<mirror::ClassLoader> class_loader(
611       hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("Transaction"))));
612 
613   gc::Heap* heap = Runtime::Current()->GetHeap();
614   Handle<mirror::Class> boolean_class = hs.NewHandle(
615       class_linker_->FindClass(soa.Self(), "Ljava/lang/Boolean;", class_loader));
616   ASSERT_TRUE(boolean_class != nullptr);
617   ASSERT_TRUE(heap->ObjectIsInBootImageSpace(boolean_class.Get()));
618   ArtField* true_field =
619       mirror::Class::FindField(soa.Self(), boolean_class.Get(), "TRUE", "Ljava/lang/Boolean;");
620   ASSERT_TRUE(true_field != nullptr);
621   ASSERT_TRUE(true_field->IsStatic());
622   Handle<mirror::Object> true_value = hs.NewHandle(true_field->GetObject(boolean_class.Get()));
623   ASSERT_TRUE(true_value != nullptr);
624   ASSERT_TRUE(heap->ObjectIsInBootImageSpace(true_value.Get()));
625   ArtField* value_field =
626       mirror::Class::FindField(soa.Self(), boolean_class.Get(), "value", "Z");
627   ASSERT_TRUE(value_field != nullptr);
628   ASSERT_FALSE(value_field->IsStatic());
629 
630   Handle<mirror::Class> static_field_class(hs.NewHandle(
631       class_linker_->FindClass(soa.Self(), "LTransaction$StaticFieldClass;", class_loader)));
632   ASSERT_TRUE(static_field_class != nullptr);
633   ASSERT_FALSE(heap->ObjectIsInBootImageSpace(static_field_class.Get()));
634   ArtField* int_field =
635       mirror::Class::FindField(soa.Self(), static_field_class.Get(), "intField", "I");
636   ASSERT_TRUE(int_field != nullptr);
637 
638   Handle<mirror::Class> static_fields_test_class(hs.NewHandle(
639       class_linker_->FindClass(soa.Self(), "LStaticFieldsTest;", class_loader)));
640   ASSERT_TRUE(static_fields_test_class != nullptr);
641   ASSERT_FALSE(heap->ObjectIsInBootImageSpace(static_fields_test_class.Get()));
642   ArtField* static_fields_test_int_field =
643       mirror::Class::FindField(soa.Self(), static_fields_test_class.Get(), "intField", "I");
644   ASSERT_TRUE(static_fields_test_int_field != nullptr);
645 
646   Handle<mirror::Class> instance_fields_test_class(hs.NewHandle(
647       class_linker_->FindClass(soa.Self(), "LInstanceFieldsTest;", class_loader)));
648   ASSERT_TRUE(instance_fields_test_class != nullptr);
649   ASSERT_FALSE(heap->ObjectIsInBootImageSpace(instance_fields_test_class.Get()));
650   ArtField* instance_fields_test_int_field =
651       mirror::Class::FindField(soa.Self(), instance_fields_test_class.Get(), "intField", "I");
652   ASSERT_TRUE(instance_fields_test_int_field != nullptr);
653   Handle<mirror::Object> instance_fields_test_object = hs.NewHandle(
654       instance_fields_test_class->Alloc(soa.Self(), heap->GetCurrentAllocator()));
655   ASSERT_TRUE(instance_fields_test_object != nullptr);
656   ASSERT_FALSE(heap->ObjectIsInBootImageSpace(instance_fields_test_object.Get()));
657 
658   Handle<mirror::Class> long_array_dim2_class = hs.NewHandle(
659       class_linker_->FindClass(soa.Self(), "[[J", class_loader));
660   ASSERT_TRUE(long_array_dim2_class != nullptr);
661   ASSERT_FALSE(heap->ObjectIsInBootImageSpace(long_array_dim2_class.Get()));
662   ASSERT_TRUE(heap->ObjectIsInBootImageSpace(long_array_dim2_class->GetComponentType()));
663   Handle<mirror::Array> long_array_dim2 = hs.NewHandle(mirror::Array::Alloc(
664       soa.Self(),
665       long_array_dim2_class.Get(),
666       /*component_count=*/ 1,
667       long_array_dim2_class->GetComponentSizeShift(),
668       heap->GetCurrentAllocator()));
669   ASSERT_TRUE(long_array_dim2 != nullptr);
670   ASSERT_FALSE(heap->ObjectIsInBootImageSpace(long_array_dim2.Get()));
671   Handle<mirror::Array> long_array = hs.NewHandle(mirror::Array::Alloc(
672       soa.Self(),
673       long_array_dim2_class->GetComponentType(),
674       /*component_count=*/ 1,
675       long_array_dim2_class->GetComponentType()->GetComponentSizeShift(),
676       heap->GetCurrentAllocator()));
677   ASSERT_TRUE(long_array != nullptr);
678   ASSERT_FALSE(heap->ObjectIsInBootImageSpace(long_array.Get()));
679 
680   // Use the Array's IfTable as an array from the boot image.
681   Handle<mirror::ObjectArray<mirror::Object>> array_iftable =
682       hs.NewHandle(long_array_dim2_class->GetIfTable());
683   ASSERT_TRUE(array_iftable != nullptr);
684   ASSERT_TRUE(heap->ObjectIsInBootImageSpace(array_iftable.Get()));
685 
686   // Test non-strict transaction.
687   Transaction transaction(/*strict=*/ false, /*root=*/ nullptr);
688   // Static field in boot image.
689   EXPECT_TRUE(transaction.WriteConstraint(soa.Self(), boolean_class.Get()));
690   EXPECT_FALSE(transaction.ReadConstraint(soa.Self(), boolean_class.Get()));
691   // Instance field or array element in boot image.
692   // Do not check ReadConstraint(), it expects only static fields (checks for class object).
693   EXPECT_TRUE(transaction.WriteConstraint(soa.Self(), true_value.Get()));
694   EXPECT_TRUE(transaction.WriteConstraint(soa.Self(), array_iftable.Get()));
695   // Static field not in boot image.
696   EXPECT_FALSE(transaction.WriteConstraint(soa.Self(), static_fields_test_class.Get()));
697   EXPECT_FALSE(transaction.ReadConstraint(soa.Self(), static_fields_test_class.Get()));
698   // Instance field or array element not in boot image.
699   // Do not check ReadConstraint(), it expects only static fields (checks for class object).
700   EXPECT_FALSE(transaction.WriteConstraint(soa.Self(), instance_fields_test_object.Get()));
701   EXPECT_FALSE(transaction.WriteConstraint(soa.Self(), long_array_dim2.Get()));
702   // Write value constraints.
703   EXPECT_FALSE(transaction.WriteValueConstraint(soa.Self(), static_fields_test_class.Get()));
704   EXPECT_FALSE(transaction.WriteValueConstraint(soa.Self(), instance_fields_test_object.Get()));
705   EXPECT_TRUE(transaction.WriteValueConstraint(soa.Self(), long_array_dim2->GetClass()));
706   EXPECT_TRUE(transaction.WriteValueConstraint(soa.Self(), long_array_dim2.Get()));
707   EXPECT_FALSE(transaction.WriteValueConstraint(soa.Self(), long_array->GetClass()));
708   EXPECT_FALSE(transaction.WriteValueConstraint(soa.Self(), long_array.Get()));
709 
710   // Test strict transaction.
711   Transaction strict_transaction(/*strict=*/ true, /*root=*/ static_field_class.Get());
712   // Static field in boot image.
713   EXPECT_TRUE(strict_transaction.WriteConstraint(soa.Self(), boolean_class.Get()));
714   EXPECT_TRUE(strict_transaction.ReadConstraint(soa.Self(), boolean_class.Get()));
715   // Instance field or array element in boot image.
716   // Do not check ReadConstraint(), it expects only static fields (checks for class object).
717   EXPECT_TRUE(strict_transaction.WriteConstraint(soa.Self(), true_value.Get()));
718   EXPECT_TRUE(strict_transaction.WriteConstraint(soa.Self(), array_iftable.Get()));
719   // Static field in another class not in boot image.
720   EXPECT_TRUE(strict_transaction.WriteConstraint(soa.Self(), static_fields_test_class.Get()));
721   EXPECT_TRUE(strict_transaction.ReadConstraint(soa.Self(), static_fields_test_class.Get()));
722   // Instance field or array element not in boot image.
723   // Do not check ReadConstraint(), it expects only static fields (checks for class object).
724   EXPECT_FALSE(strict_transaction.WriteConstraint(soa.Self(), instance_fields_test_object.Get()));
725   EXPECT_FALSE(strict_transaction.WriteConstraint(soa.Self(), long_array_dim2.Get()));
726   // Static field in the same class.
727   EXPECT_FALSE(strict_transaction.WriteConstraint(soa.Self(), static_field_class.Get()));
728   EXPECT_FALSE(strict_transaction.ReadConstraint(soa.Self(), static_field_class.Get()));
729   // Write value constraints.
730   EXPECT_FALSE(strict_transaction.WriteValueConstraint(soa.Self(), static_fields_test_class.Get()));
731   EXPECT_FALSE(
732       strict_transaction.WriteValueConstraint(soa.Self(), instance_fields_test_object.Get()));
733   // TODO: The following may be revised, see a TODO in Transaction::WriteValueConstraint().
734   EXPECT_FALSE(strict_transaction.WriteValueConstraint(soa.Self(), long_array_dim2->GetClass()));
735   EXPECT_FALSE(strict_transaction.WriteValueConstraint(soa.Self(), long_array_dim2.Get()));
736   EXPECT_FALSE(strict_transaction.WriteValueConstraint(soa.Self(), long_array->GetClass()));
737   EXPECT_FALSE(strict_transaction.WriteValueConstraint(soa.Self(), long_array.Get()));
738 }
739 
740 }  // namespace art
741