jodd-proxetta/src/main/java/jodd/asm7/ClassReader.java
private void readModuleAttributes(
      final ClassVisitor classVisitor,
      final Context context,
      final int moduleOffset,
      final int modulePackagesOffset,
      final String moduleMainClass) {
    char[] buffer = context.charBuffer;

    // Read the module_name_index, module_flags and module_version_index fields and visit them.
    int currentOffset = moduleOffset;
    String moduleName = readModule(currentOffset, buffer);
    int moduleFlags = readUnsignedShort(currentOffset + 2);
    String moduleVersion = readUTF8(currentOffset + 4, buffer);
    currentOffset += 6;
    ModuleVisitor moduleVisitor = classVisitor.visitModule(moduleName, moduleFlags, moduleVersion);
    if (moduleVisitor == null) {
      return;
    }

    // Visit the ModuleMainClass attribute.
    if (moduleMainClass != null) {
      moduleVisitor.visitMainClass(moduleMainClass);
    }

    // Visit the ModulePackages attribute.
    if (modulePackagesOffset != 0) {
      int packageCount = readUnsignedShort(modulePackagesOffset);
      int currentPackageOffset = modulePackagesOffset + 2;
      while (packageCount-- > 0) {
        moduleVisitor.visitPackage(readPackage(currentPackageOffset, buffer));
        currentPackageOffset += 2;
      }
    }

    // Read the 'requires_count' and 'requires' fields.
    int requiresCount = readUnsignedShort(currentOffset);
    currentOffset += 2;
    while (requiresCount-- > 0) {
      // Read the requires_index, requires_flags and requires_version fields and visit them.
      String requires = readModule(currentOffset, buffer);
      int requiresFlags = readUnsignedShort(currentOffset + 2);
      String requiresVersion = readUTF8(currentOffset + 4, buffer);
      currentOffset += 6;
      moduleVisitor.visitRequire(requires, requiresFlags, requiresVersion);
    }

    // Read the 'exports_count' and 'exports' fields.
    int exportsCount = readUnsignedShort(currentOffset);
    currentOffset += 2;
    while (exportsCount-- > 0) {
      // Read the exports_index, exports_flags, exports_to_count and exports_to_index fields
      // and visit them.
      String exports = readPackage(currentOffset, buffer);
      int exportsFlags = readUnsignedShort(currentOffset + 2);
      int exportsToCount = readUnsignedShort(currentOffset + 4);
      currentOffset += 6;
      String[] exportsTo = null;
      if (exportsToCount != 0) {
        exportsTo = new String[exportsToCount];
        for (int i = 0; i < exportsToCount; ++i) {
          exportsTo[i] = readModule(currentOffset, buffer);
          currentOffset += 2;
        }
      }
      moduleVisitor.visitExport(exports, exportsFlags, exportsTo);
    }

    // Reads the 'opens_count' and 'opens' fields.
    int opensCount = readUnsignedShort(currentOffset);
    currentOffset += 2;
    while (opensCount-- > 0) {
      // Read the opens_index, opens_flags, opens_to_count and opens_to_index fields and visit them.
      String opens = readPackage(currentOffset, buffer);
      int opensFlags = readUnsignedShort(currentOffset + 2);
      int opensToCount = readUnsignedShort(currentOffset + 4);
      currentOffset += 6;
      String[] opensTo = null;
      if (opensToCount != 0) {
        opensTo = new String[opensToCount];
        for (int i = 0; i < opensToCount; ++i) {
          opensTo[i] = readModule(currentOffset, buffer);
          currentOffset += 2;
        }
      }
      moduleVisitor.visitOpen(opens, opensFlags, opensTo);
    }

    // Read the 'uses_count' and 'uses' fields.
    int usesCount = readUnsignedShort(currentOffset);
    currentOffset += 2;
    while (usesCount-- > 0) {
      moduleVisitor.visitUse(readClass(currentOffset, buffer));
      currentOffset += 2;
    }

    // Read the  'provides_count' and 'provides' fields.
    int providesCount = readUnsignedShort(currentOffset);
    currentOffset += 2;
    while (providesCount-- > 0) {
      // Read the provides_index, provides_with_count and provides_with_index fields and visit them.
      String provides = readClass(currentOffset, buffer);
      int providesWithCount = readUnsignedShort(currentOffset + 2);
      currentOffset += 4;
      String[] providesWith = new String[providesWithCount];
      for (int i = 0; i < providesWithCount; ++i) {
        providesWith[i] = readClass(currentOffset, buffer);
        currentOffset += 2;
      }
      moduleVisitor.visitProvide(provides, providesWith);
    }

    // Visit the end of the module attributes.
    moduleVisitor.visitEnd();
  }
