changeset 59543:843695160574

8227046: compiler implementation for sealed classes 8225056: VM support for sealed classes 8227044: javax.lang.model for sealed classes 8227045: Preview APIs support for sealed classes 8227047: Javadoc for sealed types 8245854: JVM TI Specification for sealed classes Reviewed-by: mcimadamore, forax, darcy, dholmes, jlahoda, lfoltan, mchung, sspitsyn, vromero Contributed-by: harold.seigel@oracle.com, vicente.romero@oracle.com, jan.lahoda@oracle.com
author vromero
date Mon, 01 Jun 2020 17:00:40 -0400
parents d36bd2b59c42
children c0e7b94c35bd
files make/autoconf/spec.gmk.in make/data/jdwp/jdwp.spec make/hotspot/symbols/symbols-unix src/hotspot/share/classfile/classFileParser.cpp src/hotspot/share/classfile/classFileParser.hpp src/hotspot/share/classfile/vmSymbols.hpp src/hotspot/share/include/jvm.h src/hotspot/share/logging/logTag.hpp src/hotspot/share/oops/instanceKlass.cpp src/hotspot/share/oops/instanceKlass.hpp src/hotspot/share/prims/jvm.cpp src/hotspot/share/prims/jvmti.xml src/hotspot/share/prims/jvmtiClassFileReconstituter.cpp src/hotspot/share/prims/jvmtiClassFileReconstituter.hpp src/hotspot/share/prims/jvmtiRedefineClasses.cpp src/hotspot/share/prims/jvmtiRedefineClasses.hpp src/java.base/share/classes/java/lang/Class.java src/java.base/share/classes/jdk/internal/PreviewFeature.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassVisitor.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/Constants.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/ClassRemapper.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ClassNode.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/ASMifier.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckClassAdapter.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/Printer.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/Textifier.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceClassVisitor.java src/java.base/share/native/libjava/Class.c src/java.compiler/share/classes/javax/lang/model/SourceVersion.java src/java.compiler/share/classes/javax/lang/model/element/Modifier.java src/java.compiler/share/classes/javax/lang/model/element/TypeElement.java src/java.instrument/share/native/libinstrument/JavaExceptions.c src/jdk.compiler/share/classes/com/sun/source/tree/ClassTree.java src/jdk.compiler/share/classes/com/sun/source/util/TreeScanner.java src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Target.java src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java src/jdk.compiler/share/classes/com/sun/tools/javac/processing/PrintingProcessor.java src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeScanner.java src/jdk.compiler/share/classes/com/sun/tools/javac/util/Dependencies.java src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.java src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/LinkInfoImpl.java src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java src/jdk.jdeps/share/classes/com/sun/tools/classfile/Attribute.java src/jdk.jdeps/share/classes/com/sun/tools/classfile/ClassWriter.java src/jdk.jdeps/share/classes/com/sun/tools/classfile/PermittedSubclasses_attribute.java src/jdk.jdeps/share/classes/com/sun/tools/javap/AttributeWriter.java test/hotspot/jtreg/runtime/modules/SealedModuleTest.java test/hotspot/jtreg/runtime/modules/TEST.properties test/hotspot/jtreg/runtime/modules/sealedP1/C1.java test/hotspot/jtreg/runtime/modules/sealedP1/SuperClass.jcod test/hotspot/jtreg/runtime/modules/sealedP2/C2.java test/hotspot/jtreg/runtime/modules/sealedP3/C3.java test/hotspot/jtreg/runtime/sealedClasses/AbstractSealedTest.java test/hotspot/jtreg/runtime/sealedClasses/GetPermittedSubclasses.jcod test/hotspot/jtreg/runtime/sealedClasses/GetPermittedSubclassesTest.java test/hotspot/jtreg/runtime/sealedClasses/OverrideSealedTest.java test/hotspot/jtreg/runtime/sealedClasses/Pkg/NotPermitted.jcod test/hotspot/jtreg/runtime/sealedClasses/Pkg/Permitted.java test/hotspot/jtreg/runtime/sealedClasses/Pkg/SealedInterface.jcod test/hotspot/jtreg/runtime/sealedClasses/RedefineSealedClass.java test/hotspot/jtreg/runtime/sealedClasses/SealedTest.java test/hotspot/jtreg/runtime/sealedClasses/SealedUnnamedModuleIntfTest.java test/hotspot/jtreg/runtime/sealedClasses/SealedUnnamedModuleTest.java test/hotspot/jtreg/runtime/sealedClasses/TEST.properties test/hotspot/jtreg/runtime/sealedClasses/asteroids/Pluto.java test/hotspot/jtreg/runtime/sealedClasses/otherPkg/WrongPackage.java test/hotspot/jtreg/runtime/sealedClasses/planets/Mars.jcod test/hotspot/jtreg/runtime/sealedClasses/planets/Neptune.java test/hotspot/jtreg/runtime/sealedClasses/planets/OuterPlanets.jcod test/jdk/java/lang/instrument/RedefinePermittedSubclassesAttr/ClassFour.java test/jdk/java/lang/instrument/RedefinePermittedSubclassesAttr/ClassOne.java test/jdk/java/lang/instrument/RedefinePermittedSubclassesAttr/ClassThree.java test/jdk/java/lang/instrument/RedefinePermittedSubclassesAttr/ClassTwo.java test/jdk/java/lang/instrument/RedefinePermittedSubclassesAttr/Host/Host.java test/jdk/java/lang/instrument/RedefinePermittedSubclassesAttr/Host/redef/Host.java test/jdk/java/lang/instrument/RedefinePermittedSubclassesAttr/HostA/Host.java test/jdk/java/lang/instrument/RedefinePermittedSubclassesAttr/HostA/redef/Host.java test/jdk/java/lang/instrument/RedefinePermittedSubclassesAttr/HostAB/Host.java test/jdk/java/lang/instrument/RedefinePermittedSubclassesAttr/HostAB/redef/Host.java test/jdk/java/lang/instrument/RedefinePermittedSubclassesAttr/HostABC/Host.java test/jdk/java/lang/instrument/RedefinePermittedSubclassesAttr/HostABC/redef/Host.java test/jdk/java/lang/instrument/RedefinePermittedSubclassesAttr/HostABCD/redef/Host.java test/jdk/java/lang/instrument/RedefinePermittedSubclassesAttr/HostABD/redef/Host.java test/jdk/java/lang/instrument/RedefinePermittedSubclassesAttr/HostAC/redef/Host.java test/jdk/java/lang/instrument/RedefinePermittedSubclassesAttr/HostACB/redef/Host.java test/jdk/java/lang/instrument/RedefinePermittedSubclassesAttr/HostB/redef/Host.java test/jdk/java/lang/instrument/RedefinePermittedSubclassesAttr/HostBA/redef/Host.java test/jdk/java/lang/instrument/RedefinePermittedSubclassesAttr/HostBAC/redef/Host.java test/jdk/java/lang/instrument/RedefinePermittedSubclassesAttr/HostBCA/redef/Host.java test/jdk/java/lang/instrument/RedefinePermittedSubclassesAttr/HostCAB/redef/Host.java test/jdk/java/lang/instrument/RedefinePermittedSubclassesAttr/HostCBA/redef/Host.java test/jdk/java/lang/instrument/RedefinePermittedSubclassesAttr/TestPermittedSubclassesAttr.java test/jdk/java/lang/reflect/sealed_classes/SealedClassesReflectionTest.java test/langtools/jdk/javadoc/doclet/testSealedTypes/TestSealedTypes.java test/langtools/lib/annotations/annotations/classfile/ClassfileInspector.java test/langtools/tools/javac/MethodParameters/AttributeVisitor.java test/langtools/tools/javac/diags/examples/CantInheritFromSealed.java test/langtools/tools/javac/diags/examples/CantInheritFromSealed2.java test/langtools/tools/javac/diags/examples/DuplicateTypeInPermits.java test/langtools/tools/javac/diags/examples/LocalCantInheritFromSealed.java test/langtools/tools/javac/diags/examples/NonSealedWithNoSealedSuper.java test/langtools/tools/javac/diags/examples/PermitsCantListDeclaringClass.java test/langtools/tools/javac/diags/examples/PermitsCantListSuperType.java test/langtools/tools/javac/diags/examples/PermitsInNoSealedClass.java test/langtools/tools/javac/diags/examples/SealedMustHaveSubtypes.java test/langtools/tools/javac/diags/examples/SealedNotAllowedInLocalClass.java test/langtools/tools/javac/diags/examples/SealedTypes.java test/langtools/tools/javac/diags/examples/SubtypeDoesntExtendSealed.java test/langtools/tools/javac/diags/examples/TypeVarInPermits.java test/langtools/tools/javac/enum/FauxEnum3.java test/langtools/tools/javac/enum/FauxEnum3.out test/langtools/tools/javac/enum/FauxEnum3.preview.out test/langtools/tools/javac/parser/JavacParserTest.java test/langtools/tools/javac/processing/model/TestSourceVersion.java test/langtools/tools/javac/processing/model/element/TestSealed.java test/langtools/tools/javac/sealed/CheckSubtypesOfSealedTest.java test/langtools/tools/javac/sealed/SealedCompilationTests.java test/langtools/tools/javac/sealed/SealedDiffConfigurationsTest.java
diffstat 139 files changed, 6877 insertions(+), 192 deletions(-) [+]
line wrap: on
line diff
--- a/make/autoconf/spec.gmk.in	Mon Jun 01 22:55:22 2020 +0200
+++ b/make/autoconf/spec.gmk.in	Mon Jun 01 17:00:40 2020 -0400
@@ -650,6 +650,7 @@
     --add-exports java.base/sun.reflect.annotation=jdk.compiler.interim \
     --add-exports java.base/jdk.internal.jmod=jdk.compiler.interim \
     --add-exports java.base/jdk.internal.misc=jdk.compiler.interim \
+    --add-exports java.base/sun.invoke.util=jdk.compiler.interim \
     #
 INTERIM_LANGTOOLS_MODULES_COMMA := $(strip $(subst $(SPACE),$(COMMA),$(strip \
     $(INTERIM_LANGTOOLS_MODULES))))
--- a/make/data/jdwp/jdwp.spec	Mon Jun 01 22:55:22 2020 +0200
+++ b/make/data/jdwp/jdwp.spec	Mon Jun 01 17:00:40 2020 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2020, 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
@@ -3160,8 +3160,8 @@
                                           "canUnrestrictedlyRedefineClasses is false.")
     (Constant CLASS_ATTRIBUTE_CHANGE_NOT_IMPLEMENTED
                                      =72  "The new class version has a different NestHost, "
-                                          "NestMembers, or Record class attribute and "
-                                          "canUnrestrictedlyRedefineClasses is false.")
+                                          "NestMembers, PermittedSubclasses, or Record class attribute "
+                                          "and canUnrestrictedlyRedefineClasses is false.")
     (Constant NOT_IMPLEMENTED        =99  "The functionality is not implemented in "
                                           "this virtual machine.")
     (Constant NULL_POINTER           =100 "Invalid pointer.")
--- a/make/hotspot/symbols/symbols-unix	Mon Jun 01 22:55:22 2020 +0200
+++ b/make/hotspot/symbols/symbols-unix	Mon Jun 01 17:00:40 2020 -0400
@@ -119,6 +119,7 @@
 JVM_GetNanoTimeAdjustment
 JVM_GetNestHost
 JVM_GetNestMembers
+JVM_GetPermittedSubclasses
 JVM_GetPrimitiveArrayElement
 JVM_GetProperties
 JVM_GetProtectionDomain
--- a/src/hotspot/share/classfile/classFileParser.cpp	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/hotspot/share/classfile/classFileParser.cpp	Mon Jun 01 17:00:40 2020 -0400
@@ -3212,6 +3212,41 @@
   return length;
 }
 
+u2 ClassFileParser::parse_classfile_permitted_subclasses_attribute(const ClassFileStream* const cfs,
+                                                                   const u1* const permitted_subclasses_attribute_start,
+                                                                   TRAPS) {
+  const u1* const current_mark = cfs->current();
+  u2 length = 0;
+  if (permitted_subclasses_attribute_start != NULL) {
+    cfs->set_current(permitted_subclasses_attribute_start);
+    cfs->guarantee_more(2, CHECK_0);  // length
+    length = cfs->get_u2_fast();
+  }
+  if (length < 1) {
+    classfile_parse_error("PermittedSubclasses attribute is empty in class file %s", CHECK_0);
+  }
+  const int size = length;
+  Array<u2>* const permitted_subclasses = MetadataFactory::new_array<u2>(_loader_data, size, CHECK_0);
+  _permitted_subclasses = permitted_subclasses;
+
+  int index = 0;
+  cfs->guarantee_more(2 * length, CHECK_0);
+  for (int n = 0; n < length; n++) {
+    const u2 class_info_index = cfs->get_u2_fast();
+    check_property(
+      valid_klass_reference_at(class_info_index),
+      "Permitted subclass class_info_index %u has bad constant type in class file %s",
+      class_info_index, CHECK_0);
+    permitted_subclasses->at_put(index++, class_info_index);
+  }
+  assert(index == size, "wrong size");
+
+  // Restore buffer's current position.
+  cfs->set_current(current_mark);
+
+  return length;
+}
+
 //  Record {
 //    u2 attribute_name_index;
 //    u4 attribute_length;
@@ -3476,10 +3511,16 @@
                      CHECK);
 }
 
+bool ClassFileParser::supports_sealed_types() {
+  return _major_version == JVM_CLASSFILE_MAJOR_VERSION &&
+         _minor_version == JAVA_PREVIEW_MINOR_VERSION &&
+         Arguments::enable_preview();
+}
+
 bool ClassFileParser::supports_records() {
   return _major_version == JVM_CLASSFILE_MAJOR_VERSION &&
-    _minor_version == JAVA_PREVIEW_MINOR_VERSION &&
-    Arguments::enable_preview();
+         _minor_version == JAVA_PREVIEW_MINOR_VERSION &&
+         Arguments::enable_preview();
 }
 
 void ClassFileParser::parse_classfile_attributes(const ClassFileStream* const cfs,
@@ -3494,11 +3535,14 @@
   _inner_classes = Universe::the_empty_short_array();
   // Set nest members attribute to default sentinel
   _nest_members = Universe::the_empty_short_array();
+  // Set _permitted_subclasses attribute to default sentinel
+  _permitted_subclasses = Universe::the_empty_short_array();
   cfs->guarantee_more(2, CHECK);  // attributes_count
   u2 attributes_count = cfs->get_u2_fast();
   bool parsed_sourcefile_attribute = false;
   bool parsed_innerclasses_attribute = false;
   bool parsed_nest_members_attribute = false;
+  bool parsed_permitted_subclasses_attribute = false;
   bool parsed_nest_host_attribute = false;
   bool parsed_record_attribute = false;
   bool parsed_enclosingmethod_attribute = false;
@@ -3522,6 +3566,8 @@
   u4  nest_members_attribute_length = 0;
   const u1* record_attribute_start = NULL;
   u4  record_attribute_length = 0;
+  const u1* permitted_subclasses_attribute_start = NULL;
+  u4  permitted_subclasses_attribute_length = 0;
 
   // Iterate over attributes
   while (attributes_count--) {
@@ -3738,6 +3784,26 @@
               }
             }
             cfs->skip_u1(attribute_length, CHECK);
+          } else if (_major_version >= JAVA_15_VERSION) {
+            // Check for PermittedSubclasses tag
+            if (tag == vmSymbols::tag_permitted_subclasses()) {
+              if (supports_sealed_types()) {
+                if (parsed_permitted_subclasses_attribute) {
+                  classfile_parse_error("Multiple PermittedSubclasses attributes in class file %s", CHECK);
+                }
+                // Classes marked ACC_FINAL cannot have a PermittedSubclasses attribute.
+                if (_access_flags.is_final()) {
+                  classfile_parse_error("PermittedSubclasses attribute in final class file %s", CHECK);
+                }
+                parsed_permitted_subclasses_attribute = true;
+                permitted_subclasses_attribute_start = cfs->current();
+                permitted_subclasses_attribute_length = attribute_length;
+              }
+              cfs->skip_u1(attribute_length, CHECK);
+            } else {
+              // Unknown attribute
+              cfs->skip_u1(attribute_length, CHECK);
+            }
           } else {
             // Unknown attribute
             cfs->skip_u1(attribute_length, CHECK);
@@ -3806,6 +3872,18 @@
     }
   }
 
+  if (parsed_permitted_subclasses_attribute) {
+    const u2 num_subclasses = parse_classfile_permitted_subclasses_attribute(
+                            cfs,
+                            permitted_subclasses_attribute_start,
+                            CHECK);
+    if (_need_verify) {
+      guarantee_property(
+        permitted_subclasses_attribute_length == sizeof(num_subclasses) + sizeof(u2) * num_subclasses,
+        "Wrong PermittedSubclasses attribute length in class file %s", CHECK);
+    }
+  }
+
   if (_max_bootstrap_specifier_index >= 0) {
     guarantee_property(parsed_bootstrap_methods_attribute,
                        "Missing BootstrapMethods attribute in class file %s", CHECK);
@@ -3873,6 +3951,7 @@
   this_klass->set_nest_host_index(_nest_host);
   this_klass->set_local_interfaces(_local_interfaces);
   this_klass->set_annotations(_combined_annotations);
+  this_klass->set_permitted_subclasses(_permitted_subclasses);
   this_klass->set_record_components(_record_components);
   // Delay the setting of _transitive_interfaces until after initialize_supers() in
   // fill_instance_klass(). It is because the _transitive_interfaces may be shared with
@@ -4681,12 +4760,34 @@
   const Klass* const super = this_klass->super();
 
   if (super != NULL) {
+    const InstanceKlass* super_ik = InstanceKlass::cast(super);
+
+    if (super->is_final()) {
+      ResourceMark rm(THREAD);
+      Exceptions::fthrow(
+        THREAD_AND_LOCATION,
+        vmSymbols::java_lang_VerifyError(),
+        "class %s cannot inherit from final class %s",
+        this_klass->external_name(),
+        super_ik->external_name());
+      return;
+    }
+
+    if (super_ik->is_sealed() && !super_ik->has_as_permitted_subclass(this_klass)) {
+      ResourceMark rm(THREAD);
+      Exceptions::fthrow(
+        THREAD_AND_LOCATION,
+        vmSymbols::java_lang_IncompatibleClassChangeError(),
+        "class %s cannot inherit from sealed class %s",
+        this_klass->external_name(),
+        super_ik->external_name());
+      return;
+    }
 
     // If the loader is not the boot loader then throw an exception if its
     // superclass is in package jdk.internal.reflect and its loader is not a
     // special reflection class loader
     if (!this_klass->class_loader_data()->is_the_null_class_loader_data()) {
-      assert(super->is_instance_klass(), "super is not instance klass");
       PackageEntry* super_package = super->package();
       if (super_package != NULL &&
           super_package->name()->fast_compare(vmSymbols::jdk_internal_reflect()) == 0 &&
@@ -4742,6 +4843,19 @@
   for (int i = lng - 1; i >= 0; i--) {
     InstanceKlass* const k = local_interfaces->at(i);
     assert (k != NULL && k->is_interface(), "invalid interface");
+
+    if (k->is_sealed() && !k->has_as_permitted_subclass(this_klass)) {
+      ResourceMark rm(THREAD);
+      Exceptions::fthrow(
+        THREAD_AND_LOCATION,
+        vmSymbols::java_lang_IncompatibleClassChangeError(),
+        "class %s cannot %s sealed interface %s",
+        this_klass->external_name(),
+        this_klass->is_interface() ? "extend" : "implement",
+        k->external_name());
+      return;
+    }
+
     Reflection::VerifyClassAccessResults vca_result =
       Reflection::verify_class_access(this_klass, k, false);
     if (vca_result != Reflection::ACCESS_OK) {
@@ -5677,6 +5791,7 @@
   assert(NULL == _local_interfaces, "invariant");
   assert(NULL == _combined_annotations, "invariant");
   assert(NULL == _record_components, "invariant");
+  assert(NULL == _permitted_subclasses, "invariant");
 
   if (_has_final_method) {
     ik->set_has_final_method();
@@ -5965,6 +6080,7 @@
   _inner_classes(NULL),
   _nest_members(NULL),
   _nest_host(0),
+  _permitted_subclasses(NULL),
   _record_components(NULL),
   _local_interfaces(NULL),
   _transitive_interfaces(NULL),
@@ -6073,6 +6189,7 @@
   _methods = NULL;
   _inner_classes = NULL;
   _nest_members = NULL;
+  _permitted_subclasses = NULL;
   _local_interfaces = NULL;
   _combined_annotations = NULL;
   _class_annotations = _class_type_annotations = NULL;
@@ -6109,6 +6226,10 @@
     InstanceKlass::deallocate_record_components(_loader_data, _record_components);
   }
 
+  if (_permitted_subclasses != NULL && _permitted_subclasses != Universe::the_empty_short_array()) {
+    MetadataFactory::free_array<u2>(_loader_data, _permitted_subclasses);
+  }
+
   // Free interfaces
   InstanceKlass::deallocate_interfaces(_loader_data, _super_klass,
                                        _local_interfaces, _transitive_interfaces);
@@ -6507,10 +6628,6 @@
       );
       return;
     }
-    // Make sure super class is not final
-    if (_super_klass->is_final()) {
-      THROW_MSG(vmSymbols::java_lang_VerifyError(), "Cannot inherit from final class");
-    }
   }
 
   // Compute the transitive list of all unique interfaces implemented by this class
--- a/src/hotspot/share/classfile/classFileParser.hpp	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/hotspot/share/classfile/classFileParser.hpp	Mon Jun 01 17:00:40 2020 -0400
@@ -132,6 +132,7 @@
   Array<u2>* _inner_classes;
   Array<u2>* _nest_members;
   u2 _nest_host;
+  Array<u2>* _permitted_subclasses;
   Array<RecordComponent*>* _record_components;
   Array<InstanceKlass*>* _local_interfaces;
   Array<InstanceKlass*>* _transitive_interfaces;
@@ -327,11 +328,16 @@
                                             const u1* const nest_members_attribute_start,
                                             TRAPS);
 
+  u2 parse_classfile_permitted_subclasses_attribute(const ClassFileStream* const cfs,
+                                                    const u1* const permitted_subclasses_attribute_start,
+                                                    TRAPS);
+
   u2 parse_classfile_record_attribute(const ClassFileStream* const cfs,
                                       const ConstantPool* cp,
                                       const u1* const record_attribute_start,
                                       TRAPS);
 
+  bool supports_sealed_types();
   bool supports_records();
 
   void parse_classfile_attributes(const ClassFileStream* const cfs,
--- a/src/hotspot/share/classfile/vmSymbols.hpp	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/hotspot/share/classfile/vmSymbols.hpp	Mon Jun 01 17:00:40 2020 -0400
@@ -173,6 +173,7 @@
   template(tag_runtime_invisible_type_annotations,    "RuntimeInvisibleTypeAnnotations")          \
   template(tag_enclosing_method,                      "EnclosingMethod")                          \
   template(tag_bootstrap_methods,                     "BootstrapMethods")                         \
+  template(tag_permitted_subclasses,                  "PermittedSubclasses")                      \
                                                                                                   \
   /* exception klasses: at least all exceptions thrown by the VM have entries here */             \
   template(java_lang_ArithmeticException,             "java/lang/ArithmeticException")            \
--- a/src/hotspot/share/include/jvm.h	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/hotspot/share/include/jvm.h	Mon Jun 01 17:00:40 2020 -0400
@@ -567,6 +567,11 @@
 JNIEXPORT jobjectArray JNICALL
 JVM_GetRecordComponents(JNIEnv *env, jclass ofClass);
 
+/* Sealed types - since JDK 15 */
+
+JNIEXPORT jobjectArray JNICALL
+JVM_GetPermittedSubclasses(JNIEnv *env, jclass current);
+
 /* The following two reflection routines are still needed due to startup time issues */
 /*
  * java.lang.reflect.Method
--- a/src/hotspot/share/logging/logTag.hpp	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/hotspot/share/logging/logTag.hpp	Mon Jun 01 17:00:40 2020 -0400
@@ -147,6 +147,7 @@
   LOG_TAG(safepoint) \
   LOG_TAG(sampling) \
   LOG_TAG(scavenge) \
+  LOG_TAG(sealed) \
   LOG_TAG(setting) \
   LOG_TAG(smr) \
   LOG_TAG(stacktrace) \
--- a/src/hotspot/share/oops/instanceKlass.cpp	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/hotspot/share/oops/instanceKlass.cpp	Mon Jun 01 17:00:40 2020 -0400
@@ -218,6 +218,57 @@
   return false;
 }
 
+// Called to verify that k is a permitted subclass of this class
+bool InstanceKlass::has_as_permitted_subclass(const InstanceKlass* k) const {
+  Thread* THREAD = Thread::current();
+  assert(k != NULL, "sanity check");
+  assert(_permitted_subclasses != NULL && _permitted_subclasses != Universe::the_empty_short_array(),
+         "unexpected empty _permitted_subclasses array");
+
+  if (log_is_enabled(Trace, class, sealed)) {
+    ResourceMark rm(THREAD);
+    log_trace(class, sealed)("Checking for permitted subclass of %s in %s",
+                             k->external_name(), this->external_name());
+  }
+
+  // Check that the class and its super are in the same module.
+  if (k->module() != this->module()) {
+    ResourceMark rm(THREAD);
+    log_trace(class, sealed)("Check failed for same module of permitted subclass %s and sealed class %s",
+                             k->external_name(), this->external_name());
+    return false;
+  }
+
+  if (!k->is_public() && !is_same_class_package(k)) {
+    ResourceMark rm(THREAD);
+    log_trace(class, sealed)("Check failed, subclass %s not public and not in the same package as sealed class %s",
+                             k->external_name(), this->external_name());
+    return false;
+  }
+
+  // Check for a resolved cp entry, else fall back to a name check.
+  // We don't want to resolve any class other than the one being checked.
+  for (int i = 0; i < _permitted_subclasses->length(); i++) {
+    int cp_index = _permitted_subclasses->at(i);
+    if (_constants->tag_at(cp_index).is_klass()) {
+      Klass* k2 = _constants->klass_at(cp_index, THREAD);
+      assert(!HAS_PENDING_EXCEPTION, "Unexpected exception");
+      if (k2 == k) {
+        log_trace(class, sealed)("- class is listed at permitted_subclasses[%d] => cp[%d]", i, cp_index);
+        return true;
+      }
+    } else {
+      Symbol* name = _constants->klass_name_at(cp_index);
+      if (name == k->name()) {
+        log_trace(class, sealed)("- Found it at permitted_subclasses[%d] => cp[%d]", i, cp_index);
+        return true;
+      }
+    }
+  }
+  log_trace(class, sealed)("- class is NOT a permitted subclass!");
+  return false;
+}
+
 // Return nest-host class, resolving, validating and saving it if needed.
 // In cases where this is called from a thread that cannot do classloading
 // (such as a native JIT thread) then we simply return NULL, which in turn
@@ -484,6 +535,7 @@
   Klass(id),
   _nest_members(NULL),
   _nest_host(NULL),
+  _permitted_subclasses(NULL),
   _record_components(NULL),
   _static_field_size(parser.static_field_size()),
   _nonstatic_oop_map_size(nonstatic_oop_map_size(parser.total_oop_map_count())),
@@ -665,6 +717,13 @@
   }
   set_nest_members(NULL);
 
+  if (permitted_subclasses() != NULL &&
+      permitted_subclasses() != Universe::the_empty_short_array() &&
+      !permitted_subclasses()->is_shared()) {
+    MetadataFactory::free_array<jushort>(loader_data, permitted_subclasses());
+  }
+  set_permitted_subclasses(NULL);
+
   // We should deallocate the Annotations instance if it's not in shared spaces.
   if (annotations() != NULL && !annotations()->is_shared()) {
     MetadataFactory::free_metadata(loader_data, annotations());
@@ -676,6 +735,12 @@
   }
 }
 
+bool InstanceKlass::is_sealed() const {
+  return _permitted_subclasses != NULL &&
+         _permitted_subclasses != Universe::the_empty_short_array() &&
+         _permitted_subclasses->length() > 0;
+}
+
 bool InstanceKlass::should_be_initialized() const {
   return !is_initialized();
 }
@@ -2414,6 +2479,7 @@
   }
 
   it->push(&_nest_members);
+  it->push(&_permitted_subclasses);
   it->push(&_record_components);
 }
 
@@ -3342,6 +3408,7 @@
   if (record_components() != NULL) {
     st->print(BULLET"record components:     "); record_components()->print_value_on(st);     st->cr();
   }
+  st->print(BULLET"permitted subclasses:     "); permitted_subclasses()->print_value_on(st);     st->cr();
   if (java_mirror() != NULL) {
     st->print(BULLET"java mirror:       ");
     java_mirror()->print_value_on(st);
--- a/src/hotspot/share/oops/instanceKlass.hpp	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/hotspot/share/oops/instanceKlass.hpp	Mon Jun 01 17:00:40 2020 -0400
@@ -198,6 +198,10 @@
   // By always being set it makes nest-member access checks simpler.
   InstanceKlass* _nest_host;
 
+  // The PermittedSubclasses attribute. An array of shorts, where each is a
+  // class info index for the class that is a permitted subclass.
+  Array<jushort>* _permitted_subclasses;
+
   // The contents of the Record attribute.
   Array<RecordComponent*>* _record_components;
 
@@ -469,6 +473,10 @@
   }
   bool is_record() const { return _record_components != NULL; }
 
+  // permitted subclasses
+  Array<u2>* permitted_subclasses() const     { return _permitted_subclasses; }
+  void set_permitted_subclasses(Array<u2>* s) { _permitted_subclasses = s; }
+
 private:
   // Called to verify that k is a member of this nest - does not look at k's nest-host
   bool has_nest_member(InstanceKlass* k, TRAPS) const;
@@ -484,6 +492,9 @@
   // Check if this klass is a nestmate of k - resolves this nest-host and k's
   bool has_nestmate_access_to(InstanceKlass* k, TRAPS);
 
+  // Called to verify that k is a permitted subclass of this class
+  bool has_as_permitted_subclass(const InstanceKlass* k) const;
+
   enum InnerClassAttributeOffset {
     // From http://mirror.eng/products/jdk/1.1/docs/guide/innerclasses/spec/innerclasses.doc10.html#18814
     inner_class_inner_class_info_offset = 0,
@@ -541,6 +552,9 @@
   ClassState  init_state()                 { return (ClassState)_init_state; }
   bool is_rewritten() const                { return (_misc_flags & _misc_rewritten) != 0; }
 
+  // is this a sealed class
+  bool is_sealed() const;
+
   // defineClass specified verification
   bool should_verify_class() const         {
     return (_misc_flags & _misc_should_verify_class) != 0;
--- a/src/hotspot/share/prims/jvm.cpp	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/hotspot/share/prims/jvm.cpp	Mon Jun 01 17:00:40 2020 -0400
@@ -2101,6 +2101,33 @@
 }
 JVM_END
 
+JVM_ENTRY(jobjectArray, JVM_GetPermittedSubclasses(JNIEnv* env, jclass current))
+{
+  JVMWrapper("JVM_GetPermittedSubclasses");
+  assert(!java_lang_Class::is_primitive(JNIHandles::resolve_non_null(current)), "should not be");
+  Klass* c = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(current));
+  assert(c->is_instance_klass(), "must be");
+  InstanceKlass* ik = InstanceKlass::cast(c);
+  {
+    JvmtiVMObjectAllocEventCollector oam;
+    Array<u2>* subclasses = ik->permitted_subclasses();
+    int length = subclasses == NULL ? 0 : subclasses->length();
+    objArrayOop r = oopFactory::new_objArray(SystemDictionary::String_klass(),
+                                             length, CHECK_NULL);
+    objArrayHandle result(THREAD, r);
+    for (int i = 0; i < length; i++) {
+      int cp_index = subclasses->at(i);
+      // This returns <package-name>/<class-name>.
+      Symbol* klass_name = ik->constants()->klass_name_at(cp_index);
+      assert(klass_name != NULL, "Unexpected null klass_name");
+      Handle perm_subtype_h = java_lang_String::create_from_symbol(klass_name, CHECK_NULL);
+      result->obj_at_put(i, perm_subtype_h());
+    }
+    return (jobjectArray)JNIHandles::make_local(THREAD, result());
+  }
+}
+JVM_END
+
 // Constant pool access //////////////////////////////////////////////////////////
 
 JVM_ENTRY(jobject, JVM_GetClassConstantPool(JNIEnv *env, jclass cls))
--- a/src/hotspot/share/prims/jvmti.xml	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/hotspot/share/prims/jvmti.xml	Mon Jun 01 17:00:40 2020 -0400
@@ -6900,7 +6900,7 @@
       <synopsis>Get Classloader Classes</synopsis>
       <description>
         Returns an array of all classes which this class loader
-        can find by name via 
+        can find by name via
         <externallink id="../api/java.base/java/lang/ClassLoader.html#loadClass(java.lang.String,boolean)">ClassLoader::loadClass</externallink>,
         <externallink id="../api/java.base/java/lang/Class.html#forName(java.lang.String,boolean,java.lang.ClassLoader)">Class::forName</externallink> and bytecode linkage.
         That is, all classes for which <code>initiating_loader</code>
@@ -7680,7 +7680,8 @@
         The retransformation must not add, remove or rename fields or methods, change the
         signatures of methods, change modifiers, or change inheritance.
         The retransformation must not change the <code>NestHost</code>,
-        <code>NestMembers</code>, or <code>Record</code> attributes.
+        <code>NestMembers</code>, <code>Record</code>, or <code>PermittedSubclasses</code>
+        attributes.
         These restrictions may be lifted in future versions.
         See the error return description below for information on error codes
         returned if an unsupported retransformation is attempted.
@@ -7833,7 +7834,8 @@
         The redefinition must not add, remove or rename fields or methods, change the
         signatures of methods, change modifiers, or change inheritance.
         The redefinition must not change the <code>NestHost</code>,
-        <code>NestMembers</code>, or <code>Record</code> attributes.
+        <code>NestMembers</code>, <code>Record</code>, or <code>PermittedSubclasses</code>
+        attributes.
         These restrictions may be lifted in future versions.
         See the error return description below for information on error codes
         returned if an unsupported redefinition is attempted.
@@ -15028,6 +15030,11 @@
         - Specify that RedefineClasses and RetransformClasses are not allowed
           to change the class file Record attribute.
   </change>
+  <change date="13 May 2020" version="15.0.0">
+      Minor update for new class file PermittedSubclasses attribute:
+        - Specify that RedefineClasses and RetransformClasses are not allowed
+          to change the class file PermittedSubclasses attribute.
+  </change>
 </changehistory>
 
 </specification>
--- a/src/hotspot/share/prims/jvmtiClassFileReconstituter.cpp	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/hotspot/share/prims/jvmtiClassFileReconstituter.cpp	Mon Jun 01 17:00:40 2020 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2020, 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
@@ -424,6 +424,26 @@
   }
 }
 
+//  PermittedSubclasses {
+//    u2 attribute_name_index;
+//    u4 attribute_length;
+//    u2 number_of_classes;
+//    u2 classes[number_of_classes];
+//  }
+void JvmtiClassFileReconstituter::write_permitted_subclasses_attribute() {
+  Array<u2>* permitted_subclasses = ik()->permitted_subclasses();
+  int number_of_classes = permitted_subclasses->length();
+  int length = sizeof(u2) * (1 + number_of_classes); // '1 +' is for number_of_classes field
+
+  write_attribute_name_index("PermittedSubclasses");
+  write_u4(length);
+  write_u2(number_of_classes);
+  for (int i = 0; i < number_of_classes; i++) {
+    u2 class_cp_index = permitted_subclasses->at(i);
+    write_u2(class_cp_index);
+  }
+}
+
 //  Record {
 //    u2 attribute_name_index;
 //    u4 attribute_length;
@@ -751,6 +771,9 @@
   if (ik()->nest_members() != Universe::the_empty_short_array()) {
     ++attr_count;
   }
+  if (ik()->permitted_subclasses() != Universe::the_empty_short_array()) {
+    ++attr_count;
+  }
   if (ik()->record_components() != NULL) {
     ++attr_count;
   }
@@ -784,6 +807,9 @@
   if (ik()->nest_members() != Universe::the_empty_short_array()) {
     write_nest_members_attribute();
   }
+  if (ik()->permitted_subclasses() != Universe::the_empty_short_array()) {
+    write_permitted_subclasses_attribute();
+  }
   if (ik()->record_components() != NULL) {
     write_record_attribute();
   }
--- a/src/hotspot/share/prims/jvmtiClassFileReconstituter.hpp	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/hotspot/share/prims/jvmtiClassFileReconstituter.hpp	Mon Jun 01 17:00:40 2020 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2020, 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
@@ -118,6 +118,7 @@
   void write_bootstrapmethod_attribute();
   void write_nest_host_attribute();
   void write_nest_members_attribute();
+  void write_permitted_subclasses_attribute();
   void write_record_attribute();
 
   address writeable_address(size_t size);
--- a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp	Mon Jun 01 17:00:40 2020 -0400
@@ -854,6 +854,65 @@
 }
 
 
+static jvmtiError check_permitted_subclasses_attribute(InstanceKlass* the_class,
+                                                       InstanceKlass* scratch_class) {
+  // Check whether the class PermittedSubclasses attribute has been changed.
+  Thread* thread = Thread::current();
+  ResourceMark rm(thread);
+  Array<u2>* the_permitted_subclasses = the_class->permitted_subclasses();
+  Array<u2>* scr_permitted_subclasses = scratch_class->permitted_subclasses();
+  bool the_subclasses_exist = the_permitted_subclasses != Universe::the_empty_short_array();
+  bool scr_subclasses_exist = scr_permitted_subclasses != Universe::the_empty_short_array();
+  int subclasses_len = the_permitted_subclasses->length();
+  if (the_subclasses_exist && scr_subclasses_exist) {
+    if (subclasses_len != scr_permitted_subclasses->length()) {
+      log_trace(redefine, class, sealed)
+        ("redefined class %s attribute change error: PermittedSubclasses len=%d changed to len=%d",
+         the_class->external_name(), subclasses_len, scr_permitted_subclasses->length());
+      return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_ATTRIBUTE_CHANGED;
+    }
+
+    // The order of entries in the PermittedSubclasses array is not specified so
+    // we have to explicitly check for the same contents. We do this by copying
+    // the referenced symbols into their own arrays, sorting them and then
+    // comparing each element pair.
+
+    Symbol** the_syms = NEW_RESOURCE_ARRAY_RETURN_NULL(Symbol*, subclasses_len);
+    Symbol** scr_syms = NEW_RESOURCE_ARRAY_RETURN_NULL(Symbol*, subclasses_len);
+
+    if (the_syms == NULL || scr_syms == NULL) {
+      return JVMTI_ERROR_OUT_OF_MEMORY;
+    }
+
+    for (int i = 0; i < subclasses_len; i++) {
+      int the_cp_index = the_permitted_subclasses->at(i);
+      int scr_cp_index = scr_permitted_subclasses->at(i);
+      the_syms[i] = the_class->constants()->klass_name_at(the_cp_index);
+      scr_syms[i] = scratch_class->constants()->klass_name_at(scr_cp_index);
+    }
+
+    qsort(the_syms, subclasses_len, sizeof(Symbol*), symcmp);
+    qsort(scr_syms, subclasses_len, sizeof(Symbol*), symcmp);
+
+    for (int i = 0; i < subclasses_len; i++) {
+      if (the_syms[i] != scr_syms[i]) {
+        log_trace(redefine, class, sealed)
+          ("redefined class %s attribute change error: PermittedSubclasses[%d]: %s changed to %s",
+           the_class->external_name(), i, the_syms[i]->as_C_string(), scr_syms[i]->as_C_string());
+        return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_ATTRIBUTE_CHANGED;
+      }
+    }
+  } else if (the_subclasses_exist ^ scr_subclasses_exist) {
+    const char* action_str = (the_subclasses_exist) ? "removed" : "added";
+    log_trace(redefine, class, sealed)
+      ("redefined class %s attribute change error: PermittedSubclasses attribute %s",
+       the_class->external_name(), action_str);
+    return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_ATTRIBUTE_CHANGED;
+  }
+
+  return JVMTI_ERROR_NONE;
+}
+
 static bool can_add_or_delete(Method* m) {
       // Compatibility mode
   return (AllowRedefinitionToAddDeleteMethods &&
@@ -913,6 +972,12 @@
     return err;
   }
 
+  // Check whether the PermittedSubclasses attribute has been changed.
+  err = check_permitted_subclasses_attribute(the_class, scratch_class);
+  if (err != JVMTI_ERROR_NONE) {
+    return err;
+  }
+
   // Check whether class modifiers are the same.
   jushort old_flags = (jushort) the_class->access_flags().get_flags();
   jushort new_flags = (jushort) scratch_class->access_flags().get_flags();
@@ -1792,6 +1857,12 @@
     return false;
   }
 
+  // rewrite constant pool references in the PermittedSubclasses attribute:
+  if (!rewrite_cp_refs_in_permitted_subclasses_attribute(scratch_class)) {
+    // propagate failure back to caller
+    return false;
+  }
+
   // rewrite constant pool references in the methods:
   if (!rewrite_cp_refs_in_methods(scratch_class, THREAD)) {
     // propagate failure back to caller
@@ -1930,6 +2001,19 @@
   return true;
 }
 
+// Rewrite constant pool references in the PermittedSubclasses attribute.
+bool VM_RedefineClasses::rewrite_cp_refs_in_permitted_subclasses_attribute(
+       InstanceKlass* scratch_class) {
+
+  Array<u2>* permitted_subclasses = scratch_class->permitted_subclasses();
+  assert(permitted_subclasses != NULL, "unexpected null permitted_subclasses");
+  for (int i = 0; i < permitted_subclasses->length(); i++) {
+    u2 cp_index = permitted_subclasses->at(i);
+    permitted_subclasses->at_put(i, find_new_index(cp_index));
+  }
+  return true;
+}
+
 // Rewrite constant pool references in the methods.
 bool VM_RedefineClasses::rewrite_cp_refs_in_methods(
        InstanceKlass* scratch_class, TRAPS) {
--- a/src/hotspot/share/prims/jvmtiRedefineClasses.hpp	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/hotspot/share/prims/jvmtiRedefineClasses.hpp	Mon Jun 01 17:00:40 2020 -0400
@@ -479,6 +479,7 @@
     InstanceKlass* scratch_class, TRAPS);
   bool rewrite_cp_refs_in_nest_attributes(InstanceKlass* scratch_class);
   bool rewrite_cp_refs_in_record_attribute(InstanceKlass* scratch_class, TRAPS);
+  bool rewrite_cp_refs_in_permitted_subclasses_attribute(InstanceKlass* scratch_class);
   void rewrite_cp_refs_in_method(methodHandle method,
     methodHandle * new_method_p, TRAPS);
   bool rewrite_cp_refs_in_methods(InstanceKlass* scratch_class, TRAPS);
--- a/src/java.base/share/classes/java/lang/Class.java	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/java.base/share/classes/java/lang/Class.java	Mon Jun 01 17:00:40 2020 -0400
@@ -201,6 +201,8 @@
     private static final int ENUM      = 0x00004000;
     private static final int SYNTHETIC = 0x00001000;
 
+    private static final ClassDesc[] EMPTY_CLASS_DESC_ARRAY = new ClassDesc[0];
+
     private static native void registerNatives();
     static {
         registerNatives();
@@ -4382,4 +4384,69 @@
     @HotSpotIntrinsicCandidate
     public native boolean isHidden();
 
+    /**
+     * {@preview Associated with sealed classes, a preview feature of the Java language.
+     *
+     *           This method is associated with <i>sealed classes</i>, a preview
+     *           feature of the Java language. Preview features
+     *           may be removed in a future release, or upgraded to permanent
+     *           features of the Java language.}
+     *
+     * Returns an array containing {@code ClassDesc} objects representing all the
+     * direct subclasses or direct implementation classes permitted to extend or implement this class or interface
+     * if it is sealed. If this {@code Class} object represents a primitive type, {@code void}, an array type,
+     * or a class or interface that is not sealed, an empty array is returned.
+     *
+     * @return an array of class descriptors of all the permitted subclasses of this class or interface
+     *
+     * @jls 8.1 Class Declarations
+     * @jls 9.1 Interface Declarations
+     * @since 15
+     */
+    @jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.SEALED_CLASSES, essentialAPI=false)
+    public ClassDesc[] permittedSubclasses() {
+        String[] subclassNames;
+        if (isArray() || isPrimitive() || (subclassNames = getPermittedSubclasses0()).length == 0) {
+            return EMPTY_CLASS_DESC_ARRAY;
+        }
+        ClassDesc[] constants = new ClassDesc[subclassNames.length];
+        int i = 0;
+        for (String subclassName : subclassNames) {
+            try {
+                constants[i++] = ClassDesc.of(subclassName.replace('/', '.'));
+            } catch (IllegalArgumentException iae) {
+                throw new InternalError("Invalid type in permitted subclasses information: " + subclassName, iae);
+            }
+        }
+        return constants;
+    }
+
+    /**
+     * * {@preview Associated with sealed classes, a preview feature of the Java language.
+     *
+     *           This method is associated with <i>sealed classes</i>, a preview
+     *           feature of the Java language. Preview features
+     *           may be removed in a future release, or upgraded to permanent
+     *           features of the Java language.}
+     *
+     * Returns {@code true} if and only if this {@code Class} object represents a sealed class or interface.
+     * If this {@code Class} object represents a primitive type, {@code void}, or an array type, this method returns
+     * {@code false}.
+     *
+     * @return {@code true} if and only if this {@code Class} object represents a sealed class or interface.
+     *
+     * @jls 8.1 Class Declarations
+     * @jls 9.1 Interface Declarations
+     * @since 15
+     */
+    @jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.SEALED_CLASSES, essentialAPI=false)
+    @SuppressWarnings("preview")
+    public boolean isSealed() {
+        if (isArray() || isPrimitive()) {
+            return false;
+        }
+        return permittedSubclasses().length != 0;
+    }
+
+    private native String[] getPermittedSubclasses0();
 }
