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 
21 // These tests cover DoVarHandleInvokeCommon in interpreter_common.cc.
22 
23 public class VarHandleAccessorExceptionTests {
24     public static class NullReceiverTest extends VarHandleUnitTest {
25         private static final VarHandle vh = null;
26 
27         @Override
doTest()28         protected void doTest() {
29             try {
30                 vh.set(3);
31                 failUnreachable();
32             } catch (NullPointerException ex) {
33             }
34         }
35 
main(String[] args)36         public static void main(String[] args) {
37             new NullReceiverTest().run();
38         }
39     }
40 
41     public static class UnsupportedAccessModeTest extends VarHandleUnitTest {
42         private static final boolean b = true;
43         private static final VarHandle vh;
44 
45         static {
46             try {
47                 Class<?> cls = UnsupportedAccessModeTest.class;
48                 vh = MethodHandles.lookup().findStaticVarHandle(cls, "b", boolean.class);
49             } catch (Exception e) {
50                 throw new RuntimeException(e);
51             }
52         }
53 
54         @Override
doTest()55         protected void doTest() {
56             // A final field should not support an VarHandle access modes which can update it
57             boolean isSupported =
58                     vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND);
59             assertFalse(isSupported);
60             try {
61                 vh.getAndBitwiseAnd(true);
62                 failUnreachable();
63             } catch (UnsupportedOperationException ex) {
64             }
65         }
66 
main(String[] args)67         public static void main(String[] args) {
68             new UnsupportedAccessModeTest().run();
69         }
70     }
71 
72     public static class WrongArgumentTypeCausingWrongMethodTypeTest extends VarHandleUnitTest {
73         private short s;
74         private static final VarHandle vh;
75 
76         static {
77             try {
78                 Class<?> cls = WrongArgumentTypeCausingWrongMethodTypeTest.class;
79                 vh = MethodHandles.lookup().findVarHandle(cls, "s", short.class);
80             } catch (Exception e) {
81                 throw new RuntimeException(e);
82             }
83         }
84 
85         @Override
doTest()86         protected void doTest() {
87             vh.set(this, (short) 0xcafe);
88             try {
89                 vh.setVolatile(this, System.out); // System.out is a PrintStream, not short!
90                 failUnreachable();
91             } catch (WrongMethodTypeException ex) {
92             }
93         }
94 
main(String[] args)95         public static void main(String[] args) {
96             new WrongArgumentTypeCausingWrongMethodTypeTest().run();
97         }
98     }
99 
100     // Too many arguments causing WMTE
101     public static class TooManyArgumentsCausingWrongMethodTypeTest extends VarHandleUnitTest {
102         private int i;
103         private static final VarHandle vh;
104 
105         static {
106             try {
107                 Class<?> cls = TooManyArgumentsCausingWrongMethodTypeTest.class;
108                 vh = MethodHandles.lookup().findVarHandle(cls, "i", int.class);
109             } catch (Exception e) {
110                 throw new RuntimeException(e);
111             }
112         }
113 
114         @Override
doTest()115         protected void doTest() {
116             vh.set(this, 0x12345678);
117             try {
118                 vh.setVolatile(this, 0x5a5a55aa, 0xc3c30f0f);
119                 failUnreachable();
120             } catch (WrongMethodTypeException ex) {
121             }
122         }
123 
main(String[] args)124         public static void main(String[] args) {
125             new TooManyArgumentsCausingWrongMethodTypeTest().run();
126         }
127     }
128 
129     public static class TooFewArgumentsCausingWrongMethodTypeTest extends VarHandleUnitTest {
130         private int i;
131         private static final VarHandle vh;
132 
133         static {
134             try {
135                 Class<?> cls = TooFewArgumentsCausingWrongMethodTypeTest.class;
136                 vh = MethodHandles.lookup().findVarHandle(cls, "i", int.class);
137             } catch (Exception e) {
138                 throw new RuntimeException(e);
139             }
140         }
141 
142         @Override
doTest()143         protected void doTest() {
144             i = 33;
145             vh.compareAndSet(this, 33, 44);
146             boolean updated = false;
147             try {
148                 updated = (boolean) vh.compareAndSet(this, 44);
149                 failUnreachable();
150             } catch (WrongMethodTypeException ex) {
151             }
152             assertFalse(updated); // Should have failed too few arguments
153         }
154 
main(String[] args)155         public static void main(String[] args) {
156             new TooFewArgumentsCausingWrongMethodTypeTest().run();
157         }
158     }
159 
160     public static class ReturnTypeCausingWrongMethodTypeTest extends VarHandleUnitTest {
161         private int i;
162         private static final VarHandle vh;
163 
164         static {
165             try {
166                 Class<?> cls = ReturnTypeCausingWrongMethodTypeTest.class;
167                 vh = MethodHandles.lookup().findVarHandle(cls, "i", int.class);
168             } catch (Exception e) {
169                 throw new RuntimeException(e);
170             }
171         }
172 
173         @Override
doTest()174         protected void doTest() {
175             i = 33;
176             vh.getAndSet(this, 44);
177             Runtime runtime = null;
178             try {
179                 runtime = (Runtime) vh.getAndSet(this, 44);
180                 failUnreachable();
181             } catch (WrongMethodTypeException ex) {
182             }
183             assertEquals(null, runtime);
184         }
185 
main(String[] args)186         public static void main(String[] args) {
187             new ReturnTypeCausingWrongMethodTypeTest().run();
188         }
189     }
190 
191     public static class UnsupportedAccessModePreemptsWrongMethodTypeExceptionTest
192             extends VarHandleUnitTest {
193         private static final boolean b = true;
194         private static final VarHandle vh;
195 
196         static {
197             try {
198                 Class<?> cls = UnsupportedAccessModePreemptsWrongMethodTypeExceptionTest.class;
199                 vh = MethodHandles.lookup().findStaticVarHandle(cls, "b", boolean.class);
200             } catch (Exception e) {
201                 throw new RuntimeException(e);
202             }
203         }
204 
205         @Override
doTest()206         protected void doTest() {
207             // A final field should not support an VarHandle access modes which can update it
208             boolean supported = vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND);
209             assertFalse(supported);
210             try {
211                 // The following is both unsupported and a wrong method type...
212                 vh.getAndBitwiseAnd(System.out);
213                 failUnreachable();
214             } catch (UnsupportedOperationException ex) {
215             }
216         }
217 
main(String[] args)218         public static void main(String[] args) {
219             new UnsupportedAccessModePreemptsWrongMethodTypeExceptionTest().run();
220         }
221     }
222 
main(String[] args)223     public static void main(String[] args) {
224         NullReceiverTest.main(args);
225         UnsupportedAccessModeTest.main(args);
226         WrongArgumentTypeCausingWrongMethodTypeTest.main(args);
227         TooManyArgumentsCausingWrongMethodTypeTest.main(args);
228         TooFewArgumentsCausingWrongMethodTypeTest.main(args);
229         ReturnTypeCausingWrongMethodTypeTest.main(args);
230         UnsupportedAccessModePreemptsWrongMethodTypeExceptionTest.main(args);
231     }
232 }
233