Adopt ASM 8.0 (#4431)

Signed-off-by: Jan Supol <jan.supol@oracle.com>
diff --git a/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/AnnotationVisitor.java b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/AnnotationVisitor.java
index 9bb9e92..0bab02e 100644
--- a/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/AnnotationVisitor.java
+++ b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/AnnotationVisitor.java
@@ -68,9 +68,17 @@
    *     calls. May be {@literal null}.
    */
   public AnnotationVisitor(final int api, final AnnotationVisitor annotationVisitor) {
-    if (api != Opcodes.ASM7 && api != Opcodes.ASM6 && api != Opcodes.ASM5 && api != Opcodes.ASM4) {
+    if (api != Opcodes.ASM8
+        && api != Opcodes.ASM7
+        && api != Opcodes.ASM6
+        && api != Opcodes.ASM5
+        && api != Opcodes.ASM4
+        && api != Opcodes.ASM9_EXPERIMENTAL) {
       throw new IllegalArgumentException("Unsupported api " + api);
     }
+    if (api == Opcodes.ASM9_EXPERIMENTAL) {
+      Constants.checkAsmExperimental(this);
+    }
     this.api = api;
     this.av = annotationVisitor;
   }
diff --git a/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/AnnotationWriter.java b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/AnnotationWriter.java
index 79a13fc..69beb1b 100644
--- a/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/AnnotationWriter.java
+++ b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/AnnotationWriter.java
@@ -112,7 +112,7 @@
       final boolean useNamedValues,
       final ByteVector annotation,
       final AnnotationWriter previousAnnotation) {
-    super(Opcodes.ASM7);
+    super(/* latest api = */ Opcodes.ASM8);
     this.symbolTable = symbolTable;
     this.useNamedValues = useNamedValues;
     this.annotation = annotation;
diff --git a/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/ClassReader.java b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/ClassReader.java
index 84ec8c5..66181ae 100644
--- a/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/ClassReader.java
+++ b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/ClassReader.java
@@ -30,7 +30,6 @@
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.util.logging.Logger;
 
 /**
  * A parser to make a {@link ClassVisitor} visit a ClassFile structure, as defined in the Java
@@ -44,8 +43,6 @@
  */
 public class ClassReader {
 
-  private static final Logger LOGGER = Logger.getLogger(ClassReader.class.getName());
-
   /**
    * A flag to skip the Code attributes. If this flag is set the Code attributes are neither parsed
    * nor visited.
@@ -53,10 +50,11 @@
   public static final int SKIP_CODE = 1;
 
   /**
-   * A flag to skip the SourceFile, SourceDebugExtension, LocalVariableTable, LocalVariableTypeTable
-   * and LineNumberTable attributes. If this flag is set these attributes are neither parsed nor
-   * visited (i.e. {@link ClassVisitor#visitSource}, {@link MethodVisitor#visitLocalVariable} and
-   * {@link MethodVisitor#visitLineNumber} are not called).
+   * A flag to skip the SourceFile, SourceDebugExtension, LocalVariableTable,
+   * LocalVariableTypeTable, LineNumberTable and MethodParameters attributes. If this flag is set
+   * these attributes are neither parsed nor visited (i.e. {@link ClassVisitor#visitSource}, {@link
+   * MethodVisitor#visitLocalVariable}, {@link MethodVisitor#visitLineNumber} and {@link
+   * MethodVisitor#visitParameter} are not called).
    */
   public static final int SKIP_DEBUG = 2;
 
@@ -193,9 +191,6 @@
     this.b = classFileBuffer;
     // Check the class' major_version. This field is after the magic and minor_version fields, which
     // use 4 and 2 bytes respectively.
-    if (checkClassVersion && readShort(classFileOffset + 6) == Opcodes.V15) {
-      LOGGER.warning("Unsupported class file major version " + readShort(classFileOffset + 6));
-    }
     if (checkClassVersion && readShort(classFileOffset + 6) > Opcodes.V15) {
       throw new IllegalArgumentException(
           "Unsupported class file major version " + readShort(classFileOffset + 6));
@@ -472,6 +467,10 @@
     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 Record attribute, or 0.
+    int recordOffset = 0;
     // - The non standard attributes (linked with their {@link Attribute#nextAttribute} field).
     //   This list in the <i>reverse order</i> or their order in the ClassFile structure.
     Attribute attributes = null;
@@ -494,6 +493,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.SIGNATURE.equals(attributeName)) {
         signature = readUTF8(currentAttributeOffset, charBuffer);
       } else if (Constants.RUNTIME_VISIBLE_ANNOTATIONS.equals(attributeName)) {
@@ -511,6 +512,8 @@
         runtimeInvisibleAnnotationsOffset = currentAttributeOffset;
       } else if (Constants.RUNTIME_INVISIBLE_TYPE_ANNOTATIONS.equals(attributeName)) {
         runtimeInvisibleTypeAnnotationsOffset = currentAttributeOffset;
+      } else if (Constants.RECORD.equals(attributeName)) {
+        recordOffset = currentAttributeOffset;
       } else if (Constants.MODULE.equals(attributeName)) {
         moduleOffset = currentAttributeOffset;
       } else if (Constants.MODULE_MAIN_CLASS.equals(attributeName)) {
@@ -668,6 +671,17 @@
       }
     }
 
+    // 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 InnerClasses attribute.
     if (innerClassesOffset != 0) {
       int numberOfClasses = readUnsignedShort(innerClassesOffset);
@@ -682,6 +696,15 @@
       }
     }
 
+    // Visit Record components.
+    if (recordOffset != 0) {
+      int recordComponentsCount = readUnsignedShort(recordOffset);
+      recordOffset += 2;
+      while (recordComponentsCount-- > 0) {
+        recordOffset = readRecordComponent(classVisitor, context, recordOffset);
+      }
+    }
+
     // Visit the fields and methods.
     int fieldsCount = readUnsignedShort(currentOffset);
     currentOffset += 2;
@@ -830,6 +853,180 @@
   }
 
   /**
+   * Reads a record component and visit it.
+   *
+   * @param classVisitor the current class visitor
+   * @param context information about the class being parsed.
+   * @param recordComponentOffset the offset of the current record component.
+   * @return the offset of the first byte following the record component.
+   */
+  private int readRecordComponent(
+      final ClassVisitor classVisitor, final Context context, final int recordComponentOffset) {
+    char[] charBuffer = context.charBuffer;
+
+    int currentOffset = recordComponentOffset;
+    String name = readUTF8(currentOffset, charBuffer);
+    String descriptor = readUTF8(currentOffset + 2, charBuffer);
+    currentOffset += 4;
+
+    // Read the record component attributes (the variables are ordered as in Section 4.7 of the
+    // JVMS).
+
+    // Attribute offsets exclude the attribute_name_index and attribute_length fields.
+    // - The string corresponding to the Signature attribute, or null.
+    String signature = null;
+    // - The offset of the RuntimeVisibleAnnotations attribute, or 0.
+    int runtimeVisibleAnnotationsOffset = 0;
+    // - The offset of the RuntimeInvisibleAnnotations attribute, or 0.
+    int runtimeInvisibleAnnotationsOffset = 0;
+    // - The offset of the RuntimeVisibleTypeAnnotations attribute, or 0.
+    int runtimeVisibleTypeAnnotationsOffset = 0;
+    // - The offset of the RuntimeInvisibleTypeAnnotations attribute, or 0.
+    int runtimeInvisibleTypeAnnotationsOffset = 0;
+    // - The non standard attributes (linked with their {@link Attribute#nextAttribute} field).
+    //   This list in the <i>reverse order</i> or their order in the ClassFile structure.
+    Attribute attributes = null;
+
+    int attributesCount = readUnsignedShort(currentOffset);
+    currentOffset += 2;
+    while (attributesCount-- > 0) {
+      // Read the attribute_info's attribute_name and attribute_length fields.
+      String attributeName = readUTF8(currentOffset, charBuffer);
+      int attributeLength = readInt(currentOffset + 2);
+      currentOffset += 6;
+      // The tests are sorted in decreasing frequency order (based on frequencies observed on
+      // typical classes).
+      if (Constants.SIGNATURE.equals(attributeName)) {
+        signature = readUTF8(currentOffset, charBuffer);
+      } else if (Constants.RUNTIME_VISIBLE_ANNOTATIONS.equals(attributeName)) {
+        runtimeVisibleAnnotationsOffset = currentOffset;
+      } else if (Constants.RUNTIME_VISIBLE_TYPE_ANNOTATIONS.equals(attributeName)) {
+        runtimeVisibleTypeAnnotationsOffset = currentOffset;
+      } else if (Constants.RUNTIME_INVISIBLE_ANNOTATIONS.equals(attributeName)) {
+        runtimeInvisibleAnnotationsOffset = currentOffset;
+      } else if (Constants.RUNTIME_INVISIBLE_TYPE_ANNOTATIONS.equals(attributeName)) {
+        runtimeInvisibleTypeAnnotationsOffset = currentOffset;
+      } else {
+        Attribute attribute =
+            readAttribute(
+                context.attributePrototypes,
+                attributeName,
+                currentOffset,
+                attributeLength,
+                charBuffer,
+                -1,
+                null);
+        attribute.nextAttribute = attributes;
+        attributes = attribute;
+      }
+      currentOffset += attributeLength;
+    }
+
+    RecordComponentVisitor recordComponentVisitor =
+        classVisitor.visitRecordComponent(name, descriptor, signature);
+    if (recordComponentVisitor == null) {
+      return currentOffset;
+    }
+
+    // Visit the RuntimeVisibleAnnotations attribute.
+    if (runtimeVisibleAnnotationsOffset != 0) {
+      int numAnnotations = readUnsignedShort(runtimeVisibleAnnotationsOffset);
+      int currentAnnotationOffset = runtimeVisibleAnnotationsOffset + 2;
+      while (numAnnotations-- > 0) {
+        // Parse the type_index field.
+        String annotationDescriptor = readUTF8(currentAnnotationOffset, charBuffer);
+        currentAnnotationOffset += 2;
+        // Parse num_element_value_pairs and element_value_pairs and visit these values.
+        currentAnnotationOffset =
+            readElementValues(
+                recordComponentVisitor.visitAnnotation(annotationDescriptor, /* visible = */ true),
+                currentAnnotationOffset,
+                /* named = */ true,
+                charBuffer);
+      }
+    }
+
+    // Visit the RuntimeInvisibleAnnotations attribute.
+    if (runtimeInvisibleAnnotationsOffset != 0) {
+      int numAnnotations = readUnsignedShort(runtimeInvisibleAnnotationsOffset);
+      int currentAnnotationOffset = runtimeInvisibleAnnotationsOffset + 2;
+      while (numAnnotations-- > 0) {
+        // Parse the type_index field.
+        String annotationDescriptor = readUTF8(currentAnnotationOffset, charBuffer);
+        currentAnnotationOffset += 2;
+        // Parse num_element_value_pairs and element_value_pairs and visit these values.
+        currentAnnotationOffset =
+            readElementValues(
+                recordComponentVisitor.visitAnnotation(annotationDescriptor, /* visible = */ false),
+                currentAnnotationOffset,
+                /* named = */ true,
+                charBuffer);
+      }
+    }
+
+    // Visit the RuntimeVisibleTypeAnnotations attribute.
+    if (runtimeVisibleTypeAnnotationsOffset != 0) {
+      int numAnnotations = readUnsignedShort(runtimeVisibleTypeAnnotationsOffset);
+      int currentAnnotationOffset = runtimeVisibleTypeAnnotationsOffset + 2;
+      while (numAnnotations-- > 0) {
+        // Parse the target_type, target_info and target_path fields.
+        currentAnnotationOffset = readTypeAnnotationTarget(context, currentAnnotationOffset);
+        // Parse the type_index field.
+        String annotationDescriptor = readUTF8(currentAnnotationOffset, charBuffer);
+        currentAnnotationOffset += 2;
+        // Parse num_element_value_pairs and element_value_pairs and visit these values.
+        currentAnnotationOffset =
+            readElementValues(
+                recordComponentVisitor.visitTypeAnnotation(
+                    context.currentTypeAnnotationTarget,
+                    context.currentTypeAnnotationTargetPath,
+                    annotationDescriptor,
+                    /* visible = */ true),
+                currentAnnotationOffset,
+                /* named = */ true,
+                charBuffer);
+      }
+    }
+
+    // Visit the RuntimeInvisibleTypeAnnotations attribute.
+    if (runtimeInvisibleTypeAnnotationsOffset != 0) {
+      int numAnnotations = readUnsignedShort(runtimeInvisibleTypeAnnotationsOffset);
+      int currentAnnotationOffset = runtimeInvisibleTypeAnnotationsOffset + 2;
+      while (numAnnotations-- > 0) {
+        // Parse the target_type, target_info and target_path fields.
+        currentAnnotationOffset = readTypeAnnotationTarget(context, currentAnnotationOffset);
+        // Parse the type_index field.
+        String annotationDescriptor = readUTF8(currentAnnotationOffset, charBuffer);
+        currentAnnotationOffset += 2;
+        // Parse num_element_value_pairs and element_value_pairs and visit these values.
+        currentAnnotationOffset =
+            readElementValues(
+                recordComponentVisitor.visitTypeAnnotation(
+                    context.currentTypeAnnotationTarget,
+                    context.currentTypeAnnotationTargetPath,
+                    annotationDescriptor,
+                    /* visible = */ false),
+                currentAnnotationOffset,
+                /* named = */ true,
+                charBuffer);
+      }
+    }
+
+    // Visit the non standard attributes.
+    while (attributes != null) {
+      // Copy and reset the nextAttribute field so that it can also be used in FieldWriter.
+      Attribute nextAttribute = attributes.nextAttribute;
+      attributes.nextAttribute = null;
+      recordComponentVisitor.visitAttribute(attributes);
+      attributes = nextAttribute;
+    }
+
+    // Visit the end of the field.
+    recordComponentVisitor.visitEnd();
+    return currentOffset;
+  }
+
+  /**
    * Reads a JVMS field_info structure and makes the given visitor visit it.
    *
    * @param classVisitor the visitor that must visit the field.
@@ -1155,7 +1352,7 @@
     }
 
     // Visit the MethodParameters attribute.
-    if (methodParametersOffset != 0) {
+    if (methodParametersOffset != 0 && (context.parsingOptions & SKIP_DEBUG) == 0) {
       int parametersCount = readByte(methodParametersOffset);
       int currentParameterOffset = methodParametersOffset + 1;
       while (parametersCount-- > 0) {
@@ -1327,113 +1524,113 @@
       final int bytecodeOffset = currentOffset - bytecodeStartOffset;
       final int opcode = classBuffer[currentOffset] & 0xFF;
       switch (opcode) {
-        case Constants.NOP:
-        case Constants.ACONST_NULL:
-        case Constants.ICONST_M1:
-        case Constants.ICONST_0:
-        case Constants.ICONST_1:
-        case Constants.ICONST_2:
-        case Constants.ICONST_3:
-        case Constants.ICONST_4:
-        case Constants.ICONST_5:
-        case Constants.LCONST_0:
-        case Constants.LCONST_1:
-        case Constants.FCONST_0:
-        case Constants.FCONST_1:
-        case Constants.FCONST_2:
-        case Constants.DCONST_0:
-        case Constants.DCONST_1:
-        case Constants.IALOAD:
-        case Constants.LALOAD:
-        case Constants.FALOAD:
-        case Constants.DALOAD:
-        case Constants.AALOAD:
-        case Constants.BALOAD:
-        case Constants.CALOAD:
-        case Constants.SALOAD:
-        case Constants.IASTORE:
-        case Constants.LASTORE:
-        case Constants.FASTORE:
-        case Constants.DASTORE:
-        case Constants.AASTORE:
-        case Constants.BASTORE:
-        case Constants.CASTORE:
-        case Constants.SASTORE:
-        case Constants.POP:
-        case Constants.POP2:
-        case Constants.DUP:
-        case Constants.DUP_X1:
-        case Constants.DUP_X2:
-        case Constants.DUP2:
-        case Constants.DUP2_X1:
-        case Constants.DUP2_X2:
-        case Constants.SWAP:
-        case Constants.IADD:
-        case Constants.LADD:
-        case Constants.FADD:
-        case Constants.DADD:
-        case Constants.ISUB:
-        case Constants.LSUB:
-        case Constants.FSUB:
-        case Constants.DSUB:
-        case Constants.IMUL:
-        case Constants.LMUL:
-        case Constants.FMUL:
-        case Constants.DMUL:
-        case Constants.IDIV:
-        case Constants.LDIV:
-        case Constants.FDIV:
-        case Constants.DDIV:
-        case Constants.IREM:
-        case Constants.LREM:
-        case Constants.FREM:
-        case Constants.DREM:
-        case Constants.INEG:
-        case Constants.LNEG:
-        case Constants.FNEG:
-        case Constants.DNEG:
-        case Constants.ISHL:
-        case Constants.LSHL:
-        case Constants.ISHR:
-        case Constants.LSHR:
-        case Constants.IUSHR:
-        case Constants.LUSHR:
-        case Constants.IAND:
-        case Constants.LAND:
-        case Constants.IOR:
-        case Constants.LOR:
-        case Constants.IXOR:
-        case Constants.LXOR:
-        case Constants.I2L:
-        case Constants.I2F:
-        case Constants.I2D:
-        case Constants.L2I:
-        case Constants.L2F:
-        case Constants.L2D:
-        case Constants.F2I:
-        case Constants.F2L:
-        case Constants.F2D:
-        case Constants.D2I:
-        case Constants.D2L:
-        case Constants.D2F:
-        case Constants.I2B:
-        case Constants.I2C:
-        case Constants.I2S:
-        case Constants.LCMP:
-        case Constants.FCMPL:
-        case Constants.FCMPG:
-        case Constants.DCMPL:
-        case Constants.DCMPG:
-        case Constants.IRETURN:
-        case Constants.LRETURN:
-        case Constants.FRETURN:
-        case Constants.DRETURN:
-        case Constants.ARETURN:
-        case Constants.RETURN:
-        case Constants.ARRAYLENGTH:
-        case Constants.ATHROW:
-        case Constants.MONITORENTER:
-        case Constants.MONITOREXIT:
+        case Opcodes.NOP:
+        case Opcodes.ACONST_NULL:
+        case Opcodes.ICONST_M1:
+        case Opcodes.ICONST_0:
+        case Opcodes.ICONST_1:
+        case Opcodes.ICONST_2:
+        case Opcodes.ICONST_3:
+        case Opcodes.ICONST_4:
+        case Opcodes.ICONST_5:
+        case Opcodes.LCONST_0:
+        case Opcodes.LCONST_1:
+        case Opcodes.FCONST_0:
+        case Opcodes.FCONST_1:
+        case Opcodes.FCONST_2:
+        case Opcodes.DCONST_0:
+        case Opcodes.DCONST_1:
+        case Opcodes.IALOAD:
+        case Opcodes.LALOAD:
+        case Opcodes.FALOAD:
+        case Opcodes.DALOAD:
+        case Opcodes.AALOAD:
+        case Opcodes.BALOAD:
+        case Opcodes.CALOAD:
+        case Opcodes.SALOAD:
+        case Opcodes.IASTORE:
+        case Opcodes.LASTORE:
+        case Opcodes.FASTORE:
+        case Opcodes.DASTORE:
+        case Opcodes.AASTORE:
+        case Opcodes.BASTORE:
+        case Opcodes.CASTORE:
+        case Opcodes.SASTORE:
+        case Opcodes.POP:
+        case Opcodes.POP2:
+        case Opcodes.DUP:
+        case Opcodes.DUP_X1:
+        case Opcodes.DUP_X2:
+        case Opcodes.DUP2:
+        case Opcodes.DUP2_X1:
+        case Opcodes.DUP2_X2:
+        case Opcodes.SWAP:
+        case Opcodes.IADD:
+        case Opcodes.LADD:
+        case Opcodes.FADD:
+        case Opcodes.DADD:
+        case Opcodes.ISUB:
+        case Opcodes.LSUB:
+        case Opcodes.FSUB:
+        case Opcodes.DSUB:
+        case Opcodes.IMUL:
+        case Opcodes.LMUL:
+        case Opcodes.FMUL:
+        case Opcodes.DMUL:
+        case Opcodes.IDIV:
+        case Opcodes.LDIV:
+        case Opcodes.FDIV:
+        case Opcodes.DDIV:
+        case Opcodes.IREM:
+        case Opcodes.LREM:
+        case Opcodes.FREM:
+        case Opcodes.DREM:
+        case Opcodes.INEG:
+        case Opcodes.LNEG:
+        case Opcodes.FNEG:
+        case Opcodes.DNEG:
+        case Opcodes.ISHL:
+        case Opcodes.LSHL:
+        case Opcodes.ISHR:
+        case Opcodes.LSHR:
+        case Opcodes.IUSHR:
+        case Opcodes.LUSHR:
+        case Opcodes.IAND:
+        case Opcodes.LAND:
+        case Opcodes.IOR:
+        case Opcodes.LOR:
+        case Opcodes.IXOR:
+        case Opcodes.LXOR:
+        case Opcodes.I2L:
+        case Opcodes.I2F:
+        case Opcodes.I2D:
+        case Opcodes.L2I:
+        case Opcodes.L2F:
+        case Opcodes.L2D:
+        case Opcodes.F2I:
+        case Opcodes.F2L:
+        case Opcodes.F2D:
+        case Opcodes.D2I:
+        case Opcodes.D2L:
+        case Opcodes.D2F:
+        case Opcodes.I2B:
+        case Opcodes.I2C:
+        case Opcodes.I2S:
+        case Opcodes.LCMP:
+        case Opcodes.FCMPL:
+        case Opcodes.FCMPG:
+        case Opcodes.DCMPL:
+        case Opcodes.DCMPG:
+        case Opcodes.IRETURN:
+        case Opcodes.LRETURN:
+        case Opcodes.FRETURN:
+        case Opcodes.DRETURN:
+        case Opcodes.ARETURN:
+        case Opcodes.RETURN:
+        case Opcodes.ARRAYLENGTH:
+        case Opcodes.ATHROW:
+        case Opcodes.MONITORENTER:
+        case Opcodes.MONITOREXIT:
         case Constants.ILOAD_0:
         case Constants.ILOAD_1:
         case Constants.ILOAD_2:
@@ -1476,24 +1673,24 @@
         case Constants.ASTORE_3:
           currentOffset += 1;
           break;
-        case Constants.IFEQ:
-        case Constants.IFNE:
-        case Constants.IFLT:
-        case Constants.IFGE:
-        case Constants.IFGT:
-        case Constants.IFLE:
-        case Constants.IF_ICMPEQ:
-        case Constants.IF_ICMPNE:
-        case Constants.IF_ICMPLT:
-        case Constants.IF_ICMPGE:
-        case Constants.IF_ICMPGT:
-        case Constants.IF_ICMPLE:
-        case Constants.IF_ACMPEQ:
-        case Constants.IF_ACMPNE:
-        case Constants.GOTO:
-        case Constants.JSR:
-        case Constants.IFNULL:
-        case Constants.IFNONNULL:
+        case Opcodes.IFEQ:
+        case Opcodes.IFNE:
+        case Opcodes.IFLT:
+        case Opcodes.IFGE:
+        case Opcodes.IFGT:
+        case Opcodes.IFLE:
+        case Opcodes.IF_ICMPEQ:
+        case Opcodes.IF_ICMPNE:
+        case Opcodes.IF_ICMPLT:
+        case Opcodes.IF_ICMPGE:
+        case Opcodes.IF_ICMPGT:
+        case Opcodes.IF_ICMPLE:
+        case Opcodes.IF_ACMPEQ:
+        case Opcodes.IF_ACMPNE:
+        case Opcodes.GOTO:
+        case Opcodes.JSR:
+        case Opcodes.IFNULL:
+        case Opcodes.IFNONNULL:
           createLabel(bytecodeOffset + readShort(currentOffset + 1), labels);
           currentOffset += 3;
           break;
@@ -1526,27 +1723,27 @@
           break;
         case Constants.WIDE:
           switch (classBuffer[currentOffset + 1] & 0xFF) {
-            case Constants.ILOAD:
-            case Constants.FLOAD:
-            case Constants.ALOAD:
-            case Constants.LLOAD:
-            case Constants.DLOAD:
-            case Constants.ISTORE:
-            case Constants.FSTORE:
-            case Constants.ASTORE:
-            case Constants.LSTORE:
-            case Constants.DSTORE:
-            case Constants.RET:
+            case Opcodes.ILOAD:
+            case Opcodes.FLOAD:
+            case Opcodes.ALOAD:
+            case Opcodes.LLOAD:
+            case Opcodes.DLOAD:
+            case Opcodes.ISTORE:
+            case Opcodes.FSTORE:
+            case Opcodes.ASTORE:
+            case Opcodes.LSTORE:
+            case Opcodes.DSTORE:
+            case Opcodes.RET:
               currentOffset += 4;
               break;
-            case Constants.IINC:
+            case Opcodes.IINC:
               currentOffset += 6;
               break;
             default:
               throw new IllegalArgumentException();
           }
           break;
-        case Constants.TABLESWITCH:
+        case Opcodes.TABLESWITCH:
           // Skip 0 to 3 padding bytes.
           currentOffset += 4 - (bytecodeOffset & 3);
           // Read the default label and the number of table entries.
@@ -1559,7 +1756,7 @@
             currentOffset += 4;
           }
           break;
-        case Constants.LOOKUPSWITCH:
+        case Opcodes.LOOKUPSWITCH:
           // Skip 0 to 3 padding bytes.
           currentOffset += 4 - (bytecodeOffset & 3);
           // Read the default label and the number of switch cases.
@@ -1572,44 +1769,44 @@
             currentOffset += 8;
           }
           break;
-        case Constants.ILOAD:
-        case Constants.LLOAD:
-        case Constants.FLOAD:
-        case Constants.DLOAD:
-        case Constants.ALOAD:
-        case Constants.ISTORE:
-        case Constants.LSTORE:
-        case Constants.FSTORE:
-        case Constants.DSTORE:
-        case Constants.ASTORE:
-        case Constants.RET:
-        case Constants.BIPUSH:
-        case Constants.NEWARRAY:
-        case Constants.LDC:
+        case Opcodes.ILOAD:
+        case Opcodes.LLOAD:
+        case Opcodes.FLOAD:
+        case Opcodes.DLOAD:
+        case Opcodes.ALOAD:
+        case Opcodes.ISTORE:
+        case Opcodes.LSTORE:
+        case Opcodes.FSTORE:
+        case Opcodes.DSTORE:
+        case Opcodes.ASTORE:
+        case Opcodes.RET:
+        case Opcodes.BIPUSH:
+        case Opcodes.NEWARRAY:
+        case Opcodes.LDC:
           currentOffset += 2;
           break;
-        case Constants.SIPUSH:
+        case Opcodes.SIPUSH:
         case Constants.LDC_W:
         case Constants.LDC2_W:
-        case Constants.GETSTATIC:
-        case Constants.PUTSTATIC:
-        case Constants.GETFIELD:
-        case Constants.PUTFIELD:
-        case Constants.INVOKEVIRTUAL:
-        case Constants.INVOKESPECIAL:
-        case Constants.INVOKESTATIC:
-        case Constants.NEW:
-        case Constants.ANEWARRAY:
-        case Constants.CHECKCAST:
-        case Constants.INSTANCEOF:
-        case Constants.IINC:
+        case Opcodes.GETSTATIC:
+        case Opcodes.PUTSTATIC:
+        case Opcodes.GETFIELD:
+        case Opcodes.PUTFIELD:
+        case Opcodes.INVOKEVIRTUAL:
+        case Opcodes.INVOKESPECIAL:
+        case Opcodes.INVOKESTATIC:
+        case Opcodes.NEW:
+        case Opcodes.ANEWARRAY:
+        case Opcodes.CHECKCAST:
+        case Opcodes.INSTANCEOF:
+        case Opcodes.IINC:
           currentOffset += 3;
           break;
-        case Constants.INVOKEINTERFACE:
-        case Constants.INVOKEDYNAMIC:
+        case Opcodes.INVOKEINTERFACE:
+        case Opcodes.INVOKEDYNAMIC:
           currentOffset += 5;
           break;
-        case Constants.MULTIANEWARRAY:
+        case Opcodes.MULTIANEWARRAY:
           currentOffset += 4;
           break;
         default:
@@ -1876,113 +2073,113 @@
       // Visit the instruction at this bytecode offset.
       int opcode = classBuffer[currentOffset] & 0xFF;
       switch (opcode) {
-        case Constants.NOP:
-        case Constants.ACONST_NULL:
-        case Constants.ICONST_M1:
-        case Constants.ICONST_0:
-        case Constants.ICONST_1:
-        case Constants.ICONST_2:
-        case Constants.ICONST_3:
-        case Constants.ICONST_4:
-        case Constants.ICONST_5:
-        case Constants.LCONST_0:
-        case Constants.LCONST_1:
-        case Constants.FCONST_0:
-        case Constants.FCONST_1:
-        case Constants.FCONST_2:
-        case Constants.DCONST_0:
-        case Constants.DCONST_1:
-        case Constants.IALOAD:
-        case Constants.LALOAD:
-        case Constants.FALOAD:
-        case Constants.DALOAD:
-        case Constants.AALOAD:
-        case Constants.BALOAD:
-        case Constants.CALOAD:
-        case Constants.SALOAD:
-        case Constants.IASTORE:
-        case Constants.LASTORE:
-        case Constants.FASTORE:
-        case Constants.DASTORE:
-        case Constants.AASTORE:
-        case Constants.BASTORE:
-        case Constants.CASTORE:
-        case Constants.SASTORE:
-        case Constants.POP:
-        case Constants.POP2:
-        case Constants.DUP:
-        case Constants.DUP_X1:
-        case Constants.DUP_X2:
-        case Constants.DUP2:
-        case Constants.DUP2_X1:
-        case Constants.DUP2_X2:
-        case Constants.SWAP:
-        case Constants.IADD:
-        case Constants.LADD:
-        case Constants.FADD:
-        case Constants.DADD:
-        case Constants.ISUB:
-        case Constants.LSUB:
-        case Constants.FSUB:
-        case Constants.DSUB:
-        case Constants.IMUL:
-        case Constants.LMUL:
-        case Constants.FMUL:
-        case Constants.DMUL:
-        case Constants.IDIV:
-        case Constants.LDIV:
-        case Constants.FDIV:
-        case Constants.DDIV:
-        case Constants.IREM:
-        case Constants.LREM:
-        case Constants.FREM:
-        case Constants.DREM:
-        case Constants.INEG:
-        case Constants.LNEG:
-        case Constants.FNEG:
-        case Constants.DNEG:
-        case Constants.ISHL:
-        case Constants.LSHL:
-        case Constants.ISHR:
-        case Constants.LSHR:
-        case Constants.IUSHR:
-        case Constants.LUSHR:
-        case Constants.IAND:
-        case Constants.LAND:
-        case Constants.IOR:
-        case Constants.LOR:
-        case Constants.IXOR:
-        case Constants.LXOR:
-        case Constants.I2L:
-        case Constants.I2F:
-        case Constants.I2D:
-        case Constants.L2I:
-        case Constants.L2F:
-        case Constants.L2D:
-        case Constants.F2I:
-        case Constants.F2L:
-        case Constants.F2D:
-        case Constants.D2I:
-        case Constants.D2L:
-        case Constants.D2F:
-        case Constants.I2B:
-        case Constants.I2C:
-        case Constants.I2S:
-        case Constants.LCMP:
-        case Constants.FCMPL:
-        case Constants.FCMPG:
-        case Constants.DCMPL:
-        case Constants.DCMPG:
-        case Constants.IRETURN:
-        case Constants.LRETURN:
-        case Constants.FRETURN:
-        case Constants.DRETURN:
-        case Constants.ARETURN:
-        case Constants.RETURN:
-        case Constants.ARRAYLENGTH:
-        case Constants.ATHROW:
-        case Constants.MONITORENTER:
-        case Constants.MONITOREXIT:
+        case Opcodes.NOP:
+        case Opcodes.ACONST_NULL:
+        case Opcodes.ICONST_M1:
+        case Opcodes.ICONST_0:
+        case Opcodes.ICONST_1:
+        case Opcodes.ICONST_2:
+        case Opcodes.ICONST_3:
+        case Opcodes.ICONST_4:
+        case Opcodes.ICONST_5:
+        case Opcodes.LCONST_0:
+        case Opcodes.LCONST_1:
+        case Opcodes.FCONST_0:
+        case Opcodes.FCONST_1:
+        case Opcodes.FCONST_2:
+        case Opcodes.DCONST_0:
+        case Opcodes.DCONST_1:
+        case Opcodes.IALOAD:
+        case Opcodes.LALOAD:
+        case Opcodes.FALOAD:
+        case Opcodes.DALOAD:
+        case Opcodes.AALOAD:
+        case Opcodes.BALOAD:
+        case Opcodes.CALOAD:
+        case Opcodes.SALOAD:
+        case Opcodes.IASTORE:
+        case Opcodes.LASTORE:
+        case Opcodes.FASTORE:
+        case Opcodes.DASTORE:
+        case Opcodes.AASTORE:
+        case Opcodes.BASTORE:
+        case Opcodes.CASTORE:
+        case Opcodes.SASTORE:
+        case Opcodes.POP:
+        case Opcodes.POP2:
+        case Opcodes.DUP:
+        case Opcodes.DUP_X1:
+        case Opcodes.DUP_X2:
+        case Opcodes.DUP2:
+        case Opcodes.DUP2_X1:
+        case Opcodes.DUP2_X2:
+        case Opcodes.SWAP:
+        case Opcodes.IADD:
+        case Opcodes.LADD:
+        case Opcodes.FADD:
+        case Opcodes.DADD:
+        case Opcodes.ISUB:
+        case Opcodes.LSUB:
+        case Opcodes.FSUB:
+        case Opcodes.DSUB:
+        case Opcodes.IMUL:
+        case Opcodes.LMUL:
+        case Opcodes.FMUL:
+        case Opcodes.DMUL:
+        case Opcodes.IDIV:
+        case Opcodes.LDIV:
+        case Opcodes.FDIV:
+        case Opcodes.DDIV:
+        case Opcodes.IREM:
+        case Opcodes.LREM:
+        case Opcodes.FREM:
+        case Opcodes.DREM:
+        case Opcodes.INEG:
+        case Opcodes.LNEG:
+        case Opcodes.FNEG:
+        case Opcodes.DNEG:
+        case Opcodes.ISHL:
+        case Opcodes.LSHL:
+        case Opcodes.ISHR:
+        case Opcodes.LSHR:
+        case Opcodes.IUSHR:
+        case Opcodes.LUSHR:
+        case Opcodes.IAND:
+        case Opcodes.LAND:
+        case Opcodes.IOR:
+        case Opcodes.LOR:
+        case Opcodes.IXOR:
+        case Opcodes.LXOR:
+        case Opcodes.I2L:
+        case Opcodes.I2F:
+        case Opcodes.I2D:
+        case Opcodes.L2I:
+        case Opcodes.L2F:
+        case Opcodes.L2D:
+        case Opcodes.F2I:
+        case Opcodes.F2L:
+        case Opcodes.F2D:
+        case Opcodes.D2I:
+        case Opcodes.D2L:
+        case Opcodes.D2F:
+        case Opcodes.I2B:
+        case Opcodes.I2C:
+        case Opcodes.I2S:
+        case Opcodes.LCMP:
+        case Opcodes.FCMPL:
+        case Opcodes.FCMPG:
+        case Opcodes.DCMPL:
+        case Opcodes.DCMPG:
+        case Opcodes.IRETURN:
+        case Opcodes.LRETURN:
+        case Opcodes.FRETURN:
+        case Opcodes.DRETURN:
+        case Opcodes.ARETURN:
+        case Opcodes.RETURN:
+        case Opcodes.ARRAYLENGTH:
+        case Opcodes.ATHROW:
+        case Opcodes.MONITORENTER:
+        case Opcodes.MONITOREXIT:
           methodVisitor.visitInsn(opcode);
           currentOffset += 1;
           break;
@@ -2034,24 +2231,24 @@
           methodVisitor.visitVarInsn(Opcodes.ISTORE + (opcode >> 2), opcode & 0x3);
           currentOffset += 1;
           break;
-        case Constants.IFEQ:
-        case Constants.IFNE:
-        case Constants.IFLT:
-        case Constants.IFGE:
-        case Constants.IFGT:
-        case Constants.IFLE:
-        case Constants.IF_ICMPEQ:
-        case Constants.IF_ICMPNE:
-        case Constants.IF_ICMPLT:
-        case Constants.IF_ICMPGE:
-        case Constants.IF_ICMPGT:
-        case Constants.IF_ICMPLE:
-        case Constants.IF_ACMPEQ:
-        case Constants.IF_ACMPNE:
-        case Constants.GOTO:
-        case Constants.JSR:
-        case Constants.IFNULL:
-        case Constants.IFNONNULL:
+        case Opcodes.IFEQ:
+        case Opcodes.IFNE:
+        case Opcodes.IFLT:
+        case Opcodes.IFGE:
+        case Opcodes.IFGT:
+        case Opcodes.IFLE:
+        case Opcodes.IF_ICMPEQ:
+        case Opcodes.IF_ICMPNE:
+        case Opcodes.IF_ICMPLT:
+        case Opcodes.IF_ICMPGE:
+        case Opcodes.IF_ICMPGT:
+        case Opcodes.IF_ICMPLE:
+        case Opcodes.IF_ACMPEQ:
+        case Opcodes.IF_ACMPNE:
+        case Opcodes.GOTO:
+        case Opcodes.JSR:
+        case Opcodes.IFNULL:
+        case Opcodes.IFNONNULL:
           methodVisitor.visitJumpInsn(
               opcode, labels[currentBytecodeOffset + readShort(currentOffset + 1)]);
           currentOffset += 3;
@@ -2132,7 +2329,7 @@
             currentOffset += 4;
           }
           break;
-        case Constants.TABLESWITCH:
+        case Opcodes.TABLESWITCH:
           {
             // Skip 0 to 3 padding bytes.
             currentOffset += 4 - (currentBytecodeOffset & 3);
@@ -2149,7 +2346,7 @@
             methodVisitor.visitTableSwitchInsn(low, high, defaultLabel, table);
             break;
           }
-        case Constants.LOOKUPSWITCH:
+        case Opcodes.LOOKUPSWITCH:
           {
             // Skip 0 to 3 padding bytes.
             currentOffset += 4 - (currentBytecodeOffset & 3);
@@ -2167,30 +2364,30 @@
             methodVisitor.visitLookupSwitchInsn(defaultLabel, keys, values);
             break;
           }
-        case Constants.ILOAD:
-        case Constants.LLOAD:
-        case Constants.FLOAD:
-        case Constants.DLOAD:
-        case Constants.ALOAD:
-        case Constants.ISTORE:
-        case Constants.LSTORE:
-        case Constants.FSTORE:
-        case Constants.DSTORE:
-        case Constants.ASTORE:
-        case Constants.RET:
+        case Opcodes.ILOAD:
+        case Opcodes.LLOAD:
+        case Opcodes.FLOAD:
+        case Opcodes.DLOAD:
+        case Opcodes.ALOAD:
+        case Opcodes.ISTORE:
+        case Opcodes.LSTORE:
+        case Opcodes.FSTORE:
+        case Opcodes.DSTORE:
+        case Opcodes.ASTORE:
+        case Opcodes.RET:
           methodVisitor.visitVarInsn(opcode, classBuffer[currentOffset + 1] & 0xFF);
           currentOffset += 2;
           break;
-        case Constants.BIPUSH:
-        case Constants.NEWARRAY:
+        case Opcodes.BIPUSH:
+        case Opcodes.NEWARRAY:
           methodVisitor.visitIntInsn(opcode, classBuffer[currentOffset + 1]);
           currentOffset += 2;
           break;
-        case Constants.SIPUSH:
+        case Opcodes.SIPUSH:
           methodVisitor.visitIntInsn(opcode, readShort(currentOffset + 1));
           currentOffset += 3;
           break;
-        case Constants.LDC:
+        case Opcodes.LDC:
           methodVisitor.visitLdcInsn(readConst(classBuffer[currentOffset + 1] & 0xFF, charBuffer));
           currentOffset += 2;
           break;
@@ -2199,14 +2396,14 @@
           methodVisitor.visitLdcInsn(readConst(readUnsignedShort(currentOffset + 1), charBuffer));
           currentOffset += 3;
           break;
-        case Constants.GETSTATIC:
-        case Constants.PUTSTATIC:
-        case Constants.GETFIELD:
-        case Constants.PUTFIELD:
-        case Constants.INVOKEVIRTUAL:
-        case Constants.INVOKESPECIAL:
-        case Constants.INVOKESTATIC:
-        case Constants.INVOKEINTERFACE:
+        case Opcodes.GETSTATIC:
+        case Opcodes.PUTSTATIC:
+        case Opcodes.GETFIELD:
+        case Opcodes.PUTFIELD:
+        case Opcodes.INVOKEVIRTUAL:
+        case Opcodes.INVOKESPECIAL:
+        case Opcodes.INVOKESTATIC:
+        case Opcodes.INVOKEINTERFACE:
           {
             int cpInfoOffset = cpInfoOffsets[readUnsignedShort(currentOffset + 1)];
             int nameAndTypeCpInfoOffset = cpInfoOffsets[readUnsignedShort(cpInfoOffset + 2)];
@@ -2227,7 +2424,7 @@
             }
             break;
           }
-        case Constants.INVOKEDYNAMIC:
+        case Opcodes.INVOKEDYNAMIC:
           {
             int cpInfoOffset = cpInfoOffsets[readUnsignedShort(currentOffset + 1)];
             int nameAndTypeCpInfoOffset = cpInfoOffsets[readUnsignedShort(cpInfoOffset + 2)];
@@ -2249,19 +2446,19 @@
             currentOffset += 5;
             break;
           }
-        case Constants.NEW:
-        case Constants.ANEWARRAY:
-        case Constants.CHECKCAST:
-        case Constants.INSTANCEOF:
+        case Opcodes.NEW:
+        case Opcodes.ANEWARRAY:
+        case Opcodes.CHECKCAST:
+        case Opcodes.INSTANCEOF:
           methodVisitor.visitTypeInsn(opcode, readClass(currentOffset + 1, charBuffer));
           currentOffset += 3;
           break;
-        case Constants.IINC:
+        case Opcodes.IINC:
           methodVisitor.visitIincInsn(
               classBuffer[currentOffset + 1] & 0xFF, classBuffer[currentOffset + 2]);
           currentOffset += 3;
           break;
-        case Constants.MULTIANEWARRAY:
+        case Opcodes.MULTIANEWARRAY:
           methodVisitor.visitMultiANewArrayInsn(
               readClass(currentOffset + 1, charBuffer), classBuffer[currentOffset + 3] & 0xFF);
           currentOffset += 4;
diff --git a/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/ClassVisitor.java b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/ClassVisitor.java
index 7f97d47..3c384de 100644
--- a/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/ClassVisitor.java
+++ b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/ClassVisitor.java
@@ -30,9 +30,9 @@
 /**
  * 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
- * visitOuterClass} ] ( {@code visitAnnotation} | {@code visitTypeAnnotation} | {@code
- * visitAttribute} )* ( {@code visitNestMember} | {@code visitInnerClass} | {@code visitField} |
- * {@code visitMethod} )* {@code visitEnd}.
+ * visitPermittedSubtype} ][ {@code visitOuterClass} ] ( {@code visitAnnotation} | {@code
+ * visitTypeAnnotation} | {@code visitAttribute} )* ( {@code visitNestMember} | {@code
+ * visitInnerClass} | {@code visitField} | {@code visitMethod} )* {@code visitEnd}.
  *
  * @author Eric Bruneton
  */
