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

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

  static final _class = jni.Jni.findJClass(
      r"com/github/dart_lang/jnigen/simple_package/Example$Nested$NestedTwice");

  /// The type which includes information such as the signature of this class.
  static const type = $Example_Nested_NestedTwiceType();
  static final _id_ZERO = jni.Jni.accessors.getStaticFieldIDOf(
    _class.reference.pointer,
    r"ZERO",
    r"I",
  );

  /// from: static public int ZERO
  static int get ZERO => jni.Jni.accessors
      .getStaticField(
          _class.reference.pointer, _id_ZERO, jni.JniCallType.intType)
      .integer;

  /// from: static public int ZERO
  static set ZERO(int value) =>
      jni.Jni.env.SetStaticIntField(_class.reference.pointer, _id_ZERO, value);

  static final _id_new0 = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"<init>", r"()V");

  /// 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(jni.Jni.accessors
        .newObjectWithArgs(_class.reference.pointer, _id_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);

  static final _class = jni.Jni.findJClass(
      r"com/github/dart_lang/jnigen/simple_package/Example$Nested");

  /// The type which includes information such as the signature of this class.
  static const type = $Example_NestedType();
  static final _id_new0 = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"<init>", r"(Z)V");

  /// 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(jni.Jni.accessors.newObjectWithArgs(
        _class.reference.pointer, _id_new0, [value ? 1 : 0]).object);
  }

  static final _id_usesAnonymousInnerClass = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer, r"usesAnonymousInnerClass", r"()V");

  /// from: public void usesAnonymousInnerClass()
  void usesAnonymousInnerClass() {
    return jni.Jni.accessors.callMethodWithArgs(reference.pointer,
        _id_usesAnonymousInnerClass, jni.JniCallType.voidType, []).check();
  }

  static final _id_getValue = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"getValue", r"()Z");

  /// from: public boolean getValue()
  bool getValue() {
    return jni.Jni.accessors.callMethodWithArgs(reference.pointer, _id_getValue,
        jni.JniCallType.booleanType, []).boolean;
  }

  static final _id_setValue = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"setValue", r"(Z)V");

  /// from: public void setValue(boolean value)
  void setValue(
    bool value,
  ) {
    return jni.Jni.accessors.callMethodWithArgs(reference.pointer, _id_setValue,
        jni.JniCallType.voidType, [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);

  static final _class = jni.Jni.findJClass(
      r"com/github/dart_lang/jnigen/simple_package/Example$NonStaticNested");

  /// The type which includes information such as the signature of this class.
  static const type = $Example_NonStaticNestedType();
  static final _id_ok = jni.Jni.accessors.getFieldIDOf(
    _class.reference.pointer,
    r"ok",
    r"Z",
  );

  /// from: public boolean ok
  bool get ok => jni.Jni.accessors
      .getField(reference.pointer, _id_ok, jni.JniCallType.booleanType)
      .boolean;

  /// from: public boolean ok
  set ok(bool value) =>
      jni.Jni.env.SetBooleanField(reference.pointer, _id_ok, value ? 1 : 0);

  static final _id_new0 = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"<init>",
      r"(Lcom/github/dart_lang/jnigen/simple_package/Example;)V");

  /// 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(jni.Jni.accessors.newObjectWithArgs(
        _class.reference.pointer,
        _id_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);

  static final _class =
      jni.Jni.findJClass(r"com/github/dart_lang/jnigen/simple_package/Example");

  /// 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 _id_SEMICOLON_STRING = jni.Jni.accessors.getStaticFieldIDOf(
    _class.reference.pointer,
    r"SEMICOLON_STRING",
    r"Ljava/lang/String;",
  );

  /// 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(jni.Jni.accessors
          .getStaticField(_class.reference.pointer, _id_SEMICOLON_STRING,
              jni.JniCallType.objectType)
          .object);

  static final _id_unusedRandom = jni.Jni.accessors.getStaticFieldIDOf(
    _class.reference.pointer,
    r"unusedRandom",
    r"Ljava/util/Random;",
  );

  /// 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(jni.Jni.accessors
          .getStaticField(_class.reference.pointer, _id_unusedRandom,
              jni.JniCallType.objectType)
          .object);

  static final _id_protectedField = jni.Jni.accessors.getFieldIDOf(
    _class.reference.pointer,
    r"protectedField",
    r"Ljava/util/Random;",
  );

  /// 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(jni.Jni.accessors
          .getField(
              reference.pointer, _id_protectedField, jni.JniCallType.objectType)
          .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) => jni.Jni.env.SetObjectField(
      reference.pointer, _id_protectedField, value.reference.pointer);

  static final _id_getAmount = jni.Jni.accessors
      .getStaticMethodIDOf(_class.reference.pointer, r"getAmount", r"()I");

  /// from: static public int getAmount()
  static int getAmount() {
    return jni.Jni.accessors.callStaticMethodWithArgs(_class.reference.pointer,
        _id_getAmount, jni.JniCallType.intType, []).integer;
  }

  static final _id_getPi = jni.Jni.accessors
      .getStaticMethodIDOf(_class.reference.pointer, r"getPi", r"()D");

  /// from: static public double getPi()
  static double getPi() {
    return jni.Jni.accessors.callStaticMethodWithArgs(_class.reference.pointer,
        _id_getPi, jni.JniCallType.doubleType, []).doubleFloat;
  }

  static final _id_getAsterisk = jni.Jni.accessors
      .getStaticMethodIDOf(_class.reference.pointer, r"getAsterisk", r"()C");

  /// from: static public char getAsterisk()
  static int getAsterisk() {
    return jni.Jni.accessors.callStaticMethodWithArgs(_class.reference.pointer,
        _id_getAsterisk, jni.JniCallType.charType, []).char;
  }

  static final _id_getName = jni.Jni.accessors.getStaticMethodIDOf(
      _class.reference.pointer, r"getName", r"()Ljava/lang/String;");

  /// 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(jni.Jni.accessors
        .callStaticMethodWithArgs(_class.reference.pointer, _id_getName,
            jni.JniCallType.objectType, []).object);
  }

  static final _id_getNestedInstance = jni.Jni.accessors.getStaticMethodIDOf(
      _class.reference.pointer,
      r"getNestedInstance",
      r"()Lcom/github/dart_lang/jnigen/simple_package/Example$Nested;");

  /// 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(jni.Jni.accessors
        .callStaticMethodWithArgs(_class.reference.pointer,
            _id_getNestedInstance, jni.JniCallType.objectType, []).object);
  }

  static final _id_setAmount = jni.Jni.accessors
      .getStaticMethodIDOf(_class.reference.pointer, r"setAmount", r"(I)V");

  /// from: static public void setAmount(int newAmount)
  static void setAmount(
    int newAmount,
  ) {
    return jni.Jni.accessors.callStaticMethodWithArgs(
        _class.reference.pointer,
        _id_setAmount,
        jni.JniCallType.voidType,
        [jni.JValueInt(newAmount)]).check();
  }

  static final _id_setName = jni.Jni.accessors.getStaticMethodIDOf(
      _class.reference.pointer, r"setName", r"(Ljava/lang/String;)V");

  /// from: static public void setName(java.lang.String newName)
  static void setName(
    jni.JString newName,
  ) {
    return jni.Jni.accessors.callStaticMethodWithArgs(
        _class.reference.pointer,
        _id_setName,
        jni.JniCallType.voidType,
        [newName.reference.pointer]).check();
  }

  static final _id_setNestedInstance = jni.Jni.accessors.getStaticMethodIDOf(
      _class.reference.pointer,
      r"setNestedInstance",
      r"(Lcom/github/dart_lang/jnigen/simple_package/Example$Nested;)V");

  /// from: static public void setNestedInstance(com.github.dart_lang.jnigen.simple_package.Example.Nested newNested)
  static void setNestedInstance(
    Example_Nested newNested,
  ) {
    return jni.Jni.accessors.callStaticMethodWithArgs(
        _class.reference.pointer,
        _id_setNestedInstance,
        jni.JniCallType.voidType,
        [newNested.reference.pointer]).check();
  }

  static final _id_max4 = jni.Jni.accessors
      .getStaticMethodIDOf(_class.reference.pointer, r"max4", r"(IIII)I");

  /// 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 jni.Jni.accessors.callStaticMethodWithArgs(
        _class.reference.pointer, _id_max4, jni.JniCallType.intType, [
      jni.JValueInt(a),
      jni.JValueInt(b),
      jni.JValueInt(c),
      jni.JValueInt(d)
    ]).integer;
  }

  static final _id_max8 = jni.Jni.accessors
      .getStaticMethodIDOf(_class.reference.pointer, r"max8", r"(IIIIIIII)I");

  /// 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 jni.Jni.accessors.callStaticMethodWithArgs(
        _class.reference.pointer, _id_max8, jni.JniCallType.intType, [
      jni.JValueInt(a),
      jni.JValueInt(b),
      jni.JValueInt(c),
      jni.JValueInt(d),
      jni.JValueInt(e),
      jni.JValueInt(f),
      jni.JValueInt(g),
      jni.JValueInt(h)
    ]).integer;
  }

  static final _id_getNumber = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"getNumber", r"()I");

  /// from: public int getNumber()
  int getNumber() {
    return jni.Jni.accessors.callMethodWithArgs(
        reference.pointer, _id_getNumber, jni.JniCallType.intType, []).integer;
  }

  static final _id_setNumber = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"setNumber", r"(I)V");

  /// from: public void setNumber(int number)
  void setNumber(
    int number,
  ) {
    return jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_setNumber,
        jni.JniCallType.voidType,
        [jni.JValueInt(number)]).check();
  }

  static final _id_getIsUp = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"getIsUp", r"()Z");

  /// from: public boolean getIsUp()
  bool getIsUp() {
    return jni.Jni.accessors.callMethodWithArgs(reference.pointer, _id_getIsUp,
        jni.JniCallType.booleanType, []).boolean;
  }

  static final _id_setUp = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"setUp", r"(Z)V");

  /// from: public void setUp(boolean isUp)
  void setUp(
    bool isUp,
  ) {
    return jni.Jni.accessors.callMethodWithArgs(reference.pointer, _id_setUp,
        jni.JniCallType.voidType, [isUp ? 1 : 0]).check();
  }

  static final _id_getCodename = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer, r"getCodename", r"()Ljava/lang/String;");

  /// 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(jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_getCodename,
        jni.JniCallType.objectType, []).object);
  }

  static final _id_setCodename = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer, r"setCodename", r"(Ljava/lang/String;)V");

  /// from: public void setCodename(java.lang.String codename)
  void setCodename(
    jni.JString codename,
  ) {
    return jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_setCodename,
        jni.JniCallType.voidType,
        [codename.reference.pointer]).check();
  }

  static final _id_getRandom = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer, r"getRandom", r"()Ljava/util/Random;");

  /// 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(jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_getRandom,
        jni.JniCallType.objectType, []).object);
  }

  static final _id_setRandom = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer, r"setRandom", r"(Ljava/util/Random;)V");

  /// from: public void setRandom(java.util.Random random)
  void setRandom(
    jni.JObject random,
  ) {
    return jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_setRandom,
        jni.JniCallType.voidType,
        [random.reference.pointer]).check();
  }

  static final _id_getRandomLong = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"getRandomLong", r"()J");

  /// from: public long getRandomLong()
  int getRandomLong() {
    return jni.Jni.accessors.callMethodWithArgs(reference.pointer,
        _id_getRandomLong, jni.JniCallType.longType, []).long;
  }

  static final _id_add4Longs = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"add4Longs", r"(JJJJ)J");

  /// from: public long add4Longs(long a, long b, long c, long d)
  int add4Longs(
    int a,
    int b,
    int c,
    int d,
  ) {
    return jni.Jni.accessors.callMethodWithArgs(reference.pointer,
        _id_add4Longs, jni.JniCallType.longType, [a, b, c, d]).long;
  }

  static final _id_add8Longs = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"add8Longs", r"(JJJJJJJJ)J");

  /// 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 jni.Jni.accessors.callMethodWithArgs(reference.pointer,
        _id_add8Longs, jni.JniCallType.longType, [a, b, c, d, e, f, g, h]).long;
  }

  static final _id_getRandomNumericString = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"getRandomNumericString",
      r"(Ljava/util/Random;)Ljava/lang/String;");

  /// 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(jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_getRandomNumericString,
        jni.JniCallType.objectType,
        [random.reference.pointer]).object);
  }

  static final _id_protectedMethod = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"protectedMethod",
      r"(Ljava/lang/String;Ljava/lang/String;)V");

  /// from: protected void protectedMethod(java.lang.String a, java.lang.String b)
  void protectedMethod(
    jni.JString a,
    jni.JString b,
  ) {
    return jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_protectedMethod,
        jni.JniCallType.voidType,
        [a.reference.pointer, b.reference.pointer]).check();
  }

  static final _id_finalMethod = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"finalMethod", r"()V");

  /// from: public final void finalMethod()
  void finalMethod() {
    return jni.Jni.accessors.callMethodWithArgs(reference.pointer,
        _id_finalMethod, jni.JniCallType.voidType, []).check();
  }

  static final _id_getList = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer, r"getList", r"()Ljava/util/List;");

  /// 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(jni.Jni.accessors
        .callMethodWithArgs(reference.pointer, _id_getList,
            jni.JniCallType.objectType, []).object);
  }

  static final _id_joinStrings = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"joinStrings",
      r"(Ljava/util/List;Ljava/lang/String;)Ljava/lang/String;");

  /// 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(jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_joinStrings,
        jni.JniCallType.objectType,
        [values.reference.pointer, delim.reference.pointer]).object);
  }

  static final _id_methodWithSeveralParams = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"methodWithSeveralParams",
      r"(CLjava/lang/String;[ILjava/lang/CharSequence;Ljava/util/List;Ljava/util/Map;)V");

  /// 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 jni.Jni.accessors.callMethodWithArgs(reference.pointer,
        _id_methodWithSeveralParams, jni.JniCallType.voidType, [
      jni.JValueChar(ch),
      s.reference.pointer,
      a.reference.pointer,
      t.reference.pointer,
      lt.reference.pointer,
      wm.reference.pointer
    ]).check();
  }

  static final _id_new0 = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"<init>", r"()V");

  /// from: public void <init>()
  /// The returned object must be released after use, by calling the [release] method.
  factory Example() {
    return Example.fromRef(jni.Jni.accessors
        .newObjectWithArgs(_class.reference.pointer, _id_new0, []).object);
  }

  static final _id_new1 = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"<init>", r"(I)V");

  /// 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(jni.Jni.accessors.newObjectWithArgs(
        _class.reference.pointer, _id_new1, [jni.JValueInt(number)]).object);
  }

  static final _id_new2 = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"<init>", r"(IZ)V");

  /// 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(jni.Jni.accessors.newObjectWithArgs(
        _class.reference.pointer,
        _id_new2,
        [jni.JValueInt(number), isUp ? 1 : 0]).object);
  }

  static final _id_new3 = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer, r"<init>", r"(IZLjava/lang/String;)V");

  /// 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(jni.Jni.accessors.newObjectWithArgs(
        _class.reference.pointer, _id_new3, [
      jni.JValueInt(number),
      isUp ? 1 : 0,
      codename.reference.pointer
    ]).object);
  }

  static final _id_new4 = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"<init>", r"(IIIIIIII)V");

  /// 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(jni.Jni.accessors
        .newObjectWithArgs(_class.reference.pointer, _id_new4, [
      jni.JValueInt(a),
      jni.JValueInt(b),
      jni.JValueInt(c),
      jni.JValueInt(d),
      jni.JValueInt(e),
      jni.JValueInt(f),
      jni.JValueInt(g),
      jni.JValueInt(h)
    ]).object);
  }

  static final _id_whichExample = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"whichExample", r"()I");

  /// from: public int whichExample()
  int whichExample() {
    return jni.Jni.accessors.callMethodWithArgs(reference.pointer,
        _id_whichExample, jni.JniCallType.intType, []).integer;
  }

  static final _id_addInts = jni.Jni.accessors
      .getStaticMethodIDOf(_class.reference.pointer, r"addInts", r"(II)I");

  /// from: static public int addInts(int a, int b)
  static int addInts(
    int a,
    int b,
  ) {
    return jni.Jni.accessors.callStaticMethodWithArgs(
        _class.reference.pointer,
        _id_addInts,
        jni.JniCallType.intType,
        [jni.JValueInt(a), jni.JValueInt(b)]).integer;
  }

  static final _id_getArr = jni.Jni.accessors
      .getStaticMethodIDOf(_class.reference.pointer, r"getArr", r"()[I");

  /// 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(jni.Jni.accessors
        .callStaticMethodWithArgs(_class.reference.pointer, _id_getArr,
            jni.JniCallType.objectType, []).object);
  }

  static final _id_addAll = jni.Jni.accessors
      .getStaticMethodIDOf(_class.reference.pointer, r"addAll", r"([I)I");

  /// from: static public int addAll(int[] arr)
  static int addAll(
    jni.JArray<jni.jint> arr,
  ) {
    return jni.Jni.accessors.callStaticMethodWithArgs(_class.reference.pointer,
        _id_addAll, jni.JniCallType.intType, [arr.reference.pointer]).integer;
  }

  static final _id_getSelf = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"getSelf",
      r"()Lcom/github/dart_lang/jnigen/simple_package/Example;");

  /// 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(jni.Jni.accessors.callMethodWithArgs(
        reference.pointer, _id_getSelf, jni.JniCallType.objectType, []).object);
  }

  static final _id_throwException = jni.Jni.accessors
      .getStaticMethodIDOf(_class.reference.pointer, r"throwException", r"()V");

  /// from: static public void throwException()
  static void throwException() {
    return jni.Jni.accessors.callStaticMethodWithArgs(_class.reference.pointer,
        _id_throwException, jni.JniCallType.voidType, []).check();
  }

  static final _id_overloaded = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"overloaded", r"()V");

  /// from: public void overloaded()
  void overloaded() {
    return jni.Jni.accessors.callMethodWithArgs(reference.pointer,
        _id_overloaded, jni.JniCallType.voidType, []).check();
  }

  static final _id_overloaded1 = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer, r"overloaded", r"(ILjava/lang/String;)V");

  /// from: public void overloaded(int a, java.lang.String b)
  void overloaded1(
    int a,
    jni.JString b,
  ) {
    return jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_overloaded1,
        jni.JniCallType.voidType,
        [jni.JValueInt(a), b.reference.pointer]).check();
  }

  static final _id_overloaded2 = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"overloaded", r"(I)V");

  /// from: public void overloaded(int a)
  void overloaded2(
    int a,
  ) {
    return jni.Jni.accessors.callMethodWithArgs(reference.pointer,
        _id_overloaded2, jni.JniCallType.voidType, [jni.JValueInt(a)]).check();
  }

  static final _id_overloaded3 = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"overloaded",
      r"(Ljava/util/List;Ljava/lang/String;)V");

  /// 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 jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_overloaded3,
        jni.JniCallType.voidType,
        [a.reference.pointer, b.reference.pointer]).check();
  }

  static final _id_overloaded4 = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer, r"overloaded", r"(Ljava/util/List;)V");

  /// from: public void overloaded(java.util.List<java.lang.Integer> a)
  void overloaded4(
    jni.JList<jni.JInteger> a,
  ) {
    return jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_overloaded4,
        jni.JniCallType.voidType,
        [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);

  static final _class =
      jni.Jni.findJClass(r"com/github/dart_lang/jnigen/pkg2/C2");

  /// The type which includes information such as the signature of this class.
  static const type = $C2Type();
  static final _id_CONSTANT = jni.Jni.accessors.getStaticFieldIDOf(
    _class.reference.pointer,
    r"CONSTANT",
    r"I",
  );

  /// from: static public int CONSTANT
  static int get CONSTANT => jni.Jni.accessors
      .getStaticField(
          _class.reference.pointer, _id_CONSTANT, jni.JniCallType.intType)
      .integer;

  /// from: static public int CONSTANT
  static set CONSTANT(int value) => jni.Jni.env
      .SetStaticIntField(_class.reference.pointer, _id_CONSTANT, value);

  static final _id_new0 = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"<init>", r"()V");

  /// from: public void <init>()
  /// The returned object must be released after use, by calling the [release] method.
  factory C2() {
    return C2.fromRef(jni.Jni.accessors
        .newObjectWithArgs(_class.reference.pointer, _id_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);

  static final _class =
      jni.Jni.findJClass(r"com/github/dart_lang/jnigen/pkg2/Example");

  /// The type which includes information such as the signature of this class.
  static const type = $Example1Type();
  static final _id_new0 = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"<init>", r"()V");

  /// from: public void <init>()
  /// The returned object must be released after use, by calling the [release] method.
  factory Example1() {
    return Example1.fromRef(jni.Jni.accessors
        .newObjectWithArgs(_class.reference.pointer, _id_new0, []).object);
  }

  static final _id_whichExample = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"whichExample", r"()I");

  /// from: public int whichExample()
  int whichExample() {
    return jni.Jni.accessors.callMethodWithArgs(reference.pointer,
        _id_whichExample, jni.JniCallType.intType, []).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);

  static final _class = jni.Jni.findJClass(
      r"com/github/dart_lang/jnigen/generics/GrandParent$Parent$Child");

  /// 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 _id_grandParentValue = jni.Jni.accessors.getFieldIDOf(
    _class.reference.pointer,
    r"grandParentValue",
    r"Ljava/lang/Object;",
  );

  /// from: public T grandParentValue
  /// The returned object must be released after use, by calling the [release] method.
  $T get grandParentValue => T.fromRef(jni.Jni.accessors
      .getField(
          reference.pointer, _id_grandParentValue, jni.JniCallType.objectType)
      .object);

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

  static final _id_parentValue = jni.Jni.accessors.getFieldIDOf(
    _class.reference.pointer,
    r"parentValue",
    r"Ljava/lang/Object;",
  );

  /// from: public S parentValue
  /// The returned object must be released after use, by calling the [release] method.
  $S get parentValue => S.fromRef(jni.Jni.accessors
      .getField(reference.pointer, _id_parentValue, jni.JniCallType.objectType)
      .object);

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

  static final _id_value = jni.Jni.accessors.getFieldIDOf(
    _class.reference.pointer,
    r"value",
    r"Ljava/lang/Object;",
  );

  /// from: public U value
  /// The returned object must be released after use, by calling the [release] method.
  $U get value => U.fromRef(jni.Jni.accessors
      .getField(reference.pointer, _id_value, jni.JniCallType.objectType)
      .object);

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

  static final _id_new0 = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"<init>",
      r"(Lcom/github/dart_lang/jnigen/generics/GrandParent$Parent;Ljava/lang/Object;)V");

  /// 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,
        jni.Jni.accessors.newObjectWithArgs(_class.reference.pointer, _id_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);

  static final _class = jni.Jni.findJClass(
      r"com/github/dart_lang/jnigen/generics/GrandParent$Parent");

  /// 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 _id_parentValue = jni.Jni.accessors.getFieldIDOf(
    _class.reference.pointer,
    r"parentValue",
    r"Ljava/lang/Object;",
  );

  /// from: public T parentValue
  /// The returned object must be released after use, by calling the [release] method.
  $T get parentValue => T.fromRef(jni.Jni.accessors
      .getField(reference.pointer, _id_parentValue, jni.JniCallType.objectType)
      .object);

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

  static final _id_value = jni.Jni.accessors.getFieldIDOf(
    _class.reference.pointer,
    r"value",
    r"Ljava/lang/Object;",
  );

  /// from: public S value
  /// The returned object must be released after use, by calling the [release] method.
  $S get value => S.fromRef(jni.Jni.accessors
      .getField(reference.pointer, _id_value, jni.JniCallType.objectType)
      .object);

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

  static final _id_new0 = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"<init>",
      r"(Lcom/github/dart_lang/jnigen/generics/GrandParent;Ljava/lang/Object;)V");

  /// 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,
        jni.Jni.accessors.newObjectWithArgs(_class.reference.pointer, _id_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);

  static final _class = jni.Jni.findJClass(
      r"com/github/dart_lang/jnigen/generics/GrandParent$StaticParent$Child");

  /// 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 _id_parentValue = jni.Jni.accessors.getFieldIDOf(
    _class.reference.pointer,
    r"parentValue",
    r"Ljava/lang/Object;",
  );

  /// from: public S parentValue
  /// The returned object must be released after use, by calling the [release] method.
  $S get parentValue => S.fromRef(jni.Jni.accessors
      .getField(reference.pointer, _id_parentValue, jni.JniCallType.objectType)
      .object);

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

  static final _id_value = jni.Jni.accessors.getFieldIDOf(
    _class.reference.pointer,
    r"value",
    r"Ljava/lang/Object;",
  );

  /// from: public U value
  /// The returned object must be released after use, by calling the [release] method.
  $U get value => U.fromRef(jni.Jni.accessors
      .getField(reference.pointer, _id_value, jni.JniCallType.objectType)
      .object);

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

  static final _id_new0 = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"<init>",
      r"(Lcom/github/dart_lang/jnigen/generics/GrandParent$StaticParent;Ljava/lang/Object;Ljava/lang/Object;)V");

  /// 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,
        jni.Jni.accessors
            .newObjectWithArgs(_class.reference.pointer, _id_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);

  static final _class = jni.Jni.findJClass(
      r"com/github/dart_lang/jnigen/generics/GrandParent$StaticParent");

  /// 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 _id_value = jni.Jni.accessors.getFieldIDOf(
    _class.reference.pointer,
    r"value",
    r"Ljava/lang/Object;",
  );

  /// from: public S value
  /// The returned object must be released after use, by calling the [release] method.
  $S get value => S.fromRef(jni.Jni.accessors
      .getField(reference.pointer, _id_value, jni.JniCallType.objectType)
      .object);

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

  static final _id_new0 = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer, r"<init>", r"(Ljava/lang/Object;)V");

  /// 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,
        jni.Jni.accessors.newObjectWithArgs(_class.reference.pointer, _id_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);

  static final _class =
      jni.Jni.findJClass(r"com/github/dart_lang/jnigen/generics/GrandParent");

  /// 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 _id_value = jni.Jni.accessors.getFieldIDOf(
    _class.reference.pointer,
    r"value",
    r"Ljava/lang/Object;",
  );

  /// from: public T value
  /// The returned object must be released after use, by calling the [release] method.
  $T get value => T.fromRef(jni.Jni.accessors
      .getField(reference.pointer, _id_value, jni.JniCallType.objectType)
      .object);

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

  static final _id_new0 = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer, r"<init>", r"(Ljava/lang/Object;)V");

  /// 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,
        jni.Jni.accessors.newObjectWithArgs(_class.reference.pointer, _id_new0,
            [value.reference.pointer]).object);
  }

  static final _id_stringParent = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"stringParent",
      r"()Lcom/github/dart_lang/jnigen/generics/GrandParent$Parent;");

  /// 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(jni.Jni.accessors.callMethodWithArgs(reference.pointer,
            _id_stringParent, jni.JniCallType.objectType, []).object);
  }

  static final _id_varParent = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"varParent",
      r"(Ljava/lang/Object;)Lcom/github/dart_lang/jnigen/generics/GrandParent$Parent;");

  /// 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(
        jni.Jni.accessors.callMethodWithArgs(
            reference.pointer,
            _id_varParent,
            jni.JniCallType.objectType,
            [nestedValue.reference.pointer]).object);
  }

  static final _id_stringStaticParent = jni.Jni.accessors.getStaticMethodIDOf(
      _class.reference.pointer,
      r"stringStaticParent",
      r"()Lcom/github/dart_lang/jnigen/generics/GrandParent$StaticParent;");

  /// 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(
        jni.Jni.accessors.callStaticMethodWithArgs(_class.reference.pointer,
            _id_stringStaticParent, jni.JniCallType.objectType, []).object);
  }

  static final _id_varStaticParent = jni.Jni.accessors.getStaticMethodIDOf(
      _class.reference.pointer,
      r"varStaticParent",
      r"(Ljava/lang/Object;)Lcom/github/dart_lang/jnigen/generics/GrandParent$StaticParent;");

  /// 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(jni.Jni.accessors
        .callStaticMethodWithArgs(_class.reference.pointer, _id_varStaticParent,
            jni.JniCallType.objectType, [value.reference.pointer]).object);
  }

  static final _id_staticParentWithSameType = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"staticParentWithSameType",
      r"()Lcom/github/dart_lang/jnigen/generics/GrandParent$StaticParent;");

  /// 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(jni.Jni.accessors
        .callMethodWithArgs(reference.pointer, _id_staticParentWithSameType,
            jni.JniCallType.objectType, []).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);

  static final _class =
      jni.Jni.findJClass(r"com/github/dart_lang/jnigen/generics/MyMap$MyEntry");

  /// 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 _id_key = jni.Jni.accessors.getFieldIDOf(
    _class.reference.pointer,
    r"key",
    r"Ljava/lang/Object;",
  );

  /// from: public K key
  /// The returned object must be released after use, by calling the [release] method.
  $K get key => K.fromRef(jni.Jni.accessors
      .getField(reference.pointer, _id_key, jni.JniCallType.objectType)
      .object);

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

  static final _id_value = jni.Jni.accessors.getFieldIDOf(
    _class.reference.pointer,
    r"value",
    r"Ljava/lang/Object;",
  );

  /// from: public V value
  /// The returned object must be released after use, by calling the [release] method.
  $V get value => V.fromRef(jni.Jni.accessors
      .getField(reference.pointer, _id_value, jni.JniCallType.objectType)
      .object);

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

  static final _id_new0 = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"<init>",
      r"(Lcom/github/dart_lang/jnigen/generics/MyMap;Ljava/lang/Object;Ljava/lang/Object;)V");

  /// 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,
        jni.Jni.accessors.newObjectWithArgs(
            _class.reference.pointer, _id_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);

  static final _class =
      jni.Jni.findJClass(r"com/github/dart_lang/jnigen/generics/MyMap");

  /// 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 _id_new0 = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"<init>", r"()V");

  /// 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,
        jni.Jni.accessors
            .newObjectWithArgs(_class.reference.pointer, _id_new0, []).object);
  }

  static final _id_get0 = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"get",
      r"(Ljava/lang/Object;)Ljava/lang/Object;");

  /// 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(jni.Jni.accessors.callMethodWithArgs(reference.pointer,
        _id_get0, jni.JniCallType.objectType, [key.reference.pointer]).object);
  }

  static final _id_put = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"put",
      r"(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");

  /// 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(jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_put,
        jni.JniCallType.objectType,
        [key.reference.pointer, value.reference.pointer]).object);
  }

  static final _id_entryStack = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"entryStack",
      r"()Lcom/github/dart_lang/jnigen/generics/MyStack;");

  /// 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(jni.Jni.accessors.callMethodWithArgs(reference.pointer,
            _id_entryStack, jni.JniCallType.objectType, []).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);

  static final _class =
      jni.Jni.findJClass(r"com/github/dart_lang/jnigen/generics/MyStack");

  /// 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 _id_new0 = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"<init>", r"()V");

  /// 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,
        jni.Jni.accessors
            .newObjectWithArgs(_class.reference.pointer, _id_new0, []).object);
  }

  static final _id_fromArray = jni.Jni.accessors.getStaticMethodIDOf(
      _class.reference.pointer,
      r"fromArray",
      r"([Ljava/lang/Object;)Lcom/github/dart_lang/jnigen/generics/MyStack;");

  /// 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(jni.Jni.accessors.callStaticMethodWithArgs(
        _class.reference.pointer,
        _id_fromArray,
        jni.JniCallType.objectType,
        [arr.reference.pointer]).object);
  }

  static final _id_fromArrayOfArrayOfGrandParents = jni.Jni.accessors
      .getStaticMethodIDOf(
          _class.reference.pointer,
          r"fromArrayOfArrayOfGrandParents",
          r"([[Lcom/github/dart_lang/jnigen/generics/GrandParent;)Lcom/github/dart_lang/jnigen/generics/MyStack;");

  /// 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(jni.Jni.accessors.callStaticMethodWithArgs(
        _class.reference.pointer,
        _id_fromArrayOfArrayOfGrandParents,
        jni.JniCallType.objectType,
        [arr.reference.pointer]).object);
  }

  static final _id_of = jni.Jni.accessors.getStaticMethodIDOf(
      _class.reference.pointer,
      r"of",
      r"()Lcom/github/dart_lang/jnigen/generics/MyStack;");

  /// 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(jni.Jni.accessors.callStaticMethodWithArgs(
        _class.reference.pointer,
        _id_of,
        jni.JniCallType.objectType, []).object);
  }

  static final _id_of1 = jni.Jni.accessors.getStaticMethodIDOf(
      _class.reference.pointer,
      r"of",
      r"(Ljava/lang/Object;)Lcom/github/dart_lang/jnigen/generics/MyStack;");

  /// 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(jni.Jni.accessors.callStaticMethodWithArgs(
        _class.reference.pointer,
        _id_of1,
        jni.JniCallType.objectType,
        [obj.reference.pointer]).object);
  }

  static final _id_of2 = jni.Jni.accessors.getStaticMethodIDOf(
      _class.reference.pointer,
      r"of",
      r"(Ljava/lang/Object;Ljava/lang/Object;)Lcom/github/dart_lang/jnigen/generics/MyStack;");

  /// 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(jni.Jni.accessors.callStaticMethodWithArgs(
        _class.reference.pointer,
        _id_of2,
        jni.JniCallType.objectType,
        [obj.reference.pointer, obj2.reference.pointer]).object);
  }

  static final _id_push = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer, r"push", r"(Ljava/lang/Object;)V");

  /// from: public void push(T item)
  void push(
    $T item,
  ) {
    return jni.Jni.accessors.callMethodWithArgs(reference.pointer, _id_push,
        jni.JniCallType.voidType, [item.reference.pointer]).check();
  }

  static final _id_pop = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"pop", r"()Ljava/lang/Object;");

  /// from: public T pop()
  /// The returned object must be released after use, by calling the [release] method.
  $T pop() {
    return T.fromRef(jni.Jni.accessors.callMethodWithArgs(
        reference.pointer, _id_pop, jni.JniCallType.objectType, []).object);
  }

  static final _id_size = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"size", r"()I");

  /// from: public int size()
  int size() {
    return jni.Jni.accessors.callMethodWithArgs(
        reference.pointer, _id_size, jni.JniCallType.intType, []).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);

  static final _class = jni.Jni.findJClass(
      r"com/github/dart_lang/jnigen/generics/StringKeyedMap");

  /// 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 _id_new0 = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"<init>", r"()V");

  /// 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,
        jni.Jni.accessors
            .newObjectWithArgs(_class.reference.pointer, _id_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);

  static final _class =
      jni.Jni.findJClass(r"com/github/dart_lang/jnigen/generics/StringStack");

  /// The type which includes information such as the signature of this class.
  static const type = $StringStackType();
  static final _id_new0 = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"<init>", r"()V");

  /// from: public void <init>()
  /// The returned object must be released after use, by calling the [release] method.
  factory StringStack() {
    return StringStack.fromRef(jni.Jni.accessors
        .newObjectWithArgs(_class.reference.pointer, _id_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);

  static final _class = jni.Jni.findJClass(
      r"com/github/dart_lang/jnigen/generics/StringValuedMap");

  /// 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 _id_new0 = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"<init>", r"()V");

  /// 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,
        jni.Jni.accessors
            .newObjectWithArgs(_class.reference.pointer, _id_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);

  static final _class =
      jni.Jni.findJClass(r"com/github/dart_lang/jnigen/interfaces/MyInterface");

  /// 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 _id_voidCallback = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer, r"voidCallback", r"(Ljava/lang/String;)V");

  /// from: public abstract void voidCallback(java.lang.String s)
  void voidCallback(
    jni.JString s,
  ) {
    return jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_voidCallback,
        jni.JniCallType.voidType,
        [s.reference.pointer]).check();
  }

  static final _id_stringCallback = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"stringCallback",
      r"(Ljava/lang/String;)Ljava/lang/String;");

  /// 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(jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_stringCallback,
        jni.JniCallType.objectType,
        [s.reference.pointer]).object);
  }

  static final _id_varCallback = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"varCallback",
      r"(Ljava/lang/Object;)Ljava/lang/Object;");

  /// 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(jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_varCallback,
        jni.JniCallType.objectType,
        [t.reference.pointer]).object);
  }

  static final _id_manyPrimitives = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"manyPrimitives", r"(IZCD)J");

  /// from: public abstract long manyPrimitives(int a, boolean b, char c, double d)
  int manyPrimitives(
    int a,
    bool b,
    int c,
    double d,
  ) {
    return jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_manyPrimitives,
        jni.JniCallType.longType,
        [jni.JValueInt(a), b ? 1 : 0, jni.JValueChar(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);

  static final _class = jni.Jni.findJClass(
      r"com/github/dart_lang/jnigen/interfaces/MyInterfaceConsumer");

  /// The type which includes information such as the signature of this class.
  static const type = $MyInterfaceConsumerType();
  static final _id_new0 = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"<init>", r"()V");

  /// from: public void <init>()
  /// The returned object must be released after use, by calling the [release] method.
  factory MyInterfaceConsumer() {
    return MyInterfaceConsumer.fromRef(jni.Jni.accessors
        .newObjectWithArgs(_class.reference.pointer, _id_new0, []).object);
  }

  static final _id_consumeOnAnotherThread = jni.Jni.accessors.getStaticMethodIDOf(
      _class.reference.pointer,
      r"consumeOnAnotherThread",
      r"(Lcom/github/dart_lang/jnigen/interfaces/MyInterface;Ljava/lang/String;IZCDLjava/lang/Object;)V");

  /// 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 jni.Jni.accessors.callStaticMethodWithArgs(_class.reference.pointer,
        _id_consumeOnAnotherThread, jni.JniCallType.voidType, [
      myInterface.reference.pointer,
      s.reference.pointer,
      jni.JValueInt(a),
      b ? 1 : 0,
      jni.JValueChar(c),
      d,
      t.reference.pointer
    ]).check();
  }

  static final _id_consumeOnSameThread = jni.Jni.accessors.getStaticMethodIDOf(
      _class.reference.pointer,
      r"consumeOnSameThread",
      r"(Lcom/github/dart_lang/jnigen/interfaces/MyInterface;Ljava/lang/String;IZCDLjava/lang/Object;)V");

  /// 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 jni.Jni.accessors.callStaticMethodWithArgs(_class.reference.pointer,
        _id_consumeOnSameThread, jni.JniCallType.voidType, [
      myInterface.reference.pointer,
      s.reference.pointer,
      jni.JValueInt(a),
      b ? 1 : 0,
      jni.JValueChar(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);

  static final _class =
      jni.Jni.findJClass(r"com/github/dart_lang/jnigen/interfaces/MyRunnable");

  /// The type which includes information such as the signature of this class.
  static const type = $MyRunnableType();
  static final _id_run =
      jni.Jni.accessors.getMethodIDOf(_class.reference.pointer, r"run", r"()V");

  /// from: public abstract void run()
  void run() {
    return jni.Jni.accessors.callMethodWithArgs(
        reference.pointer, _id_run, jni.JniCallType.voidType, []).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);

  static final _class = jni.Jni.findJClass(
      r"com/github/dart_lang/jnigen/interfaces/MyRunnableRunner");

  /// The type which includes information such as the signature of this class.
  static const type = $MyRunnableRunnerType();
  static final _id_error = jni.Jni.accessors.getFieldIDOf(
    _class.reference.pointer,
    r"error",
    r"Ljava/lang/Throwable;",
  );

  /// 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(jni.Jni.accessors
      .getField(reference.pointer, _id_error, jni.JniCallType.objectType)
      .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) => jni.Jni.env
      .SetObjectField(reference.pointer, _id_error, value.reference.pointer);

  static final _id_new0 = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"<init>",
      r"(Lcom/github/dart_lang/jnigen/interfaces/MyRunnable;)V");

  /// 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(jni.Jni.accessors.newObjectWithArgs(
        _class.reference.pointer,
        _id_new0,
        [runnable.reference.pointer]).object);
  }

  static final _id_runOnSameThread = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"runOnSameThread", r"()V");

  /// from: public void runOnSameThread()
  void runOnSameThread() {
    return jni.Jni.accessors.callMethodWithArgs(reference.pointer,
        _id_runOnSameThread, jni.JniCallType.voidType, []).check();
  }

  static final _id_runOnAnotherThread = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"runOnAnotherThread", r"()V");

  /// from: public void runOnAnotherThread()
  void runOnAnotherThread() {
    return jni.Jni.accessors.callMethodWithArgs(reference.pointer,
        _id_runOnAnotherThread, jni.JniCallType.voidType, []).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);

  static final _class = jni.Jni.findJClass(
      r"com/github/dart_lang/jnigen/annotations/JsonSerializable$Case");

  /// The type which includes information such as the signature of this class.
  static const type = $JsonSerializable_CaseType();
  static final _id_values = jni.Jni.accessors.getStaticMethodIDOf(
      _class.reference.pointer,
      r"values",
      r"()[Lcom/github/dart_lang/jnigen/annotations/JsonSerializable$Case;");

  /// 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(
        jni.Jni.accessors.callStaticMethodWithArgs(_class.reference.pointer,
            _id_values, jni.JniCallType.objectType, []).object);
  }

  static final _id_valueOf = jni.Jni.accessors.getStaticMethodIDOf(
      _class.reference.pointer,
      r"valueOf",
      r"(Ljava/lang/String;)Lcom/github/dart_lang/jnigen/annotations/JsonSerializable$Case;");

  /// 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(jni.Jni.accessors
        .callStaticMethodWithArgs(_class.reference.pointer, _id_valueOf,
            jni.JniCallType.objectType, [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);

  static final _class = jni.Jni.findJClass(
      r"com/github/dart_lang/jnigen/annotations/JsonSerializable");

  /// The type which includes information such as the signature of this class.
  static const type = $JsonSerializableType();
  static final _id_value = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"value",
      r"()Lcom/github/dart_lang/jnigen/annotations/JsonSerializable$Case;");

  /// 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(jni.Jni.accessors
        .callMethodWithArgs(reference.pointer, _id_value,
            jni.JniCallType.objectType, []).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);

  static final _class = jni.Jni.findJClass(
      r"com/github/dart_lang/jnigen/annotations/MyDataClass");

  /// The type which includes information such as the signature of this class.
  static const type = $MyDataClassType();
  static final _id_new0 = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"<init>", r"()V");

  /// from: public void <init>()
  /// The returned object must be released after use, by calling the [release] method.
  factory MyDataClass() {
    return MyDataClass.fromRef(jni.Jni.accessors
        .newObjectWithArgs(_class.reference.pointer, _id_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);

  static final _class =
      jni.Jni.findJClass(r"com/github/dart_lang/jnigen/simple_package/Color");

  /// The type which includes information such as the signature of this class.
  static const type = $ColorType();
  static final _id_values = jni.Jni.accessors.getStaticMethodIDOf(
      _class.reference.pointer,
      r"values",
      r"()[Lcom/github/dart_lang/jnigen/simple_package/Color;");

  /// 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(jni.Jni.accessors
        .callStaticMethodWithArgs(_class.reference.pointer, _id_values,
            jni.JniCallType.objectType, []).object);
  }

  static final _id_valueOf = jni.Jni.accessors.getStaticMethodIDOf(
      _class.reference.pointer,
      r"valueOf",
      r"(Ljava/lang/String;)Lcom/github/dart_lang/jnigen/simple_package/Color;");

  /// 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(jni.Jni.accessors
        .callStaticMethodWithArgs(_class.reference.pointer, _id_valueOf,
            jni.JniCallType.objectType, [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);

  static final _class = jni.Jni.findJClass(
      r"com/github/dart_lang/jnigen/simple_package/Exceptions");

  /// The type which includes information such as the signature of this class.
  static const type = $ExceptionsType();
  static final _id_new0 = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"<init>", r"()V");

  /// from: public void <init>()
  /// The returned object must be released after use, by calling the [release] method.
  factory Exceptions() {
    return Exceptions.fromRef(jni.Jni.accessors
        .newObjectWithArgs(_class.reference.pointer, _id_new0, []).object);
  }

  static final _id_new1 = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"<init>", r"(F)V");

  /// 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(jni.Jni.accessors.newObjectWithArgs(
        _class.reference.pointer, _id_new1, [jni.JValueFloat(x)]).object);
  }

  static final _id_new2 = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"<init>", r"(IIIIII)V");

  /// 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(jni.Jni.accessors
        .newObjectWithArgs(_class.reference.pointer, _id_new2, [
      jni.JValueInt(a),
      jni.JValueInt(b),
      jni.JValueInt(c),
      jni.JValueInt(d),
      jni.JValueInt(e),
      jni.JValueInt(f)
    ]).object);
  }

  static final _id_staticObjectMethod = jni.Jni.accessors.getStaticMethodIDOf(
      _class.reference.pointer, r"staticObjectMethod", r"()Ljava/lang/Object;");

  /// 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(jni.Jni.accessors
        .callStaticMethodWithArgs(_class.reference.pointer,
            _id_staticObjectMethod, jni.JniCallType.objectType, []).object);
  }

  static final _id_staticIntMethod = jni.Jni.accessors.getStaticMethodIDOf(
      _class.reference.pointer, r"staticIntMethod", r"()I");

  /// from: static public int staticIntMethod()
  static int staticIntMethod() {
    return jni.Jni.accessors.callStaticMethodWithArgs(_class.reference.pointer,
        _id_staticIntMethod, jni.JniCallType.intType, []).integer;
  }

  static final _id_staticObjectArrayMethod = jni.Jni.accessors
      .getStaticMethodIDOf(_class.reference.pointer, r"staticObjectArrayMethod",
          r"()[Ljava/lang/Object;");

  /// 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(jni.Jni.accessors
        .callStaticMethodWithArgs(
            _class.reference.pointer,
            _id_staticObjectArrayMethod,
            jni.JniCallType.objectType, []).object);
  }

  static final _id_staticIntArrayMethod = jni.Jni.accessors.getStaticMethodIDOf(
      _class.reference.pointer, r"staticIntArrayMethod", r"()[I");

  /// 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(jni.Jni.accessors
        .callStaticMethodWithArgs(_class.reference.pointer,
            _id_staticIntArrayMethod, jni.JniCallType.objectType, []).object);
  }

  static final _id_objectMethod = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer, r"objectMethod", r"()Ljava/lang/Object;");

  /// 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(jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_objectMethod,
        jni.JniCallType.objectType, []).object);
  }

  static final _id_intMethod = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"intMethod", r"()I");

  /// from: public int intMethod()
  int intMethod() {
    return jni.Jni.accessors.callMethodWithArgs(
        reference.pointer, _id_intMethod, jni.JniCallType.intType, []).integer;
  }

  static final _id_objectArrayMethod = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer, r"objectArrayMethod", r"()[Ljava/lang/Object;");

  /// 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(jni.Jni.accessors
        .callMethodWithArgs(reference.pointer, _id_objectArrayMethod,
            jni.JniCallType.objectType, []).object);
  }

  static final _id_intArrayMethod = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"intArrayMethod", r"()[I");

  /// 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(jni.Jni.accessors
        .callMethodWithArgs(reference.pointer, _id_intArrayMethod,
            jni.JniCallType.objectType, []).object);
  }

  static final _id_throwNullPointerException = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer, r"throwNullPointerException", r"()I");

  /// from: public int throwNullPointerException()
  int throwNullPointerException() {
    return jni.Jni.accessors.callMethodWithArgs(reference.pointer,
        _id_throwNullPointerException, jni.JniCallType.intType, []).integer;
  }

  static final _id_throwFileNotFoundException = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"throwFileNotFoundException",
      r"()Ljava/io/InputStream;");

  /// 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(jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_throwFileNotFoundException,
        jni.JniCallType.objectType, []).object);
  }

  static final _id_throwClassCastException = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"throwClassCastException",
      r"()Ljava/io/FileInputStream;");

  /// 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(jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_throwClassCastException,
        jni.JniCallType.objectType, []).object);
  }

  static final _id_throwArrayIndexException = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer, r"throwArrayIndexException", r"()I");

  /// from: public int throwArrayIndexException()
  int throwArrayIndexException() {
    return jni.Jni.accessors.callMethodWithArgs(reference.pointer,
        _id_throwArrayIndexException, jni.JniCallType.intType, []).integer;
  }

  static final _id_throwArithmeticException = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer, r"throwArithmeticException", r"()I");

  /// from: public int throwArithmeticException()
  int throwArithmeticException() {
    return jni.Jni.accessors.callMethodWithArgs(reference.pointer,
        _id_throwArithmeticException, jni.JniCallType.intType, []).integer;
  }

  static final _id_throwLoremIpsum = jni.Jni.accessors.getStaticMethodIDOf(
      _class.reference.pointer, r"throwLoremIpsum", r"()V");

  /// from: static public void throwLoremIpsum()
  static void throwLoremIpsum() {
    return jni.Jni.accessors.callStaticMethodWithArgs(_class.reference.pointer,
        _id_throwLoremIpsum, jni.JniCallType.voidType, []).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);

  static final _class =
      jni.Jni.findJClass(r"com/github/dart_lang/jnigen/simple_package/Fields");

  /// The type which includes information such as the signature of this class.
  static const type = $FieldsType();
  static final _id_amount = jni.Jni.accessors.getStaticFieldIDOf(
    _class.reference.pointer,
    r"amount",
    r"I",
  );

  /// from: static public int amount
  static int get amount => jni.Jni.accessors
      .getStaticField(
          _class.reference.pointer, _id_amount, jni.JniCallType.intType)
      .integer;

  /// from: static public int amount
  static set amount(int value) => jni.Jni.env
      .SetStaticIntField(_class.reference.pointer, _id_amount, value);

  static final _id_pi = jni.Jni.accessors.getStaticFieldIDOf(
    _class.reference.pointer,
    r"pi",
    r"D",
  );

  /// from: static public double pi
  static double get pi => jni.Jni.accessors
      .getStaticField(
          _class.reference.pointer, _id_pi, jni.JniCallType.doubleType)
      .doubleFloat;

  /// from: static public double pi
  static set pi(double value) =>
      jni.Jni.env.SetStaticDoubleField(_class.reference.pointer, _id_pi, value);

  static final _id_asterisk = jni.Jni.accessors.getStaticFieldIDOf(
    _class.reference.pointer,
    r"asterisk",
    r"C",
  );

  /// from: static public char asterisk
  static int get asterisk => jni.Jni.accessors
      .getStaticField(
          _class.reference.pointer, _id_asterisk, jni.JniCallType.charType)
      .char;

  /// from: static public char asterisk
  static set asterisk(int value) => jni.Jni.env
      .SetStaticCharField(_class.reference.pointer, _id_asterisk, value);

  static final _id_name = jni.Jni.accessors.getStaticFieldIDOf(
    _class.reference.pointer,
    r"name",
    r"Ljava/lang/String;",
  );

  /// 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(jni.Jni.accessors
          .getStaticField(
              _class.reference.pointer, _id_name, jni.JniCallType.objectType)
          .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) => jni.Jni.env.SetStaticObjectField(
      _class.reference.pointer, _id_name, value.reference.pointer);

  static final _id_i = jni.Jni.accessors.getFieldIDOf(
    _class.reference.pointer,
    r"i",
    r"Ljava/lang/Integer;",
  );

  /// 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(jni.Jni.accessors
      .getField(reference.pointer, _id_i, jni.JniCallType.objectType)
      .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) => jni.Jni.env
      .SetObjectField(reference.pointer, _id_i, value.reference.pointer);

  static final _id_trillion = jni.Jni.accessors.getFieldIDOf(
    _class.reference.pointer,
    r"trillion",
    r"J",
  );

  /// from: public long trillion
  int get trillion => jni.Jni.accessors
      .getField(reference.pointer, _id_trillion, jni.JniCallType.longType)
      .long;

  /// from: public long trillion
  set trillion(int value) =>
      jni.Jni.env.SetLongField(reference.pointer, _id_trillion, value);

  static final _id_isAchillesDead = jni.Jni.accessors.getFieldIDOf(
    _class.reference.pointer,
    r"isAchillesDead",
    r"Z",
  );

  /// from: public boolean isAchillesDead
  bool get isAchillesDead => jni.Jni.accessors
      .getField(
          reference.pointer, _id_isAchillesDead, jni.JniCallType.booleanType)
      .boolean;

  /// from: public boolean isAchillesDead
  set isAchillesDead(bool value) => jni.Jni.env
      .SetBooleanField(reference.pointer, _id_isAchillesDead, value ? 1 : 0);

  static final _id_bestFighterInGreece = jni.Jni.accessors.getFieldIDOf(
    _class.reference.pointer,
    r"bestFighterInGreece",
    r"Ljava/lang/String;",
  );

  /// 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(jni.Jni.accessors
          .getField(reference.pointer, _id_bestFighterInGreece,
              jni.JniCallType.objectType)
          .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) => jni.Jni.env.SetObjectField(
      reference.pointer, _id_bestFighterInGreece, value.reference.pointer);

  static final _id_random = jni.Jni.accessors.getFieldIDOf(
    _class.reference.pointer,
    r"random",
    r"Ljava/util/Random;",
  );

  /// 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(jni.Jni.accessors
      .getField(reference.pointer, _id_random, jni.JniCallType.objectType)
      .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) => jni.Jni.env
      .SetObjectField(reference.pointer, _id_random, value.reference.pointer);

  static final _id_euroSymbol = jni.Jni.accessors.getStaticFieldIDOf(
    _class.reference.pointer,
    r"euroSymbol",
    r"C",
  );

  /// from: static public char euroSymbol
  static int get euroSymbol => jni.Jni.accessors
      .getStaticField(
          _class.reference.pointer, _id_euroSymbol, jni.JniCallType.charType)
      .char;

  /// from: static public char euroSymbol
  static set euroSymbol(int value) => jni.Jni.env
      .SetStaticCharField(_class.reference.pointer, _id_euroSymbol, value);

  static final _id_new0 = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"<init>", r"()V");

  /// from: public void <init>()
  /// The returned object must be released after use, by calling the [release] method.
  factory Fields() {
    return Fields.fromRef(jni.Jni.accessors
        .newObjectWithArgs(_class.reference.pointer, _id_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);

  static final _class = jni.Jni.findJClass(
      r"com/github/dart_lang/jnigen/simple_package/Fields$Nested");

  /// The type which includes information such as the signature of this class.
  static const type = $Fields_NestedType();
  static final _id_hundred = jni.Jni.accessors.getFieldIDOf(
    _class.reference.pointer,
    r"hundred",
    r"J",
  );

  /// from: public long hundred
  int get hundred => jni.Jni.accessors
      .getField(reference.pointer, _id_hundred, jni.JniCallType.longType)
      .long;

  /// from: public long hundred
  set hundred(int value) =>
      jni.Jni.env.SetLongField(reference.pointer, _id_hundred, value);

  static final _id_BEST_GOD = jni.Jni.accessors.getStaticFieldIDOf(
    _class.reference.pointer,
    r"BEST_GOD",
    r"Ljava/lang/String;",
  );

  /// 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(jni
      .Jni.accessors
      .getStaticField(
          _class.reference.pointer, _id_BEST_GOD, jni.JniCallType.objectType)
      .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) => jni.Jni.env.SetStaticObjectField(
      _class.reference.pointer, _id_BEST_GOD, value.reference.pointer);

  static final _id_new0 = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"<init>", r"()V");

  /// from: public void <init>()
  /// The returned object must be released after use, by calling the [release] method.
  factory Fields_Nested() {
    return Fields_Nested.fromRef(jni.Jni.accessors
        .newObjectWithArgs(_class.reference.pointer, _id_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);

  static final _class = jni.Jni.findJClass(
      r"com/github/dart_lang/jnigen/generics/GenericTypeParams");

  /// 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 _id_new0 = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"<init>", r"()V");

  /// 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,
        jni.Jni.accessors
            .newObjectWithArgs(_class.reference.pointer, _id_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);

  static final _class =
      jni.Jni.findJClass(r"com/github/dart_lang/jnigen/generics/StringMap");

  /// The type which includes information such as the signature of this class.
  static const type = $StringMapType();
  static final _id_new0 = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"<init>", r"()V");

  /// from: public void <init>()
  /// The returned object must be released after use, by calling the [release] method.
  factory StringMap() {
    return StringMap.fromRef(jni.Jni.accessors
        .newObjectWithArgs(_class.reference.pointer, _id_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;
  }
}