--- a/src/java.base/share/classes/jdk/internal/PreviewFeature.java	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/java.base/share/classes/jdk/internal/PreviewFeature.java	Mon Jun 01 17:00:40 2020 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2020, 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
@@ -63,6 +63,7 @@
         // necessary for PreviewFeature in JDK 15 to declare the enum constant.
         TEXT_BLOCKS,
         RECORDS,
+        SEALED_CLASSES,
         ;
     }
 }
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java	Mon Jun 01 17:00:40 2020 -0400
@@ -499,8 +499,8 @@
         String nestHostClass = null;
         // - The offset of the NestMembers attribute, or 0.
         int nestMembersOffset = 0;
-        // - The offset of the PermittedSubtypes attribute, or 0
-        int permittedSubtypesOffset = 0;
+        // - The offset of the PermittedSubclasses attribute, or 0
+        int permittedSubclassesOffset = 0;
         // - The offset of the Record attribute, or 0.
         int recordOffset = 0;
         // - The non standard attributes (linked with their {@link Attribute#nextAttribute} field).
@@ -525,8 +525,8 @@
                 nestHostClass = readClass(currentAttributeOffset, charBuffer);
             } else if (Constants.NEST_MEMBERS.equals(attributeName)) {
                 nestMembersOffset = currentAttributeOffset;
-            } else if (Constants.PERMITTED_SUBTYPES.equals(attributeName)) {
-                permittedSubtypesOffset = currentAttributeOffset;
+            } else if (Constants.PERMITTED_SUBCLASSES.equals(attributeName)) {
+                permittedSubclassesOffset = currentAttributeOffset;
             } else if (Constants.SIGNATURE.equals(attributeName)) {
                 signature = readUTF8(currentAttributeOffset, charBuffer);
             } else if (Constants.RUNTIME_VISIBLE_ANNOTATIONS.equals(attributeName)) {
@@ -704,14 +704,14 @@
             }
         }
 
