// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

// Autogenerated by jnigen. DO NOT EDIT!

// ignore_for_file: annotate_overrides
// ignore_for_file: camel_case_extensions
// ignore_for_file: camel_case_types
// ignore_for_file: constant_identifier_names
// ignore_for_file: doc_directive_unknown
// ignore_for_file: file_names
// ignore_for_file: lines_longer_than_80_chars
// ignore_for_file: no_leading_underscores_for_local_identifiers
// ignore_for_file: non_constant_identifier_names
// ignore_for_file: overridden_fields
// ignore_for_file: unnecessary_cast
// ignore_for_file: unused_element
// ignore_for_file: unused_field
// ignore_for_file: unused_import
// ignore_for_file: unused_local_variable
// ignore_for_file: unused_shown_name
// ignore_for_file: use_super_parameters

import "dart:isolate" show ReceivePort;
import "dart:ffi" as ffi;
import "package:jni/internal_helpers_for_jnigen.dart";
import "package:jni/jni.dart" as jni;

// Auto-generated initialization code.

final ffi.Pointer<T> Function<T extends ffi.NativeType>(String sym) jniLookup =
    ProtectedJniExtensions.initGeneratedLibrary("simple_package");

/// from: com.github.dart_lang.jnigen.simple_package.Example$Nested$NestedTwice
class Example_Nested_NestedTwice extends jni.JObject {
  @override
  late final jni.JObjType<Example_Nested_NestedTwice> $type = type;

  Example_Nested_NestedTwice.fromReference(
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// The type which includes information such as the signature of this class.
  static const type = $Example_Nested_NestedTwiceType();
  static final _get_ZERO =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "get_Example_Nested_NestedTwice__ZERO")
          .asFunction<jni.JniResult Function()>();

  static final _set_ZERO =
      jniLookup<ffi.NativeFunction<jni.JniResult Function(ffi.Int32)>>(
              "set_Example_Nested_NestedTwice__ZERO")
          .asFunction<jni.JniResult Function(int)>();

  /// from: static public int ZERO
  static int get ZERO => _get_ZERO().integer;

  /// from: static public int ZERO
  static set ZERO(int value) => _set_ZERO(value).check();

  static final _new0 = jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
          "Example_Nested_NestedTwice__new0")
      .asFunction<jni.JniResult Function()>();

  /// from: public void <init>()
  /// The returned object must be released after use, by calling the [release] method.
  factory Example_Nested_NestedTwice() {
    return Example_Nested_NestedTwice.fromReference(_new0().reference);
  }
}

final class $Example_Nested_NestedTwiceType
    extends jni.JObjType<Example_Nested_NestedTwice> {
  const $Example_Nested_NestedTwiceType();

  @override
  String get signature =>
      r"Lcom/github/dart_lang/jnigen/simple_package/Example$Nested$NestedTwice;";

  @override
  Example_Nested_NestedTwice fromReference(jni.JReference reference) =>
      Example_Nested_NestedTwice.fromReference(reference);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode => ($Example_Nested_NestedTwiceType).hashCode;

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($Example_Nested_NestedTwiceType) &&
        other is $Example_Nested_NestedTwiceType;
  }
}

/// from: com.github.dart_lang.jnigen.simple_package.Example$Nested
class Example_Nested extends jni.JObject {
  @override
  late final jni.JObjType<Example_Nested> $type = type;

  Example_Nested.fromReference(
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// The type which includes information such as the signature of this class.
  static const type = $Example_NestedType();
  static final _new0 =
      jniLookup<ffi.NativeFunction<jni.JniResult Function(ffi.Uint8)>>(
              "Example_Nested__new0")
          .asFunction<jni.JniResult Function(int)>();

  /// from: public void <init>(boolean value)
  /// The returned object must be released after use, by calling the [release] method.
  factory Example_Nested(
    bool value,
  ) {
    return Example_Nested.fromReference(_new0(value ? 1 : 0).reference);
  }

  static final _usesAnonymousInnerClass = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("Example_Nested__usesAnonymousInnerClass")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public void usesAnonymousInnerClass()
  void usesAnonymousInnerClass() {
    _usesAnonymousInnerClass(reference.pointer).check();
  }

  static final _getValue = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("Example_Nested__getValue")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public boolean getValue()
  bool getValue() {
    return _getValue(reference.pointer).boolean;
  }

  static final _setValue = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Uint8)>>("Example_Nested__setValue")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();

  /// from: public void setValue(boolean value)
  void setValue(
    bool value,
  ) {
    _setValue(reference.pointer, value ? 1 : 0).check();
  }
}

final class $Example_NestedType extends jni.JObjType<Example_Nested> {
  const $Example_NestedType();

  @override
  String get signature =>
      r"Lcom/github/dart_lang/jnigen/simple_package/Example$Nested;";

  @override
  Example_Nested fromReference(jni.JReference reference) =>
      Example_Nested.fromReference(reference);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode => ($Example_NestedType).hashCode;

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($Example_NestedType) &&
        other is $Example_NestedType;
  }
}

/// from: com.github.dart_lang.jnigen.simple_package.Example$NonStaticNested
class Example_NonStaticNested extends jni.JObject {
  @override
  late final jni.JObjType<Example_NonStaticNested> $type = type;

  Example_NonStaticNested.fromReference(
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// The type which includes information such as the signature of this class.
  static const type = $Example_NonStaticNestedType();
  static final _get_ok = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                jni.JObjectPtr,
              )>>("get_Example_NonStaticNested__ok")
      .asFunction<
          jni.JniResult Function(
            jni.JObjectPtr,
          )>();

  static final _set_ok = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(jni.JObjectPtr,
                  ffi.Uint8)>>("set_Example_NonStaticNested__ok")
      .asFunction<jni.JniResult Function(jni.JObjectPtr, int)>();

  /// from: public boolean ok
  bool get ok => _get_ok(reference.pointer).boolean;

  /// from: public boolean ok
  set ok(bool value) => _set_ok(reference.pointer, value ? 1 : 0).check();

  static final _new0 = jniLookup<
              ffi
              .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
          "Example_NonStaticNested__new0")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();

  /// from: public void <init>(com.github.dart_lang.jnigen.simple_package.Example $parent)
  /// The returned object must be released after use, by calling the [release] method.
  factory Example_NonStaticNested(
    Example $parent,
  ) {
    return Example_NonStaticNested.fromReference(
        _new0($parent.reference.pointer).reference);
  }
}

final class $Example_NonStaticNestedType
    extends jni.JObjType<Example_NonStaticNested> {
  const $Example_NonStaticNestedType();

  @override
  String get signature =>
      r"Lcom/github/dart_lang/jnigen/simple_package/Example$NonStaticNested;";

  @override
  Example_NonStaticNested fromReference(jni.JReference reference) =>
      Example_NonStaticNested.fromReference(reference);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode => ($Example_NonStaticNestedType).hashCode;

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($Example_NonStaticNestedType) &&
        other is $Example_NonStaticNestedType;
  }
}

/// from: com.github.dart_lang.jnigen.simple_package.Example
class Example extends jni.JObject {
  @override
  late final jni.JObjType<Example> $type = type;

  Example.fromReference(
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// The type which includes information such as the signature of this class.
  static const type = $ExampleType();

  /// from: static public final int ON
  static const ON = 1;

  /// from: static public final int OFF
  static const OFF = 0;

  /// from: static public final double PI
  static const PI = 3.14159;

  /// from: static public final char SEMICOLON
  static const SEMICOLON = 59;
  static final _get_SEMICOLON_STRING =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "get_Example__SEMICOLON_STRING")
          .asFunction<jni.JniResult Function()>();

  /// from: static public final java.lang.String SEMICOLON_STRING
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JString get SEMICOLON_STRING =>
      _get_SEMICOLON_STRING().object(const jni.JStringType());