@@ -61,14 +61,23 @@
    * Constructs a new {@link ClassVisitor}.
    *
    * @param api the ASM API version implemented by this visitor. Must be one of {@link
-   *     Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+   *     Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7} or {@link
+   *     Opcodes#ASM8}.
    * @param classVisitor the class visitor to which this visitor must delegate method calls. May be
    *     null.
    */
   public ClassVisitor(final int api, final ClassVisitor classVisitor) {
-    if (api != Opcodes.ASM7 && api != Opcodes.ASM6 && api != Opcodes.ASM5 && api != Opcodes.ASM4) {
+    if (api != Opcodes.ASM8
+        && api != Opcodes.ASM7
+        && api != Opcodes.ASM6
+        && api != Opcodes.ASM5
+        && api != Opcodes.ASM4
+        && api != Opcodes.ASM9_EXPERIMENTAL) {
       throw new IllegalArgumentException("Unsupported api " + api);
     }
+    if (api == Opcodes.ASM9_EXPERIMENTAL) {
+      Constants.checkAsmExperimental(this);
+    }
     this.api = api;
     this.cv = classVisitor;
   }
@@ -241,6 +250,24 @@
   }
 
   /**
+   * <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.
+   *
+   * @param permittedSubtype the internal name of a permitted subtype.
+   * @deprecated this API is experimental.
+   */
+  @Deprecated
+  public void visitPermittedSubtypeExperimental(final String permittedSubtype) {
+    if (api != Opcodes.ASM9_EXPERIMENTAL) {
+      throw new UnsupportedOperationException("This feature requires ASM9_EXPERIMENTAL");
+    }
+    if (cv != null) {
+      cv.visitPermittedSubtypeExperimental(permittedSubtype);
+    }
+  }
+
+  /**
    * Visits information about an inner class. This inner class is not necessarily a member of the
    * class being visited.
    *
@@ -260,6 +287,27 @@
   }
 
   /**
+   * Visits a record component of the class.
+   *
+   * @param name the record component name.
+   * @param descriptor the record component descriptor (see {@link Type}).
+   * @param signature the record component signature. May be {@literal null} if the record component
+   *     type does not use generic types.
+   * @return a visitor to visit this record component annotations and attributes, or {@literal null}
+   *     if this class visitor is not interested in visiting these annotations and attributes.
+   */
+  public RecordComponentVisitor visitRecordComponent(
+      final String name, final String descriptor, final String signature) {
+    if (api < Opcodes.ASM8) {
+      throw new UnsupportedOperationException("This feature requires ASM8");
+    }
+    if (cv != null) {
+      return cv.visitRecordComponent(name, descriptor, signature);
+    }
+    return null;
+  }
+
+  /**
    * Visits a field of the class.
    *
    * @param access the field's access flags (see {@link Opcodes}). This parameter also indicates if
diff --git a/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/ClassWriter.java b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/ClassWriter.java
index 5bdf68c..3e6f763 100644
--- a/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/ClassWriter.java
+++ b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/ClassWriter.java
@@ -177,6 +177,26 @@
   /** 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 'classes' array of the PermittedSubtypes attribute, or {@literal null}. */
+  private ByteVector permittedSubtypeClasses;
+
+  /**
+   * The record components of this class, stored in a linked list of {@link RecordComponentWriter}
+   * linked via their {@link RecordComponentWriter#delegate} field. This field stores the first
+   * element of this list.
+   */
+  private RecordComponentWriter firstRecordComponent;
+
+  /**
+   * The record components of this class, stored in a linked list of {@link RecordComponentWriter}
+   * linked via their {@link RecordComponentWriter#delegate} field. This field stores the last
+   * element of this list.
+   */
+  private RecordComponentWriter lastRecordComponent;
+
   /**
    * The first non standard attribute of this class. The next ones can be accessed with the {@link
    * Attribute#nextAttribute} field. May be {@literal null}.
@@ -234,7 +254,7 @@
    *     maximum stack size nor the stack frames will be computed for these methods</i>.
    */
   public ClassWriter(final ClassReader classReader, final int flags) {
-    super(Opcodes.ASM7);
+    super(/* latest api = */ Opcodes.ASM8);
     symbolTable = classReader == null ? new SymbolTable(this) : new SymbolTable(this, classReader);
     if ((flags & COMPUTE_FRAMES) != 0) {
       this.compute = MethodWriter.COMPUTE_ALL_FRAMES;
@@ -352,6 +372,22 @@
     nestMemberClasses.putShort(symbolTable.addConstantClass(nestMember).index);
   }
 
+  /**
+   * <b>Experimental, use at your own risk.</b>
+   *
+   * @param permittedSubtype the internal name of a permitted subtype.
+   * @deprecated this API is experimental.
+   */
+  @Override
+  @Deprecated
+  public final void visitPermittedSubtypeExperimental(final String permittedSubtype) {
+    if (permittedSubtypeClasses == null) {
+      permittedSubtypeClasses = new ByteVector();
+    }
+    ++numberOfPermittedSubtypeClasses;
+    permittedSubtypeClasses.putShort(symbolTable.addConstantClass(permittedSubtype).index);
+  }
+
   @Override
   public final void visitInnerClass(
       final String name, final String outerName, final String innerName, final int access) {
@@ -378,6 +414,19 @@
   }
 
   @Override
+  public final RecordComponentVisitor visitRecordComponent(
+      final String name, final String descriptor, final String signature) {
+    RecordComponentWriter recordComponentWriter =
+        new RecordComponentWriter(symbolTable, name, descriptor, signature);
+    if (firstRecordComponent == null) {
+      firstRecordComponent = recordComponentWriter;
+    } else {
+      lastRecordComponent.delegate = recordComponentWriter;
+    }
+    return lastRecordComponent = recordComponentWriter;
+  }
+
+  @Override
   public final FieldVisitor visitField(
       final int access,
       final String name,
@@ -447,6 +496,7 @@
       size += methodWriter.computeMethodInfoSize();
       methodWriter = (MethodWriter) methodWriter.mv;
     }
+
     // For ease of reference, we use here the same attribute order as in Section 4.7 of the JVMS.
     int attributesCount = 0;
     if (innerClasses != null) {
@@ -526,6 +576,24 @@
       size += 8 + nestMemberClasses.length;
       symbolTable.addConstantUtf8(Constants.NEST_MEMBERS);
     }
+    if (permittedSubtypeClasses != null) {
+      ++attributesCount;
+      size += 8 + permittedSubtypeClasses.length;
+      symbolTable.addConstantUtf8(Constants.PERMITTED_SUBTYPES);
+    }
+    int recordComponentCount = 0;
+    int recordSize = 0;
+    if (firstRecordComponent != null) {
+      RecordComponentWriter recordComponentWriter = firstRecordComponent;
+      while (recordComponentWriter != null) {
+        ++recordComponentCount;
+        recordSize += recordComponentWriter.computeRecordComponentInfoSize();
+        recordComponentWriter = (RecordComponentWriter) recordComponentWriter.delegate;
+      }
+      ++attributesCount;
+      size += 8 + recordSize;
+      symbolTable.addConstantUtf8(Constants.RECORD);
+    }
     if (firstAttribute != null) {
       attributesCount += firstAttribute.getAttributeCount();
       size += firstAttribute.computeAttributesSize(symbolTable);
@@ -630,6 +698,24 @@
           .putShort(numberOfNestMemberClasses)
           .putByteArray(nestMemberClasses.data, 0, nestMemberClasses.length);
     }
+    if (permittedSubtypeClasses != null) {
+      result
+          .putShort(symbolTable.addConstantUtf8(Constants.PERMITTED_SUBTYPES))
+          .putInt(permittedSubtypeClasses.length + 2)
+          .putShort(numberOfPermittedSubtypeClasses)
+          .putByteArray(permittedSubtypeClasses.data, 0, permittedSubtypeClasses.length);
+    }
+    if (firstRecordComponent != null) {
+      result
+          .putShort(symbolTable.addConstantUtf8(Constants.RECORD))
+          .putInt(recordSize + 2)
+          .putShort(recordComponentCount);
+      RecordComponentWriter recordComponentWriter = firstRecordComponent;
+      while (recordComponentWriter != null) {
+        recordComponentWriter.putRecordComponentInfo(result);
+        recordComponentWriter = (RecordComponentWriter) recordComponentWriter.delegate;
+      }
+    }
     if (firstAttribute != null) {
       firstAttribute.putAttributes(symbolTable, result);
     }
@@ -666,6 +752,10 @@
     nestHostClassIndex = 0;
     numberOfNestMemberClasses = 0;
     nestMemberClasses = null;
+    numberOfPermittedSubtypeClasses = 0;
+    permittedSubtypeClasses = null;
+    firstRecordComponent = null;
+    lastRecordComponent = null;
     firstAttribute = null;
     compute = hasFrames ? MethodWriter.COMPUTE_INSERTED_FRAMES : MethodWriter.COMPUTE_NOTHING;
     new ClassReader(classFile, 0, /* checkClassVersion = */ false)
@@ -694,6 +784,11 @@
       methodWriter.collectAttributePrototypes(attributePrototypes);
       methodWriter = (MethodWriter) methodWriter.mv;
     }
+    RecordComponentWriter recordComponentWriter = firstRecordComponent;
+    while (recordComponentWriter != null) {
+      recordComponentWriter.collectAttributePrototypes(attributePrototypes);
+      recordComponentWriter = (RecordComponentWriter) recordComponentWriter.delegate;
+    }
     return attributePrototypes.toArray();
   }
 
