1 /*
  2  * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.
  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  *
 23  */
 24 /*
 25  * @test
 26  * @bug 8269756
 27  * @summary test scenarios where getfield, putfield, and withfield access the
 28  *          same constant pool field_ref and test other withfield error cases.
 29  * @compile withfieldTests.jcod
 30  * @run main/othervm -Xverify:remote RunWithfieldTests
 31  */
 32 
 33 public class RunWithfieldTests {
 34 
 35     public static void main(String argv[]) throws Throwable {
 36 
 37         // Check that a withfield on a CONSTANT_Field_info entry that references
 38         // an identity object will fail and that subsequent putfield and getfield
 39         // operations on the same CONSTANT_FIELD_info entry will succeed.
 40         Class wfoClass = Class.forName("withfieldObject");
 41         withfieldObject wfo = (withfieldObject)wfoClass.getDeclaredConstructor().newInstance();
 42         String y = wfo.getfield();
 43         if (!y.equals("cde")) {
 44             throw new RuntimeException("Unexpected value of wfo.getfield(): " + y);
 45         }
 46 
 47 
 48         // Check that a putfield and getfield on a CONSTANT_Field_info entry that
 49         // references an identity object will succeed and that a subsequent withfield
 50         // operation on the same CONSTANT_FIELD_info entry will fail.
 51         Class pfoClass = Class.forName("putfieldObject");
 52         putfieldObject pfo = (putfieldObject)pfoClass.getDeclaredConstructor().newInstance();
 53         String x = pfo.getfield();
 54         if (!x.equals("abc")) {
 55             throw new RuntimeException("Unexpected value of pfo.getfield(): " + x);
 56         }
 57         try {
 58             pfo.withfieldFunc();
 59             throw new RuntimeException("ICCE not thrown");
 60         } catch (IncompatibleClassChangeError e) {
 61             if (!e.getMessage().contains("withfield cannot be used on identity class")) {
 62                 throw new RuntimeException("Wrong ICCE thrown: " + e.getMessage());
 63             }
 64         }
 65 
 66 
 67         // Check that a putfield on a CONSTANT_Field_info entry that references
 68         // a primitive object will fail and that subsequent withfield and getfield
 69         // operations on the same CONSTANT_FIELD_info entry will succeed.
 70         try {
 71             putfieldPrimitive pfp = new putfieldPrimitive(false);  // putfield on a primitive class
 72             throw new RuntimeException("ICCE not thrown");
 73         } catch (IncompatibleClassChangeError e) {
 74             if (!e.getMessage().contains("putfield cannot be used on primitive class")) {
 75                 throw new RuntimeException("Wrong ICCE thrown: " + e.getMessage());
 76             }
 77         }
 78         putfieldPrimitive pfp = new putfieldPrimitive(true);  // withfield on a primitive class
 79         if (pfp.getX() != 5) {
 80             throw new RuntimeException("Unexpected value of d.getfield(): " + pfp.getX());
 81         }
 82 
 83 
 84         // Check that a withfield and getfield on a CONSTANT_Field_info entry that
 85         // references a primitive object will succeed and that a subsequent putfield
 86         // operation on the same CONSTANT_FIELD_info entry will fail.
 87         withfieldPrimitive wfp = new withfieldPrimitive(true);  // withfield on a primitive class
 88         if (wfp.getX() != 5) {
 89             throw new RuntimeException("Unexpected value of d.getfield(): " + wfp.getX());
 90         }
 91         try {
 92             withfieldPrimitive wfp2 = new withfieldPrimitive(false);  // putfield on a primitive class
 93             throw new RuntimeException("ICCE not thrown");
 94         } catch (IncompatibleClassChangeError e) {
 95             if (!e.getMessage().contains("putfield cannot be used on primitive class")) {
 96                 throw new RuntimeException("Wrong ICCE thrown: " + e.getMessage());
 97             }
 98         }
 99 
100 
101         // Test withfield with a null stack operand.
102         try {
103             withfieldNull wfn = new withfieldNull();
104             throw new RuntimeException("NPE not thrown");
105         } catch (NullPointerException e) {
106             if (!e.getMessage().contains("Cannot assign field \"x\"")) {
107                 throw new RuntimeException("Wrong NPE thrown: " + e.getMessage());
108             }
109         }
110 
111 
112         // Test that a VerifyError exception is thrown for a withfield bytecode if the
113         // stack operand is a different primitive type than the primitive type in the
114         // constant pool field_ref.
115         try {
116             WrongPrimWF wPrim = new WrongPrimWF();
117             throw new RuntimeException("No exception thrown");
118         } catch (VerifyError e) {
119             if (!e.getMessage().contains("Bad type on operand stack")) {
120                 throw new RuntimeException("Wrong VerifyError thrown: " + e.getMessage());
121             }
122         }
123     }
124 }