  static final _get_unusedRandom =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "get_Example__unusedRandom")
          .asFunction<jni.JniResult Function()>();

  /// from: static public final java.util.Random unusedRandom
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JObject get unusedRandom =>
      _get_unusedRandom().object(const jni.JObjectType());

  static final _get_protectedField = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                jni.JObjectPtr,
              )>>("get_Example__protectedField")
      .asFunction<
          jni.JniResult Function(
            jni.JObjectPtr,
          )>();

  static final _set_protectedField = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(jni.JObjectPtr,
                  ffi.Pointer<ffi.Void>)>>("set_Example__protectedField")
      .asFunction<
          jni.JniResult Function(jni.JObjectPtr, ffi.Pointer<ffi.Void>)>();

  /// from: protected java.util.Random protectedField
  /// The returned object must be released after use, by calling the [release] method.
  jni.JObject get protectedField =>
      _get_protectedField(reference.pointer).object(const jni.JObjectType());

  /// from: protected java.util.Random protectedField
  /// The returned object must be released after use, by calling the [release] method.
  set protectedField(jni.JObject value) =>
      _set_protectedField(reference.pointer, value.reference.pointer).check();

  static final _getAmount =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "Example__getAmount")
          .asFunction<jni.JniResult Function()>();

  /// from: static public int getAmount()
  static int getAmount() {
    return _getAmount().integer;
  }

  static final _getPi =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>("Example__getPi")
          .asFunction<jni.JniResult Function()>();

  /// from: static public double getPi()
  static double getPi() {
    return _getPi().doubleFloat;
  }

  static final _getAsterisk =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "Example__getAsterisk")
          .asFunction<jni.JniResult Function()>();

  /// from: static public char getAsterisk()
  static int getAsterisk() {
    return _getAsterisk().char;
  }

  static final _getName =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "Example__getName")
          .asFunction<jni.JniResult Function()>();

  /// from: static public java.lang.String getName()
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JString getName() {
    return _getName().object(const jni.JStringType());
  }

  static final _getNestedInstance =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "Example__getNestedInstance")
          .asFunction<jni.JniResult Function()>();

  /// from: static public com.github.dart_lang.jnigen.simple_package.Example.Nested getNestedInstance()
  /// The returned object must be released after use, by calling the [release] method.
  static Example_Nested getNestedInstance() {
    return _getNestedInstance().object(const $Example_NestedType());
  }

  static final _setAmount =
      jniLookup<ffi.NativeFunction<jni.JniResult Function(ffi.Int32)>>(
              "Example__setAmount")
          .asFunction<jni.JniResult Function(int)>();

  /// from: static public void setAmount(int newAmount)
  static void setAmount(
    int newAmount,
  ) {
    _setAmount(newAmount).check();
  }

  static final _setName = jniLookup<
              ffi
              .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
          "Example__setName")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();

  /// from: static public void setName(java.lang.String newName)
  static void setName(
    jni.JString newName,
  ) {
    _setName(newName.reference.pointer).check();
  }

  static final _setNestedInstance = jniLookup<
              ffi
              .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
          "Example__setNestedInstance")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();

  /// from: static public void setNestedInstance(com.github.dart_lang.jnigen.simple_package.Example.Nested newNested)
  static void setNestedInstance(
    Example_Nested newNested,
  ) {
    _setNestedInstance(newNested.reference.pointer).check();
  }

  static final _max4 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Int32, ffi.Int32, ffi.Int32, ffi.Int32)>>("Example__max4")
      .asFunction<jni.JniResult Function(int, int, int, int)>();

  /// from: static public int max4(int a, int b, int c, int d)
  static int max4(
    int a,
    int b,
    int c,
    int d,
  ) {
    return _max4(a, b, c, d).integer;
  }

  static final _max8 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Int32, ffi.Int32, ffi.Int32, ffi.Int32,
                  ffi.Int32, ffi.Int32, ffi.Int32, ffi.Int32)>>("Example__max8")
      .asFunction<
          jni.JniResult Function(int, int, int, int, int, int, int, int)>();

  /// from: static public int max8(int a, int b, int c, int d, int e, int f, int g, int h)
  static int max8(
    int a,
    int b,
    int c,
    int d,
    int e,
    int f,
    int g,
    int h,
  ) {
    return _max8(a, b, c, d, e, f, g, h).integer;
  }

  static final _getNumber = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("Example__getNumber")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public int getNumber()
  int getNumber() {
    return _getNumber(reference.pointer).integer;
  }

  static final _setNumber = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>, ffi.Int32)>>("Example__setNumber")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();

  /// from: public void setNumber(int number)
  void setNumber(
    int number,
  ) {
    _setNumber(reference.pointer, number).check();
  }

  static final _getIsUp = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("Example__getIsUp")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public boolean getIsUp()
  bool getIsUp() {
    return _getIsUp(reference.pointer).boolean;
  }

  static final _setUp = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>, ffi.Uint8)>>("Example__setUp")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();

  /// from: public void setUp(boolean isUp)
  void setUp(
    bool isUp,
  ) {
    _setUp(reference.pointer, isUp ? 1 : 0).check();
  }

  static final _getCodename = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("Example__getCodename")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public java.lang.String getCodename()
  /// The returned object must be released after use, by calling the [release] method.
  jni.JString getCodename() {
    return _getCodename(reference.pointer).object(const jni.JStringType());
  }

  static final _setCodename = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("Example__setCodename")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public void setCodename(java.lang.String codename)
  void setCodename(
    jni.JString codename,
  ) {
    _setCodename(reference.pointer, codename.reference.pointer).check();
  }

  static final _getRandom = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("Example__getRandom")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public java.util.Random getRandom()
  /// The returned object must be released after use, by calling the [release] method.
  jni.JObject getRandom() {
    return _getRandom(reference.pointer).object(const jni.JObjectType());
  }

  static final _setRandom = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("Example__setRandom")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public void setRandom(java.util.Random random)
  void setRandom(
    jni.JObject random,
  ) {
    _setRandom(reference.pointer, random.reference.pointer).check();
  }

  static final _getRandomLong = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("Example__getRandomLong")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public long getRandomLong()
  int getRandomLong() {
    return _getRandomLong(reference.pointer).long;
  }

  static final _add4Longs = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Int64,
                  ffi.Int64, ffi.Int64, ffi.Int64)>>("Example__add4Longs")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, int, int, int, int)>();

  /// from: public long add4Longs(long a, long b, long c, long d)
  int add4Longs(
    int a,
    int b,
    int c,
    int d,
  ) {
    return _add4Longs(reference.pointer, a, b, c, d).long;
  }

  static final _add8Longs = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  ffi.Int64,
                  ffi.Int64,
                  ffi.Int64,
                  ffi.Int64,
                  ffi.Int64,
                  ffi.Int64,
                  ffi.Int64,
                  ffi.Int64)>>("Example__add8Longs")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, int, int, int, int, int, int, int, int)>();

  /// from: public long add8Longs(long a, long b, long c, long d, long e, long f, long g, long h)
  int add8Longs(
    int a,
    int b,
    int c,
    int d,
    int e,
    int f,
    int g,
    int h,
  ) {
    return _add8Longs(reference.pointer, a, b, c, d, e, f, g, h).long;
  }

  static final _getRandomNumericString = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("Example__getRandomNumericString")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public java.lang.String getRandomNumericString(java.util.Random random)
  /// The returned object must be released after use, by calling the [release] method.
  jni.JString getRandomNumericString(
    jni.JObject random,
  ) {
    return _getRandomNumericString(reference.pointer, random.reference.pointer)
        .object(const jni.JStringType());
  }

  static final _protectedMethod = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("Example__protectedMethod")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>)>();

  /// from: protected void protectedMethod(java.lang.String a, java.lang.String b)
  void protectedMethod(
    jni.JString a,
    jni.JString b,
  ) {
    _protectedMethod(
            reference.pointer, a.reference.pointer, b.reference.pointer)
        .check();
  }

  static final _finalMethod = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("Example__finalMethod")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public final void finalMethod()
  void finalMethod() {
    _finalMethod(reference.pointer).check();
  }

  static final _getList = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("Example__getList")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public java.util.List<java.lang.String> getList()
  /// The returned object must be released after use, by calling the [release] method.
  jni.JList<jni.JString> getList() {
    return _getList(reference.pointer)
        .object(const jni.JListType(jni.JStringType()));
  }

  static final _joinStrings = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("Example__joinStrings")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>)>();

  /// from: public java.lang.String joinStrings(java.util.List<java.lang.String> values, java.lang.String delim)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Joins the strings in the list using the given delimiter.
  jni.JString joinStrings(
    jni.JList<jni.JString> values,
    jni.JString delim,
  ) {
    return _joinStrings(reference.pointer, values.reference.pointer,
            delim.reference.pointer)
        .object(const jni.JStringType());
  }

  static final _methodWithSeveralParams = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  ffi.Uint16,
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("Example__methodWithSeveralParams")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>,
              int,
              ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>)>();

  /// from: public void methodWithSeveralParams(char ch, java.lang.String s, int[] a, T t, java.util.List<T> lt, java.util.Map<java.lang.String,? extends java.lang.CharSequence> wm)
  void methodWithSeveralParams<$T extends jni.JObject>(
    int ch,
    jni.JString s,
    jni.JArray<jni.jint> a,
    $T t,
    jni.JList<$T> lt,
    jni.JMap<jni.JString, jni.JObject> wm, {
    jni.JObjType<$T>? T,
  }) {
    T ??= jni.lowestCommonSuperType([
      (lt.$type as jni.JListType).E,
      t.$type,
    ]) as jni.JObjType<$T>;
    _methodWithSeveralParams(
            reference.pointer,
            ch,
            s.reference.pointer,
            a.reference.pointer,
            t.reference.pointer,
            lt.reference.pointer,
            wm.reference.pointer)
        .check();
  }

  static final _new0 =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>("Example__new0")
          .asFunction<jni.JniResult Function()>();

  /// from: public void <init>()
  /// The returned object must be released after use, by calling the [release] method.
  factory Example() {
    return Example.fromReference(_new0().reference);
  }

  static final _new1 =
      jniLookup<ffi.NativeFunction<jni.JniResult Function(ffi.Int32)>>(
              "Example__new1")
          .asFunction<jni.JniResult Function(int)>();

  /// from: public void <init>(int number)
  /// The returned object must be released after use, by calling the [release] method.
  factory Example.new1(
    int number,
  ) {
    return Example.fromReference(_new1(number).reference);
  }

  static final _new2 = jniLookup<
              ffi.NativeFunction<jni.JniResult Function(ffi.Int32, ffi.Uint8)>>(
          "Example__new2")
      .asFunction<jni.JniResult Function(int, int)>();

  /// from: public void <init>(int number, boolean isUp)
  /// The returned object must be released after use, by calling the [release] method.
  factory Example.new2(
    int number,
    bool isUp,
  ) {
    return Example.fromReference(_new2(number, isUp ? 1 : 0).reference);
  }

  static final _new3 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Int32, ffi.Uint8,
                  ffi.Pointer<ffi.Void>)>>("Example__new3")
      .asFunction<jni.JniResult Function(int, int, ffi.Pointer<ffi.Void>)>();

  /// from: public void <init>(int number, boolean isUp, java.lang.String codename)
  /// The returned object must be released after use, by calling the [release] method.
  factory Example.new3(
    int number,
    bool isUp,
    jni.JString codename,
  ) {
    return Example.fromReference(
        _new3(number, isUp ? 1 : 0, codename.reference.pointer).reference);
  }

  static final _new4 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Int32, ffi.Int32, ffi.Int32, ffi.Int32,
                  ffi.Int32, ffi.Int32, ffi.Int32, ffi.Int32)>>("Example__new4")
      .asFunction<
          jni.JniResult Function(int, int, int, int, int, int, int, int)>();

  /// from: public void <init>(int a, int b, int c, int d, int e, int f, int g, int h)
  /// The returned object must be released after use, by calling the [release] method.
  factory Example.new4(
    int a,
    int b,
    int c,
    int d,
    int e,
    int f,
    int g,
    int h,
  ) {
    return Example.fromReference(_new4(a, b, c, d, e, f, g, h).reference);
  }

  static final _whichExample = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("Example__whichExample")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public int whichExample()
  int whichExample() {
    return _whichExample(reference.pointer).integer;
  }

  static final _addInts = jniLookup<
              ffi.NativeFunction<jni.JniResult Function(ffi.Int32, ffi.Int32)>>(
          "Example__addInts")
      .asFunction<jni.JniResult Function(int, int)>();

  /// from: static public int addInts(int a, int b)
  static int addInts(
    int a,
    int b,
  ) {
    return _addInts(a, b).integer;
  }

  static final _getArr =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>("Example__getArr")
          .asFunction<jni.JniResult Function()>();

  /// from: static public int[] getArr()
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JArray<jni.jint> getArr() {
    return _getArr().object(const jni.JArrayType(jni.jintType()));
  }

  static final _addAll = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>)>>("Example__addAll")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();

  /// from: static public int addAll(int[] arr)
  static int addAll(
    jni.JArray<jni.jint> arr,
  ) {
    return _addAll(arr.reference.pointer).integer;
  }

  static final _getSelf = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("Example__getSelf")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public com.github.dart_lang.jnigen.simple_package.Example getSelf()
  /// The returned object must be released after use, by calling the [release] method.
  Example getSelf() {
    return _getSelf(reference.pointer).object(const $ExampleType());
  }

  static final _throwException =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "Example__throwException")
          .asFunction<jni.JniResult Function()>();

  /// from: static public void throwException()
  static void throwException() {
    _throwException().check();
  }

  static final _overloaded = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("Example__overloaded")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public void overloaded()
  void overloaded() {
    _overloaded(reference.pointer).check();
  }

  static final _overloaded1 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Int32,
                  ffi.Pointer<ffi.Void>)>>("Example__overloaded1")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, int, ffi.Pointer<ffi.Void>)>();

  /// from: public void overloaded(int a, java.lang.String b)
  void overloaded1(
    int a,
    jni.JString b,
  ) {
    _overloaded1(reference.pointer, a, b.reference.pointer).check();
  }

  static final _overloaded2 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>, ffi.Int32)>>("Example__overloaded2")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();

  /// from: public void overloaded(int a)
  void overloaded2(
    int a,
  ) {
    _overloaded2(reference.pointer, a).check();
  }

  static final _overloaded3 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("Example__overloaded3")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>)>();

  /// from: public void overloaded(java.util.List<java.lang.Integer> a, java.lang.String b)
  void overloaded3(
    jni.JList<jni.JInteger> a,
    jni.JString b,
  ) {
    _overloaded3(reference.pointer, a.reference.pointer, b.reference.pointer)
        .check();
  }

  static final _overloaded4 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("Example__overloaded4")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public void overloaded(java.util.List<java.lang.Integer> a)
  void overloaded4(
    jni.JList<jni.JInteger> a,
  ) {
    _overloaded4(reference.pointer, a.reference.pointer).check();
  }
}

final class $ExampleType extends jni.JObjType<Example> {
  const $ExampleType();

  @override
  String get signature =>
      r"Lcom/github/dart_lang/jnigen/simple_package/Example;";

  @override
  Example fromReference(jni.JReference reference) =>
      Example.fromReference(reference);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode => ($ExampleType).hashCode;

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($ExampleType) && other is $ExampleType;
  }
}

/// from: com.github.dart_lang.jnigen.pkg2.C2
class C2 extends jni.JObject {
  @override
  late final jni.JObjType<C2> $type = type;

  C2.fromReference(
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// The type which includes information such as the signature of this class.
  static const type = $C2Type();
  static final _get_CONSTANT =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "get_C2__CONSTANT")
          .asFunction<jni.JniResult Function()>();

  static final _set_CONSTANT =
      jniLookup<ffi.NativeFunction<jni.JniResult Function(ffi.Int32)>>(
              "set_C2__CONSTANT")
          .asFunction<jni.JniResult Function(int)>();

  /// from: static public int CONSTANT
  static int get CONSTANT => _get_CONSTANT().integer;

  /// from: static public int CONSTANT
  static set CONSTANT(int value) => _set_CONSTANT(value).check();

  static final _new0 =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>("C2__new0")
          .asFunction<jni.JniResult Function()>();

  /// from: public void <init>()
  /// The returned object must be released after use, by calling the [release] method.
  factory C2() {
    return C2.fromReference(_new0().reference);
  }
}

final class $C2Type extends jni.JObjType<C2> {
  const $C2Type();

  @override
  String get signature => r"Lcom/github/dart_lang/jnigen/pkg2/C2;";

  @override
  C2 fromReference(jni.JReference reference) => C2.fromReference(reference);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode => ($C2Type).hashCode;

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($C2Type) && other is $C2Type;
  }
}

/// from: com.github.dart_lang.jnigen.pkg2.Example
class Example1 extends jni.JObject {
  @override
  late final jni.JObjType<Example1> $type = type;

  Example1.fromReference(
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// The type which includes information such as the signature of this class.
  static const type = $Example1Type();
  static final _new0 =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>("Example1__new0")
          .asFunction<jni.JniResult Function()>();

  /// from: public void <init>()
  /// The returned object must be released after use, by calling the [release] method.
  factory Example1() {
    return Example1.fromReference(_new0().reference);
  }

  static final _whichExample = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("Example1__whichExample")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public int whichExample()
  int whichExample() {
    return _whichExample(reference.pointer).integer;
  }
}

final class $Example1Type extends jni.JObjType<Example1> {
  const $Example1Type();

  @override
  String get signature => r"Lcom/github/dart_lang/jnigen/pkg2/Example;";

  @override
  Example1 fromReference(jni.JReference reference) =>
      Example1.fromReference(reference);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode => ($Example1Type).hashCode;

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($Example1Type) && other is $Example1Type;
  }
}