diff --git a/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/Constants.java b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/Constants.java
index 6cbbf42..89330ef 100644
--- a/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/Constants.java
+++ b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/Constants.java
@@ -26,6 +26,10 @@
 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 // THE POSSIBILITY OF SUCH DAMAGE.
 package jersey.repackaged.org.objectweb.asm;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.regex.Pattern;
 
 /**
  * Defines additional JVM opcodes, access flags and constants which are not part of the ASM public
@@ -34,7 +38,7 @@
  * @see <a href="https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-6.html">JVMS 6</a>
  * @author Eric Bruneton
  */
-final class Constants implements Opcodes {
+final class Constants {
 
   // The ClassFile attribute names, in the order they are defined in
   // https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-4.html#jvms-4.7-300.
@@ -68,6 +72,8 @@
   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 RECORD = "Record";
 
   // ASM specific access flags.
   // WARNING: the 16 least significant bits must NOT be used, to avoid conflicts with standard
@@ -140,7 +146,7 @@
   // Constants to convert between normal and wide jump instructions.
 
   // The delta between the GOTO_W and JSR_W opcodes and GOTO and JUMP.
-  static final int WIDE_JUMP_OPCODE_DELTA = GOTO_W - GOTO;
+  static final int WIDE_JUMP_OPCODE_DELTA = GOTO_W - Opcodes.GOTO;
 
   // Constants to convert JVM opcodes to the equivalent ASM specific opcodes, and vice versa.
 
@@ -153,25 +159,62 @@
 
   // ASM specific opcodes, used for long forward jump instructions.
 
-  static final int ASM_IFEQ = IFEQ + ASM_OPCODE_DELTA;
-  static final int ASM_IFNE = IFNE + ASM_OPCODE_DELTA;
-  static final int ASM_IFLT = IFLT + ASM_OPCODE_DELTA;
-  static final int ASM_IFGE = IFGE + ASM_OPCODE_DELTA;
-  static final int ASM_IFGT = IFGT + ASM_OPCODE_DELTA;
-  static final int ASM_IFLE = IFLE + ASM_OPCODE_DELTA;
-  static final int ASM_IF_ICMPEQ = IF_ICMPEQ + ASM_OPCODE_DELTA;
-  static final int ASM_IF_ICMPNE = IF_ICMPNE + ASM_OPCODE_DELTA;
-  static final int ASM_IF_ICMPLT = IF_ICMPLT + ASM_OPCODE_DELTA;
-  static final int ASM_IF_ICMPGE = IF_ICMPGE + ASM_OPCODE_DELTA;
-  static final int ASM_IF_ICMPGT = IF_ICMPGT + ASM_OPCODE_DELTA;
-  static final int ASM_IF_ICMPLE = IF_ICMPLE + ASM_OPCODE_DELTA;
-  static final int ASM_IF_ACMPEQ = IF_ACMPEQ + ASM_OPCODE_DELTA;
-  static final int ASM_IF_ACMPNE = IF_ACMPNE + ASM_OPCODE_DELTA;
-  static final int ASM_GOTO = GOTO + ASM_OPCODE_DELTA;
-  static final int ASM_JSR = JSR + ASM_OPCODE_DELTA;
-  static final int ASM_IFNULL = IFNULL + ASM_IFNULL_OPCODE_DELTA;
-  static final int ASM_IFNONNULL = IFNONNULL + ASM_IFNULL_OPCODE_DELTA;
+  static final int ASM_IFEQ = Opcodes.IFEQ + ASM_OPCODE_DELTA;
+  static final int ASM_IFNE = Opcodes.IFNE + ASM_OPCODE_DELTA;
+  static final int ASM_IFLT = Opcodes.IFLT + ASM_OPCODE_DELTA;
+  static final int ASM_IFGE = Opcodes.IFGE + ASM_OPCODE_DELTA;
+  static final int ASM_IFGT = Opcodes.IFGT + ASM_OPCODE_DELTA;
+  static final int ASM_IFLE = Opcodes.IFLE + ASM_OPCODE_DELTA;
+  static final int ASM_IF_ICMPEQ = Opcodes.IF_ICMPEQ + ASM_OPCODE_DELTA;
+  static final int ASM_IF_ICMPNE = Opcodes.IF_ICMPNE + ASM_OPCODE_DELTA;
+  static final int ASM_IF_ICMPLT = Opcodes.IF_ICMPLT + ASM_OPCODE_DELTA;
+  static final int ASM_IF_ICMPGE = Opcodes.IF_ICMPGE + ASM_OPCODE_DELTA;
+  static final int ASM_IF_ICMPGT = Opcodes.IF_ICMPGT + ASM_OPCODE_DELTA;
+  static final int ASM_IF_ICMPLE = Opcodes.IF_ICMPLE + ASM_OPCODE_DELTA;
+  static final int ASM_IF_ACMPEQ = Opcodes.IF_ACMPEQ + ASM_OPCODE_DELTA;
+  static final int ASM_IF_ACMPNE = Opcodes.IF_ACMPNE + ASM_OPCODE_DELTA;
+  static final int ASM_GOTO = Opcodes.GOTO + ASM_OPCODE_DELTA;
+  static final int ASM_JSR = Opcodes.JSR + ASM_OPCODE_DELTA;
+  static final int ASM_IFNULL = Opcodes.IFNULL + ASM_IFNULL_OPCODE_DELTA;
+  static final int ASM_IFNONNULL = Opcodes.IFNONNULL + ASM_IFNULL_OPCODE_DELTA;
   static final int ASM_GOTO_W = 220;
 
   private Constants() {}
+
+  static void checkAsmExperimental(final Object caller) {
+    Class<?> callerClass = caller.getClass();
+    String internalName = callerClass.getName().replace('.', '/');
+    if (!isWhitelisted(internalName)) {
+      checkIsPreview(callerClass.getClassLoader().getResourceAsStream(internalName + ".class"));
+    }
+  }
+
+  static boolean isWhitelisted(final String internalName) {
+    if (!internalName.startsWith("org/objectweb/asm/")) {
+      return false;
+    }
+    String member = "(Annotation|Class|Field|Method|Module|RecordComponent|Signature)";
+    return internalName.contains("Test$")
+        || Pattern.matches(
+            "org/objectweb/asm/util/Trace" + member + "Visitor(\\$.*)?", internalName)
+        || Pattern.matches(
+            "org/objectweb/asm/util/Check" + member + "Adapter(\\$.*)?", internalName);
+  }
+
+  static void checkIsPreview(final InputStream classInputStream) {
+    if (classInputStream == null) {
+      throw new IllegalStateException("Bytecode not available, can't check class version");
+    }
+    int minorVersion;
+    try (DataInputStream callerClassStream = new DataInputStream(classInputStream); ) {
+      callerClassStream.readInt();
+      minorVersion = callerClassStream.readUnsignedShort();
+    } catch (IOException ioe) {
+      throw new IllegalStateException("I/O error, can't check class version", ioe);
+    }
+    if (minorVersion != 0xFFFF) {
+      throw new IllegalStateException(
+          "ASM9_EXPERIMENTAL can only be used by classes compiled with --enable-preview");
+    }
+  }
 }
diff --git a/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/FieldVisitor.java b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/FieldVisitor.java
index 64d39d3..eb531cf 100644
--- a/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/FieldVisitor.java
+++ b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/FieldVisitor.java
@@ -38,7 +38,8 @@
 
   /**
    * The ASM API version implemented by this visitor. The value of this field must be one of {@link
-   * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+   * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7} or {@link
+   * Opcodes#ASM8}.
    */
   protected final int api;
 
@@ -49,7 +50,8 @@
    * Constructs a new {@link FieldVisitor}.
    *
    * @param api the ASM API version implemented by this visitor. Must be one of {@link
-   *     Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+   *     Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7} or {@link
+   *     Opcodes#ASM8}.
    */
   public FieldVisitor(final int api) {
     this(api, null);
@@ -59,14 +61,23 @@
    * Constructs a new {@link FieldVisitor}.
    *
    * @param api the ASM API version implemented by this visitor. Must be one of {@link
-   *     Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+   *     Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7} or {@link
+   *     Opcodes#ASM8}.
    * @param fieldVisitor the field visitor to which this visitor must delegate method calls. May be
    *     null.
    */
   public FieldVisitor(final int api, final FieldVisitor fieldVisitor) {
-    if (api != Opcodes.ASM7 && api != Opcodes.ASM6 && api != Opcodes.ASM5 && api != Opcodes.ASM4) {
+    if (api != Opcodes.ASM8
+        && api != Opcodes.ASM7
+        && api != Opcodes.ASM6
+        && api != Opcodes.ASM5
+        && api != Opcodes.ASM4
+        && api != Opcodes.ASM9_EXPERIMENTAL) {
       throw new IllegalArgumentException("Unsupported api " + api);
     }
+    if (api == Opcodes.ASM9_EXPERIMENTAL) {
+      Constants.checkAsmExperimental(this);
+    }
     this.api = api;
     this.fv = fieldVisitor;
   }
diff --git a/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/FieldWriter.java b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/FieldWriter.java
index 93f4802..95617fb 100644
--- a/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/FieldWriter.java
+++ b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/FieldWriter.java
@@ -124,7 +124,7 @@
       final String descriptor,
       final String signature,
       final Object constantValue) {
-    super(Opcodes.ASM7);
+    super(/* latest api = */ Opcodes.ASM8);
     this.symbolTable = symbolTable;
     this.accessFlags = access;
     this.nameIndex = symbolTable.addConstantUtf8(name);
diff --git a/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/MethodVisitor.java b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/MethodVisitor.java
index e88b6bf..b59be69 100644
--- a/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/MethodVisitor.java
+++ b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/MethodVisitor.java
@@ -80,9 +80,17 @@
    *     be null.
    */
   public MethodVisitor(final int api, final MethodVisitor methodVisitor) {
-    if (api != Opcodes.ASM7 && api != Opcodes.ASM6 && api != Opcodes.ASM5 && api != Opcodes.ASM4) {
+    if (api != Opcodes.ASM8
+        && api != Opcodes.ASM7
+        && api != Opcodes.ASM6
+        && api != Opcodes.ASM5
+        && api != Opcodes.ASM4
+        && api != Opcodes.ASM9_EXPERIMENTAL) {
       throw new IllegalArgumentException("Unsupported api " + api);
     }
+    if (api == Opcodes.ASM9_EXPERIMENTAL) {
+      Constants.checkAsmExperimental(this);
+    }
     this.api = api;
     this.mv = methodVisitor;
   }
@@ -534,7 +542,7 @@
             || (value instanceof Type && ((Type) value).getSort() == Type.METHOD))) {
       throw new UnsupportedOperationException(REQUIRES_ASM5);
     }
-    if (api != Opcodes.ASM7 && value instanceof ConstantDynamic) {
+    if (api < Opcodes.ASM7 && value instanceof ConstantDynamic) {
       throw new UnsupportedOperationException("This feature requires ASM7");
     }
     if (mv != null) {
diff --git a/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/MethodWriter.java b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/MethodWriter.java
index ecded66..9231c56 100644
--- a/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/MethodWriter.java
+++ b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/MethodWriter.java
@@ -592,7 +592,7 @@
       final String signature,
       final String[] exceptions,
       final int compute) {
-    super(Opcodes.ASM7);
+    super(/* latest api = */ Opcodes.ASM8);
     this.symbolTable = symbolTable;
     this.accessFlags = "<init>".equals(name) ? access | Constants.ACC_CONSTRUCTOR : access;
     this.nameIndex = symbolTable.addConstantUtf8(name);
diff --git a/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/ModuleVisitor.java b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/ModuleVisitor.java
index ff5062b..3285b09 100644
--- a/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/ModuleVisitor.java
+++ b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/ModuleVisitor.java
@@ -66,9 +66,17 @@
    *     be null.
    */
   public ModuleVisitor(final int api, final ModuleVisitor moduleVisitor) {
-    if (api != Opcodes.ASM7 && api != Opcodes.ASM6) {
+    if (api != Opcodes.ASM8
+        && api != Opcodes.ASM7
+        && api != Opcodes.ASM6
+        && api != Opcodes.ASM5
+        && api != Opcodes.ASM4
+        && api != Opcodes.ASM9_EXPERIMENTAL) {
       throw new IllegalArgumentException("Unsupported api " + api);
     }
+    if (api == Opcodes.ASM9_EXPERIMENTAL) {
+      Constants.checkAsmExperimental(this);
+    }
     this.api = api;
     this.mv = moduleVisitor;
   }
diff --git a/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/ModuleWriter.java b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/ModuleWriter.java
index 9877ceb..1932905 100644
--- a/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/ModuleWriter.java
+++ b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/ModuleWriter.java
@@ -94,7 +94,7 @@
   private int mainClassIndex;
 
   ModuleWriter(final SymbolTable symbolTable, final int name, final int access, final int version) {
-    super(Opcodes.ASM7);
+    super(/* latest api = */ Opcodes.ASM8);
     this.symbolTable = symbolTable;
     this.moduleNameIndex = name;
     this.moduleFlags = access;
diff --git a/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/Opcodes.java b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/Opcodes.java
index 6a1019f..9e26c7b 100644
--- a/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/Opcodes.java
+++ b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/Opcodes.java
@@ -47,6 +47,15 @@
   int ASM5 = 5 << 16 | 0 << 8;
   int ASM6 = 6 << 16 | 0 << 8;
   int ASM7 = 7 << 16 | 0 << 8;
+  int ASM8 = 8 << 16 | 0 << 8;
+
+  /**
+   * <i>Experimental, use at your own risk. This field will be renamed when it becomes stable, this
+   * will break existing code using it. Only code compiled with --enable-preview can use this.</i>
+   *
+   * @deprecated This API is experimental.
+   */
+  @Deprecated int ASM9_EXPERIMENTAL = 1 << 24 | 9 << 16 | 0 << 8;
 
   /*
    * Internal flags used to redirect calls to deprecated methods. For instance, if a visitOldStuff
@@ -307,7 +316,7 @@
   int ACC_SYNTHETIC = 0x1000; // class, field, method, parameter, module *
   int ACC_ANNOTATION = 0x2000; // class
   int ACC_ENUM = 0x4000; // class(?) field inner
-  int ACC_MANDATED = 0x8000; // parameter, module, module *
+  int ACC_MANDATED = 0x8000; // field, method, parameter, module, module *
   int ACC_MODULE = 0x8000; // class
 
   // ASM specific access flags.
diff --git a/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/RecordComponentVisitor.java b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/RecordComponentVisitor.java
new file mode 100644
index 0000000..f361d2f
--- /dev/null
+++ b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/RecordComponentVisitor.java
@@ -0,0 +1,150 @@
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the copyright holders nor the names of its
+//    contributors may be used to endorse or promote products derived from
+//    this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
+package jersey.repackaged.org.objectweb.asm;
+
+/**
+ * A visitor to visit a record component. The methods of this class must be called in the following
+ * order: ( {@code visitAnnotation} | {@code visitTypeAnnotation} | {@code visitAttribute} )* {@code
+ * visitEnd}.
+ *
+ * @author Remi Forax
+ * @author Eric Bruneton
+ */
+public abstract class RecordComponentVisitor {
+  /**
+   * The ASM API version implemented by this visitor. The value of this field must be {@link
+   * Opcodes#ASM8}.
+   */
+  protected final int api;
+
+  /**
+   * The record visitor to which this visitor must delegate method calls. May be {@literal null}.
+   */
+  /*package-private*/ RecordComponentVisitor delegate;
+
+  /**
+   * Constructs a new {@link RecordComponentVisitor}.
+   *
+   * @param api the ASM API version implemented by this visitor. Must be {@link Opcodes#ASM8}.
+   */
+  public RecordComponentVisitor(final int api) {
+    this(api, null);
+  }
+
+  /**
+   * Constructs a new {@link RecordComponentVisitor}.
+   *
+   * @param api the ASM API version implemented by this visitor. Must be {@link Opcodes#ASM8}.
+   * @param recordComponentVisitor the record component visitor to which this visitor must delegate
+   *     method calls. May be null.
+   */
+  public RecordComponentVisitor(
+      final int api, final RecordComponentVisitor recordComponentVisitor) {
+    if (api != Opcodes.ASM8
+        && api != Opcodes.ASM7
+        && api != Opcodes.ASM6
+        && api != Opcodes.ASM5
+        && api != Opcodes.ASM4
+        && api != Opcodes.ASM9_EXPERIMENTAL) {
+      throw new IllegalArgumentException("Unsupported api " + api);
+    }
+    if (api == Opcodes.ASM9_EXPERIMENTAL) {
+      Constants.checkAsmExperimental(this);
+    }
+    this.api = api;
+    this.delegate = recordComponentVisitor;
+  }
+
+  /**
+   * The record visitor to which this visitor must delegate method calls. May be {@literal null}.
+   *
+   * @return the record visitor to which this visitor must delegate method calls or {@literal null}.
+   */
+  public RecordComponentVisitor getDelegate() {
+    return delegate;
+  }
+
+  /**
+   * Visits an annotation of the record component.
+   *
+   * @param descriptor the class descriptor of the annotation class.
+   * @param visible {@literal true} if the annotation is visible at runtime.
+   * @return a visitor to visit the annotation values, or {@literal null} if this visitor is not
+   *     interested in visiting this annotation.
+   */
+  public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
+    if (delegate != null) {
+      return delegate.visitAnnotation(descriptor, visible);
+    }
+    return null;
+  }
+
+  /**
+   * Visits an annotation on a type in the record component signature.
+   *
+   * @param typeRef a reference to the annotated type. The sort of this type reference must be
+   *     {@link TypeReference#CLASS_TYPE_PARAMETER}, {@link
+   *     TypeReference#CLASS_TYPE_PARAMETER_BOUND} or {@link TypeReference#CLASS_EXTENDS}. See
+   *     {@link TypeReference}.
+   * @param typePath the path to the annotated type argument, wildcard bound, array element type, or
+   *     static inner type within 'typeRef'. May be {@literal null} if the annotation targets
+   *     'typeRef' as a whole.
+   * @param descriptor the class descriptor of the annotation class.
+   * @param visible {@literal true} if the annotation is visible at runtime.
+   * @return a visitor to visit the annotation values, or {@literal null} if this visitor is not
+   *     interested in visiting this annotation.
+   */
+  public AnnotationVisitor visitTypeAnnotation(
+      final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+    if (delegate != null) {
+      return delegate.visitTypeAnnotation(typeRef, typePath, descriptor, visible);
+    }
+    return null;
+  }
+
+  /**
+   * Visits a non standard attribute of the record component.
+   *
+   * @param attribute an attribute.
+   */
+  public void visitAttribute(final Attribute attribute) {
+    if (delegate != null) {
+      delegate.visitAttribute(attribute);
+    }
+  }
+
+  /**
+   * Visits the end of the record component. This method, which is the last one to be called, is
+   * used to inform the visitor that everything have been visited.
+   */
+  public void visitEnd() {
+    if (delegate != null) {
+      delegate.visitEnd();
+    }
+  }
+}
diff --git a/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/RecordComponentWriter.java b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/RecordComponentWriter.java
new file mode 100644
index 0000000..8248170
--- /dev/null
+++ b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/RecordComponentWriter.java
@@ -0,0 +1,225 @@
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the copyright holders nor the names of its
+//    contributors may be used to endorse or promote products derived from
+//    this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
+package jersey.repackaged.org.objectweb.asm;
+
+final class RecordComponentWriter extends RecordComponentVisitor {
+  /** Where the constants used in this RecordComponentWriter must be stored. */
+  private final SymbolTable symbolTable;
+
+  // Note: fields are ordered as in the record_component_info structure, and those related to
+  // attributes are ordered as in Section 4.7 of the JVMS.
+
+  /** The name_index field of the Record attribute. */
+  private final int nameIndex;
+
+  /** The descriptor_index field of the the Record attribute. */
+  private final int descriptorIndex;
+
+  /**
+   * The signature_index field of the Signature attribute of this record component, or 0 if there is
+   * no Signature attribute.
+   */
+  private int signatureIndex;
+
+  /**
+   * The last runtime visible annotation of this record component. The previous ones can be accessed
+   * with the {@link AnnotationWriter#previousAnnotation} field. May be {@literal null}.
+   */
+  private AnnotationWriter lastRuntimeVisibleAnnotation;
+
+  /**
+   * The last runtime invisible annotation of this record component. The previous ones can be
+   * accessed with the {@link AnnotationWriter#previousAnnotation} field. May be {@literal null}.
+   */
+  private AnnotationWriter lastRuntimeInvisibleAnnotation;
+
+  /**
+   * The last runtime visible type annotation of this record component. The previous ones can be
+   * accessed with the {@link AnnotationWriter#previousAnnotation} field. May be {@literal null}.
+   */
+  private AnnotationWriter lastRuntimeVisibleTypeAnnotation;
+
+  /**
+   * The last runtime invisible type annotation of this record component. The previous ones can be
+   * accessed with the {@link AnnotationWriter#previousAnnotation} field. May be {@literal null}.
+   */
+  private AnnotationWriter lastRuntimeInvisibleTypeAnnotation;
+
+  /**
+   * The first non standard attribute of this record component. The next ones can be accessed with
+   * the {@link Attribute#nextAttribute} field. May be {@literal null}.
+   *
+   * <p><b>WARNING</b>: this list stores the attributes in the <i>reverse</i> order of their visit.
+   * firstAttribute is actually the last attribute visited in {@link #visitAttribute(Attribute)}.
+   * The {@link #putRecordComponentInfo(ByteVector)} method writes the attributes in the order
+   * defined by this list, i.e. in the reverse order specified by the user.
+   */
+  private Attribute firstAttribute;
+
+  /**
+   * Constructs a new {@link RecordComponentWriter}.
+   *
+   * @param symbolTable where the constants used in this RecordComponentWriter must be stored.
+   * @param name the record component name.
+   * @param descriptor the record component descriptor (see {@link Type}).
+   * @param signature the record component signature. May be {@literal null}.
+   */
+  RecordComponentWriter(
+      final SymbolTable symbolTable,
+      final String name,
+      final String descriptor,
+      final String signature) {
+    super(/* latest api = */ Opcodes.ASM8);
+    this.symbolTable = symbolTable;
+    this.nameIndex = symbolTable.addConstantUtf8(name);
+    this.descriptorIndex = symbolTable.addConstantUtf8(descriptor);
+    if (signature != null) {
+      this.signatureIndex = symbolTable.addConstantUtf8(signature);
+    }
+  }
+
+  // -----------------------------------------------------------------------------------------------
+  // Implementation of the FieldVisitor abstract class
+  // -----------------------------------------------------------------------------------------------
+
+  @Override
+  public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
+    if (visible) {
+      return lastRuntimeVisibleAnnotation =
+          AnnotationWriter.create(symbolTable, descriptor, lastRuntimeVisibleAnnotation);
+    } else {
+      return lastRuntimeInvisibleAnnotation =
+          AnnotationWriter.create(symbolTable, descriptor, lastRuntimeInvisibleAnnotation);
+    }
+  }
+
+  @Override
+  public AnnotationVisitor visitTypeAnnotation(
+      final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+    if (visible) {
+      return lastRuntimeVisibleTypeAnnotation =
+          AnnotationWriter.create(
+              symbolTable, typeRef, typePath, descriptor, lastRuntimeVisibleTypeAnnotation);
+    } else {
+      return lastRuntimeInvisibleTypeAnnotation =
+          AnnotationWriter.create(
+              symbolTable, typeRef, typePath, descriptor, lastRuntimeInvisibleTypeAnnotation);
+    }
+  }
+
+  @Override
+  public void visitAttribute(final Attribute attribute) {
+    // Store the attributes in the <i>reverse</i> order of their visit by this method.
+    attribute.nextAttribute = firstAttribute;
+    firstAttribute = attribute;
+  }
+
+  @Override
+  public void visitEnd() {
+    // Nothing to do.
+  }
+
+  // -----------------------------------------------------------------------------------------------
+  // Utility methods
+  // -----------------------------------------------------------------------------------------------
+
+  /**
+   * Returns the size of the record component JVMS structure generated by this
+   * RecordComponentWriter. Also adds the names of the attributes of this record component in the
+   * constant pool.
+   *
+   * @return the size in bytes of the record_component_info of the Record attribute.
+   */
+  int computeRecordComponentInfoSize() {
+    // name_index, descriptor_index and attributes_count fields use 6 bytes.
+    int size = 6;
+    size += Attribute.computeAttributesSize(symbolTable, 0, signatureIndex);
+    size +=
+        AnnotationWriter.computeAnnotationsSize(
+            lastRuntimeVisibleAnnotation,
+            lastRuntimeInvisibleAnnotation,
+            lastRuntimeVisibleTypeAnnotation,
+            lastRuntimeInvisibleTypeAnnotation);
+    if (firstAttribute != null) {
+      size += firstAttribute.computeAttributesSize(symbolTable);
+    }
+    return size;
+  }
+
+  /**
+   * Puts the content of the record component generated by this RecordComponentWriter into the given
+   * ByteVector.
+   *
+   * @param output where the record_component_info structure must be put.
+   */
+  void putRecordComponentInfo(final ByteVector output) {
+    output.putShort(nameIndex).putShort(descriptorIndex);
+    // Compute and put the attributes_count field.
+    // For ease of reference, we use here the same attribute order as in Section 4.7 of the JVMS.
+    int attributesCount = 0;
+    if (signatureIndex != 0) {
+      ++attributesCount;
+    }
+    if (lastRuntimeVisibleAnnotation != null) {
+      ++attributesCount;
+    }
+    if (lastRuntimeInvisibleAnnotation != null) {
+      ++attributesCount;
+    }
+    if (lastRuntimeVisibleTypeAnnotation != null) {
+      ++attributesCount;
+    }
+    if (lastRuntimeInvisibleTypeAnnotation != null) {
+      ++attributesCount;
+    }
+    if (firstAttribute != null) {
+      attributesCount += firstAttribute.getAttributeCount();
+    }
+    output.putShort(attributesCount);
+    Attribute.putAttributes(symbolTable, 0, signatureIndex, output);
+    AnnotationWriter.putAnnotations(
+        symbolTable,
+        lastRuntimeVisibleAnnotation,
+        lastRuntimeInvisibleAnnotation,
+        lastRuntimeVisibleTypeAnnotation,
+        lastRuntimeInvisibleTypeAnnotation,
+        output);
+    if (firstAttribute != null) {
+      firstAttribute.putAttributes(symbolTable, output);
+    }
+  }
+
+  /**
+   * Collects the attributes of this record component into the given set of attribute prototypes.
+   *
+   * @param attributePrototypes a set of attribute prototypes.
+   */
+  final void collectAttributePrototypes(final Attribute.Set attributePrototypes) {
+    attributePrototypes.addAttributes(firstAttribute);
+  }
+}
diff --git a/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/SymbolTable.java b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/SymbolTable.java
index 31bf0bf..e52af51 100644
--- a/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/SymbolTable.java
+++ b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/SymbolTable.java
@@ -31,11 +31,11 @@
  * The constant pool entries, the BootstrapMethods attribute entries and the (ASM specific) type
  * table entries of a class.
  *
+ * @author Eric Bruneton
  * @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.4">JVMS
  *     4.4</a>
  * @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.23">JVMS
  *     4.7.23</a>
- * @author Eric Bruneton
  */
 final class SymbolTable {
 
@@ -1046,8 +1046,10 @@
     // bootstrap methods. We must therefore add the bootstrap method arguments to the constant pool
     // and BootstrapMethods attribute first, so that the BootstrapMethods attribute is not modified
     // while adding the given bootstrap method to it, in the rest of this method.
-    for (Object bootstrapMethodArgument : bootstrapMethodArguments) {
-      addConstant(bootstrapMethodArgument);
+    int numBootstrapArguments = bootstrapMethodArguments.length;
+    int[] bootstrapMethodArgumentIndexes = new int[numBootstrapArguments];
+    for (int i = 0; i < numBootstrapArguments; i++) {
+      bootstrapMethodArgumentIndexes[i] = addConstant(bootstrapMethodArguments[i]).index;
     }
 
     // Write the bootstrap method in the BootstrapMethods table. This is necessary to be able to
@@ -1062,10 +1064,10 @@
                 bootstrapMethodHandle.getDesc(),
                 bootstrapMethodHandle.isInterface())
             .index);
-    int numBootstrapArguments = bootstrapMethodArguments.length;
+
     bootstrapMethodsAttribute.putShort(numBootstrapArguments);
-    for (Object bootstrapMethodArgument : bootstrapMethodArguments) {
-      bootstrapMethodsAttribute.putShort(addConstant(bootstrapMethodArgument).index);
+    for (int i = 0; i < numBootstrapArguments; i++) {
+      bootstrapMethodsAttribute.putShort(bootstrapMethodArgumentIndexes[i]);
     }
 
     // Compute the length and the hash code of the bootstrap method.
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/internal/scanning/AnnotationAcceptingListener.java b/core-server/src/main/java/org/glassfish/jersey/server/internal/scanning/AnnotationAcceptingListener.java
index d73e368..a43e3ba 100644
--- a/core-server/src/main/java/org/glassfish/jersey/server/internal/scanning/AnnotationAcceptingListener.java
+++ b/core-server/src/main/java/org/glassfish/jersey/server/internal/scanning/AnnotationAcceptingListener.java
@@ -16,6 +16,7 @@
 
 package org.glassfish.jersey.server.internal.scanning;
 
+import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.lang.annotation.Annotation;
@@ -24,10 +25,12 @@
 import java.util.HashSet;
 import java.util.LinkedHashSet;
 import java.util.Set;
+import java.util.logging.Logger;
 
 import jakarta.ws.rs.Path;
 import jakarta.ws.rs.ext.Provider;
 
+import jersey.repackaged.org.objectweb.asm.RecordComponentVisitor;
 import org.glassfish.jersey.internal.OsgiRegistry;
 import org.glassfish.jersey.internal.util.ReflectionHelper;
 import org.glassfish.jersey.server.internal.LocalizationMessages;
@@ -145,7 +148,7 @@
     }
 
     public void process(final String name, final InputStream in) throws IOException {
-        new ClassReader(in).accept(classVisitor, 0);
+        new ClassReaderWrapper(in).accept(classVisitor, 0);
     }
 
     //
@@ -166,9 +169,10 @@
         private boolean isAnnotated;
 
         private AnnotatedClassVisitor() {
-            super(Opcodes.ASM7);
+            super(Opcodes.ASM8);
         }
 
+        @Override
         public void visit(final int version, final int access, final String name,
                           final String signature, final String superName, final String[] interfaces) {
             className = name;
@@ -176,11 +180,13 @@
             isAnnotated = false;
         }
 
+        @Override
         public AnnotationVisitor visitAnnotation(final String desc, final boolean visible) {
             isAnnotated |= annotations.contains(desc);
             return null;
         }
 
+        @Override
         public void visitInnerClass(final String name, final String outerName,
                                     final String innerName, final int access) {
             // If the name of the class that was visited is equal
@@ -195,6 +201,7 @@
             }
         }
 
+        @Override
         public void visitEnd() {
             if (isScoped && isAnnotated) {
                 // Correctly scoped and annotated
@@ -203,11 +210,13 @@
             }
         }
 
+        @Override
         public void visitOuterClass(final String string, final String string0,
                                     final String string1) {
             // Do nothing
         }
 
+        @Override
         public FieldVisitor visitField(final int i, final String string,
                                        final String string0, final String string1,
                                        final Object object) {
@@ -215,14 +224,17 @@
             return null;
         }
 
+        @Override
         public void visitSource(final String string, final String string0) {
             // Do nothing
         }
 
+        @Override
         public void visitAttribute(final Attribute attribute) {
             // Do nothing
         }
 
+        @Override
         public MethodVisitor visitMethod(final int i, final String string,
                                          final String string0, final String string1,
                                          final String[] string2) {
@@ -230,19 +242,34 @@
             return null;
         }
 
+        @Override
         public ModuleVisitor visitModule(final String name, final int access, final String version) {
             // Do nothing
             return null;
         }
 
+        @Override
         public void visitNestHost(final String nestHost) {
             // do nothing
         }
 
+        @Override
         public void visitNestMember(final String nestMember) {
             // do nothing
         }
 
+        @Override
+        public void visitPermittedSubtypeExperimental(String permittedSubtype) {
+            // do nothing
+        }
+
+        @Override
+        public RecordComponentVisitor visitRecordComponent(String name, String descriptor, String signature) {
+            // do nothing
+            return null;
+        }
+
+        @Override
         public AnnotationVisitor visitTypeAnnotation(
                 final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
             //do nothing
@@ -273,4 +300,80 @@
         }
 
     }
+
+    private static class ClassReaderWrapper {
+        private static final Logger LOGGER = Logger.getLogger(ClassReader.class.getName());
+        private static final int WARN_VERSION = Opcodes.V15;
+        private static final int INPUT_STREAM_DATA_CHUNK_SIZE = 4096;
+
+        private final byte[] b;
+        private ClassReaderWrapper(InputStream inputStream) throws IOException {
+            this.b = readStream(inputStream);
+        }
+
+        private void accept(final ClassVisitor classVisitor, final int parsingOptions) {
+            final int originalVersion = getMajorVersion(b);
+            if (originalVersion == WARN_VERSION + 1) {
+                // temporarily downgrade version to bypass check in ASM
+                setMajorVersion(WARN_VERSION, b);
+                LOGGER.warning("Unsupported class file major version " + originalVersion);
+            }
+            final ClassReader classReader = new ClassReader(b);
+            setMajorVersion(originalVersion, b);
+            classReader.accept(classVisitor, parsingOptions);
+        }
+
+        /**
+         * Sets major version number in given bytes of class (unsigned two bytes at
+         * offset 6).
+         *
+         * @param majorVersion
+         *            major version of bytecode to set
+         * @param b
+         *            bytes of class
+         * @see #getMajorVersion(byte[])
+         */
+        private static void setMajorVersion(final int majorVersion, final byte[] b) {
+            b[6] = (byte) (majorVersion >>> 8);
+            b[7] = (byte) majorVersion;
+        }
+
+        /**
+         * Gets major version number from given bytes of class (unsigned two bytes
+         * at offset 6).
+         *
+         * @param b
+         *            bytes of class
+         * @return major version of bytecode
+         * @see <a href=
+         *      "https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-4.html#jvms-4.1">JVMS 4.1 - The class File Format</a>
+         */
+        private static int getMajorVersion(final byte[] b) {
+            return ((b[6] & 0xFF) << 8) | (b[7] & 0xFF);
+        }
+
+        /**
+         * Reads the given input stream and returns its content as a byte array.
+         *
+         * @param inputStream an input stream.
+         * @return the content of the given input stream.
+         * @throws IOException if a problem occurs during reading.
+         */
+        private static byte[] readStream(final InputStream inputStream) throws IOException {
+            if (inputStream == null) {
+                throw new IOException("Class not found");
+            }
+            try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
+                byte[] data = new byte[INPUT_STREAM_DATA_CHUNK_SIZE];
+                int bytesRead;
+                while ((bytesRead = inputStream.read(data, 0, data.length)) != -1) {
+                    outputStream.write(data, 0, bytesRead);
+                }
+                outputStream.flush();
+                return outputStream.toByteArray();
+            } finally {
+                inputStream.close();
+            }
+        }
+    }
 }
diff --git a/pom.xml b/pom.xml
index 6710e7d..7c3750b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -2070,7 +2070,7 @@
         <jersey.version>${project.version}</jersey.version>
         <!-- asm is now source integrated - keeping this property to see the version -->
         <!-- see core-server/src/main/java/jersey/repackaged/asm/.. -->
-        <asm.version>7.2</asm.version>
+        <asm.version>8.0</asm.version>
         <bnd.plugin.version>2.3.6</bnd.plugin.version>
         <cdi.api.version>1.1</cdi.api.version>
         <commons-lang3.version>3.3.2</commons-lang3.version>
diff --git a/tests/integration/asm/src/test/java/org/glassfish/jersey/integration/asm/AnnotatedClassVisitorTest.java b/tests/integration/asm/src/test/java/org/glassfish/jersey/integration/asm/AnnotatedClassVisitorTest.java
index 708684d..54dbdc6 100644
--- a/tests/integration/asm/src/test/java/org/glassfish/jersey/integration/asm/AnnotatedClassVisitorTest.java
+++ b/tests/integration/asm/src/test/java/org/glassfish/jersey/integration/asm/AnnotatedClassVisitorTest.java
@@ -16,11 +16,17 @@
 package org.glassfish.jersey.integration.asm;
 
 import jersey.repackaged.org.objectweb.asm.ClassVisitor;
+import jersey.repackaged.org.objectweb.asm.Opcodes;
 import org.glassfish.jersey.server.internal.scanning.AnnotationAcceptingListener;
 import org.hamcrest.Matchers;
 import org.junit.Assert;
 import org.junit.Test;
 
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.lang.reflect.Field;
 import java.lang.reflect.Method;
 import java.util.Arrays;
 import java.util.List;
@@ -75,4 +81,97 @@
         }
         Assert.assertThat(containsAllMethods, Matchers.is(true));
     }
