docs: private void readClassAttributes() throws IOException, ClassfileFormatException {
          // Class attributes (including class annotations, class type variables, module info, etc.)
          final int attributesCount = inputStreamOrByteBuffer.readUnsignedShort();
          for (int i = 0; i < attributesCount; i++) {
              final int attributeNameCpIdx = inputStreamOrByteBuffer.readUnsignedShort();
              final int attributeLength = inputStreamOrByteBuffer.readInt();
              if (scanSpec.enableAnnotationInfo //
                      && (constantPoolStringEquals(attributeNameCpIdx, "RuntimeVisibleAnnotations")
                              || (!scanSpec.disableRuntimeInvisibleAnnotations && constantPoolStringEquals(
                                      attributeNameCpIdx, "RuntimeInvisibleAnnotations")))) {
                  final int annotationCount = inputStreamOrByteBuffer.readUnsignedShort();
                  if (annotationCount > 0) {
                      if (classAnnotations == null) {
                          classAnnotations = new AnnotationInfoList();
                      }
                      for (int m = 0; m < annotationCount; m++) {
                          classAnnotations.add(readAnnotation());
                      }
                  }
              } else if (constantPoolStringEquals(attributeNameCpIdx, "InnerClasses")) {
                  final int numInnerClasses = inputStreamOrByteBuffer.readUnsignedShort();
                  for (int j = 0; j < numInnerClasses; j++) {
                      final int innerClassInfoCpIdx = inputStreamOrByteBuffer.readUnsignedShort();
                      final int outerClassInfoCpIdx = inputStreamOrByteBuffer.readUnsignedShort();
                      if (innerClassInfoCpIdx != 0 && outerClassInfoCpIdx != 0) {
                          if (classContainmentEntries == null) {
                              classContainmentEntries = new ArrayList<>();
                          }
                          classContainmentEntries.add(new SimpleEntry<>(getConstantPoolClassName(innerClassInfoCpIdx),
                                  getConstantPoolClassName(outerClassInfoCpIdx)));
                      }
                      inputStreamOrByteBuffer.skip(2); // inner_name_idx
                      inputStreamOrByteBuffer.skip(2); // inner_class_access_flags
                  }
              } else if (constantPoolStringEquals(attributeNameCpIdx, "Signature")) {
                  // Get class type signature, including type variables
                  typeSignature = getConstantPoolString(inputStreamOrByteBuffer.readUnsignedShort());
              } else if (constantPoolStringEquals(attributeNameCpIdx, "EnclosingMethod")) {
                  final String innermostEnclosingClassName = getConstantPoolClassName(
                          inputStreamOrByteBuffer.readUnsignedShort());
                  final int enclosingMethodCpIdx = inputStreamOrByteBuffer.readUnsignedShort();
                  String definingMethodName;
                  if (enclosingMethodCpIdx == 0) {
                      // A cpIdx of 0 (which is an invalid value) is used for anonymous inner classes declared in
                      // class initializer code, e.g. assigned to a class field.
                      definingMethodName = "<clinit>";
                  } else {
                      definingMethodName = getConstantPoolString(enclosingMethodCpIdx, /* subFieldIdx = */ 0);
                      // Could also fetch method type signature using subFieldIdx = 1, if needed
                  }
                  // Link anonymous inner classes into the class with their containing method
                  if (classContainmentEntries == null) {
                      classContainmentEntries = new ArrayList<>();
                  }
                  classContainmentEntries.add(new SimpleEntry<>(className, innermostEnclosingClassName));
                  // Also store the fully-qualified name of the enclosing method, to mark this as an anonymous inner
                  // class
                  this.fullyQualifiedDefiningMethodName = innermostEnclosingClassName + "." + definingMethodName;
              } else if (constantPoolStringEquals(attributeNameCpIdx, "Module")) {
                  final int moduleNameCpIdx = inputStreamOrByteBuffer.readUnsignedShort();
                  classpathElement.moduleNameFromModuleDescriptor = getConstantPoolString(moduleNameCpIdx);
                  // (Future work): parse the rest of the module descriptor fields, and add to ModuleInfo:
                  // https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.25
                  inputStreamOrByteBuffer.skip(attributeLength - 2);
              } else {
                  inputStreamOrByteBuffer.skip(attributeLength);
              }
          }
      }