/// from: com.github.dart_lang.jnigen.generics.GrandParent$Parent$Child
class GrandParent_Parent_Child<$T extends jni.JObject, $S extends jni.JObject,
    $U extends jni.JObject> extends jni.JObject {
  @override
  late final jni.JObjType<GrandParent_Parent_Child<$T, $S, $U>> $type =
      type(T, S, U);

  final jni.JObjType<$T> T;
  final jni.JObjType<$S> S;
  final jni.JObjType<$U> U;

  GrandParent_Parent_Child.fromReference(
    this.T,
    this.S,
    this.U,
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// The type which includes information such as the signature of this class.
  static $GrandParent_Parent_ChildType<$T, $S, $U> type<$T extends jni.JObject,
      $S extends jni.JObject, $U extends jni.JObject>(
    jni.JObjType<$T> T,
    jni.JObjType<$S> S,
    jni.JObjType<$U> U,
  ) {
    return $GrandParent_Parent_ChildType(
      T,
      S,
      U,
    );
  }

  static final _get_grandParentValue = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                jni.JObjectPtr,
              )>>("get_GrandParent_Parent_Child__grandParentValue")
      .asFunction<
          jni.JniResult Function(
            jni.JObjectPtr,
          )>();

  static final _set_grandParentValue = jniLookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      jni.JObjectPtr, ffi.Pointer<ffi.Void>)>>(
          "set_GrandParent_Parent_Child__grandParentValue")
      .asFunction<
          jni.JniResult Function(jni.JObjectPtr, ffi.Pointer<ffi.Void>)>();

  /// from: public T grandParentValue
  /// The returned object must be released after use, by calling the [release] method.
  $T get grandParentValue => _get_grandParentValue(reference.pointer).object(T);

  /// from: public T grandParentValue
  /// The returned object must be released after use, by calling the [release] method.
  set grandParentValue($T value) =>
      _set_grandParentValue(reference.pointer, value.reference.pointer).check();

  static final _get_parentValue = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                jni.JObjectPtr,
              )>>("get_GrandParent_Parent_Child__parentValue")
      .asFunction<
          jni.JniResult Function(
            jni.JObjectPtr,
          )>();

  static final _set_parentValue = jniLookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      jni.JObjectPtr, ffi.Pointer<ffi.Void>)>>(
          "set_GrandParent_Parent_Child__parentValue")
      .asFunction<
          jni.JniResult Function(jni.JObjectPtr, ffi.Pointer<ffi.Void>)>();

  /// from: public S parentValue
  /// The returned object must be released after use, by calling the [release] method.
  $S get parentValue => _get_parentValue(reference.pointer).object(S);

  /// from: public S parentValue
  /// The returned object must be released after use, by calling the [release] method.
  set parentValue($S value) =>
      _set_parentValue(reference.pointer, value.reference.pointer).check();

  static final _get_value = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                jni.JObjectPtr,
              )>>("get_GrandParent_Parent_Child__value")
      .asFunction<
          jni.JniResult Function(
            jni.JObjectPtr,
          )>();

  static final _set_value = jniLookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      jni.JObjectPtr, ffi.Pointer<ffi.Void>)>>(
          "set_GrandParent_Parent_Child__value")
      .asFunction<
          jni.JniResult Function(jni.JObjectPtr, ffi.Pointer<ffi.Void>)>();

  /// from: public U value
  /// The returned object must be released after use, by calling the [release] method.
  $U get value => _get_value(reference.pointer).object(U);

  /// from: public U value
  /// The returned object must be released after use, by calling the [release] method.
  set value($U value) =>
      _set_value(reference.pointer, value.reference.pointer).check();

  static final _new0 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("GrandParent_Parent_Child__new0")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public void <init>(com.github.dart_lang.jnigen.generics.GrandParent$Parent $parent, U newValue)
  /// The returned object must be released after use, by calling the [release] method.
  factory GrandParent_Parent_Child(
    GrandParent_Parent<$T, $S> $parent,
    $U newValue, {
    jni.JObjType<$T>? T,
    jni.JObjType<$S>? S,
    jni.JObjType<$U>? U,
  }) {
    T ??= jni.lowestCommonSuperType([
      ($parent.$type as $GrandParent_ParentType).T,
    ]) as jni.JObjType<$T>;
    S ??= jni.lowestCommonSuperType([
      ($parent.$type as $GrandParent_ParentType).S,
    ]) as jni.JObjType<$S>;
    U ??= jni.lowestCommonSuperType([
      newValue.$type,
    ]) as jni.JObjType<$U>;
    return GrandParent_Parent_Child.fromReference(T, S, U,
        _new0($parent.reference.pointer, newValue.reference.pointer).reference);
  }
}

final class $GrandParent_Parent_ChildType<$T extends jni.JObject,
        $S extends jni.JObject, $U extends jni.JObject>
    extends jni.JObjType<GrandParent_Parent_Child<$T, $S, $U>> {
  final jni.JObjType<$T> T;
  final jni.JObjType<$S> S;
  final jni.JObjType<$U> U;

  const $GrandParent_Parent_ChildType(
    this.T,
    this.S,
    this.U,
  );

  @override
  String get signature =>
      r"Lcom/github/dart_lang/jnigen/generics/GrandParent$Parent$Child;";

  @override
  GrandParent_Parent_Child<$T, $S, $U> fromReference(
          jni.JReference reference) =>
      GrandParent_Parent_Child.fromReference(T, S, U, reference);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode => Object.hash($GrandParent_Parent_ChildType, T, S, U);

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($GrandParent_Parent_ChildType<$T, $S, $U>) &&
        other is $GrandParent_Parent_ChildType<$T, $S, $U> &&
        T == other.T &&
        S == other.S &&
        U == other.U;
  }
}

/// from: com.github.dart_lang.jnigen.generics.GrandParent$Parent
class GrandParent_Parent<$T extends jni.JObject, $S extends jni.JObject>
    extends jni.JObject {
  @override
  late final jni.JObjType<GrandParent_Parent<$T, $S>> $type = type(T, S);

  final jni.JObjType<$T> T;
  final jni.JObjType<$S> S;

  GrandParent_Parent.fromReference(
    this.T,
    this.S,
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// The type which includes information such as the signature of this class.
  static $GrandParent_ParentType<$T, $S>
      type<$T extends jni.JObject, $S extends jni.JObject>(
    jni.JObjType<$T> T,
    jni.JObjType<$S> S,
  ) {
    return $GrandParent_ParentType(
      T,
      S,
    );
  }

  static final _get_parentValue = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                jni.JObjectPtr,
              )>>("get_GrandParent_Parent__parentValue")
      .asFunction<
          jni.JniResult Function(
            jni.JObjectPtr,
          )>();

  static final _set_parentValue = jniLookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      jni.JObjectPtr, ffi.Pointer<ffi.Void>)>>(
          "set_GrandParent_Parent__parentValue")
      .asFunction<
          jni.JniResult Function(jni.JObjectPtr, ffi.Pointer<ffi.Void>)>();

  /// from: public T parentValue
  /// The returned object must be released after use, by calling the [release] method.
  $T get parentValue => _get_parentValue(reference.pointer).object(T);

  /// from: public T parentValue
  /// The returned object must be released after use, by calling the [release] method.
  set parentValue($T value) =>
      _set_parentValue(reference.pointer, value.reference.pointer).check();

  static final _get_value = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                jni.JObjectPtr,
              )>>("get_GrandParent_Parent__value")
      .asFunction<
          jni.JniResult Function(
            jni.JObjectPtr,
          )>();

  static final _set_value = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(jni.JObjectPtr,
                  ffi.Pointer<ffi.Void>)>>("set_GrandParent_Parent__value")
      .asFunction<
          jni.JniResult Function(jni.JObjectPtr, ffi.Pointer<ffi.Void>)>();

  /// from: public S value
  /// The returned object must be released after use, by calling the [release] method.
  $S get value => _get_value(reference.pointer).object(S);

  /// from: public S value
  /// The returned object must be released after use, by calling the [release] method.
  set value($S value) =>
      _set_value(reference.pointer, value.reference.pointer).check();

  static final _new0 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("GrandParent_Parent__new0")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public void <init>(com.github.dart_lang.jnigen.generics.GrandParent $parent, S newValue)
  /// The returned object must be released after use, by calling the [release] method.
  factory GrandParent_Parent(
    GrandParent<$T> $parent,
    $S newValue, {
    jni.JObjType<$T>? T,
    jni.JObjType<$S>? S,
  }) {
    T ??= jni.lowestCommonSuperType([
      ($parent.$type as $GrandParentType).T,
    ]) as jni.JObjType<$T>;
    S ??= jni.lowestCommonSuperType([
      newValue.$type,
    ]) as jni.JObjType<$S>;
    return GrandParent_Parent.fromReference(T, S,
        _new0($parent.reference.pointer, newValue.reference.pointer).reference);
  }
}

final class $GrandParent_ParentType<$T extends jni.JObject,
    $S extends jni.JObject> extends jni.JObjType<GrandParent_Parent<$T, $S>> {
  final jni.JObjType<$T> T;
  final jni.JObjType<$S> S;

  const $GrandParent_ParentType(
    this.T,
    this.S,
  );

  @override
  String get signature =>
      r"Lcom/github/dart_lang/jnigen/generics/GrandParent$Parent;";

  @override
  GrandParent_Parent<$T, $S> fromReference(jni.JReference reference) =>
      GrandParent_Parent.fromReference(T, S, reference);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode => Object.hash($GrandParent_ParentType, T, S);

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($GrandParent_ParentType<$T, $S>) &&
        other is $GrandParent_ParentType<$T, $S> &&
        T == other.T &&
        S == other.S;
  }
}

/// from: com.github.dart_lang.jnigen.generics.GrandParent$StaticParent$Child
class GrandParent_StaticParent_Child<$S extends jni.JObject,
    $U extends jni.JObject> extends jni.JObject {
  @override
  late final jni.JObjType<GrandParent_StaticParent_Child<$S, $U>> $type =
      type(S, U);

  final jni.JObjType<$S> S;
  final jni.JObjType<$U> U;

  GrandParent_StaticParent_Child.fromReference(
    this.S,
    this.U,
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// The type which includes information such as the signature of this class.
  static $GrandParent_StaticParent_ChildType<$S, $U>
      type<$S extends jni.JObject, $U extends jni.JObject>(
    jni.JObjType<$S> S,
    jni.JObjType<$U> U,
  ) {
    return $GrandParent_StaticParent_ChildType(
      S,
      U,
    );
  }

  static final _get_parentValue = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                jni.JObjectPtr,
              )>>("get_GrandParent_StaticParent_Child__parentValue")
      .asFunction<
          jni.JniResult Function(
            jni.JObjectPtr,
          )>();

  static final _set_parentValue = jniLookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      jni.JObjectPtr, ffi.Pointer<ffi.Void>)>>(
          "set_GrandParent_StaticParent_Child__parentValue")
      .asFunction<
          jni.JniResult Function(jni.JObjectPtr, ffi.Pointer<ffi.Void>)>();

  /// from: public S parentValue
  /// The returned object must be released after use, by calling the [release] method.
  $S get parentValue => _get_parentValue(reference.pointer).object(S);

  /// from: public S parentValue
  /// The returned object must be released after use, by calling the [release] method.
  set parentValue($S value) =>
      _set_parentValue(reference.pointer, value.reference.pointer).check();

  static final _get_value = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                jni.JObjectPtr,
              )>>("get_GrandParent_StaticParent_Child__value")
      .asFunction<
          jni.JniResult Function(
            jni.JObjectPtr,
          )>();

  static final _set_value = jniLookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      jni.JObjectPtr, ffi.Pointer<ffi.Void>)>>(
          "set_GrandParent_StaticParent_Child__value")
      .asFunction<
          jni.JniResult Function(jni.JObjectPtr, ffi.Pointer<ffi.Void>)>();

  /// from: public U value
  /// The returned object must be released after use, by calling the [release] method.
  $U get value => _get_value(reference.pointer).object(U);

  /// from: public U value
  /// The returned object must be released after use, by calling the [release] method.
  set value($U value) =>
      _set_value(reference.pointer, value.reference.pointer).check();

  static final _new0 = jniLookup<
              ffi.NativeFunction<
                  jni.JniResult Function(ffi.Pointer<ffi.Void>,
                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
          "GrandParent_StaticParent_Child__new0")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>)>();

  /// from: public void <init>(com.github.dart_lang.jnigen.generics.GrandParent$StaticParent $parent, S parentValue, U value)
  /// The returned object must be released after use, by calling the [release] method.
  factory GrandParent_StaticParent_Child(
    GrandParent_StaticParent<$S> $parent,
    $S parentValue,
    $U value, {
    jni.JObjType<$S>? S,
    jni.JObjType<$U>? U,
  }) {
    S ??= jni.lowestCommonSuperType([
      parentValue.$type,
      ($parent.$type as $GrandParent_StaticParentType).S,
    ]) as jni.JObjType<$S>;
    U ??= jni.lowestCommonSuperType([
      value.$type,
    ]) as jni.JObjType<$U>;
    return GrandParent_StaticParent_Child.fromReference(
        S,
        U,
        _new0($parent.reference.pointer, parentValue.reference.pointer,
                value.reference.pointer)
            .reference);
  }
}

final class $GrandParent_StaticParent_ChildType<$S extends jni.JObject,
        $U extends jni.JObject>
    extends jni.JObjType<GrandParent_StaticParent_Child<$S, $U>> {
  final jni.JObjType<$S> S;
  final jni.JObjType<$U> U;

  const $GrandParent_StaticParent_ChildType(
    this.S,
    this.U,
  );

  @override
  String get signature =>
      r"Lcom/github/dart_lang/jnigen/generics/GrandParent$StaticParent$Child;";

  @override
  GrandParent_StaticParent_Child<$S, $U> fromReference(
          jni.JReference reference) =>
      GrandParent_StaticParent_Child.fromReference(S, U, reference);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode => Object.hash($GrandParent_StaticParent_ChildType, S, U);

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($GrandParent_StaticParent_ChildType<$S, $U>) &&
        other is $GrandParent_StaticParent_ChildType<$S, $U> &&
        S == other.S &&
        U == other.U;
  }
}

/// from: com.github.dart_lang.jnigen.generics.GrandParent$StaticParent
class GrandParent_StaticParent<$S extends jni.JObject> extends jni.JObject {
  @override
  late final jni.JObjType<GrandParent_StaticParent<$S>> $type = type(S);

  final jni.JObjType<$S> S;

  GrandParent_StaticParent.fromReference(
    this.S,
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// The type which includes information such as the signature of this class.
  static $GrandParent_StaticParentType<$S> type<$S extends jni.JObject>(
    jni.JObjType<$S> S,
  ) {
    return $GrandParent_StaticParentType(
      S,
    );
  }

  static final _get_value = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                jni.JObjectPtr,
              )>>("get_GrandParent_StaticParent__value")
      .asFunction<
          jni.JniResult Function(
            jni.JObjectPtr,
          )>();

