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