+
+    @Test
+    public void testCorrectOpcodeAsmIsUsedInAnnotationAcceptingListener() {
+        final int asmOpcode = getMaxValueOfField("ASM", 6);
+        final AnnotationAcceptingListener aal = new AnnotationAcceptingListener();
+
+        String aalOpcode = null;
+        try {
+            final Field classVisitorField = aal.getClass().getDeclaredField("classVisitor");
+            classVisitorField.setAccessible(true);
+            final Object classVisitor = classVisitorField.get(aal);
+            final Field opcodeField = classVisitor.getClass().getSuperclass().getDeclaredField("api");
+            opcodeField.setAccessible(true);
+            aalOpcode = String.valueOf(((Integer) opcodeField.get(classVisitor)) >> 16);
+        } catch (NoSuchFieldException | IllegalAccessException e) {
+            e.printStackTrace();
+        }
+
+        Assert.assertEquals(
+                "You need to set: \nAnnotatedClassVisitor() {\n    super(Opcodes.ASM" + asmOpcode + ");\n}",
+                String.valueOf(asmOpcode), aalOpcode
+        );
+    }
+
+    @Test
+    public void testWarningOpcodeInClassReaderWrapperSetCorrectly() {
+        final Integer jdkVersion = getMaxValueOfField("V", 13);
+
+        Class<?> classReaderWrapper = null;
+        for (Class<?> innerClass : AnnotationAcceptingListener.class.getDeclaredClasses()) {
+            if (innerClass.getName().contains("ClassReaderWrapper")) {
+                classReaderWrapper = innerClass;
+                break;
+            }
+        }
+
+        Integer warnFieldValue = 0;
+        try {
+            final Field warnField = classReaderWrapper.getDeclaredField("WARN_VERSION");
+            warnField.setAccessible(true);
+            warnFieldValue = (Integer) warnField.get(null) - (Opcodes.V1_1 & 0x00FF) + 1;
+        } catch (NoSuchFieldException | IllegalAccessException e) {
+            e.printStackTrace();
+        }
+
+        Assert.assertEquals(
+                "You need to set ClassReaderWrapper.WARN_VERSION=Opcodes.V" + jdkVersion,
+                jdkVersion, warnFieldValue
+        );
+    }
+
+    @Test
+    public void testLoggerInClassReaderWrapper() throws IOException {
+        final String warningMsg = "Unsupported class file major version";
+
+        final Integer maxOpcode = getMaxValueOfField("V", 13);
+        final byte[] array = new byte[10];
+        array[7] = (byte) ((maxOpcode.byteValue() + Opcodes.V1_1) & 0x00FF);
+
+        final ByteArrayOutputStream log = new ByteArrayOutputStream(500);
+        final PrintStream saveErr = System.err;
+
+        try {
+            System.setErr(new PrintStream(log));
+            try {
+                new AnnotationAcceptingListener().process("", new ByteArrayInputStream(array));
+            } catch (ArrayIndexOutOfBoundsException aioobe) {
+                //expected, given array is too small for a class file
+            }
+        } finally {
+            System.setErr(saveErr);
+        }
+
+        final String message = new String(log.toByteArray());
+        Assert.assertTrue(
+                "The WARNING `" + warningMsg + "` has not been printed for a class with byte code version " + array[7],
+                message.contains(warningMsg)
+        );
+    }
+
+    private static int getMaxValueOfField(String fieldPrefix, int initialValue) {
+        int value = initialValue;
+        do {
+            try {
+                value++;
+                Field field = Opcodes.class.getField(fieldPrefix + value);
+            } catch (NoSuchFieldException e) {
+                value--;
+                break;
+            }
+        } while (true);
+        return value;
+    }
 }