  static final _set_value = jniLookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      jni.JObjectPtr, ffi.Pointer<ffi.Void>)>>(
          "set_GrandParent_StaticParent__value")
      .asFunction<
          jni.JniResult Function(jni.JObjectPtr, ffi.Pointer<ffi.Void>)>();

  /// from: public S value
  /// The returned object must be released after use, by calling the [release] method.
  $S get value => _get_value(reference.pointer).object(S);

  /// from: public S value
  /// The returned object must be released after use, by calling the [release] method.
  set value($S value) =>
      _set_value(reference.pointer, value.reference.pointer).check();

  static final _new0 = jniLookup<
              ffi
              .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
          "GrandParent_StaticParent__new0")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();

  /// from: public void <init>(S value)
  /// The returned object must be released after use, by calling the [release] method.
  factory GrandParent_StaticParent(
    $S value, {
    jni.JObjType<$S>? S,
  }) {
    S ??= jni.lowestCommonSuperType([
      value.$type,
    ]) as jni.JObjType<$S>;
    return GrandParent_StaticParent.fromReference(
        S, _new0(value.reference.pointer).reference);
  }
}

final class $GrandParent_StaticParentType<$S extends jni.JObject>
    extends jni.JObjType<GrandParent_StaticParent<$S>> {
  final jni.JObjType<$S> S;

  const $GrandParent_StaticParentType(
    this.S,
  );

  @override
  String get signature =>
      r"Lcom/github/dart_lang/jnigen/generics/GrandParent$StaticParent;";

  @override
  GrandParent_StaticParent<$S> fromReference(jni.JReference reference) =>
      GrandParent_StaticParent.fromReference(S, reference);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode => Object.hash($GrandParent_StaticParentType, S);

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($GrandParent_StaticParentType<$S>) &&
        other is $GrandParent_StaticParentType<$S> &&
        S == other.S;
  }
}

/// from: com.github.dart_lang.jnigen.generics.GrandParent
class GrandParent<$T extends jni.JObject> extends jni.JObject {
  @override
  late final jni.JObjType<GrandParent<$T>> $type = type(T);

  final jni.JObjType<$T> T;

  GrandParent.fromReference(
    this.T,
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// The type which includes information such as the signature of this class.
  static $GrandParentType<$T> type<$T extends jni.JObject>(
    jni.JObjType<$T> T,
  ) {
    return $GrandParentType(
      T,
    );
  }

  static final _get_value = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                jni.JObjectPtr,
              )>>("get_GrandParent__value")
      .asFunction<
          jni.JniResult Function(
            jni.JObjectPtr,
          )>();

  static final _set_value = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(jni.JObjectPtr,
                  ffi.Pointer<ffi.Void>)>>("set_GrandParent__value")
      .asFunction<
          jni.JniResult Function(jni.JObjectPtr, ffi.Pointer<ffi.Void>)>();

  /// from: public T value
  /// The returned object must be released after use, by calling the [release] method.
  $T get value => _get_value(reference.pointer).object(T);

  /// from: public T value
  /// The returned object must be released after use, by calling the [release] method.
  set value($T value) =>
      _set_value(reference.pointer, value.reference.pointer).check();

  static final _new0 = jniLookup<
              ffi
              .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
          "GrandParent__new0")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();

  /// from: public void <init>(T value)
  /// The returned object must be released after use, by calling the [release] method.
  factory GrandParent(
    $T value, {
    jni.JObjType<$T>? T,
  }) {
    T ??= jni.lowestCommonSuperType([
      value.$type,
    ]) as jni.JObjType<$T>;
    return GrandParent.fromReference(
        T, _new0(value.reference.pointer).reference);
  }

  static final _stringParent = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("GrandParent__stringParent")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public com.github.dart_lang.jnigen.generics.GrandParent<T>.Parent<java.lang.String> stringParent()
  /// The returned object must be released after use, by calling the [release] method.
  GrandParent_Parent<jni.JObject, jni.JString> stringParent() {
    return _stringParent(reference.pointer).object(
        const $GrandParent_ParentType(jni.JObjectType(), jni.JStringType()));
  }

  static final _varParent = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("GrandParent__varParent")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public com.github.dart_lang.jnigen.generics.GrandParent<T>.Parent<S> varParent(S nestedValue)
  /// The returned object must be released after use, by calling the [release] method.
  GrandParent_Parent<jni.JObject, $S> varParent<$S extends jni.JObject>(
    $S nestedValue, {
    jni.JObjType<$S>? S,
  }) {
    S ??= jni.lowestCommonSuperType([
      nestedValue.$type,
    ]) as jni.JObjType<$S>;
    return _varParent(reference.pointer, nestedValue.reference.pointer)
        .object($GrandParent_ParentType(const jni.JObjectType(), S));
  }

  static final _stringStaticParent =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "GrandParent__stringStaticParent")
          .asFunction<jni.JniResult Function()>();

  /// from: static public com.github.dart_lang.jnigen.generics.GrandParent.StaticParent<java.lang.String> stringStaticParent()
  /// The returned object must be released after use, by calling the [release] method.
  static GrandParent_StaticParent<jni.JString> stringStaticParent() {
    return _stringStaticParent()
        .object(const $GrandParent_StaticParentType(jni.JStringType()));
  }

  static final _varStaticParent = jniLookup<
              ffi
              .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
          "GrandParent__varStaticParent")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();

  /// from: static public com.github.dart_lang.jnigen.generics.GrandParent.StaticParent<S> varStaticParent(S value)
  /// The returned object must be released after use, by calling the [release] method.
  static GrandParent_StaticParent<$S> varStaticParent<$S extends jni.JObject>(
    $S value, {
    jni.JObjType<$S>? S,
  }) {
    S ??= jni.lowestCommonSuperType([
      value.$type,
    ]) as jni.JObjType<$S>;
    return _varStaticParent(value.reference.pointer)
        .object($GrandParent_StaticParentType(S));
  }

  static final _staticParentWithSameType = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("GrandParent__staticParentWithSameType")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public com.github.dart_lang.jnigen.generics.GrandParent.StaticParent<T> staticParentWithSameType()
  /// The returned object must be released after use, by calling the [release] method.
  GrandParent_StaticParent<$T> staticParentWithSameType() {
    return _staticParentWithSameType(reference.pointer)
        .object($GrandParent_StaticParentType(T));
  }
}

final class $GrandParentType<$T extends jni.JObject>
    extends jni.JObjType<GrandParent<$T>> {
  final jni.JObjType<$T> T;

  const $GrandParentType(
    this.T,
  );

  @override
  String get signature => r"Lcom/github/dart_lang/jnigen/generics/GrandParent;";

  @override
  GrandParent<$T> fromReference(jni.JReference reference) =>
      GrandParent.fromReference(T, reference);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode => Object.hash($GrandParentType, T);

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($GrandParentType<$T>) &&
        other is $GrandParentType<$T> &&
        T == other.T;
  }
}

/// from: com.github.dart_lang.jnigen.generics.MyMap$MyEntry
class MyMap_MyEntry<$K extends jni.JObject, $V extends jni.JObject>
    extends jni.JObject {
  @override
  late final jni.JObjType<MyMap_MyEntry<$K, $V>> $type = type(K, V);

  final jni.JObjType<$K> K;
  final jni.JObjType<$V> V;

  MyMap_MyEntry.fromReference(
    this.K,
    this.V,
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// The type which includes information such as the signature of this class.
  static $MyMap_MyEntryType<$K, $V>
      type<$K extends jni.JObject, $V extends jni.JObject>(
    jni.JObjType<$K> K,
    jni.JObjType<$V> V,
  ) {
    return $MyMap_MyEntryType(
      K,
      V,
    );
  }

  static final _get_key = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                jni.JObjectPtr,
              )>>("get_MyMap_MyEntry__key")
      .asFunction<
          jni.JniResult Function(
            jni.JObjectPtr,
          )>();

  static final _set_key = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(jni.JObjectPtr,
                  ffi.Pointer<ffi.Void>)>>("set_MyMap_MyEntry__key")
      .asFunction<
          jni.JniResult Function(jni.JObjectPtr, ffi.Pointer<ffi.Void>)>();

  /// from: public K key
  /// The returned object must be released after use, by calling the [release] method.
  $K get key => _get_key(reference.pointer).object(K);

  /// from: public K key
  /// The returned object must be released after use, by calling the [release] method.
  set key($K value) =>
      _set_key(reference.pointer, value.reference.pointer).check();

  static final _get_value = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                jni.JObjectPtr,
              )>>("get_MyMap_MyEntry__value")
      .asFunction<
          jni.JniResult Function(
            jni.JObjectPtr,
          )>();

  static final _set_value = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(jni.JObjectPtr,
                  ffi.Pointer<ffi.Void>)>>("set_MyMap_MyEntry__value")
      .asFunction<
          jni.JniResult Function(jni.JObjectPtr, ffi.Pointer<ffi.Void>)>();

  /// from: public V value
  /// The returned object must be released after use, by calling the [release] method.
  $V get value => _get_value(reference.pointer).object(V);

  /// from: public V value
  /// The returned object must be released after use, by calling the [release] method.
  set value($V value) =>
      _set_value(reference.pointer, value.reference.pointer).check();

  static final _new0 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("MyMap_MyEntry__new0")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>)>();

  /// from: public void <init>(com.github.dart_lang.jnigen.generics.MyMap $parent, K key, V value)
  /// The returned object must be released after use, by calling the [release] method.
  factory MyMap_MyEntry(
    MyMap<$K, $V> $parent,
    $K key,
    $V value, {
    jni.JObjType<$K>? K,
    jni.JObjType<$V>? V,
  }) {
    K ??= jni.lowestCommonSuperType([
      key.$type,
      ($parent.$type as $MyMapType).K,
    ]) as jni.JObjType<$K>;
    V ??= jni.lowestCommonSuperType([
      value.$type,
      ($parent.$type as $MyMapType).V,
    ]) as jni.JObjType<$V>;
    return MyMap_MyEntry.fromReference(
        K,
        V,
        _new0($parent.reference.pointer, key.reference.pointer,
                value.reference.pointer)
            .reference);
  }
}

final class $MyMap_MyEntryType<$K extends jni.JObject, $V extends jni.JObject>
    extends jni.JObjType<MyMap_MyEntry<$K, $V>> {
  final jni.JObjType<$K> K;
  final jni.JObjType<$V> V;

  const $MyMap_MyEntryType(
    this.K,
    this.V,
  );

  @override
  String get signature =>
      r"Lcom/github/dart_lang/jnigen/generics/MyMap$MyEntry;";

  @override
  MyMap_MyEntry<$K, $V> fromReference(jni.JReference reference) =>
      MyMap_MyEntry.fromReference(K, V, reference);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode => Object.hash($MyMap_MyEntryType, K, V);

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($MyMap_MyEntryType<$K, $V>) &&
        other is $MyMap_MyEntryType<$K, $V> &&
        K == other.K &&
        V == other.V;
  }
}

/// from: com.github.dart_lang.jnigen.generics.MyMap
class MyMap<$K extends jni.JObject, $V extends jni.JObject>
    extends jni.JObject {
  @override
  late final jni.JObjType<MyMap<$K, $V>> $type = type(K, V);

  final jni.JObjType<$K> K;
  final jni.JObjType<$V> V;

  MyMap.fromReference(
    this.K,
    this.V,
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// The type which includes information such as the signature of this class.
  static $MyMapType<$K, $V>
      type<$K extends jni.JObject, $V extends jni.JObject>(
    jni.JObjType<$K> K,
    jni.JObjType<$V> V,
  ) {
    return $MyMapType(
      K,
      V,
    );
  }

  static final _new0 =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>("MyMap__new0")
          .asFunction<jni.JniResult Function()>();

  /// from: public void <init>()
  /// The returned object must be released after use, by calling the [release] method.
  factory MyMap({
    required jni.JObjType<$K> K,
    required jni.JObjType<$V> V,
  }) {
    return MyMap.fromReference(K, V, _new0().reference);
  }

  static final _get0 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>("MyMap__get0")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public V get(K key)
  /// The returned object must be released after use, by calling the [release] method.
  $V get0(
    $K key,
  ) {
    return _get0(reference.pointer, key.reference.pointer).object(V);
  }

  static final _put = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>("MyMap__put")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>)>();

  /// from: public V put(K key, V value)
  /// The returned object must be released after use, by calling the [release] method.
  $V put(
    $K key,
    $V value,
  ) {
    return _put(
            reference.pointer, key.reference.pointer, value.reference.pointer)
        .object(V);
  }

  static final _entryStack = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("MyMap__entryStack")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public com.github.dart_lang.jnigen.generics.MyStack<com.github.dart_lang.jnigen.generics.MyMap<K,V>.MyEntry> entryStack()
  /// The returned object must be released after use, by calling the [release] method.
  MyStack<MyMap_MyEntry<jni.JObject, jni.JObject>> entryStack() {
    return _entryStack(reference.pointer).object(const $MyStackType(
        $MyMap_MyEntryType(jni.JObjectType(), jni.JObjectType())));
  }
}

final class $MyMapType<$K extends jni.JObject, $V extends jni.JObject>
    extends jni.JObjType<MyMap<$K, $V>> {
  final jni.JObjType<$K> K;
  final jni.JObjType<$V> V;

  const $MyMapType(
    this.K,
    this.V,
  );

  @override
  String get signature => r"Lcom/github/dart_lang/jnigen/generics/MyMap;";

  @override
  MyMap<$K, $V> fromReference(jni.JReference reference) =>
      MyMap.fromReference(K, V, reference);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode => Object.hash($MyMapType, K, V);

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($MyMapType<$K, $V>) &&
        other is $MyMapType<$K, $V> &&
        K == other.K &&
        V == other.V;
  }
}