-        // Visit the PermittedSubtypes attribute.
-        if (permittedSubtypesOffset != 0) {
-            int numberOfPermittedSubtypes = readUnsignedShort(permittedSubtypesOffset);
-            int currentPermittedSubtypeOffset = permittedSubtypesOffset + 2;
-            while (numberOfPermittedSubtypes-- > 0) {
-                classVisitor.visitPermittedSubtypeExperimental(
-                        readClass(currentPermittedSubtypeOffset, charBuffer));
-                currentPermittedSubtypeOffset += 2;
+        // Visit the PermittedSubclasses attribute.
+        if (permittedSubclassesOffset != 0) {
+            int numberOfPermittedSubclasses = readUnsignedShort(permittedSubclassesOffset);
+            int currentPermittedSubclassOffset = permittedSubclassesOffset + 2;
+            while (numberOfPermittedSubclasses-- > 0) {
+                classVisitor.visitPermittedSubclassExperimental(
+                        readClass(currentPermittedSubclassOffset, charBuffer));
+                currentPermittedSubclassOffset += 2;
             }
         }
 
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassVisitor.java	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassVisitor.java	Mon Jun 01 17:00:40 2020 -0400
@@ -61,7 +61,7 @@
 /**
  * A visitor to visit a Java class. The methods of this class must be called in the following order:
  * {@code visit} [ {@code visitSource} ] [ {@code visitModule} ][ {@code visitNestHost} ][ {@code
- * visitPermittedSubtype} ][ {@code visitOuterClass} ] ( {@code visitAnnotation} | {@code
+ * visitPermittedSubclass} ][ {@code visitOuterClass} ] ( {@code visitAnnotation} | {@code
  * visitTypeAnnotation} | {@code visitAttribute} )* ( {@code visitNestMember} | {@code
  * visitInnerClass} | {@code visitField} | {@code visitMethod} )* {@code visitEnd}.
  *
@@ -287,19 +287,19 @@
 
     /**
       * <b>Experimental, use at your own risk. This method will be renamed when it becomes stable, this
-      * will break existing code using it</b>. Visits a permitted subtypes. A permitted subtypes is one
-      * of the allowed subtypes of the current class.
+      * will break existing code using it</b>. Visits a permitted subclass. A permitted subclass is one
+      * of the allowed subclasses of the current class.
       *
-      * @param permittedSubtype the internal name of a permitted subtype.
+      * @param permittedSubclass the internal name of a permitted subclass.
       * @deprecated this API is experimental.
       */
     @Deprecated
-    public void visitPermittedSubtypeExperimental(final String permittedSubtype) {
+    public void visitPermittedSubclassExperimental(final String permittedSubclass) {
         if (api != Opcodes.ASM9_EXPERIMENTAL) {
             throw new UnsupportedOperationException("This feature requires ASM9_EXPERIMENTAL");
         }
         if (cv != null) {
-            cv.visitPermittedSubtypeExperimental(permittedSubtype);
+            cv.visitPermittedSubclassExperimental(permittedSubclass);
         }
     }
 
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java	Mon Jun 01 17:00:40 2020 -0400
@@ -208,11 +208,11 @@
     /** The 'classes' array of the NestMembers attribute, or {@literal null}. */
     private ByteVector nestMemberClasses;
 
-    /** The number_of_classes field of the PermittedSubtypes attribute, or 0. */
-    private int numberOfPermittedSubtypeClasses;
+    /** The number_of_classes field of the PermittedSubclasses attribute, or 0. */
+    private int numberOfPermittedSubclassClasses;
 
-    /** The 'classes' array of the PermittedSubtypes attribute, or {@literal null}. */
-    private ByteVector permittedSubtypeClasses;
+    /** The 'classes' array of the PermittedSubclasses attribute, or {@literal null}. */
+    private ByteVector permittedSubclassClasses;
 
     /**
       * The record components of this class, stored in a linked list of {@link RecordComponentWriter}
@@ -406,17 +406,17 @@
     /**
       * <b>Experimental, use at your own risk.</b>
       *
-      * @param permittedSubtype the internal name of a permitted subtype.
+      * @param permittedSubclass the internal name of a permitted subclass.
       * @deprecated this API is experimental.
       */
     @Override
     @Deprecated
-    public final void visitPermittedSubtypeExperimental(final String permittedSubtype) {
-        if (permittedSubtypeClasses == null) {
-            permittedSubtypeClasses = new ByteVector();
+    public final void visitPermittedSubclassExperimental(final String permittedSubclass) {
+        if (permittedSubclassClasses == null) {
+            permittedSubclassClasses = new ByteVector();
         }
-        ++numberOfPermittedSubtypeClasses;
-        permittedSubtypeClasses.putShort(symbolTable.addConstantClass(permittedSubtype).index);
+        ++numberOfPermittedSubclassClasses;
+        permittedSubclassClasses.putShort(symbolTable.addConstantClass(permittedSubclass).index);
     }
 
     @Override
@@ -607,10 +607,10 @@
             size += 8 + nestMemberClasses.length;
             symbolTable.addConstantUtf8(Constants.NEST_MEMBERS);
         }
-        if (permittedSubtypeClasses != null) {
+        if (permittedSubclassClasses != null) {
             ++attributesCount;
-            size += 8 + permittedSubtypeClasses.length;
-            symbolTable.addConstantUtf8(Constants.PERMITTED_SUBTYPES);
+            size += 8 + permittedSubclassClasses.length;
+            symbolTable.addConstantUtf8(Constants.PERMITTED_SUBCLASSES);
         }
         int recordComponentCount = 0;
         int recordSize = 0;
@@ -729,12 +729,12 @@
                     .putShort(numberOfNestMemberClasses)
                     .putByteArray(nestMemberClasses.data, 0, nestMemberClasses.length);
         }
-        if (permittedSubtypeClasses != null) {
+        if (permittedSubclassClasses != null) {
             result
-                    .putShort(symbolTable.addConstantUtf8(Constants.PERMITTED_SUBTYPES))
-                    .putInt(permittedSubtypeClasses.length + 2)
-                    .putShort(numberOfPermittedSubtypeClasses)
-                    .putByteArray(permittedSubtypeClasses.data, 0, permittedSubtypeClasses.length);
+                    .putShort(symbolTable.addConstantUtf8(Constants.PERMITTED_SUBCLASSES))
+                    .putInt(permittedSubclassClasses.length + 2)
+                    .putShort(numberOfPermittedSubclassClasses)
+                    .putByteArray(permittedSubclassClasses.data, 0, permittedSubclassClasses.length);
         }
         if ((accessFlags & Opcodes.ACC_RECORD) != 0 || firstRecordComponent != null) {
             result
@@ -783,8 +783,8 @@
         nestHostClassIndex = 0;
         numberOfNestMemberClasses = 0;
         nestMemberClasses = null;
-        numberOfPermittedSubtypeClasses = 0;
-        permittedSubtypeClasses = null;
+        numberOfPermittedSubclassClasses = 0;
+        permittedSubclassClasses = null;
         firstRecordComponent = null;
         lastRecordComponent = null;
         firstAttribute = null;
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Constants.java	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Constants.java	Mon Jun 01 17:00:40 2020 -0400
@@ -104,7 +104,7 @@
     static final String MODULE_MAIN_CLASS = "ModuleMainClass";
     static final String NEST_HOST = "NestHost";
     static final String NEST_MEMBERS = "NestMembers";
-    static final String PERMITTED_SUBTYPES = "PermittedSubtypes";
+    static final String PERMITTED_SUBCLASSES = "PermittedSubclasses";
     static final String RECORD = "Record";
 
     // ASM specific access flags.
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/ClassRemapper.java	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/ClassRemapper.java	Mon Jun 01 17:00:40 2020 -0400
@@ -252,13 +252,13 @@
     /**
       * <b>Experimental, use at your own risk.</b>.
       *
-      * @param permittedSubtype the internal name of a permitted subtype.
+      * @param permittedSubclass the internal name of a permitted subclass.
       * @deprecated this API is experimental.
       */
     @Override
     @Deprecated
-    public void visitPermittedSubtypeExperimental(final String permittedSubtype) {
-        super.visitPermittedSubtypeExperimental(remapper.mapType(permittedSubtype));
+    public void visitPermittedSubclassExperimental(final String permittedSubclass) {
+        super.visitPermittedSubclassExperimental(remapper.mapType(permittedSubclass));
     }
 
     /**
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ClassNode.java	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ClassNode.java	Mon Jun 01 17:00:40 2020 -0400
@@ -160,12 +160,12 @@
 
     /**
       * <b>Experimental, use at your own risk. This method will be renamed when it becomes stable, this
-      * will break existing code using it</b>. The internal names of the permitted subtypes of this
+      * will break existing code using it</b>. The internal names of the permitted subclasses of this
       * class. May be {@literal null}.
       *
       * @deprecated this API is experimental.
       */
-    @Deprecated public List<String> permittedSubtypesExperimental;
+    @Deprecated public List<String> permittedSubclassesExperimental;
 
     /** The record components of this class. May be {@literal null}. */
     public List<RecordComponentNode> recordComponents;
@@ -284,13 +284,13 @@
     /**
       * <b>Experimental, use at your own risk.</b>.
       *
-      * @param permittedSubtype the internal name of a permitted subtype.
+      * @param permittedSubclass the internal name of a permitted subclass.
       * @deprecated this API is experimental.
       */
     @Override
     @Deprecated
-    public void visitPermittedSubtypeExperimental(final String permittedSubtype) {
-        permittedSubtypesExperimental = Util.add(permittedSubtypesExperimental, permittedSubtype);
+    public void visitPermittedSubclassExperimental(final String permittedSubclass) {
+        permittedSubclassesExperimental = Util.add(permittedSubclassesExperimental, permittedSubclass);
     }
 
     @Override
@@ -351,7 +351,7 @@
       */
     @SuppressWarnings("deprecation")
     public void check(final int api) {
-        if (api != Opcodes.ASM9_EXPERIMENTAL && permittedSubtypesExperimental != null) {
+        if (api != Opcodes.ASM9_EXPERIMENTAL && permittedSubclassesExperimental != null) {
             throw new UnsupportedClassVersionException();
         }
         if (api < Opcodes.ASM8 && ((access & Opcodes.ACC_RECORD) != 0 || recordComponents != null)) {
@@ -473,10 +473,10 @@
                 classVisitor.visitNestMember(nestMembers.get(i));
             }
         }
-        // Visit the permitted subtypes.
-        if (permittedSubtypesExperimental != null) {
-            for (int i = 0, n = permittedSubtypesExperimental.size(); i < n; ++i) {
-                classVisitor.visitPermittedSubtypeExperimental(permittedSubtypesExperimental.get(i));
+        // Visit the permitted subclass.
+        if (permittedSubclassesExperimental != null) {
+            for (int i = 0, n = permittedSubclassesExperimental.size(); i < n; ++i) {
+                classVisitor.visitPermittedSubclassExperimental(permittedSubclassesExperimental.get(i));
             }
         }
         // Visit the inner classes.
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/ASMifier.java	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/ASMifier.java	Mon Jun 01 17:00:40 2020 -0400
@@ -357,15 +357,15 @@
     /**
       * <b>Experimental, use at your own risk.</b>.
       *
-      * @param permittedSubtype the internal name of a permitted subtype.
+      * @param permittedSubclass the internal name of a permitted subclass.
       * @deprecated this API is experimental.
       */
     @Override
     @Deprecated
-    public void visitPermittedSubtypeExperimental(final String permittedSubtype) {
+    public void visitPermittedSubclassExperimental(final String permittedSubclass) {
         stringBuilder.setLength(0);
-        stringBuilder.append("classWriter.visitPermittedSubtypeExperimental(");
-        appendConstant(permittedSubtype);
+        stringBuilder.append("classWriter.visitPermittedSubclassExperimental(");
+        appendConstant(permittedSubclass);
         stringBuilder.append(END_PARAMETERS);
         text.add(stringBuilder.toString());
     }
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckClassAdapter.java	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckClassAdapter.java	Mon Jun 01 17:00:40 2020 -0400
@@ -356,15 +356,15 @@
     /**
       * <b>Experimental, use at your own risk.</b>.
       *
-      * @param permittedSubtype the internal name of a permitted subtype.
+      * @param permittedSubclass the internal name of a permitted subclass.
       * @deprecated this API is experimental.
       */
     @Override
     @Deprecated
-    public void visitPermittedSubtypeExperimental(final String permittedSubtype) {
+    public void visitPermittedSubclassExperimental(final String permittedSubclass) {
         checkState();
-        CheckMethodAdapter.checkInternalName(version, permittedSubtype, "permittedSubtype");
-        super.visitPermittedSubtypeExperimental(permittedSubtype);
+        CheckMethodAdapter.checkInternalName(version, permittedSubclass, "permittedSubclass");
+        super.visitPermittedSubclassExperimental(permittedSubclass);
     }
 
     @Override
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/Printer.java	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/Printer.java	Mon Jun 01 17:00:40 2020 -0400
@@ -488,15 +488,15 @@
       * <b>Experimental, use at your own risk. This method will be renamed when it becomes stable, this
       * will break existing code using it</b>.
       *
-      * <p>Visits a permitted subtypes. A permitted subtypes is one of the allowed subtypes of the
+      * <p>Visits a permitted subclass. A permitted subtclass is one of the allowed subclasses of the
       * current class. See {@link
-      * jdk.internal.org.objectweb.asm.ClassVisitor#visitPermittedSubtypeExperimental(String)}.
+      * jdk.internal.org.objectweb.asm.ClassVisitor#visitPermittedSubclassExperimental(String)}.
       *
-      * @param permittedSubtype the internal name of a permitted subtype.
+      * @param permittedSubclass the internal name of a permitted subclass.
       * @deprecated this API is experimental.
       */
     @Deprecated
-    public void visitPermittedSubtypeExperimental(final String permittedSubtype) {
+    public void visitPermittedSubclassExperimental(final String permittedSubclass) {
         throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
     }
 
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/Textifier.java	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/Textifier.java	Mon Jun 01 17:00:40 2020 -0400
@@ -340,15 +340,15 @@
     /**
       * <b>Experimental, use at your own risk.</b>.
       *
-      * @param permittedSubtype the internal name of a permitted subtype.
+      * @param permittedSubclass the internal name of a permitted subclass.
       * @deprecated this API is experimental.
       */
     @Override
     @Deprecated
-    public void visitPermittedSubtypeExperimental(final String permittedSubtype) {
+    public void visitPermittedSubclassExperimental(final String permittedSubclass) {
         stringBuilder.setLength(0);
-        stringBuilder.append(tab).append("PERMITTEDSUBTYPE ");
-        appendDescriptor(INTERNAL_NAME, permittedSubtype);
+        stringBuilder.append(tab).append("PERMITTEDSUBCLASS ");
+        appendDescriptor(INTERNAL_NAME, permittedSubclass);
         stringBuilder.append('\n');
         text.add(stringBuilder.toString());
     }
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceClassVisitor.java	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceClassVisitor.java	Mon Jun 01 17:00:40 2020 -0400
@@ -222,14 +222,14 @@
     /**
       * <b>Experimental, use at your own risk.</b>.
       *
-      * @param permittedSubtype the internal name of a permitted subtype.
+      * @param permittedSubclass the internal name of a permitted subclass.
       * @deprecated this API is experimental.
       */
     @Override
     @Deprecated
-    public void visitPermittedSubtypeExperimental(final String permittedSubtype) {
-        p.visitPermittedSubtypeExperimental(permittedSubtype);
-        super.visitPermittedSubtypeExperimental(permittedSubtype);
+    public void visitPermittedSubclassExperimental(final String permittedSubclass) {
+        p.visitPermittedSubclassExperimental(permittedSubclass);
+        super.visitPermittedSubclassExperimental(permittedSubclass);
     }
 
     @Override
--- a/src/java.base/share/native/libjava/Class.c	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/java.base/share/native/libjava/Class.c	Mon Jun 01 17:00:40 2020 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2020, 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
@@ -81,6 +81,7 @@
     {"getNestMembers0",      "()[" CLS,     (void *)&JVM_GetNestMembers},
     {"getRecordComponents0", "()[" RC,      (void *)&JVM_GetRecordComponents},
     {"isRecord0",            "()Z",         (void *)&JVM_IsRecord},
+    {"getPermittedSubclasses0", "()[" STR,  (void *)&JVM_GetPermittedSubclasses},
 };
 
 #undef OBJ
--- a/src/java.compiler/share/classes/javax/lang/model/SourceVersion.java	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/java.compiler/share/classes/javax/lang/model/SourceVersion.java	Mon Jun 01 17:00:40 2020 -0400
@@ -421,6 +421,10 @@
         case "_":
             return version.compareTo(RELEASE_9) >= 0;
 
+     // case "non-sealed": can be added once it is a keyword only
+     // dependent on release and not also preview features being
+     // enabled.
+
             // Keywords common across versions
 
             // Modifiers
--- a/src/java.compiler/share/classes/javax/lang/model/element/Modifier.java	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/java.compiler/share/classes/javax/lang/model/element/Modifier.java	Mon Jun 01 17:00:40 2020 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2020, 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
@@ -59,6 +59,40 @@
      */
      DEFAULT,
     /** The modifier {@code static} */          STATIC,
+
+    /**
+     * {@preview Associated with sealed classes, a preview feature of the Java language.
+     *
+     *           This enum constant is associated with <i>sealed classes</i>, a preview
+     *           feature of the Java language. Preview features
+     *           may be removed in a future release, or upgraded to permanent
+     *           features of the Java language.}
+     *
+     * The modifier {@code sealed}
+     * @since 15
+     */
+    @jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.SEALED_CLASSES,
+                                             essentialAPI=false)
+    SEALED,
+
+    /**
+     * {@preview Associated with sealed classes, a preview feature of the Java language.
+     *
+     *           This enum constant is associated with <i>sealed classes</i>, a preview
+     *           feature of the Java language. Preview features
+     *           may be removed in a future release, or upgraded to permanent
+     *           features of the Java language.}
+     *
+     * The modifier {@code non-sealed}
+     * @since 15
+     */
+    @jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.SEALED_CLASSES,
+            essentialAPI=false)
+    NON_SEALED {
+        public String toString() {
+            return "non-sealed";
+        }
+    },
     /** The modifier {@code final} */           FINAL,
     /** The modifier {@code transient} */       TRANSIENT,
     /** The modifier {@code volatile} */        VOLATILE,
--- a/src/java.compiler/share/classes/javax/lang/model/element/TypeElement.java	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/java.compiler/share/classes/javax/lang/model/element/TypeElement.java	Mon Jun 01 17:00:40 2020 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2020, 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
@@ -205,6 +205,29 @@
     }
 
     /**
+     * {@preview Associated with sealed classes, a preview feature of the Java language.
+     *
+     *           This method is associated with <i>sealed classes</i>, a preview
+     *           feature of the Java language. Preview features
+     *           may be removed in a future release, or upgraded to permanent
+     *           features of the Java language.}
+     * Returns the permitted classes of this type element in
+     * declaration order.
+     *
+     * @implSpec The default implementations of this method returns an
+     * empty and unmodifiable list.
+     *
+     * @return the permitted classes, or an empty list if there are none
+     *
+     * @since 15
+     */
+    @jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.SEALED_CLASSES,
+                                 essentialAPI=false)
+    default List<? extends TypeMirror> getPermittedSubclasses() {
+        return List.of();
+    }
+
+    /**
      * Returns the package of a top-level type and returns the
      * immediately lexically enclosing element for a {@linkplain
      * NestingKind#isNested nested} type.
--- a/src/java.instrument/share/native/libinstrument/JavaExceptions.c	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/java.instrument/share/native/libinstrument/JavaExceptions.c	Mon Jun 01 17:00:40 2020 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2020, 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
@@ -216,7 +216,7 @@
 
         case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_ATTRIBUTE_CHANGED:
                 throwableClassName = "java/lang/UnsupportedOperationException";
-                message = "class redefinition failed: attempted to change the class NestHost, NestMembers, or Record attribute";
+                message = "class redefinition failed: attempted to change the class NestHost, NestMembers, Record, or PermittedSubclasses attribute";
                 break;
 
         case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_MODIFIERS_CHANGED:
--- a/src/jdk.compiler/share/classes/com/sun/source/tree/ClassTree.java	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/source/tree/ClassTree.java	Mon Jun 01 17:00:40 2020 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2020, 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
@@ -25,6 +25,7 @@
 
 package com.sun.source.tree;
 
+import java.util.Collections;
 import java.util.List;
 import javax.lang.model.element.Name;
 
@@ -86,6 +87,28 @@
     List<? extends Tree> getImplementsClause();
 
     /**
+     * {@preview Associated with sealed classes, a preview feature of the Java language.
+     *
+     *           This method is associated with <i>sealed classes</i>, a preview
+     *           feature of the Java language. Preview features
+     *           may be removed in a future release, or upgraded to permanent
+     *           features of the Java language.}
+     *
+     * Returns the subclasses permitted by this type declaration.
+     *
+     * @implSpec this implementation returns an empty list
+     *
+     * @return the subclasses
+     *
+     * @since 15
+     */
+    @jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.SEALED_CLASSES,
+                                             essentialAPI=false)
+    default List<? extends Tree> getPermitsClause() {
+        return List.of();
+    }
+
+    /**
      * Returns the members declared in this type declaration.
      * @return the members
      */
--- a/src/jdk.compiler/share/classes/com/sun/source/util/TreeScanner.java	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/source/util/TreeScanner.java	Mon Jun 01 17:00:40 2020 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2020, 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
@@ -178,12 +178,14 @@
      * @param p  {@inheritDoc}
      * @return the result of scanning
      */
+    @SuppressWarnings("preview")
     @Override
     public R visitClass(ClassTree node, P p) {
         R r = scan(node.getModifiers(), p);
         r = scanAndReduce(node.getTypeParameters(), p, r);
         r = scanAndReduce(node.getExtendsClause(), p, r);
         r = scanAndReduce(node.getImplementsClause(), p, r);
+        r = scanAndReduce(node.getPermitsClause(), p, r);
         r = scanAndReduce(node.getMembers(), p, r);
         return r;
     }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java	Mon Jun 01 17:00:40 2020 -0400
@@ -366,6 +366,16 @@
      */
     public static final int GENERATED_MEMBER = 1<<24; // MethodSymbols and VarSymbols
 
+    /**
+     * Flag to indicate sealed class/interface declaration.
+     */
+    public static final long SEALED = 1L<<62; // ClassSymbols
+
+    /**
+     * Flag to indicate that the class/interface was declared with the non-sealed modifier.
+     */
+    public static final long NON_SEALED = 1L<<63; // ClassSymbols
+
     /** Modifier masks.
      */
     public static final int
@@ -385,14 +395,16 @@
         RecordMethodFlags     = AccessFlags | ABSTRACT | STATIC |
                                 SYNCHRONIZED | FINAL | STRICTFP;
     public static final long
-        ExtendedStandardFlags       = (long)StandardFlags | DEFAULT,
-        ModifierFlags               = ((long)StandardFlags & ~INTERFACE) | DEFAULT,
+        ExtendedStandardFlags       = (long)StandardFlags | DEFAULT | SEALED | NON_SEALED,
+        ExtendedMemberClassFlags    = (long)MemberClassFlags | SEALED | NON_SEALED,
+        ExtendedClassFlags          = (long)ClassFlags | SEALED | NON_SEALED,
+        ModifierFlags               = ((long)StandardFlags & ~INTERFACE) | DEFAULT | SEALED | NON_SEALED,
         InterfaceMethodMask         = ABSTRACT | PRIVATE | STATIC | PUBLIC | STRICTFP | DEFAULT,
         AnnotationTypeElementMask   = ABSTRACT | PUBLIC,
         LocalVarFlags               = FINAL | PARAMETER,
         ReceiverParamFlags          = PARAMETER;
 
-
+    @SuppressWarnings("preview")
     public static Set<Modifier> asModifierSet(long flags) {
         Set<Modifier> modifiers = modifierSets.get(flags);
         if (modifiers == null) {
@@ -402,6 +414,9 @@
             if (0 != (flags & PRIVATE))   modifiers.add(Modifier.PRIVATE);
             if (0 != (flags & ABSTRACT))  modifiers.add(Modifier.ABSTRACT);
             if (0 != (flags & STATIC))    modifiers.add(Modifier.STATIC);
+            if (0 != (flags & SEALED))    modifiers.add(Modifier.SEALED);
+            if (0 != (flags & NON_SEALED))
+                                          modifiers.add(Modifier.NON_SEALED);
             if (0 != (flags & FINAL))     modifiers.add(Modifier.FINAL);
             if (0 != (flags & TRANSIENT)) modifiers.add(Modifier.TRANSIENT);
             if (0 != (flags & VOLATILE))  modifiers.add(Modifier.VOLATILE);
@@ -492,7 +507,14 @@
         PREVIEW_ESSENTIAL_API(Flags.PREVIEW_ESSENTIAL_API),
         MATCH_BINDING(Flags.MATCH_BINDING),
         MATCH_BINDING_TO_OUTER(Flags.MATCH_BINDING_TO_OUTER),
-        RECORD(Flags.RECORD);
+        RECORD(Flags.RECORD),
+        SEALED(Flags.SEALED),
+        NON_SEALED(Flags.NON_SEALED) {
+            @Override
+            public String toString() {
+                return "non-sealed";
+            }
+        };
 
         Flag(long flag) {
             this.value = flag;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java	Mon Jun 01 17:00:40 2020 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2020, 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
@@ -167,7 +167,8 @@
     public boolean isPreview(Feature feature) {
         if (feature == Feature.PATTERN_MATCHING_IN_INSTANCEOF ||
             feature == Feature.REIFIABLE_TYPES_INSTANCEOF ||
-            feature == Feature.RECORDS)
+            feature == Feature.RECORDS ||
+            feature == Feature.SEALED_CLASSES)
             return true;
         //Note: this is a backdoor which allows to optionally treat all features as 'preview' (for testing).
         //When real preview features will be added, this method can be implemented to return 'true'
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java	Mon Jun 01 17:00:40 2020 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2020, 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
@@ -209,6 +209,7 @@
         PATTERN_MATCHING_IN_INSTANCEOF(JDK15, Fragments.FeaturePatternMatchingInstanceof, DiagKind.NORMAL),
         REIFIABLE_TYPES_INSTANCEOF(JDK15, Fragments.FeatureReifiableTypesInstanceof, DiagKind.PLURAL),
         RECORDS(JDK15, Fragments.FeatureRecords, DiagKind.PLURAL),
+        SEALED_CLASSES(JDK15, Fragments.FeatureSealedClasses, DiagKind.PLURAL),
         ;
 
         enum DiagKind {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java	Mon Jun 01 17:00:40 2020 -0400
@@ -422,6 +422,14 @@
         return (flags() & ENUM) != 0;
     }
 
+    public boolean isSealed() {
+        return (flags_field & SEALED) != 0;
+    }
+
+    public boolean isNonSealed() {
+        return (flags_field & NON_SEALED) != 0;
+    }
+
     public boolean isFinal() {
         return (flags_field & FINAL) != 0;
     }
@@ -1285,6 +1293,13 @@
          */
         private List<RecordComponent> recordComponents = List.nil();
 
+        // sealed classes related fields
+        /** The classes, or interfaces, permitted to extend this class, or interface
+         */
+        public List<Symbol> permitted;
+
+        public boolean isPermittedExplicit = false;
+
         public ClassSymbol(long flags, Name name, Type type, Symbol owner) {
             super(TYP, flags, name, type, owner);
             this.members_field = null;
@@ -1293,6 +1308,7 @@
             this.sourcefile = null;
             this.classfile = null;
             this.annotationTypeMetadata = AnnotationTypeMetadata.notAnAnnotationType();
+            this.permitted = List.nil();
         }
 
         public ClassSymbol(long flags, Name name, Symbol owner) {
@@ -1601,6 +1617,11 @@
         public boolean isRecord() {
             return (flags_field & RECORD) != 0;
         }
+
+        @DefinedBy(Api.LANGUAGE_MODEL)
+        public List<Type> getPermittedSubclasses() {
+            return permitted.map(s -> s.type);
+        }
     }
 
 
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java	Mon Jun 01 17:00:40 2020 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2020, 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
@@ -730,7 +730,7 @@
          */
         public FunctionDescriptor findDescriptorInternal(TypeSymbol origin,
                 CompoundScope membersCache) throws FunctionDescriptorLookupError {
-            if (!origin.isInterface() || (origin.flags() & ANNOTATION) != 0) {
+            if (!origin.isInterface() || (origin.flags() & ANNOTATION) != 0 || origin.isSealed()) {
                 //t must be an interface
                 throw failure("not.a.functional.intf", origin);
             }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java	Mon Jun 01 17:00:40 2020 -0400
@@ -5027,6 +5027,90 @@
             // Get environment current at the point of class definition.
             Env<AttrContext> env = typeEnvs.get(c);
 
+            if (c.isSealed() &&
+                    !c.isEnum() &&
+                    !c.isPermittedExplicit &&
+                    c.permitted.isEmpty()) {
+                log.error(TreeInfo.diagnosticPositionFor(c, env.tree), Errors.SealedClassMustHaveSubclasses);
+            }
+
+            if (c.isSealed()) {
+                Set<Symbol> permittedTypes = new HashSet<>();
+                boolean sealedInUnnamed = c.packge().modle == syms.unnamedModule || c.packge().modle == syms.noModule;
+                for (Symbol subTypeSym : c.permitted) {
+                    boolean isTypeVar = false;
+                    if (subTypeSym.type.getTag() == TYPEVAR) {
+                        isTypeVar = true; //error recovery
+                        log.error(TreeInfo.diagnosticPositionFor(subTypeSym, env.tree),
+                                Errors.InvalidPermitsClause(Fragments.IsATypeVariable(subTypeSym.type)));
+                    }
+                    if (subTypeSym.isAnonymous() && !c.isEnum()) {
+                        log.error(TreeInfo.diagnosticPositionFor(subTypeSym, env.tree), Errors.CantInheritFromSealed(c));
+                    }
+                    if (permittedTypes.contains(subTypeSym)) {
+                        DiagnosticPosition pos =
+                                env.enclClass.permitting.stream()
+                                        .filter(permittedExpr -> TreeInfo.diagnosticPositionFor(subTypeSym, permittedExpr, true) != null)
+                                        .limit(2).collect(List.collector()).get(1);
+                        log.error(pos, Errors.InvalidPermitsClause(Fragments.IsDuplicated(subTypeSym.type)));
+                    } else {
+                        permittedTypes.add(subTypeSym);
+                    }
+                    if (sealedInUnnamed) {
+                        if (subTypeSym.packge() != c.packge()) {
+                            log.error(TreeInfo.diagnosticPositionFor(subTypeSym, env.tree), Errors.CantInheritFromSealed(c));
+                        }
+                    } else if (subTypeSym.packge().modle != c.packge().modle) {
+                        log.error(TreeInfo.diagnosticPositionFor(subTypeSym, env.tree), Errors.CantInheritFromSealed(c));
+                    }
+                    if (subTypeSym == c.type.tsym || types.isSuperType(subTypeSym.type, c.type)) {
+                        log.error(TreeInfo.diagnosticPositionFor(subTypeSym, ((JCClassDecl)env.tree).permitting),
+                                Errors.InvalidPermitsClause(
+                                        subTypeSym == c.type.tsym ?
+                                                Fragments.MustNotBeSameClass :
+                                                Fragments.MustNotBeSupertype(subTypeSym.type)
+                                )
+                        );
+                    } else if (!isTypeVar) {
+                        boolean thisIsASuper = types.directSupertypes(subTypeSym.type)
+                                                    .stream()
+                                                    .anyMatch(d -> d.tsym == c);
+                        if (!thisIsASuper) {
+                            log.error(TreeInfo.diagnosticPositionFor(subTypeSym, env.tree),
+                                    Errors.InvalidPermitsClause(Fragments.DoesntExtendSealed(subTypeSym.type)));
+                        }
+                    }
+                }
+            }
+
+            List<ClassSymbol> sealedSupers = types.directSupertypes(c.type)
+                                                  .stream()
+                                                  .filter(s -> s.tsym.isSealed())
+                                                  .map(s -> (ClassSymbol) s.tsym)
+                                                  .collect(List.collector());
+
+            if (sealedSupers.isEmpty()) {
+                if ((c.flags_field & Flags.NON_SEALED) != 0) {
+                    log.error(TreeInfo.diagnosticPositionFor(c, env.tree), Errors.NonSealedWithNoSealedSupertype(c));
+                }
+            } else {
+                if (c.isLocal() && !c.isEnum()) {
+                    log.error(TreeInfo.diagnosticPositionFor(c, env.tree), Errors.LocalClassesCantExtendSealed);
+                }
+
+                for (ClassSymbol supertypeSym : sealedSupers) {
+                    if (!supertypeSym.permitted.contains(c.type.tsym)) {
+                        log.error(TreeInfo.diagnosticPositionFor(c.type.tsym, env.tree), Errors.CantInheritFromSealed(supertypeSym));
+                    }
+                }
+                if (!c.isNonSealed() && !c.isFinal() && !c.isSealed()) {
+                    log.error(TreeInfo.diagnosticPositionFor(c, env.tree),
+                            c.isInterface() ?
+                                    Errors.NonSealedOrSealedExpected :
+                                    Errors.NonSealedSealedOrFinalExpected);
+                }
+            }
+
             // The info.lint field in the envs stored in typeEnvs is deliberately uninitialized,
             // because the annotations were not available at the time the env was created. Therefore,
             // we look up the environment chain for the first enclosing environment for which the
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java	Mon Jun 01 17:00:40 2020 -0400
@@ -160,6 +160,8 @@
 
         allowRecords = (!preview.isPreview(Feature.RECORDS) || preview.isEnabled()) &&
                 Feature.RECORDS.allowedInSource(source);
+        allowSealed = (!preview.isPreview(Feature.SEALED_CLASSES) || preview.isEnabled()) &&
+                Feature.SEALED_CLASSES.allowedInSource(source);
     }
 
     /** Character for synthetic names
@@ -195,6 +197,10 @@
      */
     private final boolean allowRecords;
 
+    /** Are sealed classes allowed
+     */
+    private final boolean allowSealed;
+
 /* *************************************************************************
  * Errors and Warnings
  **************************************************************************/
@@ -1222,7 +1228,7 @@
                     }
                 }
             } else if (sym.owner.kind == TYP) {
-                mask = (flags & RECORD) != 0 ? MemberRecordFlags : MemberClassFlags;
+                mask = (flags & RECORD) != 0 ? MemberRecordFlags : ExtendedMemberClassFlags;
                 if (sym.owner.owner.kind == PCK ||
                     (sym.owner.flags_field & STATIC) != 0)
                     mask |= STATIC;
@@ -1232,14 +1238,14 @@
                 // Nested interfaces and enums are always STATIC (Spec ???)
                 if ((flags & (INTERFACE | ENUM | RECORD)) != 0 ) implicit = STATIC;
             } else {
-                mask = ClassFlags;
+                mask = ExtendedClassFlags;
             }
             // Interfaces are always ABSTRACT
             if ((flags & INTERFACE) != 0) implicit |= ABSTRACT;
 
             if ((flags & ENUM) != 0) {
-                // enums can't be declared abstract or final
-                mask &= ~(ABSTRACT | FINAL);
+                // enums can't be declared abstract, final, sealed or non-sealed
+                mask &= ~(ABSTRACT | FINAL | SEALED | NON_SEALED);
                 implicit |= implicitEnumFinalFlag(tree);
             }
             if ((flags & RECORD) != 0) {
@@ -1294,7 +1300,13 @@
                  (sym.kind == TYP ||
                   checkDisjoint(pos, flags,
                                 ABSTRACT | NATIVE,
-                                STRICTFP))) {
+                                STRICTFP))
+                 && checkDisjoint(pos, flags,
+                                FINAL,
+                           SEALED | NON_SEALED)
+                 && checkDisjoint(pos, flags,
+                                SEALED,
+                           FINAL | NON_SEALED)) {
             // skip
         }
         return flags & (mask | ~ExtendedStandardFlags) | implicit;
@@ -1334,7 +1346,7 @@
         JCClassDecl cdef = (JCClassDecl) tree;
         for (JCTree defs: cdef.defs) {
             defs.accept(sts);
-            if (sts.specialized) return 0;
+            if (sts.specialized) return allowSealed ? SEALED : 0;
         }
         return FINAL;
     }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java	Mon Jun 01 17:00:40 2020 -0400
@@ -25,9 +25,11 @@
 
 package com.sun.tools.javac.comp;
 
+import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.Set;
 import java.util.function.BiConsumer;
+import java.util.stream.Collectors;
 
 import javax.tools.JavaFileObject;
 
@@ -711,6 +713,15 @@
                 }
             }
 
+            // Determine permits.
+            ListBuffer<Symbol> permittedSubtypeSymbols = new ListBuffer<>();
+            List<JCExpression> permittedTrees = tree.permitting;
+            for (JCExpression permitted : permittedTrees) {
+                permitted = clearTypeParams(permitted);
+                Type pt = attr.attribBase(permitted, baseEnv, false, false, false);
+                permittedSubtypeSymbols.append(pt.tsym);
+            }
+
             if ((sym.flags_field & ANNOTATION) != 0) {
                 ct.interfaces_field = List.of(syms.annotationType);
                 ct.all_interfaces_field = ct.interfaces_field;
@@ -719,6 +730,9 @@
                 ct.all_interfaces_field = (all_interfaces == null)
                         ? ct.interfaces_field : all_interfaces.toList();
             }
+
+            sym.permitted = permittedSubtypeSymbols.toList();
+            sym.isPermittedExplicit = !permittedSubtypeSymbols.isEmpty();
         }
             //where:
             protected JCExpression clearTypeParams(JCExpression superType) {
@@ -729,7 +743,7 @@
     private final class HierarchyPhase extends AbstractHeaderPhase implements Completer {
 
         public HierarchyPhase() {
-            super(CompletionCause.HIERARCHY_PHASE, new HeaderPhase());
+            super(CompletionCause.HIERARCHY_PHASE, new PermitsPhase());
         }
 
         @Override
@@ -803,6 +817,33 @@
 
     }
 
+    private final class PermitsPhase extends AbstractHeaderPhase {
+
+        public PermitsPhase() {
+            super(CompletionCause.HIERARCHY_PHASE, new HeaderPhase());
+        }
+
+        @Override
+        protected void runPhase(Env<AttrContext> env) {
+            JCClassDecl tree = env.enclClass;
+            if (!tree.sym.isAnonymous() || tree.sym.isEnum()) {
+                for (Type supertype : types.directSupertypes(tree.sym.type)) {
+                    if (supertype.tsym.kind == TYP) {
+                        ClassSymbol supClass = (ClassSymbol) supertype.tsym;
+                        Env<AttrContext> supClassEnv = enter.getEnv(supClass);
+                        if (supClass.isSealed() &&
+                            !supClass.isPermittedExplicit &&
+                            supClassEnv != null &&
+                            supClassEnv.toplevel == env.toplevel) {
+                            supClass.permitted = supClass.permitted.append(tree.sym);
+                        }
+                    }
+                }
+            }
+        }
+
+    }
+
     private final class HeaderPhase extends AbstractHeaderPhase {
 
         public HeaderPhase() {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Mon Jun 01 17:00:40 2020 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2020, 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
@@ -105,6 +105,10 @@
      */
     boolean allowModules;
 
+    /** Switch: allow sealed
+     */
+    boolean allowSealedTypes;
+
     /** Switch: allow records
      */
     boolean allowRecords;
@@ -270,6 +274,8 @@
         allowModules     = Feature.MODULES.allowedInSource(source);
         allowRecords = (!preview.isPreview(Feature.RECORDS) || preview.isEnabled()) &&
                 Feature.RECORDS.allowedInSource(source);
+        allowSealedTypes = (!preview.isPreview(Feature.SEALED_CLASSES) || preview.isEnabled()) &&
+                Feature.SEALED_CLASSES.allowedInSource(source);
 
         saveParameterNames = options.isSet(PARAMETERS);
 
@@ -1202,7 +1208,23 @@
                     }
                     bp = bp + attrLen;
                 }
-            }
+            },
+            new AttributeReader(names.PermittedSubclasses, V59, CLASS_ATTRIBUTE) {
+                @Override
+                protected boolean accepts(AttributeKind kind) {
+                    return super.accepts(kind) && allowSealedTypes;
+                }
+                protected void read(Symbol sym, int attrLen) {
+                    if (sym.kind == TYP) {
+                        ListBuffer<Symbol> subtypes = new ListBuffer<>();
+                        int numberOfPermittedSubtypes = nextChar();
+                        for (int i = 0; i < numberOfPermittedSubtypes; i++) {
+                            subtypes.add(poolReader.getClass(nextChar()));
+                        }
+                        ((ClassSymbol)sym).permitted = subtypes.toList();
+                    }
+                }
+            },
         };
 
         for (AttributeReader r: readers)
@@ -2470,6 +2492,10 @@
         for (int i = 0; i < methodCount; i++) skipMember();
         readClassAttrs(c);
 
+        if (c.permitted != null && !c.permitted.isEmpty()) {
+            c.flags_field |= SEALED;
+        }
+
         // reset and read rest of classinfo
         bp = startbp;
         int n = nextChar();
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java	Mon Jun 01 17:00:40 2020 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2020, 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
@@ -909,6 +909,21 @@
         }
     }
 
+    /** Write "PermittedSubclasses" attribute.
+     */
+    int writePermittedSubclassesIfNeeded(ClassSymbol csym) {
+        if (csym.permitted.nonEmpty()) {
+            int alenIdx = writeAttr(names.PermittedSubclasses);
+            databuf.appendChar(csym.permitted.size());
+            for (Symbol c : csym.permitted) {
+                databuf.appendChar(poolWriter.putClass((ClassSymbol) c));
+            }
+            endAttr(alenIdx);
+            return 1;
+        }
+        return 0;
+    }
+
     /** Write "bootstrapMethods" attribute.
      */
     void writeBootstrapMethods() {
@@ -1635,6 +1650,10 @@
             acount += writeRecordAttribute(c);
         }
 
+        if (target.hasSealedClasses()) {
+            acount += writePermittedSubclassesIfNeeded(c);
+        }
+
         if (!poolWriter.bootstrapMethods.isEmpty()) {
             writeBootstrapMethods();
             acount++;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Target.java	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Target.java	Mon Jun 01 17:00:40 2020 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2020, 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
@@ -183,4 +183,9 @@
         return compareTo(JDK1_11) >= 0;
     }
 
+    /** Does the target VM support sealed types
+     */
+    public boolean hasSealedClasses() {
+        return compareTo(JDK1_15) >= 0;
+    }
 }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java	Mon Jun 01 17:00:40 2020 -0400
@@ -186,6 +186,8 @@
                 Feature.SWITCH_EXPRESSION.allowedInSource(source);
         this.allowRecords = (!preview.isPreview(Feature.RECORDS) || preview.isEnabled()) &&
                 Feature.RECORDS.allowedInSource(source);
+        this.allowSealedTypes = (!preview.isPreview(Feature.SEALED_CLASSES) || preview.isEnabled()) &&
+                Feature.SEALED_CLASSES.allowedInSource(source);
     }
 
     protected AbstractEndPosTable newEndPosTable(boolean keepEndPositions) {
@@ -223,6 +225,10 @@
      */
     boolean allowRecords;
 
+    /** Switch: are sealed types allowed in this source level?
+     */
+    boolean allowSealedTypes;
+
     /** The type of the method receiver, as specified by a first "this" parameter.
      */
     JCVariableDecl receiverParam;
@@ -2623,6 +2629,19 @@
                 }
 
                 //else intentional fall-through
+            } else {
+                if (isNonSealedClassStart(true)) {
+                    log.error(token.pos, Errors.SealedOrNonSealedLocalClassesNotAllowed);
+                    nextToken();
+                    nextToken();
+                    nextToken();
+                    return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), token.comment(CommentStyle.JAVADOC)));
+                } else if (isSealedClassStart(true)) {
+                    checkSourceLevel(Feature.SEALED_CLASSES);
+                    log.error(token.pos, Errors.SealedOrNonSealedLocalClassesNotAllowed);
+                    nextToken();
+                    return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), token.comment(CommentStyle.JAVADOC)));
+                }
             }
         }
         if (isRecordStart() && allowRecords) {
@@ -3072,6 +3091,20 @@
             case MONKEYS_AT  : flag = Flags.ANNOTATION; break;
             case DEFAULT     : checkSourceLevel(Feature.DEFAULT_METHODS); flag = Flags.DEFAULT; break;
             case ERROR       : flag = 0; nextToken(); break;
+            case IDENTIFIER  : {
+                if (isNonSealedClassStart(false)) {
+                    flag = Flags.NON_SEALED;
+                    nextToken();
+                    nextToken();
+                    break;
+                }
+                if (isSealedClassStart(false)) {
+                    checkSourceLevel(Feature.SEALED_CLASSES);
+                    flag = Flags.SEALED;
+                    break;
+                }
+                break loop;
+            }
             default: break loop;
             }
             if ((flags & flag) != 0) log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.RepeatedModifier);
@@ -3320,6 +3353,13 @@
                 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK14));
             }
         }
+        if (name == names.sealed) {
+            if (allowSealedTypes) {
+                return Source.JDK15;
+            } else if (shouldWarn) {
+                log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK15));
+            }
+        }
         return null;
     }
 
@@ -3714,9 +3754,18 @@
             nextToken();
             implementing = typeList();
         }
+        List<JCExpression> permitting = List.nil();
+        if (allowSealedTypes && token.kind == IDENTIFIER && token.name() == names.permits) {
+            checkSourceLevel(Feature.SEALED_CLASSES);
+            if ((mods.flags & Flags.SEALED) == 0) {
+                log.error(token.pos, Errors.InvalidPermitsClause(Fragments.ClassIsNotSealed("class")));
+            }
+            nextToken();
+            permitting = qualidentList(false);
+        }
         List<JCTree> defs = classInterfaceOrRecordBody(name, false, false);
         JCClassDecl result = toP(F.at(pos).ClassDef(
-            mods, name, typarams, extending, implementing, defs));
+            mods, name, typarams, extending, implementing, permitting, defs));
         attach(result, dc);
         return result;
     }
@@ -3793,9 +3842,19 @@
             nextToken();
             extending = typeList();
         }
-        List<JCTree> defs = classInterfaceOrRecordBody(name, true, false);
+        List<JCExpression> permitting = List.nil();
+        if (allowSealedTypes && token.kind == IDENTIFIER && token.name() == names.permits) {
+            checkSourceLevel(Feature.SEALED_CLASSES);
+            if ((mods.flags & Flags.SEALED) == 0) {
+                log.error(token.pos, Errors.InvalidPermitsClause(Fragments.ClassIsNotSealed("interface")));
+            }
+            nextToken();
+            permitting = typeList();
+        }
+        List<JCTree> defs;
+        defs = classInterfaceOrRecordBody(name, true, false);
         JCClassDecl result = toP(F.at(pos).ClassDef(
-            mods, name, typarams, null, extending, defs));
+            mods, name, typarams, null, extending, permitting, defs));
         attach(result, dc);
         return result;
     }