private void readModuleAttributes(
      final ClassVisitor classVisitor,
      final Context context,
      final int moduleOffset,
      final int modulePackagesOffset,
      final String moduleMainClass) {
    char[] buffer = context.charBuffer;

    // Read the module_name_index, module_flags and module_version_index fields and visit them.
    int currentOffset = moduleOffset;
    String moduleName = readModule(currentOffset, buffer);
    int moduleFlags = readUnsignedShort(currentOffset + 2);
    String moduleVersion = readUTF8(currentOffset + 4, buffer);
    currentOffset += 6;
    ModuleVisitor moduleVisitor = classVisitor.visitModule(moduleName, moduleFlags, moduleVersion);
    if (moduleVisitor == null) {
      return;
    }

    // Visit the ModuleMainClass attribute.
    if (moduleMainClass != null) {
      moduleVisitor.visitMainClass(moduleMainClass);
    }

    // Visit the ModulePackages attribute.
    if (modulePackagesOffset != 0) {
      int packageCount = readUnsignedShort(modulePackagesOffset);
      int currentPackageOffset = modulePackagesOffset + 2;
      while (packageCount-- > 0) {
        moduleVisitor.visitPackage(readPackage(currentPackageOffset, buffer));
        currentPackageOffset += 2;
      }
    }

    // Read the 'requires_count' and 'requires' fields.
    int requiresCount = readUnsignedShort(currentOffset);
    currentOffset += 2;
    while (requiresCount-- > 0) {
      // Read the requires_index, requires_flags and requires_version fields and visit them.
      String requires = readModule(currentOffset, buffer);
      int requiresFlags = readUnsignedShort(currentOffset + 2);
      String requiresVersion = readUTF8(currentOffset + 4, buffer);
      currentOffset += 6;
      moduleVisitor.visitRequire(requires, requiresFlags, requiresVersion);
    }

    // Read the 'exports_count' and 'exports' fields.
    int exportsCount = readUnsignedShort(currentOffset);
    currentOffset += 2;
    while (exportsCount-- > 0) {
      // Read the exports_index, exports_flags, exports_to_count and exports_to_index fields
      // and visit them.
      String exports = readPackage(currentOffset, buffer);
      int exportsFlags = readUnsignedShort(currentOffset + 2);
      int exportsToCount = readUnsignedShort(currentOffset + 4);
      currentOffset += 6;
      String[] exportsTo = null;
      if (exportsToCount != 0) {
        exportsTo = new String[exportsToCount];
        for (int i = 0; i < exportsToCount; ++i) {
          exportsTo[i] = readModule(currentOffset, buffer);
          currentOffset += 2;
        }
      }
      moduleVisitor.visitExport(exports, exportsFlags, exportsTo);
    }

    // Reads the 'opens_count' and 'opens' fields.
    int opensCount = readUnsignedShort(currentOffset);
    currentOffset += 2;
    while (opensCount-- > 0) {
      // Read the opens_index, opens_flags, opens_to_count and opens_to_index fields and visit them.
      String opens = readPackage(currentOffset, buffer);
      int opensFlags = readUnsignedShort(currentOffset + 2);
      int opensToCount = readUnsignedShort(currentOffset + 4);
      currentOffset += 6;
      String[] opensTo = null;
      if (opensToCount != 0) {
        opensTo = new String[opensToCount];
        for (int i = 0; i < opensToCount; ++i) {
          opensTo[i] = readModule(currentOffset, buffer);
          currentOffset += 2;
        }
      }
      moduleVisitor.visitOpen(opens, opensFlags, opensTo);
    }

    // Read the 'uses_count' and 'uses' fields.
    int usesCount = readUnsignedShort(currentOffset);
    currentOffset += 2;
    while (usesCount-- > 0) {
      moduleVisitor.visitUse(readClass(currentOffset, buffer));
      currentOffset += 2;
    }

    // Read the  'provides_count' and 'provides' fields.
    int providesCount = readUnsignedShort(currentOffset);
    currentOffset += 2;
    while (providesCount-- > 0) {
      // Read the provides_index, provides_with_count and provides_with_index fields and visit them.
      String provides = readClass(currentOffset, buffer);
      int providesWithCount = readUnsignedShort(currentOffset + 2);
      currentOffset += 4;
      String[] providesWith = new String[providesWithCount];
      for (int i = 0; i < providesWithCount; ++i) {
        providesWith[i] = readClass(currentOffset, buffer);
        currentOffset += 2;
      }
      moduleVisitor.visitProvide(provides, providesWith);
    }

    // Visit the end of the module attributes.
    moduleVisitor.visitEnd();
  }
Reads the Module, ModulePackages and ModuleMainClass attributes and visit them.

@param classVisitor the current class visitor
@param context information about the class being parsed.
@param moduleOffset the offset of the Module attribute (excluding the attribute_info's
attribute_name_index and attribute_length fields).
@param modulePackagesOffset the offset of the ModulePackages attribute (excluding the
attribute_info's attribute_name_index and attribute_length fields), or 0.
@param moduleMainClass the string corresponding to the ModuleMainClass attribute, or null.