/// from: com.github.dart_lang.jnigen.generics.MyStack
class MyStack<$T extends jni.JObject> extends jni.JObject {
  @override
  late final jni.JObjType<MyStack<$T>> $type = type(T);

  final jni.JObjType<$T> T;

  MyStack.fromReference(
    this.T,
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// The type which includes information such as the signature of this class.
  static $MyStackType<$T> type<$T extends jni.JObject>(
    jni.JObjType<$T> T,
  ) {
    return $MyStackType(
      T,
    );
  }

  static final _new0 =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>("MyStack__new0")
          .asFunction<jni.JniResult Function()>();

  /// from: public void <init>()
  /// The returned object must be released after use, by calling the [release] method.
  factory MyStack({
    required jni.JObjType<$T> T,
  }) {
    return MyStack.fromReference(T, _new0().reference);
  }

  static final _fromArray = jniLookup<
              ffi
              .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
          "MyStack__fromArray")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();

  /// from: static public com.github.dart_lang.jnigen.generics.MyStack<T> fromArray(T[] arr)
  /// The returned object must be released after use, by calling the [release] method.
  static MyStack<$T> fromArray<$T extends jni.JObject>(
    jni.JArray<$T> arr, {
    jni.JObjType<$T>? T,
  }) {
    T ??= jni.lowestCommonSuperType([
      ((arr.$type as jni.JArrayType).elementType as jni.JObjType),
    ]) as jni.JObjType<$T>;
    return _fromArray(arr.reference.pointer).object($MyStackType(T));
  }

  static final _fromArrayOfArrayOfGrandParents = jniLookup<
              ffi
              .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
          "MyStack__fromArrayOfArrayOfGrandParents")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();

  /// from: static public com.github.dart_lang.jnigen.generics.MyStack<S> fromArrayOfArrayOfGrandParents(com.github.dart_lang.jnigen.generics.GrandParent<S>[][] arr)
  /// The returned object must be released after use, by calling the [release] method.
  static MyStack<$S> fromArrayOfArrayOfGrandParents<$S extends jni.JObject>(
    jni.JArray<jni.JArray<GrandParent<$S>>> arr, {
    jni.JObjType<$S>? S,
  }) {
    S ??= jni.lowestCommonSuperType([
      (((((arr.$type as jni.JArrayType).elementType as jni.JObjType)
                  as jni.JArrayType)
              .elementType as jni.JObjType) as $GrandParentType)
          .T,
    ]) as jni.JObjType<$S>;
    return _fromArrayOfArrayOfGrandParents(arr.reference.pointer)
        .object($MyStackType(S));
  }

  static final _of =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>("MyStack__of")
          .asFunction<jni.JniResult Function()>();

  /// from: static public com.github.dart_lang.jnigen.generics.MyStack<T> of()
  /// The returned object must be released after use, by calling the [release] method.
  static MyStack<$T> of<$T extends jni.JObject>({
    required jni.JObjType<$T> T,
  }) {
    return _of().object($MyStackType(T));
  }

  static final _of1 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>)>>("MyStack__of1")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();

  /// from: static public com.github.dart_lang.jnigen.generics.MyStack<T> of(T obj)
  /// The returned object must be released after use, by calling the [release] method.
  static MyStack<$T> of1<$T extends jni.JObject>(
    $T obj, {
    jni.JObjType<$T>? T,
  }) {
    T ??= jni.lowestCommonSuperType([
      obj.$type,
    ]) as jni.JObjType<$T>;
    return _of1(obj.reference.pointer).object($MyStackType(T));
  }

  static final _of2 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("MyStack__of2")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: static public com.github.dart_lang.jnigen.generics.MyStack<T> of(T obj, T obj2)
  /// The returned object must be released after use, by calling the [release] method.
  static MyStack<$T> of2<$T extends jni.JObject>(
    $T obj,
    $T obj2, {
    jni.JObjType<$T>? T,
  }) {
    T ??= jni.lowestCommonSuperType([
      obj2.$type,
      obj.$type,
    ]) as jni.JObjType<$T>;
    return _of2(obj.reference.pointer, obj2.reference.pointer)
        .object($MyStackType(T));
  }

  static final _push = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("MyStack__push")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public void push(T item)
  void push(
    $T item,
  ) {
    _push(reference.pointer, item.reference.pointer).check();
  }

  static final _pop = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("MyStack__pop")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public T pop()
  /// The returned object must be released after use, by calling the [release] method.
  $T pop() {
    return _pop(reference.pointer).object(T);
  }

  static final _size = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("MyStack__size")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public int size()
  int size() {
    return _size(reference.pointer).integer;
  }
}

final class $MyStackType<$T extends jni.JObject>
    extends jni.JObjType<MyStack<$T>> {
  final jni.JObjType<$T> T;

  const $MyStackType(
    this.T,
  );

  @override
  String get signature => r"Lcom/github/dart_lang/jnigen/generics/MyStack;";

  @override
  MyStack<$T> fromReference(jni.JReference reference) =>
      MyStack.fromReference(T, reference);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode => Object.hash($MyStackType, T);

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($MyStackType<$T>) &&
        other is $MyStackType<$T> &&
        T == other.T;
  }
}

/// from: com.github.dart_lang.jnigen.generics.StringKeyedMap
class StringKeyedMap<$V extends jni.JObject> extends MyMap<jni.JString, $V> {
  @override
  late final jni.JObjType<StringKeyedMap<$V>> $type = type(V);

  final jni.JObjType<$V> V;

  StringKeyedMap.fromReference(
    this.V,
    jni.JReference reference,
  ) : super.fromReference(const jni.JStringType(), V, reference);

  /// The type which includes information such as the signature of this class.
  static $StringKeyedMapType<$V> type<$V extends jni.JObject>(
    jni.JObjType<$V> V,
  ) {
    return $StringKeyedMapType(
      V,
    );
  }

  static final _new0 = jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
          "StringKeyedMap__new0")
      .asFunction<jni.JniResult Function()>();

  /// from: public void <init>()
  /// The returned object must be released after use, by calling the [release] method.
  factory StringKeyedMap({
    required jni.JObjType<$V> V,
  }) {
    return StringKeyedMap.fromReference(V, _new0().reference);
  }
}

final class $StringKeyedMapType<$V extends jni.JObject>
    extends jni.JObjType<StringKeyedMap<$V>> {
  final jni.JObjType<$V> V;

  const $StringKeyedMapType(
    this.V,
  );

  @override
  String get signature =>
      r"Lcom/github/dart_lang/jnigen/generics/StringKeyedMap;";

  @override
  StringKeyedMap<$V> fromReference(jni.JReference reference) =>
      StringKeyedMap.fromReference(V, reference);

  @override
  jni.JObjType get superType => $MyMapType(const jni.JStringType(), V);

  @override
  final superCount = 2;

  @override
  int get hashCode => Object.hash($StringKeyedMapType, V);

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($StringKeyedMapType<$V>) &&
        other is $StringKeyedMapType<$V> &&
        V == other.V;
  }
}

/// from: com.github.dart_lang.jnigen.generics.StringStack
class StringStack extends MyStack<jni.JString> {
  @override
  late final jni.JObjType<StringStack> $type = type;

  StringStack.fromReference(
    jni.JReference reference,
  ) : super.fromReference(const jni.JStringType(), reference);

  /// The type which includes information such as the signature of this class.
  static const type = $StringStackType();
  static final _new0 = jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
          "StringStack__new0")
      .asFunction<jni.JniResult Function()>();

  /// from: public void <init>()
  /// The returned object must be released after use, by calling the [release] method.
  factory StringStack() {
    return StringStack.fromReference(_new0().reference);
  }
}

final class $StringStackType extends jni.JObjType<StringStack> {
  const $StringStackType();

  @override
  String get signature => r"Lcom/github/dart_lang/jnigen/generics/StringStack;";

  @override
  StringStack fromReference(jni.JReference reference) =>
      StringStack.fromReference(reference);

  @override
  jni.JObjType get superType => const $MyStackType(jni.JStringType());

  @override
  final superCount = 2;

  @override
  int get hashCode => ($StringStackType).hashCode;

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($StringStackType) && other is $StringStackType;
  }
}

/// from: com.github.dart_lang.jnigen.generics.StringValuedMap
class StringValuedMap<$K extends jni.JObject> extends MyMap<$K, jni.JString> {
  @override
  late final jni.JObjType<StringValuedMap<$K>> $type = type(K);

  final jni.JObjType<$K> K;

  StringValuedMap.fromReference(
    this.K,
    jni.JReference reference,
  ) : super.fromReference(K, const jni.JStringType(), reference);

  /// The type which includes information such as the signature of this class.
  static $StringValuedMapType<$K> type<$K extends jni.JObject>(
    jni.JObjType<$K> K,
  ) {
    return $StringValuedMapType(
      K,
    );
  }

  static final _new0 = jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
          "StringValuedMap__new0")
      .asFunction<jni.JniResult Function()>();

  /// from: public void <init>()
  /// The returned object must be released after use, by calling the [release] method.
  factory StringValuedMap({
    required jni.JObjType<$K> K,
  }) {
    return StringValuedMap.fromReference(K, _new0().reference);
  }
}

final class $StringValuedMapType<$K extends jni.JObject>
    extends jni.JObjType<StringValuedMap<$K>> {
  final jni.JObjType<$K> K;

  const $StringValuedMapType(
    this.K,
  );

  @override
  String get signature =>
      r"Lcom/github/dart_lang/jnigen/generics/StringValuedMap;";

  @override
  StringValuedMap<$K> fromReference(jni.JReference reference) =>
      StringValuedMap.fromReference(K, reference);

  @override
  jni.JObjType get superType => $MyMapType(K, const jni.JStringType());

  @override
  final superCount = 2;

  @override
  int get hashCode => Object.hash($StringValuedMapType, K);

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($StringValuedMapType<$K>) &&
        other is $StringValuedMapType<$K> &&
        K == other.K;
  }
}

/// from: com.github.dart_lang.jnigen.interfaces.MyInterface
class MyInterface<$T extends jni.JObject> extends jni.JObject {
  @override
  late final jni.JObjType<MyInterface<$T>> $type = type(T);

  final jni.JObjType<$T> T;

  MyInterface.fromReference(
    this.T,
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// The type which includes information such as the signature of this class.
  static $MyInterfaceType<$T> type<$T extends jni.JObject>(
    jni.JObjType<$T> T,
  ) {
    return $MyInterfaceType(
      T,
    );
  }

  static final _voidCallback = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("MyInterface__voidCallback")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public abstract void voidCallback(java.lang.String s)
  void voidCallback(
    jni.JString s,
  ) {
    _voidCallback(reference.pointer, s.reference.pointer).check();
  }

  static final _stringCallback = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("MyInterface__stringCallback")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public abstract java.lang.String stringCallback(java.lang.String s)
  /// The returned object must be released after use, by calling the [release] method.
  jni.JString stringCallback(
    jni.JString s,
  ) {
    return _stringCallback(reference.pointer, s.reference.pointer)
        .object(const jni.JStringType());
  }

  static final _varCallback = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("MyInterface__varCallback")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public abstract T varCallback(T t)
  /// The returned object must be released after use, by calling the [release] method.
  $T varCallback(
    $T t,
  ) {
    return _varCallback(reference.pointer, t.reference.pointer).object(T);
  }

  static final _manyPrimitives = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  ffi.Int32,
                  ffi.Uint8,
                  ffi.Uint16,
                  ffi.Double)>>("MyInterface__manyPrimitives")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, int, int, int, double)>();

  /// from: public abstract long manyPrimitives(int a, boolean b, char c, double d)
  int manyPrimitives(
    int a,
    bool b,
    int c,
    double d,
  ) {
    return _manyPrimitives(reference.pointer, a, b ? 1 : 0, c, d).long;
  }

  /// Maps a specific port to the implemented interface.
  static final Map<int, $MyInterfaceImpl> _$impls = {};
  ReceivePort? _$p;

  static jni.JObjectPtr _$invoke(
    int port,
    jni.JObjectPtr descriptor,
    jni.JObjectPtr args,
  ) {
    return _$invokeMethod(
      port,
      $MethodInvocation.fromAddresses(
        0,
        descriptor.address,
        args.address,
      ),
    );
  }

  static final ffi.Pointer<
          ffi.NativeFunction<
              jni.JObjectPtr Function(
                  ffi.Uint64, jni.JObjectPtr, jni.JObjectPtr)>>
      _$invokePointer = ffi.Pointer.fromFunction(_$invoke);

  static ffi.Pointer<ffi.Void> _$invokeMethod(
    int $p,
    $MethodInvocation $i,
  ) {
    try {
      final $d = $i.methodDescriptor.toDartString(releaseOriginal: true);
      final $a = $i.args;
      if ($d == r"voidCallback(Ljava/lang/String;)V") {
        _$impls[$p]!.voidCallback(
          $a[0].castTo(const jni.JStringType(), releaseOriginal: true),
        );
        return jni.nullptr;
      }
      if ($d == r"stringCallback(Ljava/lang/String;)Ljava/lang/String;") {
        final $r = _$impls[$p]!.stringCallback(
          $a[0].castTo(const jni.JStringType(), releaseOriginal: true),
        );
        return ($r as jni.JObject)
            .castTo(const jni.JObjectType())
            .reference
            .toPointer();
      }
      if ($d == r"varCallback(Ljava/lang/Object;)Ljava/lang/Object;") {
        final $r = _$impls[$p]!.varCallback(
          $a[0].castTo(_$impls[$p]!.T, releaseOriginal: true),
        );
        return ($r as jni.JObject)
            .castTo(const jni.JObjectType())
            .reference
            .toPointer();
      }
      if ($d == r"manyPrimitives(IZCD)J") {
        final $r = _$impls[$p]!.manyPrimitives(
          $a[0]
              .castTo(const jni.JIntegerType(), releaseOriginal: true)
              .intValue(releaseOriginal: true),
          $a[1]
              .castTo(const jni.JBooleanType(), releaseOriginal: true)
              .booleanValue(releaseOriginal: true),
          $a[2]
              .castTo(const jni.JCharacterType(), releaseOriginal: true)
              .charValue(releaseOriginal: true),
          $a[3]
              .castTo(const jni.JDoubleType(), releaseOriginal: true)
              .doubleValue(releaseOriginal: true),
        );
        return jni.JLong($r).reference.toPointer();
      }
    } catch (e) {
      return ProtectedJniExtensions.newDartException(e.toString());
    }
    return jni.nullptr;
  }

  factory MyInterface.implement(
    $MyInterfaceImpl<$T> $impl,
  ) {
    final $p = ReceivePort();
    final $x = MyInterface.fromReference(
      $impl.T,
      ProtectedJniExtensions.newPortProxy(
        r"com.github.dart_lang.jnigen.interfaces.MyInterface",
        $p,
        _$invokePointer,
      ),
    ).._$p = $p;
    final $a = $p.sendPort.nativePort;
    _$impls[$a] = $impl;
    $p.listen(($m) {
      if ($m == null) {
        _$impls.remove($p.sendPort.nativePort);
        $p.close();
        return;
      }
      final $i = $MethodInvocation.fromMessage($m as List<dynamic>);
      final $r = _$invokeMethod($p.sendPort.nativePort, $i);
      ProtectedJniExtensions.returnResult($i.result, $r);
    });
    return $x;
  }
  static Map<int, $MyInterfaceImpl> get $impls => _$impls;
}