@@ -4141,16 +4200,62 @@
     }
 
     protected boolean isRecordStart() {
-     if (token.kind == IDENTIFIER && token.name() == names.record &&
+        if (token.kind == IDENTIFIER && token.name() == names.record &&
             (peekToken(TokenKind.IDENTIFIER, TokenKind.LPAREN) ||
              peekToken(TokenKind.IDENTIFIER, TokenKind.EOF) ||
              peekToken(TokenKind.IDENTIFIER, TokenKind.LT))) {
-          checkSourceLevel(Feature.RECORDS);
-          return true;
-    } else {
-       return false;
-   }
-}
+             checkSourceLevel(Feature.RECORDS);
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    protected boolean isNonSealedClassStart(boolean local) {
+        if (isNonSealedIdentifier(token, 0)) {
+            Token next = S.token(3);
+            return allowedAfterSealedOrNonSealed(next, local, true);
+        }
+        return false;
+    }
+
+    protected boolean isNonSealedIdentifier(Token someToken, int lookAheadOffset) {
+        if (someToken.name() == names.non && peekToken(lookAheadOffset, TokenKind.SUB, TokenKind.IDENTIFIER)) {
+            Token tokenSub = S.token(lookAheadOffset + 1);
+            Token tokenSealed = S.token(lookAheadOffset + 2);
+            if (someToken.endPos == tokenSub.pos &&
+                    tokenSub.endPos == tokenSealed.pos &&
+                    tokenSealed.name() == names.sealed) {
+                checkSourceLevel(Feature.SEALED_CLASSES);
+                return true;
+            }
+        }
+        return false;
+    }
+
+    protected boolean isSealedClassStart(boolean local) {
+        if (token.name() == names.sealed) {
+            Token next = S.token(1);
+            if (allowedAfterSealedOrNonSealed(next, local, false)) {
+                checkSourceLevel(Feature.SEALED_CLASSES);
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean allowedAfterSealedOrNonSealed(Token next, boolean local, boolean currentIsNonSealed) {
+        return local ?
+            switch (next.kind) {
+                case MONKEYS_AT, ABSTRACT, FINAL, STRICTFP, CLASS, INTERFACE, ENUM -> true;
+                default -> false;
+            } :
+            switch (next.kind) {
+                case MONKEYS_AT, PUBLIC, PROTECTED, PRIVATE, ABSTRACT, STATIC, FINAL, STRICTFP, CLASS, INTERFACE, ENUM -> true;
+                case IDENTIFIER -> isNonSealedIdentifier(next, currentIsNonSealed ? 3 : 1) || next.name() == names.sealed;
+                default -> false;
+            };
+    }
 
     /** MethodDeclaratorRest =
      *      FormalParameters BracketsOpt [THROWS TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/PrintingProcessor.java	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/PrintingProcessor.java	Mon Jun 01 17:00:40 2020 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2020, 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
@@ -30,7 +30,6 @@
 import javax.lang.model.element.*;
 import static javax.lang.model.element.ElementKind.*;
 import static javax.lang.model.element.NestingKind.*;
-import static javax.lang.model.element.ModuleElement.DirectiveKind.*;
 import static javax.lang.model.element.ModuleElement.*;
 import javax.lang.model.type.*;
 import javax.lang.model.util.*;
@@ -39,7 +38,6 @@
 import java.io.Writer;
 import java.util.*;
 import java.util.stream.Collectors;
-import java.util.stream.Stream;
 
 
 import com.sun.tools.javac.util.DefinedBy;
@@ -248,6 +246,7 @@
                 }
 
                 printInterfaces(e);
+                printPermittedSubclasses(e);
             }
             writer.println(" {");
             indentation++;
@@ -472,6 +471,7 @@
             case ENUM:
                 modifiers.remove(Modifier.FINAL);
                 modifiers.remove(Modifier.ABSTRACT);
+                modifiers.remove(Modifier.SEALED);
                 break;
 
             case RECORD:
@@ -602,6 +602,17 @@
             }
         }
 
+        private void printPermittedSubclasses(TypeElement e) {
+            List<? extends TypeMirror> subtypes = e.getPermittedSubclasses();
+            if (!subtypes.isEmpty()) { // could remove this check with more complicated joining call
+                writer.print(" permits ");
+                writer.print(subtypes
+                             .stream()
+                             .map(subtype -> subtype.toString())
+                             .collect(Collectors.joining(", ")));
+            }
+        }
+
         private void printThrows(ExecutableElement e) {
             List<? extends TypeMirror> thrownTypes = e.getThrownTypes();
             final int size = thrownTypes.size();
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties	Mon Jun 01 17:00:40 2020 -0400
@@ -2933,6 +2933,9 @@
 compiler.misc.feature.records=\
     records
 
+compiler.misc.feature.sealed.classes=\
+    sealed classes
+
 compiler.warn.underscore.as.identifier=\
     as of release 9, ''_'' is a keyword, and may not be used as an identifier
 
@@ -3436,6 +3439,65 @@
     different case kinds used in the switch
 
 ###
+# errors related to sealed classes
+
+# permits clause
+# 0: fragment
+compiler.err.invalid.permits.clause=\
+    invalid permits clause\n\
+    ({0})
+
+# 0: string
+compiler.misc.class.is.not.sealed=\
+    {0} must be sealed
+
+# 0: type
+compiler.misc.is.a.type.variable=\
+    must not include type variables: {0}
+
+# 0: type
+compiler.misc.is.duplicated=\
+    must not contain duplicates: {0}
+
+# 0: type
+compiler.misc.doesnt.extend.sealed=\
+    subclass {0} must extend sealed class
+
+compiler.misc.must.not.be.same.class=\
+    illegal self-reference in permits clause
+
+# 0: type
+compiler.misc.must.not.be.supertype=\
+    illegal reference to supertype {0}
+
+# other sealed types related errors
+
+compiler.err.sealed.class.must.have.subclasses=\
+    sealed class must have subclasses
+
+# errors in subclasses of sealed classes
+# 0: symbol
+compiler.err.cant.inherit.from.sealed=\
+    class is not allowed to extend sealed class: {0}
+
+# 0: symbol
+compiler.err.non.sealed.with.no.sealed.supertype=\
+    non-sealed modifier not allowed here\n\
+    (class {0} does not have any sealed supertypes)
+
+compiler.err.non.sealed.sealed.or.final.expected=\
+    sealed, non-sealed or final modifiers expected
+
+compiler.err.non.sealed.or.sealed.expected=\
+    sealed or non-sealed modifiers expected
+
+compiler.err.sealed.or.non.sealed.local.classes.not.allowed=\
+    sealed or non-sealed local classes are not allowed
+
+compiler.err.local.classes.cant.extend.sealed=\
+    local classes must not extend sealed classes
+
+###
 # errors related to records
 
 # record components
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java	Mon Jun 01 17:00:40 2020 -0400
@@ -762,6 +762,8 @@
         public JCExpression extending;
         /** the interfaces implemented by this class */
         public List<JCExpression> implementing;
+        /** the subclasses allowed to extend this class, if sealed */
+        public List<JCExpression> permitting;
         /** all variables and methods defined in this class */
         public List<JCTree> defs;
         /** the symbol */
@@ -771,6 +773,7 @@
                            List<JCTypeParameter> typarams,
                            JCExpression extending,
                            List<JCExpression> implementing,
+                           List<JCExpression> permitting,
                            List<JCTree> defs,
                            ClassSymbol sym)
         {
@@ -779,6 +782,7 @@
             this.typarams = typarams;
             this.extending = extending;
             this.implementing = implementing;
+            this.permitting = permitting;
             this.defs = defs;
             this.sym = sym;
         }
@@ -814,6 +818,11 @@
         public List<JCExpression> getImplementsClause() {
             return implementing;
         }
+        @SuppressWarnings("removal")
+        @DefinedBy(Api.COMPILER_TREE)
+        public List<JCExpression> getPermitsClause() {
+            return permitting;
+        }
         @DefinedBy(Api.COMPILER_TREE)
         public List<JCTree> getMembers() {
             return defs;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java	Mon Jun 01 17:00:40 2020 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2020, 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
@@ -564,6 +564,10 @@
                     print(" extends ");
                     printExprs(tree.implementing);
                 }
+                if (tree.permitting.nonEmpty()) {
+                    print(" permits ");
+                    printExprs(tree.permitting);
+                }
             } else {
                 if ((tree.mods.flags & ENUM) != 0)
                     print("enum " + tree.name);
@@ -578,6 +582,10 @@
                     print(" implements ");
                     printExprs(tree.implementing);
                 }
+                if (tree.permitting.nonEmpty()) {
+                    print(" permits ");
+                    printExprs(tree.permitting);
+                }
             }
             print(" ");
             if ((tree.mods.flags & ENUM) != 0) {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java	Mon Jun 01 17:00:40 2020 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2020, 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
@@ -692,49 +692,81 @@
     /** Find the position for reporting an error about a symbol, where
      *  that symbol is defined somewhere in the given tree. */
     public static DiagnosticPosition diagnosticPositionFor(final Symbol sym, final JCTree tree) {
-        JCTree decl = declarationFor(sym, tree);
+        return diagnosticPositionFor(sym, tree, false);
+    }
+
+    public static DiagnosticPosition diagnosticPositionFor(final Symbol sym, final JCTree tree, boolean returnNullIfNotFound) {
+        class DiagScanner extends DeclScanner {
+            DiagScanner(Symbol sym) {
+                super(sym);
+            }
+
+            public void visitIdent(JCIdent that) {
+                if (that.sym == sym) result = that;
+                else super.visitIdent(that);
+            }
+            public void visitSelect(JCFieldAccess that) {
+                if (that.sym == sym) result = that;
+                else super.visitSelect(that);
+            }
+        }
+        DiagScanner s = new DiagScanner(sym);
+        tree.accept(s);
+        JCTree decl = s.result;
+        if (decl == null && returnNullIfNotFound) { return null; }
         return ((decl != null) ? decl : tree).pos();
     }
 
+    public static DiagnosticPosition diagnosticPositionFor(final Symbol sym, final List<? extends JCTree> trees) {
+        return trees.stream().map(t -> TreeInfo.diagnosticPositionFor(sym, t)).filter(t -> t != null).findFirst().get();
+    }
+
+    private static class DeclScanner extends TreeScanner {
+        final Symbol sym;
+
+        DeclScanner(final Symbol sym) {
+            this.sym = sym;
+        }
+
+        JCTree result = null;
+        public void scan(JCTree tree) {
+            if (tree!=null && result==null)
+                tree.accept(this);
+        }
+        public void visitTopLevel(JCCompilationUnit that) {
+            if (that.packge == sym) result = that;
+            else super.visitTopLevel(that);
+        }
+        public void visitModuleDef(JCModuleDecl that) {
+            if (that.sym == sym) result = that;
+            // no need to scan within module declaration
+        }
+        public void visitPackageDef(JCPackageDecl that) {
+            if (that.packge == sym) result = that;
+            else super.visitPackageDef(that);
+        }
+        public void visitClassDef(JCClassDecl that) {
+            if (that.sym == sym) result = that;
+            else super.visitClassDef(that);
+        }
+        public void visitMethodDef(JCMethodDecl that) {
+            if (that.sym == sym) result = that;
+            else super.visitMethodDef(that);
+        }
+        public void visitVarDef(JCVariableDecl that) {
+            if (that.sym == sym) result = that;
+            else super.visitVarDef(that);
+        }
+        public void visitTypeParameter(JCTypeParameter that) {
+            if (that.type != null && that.type.tsym == sym) result = that;
+            else super.visitTypeParameter(that);
+        }
+    }
+
     /** Find the declaration for a symbol, where
      *  that symbol is defined somewhere in the given tree. */
     public static JCTree declarationFor(final Symbol sym, final JCTree tree) {
-        class DeclScanner extends TreeScanner {
-            JCTree result = null;
-            public void scan(JCTree tree) {
-                if (tree!=null && result==null)
-                    tree.accept(this);
-            }
-            public void visitTopLevel(JCCompilationUnit that) {
-                if (that.packge == sym) result = that;
-                else super.visitTopLevel(that);
-            }
-            public void visitModuleDef(JCModuleDecl that) {
-                if (that.sym == sym) result = that;
-                // no need to scan within module declaration
-            }
-            public void visitPackageDef(JCPackageDecl that) {
-                if (that.packge == sym) result = that;
-                else super.visitPackageDef(that);
-            }
-            public void visitClassDef(JCClassDecl that) {
-                if (that.sym == sym) result = that;
-                else super.visitClassDef(that);
-            }
-            public void visitMethodDef(JCMethodDecl that) {
-                if (that.sym == sym) result = that;
-                else super.visitMethodDef(that);
-            }
-            public void visitVarDef(JCVariableDecl that) {
-                if (that.sym == sym) result = that;
-                else super.visitVarDef(that);
-            }
-            public void visitTypeParameter(JCTypeParameter that) {
-                if (that.type != null && that.type.tsym == sym) result = that;
-                else super.visitTypeParameter(that);
-            }
-        }
-        DeclScanner s = new DeclScanner();
+        DeclScanner s = new DeclScanner(sym);
         tree.accept(s);
         return s.result;
     }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java	Mon Jun 01 17:00:40 2020 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2020, 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
@@ -161,11 +161,23 @@
                                 List<JCExpression> implementing,
                                 List<JCTree> defs)
     {
+        return ClassDef(mods, name, typarams, extending, implementing, List.nil(), defs);
+    }
+
+    public JCClassDecl ClassDef(JCModifiers mods,
+                                Name name,
+                                List<JCTypeParameter> typarams,
+                                JCExpression extending,
+                                List<JCExpression> implementing,
+                                List<JCExpression> permitting,
+                                List<JCTree> defs)
+    {
         JCClassDecl tree = new JCClassDecl(mods,
                                      name,
                                      typarams,
                                      extending,
                                      implementing,
+                                     permitting,
                                      defs,
                                      null);
         tree.pos = pos;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeScanner.java	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeScanner.java	Mon Jun 01 17:00:40 2020 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2020, 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
@@ -115,6 +115,7 @@
         scan(tree.typarams);
         scan(tree.extending);
         scan(tree.implementing);
+        scan(tree.permitting);
         scan(tree.defs);
     }
 
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Dependencies.java	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Dependencies.java	Mon Jun 01 17:00:40 2020 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2020, 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
@@ -93,6 +93,7 @@
         MEMBER_ENTER,
         RECORD_PHASE,
         MEMBERS_PHASE,
+        PERMITS_PHASE,
         OTHER;
     }
 
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java	Mon Jun 01 17:00:40 2020 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2020, 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
@@ -25,8 +25,6 @@
 
 package com.sun.tools.javac.util;
 
-import java.util.Set;
-
 /**
  * Access to the compiler's name table.  Standard names are defined,
  * as well as methods to create new names.
@@ -161,6 +159,7 @@
     public final Name Synthetic;
     public final Name Value;
     public final Name Varargs;
+    public final Name PermittedSubclasses;
 
     // members of java.lang.annotation.ElementType
     public final Name ANNOTATION_TYPE;
@@ -203,6 +202,7 @@
     public final Name bootstrap;
 
     public final Name record;
+    public final Name non;
 
     // serialization members, used by records too
     public final Name serialPersistentFields;
@@ -210,6 +210,10 @@
     public final Name writeReplace;
     public final Name readObjectNoData;
 
+    // sealed types
+    public final Name permits;
+    public final Name sealed;
+
     public final Name.Table table;
 
     public Names(Context context) {
@@ -329,6 +333,7 @@
         Synthetic = fromString("Synthetic");
         Value = fromString("Value");
         Varargs = fromString("Varargs");
+        PermittedSubclasses = fromString("PermittedSubclasses");
 
         // members of java.lang.annotation.ElementType
         ANNOTATION_TYPE = fromString("ANNOTATION_TYPE");
@@ -367,11 +372,16 @@
 
         bootstrap = fromString("bootstrap");
         record = fromString("record");
+        non = fromString("non");
 
         serialPersistentFields = fromString("serialPersistentFields");
         writeObject = fromString("writeObject");
         writeReplace = fromString("writeReplace");
         readObjectNoData = fromString("readObjectNoData");
+
+        // sealed types
+        permits = fromString("permits");
+        sealed = fromString("sealed");
     }
 
     protected Name.Table createTable(Options options) {
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.java	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.java	Mon Jun 01 17:00:40 2020 -0400
@@ -112,8 +112,7 @@
             Content tdSummary) {
         ExecutableElement ee = (ExecutableElement)member;
         Content memberLink = HtmlTree.SPAN(HtmlStyle.memberNameLink,
-                writer.getDocLink(context, te, ee,
-                name(ee), false));
+                writer.getDocLink(context, te, ee, name(ee), false));
         Content code = HtmlTree.CODE(memberLink);
         addParameters(ee, code);
         tdSummary.add(code);
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java	Mon Jun 01 17:00:40 2020 -0400
@@ -30,6 +30,7 @@
 import java.util.Set;
 import java.util.SortedSet;
 import java.util.TreeSet;
+import java.util.stream.Collectors;
 
 import javax.lang.model.element.AnnotationMirror;
 import javax.lang.model.element.Element;
@@ -248,6 +249,32 @@
                 }
             }
         }
+        List<? extends TypeMirror> permits = typeElement.getPermittedSubclasses();
+        List<? extends TypeMirror> linkablePermits = permits.stream()
+                .filter(t -> utils.isLinkable(utils.asTypeElement(t)))
+                .collect(Collectors.toList());
+        if (!linkablePermits.isEmpty()) {
+            boolean isFirst = true;
+            for (TypeMirror type : linkablePermits) {
+                TypeElement tDoc = utils.asTypeElement(type);
+                if (isFirst) {
+                    pre.add(DocletConstants.NL);
+                    pre.add("permits ");
+                    isFirst = false;
+                } else {
+                    pre.add(", ");
+                }
+                Content link = getLink(new LinkInfoImpl(configuration,
+                        LinkInfoImpl.Kind.PERMITTED_SUBCLASSES,
+                        type));
+                pre.add(link);
+            }
+            if (linkablePermits.size() < permits.size()) {
+                Content c = new StringContent(resources.getText("doclet.not.exhaustive"));
+                pre.add(" ");
+                pre.add(HtmlTree.SPAN(HtmlStyle.permitsNote, c));
+            }
+        }
         classInfoTree.add(pre);
     }
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/LinkInfoImpl.java	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/LinkInfoImpl.java	Mon Jun 01 17:00:40 2020 -0400
@@ -163,6 +163,11 @@
         CLASS_SIGNATURE_PARENT_NAME,
 
         /**
+         * Permitted subclasses of a sealed type.
+         */
+        PERMITTED_SUBCLASSES,
+
+        /**
          * The header for method documentation copied from parent.
          */
         EXECUTABLE_ELEMENT_COPY,
@@ -360,6 +365,7 @@
             case CLASS_TREE_PARENT:
             case TREE:
             case CLASS_SIGNATURE_PARENT_NAME:
+            case PERMITTED_SUBCLASSES:
                 excludeTypeParameterLinks = true;
                 excludeTypeBounds = true;
                 includeTypeInClassLinkLabel = false;
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java	Mon Jun 01 17:00:40 2020 -0400
@@ -77,6 +77,7 @@
     packages,
     packageHierarchyLabel,
     packageUses,
+    permitsNote,
     searchTagLink,
     searchTagResult,
     serializedPackageContainer,
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties	Mon Jun 01 17:00:40 2020 -0400
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2010, 2020, 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
@@ -62,6 +62,7 @@
 doclet.navEnum=Enum Constants
 doclet.navConstructor=Constr
 doclet.navMethod=Method
+doclet.not.exhaustive=(not exhaustive)
 doclet.Index=Index
 doclet.Window_Single_Index=Index
 doclet.Window_Split_Index={0}-Index
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java	Mon Jun 01 17:00:40 2020 -0400
@@ -504,8 +504,18 @@
                 }
             }
 
+            void addSealed(TypeElement e) {
+                if (e.getModifiers().contains(Modifier.SEALED)) {
+                    append("sealed");
+                } else if (e.getModifiers().contains(Modifier.NON_SEALED)) {
+                    append("non-sealed");
+                }
+            }
+
             void addModifiers(Set<Modifier> modifiers) {
-                modifiers.stream().map(Modifier::toString).forEachOrdered(this::append);
+                modifiers.stream()
+                        .map(Modifier::toString)
+                        .forEachOrdered(this::append);
             }
 
             void append(String s) {
@@ -527,6 +537,7 @@
             public String visitTypeAsInterface(TypeElement e, SortedSet<Modifier> mods) {
                 addVisibilityModifier(mods);
                 addStatic(mods);
+                addSealed(e);
                 return finalString("interface");
             }
 
--- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Attribute.java	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Attribute.java	Mon Jun 01 17:00:40 2020 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2020, 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
@@ -67,6 +67,7 @@
     public static final String RuntimeInvisibleParameterAnnotations = "RuntimeInvisibleParameterAnnotations";
     public static final String RuntimeVisibleTypeAnnotations = "RuntimeVisibleTypeAnnotations";
     public static final String RuntimeInvisibleTypeAnnotations = "RuntimeInvisibleTypeAnnotations";
+    public static final String PermittedSubclasses      = "PermittedSubclasses";
     public static final String Signature                = "Signature";
     public static final String SourceDebugExtension     = "SourceDebugExtension";
     public static final String SourceFile               = "SourceFile";
@@ -142,6 +143,7 @@
             standardAttributes.put(RuntimeVisibleParameterAnnotations, RuntimeVisibleParameterAnnotations_attribute.class);
             standardAttributes.put(RuntimeVisibleTypeAnnotations, RuntimeVisibleTypeAnnotations_attribute.class);
             standardAttributes.put(RuntimeInvisibleTypeAnnotations, RuntimeInvisibleTypeAnnotations_attribute.class);
+            standardAttributes.put(PermittedSubclasses, PermittedSubclasses_attribute.class);
             standardAttributes.put(Signature,         Signature_attribute.class);
             standardAttributes.put(SourceDebugExtension, SourceDebugExtension_attribute.class);
             standardAttributes.put(SourceFile,        SourceFile_attribute.class);
@@ -208,6 +210,7 @@
         R visitRuntimeInvisibleParameterAnnotations(RuntimeInvisibleParameterAnnotations_attribute attr, P p);
         R visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute attr, P p);
         R visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute attr, P p);
+        R visitPermittedSubclasses(PermittedSubclasses_attribute attr, P p);
         R visitSignature(Signature_attribute attr, P p);
         R visitSourceDebugExtension(SourceDebugExtension_attribute attr, P p);
         R visitSourceFile(SourceFile_attribute attr, P p);
--- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ClassWriter.java	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ClassWriter.java	Mon Jun 01 17:00:40 2020 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2020, 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
@@ -696,6 +696,16 @@
         }
 
         @Override
