changeset 56998:a8905b85b1f8 amber-demo-II

Automatic merge with records-and-sealed
author mcimadamore
date Fri, 16 Aug 2019 16:05:45 +0000
parents 7ddffaf8b702 6fbc84eefe66
children 3d7072d56e6d
files test/hotspot/jtreg/runtime/sealedTypes/noLoadSubtypes.jcod
diffstat 9 files changed, 375 insertions(+), 124 deletions(-) [+]
line wrap: on
line diff
--- a/src/hotspot/share/classfile/classFileParser.cpp	Fri Aug 16 15:05:55 2019 +0000
+++ b/src/hotspot/share/classfile/classFileParser.cpp	Fri Aug 16 16:05:45 2019 +0000
@@ -3411,6 +3411,11 @@
                      CHECK);
 }
 
+bool ClassFileParser::supports_sealed_types() {
+  return _major_version == JAVA_14_VERSION;
+    // TBD: add: && _minor_version == JAVA_PREVIEW_MINOR_VERSION && Arguments::enable_preview()
+}
+
 void ClassFileParser::parse_classfile_attributes(const ClassFileStream* const cfs,
                                                  ConstantPool* cp,
                  ClassFileParser::ClassAnnotationCollector* parsed_annotations,
@@ -3641,18 +3646,20 @@
                          class_info_index, CHECK);
           _nest_host = class_info_index;
         } else if (tag == vmSymbols::tag_permitted_subtypes()) {
-            // Check for PermittedSubtypes tag
-            if (!_access_flags.is_final()) {
-                classfile_parse_error("PermittedSubtypes attribute in non-final class file %s", CHECK);
+            if (supports_sealed_types()) {
+              // Check for PermittedSubtypes tag
+              if (!_access_flags.is_final()) {
+                  classfile_parse_error("PermittedSubtypes attribute in non-final class file %s", CHECK);
+              }
+              if (parsed_permitted_subtypes_attribute) {
+                classfile_parse_error("Multiple PermittedSubtypes attributes in class file %s", CHECK);
+              } else {
+                parsed_permitted_subtypes_attribute = true;
+              }
+              permitted_subtypes_attribute_start = cfs->current();
+              permitted_subtypes_attribute_length = attribute_length;
             }
-            if (parsed_permitted_subtypes_attribute) {
-              classfile_parse_error("Multiple PermittedSubtypes attributes in class file %s", CHECK);
-            } else {
-              parsed_permitted_subtypes_attribute = true;
-            }
-            permitted_subtypes_attribute_start = cfs->current();
-            permitted_subtypes_attribute_length = attribute_length;
-            cfs->skip_u1(permitted_subtypes_attribute_length, CHECK);
+            cfs->skip_u1(attribute_length, CHECK);
         } else if (tag == vmSymbols::tag_record()) {
           if (parsed_record_attribute) {
             classfile_parse_error("Multiple Record attributes in class file %s", CHECK);
--- a/src/hotspot/share/classfile/classFileParser.hpp	Fri Aug 16 15:05:55 2019 +0000
+++ b/src/hotspot/share/classfile/classFileParser.hpp	Fri Aug 16 16:05:45 2019 +0000
@@ -299,6 +299,7 @@
                                         ConstantPool* cp,
                                         int* const record_params_count_ptr,
                                         TRAPS);
+  bool supports_sealed_types();
 
   void parse_classfile_attributes(const ClassFileStream* const cfs,
                                   ConstantPool* cp,
--- a/src/hotspot/share/memory/heapInspection.hpp	Fri Aug 16 15:05:55 2019 +0000
+++ b/src/hotspot/share/memory/heapInspection.hpp	Fri Aug 16 16:05:45 2019 +0000
@@ -88,6 +88,8 @@
         "Number of bytes used by the InstanceKlass::inner_classes() array") \
     f(nest_members_bytes, IK_nest_members, \
         "Number of bytes used by the InstanceKlass::nest_members() array") \
+    f(permitted_subtypes_bytes, IK_nest_members, \
+        "Number of bytes used by the InstanceKlass::permitted_subtypes() array") \
     f(signers_bytes, IK_signers, \
         "Number of bytes used by the InstanceKlass::singers() array") \
     f(class_annotations_bytes, class_annotations, \
--- a/src/hotspot/share/oops/instanceKlass.cpp	Fri Aug 16 15:05:55 2019 +0000
+++ b/src/hotspot/share/oops/instanceKlass.cpp	Fri Aug 16 16:05:45 2019 +0000
@@ -3586,6 +3586,7 @@
   n += (sz->_fields_bytes                = sz->count_array(fields()));
   n += (sz->_inner_classes_bytes         = sz->count_array(inner_classes()));
   n += (sz->_nest_members_bytes          = sz->count_array(nest_members()));
+  n += (sz->_permitted_subtypes_bytes    = sz->count_array(permitted_subtypes()));
   sz->_ro_bytes += n;
 
   const ConstantPool* cp = constants();
--- a/src/hotspot/share/oops/instanceKlass.hpp	Fri Aug 16 15:05:55 2019 +0000
+++ b/src/hotspot/share/oops/instanceKlass.hpp	Fri Aug 16 16:05:45 2019 +0000
@@ -468,7 +468,7 @@
     _record_params_count = record_params_count;
   }
 
-// permitted subtypes
+  // permitted subtypes
   Array<u2>* permitted_subtypes() const     { return _permitted_subtypes; }
   void set_permitted_subtypes(Array<u2>* s) { _permitted_subtypes = s; }
 
--- a/src/java.base/share/classes/java/lang/Class.java	Fri Aug 16 15:05:55 2019 +0000
+++ b/src/java.base/share/classes/java/lang/Class.java	Fri Aug 16 16:05:45 2019 +0000
@@ -4151,7 +4151,7 @@
         ClassDesc[] constants = new ClassDesc[descriptors.length];
         int i = 0;
         for (String descriptor : descriptors) {
-            ClassDesc cd = ClassDesc.of(descriptor);
+            ClassDesc cd = ClassDesc.of(descriptor.replace('/', '.'));
             constants[i++] = cd;
         }
         return constants;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/sealedTypes/getPermittedSubtypes.jcod	Fri Aug 16 16:05:45 2019 +0000
@@ -0,0 +1,327 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+// This class has entries in its PermittedSubtypes attribute that do not exist.
+// Test that this does not prevent JVM_GetPermittedSubtypes() from returning
+// their names.
+//
+// sealed class noLoadSubtypes permits iDontExist, I/Dont/Exist/Either { }
+//
+class noLoadSubtypes {
+  0xCAFEBABE;
+  0; // minor version
+  58; // version
+  [18] { // Constant Pool
+    ; // first element is empty
+    Method #2 #3; // #1     at 0x0A
+    class #4; // #2     at 0x0F
+    NameAndType #5 #6; // #3     at 0x12
+    Utf8 "java/lang/Object"; // #4     at 0x17
+    Utf8 "<init>"; // #5     at 0x2A
+    Utf8 "()V"; // #6     at 0x33
+    class #8; // #7     at 0x39
+    Utf8 "noLoadSubtypes"; // #8     at 0x3C
+    Utf8 "Code"; // #9     at 0x4D
+    Utf8 "LineNumberTable"; // #10     at 0x54
+    Utf8 "SourceFile"; // #11     at 0x66
+    Utf8 "noLoadSubtypes.java"; // #12     at 0x73
+    Utf8 "PermittedSubtypes"; // #13     at 0x89
+    class #15; // #14     at 0x9D
+    Utf8 "iDontExist"; // #15     at 0xA0
+    class #17; // #16     at 0xAA
+    Utf8 "I/Dont/Exist/Either"; // #17     at 0xAD
+  } // Constant Pool
+
+  0x0030; // access [ ACC_SUPER ACC_FINAL ]
+  #7;// this_cpx
+  #2;// super_cpx
+
+  [0] { // Interfaces
+  } // Interfaces
+
+  [0] { // fields
+  } // fields
+
+  [1] { // methods
+    { // Member at 0xC1
+      0x0000; // access
+      #5; // name_cpx
+      #6; // sig_cpx
+      [1] { // Attributes
+        Attr(#9, 29) { // Code at 0xC9
+          1; // max_stack
+          1; // max_locals
+          Bytes[5]{
+            0x2AB70001B1;
+          }
+          [0] { // Traps
+          } // end Traps
+          [1] { // Attributes
+            Attr(#10, 6) { // LineNumberTable at 0xE0
+              [1] { // LineNumberTable
+                0  1; //  at 0xEC
+              }
+            } // end LineNumberTable
+          } // Attributes
+        } // end Code
+      } // Attributes
+    } // Member
+  } // methods
+
+  [2] { // Attributes
+    Attr(#13, 6) { // PermittedSubtypes at 0xF6
+      0x0002000E0010;
+    } // end PermittedSubtypes
+    ;
+    Attr(#11, 2) { // SourceFile at 0xEE
+      #12;
+    } // end SourceFile
+  } // Attributes
+} // end class noLoadSubtypes
+
+
+
+// This class contains an empty PermittedSubtypes attribute.  Test that
+// this does not cause an exception to get thrown.
+class noSubtypes {
+  0xCAFEBABE;
+  0; // minor version
+  58; // version
+  [14] { // Constant Pool
+    ; // first element is empty
+    Method #2 #3; // #1     at 0x0A
+    class #4; // #2     at 0x0F
+    NameAndType #5 #6; // #3     at 0x12
+    Utf8 "java/lang/Object"; // #4     at 0x17
+    Utf8 "<init>"; // #5     at 0x2A
+    Utf8 "()V"; // #6     at 0x33
+    class #8; // #7     at 0x39
+    Utf8 "noSubtypes"; // #8     at 0x3C
+    Utf8 "Code"; // #9     at 0x49
+    Utf8 "LineNumberTable"; // #10     at 0x50
+    Utf8 "SourceFile"; // #11     at 0x62
+    Utf8 "noSubtypes.java"; // #12     at 0x6F
+    Utf8 "PermittedSubtypes"; // #13     at 0x81
+  } // Constant Pool
+
+  0x0030; // access [ ACC_SUPER ACC_FINAL ]
+  #7;// this_cpx
+  #2;// super_cpx
+
+  [0] { // Interfaces
+  } // Interfaces
+
+  [0] { // fields
+  } // fields
+
+  [1] { // methods
+    { // Member at 0xAB
+      0x0000; // access
+      #5; // name_cpx
+      #6; // sig_cpx
+      [1] { // Attributes
+        Attr(#9, 29) { // Code at 0xB3
+          1; // max_stack
+          1; // max_locals
+          Bytes[5]{
+            0x2AB70001B1;
+          }
+          [0] { // Traps
+          } // end Traps
+          [1] { // Attributes
+            Attr(#10, 6) { // LineNumberTable at 0xCA
+              [1] { // LineNumberTable
+                0  1; //  at 0xD6
+              }
+            } // end LineNumberTable
+          } // Attributes
+        } // end Code
+      } // Attributes
+    } // Member
+  } // methods
+
+  [2] { // Attributes
+    Attr(#11, 2) { // SourceFile at 0xD8
+      #12;
+    } // end SourceFile
+    ;
+    Attr(#13, 2) { // PermittedSubtypes at 0xE0
+      0x0000;
+    } // end PermittedSubtypes
+  } // Attributes
+} // end class noSubtypes
+
+
+
+// This class has a PermittedSubtypes attribute but an old class file version.
+// The PermittedSubtypes attribute should be ignored.
+//
+// sealed class oldClassFile permits iDontExist, I/Dont/Exist/Either { }
+//
+class oldClassFile {
+  0xCAFEBABE;
+  0; // minor version
+  57; // version
+  [18] { // Constant Pool
+    ; // first element is empty
+    Method #2 #3; // #1     at 0x0A
+    class #4; // #2     at 0x0F
+    NameAndType #5 #6; // #3     at 0x12
+    Utf8 "java/lang/Object"; // #4     at 0x17
+    Utf8 "<init>"; // #5     at 0x2A
+    Utf8 "()V"; // #6     at 0x33
+    class #8; // #7     at 0x39
+    Utf8 "oldClassFile"; // #8     at 0x3C
+    Utf8 "Code"; // #9     at 0x4D
+    Utf8 "LineNumberTable"; // #10     at 0x54
+    Utf8 "SourceFile"; // #11     at 0x66
+    Utf8 "oldClassFile.java"; // #12     at 0x73
+    Utf8 "PermittedSubtypes"; // #13     at 0x89
+    class #15; // #14     at 0x9D
+    Utf8 "iDontExist"; // #15     at 0xA0
+    class #17; // #16     at 0xAA
+    Utf8 "I/Dont/Exist/Either"; // #17     at 0xAD
+  } // Constant Pool
+
+  0x0030; // access [ ACC_SUPER ACC_FINAL ]
+  #7;// this_cpx
+  #2;// super_cpx
+
+  [0] { // Interfaces
+  } // Interfaces
+
+  [0] { // fields
+  } // fields
+
+  [1] { // methods
+    { // Member at 0xC1
+      0x0000; // access
+      #5; // name_cpx
+      #6; // sig_cpx
+      [1] { // Attributes
+        Attr(#9, 29) { // Code at 0xC9
+          1; // max_stack
+          1; // max_locals
+          Bytes[5]{
+            0x2AB70001B1;
+          }
+          [0] { // Traps
+          } // end Traps
+          [1] { // Attributes
+            Attr(#10, 6) { // LineNumberTable at 0xE0
+              [1] { // LineNumberTable
+                0  1; //  at 0xEC
+              }
+            } // end LineNumberTable
+          } // Attributes
+        } // end Code
+      } // Attributes
+    } // Member
+  } // methods
+
+  [2] { // Attributes
+    Attr(#11, 2) { // SourceFile at 0xEE
+      #12;
+    } // end SourceFile
+    ;
+    Attr(#13, 6) { // PermittedSubtypes at 0xF6
+      0x0002000E0010;
+    } // end PermittedSubtypes
+  } // Attributes
+} // end class oldClassFile
+
+
+
+// This class has a corrupted PermittedSubtypes attribute.  Attempts to load it
+// should throw ClassFormatError.
+class badPermittedAttr {
+  0xCAFEBABE;
+  0; // minor version
+  58; // version
+  [18] { // Constant Pool
+    ; // first element is empty
+    Method #2 #3; // #1     at 0x0A
+    class #4; // #2     at 0x0F
+    NameAndType #5 #6; // #3     at 0x12
+    Utf8 "java/lang/Object"; // #4     at 0x17
+    Utf8 "<init>"; // #5     at 0x2A
+    Utf8 "()V"; // #6     at 0x33
+    class #8; // #7     at 0x39
+    Utf8 "badPermittedAttr"; // #8     at 0x3C
+    Utf8 "Code"; // #9     at 0x4D
+    Utf8 "LineNumberTable"; // #10     at 0x54
+    Utf8 "SourceFile"; // #11     at 0x66
+    Utf8 "badPermittedAttr.java"; // #12     at 0x73
+    Utf8 "PermittedSubtypes"; // #13     at 0x89
+    class #15; // #14     at 0x9D
+    Utf8 "iDontExist"; // #15     at 0xA0
+    class #17; // #16     at 0xAA
+    Utf8 "I/Dont/Exist/Either"; // #17     at 0xAD
+  } // Constant Pool
+
+  0x0030; // access [ ACC_SUPER ACC_FINAL ]
+  #7;// this_cpx
+  #2;// super_cpx
+
+  [0] { // Interfaces
+  } // Interfaces
+
+  [0] { // fields
+  } // fields
+
+  [1] { // methods
+    { // Member at 0xC1
+      0x0000; // access
+      #5; // name_cpx
+      #6; // sig_cpx
+      [1] { // Attributes
+        Attr(#9, 29) { // Code at 0xC9
+          1; // max_stack
+          1; // max_locals
+          Bytes[5]{
+            0x2AB70001B1;
+          }
+          [0] { // Traps
+          } // end Traps
+          [1] { // Attributes
+            Attr(#10, 6) { // LineNumberTable at 0xE0
+              [1] { // LineNumberTable
+                0  1; //  at 0xEC
+              }
+            } // end LineNumberTable
+          } // Attributes
+        } // end Code
+      } // Attributes
+    } // Member
+  } // methods
+
+  [2] { // Attributes
+    Attr(#11, 2) { // SourceFile at 0xEE
+      #12;
+    } // end SourceFile
+    ;
+    Attr(#13, 6) { // PermittedSubtypes at 0xF6
+      0x0002000F0010;
+    } // end PermittedSubtypes
+  } // Attributes
+} // end class badPermittedAttr
--- a/test/hotspot/jtreg/runtime/sealedTypes/getPermittedSubtypesTest.java	Fri Aug 16 15:05:55 2019 +0000
+++ b/test/hotspot/jtreg/runtime/sealedTypes/getPermittedSubtypesTest.java	Fri Aug 16 16:05:45 2019 +0000
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @compile noLoadSubtypes.jcod
+ * @compile getPermittedSubtypes.jcod
  * @run main getPermittedSubtypesTest
  */
 
@@ -63,7 +63,7 @@
             // Create ArrayList of permitted subtypes class names.
             ArrayList<String> permittedNames = new ArrayList<String>();
             for (int i = 0; i < permitted.length; i++) {
-                permittedNames.add(((ClassDesc)permitted[i]).displayName());
+                permittedNames.add(((ClassDesc)permitted[i]).descriptorString());
             }
 
             if (permittedNames.size() != expected.length) {
@@ -87,21 +87,33 @@
         }
     }
 
-    public static void main(String... args) {
-        testSealedInfo(SealedI1.class, new String[] {"getPermittedSubtypesTest$notSealed",
-                                                     "getPermittedSubtypesTest$Sub1",
-                                                     "getPermittedSubtypesTest$Extender"});
-        testSealedInfo(Sealed1.class, new String[] {"getPermittedSubtypesTest$Sub1"});
+    public static void main(String... args) throws Throwable {
+        testSealedInfo(SealedI1.class, new String[] {"LgetPermittedSubtypesTest$notSealed;",
+                                                     "LgetPermittedSubtypesTest$Sub1;",
+                                                     "LgetPermittedSubtypesTest$Extender;"});
+        testSealedInfo(Sealed1.class, new String[] {"LgetPermittedSubtypesTest$Sub1;"});
         testSealedInfo(noPermits.class, new String[] { });
         testSealedInfo(Final4.class, new String[] { });
         testSealedInfo(notSealed.class, new String[] { });
+
+        // Test class with PermittedSubtypes attribute but old class file version.
+        testSealedInfo(oldClassFile.class, new String[] { });
+
+        // Test class with empty PermittedSubtypes attribute.
+        testSealedInfo(noSubtypes.class, new String[] { });
+
         // Test returning names of non-existing classes.
+        testSealedInfo(noLoadSubtypes.class, new String[]{"LiDontExist;", "LI/Dont/Exist/Either;"});
+
+        // Test that loading a class with a corrupted PermittedSubtypes attribute
+        // causes a ClassFormatError.
         try {
-            testSealedInfo(noLoadSubtypes.class, new String[]{"iDontExist",
-                    "I/Dont/Exist/Either"});
-            throw new AssertionError("should fail");
-        } catch (IllegalArgumentException iae) {
-            // ok
+            Class.forName("badPermittedAttr");
+            throw new RuntimeException("Expected ClasFormatError exception not thrown");
+        } catch (ClassFormatError cfe) {
+            if (!cfe.getMessage().contains("Permitted subtype class_info_index 15 has bad constant type")) {
+                throw new RuntimeException("Unexpected ClassFormatError exception: " + cfe.getMessage());
+            }
         }
     }
 }
--- a/test/hotspot/jtreg/runtime/sealedTypes/noLoadSubtypes.jcod	Fri Aug 16 15:05:55 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,99 +0,0 @@
-/*
- * Copyright (c) 2019, 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.
- */
-
-// This class has PermittedSubtypes that do not exist.  Test that this does
-// not prevent JVM_GetPermittedSubtypes() from returning their names.
-//
-// sealed class noLoadSubtypes permits iDontExist, I/Dont/Exist/Either { }
-//
-class noLoadSubtypes {
-  0xCAFEBABE;
-  0; // minor version
-  58; // version
-  [18] { // Constant Pool
-    ; // first element is empty
-    Method #2 #3; // #1     at 0x0A
-    class #4; // #2     at 0x0F
-    NameAndType #5 #6; // #3     at 0x12
-    Utf8 "java/lang/Object"; // #4     at 0x17
-    Utf8 "<init>"; // #5     at 0x2A
-    Utf8 "()V"; // #6     at 0x33
-    class #8; // #7     at 0x39
-    Utf8 "noLoadSubtypes"; // #8     at 0x3C
-    Utf8 "Code"; // #9     at 0x4D
-    Utf8 "LineNumberTable"; // #10     at 0x54
-    Utf8 "SourceFile"; // #11     at 0x66
-    Utf8 "noLoadSubtypes.java"; // #12     at 0x73
-    Utf8 "PermittedSubtypes"; // #13     at 0x89
-    class #15; // #14     at 0x9D
-    Utf8 "iDontExist"; // #15     at 0xA0
-    class #17; // #16     at 0xAA
-    Utf8 "I/Dont/Exist/Either"; // #17     at 0xAD
-  } // Constant Pool
-
-  0x0030; // access [ ACC_SUPER ACC_FINAL ]
-  #7;// this_cpx
-  #2;// super_cpx
-
-  [0] { // Interfaces
-  } // Interfaces
-
-  [0] { // fields
-  } // fields
-
-  [1] { // methods
-    { // Member at 0xC1
-      0x0000; // access
-      #5; // name_cpx
-      #6; // sig_cpx
-      [1] { // Attributes
-        Attr(#9, 29) { // Code at 0xC9
-          1; // max_stack
-          1; // max_locals
-          Bytes[5]{
-            0x2AB70001B1;
-          }
-          [0] { // Traps
-          } // end Traps
-          [1] { // Attributes
-            Attr(#10, 6) { // LineNumberTable at 0xE0
-              [1] { // LineNumberTable
-                0  1; //  at 0xEC
-              }
-            } // end LineNumberTable
-          } // Attributes
-        } // end Code
-      } // Attributes
-    } // Member
-  } // methods
-
-  [2] { // Attributes
-    Attr(#11, 2) { // SourceFile at 0xEE
-      #12;
-    } // end SourceFile
-    ;
-    Attr(#13, 6) { // PermittedSubtypes at 0xF6
-      0x0002000E0010;
-    } // end PermittedSubtypes
-  } // Attributes
-} // end class noLoadSubtypes