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 "mirror/array-inl.h" 24#include "scoped_thread_state_change.h" 25 26namespace art { 27 28class TransactionTest : public CommonRuntimeTest { 29 public: 30 // Tests failing class initialization due to native call with transaction rollback. 31 void testTransactionAbort(const char* tested_class_signature) { 32 ScopedObjectAccess soa(Thread::Current()); 33 jobject jclass_loader = LoadDex("Transaction"); 34 StackHandleScope<2> hs(soa.Self()); 35 Handle<mirror::ClassLoader> class_loader( 36 hs.NewHandle(soa.Decode<mirror::ClassLoader*>(jclass_loader))); 37 ASSERT_TRUE(class_loader.Get() != nullptr); 38 39 // Load and initialize java.lang.ExceptionInInitializerError and the exception class used 40 // to abort transaction so they can be thrown during class initialization if the transaction 41 // aborts. 42 MutableHandle<mirror::Class> h_klass( 43 hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), 44 "Ljava/lang/ExceptionInInitializerError;"))); 45 ASSERT_TRUE(h_klass.Get() != nullptr); 46 class_linker_->EnsureInitialized(soa.Self(), h_klass, true, true); 47 ASSERT_TRUE(h_klass->IsInitialized()); 48 49 h_klass.Assign(class_linker_->FindSystemClass(soa.Self(), 50 Transaction::kAbortExceptionSignature)); 51 ASSERT_TRUE(h_klass.Get() != nullptr); 52 class_linker_->EnsureInitialized(soa.Self(), h_klass, true, true); 53 ASSERT_TRUE(h_klass->IsInitialized()); 54 55 // Load and verify utility class. 56 h_klass.Assign(class_linker_->FindClass(soa.Self(), "LTransaction$AbortHelperClass;", 57 class_loader)); 58 ASSERT_TRUE(h_klass.Get() != nullptr); 59 class_linker_->VerifyClass(soa.Self(), h_klass); 60 ASSERT_TRUE(h_klass->IsVerified()); 61 62 // Load and verify tested class. 63 h_klass.Assign(class_linker_->FindClass(soa.Self(), tested_class_signature, class_loader)); 64 ASSERT_TRUE(h_klass.Get() != nullptr); 65 class_linker_->VerifyClass(soa.Self(), h_klass); 66 ASSERT_TRUE(h_klass->IsVerified()); 67 68 mirror::Class::Status old_status = h_klass->GetStatus(); 69 LockWord old_lock_word = h_klass->GetLockWord(false); 70 71 Transaction transaction; 72 Runtime::Current()->EnterTransactionMode(&transaction); 73 bool success = class_linker_->EnsureInitialized(soa.Self(), h_klass, true, true); 74 Runtime::Current()->ExitTransactionMode(); 75 ASSERT_FALSE(success); 76 ASSERT_TRUE(h_klass->IsErroneous()); 77 ASSERT_TRUE(soa.Self()->IsExceptionPending()); 78 ASSERT_TRUE(transaction.IsAborted()); 79 80 // Check class's monitor get back to its original state without rolling back changes. 81 LockWord new_lock_word = h_klass->GetLockWord(false); 82 EXPECT_TRUE(LockWord::Equal<false>(old_lock_word, new_lock_word)); 83 84 // Check class status is rolled back properly. 85 soa.Self()->ClearException(); 86 transaction.Rollback(); 87 ASSERT_EQ(old_status, h_klass->GetStatus()); 88 } 89}; 90 91// Tests object's class is preserved after transaction rollback. 92TEST_F(TransactionTest, Object_class) { 93 ScopedObjectAccess soa(Thread::Current()); 94 StackHandleScope<2> hs(soa.Self()); 95 Handle<mirror::Class> h_klass( 96 hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;"))); 97 ASSERT_TRUE(h_klass.Get() != nullptr); 98 99 Transaction transaction; 100 Runtime::Current()->EnterTransactionMode(&transaction); 101 Handle<mirror::Object> h_obj(hs.NewHandle(h_klass->AllocObject(soa.Self()))); 102 ASSERT_TRUE(h_obj.Get() != nullptr); 103 ASSERT_EQ(h_obj->GetClass(), h_klass.Get()); 104 Runtime::Current()->ExitTransactionMode(); 105 106 // Rolling back transaction's changes must not clear the Object::class field. 107 transaction.Rollback(); 108 EXPECT_EQ(h_obj->GetClass(), h_klass.Get()); 109} 110 111// Tests object's monitor state is preserved after transaction rollback. 112TEST_F(TransactionTest, Object_monitor) { 113 ScopedObjectAccess soa(Thread::Current()); 114 StackHandleScope<2> hs(soa.Self()); 115 Handle<mirror::Class> h_klass( 116 hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;"))); 117 ASSERT_TRUE(h_klass.Get() != nullptr); 118 Handle<mirror::Object> h_obj(hs.NewHandle(h_klass->AllocObject(soa.Self()))); 119 ASSERT_TRUE(h_obj.Get() != nullptr); 120 ASSERT_EQ(h_obj->GetClass(), h_klass.Get()); 121 122 // Lock object's monitor outside the transaction. 123 h_obj->MonitorEnter(soa.Self()); 124 LockWord old_lock_word = h_obj->GetLockWord(false); 125 126 Transaction transaction; 127 Runtime::Current()->EnterTransactionMode(&transaction); 128 // Unlock object's monitor inside the transaction. 129 h_obj->MonitorExit(soa.Self()); 130 LockWord new_lock_word = h_obj->GetLockWord(false); 131 Runtime::Current()->ExitTransactionMode(); 132 133 // Rolling back transaction's changes must not change monitor's state. 134 transaction.Rollback(); 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. 141TEST_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.Get() != nullptr); 147 148 constexpr int32_t kArraySize = 2; 149 150 Transaction transaction; 151 Runtime::Current()->EnterTransactionMode(&transaction); 152 153 // Allocate an array during transaction. 154 Handle<mirror::Array> h_obj( 155 hs.NewHandle( 156 mirror::Array::Alloc<true>(soa.Self(), h_klass.Get(), kArraySize, 157 h_klass->GetComponentSizeShift(), 158 Runtime::Current()->GetHeap()->GetCurrentAllocator()))); 159 ASSERT_TRUE(h_obj.Get() != nullptr); 160 ASSERT_EQ(h_obj->GetClass(), h_klass.Get()); 161 Runtime::Current()->ExitTransactionMode(); 162 163 // Rolling back transaction's changes must not reset array's length. 164 transaction.Rollback(); 165 EXPECT_EQ(h_obj->GetLength(), kArraySize); 166} 167 168// Tests static fields are reset to their default value after transaction rollback. 169TEST_F(TransactionTest, StaticFieldsTest) { 170 ScopedObjectAccess soa(Thread::Current()); 171 StackHandleScope<4> hs(soa.Self()); 172 Handle<mirror::ClassLoader> class_loader( 173 hs.NewHandle(soa.Decode<mirror::ClassLoader*>(LoadDex("Transaction")))); 174 ASSERT_TRUE(class_loader.Get() != nullptr); 175 176 Handle<mirror::Class> h_klass( 177 hs.NewHandle(class_linker_->FindClass(soa.Self(), "LStaticFieldsTest;", class_loader))); 178 ASSERT_TRUE(h_klass.Get() != nullptr); 179 bool success = class_linker_->EnsureInitialized(soa.Self(), h_klass, true, true); 180 ASSERT_TRUE(success); 181 ASSERT_TRUE(h_klass->IsInitialized()); 182 ASSERT_FALSE(soa.Self()->IsExceptionPending()); 183 184 // Lookup fields. 185 ArtField* booleanField = h_klass->FindDeclaredStaticField("booleanField", "Z"); 186 ASSERT_TRUE(booleanField != nullptr); 187 ASSERT_EQ(booleanField->GetTypeAsPrimitiveType(), Primitive::kPrimBoolean); 188 ASSERT_EQ(booleanField->GetBoolean(h_klass.Get()), false); 189 190 ArtField* byteField = h_klass->FindDeclaredStaticField("byteField", "B"); 191 ASSERT_TRUE(byteField != nullptr); 192 ASSERT_EQ(byteField->GetTypeAsPrimitiveType(), Primitive::kPrimByte); 193 ASSERT_EQ(byteField->GetByte(h_klass.Get()), 0); 194 195 ArtField* charField = h_klass->FindDeclaredStaticField("charField", "C"); 196 ASSERT_TRUE(charField != nullptr); 197 ASSERT_EQ(charField->GetTypeAsPrimitiveType(), Primitive::kPrimChar); 198 ASSERT_EQ(charField->GetChar(h_klass.Get()), 0u); 199 200 ArtField* shortField = h_klass->FindDeclaredStaticField("shortField", "S"); 201 ASSERT_TRUE(shortField != nullptr); 202 ASSERT_EQ(shortField->GetTypeAsPrimitiveType(), Primitive::kPrimShort); 203 ASSERT_EQ(shortField->GetShort(h_klass.Get()), 0); 204 205 ArtField* intField = h_klass->FindDeclaredStaticField("intField", "I"); 206 ASSERT_TRUE(intField != nullptr); 207 ASSERT_EQ(intField->GetTypeAsPrimitiveType(), Primitive::kPrimInt); 208 ASSERT_EQ(intField->GetInt(h_klass.Get()), 0); 209 210 ArtField* longField = h_klass->FindDeclaredStaticField("longField", "J"); 211 ASSERT_TRUE(longField != nullptr); 212 ASSERT_EQ(longField->GetTypeAsPrimitiveType(), Primitive::kPrimLong); 213 ASSERT_EQ(longField->GetLong(h_klass.Get()), static_cast<int64_t>(0)); 214 215 ArtField* floatField = h_klass->FindDeclaredStaticField("floatField", "F"); 216 ASSERT_TRUE(floatField != nullptr); 217 ASSERT_EQ(floatField->GetTypeAsPrimitiveType(), Primitive::kPrimFloat); 218 ASSERT_FLOAT_EQ(floatField->GetFloat(h_klass.Get()), static_cast<float>(0.0f)); 219 220 ArtField* doubleField = h_klass->FindDeclaredStaticField("doubleField", "D"); 221 ASSERT_TRUE(doubleField != nullptr); 222 ASSERT_EQ(doubleField->GetTypeAsPrimitiveType(), Primitive::kPrimDouble); 223 ASSERT_DOUBLE_EQ(doubleField->GetDouble(h_klass.Get()), static_cast<double>(0.0)); 224 225 ArtField* objectField = h_klass->FindDeclaredStaticField("objectField", 226 "Ljava/lang/Object;"); 227 ASSERT_TRUE(objectField != nullptr); 228 ASSERT_EQ(objectField->GetTypeAsPrimitiveType(), Primitive::kPrimNot); 229 ASSERT_EQ(objectField->GetObject(h_klass.Get()), nullptr); 230 231 // Create a java.lang.Object instance to set objectField. 232 Handle<mirror::Class> object_klass( 233 hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;"))); 234 ASSERT_TRUE(object_klass.Get() != nullptr); 235 Handle<mirror::Object> h_obj(hs.NewHandle(h_klass->AllocObject(soa.Self()))); 236 ASSERT_TRUE(h_obj.Get() != nullptr); 237 ASSERT_EQ(h_obj->GetClass(), h_klass.Get()); 238 239 // Modify fields inside transaction then rollback changes. 240 Transaction transaction; 241 Runtime::Current()->EnterTransactionMode(&transaction); 242 booleanField->SetBoolean<true>(h_klass.Get(), true); 243 byteField->SetByte<true>(h_klass.Get(), 1); 244 charField->SetChar<true>(h_klass.Get(), 1u); 245 shortField->SetShort<true>(h_klass.Get(), 1); 246 intField->SetInt<true>(h_klass.Get(), 1); 247 longField->SetLong<true>(h_klass.Get(), 1); 248 floatField->SetFloat<true>(h_klass.Get(), 1.0); 249 doubleField->SetDouble<true>(h_klass.Get(), 1.0); 250 objectField->SetObject<true>(h_klass.Get(), h_obj.Get()); 251 Runtime::Current()->ExitTransactionMode(); 252 transaction.Rollback(); 253 254 // Check values have properly been restored to their original (default) value. 255 EXPECT_EQ(booleanField->GetBoolean(h_klass.Get()), false); 256 EXPECT_EQ(byteField->GetByte(h_klass.Get()), 0); 257 EXPECT_EQ(charField->GetChar(h_klass.Get()), 0u); 258 EXPECT_EQ(shortField->GetShort(h_klass.Get()), 0); 259 EXPECT_EQ(intField->GetInt(h_klass.Get()), 0); 260 EXPECT_EQ(longField->GetLong(h_klass.Get()), static_cast<int64_t>(0)); 261 EXPECT_FLOAT_EQ(floatField->GetFloat(h_klass.Get()), static_cast<float>(0.0f)); 262 EXPECT_DOUBLE_EQ(doubleField->GetDouble(h_klass.Get()), static_cast<double>(0.0)); 263 EXPECT_EQ(objectField->GetObject(h_klass.Get()), nullptr); 264} 265 266// Tests instance fields are reset to their default value after transaction rollback. 267TEST_F(TransactionTest, InstanceFieldsTest) { 268 ScopedObjectAccess soa(Thread::Current()); 269 StackHandleScope<5> hs(soa.Self()); 270 Handle<mirror::ClassLoader> class_loader( 271 hs.NewHandle(soa.Decode<mirror::ClassLoader*>(LoadDex("Transaction")))); 272 ASSERT_TRUE(class_loader.Get() != nullptr); 273 274 Handle<mirror::Class> h_klass( 275 hs.NewHandle(class_linker_->FindClass(soa.Self(), "LInstanceFieldsTest;", class_loader))); 276 ASSERT_TRUE(h_klass.Get() != nullptr); 277 bool success = class_linker_->EnsureInitialized(soa.Self(), h_klass, true, true); 278 ASSERT_TRUE(success); 279 ASSERT_TRUE(h_klass->IsInitialized()); 280 ASSERT_FALSE(soa.Self()->IsExceptionPending()); 281 282 // Allocate an InstanceFieldTest object. 283 Handle<mirror::Object> h_instance(hs.NewHandle(h_klass->AllocObject(soa.Self()))); 284 ASSERT_TRUE(h_instance.Get() != nullptr); 285 286 // Lookup fields. 287 ArtField* booleanField = h_klass->FindDeclaredInstanceField("booleanField", "Z"); 288 ASSERT_TRUE(booleanField != nullptr); 289 ASSERT_EQ(booleanField->GetTypeAsPrimitiveType(), Primitive::kPrimBoolean); 290 ASSERT_EQ(booleanField->GetBoolean(h_instance.Get()), false); 291 292 ArtField* byteField = h_klass->FindDeclaredInstanceField("byteField", "B"); 293 ASSERT_TRUE(byteField != nullptr); 294 ASSERT_EQ(byteField->GetTypeAsPrimitiveType(), Primitive::kPrimByte); 295 ASSERT_EQ(byteField->GetByte(h_instance.Get()), 0); 296 297 ArtField* charField = h_klass->FindDeclaredInstanceField("charField", "C"); 298 ASSERT_TRUE(charField != nullptr); 299 ASSERT_EQ(charField->GetTypeAsPrimitiveType(), Primitive::kPrimChar); 300 ASSERT_EQ(charField->GetChar(h_instance.Get()), 0u); 301 302 ArtField* shortField = h_klass->FindDeclaredInstanceField("shortField", "S"); 303 ASSERT_TRUE(shortField != nullptr); 304 ASSERT_EQ(shortField->GetTypeAsPrimitiveType(), Primitive::kPrimShort); 305 ASSERT_EQ(shortField->GetShort(h_instance.Get()), 0); 306 307 ArtField* intField = h_klass->FindDeclaredInstanceField("intField", "I"); 308 ASSERT_TRUE(intField != nullptr); 309 ASSERT_EQ(intField->GetTypeAsPrimitiveType(), Primitive::kPrimInt); 310 ASSERT_EQ(intField->GetInt(h_instance.Get()), 0); 311 312 ArtField* longField = h_klass->FindDeclaredInstanceField("longField", "J"); 313 ASSERT_TRUE(longField != nullptr); 314 ASSERT_EQ(longField->GetTypeAsPrimitiveType(), Primitive::kPrimLong); 315 ASSERT_EQ(longField->GetLong(h_instance.Get()), static_cast<int64_t>(0)); 316 317 ArtField* floatField = h_klass->FindDeclaredInstanceField("floatField", "F"); 318 ASSERT_TRUE(floatField != nullptr); 319 ASSERT_EQ(floatField->GetTypeAsPrimitiveType(), Primitive::kPrimFloat); 320 ASSERT_FLOAT_EQ(floatField->GetFloat(h_instance.Get()), static_cast<float>(0.0f)); 321 322 ArtField* doubleField = h_klass->FindDeclaredInstanceField("doubleField", "D"); 323 ASSERT_TRUE(doubleField != nullptr); 324 ASSERT_EQ(doubleField->GetTypeAsPrimitiveType(), Primitive::kPrimDouble); 325 ASSERT_DOUBLE_EQ(doubleField->GetDouble(h_instance.Get()), static_cast<double>(0.0)); 326 327 ArtField* objectField = h_klass->FindDeclaredInstanceField("objectField", 328 "Ljava/lang/Object;"); 329 ASSERT_TRUE(objectField != nullptr); 330 ASSERT_EQ(objectField->GetTypeAsPrimitiveType(), Primitive::kPrimNot); 331 ASSERT_EQ(objectField->GetObject(h_instance.Get()), nullptr); 332 333 // Create a java.lang.Object instance to set objectField. 334 Handle<mirror::Class> object_klass( 335 hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;"))); 336 ASSERT_TRUE(object_klass.Get() != nullptr); 337 Handle<mirror::Object> h_obj(hs.NewHandle(h_klass->AllocObject(soa.Self()))); 338 ASSERT_TRUE(h_obj.Get() != nullptr); 339 ASSERT_EQ(h_obj->GetClass(), h_klass.Get()); 340 341 // Modify fields inside transaction then rollback changes. 342 Transaction transaction; 343 Runtime::Current()->EnterTransactionMode(&transaction); 344 booleanField->SetBoolean<true>(h_instance.Get(), true); 345 byteField->SetByte<true>(h_instance.Get(), 1); 346 charField->SetChar<true>(h_instance.Get(), 1u); 347 shortField->SetShort<true>(h_instance.Get(), 1); 348 intField->SetInt<true>(h_instance.Get(), 1); 349 longField->SetLong<true>(h_instance.Get(), 1); 350 floatField->SetFloat<true>(h_instance.Get(), 1.0); 351 doubleField->SetDouble<true>(h_instance.Get(), 1.0); 352 objectField->SetObject<true>(h_instance.Get(), h_obj.Get()); 353 Runtime::Current()->ExitTransactionMode(); 354 transaction.Rollback(); 355 356 // Check values have properly been restored to their original (default) value. 357 EXPECT_EQ(booleanField->GetBoolean(h_instance.Get()), false); 358 EXPECT_EQ(byteField->GetByte(h_instance.Get()), 0); 359 EXPECT_EQ(charField->GetChar(h_instance.Get()), 0u); 360 EXPECT_EQ(shortField->GetShort(h_instance.Get()), 0); 361 EXPECT_EQ(intField->GetInt(h_instance.Get()), 0); 362 EXPECT_EQ(longField->GetLong(h_instance.Get()), static_cast<int64_t>(0)); 363 EXPECT_FLOAT_EQ(floatField->GetFloat(h_instance.Get()), static_cast<float>(0.0f)); 364 EXPECT_DOUBLE_EQ(doubleField->GetDouble(h_instance.Get()), static_cast<double>(0.0)); 365 EXPECT_EQ(objectField->GetObject(h_instance.Get()), nullptr); 366} 367 368// Tests static array fields are reset to their default value after transaction rollback. 369TEST_F(TransactionTest, StaticArrayFieldsTest) { 370 ScopedObjectAccess soa(Thread::Current()); 371 StackHandleScope<4> hs(soa.Self()); 372 Handle<mirror::ClassLoader> class_loader( 373 hs.NewHandle(soa.Decode<mirror::ClassLoader*>(LoadDex("Transaction")))); 374 ASSERT_TRUE(class_loader.Get() != nullptr); 375 376 Handle<mirror::Class> h_klass( 377 hs.NewHandle(class_linker_->FindClass(soa.Self(), "LStaticArrayFieldsTest;", class_loader))); 378 ASSERT_TRUE(h_klass.Get() != nullptr); 379 bool success = class_linker_->EnsureInitialized(soa.Self(), h_klass, true, true); 380 ASSERT_TRUE(success); 381 ASSERT_TRUE(h_klass->IsInitialized()); 382 ASSERT_FALSE(soa.Self()->IsExceptionPending()); 383 384 // Lookup fields. 385 ArtField* booleanArrayField = h_klass->FindDeclaredStaticField("booleanArrayField", "[Z"); 386 ASSERT_TRUE(booleanArrayField != nullptr); 387 mirror::BooleanArray* booleanArray = booleanArrayField->GetObject(h_klass.Get())->AsBooleanArray(); 388 ASSERT_TRUE(booleanArray != nullptr); 389 ASSERT_EQ(booleanArray->GetLength(), 1); 390 ASSERT_EQ(booleanArray->GetWithoutChecks(0), false); 391 392 ArtField* byteArrayField = h_klass->FindDeclaredStaticField("byteArrayField", "[B"); 393 ASSERT_TRUE(byteArrayField != nullptr); 394 mirror::ByteArray* byteArray = byteArrayField->GetObject(h_klass.Get())->AsByteArray(); 395 ASSERT_TRUE(byteArray != nullptr); 396 ASSERT_EQ(byteArray->GetLength(), 1); 397 ASSERT_EQ(byteArray->GetWithoutChecks(0), 0); 398 399 ArtField* charArrayField = h_klass->FindDeclaredStaticField("charArrayField", "[C"); 400 ASSERT_TRUE(charArrayField != nullptr); 401 mirror::CharArray* charArray = charArrayField->GetObject(h_klass.Get())->AsCharArray(); 402 ASSERT_TRUE(charArray != nullptr); 403 ASSERT_EQ(charArray->GetLength(), 1); 404 ASSERT_EQ(charArray->GetWithoutChecks(0), 0u); 405 406 ArtField* shortArrayField = h_klass->FindDeclaredStaticField("shortArrayField", "[S"); 407 ASSERT_TRUE(shortArrayField != nullptr); 408 mirror::ShortArray* shortArray = shortArrayField->GetObject(h_klass.Get())->AsShortArray(); 409 ASSERT_TRUE(shortArray != nullptr); 410 ASSERT_EQ(shortArray->GetLength(), 1); 411 ASSERT_EQ(shortArray->GetWithoutChecks(0), 0); 412 413 ArtField* intArrayField = h_klass->FindDeclaredStaticField("intArrayField", "[I"); 414 ASSERT_TRUE(intArrayField != nullptr); 415 mirror::IntArray* intArray = 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 mirror::LongArray* longArray = longArrayField->GetObject(h_klass.Get())->AsLongArray(); 423 ASSERT_TRUE(longArray != nullptr); 424 ASSERT_EQ(longArray->GetLength(), 1); 425 ASSERT_EQ(longArray->GetWithoutChecks(0), static_cast<int64_t>(0)); 426 427 ArtField* floatArrayField = h_klass->FindDeclaredStaticField("floatArrayField", "[F"); 428 ASSERT_TRUE(floatArrayField != nullptr); 429 mirror::FloatArray* floatArray = floatArrayField->GetObject(h_klass.Get())->AsFloatArray(); 430 ASSERT_TRUE(floatArray != nullptr); 431 ASSERT_EQ(floatArray->GetLength(), 1); 432 ASSERT_FLOAT_EQ(floatArray->GetWithoutChecks(0), static_cast<float>(0.0f)); 433 434 ArtField* doubleArrayField = h_klass->FindDeclaredStaticField("doubleArrayField", "[D"); 435 ASSERT_TRUE(doubleArrayField != nullptr); 436 mirror::DoubleArray* doubleArray = doubleArrayField->GetObject(h_klass.Get())->AsDoubleArray(); 437 ASSERT_TRUE(doubleArray != nullptr); 438 ASSERT_EQ(doubleArray->GetLength(), 1); 439 ASSERT_DOUBLE_EQ(doubleArray->GetWithoutChecks(0), static_cast<double>(0.0f)); 440 441 ArtField* objectArrayField = h_klass->FindDeclaredStaticField("objectArrayField", 442 "[Ljava/lang/Object;"); 443 ASSERT_TRUE(objectArrayField != nullptr); 444 mirror::ObjectArray<mirror::Object>* objectArray = 445 objectArrayField->GetObject(h_klass.Get())->AsObjectArray<mirror::Object>(); 446 ASSERT_TRUE(objectArray != nullptr); 447 ASSERT_EQ(objectArray->GetLength(), 1); 448 ASSERT_EQ(objectArray->GetWithoutChecks(0), nullptr); 449 450 // Create a java.lang.Object instance to set objectField. 451 Handle<mirror::Class> object_klass( 452 hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;"))); 453 ASSERT_TRUE(object_klass.Get() != nullptr); 454 Handle<mirror::Object> h_obj(hs.NewHandle(h_klass->AllocObject(soa.Self()))); 455 ASSERT_TRUE(h_obj.Get() != nullptr); 456 ASSERT_EQ(h_obj->GetClass(), h_klass.Get()); 457 458 // Modify fields inside transaction then rollback changes. 459 Transaction transaction; 460 Runtime::Current()->EnterTransactionMode(&transaction); 461 booleanArray->SetWithoutChecks<true>(0, true); 462 byteArray->SetWithoutChecks<true>(0, 1); 463 charArray->SetWithoutChecks<true>(0, 1u); 464 shortArray->SetWithoutChecks<true>(0, 1); 465 intArray->SetWithoutChecks<true>(0, 1); 466 longArray->SetWithoutChecks<true>(0, 1); 467 floatArray->SetWithoutChecks<true>(0, 1.0); 468 doubleArray->SetWithoutChecks<true>(0, 1.0); 469 objectArray->SetWithoutChecks<true>(0, h_obj.Get()); 470 Runtime::Current()->ExitTransactionMode(); 471 transaction.Rollback(); 472 473 // Check values have properly been restored to their original (default) value. 474 EXPECT_EQ(booleanArray->GetWithoutChecks(0), false); 475 EXPECT_EQ(byteArray->GetWithoutChecks(0), 0); 476 EXPECT_EQ(charArray->GetWithoutChecks(0), 0u); 477 EXPECT_EQ(shortArray->GetWithoutChecks(0), 0); 478 EXPECT_EQ(intArray->GetWithoutChecks(0), 0); 479 EXPECT_EQ(longArray->GetWithoutChecks(0), static_cast<int64_t>(0)); 480 EXPECT_FLOAT_EQ(floatArray->GetWithoutChecks(0), static_cast<float>(0.0f)); 481 EXPECT_DOUBLE_EQ(doubleArray->GetWithoutChecks(0), static_cast<double>(0.0f)); 482 EXPECT_EQ(objectArray->GetWithoutChecks(0), nullptr); 483} 484 485// Tests successful class initialization without class initializer. 486TEST_F(TransactionTest, EmptyClass) { 487 ScopedObjectAccess soa(Thread::Current()); 488 StackHandleScope<2> hs(soa.Self()); 489 Handle<mirror::ClassLoader> class_loader( 490 hs.NewHandle(soa.Decode<mirror::ClassLoader*>(LoadDex("Transaction")))); 491 ASSERT_TRUE(class_loader.Get() != nullptr); 492 493 Handle<mirror::Class> h_klass( 494 hs.NewHandle(class_linker_->FindClass(soa.Self(), "LTransaction$EmptyStatic;", 495 class_loader))); 496 ASSERT_TRUE(h_klass.Get() != nullptr); 497 class_linker_->VerifyClass(soa.Self(), h_klass); 498 ASSERT_TRUE(h_klass->IsVerified()); 499 500 Transaction transaction; 501 Runtime::Current()->EnterTransactionMode(&transaction); 502 bool success = class_linker_->EnsureInitialized(soa.Self(), h_klass, true, true); 503 Runtime::Current()->ExitTransactionMode(); 504 ASSERT_TRUE(success); 505 ASSERT_TRUE(h_klass->IsInitialized()); 506 ASSERT_FALSE(soa.Self()->IsExceptionPending()); 507} 508 509// Tests successful class initialization with class initializer. 510TEST_F(TransactionTest, StaticFieldClass) { 511 ScopedObjectAccess soa(Thread::Current()); 512 StackHandleScope<2> hs(soa.Self()); 513 Handle<mirror::ClassLoader> class_loader( 514 hs.NewHandle(soa.Decode<mirror::ClassLoader*>(LoadDex("Transaction")))); 515 ASSERT_TRUE(class_loader.Get() != nullptr); 516 517 Handle<mirror::Class> h_klass( 518 hs.NewHandle(class_linker_->FindClass(soa.Self(), "LTransaction$StaticFieldClass;", 519 class_loader))); 520 ASSERT_TRUE(h_klass.Get() != nullptr); 521 class_linker_->VerifyClass(soa.Self(), h_klass); 522 ASSERT_TRUE(h_klass->IsVerified()); 523 524 Transaction transaction; 525 Runtime::Current()->EnterTransactionMode(&transaction); 526 bool success = class_linker_->EnsureInitialized(soa.Self(), h_klass, true, true); 527 Runtime::Current()->ExitTransactionMode(); 528 ASSERT_TRUE(success); 529 ASSERT_TRUE(h_klass->IsInitialized()); 530 ASSERT_FALSE(soa.Self()->IsExceptionPending()); 531} 532 533// Tests failing class initialization due to native call. 534TEST_F(TransactionTest, NativeCallAbortClass) { 535 testTransactionAbort("LTransaction$NativeCallAbortClass;"); 536} 537 538// Tests failing class initialization due to native call in a "synchronized" statement 539// (which must catch any exception, do the monitor-exit then re-throw the caught exception). 540TEST_F(TransactionTest, SynchronizedNativeCallAbortClass) { 541 testTransactionAbort("LTransaction$SynchronizedNativeCallAbortClass;"); 542} 543 544// Tests failing class initialization due to native call, even if an "all" catch handler 545// catches the exception thrown when aborting the transaction. 546TEST_F(TransactionTest, CatchNativeCallAbortClass) { 547 testTransactionAbort("LTransaction$CatchNativeCallAbortClass;"); 548} 549 550// Tests failing class initialization with multiple transaction aborts. 551TEST_F(TransactionTest, MultipleNativeCallAbortClass) { 552 testTransactionAbort("LTransaction$MultipleNativeCallAbortClass;"); 553} 554 555// Tests failing class initialization due to allocating instance of finalizable class. 556TEST_F(TransactionTest, FinalizableAbortClass) { 557 testTransactionAbort("LTransaction$FinalizableAbortClass;"); 558} 559} // namespace art 560