+        public Void visitPermittedSubclasses(PermittedSubclasses_attribute attr, ClassOutputStream out) {
+            int n = attr.subtypes.length;
+            out.writeShort(n);
+            for (int i = 0 ; i < n ; i++) {
+                out.writeShort(attr.subtypes[i]);
+            }
+            return null;
+        }
+
+        @Override
         public Void visitSignature(Signature_attribute attr, ClassOutputStream out) {
             out.writeShort(attr.signature_index);
             return null;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/PermittedSubclasses_attribute.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2019, 2020, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package com.sun.tools.classfile;
+
+import java.io.IOException;
+import java.util.stream.IntStream;
+
+import com.sun.tools.classfile.ConstantPool.CONSTANT_Class_info;
+
+public class PermittedSubclasses_attribute extends Attribute {
+
+    public int[] subtypes;
+
+    PermittedSubclasses_attribute(ClassReader cr, int name_index, int length) throws IOException {
+        super(name_index, length);
+        int number_of_classes = cr.readUnsignedShort();
+        subtypes = new int[number_of_classes];
+        for (int i = 0; i < number_of_classes; i++)
+            subtypes[i] = cr.readUnsignedShort();
+    }
+
+    public PermittedSubclasses_attribute(int name_index, int[] subtypes) {
+        super(name_index, 2);
+        this.subtypes = subtypes;
+    }
+
+    public CONSTANT_Class_info[] getSubtypes(ConstantPool constant_pool) throws ConstantPoolException {
+        return IntStream.of(subtypes)
+                .mapToObj(i -> {
+                    try {
+                        return constant_pool.getClassInfo(i);
+                    } catch (ConstantPoolException ex) {
+                        throw new AssertionError(ex);
+                    }
+                }).toArray(CONSTANT_Class_info[]::new);
+    }
+
+    @Override
+    public <R, D> R accept(Visitor<R, D> visitor, D data) {
+        return visitor.visitPermittedSubclasses(this, data);
+    }
+}
--- a/src/jdk.jdeps/share/classes/com/sun/tools/javap/AttributeWriter.java	Mon Jun 01 22:55:22 2020 +0200
+++ b/src/jdk.jdeps/share/classes/com/sun/tools/javap/AttributeWriter.java	Mon Jun 01 17:00:40 2020 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2020, 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
@@ -68,7 +68,7 @@
 import com.sun.tools.classfile.RuntimeVisibleAnnotations_attribute;
 import com.sun.tools.classfile.RuntimeVisibleParameterAnnotations_attribute;
 import com.sun.tools.classfile.RuntimeVisibleTypeAnnotations_attribute;
-import com.sun.tools.classfile.Signature;
+import com.sun.tools.classfile.PermittedSubclasses_attribute;
 import com.sun.tools.classfile.Signature_attribute;
 import com.sun.tools.classfile.SourceDebugExtension_attribute;
 import com.sun.tools.classfile.SourceFile_attribute;
@@ -83,10 +83,6 @@
 import com.sun.tools.javac.util.Assert;
 import com.sun.tools.javac.util.StringUtils;
 
-import java.util.stream.Collectors;
-import java.util.stream.IntStream;
-import java.util.stream.Stream;
-
 /*
  *  A writer for writing Attributes as text.
  *
@@ -886,6 +882,22 @@
     }
 
     @Override
+    public Void visitPermittedSubclasses(PermittedSubclasses_attribute attr, Void ignore) {
+        println("PermittedSubclasses:");
+        indent(+1);
+        try {
+            CONSTANT_Class_info[] subtypes = attr.getSubtypes(constant_pool);
+            for (int i = 0; i < subtypes.length; i++) {
+                println(constantWriter.stringValue(subtypes[i]));
+            }
+            indent(-1);
+        } catch (ConstantPoolException ex) {
+            throw new AssertionError(ex);
+        }
+        return null;
+    }
+
+    @Override
     public Void visitSignature(Signature_attribute attr, Void ignore) {
         print("Signature: #" + attr.signature_index);
         tab();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/modules/SealedModuleTest.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2020, 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
+ * @bug 8225056
+ * @modules java.base/jdk.internal.misc
+ * @library /test/lib ..
+ * @compile sealedP1/SuperClass.jcod
+ * @compile --enable-preview --source ${jdk.version} sealedP1/C1.java sealedP2/C2.java sealedP3/C3.java
+ * @build sun.hotspot.WhiteBox
+ * @compile/module=java.base java/lang/ModuleHelper.java
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. --enable-preview -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI SealedModuleTest
+ */
+
+public class SealedModuleTest {
+
+    // Test sub-classing a sealed super class in a named module. In this test,
+    // sealed class sealedP1/SuperClass permits sealedP1.C1, sealedP2.C2, and
+    // sealedP3.C3.  All three of those classes extend sealedP1/SuperClass.
+
+    public static void main(String args[]) throws Throwable {
+        Object m1x, m2x;
+
+        // Get the class loader for SealedModuleTest and assume it's also used
+        // to load the other classes.
+        ClassLoader this_cldr = AccessCheckRead.class.getClassLoader();
+
+        // Define a module for packages sealedP1 and sealedP2.
+        m1x = ModuleHelper.ModuleObject("module_one", this_cldr,
+                                        new String[] { "sealedP1", "sealedP2" });
+        ModuleHelper.DefineModule(m1x, false, "9.0", "m1x/here",
+                                  new String[] { "sealedP1", "sealedP2" });
+
+        // Define a module for package sealedP3 with the same class loader.
+        m2x = ModuleHelper.ModuleObject("module_two", this_cldr, new String[] { "sealedP3" });
+        ModuleHelper.DefineModule(m2x, false, "9.0", "m2x/there", new String[] { "sealedP3" });
+
+        // Make package sealedP1 in m1x visible to everyone because it contains
+        // the super class for C1, C2, and C3.
+        ModuleHelper.AddModuleExportsToAll(m1x, "sealedP1");
+        ModuleHelper.AddReadsModule(m2x, m1x);
+
+        // Test subtype in the same named package and named module as its super
+        // class.  This should succeed.
+        // Class sealedP1.C1 extends class sealedP1.SuperClass.
+        Class p1_C1_class = Class.forName("sealedP1.C1");
+
+        // Test non-public class in same module but different package than its
+        // super class. This should throw ICCE.
+        // Class sealedP2.C2 extends class sealedP1.SuperClass.
+        try {
+            Class p2_C2_class = Class.forName("sealedP2.C2");
+            throw new RuntimeException("Expected IncompatibleClassChangeError exception not thrown");
+        } catch (IncompatibleClassChangeError e) {
+            if (!e.getMessage().contains("cannot inherit from sealed class")) {
+                throw new RuntimeException("Wrong IncompatibleClassChangeError exception thrown: " + e.getMessage());
+            }
+        }
+
+        // Test subtype in a different module than its super type.  This should
+        // fail even though they have the same class loader.
+        // Class sealedP3.C3 extends class sealedP1.SuperClass.
+        try {
+            Class p3_C3_class = Class.forName("sealedP3.C3");
+            throw new RuntimeException("Expected IncompatibleClassChangeError exception not thrown");
+        } catch (IncompatibleClassChangeError e) {
+            if (!e.getMessage().contains("cannot inherit from sealed class")) {
+                throw new RuntimeException("Wrong IncompatibleClassChangeError exception thrown: " + e.getMessage());
+            }
+        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/modules/TEST.properties	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,23 @@
+#
+# Copyright (c) 2020, 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.
+#
+allowSmartActionArgs=true
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/modules/sealedP1/C1.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2020, 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.
+ */
+
+// Small class used by SealedModuleTest
+package sealedP1;
+
+public final class C1 extends sealedP1.SuperClass {
+
+    public C1() { }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/modules/sealedP1/SuperClass.jcod	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2020, 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 sealed class cannot be a java file because its permits clause names
+// a class in another package causing javac to issue a compilation error.
+//
+// Sealed super class used by SealedModuleTest.
+//
+// package sealedP1;
+//
+// public sealed class SuperClass permits sealedP1.C1, sealedP2.C2, sealedP3.C3 { }
+
+class sealedP1/SuperClass {
+  0xCAFEBABE;
+  65535; // minor version
+  59; // version
+  [20] { // 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 "sealedP1/SuperClass"; // #8     at 0x3C
+    Utf8 "Code"; // #9     at 0x52
+    Utf8 "LineNumberTable"; // #10     at 0x59
+    Utf8 "SourceFile"; // #11     at 0x6B
+    Utf8 "SuperClass.java"; // #12     at 0x78
+    Utf8 "PermittedSubclasses"; // #13     at 0x8A
+    class #15; // #14     at 0x9E
+    Utf8 "sealedP1/C1"; // #15     at 0xA1
+    class #17; // #16     at 0xAF
+    Utf8 "sealedP2/C2"; // #17     at 0xB2
+    class #19; // #18     at 0xC0
+    Utf8 "sealedP3/C3"; // #19     at 0xC3
+  } // Constant Pool
+
+  0x0021; // access [ ACC_PUBLIC ACC_SUPER ]
+  #7;// this_cpx
+  #2;// super_cpx
+
+  [0] { // Interfaces
+  } // Interfaces
+
+  [0] { // fields
+  } // fields
+
+  [1] { // methods
+    { // Member at 0xDD
+      0x0001; // access
+      #5; // name_cpx
+      #6; // sig_cpx
+      [1] { // Attributes
+        Attr(#9, 29) { // Code at 0xE5
+          1; // max_stack
+          1; // max_locals
+          Bytes[5]{
+            0x2AB70001B1;
+          }
+          [0] { // Traps
+          } // end Traps
+          [1] { // Attributes
+            Attr(#10, 6) { // LineNumberTable at 0xFC
+              [1] { // LineNumberTable
+                0  28; //  at 0x0108
+              }
+            } // end LineNumberTable
+          } // Attributes
+        } // end Code
+      } // Attributes
+    } // Member
+  } // methods
+
+  [2] { // Attributes
+    Attr(#11, 2) { // SourceFile at 0x010A
+      #12;
+    } // end SourceFile
+    ;
+    Attr(#13, 8) { // PermittedSubclasses at 0x0112
+      0x0003000E00100012;
+    } // end PermittedSubclasses
+  } // Attributes
+} // end class sealedP1/SuperClass
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/modules/sealedP2/C2.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2020, 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.
+ */
+
+// Small class used by SealedModuleTest
+package sealedP2;
+
+final class C2 extends sealedP1.SuperClass {
+    public void method2() { }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/modules/sealedP3/C3.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2020, 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.
+ */
+
+// Small class used by SealedModuleTest
+package sealedP3;
+
+public final class C3 extends sealedP1.SuperClass {
+    public void method3() { }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/sealedClasses/AbstractSealedTest.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2020, 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
+ * @bug 8225056
+ * @compile --enable-preview -source ${jdk.version} AbstractSealedTest.java
+ * @run main/othervm --enable-preview AbstractSealedTest
+ */
+
+// Test that a sealed class can be abstract
+public class AbstractSealedTest {
+
+    abstract sealed class AbstractShape permits Circle {
+        abstract void draw();
+    }
+
+    final class Circle extends AbstractShape {
+        void draw() {}
+    }
+
+    Circle circle = new Circle();
+
+    public static void main(String... args) { }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/sealedClasses/GetPermittedSubclasses.jcod	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,560 @@
+/*
+ * Copyright (c) 2020, 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 PermittedSubclasses attribute that do not exist.
+// Test that this does not prevent JVM_GetPermittedSubclasses() from returning
+// their names.
+//
+// sealed class NoLoadSubclasses permits iDontExist, I/Dont/Exist/Either { }
+//
+class NoLoadSubclasses {
+  0xCAFEBABE;
+  65535; // minor version
+  59; // 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 "NoLoadSubclasses"; // #8     at 0x3C
+    Utf8 "Code"; // #9     at 0x4D
+    Utf8 "LineNumberTable"; // #10     at 0x54
+    Utf8 "SourceFile"; // #11     at 0x66
+    Utf8 "NoLoadSubclasses.java"; // #12     at 0x73
+    Utf8 "PermittedSubclasses"; // #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
+
+  0x0020; // access [ ACC_SUPER ]
+  #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) { // PermittedSubclasses at 0xF6
+      0x0002000E0010;
+    } // end PermittedSubclasses
+    ;
+    Attr(#11, 2) { // SourceFile at 0xEE
+      #12;
+    } // end SourceFile
+  } // Attributes
+} // end class NoLoadSubclasses
+
+
+
+// This class contains an empty PermittedSubclasses attribute.  Test that
+// this causes an exception to get thrown.
+class NoSubclasses {
+  0xCAFEBABE;
+  65535; // minor version
+  59; // 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 "NoSubclasses"; // #8     at 0x3C
+    Utf8 "Code"; // #9     at 0x49
+    Utf8 "LineNumberTable"; // #10     at 0x50
+    Utf8 "SourceFile"; // #11     at 0x62
+    Utf8 "NoSubclasses.java"; // #12     at 0x6F
+    Utf8 "PermittedSubclasses"; // #13     at 0x81
+  } // Constant Pool
+
+  0x0020; // access [ ACC_SUPER ]
+  #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) { // PermittedSubclasses at 0xE0
+      0x0000;
+    } // end PermittedSubclasses
+  } // Attributes
+} // end class NoSubclasses
+
+
+
+// This class has a PermittedSubclasses attribute but an old class file version.
+// The PermittedSubclasses 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 "PermittedSubclasses"; // #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) { // PermittedSubclasses at 0xF6
+      0x0002000E0010;
+    } // end PermittedSubclasses
+  } // Attributes
+} // end class OldClassFile
+
+
+
+// This class has a corrupted PermittedSubclasses attribute.  Attempts to load it
+// should throw ClassFormatError.
+class BadPermittedAttr {
+  0xCAFEBABE;
+  65535; // minor version
+  59; // 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 "PermittedSubclasses"; // #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
+
+  0x0020; // access [ ACC_SUPER ]
+  #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) { // PermittedSubclasses at 0xF6
+      0x0002000F0010;
+    } // end PermittedSubclasses
+  } // Attributes
+} // end class BadPermittedAttr
+
+
+// This class has a PermittedSubclasses attribute and is marked Final.
+// Loading this class should throw a ClassFormatError exception.
+//
+// sealed class SealedButFinal permits iDontExist, I/Dont/Exist/Either { }
+//
+class SealedButFinal {
+  0xCAFEBABE;
+  65535; // minor version
+  59; // 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 "SealedButFinal"; // #8     at 0x3C
+    Utf8 "Code"; // #9     at 0x4D
+    Utf8 "LineNumberTable"; // #10     at 0x54
+    Utf8 "SourceFile"; // #11     at 0x66
+    Utf8 "SealedButFinal.java"; // #12     at 0x73
+    Utf8 "PermittedSubclasses"; // #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) { // PermittedSubclasses at 0xF6
+      0x0002000E0010;
+    } // end PermittedSubclasses
+  } // Attributes
+} // end class SealedButFinal
+
+
+// This class contains a PermittedSubclasses attribute with an invalid class
+// name.  Test that this causes a ClassFormatError exception to get thrown.
+//
+// sealed class BadPermittedSubclassEntry permits iDont;;Exist, I/Dont/Exist/Either { }
+//
+class BadPermittedSubclassEntry {
+  0xCAFEBABE;
+  65535; // minor version
+  59; // 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 "BadPermittedSubclassEntry"; // #8     at 0x3C
+    Utf8 "Code"; // #9     at 0x4D
+    Utf8 "LineNumberTable"; // #10     at 0x54
+    Utf8 "SourceFile"; // #11     at 0x66
+    Utf8 "BadPermittedSubclassEntry.java"; // #12     at 0x73
+    Utf8 "PermittedSubclasses"; // #13     at 0x89
+    class #15; // #14     at 0x9D
+    Utf8 "iDont;;Exist"; // #15     at 0xA0
+    class #17; // #16     at 0xAA
+    Utf8 "I/Dont/Exist/Either"; // #17     at 0xAD
+  } // Constant Pool
+
+  0x0020; // access [ ACC_SUPER ]
+  #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) { // PermittedSubclasses at 0xF6
+      0x0002000E0010;
+    } // end PermittedSubclasses
+    ;
+    Attr(#11, 2) { // SourceFile at 0xEE
+      #12;
+    } // end SourceFile
+  } // Attributes
+}
+
+// This class contains a PermittedSubclasses attribute with an empty class
+// name.  Test that this causes a ClassFormatError exception to get thrown.
+//
+// sealed class EmptyPermittedSubclassEntry permits "", I/Dont/Exist/Either { }
+//
+class EmptyPermittedSubclassEntry {
+  0xCAFEBABE;
+  65535; // minor version
+  59; // 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 "EmptyPermittedSubclassEntry"; // #8     at 0x3C
+    Utf8 "Code"; // #9     at 0x4D
+    Utf8 "LineNumberTable"; // #10     at 0x54
+    Utf8 "SourceFile"; // #11     at 0x66
+    Utf8 "EmptyPermittedSubclassEntry.java"; // #12     at 0x73
+    Utf8 "PermittedSubclasses"; // #13     at 0x89
+    class #15; // #14     at 0x9D
+    Utf8 ""; // #15     at 0xA0
+    class #17; // #16     at 0xAA
+    Utf8 "I/Dont/Exist/Either"; // #17     at 0xAD
+  } // Constant Pool
+
+  0x0020; // access [ ACC_SUPER ]
+  #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) { // PermittedSubclasses at 0xF6
+      0x0002000E0010;
+    } // end PermittedSubclasses
+    ;
+    Attr(#11, 2) { // SourceFile at 0xEE
+      #12;
+    } // end SourceFile
+  } // Attributes
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/sealedClasses/GetPermittedSubclassesTest.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2020, 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
+ * @bug 8225056
+ * @compile GetPermittedSubclasses.jcod
+ * @compile --enable-preview -source ${jdk.version} GetPermittedSubclassesTest.java
+ * @run main/othervm --enable-preview GetPermittedSubclassesTest
+ */
+
+import java.lang.constant.ClassDesc;
+import java.util.ArrayList;
+
+// Test Class GetPermittedSubtpes() and Class.isSealed() APIs.
+public class GetPermittedSubclassesTest {
+
+    sealed class Sealed1 permits Sub1 {}
+
+    final class Sub1 extends Sealed1 implements SealedI1 {}
+
+    sealed interface SealedI1 permits NotSealed, Sub1, Extender {}
+
+    non-sealed interface Extender extends SealedI1 { }
+
+    final class FinalC implements Extender {}
+
+    final class NotSealed implements SealedI1 {}
+
+    final class Final4 {}
+
+    public static void testSealedInfo(Class<?> c, String[] expected) {
+        Object[] permitted = c.permittedSubclasses();
+
+        if (permitted.length != expected.length) {
+            throw new RuntimeException(
+                "Unexpected number of permitted subclasses for: " + c.toString());
+        }
+
+        if (permitted.length > 0) {
+            if (!c.isSealed()) {
+                throw new RuntimeException("Expected sealed class: " + c.toString());
+            }
+
+            // Create ArrayList of permitted subclasses class names.
+            ArrayList<String> permittedNames = new ArrayList<String>();
+            for (int i = 0; i < permitted.length; i++) {
+                permittedNames.add(((ClassDesc)permitted[i]).descriptorString());
+            }
+
+            if (permittedNames.size() != expected.length) {
+                throw new RuntimeException(
+                    "Unexpected number of permitted names for: " + c.toString());
+            }
+
+            // Check that expected class names are in the permitted subclasses list.
+            for (int i = 0; i < expected.length; i++) {
+                if (!permittedNames.contains(expected[i])) {
+                    throw new RuntimeException(
+                         "Expected class not found in permitted subclases list, super class: " +
+                         c.getName() + ", expected class: " + expected[i]);
+                }
+            }
+        } else {
+            // Must not be sealed if no permitted subclasses.
+            if (c.isSealed()) {
+                throw new RuntimeException("Unexpected sealed class: " + c.toString());
+            }
+        }
+    }
+
+    public static void testBadSealedClass(String className, String expectedCFEMessage) throws Throwable {
+        try {
+            Class.forName(className);
+            throw new RuntimeException("Expected ClassFormatError exception not thrown for " + className);
+        } catch (ClassFormatError cfe) {
+            if (!cfe.getMessage().contains(expectedCFEMessage)) {
+                throw new RuntimeException(
+                    "Class " + className + " got unexpected ClassFormatError exception: " + cfe.getMessage());
+            }
+        }
+    }
+
+    public static void main(String... args) throws Throwable {
+        testSealedInfo(SealedI1.class, new String[] {"LGetPermittedSubclassesTest$NotSealed;",
+                                                     "LGetPermittedSubclassesTest$Sub1;",
+                                                     "LGetPermittedSubclassesTest$Extender;"});
+        testSealedInfo(Sealed1.class, new String[] {"LGetPermittedSubclassesTest$Sub1;"});
+        testSealedInfo(Final4.class, new String[] { });
+        testSealedInfo(NotSealed.class, new String[] { });
+
+        // Test class with PermittedSubclasses attribute but old class file version.
+        testSealedInfo(OldClassFile.class, new String[] { });
+
+        // Test class with an empty PermittedSubclasses attribute.
+        testBadSealedClass("NoSubclasses", "PermittedSubclasses attribute is empty");
+
+        // Test returning names of non-existing classes.
+        testSealedInfo(NoLoadSubclasses.class, new String[]{"LiDontExist;", "LI/Dont/Exist/Either;"});
+
+        // Test that loading a class with a corrupted PermittedSubclasses attribute
+        // causes a ClassFormatError.
+        testBadSealedClass("BadPermittedAttr",
+                          "Permitted subclass class_info_index 15 has bad constant type");
+
+        // Test that loading a sealed final class with a PermittedSubclasses
+        // attribute causes a ClassFormatError.
+        testBadSealedClass("SealedButFinal", "PermittedSubclasses attribute in final class");
+
+        // Test that loading a sealed class with a bad class name in its PermittedSubclasses
+        // attribute causes a ClassFormatError.
+        testBadSealedClass("BadPermittedSubclassEntry", "Illegal class name \"iDont;;Exist\" in class file");
+
+        // Test that loading a sealed class with an empty class name in its PermittedSubclasses
+        // attribute causes a ClassFormatError.
+        testBadSealedClass("EmptyPermittedSubclassEntry", "Illegal class name \"\" in class file");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/sealedClasses/OverrideSealedTest.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2020, 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
+ * @bug 8225056
+ * @compile --enable-preview -source ${jdk.version} OverrideSealedTest.java
+ * @run main/othervm --enable-preview OverrideSealedTest
+ */
+
+// Test that a method in a sealed class or interface can be overridden.
+public class OverrideSealedTest {
+
+    sealed class Rectangle permits Square {
+        public String draw() { return "rectangle"; }
+    }
+
+    final class Square extends Rectangle {
+        public String draw() { return "square"; }
+    }
+
+    Rectangle r = new Rectangle();
+    Rectangle rs = new Square();
+    Square s = new Square();
+
+
+    public sealed interface Shape permits Circle {
+        default String name() { return "shape"; }
+    }
+
+    final class Circle implements Shape {
+        public String name() { return "circle"; }
+    }
+
+    Shape sc = new Circle();
+    Circle c = new Circle();
+
+
+    public static void main(String... args) {
+        OverrideSealedTest ost = new OverrideSealedTest();
+        if (ost.r.draw() != "rectangle")
+            throw new RuntimeException("Bad value returned by draw(): " + ost.r.draw());
+        if (ost.rs.draw() != "square")
+            throw new RuntimeException("Bad value returned by draw(): " + ost.rs.draw());
+        if (ost.s.draw() != "square")
+            throw new RuntimeException("Bad value returned by draw(): " + ost.s.draw());
+
+        if (ost.sc.name() != "circle")
+            throw new RuntimeException("Bad value returned by name(): " + ost.sc.name());
+        if (ost.c.name() != "circle")
+            throw new RuntimeException("Bad value returned by name(): " + ost.c.name());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/sealedClasses/Pkg/NotPermitted.jcod	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2020, 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 was written using jcod because it implements sealed interface
+// SealedInterface but is not listed in its PermittedSubclasses attribute.
+// It consists of the following:
+//
+//    package Pkg;
+//    public class NotPermitted implements SealedInterface { }
+//
+class Pkg/NotPermitted {
+  0xCAFEBABE;
+  0; // minor version
+  59; // version
+  [15] { // 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 "Pkg/NotPermitted"; // #8     at 0x3C
+    class #10; // #9     at 0x4C
+    Utf8 "Pkg/SealedInterface"; // #10     at 0x4F
+    Utf8 "Code"; // #11     at 0x65
+    Utf8 "LineNumberTable"; // #12     at 0x6C
+    Utf8 "SourceFile"; // #13     at 0x7E
+    Utf8 "NotPermitted.java"; // #14     at 0x8B
+  } // Constant Pool
+
+  0x0031; // access [ ACC_PUBLIC ACC_SUPER ACC_FINAL ]
+  #7;// this_cpx
+  #2;// super_cpx
+
+  [1] { // Interfaces
+    #9;
+  } // Interfaces
+
+  [0] { // fields
+  } // fields
+
+  [1] { // methods
+    { // Member at 0xAA
+      0x0001; // access
+      #5; // name_cpx
+      #6; // sig_cpx
+      [1] { // Attributes
+        Attr(#11, 29) { // Code at 0xB2
+          1; // max_stack
+          1; // max_locals
+          Bytes[5]{
+            0x2AB70001B1;
+          };
+          [0] { // Traps
+          } // end Traps
+          [1] { // Attributes
+            Attr(#12, 6) { // LineNumberTable at 0xC9
+              [1] { // LineNumberTable
+                0  26; //  at 0xD5
+              }
+            } // end LineNumberTable
+          } // Attributes
+        } // end Code
+      } // Attributes
+    } // Member
+  } // methods
+
+  [1] { // Attributes
+    Attr(#13, 2) { // SourceFile at 0xD7
+      #14;
+    } // end SourceFile
+  } // Attributes
+} // end class Pkg/NotPermitted
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/sealedClasses/Pkg/Permitted.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2020, 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.
+ */
+
+package Pkg;
+
+final class Permitted implements SealedInterface { }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/sealedClasses/Pkg/SealedInterface.jcod	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2020, 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 sealed class cannot be a java file because its permits clause names
+// a class in another package causing javac to issue a compilation error.
+//
+// package Pkg;
+//
+// sealed public interface SealedInterface permits Permitted, otherPkg.WrongPackage { }
+
+class Pkg/SealedInterface {
+  0xCAFEBABE;
+  65535; // minor version
+  59; // version
+  [12] { // Constant Pool
+    ; // first element is empty
+    class #2; // #1     at 0x0A
+    Utf8 "Pkg/SealedInterface"; // #2     at 0x0D
+    class #4; // #3     at 0x23
+    Utf8 "java/lang/Object"; // #4     at 0x26
+    Utf8 "SourceFile"; // #5     at 0x39
+    Utf8 "SealedInterface.java"; // #6     at 0x46
+    Utf8 "PermittedSubclasses"; // #7     at 0x5D
+    class #9; // #8     at 0x71
+    Utf8 "Pkg/Permitted"; // #9     at 0x74
+    class #11; // #10     at 0x84
+    Utf8 "otherPkg/WrongPackage"; // #11     at 0x87
+  } // Constant Pool
+
+  0x0601; // access [ ACC_PUBLIC ACC_INTERFACE ]
+  #1;// this_cpx
+  #3;// super_cpx
+
+  [0] { // Interfaces
+  } // Interfaces
+
+  [0] { // fields
+  } // fields
+
+  [0] { // methods
+  } // methods
+
+  [2] { // Attributes
+    Attr(#5, 2) { // SourceFile at 0xAD
+      #6;
+    } // end SourceFile
+    ;
+    Attr(#7, 6) { // PermittedSubtclasses at 0xB5
+      0x00020008000A;
+    } // end PermittedSubclasses
+  } // Attributes
+} // end class Pkg/SealedInterface
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/sealedClasses/RedefineSealedClass.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2020, 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
+ * @bug 8225056
+ * @library /test/lib
+ * @summary Test that a class that is a sealed class can be redefined.
+ * @modules java.base/jdk.internal.misc
+ * @modules java.instrument
+ *          jdk.jartool/sun.tools.jar
+ * @compile --enable-preview -source ${jdk.version} RedefineSealedClass.java
+ * @run main/othervm --enable-preview RedefineSealedClass buildagent
+ * @run main/othervm/timeout=6000 --enable-preview RedefineSealedClass runtest
+ */
+
+import java.io.FileNotFoundException;
+import java.io.PrintWriter;
+import java.lang.RuntimeException;
+import java.lang.instrument.ClassFileTransformer;
+import java.lang.instrument.Instrumentation;
+import java.security.ProtectionDomain;
+import java.lang.instrument.IllegalClassFormatException;
+import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.process.OutputAnalyzer;
+
+public class RedefineSealedClass {
+
+    final class A extends Tester { }
+    final class B extends Tester { }
+
+    sealed static class Tester permits A, B {}
+
+    static class LoggingTransformer implements ClassFileTransformer {
+
+        public LoggingTransformer() {}
+
+        public byte[] transform(ClassLoader loader, String className,
+                                Class classBeingRedefined, ProtectionDomain protectionDomain,
+                                byte[] classfileBuffer) throws IllegalClassFormatException {
+            return null;
+        }
+    }
+
+    public static void premain(String agentArgs, Instrumentation inst) throws Exception {
+        LoggingTransformer t = new LoggingTransformer();
+        inst.addTransformer(t, true);
+        {
+            Class demoClass = Class.forName("RedefineSealedClass$Tester");
+            inst.retransformClasses(demoClass);
+        }
+    }
+
+    private static void buildAgent() {
+        try {
+            ClassFileInstaller.main("RedefineSealedClass");
+        } catch (Exception e) {
+            throw new RuntimeException("Could not write agent classfile", e);
+        }
+
+        try {
+            PrintWriter pw = new PrintWriter("MANIFEST.MF");
+            pw.println("Premain-Class: RedefineSealedClass");
+            pw.println("Agent-Class: RedefineSealedClass");
+            pw.println("Can-Redefine-Classes: true");
+            pw.println("Can-Retransform-Classes: true");
+            pw.close();
+        } catch (FileNotFoundException e) {
+            throw new RuntimeException("Could not write manifest file for the agent", e);
+        }
+
+        sun.tools.jar.Main jarTool = new sun.tools.jar.Main(System.out, System.err, "jar");
+        if (!jarTool.run(new String[] { "-cmf", "MANIFEST.MF", "redefineagent.jar", "RedefineSealedClass.class" })) {
+            throw new RuntimeException("Could not write the agent jar file");
+        }
+    }
+
+    public static void main(String argv[]) throws Exception {
+        if (argv.length == 1 && argv[0].equals("buildagent")) {
+            buildAgent();
+            return;
+        }
+        if (argv.length == 1 && argv[0].equals("runtest")) {
+            String[] javaArgs1 = { "-XX:MetaspaceSize=12m", "-XX:MaxMetaspaceSize=12m",
+                                   "-javaagent:redefineagent.jar", "--enable-preview",
+                                   "RedefineSealedClass"};
+            ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(javaArgs1);
+            OutputAnalyzer output = new OutputAnalyzer(pb.start());
+            output.shouldNotContain("processing of -javaagent failed");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/sealedClasses/SealedTest.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2020, 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
+ * @bug 8225056
+ * @compile --enable-preview -source ${jdk.version} SealedTest.java
+ * @run main/othervm --enable-preview SealedTest
+ */
+
+public class SealedTest {
+
+    sealed class Sealed1 permits Sub1 {}
+
+    final class Sub1 extends Sealed1 {}
+
+    sealed interface SealedI1 permits Sub2 {}
+
+    final class Sub2 extends Sealed2 implements SealedI1 {}
+
+    sealed class Sealed2 permits Sub2 {}
+
+    Sub1 sub1 = new Sub1();
+    Sub2 sub2 = new Sub2();
+
+    public static void main(String... args) {
+        System.out.println("Basic testing of sealed types");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/sealedClasses/SealedUnnamedModuleIntfTest.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2020, 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
+ * @bug 8225056
+ * @compile Pkg/SealedInterface.jcod Pkg/NotPermitted.jcod
+ * @compile --enable-preview -source ${jdk.version} Pkg/Permitted.java otherPkg/WrongPackage.java
+ * @run main/othervm --enable-preview SealedUnnamedModuleIntfTest
+ */
+
+public class SealedUnnamedModuleIntfTest {
+
+    public static void main(String args[]) throws Throwable {
+
+        // Classes Permitted, NotPermitted, and WrongPackage all try to implement
+        // sealed interface SealedInterface.
+        // Interface SealedInterface permits classes Permitted and WrongPackage.
+
+        // Test non-public permitted subclass and superclass in unnamed module and
+        // same package.  This should succeed.
+        Class permitted = Class.forName("Pkg.Permitted");
+
+        // Test unpermitted subclass and superclass in unnamed module and same package.
+        // This should throw an exception.
+        try {
+            Class notPermitted = Class.forName("Pkg.NotPermitted");
+            throw new RuntimeException("Expected IncompatibleClassChangeError exception not thrown");
+        } catch (IncompatibleClassChangeError e) {
+            if (!e.getMessage().contains("cannot implement sealed interface")) {
+                throw new RuntimeException("Wrong IncompatibleClassChangeError exception thrown: " + e.getMessage());
+            }
+        }
+
+        // Test public permitted subclass and superclass in same unnamed module but in
+        // different packages.  This should not throw an exception.
+        Class wrongPkg = Class.forName("otherPkg.WrongPackage");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/sealedClasses/SealedUnnamedModuleTest.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2020, 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
+ * @bug 8225056
+ * @compile planets/OuterPlanets.jcod planets/Mars.jcod
+ * @compile --enable-preview -source ${jdk.version} planets/Neptune.java asteroids/Pluto.java
+ * @run main/othervm --enable-preview SealedUnnamedModuleTest
+ */
+
+public class SealedUnnamedModuleTest {
+
+    public static void main(String args[]) throws Throwable {
+
+        // Classes Neptune, Mars, and Pluto all try to extend sealed class OuterPlanets.
+        // Class OuterPlanets permits Nepturn and Pluto.
+
+        // Test permitted subclass and superclass in unnamed module and same package.
+        // This should succeed.
+        Class neptune = Class.forName("planets.Neptune");
+
+        // Test unpermitted subclass and superclass in unnamed module and same package.
+        // This should fail.
+        try {
+            Class mars = Class.forName("planets.Mars");
+            throw new RuntimeException("Expected IncompatibleClassChangeError exception not thrown");
+        } catch (IncompatibleClassChangeError e) {
+            if (!e.getMessage().contains("cannot inherit from sealed class")) {
+                throw new RuntimeException("Wrong IncompatibleClassChangeError exception thrown: " + e.getMessage());
+            }
+        }
+
+        // Test non-public permitted subclass and superclass in same unnamed module but
+        // in different packages.  This should fail.
+        try {
+            Class pluto = Class.forName("asteroids.Pluto");
+            throw new RuntimeException("Expected IncompatibleClassChangeError exception not thrown");
+        } catch (IncompatibleClassChangeError e) {
+            if (!e.getMessage().contains("cannot inherit from sealed class")) {
+                throw new RuntimeException("Wrong IncompatibleClassChangeError exception thrown: " + e.getMessage());
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/sealedClasses/TEST.properties	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,23 @@
+#
+# Copyright (c) 2020, 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.
+#
+allowSmartActionArgs=true
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/sealedClasses/asteroids/Pluto.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2020, 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.
+ */
+
+package asteroids;
+
+final class Pluto extends planets.OuterPlanets { }
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/sealedClasses/otherPkg/WrongPackage.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2020, 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.
+ */
+
+package otherPkg;
+
+public final class WrongPackage implements Pkg.SealedInterface { }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/sealedClasses/planets/Mars.jcod	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2020, 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 was written using jcod because it extends sealed class
+// planets.OuterPlanets but is not listed in its PermittedSubclasses
+// attribute.  It consists of the following:
+//
+//    package planets;
+//    public class Mars extends OuterPlanets { }
+//
+class planets/Mars {
+  0xCAFEBABE;
+  0; // minor version
+  59; // version
+  [13] { // Constant Pool
+    ; // first element is empty
+    Method #2 #3; // #1     at 0x0A
+    class #4; // #2     at 0x0F
+    NameAndType #5 #6; // #3     at 0x12
+    Utf8 "planets/OuterPlanets"; // #4     at 0x17
+    Utf8 "<init>"; // #5     at 0x2E
+    Utf8 "()V"; // #6     at 0x37
+    class #8; // #7     at 0x3D
+    Utf8 "planets/Mars"; // #8     at 0x40
+    Utf8 "Code"; // #9     at 0x52
+    Utf8 "LineNumberTable"; // #10     at 0x59
+    Utf8 "SourceFile"; // #11     at 0x6B
+    Utf8 "Mars.java"; // #12     at 0x78
+  } // Constant Pool
+
+  0x0031; // access [ ACC_PUBLIC ACC_SUPER ACC_FINAL ]
+  #7;// this_cpx
+  #2;// super_cpx
+
+  [0] { // Interfaces
+  } // Interfaces
+
+  [0] { // fields
+  } // fields
+
+  [1] { // methods
+    { // Member at 0x93
+      0x0001; // access
+      #5; // name_cpx
+      #6; // sig_cpx
+      [1] { // Attributes
+        Attr(#9, 29) { // Code at 0x9B
+          1; // max_stack
+          1; // max_locals
+          Bytes[5]{
+            0x2AB70001B1;
+          };
+          [0] { // Traps
+          } // end Traps
+          [1] { // Attributes
+            Attr(#10, 6) { // LineNumberTable at 0xB2
+              [1] { // LineNumberTable
+                0  3; //  at 0xBE
+              }
+            } // end LineNumberTable
+          } // Attributes
+        } // end Code
+      } // Attributes
+    } // Member
+  } // methods
+
+  [1] { // Attributes
+    Attr(#11, 2) { // SourceFile at 0xC0
+      #12;
+    } // end SourceFile
+  } // Attributes
+} // end class planets/Mars
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/sealedClasses/planets/Neptune.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2020, 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.
+ */
+
+package planets;
+
+public final class Neptune extends OuterPlanets { }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/sealedClasses/planets/OuterPlanets.jcod	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2019, 2020, 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.
+ */
+
+// package planets;
+//
+// sealed public class OuterPlanets permits Neptune, asteroids.Pluto { }
+
+class planets/OuterPlanets {
+  0xCAFEBABE;
+  65535; // minor version
+  59; // 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 "planets/OuterPlanets"; // #8     at 0x3C
+    Utf8 "Code"; // #9     at 0x53
+    Utf8 "LineNumberTable"; // #10     at 0x5A
+    Utf8 "SourceFile"; // #11     at 0x6C
+    Utf8 "OuterPlanets.java"; // #12     at 0x79
+    Utf8 "PermittedSubclasses"; // #13     at 0x8D
+    class #15; // #14     at 0xA1
+    Utf8 "planets/Neptune"; // #15     at 0xA4
+    class #17; // #16     at 0xB6
+    Utf8 "asteroids/Pluto"; // #17     at 0xB9
+  } // Constant Pool
+
+  0x0021; // access [ ACC_PUBLIC ACC_SUPER ]
+  #7;// this_cpx
+  #2;// super_cpx
+
+  [0] { // Interfaces
+  } // Interfaces
+
+  [0] { // fields
+  } // fields
+
+  [1] { // methods
+    { // Member at 0xD7
+      0x0001; // access
+      #5; // name_cpx
+      #6; // sig_cpx
+      [1] { // Attributes
+        Attr(#9, 29) { // Code at 0xDF
+          1; // max_stack
+          1; // max_locals
+          Bytes[5]{
+            0x2AB70001B1;
+          }
+          [0] { // Traps
+          } // end Traps
+          [1] { // Attributes
+            Attr(#10, 6) { // LineNumberTable at 0xF6
+              [1] { // LineNumberTable
+                0  26; //  at 0x0102
+              }
+            } // end LineNumberTable
+          } // Attributes
+        } // end Code
+      } // Attributes
+    } // Member
+  } // methods
+
+  [2] { // Attributes
+    Attr(#11, 2) { // SourceFile at 0x0104
+      #12;
+    } // end SourceFile
+    ;
+    Attr(#13, 6) { // PermittedSubclasses at 0x010C
+      0x0002000E0010;
+    } // end PermittedSubclasses
+  } // Attributes
+} // end class planets/OuterPlanets
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/instrument/RedefinePermittedSubclassesAttr/ClassFour.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2020, 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.
+ */
+
+final public class ClassFour extends Host { }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/instrument/RedefinePermittedSubclassesAttr/ClassOne.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2020, 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.
+ */
+
+final public class ClassOne extends Host { }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/instrument/RedefinePermittedSubclassesAttr/ClassThree.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2020, 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.
+ */
+
+final public class ClassThree extends Host { }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/instrument/RedefinePermittedSubclassesAttr/ClassTwo.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2020, 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.
+ */
+
+final public class ClassTwo extends Host { }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/instrument/RedefinePermittedSubclassesAttr/Host/Host.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2020, 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.
+ */
+
+public class Host {
+    public static String getID() { return "Host/Host.java";}
+    public int m() {
+        return 1; // original class
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/instrument/RedefinePermittedSubclassesAttr/Host/redef/Host.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2020, 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.
+ */
+
+public class Host {
+    public static String getID() { return "Host/redef/Host.java";}
+    public int m() {
+        return 2; // redefined class
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/instrument/RedefinePermittedSubclassesAttr/HostA/Host.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2020, 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.
+ */
+
+public sealed class Host permits ClassOne {
+    public static String getID() { return "HostA/Host.java";}
+    public int m() {
+        return 1; // original class
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/instrument/RedefinePermittedSubclassesAttr/HostA/redef/Host.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2020, 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.
+ */
+
+public sealed class Host permits ClassOne {
+    public static String getID() { return "HostA/redef/Host.java"; }
+    public int m() {
+        return 2; // redefined class
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/instrument/RedefinePermittedSubclassesAttr/HostAB/Host.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2020, 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.
+ */
+
+public sealed class Host permits ClassOne,ClassTwo {
+    public static String getID() { return "HostAB/Host.java";}
+    public int m() {
+        return 1; // original class
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/instrument/RedefinePermittedSubclassesAttr/HostAB/redef/Host.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2020, 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.
+ */
+
+public sealed class Host permits ClassOne,ClassTwo {
+    public static String getID() { return "HostAB/redef/Host.java"; }
+    public int m() {
+        return 2; // redefined class
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/instrument/RedefinePermittedSubclassesAttr/HostABC/Host.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2020, 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.
+ */
+
+public sealed class Host permits ClassOne,ClassTwo,ClassThree {
+    public static String getID() { return "HostABC/Host.java";}
+    public int m() {
+        return 1; // original class
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/instrument/RedefinePermittedSubclassesAttr/HostABC/redef/Host.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2020, 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.
+ */
+
+public sealed class Host permits ClassOne,ClassTwo,ClassThree {
+    public static String getID() { return "HostABC/redef/Host.java"; }
+    public int m() {
+        return 2; // redefined class
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/instrument/RedefinePermittedSubclassesAttr/HostABCD/redef/Host.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2020, 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.
+ */
+
+public sealed class Host permits ClassOne,ClassTwo,ClassThree,ClassFour {
+    public static String getID() { return "HostABCD/redef/Host.java"; }
+    public int m() {
+        return 2; // redefined class
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/instrument/RedefinePermittedSubclassesAttr/HostABD/redef/Host.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2020, 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.
+ */
+
+public sealed class Host permits ClassOne,ClassTwo,ClassFour {
+    public static String getID() { return "HostABD/redef/Host.java"; }
+    public int m() {
+        return 2; // redefined class
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/instrument/RedefinePermittedSubclassesAttr/HostAC/redef/Host.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2020, 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.
+ */
+
+public sealed class Host permits ClassOne,ClassThree {
+    public static String getID() { return "HostAC/redef/Host.java"; }
+    public int m() {
+        return 2; // redefined class
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/instrument/RedefinePermittedSubclassesAttr/HostACB/redef/Host.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2020, 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.
+ */
+
+public sealed class Host permits ClassOne,ClassThree,ClassTwo {
+    public static String getID() { return "HostACB/redef/Host.java"; }
+    public int m() {
+        return 2; // redefined class
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/instrument/RedefinePermittedSubclassesAttr/HostB/redef/Host.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2020, 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.
+ */
+
+public sealed class Host permits ClassTwo {
+    public static String getID() { return "HostB/redef/Host.java"; }
+    public int m() {
+        return 2; // redefined class
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/instrument/RedefinePermittedSubclassesAttr/HostBA/redef/Host.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2020, 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.
+ */
+
+public sealed class Host permits ClassTwo,ClassOne {
+    public static String getID() { return "HostBA/redef/Host.java"; }
+    public int m() {
+        return 2; // redefined class
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/instrument/RedefinePermittedSubclassesAttr/HostBAC/redef/Host.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2020, 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.
+ */
+
+public sealed class Host permits ClassTwo,ClassOne,ClassThree {
+    public static String getID() { return "HostBAC/redef/Host.java"; }
+    public int m() {
+        return 2; // redefined class
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/instrument/RedefinePermittedSubclassesAttr/HostBCA/redef/Host.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2020, 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.
+ */
+
+public sealed class Host permits ClassTwo,ClassThree,ClassOne {
+    public static String getID() { return "HostBCA/redef/Host.java"; }
+    public int m() {
+        return 2; // redefined class
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/instrument/RedefinePermittedSubclassesAttr/HostCAB/redef/Host.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2020, 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.
+ */
+
+public sealed class Host permits ClassThree,ClassOne,ClassTwo {
+    public static String getID() { return "HostCAB/redef/Host.java"; }
+    public int m() {
+        return 2; // redefined class
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/instrument/RedefinePermittedSubclassesAttr/HostCBA/redef/Host.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2020, 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.
+ */
+
+public sealed class Host permits ClassThree,ClassTwo,ClassOne {
+    public static String getID() { return "HostCBA/redef/Host.java"; }
+    public int m() {
+        return 2; // redefined class
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/instrument/RedefinePermittedSubclassesAttr/TestPermittedSubclassesAttr.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,273 @@
+/*
+ * Copyright (c) 2020, 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
+ * @bug 8225056
+ * @summary Class redefinition must preclude changes to PermittedSubclasses attributes
+ * @comment This is a copy of test/jdk/java/lang/instrument/RedefineNestmateAttr/
+ * @comment modified for sealed classes and the PermittedSubclasses attribute.
+ *
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * @modules java.compiler
+ *          java.instrument
+ * @compile ../NamedBuffer.java
+ * @run main RedefineClassHelper
+ * @compile --enable-preview --source ${jdk.version} Host/Host.java ClassOne.java ClassTwo.java ClassThree.java ClassFour.java
+ * @compile --enable-preview --source ${jdk.version} TestPermittedSubclassesAttr.java
+ * @run main/othervm -javaagent:redefineagent.jar --enable-preview -Xlog:redefine+class+sealed=trace TestPermittedSubclassesAttr Host
+ * @compile --enable-preview --source ${jdk.version} HostA/Host.java
+ * @run main/othervm -javaagent:redefineagent.jar --enable-preview -Xlog:redefine+class+sealed=trace TestPermittedSubclassesAttr HostA
+ * @compile --enable-preview --source ${jdk.version} HostAB/Host.java
+ * @run main/othervm -javaagent:redefineagent.jar --enable-preview -Xlog:redefine+class+sealed=trace TestPermittedSubclassesAttr HostAB
+ * @compile --enable-preview --source ${jdk.version} HostABC/Host.java
+ * @run main/othervm -javaagent:redefineagent.jar --enable-preview -Xlog:redefine+class+sealed=trace TestPermittedSubclassesAttr HostABC
+ */
+
+/* Test Description
+
+The basic test class is called Host and we have variants that have zero or more
+permitted subclasses ClassOne, ClassTwo, ClassThree, and ClassFour. Each variant
+of Host is defined in source code in its own directory i.e.
+
+Host/Host.java defines zero permitted classes
+Sealed class HostA/Host.java permits ClassOne
+Sealed HostAB/Host.java permits ClassOne and ClassTwo (in that order)
+Sealed HostABC/Host.java permits ClassOne, ClassTwo, and ClassThree (in that order)
+etc.
+
+Each Host class has the form:
+
+  public sealed class Host <permits zero or more classes> {
+    public static String getID() { return "<directory name>/Host.java"; }
+
+    public int m() {
+        return 1; // original class
+    }
+  }
+
+Under each directory is a directory "redef" with a modified version of the Host
+class that changes the ID to e.g. Host/redef/Host.java, and the method m()
+returns 2. This allows us to check we have the redefined class loaded.
+
+Using Host' to represent the redefined version we test redefinition
+combinations as follows:
+
+Host:
+  Host -> Host'  - succeeds m() returns 2
+  Host -> HostA' - fails - added a permitted subclass
+
+HostA:
+  HostA -> HostA'  - succeeds m() returns 2
+  HostA -> Host'   - fails - removed a permitted subclass
+  HostA -> HostAB' - fails - added a permitted subclass
+  HostA -> HostB'  - fails - replaced a permitted subclass
+
+HostAB:
+  HostAB -> HostAB'  - succeeds m() returns 2
+  HostAB -> HostBA'  - succeeds m() returns 2
+  HostAB -> HostA'   - fails - removed a permitted subclass
+  HostAB -> HostABC' - fails - added a permitted subclass
+  HostAB -> HostAC'  - fails - replaced a permitted subclass
+
+HostABC:
+  HostABC -> HostABC'  - succeeds m() returns 2
+  HostABC -> HostACB'  - succeeds m() returns 2
+  HostABC -> HostBAC'  - succeeds m() returns 2
+  HostABC -> HostBCA'  - succeeds m() returns 2
+  HostABC -> HostCAB'  - succeeds m() returns 2
+  HostABC -> HostCBA'  - succeeds m() returns 2
+  HostABC -> HostAB'   - fails - removed a permitted subclass
+  HostABC -> HostABCD' - fails - added a permitted subclass
+  HostABC -> HostABD'  - fails - replaced a permitted subclass
+
+More than three permitted subclasses doesn't add to the code coverage so
+we stop here.
+
+Note that we always try to load the redefined version even when we expect it
+to fail.
+
+We can only directly load one class Host per classloader, so to run all the
+groups we either need to use new classloaders, or we reinvoke the test
+requesting a different primary directory. We chose the latter using
+multiple @run tags. So we preceed as follows:
+
+ @compile Host/Host.java
+ @run TestPermittedSubclassesAttr Host
+ @compile HostA/Host.java  - replaces previous Host.class
+ @run TestPermittedSubclassesAttr HostA
+ @compile HostAB/Host.java  - replaces previous Host.class
+ @run TestPermittedSubclassesAttr HostAB
+etc.
+
+Within the test we directly compile redefined versions of the classes,
+using CompilerUtil, and then read the .class file directly as a byte[]
+to use with the RedefineClassHelper.
+
+*/
+
+import java.io.File;
+import java.io.FileInputStream;
+import jdk.test.lib.ByteCodeLoader;
+import jdk.test.lib.compiler.CompilerUtils;
+import jdk.test.lib.compiler.InMemoryJavaCompiler;
+import static jdk.test.lib.Asserts.assertTrue;
+
+public class TestPermittedSubclassesAttr {
+
+    static final String SRC = System.getProperty("test.src");
+    static final String DEST = System.getProperty("test.classes");
+    static final boolean VERBOSE = Boolean.getBoolean("verbose");
+    private static final String VERSION = Integer.toString(Runtime.version().feature());
+
+    public static void main(String[] args) throws Throwable {
+        String origin = args[0];
+        System.out.println("Testing original Host class from " + origin);
+
+        // Make sure the Host class loaded directly is an original version
+        // and from the expected location
+        Host h = new Host();
+        assertTrue(h.m() == 1);
+        assertTrue(Host.getID().startsWith(origin + "/"));
+
+        String[] badTransforms;  // directories of bad classes
+        String[] goodTransforms; // directories of good classes
+
+        switch (origin) {
+        case "Host":
+            badTransforms = new String[] {
+                "HostA" // add permitted subclass
+            };
+            goodTransforms = new String[] {
+                origin
+            };
+            break;
+
+        case "HostA":
+            badTransforms = new String[] {
+                "Host",   // remove permitted subclass
+                "HostAB", // add permitted subclass
+                "HostB"   // change permitted subclass
+            };
+            goodTransforms = new String[] {
+                origin
+            };
+            break;
+
+        case "HostAB":
+            badTransforms = new String[] {
+                "HostA",   // remove permitted subclass
+                "HostABC", // add permitted subclass
+                "HostAC"   // change permitted subclass
+            };
+            goodTransforms = new String[] {
+                origin,
+                "HostBA"  // reorder permitted subclasses
+            };
+            break;
+
+        case "HostABC":
+            badTransforms = new String[] {
+                "HostAB",   // remove permitted subclass
+                "HostABCD", // add permitted subclass
+                "HostABD"   // change permitted subclass
+            };
+            goodTransforms = new String[] {
+                origin,
+                "HostACB",  // reorder permitted subclasses
+                "HostBAC",  // reorder permitted subclasses
+                "HostBCA",  // reorder permitted subclasses
+                "HostCAB",  // reorder permitted subclasses
+                "HostCBA"   // reorder permitted subclasses
+            };
+            break;
+
+        default: throw new Error("Unknown test directory: " + origin);
+        }
+
+        // Compile and check bad transformations
+        checkBadTransforms(Host.class, badTransforms);
+
+        // Compile and check good transformations
+        checkGoodTransforms(Host.class, goodTransforms);
+    }
+
+    static void checkGoodTransforms(Class<?> c, String[] dirs) throws Throwable {
+        for (String dir : dirs) {
+            dir += "/redef";
+            System.out.println("Trying good retransform from " + dir);
+            byte[] buf = bytesForHostClass(dir);
+            RedefineClassHelper.redefineClass(c, buf);
+
+            // Test redefintion worked
+            Host h = new Host();
+            assertTrue(h.m() == 2);
+            if (VERBOSE) System.out.println("Redefined ID: " + Host.getID());
+            assertTrue(Host.getID().startsWith(dir));
+        }
+    }
+
+    static void checkBadTransforms(Class<?> c, String[] dirs) throws Throwable {
+        for (String dir : dirs) {
+            dir += "/redef";
+            System.out.println("Trying bad retransform from " + dir);
+            byte[] buf = bytesForHostClass(dir);
+            try {
+                RedefineClassHelper.redefineClass(c, buf);
+                throw new Error("Retransformation from directory " + dir +
+                                " succeeded unexpectedly");
+            }
+            catch (UnsupportedOperationException uoe) {
+                if (uoe.getMessage().contains("attempted to change the class") &&
+                    uoe.getMessage().contains(" PermittedSubclasses")) {
+                    System.out.println("Got expected exception " + uoe);
+                }
+                else throw new Error("Wrong UnsupportedOperationException", uoe);
+            }
+        }
+    }
+
+    static byte[] bytesForHostClass(String dir) throws Throwable {
+        compile("/" + dir);
+        File clsfile = new File(DEST + "/" + dir + "/Host.class");
+        if (VERBOSE) System.out.println("Reading bytes from " + clsfile);
+        byte[] buf = null;
+        try (FileInputStream str = new FileInputStream(clsfile)) {
+            return buf = NamedBuffer.loadBufferFromStream(str);
+        }
+    }
+
+    static void compile(String dir) throws Throwable {
+        File src = new File(SRC + dir);
+        File dst = new File(DEST + dir);
+        if (VERBOSE) System.out.println("Compiling from: " + src + "\n" +
+                                        "            to: " + dst);
+        CompilerUtils.compile(src.toPath(),
+                              dst.toPath(),
+                              false /* don't recurse */,
+                              "-classpath", DEST,
+                              "--enable-preview",
+                              "--source", VERSION);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/reflect/sealed_classes/SealedClassesReflectionTest.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 2020, 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
+ * @bug 8227046
+ * @summary reflection test for sealed classes
+ * @compile --enable-preview -source ${jdk.version} SealedClassesReflectionTest.java
+ * @run testng/othervm --enable-preview SealedClassesReflectionTest
+ */
+
+import java.lang.annotation.*;
+import java.lang.constant.ClassDesc;
+import java.lang.reflect.*;
+import java.util.Arrays;
+import java.util.List;
+import org.testng.annotations.*;
+import static org.testng.Assert.*;
+
+@Test
+public class SealedClassesReflectionTest {
+
+    sealed class SealedClass1 permits FinalSubclass1, NonSealedSubclass1 {}
+    final class FinalSubclass1 extends SealedClass1 {}
+    non-sealed class NonSealedSubclass1 extends SealedClass1 {}
+
+    sealed class SealedClass2 permits FinalSubclass2, FinalSubclass3 {}
+    final class FinalSubclass2 extends SealedClass2 {}
+    final class FinalSubclass3 extends SealedClass2 {}
+
+    sealed class SealedClass3 permits FinalSubclass4, SealedSubclass1 {}
+    final class FinalSubclass4 extends SealedClass3  {}
+    sealed class SealedSubclass1 extends SealedClass3 permits FinalSubclass5 {}
+    final class FinalSubclass5 extends SealedSubclass1 {}
+
+    sealed interface SealedInt1 permits FinalSubclass6, NonSealedSubInt1 {}
+    final class FinalSubclass6 implements SealedInt1 {}
+    non-sealed interface NonSealedSubInt1 extends SealedInt1 {}
+
+    sealed interface SealedInt2 permits FinalSubclass7, FinalSubclass8 {}
+    final class FinalSubclass7 implements SealedInt2 {}
+    final class FinalSubclass8 implements SealedInt2 {}
+
+    sealed interface SealedInt3 permits FinalSubclass9, SealedSubInt1, SealedSubclass2 {}
+    final class FinalSubclass9 implements SealedInt3  {}
+    sealed interface SealedSubInt1 extends SealedInt3 permits FinalSubclass10 {}
+    final class FinalSubclass10 implements SealedSubInt1 {}
+    sealed class SealedSubclass2 implements SealedInt3 permits NonSealedSubclass2 {}
+    non-sealed class NonSealedSubclass2 extends SealedSubclass2 {}
+
+    @DataProvider(name = "sealedClasses")
+    public Object[][] sealedClassesData() {
+        return List.of(
+                SealedClass1.class,
+                SealedClass2.class,
+                SealedClass3.class,
+                SealedSubclass1.class,
+                SealedInt1.class,
+                SealedInt2.class,
+                SealedInt3.class,
+                SealedSubInt1.class
+        ).stream().map(c -> new Object[] {c}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "sealedClasses")
+    public void testSealedClasses(Class<?> cls) {
+        assertTrue(cls.isSealed());
+        assertTrue(!Modifier.isFinal(cls.getModifiers()));
+        assertTrue(cls.permittedSubclasses() != null);
+        assertTrue(cls.permittedSubclasses().length > 0);
+    }
+
+    @DataProvider(name = "notSealedClasses")
+    public Object[][] notSealedClassesData() {
+        return List.of(
+                Object.class,
+                void.class, Void.class, Void[].class,
+                byte.class, byte[].class, Byte.class, Byte[].class,
+                short.class, short[].class, Short.class, Short[].class,
+                char.class, char[].class, Character.class, Character[].class,
+                int.class, int[].class, Integer.class, Integer[].class,
+                long.class, long[].class, Long.class, Long[].class,
+                float.class, float[].class, Float.class, Float[].class,
+                double.class, double[].class, Double.class, Double[].class,
+                boolean.class, boolean[].class, Boolean.class, Boolean[].class,
+                String.class, String[].class
+        ).stream().map(c -> new Object[] {c}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "notSealedClasses")
+    public void testNotSealedClasses(Class<?> cls) {
+        assertTrue(!cls.isSealed());
+        assertTrue(cls.permittedSubclasses() != null);
+        assertTrue(cls.permittedSubclasses().length == 0);
+    }
+
+    @DataProvider(name = "non_sealedClasses")
+    public Object[][] non_sealedClassesData() {
+        return List.of(
+                NonSealedSubclass1.class,
+                NonSealedSubInt1.class,
+                NonSealedSubclass2.class
+        ).stream().map(c -> new Object[] {c}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "non_sealedClasses")
+    public void testnon_sealedClasses(Class<?> cls) {
+        assertTrue(!cls.isSealed());
+        assertTrue(!Modifier.isFinal(cls.getModifiers()));
+        assertTrue((cls.getSuperclass() != null && cls.getSuperclass().isSealed()) || Arrays.stream(cls.getInterfaces()).anyMatch(Class::isSealed));
+        assertTrue(cls.permittedSubclasses() != null);
+        assertTrue(cls.permittedSubclasses().length == 0);
+    }
+
+    @DataProvider(name = "reflectionData")
+    public Object[][] reflectionData() {
+        return new Object[][] {
+                new Object[] {
+                        SealedClass1.class,
+                        2,
+                        new String[] {"SealedClassesReflectionTest$FinalSubclass1", "SealedClassesReflectionTest$NonSealedSubclass1"},
+                        new Class<?>[] {FinalSubclass1.class, NonSealedSubclass1.class},
+                        new SealedStatus[] {SealedStatus.FINAL, SealedStatus.NON_SEALED}},
+
+                new Object[] {
+                        SealedClass2.class,
+                        2,
+                        new String[] {"SealedClassesReflectionTest$FinalSubclass2", "SealedClassesReflectionTest$FinalSubclass3"},
+                        new Class<?>[] {FinalSubclass2.class, FinalSubclass3.class},
+                        new SealedStatus[] {SealedStatus.FINAL, SealedStatus.FINAL}},
+
+                new Object[] {
+                        SealedClass3.class,
+                        2,
+                        new String[] {"SealedClassesReflectionTest$FinalSubclass4", "SealedClassesReflectionTest$SealedSubclass1"},
+                        new Class<?>[] {FinalSubclass4.class, SealedSubclass1.class},
+                        new SealedStatus[] {SealedStatus.FINAL, SealedStatus.SEALED}},
+
+                new Object[] {
+                        SealedSubclass1.class,
+                        1,
+                        new String[] {"SealedClassesReflectionTest$FinalSubclass5"},
+                        new Class<?>[] {FinalSubclass5.class},
+                        new SealedStatus[] {SealedStatus.FINAL}},
+
+                new Object[] {
+                        SealedInt1.class,
+                        2,
+                        new String[] {"SealedClassesReflectionTest$FinalSubclass6", "SealedClassesReflectionTest$NonSealedSubInt1"},
+                        new Class<?>[] {FinalSubclass6.class, NonSealedSubInt1.class},
+                        new SealedStatus[] {SealedStatus.FINAL, SealedStatus.NON_SEALED}},
+
+                new Object[] {
+                        SealedInt2.class,
+                        2,
+                        new String[] {"SealedClassesReflectionTest$FinalSubclass7", "SealedClassesReflectionTest$FinalSubclass8"},
+                        new Class<?>[] {FinalSubclass7.class, FinalSubclass8.class},
+                        new SealedStatus[] {SealedStatus.FINAL, SealedStatus.FINAL}},
+
+                new Object[] {
+                        SealedInt3.class,
+                        3,
+                        new String[] {"SealedClassesReflectionTest$FinalSubclass9",
+                                "SealedClassesReflectionTest$SealedSubInt1",
+                                "SealedClassesReflectionTest$SealedSubclass2"},
+                        new Class<?>[] {FinalSubclass9.class, SealedSubInt1.class, SealedSubclass2.class},
+                        new SealedStatus[] {SealedStatus.FINAL, SealedStatus.SEALED, SealedStatus.SEALED}},
+
+                new Object[] {
+                        SealedSubInt1.class,
+                        1,
+                        new String[] {"SealedClassesReflectionTest$FinalSubclass10"},
+                        new Class<?>[] {FinalSubclass10.class},
+                        new SealedStatus[] {SealedStatus.FINAL}},
+
+                new Object[] {
+                        SealedSubclass2.class,
+                        1,
+                        new String[] {"SealedClassesReflectionTest$NonSealedSubclass2"},
+                        new Class<?>[] {NonSealedSubclass2.class},
+                        new SealedStatus[] {SealedStatus.NON_SEALED}},
+        };
+    }
+
+    enum SealedStatus {
+        SEALED, NON_SEALED, FINAL
+    }
+
+    @Test(dataProvider = "reflectionData")
+    public void testSealedReflection(Class<?> sealedClass,
+                                     int numberOfSubclasses,
+                                     String[] subclassDescriptors,
+                                     Class<?>[] subclasses,
+                                     SealedStatus[] subclassSealedStatus)
+            throws ReflectiveOperationException
+    {
+        assertTrue(sealedClass.isSealed());
+        assertTrue(sealedClass.permittedSubclasses().length == numberOfSubclasses);
+        int i = 0;
+        for (ClassDesc cd : sealedClass.permittedSubclasses()) {
+            assertTrue(cd.displayName().equals(subclassDescriptors[i]), "expected: " + subclassDescriptors[i] + " found: " + cd.displayName());
+            i++;
+        }
+        i = 0;
+        for (Class<?> subclass : subclasses) {
+            switch (subclassSealedStatus[i++]) {
+                case SEALED:
+                    assertTrue(subclass.isSealed());
+                    break;
+                case FINAL:
+                    assertTrue(Modifier.isFinal(subclass.getModifiers()));
+                    break;
+                case NON_SEALED:
+                    assertTrue(!subclass.isSealed() && !Modifier.isFinal(subclass.getModifiers()));
+                    break;
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testSealedTypes/TestSealedTypes.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,322 @@
+/*
+ * Copyright (c) 2019, 2020, 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
+ * @bug      8227047
+ * @summary  Sealed types
+ * @library  /tools/lib ../../lib
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
+ * @build    toolbox.ToolBox javadoc.tester.*
+ * @run main TestSealedTypes
+ */
+
+import java.io.IOException;
+import java.nio.file.Path;
+
+import javadoc.tester.JavadocTester;
+import toolbox.ToolBox;
+
+public class TestSealedTypes extends JavadocTester {
+
+    public static void main(String... args) throws Exception {
+        TestSealedTypes tester = new TestSealedTypes();
+        tester.runTests(m -> new Object[] { Path.of(m.getName()) });
+    }
+
+    private final ToolBox tb = new ToolBox();
+
+    @Test
+    public void testSealedModifierClass(Path base) throws IOException {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "package p; public sealed class A { }");
+
+        javadoc("-d", base.resolve("out").toString(),
+                "-sourcepath", src.toString(),
+                "--enable-preview", "--source", thisRelease,
+                "p");
+        checkExit(Exit.OK);
+
+        checkOutput("p/A.html", true,
+                "public sealed class <span class=\"type-name-label\">A</span>");
+    }
+
+    @Test
+    public void testSealedModifierInterface(Path base) throws IOException {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "package p; public sealed interface A { }");
+
+        javadoc("-d", base.resolve("out").toString(),
+                "-sourcepath", src.toString(),
+                "--enable-preview", "--source", thisRelease,
+                "p");
+        checkExit(Exit.OK);
+
+        checkOutput("p/A.html", true,
+                "public sealed interface <span class=\"type-name-label\">A</span>");
+    }
+
+    @Test
+    public void testNonSealedModifierClass(Path base) throws IOException {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "package p; public sealed class A permits B { }",
+                "package p; public non-sealed class B extends A { }");
+
+        javadoc("-d", base.resolve("out").toString(),
+                "--source-path", src.toString(),
+                "--enable-preview", "--source", thisRelease,
+                "p");
+        checkExit(Exit.OK);
+
+        checkOutput("p/A.html", true,
+                "public sealed class <span class=\"type-name-label\">A</span>");
+
+        checkOutput("p/B.html", true,
+                "public non-sealed class <span class=\"type-name-label\">B</span>");
+    }
+
+    @Test
+    public void testNonSealedModifierInterface(Path base) throws IOException {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "package p; public sealed interface A permits B { }",
+                "package p; public non-sealed interface B extends A { }");
+
+        javadoc("-d", base.resolve("out").toString(),
+                "--source-path", src.toString(),
+                "--enable-preview", "--source", thisRelease,
+                "p");
+        checkExit(Exit.OK);
+
+        checkOutput("p/A.html", true,
+                "public sealed interface <span class=\"type-name-label\">A</span>");
+
+        checkOutput("p/B.html", true,
+                "public non-sealed interface <span class=\"type-name-label\">B</span>");
+    }
+
+    @Test
+    public void testSealedSubtypeModifierClass(Path base) throws IOException {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "package p; public sealed class A permits B { }",
+                "package p; public sealed abstract class B extends A { }");
+
+        javadoc("-d", base.resolve("out").toString(),
+                "--source-path", src.toString(),
+                "--enable-preview", "--source", thisRelease,
+                "p");
+        checkExit(Exit.OK);
+
+        checkOutput("p/A.html", true,
+                "public sealed class <span class=\"type-name-label\">A</span>");
+
+        checkOutput("p/B.html", true,
+                "public abstract sealed class <span class=\"type-name-label\">B</span>");
+    }
+
+    @Test
+    public void testSealedSubtypeInterface(Path base) throws IOException {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "package p; public sealed interface A permits B { }",
+                "package p; public sealed interface B extends A { }");
+
+        javadoc("-d", base.resolve("out").toString(),
+                "--source-path", src.toString(),
+                "--enable-preview", "--source", thisRelease,
+                "p");
+        checkExit(Exit.OK);
+
+        checkOutput("p/A.html", true,
+                "public sealed interface <span class=\"type-name-label\">A</span>");
+
+        checkOutput("p/B.html", true,
+                "public sealed interface <span class=\"type-name-label\">B</span>");
+    }
+
+    @Test
+    public void testSinglePermits(Path base) throws IOException {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "package p; public sealed class A permits B { }",
+                "package p; public final class B extends A { }");
+
+        javadoc("-d", base.resolve("out").toString(),
+                "--source-path", src.toString(),
+                "--enable-preview", "--source", thisRelease,
+                "p");
+        checkExit(Exit.OK);
+
+        checkOutput("p/A.html", true,
+                "<pre>public sealed class <span class=\"type-name-label\">A</span>\n"
+                + "extends java.lang.Object\n"
+                + "permits <a href=\"B.html\" title=\"class in p\">B</a></pre>");
+    }
+
+    @Test
+    public void testMultiplePermits(Path base) throws IOException {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "package p; public sealed class A permits B,C,D { }",
+                "package p; public final class B extends A { }",
+                "package p; public final class C extends A { }",
+                "package p; public final class D extends A { }");
+
+        javadoc("-d", base.resolve("out").toString(),
+                "--source-path", src.toString(),
+                "--enable-preview", "--source", thisRelease,
+                "p");
+        checkExit(Exit.OK);
+
+        checkOutput("p/A.html", true,
+                "<pre>public sealed class <span class=\"type-name-label\">A</span>\n"
+                + "extends java.lang.Object\n"
+                + "permits <a href=\"B.html\" title=\"class in p\">B</a>, "
+                + "<a href=\"C.html\" title=\"class in p\">C</a>, "
+                + "<a href=\"D.html\" title=\"class in p\">D</a></pre>");
+    }
+
+    @Test
+    public void testPartialMultiplePermits(Path base) throws IOException {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "package p; public sealed class A permits B,C,D { }",
+                "package p; public final class B extends A { }",
+                "package p; public final class C extends A { }",
+                "package p;        final class D extends A { }");
+
+        javadoc("-d", base.resolve("out").toString(),
+                "--source-path", src.toString(),
+                "--enable-preview", "--source", thisRelease,
+                "p");
+        checkExit(Exit.OK);
+
+        checkOutput("p/A.html", true,
+                "<pre>public sealed class <span class=\"type-name-label\">A</span>\n"
+                + "extends java.lang.Object\n"
+                + "permits <a href=\"B.html\" title=\"class in p\">B</a>, "
+                + "<a href=\"C.html\" title=\"class in p\">C</a> "
+                + "<span class=\"permits-note\">(not exhaustive)</span></pre>");
+    }
+
+    // @Test // javac incorrectly rejects the source
+    public void testPartialMultiplePermitsWithSubtypes1(Path base) throws IOException {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "package p; public sealed class A permits B,C,D { }",
+                "package p; public final  class B extends A { }",
+                "package p; public final  class C extends A { }",
+                "package p;        sealed class D extends A permits D1, D2 { }",
+                "package p; public final  class D1 extends D { }",
+                "package p; public final  class D2 extends D { }");
+
+        javadoc("-d", base.resolve("out").toString(),
+                "--source-path", src.toString(),
+                "--enable-preview", "--source", thisRelease,
+                "p");
+        checkExit(Exit.OK);
+
+        checkOutput("p/A.html", true,
+                "<pre>public sealed class <span class=\"type-name-label\">A</span>\n"
+                + "extends java.lang.Object\n"
+                + "permits <a href=\"B.html\" title=\"class in p\">B</a>, "
+                + "<a href=\"C.html\" title=\"class in p\">C</a>, p.D</pre>");
+    }
+
+    @Test
+    public void testPartialMultiplePermitsWithSubtypes2(Path base) throws IOException {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "package p; public sealed class A permits B,C,D { }",
+                "package p; public final  class B extends A { }",
+                "package p; public final  class C extends A { }",
+                "package p;    non-sealed class D extends A { }",
+                "package p; public final  class D1 extends D { }",
+                "package p; public final  class D2 extends D { }");
+
+        javadoc("-d", base.resolve("out").toString(),
+                "--source-path", src.toString(),
+                "--enable-preview", "--source", thisRelease,
+                "p");
+        checkExit(Exit.OK);
+
+        checkOutput("p/A.html", true,
+                "<pre>public sealed class <span class=\"type-name-label\">A</span>\n"
+                + "extends java.lang.Object\n"
+                + "permits <a href=\"B.html\" title=\"class in p\">B</a>, "
+                + "<a href=\"C.html\" title=\"class in p\">C</a> "
+                + "<span class=\"permits-note\">(not exhaustive)</span></pre>");
+    }
+
+    @Test
+    public void testImplicitPermitsAuxiliary(Path base) throws IOException {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "package p; public sealed class A { }\n"
+                + "final class B extends A { }\n"
+                + "final class C extends A { }\n"
+                + "final class D extends A { }\n");
+
+        javadoc("-d", base.resolve("out").toString(),
+                "--source-path", src.toString(),
+                "-package",
+                "--enable-preview", "--source", thisRelease,
+                "p");
+        checkExit(Exit.OK);
+
+        checkOutput("p/A.html", true,
+                "<pre>public sealed class <span class=\"type-name-label\">A</span>\n"
+                + "extends java.lang.Object\n"
+                + "permits <a href=\"B.html\" title=\"class in p\">B</a>, "
+                + "<a href=\"C.html\" title=\"class in p\">C</a>, "
+                + "<a href=\"D.html\" title=\"class in p\">D</a></pre>");
+    }
+
+    @Test
+    public void testImplicitPermitsNested(Path base) throws IOException {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "package p; public sealed class A {\n"
+                + "  public static final class B extends A { }\n"
+                + "  public static final class C extends A { }\n"
+                + "  public static final class D extends A { }\n"
+                + "}");
+
+        javadoc("-d", base.resolve("out").toString(),
+                "--source-path", src.toString(),
+                "--enable-preview", "--source", thisRelease,
+                "p");
+        checkExit(Exit.OK);
+
+        checkOutput("p/A.html", true,
+                "<pre>public sealed class <span class=\"type-name-label\">A</span>\n"
+                + "extends java.lang.Object\n"
+                + "permits <a href=\"A.B.html\" title=\"class in p\">A.B</a>, "
+                + "<a href=\"A.C.html\" title=\"class in p\">A.C</a>, "
+                + "<a href=\"A.D.html\" title=\"class in p\">A.D</a></pre>");
+    }
+}
--- a/test/langtools/lib/annotations/annotations/classfile/ClassfileInspector.java	Mon Jun 01 22:55:22 2020 +0200
+++ b/test/langtools/lib/annotations/annotations/classfile/ClassfileInspector.java	Mon Jun 01 17:00:40 2020 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2020, 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
@@ -1363,6 +1363,11 @@
         }
 
         @Override
+        public Void visitPermittedSubclasses(PermittedSubclasses_attribute attr, T p) {
+            return null;
+        }
+
+        @Override
         public Void visitRecord(Record_attribute attr, T p) {
             return null;
         }
--- a/test/langtools/tools/javac/MethodParameters/AttributeVisitor.java	Mon Jun 01 22:55:22 2020 +0200
+++ b/test/langtools/tools/javac/MethodParameters/AttributeVisitor.java	Mon Jun 01 17:00:40 2020 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2020, 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
@@ -64,5 +64,6 @@
     public R visitStackMap(StackMap_attribute attr, P p) { return null; }
     public R visitStackMapTable(StackMapTable_attribute attr, P p) { return null; }
     public R visitSynthetic(Synthetic_attribute attr, P p) { return null; }
+    public R visitPermittedSubclasses(PermittedSubclasses_attribute attr, P p) { return null; }
     public R visitRecord(Record_attribute attr, P p) { return null; }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/diags/examples/CantInheritFromSealed.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2017, 2020, 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.
+ */
+
+// key: compiler.err.cant.inherit.from.sealed
+// key: compiler.err.non.sealed.sealed.or.final.expected
+// key: compiler.note.preview.filename
+// key: compiler.note.preview.recompile
+// options: --enable-preview -source ${jdk.version}
+
+sealed interface SealedInterface permits Sub1 {
+    void m();
+}
+
+class Sub1 implements SealedInterface {
+    public void m() { }
+}
+
+class CantInheritFromSealed implements SealedInterface {
+    public void m() { }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/diags/examples/CantInheritFromSealed2.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2017, 2020, 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.
+ */
+
+// key: compiler.err.non.sealed.or.sealed.expected
+// key: compiler.note.preview.filename
+// key: compiler.note.preview.recompile
+// options: --enable-preview -source ${jdk.version}
+
+sealed interface SealedInterface permits Sub1 {
+    void m();
+}
+interface Sub1 extends SealedInterface {}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/diags/examples/DuplicateTypeInPermits.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2017, 2020, 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.
+ */
+
+// key: compiler.err.invalid.permits.clause
+// key: compiler.misc.is.duplicated
+// key: compiler.note.preview.filename
+// key: compiler.note.preview.recompile
+// options: --enable-preview -source ${jdk.version}
+
+sealed class Sealed permits Sub, Sub {}
+
+final class Sub extends Sealed {}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/diags/examples/LocalCantInheritFromSealed.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2017, 2020, 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.
+ */
+
+// key: compiler.err.local.classes.cant.extend.sealed
+// key: compiler.err.sealed.class.must.have.subclasses
+// key: compiler.note.preview.filename
+// key: compiler.note.preview.recompile
+// options: --enable-preview -source ${jdk.version}
+
+sealed class C {
+    void m() {
+        final class D extends C { }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/diags/examples/NonSealedWithNoSealedSuper.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2017, 2020, 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.
+ */
+
+// key: compiler.err.non.sealed.with.no.sealed.supertype
+// key: compiler.note.preview.filename
+// key: compiler.note.preview.recompile
+// options: --enable-preview -source ${jdk.version}
+
+class C {}
+
+non-sealed class Sub extends C {}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/diags/examples/PermitsCantListDeclaringClass.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2020, 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.
+ */
+
+// key: compiler.err.invalid.permits.clause
+// key: compiler.misc.must.not.be.same.class
+// key: compiler.note.preview.filename
+// key: compiler.note.preview.recompile
+// options: --enable-preview -source ${jdk.version}
+
+sealed class C permits C {}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/diags/examples/PermitsCantListSuperType.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2020, 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.
+ */
+
+// key: compiler.err.invalid.permits.clause
+// key: compiler.misc.must.not.be.supertype
+// key: compiler.note.preview.filename
+// key: compiler.note.preview.recompile
+// options: --enable-preview -source ${jdk.version}
+
+interface I {}
+
+sealed class C implements I permits I {}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/diags/examples/PermitsInNoSealedClass.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2017, 2020, 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.
+ */
+
+// key: compiler.err.invalid.permits.clause
+// key: compiler.misc.class.is.not.sealed
+// key: compiler.note.preview.filename
+// key: compiler.note.preview.recompile
+// options: --enable-preview -source ${jdk.version}
+
+class C permits Sub {}
+
+final class Sub extends C {}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/diags/examples/SealedMustHaveSubtypes.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2017, 2020, 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.
+ */
+
+// key: compiler.err.sealed.class.must.have.subclasses
+// key: compiler.note.preview.filename
+// key: compiler.note.preview.recompile
+// options: --enable-preview -source ${jdk.version}
+
+sealed class Sealed {}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/diags/examples/SealedNotAllowedInLocalClass.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2017, 2020, 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.
+ */
+
+// key: compiler.err.sealed.or.non.sealed.local.classes.not.allowed
+// key: compiler.note.preview.filename
+// key: compiler.note.preview.recompile
+// options: --enable-preview -source ${jdk.version}
+
+class Outer {
+    void m() {
+        sealed class S { }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/diags/examples/SealedTypes.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2020, 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.
+ */
+
+// key: compiler.misc.feature.sealed.classes
+// key: compiler.warn.preview.feature.use.plural
+// options: --enable-preview -source ${jdk.version} -Xlint:preview
+
+sealed class Sealed {}
+
+final class C extends Sealed {}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/diags/examples/SubtypeDoesntExtendSealed.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2017, 2020, 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.
+ */
+
+// key: compiler.err.invalid.permits.clause
+// key: compiler.misc.doesnt.extend.sealed
+// key: compiler.note.preview.filename
+// key: compiler.note.preview.recompile
+// options: --enable-preview -source ${jdk.version}
+
+sealed class Sealed permits Sub {}
+
+final class Sub {}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/diags/examples/TypeVarInPermits.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2017, 2020, 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.
+ */
+
+// key: compiler.err.invalid.permits.clause
+// key: compiler.misc.is.a.type.variable
+// key: compiler.note.preview.filename
+// key: compiler.note.preview.recompile
+// options: --enable-preview -source ${jdk.version}
+
+class Outer<T> {
+    sealed class Sealed permits T {}
+}
--- a/test/langtools/tools/javac/enum/FauxEnum3.java	Mon Jun 01 22:55:22 2020 +0200
+++ b/test/langtools/tools/javac/enum/FauxEnum3.java	Mon Jun 01 17:00:40 2020 -0400
@@ -5,6 +5,7 @@
  * @author Joseph D. Darcy
  *
  * @compile/fail/ref=FauxEnum3.out -XDrawDiagnostics  FauxEnum3.java
+ * @compile/fail/ref=FauxEnum3.preview.out -XDrawDiagnostics --enable-preview -source ${jdk.version} FauxEnum3.java
  */
 
 public class FauxEnum3 extends SpecializedEnum {
--- a/test/langtools/tools/javac/enum/FauxEnum3.out	Mon Jun 01 22:55:22 2020 +0200
+++ b/test/langtools/tools/javac/enum/FauxEnum3.out	Mon Jun 01 17:00:40 2020 -0400
@@ -1,2 +1,2 @@
-FauxEnum3.java:10:8: compiler.err.enum.types.not.extensible
-1 error
+FauxEnum3.java:11:8: compiler.err.enum.types.not.extensible
+1 error
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/enum/FauxEnum3.preview.out	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,2 @@
+FauxEnum3.java:11:8: compiler.err.cant.inherit.from.sealed: SpecializedEnum
+1 error
\ No newline at end of file
--- a/test/langtools/tools/javac/parser/JavacParserTest.java	Mon Jun 01 22:55:22 2020 +0200
+++ b/test/langtools/tools/javac/parser/JavacParserTest.java	Mon Jun 01 17:00:40 2020 -0400
@@ -1492,6 +1492,26 @@
                      expectedAST);
     }
 
+    @Test
+    void testStartAndEndPositionForClassesInPermitsClause() throws IOException {
+        String code = "package t; sealed class Test permits Sub1, Sub2 {} final class Sub1 extends Test {} final class Sub2 extends Test {}";
+        JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, null,
+                List.of("--enable-preview", "-source", Integer.toString(Runtime.version().feature())),
+                null, Arrays.asList(new MyFileObject(code)));
+        CompilationUnitTree cut = ct.parse().iterator().next();
+        ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0);
+        List<? extends Tree> permitsList = clazz.getPermitsClause();
+        assertEquals("testStartAndEndPositionForClassesInPermitsClause", 2, permitsList.size());
+        Trees t = Trees.instance(ct);
+        List<String> expected = List.of("Sub1", "Sub2");
+        int i = 0;
+        for (Tree permitted: permitsList) {
+            int start = (int) t.getSourcePositions().getStartPosition(cut, permitted);
+            int end = (int) t.getSourcePositions().getEndPosition(cut, permitted);
+            assertEquals("testStartAndEndPositionForClassesInPermitsClause", expected.get(i++), code.substring(start, end));
+        }
+    }
+
     void run(String[] args) throws Exception {
         int passed = 0, failed = 0;
         final Pattern p = (args != null && args.length > 0)
--- a/test/langtools/tools/javac/processing/model/TestSourceVersion.java	Mon Jun 01 22:55:22 2020 +0200
+++ b/test/langtools/tools/javac/processing/model/TestSourceVersion.java	Mon Jun 01 17:00:40 2020 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2020, 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
@@ -101,8 +101,8 @@
         Set<String> restrictedKeywords =
             Set.of("open", "module", "requires", "transitive", "exports",
                    "opens", "to", "uses", "provides", "with",
-                   // Assume "record" will be a restricted keyword.
-                   "record");
+                   // Assume "record" and "sealed" will be restricted keywords.
+                   "record", "sealed");
 
         for (String key : restrictedKeywords) {
             for (SourceVersion version : SourceVersion.values()) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/processing/model/element/TestSealed.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2019, 2020, 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
+ * @bug 8227046
+ * @summary Test basic modeling for sealed classes
+ * @library /tools/lib /tools/javac/lib
+ * @modules
+ *     jdk.compiler/com.sun.tools.javac.api
+ *     jdk.compiler/com.sun.tools.javac.main
+ * @build toolbox.ToolBox toolbox.JavacTask JavacTestingAbstractProcessor
+ * @compile --enable-preview -source ${jdk.version} TestSealed.java
+ * @run main/othervm --enable-preview TestSealed
+ */
+
+import java.io.*;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.*;
+
+import javax.annotation.processing.*;
+import javax.lang.model.*;
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.lang.model.util.*;
+import java.time.*;
+
+import javax.tools.Diagnostic.Kind;
+
+import toolbox.JavacTask;
+import toolbox.Task;
+import toolbox.Task.Mode;
+import toolbox.Task.OutputKind;
+import toolbox.TestRunner;
+import toolbox.ToolBox;
+
+public class TestSealed extends TestRunner {
+
+    protected ToolBox tb;
+
+    TestSealed() {
+        super(System.err);
+        tb = new ToolBox();
+    }
+
+    public static void main(String... args) throws Exception {
+        new TestSealed().runTests();
+    }
+
+    /**
+     * Run all methods annotated with @Test, and throw an exception if any
+     * errors are reported..
+     *
+     * @throws Exception if any errors occurred
+     */
+    protected void runTests() throws Exception {
+        runTests(m -> new Object[] { Paths.get(m.getName()) });
+    }
+
+    Path[] findJavaFiles(Path... paths) throws IOException {
+        return tb.findJavaFiles(paths);
+    }
+
+    void checkOutputContains(String log, String... expect) throws Exception {
+        for (String e : expect) {
+            if (!log.contains(e)) {
+                throw new Exception("expected output not found: " + e);
+            }
+        }
+    }
+
+    @Test
+    public void testSealedClassesProcessor(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path r = src.resolve("Test");
+
+        Path classes = base.resolve("classes");
+
+        Files.createDirectories(classes);
+
+        tb.writeJavaFiles(r,
+            """
+            sealed interface SealedInterface permits NonSealedClass1, SealedClass {}
+
+            non-sealed class NonSealedClass1 implements SealedInterface {}
+
+            sealed class SealedClass implements SealedInterface {}
+                final class FinalClass extends SealedClass {}
+                non-sealed class NonSealedClass2 extends SealedClass {}
+
+            class ClassOutOfSealedHierarchy extends NonSealedClass1 {}
+            """
+        );
+
+        List<String> expected = List.of(
+                "Note: visiting: SealedInterface Modifiers: [abstract, sealed]",
+                "Note:     this class has: 2, permitted subclasses",
+                "Note:     permitted subclass: NonSealedClass1",
+                "Note:     permitted subclass: SealedClass",
+                "Note: visiting: NonSealedClass1 Modifiers: [non-sealed]",
+                "Note:     this class has: 0, permitted subclasses",
+                "Note: visiting: SealedClass Modifiers: [sealed]",
+                "Note:     this class has: 2, permitted subclasses",
+                "Note:     permitted subclass: FinalClass",
+                "Note:     permitted subclass: NonSealedClass2",
+                "Note: visiting: FinalClass Modifiers: [final]",
+                "Note:     this class has: 0, permitted subclasses",
+                "Note: visiting: NonSealedClass2 Modifiers: [non-sealed]",
+                "Note:     this class has: 0, permitted subclasses",
+                "Note: visiting: ClassOutOfSealedHierarchy Modifiers: []",
+                "Note:     this class has: 0, permitted subclasses",
+                "Note: testSealedClassesProcessor" + File.separator + "src" + File.separator
+                        + "Test" + File.separator + "SealedInterface.java uses preview language features.",
+                "Note: Recompile with -Xlint:preview for details."
+        );
+
+        for (Mode mode : new Mode[] {Mode.API}) {
+            List<String> log = new JavacTask(tb, mode)
+                    .options("-processor", SealedClassesProcessor.class.getName(),
+                            "--enable-preview",
+                            "-source", Integer.toString(Runtime.version().feature()))
+                    .files(findJavaFiles(src))
+                    .outdir(classes)
+                    .run()
+                    .writeAll()
+                    .getOutputLines(Task.OutputKind.DIRECT);
+
+            System.out.println("log:" +log);
+
+            if (!expected.equals(log)) {
+                if (expected.size() == log.size()) {
+                    for (int i = 0; i < expected.size(); i++) {
+                        if (!expected.get(i).equals(log.get(i))) {
+                            System.err.println("failing at line " + (i + 1));
+                            System.err.println("    expecting " + expected.get(i));
+                            System.err.println("    found " + log.get(i));
+                        }
+                    }
+                } else {
+                    System.err.println("expected and log lists differ in length");
+                }
+                throw new AssertionError("Unexpected output: " + log);
+            }
+        }
+    }
+
+    public static final class SealedClassesProcessor extends JavacTestingAbstractProcessor {
+
+        @Override
+        public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+            if (!roundEnv.processingOver()) {
+                Messager messager = processingEnv.getMessager();
+                ElementScanner scanner = new SealedScanner(messager);
+                for(Element rootElement : roundEnv.getRootElements()) {
+                    scanner.visit(rootElement);
+                }
+            }
+            return true;
+        }
+
+        class SealedScanner extends ElementScanner<Void, Void> {
+
+            Messager messager;
+
+            public SealedScanner(Messager messager) {
+                this.messager = messager;
+            }
+
+            @Override
+            public Void visitType(TypeElement element, Void p) {
+                messager.printMessage(Kind.NOTE, "visiting: " + element.getSimpleName() + " Modifiers: " + element.getModifiers());
+                List<? extends TypeMirror> permittedSubclasses = element.getPermittedSubclasses();
+                messager.printMessage(Kind.NOTE, String.format("    this class has: %d, permitted subclasses", permittedSubclasses.size()));
+                for (TypeMirror tm: permittedSubclasses) {
+                    messager.printMessage(Kind.NOTE, String.format("    permitted subclass: %s", ((DeclaredType)tm).asElement().getSimpleName()));
+                }
+                return super.visitType(element, p);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/sealed/CheckSubtypesOfSealedTest.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2018, 2020, 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 check subtypes of sealed classes
+ * @library /tools/lib /tools/javac/lib /tools/javac/classfiles/attributes/lib
+ * @modules jdk.jdeps/com.sun.tools.classfile
+ *          jdk.compiler/com.sun.tools.javac.code
+ *          jdk.compiler/com.sun.tools.javac.api
+ *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.compiler/com.sun.tools.javac.util
+ * @build toolbox.ToolBox toolbox.JavacTask InMemoryFileManager TestBase
+ * @run main CheckSubtypesOfSealedTest
+ */
+
+import java.util.List;
+import com.sun.tools.classfile.*;
+import com.sun.tools.classfile.ConstantPool.CONSTANT_Utf8_info;
+import com.sun.tools.javac.code.Flags;
+import com.sun.tools.javac.util.Assert;
+
+public class CheckSubtypesOfSealedTest extends TestBase {
+
+    static final String testSource =
+            "public class SealedClasses {\n" +
+            "    sealed abstract class SAC {}\n" +
+            "    sealed abstract class SAC2 extends SAC {}\n" +
+            "    final class SAC3 extends SAC {}\n" +
+            "    final class SAC4 extends SAC2 {}\n" +
+            "    sealed interface SI {}\n" +
+            "    sealed interface SSI extends SI {}\n" +
+            "    final class SAC5 implements SI, SSI {}\n" +
+            "    non-sealed abstract class SAC6 extends SAC {}\n" +
+            "    non-sealed class SAC7 extends SAC {}\n" +
+            "}";
+
+    public static void main(String[] args) throws Exception {
+        new CheckSubtypesOfSealedTest().run();
+    }
+
+    void run() throws Exception {
+        InMemoryFileManager fileManager = compile(List.of("--enable-preview", "-source",
+                Integer.toString(Runtime.version().feature())), testSource);
+        checkClassFile(readClassFile(fileManager.getClasses().get("SealedClasses$SAC2")), CheckFor.SEALED);
+        checkClassFile(readClassFile(fileManager.getClasses().get("SealedClasses$SAC3")), CheckFor.FINAL);
+        checkClassFile(readClassFile(fileManager.getClasses().get("SealedClasses$SAC4")), CheckFor.FINAL);
+        checkClassFile(readClassFile(fileManager.getClasses().get("SealedClasses$SSI")), CheckFor.SEALED);
+        checkClassFile(readClassFile(fileManager.getClasses().get("SealedClasses$SAC5")), CheckFor.FINAL);
+        checkClassFile(readClassFile(fileManager.getClasses().get("SealedClasses$SAC6")), CheckFor.NOT_SEALED);
+        checkClassFile(readClassFile(fileManager.getClasses().get("SealedClasses$SAC7")), CheckFor.NOT_SEALED);
+    }
+
+    enum CheckFor {
+        SEALED {
+            void check(ClassFile classFile) throws Exception {
+                boolean found = false;
+                for (Attribute attr: classFile.attributes) {
+                    if (attr.getName(classFile.constant_pool).equals("PermittedSubclasses")) {
+                        PermittedSubclasses_attribute permittedSubclasses = (PermittedSubclasses_attribute)attr;
+                        found = true;
+                        if (permittedSubclasses.subtypes == null || permittedSubclasses.subtypes.length == 0) {
+                            throw new AssertionError(classFile.getName() + " should be sealed");
+                        }
+                    }
+                }
+                if (!found) {
+                    throw new AssertionError(classFile.getName() + " should be sealed");
+                }
+            }
+        },
+        FINAL {
+            void check(ClassFile classFile) throws Exception {
+                if ((classFile.access_flags.flags & Flags.FINAL) == 0) {
+                    throw new AssertionError(classFile.getName() + " should be final");
+                }
+            }
+        },
+        NOT_SEALED {
+            void check(ClassFile classFile) throws Exception {
+                for (Attribute attr: classFile.attributes) {
+                    if (attr.getName(classFile.constant_pool).equals("PermittedSubclasses")) {
+                        throw new AssertionError(classFile.getName() + " should not be sealed");
+                    }
+                }
+                if ((classFile.access_flags.flags & Flags.FINAL) != 0) {
+                    throw new AssertionError(classFile.getName() + " should not be final");
+                }
+            }
+        };
+
+        abstract void check(ClassFile classFile) throws Exception;
+    }
+
+    void checkClassFile(final ClassFile classFile, CheckFor... checkFor) throws Exception {
+        for (CheckFor whatToCheckFor : checkFor) {
+            whatToCheckFor.check(classFile);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/sealed/SealedCompilationTests.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,753 @@
+/*
+ * Copyright (c) 2019, 2020, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+/**
+ * SealedCompilationTests
+ *
+ * @test
+ * @summary Negative compilation tests, and positive compilation (smoke) tests for sealed classes
+ * @library /lib/combo /tools/lib
+ * @modules
+ *     jdk.compiler/com.sun.tools.javac.util
+ *     jdk.compiler/com.sun.tools.javac.api
+ *     jdk.compiler/com.sun.tools.javac.main
+ * @build toolbox.ToolBox toolbox.JavacTask
+ * @compile --enable-preview -source ${jdk.version} SealedCompilationTests.java
+ * @run testng/othervm --enable-preview SealedCompilationTests
+ */
+
+import java.lang.constant.ClassDesc;
+
+import java.io.File;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import com.sun.tools.javac.util.Assert;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+import org.testng.annotations.Test;
+import tools.javac.combo.CompilationTestCase;
+
+import toolbox.ToolBox;
+import toolbox.JavacTask;
+import toolbox.Task;
+import toolbox.Task.OutputKind;
+
+@Test
+public class SealedCompilationTests extends CompilationTestCase {
+
+    ToolBox tb = new ToolBox();
+
+    // When sealed classes become a permanent feature, we don't need these any more
+    private static String[] PREVIEW_OPTIONS = {"--enable-preview", "-source",
+                                               Integer.toString(Runtime.version().feature())};
+
+    {
+        setDefaultFilename("SealedTest.java");
+        setCompileOptions(PREVIEW_OPTIONS);
+    }
+
+    private static final String NO_SHELL = """
+                 #
+                 """;
+    private static final String NEST_SHELL = """
+                 class SealedTest {
+                     #
+                 }
+                 """;
+    private static final String AUX_SHELL = """
+                 class SealedTest {
+                 }
+                 #
+                 """;
+    private static final List<String> SHELLS = List.of(NO_SHELL, NEST_SHELL, AUX_SHELL);
+
+    public void testSimpleExtension() {
+        String CC1 =
+            """
+            sealed class Sup # { }
+            # class Sub extends Sup { }
+            """;
+
+        String CC2 =
+                """
+                sealed class Sup<T> # { }
+                # class Sub<T> extends Sup<T> { }
+                """;
+        String CC3 =
+                """
+                sealed class Sup<T> # { }
+                    # class Sub extends Sup<String> { }
+                """;
+        String AC1 =
+            """
+            sealed abstract class Sup # { }
+            # class Sub extends Sup { }
+            """;
+        String AC2 =
+                """
+                sealed abstract class Sup<T> # { }
+                    # class Sub<T> extends Sup<T> { }
+                """;
+        String AC3 =
+                """
+                sealed abstract class Sup<T> # { }
+                    # class Sub extends Sup<String> { }
+                """;
+        String I1 =
+            """
+            sealed interface Sup # { }
+            # class Sub implements Sup { }
+            """;
+        String I11 =
+                """
+                sealed interface Sup<T> # { }
+                # class Sub<T> implements Sup<T> { }
+                """;
+        String I12 =
+                """
+                sealed interface Sup<T> # { }
+                # class Sub<T> implements Sup<String> { }
+                """;
+        String I2 =
+            """
+            sealed interface Sup # { }
+            # class Sub1 implements Sup { }
+            # class Sub2 implements Sup { }
+            """;
+
+        // Assert that all combinations work:
+        // { class, abs class, interface } x { implicit permits, explicit permits }
+        //                                 x { final, non-sealed subtype }
+        for (String shell : SHELLS)
+            for (String b : List.of(CC1, CC2, CC3, AC1, AC2, AC3, I1, I11, I12))
+                for (String p : List.of("", "permits Sub"))
+                    for (String m : List.of("final", "non-sealed", "non\u002Dsealed"))
+                        assertOK(shell, b, p, m);
+
+
+        // Same for type with two subtypes
+        for (String shell : SHELLS)
+            for (String p : List.of("", "permits Sub1, Sub2"))
+                for (String m : List.of("final", "non-sealed", "non\u002Dsealed"))
+                    assertOK(shell, expandMarkers(I2, p, m, m));
+
+        // Expect failure if there is no explicit final / sealed / non-sealed
+        for (String shell : SHELLS)
+            for (String b : List.of(CC1, CC2, CC3, AC1, AC2, AC3, I1, I11, I12))
+                for (String p : List.of("", "permits Sub"))
+                    for (String m : List.of(""))
+                        assertFail("compiler.err.non.sealed.sealed.or.final.expected", shell, expandMarkers(b, p, m));
+    }
+
+    public void testSealedAndRecords() {
+        String P =
+            """
+            sealed interface Sup # { }
+            record A(int a) implements Sup { }
+            record B(int b) implements Sup { }
+            record C(int c) implements Sup { }
+            """;
+
+        for (String shell : SHELLS)
+            for (String b : List.of(P))
+                for (String p : List.of("", "permits A, B, C"))
+                    assertOK(shell, b, p);
+    }
+
+    // Test that a type that explicitly permits one type, can't be extended by another
+    public void testBadExtension() {
+        String CC2 =
+                """
+                sealed class Sup permits Sub1 { }
+                final class Sub1 extends Sup { }
+                final class Sub2 extends Sup { }
+                """;
+        String AC2 =
+                """
+                sealed abstract class Sup permits Sub1 { }
+                final class Sub1 extends Sup { }
+                final class Sub2 extends Sup { }
+                """;
+        String I2c =
+                """
+                sealed interface Sup permits Sub1 { }
+                final class Sub1 implements Sup { }
+                final class Sub2 implements Sup { }
+                """;
+        String I2i =
+                """
+                sealed interface Sup permits Sub1 { }
+                non-sealed interface Sub1 extends Sup { }
+                non-sealed interface Sub2 extends Sup { }
+                """;
+
+        for (String shell : SHELLS)
+            for (String b : List.of(CC2, AC2, I2c, I2i))
+                assertFail("compiler.err.cant.inherit.from.sealed", shell, b);
+    }
+
+    public void testRestrictedKeyword() {
+        for (String s : List.of(
+                "class SealedTest { String sealed; }",
+                "class SealedTest { int sealed = 0; int non = 0; int ns = non-sealed; }",
+                "class SealedTest { void test(String sealed) { } }",
+                "class SealedTest { void sealed(String sealed) { } }",
+                "class SealedTest { void test() { String sealed = null; } }"
+        )) {
+            assertOK(s);
+        }
+
+        for (String s : List.of(
+                "class sealed {}",
+                "interface sealed {}",
+                "@interface sealed {}"
+        )) {
+            assertFail("compiler.err.restricted.type.not.allowed", s);
+        }
+
+        for (String s : List.of(
+                "class Foo { sealed m() {} }",
+                "class Foo { sealed i; }",
+                "class Foo { void m(sealed i) {} }"
+                )) {
+            assertFail("compiler.err.restricted.type.not.allowed.here", s);
+        }
+
+        String[] testOptions = {/* no options */};
+        setCompileOptions(testOptions);
+        // now testing with preview disabled
+        for (String s : List.of(
+                "sealed class S {}",
+                "class Outer { sealed class S {} }",
+                "class Outer { void m() { sealed class S {} } }",
+                "non-sealed class S {}",
+                "class Outer { non-sealed class S {} }",
+                "class Outer { void m() { non-sealed class S {} } }"
+        )) {
+            assertFail("compiler.err.preview.feature.disabled.plural", s);
+        }
+        setCompileOptions(PREVIEW_OPTIONS);
+    }
+
+    public void testRejectPermitsInNonSealedClass() {
+        assertFail("compiler.err.invalid.permits.clause",
+                "class SealedTest {\n" +
+                "    class NotSealed permits Sub {}\n" +
+                "    class Sub extends NotSealed {}\n" +
+                "}");
+        assertFail("compiler.err.invalid.permits.clause",
+                "class SealedTest {\n" +
+                "    interface NotSealed permits Sub {}\n" +
+                "    class Sub implements NotSealed {}\n" +
+                "}");
+    }
+
+    public void testTypeInPermitsIsSameClassOrSuper() {
+        assertFail("compiler.err.invalid.permits.clause",
+                """
+                sealed class Sealed permits Sealed {}
+                """
+                );
+        assertFail("compiler.err.invalid.permits.clause",
+                """
+                interface I {}
+                sealed class Sealed implements I permits I {}
+                """
+                );
+        assertFail("compiler.err.invalid.permits.clause",
+                """
+                interface I {}
+                interface I2 extends I {}
+                sealed class Sealed implements I2 permits I {}
+                """
+                );
+    }
+
+    /* It is a compile-time error if a class declaration has more than one of the class modifiers
+     * sealed, non-sealed and final
+     */
+    public void testBadModifiers() {
+        assertFail("compiler.err.non.sealed.with.no.sealed.supertype",
+                "class SealedTest { non-sealed class NoSealedSuper {} }");
+        assertFail("compiler.err.mod.not.allowed.here",
+                   "class SealedTest { sealed public void m() {} }");
+        for (String s : List.of(
+                "class SealedTest { sealed non-sealed class Super {} }",
+                "class SealedTest { final non-sealed class Super {} }",
+                "class SealedTest { final sealed class Super {} }",
+                "class SealedTest { final sealed non-sealed class Super {} }",
+                "class SealedTest {\n" +
+                "    sealed class Super {}\n" +
+                "    sealed non-sealed class Sub extends Super {}\n" +
+                "}"))
+            assertFail("compiler.err.illegal.combination.of.modifiers", s);
+    }
+
+    public void testAnonymous_FunctionalExpr_and_Sealed() {
+        for (String s : List.of(
+                """
+                sealed interface I extends Runnable {
+                    public static I i = () -> {};
+                }
+
+                final class Sub implements I {}
+                """,
+                """
+                sealed interface I extends Runnable {}
+
+                final class Sub implements I {
+                    I a = Sub::action;
+                    static void action() {}
+                }
+                """
+                ))
+            assertFail("compiler.err.prob.found.req", s);
+
+        for (String s : List.of(
+                """
+                @FunctionalInterface
+                sealed interface Action {
+                    void doAction();
+                }
+
+                final class C implements Action {
+                    public void doAction() {}
+                }
+                """
+                ))
+            assertFail("compiler.err.bad.functional.intf.anno.1", s);
+
+        for (String s : List.of(
+                """
+                sealed interface I extends Runnable {
+                    public static I i = new I() { public void run() { } };
+                }
+                final class C implements I {
+                    @Override public void run() {}
+                }
+                """
+                ))
+            assertFail("compiler.err.local.classes.cant.extend.sealed", s);
+
+        for (String s : List.of(
+                """
+                sealed interface I extends Runnable {
+                    public static void foo() { new I() { public void run() { } }; }
+                }
+                final class C implements I {
+                    @Override public void run() {}
+                }
+                """
+                ))
+        assertFail("compiler.err.local.classes.cant.extend.sealed", s);
+    }
+
+    public void testNoLocalSealedClasses() {
+        for (String s : List.of(
+                """
+                sealed class C {
+                    void m() {
+                        sealed class D { }
+                    }
+                }
+                """,
+                """
+                sealed class C {
+                    void m() {
+                        non-sealed class D { }
+                    }
+                }
+                """))
+            assertFail("compiler.err.sealed.or.non.sealed.local.classes.not.allowed", s);
+    }
+
+    public void testLocalCantExtendSealed() {
+        for (String s : List.of(
+                """
+                sealed class C {
+                    void m() {
+                        final class D extends C { }
+                    }
+                }
+                """))
+            assertFail("compiler.err.local.classes.cant.extend.sealed", s);
+    }
+
+    public void testSealedInterfaceAndAbstracClasses() {
+        for (String s : List.of(
+                """
+                sealed interface I {}
+                """,
+                """
+                sealed abstract class AC {}
+                """,
+                """
+                sealed class C {}
+                """))
+            assertFail("compiler.err.sealed.class.must.have.subclasses", s);
+
+        for (String s : List.of(
+                """
+                sealed interface I {}
+
+                non-sealed interface I2 extends I {}
+                """,
+                """
+                sealed interface I {}
+
+                sealed interface I2 extends I {}
+
+                non-sealed interface I3 extends I2 {}
+                """,
+                """
+                sealed interface I permits I2 {}
+
+                non-sealed interface I2 extends I {}
+                """,
+                """
+                sealed interface I permits I2 {}
+
+                sealed interface I2 extends I permits I3 {}
+
+                non-sealed interface I3 extends I2 {}
+                """
+                ))
+            assertOK(s);
+    }
+
+    public void testEnumsCantBeSealedOrNonSealed() {
+        for (String s : List.of(
+                """
+                sealed interface I {}
+
+                sealed enum E implements I {E1}
+                """,
+                """
+                sealed interface I {}
+
+                non-sealed enum E implements I {E1}
+                """))
+            assertFail("compiler.err.mod.not.allowed.here", s);
+    }
+
+    public void testEnumsCanImplementSealedInterfaces() {
+        for (String s : List.of(
+                """
+                sealed interface I {}
+
+                enum E implements I {E1}
+                """))
+            assertOK(s);
+    }
+
+    public void testClassesCanExtendNonSealed() {
+        for (String s : List.of(
+                """
+                sealed class C {}
+
+                non-sealed class Sub extends C {}
+
+                class Sub2 extends Sub {}
+                """)) {
+            assertOK(s);
+        }
+    }
+
+    public void testEmptyPermits() {
+        for (String s : List.of(
+            """
+            sealed class C permits {}
+            non-sealed class Sub extends C {}
+            """)) {
+            assertFail("compiler.err.expected", s);
+        }
+    }
+
+    public void testTypeVarInPermits() {
+        for (String s : List.of(
+            """
+            class Outer<T> {
+                sealed class C permits T  {}
+            }
+            """)) {
+            assertFail("compiler.err.invalid.permits.clause", s);
+        }
+    }
+
+    public void testRepeatedTypeInPermits() {
+        for (String s : List.of(
+            """
+            sealed class C permits Sub, Sub {}
+
+            final class Sub extends C {}
+            """)) {
+            assertFail("compiler.err.invalid.permits.clause", s);
+        }
+    }
+
+    public void testSubtypeDoesntExtendSealed() {
+        for (String s : List.of(
+            """
+            sealed class C permits Sub {}
+
+            final class Sub {}
+            """,
+            """
+            sealed interface I permits Sub {}
+
+            final class Sub {}
+            """,
+            """
+            sealed class C permits Sub1, Sub2 {}
+
+            sealed class Sub1 extends C permits Sub2 {}
+
+            final class Sub2 extends Sub1 {}
+            """
+            )) {
+            assertFail("compiler.err.invalid.permits.clause", s);
+        }
+    }
+
+    public void testAPIForPrimitiveAndArrayClasses() {
+        for (Class<?> c : new Class[]{byte.class, byte[].class, short.class, short[].class, int.class, int[].class, long.class, long[].class,
+            float.class, float[].class, double.class, double[].class, char.class, char[].class, boolean.class, boolean[].class, void.class,
+            String[].class}) {
+            Assert.check(!c.isSealed());
+            Assert.check(c.permittedSubclasses().length == 0);
+        }
+    }
+
+    public void testPrinting() throws Exception {
+        Path base = Paths.get("testPrinting");
+        Path src = base.resolve("src");
+        Path test = src.resolve("Test");
+
+        tb.writeJavaFiles(test,
+            """
+            sealed class SealedClassNoPermits {}
+
+            final class FinalSubClass extends SealedClassNoPermits {}
+
+            non-sealed class NonSealedSubClass extends SealedClassNoPermits {}
+
+            sealed interface SealedInterfaceNoPermits {}
+
+            non-sealed interface NonSealedInterface extends SealedInterfaceNoPermits {}
+
+            final class FinalSubClass2 implements SealedInterfaceNoPermits {}
+
+
+            sealed class SealedClassWithPermits permits SealedClassWithPermits, NonSealedSubClass2 {}
+
+            final class FinalSubClass3 extends SealedClassWithPermits {}
+
+            non-sealed class NonSealedSubClass2 extends SealedClassWithPermits {}
+
+            sealed interface SealedInterfaceWithPermits permits NonSealedInterface2, FinalSubClass4 {}
+
+            non-sealed interface NonSealedInterface2 extends SealedInterfaceWithPermits {}
+
+            final class FinalSubClass4 implements SealedInterfaceWithPermits {}
+
+
+            enum SealedEnum {
+                E {}
+            }
+
+            enum Enum {
+                E
+            }
+            """
+        );
+
+        Path out = base.resolve("out");
+
+        Files.createDirectories(out);
+
+        List<String> output = new JavacTask(tb)
+            .outdir(out)
+            .options("--enable-preview", "-source", Integer.toString(Runtime.version().feature()), "-Xprint")
+            .files(findJavaFiles(test))
+            .run()
+            .writeAll()
+            .getOutputLines(OutputKind.STDOUT);
+
+        List<String> expected = List.of(
+            "sealed class SealedClassNoPermits permits FinalSubClass, NonSealedSubClass {",
+            "  SealedClassNoPermits();",
+            "}",
+            "final class FinalSubClass extends SealedClassNoPermits {",
+            "  FinalSubClass();",
+            "}",
+            "non-sealed class NonSealedSubClass extends SealedClassNoPermits {",
+            "  NonSealedSubClass();",
+            "}",
+            "sealed interface SealedInterfaceNoPermits permits NonSealedInterface, FinalSubClass2 {",
+            "}",
+            "non-sealed interface NonSealedInterface extends SealedInterfaceNoPermits {",
+            "}",
+            "final class FinalSubClass2 implements SealedInterfaceNoPermits {",
+            "  FinalSubClass2();",
+            "}",
+            "sealed class SealedClassWithPermits permits SealedClassWithPermits, NonSealedSubClass2 {",
+            "  SealedClassWithPermits();",
+            "}",
+            "final class FinalSubClass3 extends SealedClassWithPermits {",
+            "  FinalSubClass3();",
+            "}",
+            "non-sealed class NonSealedSubClass2 extends SealedClassWithPermits {",
+            "  NonSealedSubClass2();",
+            "}",
+            "sealed interface SealedInterfaceWithPermits permits NonSealedInterface2, FinalSubClass4 {",
+            "}",
+            "non-sealed interface NonSealedInterface2 extends SealedInterfaceWithPermits {",
+            "}",
+            "final class FinalSubClass4 implements SealedInterfaceWithPermits {",
+            "  FinalSubClass4();",
+            "}",
+            "enum SealedEnum {",
+            "  E;",
+            "  public static SealedEnum[] values();",
+            "  public static SealedEnum valueOf(java.lang.String name);",
+            "  private SealedEnum();",
+            "}",
+            "enum Enum {",
+            "  E;",
+            "  public static Enum[] values();",
+            "  public static Enum valueOf(java.lang.String name);",
+            "  private Enum();",
+            "}"
+        );
+        // remove empty strings
+        String newLine = System.getProperty("line.separator");
+        output = output.stream().filter(s -> !s.isEmpty()).map(s -> s.replaceAll(newLine, "\n").replaceAll("\n", "")).collect(Collectors.toList());
+        if (!output.containsAll(expected)) {
+            for (int i = 0; i < output.size(); i++) {
+                if (!output.get(i).equals(expected.get(i))) {
+                    System.out.println("failing at index " + i);
+                    System.out.println("expected:" + expected.get(i));
+                    System.out.println("found:" + output.get(i));
+                }
+            }
+            throw new AssertionError("Expected output not found. Expected: " + expected);
+        }
+    }
+
+    public void testIllFormedNonSealed() {
+        for (String s : List.of(
+            """
+            sealed class C permits Sub {}
+            non -sealed class Sub extends C {}
+            """,
+            """
+            sealed class C permits Sub {}
+            non sealed class Sub extends C {}
+            """,
+            """
+            sealed class C permits Sub {}
+            non - sealed class Sub extends C {}
+            """,
+            """
+            sealed class C permits Sub {}
+            non/**/sealed class Sub extends C {}
+            """
+            )) {
+            assertFail("compiler.err.expected4", s);
+        }
+    }
+
+    public void testParameterizedPermitted() {
+        for (String s : List.of(
+            """
+            sealed class C<T> permits Sub<T> {}
+            final class Sub<T> extends C<T> {}
+            """,
+            """
+            sealed class C permits Sub<String> {}
+            final class Sub<T> extends C {}
+            """
+            )) {
+            assertFail("compiler.err.expected", s);
+        }
+    }
+
+    private Path[] findJavaFiles(Path... paths) throws IOException {
+        return tb.findJavaFiles(paths);
+    }
+
+    public void testSealedNonSealedWithOtherModifiers() {
+        String template1 =
+            """
+            @interface A {}
+
+            class Outer {
+                sealed class Sup { }
+                # # class Sub extends Sup {}
+                final class Sub2 extends Sub {}
+            }
+            """;
+
+        String template2 =
+            """
+            @interface A {}
+
+            class Outer {
+                sealed interface Sup { }
+                # # interface Sub extends Sup {}
+                final class Sub2 implements Sub {}
+            }
+            """;
+
+        List<String> templateList = List.of(template1, template2);
+        List<String> otherModifiers = List.of(
+                "@A", "public", "protected", "private", "abstract", "static", "strictfp", "final", "sealed", "non-sealed"
+        );
+
+        for (String template : templateList) {
+            for (String sealed_non_sealed : List.of("sealed", "non-sealed")) {
+                for (String modifier : otherModifiers) {
+                    if (sealed_non_sealed.equals(modifier)) {
+                        assertFail("compiler.err.repeated.modifier", template, sealed_non_sealed, modifier);
+                    } else if (modifier.equals("final") || modifier.equals("sealed") || modifier.equals("non-sealed")) {
+                        assertFail("compiler.err.illegal.combination.of.modifiers", template, sealed_non_sealed, modifier);
+                    } else {
+                        assertOK(template, sealed_non_sealed, modifier);
+                    }
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/sealed/SealedDiffConfigurationsTest.java	Mon Jun 01 17:00:40 2020 -0400
@@ -0,0 +1,680 @@
+/*
+ * Copyright (c) 2018, 2020, 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 different configurations of sealed classes, same compilation unit, diff pkg or mdl, etc
+ * @library /tools/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.compiler/com.sun.tools.javac.util
+ *          jdk.compiler/com.sun.tools.javac.code
+ *          jdk.jdeps/com.sun.tools.classfile
+ * @build toolbox.ToolBox toolbox.JavacTask
+ * @run main SealedDiffConfigurationsTest
+ */
+
+import java.util.*;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.stream.IntStream;
+
+import com.sun.tools.classfile.*;
+import com.sun.tools.javac.code.Flags;
+import com.sun.tools.javac.util.Assert;
+import toolbox.TestRunner;
+import toolbox.ToolBox;
+import toolbox.JavacTask;
+import toolbox.Task;
+import toolbox.Task.OutputKind;
+
+import static com.sun.tools.classfile.ConstantPool.*;
+
+public class SealedDiffConfigurationsTest extends TestRunner {
+    ToolBox tb;
+
+    SealedDiffConfigurationsTest() {
+        super(System.err);
+        tb = new ToolBox();
+    }
+
+    protected void runTests() throws Exception {
+        runTests(m -> new Object[] { Paths.get(m.getName()) });
+    }
+
+    public static void main(String... args) throws Exception {
+        SealedDiffConfigurationsTest t = new SealedDiffConfigurationsTest();
+        t.runTests();
+    }
+
+    Path[] findJavaFiles(Path... paths) throws IOException {
+        return tb.findJavaFiles(paths);
+    }
+
+    @Test
+    public void testSameCompilationUnitPos(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path test = src.resolve("Test");
+
+        tb.writeJavaFiles(test,
+                          "class Test {\n" +
+                           "    sealed class Sealed permits Sub1, Sub2 {}\n" +
+                           "    final class Sub1 extends Sealed {}\n" +
+                           "    final class Sub2 extends Sealed {}\n" +
+                           "}");
+
+        Path out = base.resolve("out");
+
+        Files.createDirectories(out);
+
+        new JavacTask(tb)
+                .outdir(out)
+                .options("--enable-preview", "-source", Integer.toString(Runtime.version().feature()))
+                .files(findJavaFiles(test))
+                .run()
+                .writeAll();
+
+        checkSealedClassFile(out, "Test$Sealed.class", List.of("Test$Sub1", "Test$Sub2"));
+        checkSubtypeClassFile(out, "Test$Sub1.class", "Test$Sealed", true);
+        checkSubtypeClassFile(out, "Test$Sub2.class", "Test$Sealed", true);
+    }
+
+    @Test
+    public void testSameCompilationUnitPos2(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path test = src.resolve("Test");
+
+        tb.writeJavaFiles(test,
+                "class Test {\n" +
+                        "    sealed class Sealed {}\n" +
+                        "    final class Sub1 extends Sealed {}\n" +
+                        "    final class Sub2 extends Sealed {}\n" +
+                        "}");
+
+        Path out = base.resolve("out");
+
+        Files.createDirectories(out);
+
+        new JavacTask(tb)
+                .outdir(out)
+                .files(findJavaFiles(test))
+                .options("--enable-preview", "-source", Integer.toString(Runtime.version().feature()))
+                .run()
+                .writeAll();
+
+        checkSealedClassFile(out, "Test$Sealed.class", List.of("Test$Sub1", "Test$Sub2"));
+        checkSubtypeClassFile(out, "Test$Sub1.class", "Test$Sealed", true);
+        checkSubtypeClassFile(out, "Test$Sub2.class", "Test$Sealed", true);
+    }
+
+    private void checkSealedClassFile(Path out, String cfName, List<String> expectedSubTypeNames) throws ConstantPoolException, Exception {
+        ClassFile sealedCF = ClassFile.read(out.resolve(cfName));
+        Assert.check((sealedCF.access_flags.flags & Flags.FINAL) == 0, String.format("class at file %s must not be final", cfName));
+        PermittedSubclasses_attribute permittedSubclasses = (PermittedSubclasses_attribute)sealedCF.attributes.get("PermittedSubclasses");
+        Assert.check(permittedSubclasses.subtypes.length == expectedSubTypeNames.size());
+        List<String> subtypeNames = new ArrayList<>();
+        IntStream.of(permittedSubclasses.subtypes).forEach(i -> {
+            try {
+                subtypeNames.add(((CONSTANT_Class_info)sealedCF.constant_pool.get(i)).getName());
+            } catch (ConstantPoolException ex) {
+            }
+        });
+        subtypeNames.sort((s1, s2) -> s1.compareTo(s2));
+        for (int i = 0; i < expectedSubTypeNames.size(); i++) {
+            Assert.check(expectedSubTypeNames.get(0).equals(subtypeNames.get(0)));
+        }
+    }
+
+    private void checkSubtypeClassFile(Path out, String cfName, String superClassName, boolean shouldBeFinal) throws Exception {
+        ClassFile subCF1 = ClassFile.read(out.resolve(cfName));
+        if (shouldBeFinal) {
+            Assert.check((subCF1.access_flags.flags & Flags.FINAL) != 0, String.format("class at file %s must be final", cfName));
+        }
+        Assert.checkNull((PermittedSubclasses_attribute)subCF1.attributes.get("PermittedSubclasses"));
+        Assert.check(((CONSTANT_Class_info)subCF1.constant_pool.get(subCF1.super_class)).getName().equals(superClassName));
+    }
+
+    @Test
+    public void testSamePackagePos(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path pkg = src.resolve("pkg");
+        Path sealed = pkg.resolve("Sealed");
+        Path sub1 = pkg.resolve("Sub1");
+        Path sub2 = pkg.resolve("Sub2");
+
+        tb.writeJavaFiles(sealed,
+                          "package pkg;\n" +
+                          "\n" +
+                          "sealed class Sealed permits Sub1, Sub2 {\n" +
+                          "}");
+        tb.writeJavaFiles(sub1,
+                          "package pkg;\n" +
+                          "\n" +
+                          "final class Sub1 extends Sealed {\n" +
+                          "}");
+        tb.writeJavaFiles(sub2,
+                          "package pkg;\n" +
+                          "\n" +
+                          "final class Sub2 extends Sealed {\n" +
+                          "}");
+
+        Path out = base.resolve("out");
+
+        Files.createDirectories(out);
+
+        new JavacTask(tb)
+                .outdir(out)
+                .files(findJavaFiles(pkg))
+                .options("--enable-preview", "-source", Integer.toString(Runtime.version().feature()))
+                .run()
+                .writeAll();
+
+        checkSealedClassFile(out.resolve("pkg"), "Sealed.class", List.of("pkg/Sub1", "pkg/Sub1"));
+        checkSubtypeClassFile(out.resolve("pkg"), "Sub1.class", "pkg/Sealed", true);
+        checkSubtypeClassFile(out.resolve("pkg"), "Sub2.class", "pkg/Sealed", true);
+    }
+
+    @Test
+    public void testSameCompilationUnitNeg(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path test = src.resolve("Test");
+
+        tb.writeJavaFiles(test,
+                          "class Test {\n" +
+                           "    sealed class Sealed permits Sub1 {}\n" +
+                           "    final class Sub1 extends Sealed {}\n" +
+                           "    class Sub2 extends Sealed {}\n" +
+                           "}");
+
+        List<String> error = new JavacTask(tb)
+                .options("-XDrawDiagnostics", "--enable-preview", "-source", Integer.toString(Runtime.version().feature()))
+                .files(findJavaFiles(test))
+                .run(Task.Expect.FAIL)
+                .writeAll()
+                .getOutputLines(OutputKind.DIRECT);
+
+        List<String> expected = List.of(
+                "Test.java:4:5: compiler.err.cant.inherit.from.sealed: Test.Sealed",
+                "1 error");
+        if (!error.containsAll(expected)) {
+            throw new AssertionError("Expected output not found. Expected: " + expected);
+        }
+    }
+
+    @Test
+    public void testSameCompilationUnitNeg2(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path test = src.resolve("Test");
+
+        tb.writeJavaFiles(test,
+                "class Test {\n" +
+                        "    sealed class Sealed permits Sub1 {}\n" +
+                        "    class Sub1 extends Sealed {}\n" +
+                        "}");
+
+        List<String> error = new JavacTask(tb)
+                .options("-XDrawDiagnostics", "--enable-preview", "-source", Integer.toString(Runtime.version().feature()))
+                .files(findJavaFiles(test))
+                .run(Task.Expect.FAIL)
+                .writeAll()
+                .getOutputLines(OutputKind.DIRECT);
+
+        List<String> expected = List.of(
+                "Test.java:3:5: compiler.err.non.sealed.sealed.or.final.expected",
+                "1 error");
+        if (!error.containsAll(expected)) {
+            throw new AssertionError("Expected output not found. Expected: " + expected);
+        }
+    }
+
+    @Test
+    public void testSamePackageNeg(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path pkg = src.resolve("pkg");
+        Path sealed = pkg.resolve("Sealed");
+        Path sub1 = pkg.resolve("Sub1");
+        Path sub2 = pkg.resolve("Sub2");
+
+        tb.writeJavaFiles(sealed,
+                          "package pkg;\n" +
+                          "\n" +
+                          "sealed class Sealed permits Sub1 {\n" +
+                          "}");
+        tb.writeJavaFiles(sub1,
+                          "package pkg;\n" +
+                          "\n" +
+                          "final class Sub1 extends Sealed {\n" +
+                          "}");
+        tb.writeJavaFiles(sub2,
+                          "package pkg;\n" +
+                          "\n" +
+                          "class Sub2 extends Sealed {\n" +
+                          "}");
+
+        List<String> error = new JavacTask(tb)
+                .options("-XDrawDiagnostics", "--enable-preview", "-source", Integer.toString(Runtime.version().feature()))
+                .files(findJavaFiles(pkg))
+                .run(Task.Expect.FAIL)
+                .writeAll()
+                .getOutputLines(OutputKind.DIRECT);
+
+        List<String> expected = List.of(
+                "Sub2.java:3:1: compiler.err.cant.inherit.from.sealed: pkg.Sealed",
+                "1 error"
+                );
+        if (!error.containsAll(expected)) {
+            throw new AssertionError("Expected output not found. Expected: " + expected);
+        }
+    }
+
+    @Test
+    public void testSamePackageNeg2(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path pkg = src.resolve("pkg");
+        Path sealed = pkg.resolve("Sealed");
+        Path sub1 = pkg.resolve("Sub1");
+
+        tb.writeJavaFiles(sealed,
+                "package pkg;\n" +
+                        "\n" +
+                        "final class Sealed {\n" +
+                        "}");
+        tb.writeJavaFiles(sub1,
+                "package pkg;\n" +
+                        "\n" +
+                        "class Sub1 extends Sealed {\n" +
+                        "}");
+
+        List<String> error = new JavacTask(tb)
+                .options("-XDrawDiagnostics", "--enable-preview", "-source", Integer.toString(Runtime.version().feature()))
+                .files(findJavaFiles(pkg))
+                .run(Task.Expect.FAIL)
+                .writeAll()
+                .getOutputLines(OutputKind.DIRECT);
+
+        List<String> expected = List.of(
+                "Sub1.java:3:20: compiler.err.cant.inherit.from.final: pkg.Sealed",
+                "1 error");
+        if (!error.containsAll(expected)) {
+            throw new AssertionError("Expected output not found. Expected: " + expected);
+        }
+    }
+
+    @Test
+    public void testSamePackageNeg3(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path pkg = src.resolve("pkg");
+        Path sealed = pkg.resolve("Sealed");
+        Path sub1 = pkg.resolve("Sub1");
+
+        tb.writeJavaFiles(sealed,
+                "package pkg;\n" +
+                        "\n" +
+                        "sealed class Sealed permits Sub1{\n" +
+                        "}");
+        tb.writeJavaFiles(sub1,
+                "package pkg;\n" +
+                        "\n" +
+                        "class Sub1 extends Sealed {\n" +
+                        "}");
+
+        List<String> error = new JavacTask(tb)
+                .options("-XDrawDiagnostics", "--enable-preview", "-source", Integer.toString(Runtime.version().feature()))
+                .files(findJavaFiles(pkg))
+                .run(Task.Expect.FAIL)
+                .writeAll()
+                .getOutputLines(OutputKind.DIRECT);
+
+        List<String> expected = List.of(
+                "Sub1.java:3:1: compiler.err.non.sealed.sealed.or.final.expected",
+                "1 error");
+        if (!error.containsAll(expected)) {
+            throw new AssertionError("Expected output not found. Expected: " + expected);
+        }
+    }
+
+    @Test
+    public void testDiffPackageNeg(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path pkg1 = src.resolve("pkg1");
+        Path pkg2 = src.resolve("pkg2");
+        Path sealed = pkg1.resolve("Sealed");
+        Path sub1 = pkg2.resolve("Sub1");
+        Path sub2 = pkg2.resolve("Sub2");
+
+        tb.writeJavaFiles(sealed,
+                "package pkg1;\n" +
+                        "import pkg2.*;\n" +
+                        "public sealed class Sealed permits pkg2.Sub1 {\n" +
+                        "}");
+        tb.writeJavaFiles(sub1,
+                "package pkg2;\n" +
+                        "import pkg1.*;\n" +
+                        "public class Sub1 extends pkg1.Sealed {\n" +
+                        "}");
+
+        List<String> error = new JavacTask(tb)
+                .options("-XDrawDiagnostics", "--enable-preview", "-source", Integer.toString(Runtime.version().feature()))
+                .files(findJavaFiles(pkg1, pkg2))
+                .run(Task.Expect.FAIL)
+                .writeAll()
+                .getOutputLines(OutputKind.DIRECT);
+
+        List<String> expected = List.of(
+                "Sub1.java:3:8: compiler.err.non.sealed.sealed.or.final.expected",
+                "Sealed.java:3:40: compiler.err.cant.inherit.from.sealed: pkg1.Sealed",
+                "2 errors");
+        if (!error.containsAll(expected)) {
+            throw new AssertionError("Expected output not found. Expected: " + expected);
+        }
+    }
+
+    @Test
+    public void testDiffPackageNeg2(Path base) throws Exception {
+        // test that the compiler rejects a subtype that is not accessible to the sealed class
+        Path src = base.resolve("src");
+        Path pkg1 = src.resolve("pkg1");
+        Path pkg2 = src.resolve("pkg2");
+        Path sealed = pkg1.resolve("Sealed");
+        Path sub1 = pkg2.resolve("Sub1");
+        Path sub2 = pkg2.resolve("Sub2");
+
+        tb.writeJavaFiles(sealed,
+                "package pkg1;\n" +
+                        "import pkg2.*;\n" +
+                        "public sealed class Sealed permits pkg2.Sub1 {\n" +
+                        "}");
+        tb.writeJavaFiles(sub1,
+                "package pkg2;\n" +
+                        "import pkg1.*;\n" +
+                        "final class Sub1 extends pkg1.Sealed {\n" +
+                        "}");
+
+        List<String> error = new JavacTask(tb)
+                .options("-XDrawDiagnostics", "--enable-preview", "-source", Integer.toString(Runtime.version().feature()))
+                .files(findJavaFiles(pkg1, pkg2))
+                .run(Task.Expect.FAIL)
+                .writeAll()
+                .getOutputLines(OutputKind.DIRECT);
+
+        List<String> expected = List.of(
+                "Sealed.java:3:40: compiler.err.not.def.public.cant.access: pkg2.Sub1, pkg2",
+                "Sub1.java:3:7: compiler.err.cant.inherit.from.sealed: pkg1.Sealed",
+                "2 errors");
+        if (!error.containsAll(expected)) {
+            throw new AssertionError("Expected output not found. Expected: " + expected);
+        }
+    }
+
+    @Test
+    public void testDiffPackageNeg3(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path pkg1 = src.resolve("pkg1");
+        Path pkg2 = src.resolve("pkg2");
+        Path sealed = pkg1.resolve("Sealed");
+        Path sub1 = pkg2.resolve("Sub1");
+        Path sub2 = pkg2.resolve("Sub2");
+
+        tb.writeJavaFiles(sealed,
+                "package pkg1;\n" +
+                        "import pkg2.*;\n" +
+                        "public sealed class Sealed permits pkg2.Sub1 {\n" +
+                        "}");
+        tb.writeJavaFiles(sub1,
+                "package pkg2;\n" +
+                        "import pkg1.*;\n" +
+                        "public final class Sub1 extends pkg1.Sealed {\n" +
+                        "}");
+
+        Path out = base.resolve("out");
+
+        Files.createDirectories(out);
+
+        List<String> error = new JavacTask(tb)
+                .options("-XDrawDiagnostics", "--enable-preview", "-source", Integer.toString(Runtime.version().feature()))
+                .files(findJavaFiles(pkg1, pkg2))
+                .run(Task.Expect.FAIL)
+                .writeAll()
+                .getOutputLines(OutputKind.DIRECT);
+
+        List<String> expected = List.of(
+                "Sealed.java:3:40: compiler.err.cant.inherit.from.sealed: pkg1.Sealed",
+                "1 error");
+        if (!error.containsAll(expected)) {
+            throw new AssertionError("Expected output not found. Found: " + error);
+        }
+    }
+
+    @Test
+    public void testSameModuleSamePkgPos(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path src_m1 = src.resolve("mSealed");
+        tb.writeJavaFiles(src_m1,
+                "module mSealed {}",
+                "package pkg; public sealed class Sealed permits pkg.Sub{}",
+                "package pkg; public final class Sub extends pkg.Sealed{}");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        new JavacTask(tb)
+                .options("--module-source-path", src.toString(), "--enable-preview", "-source", Integer.toString(Runtime.version().feature()))
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+    }
+
+    @Test
+    public void testSameModuleDiffPkgPos(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path src_m1 = src.resolve("mSealed");
+        tb.writeJavaFiles(src_m1,
+                "module mSealed {}",
+                "package pkg1; public sealed class Sealed permits pkg2.Sub{}",
+                "package pkg2; public final class Sub extends pkg1.Sealed{}");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        new JavacTask(tb)
+                .options("--module-source-path", src.toString(), "--enable-preview", "-source", Integer.toString(Runtime.version().feature()))
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+    }
+
+    @Test
+    public void testSameModuleSamePkgNeg1(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path src_m1 = src.resolve("mSealed");
+        // subclass doesn't extend super class
+        tb.writeJavaFiles(src_m1,
+                "module mSealed {}",
+                "package pkg; public sealed class Sealed permits pkg.Sub {}",
+                "package pkg; public final class Sub {}");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        List<String> error = new JavacTask(tb)
+                .options("-XDrawDiagnostics", "--module-source-path",
+                        src.toString(), "--enable-preview",
+                        "-source", Integer.toString(Runtime.version().feature()))
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(Task.Expect.FAIL)
+                .writeAll()
+                .getOutputLines(OutputKind.DIRECT);
+
+        List<String> expected = List.of(
+                "Sealed.java:1:52: compiler.err.invalid.permits.clause: (compiler.misc.doesnt.extend.sealed: pkg.Sub)",
+                "1 error");
+        if (!error.containsAll(expected)) {
+            throw new AssertionError("Expected output not found. Found: " + error);
+        }
+    }
+
+    @Test
+    public void testSameModuleSamePkgNeg2(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path src_m1 = src.resolve("mSealed");
+        // subclass doesn't extend super class
+        tb.writeJavaFiles(src_m1,
+                "module mSealed {}",
+                "package pkg; public sealed interface Sealed permits pkg.Sub1, pkg.Sub2 {}",
+                "package pkg; public sealed class Sub1 implements Sealed permits Sub2 {}",
+                "package pkg; public final class Sub2 extends Sub1 {}");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        List<String> error = new JavacTask(tb)
+                .options("-XDrawDiagnostics", "--module-source-path",
+                        src.toString(), "--enable-preview",
+                        "-source", Integer.toString(Runtime.version().feature()))
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(Task.Expect.FAIL)
+                .writeAll()
+                .getOutputLines(OutputKind.DIRECT);
+
+        List<String> expected = List.of(
+                "Sealed.java:1:66: compiler.err.invalid.permits.clause: (compiler.misc.doesnt.extend.sealed: pkg.Sub2)",
+                "1 error");
+        if (!error.containsAll(expected)) {
+            throw new AssertionError("Expected output not found. Found: " + error);
+        }
+    }
+
+    @Test
+    public void testDifferentModuleNeg(Path base) throws Exception {
+        // check that a subclass in one module can't extend a sealed class in another module
+        Path src = base.resolve("src");
+        Path src_m1 = src.resolve("mSealed");
+        tb.writeJavaFiles(src_m1,
+                "module mSealed { exports a; }",
+                "package a; public sealed class Base permits b.Impl {}"
+        );
+
+        Path src_m2 = src.resolve("mSub");
+        tb.writeJavaFiles(src_m2,
+                "module mSub { exports b; requires mSealed; }",
+                "package b; public final class Impl extends a.Base {}"
+        );
+
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+
+        List<String> error =
+            new JavacTask(tb)
+                .options("-XDrawDiagnostics",
+                        "--module-source-path", src.toString(),
+                        "--add-reads", "mSealed=mSub",
+                        "--enable-preview",
+                        "-source", Integer.toString(Runtime.version().feature()))
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(Task.Expect.FAIL)
+                .writeAll()
+                .getOutputLines(OutputKind.DIRECT);
+
+        List<String> expected = List.of(
+            "Base.java:1:46: compiler.err.cant.inherit.from.sealed: a.Base",
+            "- compiler.note.preview.filename: Base.java",
+            "- compiler.note.preview.recompile",
+            "1 error"
+        );
+        if (!error.containsAll(expected)) {
+            throw new AssertionError("Expected output not found. Found: " + error);
+        }
+    }
+
+    @Test
+    public void testSeparateCompilation(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path src_m = src.resolve("m");
+        tb.writeJavaFiles(src_m,
+                "module m {}",
+                "package pkg.a; public sealed interface Sealed permits pkg.b.Sub {}",
+                "package pkg.b; public final class Sub implements pkg.a.Sealed {}");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        new JavacTask(tb)
+                .options("-XDrawDiagnostics", "--module-source-path",
+                        src.toString(), "--enable-preview",
+                        "-source", Integer.toString(Runtime.version().feature()))
+                .outdir(classes)
+                .files(findJavaFiles(src_m))
+                .run()
+                .writeAll()
+                .getOutputLines(OutputKind.DIRECT);
+
+        new JavacTask(tb)
+                .options("-XDrawDiagnostics", "--module-source-path",
+                        src.toString(), "--enable-preview", "-doe",
+                        "-source", Integer.toString(Runtime.version().feature()))
+                .outdir(classes)
+                .files(findJavaFiles(src_m.resolve("pkg").resolve("a")))
+                .run()
+                .writeAll()
+                .getOutputLines(OutputKind.DIRECT);
+
+        new JavacTask(tb)
+                .options("-XDrawDiagnostics", "--module-source-path",
+                        src.toString(), "--enable-preview", "-doe",
+                        "-source", Integer.toString(Runtime.version().feature()))
+                .outdir(classes)
+                .files(findJavaFiles(src_m.resolve("pkg").resolve("b")))
+                .run()
+                .writeAll()
+                .getOutputLines(OutputKind.DIRECT);
+
+        tb.cleanDirectory(classes);
+
+        //implicit compilations:
+        new JavacTask(tb)
+                .options("-XDrawDiagnostics", "--module-source-path",
+                        src.toString(), "--enable-preview", "-doe",
+                        "-source", Integer.toString(Runtime.version().feature()))
+                .outdir(classes)
+                .files(findJavaFiles(src_m.resolve("pkg").resolve("a")))
+                .run()
+                .writeAll()
+                .getOutputLines(OutputKind.DIRECT);
+
+        tb.cleanDirectory(classes);
+
+        new JavacTask(tb)
+                .options("-XDrawDiagnostics", "--module-source-path",
+                        src.toString(), "--enable-preview", "-doe",
+                        "-source", Integer.toString(Runtime.version().feature()))
+                .outdir(classes)
+                .files(findJavaFiles(src_m.resolve("pkg").resolve("b")))
+                .run()
+                .writeAll()
+                .getOutputLines(OutputKind.DIRECT);
+    }
+}