abstract interface class $MyInterfaceImpl<$T extends jni.JObject> {
  factory $MyInterfaceImpl({
    required jni.JObjType<$T> T,
    required void Function(jni.JString s) voidCallback,
    required jni.JString Function(jni.JString s) stringCallback,
    required $T Function($T t) varCallback,
    required int Function(int a, bool b, int c, double d) manyPrimitives,
  }) = _$MyInterfaceImpl;

  jni.JObjType<$T> get T;

  void voidCallback(jni.JString s);
  jni.JString stringCallback(jni.JString s);
  $T varCallback($T t);
  int manyPrimitives(int a, bool b, int c, double d);
}

class _$MyInterfaceImpl<$T extends jni.JObject>
    implements $MyInterfaceImpl<$T> {
  _$MyInterfaceImpl({
    required this.T,
    required void Function(jni.JString s) voidCallback,
    required jni.JString Function(jni.JString s) stringCallback,
    required $T Function($T t) varCallback,
    required int Function(int a, bool b, int c, double d) manyPrimitives,
  })  : _voidCallback = voidCallback,
        _stringCallback = stringCallback,
        _varCallback = varCallback,
        _manyPrimitives = manyPrimitives;

  @override
  final jni.JObjType<$T> T;

  final void Function(jni.JString s) _voidCallback;
  final jni.JString Function(jni.JString s) _stringCallback;
  final $T Function($T t) _varCallback;
  final int Function(int a, bool b, int c, double d) _manyPrimitives;

  void voidCallback(jni.JString s) {
    return _voidCallback(s);
  }

  jni.JString stringCallback(jni.JString s) {
    return _stringCallback(s);
  }

  $T varCallback($T t) {
    return _varCallback(t);
  }

  int manyPrimitives(int a, bool b, int c, double d) {
    return _manyPrimitives(a, b, c, d);
  }
}

final class $MyInterfaceType<$T extends jni.JObject>
    extends jni.JObjType<MyInterface<$T>> {
  final jni.JObjType<$T> T;

  const $MyInterfaceType(
    this.T,
  );

  @override
  String get signature =>
      r"Lcom/github/dart_lang/jnigen/interfaces/MyInterface;";

  @override
  MyInterface<$T> fromReference(jni.JReference reference) =>
      MyInterface.fromReference(T, reference);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode => Object.hash($MyInterfaceType, T);

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($MyInterfaceType<$T>) &&
        other is $MyInterfaceType<$T> &&
        T == other.T;
  }
}

/// from: com.github.dart_lang.jnigen.interfaces.MyInterfaceConsumer
class MyInterfaceConsumer extends jni.JObject {
  @override
  late final jni.JObjType<MyInterfaceConsumer> $type = type;

  MyInterfaceConsumer.fromReference(
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// The type which includes information such as the signature of this class.
  static const type = $MyInterfaceConsumerType();
  static final _new0 = jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
          "MyInterfaceConsumer__new0")
      .asFunction<jni.JniResult Function()>();

  /// from: public void <init>()
  /// The returned object must be released after use, by calling the [release] method.
  factory MyInterfaceConsumer() {
    return MyInterfaceConsumer.fromReference(_new0().reference);
  }

  static final _consumeOnAnotherThread = jniLookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>,
                      ffi.Pointer<ffi.Void>,
                      ffi.Int32,
                      ffi.Uint8,
                      ffi.Uint16,
                      ffi.Double,
                      ffi.Pointer<ffi.Void>)>>(
          "MyInterfaceConsumer__consumeOnAnotherThread")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
              int, int, int, double, ffi.Pointer<ffi.Void>)>();

  /// from: static public void consumeOnAnotherThread(com.github.dart_lang.jnigen.interfaces.MyInterface<T> myInterface, java.lang.String s, int a, boolean b, char c, double d, T t)
  static void consumeOnAnotherThread<$T extends jni.JObject>(
    MyInterface<$T> myInterface,
    jni.JString s,
    int a,
    bool b,
    int c,
    double d,
    $T t, {
    jni.JObjType<$T>? T,
  }) {
    T ??= jni.lowestCommonSuperType([
      t.$type,
      (myInterface.$type as $MyInterfaceType).T,
    ]) as jni.JObjType<$T>;
    _consumeOnAnotherThread(myInterface.reference.pointer, s.reference.pointer,
            a, b ? 1 : 0, c, d, t.reference.pointer)
        .check();
  }

  static final _consumeOnSameThread = jniLookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>,
                      ffi.Pointer<ffi.Void>,
                      ffi.Int32,
                      ffi.Uint8,
                      ffi.Uint16,
                      ffi.Double,
                      ffi.Pointer<ffi.Void>)>>(
          "MyInterfaceConsumer__consumeOnSameThread")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
              int, int, int, double, ffi.Pointer<ffi.Void>)>();

  /// from: static public void consumeOnSameThread(com.github.dart_lang.jnigen.interfaces.MyInterface<T> myInterface, java.lang.String s, int a, boolean b, char c, double d, T t)
  static void consumeOnSameThread<$T extends jni.JObject>(
    MyInterface<$T> myInterface,
    jni.JString s,
    int a,
    bool b,
    int c,
    double d,
    $T t, {
    jni.JObjType<$T>? T,
  }) {
    T ??= jni.lowestCommonSuperType([
      t.$type,
      (myInterface.$type as $MyInterfaceType).T,
    ]) as jni.JObjType<$T>;
    _consumeOnSameThread(myInterface.reference.pointer, s.reference.pointer, a,
            b ? 1 : 0, c, d, t.reference.pointer)
        .check();
  }
}

final class $MyInterfaceConsumerType extends jni.JObjType<MyInterfaceConsumer> {
  const $MyInterfaceConsumerType();

  @override
  String get signature =>
      r"Lcom/github/dart_lang/jnigen/interfaces/MyInterfaceConsumer;";

  @override
  MyInterfaceConsumer fromReference(jni.JReference reference) =>
      MyInterfaceConsumer.fromReference(reference);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode => ($MyInterfaceConsumerType).hashCode;

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($MyInterfaceConsumerType) &&
        other is $MyInterfaceConsumerType;
  }
}

/// from: com.github.dart_lang.jnigen.interfaces.MyRunnable
class MyRunnable extends jni.JObject {
  @override
  late final jni.JObjType<MyRunnable> $type = type;

  MyRunnable.fromReference(
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// The type which includes information such as the signature of this class.
  static const type = $MyRunnableType();
  static final _run = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("MyRunnable__run")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public abstract void run()
  void run() {
    _run(reference.pointer).check();
  }

  /// Maps a specific port to the implemented interface.
  static final Map<int, $MyRunnableImpl> _$impls = {};
  ReceivePort? _$p;

  static jni.JObjectPtr _$invoke(
    int port,
    jni.JObjectPtr descriptor,
    jni.JObjectPtr args,
  ) {
    return _$invokeMethod(
      port,
      $MethodInvocation.fromAddresses(
        0,
        descriptor.address,
        args.address,
      ),
    );
  }

  static final ffi.Pointer<
          ffi.NativeFunction<
              jni.JObjectPtr Function(
                  ffi.Uint64, jni.JObjectPtr, jni.JObjectPtr)>>
      _$invokePointer = ffi.Pointer.fromFunction(_$invoke);

  static ffi.Pointer<ffi.Void> _$invokeMethod(
    int $p,
    $MethodInvocation $i,
  ) {
    try {
      final $d = $i.methodDescriptor.toDartString(releaseOriginal: true);
      final $a = $i.args;
      if ($d == r"run()V") {
        _$impls[$p]!.run();
        return jni.nullptr;
      }
    } catch (e) {
      return ProtectedJniExtensions.newDartException(e.toString());
    }
    return jni.nullptr;
  }

  factory MyRunnable.implement(
    $MyRunnableImpl $impl,
  ) {
    final $p = ReceivePort();
    final $x = MyRunnable.fromReference(
      ProtectedJniExtensions.newPortProxy(
        r"com.github.dart_lang.jnigen.interfaces.MyRunnable",
        $p,
        _$invokePointer,
      ),
    ).._$p = $p;
    final $a = $p.sendPort.nativePort;
    _$impls[$a] = $impl;
    $p.listen(($m) {
      if ($m == null) {
        _$impls.remove($p.sendPort.nativePort);
        $p.close();
        return;
      }
      final $i = $MethodInvocation.fromMessage($m as List<dynamic>);
      final $r = _$invokeMethod($p.sendPort.nativePort, $i);
      ProtectedJniExtensions.returnResult($i.result, $r);
    });
    return $x;
  }
}

abstract interface class $MyRunnableImpl {
  factory $MyRunnableImpl({
    required void Function() run,
  }) = _$MyRunnableImpl;

  void run();
}

class _$MyRunnableImpl implements $MyRunnableImpl {
  _$MyRunnableImpl({
    required void Function() run,
  }) : _run = run;

  final void Function() _run;

  void run() {
    return _run();
  }
}

final class $MyRunnableType extends jni.JObjType<MyRunnable> {
  const $MyRunnableType();

  @override
  String get signature =>
      r"Lcom/github/dart_lang/jnigen/interfaces/MyRunnable;";

  @override
  MyRunnable fromReference(jni.JReference reference) =>
      MyRunnable.fromReference(reference);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode => ($MyRunnableType).hashCode;

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($MyRunnableType) && other is $MyRunnableType;
  }
}

/// from: com.github.dart_lang.jnigen.interfaces.MyRunnableRunner
class MyRunnableRunner extends jni.JObject {
  @override
  late final jni.JObjType<MyRunnableRunner> $type = type;

  MyRunnableRunner.fromReference(
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// The type which includes information such as the signature of this class.
  static const type = $MyRunnableRunnerType();
  static final _get_error = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                jni.JObjectPtr,
              )>>("get_MyRunnableRunner__error")
      .asFunction<
          jni.JniResult Function(
            jni.JObjectPtr,
          )>();

  static final _set_error = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(jni.JObjectPtr,
                  ffi.Pointer<ffi.Void>)>>("set_MyRunnableRunner__error")
      .asFunction<
          jni.JniResult Function(jni.JObjectPtr, ffi.Pointer<ffi.Void>)>();

  /// from: public java.lang.Throwable error
  /// The returned object must be released after use, by calling the [release] method.
  jni.JObject get error =>
      _get_error(reference.pointer).object(const jni.JObjectType());

  /// from: public java.lang.Throwable error
  /// The returned object must be released after use, by calling the [release] method.
  set error(jni.JObject value) =>
      _set_error(reference.pointer, value.reference.pointer).check();

  static final _new0 = jniLookup<
              ffi
              .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
          "MyRunnableRunner__new0")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();

  /// from: public void <init>(com.github.dart_lang.jnigen.interfaces.MyRunnable runnable)
  /// The returned object must be released after use, by calling the [release] method.
  factory MyRunnableRunner(
    MyRunnable runnable,
  ) {
    return MyRunnableRunner.fromReference(
        _new0(runnable.reference.pointer).reference);
  }

  static final _runOnSameThread = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("MyRunnableRunner__runOnSameThread")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public void runOnSameThread()
  void runOnSameThread() {
    _runOnSameThread(reference.pointer).check();
  }

  static final _runOnAnotherThread = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("MyRunnableRunner__runOnAnotherThread")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public void runOnAnotherThread()
  void runOnAnotherThread() {
    _runOnAnotherThread(reference.pointer).check();
  }
}

