/* * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /** * @test * @summary Test for value types consistency checks * * @comment CASE [A] ConsistencyTest.java uses Point as a VT, but Mismatched.java uses Point as a POJO Type. * @compile -XDenableValueTypes -XDallowFlattenabilityModifiers ConsistencyTest.java POJOPoint.java Mismatched.java * @compile -XDenableValueTypes -XDallowFlattenabilityModifiers ConsistencyTest.java ValuePoint.java * @run main/othervm -Xint -XX:+EnableValhalla ConsistencyTest * @run main/othervm -Xcomp -XX:+EnableValhalla ConsistencyTest * * @comment CASE [B] ConsistencyTest.java uses Point as a POJO Type, but Mismatched.java uses Point as a VT. * @compile -XDenableValueTypes -XDallowFlattenabilityModifiers ConsistencyTest.java ValuePoint.java Mismatched.java * @compile -XDenableValueTypes -XDallowFlattenabilityModifiers ConsistencyTest.java POJOPoint.java * @run main/othervm -Xint -XX:+EnableValhalla ConsistencyTest * @run main/othervm -Xcomp -XX:+EnableValhalla ConsistencyTest */ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.invoke.*; import java.lang.reflect.*; import java.util.*; // !!! NOTE !!! // ConsistentTest.java and Mismatched.java are compiled separately, such that the classes in the two files // will have the exact opposite understanding of whether Point is a VT. // Each test case for ConsistencyTest is written as a separate class, which must have exactly // one of the following 3 annotations: @NegativeTest, @PositiveTest or @LegacyPositiveTest. // The test case must always fail with an ICCE. @Retention(RetentionPolicy.RUNTIME) @interface NegativeTest {} // The test case must always succeed. @Retention(RetentionPolicy.RUNTIME) @interface PositiveTest {} // The test case is for a "legacy" class, which doesn't know that Point is a VT. Some // operations by such legacy classes are allowed (such as declaring, but not using, a method // whose signature includes LPoint;). See LocalMethod in Mismatched.java for an example @Retention(RetentionPolicy.RUNTIME) @interface LegacyPositiveTest {} public class ConsistencyTest { public static void main(String[] args) { // Resolve this class now, before some of the test classes try to declare // a field or parameter of this type. Class pointClass = Point.class; boolean isVT = pointClass.isValue(); System.out.println("Is class " + pointClass + " a ValueType? " + (isVT ? "YES" : "NO")); // Run with "jtreg -DNonVTOnly ConsistencyTest.java", etc, to select a test scenario. if (isVT && (System.getProperty("NonVTOnly") != null)) { System.out.println("-DNonVTOnly is specified. Test skipped"); return; } if (!isVT && (System.getProperty("VTOnly") != null)) { System.out.println("-DVTOnly is specified. Test skipped"); return; } test( "InvokeMethodHandle", "FlattenableField", "NotFlattenableField", "NotFlattenableStaticField", "ValueArrayField", "ResolveClass", "ResolveArray", "ResolveMultiArray", "ResolveMethod", "LocalMethod", "LocalMethodWithArray", "LocalOverridingMethod", "LocalOverridingDefaultMethod", "RemoteMethod", "RemoteMethodNull", "RemoteMethodWithArray", "BothWrongRemoteMethod"); } public static void test(String...tests) { List failed = new ArrayList<>(); List exceptions = new ArrayList<>(); Arrays.sort(tests); for (String name : tests) { try { testOne(name); } catch (Throwable t) { failed.add(name); exceptions.add(t); } } if (failed.size() > 0) { System.out.println("-----------------------------------------"); for (int i=0; i"); } } } // This class has a *correct* notion of whether Point is a VT class CorrectProvider { static __NotFlattened Point p; // to get a null value static Point getPoint() { return Point.createPoint(); } static Point getNullPoint() { return p; } static Point[] getPointArray() { return new Point[10]; } } //---------------------------------------------------------------------- // Here are the test cases. More test cases are in Mismatched.java //---------------------------------------------------------------------- // It must not be possible to override a method with a mismatched type @NegativeTest class LocalOverridingMethod { static class Helper extends Parent { Point foo() { return Point.createPoint(); } } public static void run() { new Helper(); } } // It must not be possible to override a default method with a mismatched type @NegativeTest class LocalOverridingDefaultMethod { static class Helper implements InterfaceWithDefault { public Point foo() { return Point.createPoint(); } } public static void run() { new Helper(); } } // Cannot call a method whose signature contains a mismatched VT. @NegativeTest class RemoteMethod { public static void run() { Point p = Provider.getPoint(); } } // Cannot call a method whose parameter is a mismatched VT, even if you are passing null. @NegativeTest class RemoteMethodNull { static __NotFlattened Point p; // to get a null value public static void run() { Provider.processPoint(p); } } // Cannot call a method whose signature contains an array of a mismatched VT, even if you are passing null. @NegativeTest class RemoteMethodWithArray { public static void run() { Provider.foo(null); } } // You shouldn't be able to invoke a method defined by a class who has a different idea of whether Point is VT. @NegativeTest class InvokeMethodHandle { public static void run() throws Throwable { MethodHandles.Lookup lookup = MethodHandles.lookup(); MethodType mt = MethodType.methodType(Point.class); MethodHandle mh = lookup.findStatic(CorrectProvider.class, "getNullPoint", mt); InvokeMethodHandle_mismatched.test(mh); } }