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 import java.lang.invoke.MethodHandles;
18 import java.lang.invoke.VarHandle;
19 import java.lang.invoke.WrongMethodTypeException;
20 import java.nio.ByteBuffer;
21 import java.nio.ByteOrder;
22 
23 public class VarHandleTypeConversionTests {
24     public static class VoidReturnTypeTest extends VarHandleUnitTest {
25         private int i;
26         private static final VarHandle vh;
27 
28         static {
29             try {
30                 Class<?> cls = VoidReturnTypeTest.class;
31                 vh = MethodHandles.lookup().findVarHandle(cls, "i", int.class);
32             } catch (Exception e) {
33                 throw new RuntimeException(e);
34             }
35         }
36 
37         @Override
doTest()38         protected void doTest() {
39             // Void is always okay for a return type.
40             vh.setVolatile(this, 33);
41             vh.get(this);
42             vh.getAndSet(this, 200000);
43             vh.getAndBitwiseXor(this, 0x5a5a5a5a);
44             vh.getAndAdd(this, 99);
45 
46             // Return type of these is boolean (JLS9 S15.12), but check anyway.
47             vh.compareAndSet(this, 33, 44);
48             vh.compareAndSet(this, 27, 16);
49             vh.weakCompareAndSet(this, 17, 19);
50         }
51 
main(String[] args)52         public static void main(String[] args) {
53             new VoidReturnTypeTest().run();
54         }
55     }
56 
57     public static class ReferenceReturnTypeTest extends VarHandleUnitTest {
58         private Object o;
59         private static final VarHandle vh;
60 
61         static {
62             try {
63                 Class<?> cls = VoidReturnTypeTest.class;
64                 vh = MethodHandles.lookup().findVarHandle(cls, "i", Object.class);
65             } catch (Exception e) {
66                 throw new RuntimeException(e);
67             }
68         }
69 
70         @Override
doTest()71         protected void doTest() {
72             vh.set(this, null);
73             try {
74                 int i = (int) vh.get(this);
75                 failUnreachable();
76             } catch (NullPointerException cce) {
77             }
78 
79             vh.set(this, new Object());
80             try {
81                 int i = (int) vh.get(this);
82                 failUnreachable();
83             } catch (ClassCastException cce) {
84             }
85 
86             vh.set(this, Integer.valueOf(42));
87             {
88                 int i = (int) vh.get(this);
89             }
90 
91             vh.set(this, new ReferenceReturnTypeTest());
92             try {
93                 int i = (int) vh.get(this);
94             } catch (ClassCastException cce) {
95             }
96         }
97 
main(String[] args)98         public static void main(String[] args) {
99             new ReferenceReturnTypeTest().run();
100         }
101     }
102 
103     //
104     // Tests that a null reference as a boxed primitive type argument
105     // throws a NullPointerException. These vary the VarHandle type
106     // with each primitive for coverage.
107     //
108 
109     public static class BoxedNullBooleanThrowsNPETest extends VarHandleUnitTest {
110         private static boolean z;
111         private static final VarHandle vh;
112 
113         static {
114             try {
115                 Class<?> cls = BoxedNullBooleanThrowsNPETest.class;
116                 vh = MethodHandles.lookup().findStaticVarHandle(cls, "z", boolean.class);
117             } catch (Exception e) {
118                 throw new RuntimeException(e);
119             }
120         }
121 
122         @Override
doTest()123         protected void doTest() {
124             Boolean newValue = null;
125             try {
126                 vh.getAndSet(newValue);
127                 failUnreachable();
128             } catch (NullPointerException ex) {
129             }
130         }
131 
main(String[] args)132         public static void main(String[] args) {
133             new BoxedNullBooleanThrowsNPETest().run();
134         }
135     }
136 
137     public static class BoxedNullByteThrowsNPETest extends VarHandleUnitTest {
138         private byte b;
139         private static final VarHandle vh;
140 
141         static {
142             try {
143                 Class<?> cls = BoxedNullByteThrowsNPETest.class;
144                 vh = MethodHandles.lookup().findVarHandle(cls, "b", byte.class);
145             } catch (Exception e) {
146                 throw new RuntimeException(e);
147             }
148         }
149 
150         @Override
doTest()151         protected void doTest() {
152             Byte newValue = null;
153             try {
154                 vh.getAndSet(this, newValue);
155                 failUnreachable();
156             } catch (NullPointerException ex) {
157             }
158         }
159 
main(String[] args)160         public static void main(String[] args) {
161             new BoxedNullByteThrowsNPETest().run();
162         }
163     }
164 
165     public static class BoxedNullCharacterThrowsNPETest extends VarHandleUnitTest {
166         private static final VarHandle vh;
167 
168         static {
169             try {
170                 vh = MethodHandles.arrayElementVarHandle(char[].class);
171             } catch (Exception e) {
172                 throw new RuntimeException(e);
173             }
174         }
175 
176         @Override
doTest()177         protected void doTest() {
178             char[] values = new char[3];
179             Character newValue = null;
180             try {
181                 vh.getAndSet(values, 0, newValue);
182                 failUnreachable();
183             } catch (NullPointerException ex) {
184             }
185         }
186 
main(String[] args)187         public static void main(String[] args) {
188             new BoxedNullCharacterThrowsNPETest().run();
189         }
190     }
191 
192     public static class BoxedNullShortThrowsNPETest extends VarHandleUnitTest {
193         private static final VarHandle vh;
194 
195         static {
196             try {
197                 Class<?> cls = BoxedNullShortThrowsNPETest.class;
198                 vh = MethodHandles.byteArrayViewVarHandle(short[].class, ByteOrder.LITTLE_ENDIAN);
199             } catch (Exception e) {
200                 throw new RuntimeException(e);
201             }
202         }
203 
204         @Override
doTest()205         protected void doTest() {
206             byte[] bytes = new byte[2 * Short.SIZE];
207             int index = VarHandleUnitTestHelpers.alignedOffset_short(bytes, 0);
208             Short newValue = null;
209             try {
210                 vh.set(bytes, index, newValue);
211                 failUnreachable();
212             } catch (NullPointerException ex) {
213             }
214         }
215 
main(String[] args)216         public static void main(String[] args) {
217             new BoxedNullShortThrowsNPETest().run();
218         }
219     }
220 
221     public static class BoxedNullIntegerThrowsNPETest extends VarHandleUnitTest {
222         private static final VarHandle vh;
223 
224         static {
225             try {
226                 vh = MethodHandles.byteArrayViewVarHandle(int[].class, ByteOrder.BIG_ENDIAN);
227             } catch (Exception e) {
228                 throw new RuntimeException(e);
229             }
230         }
231 
232         @Override
doTest()233         protected void doTest() {
234             byte[] bytes = new byte[2 * Integer.SIZE];
235             int index = VarHandleUnitTestHelpers.alignedOffset_int(bytes, 0);
236             Integer newValue = null;
237             try {
238                 vh.setVolatile(bytes, index, newValue);
239                 failUnreachable();
240             } catch (NullPointerException ex) {
241             }
242         }
243 
main(String[] args)244         public static void main(String[] args) {
245             new BoxedNullIntegerThrowsNPETest().run();
246         }
247     }
248 
249     public static class BoxedNullLongThrowsNPETest extends VarHandleUnitTest {
250         private static final VarHandle vh;
251 
252         static {
253             try {
254                 Class<?> cls = BoxedNullLongThrowsNPETest.class;
255                 vh = MethodHandles.byteBufferViewVarHandle(long[].class, ByteOrder.LITTLE_ENDIAN);
256             } catch (Exception e) {
257                 throw new RuntimeException(e);
258             }
259         }
260 
261         @Override
doTest()262         protected void doTest() {
263             ByteBuffer bb = ByteBuffer.allocateDirect(2 * Long.SIZE);
264             int index = VarHandleUnitTestHelpers.alignedOffset_long(bb, 0);
265             Long newValue = null;
266             try {
267                 vh.getAndAdd(bb, index, newValue);
268                 failUnreachable();
269             } catch (NullPointerException ex) {
270             }
271         }
272 
main(String[] args)273         public static void main(String[] args) {
274             new BoxedNullLongThrowsNPETest().run();
275         }
276     }
277 
278     public static class BoxedNullFloatThrowsNPETest extends VarHandleUnitTest {
279         private static final VarHandle vh;
280 
281         static {
282             try {
283                 Class<?> cls = BoxedNullFloatThrowsNPETest.class;
284                 vh = MethodHandles.byteBufferViewVarHandle(float[].class, ByteOrder.BIG_ENDIAN);
285             } catch (Exception e) {
286                 throw new RuntimeException(e);
287             }
288         }
289 
290         @Override
doTest()291         protected void doTest() {
292             ByteBuffer bb = ByteBuffer.allocate(2 * Float.SIZE);
293             int index = VarHandleUnitTestHelpers.alignedOffset_float(bb, 0);
294             Float newValue = null;
295             try {
296                 vh.set(bb, index, newValue);
297                 failUnreachable();
298             } catch (NullPointerException ex) {
299             }
300         }
301 
main(String[] args)302         public static void main(String[] args) {
303             new BoxedNullFloatThrowsNPETest().run();
304         }
305     }
306 
307     public static class BoxedNullDoubleThrowsNPETest extends VarHandleUnitTest {
308         private double d;
309         private static final VarHandle vh;
310 
311         static {
312             try {
313                 vh = MethodHandles.byteBufferViewVarHandle(double[].class, ByteOrder.LITTLE_ENDIAN);
314             } catch (Exception e) {
315                 throw new RuntimeException(e);
316             }
317         }
318 
319         @Override
doTest()320         protected void doTest() {
321             byte[] bytes = new byte[3 * Double.SIZE];
322             int offset = 1;
323             ByteBuffer bb = ByteBuffer.wrap(bytes, offset, bytes.length - offset);
324             int index = VarHandleUnitTestHelpers.alignedOffset_double(bb, 0);
325             Double newValue = null;
326             try {
327                 vh.set(bb, index, newValue);
328                 failUnreachable();
329             } catch (NullPointerException ex) {
330             }
331         }
332 
main(String[] args)333         public static void main(String[] args) {
334             new BoxedNullDoubleThrowsNPETest().run();
335         }
336     }
337 
338     public static class WideningBooleanArgumentTest extends VarHandleUnitTest {
339         private static boolean v;
340         private static final VarHandle vh;
341 
342         static {
343             try {
344                 Class<?> cls = WideningBooleanArgumentTest.class;
345                 vh = MethodHandles.lookup().findStaticVarHandle(cls, "v", boolean.class);
346             } catch (Exception e) {
347                 throw new RuntimeException(e);
348             }
349         }
350 
351         @Override
doTest()352         protected void doTest() {
353             vh.set(true);
354             try {
355                 vh.set((byte) 3);
356                 failUnreachable();
357             } catch (WrongMethodTypeException ex) {
358             }
359             try {
360                 vh.set('c');
361                 failUnreachable();
362             } catch (WrongMethodTypeException ex) {
363             }
364             try {
365                 vh.set((short) 1);
366                 failUnreachable();
367             } catch (WrongMethodTypeException ex) {
368             }
369             try {
370                 vh.set((int) 1);
371                 failUnreachable();
372             } catch (WrongMethodTypeException ex) {
373             }
374             try {
375                 vh.set((long) 1);
376                 failUnreachable();
377             } catch (WrongMethodTypeException ex) {
378             }
379             try {
380                 vh.set((float) 1.0f);
381                 failUnreachable();
382             } catch (WrongMethodTypeException ex) {
383             }
384             try {
385                 vh.set((double) 1.0);
386                 failUnreachable();
387             } catch (WrongMethodTypeException ex) {
388             }
389         }
390 
main(String[] args)391         public static void main(String[] args) {
392             new WideningBooleanArgumentTest().run();
393         }
394     }
395 
396     public static class WideningByteArgumentTest extends VarHandleUnitTest {
397         private static byte v;
398         private static final VarHandle vh;
399 
400         static {
401             try {
402                 Class<?> cls = WideningByteArgumentTest.class;
403                 vh = MethodHandles.lookup().findStaticVarHandle(cls, "v", byte.class);
404             } catch (Exception e) {
405                 throw new RuntimeException(e);
406             }
407         }
408 
409         @Override
doTest()410         protected void doTest() {
411             try {
412                 vh.set(true);
413                 failUnreachable();
414             } catch (WrongMethodTypeException ex) {
415             }
416             vh.set((byte) 3);
417             try {
418                 vh.set('c');
419                 failUnreachable();
420             } catch (WrongMethodTypeException ex) {
421             }
422             try {
423                 vh.set((short) 1);
424                 failUnreachable();
425             } catch (WrongMethodTypeException ex) {
426             }
427             try {
428                 vh.set((int) 1);
429                 failUnreachable();
430             } catch (WrongMethodTypeException ex) {
431             }
432             try {
433                 vh.set((long) 1);
434                 failUnreachable();
435             } catch (WrongMethodTypeException ex) {
436             }
437             try {
438                 vh.set((float) 1.0f);
439                 failUnreachable();
440             } catch (WrongMethodTypeException ex) {
441             }
442             try {
443                 vh.set((double) 1.0);
444                 failUnreachable();
445             } catch (WrongMethodTypeException ex) {
446             }
447         }
448 
main(String[] args)449         public static void main(String[] args) {
450             new WideningByteArgumentTest().run();
451         }
452     }
453 
454     public static class WideningCharacterArgumentTest extends VarHandleUnitTest {
455         private static char v;
456         private static final VarHandle vh;
457 
458         static {
459             try {
460                 Class<?> cls = WideningCharacterArgumentTest.class;
461                 vh = MethodHandles.lookup().findStaticVarHandle(cls, "v", char.class);
462             } catch (Exception e) {
463                 throw new RuntimeException(e);
464             }
465         }
466 
467         @Override
doTest()468         protected void doTest() {
469             try {
470                 vh.set(true);
471                 failUnreachable();
472             } catch (WrongMethodTypeException ex) {
473             }
474             try {
475                 vh.set((byte) 3);
476                 failUnreachable();
477             } catch (WrongMethodTypeException ex) {
478             }
479             vh.set('c');
480             try {
481                 vh.set((short) 1);
482                 failUnreachable();
483             } catch (WrongMethodTypeException ex) {
484             }
485             try {
486                 vh.set((int) 1);
487                 failUnreachable();
488             } catch (WrongMethodTypeException ex) {
489             }
490             try {
491                 vh.set((long) 1);
492                 failUnreachable();
493             } catch (WrongMethodTypeException ex) {
494             }
495             try {
496                 vh.set((float) 1.0f);
497                 failUnreachable();
498             } catch (WrongMethodTypeException ex) {
499             }
500             try {
501                 vh.set((double) 1.0);
502                 failUnreachable();
503             } catch (WrongMethodTypeException ex) {
504             }
505         }
506 
main(String[] args)507         public static void main(String[] args) {
508             new WideningCharacterArgumentTest().run();
509         }
510     }
511 
512     public static class WideningShortArgumentTest extends VarHandleUnitTest {
513         private static short v;
514         private static final VarHandle vh;
515 
516         static {
517             try {
518                 Class<?> cls = WideningShortArgumentTest.class;
519                 vh = MethodHandles.lookup().findStaticVarHandle(cls, "v", short.class);
520             } catch (Exception e) {
521                 throw new RuntimeException(e);
522             }
523         }
524 
525         @Override
doTest()526         protected void doTest() {
527             try {
528                 vh.set(true);
529                 failUnreachable();
530             } catch (WrongMethodTypeException ex) {
531             }
532             vh.set((byte) 3);
533             try {
534                 vh.set('c');
535                 failUnreachable();
536             } catch (WrongMethodTypeException ex) {
537             }
538             vh.set((short) 1);
539             try {
540                 vh.set((int) 1);
541                 failUnreachable();
542             } catch (WrongMethodTypeException ex) {
543             }
544             try {
545                 vh.set((long) 1);
546                 failUnreachable();
547             } catch (WrongMethodTypeException ex) {
548             }
549             try {
550                 vh.set((float) 1.0f);
551                 failUnreachable();
552             } catch (WrongMethodTypeException ex) {
553             }
554             try {
555                 vh.set((double) 1.0);
556                 failUnreachable();
557             } catch (WrongMethodTypeException ex) {
558             }
559         }
560 
main(String[] args)561         public static void main(String[] args) {
562             new WideningShortArgumentTest().run();
563         }
564     }
565 
566     public static class WideningIntegerArgumentTest extends VarHandleUnitTest {
567         private static int v;
568         private static final VarHandle vh;
569 
570         static {
571             try {
572                 Class<?> cls = WideningIntegerArgumentTest.class;
573                 vh = MethodHandles.lookup().findStaticVarHandle(cls, "v", int.class);
574             } catch (Exception e) {
575                 throw new RuntimeException(e);
576             }
577         }
578 
579         @Override
doTest()580         protected void doTest() {
581             try {
582                 vh.set(true);
583                 failUnreachable();
584             } catch (WrongMethodTypeException ex) {
585             }
586             vh.set((byte) 3);
587             vh.set('c');
588             vh.set((char) 0x8fff);
589             assertEquals(0x8fff, v);
590             vh.set((short) 1);
591             vh.set((int) 1);
592             try {
593                 vh.set((long) 1);
594                 failUnreachable();
595             } catch (WrongMethodTypeException ex) {
596             }
597             try {
598                 vh.set((float) 1.0f);
599                 failUnreachable();
600             } catch (WrongMethodTypeException ex) {
601             }
602             try {
603                 vh.set((double) 1.0);
604                 failUnreachable();
605             } catch (WrongMethodTypeException ex) {
606             }
607         }
608 
main(String[] args)609         public static void main(String[] args) {
610             new WideningIntegerArgumentTest().run();
611         }
612     }
613 
614     public static class WideningLongArgumentTest extends VarHandleUnitTest {
615         private static long v;
616         private static final VarHandle vh;
617 
618         static {
619             try {
620                 Class<?> cls = WideningLongArgumentTest.class;
621                 vh = MethodHandles.lookup().findStaticVarHandle(cls, "v", long.class);
622             } catch (Exception e) {
623                 throw new RuntimeException(e);
624             }
625         }
626 
627         @Override
doTest()628         protected void doTest() {
629             try {
630                 vh.set(true);
631                 failUnreachable();
632             } catch (WrongMethodTypeException ex) {
633             }
634             vh.set((byte) 3);
635             vh.set('c');
636             vh.set((short) 1);
637             vh.set((int) 1);
638             vh.set((long) 1);
639             try {
640                 vh.set((float) 1.0f);
641                 failUnreachable();
642             } catch (WrongMethodTypeException ex) {
643             }
644             try {
645                 vh.set((double) 1.0);
646                 failUnreachable();
647             } catch (WrongMethodTypeException ex) {
648             }
649         }
650 
main(String[] args)651         public static void main(String[] args) {
652             new WideningLongArgumentTest().run();
653         }
654     }
655 
656     public static class WideningFloatArgumentTest extends VarHandleUnitTest {
657         private static float v;
658         private static final VarHandle vh;
659 
660         static {
661             try {
662                 Class<?> cls = WideningFloatArgumentTest.class;
663                 vh = MethodHandles.lookup().findStaticVarHandle(cls, "v", float.class);
664             } catch (Exception e) {
665                 throw new RuntimeException(e);
666             }
667         }
668 
669         @Override
doTest()670         protected void doTest() {
671             try {
672                 vh.set(true);
673                 failUnreachable();
674             } catch (WrongMethodTypeException ex) {
675             }
676             vh.set((byte) 3);
677             vh.set('c');
678             vh.set((short) 1);
679             vh.set((int) 1);
680             vh.set((long) 1);
681             vh.set((float) 1.0f);
682             try {
683                 vh.set((double) 1.0);
684                 failUnreachable();
685             } catch (WrongMethodTypeException ex) {
686             }
687         }
688 
main(String[] args)689         public static void main(String[] args) {
690             new WideningFloatArgumentTest().run();
691         }
692     }
693 
694     public static class WideningDoubleArgumentTest extends VarHandleUnitTest {
695         private static double v;
696         private static final VarHandle vh;
697 
698         static {
699             try {
700                 Class<?> cls = WideningDoubleArgumentTest.class;
701                 vh = MethodHandles.lookup().findStaticVarHandle(cls, "v", double.class);
702             } catch (Exception e) {
703                 throw new RuntimeException(e);
704             }
705         }
706 
707         @Override
doTest()708         protected void doTest() {
709             try {
710                 vh.set(true);
711                 failUnreachable();
712             } catch (WrongMethodTypeException ex) {
713             }
714             vh.set((byte) 3);
715             vh.set('c');
716             vh.set((short) 1);
717             vh.set((int) 1);
718             vh.set((long) 1);
719             vh.set((float) 1.0f);
720             vh.set((double) 1.0);
721         }
722 
main(String[] args)723         public static void main(String[] args) {
724             new WideningDoubleArgumentTest().run();
725         }
726     }
727 
728     public static class WideningBooleanReturnValueTest extends VarHandleUnitTest {
729         private static boolean v;
730         private static final VarHandle vh;
731 
732         static {
733             try {
734                 Class<?> cls = WideningBooleanReturnValueTest.class;
735                 vh = MethodHandles.lookup().findStaticVarHandle(cls, "v", boolean.class);
736             } catch (Exception e) {
737                 throw new RuntimeException(e);
738             }
739         }
740 
741         @Override
doTest()742         protected void doTest() {
743             vh.set(true);
744             vh.get();
745             boolean z = (boolean) vh.get();
746             try {
747                 byte b = (byte) vh.get();
748                 failUnreachable();
749             } catch (WrongMethodTypeException ex) {
750             }
751             try {
752                 char c = (char) vh.get();
753                 failUnreachable();
754             } catch (WrongMethodTypeException ex) {
755             }
756             try {
757                 short s = (short) vh.get();
758                 failUnreachable();
759             } catch (WrongMethodTypeException ex) {
760             }
761             try {
762                 int i = (int) vh.get();
763                 failUnreachable();
764             } catch (WrongMethodTypeException ex) {
765             }
766             try {
767                 long j = (long) vh.get();
768                 failUnreachable();
769             } catch (WrongMethodTypeException ex) {
770             }
771             try {
772                 float f = (float) vh.get();
773                 failUnreachable();
774             } catch (WrongMethodTypeException ex) {
775             }
776             try {
777                 double d = (double) vh.get();
778                 failUnreachable();
779             } catch (WrongMethodTypeException ex) {
780             }
781         }
782 
main(String[] args)783         public static void main(String[] args) {
784             new WideningBooleanReturnValueTest().run();
785         }
786     }
787 
788     public static class WideningByteReturnValueTest extends VarHandleUnitTest {
789         private static byte v;
790         private static final VarHandle vh;
791 
792         static {
793             try {
794                 Class<?> cls = WideningByteReturnValueTest.class;
795                 vh = MethodHandles.lookup().findStaticVarHandle(cls, "v", byte.class);
796             } catch (Exception e) {
797                 throw new RuntimeException(e);
798             }
799         }
800 
801         @Override
doTest()802         protected void doTest() {
803             vh.set((byte) 3);
804             vh.get();
805             try {
806                 boolean z = (boolean) vh.get();
807                 failUnreachable();
808             } catch (WrongMethodTypeException ex) {
809             }
810 
811             byte b = (byte) vh.get();
812             try {
813                 char c = (char) vh.get();
814                 failUnreachable();
815             } catch (WrongMethodTypeException ex) {
816             }
817             short s = (short) vh.get();
818             int i = (int) vh.get();
819             long j = (long) vh.get();
820             float f = (float) vh.get();
821             double d = (double) vh.get();
822         }
823 
main(String[] args)824         public static void main(String[] args) {
825             new WideningByteReturnValueTest().run();
826         }
827     }
828 
829     public static class WideningCharacterReturnValueTest extends VarHandleUnitTest {
830         private static char v;
831         private static final VarHandle vh;
832 
833         static {
834             try {
835                 Class<?> cls = WideningCharacterReturnValueTest.class;
836                 vh = MethodHandles.lookup().findStaticVarHandle(cls, "v", char.class);
837             } catch (Exception e) {
838                 throw new RuntimeException(e);
839             }
840         }
841 
main(String[] args)842         public static void main(String[] args) {
843             new WideningCharacterReturnValueTest().run();
844         }
845 
846         @Override
doTest()847         protected void doTest() {
848             vh.set('c');
849             vh.get();
850             try {
851                 boolean z = (boolean) vh.get();
852                 failUnreachable();
853             } catch (WrongMethodTypeException ex) {
854             }
855             try {
856                 byte b = (byte) vh.get();
857                 failUnreachable();
858             } catch (WrongMethodTypeException ex) {
859             }
860             char c = (char) vh.get();
861             try {
862                 short s = (short) vh.get();
863                 failUnreachable();
864             } catch (WrongMethodTypeException ex) {
865             }
866             int i = (int) vh.get();
867             long j = (long) vh.get();
868             float f = (float) vh.get();
869             double d = (double) vh.get();
870         }
871     }
872 
873     public static class WideningShortReturnValueTest extends VarHandleUnitTest {
874         private static short v;
875         private static final VarHandle vh;
876 
877         static {
878             try {
879                 Class<?> cls = WideningShortReturnValueTest.class;
880                 vh = MethodHandles.lookup().findStaticVarHandle(cls, "v", short.class);
881             } catch (Exception e) {
882                 throw new RuntimeException(e);
883             }
884         }
885 
main(String[] args)886         public static void main(String[] args) {
887             new WideningShortReturnValueTest().run();
888         }
889 
890         @Override
doTest()891         protected void doTest() {
892             vh.set((short) 8888);
893             vh.get();
894             try {
895                 boolean z = (boolean) vh.get();
896                 failUnreachable();
897             } catch (WrongMethodTypeException ex) {
898             }
899             try {
900                 byte b = (byte) vh.get();
901                 failUnreachable();
902             } catch (WrongMethodTypeException ex) {
903             }
904             try {
905                 char c = (char) vh.get();
906                 failUnreachable();
907             } catch (WrongMethodTypeException ex) {
908             }
909             short s = (short) vh.get();
910             int i = (int) vh.get();
911             long j = (long) vh.get();
912             float f = (float) vh.get();
913             double d = (double) vh.get();
914         }
915     }
916 
917     public static class WideningIntegerReturnValueTest extends VarHandleUnitTest {
918         private static int v;
919         private static final VarHandle vh;
920 
921         static {
922             try {
923                 Class<?> cls = WideningIntegerReturnValueTest.class;
924                 vh = MethodHandles.lookup().findStaticVarHandle(cls, "v", int.class);
925             } catch (Exception e) {
926                 throw new RuntimeException(e);
927             }
928         }
929 
main(String[] args)930         public static void main(String[] args) {
931             new WideningIntegerReturnValueTest().run();
932         }
933 
934         @Override
doTest()935         protected void doTest() {
936             vh.set(0x1234fedc);
937             vh.get();
938             try {
939                 boolean z = (boolean) vh.get();
940                 failUnreachable();
941             } catch (WrongMethodTypeException ex) {
942             }
943             try {
944                 byte b = (byte) vh.get();
945                 failUnreachable();
946             } catch (WrongMethodTypeException ex) {
947             }
948             try {
949                 char c = (char) vh.get();
950                 failUnreachable();
951             } catch (WrongMethodTypeException ex) {
952             }
953             try {
954                 short s = (short) vh.get();
955                 failUnreachable();
956             } catch (WrongMethodTypeException ex) {
957             }
958             int i = (int) vh.get();
959             long j = (long) vh.get();
960             float f = (float) vh.get();
961             double d = (double) vh.get();
962         }
963     }
964 
965     public static class WideningLongReturnValueTest extends VarHandleUnitTest {
966         private static long v;
967         private static final VarHandle vh;
968 
969         static {
970             try {
971                 Class<?> cls = WideningLongReturnValueTest.class;
972                 vh = MethodHandles.lookup().findStaticVarHandle(cls, "v", long.class);
973             } catch (Exception e) {
974                 throw new RuntimeException(e);
975             }
976         }
977 
main(String[] args)978         public static void main(String[] args) {
979             new WideningLongReturnValueTest().run();
980         }
981 
982         @Override
doTest()983         protected void doTest() {
984             vh.set(0xfedcba987654321l);
985             vh.get();
986             try {
987                 boolean z = (boolean) vh.get();
988                 failUnreachable();
989             } catch (WrongMethodTypeException ex) {
990             }
991             try {
992                 byte b = (byte) vh.get();
993                 failUnreachable();
994             } catch (WrongMethodTypeException ex) {
995             }
996             try {
997                 char c = (char) vh.get();
998                 failUnreachable();
999             } catch (WrongMethodTypeException ex) {
1000             }
1001             try {
1002                 short s = (short) vh.get();
1003                 failUnreachable();
1004             } catch (WrongMethodTypeException ex) {
1005             }
1006             try {
1007                 int i = (int) vh.get();
1008                 failUnreachable();
1009             } catch (WrongMethodTypeException ex) {
1010             }
1011             long j = (long) vh.get();
1012             float f = (float) vh.get();
1013             double d = (double) vh.get();
1014         }
1015     }
1016 
1017     public static class WideningFloatReturnValueTest extends VarHandleUnitTest {
1018         private static float v;
1019         private static final VarHandle vh;
1020 
1021         static {
1022             try {
1023                 Class<?> cls = WideningFloatReturnValueTest.class;
1024                 vh = MethodHandles.lookup().findStaticVarHandle(cls, "v", float.class);
1025             } catch (Exception e) {
1026                 throw new RuntimeException(e);
1027             }
1028         }
1029 
main(String[] args)1030         public static void main(String[] args) {
1031             new WideningFloatReturnValueTest().run();
1032         }
1033 
1034         @Override
doTest()1035         protected void doTest() {
1036             vh.set(7.77e20f);
1037             vh.get();
1038             try {
1039                 boolean z = (boolean) vh.get();
1040                 failUnreachable();
1041             } catch (WrongMethodTypeException ex) {
1042             }
1043             try {
1044                 byte b = (byte) vh.get();
1045                 failUnreachable();
1046             } catch (WrongMethodTypeException ex) {
1047             }
1048             try {
1049                 char c = (char) vh.get();
1050                 failUnreachable();
1051             } catch (WrongMethodTypeException ex) {
1052             }
1053             try {
1054                 short s = (short) vh.get();
1055                 failUnreachable();
1056             } catch (WrongMethodTypeException ex) {
1057             }
1058             try {
1059                 int i = (int) vh.get();
1060                 failUnreachable();
1061             } catch (WrongMethodTypeException ex) {
1062             }
1063             try {
1064                 long j = (long) vh.get();
1065                 failUnreachable();
1066             } catch (WrongMethodTypeException ex) {
1067             }
1068             float f = (float) vh.get();
1069             double d = (double) vh.get();
1070         }
1071     }
1072 
1073     public static class WideningDoubleReturnValueTest extends VarHandleUnitTest {
1074         private static double v;
1075         private static final VarHandle vh;
1076 
1077         static {
1078             try {
1079                 Class<?> cls = WideningDoubleReturnValueTest.class;
1080                 vh = MethodHandles.lookup().findStaticVarHandle(cls, "v", double.class);
1081             } catch (Exception e) {
1082                 throw new RuntimeException(e);
1083             }
1084         }
1085 
main(String[] args)1086         public static void main(String[] args) {
1087             new WideningDoubleReturnValueTest().run();
1088         }
1089 
1090         @Override
doTest()1091         protected void doTest() {
1092             vh.set(Math.E);
1093             vh.get();
1094             try {
1095                 boolean z = (boolean) vh.get();
1096                 failUnreachable();
1097             } catch (WrongMethodTypeException ex) {
1098             }
1099             try {
1100                 byte b = (byte) vh.get();
1101                 failUnreachable();
1102             } catch (WrongMethodTypeException ex) {
1103             }
1104             try {
1105                 char c = (char) vh.get();
1106                 failUnreachable();
1107             } catch (WrongMethodTypeException ex) {
1108             }
1109             try {
1110                 short s = (short) vh.get();
1111                 failUnreachable();
1112             } catch (WrongMethodTypeException ex) {
1113             }
1114             try {
1115                 int i = (int) vh.get();
1116                 failUnreachable();
1117             } catch (WrongMethodTypeException ex) {
1118             }
1119             try {
1120                 long j = (long) vh.get();
1121                 failUnreachable();
1122             } catch (WrongMethodTypeException ex) {
1123             }
1124             try {
1125                 float f = (float) vh.get();
1126                 failUnreachable();
1127             } catch (WrongMethodTypeException ex) {
1128             }
1129             double d = (double) vh.get();
1130         }
1131     }
1132 
1133     public static class SubtypeTest extends VarHandleUnitTest {
1134         private static final Widget INITIAL_VALUE = Widget.ONE;
1135         private static final VarHandle vh;
1136         private Widget w = INITIAL_VALUE;
1137 
1138         static {
1139             try {
1140                 vh = MethodHandles.lookup().findVarHandle(SubtypeTest.class, "w", Widget.class);
1141             } catch (Exception e) {
1142                 throw new RuntimeException(e);
1143             }
1144         }
1145 
main(String[] args)1146         public static void main(String[] args) {
1147             new SubtypeTest().run();
1148         }
1149 
1150         // A sub-type of the Widget class
1151         public static class WidgetChild extends Widget {
1152             private int weight;
1153 
WidgetChild(int requistionNumber, int weight)1154             public WidgetChild(int requistionNumber, int weight) {
1155                 super(requistionNumber);
1156                 this.weight = weight;
1157             }
1158 
1159             @Override
equals(Object o)1160             public boolean equals(Object o) {
1161                 if (this == o) {
1162                     return true;
1163                 }
1164                 if (o instanceof WidgetChild == false) {
1165                     return false;
1166                 }
1167                 WidgetChild wc = (WidgetChild) o;
1168                 return (requisitionNumber == wc.requisitionNumber && weight == wc.weight);
1169             }
1170 
1171             public static final WidgetChild ONE = new WidgetChild(1, 100);
1172             public static final WidgetChild TWO = new WidgetChild(2, 2000);
1173         }
1174 
1175         @Override
doTest()1176         public void doTest() {
1177             assertEquals(INITIAL_VALUE, vh.getVolatile(this));
1178             vh.setVolatile(this, null);
1179             Widget rw = (Widget) vh.compareAndExchange(this, null, WidgetChild.ONE);
1180             assertEquals(null, rw);
1181             assertEquals(WidgetChild.ONE, this.w);
1182             WidgetChild rwc =
1183                     (WidgetChild)
1184                             vh.compareAndExchangeRelease(this, WidgetChild.ONE, WidgetChild.TWO);
1185             assertEquals(WidgetChild.TWO, w);
1186             rwc = (WidgetChild) vh.compareAndExchangeAcquire(this, WidgetChild.TWO, Widget.ONE);
1187             assertEquals(Widget.ONE, w);
1188             assertEquals(false, (boolean) vh.compareAndSet(this, null, null));
1189             assertEquals(true, vh.compareAndSet(this, Widget.ONE, Widget.TWO));
1190             assertEquals(Widget.TWO, w);
1191             vh.set(this, null);
1192             assertEquals(null, (Widget) vh.get(this));
1193             vh.setRelease(this, WidgetChild.ONE);
1194             assertEquals(WidgetChild.ONE, (WidgetChild) vh.getAcquire(this));
1195             assertEquals(WidgetChild.ONE, w);
1196             vh.setOpaque(this, WidgetChild.TWO);
1197             assertEquals(WidgetChild.TWO, vh.getOpaque(this));
1198             assertEquals(WidgetChild.TWO, w);
1199             vh.setVolatile(this, null);
1200             assertEquals(null, (Widget) vh.getVolatile(this));
1201             assertEquals(null, w);
1202             assertEquals(null, (WidgetChild) vh.getAndSet(this, WidgetChild.ONE));
1203             assertEquals(WidgetChild.ONE, w);
1204             assertEquals(WidgetChild.ONE, (WidgetChild) vh.getAndSetRelease(this, WidgetChild.TWO));
1205             assertEquals(WidgetChild.TWO, (WidgetChild) vh.getAndSetAcquire(this, WidgetChild.ONE));
1206             try {
1207                 WidgetChild result = (WidgetChild) vh.getAndAdd(this, WidgetChild.ONE);
1208                 failUnreachable();
1209             } catch (UnsupportedOperationException e) {
1210             }
1211             try {
1212                 WidgetChild result = (WidgetChild) vh.getAndAddAcquire(this, 1);
1213                 failUnreachable();
1214             } catch (UnsupportedOperationException e) {
1215             }
1216             try {
1217                 WidgetChild result = (WidgetChild) vh.getAndAddRelease(this, 1);
1218                 failUnreachable();
1219             } catch (UnsupportedOperationException e) {
1220             }
1221             try {
1222                 WidgetChild result = (WidgetChild) vh.getAndBitwiseAnd(this, 1);
1223                 failUnreachable();
1224             } catch (UnsupportedOperationException e) {
1225             }
1226             try {
1227                 WidgetChild result = (WidgetChild) vh.getAndBitwiseAndAcquire(this, 1);
1228                 failUnreachable();
1229             } catch (UnsupportedOperationException e) {
1230             }
1231             try {
1232                 WidgetChild result = (WidgetChild) vh.getAndBitwiseAndRelease(this, 1);
1233                 failUnreachable();
1234             } catch (UnsupportedOperationException e) {
1235             }
1236             try {
1237                 WidgetChild result = (WidgetChild) vh.getAndBitwiseOr(this, 1);
1238                 failUnreachable();
1239             } catch (UnsupportedOperationException e) {
1240             }
1241             try {
1242                 WidgetChild result = (WidgetChild) vh.getAndBitwiseOrAcquire(this, 1);
1243                 failUnreachable();
1244             } catch (UnsupportedOperationException e) {
1245             }
1246             try {
1247                 WidgetChild result = (WidgetChild) vh.getAndBitwiseOrRelease(this, 1);
1248                 failUnreachable();
1249             } catch (UnsupportedOperationException e) {
1250             }
1251             try {
1252                 WidgetChild result = (WidgetChild) vh.getAndBitwiseXor(this, 1);
1253                 failUnreachable();
1254             } catch (UnsupportedOperationException e) {
1255             }
1256             try {
1257                 WidgetChild result = (WidgetChild) vh.getAndBitwiseXorAcquire(this, 1);
1258                 failUnreachable();
1259             } catch (UnsupportedOperationException e) {
1260             }
1261             try {
1262                 WidgetChild result = (WidgetChild) vh.getAndBitwiseXorRelease(this, 1);
1263                 failUnreachable();
1264             } catch (UnsupportedOperationException e) {
1265             }
1266             try {
1267                 boolean result = vh.compareAndSet(this, new Object(), Widget.ONE);
1268                 failUnreachable();
1269             } catch (ClassCastException e) {
1270             }
1271         }
1272     }
1273 
1274     public static class SupertypeTest extends VarHandleUnitTest {
1275         private Widget w = null;
1276         private static final VarHandle vh;
1277 
1278         static {
1279             try {
1280                 vh = MethodHandles.lookup().findVarHandle(SupertypeTest.class, "w", Widget.class);
1281             } catch (Exception e) {
1282                 throw new RuntimeException(e);
1283             }
1284         }
1285 
main(String[] args)1286         public static void main(String[] args) {
1287             new SupertypeTest().run();
1288         }
1289 
1290         @Override
doTest()1291         public void doTest() {
1292             assertEquals(null, (Object) vh.get(this));
1293             vh.set(this, Widget.ONE);
1294             assertEquals(Widget.ONE, vh.getVolatile(this));
1295             try {
1296                 vh.setVolatile(this, new Object());
1297             } catch (ClassCastException e) {
1298             }
1299         }
1300     }
1301 
1302     public static class InterfaceTest extends VarHandleUnitTest {
1303         public interface ParentInterface {
getValue()1304             int getValue();
1305         }
1306 
1307         public interface ChildInterface extends ParentInterface {
setValue(int newValue)1308             void setValue(int newValue);
1309         }
1310 
1311         public class A implements ParentInterface {
1312             protected int value = 0;
getValue()1313             public int getValue() { return value; }
1314         }
1315 
1316         public class B extends A implements ChildInterface {
setValue(int newValue)1317             public void setValue(int newValue) { value = newValue; }
1318         }
1319 
1320         private ParentInterface pi;
1321         private A obj;
1322 
1323         private VarHandle vh_pi;
1324         private VarHandle vh_obj;
1325         {
1326             try {
1327                 vh_pi = MethodHandles.lookup().findVarHandle(InterfaceTest.class, "pi",
1328                                                              InterfaceTest.ParentInterface.class);
1329                 vh_obj = MethodHandles.lookup().findVarHandle(InterfaceTest.class, "obj",
1330                                                               InterfaceTest.A.class);
1331             } catch (Exception e) {
1332                 throw new RuntimeException(e);
1333             }
1334         }
1335 
main(String[] args)1336         public static void main(String[] args) {
1337             new InterfaceTest().run();
1338         }
1339 
1340         @Override
doTest()1341         public void doTest() {
1342             // Tests using VarHandle to field of type ParentInterface.
1343             {
1344                 pi = (ParentInterface) new A();
1345                 ParentInterface p = (ParentInterface) vh_pi.get(this);
1346                 Object o = (Object) vh_pi.get(this);
1347                 try {
1348                     ChildInterface c = (ChildInterface) vh_pi.get(this);
1349                     failUnreachable();
1350                 } catch (ClassCastException expected) {}
1351             }
1352             {
1353                 pi = new B();
1354                 ParentInterface p = (ParentInterface) vh_pi.get(this);
1355                 B b = (B) vh_pi.get(this);
1356                 Object o = (Object) vh_pi.get(this);
1357                 ChildInterface c = (ChildInterface) vh_pi.get(this);
1358             }
1359             {
1360                 pi = null;
1361                 ParentInterface p = (ParentInterface) vh_pi.get(this);
1362                 B b = (B) vh_pi.get(this);
1363                 Object o = (Object) vh_pi.get(this);
1364                 ChildInterface c = (ChildInterface) vh_pi.get(this);
1365             }
1366 
1367             // Tests using VarHandle to field of type A.
1368             {
1369                 obj = new A();
1370                 ParentInterface p = (ParentInterface) vh_obj.get(this);
1371                 Object o = (Object) vh_obj.get(this);
1372                 A a = (A) vh_obj.get(this);
1373                 try {
1374                     B b = (B) vh_obj.get(this);
1375                     failUnreachable();
1376                 } catch (ClassCastException e) {}
1377                 try {
1378                     ChildInterface c = (ChildInterface) vh_obj.get(this);
1379                     failUnreachable();
1380                 } catch (ClassCastException e) {}
1381             }
1382             {
1383                 obj = new B();
1384                 ParentInterface p = (ParentInterface) vh_obj.get(this);
1385                 Object o = (Object) vh_obj.get(this);
1386                 A a = (A) vh_obj.get(this);
1387                 B b = (B) vh_obj.get(this);
1388                 ChildInterface c = (ChildInterface) vh_obj.get(this);
1389             }
1390             {
1391                 obj = null;
1392                 ParentInterface p = (ParentInterface) vh_obj.get(this);
1393                 Object o = (Object) vh_obj.get(this);
1394                 A a = (A) vh_obj.get(this);
1395                 B b = (B) vh_obj.get(this);
1396                 ChildInterface c = (ChildInterface) vh_obj.get(this);
1397             }
1398         }
1399     }
1400 
1401     public static class ImplicitBoxingIntegerTest extends VarHandleUnitTest {
1402         private static Integer field;
1403         private static final VarHandle vh;
1404 
1405         static {
1406             try {
1407                 vh =
1408                         MethodHandles.lookup()
1409                                 .findStaticVarHandle(
1410                                         ImplicitBoxingIntegerTest.class, "field", Integer.class);
1411             } catch (Exception e) {
1412                 throw new RuntimeException(e);
1413             }
1414         }
1415 
main(String[] args)1416         public static void main(String[] args) {
1417             new ImplicitBoxingIntegerTest().run();
1418         }
1419 
1420         @Override
doTest()1421         public void doTest() {
1422             try {
1423                 vh.set(true);
1424                 failUnreachable();
1425             } catch (WrongMethodTypeException e) {
1426             }
1427             try {
1428                 vh.set((byte) 0);
1429                 failUnreachable();
1430             } catch (WrongMethodTypeException e) {
1431             }
1432             try {
1433                 vh.set('A');
1434                 failUnreachable();
1435             } catch (WrongMethodTypeException e) {
1436             }
1437             try {
1438                 vh.set((short) 1);
1439                 failUnreachable();
1440             } catch (WrongMethodTypeException e) {
1441             }
1442             vh.set(2);
1443             try {
1444                 vh.setRelease(Long.MAX_VALUE);
1445                 failUnreachable();
1446             } catch (WrongMethodTypeException e) {
1447             }
1448             try {
1449                 vh.setRelease(Float.MAX_VALUE);
1450                 failUnreachable();
1451             } catch (WrongMethodTypeException e) {
1452             }
1453             try {
1454                 vh.setRelease(Double.MAX_VALUE);
1455                 failUnreachable();
1456             } catch (WrongMethodTypeException e) {
1457             }
1458             vh.set(null);
1459             vh.set(Integer.valueOf(Integer.MAX_VALUE));
1460         }
1461     }
1462 
main(String[] args)1463     public static void main(String[] args) {
1464         VoidReturnTypeTest.main(args);
1465 
1466         BoxedNullBooleanThrowsNPETest.main(args);
1467         BoxedNullByteThrowsNPETest.main(args);
1468         BoxedNullCharacterThrowsNPETest.main(args);
1469         BoxedNullShortThrowsNPETest.main(args);
1470         BoxedNullIntegerThrowsNPETest.main(args);
1471         BoxedNullLongThrowsNPETest.main(args);
1472         BoxedNullFloatThrowsNPETest.main(args);
1473         BoxedNullDoubleThrowsNPETest.main(args);
1474 
1475         WideningBooleanArgumentTest.main(args);
1476         WideningByteArgumentTest.main(args);
1477         WideningCharacterArgumentTest.main(args);
1478         WideningShortArgumentTest.main(args);
1479         WideningIntegerArgumentTest.main(args);
1480         WideningLongArgumentTest.main(args);
1481         WideningFloatArgumentTest.main(args);
1482         WideningDoubleArgumentTest.main(args);
1483 
1484         WideningBooleanReturnValueTest.main(args);
1485         WideningByteReturnValueTest.main(args);
1486         WideningCharacterReturnValueTest.main(args);
1487         WideningShortReturnValueTest.main(args);
1488         WideningIntegerReturnValueTest.main(args);
1489         WideningLongReturnValueTest.main(args);
1490         WideningFloatReturnValueTest.main(args);
1491         WideningDoubleReturnValueTest.main(args);
1492 
1493         SubtypeTest.main(args);
1494         SupertypeTest.main(args);
1495         InterfaceTest.main(args);
1496 
1497         ImplicitBoxingIntegerTest.main(args);
1498     }
1499 }
1500