// 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

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.fromRef(
    jni.JObjectPtr ref,
  ) : super.fromRef(ref);

  /// 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.fromRef(_new0().object);
  }
}

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 fromRef(jni.JObjectPtr ref) =>
      Example_Nested_NestedTwice.fromRef(ref);

  @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.fromRef(
    jni.JObjectPtr ref,
  ) : super.fromRef(ref);

  /// 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.fromRef(_new0(value ? 1 : 0).object);
  }

  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() {
    return _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,
  ) {
    return _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 fromRef(jni.JObjectPtr ref) => Example_Nested.fromRef(ref);

  @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.fromRef(
    jni.JObjectPtr ref,
  ) : super.fromRef(ref);

  /// 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.fromRef(
        _new0($parent.reference.pointer).object);
  }
}

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 fromRef(jni.JObjectPtr ref) =>
      Example_NonStaticNested.fromRef(ref);

  @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.fromRef(
    jni.JObjectPtr ref,
  ) : super.fromRef(ref);

  /// 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 =>
      const jni.JStringType().fromRef(_get_SEMICOLON_STRING().object);

  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 =>
      const jni.JObjectType().fromRef(_get_unusedRandom().object);

  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 => const jni.JObjectType()
      .fromRef(_get_protectedField(reference.pointer).object);

  /// 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 const jni.JStringType().fromRef(_getName().object);
  }

  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 const $Example_NestedType().fromRef(_getNestedInstance().object);
  }

  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,
  ) {
    return _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,
  ) {
    return _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,
  ) {
    return _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,
  ) {
    return _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,
  ) {
    return _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 const jni.JStringType()
        .fromRef(_getCodename(reference.pointer).object);
  }

  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,
  ) {
    return _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 const jni.JObjectType()
        .fromRef(_getRandom(reference.pointer).object);
  }

  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,
  ) {
    return _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 const jni.JStringType().fromRef(
        _getRandomNumericString(reference.pointer, random.reference.pointer)
            .object);
  }

  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,
  ) {
    return _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() {
    return _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 const jni.JListType(jni.JStringType())
        .fromRef(_getList(reference.pointer).object);
  }

  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 const jni.JStringType().fromRef(_joinStrings(reference.pointer,
            values.reference.pointer, delim.reference.pointer)
        .object);
  }

  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>;
    return _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.fromRef(_new0().object);
  }

  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.fromRef(_new1(number).object);
  }

  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.fromRef(_new2(number, isUp ? 1 : 0).object);
  }

  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.fromRef(
        _new3(number, isUp ? 1 : 0, codename.reference.pointer).object);
  }

  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.fromRef(_new4(a, b, c, d, e, f, g, h).object);
  }

  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 const jni.JArrayType(jni.jintType()).fromRef(_getArr().object);
  }

  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 const $ExampleType().fromRef(_getSelf(reference.pointer).object);
  }

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

  /// from: static public void throwException()
  static void throwException() {
    return _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() {
    return _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,
  ) {
    return _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,
  ) {
    return _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,
  ) {
    return _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,
  ) {
    return _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 fromRef(jni.JObjectPtr ref) => Example.fromRef(ref);

  @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.fromRef(
    jni.JObjectPtr ref,
  ) : super.fromRef(ref);

  /// 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.fromRef(_new0().object);
  }
}

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

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

  @override
  C2 fromRef(jni.JObjectPtr ref) => C2.fromRef(ref);

  @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.fromRef(
    jni.JObjectPtr ref,
  ) : super.fromRef(ref);

  /// 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.fromRef(_new0().object);
  }

  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 fromRef(jni.JObjectPtr ref) => Example1.fromRef(ref);

  @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.fromRef(
    this.T,
    this.S,
    this.U,
    jni.JObjectPtr ref,
  ) : super.fromRef(ref);

  /// 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 =>
      T.fromRef(_get_grandParentValue(reference.pointer).object);

  /// 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 => S.fromRef(_get_parentValue(reference.pointer).object);

  /// 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 => U.fromRef(_get_value(reference.pointer).object);

  /// 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.fromRef(T, S, U,
        _new0($parent.reference.pointer, newValue.reference.pointer).object);
  }
}

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> fromRef(jni.JObjectPtr ref) =>
      GrandParent_Parent_Child.fromRef(T, S, U, ref);

  @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.fromRef(
    this.T,
    this.S,
    jni.JObjectPtr ref,
  ) : super.fromRef(ref);

  /// 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 => T.fromRef(_get_parentValue(reference.pointer).object);

  /// 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 => S.fromRef(_get_value(reference.pointer).object);

  /// 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.fromRef(T, S,
        _new0($parent.reference.pointer, newValue.reference.pointer).object);
  }
}

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> fromRef(jni.JObjectPtr ref) =>
      GrandParent_Parent.fromRef(T, S, ref);

  @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.fromRef(
    this.S,
    this.U,
    jni.JObjectPtr ref,
  ) : super.fromRef(ref);

  /// 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 => S.fromRef(_get_parentValue(reference.pointer).object);

  /// 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 => U.fromRef(_get_value(reference.pointer).object);

  /// 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.fromRef(
        S,
        U,
        _new0($parent.reference.pointer, parentValue.reference.pointer,
                value.reference.pointer)
            .object);
  }
}

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> fromRef(jni.JObjectPtr ref) =>
      GrandParent_StaticParent_Child.fromRef(S, U, ref);

  @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.fromRef(
    this.S,
    jni.JObjectPtr ref,
  ) : super.fromRef(ref);

  /// 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 => S.fromRef(_get_value(reference.pointer).object);

  /// 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.fromRef(
        S, _new0(value.reference.pointer).object);
  }
}

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> fromRef(jni.JObjectPtr ref) =>
      GrandParent_StaticParent.fromRef(S, ref);

  @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.fromRef(
    this.T,
    jni.JObjectPtr ref,
  ) : super.fromRef(ref);

  /// 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 => T.fromRef(_get_value(reference.pointer).object);

  /// 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.fromRef(T, _new0(value.reference.pointer).object);
  }

  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 const $GrandParent_ParentType(jni.JObjectType(), jni.JStringType())
        .fromRef(_stringParent(reference.pointer).object);
  }

  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 $GrandParent_ParentType(const jni.JObjectType(), S).fromRef(
        _varParent(reference.pointer, nestedValue.reference.pointer).object);
  }

  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 const $GrandParent_StaticParentType(jni.JStringType())
        .fromRef(_stringStaticParent().object);
  }

  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 $GrandParent_StaticParentType(S)
        .fromRef(_varStaticParent(value.reference.pointer).object);
  }

  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 $GrandParent_StaticParentType(T)
        .fromRef(_staticParentWithSameType(reference.pointer).object);
  }
}

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> fromRef(jni.JObjectPtr ref) => GrandParent.fromRef(T, ref);

  @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.fromRef(
    this.K,
    this.V,
    jni.JObjectPtr ref,
  ) : super.fromRef(ref);

  /// 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 => K.fromRef(_get_key(reference.pointer).object);

  /// 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 => V.fromRef(_get_value(reference.pointer).object);

  /// 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.fromRef(
        K,
        V,
        _new0($parent.reference.pointer, key.reference.pointer,
                value.reference.pointer)
            .object);
  }
}

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> fromRef(jni.JObjectPtr ref) =>
      MyMap_MyEntry.fromRef(K, V, ref);

  @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.fromRef(
    this.K,
    this.V,
    jni.JObjectPtr ref,
  ) : super.fromRef(ref);

  /// 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.fromRef(K, V, _new0().object);
  }

  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 V.fromRef(_get0(reference.pointer, key.reference.pointer).object);
  }

  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 V.fromRef(
        _put(reference.pointer, key.reference.pointer, value.reference.pointer)
            .object);
  }

  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 const $MyStackType(
            $MyMap_MyEntryType(jni.JObjectType(), jni.JObjectType()))
        .fromRef(_entryStack(reference.pointer).object);
  }
}

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> fromRef(jni.JObjectPtr ref) => MyMap.fromRef(K, V, ref);

  @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.fromRef(
    this.T,
    jni.JObjectPtr ref,
  ) : super.fromRef(ref);

  /// 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.fromRef(T, _new0().object);
  }

  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 $MyStackType(T).fromRef(_fromArray(arr.reference.pointer).object);
  }

  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 $MyStackType(S)
        .fromRef(_fromArrayOfArrayOfGrandParents(arr.reference.pointer).object);
  }

  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 $MyStackType(T).fromRef(_of().object);
  }

  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 $MyStackType(T).fromRef(_of1(obj.reference.pointer).object);
  }

  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 $MyStackType(T)
        .fromRef(_of2(obj.reference.pointer, obj2.reference.pointer).object);
  }

  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,
  ) {
    return _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 T.fromRef(_pop(reference.pointer).object);
  }

  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> fromRef(jni.JObjectPtr ref) => MyStack.fromRef(T, ref);

  @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.fromRef(
    this.V,
    jni.JObjectPtr ref,
  ) : super.fromRef(const jni.JStringType(), V, ref);

  /// 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.fromRef(V, _new0().object);
  }
}

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> fromRef(jni.JObjectPtr ref) =>
      StringKeyedMap.fromRef(V, ref);

  @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.fromRef(
    jni.JObjectPtr ref,
  ) : super.fromRef(const jni.JStringType(), ref);

  /// 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.fromRef(_new0().object);
  }
}

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

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

  @override
  StringStack fromRef(jni.JObjectPtr ref) => StringStack.fromRef(ref);

  @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.fromRef(
    this.K,
    jni.JObjectPtr ref,
  ) : super.fromRef(K, const jni.JStringType(), ref);

  /// 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.fromRef(K, _new0().object);
  }
}

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> fromRef(jni.JObjectPtr ref) =>
      StringValuedMap.fromRef(K, ref);

  @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.fromRef(
    this.T,
    jni.JObjectPtr ref,
  ) : super.fromRef(ref);

  /// 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,
  ) {
    return _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 const jni.JStringType().fromRef(
        _stringCallback(reference.pointer, s.reference.pointer).object);
  }

  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 T
        .fromRef(_varCallback(reference.pointer, t.reference.pointer).object);
  }

  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.fromRef(
      $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> fromRef(jni.JObjectPtr ref) => MyInterface.fromRef(T, ref);

  @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.fromRef(
    jni.JObjectPtr ref,
  ) : super.fromRef(ref);

  /// 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.fromRef(_new0().object);
  }

  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>;
    return _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>;
    return _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 fromRef(jni.JObjectPtr ref) =>
      MyInterfaceConsumer.fromRef(ref);

  @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.fromRef(
    jni.JObjectPtr ref,
  ) : super.fromRef(ref);

  /// 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() {
    return _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.fromRef(
      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 fromRef(jni.JObjectPtr ref) => MyRunnable.fromRef(ref);

  @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.fromRef(
    jni.JObjectPtr ref,
  ) : super.fromRef(ref);

  /// 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 =>
      const jni.JObjectType().fromRef(_get_error(reference.pointer).object);

  /// 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.fromRef(_new0(runnable.reference.pointer).object);
  }

  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() {
    return _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() {
    return _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 fromRef(jni.JObjectPtr ref) => MyRunnableRunner.fromRef(ref);

  @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.fromRef(
    jni.JObjectPtr ref,
  ) : super.fromRef(ref);

  /// 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 const jni.JArrayType($JsonSerializable_CaseType())
        .fromRef(_values().object);
  }

  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 const $JsonSerializable_CaseType()
        .fromRef(_valueOf(name.reference.pointer).object);
  }
}

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 fromRef(jni.JObjectPtr ref) =>
      JsonSerializable_Case.fromRef(ref);

  @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.fromRef(
    jni.JObjectPtr ref,
  ) : super.fromRef(ref);

  /// 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 const $JsonSerializable_CaseType()
        .fromRef(_value(reference.pointer).object);
  }

  /// 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.fromRef(
      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 fromRef(jni.JObjectPtr ref) => JsonSerializable.fromRef(ref);

  @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.fromRef(
    jni.JObjectPtr ref,
  ) : super.fromRef(ref);

  /// 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.fromRef(_new0().object);
  }
}

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

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

  @override
  MyDataClass fromRef(jni.JObjectPtr ref) => MyDataClass.fromRef(ref);

  @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.fromRef(
    jni.JObjectPtr ref,
  ) : super.fromRef(ref);

  /// 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 const jni.JArrayType($ColorType()).fromRef(_values().object);
  }

  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 const $ColorType().fromRef(_valueOf(name.reference.pointer).object);
  }
}

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

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

  @override
  Color fromRef(jni.JObjectPtr ref) => Color.fromRef(ref);

  @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.fromRef(
    jni.JObjectPtr ref,
  ) : super.fromRef(ref);

  /// 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.fromRef(_new0().object);
  }

  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.fromRef(_new1(x).object);
  }

  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.fromRef(_new2(a, b, c, d, e, f).object);
  }

  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 const jni.JObjectType().fromRef(_staticObjectMethod().object);
  }

  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 const jni.JArrayType(jni.JObjectType())
        .fromRef(_staticObjectArrayMethod().object);
  }

  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 const jni.JArrayType(jni.jintType())
        .fromRef(_staticIntArrayMethod().object);
  }

  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 const jni.JObjectType()
        .fromRef(_objectMethod(reference.pointer).object);
  }

  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 const jni.JArrayType(jni.JObjectType())
        .fromRef(_objectArrayMethod(reference.pointer).object);
  }

  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 const jni.JArrayType(jni.jintType())
        .fromRef(_intArrayMethod(reference.pointer).object);
  }

  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 const jni.JObjectType()
        .fromRef(_throwFileNotFoundException(reference.pointer).object);
  }

  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 const jni.JObjectType()
        .fromRef(_throwClassCastException(reference.pointer).object);
  }

  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() {
    return _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 fromRef(jni.JObjectPtr ref) => Exceptions.fromRef(ref);

  @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.fromRef(
    jni.JObjectPtr ref,
  ) : super.fromRef(ref);

  /// 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 =>
      const jni.JStringType().fromRef(_get_name().object);

  /// 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 =>
      const jni.JIntegerType().fromRef(_get_i(reference.pointer).object);

  /// 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 => const jni.JStringType()
      .fromRef(_get_bestFighterInGreece(reference.pointer).object);

  /// 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 =>
      const jni.JObjectType().fromRef(_get_random(reference.pointer).object);

  /// 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.fromRef(_new0().object);
  }
}

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

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

  @override
  Fields fromRef(jni.JObjectPtr ref) => Fields.fromRef(ref);

  @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.fromRef(
    jni.JObjectPtr ref,
  ) : super.fromRef(ref);

  /// 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 =>
      const jni.JStringType().fromRef(_get_BEST_GOD().object);

  /// 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.fromRef(_new0().object);
  }
}

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 fromRef(jni.JObjectPtr ref) => Fields_Nested.fromRef(ref);

  @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.fromRef(
    this.S,
    this.K,
    jni.JObjectPtr ref,
  ) : super.fromRef(ref);

  /// 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.fromRef(S, K, _new0().object);
  }
}

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> fromRef(jni.JObjectPtr ref) =>
      GenericTypeParams.fromRef(S, K, ref);

  @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.fromRef(
    jni.JObjectPtr ref,
  ) : super.fromRef(const jni.JStringType(), ref);

  /// 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.fromRef(_new0().object);
  }
}

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

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

  @override
  StringMap fromRef(jni.JObjectPtr ref) => StringMap.fromRef(ref);

  @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;
  }
}
