1 /* 2 * Copyright (C) 2018 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 "method_handles.h" 18 19 #include "class_linker-inl.h" 20 #include "common_runtime_test.h" 21 #include "handle_scope-inl.h" 22 #include "jvalue-inl.h" 23 #include "mirror/method_type.h" 24 #include "mirror/object_array-inl.h" 25 #include "reflection.h" 26 #include "scoped_thread_state_change-inl.h" 27 #include "thread-current-inl.h" 28 29 namespace art { 30 31 namespace { 32 bool IsClassCastException(ObjPtr<mirror::Throwable> throwable) 33 REQUIRES_SHARED(Locks::mutator_lock_) { 34 return throwable->GetClass()->DescriptorEquals("Ljava/lang/ClassCastException;"); 35 } 36 37 bool IsNullPointerException(ObjPtr<mirror::Throwable> throwable) 38 REQUIRES_SHARED(Locks::mutator_lock_) { 39 return throwable->GetClass()->DescriptorEquals("Ljava/lang/NullPointerException;"); 40 } 41 42 bool IsWrongMethodTypeException(ObjPtr<mirror::Throwable> throwable) 43 REQUIRES_SHARED(Locks::mutator_lock_) { 44 return throwable->GetClass()->DescriptorEquals("Ljava/lang/invoke/WrongMethodTypeException;"); 45 } 46 47 static mirror::MethodType* CreateVoidMethodType(Thread* self, 48 Handle<mirror::Class> parameter_type) 49 REQUIRES_SHARED(Locks::mutator_lock_) { 50 ClassLinker* cl = Runtime::Current()->GetClassLinker(); 51 StackHandleScope<2> hs(self); 52 ObjPtr<mirror::Class> class_type = mirror::Class::GetJavaLangClass(); 53 ObjPtr<mirror::Class> class_array_type = cl->FindArrayClass(self, &class_type); 54 auto parameter_types = hs.NewHandle( 55 mirror::ObjectArray<mirror::Class>::Alloc(self, class_array_type, 1)); 56 parameter_types->Set(0, parameter_type.Get()); 57 Handle<mirror::Class> void_class = hs.NewHandle(cl->FindPrimitiveClass('V')); 58 return mirror::MethodType::Create(self, void_class, parameter_types); 59 } 60 61 static bool TryConversion(Thread* self, 62 Handle<mirror::Class> from, 63 Handle<mirror::Class> to, 64 JValue* value) 65 REQUIRES_SHARED(Locks::mutator_lock_) { 66 StackHandleScope<2> hs(self); 67 Handle<mirror::MethodType> from_mt = hs.NewHandle(CreateVoidMethodType(self, from)); 68 Handle<mirror::MethodType> to_mt = hs.NewHandle(CreateVoidMethodType(self, to)); 69 return ConvertJValueCommon(from_mt, to_mt, from.Get(), to.Get(), value); 70 } 71 } // namespace 72 73 class MethodHandlesTest : public CommonRuntimeTest {}; 74 75 // 76 // Primitive -> Primitive Conversions 77 // 78 79 TEST_F(MethodHandlesTest, SupportedPrimitiveWideningBI) { 80 ScopedObjectAccess soa(Thread::Current()); 81 ClassLinker* cl = Runtime::Current()->GetClassLinker(); 82 StackHandleScope<2> hs(soa.Self()); 83 Handle<mirror::Class> from = hs.NewHandle(cl->FindPrimitiveClass('B')); 84 Handle<mirror::Class> to = hs.NewHandle(cl->FindPrimitiveClass('I')); 85 JValue value = JValue::FromPrimitive(static_cast<int8_t>(3)); 86 ASSERT_TRUE(TryConversion(soa.Self(), from, to, &value)); 87 ASSERT_EQ(3, value.GetI()); 88 ASSERT_FALSE(soa.Self()->IsExceptionPending()); 89 } 90 91 TEST_F(MethodHandlesTest, SupportedPrimitiveWideningCJ) { 92 ScopedObjectAccess soa(Thread::Current()); 93 ClassLinker* cl = Runtime::Current()->GetClassLinker(); 94 StackHandleScope<2> hs(soa.Self()); 95 Handle<mirror::Class> from = hs.NewHandle(cl->FindPrimitiveClass('C')); 96 Handle<mirror::Class> to = hs.NewHandle(cl->FindPrimitiveClass('J')); 97 uint16_t raw_value = 0x8000; 98 JValue value = JValue::FromPrimitive(raw_value); 99 ASSERT_TRUE(TryConversion(soa.Self(), from, to, &value)); 100 ASSERT_FALSE(soa.Self()->IsExceptionPending()); 101 ASSERT_EQ(static_cast<int64_t>(raw_value), value.GetJ()); 102 } 103 104 TEST_F(MethodHandlesTest, SupportedPrimitiveWideningIF) { 105 ScopedObjectAccess soa(Thread::Current()); 106 ClassLinker* cl = Runtime::Current()->GetClassLinker(); 107 StackHandleScope<2> hs(soa.Self()); 108 Handle<mirror::Class> from = hs.NewHandle(cl->FindPrimitiveClass('I')); 109 Handle<mirror::Class> to = hs.NewHandle(cl->FindPrimitiveClass('F')); 110 JValue value = JValue::FromPrimitive(-16); 111 ASSERT_TRUE(TryConversion(soa.Self(), from, to, &value)); 112 ASSERT_FALSE(soa.Self()->IsExceptionPending()); 113 ASSERT_FLOAT_EQ(-16.0f, value.GetF()); 114 } 115 116 TEST_F(MethodHandlesTest, UnsupportedPrimitiveWideningBC) { 117 ScopedObjectAccess soa(Thread::Current()); 118 ClassLinker* cl = Runtime::Current()->GetClassLinker(); 119 StackHandleScope<2> hs(soa.Self()); 120 Handle<mirror::Class> from = hs.NewHandle(cl->FindPrimitiveClass('B')); 121 Handle<mirror::Class> to = hs.NewHandle(cl->FindPrimitiveClass('C')); 122 JValue value; 123 value.SetB(0); 124 ASSERT_FALSE(TryConversion(soa.Self(), from, to, &value)); 125 ASSERT_TRUE(soa.Self()->IsExceptionPending()); 126 ASSERT_TRUE(IsWrongMethodTypeException(soa.Self()->GetException())); 127 soa.Self()->ClearException(); 128 } 129 130 TEST_F(MethodHandlesTest, UnsupportedPrimitiveWideningSC) { 131 ScopedObjectAccess soa(Thread::Current()); 132 ClassLinker* cl = Runtime::Current()->GetClassLinker(); 133 StackHandleScope<2> hs(soa.Self()); 134 Handle<mirror::Class> from = hs.NewHandle(cl->FindPrimitiveClass('S')); 135 Handle<mirror::Class> to = hs.NewHandle(cl->FindPrimitiveClass('C')); 136 JValue value; 137 value.SetS(0x1234); 138 ASSERT_FALSE(TryConversion(soa.Self(), from, to, &value)); 139 ASSERT_TRUE(soa.Self()->IsExceptionPending()); 140 ASSERT_TRUE(IsWrongMethodTypeException(soa.Self()->GetException())); 141 soa.Self()->ClearException(); 142 } 143 144 TEST_F(MethodHandlesTest, UnsupportedPrimitiveWideningDJ) { 145 ScopedObjectAccess soa(Thread::Current()); 146 ClassLinker* cl = Runtime::Current()->GetClassLinker(); 147 StackHandleScope<2> hs(soa.Self()); 148 Handle<mirror::Class> from = hs.NewHandle(cl->FindPrimitiveClass('D')); 149 Handle<mirror::Class> to = hs.NewHandle(cl->FindPrimitiveClass('J')); 150 JValue value; 151 value.SetD(1e72); 152 ASSERT_FALSE(TryConversion(soa.Self(), from, to, &value)); 153 ASSERT_TRUE(soa.Self()->IsExceptionPending()); 154 ASSERT_TRUE(IsWrongMethodTypeException(soa.Self()->GetException())); 155 soa.Self()->ClearException(); 156 } 157 158 TEST_F(MethodHandlesTest, UnsupportedPrimitiveWideningZI) { 159 ScopedObjectAccess soa(Thread::Current()); 160 ClassLinker* cl = Runtime::Current()->GetClassLinker(); 161 StackHandleScope<2> hs(soa.Self()); 162 Handle<mirror::Class> from = hs.NewHandle(cl->FindPrimitiveClass('Z')); 163 Handle<mirror::Class> to = hs.NewHandle(cl->FindPrimitiveClass('I')); 164 JValue value; 165 value.SetZ(true); 166 ASSERT_FALSE(TryConversion(soa.Self(), from, to, &value)); 167 ASSERT_TRUE(soa.Self()->IsExceptionPending()); 168 ASSERT_TRUE(IsWrongMethodTypeException(soa.Self()->GetException())); 169 soa.Self()->ClearException(); 170 } 171 172 // 173 // Reference -> Reference Conversions 174 // 175 176 TEST_F(MethodHandlesTest, SupportedReferenceCast) { 177 ScopedObjectAccess soa(Thread::Current()); 178 ClassLinker* cl = Runtime::Current()->GetClassLinker(); 179 StackHandleScope<3> hs(soa.Self()); 180 static const int32_t kInitialValue = 101; 181 JValue value = JValue::FromPrimitive(kInitialValue); 182 Handle<mirror::Object> boxed_value = hs.NewHandle(BoxPrimitive(Primitive::kPrimInt, value).Ptr()); 183 Handle<mirror::Class> from = hs.NewHandle(boxed_value->GetClass()); 184 Handle<mirror::Class> to = hs.NewHandle(cl->FindSystemClass(soa.Self(), "Ljava/lang/Number;")); 185 value.SetL(boxed_value.Get()); 186 ASSERT_TRUE(TryConversion(soa.Self(), from, to, &value)); 187 ASSERT_FALSE(soa.Self()->IsExceptionPending()); 188 JValue unboxed_value; 189 ASSERT_TRUE(UnboxPrimitiveForResult(value.GetL(), cl->FindPrimitiveClass('I'), &unboxed_value)); 190 ASSERT_EQ(kInitialValue, unboxed_value.GetI()); 191 } 192 193 TEST_F(MethodHandlesTest, UnsupportedReferenceCast) { 194 ScopedObjectAccess soa(Thread::Current()); 195 ClassLinker* cl = Runtime::Current()->GetClassLinker(); 196 StackHandleScope<3> hs(soa.Self()); 197 JValue value = JValue::FromPrimitive(3.733e2); 198 Handle<mirror::Object> boxed_value = 199 hs.NewHandle(BoxPrimitive(Primitive::kPrimDouble, value).Ptr()); 200 Handle<mirror::Class> from = hs.NewHandle(boxed_value->GetClass()); 201 Handle<mirror::Class> to = hs.NewHandle(cl->FindSystemClass(soa.Self(), "Ljava/lang/Integer;")); 202 value.SetL(boxed_value.Get()); 203 ASSERT_FALSE(soa.Self()->IsExceptionPending()); 204 ASSERT_FALSE(TryConversion(soa.Self(), from, to, &value)); 205 ASSERT_TRUE(soa.Self()->IsExceptionPending()); 206 ASSERT_TRUE(IsClassCastException(soa.Self()->GetException())); 207 soa.Self()->ClearException(); 208 } 209 210 // 211 // Primitive -> Reference Conversions 212 // 213 214 TEST_F(MethodHandlesTest, SupportedPrimitiveConversionPrimitiveToBoxed) { 215 ScopedObjectAccess soa(Thread::Current()); 216 ClassLinker* cl = Runtime::Current()->GetClassLinker(); 217 StackHandleScope<2> hs(soa.Self()); 218 const int32_t kInitialValue = 1; 219 JValue value = JValue::FromPrimitive(kInitialValue); 220 Handle<mirror::Class> from = hs.NewHandle(cl->FindPrimitiveClass('I')); 221 Handle<mirror::Class> to = hs.NewHandle(cl->FindSystemClass(soa.Self(), "Ljava/lang/Integer;")); 222 ASSERT_TRUE(TryConversion(soa.Self(), from, to, &value)); 223 ASSERT_FALSE(soa.Self()->IsExceptionPending()); 224 JValue unboxed_to_value; 225 ASSERT_TRUE(UnboxPrimitiveForResult(value.GetL(), from.Get(), &unboxed_to_value)); 226 ASSERT_EQ(kInitialValue, unboxed_to_value.GetI()); 227 } 228 229 TEST_F(MethodHandlesTest, SupportedPrimitiveConversionPrimitiveToBoxedSuper) { 230 ScopedObjectAccess soa(Thread::Current()); 231 ClassLinker* cl = Runtime::Current()->GetClassLinker(); 232 StackHandleScope<2> hs(soa.Self()); 233 const int32_t kInitialValue = 1; 234 JValue value = JValue::FromPrimitive(kInitialValue); 235 Handle<mirror::Class> from = hs.NewHandle(cl->FindPrimitiveClass('I')); 236 Handle<mirror::Class> to = hs.NewHandle(cl->FindSystemClass(soa.Self(), "Ljava/lang/Number;")); 237 ASSERT_TRUE(TryConversion(soa.Self(), from, to, &value)); 238 ASSERT_FALSE(soa.Self()->IsExceptionPending()); 239 JValue unboxed_to_value; 240 ASSERT_TRUE(UnboxPrimitiveForResult(value.GetL(), from.Get(), &unboxed_to_value)); 241 ASSERT_EQ(kInitialValue, unboxed_to_value.GetI()); 242 } 243 244 TEST_F(MethodHandlesTest, UnsupportedPrimitiveConversionNotBoxable) { 245 ScopedObjectAccess soa(Thread::Current()); 246 ClassLinker* cl = Runtime::Current()->GetClassLinker(); 247 StackHandleScope<2> hs(soa.Self()); 248 const int32_t kInitialValue = 1; 249 JValue value = JValue::FromPrimitive(kInitialValue); 250 Handle<mirror::Class> from = hs.NewHandle(cl->FindPrimitiveClass('I')); 251 Handle<mirror::Class> to = hs.NewHandle(cl->FindSystemClass(soa.Self(), "Ljava/lang/Runtime;")); 252 ASSERT_FALSE(TryConversion(soa.Self(), from, to, &value)); 253 ASSERT_TRUE(soa.Self()->IsExceptionPending()); 254 ASSERT_TRUE(IsWrongMethodTypeException(soa.Self()->GetException())); 255 soa.Self()->ClearException(); 256 } 257 258 TEST_F(MethodHandlesTest, UnsupportedPrimitiveConversionPrimitiveToBoxedWider) { 259 ScopedObjectAccess soa(Thread::Current()); 260 ClassLinker* cl = Runtime::Current()->GetClassLinker(); 261 StackHandleScope<2> hs(soa.Self()); 262 const int32_t kInitialValue = 1; 263 JValue value = JValue::FromPrimitive(kInitialValue); 264 Handle<mirror::Class> from = hs.NewHandle(cl->FindPrimitiveClass('I')); 265 Handle<mirror::Class> to = hs.NewHandle(cl->FindSystemClass(soa.Self(), "Ljava/lang/Long;")); 266 ASSERT_FALSE(TryConversion(soa.Self(), from, to, &value)); 267 ASSERT_TRUE(soa.Self()->IsExceptionPending()); 268 ASSERT_TRUE(IsWrongMethodTypeException(soa.Self()->GetException())); 269 soa.Self()->ClearException(); 270 } 271 272 TEST_F(MethodHandlesTest, UnsupportedPrimitiveConversionPrimitiveToBoxedNarrower) { 273 ScopedObjectAccess soa(Thread::Current()); 274 ClassLinker* cl = Runtime::Current()->GetClassLinker(); 275 StackHandleScope<2> hs(soa.Self()); 276 const int32_t kInitialValue = 1; 277 JValue value = JValue::FromPrimitive(kInitialValue); 278 Handle<mirror::Class> from = hs.NewHandle(cl->FindPrimitiveClass('I')); 279 Handle<mirror::Class> to = hs.NewHandle(cl->FindSystemClass(soa.Self(), "Ljava/lang/Byte;")); 280 ASSERT_FALSE(TryConversion(soa.Self(), from, to, &value)); 281 ASSERT_TRUE(soa.Self()->IsExceptionPending()); 282 ASSERT_TRUE(IsWrongMethodTypeException(soa.Self()->GetException())); 283 soa.Self()->ClearException(); 284 } 285 286 // 287 // Reference -> Primitive Conversions 288 // 289 290 TEST_F(MethodHandlesTest, SupportedBoxedToPrimitiveConversion) { 291 ScopedObjectAccess soa(Thread::Current()); 292 ClassLinker* cl = Runtime::Current()->GetClassLinker(); 293 StackHandleScope<3> hs(soa.Self()); 294 const int32_t kInitialValue = 101; 295 JValue value = JValue::FromPrimitive(kInitialValue); 296 Handle<mirror::Object> boxed_value = hs.NewHandle(BoxPrimitive(Primitive::kPrimInt, value).Ptr()); 297 Handle<mirror::Class> from = hs.NewHandle(cl->FindSystemClass(soa.Self(), "Ljava/lang/Integer;")); 298 Handle<mirror::Class> to = hs.NewHandle(cl->FindPrimitiveClass('I')); 299 value.SetL(boxed_value.Get()); 300 ASSERT_TRUE(TryConversion(soa.Self(), from, to, &value)); 301 ASSERT_FALSE(soa.Self()->IsExceptionPending()); 302 ASSERT_EQ(kInitialValue, value.GetI()); 303 } 304 305 TEST_F(MethodHandlesTest, SupportedBoxedToWiderPrimitiveConversion) { 306 ScopedObjectAccess soa(Thread::Current()); 307 ClassLinker* cl = Runtime::Current()->GetClassLinker(); 308 StackHandleScope<3> hs(soa.Self()); 309 static const int32_t kInitialValue = 101; 310 JValue value = JValue::FromPrimitive(kInitialValue); 311 Handle<mirror::Object> boxed_value = hs.NewHandle(BoxPrimitive(Primitive::kPrimInt, value).Ptr()); 312 Handle<mirror::Class> from = hs.NewHandle(cl->FindSystemClass(soa.Self(), "Ljava/lang/Integer;")); 313 Handle<mirror::Class> to = hs.NewHandle(cl->FindPrimitiveClass('J')); 314 value.SetL(boxed_value.Get()); 315 ASSERT_TRUE(TryConversion(soa.Self(), from, to, &value)); 316 ASSERT_EQ(kInitialValue, value.GetJ()); 317 } 318 319 TEST_F(MethodHandlesTest, UnsupportedNullBoxedToPrimitiveConversion) { 320 ScopedObjectAccess soa(Thread::Current()); 321 ClassLinker* cl = Runtime::Current()->GetClassLinker(); 322 StackHandleScope<3> hs(soa.Self()); 323 JValue value = JValue::FromPrimitive(101); 324 ScopedNullHandle<mirror::Object> boxed_value; 325 Handle<mirror::Class> from = hs.NewHandle(cl->FindSystemClass(soa.Self(), "Ljava/lang/Integer;")); 326 Handle<mirror::Class> to = hs.NewHandle(cl->FindPrimitiveClass('I')); 327 value.SetL(boxed_value.Get()); 328 ASSERT_FALSE(TryConversion(soa.Self(), from, to, &value)); 329 ASSERT_TRUE(soa.Self()->IsExceptionPending()); 330 ASSERT_TRUE(IsNullPointerException(soa.Self()->GetException())); 331 soa.Self()->ClearException(); 332 } 333 334 TEST_F(MethodHandlesTest, UnsupportedNotBoxReferenceToPrimitiveConversion) { 335 ScopedObjectAccess soa(Thread::Current()); 336 ClassLinker* cl = Runtime::Current()->GetClassLinker(); 337 StackHandleScope<2> hs(soa.Self()); 338 Handle<mirror::Class> from = hs.NewHandle(cl->FindSystemClass(soa.Self(), "Ljava/lang/Class;")); 339 Handle<mirror::Class> to = hs.NewHandle(cl->FindPrimitiveClass('I')); 340 // Set value to be converted as some non-primitive type. 341 JValue value; 342 value.SetL(cl->FindPrimitiveClass('V')); 343 ASSERT_FALSE(TryConversion(soa.Self(), from, to, &value)); 344 ASSERT_TRUE(soa.Self()->IsExceptionPending()); 345 ASSERT_TRUE(IsWrongMethodTypeException(soa.Self()->GetException())); 346 soa.Self()->ClearException(); 347 } 348 349 TEST_F(MethodHandlesTest, UnsupportedBoxedToNarrowerPrimitiveConversionNoCast) { 350 ScopedObjectAccess soa(Thread::Current()); 351 ClassLinker* cl = Runtime::Current()->GetClassLinker(); 352 StackHandleScope<3> hs(soa.Self()); 353 static const int32_t kInitialValue = 101; 354 JValue value = JValue::FromPrimitive(kInitialValue); 355 Handle<mirror::Object> boxed_value = hs.NewHandle(BoxPrimitive(Primitive::kPrimInt, value).Ptr()); 356 Handle<mirror::Class> from = hs.NewHandle(cl->FindSystemClass(soa.Self(), "Ljava/lang/Integer;")); 357 Handle<mirror::Class> to = hs.NewHandle(cl->FindPrimitiveClass('S')); 358 value.SetL(boxed_value.Get()); 359 ASSERT_FALSE(TryConversion(soa.Self(), from, to, &value)); 360 ASSERT_TRUE(soa.Self()->IsExceptionPending()); 361 ASSERT_TRUE(IsWrongMethodTypeException(soa.Self()->GetException())); 362 soa.Self()->ClearException(); 363 } 364 365 TEST_F(MethodHandlesTest, UnsupportedBoxedToNarrowerPrimitiveConversionWithCast) { 366 ScopedObjectAccess soa(Thread::Current()); 367 ClassLinker* cl = Runtime::Current()->GetClassLinker(); 368 StackHandleScope<3> hs(soa.Self()); 369 static const double kInitialValue = 1e77; 370 JValue value = JValue::FromPrimitive(kInitialValue); 371 Handle<mirror::Object> boxed_value = 372 hs.NewHandle(BoxPrimitive(Primitive::kPrimDouble, value).Ptr()); 373 Handle<mirror::Class> from = hs.NewHandle(cl->FindSystemClass(soa.Self(), "Ljava/lang/Number;")); 374 Handle<mirror::Class> to = hs.NewHandle(cl->FindPrimitiveClass('F')); 375 value.SetL(boxed_value.Get()); 376 ASSERT_FALSE(TryConversion(soa.Self(), from, to, &value)); 377 ASSERT_TRUE(soa.Self()->IsExceptionPending()); 378 ASSERT_TRUE(IsClassCastException(soa.Self()->GetException())); 379 soa.Self()->ClearException(); 380 } 381 382 } // namespace art 383