final class $MyRunnableRunnerType extends jni.JObjType<MyRunnableRunner> {
  const $MyRunnableRunnerType();

  @override
  String get signature =>
      r"Lcom/github/dart_lang/jnigen/interfaces/MyRunnableRunner;";

  @override
  MyRunnableRunner fromReference(jni.JReference reference) =>
      MyRunnableRunner.fromReference(reference);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode => ($MyRunnableRunnerType).hashCode;

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($MyRunnableRunnerType) &&
        other is $MyRunnableRunnerType;
  }
}

/// from: com.github.dart_lang.jnigen.annotations.JsonSerializable$Case
class JsonSerializable_Case extends jni.JObject {
  @override
  late final jni.JObjType<JsonSerializable_Case> $type = type;

  JsonSerializable_Case.fromReference(
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// The type which includes information such as the signature of this class.
  static const type = $JsonSerializable_CaseType();
  static final _values =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "JsonSerializable_Case__values")
          .asFunction<jni.JniResult Function()>();

  /// from: static public com.github.dart_lang.jnigen.annotations.JsonSerializable.Case[] values()
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JArray<JsonSerializable_Case> values() {
    return _values().object(const jni.JArrayType($JsonSerializable_CaseType()));
  }

  static final _valueOf = jniLookup<
              ffi
              .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
          "JsonSerializable_Case__valueOf")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();

  /// from: static public com.github.dart_lang.jnigen.annotations.JsonSerializable.Case valueOf(java.lang.String name)
  /// The returned object must be released after use, by calling the [release] method.
  static JsonSerializable_Case valueOf(
    jni.JString name,
  ) {
    return _valueOf(name.reference.pointer)
        .object(const $JsonSerializable_CaseType());
  }
}

final class $JsonSerializable_CaseType
    extends jni.JObjType<JsonSerializable_Case> {
  const $JsonSerializable_CaseType();

  @override
  String get signature =>
      r"Lcom/github/dart_lang/jnigen/annotations/JsonSerializable$Case;";

  @override
  JsonSerializable_Case fromReference(jni.JReference reference) =>
      JsonSerializable_Case.fromReference(reference);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode => ($JsonSerializable_CaseType).hashCode;

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($JsonSerializable_CaseType) &&
        other is $JsonSerializable_CaseType;
  }
}

/// from: com.github.dart_lang.jnigen.annotations.JsonSerializable
class JsonSerializable extends jni.JObject {
  @override
  late final jni.JObjType<JsonSerializable> $type = type;

  JsonSerializable.fromReference(
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// The type which includes information such as the signature of this class.
  static const type = $JsonSerializableType();
  static final _value = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonSerializable__value")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public abstract com.github.dart_lang.jnigen.annotations.JsonSerializable$Case value()
  /// The returned object must be released after use, by calling the [release] method.
  JsonSerializable_Case value() {
    return _value(reference.pointer).object(const $JsonSerializable_CaseType());
  }

  /// Maps a specific port to the implemented interface.
  static final Map<int, $JsonSerializableImpl> _$impls = {};
  ReceivePort? _$p;

  static jni.JObjectPtr _$invoke(
    int port,
    jni.JObjectPtr descriptor,
    jni.JObjectPtr args,
  ) {
    return _$invokeMethod(
      port,
      $MethodInvocation.fromAddresses(
        0,
        descriptor.address,
        args.address,
      ),
    );
  }

  static final ffi.Pointer<
          ffi.NativeFunction<
              jni.JObjectPtr Function(
                  ffi.Uint64, jni.JObjectPtr, jni.JObjectPtr)>>
      _$invokePointer = ffi.Pointer.fromFunction(_$invoke);

  static ffi.Pointer<ffi.Void> _$invokeMethod(
    int $p,
    $MethodInvocation $i,
  ) {
    try {
      final $d = $i.methodDescriptor.toDartString(releaseOriginal: true);
      final $a = $i.args;
      if ($d ==
          r"value()Lcom/github/dart_lang/jnigen/annotations/JsonSerializable$Case;") {
        final $r = _$impls[$p]!.value();
        return ($r as jni.JObject)
            .castTo(const jni.JObjectType())
            .reference
            .toPointer();
      }
    } catch (e) {
      return ProtectedJniExtensions.newDartException(e.toString());
    }
    return jni.nullptr;
  }

  factory JsonSerializable.implement(
    $JsonSerializableImpl $impl,
  ) {
    final $p = ReceivePort();
    final $x = JsonSerializable.fromReference(
      ProtectedJniExtensions.newPortProxy(
        r"com.github.dart_lang.jnigen.annotations.JsonSerializable",
        $p,
        _$invokePointer,
      ),
    ).._$p = $p;
    final $a = $p.sendPort.nativePort;
    _$impls[$a] = $impl;
    $p.listen(($m) {
      if ($m == null) {
        _$impls.remove($p.sendPort.nativePort);
        $p.close();
        return;
      }
      final $i = $MethodInvocation.fromMessage($m as List<dynamic>);
      final $r = _$invokeMethod($p.sendPort.nativePort, $i);
      ProtectedJniExtensions.returnResult($i.result, $r);
    });
    return $x;
  }
}

abstract interface class $JsonSerializableImpl {
  factory $JsonSerializableImpl({
    required JsonSerializable_Case Function() value,
  }) = _$JsonSerializableImpl;

  JsonSerializable_Case value();
}

class _$JsonSerializableImpl implements $JsonSerializableImpl {
  _$JsonSerializableImpl({
    required JsonSerializable_Case Function() value,
  }) : _value = value;

  final JsonSerializable_Case Function() _value;

  JsonSerializable_Case value() {
    return _value();
  }
}

final class $JsonSerializableType extends jni.JObjType<JsonSerializable> {
  const $JsonSerializableType();

  @override
  String get signature =>
      r"Lcom/github/dart_lang/jnigen/annotations/JsonSerializable;";

  @override
  JsonSerializable fromReference(jni.JReference reference) =>
      JsonSerializable.fromReference(reference);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode => ($JsonSerializableType).hashCode;

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($JsonSerializableType) &&
        other is $JsonSerializableType;
  }
}

/// from: com.github.dart_lang.jnigen.annotations.MyDataClass
class MyDataClass extends jni.JObject {
  @override
  late final jni.JObjType<MyDataClass> $type = type;

  MyDataClass.fromReference(
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// The type which includes information such as the signature of this class.
  static const type = $MyDataClassType();
  static final _new0 = jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
          "MyDataClass__new0")
      .asFunction<jni.JniResult Function()>();

  /// from: public void <init>()
  /// The returned object must be released after use, by calling the [release] method.
  factory MyDataClass() {
    return MyDataClass.fromReference(_new0().reference);
  }
}

final class $MyDataClassType extends jni.JObjType<MyDataClass> {
  const $MyDataClassType();

  @override
  String get signature =>
      r"Lcom/github/dart_lang/jnigen/annotations/MyDataClass;";

  @override
  MyDataClass fromReference(jni.JReference reference) =>
      MyDataClass.fromReference(reference);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode => ($MyDataClassType).hashCode;

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($MyDataClassType) && other is $MyDataClassType;
  }
}

/// from: com.github.dart_lang.jnigen.simple_package.Color
class Color extends jni.JObject {
  @override
  late final jni.JObjType<Color> $type = type;

  Color.fromReference(
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// The type which includes information such as the signature of this class.
  static const type = $ColorType();
  static final _values =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>("Color__values")
          .asFunction<jni.JniResult Function()>();

  /// from: static public com.github.dart_lang.jnigen.simple_package.Color[] values()
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JArray<Color> values() {
    return _values().object(const jni.JArrayType($ColorType()));
  }

  static final _valueOf = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>)>>("Color__valueOf")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();

  /// from: static public com.github.dart_lang.jnigen.simple_package.Color valueOf(java.lang.String name)
  /// The returned object must be released after use, by calling the [release] method.
  static Color valueOf(
    jni.JString name,
  ) {
    return _valueOf(name.reference.pointer).object(const $ColorType());
  }
}

final class $ColorType extends jni.JObjType<Color> {
  const $ColorType();

  @override
  String get signature => r"Lcom/github/dart_lang/jnigen/simple_package/Color;";

  @override
  Color fromReference(jni.JReference reference) =>
      Color.fromReference(reference);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode => ($ColorType).hashCode;

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($ColorType) && other is $ColorType;
  }
}

/// from: com.github.dart_lang.jnigen.simple_package.Exceptions
class Exceptions extends jni.JObject {
  @override
  late final jni.JObjType<Exceptions> $type = type;

  Exceptions.fromReference(
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// The type which includes information such as the signature of this class.
  static const type = $ExceptionsType();
  static final _new0 = jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
          "Exceptions__new0")
      .asFunction<jni.JniResult Function()>();

  /// from: public void <init>()
  /// The returned object must be released after use, by calling the [release] method.
  factory Exceptions() {
    return Exceptions.fromReference(_new0().reference);
  }

  static final _new1 =
      jniLookup<ffi.NativeFunction<jni.JniResult Function(ffi.Float)>>(
              "Exceptions__new1")
          .asFunction<jni.JniResult Function(double)>();

  /// from: public void <init>(float x)
  /// The returned object must be released after use, by calling the [release] method.
  factory Exceptions.new1(
    double x,
  ) {
    return Exceptions.fromReference(_new1(x).reference);
  }

  static final _new2 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Int32, ffi.Int32, ffi.Int32, ffi.Int32,
                  ffi.Int32, ffi.Int32)>>("Exceptions__new2")
      .asFunction<jni.JniResult Function(int, int, int, int, int, int)>();

  /// from: public void <init>(int a, int b, int c, int d, int e, int f)
  /// The returned object must be released after use, by calling the [release] method.
  factory Exceptions.new2(
    int a,
    int b,
    int c,
    int d,
    int e,
    int f,
  ) {
    return Exceptions.fromReference(_new2(a, b, c, d, e, f).reference);
  }

  static final _staticObjectMethod =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "Exceptions__staticObjectMethod")
          .asFunction<jni.JniResult Function()>();

  /// from: static public java.lang.Object staticObjectMethod()
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JObject staticObjectMethod() {
    return _staticObjectMethod().object(const jni.JObjectType());
  }

  static final _staticIntMethod =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "Exceptions__staticIntMethod")
          .asFunction<jni.JniResult Function()>();

  /// from: static public int staticIntMethod()
  static int staticIntMethod() {
    return _staticIntMethod().integer;
  }

  static final _staticObjectArrayMethod =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "Exceptions__staticObjectArrayMethod")
          .asFunction<jni.JniResult Function()>();

  /// from: static public java.lang.Object[] staticObjectArrayMethod()
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JArray<jni.JObject> staticObjectArrayMethod() {
    return _staticObjectArrayMethod()
        .object(const jni.JArrayType(jni.JObjectType()));
  }

  static final _staticIntArrayMethod =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "Exceptions__staticIntArrayMethod")
          .asFunction<jni.JniResult Function()>();

  /// from: static public int[] staticIntArrayMethod()
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JArray<jni.jint> staticIntArrayMethod() {
    return _staticIntArrayMethod().object(const jni.JArrayType(jni.jintType()));
  }

  static final _objectMethod = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("Exceptions__objectMethod")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public java.lang.Object objectMethod()
  /// The returned object must be released after use, by calling the [release] method.
  jni.JObject objectMethod() {
    return _objectMethod(reference.pointer).object(const jni.JObjectType());
  }

  static final _intMethod = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("Exceptions__intMethod")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public int intMethod()
  int intMethod() {
    return _intMethod(reference.pointer).integer;
  }

  static final _objectArrayMethod = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("Exceptions__objectArrayMethod")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public java.lang.Object[] objectArrayMethod()
  /// The returned object must be released after use, by calling the [release] method.
  jni.JArray<jni.JObject> objectArrayMethod() {
    return _objectArrayMethod(reference.pointer)
        .object(const jni.JArrayType(jni.JObjectType()));
  }

  static final _intArrayMethod = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("Exceptions__intArrayMethod")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public int[] intArrayMethod()
  /// The returned object must be released after use, by calling the [release] method.
  jni.JArray<jni.jint> intArrayMethod() {
    return _intArrayMethod(reference.pointer)
        .object(const jni.JArrayType(jni.jintType()));
  }

  static final _throwNullPointerException = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("Exceptions__throwNullPointerException")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public int throwNullPointerException()
  int throwNullPointerException() {
    return _throwNullPointerException(reference.pointer).integer;
  }

  static final _throwFileNotFoundException = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("Exceptions__throwFileNotFoundException")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public java.io.InputStream throwFileNotFoundException()
  /// The returned object must be released after use, by calling the [release] method.
  jni.JObject throwFileNotFoundException() {
    return _throwFileNotFoundException(reference.pointer)
        .object(const jni.JObjectType());
  }

  static final _throwClassCastException = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("Exceptions__throwClassCastException")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public java.io.FileInputStream throwClassCastException()
  /// The returned object must be released after use, by calling the [release] method.
  jni.JObject throwClassCastException() {
    return _throwClassCastException(reference.pointer)
        .object(const jni.JObjectType());
  }

  static final _throwArrayIndexException = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("Exceptions__throwArrayIndexException")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public int throwArrayIndexException()
  int throwArrayIndexException() {
    return _throwArrayIndexException(reference.pointer).integer;
  }

  static final _throwArithmeticException = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("Exceptions__throwArithmeticException")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public int throwArithmeticException()
  int throwArithmeticException() {
    return _throwArithmeticException(reference.pointer).integer;
  }

  static final _throwLoremIpsum =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "Exceptions__throwLoremIpsum")
          .asFunction<jni.JniResult Function()>();

  /// from: static public void throwLoremIpsum()
  static void throwLoremIpsum() {
    _throwLoremIpsum().check();
  }
}

final class $ExceptionsType extends jni.JObjType<Exceptions> {
  const $ExceptionsType();

  @override
  String get signature =>
      r"Lcom/github/dart_lang/jnigen/simple_package/Exceptions;";

  @override
  Exceptions fromReference(jni.JReference reference) =>
      Exceptions.fromReference(reference);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode => ($ExceptionsType).hashCode;

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($ExceptionsType) && other is $ExceptionsType;
  }
}

/// from: com.github.dart_lang.jnigen.simple_package.Fields
class Fields extends jni.JObject {
  @override
  late final jni.JObjType<Fields> $type = type;

  Fields.fromReference(
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// The type which includes information such as the signature of this class.
  static const type = $FieldsType();
  static final _get_amount =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "get_Fields__amount")
          .asFunction<jni.JniResult Function()>();

  static final _set_amount =
      jniLookup<ffi.NativeFunction<jni.JniResult Function(ffi.Int32)>>(
              "set_Fields__amount")
          .asFunction<jni.JniResult Function(int)>();

  /// from: static public int amount
  static int get amount => _get_amount().integer;

  /// from: static public int amount
  static set amount(int value) => _set_amount(value).check();

  static final _get_pi =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>("get_Fields__pi")
          .asFunction<jni.JniResult Function()>();

  static final _set_pi =
      jniLookup<ffi.NativeFunction<jni.JniResult Function(ffi.Double)>>(
              "set_Fields__pi")
          .asFunction<jni.JniResult Function(double)>();

  /// from: static public double pi
  static double get pi => _get_pi().doubleFloat;

  /// from: static public double pi
  static set pi(double value) => _set_pi(value).check();

  static final _get_asterisk =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "get_Fields__asterisk")
          .asFunction<jni.JniResult Function()>();

  static final _set_asterisk =
      jniLookup<ffi.NativeFunction<jni.JniResult Function(ffi.Uint16)>>(
              "set_Fields__asterisk")
          .asFunction<jni.JniResult Function(int)>();

  /// from: static public char asterisk
  static int get asterisk => _get_asterisk().char;

  /// from: static public char asterisk
  static set asterisk(int value) => _set_asterisk(value).check();

  static final _get_name =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "get_Fields__name")
          .asFunction<jni.JniResult Function()>();

  static final _set_name = jniLookup<
              ffi
              .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
          "set_Fields__name")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();

  /// from: static public java.lang.String name
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JString get name => _get_name().object(const jni.JStringType());

  /// from: static public java.lang.String name
  /// The returned object must be released after use, by calling the [release] method.
  static set name(jni.JString value) =>
      _set_name(value.reference.pointer).check();

  static final _get_i = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                jni.JObjectPtr,
              )>>("get_Fields__i")
      .asFunction<
          jni.JniResult Function(
            jni.JObjectPtr,
          )>();

  static final _set_i = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  jni.JObjectPtr, ffi.Pointer<ffi.Void>)>>("set_Fields__i")
      .asFunction<
          jni.JniResult Function(jni.JObjectPtr, ffi.Pointer<ffi.Void>)>();

  /// from: public java.lang.Integer i
  /// The returned object must be released after use, by calling the [release] method.
  jni.JInteger get i =>
      _get_i(reference.pointer).object(const jni.JIntegerType());

  /// from: public java.lang.Integer i
  /// The returned object must be released after use, by calling the [release] method.
  set i(jni.JInteger value) =>
      _set_i(reference.pointer, value.reference.pointer).check();

  static final _get_trillion = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                jni.JObjectPtr,
              )>>("get_Fields__trillion")
      .asFunction<
          jni.JniResult Function(
            jni.JObjectPtr,
          )>();

  static final _set_trillion = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  jni.JObjectPtr, ffi.Int64)>>("set_Fields__trillion")
      .asFunction<jni.JniResult Function(jni.JObjectPtr, int)>();

  /// from: public long trillion
  int get trillion => _get_trillion(reference.pointer).long;

  /// from: public long trillion
  set trillion(int value) => _set_trillion(reference.pointer, value).check();

  static final _get_isAchillesDead = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                jni.JObjectPtr,
              )>>("get_Fields__isAchillesDead")
      .asFunction<
          jni.JniResult Function(
            jni.JObjectPtr,
          )>();

  static final _set_isAchillesDead = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  jni.JObjectPtr, ffi.Uint8)>>("set_Fields__isAchillesDead")
      .asFunction<jni.JniResult Function(jni.JObjectPtr, int)>();

  /// from: public boolean isAchillesDead
  bool get isAchillesDead => _get_isAchillesDead(reference.pointer).boolean;

  /// from: public boolean isAchillesDead
  set isAchillesDead(bool value) =>
      _set_isAchillesDead(reference.pointer, value ? 1 : 0).check();

  static final _get_bestFighterInGreece = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                jni.JObjectPtr,
              )>>("get_Fields__bestFighterInGreece")
      .asFunction<
          jni.JniResult Function(
            jni.JObjectPtr,
          )>();

  static final _set_bestFighterInGreece = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(jni.JObjectPtr,
                  ffi.Pointer<ffi.Void>)>>("set_Fields__bestFighterInGreece")
      .asFunction<
          jni.JniResult Function(jni.JObjectPtr, ffi.Pointer<ffi.Void>)>();

  /// from: public java.lang.String bestFighterInGreece
  /// The returned object must be released after use, by calling the [release] method.
  jni.JString get bestFighterInGreece =>
      _get_bestFighterInGreece(reference.pointer)
          .object(const jni.JStringType());

  /// from: public java.lang.String bestFighterInGreece
  /// The returned object must be released after use, by calling the [release] method.
  set bestFighterInGreece(jni.JString value) =>
      _set_bestFighterInGreece(reference.pointer, value.reference.pointer)
          .check();

  static final _get_random = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                jni.JObjectPtr,
              )>>("get_Fields__random")
      .asFunction<
          jni.JniResult Function(
            jni.JObjectPtr,
          )>();

  static final _set_random = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  jni.JObjectPtr, ffi.Pointer<ffi.Void>)>>("set_Fields__random")
      .asFunction<
          jni.JniResult Function(jni.JObjectPtr, ffi.Pointer<ffi.Void>)>();

  /// from: public java.util.Random random
  /// The returned object must be released after use, by calling the [release] method.
  jni.JObject get random =>
      _get_random(reference.pointer).object(const jni.JObjectType());

  /// from: public java.util.Random random
  /// The returned object must be released after use, by calling the [release] method.
  set random(jni.JObject value) =>
      _set_random(reference.pointer, value.reference.pointer).check();

  static final _get_euroSymbol =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "get_Fields__euroSymbol")
          .asFunction<jni.JniResult Function()>();

  static final _set_euroSymbol =
      jniLookup<ffi.NativeFunction<jni.JniResult Function(ffi.Uint16)>>(
              "set_Fields__euroSymbol")
          .asFunction<jni.JniResult Function(int)>();

  /// from: static public char euroSymbol
  static int get euroSymbol => _get_euroSymbol().char;

  /// from: static public char euroSymbol
  static set euroSymbol(int value) => _set_euroSymbol(value).check();

  static final _new0 =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>("Fields__new0")
          .asFunction<jni.JniResult Function()>();

  /// from: public void <init>()
  /// The returned object must be released after use, by calling the [release] method.
  factory Fields() {
    return Fields.fromReference(_new0().reference);
  }
}

final class $FieldsType extends jni.JObjType<Fields> {
  const $FieldsType();

  @override
  String get signature =>
      r"Lcom/github/dart_lang/jnigen/simple_package/Fields;";

  @override
  Fields fromReference(jni.JReference reference) =>
      Fields.fromReference(reference);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode => ($FieldsType).hashCode;

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($FieldsType) && other is $FieldsType;
  }
}

/// from: com.github.dart_lang.jnigen.simple_package.Fields$Nested
class Fields_Nested extends jni.JObject {
  @override
  late final jni.JObjType<Fields_Nested> $type = type;

  Fields_Nested.fromReference(
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// The type which includes information such as the signature of this class.
  static const type = $Fields_NestedType();
  static final _get_hundred = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                jni.JObjectPtr,
              )>>("get_Fields_Nested__hundred")
      .asFunction<
          jni.JniResult Function(
            jni.JObjectPtr,
          )>();

  static final _set_hundred = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  jni.JObjectPtr, ffi.Int64)>>("set_Fields_Nested__hundred")
      .asFunction<jni.JniResult Function(jni.JObjectPtr, int)>();

  /// from: public long hundred
  int get hundred => _get_hundred(reference.pointer).long;

  /// from: public long hundred
  set hundred(int value) => _set_hundred(reference.pointer, value).check();

  static final _get_BEST_GOD =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "get_Fields_Nested__BEST_GOD")
          .asFunction<jni.JniResult Function()>();

  static final _set_BEST_GOD = jniLookup<
              ffi
              .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
          "set_Fields_Nested__BEST_GOD")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();

  /// from: static public java.lang.String BEST_GOD
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JString get BEST_GOD =>
      _get_BEST_GOD().object(const jni.JStringType());

  /// from: static public java.lang.String BEST_GOD
  /// The returned object must be released after use, by calling the [release] method.
  static set BEST_GOD(jni.JString value) =>
      _set_BEST_GOD(value.reference.pointer).check();

  static final _new0 = jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
          "Fields_Nested__new0")
      .asFunction<jni.JniResult Function()>();

  /// from: public void <init>()
  /// The returned object must be released after use, by calling the [release] method.
  factory Fields_Nested() {
    return Fields_Nested.fromReference(_new0().reference);
  }
}

final class $Fields_NestedType extends jni.JObjType<Fields_Nested> {
  const $Fields_NestedType();

  @override
  String get signature =>
      r"Lcom/github/dart_lang/jnigen/simple_package/Fields$Nested;";

  @override
  Fields_Nested fromReference(jni.JReference reference) =>
      Fields_Nested.fromReference(reference);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode => ($Fields_NestedType).hashCode;

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($Fields_NestedType) &&
        other is $Fields_NestedType;
  }
}

/// from: com.github.dart_lang.jnigen.generics.GenericTypeParams
class GenericTypeParams<$S extends jni.JObject, $K extends jni.JObject>
    extends jni.JObject {
  @override
  late final jni.JObjType<GenericTypeParams<$S, $K>> $type = type(S, K);

  final jni.JObjType<$S> S;
  final jni.JObjType<$K> K;

  GenericTypeParams.fromReference(
    this.S,
    this.K,
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// The type which includes information such as the signature of this class.
  static $GenericTypeParamsType<$S, $K>
      type<$S extends jni.JObject, $K extends jni.JObject>(
    jni.JObjType<$S> S,
    jni.JObjType<$K> K,
  ) {
    return $GenericTypeParamsType(
      S,
      K,
    );
  }

  static final _new0 = jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
          "GenericTypeParams__new0")
      .asFunction<jni.JniResult Function()>();

  /// from: public void <init>()
  /// The returned object must be released after use, by calling the [release] method.
  factory GenericTypeParams({
    required jni.JObjType<$S> S,
    required jni.JObjType<$K> K,
  }) {
    return GenericTypeParams.fromReference(S, K, _new0().reference);
  }
}

final class $GenericTypeParamsType<$S extends jni.JObject,
    $K extends jni.JObject> extends jni.JObjType<GenericTypeParams<$S, $K>> {
  final jni.JObjType<$S> S;
  final jni.JObjType<$K> K;

  const $GenericTypeParamsType(
    this.S,
    this.K,
  );

  @override
  String get signature =>
      r"Lcom/github/dart_lang/jnigen/generics/GenericTypeParams;";

  @override
  GenericTypeParams<$S, $K> fromReference(jni.JReference reference) =>
      GenericTypeParams.fromReference(S, K, reference);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode => Object.hash($GenericTypeParamsType, S, K);

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($GenericTypeParamsType<$S, $K>) &&
        other is $GenericTypeParamsType<$S, $K> &&
        S == other.S &&
        K == other.K;
  }
}

/// from: com.github.dart_lang.jnigen.generics.StringMap
class StringMap extends StringKeyedMap<jni.JString> {
  @override
  late final jni.JObjType<StringMap> $type = type;

  StringMap.fromReference(
    jni.JReference reference,
  ) : super.fromReference(const jni.JStringType(), reference);

  /// The type which includes information such as the signature of this class.
  static const type = $StringMapType();
  static final _new0 =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>("StringMap__new0")
          .asFunction<jni.JniResult Function()>();

  /// from: public void <init>()
  /// The returned object must be released after use, by calling the [release] method.
  factory StringMap() {
    return StringMap.fromReference(_new0().reference);
  }
}

final class $StringMapType extends jni.JObjType<StringMap> {
  const $StringMapType();

  @override
  String get signature => r"Lcom/github/dart_lang/jnigen/generics/StringMap;";

  @override
  StringMap fromReference(jni.JReference reference) =>
      StringMap.fromReference(reference);

  @override
  jni.JObjType get superType => const $StringKeyedMapType(jni.JStringType());

  @override
  final superCount = 3;

  @override
  int get hashCode => ($StringMapType).hashCode;

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($StringMapType) && other is $StringMapType;
  }
}
