[jnigen] Remove FFI patch and use mutex around method/field lookups (https://github.com/dart-lang/jnigen/issues/246)

* Add pubspec.lock from JNI example to git. 
This file should be checked in.

* Remove ffi patch and instead depend on the internals of a pinned package:ffi version (closes https://github.com/dart-lang/jnigen/issues/149)
* Add new tests on GlobalJniEnv
* Rename findJniClass -> findJClass
* Locking around method/field lookups. (closes https://github.com/dart-lang/jnigen/issues/85)
* Rename asJString and asDartString to toJStringPtr and toDartString for uniform naming
* Rename JniClass -> JClass
* Compare bindings normally and fallback to ignoring spaces
diff --git a/.github/workflows/test-package.yml b/.github/workflows/test-package.yml
index a4f17bc..f1afa9d 100644
--- a/.github/workflows/test-package.yml
+++ b/.github/workflows/test-package.yml
@@ -182,10 +182,10 @@
           parallel: true
           path-to-lcov: ./pkgs/jni/coverage/lcov.info
       - name: regenerate & compare ffigen bindings
+        ## Use git to verify no source files have changed
         run: |
-          cp lib/src/third_party/jni_bindings_generated.dart __old_bindings
-          dart run ffigen --config ffigen.yaml
-          diff lib/src/third_party/jni_bindings_generated.dart __old_bindings
+          dart run tool/generate_ffi_bindings.dart
+          git diff --exit-code -- lib/src/third_party src/third_party
 
   ## Run tests for package:jni on windows, just to confirm it works.
   ## Do not, for example, collect coverage or check formatting.
diff --git a/pkgs/jni/.gitignore b/pkgs/jni/.gitignore
index 96486fd..ae8c6c2 100644
--- a/pkgs/jni/.gitignore
+++ b/pkgs/jni/.gitignore
@@ -28,3 +28,5 @@
 .dart_tool/
 .packages
 build/
+
+.vscode/
\ No newline at end of file
diff --git a/pkgs/jni/example/integration_test/on_device_jni_test.dart b/pkgs/jni/example/integration_test/on_device_jni_test.dart
index 3b547ad..769ae6b 100644
--- a/pkgs/jni/example/integration_test/on_device_jni_test.dart
+++ b/pkgs/jni/example/integration_test/on_device_jni_test.dart
@@ -2,123 +2,27 @@
 // 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.
 
-// This file contains mostly the same tests from package:jni's
-// test/jni_object_test.dart. This file can be run on android device using
-// flutter test integration_test/ and therefore useful for checking the
-// working of JNI on an Android device (or emulator).
-
-import 'dart:io';
-
 import 'package:flutter_test/flutter_test.dart';
 
-import 'package:jni/jni.dart';
+import '../../test/global_env_test.dart' as global_env_test;
+import '../../test/exception_test.dart' as exception_test;
+import '../../test/jobject_test.dart' as jobject_test;
+import '../../test/jarray_test.dart' as jarray_test;
+import '../../test/type_test.dart' as type_test;
+
+void integrationTestRunner(String description, void Function() testCallback) {
+  testWidgets(description, (widgetTester) async => testCallback());
+}
 
 void main() {
-  if (!Platform.isAndroid) {
-    try {
-      Jni.spawn(dylibDir: "build/jni_libs");
-    } on JvmExistsException {
-      // TODO(#51): Support destroying and restarting JVM.
-    }
+  final testSuites = [
+    global_env_test.run,
+    exception_test.run,
+    jobject_test.run,
+    jarray_test.run,
+    type_test.run,
+  ];
+  for (var testSuite in testSuites) {
+    testSuite(testRunner: integrationTestRunner);
   }
-
-  testWidgets("Long.intValue() using JObject", (t) async {
-    final longClass = Jni.findJniClass("java/lang/Long");
-
-    final longCtor = longClass.getCtorID("(J)V");
-
-    final long = longClass.newInstance(longCtor, [176]);
-
-    final intValue = long.callMethodByName<int>("intValue", "()I", []);
-    expect(intValue, equals(176));
-
-    long.delete();
-    longClass.delete();
-  });
-
-  testWidgets("call a static method using JniClass APIs", (t) async {
-    final integerClass = JniClass.fromRef(Jni.findClass("java/lang/Integer"));
-    final result = integerClass.callStaticMethodByName<JString>(
-        "toHexString", "(I)Ljava/lang/String;", [JValueInt(31)]);
-
-    final resultString = result.toDartString();
-
-    result.delete();
-    expect(resultString, equals("1f"));
-
-    integerClass.delete();
-  });
-
-  testWidgets("Example for using getMethodID", (t) async {
-    final longClass = Jni.findJniClass("java/lang/Long");
-    final bitCountMethod = longClass.getStaticMethodID("bitCount", "(J)I");
-
-    final random = Jni.newInstance("java/util/Random", "()V", []);
-
-    final nextIntMethod = random.getMethodID("nextInt", "(I)I");
-
-    for (int i = 0; i < 100; i++) {
-      int r = random.callMethod<int>(nextIntMethod, [JValueInt(256 * 256)]);
-      int bits = 0;
-      final jbc = longClass.callStaticMethod<int>(bitCountMethod, [r]);
-      while (r != 0) {
-        bits += r % 2;
-        r = (r / 2).floor();
-      }
-      expect(jbc, equals(bits));
-    }
-    random.delete();
-    longClass.delete();
-  });
-
-  // Actually it's not even required to get a reference to class
-  testWidgets("invoke_", (t) async {
-    final m = Jni.invokeStaticMethod<int>(
-        "java/lang/Long", "min", "(JJ)J", [1234, 1324], JniCallType.longType);
-    expect(m, equals(1234));
-  });
-
-  testWidgets("retrieve_", (t) async {
-    final maxLong = Jni.retrieveStaticField<int>(
-        "java/lang/Short", "MAX_VALUE", "S", JniCallType.shortType);
-    expect(maxLong, equals(32767));
-  });
-
-  testWidgets("Call method with null argument, expect exception",
-      (tester) async {
-    final integerClass = Jni.findJniClass("java/lang/Integer");
-    expect(
-        () => integerClass.callStaticMethodByName<int>(
-            "parseInt", "(Ljava/lang/String;)I", [nullptr]),
-        throwsException);
-  });
-
-  testWidgets("callStaticStringMethod", (t) async {
-    final longClass = Jni.findJniClass("java/lang/Long");
-    const n = 1223334444;
-    final strFromJava = longClass.callStaticMethodByName<String>(
-        "toOctalString", "(J)Ljava/lang/String;", [n]);
-    expect(strFromJava, equals(n.toRadixString(8)));
-    longClass.delete();
-  });
-
-  testWidgets("Passing strings in arguments", (t) async {
-    final twelve = Jni.invokeStaticMethod<int>("java/lang/Byte", "parseByte",
-        "(Ljava/lang/String;)B", ["12"], JniCallType.byteType);
-    expect(twelve, equals(12));
-  });
-
-  testWidgets("use() method", (t) async {
-    final randomInt = Jni.newInstance("java/util/Random", "()V", []).use(
-        (random) =>
-            random.callMethodByName<int>("nextInt", "(I)I", [JValueInt(15)]));
-    expect(randomInt, lessThan(15));
-  });
-
-  testWidgets("enums", (t) async {
-    final ordinal = Jni.retrieveStaticField<JObject>(
-            "java/net/Proxy\$Type", "HTTP", "Ljava/net/Proxy\$Type;")
-        .use((f) => f.callMethodByName<int>("ordinal", "()I", []));
-    expect(ordinal, equals(1));
-  });
 }
diff --git a/pkgs/jni/example/lib/main.dart b/pkgs/jni/example/lib/main.dart
index b23b279..50c3c75 100644
--- a/pkgs/jni/example/lib/main.dart
+++ b/pkgs/jni/example/lib/main.dart
@@ -15,7 +15,7 @@
 // GlobalJniEnv is a thin abstraction over JNIEnv in JNI C API.
 //
 // For a more ergonomic API for common use cases of calling methods and
-// accessing fields, see next examples using JObject and JniClass.
+// accessing fields, see next examples using JObject and JClass.
 String toJavaStringUsingEnv(int n) => using((arena) {
       final env = Jni.env;
       final cls = env.FindClass("java/lang/String".toNativeChars(arena));
@@ -24,7 +24,7 @@
       final i = arena<JValue>();
       i.ref.i = n;
       final res = env.CallStaticObjectMethodA(cls, mId, i);
-      final str = env.asDartString(res);
+      final str = env.toDartString(res);
       env.deleteAllRefs([res, cls]);
       return str;
     });
@@ -42,14 +42,14 @@
       return res;
     });
 double randomDouble() {
-  final math = Jni.findJniClass("java/lang/Math");
+  final math = Jni.findJClass("java/lang/Math");
   final random = math.callStaticMethodByName<double>("random", "()D", []);
   math.delete();
   return random;
 }
 
 int uptime() {
-  return Jni.findJniClass("android/os/SystemClock").use(
+  return Jni.findJClass("android/os/SystemClock").use(
     (systemClock) => systemClock.callStaticMethodByName<int>(
         "uptimeMillis", "()J", [], JniCallType.longType),
   );
diff --git a/pkgs/jni/example/pubspec.lock b/pkgs/jni/example/pubspec.lock
new file mode 100644
index 0000000..5925148
--- /dev/null
+++ b/pkgs/jni/example/pubspec.lock
@@ -0,0 +1,523 @@
+# Generated by pub
+# See https://dart.dev/tools/pub/glossary#lockfile
+packages:
+  _fe_analyzer_shared:
+    dependency: transitive
+    description:
+      name: _fe_analyzer_shared
+      sha256: a36ec4843dc30ea6bf652bf25e3448db6c5e8bcf4aa55f063a5d1dad216d8214
+      url: "https://pub.dev"
+    source: hosted
+    version: "58.0.0"
+  analyzer:
+    dependency: transitive
+    description:
+      name: analyzer
+      sha256: cc4242565347e98424ce9945c819c192ec0838cb9d1f6aa4a97cc96becbc5b27
+      url: "https://pub.dev"
+    source: hosted
+    version: "5.10.0"
+  archive:
+    dependency: transitive
+    description:
+      name: archive
+      sha256: "80e5141fafcb3361653ce308776cfd7d45e6e9fbb429e14eec571382c0c5fecb"
+      url: "https://pub.dev"
+    source: hosted
+    version: "3.3.2"
+  args:
+    dependency: transitive
+    description:
+      name: args
+      sha256: "4cab82a83ffef80b262ddedf47a0a8e56ee6fbf7fe21e6e768b02792034dd440"
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.4.0"
+  async:
+    dependency: transitive
+    description:
+      name: async
+      sha256: bfe67ef28df125b7dddcea62755991f807aa39a2492a23e1550161692950bbe0
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.10.0"
+  boolean_selector:
+    dependency: transitive
+    description:
+      name: boolean_selector
+      sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.1.1"
+  characters:
+    dependency: transitive
+    description:
+      name: characters
+      sha256: e6a326c8af69605aec75ed6c187d06b349707a27fbff8222ca9cc2cff167975c
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.2.1"
+  clock:
+    dependency: transitive
+    description:
+      name: clock
+      sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.1.1"
+  collection:
+    dependency: transitive
+    description:
+      name: collection
+      sha256: cfc915e6923fe5ce6e153b0723c753045de46de1b4d63771530504004a45fae0
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.17.0"
+  convert:
+    dependency: transitive
+    description:
+      name: convert
+      sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592"
+      url: "https://pub.dev"
+    source: hosted
+    version: "3.1.1"
+  coverage:
+    dependency: transitive
+    description:
+      name: coverage
+      sha256: "2fb815080e44a09b85e0f2ca8a820b15053982b2e714b59267719e8a9ff17097"
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.6.3"
+  crypto:
+    dependency: transitive
+    description:
+      name: crypto
+      sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67
+      url: "https://pub.dev"
+    source: hosted
+    version: "3.0.2"
+  cupertino_icons:
+    dependency: "direct main"
+    description:
+      name: cupertino_icons
+      sha256: e35129dc44c9118cee2a5603506d823bab99c68393879edb440e0090d07586be
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.0.5"
+  fake_async:
+    dependency: transitive
+    description:
+      name: fake_async
+      sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78"
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.3.1"
+  ffi:
+    dependency: "direct main"
+    description:
+      name: ffi
+      sha256: a38574032c5f1dd06c4aee541789906c12ccaab8ba01446e800d9c5b79c4a978
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.0.1"
+  file:
+    dependency: transitive
+    description:
+      name: file
+      sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d"
+      url: "https://pub.dev"
+    source: hosted
+    version: "6.1.4"
+  flutter:
+    dependency: "direct main"
+    description: flutter
+    source: sdk
+    version: "0.0.0"
+  flutter_driver:
+    dependency: transitive
+    description: flutter
+    source: sdk
+    version: "0.0.0"
+  flutter_lints:
+    dependency: "direct dev"
+    description:
+      name: flutter_lints
+      sha256: aeb0b80a8b3709709c9cc496cdc027c5b3216796bc0af0ce1007eaf24464fd4c
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.0.1"
+  flutter_test:
+    dependency: "direct dev"
+    description: flutter
+    source: sdk
+    version: "0.0.0"
+  frontend_server_client:
+    dependency: transitive
+    description:
+      name: frontend_server_client
+      sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612"
+      url: "https://pub.dev"
+    source: hosted
+    version: "3.2.0"
+  fuchsia_remote_debug_protocol:
+    dependency: transitive
+    description: flutter
+    source: sdk
+    version: "0.0.0"
+  glob:
+    dependency: transitive
+    description:
+      name: glob
+      sha256: "4515b5b6ddb505ebdd242a5f2cc5d22d3d6a80013789debfbda7777f47ea308c"
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.1.1"
+  http_multi_server:
+    dependency: transitive
+    description:
+      name: http_multi_server
+      sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b"
+      url: "https://pub.dev"
+    source: hosted
+    version: "3.2.1"
+  http_parser:
+    dependency: transitive
+    description:
+      name: http_parser
+      sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b"
+      url: "https://pub.dev"
+    source: hosted
+    version: "4.0.2"
+  integration_test:
+    dependency: "direct dev"
+    description: flutter
+    source: sdk
+    version: "0.0.0"
+  io:
+    dependency: transitive
+    description:
+      name: io
+      sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e"
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.0.4"
+  jni:
+    dependency: "direct main"
+    description:
+      path: ".."
+      relative: true
+    source: path
+    version: "0.3.0"
+  js:
+    dependency: transitive
+    description:
+      name: js
+      sha256: "5528c2f391ededb7775ec1daa69e65a2d61276f7552de2b5f7b8d34ee9fd4ab7"
+      url: "https://pub.dev"
+    source: hosted
+    version: "0.6.5"
+  lints:
+    dependency: transitive
+    description:
+      name: lints
+      sha256: "5e4a9cd06d447758280a8ac2405101e0e2094d2a1dbdd3756aec3fe7775ba593"
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.0.1"
+  logging:
+    dependency: transitive
+    description:
+      name: logging
+      sha256: "04094f2eb032cbb06c6f6e8d3607edcfcb0455e2bb6cbc010cb01171dcb64e6d"
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.1.1"
+  matcher:
+    dependency: transitive
+    description:
+      name: matcher
+      sha256: "16db949ceee371e9b99d22f88fa3a73c4e59fd0afed0bd25fc336eb76c198b72"
+      url: "https://pub.dev"
+    source: hosted
+    version: "0.12.13"
+  material_color_utilities:
+    dependency: transitive
+    description:
+      name: material_color_utilities
+      sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724
+      url: "https://pub.dev"
+    source: hosted
+    version: "0.2.0"
+  meta:
+    dependency: transitive
+    description:
+      name: meta
+      sha256: "6c268b42ed578a53088d834796959e4a1814b5e9e164f147f580a386e5decf42"
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.8.0"
+  mime:
+    dependency: transitive
+    description:
+      name: mime
+      sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.0.4"
+  node_preamble:
+    dependency: transitive
+    description:
+      name: node_preamble
+      sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db"
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.0.2"
+  package_config:
+    dependency: transitive
+    description:
+      name: package_config
+      sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd"
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.1.0"
+  path:
+    dependency: transitive
+    description:
+      name: path
+      sha256: db9d4f58c908a4ba5953fcee2ae317c94889433e5024c27ce74a37f94267945b
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.8.2"
+  platform:
+    dependency: transitive
+    description:
+      name: platform
+      sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76"
+      url: "https://pub.dev"
+    source: hosted
+    version: "3.1.0"
+  plugin_platform_interface:
+    dependency: transitive
+    description:
+      name: plugin_platform_interface
+      sha256: "6a2128648c854906c53fa8e33986fc0247a1116122f9534dd20e3ab9e16a32bc"
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.1.4"
+  pool:
+    dependency: transitive
+    description:
+      name: pool
+      sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a"
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.5.1"
+  process:
+    dependency: transitive
+    description:
+      name: process
+      sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09"
+      url: "https://pub.dev"
+    source: hosted
+    version: "4.2.4"
+  pub_semver:
+    dependency: transitive
+    description:
+      name: pub_semver
+      sha256: "307de764d305289ff24ad257ad5c5793ce56d04947599ad68b3baa124105fc17"
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.1.3"
+  shelf:
+    dependency: transitive
+    description:
+      name: shelf
+      sha256: c24a96135a2ccd62c64b69315a14adc5c3419df63b4d7c05832a346fdb73682c
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.4.0"
+  shelf_packages_handler:
+    dependency: transitive
+    description:
+      name: shelf_packages_handler
+      sha256: aef74dc9195746a384843102142ab65b6a4735bb3beea791e63527b88cc83306
+      url: "https://pub.dev"
+    source: hosted
+    version: "3.0.1"
+  shelf_static:
+    dependency: transitive
+    description:
+      name: shelf_static
+      sha256: e792b76b96a36d4a41b819da593aff4bdd413576b3ba6150df5d8d9996d2e74c
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.1.1"
+  shelf_web_socket:
+    dependency: transitive
+    description:
+      name: shelf_web_socket
+      sha256: a988c0e8d8ffbdb8a28aa7ec8e449c260f3deb808781fe1284d22c5bba7156e8
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.0.3"
+  sky_engine:
+    dependency: transitive
+    description: flutter
+    source: sdk
+    version: "0.0.99"
+  source_map_stack_trace:
+    dependency: transitive
+    description:
+      name: source_map_stack_trace
+      sha256: "84cf769ad83aa6bb61e0aa5a18e53aea683395f196a6f39c4c881fb90ed4f7ae"
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.1.1"
+  source_maps:
+    dependency: transitive
+    description:
+      name: source_maps
+      sha256: "708b3f6b97248e5781f493b765c3337db11c5d2c81c3094f10904bfa8004c703"
+      url: "https://pub.dev"
+    source: hosted
+    version: "0.10.12"
+  source_span:
+    dependency: transitive
+    description:
+      name: source_span
+      sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.9.1"
+  stack_trace:
+    dependency: transitive
+    description:
+      name: stack_trace
+      sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.11.0"
+  stream_channel:
+    dependency: transitive
+    description:
+      name: stream_channel
+      sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8"
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.1.1"
+  string_scanner:
+    dependency: transitive
+    description:
+      name: string_scanner
+      sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.2.0"
+  sync_http:
+    dependency: transitive
+    description:
+      name: sync_http
+      sha256: "7f0cd72eca000d2e026bcd6f990b81d0ca06022ef4e32fb257b30d3d1014a961"
+      url: "https://pub.dev"
+    source: hosted
+    version: "0.3.1"
+  term_glyph:
+    dependency: transitive
+    description:
+      name: term_glyph
+      sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.2.1"
+  test:
+    dependency: "direct dev"
+    description:
+      name: test
+      sha256: a5fcd2d25eeadbb6589e80198a47d6a464ba3e2049da473943b8af9797900c2d
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.22.0"
+  test_api:
+    dependency: transitive
+    description:
+      name: test_api
+      sha256: ad540f65f92caa91bf21dfc8ffb8c589d6e4dc0c2267818b4cc2792857706206
+      url: "https://pub.dev"
+    source: hosted
+    version: "0.4.16"
+  test_core:
+    dependency: transitive
+    description:
+      name: test_core
+      sha256: "0ef9755ec6d746951ba0aabe62f874b707690b5ede0fecc818b138fcc9b14888"
+      url: "https://pub.dev"
+    source: hosted
+    version: "0.4.20"
+  typed_data:
+    dependency: transitive
+    description:
+      name: typed_data
+      sha256: "26f87ade979c47a150c9eaab93ccd2bebe70a27dc0b4b29517f2904f04eb11a5"
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.3.1"
+  vector_math:
+    dependency: transitive
+    description:
+      name: vector_math
+      sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.1.4"
+  vm_service:
+    dependency: transitive
+    description:
+      name: vm_service
+      sha256: e7fb6c2282f7631712b69c19d1bff82f3767eea33a2321c14fa59ad67ea391c7
+      url: "https://pub.dev"
+    source: hosted
+    version: "9.4.0"
+  watcher:
+    dependency: transitive
+    description:
+      name: watcher
+      sha256: "6a7f46926b01ce81bfc339da6a7f20afbe7733eff9846f6d6a5466aa4c6667c0"
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.0.2"
+  web_socket_channel:
+    dependency: transitive
+    description:
+      name: web_socket_channel
+      sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.4.0"
+  webdriver:
+    dependency: transitive
+    description:
+      name: webdriver
+      sha256: ef67178f0cc7e32c1494645b11639dd1335f1d18814aa8435113a92e9ef9d841
+      url: "https://pub.dev"
+    source: hosted
+    version: "3.0.1"
+  webkit_inspection_protocol:
+    dependency: transitive
+    description:
+      name: webkit_inspection_protocol
+      sha256: "67d3a8b6c79e1987d19d848b0892e582dbb0c66c57cc1fef58a177dd2aa2823d"
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.2.0"
+  yaml:
+    dependency: transitive
+    description:
+      name: yaml
+      sha256: "23812a9b125b48d4007117254bca50abb6c712352927eece9e155207b1db2370"
+      url: "https://pub.dev"
+    source: hosted
+    version: "3.1.1"
+sdks:
+  dart: ">=2.19.0 <3.0.0"
+  flutter: ">=2.11.0"
diff --git a/pkgs/jni/example/pubspec.yaml b/pkgs/jni/example/pubspec.yaml
index 70624e6..30408f9 100644
--- a/pkgs/jni/example/pubspec.yaml
+++ b/pkgs/jni/example/pubspec.yaml
@@ -18,7 +18,7 @@
 version: 1.0.0+1
 
 environment:
-  sdk: ">=2.17.5 <4.0.0"
+  sdk: '>=2.17.5 <4.0.0'
 
 # Dependencies specify other packages that your package needs in order to work.
 # To automatically upgrade your package dependencies to the latest versions
@@ -45,6 +45,7 @@
   cupertino_icons: ^1.0.2
 
 dev_dependencies:
+  test: any
   flutter_test:
     sdk: flutter
   integration_test:
@@ -62,7 +63,6 @@
 
 # The following section is specific to Flutter packages.
 flutter:
-
   # The following line ensures that the Material Icons font is
   # included with your application, so that you can use the icons in
   # the material Icons class.
diff --git a/pkgs/jni/ffigen.yaml b/pkgs/jni/ffigen.yaml
index dc1cea2..1704f43 100644
--- a/pkgs/jni/ffigen.yaml
+++ b/pkgs/jni/ffigen.yaml
@@ -13,27 +13,46 @@
   entry-points:
     - 'src/dartjni.h' # Exports majority of JNI functions
     - 'src/third_party/global_jni_env.h' # Exports GlobalJniEnv type
+    - 'src/jni_constants.h'
   include-directives:
     - 'src/dartjni.h'
     - 'src/third_party/global_jni_env.h'
     - 'third_party/jni.h' # jni.h from Android NDK
+    - 'src/jni_constants.h'
 compiler-opts:
   - '-Ithird_party/'
 enums:
   rename:
     'JniType': 'JniCallType'
+    'jobjectRefType': 'JObjectRefType'
 functions:
   exclude:
     # Exclude init functions supposed to be defined in loaded DLL, not JNI
     - 'JNI_.*'
-    - 'GetJniContext'
+    - 'GetJniContextPtr'
     - 'setJniGetters'
     - 'jni_log'
+    # Inline functions
+    - 'acquire_lock'
+    - 'release_lock'
+    - 'init_lock'
+    - 'destroy_lock'
+    - 'load_class'
+    - 'load_class_global_ref'
+    - 'attach_thread'
+    - 'load_method'
+    - 'load_static_method'
+    - 'load_field'
+    - 'load_static_field'
+    - 'to_global_ref'
+    - 'check_exception'
+    - 'load_env'
     # This is a native function in Java. No need to call it from Dart.
     - 'Java_com_github_dart_1lang_jni_PortContinuation__1resumeWith'
 structs:
   exclude:
     - 'JniContext'
+    - 'JniLocks'
     - 'JNIEnv'
     - '_JNIEnv'
     - 'JNIInvokeInterface'
@@ -41,7 +60,8 @@
   rename:
     ## opaque struct definitions, base types of jfieldID and jmethodID
     '_jfieldID': 'jfieldID_'
-    '_jmethodID': 'jmethodID_'
+    '_jmethodID':
+      'jmethodID_'
       #'JNI(.*)': 'Jni$1'
 unions:
   rename:
@@ -126,4 +146,3 @@
 comments:
   style: any
   length: full
-
diff --git a/pkgs/jni/ffigen_exts.yaml b/pkgs/jni/ffigen_exts.yaml
new file mode 100644
index 0000000..d292ad6
--- /dev/null
+++ b/pkgs/jni/ffigen_exts.yaml
@@ -0,0 +1,16 @@
+# Run with `dart run ffigen --config ffigen.yaml`.
+name: JniExtensions
+description: |
+  This config is for use by the script that generates extension methods in C.
+  This config only scans jni.h and does not do renaming etc..
+output: 'unused.dart'
+headers:
+  entry-points:
+    - 'third_party/jni.h' # Exports majority of JNI functions
+    #- 'src/third_party/global_jni_env.h' # Exports GlobalJniEnv type
+  include-directives:
+    #- 'src/dartjni.h'
+    #- 'src/third_party/global_jni_env.h'
+    - 'third_party/jni.h' # jni.h from Android NDK
+compiler-opts:
+  - '-Ithird_party/'
diff --git a/pkgs/jni/lib/jni.dart b/pkgs/jni/lib/jni.dart
index 72ef7582..a4a45ec 100644
--- a/pkgs/jni/lib/jni.dart
+++ b/pkgs/jni/lib/jni.dart
@@ -60,7 +60,7 @@
 /// This library provides classes and functions for JNI interop from Dart.
 library jni;
 
-export 'src/third_party/jni_bindings_generated.dart'
+export 'src/third_party/generated_bindings.dart'
     hide JniBindings, JniEnv, JniEnv1, JniExceptionDetails;
 export 'src/jni.dart' hide ProtectedJniExtensions;
 export 'src/jvalues.dart' hide JValueArgs, toJValues;
diff --git a/pkgs/jni/lib/src/accessors.dart b/pkgs/jni/lib/src/accessors.dart
index 6d01865..66045ae 100644
--- a/pkgs/jni/lib/src/accessors.dart
+++ b/pkgs/jni/lib/src/accessors.dart
@@ -7,7 +7,7 @@
 
 import 'package:jni/src/jvalues.dart';
 
-import 'third_party/jni_bindings_generated.dart';
+import 'third_party/generated_bindings.dart';
 import 'jni.dart';
 import 'types.dart';
 
@@ -22,71 +22,81 @@
 
   int get byte {
     check();
-    return result.b;
+    return value.b;
   }
 
   int get short {
     check();
-    return result.s;
+    return value.s;
   }
 
   int get char {
     check();
-    return result.c;
+    return value.c;
   }
 
   int get integer {
     check();
-    return result.i;
+    return value.i;
   }
 
   int get long {
     check();
-    return result.j;
+    return value.j;
   }
 
   double get float {
     check();
-    return result.f;
+    return value.f;
   }
 
   double get doubleFloat {
     check();
-    return result.d;
+    return value.d;
   }
 
   JObjectPtr get object {
     check();
-    return result.l;
+    return value.l;
   }
 
   bool get boolean {
     check();
-    return result.z != 0;
+    return value.z != 0;
   }
 }
 
 extension JniIdLookupResultMethods on JniPointerResult {
   JMethodIDPtr get methodID {
     _check(exception);
-    return id.cast<jmethodID_>();
+    return value.cast<jmethodID_>();
   }
 
   JFieldIDPtr get fieldID {
     _check(exception);
-    return id.cast<jfieldID_>();
+    return value.cast<jfieldID_>();
   }
 
   Pointer<Void> get checkedRef {
     _check(exception);
-    return id;
+    return value;
+  }
+
+  Pointer<T> getPointer<T extends NativeType>() {
+    return value.cast<T>();
   }
 }
 
 extension JniClassLookupResultMethods on JniClassLookupResult {
   JClassPtr get checkedClassRef {
     _check(exception);
-    return classRef;
+    return value;
+  }
+}
+
+extension JThrowableCheckMethod on JThrowablePtr {
+  void check() {
+    _check(this);
   }
 }
 
@@ -98,8 +108,8 @@
   void throwException(JThrowablePtr exception) {
     final details = getExceptionDetails(exception);
     final env = Jni.env;
-    final message = env.asDartString(details.message);
-    final stacktrace = env.asDartString(details.stacktrace);
+    final message = env.toDartString(details.message);
+    final stacktrace = env.toDartString(details.stacktrace);
     env.DeleteGlobalRef(exception);
     env.DeleteGlobalRef(details.message);
     env.DeleteGlobalRef(details.stacktrace);
diff --git a/pkgs/jni/lib/src/jexceptions.dart b/pkgs/jni/lib/src/jexceptions.dart
index a9a3cfc..3200880 100644
--- a/pkgs/jni/lib/src/jexceptions.dart
+++ b/pkgs/jni/lib/src/jexceptions.dart
@@ -43,7 +43,24 @@
 
 class JvmExistsException implements JException {
   @override
-  String toString() => 'A JVM already exists';
+  String toString() => 'A JVM is already spawned';
+}
+
+/// Represents spawn errors that might be returned by JNI_CreateJavaVM
+class SpawnException implements JException {
+  static const _errors = {
+    JniErrorCode.JNI_ERR: 'Generic JNI error',
+    JniErrorCode.JNI_EDETACHED: 'Thread detached from VM',
+    JniErrorCode.JNI_EVERSION: 'JNI version error',
+    JniErrorCode.JNI_ENOMEM: 'Out of memory',
+    JniErrorCode.JNI_EEXIST: 'VM Already created',
+    JniErrorCode.JNI_EINVAL: 'Invalid arguments',
+  };
+  int status;
+  SpawnException.of(this.status);
+
+  @override
+  String toString() => _errors[status] ?? 'Unknown status code: $status';
 }
 
 class NoJvmInstanceException implements JException {
diff --git a/pkgs/jni/lib/src/jni.dart b/pkgs/jni/lib/src/jni.dart
index 4d5a2ab..8ad7fd4 100644
--- a/pkgs/jni/lib/src/jni.dart
+++ b/pkgs/jni/lib/src/jni.dart
@@ -9,7 +9,7 @@
 import 'package:ffi/ffi.dart';
 import 'package:path/path.dart';
 
-import 'third_party/jni_bindings_generated.dart';
+import 'third_party/generated_bindings.dart';
 import 'jvalues.dart';
 import 'types.dart';
 import 'accessors.dart';
@@ -46,7 +46,7 @@
   static final DynamicLibrary _dylib = _loadDartJniLibrary(dir: _dylibDir);
   static final JniBindings _bindings = JniBindings(_dylib);
   static final _getJniEnvFn = _dylib.lookup<Void>('GetJniEnv');
-  static final _getJniContextFn = _dylib.lookup<Void>('GetJniContext');
+  static final _getJniContextFn = _dylib.lookup<Void>('GetJniContextPtr');
 
   /// Store dylibDir if any was used.
   static String? _dylibDir;
@@ -84,7 +84,7 @@
     List<String> jvmOptions = const [],
     List<String> classPath = const [],
     bool ignoreUnrecognized = false,
-    int jniVersion = JNI_VERSION_1_6,
+    int jniVersion = JniVersions.JNI_VERSION_1_6,
   }) =>
       using((arena) {
         _dylibDir = dylibDir;
@@ -100,7 +100,17 @@
           ignoreUnrecognized: ignoreUnrecognized,
           allocator: arena,
         );
-        _bindings.SpawnJvm(jvmArgs);
+        final status = _bindings.SpawnJvm(jvmArgs);
+        if (status == JniErrorCode.JNI_OK) {
+          return;
+        } else if (status == DART_JNI_SINGLETON_EXISTS) {
+          throw JvmExistsException();
+        } else if (status == JniErrorCode.JNI_EEXIST) {
+          sleep(const Duration(seconds: 1));
+          throw JvmExistsException();
+        } else {
+          throw SpawnException.of(status);
+        }
       });
 
   static Pointer<JavaVMInitArgs> _createVMArgs({
@@ -108,7 +118,7 @@
     List<String> classPath = const [],
     String? dylibPath,
     bool ignoreUnrecognized = false,
-    int version = JNI_VERSION_1_6,
+    int version = JniVersions.JNI_VERSION_1_6,
     required Allocator allocator,
   }) {
     final args = allocator<JavaVMInitArgs>();
@@ -195,9 +205,9 @@
       });
 
   /// Returns class for [qualifiedName] found by platform-specific mechanism,
-  /// wrapped in a [JniClass].
-  static JniClass findJniClass(String qualifiedName) =>
-      JniClass.fromRef(findClass(qualifiedName));
+  /// wrapped in a [JClass].
+  static JClass findJClass(String qualifiedName) =>
+      JClass.fromRef(findClass(qualifiedName));
 
   /// Constructs an instance of class with given arguments.
   ///
@@ -205,7 +215,7 @@
   /// required themselves.
   static JObject newInstance(
       String qualifiedName, String ctorSignature, List<dynamic> args) {
-    final cls = findJniClass(qualifiedName);
+    final cls = findJClass(qualifiedName);
     final ctor = cls.getCtorID(ctorSignature);
     final obj = cls.newInstance(ctor, args);
     cls.delete();
@@ -228,7 +238,7 @@
   static T retrieveStaticField<T>(
       String className, String fieldName, String signature,
       [int? callType]) {
-    final cls = findJniClass(className);
+    final cls = findJClass(className);
     final result = cls.getStaticFieldByName<T>(fieldName, signature, callType);
     cls.delete();
     return result;
@@ -242,7 +252,7 @@
   static T invokeStaticMethod<T>(
       String className, String methodName, String signature, List<dynamic> args,
       [int? callType]) {
-    final cls = findJniClass(className);
+    final cls = findJClass(className);
     final result =
         cls.callStaticMethodByName<T>(methodName, signature, args, callType);
     cls.delete();
@@ -283,7 +293,7 @@
   /// to dart string.
   /// if [deleteOriginal] is specified, jstring passed will be deleted using
   /// DeleteLocalRef.
-  String asDartString(JStringPtr jstringPtr, {bool deleteOriginal = false}) {
+  String toDartString(JStringPtr jstringPtr, {bool deleteOriginal = false}) {
     if (jstringPtr == nullptr) {
       throw NullJStringException();
     }
@@ -300,7 +310,7 @@
   }
 
   /// Return a new [JStringPtr] from contents of [s].
-  JStringPtr asJString(String s) => using((arena) {
+  JStringPtr toJStringPtr(String s) => using((arena) {
         final utf = s.toNativeUtf8().cast<Char>();
         final result = NewStringUTF(utf);
         malloc.free(utf);
diff --git a/pkgs/jni/lib/src/jobject.dart b/pkgs/jni/lib/src/jobject.dart
index dff8fda..3eb4074 100644
--- a/pkgs/jni/lib/src/jobject.dart
+++ b/pkgs/jni/lib/src/jobject.dart
@@ -44,7 +44,7 @@
   if (result.exception != nullptr) {
     _accessors.throwException(result.exception);
   }
-  return result.id.cast<T>();
+  return result.value.cast<T>();
 }
 
 int _getCallType(int? callType, int defaultType, Set<int> allowed) {
@@ -109,10 +109,15 @@
           callType, JniCallType.objectType, {JniCallType.objectType});
       final ref = function(finalCallType).object;
       final ctor = T == String
-          ? (ref) => _env.asDartString(ref, deleteOriginal: true)
+          ? (ref) => _env.toDartString(ref, deleteOriginal: true)
           : (T == JObject ? JObject.fromRef : JString.fromRef);
       result = ctor(ref) as T;
       break;
+    case Pointer<Void>: // JObjectPtr
+      finalCallType = _getCallType(
+          callType, JniCallType.objectType, {JniCallType.objectType});
+      result = function(finalCallType).object as T;
+      break;
     case _VoidType:
       finalCallType =
           _getCallType(callType, JniCallType.voidType, {JniCallType.voidType});
@@ -131,7 +136,6 @@
         JniResult Function(int, Pointer<JValue>) f) =>
     using((arena) {
       final jArgs = JValueArgs(args, arena);
-      arena.onReleaseAll(jArgs.dispose);
       return _callOrGet<T>(callType, (ct) => f(ct, jArgs.values));
     });
 
@@ -153,30 +157,30 @@
   /// Construct a new [JObject] with [reference] as its underlying reference.
   JObject.fromRef(JObjectPtr reference) : super.fromRef(reference);
 
-  JniClass? _jniClass;
+  JClass? _jClass;
 
-  JniClass get _class {
-    return _jniClass ??= getClass();
+  JClass get _class {
+    return _jClass ??= getClass();
   }
 
   /// Deletes the JNI reference and marks this object as deleted. Any further
   /// uses will throw [UseAfterFreeException].
   @override
   void delete() {
-    _jniClass?.delete();
+    _jClass?.delete();
     super.delete();
   }
 
-  /// Returns [JniClass] corresponding to concrete class of this object.
+  /// Returns [JClass] corresponding to concrete class of this object.
   ///
   /// This may be a subclass of compile-time class.
-  JniClass getClass() {
+  JClass getClass() {
     _ensureNotDeleted();
     final classRef = _env.GetObjectClass(reference);
     if (classRef == nullptr) {
       _accessors.throwException(_env.ExceptionOccurred());
     }
-    return JniClass.fromRef(classRef);
+    return JClass.fromRef(classRef);
   }
 
   /// Get [JFieldIDPtr] of instance field identified by [fieldName] & [signature].
@@ -295,7 +299,7 @@
   /// Casts this object to another type.
   T castTo<T extends JObject>(JObjType<T> type, {bool deleteOriginal = false}) {
     if (deleteOriginal) {
-      _jniClass?.delete();
+      _jClass?.delete();
       _setAsDeleted();
       return type.fromRef(reference);
     }
@@ -305,9 +309,9 @@
 }
 
 /// A high level wrapper over a JNI class reference.
-class JniClass extends JReference {
-  /// Construct a new [JniClass] with [reference] as its underlying reference.
-  JniClass.fromRef(JObjectPtr reference) : super.fromRef(reference);
+class JClass extends JReference {
+  /// Construct a new [JClass] with [reference] as its underlying reference.
+  JClass.fromRef(JObjectPtr reference) : super.fromRef(reference);
 
   /// Get [JFieldIDPtr] of static field [fieldName] with [signature].
   JFieldIDPtr getStaticFieldID(String fieldName, String signature) {
@@ -384,7 +388,6 @@
   JObject newInstance(JMethodIDPtr ctor, List<dynamic> args) => using((arena) {
         _ensureNotDeleted();
         final jArgs = JValueArgs(args, arena);
-        arena.onReleaseAll(jArgs.dispose);
         final res = _accessors.newObject(reference, ctor, jArgs.values).object;
         return JObject.fromRef(res);
       });
diff --git a/pkgs/jni/lib/src/jreference.dart b/pkgs/jni/lib/src/jreference.dart
index 1bd6c5c..e71febf 100644
--- a/pkgs/jni/lib/src/jreference.dart
+++ b/pkgs/jni/lib/src/jreference.dart
@@ -7,7 +7,8 @@
 /// A class which holds one or more JNI references, and has a `delete` operation
 /// which disposes the reference(s).
 abstract class JReference implements Finalizable {
-  static final _finalizer = NativeFinalizer(_env.ref.DeleteGlobalRef);
+  //TODO(PR): Is it safe to cast void *f (void *) to void f (void *)?
+  static final _finalizer = NativeFinalizer(_env.ref.DeleteGlobalRef.cast());
 
   JReference.fromRef(this.reference) {
     _finalizer.attach(this, reference, detach: this);
diff --git a/pkgs/jni/lib/src/jvalues.dart b/pkgs/jni/lib/src/jvalues.dart
index ce0cac6..b34e306 100644
--- a/pkgs/jni/lib/src/jvalues.dart
+++ b/pkgs/jni/lib/src/jvalues.dart
@@ -5,7 +5,7 @@
 import 'dart:ffi';
 import 'package:ffi/ffi.dart';
 
-import 'third_party/jni_bindings_generated.dart';
+import 'third_party/generated_bindings.dart';
 import 'jni.dart';
 import 'types.dart';
 
@@ -120,23 +120,24 @@
   final List<JObjectPtr> createdRefs = [];
   final _env = Jni.env;
 
-  JValueArgs(List<dynamic> args, [Allocator allocator = malloc]) {
-    values = allocator<JValue>(args.length);
+  JValueArgs(List<dynamic> args, Arena arena) {
+    values = arena<JValue>(args.length);
     for (int i = 0; i < args.length; i++) {
       final arg = args[i];
       final ptr = values.elementAt(i);
       if (arg is String) {
-        final jstr = _env.asJString(arg);
+        final jstr = _env.toJStringPtr(arg);
         ptr.ref.l = jstr;
         createdRefs.add(jstr);
       } else {
         _fillJValue(ptr, arg);
       }
+      arena.onReleaseAll(_dispose);
     }
   }
 
   /// Deletes temporary references such as [JStringPtr]s.
-  void dispose() {
+  void _dispose() {
     for (var ref in createdRefs) {
       _env.DeleteGlobalRef(ref);
     }
diff --git a/pkgs/jni/lib/src/third_party/generated_bindings.dart b/pkgs/jni/lib/src/third_party/generated_bindings.dart
new file mode 100644
index 0000000..6047975
--- /dev/null
+++ b/pkgs/jni/lib/src/third_party/generated_bindings.dart
@@ -0,0 +1,2 @@
+export 'jni_bindings_generated.dart';
+export 'global_env_extensions.dart';
diff --git a/pkgs/jni/lib/src/third_party/global_env_extensions.dart b/pkgs/jni/lib/src/third_party/global_env_extensions.dart
new file mode 100644
index 0000000..e561eef
--- /dev/null
+++ b/pkgs/jni/lib/src/third_party/global_env_extensions.dart
@@ -0,0 +1,1391 @@
+// Auto generated file. Do not edit.
+
+// This is generated from JNI header in Android NDK. License for the same is
+// provided below.
+
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * JNI specification, as defined by Sun:
+ * http://java.sun.com/javase/6/docs/technotes/guides/jni/spec/jniTOC.html
+ *
+ * Everything here is expected to be VM-neutral.
+ */
+
+// ignore_for_file: non_constant_identifier_names
+// coverage:ignore-file
+
+import "dart:ffi" as ffi;
+
+import "jni_bindings_generated.dart";
+
+import "../accessors.dart";
+
+extension EnvExtension on ffi.Pointer<GlobalJniEnv> {
+  int GetVersion() =>
+      ref.GetVersion.asFunction<JniResult Function()>()().integer;
+
+  JClassPtr DefineClass(ffi.Pointer<ffi.Char> name, JObjectPtr loader,
+          ffi.Pointer<JByteMarker> buf, int bufLen) =>
+      ref.DefineClass.asFunction<
+              JniClassLookupResult Function(
+                  ffi.Pointer<ffi.Char> name,
+                  JObjectPtr loader,
+                  ffi.Pointer<JByteMarker> buf,
+                  int bufLen)>()(name, loader, buf, bufLen)
+          .value;
+
+  JClassPtr FindClass(ffi.Pointer<ffi.Char> name) => ref.FindClass.asFunction<
+          JniClassLookupResult Function(ffi.Pointer<ffi.Char> name)>()(name)
+      .value;
+
+  JMethodIDPtr FromReflectedMethod(JObjectPtr method) => ref.FromReflectedMethod
+          .asFunction<JniPointerResult Function(JObjectPtr method)>()(method)
+      .methodID;
+
+  JFieldIDPtr FromReflectedField(JObjectPtr field) => ref.FromReflectedField
+          .asFunction<JniPointerResult Function(JObjectPtr field)>()(field)
+      .fieldID;
+
+  JObjectPtr ToReflectedMethod(
+          JClassPtr cls, JMethodIDPtr methodId, int isStatic) =>
+      ref.ToReflectedMethod.asFunction<
+              JniResult Function(JClassPtr cls, JMethodIDPtr methodId,
+                  int isStatic)>()(cls, methodId, isStatic)
+          .object;
+
+  JClassPtr GetSuperclass(JClassPtr clazz) => ref.GetSuperclass.asFunction<
+          JniClassLookupResult Function(JClassPtr clazz)>()(clazz)
+      .value;
+
+  bool IsAssignableFrom(JClassPtr clazz1, JClassPtr clazz2) =>
+      ref.IsAssignableFrom.asFunction<
+              JniResult Function(
+                  JClassPtr clazz1, JClassPtr clazz2)>()(clazz1, clazz2)
+          .boolean;
+
+  JObjectPtr ToReflectedField(
+          JClassPtr cls, JFieldIDPtr fieldID, int isStatic) =>
+      ref.ToReflectedField.asFunction<
+              JniResult Function(JClassPtr cls, JFieldIDPtr fieldID,
+                  int isStatic)>()(cls, fieldID, isStatic)
+          .object;
+
+  int Throw(JThrowablePtr obj) =>
+      ref.Throw.asFunction<JniResult Function(JThrowablePtr obj)>()(obj)
+          .integer;
+
+  int ThrowNew(JClassPtr clazz, ffi.Pointer<ffi.Char> message) =>
+      ref.ThrowNew.asFunction<
+              JniResult Function(JClassPtr clazz,
+                  ffi.Pointer<ffi.Char> message)>()(clazz, message)
+          .integer;
+
+  JThrowablePtr ExceptionOccurred() =>
+      ref.ExceptionOccurred.asFunction<JniResult Function()>()().object;
+
+  void ExceptionDescribe() =>
+      ref.ExceptionDescribe.asFunction<JThrowablePtr Function()>()().check();
+
+  void ExceptionClear() =>
+      ref.ExceptionClear.asFunction<JThrowablePtr Function()>()().check();
+
+  void FatalError(ffi.Pointer<ffi.Char> msg) => ref.FatalError.asFunction<
+          JThrowablePtr Function(ffi.Pointer<ffi.Char> msg)>()(msg)
+      .check();
+
+  int PushLocalFrame(int capacity) =>
+      ref.PushLocalFrame.asFunction<JniResult Function(int capacity)>()(
+              capacity)
+          .integer;
+
+  JObjectPtr PopLocalFrame(JObjectPtr result) =>
+      ref.PopLocalFrame.asFunction<JniResult Function(JObjectPtr result)>()(
+              result)
+          .object;
+
+  JObjectPtr NewGlobalRef(JObjectPtr obj) =>
+      ref.NewGlobalRef.asFunction<JniResult Function(JObjectPtr obj)>()(obj)
+          .object;
+
+  void DeleteGlobalRef(JObjectPtr globalRef) => ref.DeleteGlobalRef.asFunction<
+          JThrowablePtr Function(JObjectPtr globalRef)>()(globalRef)
+      .check();
+
+  void DeleteLocalRef(JObjectPtr localRef) => ref.DeleteLocalRef.asFunction<
+          JThrowablePtr Function(JObjectPtr localRef)>()(localRef)
+      .check();
+
+  bool IsSameObject(JObjectPtr ref1, JObjectPtr ref2) =>
+      ref.IsSameObject.asFunction<
+              JniResult Function(
+                  JObjectPtr ref1, JObjectPtr ref2)>()(ref1, ref2)
+          .boolean;
+
+  JObjectPtr NewLocalRef(JObjectPtr obj) =>
+      ref.NewLocalRef.asFunction<JniResult Function(JObjectPtr obj)>()(obj)
+          .object;
+
+  int EnsureLocalCapacity(int capacity) =>
+      ref.EnsureLocalCapacity.asFunction<JniResult Function(int capacity)>()(
+              capacity)
+          .integer;
+
+  JObjectPtr AllocObject(JClassPtr clazz) =>
+      ref.AllocObject.asFunction<JniResult Function(JClassPtr clazz)>()(clazz)
+          .object;
+
+  JObjectPtr NewObject(JClassPtr clazz, JMethodIDPtr methodID) =>
+      ref.NewObject.asFunction<
+              JniResult Function(
+                  JClassPtr clazz, JMethodIDPtr methodID)>()(clazz, methodID)
+          .object;
+
+  JObjectPtr NewObjectA(
+          JClassPtr clazz, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      ref.NewObjectA.asFunction<
+              JniResult Function(JClassPtr clazz, JMethodIDPtr methodID,
+                  ffi.Pointer<JValue> args)>()(clazz, methodID, args)
+          .object;
+
+  JClassPtr GetObjectClass(JObjectPtr obj) => ref.GetObjectClass.asFunction<
+          JniClassLookupResult Function(JObjectPtr obj)>()(obj)
+      .value;
+
+  bool IsInstanceOf(JObjectPtr obj, JClassPtr clazz) =>
+      ref.IsInstanceOf.asFunction<
+              JniResult Function(JObjectPtr obj, JClassPtr clazz)>()(obj, clazz)
+          .boolean;
+
+  JMethodIDPtr GetMethodID(JClassPtr clazz, ffi.Pointer<ffi.Char> name,
+          ffi.Pointer<ffi.Char> sig) =>
+      ref.GetMethodID.asFunction<
+              JniPointerResult Function(
+                  JClassPtr clazz,
+                  ffi.Pointer<ffi.Char> name,
+                  ffi.Pointer<ffi.Char> sig)>()(clazz, name, sig)
+          .methodID;
+
+  JObjectPtr CallObjectMethod(JObjectPtr obj, JMethodIDPtr methodID) =>
+      ref.CallObjectMethod.asFunction<
+              JniResult Function(
+                  JObjectPtr obj, JMethodIDPtr methodID)>()(obj, methodID)
+          .object;
+
+  JObjectPtr CallObjectMethodA(
+          JObjectPtr obj, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      ref.CallObjectMethodA.asFunction<
+              JniResult Function(JObjectPtr obj, JMethodIDPtr methodID,
+                  ffi.Pointer<JValue> args)>()(obj, methodID, args)
+          .object;
+
+  bool CallBooleanMethod(JObjectPtr obj, JMethodIDPtr methodID) =>
+      ref.CallBooleanMethod.asFunction<
+              JniResult Function(
+                  JObjectPtr obj, JMethodIDPtr methodID)>()(obj, methodID)
+          .boolean;
+
+  bool CallBooleanMethodA(
+          JObjectPtr obj, JMethodIDPtr methodId, ffi.Pointer<JValue> args) =>
+      ref.CallBooleanMethodA.asFunction<
+              JniResult Function(JObjectPtr obj, JMethodIDPtr methodId,
+                  ffi.Pointer<JValue> args)>()(obj, methodId, args)
+          .boolean;
+
+  int CallByteMethod(JObjectPtr obj, JMethodIDPtr methodID) =>
+      ref.CallByteMethod.asFunction<
+              JniResult Function(
+                  JObjectPtr obj, JMethodIDPtr methodID)>()(obj, methodID)
+          .byte;
+
+  int CallByteMethodA(
+          JObjectPtr obj, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      ref.CallByteMethodA.asFunction<
+              JniResult Function(JObjectPtr obj, JMethodIDPtr methodID,
+                  ffi.Pointer<JValue> args)>()(obj, methodID, args)
+          .byte;
+
+  int CallCharMethod(JObjectPtr obj, JMethodIDPtr methodID) =>
+      ref.CallCharMethod.asFunction<
+              JniResult Function(
+                  JObjectPtr obj, JMethodIDPtr methodID)>()(obj, methodID)
+          .char;
+
+  int CallCharMethodA(
+          JObjectPtr obj, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      ref.CallCharMethodA.asFunction<
+              JniResult Function(JObjectPtr obj, JMethodIDPtr methodID,
+                  ffi.Pointer<JValue> args)>()(obj, methodID, args)
+          .char;
+
+  int CallShortMethod(JObjectPtr obj, JMethodIDPtr methodID) =>
+      ref.CallShortMethod.asFunction<
+              JniResult Function(
+                  JObjectPtr obj, JMethodIDPtr methodID)>()(obj, methodID)
+          .short;
+
+  int CallShortMethodA(
+          JObjectPtr obj, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      ref.CallShortMethodA.asFunction<
+              JniResult Function(JObjectPtr obj, JMethodIDPtr methodID,
+                  ffi.Pointer<JValue> args)>()(obj, methodID, args)
+          .short;
+
+  int CallIntMethod(JObjectPtr obj, JMethodIDPtr methodID) =>
+      ref.CallIntMethod.asFunction<
+              JniResult Function(
+                  JObjectPtr obj, JMethodIDPtr methodID)>()(obj, methodID)
+          .integer;
+
+  int CallIntMethodA(
+          JObjectPtr obj, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      ref.CallIntMethodA.asFunction<
+              JniResult Function(JObjectPtr obj, JMethodIDPtr methodID,
+                  ffi.Pointer<JValue> args)>()(obj, methodID, args)
+          .integer;
+
+  int CallLongMethod(JObjectPtr obj, JMethodIDPtr methodID) =>
+      ref.CallLongMethod.asFunction<
+              JniResult Function(
+                  JObjectPtr obj, JMethodIDPtr methodID)>()(obj, methodID)
+          .long;
+
+  int CallLongMethodA(
+          JObjectPtr obj, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      ref.CallLongMethodA.asFunction<
+              JniResult Function(JObjectPtr obj, JMethodIDPtr methodID,
+                  ffi.Pointer<JValue> args)>()(obj, methodID, args)
+          .long;
+
+  double CallFloatMethod(JObjectPtr obj, JMethodIDPtr methodID) =>
+      ref.CallFloatMethod.asFunction<
+              JniResult Function(
+                  JObjectPtr obj, JMethodIDPtr methodID)>()(obj, methodID)
+          .float;
+
+  double CallFloatMethodA(
+          JObjectPtr obj, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      ref.CallFloatMethodA.asFunction<
+              JniResult Function(JObjectPtr obj, JMethodIDPtr methodID,
+                  ffi.Pointer<JValue> args)>()(obj, methodID, args)
+          .float;
+
+  double CallDoubleMethod(JObjectPtr obj, JMethodIDPtr methodID) =>
+      ref.CallDoubleMethod.asFunction<
+              JniResult Function(
+                  JObjectPtr obj, JMethodIDPtr methodID)>()(obj, methodID)
+          .doubleFloat;
+
+  double CallDoubleMethodA(
+          JObjectPtr obj, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      ref.CallDoubleMethodA.asFunction<
+              JniResult Function(JObjectPtr obj, JMethodIDPtr methodID,
+                  ffi.Pointer<JValue> args)>()(obj, methodID, args)
+          .doubleFloat;
+
+  void CallVoidMethod(JObjectPtr obj, JMethodIDPtr methodID) =>
+      ref.CallVoidMethod.asFunction<
+              JThrowablePtr Function(
+                  JObjectPtr obj, JMethodIDPtr methodID)>()(obj, methodID)
+          .check();
+
+  void CallVoidMethodA(
+          JObjectPtr obj, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      ref.CallVoidMethodA.asFunction<
+              JThrowablePtr Function(JObjectPtr obj, JMethodIDPtr methodID,
+                  ffi.Pointer<JValue> args)>()(obj, methodID, args)
+          .check();
+
+  JObjectPtr CallNonvirtualObjectMethod(
+          JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID) =>
+      ref.CallNonvirtualObjectMethod.asFunction<
+              JniResult Function(JObjectPtr obj, JClassPtr clazz,
+                  JMethodIDPtr methodID)>()(obj, clazz, methodID)
+          .object;
+
+  JObjectPtr CallNonvirtualObjectMethodA(JObjectPtr obj, JClassPtr clazz,
+          JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      ref.CallNonvirtualObjectMethodA.asFunction<
+              JniResult Function(
+                  JObjectPtr obj,
+                  JClassPtr clazz,
+                  JMethodIDPtr methodID,
+                  ffi.Pointer<JValue> args)>()(obj, clazz, methodID, args)
+          .object;
+
+  bool CallNonvirtualBooleanMethod(
+          JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID) =>
+      ref.CallNonvirtualBooleanMethod.asFunction<
+              JniResult Function(JObjectPtr obj, JClassPtr clazz,
+                  JMethodIDPtr methodID)>()(obj, clazz, methodID)
+          .boolean;
+
+  bool CallNonvirtualBooleanMethodA(JObjectPtr obj, JClassPtr clazz,
+          JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      ref.CallNonvirtualBooleanMethodA.asFunction<
+              JniResult Function(
+                  JObjectPtr obj,
+                  JClassPtr clazz,
+                  JMethodIDPtr methodID,
+                  ffi.Pointer<JValue> args)>()(obj, clazz, methodID, args)
+          .boolean;
+
+  int CallNonvirtualByteMethod(
+          JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID) =>
+      ref.CallNonvirtualByteMethod.asFunction<
+              JniResult Function(JObjectPtr obj, JClassPtr clazz,
+                  JMethodIDPtr methodID)>()(obj, clazz, methodID)
+          .byte;
+
+  int CallNonvirtualByteMethodA(JObjectPtr obj, JClassPtr clazz,
+          JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      ref.CallNonvirtualByteMethodA.asFunction<
+              JniResult Function(
+                  JObjectPtr obj,
+                  JClassPtr clazz,
+                  JMethodIDPtr methodID,
+                  ffi.Pointer<JValue> args)>()(obj, clazz, methodID, args)
+          .byte;
+
+  int CallNonvirtualCharMethod(
+          JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID) =>
+      ref.CallNonvirtualCharMethod.asFunction<
+              JniResult Function(JObjectPtr obj, JClassPtr clazz,
+                  JMethodIDPtr methodID)>()(obj, clazz, methodID)
+          .char;
+
+  int CallNonvirtualCharMethodA(JObjectPtr obj, JClassPtr clazz,
+          JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      ref.CallNonvirtualCharMethodA.asFunction<
+              JniResult Function(
+                  JObjectPtr obj,
+                  JClassPtr clazz,
+                  JMethodIDPtr methodID,
+                  ffi.Pointer<JValue> args)>()(obj, clazz, methodID, args)
+          .char;
+
+  int CallNonvirtualShortMethod(
+          JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID) =>
+      ref.CallNonvirtualShortMethod.asFunction<
+              JniResult Function(JObjectPtr obj, JClassPtr clazz,
+                  JMethodIDPtr methodID)>()(obj, clazz, methodID)
+          .short;
+
+  int CallNonvirtualShortMethodA(JObjectPtr obj, JClassPtr clazz,
+          JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      ref.CallNonvirtualShortMethodA.asFunction<
+              JniResult Function(
+                  JObjectPtr obj,
+                  JClassPtr clazz,
+                  JMethodIDPtr methodID,
+                  ffi.Pointer<JValue> args)>()(obj, clazz, methodID, args)
+          .short;
+
+  int CallNonvirtualIntMethod(
+          JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID) =>
+      ref.CallNonvirtualIntMethod.asFunction<
+              JniResult Function(JObjectPtr obj, JClassPtr clazz,
+                  JMethodIDPtr methodID)>()(obj, clazz, methodID)
+          .integer;
+
+  int CallNonvirtualIntMethodA(JObjectPtr obj, JClassPtr clazz,
+          JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      ref.CallNonvirtualIntMethodA.asFunction<
+              JniResult Function(
+                  JObjectPtr obj,
+                  JClassPtr clazz,
+                  JMethodIDPtr methodID,
+                  ffi.Pointer<JValue> args)>()(obj, clazz, methodID, args)
+          .integer;
+
+  int CallNonvirtualLongMethod(
+          JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID) =>
+      ref.CallNonvirtualLongMethod.asFunction<
+              JniResult Function(JObjectPtr obj, JClassPtr clazz,
+                  JMethodIDPtr methodID)>()(obj, clazz, methodID)
+          .long;
+
+  int CallNonvirtualLongMethodA(JObjectPtr obj, JClassPtr clazz,
+          JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      ref.CallNonvirtualLongMethodA.asFunction<
+              JniResult Function(
+                  JObjectPtr obj,
+                  JClassPtr clazz,
+                  JMethodIDPtr methodID,
+                  ffi.Pointer<JValue> args)>()(obj, clazz, methodID, args)
+          .long;
+
+  double CallNonvirtualFloatMethod(
+          JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID) =>
+      ref.CallNonvirtualFloatMethod.asFunction<
+              JniResult Function(JObjectPtr obj, JClassPtr clazz,
+                  JMethodIDPtr methodID)>()(obj, clazz, methodID)
+          .float;
+
+  double CallNonvirtualFloatMethodA(JObjectPtr obj, JClassPtr clazz,
+          JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      ref.CallNonvirtualFloatMethodA.asFunction<
+              JniResult Function(
+                  JObjectPtr obj,
+                  JClassPtr clazz,
+                  JMethodIDPtr methodID,
+                  ffi.Pointer<JValue> args)>()(obj, clazz, methodID, args)
+          .float;
+
+  double CallNonvirtualDoubleMethod(
+          JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID) =>
+      ref.CallNonvirtualDoubleMethod.asFunction<
+              JniResult Function(JObjectPtr obj, JClassPtr clazz,
+                  JMethodIDPtr methodID)>()(obj, clazz, methodID)
+          .doubleFloat;
+
+  double CallNonvirtualDoubleMethodA(JObjectPtr obj, JClassPtr clazz,
+          JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      ref.CallNonvirtualDoubleMethodA.asFunction<
+              JniResult Function(
+                  JObjectPtr obj,
+                  JClassPtr clazz,
+                  JMethodIDPtr methodID,
+                  ffi.Pointer<JValue> args)>()(obj, clazz, methodID, args)
+          .doubleFloat;
+
+  void CallNonvirtualVoidMethod(
+          JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID) =>
+      ref.CallNonvirtualVoidMethod.asFunction<
+              JThrowablePtr Function(JObjectPtr obj, JClassPtr clazz,
+                  JMethodIDPtr methodID)>()(obj, clazz, methodID)
+          .check();
+
+  void CallNonvirtualVoidMethodA(JObjectPtr obj, JClassPtr clazz,
+          JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      ref.CallNonvirtualVoidMethodA.asFunction<
+              JThrowablePtr Function(
+                  JObjectPtr obj,
+                  JClassPtr clazz,
+                  JMethodIDPtr methodID,
+                  ffi.Pointer<JValue> args)>()(obj, clazz, methodID, args)
+          .check();
+
+  JFieldIDPtr GetFieldID(JClassPtr clazz, ffi.Pointer<ffi.Char> name,
+          ffi.Pointer<ffi.Char> sig) =>
+      ref.GetFieldID.asFunction<
+              JniPointerResult Function(
+                  JClassPtr clazz,
+                  ffi.Pointer<ffi.Char> name,
+                  ffi.Pointer<ffi.Char> sig)>()(clazz, name, sig)
+          .fieldID;
+
+  JObjectPtr GetObjectField(JObjectPtr obj, JFieldIDPtr fieldID) =>
+      ref.GetObjectField.asFunction<
+              JniResult Function(
+                  JObjectPtr obj, JFieldIDPtr fieldID)>()(obj, fieldID)
+          .object;
+
+  bool GetBooleanField(JObjectPtr obj, JFieldIDPtr fieldID) =>
+      ref.GetBooleanField.asFunction<
+              JniResult Function(
+                  JObjectPtr obj, JFieldIDPtr fieldID)>()(obj, fieldID)
+          .boolean;
+
+  int GetByteField(JObjectPtr obj, JFieldIDPtr fieldID) =>
+      ref.GetByteField.asFunction<
+              JniResult Function(
+                  JObjectPtr obj, JFieldIDPtr fieldID)>()(obj, fieldID)
+          .byte;
+
+  int GetCharField(JObjectPtr obj, JFieldIDPtr fieldID) =>
+      ref.GetCharField.asFunction<
+              JniResult Function(
+                  JObjectPtr obj, JFieldIDPtr fieldID)>()(obj, fieldID)
+          .char;
+
+  int GetShortField(JObjectPtr obj, JFieldIDPtr fieldID) =>
+      ref.GetShortField.asFunction<
+              JniResult Function(
+                  JObjectPtr obj, JFieldIDPtr fieldID)>()(obj, fieldID)
+          .short;
+
+  int GetIntField(JObjectPtr obj, JFieldIDPtr fieldID) =>
+      ref.GetIntField.asFunction<
+              JniResult Function(
+                  JObjectPtr obj, JFieldIDPtr fieldID)>()(obj, fieldID)
+          .integer;
+
+  int GetLongField(JObjectPtr obj, JFieldIDPtr fieldID) =>
+      ref.GetLongField.asFunction<
+              JniResult Function(
+                  JObjectPtr obj, JFieldIDPtr fieldID)>()(obj, fieldID)
+          .long;
+
+  double GetFloatField(JObjectPtr obj, JFieldIDPtr fieldID) =>
+      ref.GetFloatField.asFunction<
+              JniResult Function(
+                  JObjectPtr obj, JFieldIDPtr fieldID)>()(obj, fieldID)
+          .float;
+
+  double GetDoubleField(JObjectPtr obj, JFieldIDPtr fieldID) =>
+      ref.GetDoubleField.asFunction<
+              JniResult Function(
+                  JObjectPtr obj, JFieldIDPtr fieldID)>()(obj, fieldID)
+          .doubleFloat;
+
+  void SetObjectField(JObjectPtr obj, JFieldIDPtr fieldID, JObjectPtr val) =>
+      ref.SetObjectField.asFunction<
+              JThrowablePtr Function(JObjectPtr obj, JFieldIDPtr fieldID,
+                  JObjectPtr val)>()(obj, fieldID, val)
+          .check();
+
+  void SetBooleanField(JObjectPtr obj, JFieldIDPtr fieldID, int val) =>
+      ref.SetBooleanField.asFunction<
+              JThrowablePtr Function(JObjectPtr obj, JFieldIDPtr fieldID,
+                  int val)>()(obj, fieldID, val)
+          .check();
+
+  void SetByteField(JObjectPtr obj, JFieldIDPtr fieldID, int val) =>
+      ref.SetByteField.asFunction<
+              JThrowablePtr Function(JObjectPtr obj, JFieldIDPtr fieldID,
+                  int val)>()(obj, fieldID, val)
+          .check();
+
+  void SetCharField(JObjectPtr obj, JFieldIDPtr fieldID, int val) =>
+      ref.SetCharField.asFunction<
+              JThrowablePtr Function(JObjectPtr obj, JFieldIDPtr fieldID,
+                  int val)>()(obj, fieldID, val)
+          .check();
+
+  void SetShortField(JObjectPtr obj, JFieldIDPtr fieldID, int val) =>
+      ref.SetShortField.asFunction<
+              JThrowablePtr Function(JObjectPtr obj, JFieldIDPtr fieldID,
+                  int val)>()(obj, fieldID, val)
+          .check();
+
+  void SetIntField(JObjectPtr obj, JFieldIDPtr fieldID, int val) =>
+      ref.SetIntField.asFunction<
+              JThrowablePtr Function(JObjectPtr obj, JFieldIDPtr fieldID,
+                  int val)>()(obj, fieldID, val)
+          .check();
+
+  void SetLongField(JObjectPtr obj, JFieldIDPtr fieldID, int val) =>
+      ref.SetLongField.asFunction<
+              JThrowablePtr Function(JObjectPtr obj, JFieldIDPtr fieldID,
+                  int val)>()(obj, fieldID, val)
+          .check();
+
+  void SetFloatField(JObjectPtr obj, JFieldIDPtr fieldID, double val) =>
+      ref.SetFloatField.asFunction<
+              JThrowablePtr Function(JObjectPtr obj, JFieldIDPtr fieldID,
+                  double val)>()(obj, fieldID, val)
+          .check();
+
+  void SetDoubleField(JObjectPtr obj, JFieldIDPtr fieldID, double val) =>
+      ref.SetDoubleField.asFunction<
+              JThrowablePtr Function(JObjectPtr obj, JFieldIDPtr fieldID,
+                  double val)>()(obj, fieldID, val)
+          .check();
+
+  JMethodIDPtr GetStaticMethodID(JClassPtr clazz, ffi.Pointer<ffi.Char> name,
+          ffi.Pointer<ffi.Char> sig) =>
+      ref.GetStaticMethodID.asFunction<
+              JniPointerResult Function(
+                  JClassPtr clazz,
+                  ffi.Pointer<ffi.Char> name,
+                  ffi.Pointer<ffi.Char> sig)>()(clazz, name, sig)
+          .methodID;
+
+  JObjectPtr CallStaticObjectMethod(JClassPtr clazz, JMethodIDPtr methodID) =>
+      ref.CallStaticObjectMethod.asFunction<
+              JniResult Function(
+                  JClassPtr clazz, JMethodIDPtr methodID)>()(clazz, methodID)
+          .object;
+
+  JObjectPtr CallStaticObjectMethodA(
+          JClassPtr clazz, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      ref.CallStaticObjectMethodA.asFunction<
+              JniResult Function(JClassPtr clazz, JMethodIDPtr methodID,
+                  ffi.Pointer<JValue> args)>()(clazz, methodID, args)
+          .object;
+
+  bool CallStaticBooleanMethod(JClassPtr clazz, JMethodIDPtr methodID) =>
+      ref.CallStaticBooleanMethod.asFunction<
+              JniResult Function(
+                  JClassPtr clazz, JMethodIDPtr methodID)>()(clazz, methodID)
+          .boolean;
+
+  bool CallStaticBooleanMethodA(
+          JClassPtr clazz, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      ref.CallStaticBooleanMethodA.asFunction<
+              JniResult Function(JClassPtr clazz, JMethodIDPtr methodID,
+                  ffi.Pointer<JValue> args)>()(clazz, methodID, args)
+          .boolean;
+
+  int CallStaticByteMethod(JClassPtr clazz, JMethodIDPtr methodID) =>
+      ref.CallStaticByteMethod.asFunction<
+              JniResult Function(
+                  JClassPtr clazz, JMethodIDPtr methodID)>()(clazz, methodID)
+          .byte;
+
+  int CallStaticByteMethodA(
+          JClassPtr clazz, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      ref.CallStaticByteMethodA.asFunction<
+              JniResult Function(JClassPtr clazz, JMethodIDPtr methodID,
+                  ffi.Pointer<JValue> args)>()(clazz, methodID, args)
+          .byte;
+
+  int CallStaticCharMethod(JClassPtr clazz, JMethodIDPtr methodID) =>
+      ref.CallStaticCharMethod.asFunction<
+              JniResult Function(
+                  JClassPtr clazz, JMethodIDPtr methodID)>()(clazz, methodID)
+          .char;
+
+  int CallStaticCharMethodA(
+          JClassPtr clazz, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      ref.CallStaticCharMethodA.asFunction<
+              JniResult Function(JClassPtr clazz, JMethodIDPtr methodID,
+                  ffi.Pointer<JValue> args)>()(clazz, methodID, args)
+          .char;
+
+  int CallStaticShortMethod(JClassPtr clazz, JMethodIDPtr methodID) =>
+      ref.CallStaticShortMethod.asFunction<
+              JniResult Function(
+                  JClassPtr clazz, JMethodIDPtr methodID)>()(clazz, methodID)
+          .short;
+
+  int CallStaticShortMethodA(
+          JClassPtr clazz, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      ref.CallStaticShortMethodA.asFunction<
+              JniResult Function(JClassPtr clazz, JMethodIDPtr methodID,
+                  ffi.Pointer<JValue> args)>()(clazz, methodID, args)
+          .short;
+
+  int CallStaticIntMethod(JClassPtr clazz, JMethodIDPtr methodID) =>
+      ref.CallStaticIntMethod.asFunction<
+              JniResult Function(
+                  JClassPtr clazz, JMethodIDPtr methodID)>()(clazz, methodID)
+          .integer;
+
+  int CallStaticIntMethodA(
+          JClassPtr clazz, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      ref.CallStaticIntMethodA.asFunction<
+              JniResult Function(JClassPtr clazz, JMethodIDPtr methodID,
+                  ffi.Pointer<JValue> args)>()(clazz, methodID, args)
+          .integer;
+
+  int CallStaticLongMethod(JClassPtr clazz, JMethodIDPtr methodID) =>
+      ref.CallStaticLongMethod.asFunction<
+              JniResult Function(
+                  JClassPtr clazz, JMethodIDPtr methodID)>()(clazz, methodID)
+          .long;
+
+  int CallStaticLongMethodA(
+          JClassPtr clazz, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      ref.CallStaticLongMethodA.asFunction<
+              JniResult Function(JClassPtr clazz, JMethodIDPtr methodID,
+                  ffi.Pointer<JValue> args)>()(clazz, methodID, args)
+          .long;
+
+  double CallStaticFloatMethod(JClassPtr clazz, JMethodIDPtr methodID) =>
+      ref.CallStaticFloatMethod.asFunction<
+              JniResult Function(
+                  JClassPtr clazz, JMethodIDPtr methodID)>()(clazz, methodID)
+          .float;
+
+  double CallStaticFloatMethodA(
+          JClassPtr clazz, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      ref.CallStaticFloatMethodA.asFunction<
+              JniResult Function(JClassPtr clazz, JMethodIDPtr methodID,
+                  ffi.Pointer<JValue> args)>()(clazz, methodID, args)
+          .float;
+
+  double CallStaticDoubleMethod(JClassPtr clazz, JMethodIDPtr methodID) =>
+      ref.CallStaticDoubleMethod.asFunction<
+              JniResult Function(
+                  JClassPtr clazz, JMethodIDPtr methodID)>()(clazz, methodID)
+          .doubleFloat;
+
+  double CallStaticDoubleMethodA(
+          JClassPtr clazz, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      ref.CallStaticDoubleMethodA.asFunction<
+              JniResult Function(JClassPtr clazz, JMethodIDPtr methodID,
+                  ffi.Pointer<JValue> args)>()(clazz, methodID, args)
+          .doubleFloat;
+
+  void CallStaticVoidMethod(JClassPtr clazz, JMethodIDPtr methodID) =>
+      ref.CallStaticVoidMethod.asFunction<
+              JThrowablePtr Function(
+                  JClassPtr clazz, JMethodIDPtr methodID)>()(clazz, methodID)
+          .check();
+
+  void CallStaticVoidMethodA(
+          JClassPtr clazz, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      ref.CallStaticVoidMethodA.asFunction<
+              JThrowablePtr Function(JClassPtr clazz, JMethodIDPtr methodID,
+                  ffi.Pointer<JValue> args)>()(clazz, methodID, args)
+          .check();
+
+  JFieldIDPtr GetStaticFieldID(JClassPtr clazz, ffi.Pointer<ffi.Char> name,
+          ffi.Pointer<ffi.Char> sig) =>
+      ref.GetStaticFieldID.asFunction<
+              JniPointerResult Function(
+                  JClassPtr clazz,
+                  ffi.Pointer<ffi.Char> name,
+                  ffi.Pointer<ffi.Char> sig)>()(clazz, name, sig)
+          .fieldID;
+
+  JObjectPtr GetStaticObjectField(JClassPtr clazz, JFieldIDPtr fieldID) =>
+      ref.GetStaticObjectField.asFunction<
+              JniResult Function(
+                  JClassPtr clazz, JFieldIDPtr fieldID)>()(clazz, fieldID)
+          .object;
+
+  bool GetStaticBooleanField(JClassPtr clazz, JFieldIDPtr fieldID) =>
+      ref.GetStaticBooleanField.asFunction<
+              JniResult Function(
+                  JClassPtr clazz, JFieldIDPtr fieldID)>()(clazz, fieldID)
+          .boolean;
+
+  int GetStaticByteField(JClassPtr clazz, JFieldIDPtr fieldID) =>
+      ref.GetStaticByteField.asFunction<
+              JniResult Function(
+                  JClassPtr clazz, JFieldIDPtr fieldID)>()(clazz, fieldID)
+          .byte;
+
+  int GetStaticCharField(JClassPtr clazz, JFieldIDPtr fieldID) =>
+      ref.GetStaticCharField.asFunction<
+              JniResult Function(
+                  JClassPtr clazz, JFieldIDPtr fieldID)>()(clazz, fieldID)
+          .char;
+
+  int GetStaticShortField(JClassPtr clazz, JFieldIDPtr fieldID) =>
+      ref.GetStaticShortField.asFunction<
+              JniResult Function(
+                  JClassPtr clazz, JFieldIDPtr fieldID)>()(clazz, fieldID)
+          .short;
+
+  int GetStaticIntField(JClassPtr clazz, JFieldIDPtr fieldID) =>
+      ref.GetStaticIntField.asFunction<
+              JniResult Function(
+                  JClassPtr clazz, JFieldIDPtr fieldID)>()(clazz, fieldID)
+          .integer;
+
+  int GetStaticLongField(JClassPtr clazz, JFieldIDPtr fieldID) =>
+      ref.GetStaticLongField.asFunction<
+              JniResult Function(
+                  JClassPtr clazz, JFieldIDPtr fieldID)>()(clazz, fieldID)
+          .long;
+
+  double GetStaticFloatField(JClassPtr clazz, JFieldIDPtr fieldID) =>
+      ref.GetStaticFloatField.asFunction<
+              JniResult Function(
+                  JClassPtr clazz, JFieldIDPtr fieldID)>()(clazz, fieldID)
+          .float;
+
+  double GetStaticDoubleField(JClassPtr clazz, JFieldIDPtr fieldID) =>
+      ref.GetStaticDoubleField.asFunction<
+              JniResult Function(
+                  JClassPtr clazz, JFieldIDPtr fieldID)>()(clazz, fieldID)
+          .doubleFloat;
+
+  void SetStaticObjectField(
+          JClassPtr clazz, JFieldIDPtr fieldID, JObjectPtr val) =>
+      ref.SetStaticObjectField.asFunction<
+              JThrowablePtr Function(JClassPtr clazz, JFieldIDPtr fieldID,
+                  JObjectPtr val)>()(clazz, fieldID, val)
+          .check();
+
+  void SetStaticBooleanField(JClassPtr clazz, JFieldIDPtr fieldID, int val) =>
+      ref.SetStaticBooleanField.asFunction<
+              JThrowablePtr Function(JClassPtr clazz, JFieldIDPtr fieldID,
+                  int val)>()(clazz, fieldID, val)
+          .check();
+
+  void SetStaticByteField(JClassPtr clazz, JFieldIDPtr fieldID, int val) =>
+      ref.SetStaticByteField.asFunction<
+              JThrowablePtr Function(JClassPtr clazz, JFieldIDPtr fieldID,
+                  int val)>()(clazz, fieldID, val)
+          .check();
+
+  void SetStaticCharField(JClassPtr clazz, JFieldIDPtr fieldID, int val) =>
+      ref.SetStaticCharField.asFunction<
+              JThrowablePtr Function(JClassPtr clazz, JFieldIDPtr fieldID,
+                  int val)>()(clazz, fieldID, val)
+          .check();
+
+  void SetStaticShortField(JClassPtr clazz, JFieldIDPtr fieldID, int val) =>
+      ref.SetStaticShortField.asFunction<
+              JThrowablePtr Function(JClassPtr clazz, JFieldIDPtr fieldID,
+                  int val)>()(clazz, fieldID, val)
+          .check();
+
+  void SetStaticIntField(JClassPtr clazz, JFieldIDPtr fieldID, int val) =>
+      ref.SetStaticIntField.asFunction<
+              JThrowablePtr Function(JClassPtr clazz, JFieldIDPtr fieldID,
+                  int val)>()(clazz, fieldID, val)
+          .check();
+
+  void SetStaticLongField(JClassPtr clazz, JFieldIDPtr fieldID, int val) =>
+      ref.SetStaticLongField.asFunction<
+              JThrowablePtr Function(JClassPtr clazz, JFieldIDPtr fieldID,
+                  int val)>()(clazz, fieldID, val)
+          .check();
+
+  void SetStaticFloatField(JClassPtr clazz, JFieldIDPtr fieldID, double val) =>
+      ref.SetStaticFloatField.asFunction<
+              JThrowablePtr Function(JClassPtr clazz, JFieldIDPtr fieldID,
+                  double val)>()(clazz, fieldID, val)
+          .check();
+
+  void SetStaticDoubleField(JClassPtr clazz, JFieldIDPtr fieldID, double val) =>
+      ref.SetStaticDoubleField.asFunction<
+              JThrowablePtr Function(JClassPtr clazz, JFieldIDPtr fieldID,
+                  double val)>()(clazz, fieldID, val)
+          .check();
+
+  JStringPtr NewString(ffi.Pointer<JCharMarker> unicodeChars, int len) =>
+      ref.NewString.asFunction<
+              JniResult Function(ffi.Pointer<JCharMarker> unicodeChars,
+                  int len)>()(unicodeChars, len)
+          .object;
+
+  int GetStringLength(JStringPtr string) =>
+      ref.GetStringLength.asFunction<JniResult Function(JStringPtr string)>()(
+              string)
+          .integer;
+
+  ffi.Pointer<JCharMarker> GetStringChars(
+          JStringPtr string, ffi.Pointer<JBooleanMarker> isCopy) =>
+      ref.GetStringChars.asFunction<
+              JniPointerResult Function(JStringPtr string,
+                  ffi.Pointer<JBooleanMarker> isCopy)>()(string, isCopy)
+          .getPointer<JCharMarker>();
+
+  void ReleaseStringChars(JStringPtr string, ffi.Pointer<JCharMarker> isCopy) =>
+      ref.ReleaseStringChars.asFunction<
+              JThrowablePtr Function(JStringPtr string,
+                  ffi.Pointer<JCharMarker> isCopy)>()(string, isCopy)
+          .check();
+
+  JStringPtr NewStringUTF(ffi.Pointer<ffi.Char> bytes) => ref.NewStringUTF
+          .asFunction<JniResult Function(ffi.Pointer<ffi.Char> bytes)>()(bytes)
+      .object;
+
+  int GetStringUTFLength(JStringPtr string) => ref.GetStringUTFLength
+          .asFunction<JniResult Function(JStringPtr string)>()(string)
+      .integer;
+
+  ffi.Pointer<ffi.Char> GetStringUTFChars(
+          JStringPtr string, ffi.Pointer<JBooleanMarker> isCopy) =>
+      ref.GetStringUTFChars.asFunction<
+              JniPointerResult Function(JStringPtr string,
+                  ffi.Pointer<JBooleanMarker> isCopy)>()(string, isCopy)
+          .getPointer<ffi.Char>();
+
+  void ReleaseStringUTFChars(JStringPtr string, ffi.Pointer<ffi.Char> utf) =>
+      ref.ReleaseStringUTFChars.asFunction<
+              JThrowablePtr Function(
+                  JStringPtr string, ffi.Pointer<ffi.Char> utf)>()(string, utf)
+          .check();
+
+  int GetArrayLength(JArrayPtr array) =>
+      ref.GetArrayLength.asFunction<JniResult Function(JArrayPtr array)>()(
+              array)
+          .integer;
+
+  JObjectArrayPtr NewObjectArray(
+          int length, JClassPtr elementClass, JObjectPtr initialElement) =>
+      ref.NewObjectArray.asFunction<
+                  JniResult Function(int length, JClassPtr elementClass,
+                      JObjectPtr initialElement)>()(
+              length, elementClass, initialElement)
+          .object;
+
+  JObjectPtr GetObjectArrayElement(JObjectArrayPtr array, int index) =>
+      ref.GetObjectArrayElement.asFunction<
+              JniResult Function(
+                  JObjectArrayPtr array, int index)>()(array, index)
+          .object;
+
+  void SetObjectArrayElement(
+          JObjectArrayPtr array, int index, JObjectPtr val) =>
+      ref.SetObjectArrayElement.asFunction<
+              JThrowablePtr Function(JObjectArrayPtr array, int index,
+                  JObjectPtr val)>()(array, index, val)
+          .check();
+
+  JBooleanArrayPtr NewBooleanArray(int length) =>
+      ref.NewBooleanArray.asFunction<JniResult Function(int length)>()(length)
+          .object;
+
+  JByteArrayPtr NewByteArray(int length) =>
+      ref.NewByteArray.asFunction<JniResult Function(int length)>()(length)
+          .object;
+
+  JCharArrayPtr NewCharArray(int length) =>
+      ref.NewCharArray.asFunction<JniResult Function(int length)>()(length)
+          .object;
+
+  JShortArrayPtr NewShortArray(int length) =>
+      ref.NewShortArray.asFunction<JniResult Function(int length)>()(length)
+          .object;
+
+  JIntArrayPtr NewIntArray(int length) =>
+      ref.NewIntArray.asFunction<JniResult Function(int length)>()(length)
+          .object;
+
+  JLongArrayPtr NewLongArray(int length) =>
+      ref.NewLongArray.asFunction<JniResult Function(int length)>()(length)
+          .object;
+
+  JFloatArrayPtr NewFloatArray(int length) =>
+      ref.NewFloatArray.asFunction<JniResult Function(int length)>()(length)
+          .object;
+
+  JDoubleArrayPtr NewDoubleArray(int length) =>
+      ref.NewDoubleArray.asFunction<JniResult Function(int length)>()(length)
+          .object;
+
+  ffi.Pointer<JBooleanMarker> GetBooleanArrayElements(
+          JBooleanArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy) =>
+      ref.GetBooleanArrayElements.asFunction<
+              JniPointerResult Function(JBooleanArrayPtr array,
+                  ffi.Pointer<JBooleanMarker> isCopy)>()(array, isCopy)
+          .getPointer<JBooleanMarker>();
+
+  ffi.Pointer<JByteMarker> GetByteArrayElements(
+          JByteArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy) =>
+      ref.GetByteArrayElements.asFunction<
+              JniPointerResult Function(JByteArrayPtr array,
+                  ffi.Pointer<JBooleanMarker> isCopy)>()(array, isCopy)
+          .getPointer<JByteMarker>();
+
+  ffi.Pointer<JCharMarker> GetCharArrayElements(
+          JCharArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy) =>
+      ref.GetCharArrayElements.asFunction<
+              JniPointerResult Function(JCharArrayPtr array,
+                  ffi.Pointer<JBooleanMarker> isCopy)>()(array, isCopy)
+          .getPointer<JCharMarker>();
+
+  ffi.Pointer<JShortMarker> GetShortArrayElements(
+          JShortArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy) =>
+      ref.GetShortArrayElements.asFunction<
+              JniPointerResult Function(JShortArrayPtr array,
+                  ffi.Pointer<JBooleanMarker> isCopy)>()(array, isCopy)
+          .getPointer<JShortMarker>();
+
+  ffi.Pointer<JIntMarker> GetIntArrayElements(
+          JIntArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy) =>
+      ref.GetIntArrayElements.asFunction<
+              JniPointerResult Function(JIntArrayPtr array,
+                  ffi.Pointer<JBooleanMarker> isCopy)>()(array, isCopy)
+          .getPointer<JIntMarker>();
+
+  ffi.Pointer<JLongMarker> GetLongArrayElements(
+          JLongArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy) =>
+      ref.GetLongArrayElements.asFunction<
+              JniPointerResult Function(JLongArrayPtr array,
+                  ffi.Pointer<JBooleanMarker> isCopy)>()(array, isCopy)
+          .getPointer<JLongMarker>();
+
+  ffi.Pointer<JFloatMarker> GetFloatArrayElements(
+          JFloatArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy) =>
+      ref.GetFloatArrayElements.asFunction<
+              JniPointerResult Function(JFloatArrayPtr array,
+                  ffi.Pointer<JBooleanMarker> isCopy)>()(array, isCopy)
+          .getPointer<JFloatMarker>();
+
+  ffi.Pointer<JDoubleMarker> GetDoubleArrayElements(
+          JDoubleArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy) =>
+      ref.GetDoubleArrayElements.asFunction<
+              JniPointerResult Function(JDoubleArrayPtr array,
+                  ffi.Pointer<JBooleanMarker> isCopy)>()(array, isCopy)
+          .getPointer<JDoubleMarker>();
+
+  void ReleaseBooleanArrayElements(JBooleanArrayPtr array,
+          ffi.Pointer<JBooleanMarker> elems, int mode) =>
+      ref.ReleaseBooleanArrayElements.asFunction<
+              JThrowablePtr Function(
+                  JBooleanArrayPtr array,
+                  ffi.Pointer<JBooleanMarker> elems,
+                  int mode)>()(array, elems, mode)
+          .check();
+
+  void ReleaseByteArrayElements(
+          JByteArrayPtr array, ffi.Pointer<JByteMarker> elems, int mode) =>
+      ref.ReleaseByteArrayElements.asFunction<
+              JThrowablePtr Function(
+                  JByteArrayPtr array,
+                  ffi.Pointer<JByteMarker> elems,
+                  int mode)>()(array, elems, mode)
+          .check();
+
+  void ReleaseCharArrayElements(
+          JCharArrayPtr array, ffi.Pointer<JCharMarker> elems, int mode) =>
+      ref.ReleaseCharArrayElements.asFunction<
+              JThrowablePtr Function(
+                  JCharArrayPtr array,
+                  ffi.Pointer<JCharMarker> elems,
+                  int mode)>()(array, elems, mode)
+          .check();
+
+  void ReleaseShortArrayElements(
+          JShortArrayPtr array, ffi.Pointer<JShortMarker> elems, int mode) =>
+      ref.ReleaseShortArrayElements.asFunction<
+              JThrowablePtr Function(
+                  JShortArrayPtr array,
+                  ffi.Pointer<JShortMarker> elems,
+                  int mode)>()(array, elems, mode)
+          .check();
+
+  void ReleaseIntArrayElements(
+          JIntArrayPtr array, ffi.Pointer<JIntMarker> elems, int mode) =>
+      ref.ReleaseIntArrayElements.asFunction<
+              JThrowablePtr Function(
+                  JIntArrayPtr array,
+                  ffi.Pointer<JIntMarker> elems,
+                  int mode)>()(array, elems, mode)
+          .check();
+
+  void ReleaseLongArrayElements(
+          JLongArrayPtr array, ffi.Pointer<JLongMarker> elems, int mode) =>
+      ref.ReleaseLongArrayElements.asFunction<
+              JThrowablePtr Function(
+                  JLongArrayPtr array,
+                  ffi.Pointer<JLongMarker> elems,
+                  int mode)>()(array, elems, mode)
+          .check();
+
+  void ReleaseFloatArrayElements(
+          JFloatArrayPtr array, ffi.Pointer<JFloatMarker> elems, int mode) =>
+      ref.ReleaseFloatArrayElements.asFunction<
+              JThrowablePtr Function(
+                  JFloatArrayPtr array,
+                  ffi.Pointer<JFloatMarker> elems,
+                  int mode)>()(array, elems, mode)
+          .check();
+
+  void ReleaseDoubleArrayElements(
+          JDoubleArrayPtr array, ffi.Pointer<JDoubleMarker> elems, int mode) =>
+      ref.ReleaseDoubleArrayElements.asFunction<
+              JThrowablePtr Function(
+                  JDoubleArrayPtr array,
+                  ffi.Pointer<JDoubleMarker> elems,
+                  int mode)>()(array, elems, mode)
+          .check();
+
+  void GetBooleanArrayRegion(JBooleanArrayPtr array, int start, int len,
+          ffi.Pointer<JBooleanMarker> buf) =>
+      ref.GetBooleanArrayRegion.asFunction<
+              JThrowablePtr Function(JBooleanArrayPtr array, int start, int len,
+                  ffi.Pointer<JBooleanMarker> buf)>()(array, start, len, buf)
+          .check();
+
+  void GetByteArrayRegion(JByteArrayPtr array, int start, int len,
+          ffi.Pointer<JByteMarker> buf) =>
+      ref.GetByteArrayRegion.asFunction<
+              JThrowablePtr Function(JByteArrayPtr array, int start, int len,
+                  ffi.Pointer<JByteMarker> buf)>()(array, start, len, buf)
+          .check();
+
+  void GetCharArrayRegion(JCharArrayPtr array, int start, int len,
+          ffi.Pointer<JCharMarker> buf) =>
+      ref.GetCharArrayRegion.asFunction<
+              JThrowablePtr Function(JCharArrayPtr array, int start, int len,
+                  ffi.Pointer<JCharMarker> buf)>()(array, start, len, buf)
+          .check();
+
+  void GetShortArrayRegion(JShortArrayPtr array, int start, int len,
+          ffi.Pointer<JShortMarker> buf) =>
+      ref.GetShortArrayRegion.asFunction<
+              JThrowablePtr Function(JShortArrayPtr array, int start, int len,
+                  ffi.Pointer<JShortMarker> buf)>()(array, start, len, buf)
+          .check();
+
+  void GetIntArrayRegion(JIntArrayPtr array, int start, int len,
+          ffi.Pointer<JIntMarker> buf) =>
+      ref.GetIntArrayRegion.asFunction<
+              JThrowablePtr Function(JIntArrayPtr array, int start, int len,
+                  ffi.Pointer<JIntMarker> buf)>()(array, start, len, buf)
+          .check();
+
+  void GetLongArrayRegion(JLongArrayPtr array, int start, int len,
+          ffi.Pointer<JLongMarker> buf) =>
+      ref.GetLongArrayRegion.asFunction<
+              JThrowablePtr Function(JLongArrayPtr array, int start, int len,
+                  ffi.Pointer<JLongMarker> buf)>()(array, start, len, buf)
+          .check();
+
+  void GetFloatArrayRegion(JFloatArrayPtr array, int start, int len,
+          ffi.Pointer<JFloatMarker> buf) =>
+      ref.GetFloatArrayRegion.asFunction<
+              JThrowablePtr Function(JFloatArrayPtr array, int start, int len,
+                  ffi.Pointer<JFloatMarker> buf)>()(array, start, len, buf)
+          .check();
+
+  void GetDoubleArrayRegion(JDoubleArrayPtr array, int start, int len,
+          ffi.Pointer<JDoubleMarker> buf) =>
+      ref.GetDoubleArrayRegion.asFunction<
+              JThrowablePtr Function(JDoubleArrayPtr array, int start, int len,
+                  ffi.Pointer<JDoubleMarker> buf)>()(array, start, len, buf)
+          .check();
+
+  void SetBooleanArrayRegion(JBooleanArrayPtr array, int start, int len,
+          ffi.Pointer<JBooleanMarker> buf) =>
+      ref.SetBooleanArrayRegion.asFunction<
+              JThrowablePtr Function(JBooleanArrayPtr array, int start, int len,
+                  ffi.Pointer<JBooleanMarker> buf)>()(array, start, len, buf)
+          .check();
+
+  void SetByteArrayRegion(JByteArrayPtr array, int start, int len,
+          ffi.Pointer<JByteMarker> buf) =>
+      ref.SetByteArrayRegion.asFunction<
+              JThrowablePtr Function(JByteArrayPtr array, int start, int len,
+                  ffi.Pointer<JByteMarker> buf)>()(array, start, len, buf)
+          .check();
+
+  void SetCharArrayRegion(JCharArrayPtr array, int start, int len,
+          ffi.Pointer<JCharMarker> buf) =>
+      ref.SetCharArrayRegion.asFunction<
+              JThrowablePtr Function(JCharArrayPtr array, int start, int len,
+                  ffi.Pointer<JCharMarker> buf)>()(array, start, len, buf)
+          .check();
+
+  void SetShortArrayRegion(JShortArrayPtr array, int start, int len,
+          ffi.Pointer<JShortMarker> buf) =>
+      ref.SetShortArrayRegion.asFunction<
+              JThrowablePtr Function(JShortArrayPtr array, int start, int len,
+                  ffi.Pointer<JShortMarker> buf)>()(array, start, len, buf)
+          .check();
+
+  void SetIntArrayRegion(JIntArrayPtr array, int start, int len,
+          ffi.Pointer<JIntMarker> buf) =>
+      ref.SetIntArrayRegion.asFunction<
+              JThrowablePtr Function(JIntArrayPtr array, int start, int len,
+                  ffi.Pointer<JIntMarker> buf)>()(array, start, len, buf)
+          .check();
+
+  void SetLongArrayRegion(JLongArrayPtr array, int start, int len,
+          ffi.Pointer<JLongMarker> buf) =>
+      ref.SetLongArrayRegion.asFunction<
+              JThrowablePtr Function(JLongArrayPtr array, int start, int len,
+                  ffi.Pointer<JLongMarker> buf)>()(array, start, len, buf)
+          .check();
+
+  void SetFloatArrayRegion(JFloatArrayPtr array, int start, int len,
+          ffi.Pointer<JFloatMarker> buf) =>
+      ref.SetFloatArrayRegion.asFunction<
+              JThrowablePtr Function(JFloatArrayPtr array, int start, int len,
+                  ffi.Pointer<JFloatMarker> buf)>()(array, start, len, buf)
+          .check();
+
+  void SetDoubleArrayRegion(JDoubleArrayPtr array, int start, int len,
+          ffi.Pointer<JDoubleMarker> buf) =>
+      ref.SetDoubleArrayRegion.asFunction<
+              JThrowablePtr Function(JDoubleArrayPtr array, int start, int len,
+                  ffi.Pointer<JDoubleMarker> buf)>()(array, start, len, buf)
+          .check();
+
+  int RegisterNatives(JClassPtr clazz, ffi.Pointer<JNINativeMethod> methods,
+          int nMethods) =>
+      ref.RegisterNatives.asFunction<
+              JniResult Function(
+                  JClassPtr clazz,
+                  ffi.Pointer<JNINativeMethod> methods,
+                  int nMethods)>()(clazz, methods, nMethods)
+          .integer;
+
+  int UnregisterNatives(JClassPtr clazz) =>
+      ref.UnregisterNatives.asFunction<JniResult Function(JClassPtr clazz)>()(
+              clazz)
+          .integer;
+
+  int MonitorEnter(JObjectPtr obj) =>
+      ref.MonitorEnter.asFunction<JniResult Function(JObjectPtr obj)>()(obj)
+          .integer;
+
+  int MonitorExit(JObjectPtr obj) =>
+      ref.MonitorExit.asFunction<JniResult Function(JObjectPtr obj)>()(obj)
+          .integer;
+
+  int GetJavaVM(ffi.Pointer<ffi.Pointer<JavaVM1>> vm) =>
+      ref.GetJavaVM.asFunction<
+              JniResult Function(ffi.Pointer<ffi.Pointer<JavaVM1>> vm)>()(vm)
+          .integer;
+
+  void GetStringRegion(
+          JStringPtr str, int start, int len, ffi.Pointer<JCharMarker> buf) =>
+      ref.GetStringRegion.asFunction<
+              JThrowablePtr Function(JStringPtr str, int start, int len,
+                  ffi.Pointer<JCharMarker> buf)>()(str, start, len, buf)
+          .check();
+
+  void GetStringUTFRegion(
+          JStringPtr str, int start, int len, ffi.Pointer<ffi.Char> buf) =>
+      ref.GetStringUTFRegion.asFunction<
+              JThrowablePtr Function(JStringPtr str, int start, int len,
+                  ffi.Pointer<ffi.Char> buf)>()(str, start, len, buf)
+          .check();
+
+  ffi.Pointer<ffi.Void> GetPrimitiveArrayCritical(
+          JArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy) =>
+      ref.GetPrimitiveArrayCritical.asFunction<
+              JniPointerResult Function(JArrayPtr array,
+                  ffi.Pointer<JBooleanMarker> isCopy)>()(array, isCopy)
+          .getPointer<ffi.Void>();
+
+  void ReleasePrimitiveArrayCritical(
+          JArrayPtr array, ffi.Pointer<ffi.Void> carray, int mode) =>
+      ref.ReleasePrimitiveArrayCritical.asFunction<
+              JThrowablePtr Function(
+                  JArrayPtr array,
+                  ffi.Pointer<ffi.Void> carray,
+                  int mode)>()(array, carray, mode)
+          .check();
+
+  ffi.Pointer<JCharMarker> GetStringCritical(
+          JStringPtr str, ffi.Pointer<JBooleanMarker> isCopy) =>
+      ref.GetStringCritical.asFunction<
+              JniPointerResult Function(JStringPtr str,
+                  ffi.Pointer<JBooleanMarker> isCopy)>()(str, isCopy)
+          .getPointer<JCharMarker>();
+
+  void ReleaseStringCritical(JStringPtr str, ffi.Pointer<JCharMarker> carray) =>
+      ref.ReleaseStringCritical.asFunction<
+              JThrowablePtr Function(JStringPtr str,
+                  ffi.Pointer<JCharMarker> carray)>()(str, carray)
+          .check();
+
+  JWeakPtr NewWeakGlobalRef(JObjectPtr obj) =>
+      ref.NewWeakGlobalRef.asFunction<JniResult Function(JObjectPtr obj)>()(obj)
+          .object;
+
+  void DeleteWeakGlobalRef(JWeakPtr obj) => ref.DeleteWeakGlobalRef.asFunction<
+          JThrowablePtr Function(JWeakPtr obj)>()(obj)
+      .check();
+
+  bool ExceptionCheck() =>
+      ref.ExceptionCheck.asFunction<JniResult Function()>()().boolean;
+
+  JObjectPtr NewDirectByteBuffer(ffi.Pointer<ffi.Void> address, int capacity) =>
+      ref.NewDirectByteBuffer.asFunction<
+              JniResult Function(ffi.Pointer<ffi.Void> address,
+                  int capacity)>()(address, capacity)
+          .object;
+
+  ffi.Pointer<ffi.Void> GetDirectBufferAddress(JObjectPtr buf) =>
+      ref.GetDirectBufferAddress.asFunction<
+              JniPointerResult Function(JObjectPtr buf)>()(buf)
+          .getPointer<ffi.Void>();
+
+  int GetDirectBufferCapacity(JObjectPtr buf) => ref.GetDirectBufferCapacity
+          .asFunction<JniResult Function(JObjectPtr buf)>()(buf)
+      .long;
+
+  int GetObjectRefType(JObjectPtr obj) =>
+      ref.GetObjectRefType.asFunction<JniResult Function(JObjectPtr obj)>()(obj)
+          .integer;
+}
+
+extension JniAccessorsExtension on ffi.Pointer<JniAccessors> {
+  JniClassLookupResult getClass(ffi.Pointer<ffi.Char> internalName) =>
+      ref.getClass.asFunction<
+          JniClassLookupResult Function(
+              ffi.Pointer<ffi.Char> internalName)>()(internalName);
+
+  JniPointerResult getFieldID(JClassPtr cls, ffi.Pointer<ffi.Char> fieldName,
+          ffi.Pointer<ffi.Char> signature) =>
+      ref.getFieldID.asFunction<
+          JniPointerResult Function(
+              JClassPtr cls,
+              ffi.Pointer<ffi.Char> fieldName,
+              ffi.Pointer<ffi.Char> signature)>()(cls, fieldName, signature);
+
+  JniPointerResult getStaticFieldID(JClassPtr cls,
+          ffi.Pointer<ffi.Char> fieldName, ffi.Pointer<ffi.Char> signature) =>
+      ref.getStaticFieldID.asFunction<
+          JniPointerResult Function(
+              JClassPtr cls,
+              ffi.Pointer<ffi.Char> fieldName,
+              ffi.Pointer<ffi.Char> signature)>()(cls, fieldName, signature);
+
+  JniPointerResult getMethodID(JClassPtr cls, ffi.Pointer<ffi.Char> methodName,
+          ffi.Pointer<ffi.Char> signature) =>
+      ref.getMethodID.asFunction<
+          JniPointerResult Function(
+              JClassPtr cls,
+              ffi.Pointer<ffi.Char> methodName,
+              ffi.Pointer<ffi.Char> signature)>()(cls, methodName, signature);
+
+  JniPointerResult getStaticMethodID(JClassPtr cls,
+          ffi.Pointer<ffi.Char> methodName, ffi.Pointer<ffi.Char> signature) =>
+      ref.getStaticMethodID.asFunction<
+          JniPointerResult Function(
+              JClassPtr cls,
+              ffi.Pointer<ffi.Char> methodName,
+              ffi.Pointer<ffi.Char> signature)>()(cls, methodName, signature);
+
+  JniResult newObject(
+          JClassPtr cls, JMethodIDPtr ctor, ffi.Pointer<JValue> args) =>
+      ref.newObject.asFunction<
+          JniResult Function(JClassPtr cls, JMethodIDPtr ctor,
+              ffi.Pointer<JValue> args)>()(cls, ctor, args);
+
+  JniPointerResult newPrimitiveArray(int length, int type) =>
+      ref.newPrimitiveArray
+              .asFunction<JniPointerResult Function(int length, int type)>()(
+          length, type);
+
+  JniPointerResult newObjectArray(
+          int length, JClassPtr elementClass, JObjectPtr initialElement) =>
+      ref.newObjectArray.asFunction<
+              JniPointerResult Function(int length, JClassPtr elementClass,
+                  JObjectPtr initialElement)>()(
+          length, elementClass, initialElement);
+
+  JniResult getArrayElement(JArrayPtr array, int index, int type) =>
+      ref.getArrayElement.asFunction<
+          JniResult Function(
+              JArrayPtr array, int index, int type)>()(array, index, type);
+
+  JniResult callMethod(JObjectPtr obj, JMethodIDPtr methodID, int callType,
+          ffi.Pointer<JValue> args) =>
+      ref.callMethod.asFunction<
+          JniResult Function(
+              JObjectPtr obj,
+              JMethodIDPtr methodID,
+              int callType,
+              ffi.Pointer<JValue> args)>()(obj, methodID, callType, args);
+
+  JniResult callStaticMethod(JClassPtr cls, JMethodIDPtr methodID, int callType,
+          ffi.Pointer<JValue> args) =>
+      ref.callStaticMethod.asFunction<
+          JniResult Function(JClassPtr cls, JMethodIDPtr methodID, int callType,
+              ffi.Pointer<JValue> args)>()(cls, methodID, callType, args);
+
+  JniResult getField(JObjectPtr obj, JFieldIDPtr fieldID, int callType) =>
+      ref.getField.asFunction<
+          JniResult Function(JObjectPtr obj, JFieldIDPtr fieldID,
+              int callType)>()(obj, fieldID, callType);
+
+  JniResult getStaticField(JClassPtr cls, JFieldIDPtr fieldID, int callType) =>
+      ref.getStaticField.asFunction<
+          JniResult Function(JClassPtr cls, JFieldIDPtr fieldID,
+              int callType)>()(cls, fieldID, callType);
+
+  JniExceptionDetails getExceptionDetails(JThrowablePtr exception) => ref
+          .getExceptionDetails
+          .asFunction<JniExceptionDetails Function(JThrowablePtr exception)>()(
+      exception);
+}
diff --git a/pkgs/jni/lib/src/third_party/jni_bindings_generated.dart b/pkgs/jni/lib/src/third_party/jni_bindings_generated.dart
index 3ca9198..eb5ba0b 100644
--- a/pkgs/jni/lib/src/third_party/jni_bindings_generated.dart
+++ b/pkgs/jni/lib/src/third_party/jni_bindings_generated.dart
@@ -37,6 +37,7 @@
 // AUTO GENERATED FILE, DO NOT EDIT.
 //
 // Generated by `package:ffigen`.
+// ignore_for_file: type=lint
 import 'dart:ffi' as ffi;
 
 /// Bindings for libdartjni.so which is part of jni plugin.
@@ -90,7 +91,12 @@
   late final _GetJniEnv =
       _GetJniEnvPtr.asFunction<ffi.Pointer<JniEnv> Function()>();
 
-  ffi.Pointer<JniEnv> SpawnJvm(
+  /// Spawn a JVM with given arguments.
+  ///
+  /// Returns JNI_OK on success, and one of the documented JNI error codes on
+  /// failure. It returns DART_JNI_SINGLETON_EXISTS if an attempt to spawn multiple
+  /// JVMs is made, even if the underlying API potentially supports multiple VMs.
+  int SpawnJvm(
     ffi.Pointer<JavaVMInitArgs> args,
   ) {
     return _SpawnJvm(
@@ -99,26 +105,33 @@
   }
 
   late final _SpawnJvmPtr = _lookup<
-      ffi.NativeFunction<
-          ffi.Pointer<JniEnv> Function(
-              ffi.Pointer<JavaVMInitArgs>)>>('SpawnJvm');
-  late final _SpawnJvm = _SpawnJvmPtr.asFunction<
-      ffi.Pointer<JniEnv> Function(ffi.Pointer<JavaVMInitArgs>)>();
+          ffi.NativeFunction<ffi.Int Function(ffi.Pointer<JavaVMInitArgs>)>>(
+      'SpawnJvm');
+  late final _SpawnJvm =
+      _SpawnJvmPtr.asFunction<int Function(ffi.Pointer<JavaVMInitArgs>)>();
 
-  JClassPtr LoadClass(
+  /// Load class through platform-specific mechanism.
+  ///
+  /// Currently uses application classloader on android,
+  /// and JNIEnv->FindClass on other platforms.
+  JClassPtr FindClass(
     ffi.Pointer<ffi.Char> name,
   ) {
-    return _LoadClass(
+    return _FindClass(
       name,
     );
   }
 
-  late final _LoadClassPtr =
+  late final _FindClassPtr =
       _lookup<ffi.NativeFunction<JClassPtr Function(ffi.Pointer<ffi.Char>)>>(
-          'LoadClass');
-  late final _LoadClass =
-      _LoadClassPtr.asFunction<JClassPtr Function(ffi.Pointer<ffi.Char>)>();
+          'FindClass');
+  late final _FindClass =
+      _FindClassPtr.asFunction<JClassPtr Function(ffi.Pointer<ffi.Char>)>();
 
+  /// Returns Application classLoader (on Android),
+  /// which can be used to load application and platform classes.
+  ///
+  /// On other platforms, NULL is returned.
   JObjectPtr GetClassLoader() {
     return _GetClassLoader();
   }
@@ -128,6 +141,9 @@
   late final _GetClassLoader =
       _GetClassLoaderPtr.asFunction<JObjectPtr Function()>();
 
+  /// Returns application context on Android.
+  ///
+  /// On other platforms, NULL is returned.
   JObjectPtr GetApplicationContext() {
     return _GetApplicationContext();
   }
@@ -138,6 +154,7 @@
   late final _GetApplicationContext =
       _GetApplicationContextPtr.asFunction<JObjectPtr Function()>();
 
+  /// Returns current activity of the app on Android.
   JObjectPtr GetCurrentActivity() {
     return _GetCurrentActivity();
   }
@@ -186,9 +203,29 @@
       _GetGlobalEnvPtr.asFunction<ffi.Pointer<GlobalJniEnv> Function()>();
 }
 
-class jfieldID_ extends ffi.Opaque {}
+/// Types used by JNI API to distinguish between primitive types.
+abstract class JniCallType {
+  static const int booleanType = 0;
+  static const int byteType = 1;
+  static const int shortType = 2;
+  static const int charType = 3;
+  static const int intType = 4;
+  static const int longType = 5;
+  static const int floatType = 6;
+  static const int doubleType = 7;
+  static const int objectType = 8;
+  static const int voidType = 9;
+}
 
-class jmethodID_ extends ffi.Opaque {}
+/// Result type for use by JNI.
+///
+/// If [exception] is null, it means the result is valid.
+/// It's assumed that the caller knows the expected type in [result].
+class JniResult extends ffi.Struct {
+  external JValue value;
+
+  external JThrowablePtr exception;
+}
 
 class JValue extends ffi.Union {
   @JBooleanMarker()
@@ -230,27 +267,135 @@
 
 /// Reference types, in C.
 typedef JObjectPtr = ffi.Pointer<ffi.Void>;
+typedef JThrowablePtr = JObjectPtr;
 
-abstract class jobjectRefType {
-  static const int JNIInvalidRefType = 0;
-  static const int JNILocalRefType = 1;
-  static const int JNIGlobalRefType = 2;
-  static const int JNIWeakGlobalRefType = 3;
+/// Similar to [JniResult] but for class lookups.
+class JniClassLookupResult extends ffi.Struct {
+  external JClassPtr value;
+
+  external JThrowablePtr exception;
 }
 
-class JNINativeMethod extends ffi.Struct {
-  external ffi.Pointer<ffi.Char> name;
+typedef JClassPtr = JObjectPtr;
 
-  external ffi.Pointer<ffi.Char> signature;
+/// Similar to [JniResult] but for method/field ID lookups.
+class JniPointerResult extends ffi.Struct {
+  external ffi.Pointer<ffi.Void> value;
 
-  external ffi.Pointer<ffi.Void> fnPtr;
+  external JThrowablePtr exception;
 }
 
-/// C++ version.
-class _JavaVM extends ffi.Struct {
-  external ffi.Pointer<JNIInvokeInterface> functions;
+/// JniExceptionDetails holds 2 jstring objects, one is the result of
+/// calling `toString` on exception object, other is stack trace;
+class JniExceptionDetails extends ffi.Struct {
+  external JStringPtr message;
+
+  external JStringPtr stacktrace;
 }
 
+typedef JStringPtr = JObjectPtr;
+
+/// This struct contains functions which wrap method call / field access conveniently along with
+/// exception checking.
+///
+/// Flutter embedding checks for pending JNI exceptions before an FFI transition, which requires us
+/// to check for and clear the exception before returning to dart code, which requires these functions
+/// to return result types.
+class JniAccessors extends ffi.Struct {
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JniClassLookupResult Function(
+              ffi.Pointer<ffi.Char> internalName)>> getClass;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JniPointerResult Function(
+              JClassPtr cls,
+              ffi.Pointer<ffi.Char> fieldName,
+              ffi.Pointer<ffi.Char> signature)>> getFieldID;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JniPointerResult Function(
+              JClassPtr cls,
+              ffi.Pointer<ffi.Char> fieldName,
+              ffi.Pointer<ffi.Char> signature)>> getStaticFieldID;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JniPointerResult Function(
+              JClassPtr cls,
+              ffi.Pointer<ffi.Char> methodName,
+              ffi.Pointer<ffi.Char> signature)>> getMethodID;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JniPointerResult Function(
+              JClassPtr cls,
+              ffi.Pointer<ffi.Char> methodName,
+              ffi.Pointer<ffi.Char> signature)>> getStaticMethodID;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JniResult Function(
+                  JClassPtr cls, JMethodIDPtr ctor, ffi.Pointer<JValue> args)>>
+      newObject;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JniPointerResult Function(JSizeMarker length, ffi.Int type)>>
+      newPrimitiveArray;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JniPointerResult Function(JSizeMarker length, JClassPtr elementClass,
+              JObjectPtr initialElement)>> newObjectArray;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JniResult Function(JArrayPtr array, ffi.Int index, ffi.Int type)>>
+      getArrayElement;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JniResult Function(JObjectPtr obj, JMethodIDPtr methodID,
+              ffi.Int callType, ffi.Pointer<JValue> args)>> callMethod;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JniResult Function(JClassPtr cls, JMethodIDPtr methodID,
+              ffi.Int callType, ffi.Pointer<JValue> args)>> callStaticMethod;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JniResult Function(
+              JObjectPtr obj, JFieldIDPtr fieldID, ffi.Int callType)>> getField;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JniResult Function(
+                  JClassPtr cls, JFieldIDPtr fieldID, ffi.Int callType)>>
+      getStaticField;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JniExceptionDetails Function(JThrowablePtr exception)>>
+      getExceptionDetails;
+}
+
+typedef JMethodIDPtr = ffi.Pointer<jmethodID_>;
+
+class jmethodID_ extends ffi.Opaque {}
+
+/// "cardinal indices and sizes"
+typedef JSizeMarker = JIntMarker;
+typedef JArrayPtr = JObjectPtr;
+typedef JFieldIDPtr = ffi.Pointer<jfieldID_>;
+
+class jfieldID_ extends ffi.Opaque {}
+
+typedef JavaVM = ffi.Pointer<JNIInvokeInterface>;
+
 /// JNI invocation interface.
 class JNIInvokeInterface extends ffi.Struct {
   external ffi.Pointer<ffi.Void> reserved0;
@@ -259,67 +404,37 @@
 
   external ffi.Pointer<ffi.Void> reserved2;
 
-  external ffi
-          .Pointer<ffi.NativeFunction<JIntMarker Function(ffi.Pointer<JavaVM>)>>
+  external ffi.Pointer<
+          ffi.NativeFunction<JIntMarker Function(ffi.Pointer<JavaVM1> vm)>>
       DestroyJavaVM;
 
   external ffi.Pointer<
       ffi.NativeFunction<
           JIntMarker Function(
-              ffi.Pointer<JavaVM>,
-              ffi.Pointer<ffi.Pointer<JniEnv>>,
-              ffi.Pointer<ffi.Void>)>> AttachCurrentThread;
+              ffi.Pointer<JavaVM1> vm,
+              ffi.Pointer<ffi.Pointer<JniEnv>> p_env,
+              ffi.Pointer<ffi.Void> thr_args)>> AttachCurrentThread;
 
-  external ffi
-          .Pointer<ffi.NativeFunction<JIntMarker Function(ffi.Pointer<JavaVM>)>>
+  external ffi.Pointer<
+          ffi.NativeFunction<JIntMarker Function(ffi.Pointer<JavaVM1> vm)>>
       DetachCurrentThread;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          JIntMarker Function(ffi.Pointer<JavaVM>,
-              ffi.Pointer<ffi.Pointer<ffi.Void>>, JIntMarker)>> GetEnv;
+          JIntMarker Function(
+              ffi.Pointer<JavaVM1> vm,
+              ffi.Pointer<ffi.Pointer<ffi.Void>> p_env,
+              JIntMarker version)>> GetEnv;
 
   external ffi.Pointer<
       ffi.NativeFunction<
           JIntMarker Function(
-              ffi.Pointer<JavaVM>,
-              ffi.Pointer<ffi.Pointer<JniEnv>>,
-              ffi.Pointer<ffi.Void>)>> AttachCurrentThreadAsDaemon;
+              ffi.Pointer<JavaVM1> vm,
+              ffi.Pointer<ffi.Pointer<JniEnv>> p_env,
+              ffi.Pointer<ffi.Void> thr_args)>> AttachCurrentThreadAsDaemon;
 }
 
-extension JNIInvokeInterfaceExtension on ffi.Pointer<JavaVM> {
-  int DestroyJavaVM() {
-    return value.ref.DestroyJavaVM
-        .asFunction<int Function(ffi.Pointer<JavaVM>)>()(this);
-  }
-
-  int AttachCurrentThread(
-      ffi.Pointer<ffi.Pointer<JniEnv>> p_env, ffi.Pointer<ffi.Void> thr_args) {
-    return value.ref.AttachCurrentThread.asFunction<
-        int Function(ffi.Pointer<JavaVM>, ffi.Pointer<ffi.Pointer<JniEnv>>,
-            ffi.Pointer<ffi.Void>)>()(this, p_env, thr_args);
-  }
-
-  int DetachCurrentThread() {
-    return value.ref.DetachCurrentThread
-        .asFunction<int Function(ffi.Pointer<JavaVM>)>()(this);
-  }
-
-  int GetEnv(ffi.Pointer<ffi.Pointer<ffi.Void>> p_env, int version) {
-    return value.ref.GetEnv.asFunction<
-        int Function(ffi.Pointer<JavaVM>, ffi.Pointer<ffi.Pointer<ffi.Void>>,
-            int)>()(this, p_env, version);
-  }
-
-  int AttachCurrentThreadAsDaemon(
-      ffi.Pointer<ffi.Pointer<JniEnv>> p_env, ffi.Pointer<ffi.Void> thr_args) {
-    return value.ref.AttachCurrentThreadAsDaemon.asFunction<
-        int Function(ffi.Pointer<JavaVM>, ffi.Pointer<ffi.Pointer<JniEnv>>,
-            ffi.Pointer<ffi.Void>)>()(this, p_env, thr_args);
-  }
-}
-
-typedef JavaVM = ffi.Pointer<JNIInvokeInterface>;
+typedef JavaVM1 = ffi.Pointer<JNIInvokeInterface>;
 typedef JniEnv = ffi.Pointer<JNINativeInterface>;
 
 /// Table of interface function pointers.
@@ -333,1131 +448,1445 @@
   external ffi.Pointer<ffi.Void> reserved3;
 
   external ffi.Pointer<
-      ffi.NativeFunction<JIntMarker Function(ffi.Pointer<JniEnv1>)>> GetVersion;
+          ffi.NativeFunction<JIntMarker Function(ffi.Pointer<JniEnv1> env)>>
+      GetVersion;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          JClassPtr Function(ffi.Pointer<JniEnv1>, ffi.Pointer<ffi.Char>,
-              JObjectPtr, ffi.Pointer<JByteMarker>, JSizeMarker)>> DefineClass;
+          JClassPtr Function(
+              ffi.Pointer<JniEnv1> env,
+              ffi.Pointer<ffi.Char> name,
+              JObjectPtr loader,
+              ffi.Pointer<JByteMarker> buf,
+              JSizeMarker bufLen)>> DefineClass;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JClassPtr Function(
+              ffi.Pointer<JniEnv1> env, ffi.Pointer<ffi.Char> name)>> FindClass;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              JClassPtr Function(ffi.Pointer<JniEnv1>, ffi.Pointer<ffi.Char>)>>
-      FindClass;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              JMethodIDPtr Function(ffi.Pointer<JniEnv1>, JObjectPtr)>>
+              JMethodIDPtr Function(
+                  ffi.Pointer<JniEnv1> env, JObjectPtr method)>>
       FromReflectedMethod;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              JFieldIDPtr Function(ffi.Pointer<JniEnv1>, JObjectPtr)>>
+              JFieldIDPtr Function(ffi.Pointer<JniEnv1> env, JObjectPtr field)>>
       FromReflectedField;
 
   /// spec doesn't show jboolean parameter
   external ffi.Pointer<
       ffi.NativeFunction<
-          JObjectPtr Function(ffi.Pointer<JniEnv1>, JClassPtr, JMethodIDPtr,
-              JBooleanMarker)>> ToReflectedMethod;
+          JObjectPtr Function(
+              ffi.Pointer<JniEnv1> env,
+              JClassPtr cls,
+              JMethodIDPtr methodId,
+              JBooleanMarker isStatic)>> ToReflectedMethod;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JClassPtr Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz)>>
+      GetSuperclass;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          JClassPtr Function(ffi.Pointer<JniEnv1>, JClassPtr)>> GetSuperclass;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          JBooleanMarker Function(
-              ffi.Pointer<JniEnv1>, JClassPtr, JClassPtr)>> IsAssignableFrom;
+          JBooleanMarker Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz1,
+              JClassPtr clazz2)>> IsAssignableFrom;
 
   /// spec doesn't show jboolean parameter
   external ffi.Pointer<
       ffi.NativeFunction<
-          JObjectPtr Function(ffi.Pointer<JniEnv1>, JClassPtr, JFieldIDPtr,
-              JBooleanMarker)>> ToReflectedField;
+          JObjectPtr Function(ffi.Pointer<JniEnv1> env, JClassPtr cls,
+              JFieldIDPtr fieldID, JBooleanMarker isStatic)>> ToReflectedField;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JIntMarker Function(ffi.Pointer<JniEnv1> env, JThrowablePtr obj)>>
+      Throw;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          JIntMarker Function(ffi.Pointer<JniEnv1>, JThrowablePtr)>> Throw;
+          JIntMarker Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              ffi.Pointer<ffi.Char> message)>> ThrowNew;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<JThrowablePtr Function(ffi.Pointer<JniEnv1> env)>>
+      ExceptionOccurred;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<ffi.Void Function(ffi.Pointer<JniEnv1> env)>>
+      ExceptionDescribe;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<ffi.Void Function(ffi.Pointer<JniEnv1> env)>>
+      ExceptionClear;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          ffi.Void Function(
+              ffi.Pointer<JniEnv1> env, ffi.Pointer<ffi.Char> msg)>> FatalError;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JIntMarker Function(
+              ffi.Pointer<JniEnv1> env, JIntMarker capacity)>> PushLocalFrame;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JObjectPtr Function(ffi.Pointer<JniEnv1> env, JObjectPtr result)>>
+      PopLocalFrame;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JObjectPtr Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj)>>
+      NewGlobalRef;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          ffi.Void Function(
+              ffi.Pointer<JniEnv1> env, JObjectPtr globalRef)>> DeleteGlobalRef;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              ffi.Void Function(ffi.Pointer<JniEnv1> env, JObjectPtr localRef)>>
+      DeleteLocalRef;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JBooleanMarker Function(
+                  ffi.Pointer<JniEnv1> env, JObjectPtr ref1, JObjectPtr ref2)>>
+      IsSameObject;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JObjectPtr Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj)>>
+      NewLocalRef;
 
   external ffi.Pointer<
           ffi.NativeFunction<
               JIntMarker Function(
-                  ffi.Pointer<JniEnv1>, JClassPtr, ffi.Pointer<ffi.Char>)>>
-      ThrowNew;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<JThrowablePtr Function(ffi.Pointer<JniEnv1>)>>
-      ExceptionOccurred;
-
-  external ffi
-          .Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<JniEnv1>)>>
-      ExceptionDescribe;
-
-  external ffi
-          .Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<JniEnv1>)>>
-      ExceptionClear;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              ffi.Void Function(ffi.Pointer<JniEnv1>, ffi.Pointer<ffi.Char>)>>
-      FatalError;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              JIntMarker Function(ffi.Pointer<JniEnv1>, JIntMarker)>>
-      PushLocalFrame;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          JObjectPtr Function(ffi.Pointer<JniEnv1>, JObjectPtr)>> PopLocalFrame;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          JObjectPtr Function(ffi.Pointer<JniEnv1>, JObjectPtr)>> NewGlobalRef;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          ffi.Void Function(ffi.Pointer<JniEnv1>, JObjectPtr)>> DeleteGlobalRef;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          ffi.Void Function(ffi.Pointer<JniEnv1>, JObjectPtr)>> DeleteLocalRef;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          JBooleanMarker Function(
-              ffi.Pointer<JniEnv1>, JObjectPtr, JObjectPtr)>> IsSameObject;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          JObjectPtr Function(ffi.Pointer<JniEnv1>, JObjectPtr)>> NewLocalRef;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              JIntMarker Function(ffi.Pointer<JniEnv1>, JIntMarker)>>
+                  ffi.Pointer<JniEnv1> env, JIntMarker capacity)>>
       EnsureLocalCapacity;
 
   external ffi.Pointer<
-      ffi.NativeFunction<
-          JObjectPtr Function(ffi.Pointer<JniEnv1>, JClassPtr)>> AllocObject;
+          ffi.NativeFunction<
+              JObjectPtr Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz)>>
+      AllocObject;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          JObjectPtr Function(
-              ffi.Pointer<JniEnv1>, JClassPtr, JMethodIDPtr)>> NewObject;
-
-  external ffi.Pointer<ffi.Void> _NewObjectV;
+          JObjectPtr Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JMethodIDPtr methodID)>> NewObject;
 
   external ffi.Pointer<
       ffi.NativeFunction<
           JObjectPtr Function(ffi.Pointer<JniEnv1>, JClassPtr, JMethodIDPtr,
-              ffi.Pointer<JValue>)>> NewObjectA;
+              ffi.Pointer<ffi.Void>)>> NewObjectV;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          JClassPtr Function(ffi.Pointer<JniEnv1>, JObjectPtr)>> GetObjectClass;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          JBooleanMarker Function(
-              ffi.Pointer<JniEnv1>, JObjectPtr, JClassPtr)>> IsInstanceOf;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          JMethodIDPtr Function(ffi.Pointer<JniEnv1>, JClassPtr,
-              ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Char>)>> GetMethodID;
+          JObjectPtr Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JMethodIDPtr methodID, ffi.Pointer<JValue> args)>> NewObjectA;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              JObjectPtr Function(
-                  ffi.Pointer<JniEnv1>, JObjectPtr, JMethodIDPtr)>>
-      CallObjectMethod;
+              JClassPtr Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj)>>
+      GetObjectClass;
 
-  external ffi.Pointer<ffi.Void> _CallObjectMethodV;
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JBooleanMarker Function(
+                  ffi.Pointer<JniEnv1> env, JObjectPtr obj, JClassPtr clazz)>>
+      IsInstanceOf;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JMethodIDPtr Function(
+              ffi.Pointer<JniEnv1> env,
+              JClassPtr clazz,
+              ffi.Pointer<ffi.Char> name,
+              ffi.Pointer<ffi.Char> sig)>> GetMethodID;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JObjectPtr Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JMethodIDPtr methodID)>> CallObjectMethod;
 
   external ffi.Pointer<
       ffi.NativeFunction<
           JObjectPtr Function(ffi.Pointer<JniEnv1>, JObjectPtr, JMethodIDPtr,
-              ffi.Pointer<JValue>)>> CallObjectMethodA;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              JBooleanMarker Function(
-                  ffi.Pointer<JniEnv1>, JObjectPtr, JMethodIDPtr)>>
-      CallBooleanMethod;
-
-  external ffi.Pointer<ffi.Void> _CallBooleanMethodV;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          JBooleanMarker Function(ffi.Pointer<JniEnv1>, JObjectPtr,
-              JMethodIDPtr, ffi.Pointer<JValue>)>> CallBooleanMethodA;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          JByteMarker Function(
-              ffi.Pointer<JniEnv1>, JObjectPtr, JMethodIDPtr)>> CallByteMethod;
-
-  external ffi.Pointer<ffi.Void> _CallByteMethodV;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          JByteMarker Function(ffi.Pointer<JniEnv1>, JObjectPtr, JMethodIDPtr,
-              ffi.Pointer<JValue>)>> CallByteMethodA;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          JCharMarker Function(
-              ffi.Pointer<JniEnv1>, JObjectPtr, JMethodIDPtr)>> CallCharMethod;
-
-  external ffi.Pointer<ffi.Void> _CallCharMethodV;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          JCharMarker Function(ffi.Pointer<JniEnv1>, JObjectPtr, JMethodIDPtr,
-              ffi.Pointer<JValue>)>> CallCharMethodA;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          JShortMarker Function(
-              ffi.Pointer<JniEnv1>, JObjectPtr, JMethodIDPtr)>> CallShortMethod;
-
-  external ffi.Pointer<ffi.Void> _CallShortMethodV;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          JShortMarker Function(ffi.Pointer<JniEnv1>, JObjectPtr, JMethodIDPtr,
-              ffi.Pointer<JValue>)>> CallShortMethodA;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          JIntMarker Function(
-              ffi.Pointer<JniEnv1>, JObjectPtr, JMethodIDPtr)>> CallIntMethod;
-
-  external ffi.Pointer<ffi.Void> _CallIntMethodV;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          JIntMarker Function(ffi.Pointer<JniEnv1>, JObjectPtr, JMethodIDPtr,
-              ffi.Pointer<JValue>)>> CallIntMethodA;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          JLongMarker Function(
-              ffi.Pointer<JniEnv1>, JObjectPtr, JMethodIDPtr)>> CallLongMethod;
-
-  external ffi.Pointer<ffi.Void> _CallLongMethodV;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          JLongMarker Function(ffi.Pointer<JniEnv1>, JObjectPtr, JMethodIDPtr,
-              ffi.Pointer<JValue>)>> CallLongMethodA;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          JFloatMarker Function(
-              ffi.Pointer<JniEnv1>, JObjectPtr, JMethodIDPtr)>> CallFloatMethod;
-
-  external ffi.Pointer<ffi.Void> _CallFloatMethodV;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          JFloatMarker Function(ffi.Pointer<JniEnv1>, JObjectPtr, JMethodIDPtr,
-              ffi.Pointer<JValue>)>> CallFloatMethodA;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              JDoubleMarker Function(
-                  ffi.Pointer<JniEnv1>, JObjectPtr, JMethodIDPtr)>>
-      CallDoubleMethod;
-
-  external ffi.Pointer<ffi.Void> _CallDoubleMethodV;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          JDoubleMarker Function(ffi.Pointer<JniEnv1>, JObjectPtr, JMethodIDPtr,
-              ffi.Pointer<JValue>)>> CallDoubleMethodA;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          ffi.Void Function(
-              ffi.Pointer<JniEnv1>, JObjectPtr, JMethodIDPtr)>> CallVoidMethod;
-
-  external ffi.Pointer<ffi.Void> _CallVoidMethodV;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          ffi.Void Function(ffi.Pointer<JniEnv1>, JObjectPtr, JMethodIDPtr,
-              ffi.Pointer<JValue>)>> CallVoidMethodA;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              JObjectPtr Function(
-                  ffi.Pointer<JniEnv1>, JObjectPtr, JClassPtr, JMethodIDPtr)>>
-      CallNonvirtualObjectMethod;
-
-  external ffi.Pointer<ffi.Void> _CallNonvirtualObjectMethodV;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          JObjectPtr Function(ffi.Pointer<JniEnv1>, JObjectPtr, JClassPtr,
-              JMethodIDPtr, ffi.Pointer<JValue>)>> CallNonvirtualObjectMethodA;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              JBooleanMarker Function(
-                  ffi.Pointer<JniEnv1>, JObjectPtr, JClassPtr, JMethodIDPtr)>>
-      CallNonvirtualBooleanMethod;
-
-  external ffi.Pointer<ffi.Void> _CallNonvirtualBooleanMethodV;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          JBooleanMarker Function(ffi.Pointer<JniEnv1>, JObjectPtr, JClassPtr,
-              JMethodIDPtr, ffi.Pointer<JValue>)>> CallNonvirtualBooleanMethodA;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              JByteMarker Function(
-                  ffi.Pointer<JniEnv1>, JObjectPtr, JClassPtr, JMethodIDPtr)>>
-      CallNonvirtualByteMethod;
-
-  external ffi.Pointer<ffi.Void> _CallNonvirtualByteMethodV;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          JByteMarker Function(ffi.Pointer<JniEnv1>, JObjectPtr, JClassPtr,
-              JMethodIDPtr, ffi.Pointer<JValue>)>> CallNonvirtualByteMethodA;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              JCharMarker Function(
-                  ffi.Pointer<JniEnv1>, JObjectPtr, JClassPtr, JMethodIDPtr)>>
-      CallNonvirtualCharMethod;
-
-  external ffi.Pointer<ffi.Void> _CallNonvirtualCharMethodV;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          JCharMarker Function(ffi.Pointer<JniEnv1>, JObjectPtr, JClassPtr,
-              JMethodIDPtr, ffi.Pointer<JValue>)>> CallNonvirtualCharMethodA;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              JShortMarker Function(
-                  ffi.Pointer<JniEnv1>, JObjectPtr, JClassPtr, JMethodIDPtr)>>
-      CallNonvirtualShortMethod;
-
-  external ffi.Pointer<ffi.Void> _CallNonvirtualShortMethodV;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          JShortMarker Function(ffi.Pointer<JniEnv1>, JObjectPtr, JClassPtr,
-              JMethodIDPtr, ffi.Pointer<JValue>)>> CallNonvirtualShortMethodA;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              JIntMarker Function(
-                  ffi.Pointer<JniEnv1>, JObjectPtr, JClassPtr, JMethodIDPtr)>>
-      CallNonvirtualIntMethod;
-
-  external ffi.Pointer<ffi.Void> _CallNonvirtualIntMethodV;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          JIntMarker Function(ffi.Pointer<JniEnv1>, JObjectPtr, JClassPtr,
-              JMethodIDPtr, ffi.Pointer<JValue>)>> CallNonvirtualIntMethodA;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              JLongMarker Function(
-                  ffi.Pointer<JniEnv1>, JObjectPtr, JClassPtr, JMethodIDPtr)>>
-      CallNonvirtualLongMethod;
-
-  external ffi.Pointer<ffi.Void> _CallNonvirtualLongMethodV;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          JLongMarker Function(ffi.Pointer<JniEnv1>, JObjectPtr, JClassPtr,
-              JMethodIDPtr, ffi.Pointer<JValue>)>> CallNonvirtualLongMethodA;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              JFloatMarker Function(
-                  ffi.Pointer<JniEnv1>, JObjectPtr, JClassPtr, JMethodIDPtr)>>
-      CallNonvirtualFloatMethod;
-
-  external ffi.Pointer<ffi.Void> _CallNonvirtualFloatMethodV;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          JFloatMarker Function(ffi.Pointer<JniEnv1>, JObjectPtr, JClassPtr,
-              JMethodIDPtr, ffi.Pointer<JValue>)>> CallNonvirtualFloatMethodA;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              JDoubleMarker Function(
-                  ffi.Pointer<JniEnv1>, JObjectPtr, JClassPtr, JMethodIDPtr)>>
-      CallNonvirtualDoubleMethod;
-
-  external ffi.Pointer<ffi.Void> _CallNonvirtualDoubleMethodV;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          JDoubleMarker Function(ffi.Pointer<JniEnv1>, JObjectPtr, JClassPtr,
-              JMethodIDPtr, ffi.Pointer<JValue>)>> CallNonvirtualDoubleMethodA;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              ffi.Void Function(
-                  ffi.Pointer<JniEnv1>, JObjectPtr, JClassPtr, JMethodIDPtr)>>
-      CallNonvirtualVoidMethod;
-
-  external ffi.Pointer<ffi.Void> _CallNonvirtualVoidMethodV;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          ffi.Void Function(ffi.Pointer<JniEnv1>, JObjectPtr, JClassPtr,
-              JMethodIDPtr, ffi.Pointer<JValue>)>> CallNonvirtualVoidMethodA;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          JFieldIDPtr Function(ffi.Pointer<JniEnv1>, JClassPtr,
-              ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Char>)>> GetFieldID;
+              ffi.Pointer<ffi.Void>)>> CallObjectMethodV;
 
   external ffi.Pointer<
       ffi.NativeFunction<
           JObjectPtr Function(
-              ffi.Pointer<JniEnv1>, JObjectPtr, JFieldIDPtr)>> GetObjectField;
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallObjectMethodA;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JBooleanMarker Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JMethodIDPtr methodID)>> CallBooleanMethod;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JBooleanMarker Function(ffi.Pointer<JniEnv1>, JObjectPtr,
+              JMethodIDPtr, ffi.Pointer<ffi.Void>)>> CallBooleanMethodV;
 
   external ffi.Pointer<
       ffi.NativeFunction<
           JBooleanMarker Function(
-              ffi.Pointer<JniEnv1>, JObjectPtr, JFieldIDPtr)>> GetBooleanField;
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JMethodIDPtr methodId,
+              ffi.Pointer<JValue> args)>> CallBooleanMethodA;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JByteMarker Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JMethodIDPtr methodID)>> CallByteMethod;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JByteMarker Function(ffi.Pointer<JniEnv1>, JObjectPtr, JMethodIDPtr,
+              ffi.Pointer<ffi.Void>)>> CallByteMethodV;
 
   external ffi.Pointer<
       ffi.NativeFunction<
           JByteMarker Function(
-              ffi.Pointer<JniEnv1>, JObjectPtr, JFieldIDPtr)>> GetByteField;
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallByteMethodA;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JCharMarker Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JMethodIDPtr methodID)>> CallCharMethod;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JCharMarker Function(ffi.Pointer<JniEnv1>, JObjectPtr, JMethodIDPtr,
+              ffi.Pointer<ffi.Void>)>> CallCharMethodV;
 
   external ffi.Pointer<
       ffi.NativeFunction<
           JCharMarker Function(
-              ffi.Pointer<JniEnv1>, JObjectPtr, JFieldIDPtr)>> GetCharField;
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallCharMethodA;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JShortMarker Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JMethodIDPtr methodID)>> CallShortMethod;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JShortMarker Function(ffi.Pointer<JniEnv1>, JObjectPtr, JMethodIDPtr,
+              ffi.Pointer<ffi.Void>)>> CallShortMethodV;
 
   external ffi.Pointer<
       ffi.NativeFunction<
           JShortMarker Function(
-              ffi.Pointer<JniEnv1>, JObjectPtr, JFieldIDPtr)>> GetShortField;
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallShortMethodA;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          JIntMarker Function(
-              ffi.Pointer<JniEnv1>, JObjectPtr, JFieldIDPtr)>> GetIntField;
+          JIntMarker Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JMethodIDPtr methodID)>> CallIntMethod;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JIntMarker Function(ffi.Pointer<JniEnv1>, JObjectPtr, JMethodIDPtr,
+              ffi.Pointer<ffi.Void>)>> CallIntMethodV;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JIntMarker Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JMethodIDPtr methodID, ffi.Pointer<JValue> args)>> CallIntMethodA;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JLongMarker Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JMethodIDPtr methodID)>> CallLongMethod;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JLongMarker Function(ffi.Pointer<JniEnv1>, JObjectPtr, JMethodIDPtr,
+              ffi.Pointer<ffi.Void>)>> CallLongMethodV;
 
   external ffi.Pointer<
       ffi.NativeFunction<
           JLongMarker Function(
-              ffi.Pointer<JniEnv1>, JObjectPtr, JFieldIDPtr)>> GetLongField;
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallLongMethodA;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JFloatMarker Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JMethodIDPtr methodID)>> CallFloatMethod;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JFloatMarker Function(ffi.Pointer<JniEnv1>, JObjectPtr, JMethodIDPtr,
+              ffi.Pointer<ffi.Void>)>> CallFloatMethodV;
 
   external ffi.Pointer<
       ffi.NativeFunction<
           JFloatMarker Function(
-              ffi.Pointer<JniEnv1>, JObjectPtr, JFieldIDPtr)>> GetFloatField;
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallFloatMethodA;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JDoubleMarker Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JMethodIDPtr methodID)>> CallDoubleMethod;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JDoubleMarker Function(ffi.Pointer<JniEnv1>, JObjectPtr, JMethodIDPtr,
+              ffi.Pointer<ffi.Void>)>> CallDoubleMethodV;
 
   external ffi.Pointer<
       ffi.NativeFunction<
           JDoubleMarker Function(
-              ffi.Pointer<JniEnv1>, JObjectPtr, JFieldIDPtr)>> GetDoubleField;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              ffi.Void Function(
-                  ffi.Pointer<JniEnv1>, JObjectPtr, JFieldIDPtr, JObjectPtr)>>
-      SetObjectField;
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallDoubleMethodA;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          ffi.Void Function(ffi.Pointer<JniEnv1>, JObjectPtr, JFieldIDPtr,
-              JBooleanMarker)>> SetBooleanField;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              ffi.Void Function(
-                  ffi.Pointer<JniEnv1>, JObjectPtr, JFieldIDPtr, JByteMarker)>>
-      SetByteField;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              ffi.Void Function(
-                  ffi.Pointer<JniEnv1>, JObjectPtr, JFieldIDPtr, JCharMarker)>>
-      SetCharField;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              ffi.Void Function(
-                  ffi.Pointer<JniEnv1>, JObjectPtr, JFieldIDPtr, JShortMarker)>>
-      SetShortField;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              ffi.Void Function(
-                  ffi.Pointer<JniEnv1>, JObjectPtr, JFieldIDPtr, JIntMarker)>>
-      SetIntField;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              ffi.Void Function(
-                  ffi.Pointer<JniEnv1>, JObjectPtr, JFieldIDPtr, JLongMarker)>>
-      SetLongField;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              ffi.Void Function(
-                  ffi.Pointer<JniEnv1>, JObjectPtr, JFieldIDPtr, JFloatMarker)>>
-      SetFloatField;
+          ffi.Void Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JMethodIDPtr methodID)>> CallVoidMethod;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          ffi.Void Function(ffi.Pointer<JniEnv1>, JObjectPtr, JFieldIDPtr,
-              JDoubleMarker)>> SetDoubleField;
+          ffi.Void Function(ffi.Pointer<JniEnv1>, JObjectPtr, JMethodIDPtr,
+              ffi.Pointer<ffi.Void>)>> CallVoidMethodV;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          JMethodIDPtr Function(ffi.Pointer<JniEnv1>, JClassPtr,
-              ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Char>)>> GetStaticMethodID;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              JObjectPtr Function(
-                  ffi.Pointer<JniEnv1>, JClassPtr, JMethodIDPtr)>>
-      CallStaticObjectMethod;
-
-  external ffi.Pointer<ffi.Void> _CallStaticObjectMethodV;
+          ffi.Void Function(
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallVoidMethodA;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          JObjectPtr Function(ffi.Pointer<JniEnv1>, JClassPtr, JMethodIDPtr,
-              ffi.Pointer<JValue>)>> CallStaticObjectMethodA;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              JBooleanMarker Function(
-                  ffi.Pointer<JniEnv1>, JClassPtr, JMethodIDPtr)>>
-      CallStaticBooleanMethod;
-
-  external ffi.Pointer<ffi.Void> _CallStaticBooleanMethodV;
+          JObjectPtr Function(
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JClassPtr clazz,
+              JMethodIDPtr methodID)>> CallNonvirtualObjectMethod;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          JBooleanMarker Function(ffi.Pointer<JniEnv1>, JClassPtr, JMethodIDPtr,
-              ffi.Pointer<JValue>)>> CallStaticBooleanMethodA;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              JByteMarker Function(
-                  ffi.Pointer<JniEnv1>, JClassPtr, JMethodIDPtr)>>
-      CallStaticByteMethod;
-
-  external ffi.Pointer<ffi.Void> _CallStaticByteMethodV;
+          JObjectPtr Function(
+              ffi.Pointer<JniEnv1>,
+              JObjectPtr,
+              JClassPtr,
+              JMethodIDPtr,
+              ffi.Pointer<ffi.Void>)>> CallNonvirtualObjectMethodV;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          JByteMarker Function(ffi.Pointer<JniEnv1>, JClassPtr, JMethodIDPtr,
-              ffi.Pointer<JValue>)>> CallStaticByteMethodA;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              JCharMarker Function(
-                  ffi.Pointer<JniEnv1>, JClassPtr, JMethodIDPtr)>>
-      CallStaticCharMethod;
-
-  external ffi.Pointer<ffi.Void> _CallStaticCharMethodV;
+          JObjectPtr Function(
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JClassPtr clazz,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallNonvirtualObjectMethodA;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          JCharMarker Function(ffi.Pointer<JniEnv1>, JClassPtr, JMethodIDPtr,
-              ffi.Pointer<JValue>)>> CallStaticCharMethodA;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              JShortMarker Function(
-                  ffi.Pointer<JniEnv1>, JClassPtr, JMethodIDPtr)>>
-      CallStaticShortMethod;
-
-  external ffi.Pointer<ffi.Void> _CallStaticShortMethodV;
+          JBooleanMarker Function(
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JClassPtr clazz,
+              JMethodIDPtr methodID)>> CallNonvirtualBooleanMethod;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          JShortMarker Function(ffi.Pointer<JniEnv1>, JClassPtr, JMethodIDPtr,
-              ffi.Pointer<JValue>)>> CallStaticShortMethodA;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              JIntMarker Function(
-                  ffi.Pointer<JniEnv1>, JClassPtr, JMethodIDPtr)>>
-      CallStaticIntMethod;
-
-  external ffi.Pointer<ffi.Void> _CallStaticIntMethodV;
+          JBooleanMarker Function(
+              ffi.Pointer<JniEnv1>,
+              JObjectPtr,
+              JClassPtr,
+              JMethodIDPtr,
+              ffi.Pointer<ffi.Void>)>> CallNonvirtualBooleanMethodV;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          JIntMarker Function(ffi.Pointer<JniEnv1>, JClassPtr, JMethodIDPtr,
-              ffi.Pointer<JValue>)>> CallStaticIntMethodA;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              JLongMarker Function(
-                  ffi.Pointer<JniEnv1>, JClassPtr, JMethodIDPtr)>>
-      CallStaticLongMethod;
-
-  external ffi.Pointer<ffi.Void> _CallStaticLongMethodV;
+          JBooleanMarker Function(
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JClassPtr clazz,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallNonvirtualBooleanMethodA;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          JLongMarker Function(ffi.Pointer<JniEnv1>, JClassPtr, JMethodIDPtr,
-              ffi.Pointer<JValue>)>> CallStaticLongMethodA;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              JFloatMarker Function(
-                  ffi.Pointer<JniEnv1>, JClassPtr, JMethodIDPtr)>>
-      CallStaticFloatMethod;
-
-  external ffi.Pointer<ffi.Void> _CallStaticFloatMethodV;
+          JByteMarker Function(
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JClassPtr clazz,
+              JMethodIDPtr methodID)>> CallNonvirtualByteMethod;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          JFloatMarker Function(ffi.Pointer<JniEnv1>, JClassPtr, JMethodIDPtr,
-              ffi.Pointer<JValue>)>> CallStaticFloatMethodA;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              JDoubleMarker Function(
-                  ffi.Pointer<JniEnv1>, JClassPtr, JMethodIDPtr)>>
-      CallStaticDoubleMethod;
-
-  external ffi.Pointer<ffi.Void> _CallStaticDoubleMethodV;
+          JByteMarker Function(ffi.Pointer<JniEnv1>, JObjectPtr, JClassPtr,
+              JMethodIDPtr, ffi.Pointer<ffi.Void>)>> CallNonvirtualByteMethodV;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          JDoubleMarker Function(ffi.Pointer<JniEnv1>, JClassPtr, JMethodIDPtr,
-              ffi.Pointer<JValue>)>> CallStaticDoubleMethodA;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              ffi.Void Function(ffi.Pointer<JniEnv1>, JClassPtr, JMethodIDPtr)>>
-      CallStaticVoidMethod;
-
-  external ffi.Pointer<ffi.Void> _CallStaticVoidMethodV;
+          JByteMarker Function(
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JClassPtr clazz,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallNonvirtualByteMethodA;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          ffi.Void Function(ffi.Pointer<JniEnv1>, JClassPtr, JMethodIDPtr,
-              ffi.Pointer<JValue>)>> CallStaticVoidMethodA;
+          JCharMarker Function(
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JClassPtr clazz,
+              JMethodIDPtr methodID)>> CallNonvirtualCharMethod;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          JFieldIDPtr Function(ffi.Pointer<JniEnv1>, JClassPtr,
-              ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Char>)>> GetStaticFieldID;
+          JCharMarker Function(ffi.Pointer<JniEnv1>, JObjectPtr, JClassPtr,
+              JMethodIDPtr, ffi.Pointer<ffi.Void>)>> CallNonvirtualCharMethodV;
 
   external ffi.Pointer<
-          ffi.NativeFunction<
-              JObjectPtr Function(
-                  ffi.Pointer<JniEnv1>, JClassPtr, JFieldIDPtr)>>
-      GetStaticObjectField;
+      ffi.NativeFunction<
+          JCharMarker Function(
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JClassPtr clazz,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallNonvirtualCharMethodA;
 
   external ffi.Pointer<
-          ffi.NativeFunction<
-              JBooleanMarker Function(
-                  ffi.Pointer<JniEnv1>, JClassPtr, JFieldIDPtr)>>
-      GetStaticBooleanField;
+      ffi.NativeFunction<
+          JShortMarker Function(
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JClassPtr clazz,
+              JMethodIDPtr methodID)>> CallNonvirtualShortMethod;
 
   external ffi.Pointer<
-          ffi.NativeFunction<
-              JByteMarker Function(
-                  ffi.Pointer<JniEnv1>, JClassPtr, JFieldIDPtr)>>
-      GetStaticByteField;
+      ffi.NativeFunction<
+          JShortMarker Function(ffi.Pointer<JniEnv1>, JObjectPtr, JClassPtr,
+              JMethodIDPtr, ffi.Pointer<ffi.Void>)>> CallNonvirtualShortMethodV;
 
   external ffi.Pointer<
-          ffi.NativeFunction<
-              JCharMarker Function(
-                  ffi.Pointer<JniEnv1>, JClassPtr, JFieldIDPtr)>>
-      GetStaticCharField;
+      ffi.NativeFunction<
+          JShortMarker Function(
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JClassPtr clazz,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallNonvirtualShortMethodA;
 
   external ffi.Pointer<
-          ffi.NativeFunction<
-              JShortMarker Function(
-                  ffi.Pointer<JniEnv1>, JClassPtr, JFieldIDPtr)>>
-      GetStaticShortField;
+      ffi.NativeFunction<
+          JIntMarker Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JClassPtr clazz, JMethodIDPtr methodID)>> CallNonvirtualIntMethod;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JIntMarker Function(ffi.Pointer<JniEnv1>, JObjectPtr, JClassPtr,
+              JMethodIDPtr, ffi.Pointer<ffi.Void>)>> CallNonvirtualIntMethodV;
 
   external ffi.Pointer<
       ffi.NativeFunction<
           JIntMarker Function(
-              ffi.Pointer<JniEnv1>, JClassPtr, JFieldIDPtr)>> GetStaticIntField;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              JLongMarker Function(
-                  ffi.Pointer<JniEnv1>, JClassPtr, JFieldIDPtr)>>
-      GetStaticLongField;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              JFloatMarker Function(
-                  ffi.Pointer<JniEnv1>, JClassPtr, JFieldIDPtr)>>
-      GetStaticFloatField;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              JDoubleMarker Function(
-                  ffi.Pointer<JniEnv1>, JClassPtr, JFieldIDPtr)>>
-      GetStaticDoubleField;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              ffi.Void Function(
-                  ffi.Pointer<JniEnv1>, JClassPtr, JFieldIDPtr, JObjectPtr)>>
-      SetStaticObjectField;
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JClassPtr clazz,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallNonvirtualIntMethodA;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          ffi.Void Function(ffi.Pointer<JniEnv1>, JClassPtr, JFieldIDPtr,
-              JBooleanMarker)>> SetStaticBooleanField;
+          JLongMarker Function(
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JClassPtr clazz,
+              JMethodIDPtr methodID)>> CallNonvirtualLongMethod;
 
   external ffi.Pointer<
-          ffi.NativeFunction<
-              ffi.Void Function(
-                  ffi.Pointer<JniEnv1>, JClassPtr, JFieldIDPtr, JByteMarker)>>
-      SetStaticByteField;
+      ffi.NativeFunction<
+          JLongMarker Function(ffi.Pointer<JniEnv1>, JObjectPtr, JClassPtr,
+              JMethodIDPtr, ffi.Pointer<ffi.Void>)>> CallNonvirtualLongMethodV;
 
   external ffi.Pointer<
-          ffi.NativeFunction<
-              ffi.Void Function(
-                  ffi.Pointer<JniEnv1>, JClassPtr, JFieldIDPtr, JCharMarker)>>
-      SetStaticCharField;
+      ffi.NativeFunction<
+          JLongMarker Function(
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JClassPtr clazz,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallNonvirtualLongMethodA;
 
   external ffi.Pointer<
-          ffi.NativeFunction<
-              ffi.Void Function(
-                  ffi.Pointer<JniEnv1>, JClassPtr, JFieldIDPtr, JShortMarker)>>
-      SetStaticShortField;
+      ffi.NativeFunction<
+          JFloatMarker Function(
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JClassPtr clazz,
+              JMethodIDPtr methodID)>> CallNonvirtualFloatMethod;
 
   external ffi.Pointer<
-          ffi.NativeFunction<
-              ffi.Void Function(
-                  ffi.Pointer<JniEnv1>, JClassPtr, JFieldIDPtr, JIntMarker)>>
-      SetStaticIntField;
+      ffi.NativeFunction<
+          JFloatMarker Function(ffi.Pointer<JniEnv1>, JObjectPtr, JClassPtr,
+              JMethodIDPtr, ffi.Pointer<ffi.Void>)>> CallNonvirtualFloatMethodV;
 
   external ffi.Pointer<
-          ffi.NativeFunction<
-              ffi.Void Function(
-                  ffi.Pointer<JniEnv1>, JClassPtr, JFieldIDPtr, JLongMarker)>>
-      SetStaticLongField;
+      ffi.NativeFunction<
+          JFloatMarker Function(
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JClassPtr clazz,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallNonvirtualFloatMethodA;
 
   external ffi.Pointer<
-          ffi.NativeFunction<
-              ffi.Void Function(
-                  ffi.Pointer<JniEnv1>, JClassPtr, JFieldIDPtr, JFloatMarker)>>
-      SetStaticFloatField;
+      ffi.NativeFunction<
+          JDoubleMarker Function(
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JClassPtr clazz,
+              JMethodIDPtr methodID)>> CallNonvirtualDoubleMethod;
 
   external ffi.Pointer<
-          ffi.NativeFunction<
-              ffi.Void Function(
-                  ffi.Pointer<JniEnv1>, JClassPtr, JFieldIDPtr, JDoubleMarker)>>
-      SetStaticDoubleField;
+      ffi.NativeFunction<
+          JDoubleMarker Function(
+              ffi.Pointer<JniEnv1>,
+              JObjectPtr,
+              JClassPtr,
+              JMethodIDPtr,
+              ffi.Pointer<ffi.Void>)>> CallNonvirtualDoubleMethodV;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JDoubleMarker Function(
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JClassPtr clazz,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallNonvirtualDoubleMethodA;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          ffi.Void Function(
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JClassPtr clazz,
+              JMethodIDPtr methodID)>> CallNonvirtualVoidMethod;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          ffi.Void Function(ffi.Pointer<JniEnv1>, JObjectPtr, JClassPtr,
+              JMethodIDPtr, ffi.Pointer<ffi.Void>)>> CallNonvirtualVoidMethodV;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          ffi.Void Function(
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JClassPtr clazz,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallNonvirtualVoidMethodA;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JFieldIDPtr Function(
+              ffi.Pointer<JniEnv1> env,
+              JClassPtr clazz,
+              ffi.Pointer<ffi.Char> name,
+              ffi.Pointer<ffi.Char> sig)>> GetFieldID;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JObjectPtr Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JFieldIDPtr fieldID)>> GetObjectField;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JBooleanMarker Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JFieldIDPtr fieldID)>> GetBooleanField;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JByteMarker Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JFieldIDPtr fieldID)>> GetByteField;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JCharMarker Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JFieldIDPtr fieldID)>> GetCharField;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JShortMarker Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JFieldIDPtr fieldID)>> GetShortField;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JIntMarker Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JFieldIDPtr fieldID)>> GetIntField;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JLongMarker Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JFieldIDPtr fieldID)>> GetLongField;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JFloatMarker Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JFieldIDPtr fieldID)>> GetFloatField;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JDoubleMarker Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JFieldIDPtr fieldID)>> GetDoubleField;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          ffi.Void Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JFieldIDPtr fieldID, JObjectPtr val)>> SetObjectField;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          ffi.Void Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JFieldIDPtr fieldID, JBooleanMarker val)>> SetBooleanField;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          ffi.Void Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JFieldIDPtr fieldID, JByteMarker val)>> SetByteField;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          ffi.Void Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JFieldIDPtr fieldID, JCharMarker val)>> SetCharField;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          ffi.Void Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JFieldIDPtr fieldID, JShortMarker val)>> SetShortField;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          ffi.Void Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JFieldIDPtr fieldID, JIntMarker val)>> SetIntField;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          ffi.Void Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JFieldIDPtr fieldID, JLongMarker val)>> SetLongField;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          ffi.Void Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JFieldIDPtr fieldID, JFloatMarker val)>> SetFloatField;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          ffi.Void Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JFieldIDPtr fieldID, JDoubleMarker val)>> SetDoubleField;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JMethodIDPtr Function(
+              ffi.Pointer<JniEnv1> env,
+              JClassPtr clazz,
+              ffi.Pointer<ffi.Char> name,
+              ffi.Pointer<ffi.Char> sig)>> GetStaticMethodID;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JObjectPtr Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JMethodIDPtr methodID)>> CallStaticObjectMethod;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JObjectPtr Function(ffi.Pointer<JniEnv1>, JClassPtr, JMethodIDPtr,
+              ffi.Pointer<ffi.Void>)>> CallStaticObjectMethodV;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JObjectPtr Function(
+              ffi.Pointer<JniEnv1> env,
+              JClassPtr clazz,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallStaticObjectMethodA;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JBooleanMarker Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JMethodIDPtr methodID)>> CallStaticBooleanMethod;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JBooleanMarker Function(ffi.Pointer<JniEnv1>, JClassPtr, JMethodIDPtr,
+              ffi.Pointer<ffi.Void>)>> CallStaticBooleanMethodV;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JBooleanMarker Function(
+              ffi.Pointer<JniEnv1> env,
+              JClassPtr clazz,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallStaticBooleanMethodA;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JByteMarker Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JMethodIDPtr methodID)>> CallStaticByteMethod;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JByteMarker Function(ffi.Pointer<JniEnv1>, JClassPtr, JMethodIDPtr,
+              ffi.Pointer<ffi.Void>)>> CallStaticByteMethodV;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JByteMarker Function(
+              ffi.Pointer<JniEnv1> env,
+              JClassPtr clazz,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallStaticByteMethodA;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JCharMarker Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JMethodIDPtr methodID)>> CallStaticCharMethod;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JCharMarker Function(ffi.Pointer<JniEnv1>, JClassPtr, JMethodIDPtr,
+              ffi.Pointer<ffi.Void>)>> CallStaticCharMethodV;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JCharMarker Function(
+              ffi.Pointer<JniEnv1> env,
+              JClassPtr clazz,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallStaticCharMethodA;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JShortMarker Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JMethodIDPtr methodID)>> CallStaticShortMethod;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JShortMarker Function(ffi.Pointer<JniEnv1>, JClassPtr, JMethodIDPtr,
+              ffi.Pointer<ffi.Void>)>> CallStaticShortMethodV;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JShortMarker Function(
+              ffi.Pointer<JniEnv1> env,
+              JClassPtr clazz,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallStaticShortMethodA;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JIntMarker Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JMethodIDPtr methodID)>> CallStaticIntMethod;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JIntMarker Function(ffi.Pointer<JniEnv1>, JClassPtr, JMethodIDPtr,
+              ffi.Pointer<ffi.Void>)>> CallStaticIntMethodV;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JIntMarker Function(
+              ffi.Pointer<JniEnv1> env,
+              JClassPtr clazz,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallStaticIntMethodA;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JLongMarker Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JMethodIDPtr methodID)>> CallStaticLongMethod;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JLongMarker Function(ffi.Pointer<JniEnv1>, JClassPtr, JMethodIDPtr,
+              ffi.Pointer<ffi.Void>)>> CallStaticLongMethodV;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JLongMarker Function(
+              ffi.Pointer<JniEnv1> env,
+              JClassPtr clazz,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallStaticLongMethodA;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JFloatMarker Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JMethodIDPtr methodID)>> CallStaticFloatMethod;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JFloatMarker Function(ffi.Pointer<JniEnv1>, JClassPtr, JMethodIDPtr,
+              ffi.Pointer<ffi.Void>)>> CallStaticFloatMethodV;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JFloatMarker Function(
+              ffi.Pointer<JniEnv1> env,
+              JClassPtr clazz,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallStaticFloatMethodA;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JDoubleMarker Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JMethodIDPtr methodID)>> CallStaticDoubleMethod;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JDoubleMarker Function(ffi.Pointer<JniEnv1>, JClassPtr, JMethodIDPtr,
+              ffi.Pointer<ffi.Void>)>> CallStaticDoubleMethodV;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JDoubleMarker Function(
+              ffi.Pointer<JniEnv1> env,
+              JClassPtr clazz,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallStaticDoubleMethodA;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          ffi.Void Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JMethodIDPtr methodID)>> CallStaticVoidMethod;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          ffi.Void Function(ffi.Pointer<JniEnv1>, JClassPtr, JMethodIDPtr,
+              ffi.Pointer<ffi.Void>)>> CallStaticVoidMethodV;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          ffi.Void Function(
+              ffi.Pointer<JniEnv1> env,
+              JClassPtr clazz,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallStaticVoidMethodA;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JFieldIDPtr Function(
+              ffi.Pointer<JniEnv1> env,
+              JClassPtr clazz,
+              ffi.Pointer<ffi.Char> name,
+              ffi.Pointer<ffi.Char> sig)>> GetStaticFieldID;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JObjectPtr Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JFieldIDPtr fieldID)>> GetStaticObjectField;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JBooleanMarker Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JFieldIDPtr fieldID)>> GetStaticBooleanField;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JByteMarker Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JFieldIDPtr fieldID)>> GetStaticByteField;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JCharMarker Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JFieldIDPtr fieldID)>> GetStaticCharField;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JShortMarker Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JFieldIDPtr fieldID)>> GetStaticShortField;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JIntMarker Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JFieldIDPtr fieldID)>> GetStaticIntField;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JLongMarker Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JFieldIDPtr fieldID)>> GetStaticLongField;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JFloatMarker Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JFieldIDPtr fieldID)>> GetStaticFloatField;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JDoubleMarker Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JFieldIDPtr fieldID)>> GetStaticDoubleField;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          ffi.Void Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JFieldIDPtr fieldID, JObjectPtr val)>> SetStaticObjectField;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          ffi.Void Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JFieldIDPtr fieldID, JBooleanMarker val)>> SetStaticBooleanField;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          ffi.Void Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JFieldIDPtr fieldID, JByteMarker val)>> SetStaticByteField;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          ffi.Void Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JFieldIDPtr fieldID, JCharMarker val)>> SetStaticCharField;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          ffi.Void Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JFieldIDPtr fieldID, JShortMarker val)>> SetStaticShortField;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          ffi.Void Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JFieldIDPtr fieldID, JIntMarker val)>> SetStaticIntField;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          ffi.Void Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JFieldIDPtr fieldID, JLongMarker val)>> SetStaticLongField;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          ffi.Void Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JFieldIDPtr fieldID, JFloatMarker val)>> SetStaticFloatField;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          ffi.Void Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JFieldIDPtr fieldID, JDoubleMarker val)>> SetStaticDoubleField;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JStringPtr Function(
+              ffi.Pointer<JniEnv1> env,
+              ffi.Pointer<JCharMarker> unicodeChars,
+              JSizeMarker len)>> NewString;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JSizeMarker Function(
+              ffi.Pointer<JniEnv1> env, JStringPtr string)>> GetStringLength;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          ffi.Pointer<JCharMarker> Function(
+              ffi.Pointer<JniEnv1> env,
+              JStringPtr string,
+              ffi.Pointer<JBooleanMarker> isCopy)>> GetStringChars;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          ffi.Void Function(ffi.Pointer<JniEnv1> env, JStringPtr string,
+              ffi.Pointer<JCharMarker> isCopy)>> ReleaseStringChars;
 
   external ffi.Pointer<
           ffi.NativeFunction<
               JStringPtr Function(
-                  ffi.Pointer<JniEnv1>, ffi.Pointer<JCharMarker>, JSizeMarker)>>
-      NewString;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              JSizeMarker Function(ffi.Pointer<JniEnv1>, JStringPtr)>>
-      GetStringLength;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          ffi.Pointer<JCharMarker> Function(ffi.Pointer<JniEnv1>, JStringPtr,
-              ffi.Pointer<JBooleanMarker>)>> GetStringChars;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              ffi.Void Function(
-                  ffi.Pointer<JniEnv1>, JStringPtr, ffi.Pointer<JCharMarker>)>>
-      ReleaseStringChars;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              JStringPtr Function(ffi.Pointer<JniEnv1>, ffi.Pointer<ffi.Char>)>>
+                  ffi.Pointer<JniEnv1> env, ffi.Pointer<ffi.Char> bytes)>>
       NewStringUTF;
 
   external ffi.Pointer<
-          ffi.NativeFunction<
-              JSizeMarker Function(ffi.Pointer<JniEnv1>, JStringPtr)>>
-      GetStringUTFLength;
+      ffi.NativeFunction<
+          JSizeMarker Function(
+              ffi.Pointer<JniEnv1> env, JStringPtr string)>> GetStringUTFLength;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          ffi.Pointer<ffi.Char> Function(ffi.Pointer<JniEnv1>, JStringPtr,
-              ffi.Pointer<JBooleanMarker>)>> GetStringUTFChars;
+          ffi.Pointer<ffi.Char> Function(
+              ffi.Pointer<JniEnv1> env,
+              JStringPtr string,
+              ffi.Pointer<JBooleanMarker> isCopy)>> GetStringUTFChars;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          ffi.Void Function(ffi.Pointer<JniEnv1> env, JStringPtr string,
+              ffi.Pointer<ffi.Char> utf)>> ReleaseStringUTFChars;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              ffi.Void Function(
-                  ffi.Pointer<JniEnv1>, JStringPtr, ffi.Pointer<ffi.Char>)>>
-      ReleaseStringUTFChars;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              JSizeMarker Function(ffi.Pointer<JniEnv1>, JArrayPtr)>>
+              JSizeMarker Function(ffi.Pointer<JniEnv1> env, JArrayPtr array)>>
       GetArrayLength;
 
   external ffi.Pointer<
-          ffi.NativeFunction<
-              JObjectArrayPtr Function(
-                  ffi.Pointer<JniEnv1>, JSizeMarker, JClassPtr, JObjectPtr)>>
-      NewObjectArray;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              JObjectPtr Function(
-                  ffi.Pointer<JniEnv1>, JObjectArrayPtr, JSizeMarker)>>
-      GetObjectArrayElement;
+      ffi.NativeFunction<
+          JObjectArrayPtr Function(
+              ffi.Pointer<JniEnv1> env,
+              JSizeMarker length,
+              JClassPtr elementClass,
+              JObjectPtr initialElement)>> NewObjectArray;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          ffi.Void Function(ffi.Pointer<JniEnv1>, JObjectArrayPtr, JSizeMarker,
-              JObjectPtr)>> SetObjectArrayElement;
+          JObjectPtr Function(ffi.Pointer<JniEnv1> env, JObjectArrayPtr array,
+              JSizeMarker index)>> GetObjectArrayElement;
 
   external ffi.Pointer<
-          ffi.NativeFunction<
-              JBooleanArrayPtr Function(ffi.Pointer<JniEnv1>, JSizeMarker)>>
-      NewBooleanArray;
+      ffi.NativeFunction<
+          ffi.Void Function(ffi.Pointer<JniEnv1> env, JObjectArrayPtr array,
+              JSizeMarker index, JObjectPtr val)>> SetObjectArrayElement;
 
   external ffi.Pointer<
-          ffi.NativeFunction<
-              JByteArrayPtr Function(ffi.Pointer<JniEnv1>, JSizeMarker)>>
-      NewByteArray;
+      ffi.NativeFunction<
+          JBooleanArrayPtr Function(
+              ffi.Pointer<JniEnv1> env, JSizeMarker length)>> NewBooleanArray;
 
   external ffi.Pointer<
-          ffi.NativeFunction<
-              JCharArrayPtr Function(ffi.Pointer<JniEnv1>, JSizeMarker)>>
-      NewCharArray;
+      ffi.NativeFunction<
+          JByteArrayPtr Function(
+              ffi.Pointer<JniEnv1> env, JSizeMarker length)>> NewByteArray;
 
   external ffi.Pointer<
-          ffi.NativeFunction<
-              JShortArrayPtr Function(ffi.Pointer<JniEnv1>, JSizeMarker)>>
-      NewShortArray;
+      ffi.NativeFunction<
+          JCharArrayPtr Function(
+              ffi.Pointer<JniEnv1> env, JSizeMarker length)>> NewCharArray;
 
   external ffi.Pointer<
-          ffi.NativeFunction<
-              JIntArrayPtr Function(ffi.Pointer<JniEnv1>, JSizeMarker)>>
-      NewIntArray;
+      ffi.NativeFunction<
+          JShortArrayPtr Function(
+              ffi.Pointer<JniEnv1> env, JSizeMarker length)>> NewShortArray;
 
   external ffi.Pointer<
-          ffi.NativeFunction<
-              JLongArrayPtr Function(ffi.Pointer<JniEnv1>, JSizeMarker)>>
-      NewLongArray;
+      ffi.NativeFunction<
+          JIntArrayPtr Function(
+              ffi.Pointer<JniEnv1> env, JSizeMarker length)>> NewIntArray;
 
   external ffi.Pointer<
-          ffi.NativeFunction<
-              JFloatArrayPtr Function(ffi.Pointer<JniEnv1>, JSizeMarker)>>
-      NewFloatArray;
+      ffi.NativeFunction<
+          JLongArrayPtr Function(
+              ffi.Pointer<JniEnv1> env, JSizeMarker length)>> NewLongArray;
 
   external ffi.Pointer<
-          ffi.NativeFunction<
-              JDoubleArrayPtr Function(ffi.Pointer<JniEnv1>, JSizeMarker)>>
-      NewDoubleArray;
+      ffi.NativeFunction<
+          JFloatArrayPtr Function(
+              ffi.Pointer<JniEnv1> env, JSizeMarker length)>> NewFloatArray;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JDoubleArrayPtr Function(
+              ffi.Pointer<JniEnv1> env, JSizeMarker length)>> NewDoubleArray;
 
   external ffi.Pointer<
       ffi.NativeFunction<
           ffi.Pointer<JBooleanMarker> Function(
-              ffi.Pointer<JniEnv1>,
-              JBooleanArrayPtr,
-              ffi.Pointer<JBooleanMarker>)>> GetBooleanArrayElements;
+              ffi.Pointer<JniEnv1> env,
+              JBooleanArrayPtr array,
+              ffi.Pointer<JBooleanMarker> isCopy)>> GetBooleanArrayElements;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          ffi.Pointer<JByteMarker> Function(ffi.Pointer<JniEnv1>, JByteArrayPtr,
-              ffi.Pointer<JBooleanMarker>)>> GetByteArrayElements;
+          ffi.Pointer<JByteMarker> Function(
+              ffi.Pointer<JniEnv1> env,
+              JByteArrayPtr array,
+              ffi.Pointer<JBooleanMarker> isCopy)>> GetByteArrayElements;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          ffi.Pointer<JCharMarker> Function(ffi.Pointer<JniEnv1>, JCharArrayPtr,
-              ffi.Pointer<JBooleanMarker>)>> GetCharArrayElements;
+          ffi.Pointer<JCharMarker> Function(
+              ffi.Pointer<JniEnv1> env,
+              JCharArrayPtr array,
+              ffi.Pointer<JBooleanMarker> isCopy)>> GetCharArrayElements;
 
   external ffi.Pointer<
       ffi.NativeFunction<
           ffi.Pointer<JShortMarker> Function(
-              ffi.Pointer<JniEnv1>,
-              JShortArrayPtr,
-              ffi.Pointer<JBooleanMarker>)>> GetShortArrayElements;
+              ffi.Pointer<JniEnv1> env,
+              JShortArrayPtr array,
+              ffi.Pointer<JBooleanMarker> isCopy)>> GetShortArrayElements;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          ffi.Pointer<JIntMarker> Function(ffi.Pointer<JniEnv1>, JIntArrayPtr,
-              ffi.Pointer<JBooleanMarker>)>> GetIntArrayElements;
+          ffi.Pointer<JIntMarker> Function(
+              ffi.Pointer<JniEnv1> env,
+              JIntArrayPtr array,
+              ffi.Pointer<JBooleanMarker> isCopy)>> GetIntArrayElements;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          ffi.Pointer<JLongMarker> Function(ffi.Pointer<JniEnv1>, JLongArrayPtr,
-              ffi.Pointer<JBooleanMarker>)>> GetLongArrayElements;
+          ffi.Pointer<JLongMarker> Function(
+              ffi.Pointer<JniEnv1> env,
+              JLongArrayPtr array,
+              ffi.Pointer<JBooleanMarker> isCopy)>> GetLongArrayElements;
 
   external ffi.Pointer<
       ffi.NativeFunction<
           ffi.Pointer<JFloatMarker> Function(
-              ffi.Pointer<JniEnv1>,
-              JFloatArrayPtr,
-              ffi.Pointer<JBooleanMarker>)>> GetFloatArrayElements;
+              ffi.Pointer<JniEnv1> env,
+              JFloatArrayPtr array,
+              ffi.Pointer<JBooleanMarker> isCopy)>> GetFloatArrayElements;
 
   external ffi.Pointer<
       ffi.NativeFunction<
           ffi.Pointer<JDoubleMarker> Function(
-              ffi.Pointer<JniEnv1>,
-              JDoubleArrayPtr,
-              ffi.Pointer<JBooleanMarker>)>> GetDoubleArrayElements;
+              ffi.Pointer<JniEnv1> env,
+              JDoubleArrayPtr array,
+              ffi.Pointer<JBooleanMarker> isCopy)>> GetDoubleArrayElements;
 
   external ffi.Pointer<
       ffi.NativeFunction<
           ffi.Void Function(
-              ffi.Pointer<JniEnv1>,
-              JBooleanArrayPtr,
-              ffi.Pointer<JBooleanMarker>,
-              JIntMarker)>> ReleaseBooleanArrayElements;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          ffi.Void Function(ffi.Pointer<JniEnv1>, JByteArrayPtr,
-              ffi.Pointer<JByteMarker>, JIntMarker)>> ReleaseByteArrayElements;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          ffi.Void Function(ffi.Pointer<JniEnv1>, JCharArrayPtr,
-              ffi.Pointer<JCharMarker>, JIntMarker)>> ReleaseCharArrayElements;
+              ffi.Pointer<JniEnv1> env,
+              JBooleanArrayPtr array,
+              ffi.Pointer<JBooleanMarker> elems,
+              JIntMarker mode)>> ReleaseBooleanArrayElements;
 
   external ffi.Pointer<
       ffi.NativeFunction<
           ffi.Void Function(
-              ffi.Pointer<JniEnv1>,
-              JShortArrayPtr,
-              ffi.Pointer<JShortMarker>,
-              JIntMarker)>> ReleaseShortArrayElements;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          ffi.Void Function(ffi.Pointer<JniEnv1>, JIntArrayPtr,
-              ffi.Pointer<JIntMarker>, JIntMarker)>> ReleaseIntArrayElements;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          ffi.Void Function(ffi.Pointer<JniEnv1>, JLongArrayPtr,
-              ffi.Pointer<JLongMarker>, JIntMarker)>> ReleaseLongArrayElements;
+              ffi.Pointer<JniEnv1> env,
+              JByteArrayPtr array,
+              ffi.Pointer<JByteMarker> elems,
+              JIntMarker mode)>> ReleaseByteArrayElements;
 
   external ffi.Pointer<
       ffi.NativeFunction<
           ffi.Void Function(
-              ffi.Pointer<JniEnv1>,
-              JFloatArrayPtr,
-              ffi.Pointer<JFloatMarker>,
-              JIntMarker)>> ReleaseFloatArrayElements;
+              ffi.Pointer<JniEnv1> env,
+              JCharArrayPtr array,
+              ffi.Pointer<JCharMarker> elems,
+              JIntMarker mode)>> ReleaseCharArrayElements;
 
   external ffi.Pointer<
       ffi.NativeFunction<
           ffi.Void Function(
-              ffi.Pointer<JniEnv1>,
-              JDoubleArrayPtr,
-              ffi.Pointer<JDoubleMarker>,
-              JIntMarker)>> ReleaseDoubleArrayElements;
+              ffi.Pointer<JniEnv1> env,
+              JShortArrayPtr array,
+              ffi.Pointer<JShortMarker> elems,
+              JIntMarker mode)>> ReleaseShortArrayElements;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          ffi.Void Function(ffi.Pointer<JniEnv1>, JBooleanArrayPtr, JSizeMarker,
-              JSizeMarker, ffi.Pointer<JBooleanMarker>)>> GetBooleanArrayRegion;
+          ffi.Void Function(
+              ffi.Pointer<JniEnv1> env,
+              JIntArrayPtr array,
+              ffi.Pointer<JIntMarker> elems,
+              JIntMarker mode)>> ReleaseIntArrayElements;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          ffi.Void Function(ffi.Pointer<JniEnv1>, JByteArrayPtr, JSizeMarker,
-              JSizeMarker, ffi.Pointer<JByteMarker>)>> GetByteArrayRegion;
+          ffi.Void Function(
+              ffi.Pointer<JniEnv1> env,
+              JLongArrayPtr array,
+              ffi.Pointer<JLongMarker> elems,
+              JIntMarker mode)>> ReleaseLongArrayElements;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          ffi.Void Function(ffi.Pointer<JniEnv1>, JCharArrayPtr, JSizeMarker,
-              JSizeMarker, ffi.Pointer<JCharMarker>)>> GetCharArrayRegion;
+          ffi.Void Function(
+              ffi.Pointer<JniEnv1> env,
+              JFloatArrayPtr array,
+              ffi.Pointer<JFloatMarker> elems,
+              JIntMarker mode)>> ReleaseFloatArrayElements;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          ffi.Void Function(ffi.Pointer<JniEnv1>, JShortArrayPtr, JSizeMarker,
-              JSizeMarker, ffi.Pointer<JShortMarker>)>> GetShortArrayRegion;
+          ffi.Void Function(
+              ffi.Pointer<JniEnv1> env,
+              JDoubleArrayPtr array,
+              ffi.Pointer<JDoubleMarker> elems,
+              JIntMarker mode)>> ReleaseDoubleArrayElements;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          ffi.Void Function(ffi.Pointer<JniEnv1>, JIntArrayPtr, JSizeMarker,
-              JSizeMarker, ffi.Pointer<JIntMarker>)>> GetIntArrayRegion;
+          ffi.Void Function(
+              ffi.Pointer<JniEnv1> env,
+              JBooleanArrayPtr array,
+              JSizeMarker start,
+              JSizeMarker len,
+              ffi.Pointer<JBooleanMarker> buf)>> GetBooleanArrayRegion;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          ffi.Void Function(ffi.Pointer<JniEnv1>, JLongArrayPtr, JSizeMarker,
-              JSizeMarker, ffi.Pointer<JLongMarker>)>> GetLongArrayRegion;
+          ffi.Void Function(
+              ffi.Pointer<JniEnv1> env,
+              JByteArrayPtr array,
+              JSizeMarker start,
+              JSizeMarker len,
+              ffi.Pointer<JByteMarker> buf)>> GetByteArrayRegion;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          ffi.Void Function(ffi.Pointer<JniEnv1>, JFloatArrayPtr, JSizeMarker,
-              JSizeMarker, ffi.Pointer<JFloatMarker>)>> GetFloatArrayRegion;
+          ffi.Void Function(
+              ffi.Pointer<JniEnv1> env,
+              JCharArrayPtr array,
+              JSizeMarker start,
+              JSizeMarker len,
+              ffi.Pointer<JCharMarker> buf)>> GetCharArrayRegion;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          ffi.Void Function(ffi.Pointer<JniEnv1>, JDoubleArrayPtr, JSizeMarker,
-              JSizeMarker, ffi.Pointer<JDoubleMarker>)>> GetDoubleArrayRegion;
+          ffi.Void Function(
+              ffi.Pointer<JniEnv1> env,
+              JShortArrayPtr array,
+              JSizeMarker start,
+              JSizeMarker len,
+              ffi.Pointer<JShortMarker> buf)>> GetShortArrayRegion;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          ffi.Void Function(
+              ffi.Pointer<JniEnv1> env,
+              JIntArrayPtr array,
+              JSizeMarker start,
+              JSizeMarker len,
+              ffi.Pointer<JIntMarker> buf)>> GetIntArrayRegion;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          ffi.Void Function(
+              ffi.Pointer<JniEnv1> env,
+              JLongArrayPtr array,
+              JSizeMarker start,
+              JSizeMarker len,
+              ffi.Pointer<JLongMarker> buf)>> GetLongArrayRegion;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          ffi.Void Function(
+              ffi.Pointer<JniEnv1> env,
+              JFloatArrayPtr array,
+              JSizeMarker start,
+              JSizeMarker len,
+              ffi.Pointer<JFloatMarker> buf)>> GetFloatArrayRegion;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          ffi.Void Function(
+              ffi.Pointer<JniEnv1> env,
+              JDoubleArrayPtr array,
+              JSizeMarker start,
+              JSizeMarker len,
+              ffi.Pointer<JDoubleMarker> buf)>> GetDoubleArrayRegion;
 
   /// spec shows these without const; some jni.h do, some don't
   external ffi.Pointer<
       ffi.NativeFunction<
-          ffi.Void Function(ffi.Pointer<JniEnv1>, JBooleanArrayPtr, JSizeMarker,
-              JSizeMarker, ffi.Pointer<JBooleanMarker>)>> SetBooleanArrayRegion;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          ffi.Void Function(ffi.Pointer<JniEnv1>, JByteArrayPtr, JSizeMarker,
-              JSizeMarker, ffi.Pointer<JByteMarker>)>> SetByteArrayRegion;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          ffi.Void Function(ffi.Pointer<JniEnv1>, JCharArrayPtr, JSizeMarker,
-              JSizeMarker, ffi.Pointer<JCharMarker>)>> SetCharArrayRegion;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          ffi.Void Function(ffi.Pointer<JniEnv1>, JShortArrayPtr, JSizeMarker,
-              JSizeMarker, ffi.Pointer<JShortMarker>)>> SetShortArrayRegion;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          ffi.Void Function(ffi.Pointer<JniEnv1>, JIntArrayPtr, JSizeMarker,
-              JSizeMarker, ffi.Pointer<JIntMarker>)>> SetIntArrayRegion;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          ffi.Void Function(ffi.Pointer<JniEnv1>, JLongArrayPtr, JSizeMarker,
-              JSizeMarker, ffi.Pointer<JLongMarker>)>> SetLongArrayRegion;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          ffi.Void Function(ffi.Pointer<JniEnv1>, JFloatArrayPtr, JSizeMarker,
-              JSizeMarker, ffi.Pointer<JFloatMarker>)>> SetFloatArrayRegion;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          ffi.Void Function(ffi.Pointer<JniEnv1>, JDoubleArrayPtr, JSizeMarker,
-              JSizeMarker, ffi.Pointer<JDoubleMarker>)>> SetDoubleArrayRegion;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          JIntMarker Function(ffi.Pointer<JniEnv1>, JClassPtr,
-              ffi.Pointer<JNINativeMethod>, JIntMarker)>> RegisterNatives;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              JIntMarker Function(ffi.Pointer<JniEnv1>, JClassPtr)>>
-      UnregisterNatives;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          JIntMarker Function(ffi.Pointer<JniEnv1>, JObjectPtr)>> MonitorEnter;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          JIntMarker Function(ffi.Pointer<JniEnv1>, JObjectPtr)>> MonitorExit;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              JIntMarker Function(
-                  ffi.Pointer<JniEnv1>, ffi.Pointer<ffi.Pointer<JavaVM>>)>>
-      GetJavaVM;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          ffi.Void Function(ffi.Pointer<JniEnv1>, JStringPtr, JSizeMarker,
-              JSizeMarker, ffi.Pointer<JCharMarker>)>> GetStringRegion;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          ffi.Void Function(ffi.Pointer<JniEnv1>, JStringPtr, JSizeMarker,
-              JSizeMarker, ffi.Pointer<ffi.Char>)>> GetStringUTFRegion;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          ffi.Pointer<ffi.Void> Function(ffi.Pointer<JniEnv1>, JArrayPtr,
-              ffi.Pointer<JBooleanMarker>)>> GetPrimitiveArrayCritical;
+          ffi.Void Function(
+              ffi.Pointer<JniEnv1> env,
+              JBooleanArrayPtr array,
+              JSizeMarker start,
+              JSizeMarker len,
+              ffi.Pointer<JBooleanMarker> buf)>> SetBooleanArrayRegion;
 
   external ffi.Pointer<
       ffi.NativeFunction<
           ffi.Void Function(
-              ffi.Pointer<JniEnv1>,
-              JArrayPtr,
-              ffi.Pointer<ffi.Void>,
-              JIntMarker)>> ReleasePrimitiveArrayCritical;
+              ffi.Pointer<JniEnv1> env,
+              JByteArrayPtr array,
+              JSizeMarker start,
+              JSizeMarker len,
+              ffi.Pointer<JByteMarker> buf)>> SetByteArrayRegion;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          ffi.Pointer<JCharMarker> Function(ffi.Pointer<JniEnv1>, JStringPtr,
-              ffi.Pointer<JBooleanMarker>)>> GetStringCritical;
+          ffi.Void Function(
+              ffi.Pointer<JniEnv1> env,
+              JCharArrayPtr array,
+              JSizeMarker start,
+              JSizeMarker len,
+              ffi.Pointer<JCharMarker> buf)>> SetCharArrayRegion;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          ffi.Void Function(
+              ffi.Pointer<JniEnv1> env,
+              JShortArrayPtr array,
+              JSizeMarker start,
+              JSizeMarker len,
+              ffi.Pointer<JShortMarker> buf)>> SetShortArrayRegion;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          ffi.Void Function(
+              ffi.Pointer<JniEnv1> env,
+              JIntArrayPtr array,
+              JSizeMarker start,
+              JSizeMarker len,
+              ffi.Pointer<JIntMarker> buf)>> SetIntArrayRegion;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          ffi.Void Function(
+              ffi.Pointer<JniEnv1> env,
+              JLongArrayPtr array,
+              JSizeMarker start,
+              JSizeMarker len,
+              ffi.Pointer<JLongMarker> buf)>> SetLongArrayRegion;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          ffi.Void Function(
+              ffi.Pointer<JniEnv1> env,
+              JFloatArrayPtr array,
+              JSizeMarker start,
+              JSizeMarker len,
+              ffi.Pointer<JFloatMarker> buf)>> SetFloatArrayRegion;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          ffi.Void Function(
+              ffi.Pointer<JniEnv1> env,
+              JDoubleArrayPtr array,
+              JSizeMarker start,
+              JSizeMarker len,
+              ffi.Pointer<JDoubleMarker> buf)>> SetDoubleArrayRegion;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JIntMarker Function(
+              ffi.Pointer<JniEnv1> env,
+              JClassPtr clazz,
+              ffi.Pointer<JNINativeMethod> methods,
+              JIntMarker nMethods)>> RegisterNatives;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              ffi.Void Function(
-                  ffi.Pointer<JniEnv1>, JStringPtr, ffi.Pointer<JCharMarker>)>>
-      ReleaseStringCritical;
+              JIntMarker Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz)>>
+      UnregisterNatives;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              JWeakPtr Function(ffi.Pointer<JniEnv1>, JObjectPtr)>>
+              JIntMarker Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj)>>
+      MonitorEnter;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JIntMarker Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj)>>
+      MonitorExit;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JIntMarker Function(ffi.Pointer<JniEnv1> env,
+              ffi.Pointer<ffi.Pointer<JavaVM1>> vm)>> GetJavaVM;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          ffi.Void Function(
+              ffi.Pointer<JniEnv1> env,
+              JStringPtr str,
+              JSizeMarker start,
+              JSizeMarker len,
+              ffi.Pointer<JCharMarker> buf)>> GetStringRegion;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          ffi.Void Function(
+              ffi.Pointer<JniEnv1> env,
+              JStringPtr str,
+              JSizeMarker start,
+              JSizeMarker len,
+              ffi.Pointer<ffi.Char> buf)>> GetStringUTFRegion;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          ffi.Pointer<ffi.Void> Function(
+              ffi.Pointer<JniEnv1> env,
+              JArrayPtr array,
+              ffi.Pointer<JBooleanMarker> isCopy)>> GetPrimitiveArrayCritical;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          ffi.Void Function(
+              ffi.Pointer<JniEnv1> env,
+              JArrayPtr array,
+              ffi.Pointer<ffi.Void> carray,
+              JIntMarker mode)>> ReleasePrimitiveArrayCritical;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          ffi.Pointer<JCharMarker> Function(
+              ffi.Pointer<JniEnv1> env,
+              JStringPtr str,
+              ffi.Pointer<JBooleanMarker> isCopy)>> GetStringCritical;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          ffi.Void Function(ffi.Pointer<JniEnv1> env, JStringPtr str,
+              ffi.Pointer<JCharMarker> carray)>> ReleaseStringCritical;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JWeakPtr Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj)>>
       NewWeakGlobalRef;
 
   external ffi.Pointer<
-          ffi.NativeFunction<ffi.Void Function(ffi.Pointer<JniEnv1>, JWeakPtr)>>
+          ffi.NativeFunction<
+              ffi.Void Function(ffi.Pointer<JniEnv1> env, JWeakPtr obj)>>
       DeleteWeakGlobalRef;
 
   external ffi.Pointer<
-          ffi.NativeFunction<JBooleanMarker Function(ffi.Pointer<JniEnv1>)>>
+          ffi.NativeFunction<JBooleanMarker Function(ffi.Pointer<JniEnv1> env)>>
       ExceptionCheck;
 
   external ffi.Pointer<
-          ffi.NativeFunction<
-              JObjectPtr Function(
-                  ffi.Pointer<JniEnv1>, ffi.Pointer<ffi.Void>, JLongMarker)>>
-      NewDirectByteBuffer;
+      ffi.NativeFunction<
+          JObjectPtr Function(
+              ffi.Pointer<JniEnv1> env,
+              ffi.Pointer<ffi.Void> address,
+              JLongMarker capacity)>> NewDirectByteBuffer;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              ffi.Pointer<ffi.Void> Function(ffi.Pointer<JniEnv1>, JObjectPtr)>>
+              ffi.Pointer<ffi.Void> Function(
+                  ffi.Pointer<JniEnv1> env, JObjectPtr buf)>>
       GetDirectBufferAddress;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              JLongMarker Function(ffi.Pointer<JniEnv1>, JObjectPtr)>>
+              JLongMarker Function(ffi.Pointer<JniEnv1> env, JObjectPtr buf)>>
       GetDirectBufferCapacity;
 
   /// added in JNI 1.6
   external ffi.Pointer<
           ffi.NativeFunction<
-              ffi.Int32 Function(ffi.Pointer<JniEnv1>, JObjectPtr)>>
+              ffi.Int32 Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj)>>
       GetObjectRefType;
 }
 
 typedef JniEnv1 = ffi.Pointer<JNINativeInterface>;
-typedef JClassPtr = JObjectPtr;
-
-/// "cardinal indices and sizes"
-typedef JSizeMarker = JIntMarker;
-typedef JMethodIDPtr = ffi.Pointer<jmethodID_>;
-typedef JFieldIDPtr = ffi.Pointer<jfieldID_>;
-typedef JThrowablePtr = JObjectPtr;
-typedef JStringPtr = JObjectPtr;
-typedef JArrayPtr = JObjectPtr;
 typedef JObjectArrayPtr = JArrayPtr;
 typedef JBooleanArrayPtr = JArrayPtr;
 typedef JByteArrayPtr = JArrayPtr;
@@ -1467,26 +1896,22 @@
 typedef JLongArrayPtr = JArrayPtr;
 typedef JFloatArrayPtr = JArrayPtr;
 typedef JDoubleArrayPtr = JArrayPtr;
-typedef JWeakPtr = JObjectPtr;
 
-class JavaVMAttachArgs extends ffi.Struct {
-  /// must be >= JNI_VERSION_1_2
-  @JIntMarker()
-  external int version;
-
-  /// NULL or name of thread as modified UTF-8 str
+class JNINativeMethod extends ffi.Struct {
   external ffi.Pointer<ffi.Char> name;
 
-  /// global ref of a ThreadGroup object, or NULL
-  external JObjectPtr group;
+  external ffi.Pointer<ffi.Char> signature;
+
+  external ffi.Pointer<ffi.Void> fnPtr;
 }
 
-/// JNI 1.2+ initialization.  (As of 1.6, the pre-1.2 structures are no
-/// longer supported.)
-class JavaVMOption extends ffi.Struct {
-  external ffi.Pointer<ffi.Char> optionString;
+typedef JWeakPtr = JObjectPtr;
 
-  external ffi.Pointer<ffi.Void> extraInfo;
+abstract class JObjectRefType {
+  static const int JNIInvalidRefType = 0;
+  static const int JNILocalRefType = 1;
+  static const int JNIGlobalRefType = 2;
+  static const int JNIWeakGlobalRefType = 3;
 }
 
 class JavaVMInitArgs extends ffi.Struct {
@@ -1503,2300 +1928,1318 @@
   external int ignoreUnrecognized;
 }
 
-/// Types used by JNI API to distinguish between primitive types.
-abstract class JniCallType {
-  static const int booleanType = 0;
-  static const int byteType = 1;
-  static const int shortType = 2;
-  static const int charType = 3;
-  static const int intType = 4;
-  static const int longType = 5;
-  static const int floatType = 6;
-  static const int doubleType = 7;
-  static const int objectType = 8;
-  static const int voidType = 9;
+/// JNI 1.2+ initialization.  (As of 1.6, the pre-1.2 structures are no
+/// longer supported.)
+class JavaVMOption extends ffi.Struct {
+  external ffi.Pointer<ffi.Char> optionString;
+
+  external ffi.Pointer<ffi.Void> extraInfo;
 }
 
-/// Result type for use by JNI.
-///
-/// If [exception] is null, it means the result is valid.
-/// It's assumed that the caller knows the expected type in [result].
-class JniResult extends ffi.Struct {
-  external JValue result;
-
-  external JThrowablePtr exception;
-}
-
-/// Similar to [JniResult] but for class lookups.
-class JniClassLookupResult extends ffi.Struct {
-  external JClassPtr classRef;
-
-  external JThrowablePtr exception;
-}
-
-/// Similar to [JniResult] but for method/field ID lookups.
-class JniPointerResult extends ffi.Struct {
-  external ffi.Pointer<ffi.Void> id;
-
-  external JThrowablePtr exception;
-}
-
-/// JniExceptionDetails holds 2 jstring objects, one is the result of
-/// calling `toString` on exception object, other is stack trace;
-class JniExceptionDetails extends ffi.Struct {
-  external JStringPtr message;
-
-  external JStringPtr stacktrace;
-}
-
-/// This struct contains functions which wrap method call / field access conveniently along with
-/// exception checking.
-///
-/// Flutter embedding checks for pending JNI exceptions before an FFI transition, which requires us
-/// to check for and clear the exception before returning to dart code, which requires these functions
-/// to return result types.
-class JniAccessors extends ffi.Struct {
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          JniClassLookupResult Function(ffi.Pointer<ffi.Char>)>> getClass;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              JniPointerResult Function(
-                  JClassPtr, ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Char>)>>
-      getFieldID;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              JniPointerResult Function(
-                  JClassPtr, ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Char>)>>
-      getStaticFieldID;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              JniPointerResult Function(
-                  JClassPtr, ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Char>)>>
-      getMethodID;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              JniPointerResult Function(
-                  JClassPtr, ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Char>)>>
-      getStaticMethodID;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              JniResult Function(JClassPtr, JMethodIDPtr, ffi.Pointer<JValue>)>>
-      newObject;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<JniPointerResult Function(JSizeMarker, ffi.Int)>>
-      newPrimitiveArray;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              JniPointerResult Function(JSizeMarker, JClassPtr, JObjectPtr)>>
-      newObjectArray;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<JniResult Function(JArrayPtr, ffi.Int, ffi.Int)>>
-      getArrayElement;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              JniResult Function(
-                  JObjectPtr, JMethodIDPtr, ffi.Int, ffi.Pointer<JValue>)>>
-      callMethod;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              JniResult Function(
-                  JClassPtr, JMethodIDPtr, ffi.Int, ffi.Pointer<JValue>)>>
-      callStaticMethod;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          JniResult Function(JObjectPtr, JFieldIDPtr, ffi.Int)>> getField;
-
-  external ffi.Pointer<
-      ffi.NativeFunction<
-          JniResult Function(JClassPtr, JFieldIDPtr, ffi.Int)>> getStaticField;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<JniExceptionDetails Function(JThrowablePtr)>>
-      getExceptionDetails;
-}
-
-extension JniAccessorsExtension on ffi.Pointer<JniAccessors> {
-  JniClassLookupResult getClass(ffi.Pointer<ffi.Char> internalName) {
-    return ref.getClass
-            .asFunction<JniClassLookupResult Function(ffi.Pointer<ffi.Char>)>()(
-        internalName);
-  }
-
-  JniPointerResult getFieldID(JClassPtr cls, ffi.Pointer<ffi.Char> fieldName,
-      ffi.Pointer<ffi.Char> signature) {
-    return ref.getFieldID.asFunction<
-        JniPointerResult Function(JClassPtr, ffi.Pointer<ffi.Char>,
-            ffi.Pointer<ffi.Char>)>()(cls, fieldName, signature);
-  }
-
-  JniPointerResult getStaticFieldID(JClassPtr cls,
-      ffi.Pointer<ffi.Char> fieldName, ffi.Pointer<ffi.Char> signature) {
-    return ref.getStaticFieldID.asFunction<
-        JniPointerResult Function(JClassPtr, ffi.Pointer<ffi.Char>,
-            ffi.Pointer<ffi.Char>)>()(cls, fieldName, signature);
-  }
-
-  JniPointerResult getMethodID(JClassPtr cls, ffi.Pointer<ffi.Char> methodName,
-      ffi.Pointer<ffi.Char> signature) {
-    return ref.getMethodID.asFunction<
-        JniPointerResult Function(JClassPtr, ffi.Pointer<ffi.Char>,
-            ffi.Pointer<ffi.Char>)>()(cls, methodName, signature);
-  }
-
-  JniPointerResult getStaticMethodID(JClassPtr cls,
-      ffi.Pointer<ffi.Char> methodName, ffi.Pointer<ffi.Char> signature) {
-    return ref.getStaticMethodID.asFunction<
-        JniPointerResult Function(JClassPtr, ffi.Pointer<ffi.Char>,
-            ffi.Pointer<ffi.Char>)>()(cls, methodName, signature);
-  }
-
-  JniResult newObject(
-      JClassPtr cls, JMethodIDPtr ctor, ffi.Pointer<JValue> args) {
-    return ref.newObject.asFunction<
-        JniResult Function(
-            JClassPtr, JMethodIDPtr, ffi.Pointer<JValue>)>()(cls, ctor, args);
-  }
-
-  JniPointerResult newPrimitiveArray(int length, int type) {
-    return ref.newPrimitiveArray
-        .asFunction<JniPointerResult Function(int, int)>()(length, type);
-  }
-
-  JniPointerResult newObjectArray(
-      int length, JClassPtr elementClass, JObjectPtr initialElement) {
-    return ref.newObjectArray.asFunction<
-            JniPointerResult Function(int, JClassPtr, JObjectPtr)>()(
-        length, elementClass, initialElement);
-  }
-
-  JniResult getArrayElement(JArrayPtr array, int index, int type) {
-    return ref.getArrayElement
-            .asFunction<JniResult Function(JArrayPtr, int, int)>()(
-        array, index, type);
-  }
-
-  JniResult callMethod(JObjectPtr obj, JMethodIDPtr methodID, int callType,
-      ffi.Pointer<JValue> args) {
-    return ref.callMethod.asFunction<
-        JniResult Function(JObjectPtr, JMethodIDPtr, int,
-            ffi.Pointer<JValue>)>()(obj, methodID, callType, args);
-  }
-
-  JniResult callStaticMethod(JClassPtr cls, JMethodIDPtr methodID, int callType,
-      ffi.Pointer<JValue> args) {
-    return ref.callStaticMethod.asFunction<
-        JniResult Function(JClassPtr, JMethodIDPtr, int,
-            ffi.Pointer<JValue>)>()(cls, methodID, callType, args);
-  }
-
-  JniResult getField(JObjectPtr obj, JFieldIDPtr fieldID, int callType) {
-    return ref.getField
-            .asFunction<JniResult Function(JObjectPtr, JFieldIDPtr, int)>()(
-        obj, fieldID, callType);
-  }
-
-  JniResult getStaticField(JClassPtr cls, JFieldIDPtr fieldID, int callType) {
-    return ref.getStaticField
-            .asFunction<JniResult Function(JClassPtr, JFieldIDPtr, int)>()(
-        cls, fieldID, callType);
-  }
-
-  JniExceptionDetails getExceptionDetails(JThrowablePtr exception) {
-    return ref.getExceptionDetails
-        .asFunction<JniExceptionDetails Function(JThrowablePtr)>()(exception);
-  }
-}
-
-/// Wrapper over JNIEnv in the JNI API, which can be used from multiple Dart
-/// Threads.
-///
-/// It consists of wrappers to JNIEnv methods which manage the thread-local
-/// JNIEnv pointer in C code. Additionally, any returned local reference value
-/// is converted to global reference.
-///
-/// For the documentation on methods themselves, see the JNI Specification at
-/// https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html
-///
-/// Apart from the specification, the Android NDK's JNI page consists of useful
-/// information about using the JNI:
-/// https://developer.android.com/training/articles/perf-jni
 class GlobalJniEnv extends ffi.Struct {
-  external ffi.Pointer<ffi.NativeFunction<JIntMarker Function()>> GetVersion;
+  external ffi.Pointer<ffi.Void> reserved0;
+
+  external ffi.Pointer<ffi.Void> reserved1;
+
+  external ffi.Pointer<ffi.Void> reserved2;
+
+  external ffi.Pointer<ffi.Void> reserved3;
+
+  external ffi.Pointer<ffi.NativeFunction<JniResult Function()>> GetVersion;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          JClassPtr Function(ffi.Pointer<ffi.Char>, JObjectPtr,
-              ffi.Pointer<JByteMarker>, JSizeMarker)>> DefineClass;
+          JniClassLookupResult Function(
+              ffi.Pointer<ffi.Char> name,
+              JObjectPtr loader,
+              ffi.Pointer<JByteMarker> buf,
+              JSizeMarker bufLen)>> DefineClass;
 
   external ffi.Pointer<
-      ffi.NativeFunction<JClassPtr Function(ffi.Pointer<ffi.Char>)>> FindClass;
+      ffi.NativeFunction<
+          JniClassLookupResult Function(ffi.Pointer<ffi.Char> name)>> FindClass;
 
-  external ffi.Pointer<ffi.NativeFunction<JMethodIDPtr Function(JObjectPtr)>>
+  external ffi.Pointer<
+          ffi.NativeFunction<JniPointerResult Function(JObjectPtr method)>>
       FromReflectedMethod;
 
-  external ffi.Pointer<ffi.NativeFunction<JFieldIDPtr Function(JObjectPtr)>>
+  external ffi.Pointer<
+          ffi.NativeFunction<JniPointerResult Function(JObjectPtr field)>>
       FromReflectedField;
 
   external ffi.Pointer<
-          ffi.NativeFunction<
-              JObjectPtr Function(JClassPtr, JMethodIDPtr, JBooleanMarker)>>
-      ToReflectedMethod;
+      ffi.NativeFunction<
+          JniResult Function(JClassPtr cls, JMethodIDPtr methodId,
+              JBooleanMarker isStatic)>> ToReflectedMethod;
 
-  external ffi.Pointer<ffi.NativeFunction<JClassPtr Function(JClassPtr)>>
+  external ffi.Pointer<
+          ffi.NativeFunction<JniClassLookupResult Function(JClassPtr clazz)>>
       GetSuperclass;
 
   external ffi.Pointer<
-          ffi.NativeFunction<JBooleanMarker Function(JClassPtr, JClassPtr)>>
+          ffi.NativeFunction<
+              JniResult Function(JClassPtr clazz1, JClassPtr clazz2)>>
       IsAssignableFrom;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              JObjectPtr Function(JClassPtr, JFieldIDPtr, JBooleanMarker)>>
+              JniResult Function(
+                  JClassPtr cls, JFieldIDPtr fieldID, JBooleanMarker isStatic)>>
       ToReflectedField;
 
-  external ffi.Pointer<ffi.NativeFunction<JIntMarker Function(JThrowablePtr)>>
-      Throw;
+  external ffi
+      .Pointer<ffi.NativeFunction<JniResult Function(JThrowablePtr obj)>> Throw;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          JIntMarker Function(JClassPtr, ffi.Pointer<ffi.Char>)>> ThrowNew;
+          JniResult Function(
+              JClassPtr clazz, ffi.Pointer<ffi.Char> message)>> ThrowNew;
 
-  external ffi.Pointer<ffi.NativeFunction<JThrowablePtr Function()>>
+  external ffi.Pointer<ffi.NativeFunction<JniResult Function()>>
       ExceptionOccurred;
 
-  external ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>
+  external ffi.Pointer<ffi.NativeFunction<JThrowablePtr Function()>>
       ExceptionDescribe;
 
-  external ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> ExceptionClear;
+  external ffi.Pointer<ffi.NativeFunction<JThrowablePtr Function()>>
+      ExceptionClear;
 
-  external ffi
-          .Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Char>)>>
+  external ffi.Pointer<
+          ffi.NativeFunction<JThrowablePtr Function(ffi.Pointer<ffi.Char> msg)>>
       FatalError;
 
-  external ffi.Pointer<ffi.NativeFunction<JIntMarker Function(JIntMarker)>>
+  external ffi
+          .Pointer<ffi.NativeFunction<JniResult Function(JIntMarker capacity)>>
       PushLocalFrame;
 
-  external ffi.Pointer<ffi.NativeFunction<JObjectPtr Function(JObjectPtr)>>
+  external ffi
+          .Pointer<ffi.NativeFunction<JniResult Function(JObjectPtr result)>>
       PopLocalFrame;
 
-  external ffi.Pointer<ffi.NativeFunction<JObjectPtr Function(JObjectPtr)>>
+  external ffi.Pointer<ffi.NativeFunction<JniResult Function(JObjectPtr obj)>>
       NewGlobalRef;
 
-  external ffi.Pointer<ffi.NativeFunction<ffi.Void Function(JObjectPtr)>>
+  external ffi.Pointer<
+          ffi.NativeFunction<JThrowablePtr Function(JObjectPtr globalRef)>>
       DeleteGlobalRef;
 
   external ffi.Pointer<
-          ffi.NativeFunction<JBooleanMarker Function(JObjectPtr, JObjectPtr)>>
-      IsSameObject;
+          ffi.NativeFunction<JThrowablePtr Function(JObjectPtr localRef)>>
+      DeleteLocalRef;
 
-  external ffi.Pointer<ffi.NativeFunction<JIntMarker Function(JIntMarker)>>
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JniResult Function(JObjectPtr ref1, JObjectPtr ref2)>> IsSameObject;
+
+  external ffi.Pointer<ffi.NativeFunction<JniResult Function(JObjectPtr obj)>>
+      NewLocalRef;
+
+  external ffi
+          .Pointer<ffi.NativeFunction<JniResult Function(JIntMarker capacity)>>
       EnsureLocalCapacity;
 
-  external ffi.Pointer<ffi.NativeFunction<JObjectPtr Function(JClassPtr)>>
+  external ffi.Pointer<ffi.NativeFunction<JniResult Function(JClassPtr clazz)>>
       AllocObject;
 
   external ffi.Pointer<
-          ffi.NativeFunction<JObjectPtr Function(JClassPtr, JMethodIDPtr)>>
+          ffi.NativeFunction<
+              JniResult Function(JClassPtr clazz, JMethodIDPtr methodID)>>
       NewObject;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          JObjectPtr Function(
-              JClassPtr, JMethodIDPtr, ffi.Pointer<JValue>)>> NewObjectA;
+          JniResult Function(
+              JClassPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>> NewObjectV;
 
-  external ffi.Pointer<ffi.NativeFunction<JClassPtr Function(JObjectPtr)>>
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JniResult Function(JClassPtr clazz, JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> NewObjectA;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<JniClassLookupResult Function(JObjectPtr obj)>>
       GetObjectClass;
 
   external ffi.Pointer<
-          ffi.NativeFunction<JBooleanMarker Function(JObjectPtr, JClassPtr)>>
-      IsInstanceOf;
+      ffi.NativeFunction<
+          JniResult Function(JObjectPtr obj, JClassPtr clazz)>> IsInstanceOf;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JniPointerResult Function(JClassPtr clazz, ffi.Pointer<ffi.Char> name,
+              ffi.Pointer<ffi.Char> sig)>> GetMethodID;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              JMethodIDPtr Function(
-                  JClassPtr, ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Char>)>>
-      GetMethodID;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<JObjectPtr Function(JObjectPtr, JMethodIDPtr)>>
+              JniResult Function(JObjectPtr obj, JMethodIDPtr methodID)>>
       CallObjectMethod;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              JObjectPtr Function(
-                  JObjectPtr, JMethodIDPtr, ffi.Pointer<JValue>)>>
-      CallObjectMethodA;
+              JniResult Function(
+                  JObjectPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+      CallObjectMethodV;
 
   external ffi.Pointer<
-          ffi.NativeFunction<JBooleanMarker Function(JObjectPtr, JMethodIDPtr)>>
+      ffi.NativeFunction<
+          JniResult Function(JObjectPtr obj, JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallObjectMethodA;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JniResult Function(JObjectPtr obj, JMethodIDPtr methodID)>>
       CallBooleanMethod;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              JBooleanMarker Function(
-                  JObjectPtr, JMethodIDPtr, ffi.Pointer<JValue>)>>
-      CallBooleanMethodA;
+              JniResult Function(
+                  JObjectPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+      CallBooleanMethodV;
 
   external ffi.Pointer<
-          ffi.NativeFunction<JByteMarker Function(JObjectPtr, JMethodIDPtr)>>
+      ffi.NativeFunction<
+          JniResult Function(JObjectPtr obj, JMethodIDPtr methodId,
+              ffi.Pointer<JValue> args)>> CallBooleanMethodA;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JniResult Function(JObjectPtr obj, JMethodIDPtr methodID)>>
       CallByteMethod;
 
   external ffi.Pointer<
-      ffi.NativeFunction<
-          JByteMarker Function(
-              JObjectPtr, JMethodIDPtr, ffi.Pointer<JValue>)>> CallByteMethodA;
+          ffi.NativeFunction<
+              JniResult Function(
+                  JObjectPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+      CallByteMethodV;
 
   external ffi.Pointer<
-          ffi.NativeFunction<JCharMarker Function(JObjectPtr, JMethodIDPtr)>>
+      ffi.NativeFunction<
+          JniResult Function(JObjectPtr obj, JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallByteMethodA;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JniResult Function(JObjectPtr obj, JMethodIDPtr methodID)>>
       CallCharMethod;
 
   external ffi.Pointer<
-      ffi.NativeFunction<
-          JCharMarker Function(
-              JObjectPtr, JMethodIDPtr, ffi.Pointer<JValue>)>> CallCharMethodA;
+          ffi.NativeFunction<
+              JniResult Function(
+                  JObjectPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+      CallCharMethodV;
 
   external ffi.Pointer<
-          ffi.NativeFunction<JShortMarker Function(JObjectPtr, JMethodIDPtr)>>
+      ffi.NativeFunction<
+          JniResult Function(JObjectPtr obj, JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallCharMethodA;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JniResult Function(JObjectPtr obj, JMethodIDPtr methodID)>>
       CallShortMethod;
 
   external ffi.Pointer<
-      ffi.NativeFunction<
-          JShortMarker Function(
-              JObjectPtr, JMethodIDPtr, ffi.Pointer<JValue>)>> CallShortMethodA;
+          ffi.NativeFunction<
+              JniResult Function(
+                  JObjectPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+      CallShortMethodV;
 
   external ffi.Pointer<
-          ffi.NativeFunction<JIntMarker Function(JObjectPtr, JMethodIDPtr)>>
+      ffi.NativeFunction<
+          JniResult Function(JObjectPtr obj, JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallShortMethodA;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JniResult Function(JObjectPtr obj, JMethodIDPtr methodID)>>
       CallIntMethod;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          JIntMarker Function(
-              JObjectPtr, JMethodIDPtr, ffi.Pointer<JValue>)>> CallIntMethodA;
+          JniResult Function(
+              JObjectPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>> CallIntMethodV;
 
   external ffi.Pointer<
-          ffi.NativeFunction<JLongMarker Function(JObjectPtr, JMethodIDPtr)>>
+      ffi.NativeFunction<
+          JniResult Function(JObjectPtr obj, JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallIntMethodA;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JniResult Function(JObjectPtr obj, JMethodIDPtr methodID)>>
       CallLongMethod;
 
   external ffi.Pointer<
-      ffi.NativeFunction<
-          JLongMarker Function(
-              JObjectPtr, JMethodIDPtr, ffi.Pointer<JValue>)>> CallLongMethodA;
+          ffi.NativeFunction<
+              JniResult Function(
+                  JObjectPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+      CallLongMethodV;
 
   external ffi.Pointer<
-          ffi.NativeFunction<JFloatMarker Function(JObjectPtr, JMethodIDPtr)>>
+      ffi.NativeFunction<
+          JniResult Function(JObjectPtr obj, JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallLongMethodA;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JniResult Function(JObjectPtr obj, JMethodIDPtr methodID)>>
       CallFloatMethod;
 
   external ffi.Pointer<
-      ffi.NativeFunction<
-          JFloatMarker Function(
-              JObjectPtr, JMethodIDPtr, ffi.Pointer<JValue>)>> CallFloatMethodA;
+          ffi.NativeFunction<
+              JniResult Function(
+                  JObjectPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+      CallFloatMethodV;
 
   external ffi.Pointer<
-          ffi.NativeFunction<JDoubleMarker Function(JObjectPtr, JMethodIDPtr)>>
+      ffi.NativeFunction<
+          JniResult Function(JObjectPtr obj, JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallFloatMethodA;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JniResult Function(JObjectPtr obj, JMethodIDPtr methodID)>>
       CallDoubleMethod;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              JDoubleMarker Function(
-                  JObjectPtr, JMethodIDPtr, ffi.Pointer<JValue>)>>
-      CallDoubleMethodA;
+              JniResult Function(
+                  JObjectPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+      CallDoubleMethodV;
 
   external ffi.Pointer<
-          ffi.NativeFunction<ffi.Void Function(JObjectPtr, JMethodIDPtr)>>
+      ffi.NativeFunction<
+          JniResult Function(JObjectPtr obj, JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallDoubleMethodA;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JThrowablePtr Function(JObjectPtr obj, JMethodIDPtr methodID)>>
       CallVoidMethod;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              ffi.Void Function(JObjectPtr, JMethodIDPtr, ffi.Pointer<JValue>)>>
-      CallVoidMethodA;
+              JThrowablePtr Function(
+                  JObjectPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+      CallVoidMethodV;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JThrowablePtr Function(JObjectPtr obj, JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallVoidMethodA;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              JObjectPtr Function(JObjectPtr, JClassPtr, JMethodIDPtr)>>
+              JniResult Function(
+                  JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID)>>
       CallNonvirtualObjectMethod;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              JObjectPtr Function(
-                  JObjectPtr, JClassPtr, JMethodIDPtr, ffi.Pointer<JValue>)>>
-      CallNonvirtualObjectMethodA;
+              JniResult Function(
+                  JObjectPtr, JClassPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+      CallNonvirtualObjectMethodV;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JniResult Function(
+              JObjectPtr obj,
+              JClassPtr clazz,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallNonvirtualObjectMethodA;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              JBooleanMarker Function(JObjectPtr, JClassPtr, JMethodIDPtr)>>
+              JniResult Function(
+                  JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID)>>
       CallNonvirtualBooleanMethod;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              JBooleanMarker Function(
-                  JObjectPtr, JClassPtr, JMethodIDPtr, ffi.Pointer<JValue>)>>
-      CallNonvirtualBooleanMethodA;
+              JniResult Function(
+                  JObjectPtr, JClassPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+      CallNonvirtualBooleanMethodV;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JniResult Function(
+              JObjectPtr obj,
+              JClassPtr clazz,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallNonvirtualBooleanMethodA;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              JByteMarker Function(JObjectPtr, JClassPtr, JMethodIDPtr)>>
+              JniResult Function(
+                  JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID)>>
       CallNonvirtualByteMethod;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              JByteMarker Function(
-                  JObjectPtr, JClassPtr, JMethodIDPtr, ffi.Pointer<JValue>)>>
-      CallNonvirtualByteMethodA;
+              JniResult Function(
+                  JObjectPtr, JClassPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+      CallNonvirtualByteMethodV;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JniResult Function(
+              JObjectPtr obj,
+              JClassPtr clazz,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallNonvirtualByteMethodA;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              JCharMarker Function(JObjectPtr, JClassPtr, JMethodIDPtr)>>
+              JniResult Function(
+                  JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID)>>
       CallNonvirtualCharMethod;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              JCharMarker Function(
-                  JObjectPtr, JClassPtr, JMethodIDPtr, ffi.Pointer<JValue>)>>
-      CallNonvirtualCharMethodA;
+              JniResult Function(
+                  JObjectPtr, JClassPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+      CallNonvirtualCharMethodV;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JniResult Function(
+              JObjectPtr obj,
+              JClassPtr clazz,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallNonvirtualCharMethodA;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              JShortMarker Function(JObjectPtr, JClassPtr, JMethodIDPtr)>>
+              JniResult Function(
+                  JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID)>>
       CallNonvirtualShortMethod;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              JShortMarker Function(
-                  JObjectPtr, JClassPtr, JMethodIDPtr, ffi.Pointer<JValue>)>>
-      CallNonvirtualShortMethodA;
+              JniResult Function(
+                  JObjectPtr, JClassPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+      CallNonvirtualShortMethodV;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JniResult Function(
+              JObjectPtr obj,
+              JClassPtr clazz,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallNonvirtualShortMethodA;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              JIntMarker Function(JObjectPtr, JClassPtr, JMethodIDPtr)>>
+              JniResult Function(
+                  JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID)>>
       CallNonvirtualIntMethod;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              JIntMarker Function(
-                  JObjectPtr, JClassPtr, JMethodIDPtr, ffi.Pointer<JValue>)>>
-      CallNonvirtualIntMethodA;
+              JniResult Function(
+                  JObjectPtr, JClassPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+      CallNonvirtualIntMethodV;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JniResult Function(
+              JObjectPtr obj,
+              JClassPtr clazz,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallNonvirtualIntMethodA;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              JLongMarker Function(JObjectPtr, JClassPtr, JMethodIDPtr)>>
+              JniResult Function(
+                  JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID)>>
       CallNonvirtualLongMethod;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              JLongMarker Function(
-                  JObjectPtr, JClassPtr, JMethodIDPtr, ffi.Pointer<JValue>)>>
-      CallNonvirtualLongMethodA;
+              JniResult Function(
+                  JObjectPtr, JClassPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+      CallNonvirtualLongMethodV;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JniResult Function(
+              JObjectPtr obj,
+              JClassPtr clazz,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallNonvirtualLongMethodA;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              JFloatMarker Function(JObjectPtr, JClassPtr, JMethodIDPtr)>>
+              JniResult Function(
+                  JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID)>>
       CallNonvirtualFloatMethod;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              JFloatMarker Function(
-                  JObjectPtr, JClassPtr, JMethodIDPtr, ffi.Pointer<JValue>)>>
-      CallNonvirtualFloatMethodA;
+              JniResult Function(
+                  JObjectPtr, JClassPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+      CallNonvirtualFloatMethodV;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JniResult Function(
+              JObjectPtr obj,
+              JClassPtr clazz,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallNonvirtualFloatMethodA;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              JDoubleMarker Function(JObjectPtr, JClassPtr, JMethodIDPtr)>>
+              JniResult Function(
+                  JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID)>>
       CallNonvirtualDoubleMethod;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              JDoubleMarker Function(
-                  JObjectPtr, JClassPtr, JMethodIDPtr, ffi.Pointer<JValue>)>>
-      CallNonvirtualDoubleMethodA;
+              JniResult Function(
+                  JObjectPtr, JClassPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+      CallNonvirtualDoubleMethodV;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JniResult Function(
+              JObjectPtr obj,
+              JClassPtr clazz,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallNonvirtualDoubleMethodA;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              ffi.Void Function(JObjectPtr, JClassPtr, JMethodIDPtr)>>
+              JThrowablePtr Function(
+                  JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID)>>
       CallNonvirtualVoidMethod;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              ffi.Void Function(
-                  JObjectPtr, JClassPtr, JMethodIDPtr, ffi.Pointer<JValue>)>>
-      CallNonvirtualVoidMethodA;
+              JThrowablePtr Function(
+                  JObjectPtr, JClassPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+      CallNonvirtualVoidMethodV;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JThrowablePtr Function(
+              JObjectPtr obj,
+              JClassPtr clazz,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallNonvirtualVoidMethodA;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JniPointerResult Function(JClassPtr clazz, ffi.Pointer<ffi.Char> name,
+              ffi.Pointer<ffi.Char> sig)>> GetFieldID;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              JFieldIDPtr Function(
-                  JClassPtr, ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Char>)>>
-      GetFieldID;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<JObjectPtr Function(JObjectPtr, JFieldIDPtr)>>
+              JniResult Function(JObjectPtr obj, JFieldIDPtr fieldID)>>
       GetObjectField;
 
   external ffi.Pointer<
-          ffi.NativeFunction<JBooleanMarker Function(JObjectPtr, JFieldIDPtr)>>
+          ffi.NativeFunction<
+              JniResult Function(JObjectPtr obj, JFieldIDPtr fieldID)>>
       GetBooleanField;
 
   external ffi.Pointer<
-          ffi.NativeFunction<JByteMarker Function(JObjectPtr, JFieldIDPtr)>>
+          ffi.NativeFunction<
+              JniResult Function(JObjectPtr obj, JFieldIDPtr fieldID)>>
       GetByteField;
 
   external ffi.Pointer<
-          ffi.NativeFunction<JCharMarker Function(JObjectPtr, JFieldIDPtr)>>
+          ffi.NativeFunction<
+              JniResult Function(JObjectPtr obj, JFieldIDPtr fieldID)>>
       GetCharField;
 
   external ffi.Pointer<
-          ffi.NativeFunction<JShortMarker Function(JObjectPtr, JFieldIDPtr)>>
+          ffi.NativeFunction<
+              JniResult Function(JObjectPtr obj, JFieldIDPtr fieldID)>>
       GetShortField;
 
   external ffi.Pointer<
-          ffi.NativeFunction<JIntMarker Function(JObjectPtr, JFieldIDPtr)>>
-      GetIntField;
+      ffi.NativeFunction<
+          JniResult Function(JObjectPtr obj, JFieldIDPtr fieldID)>> GetIntField;
 
   external ffi.Pointer<
-          ffi.NativeFunction<JLongMarker Function(JObjectPtr, JFieldIDPtr)>>
+          ffi.NativeFunction<
+              JniResult Function(JObjectPtr obj, JFieldIDPtr fieldID)>>
       GetLongField;
 
   external ffi.Pointer<
-          ffi.NativeFunction<JFloatMarker Function(JObjectPtr, JFieldIDPtr)>>
+          ffi.NativeFunction<
+              JniResult Function(JObjectPtr obj, JFieldIDPtr fieldID)>>
       GetFloatField;
 
   external ffi.Pointer<
-          ffi.NativeFunction<JDoubleMarker Function(JObjectPtr, JFieldIDPtr)>>
+          ffi.NativeFunction<
+              JniResult Function(JObjectPtr obj, JFieldIDPtr fieldID)>>
       GetDoubleField;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              ffi.Void Function(JObjectPtr, JFieldIDPtr, JObjectPtr)>>
+              JThrowablePtr Function(
+                  JObjectPtr obj, JFieldIDPtr fieldID, JObjectPtr val)>>
       SetObjectField;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              ffi.Void Function(JObjectPtr, JFieldIDPtr, JBooleanMarker)>>
+              JThrowablePtr Function(
+                  JObjectPtr obj, JFieldIDPtr fieldID, JBooleanMarker val)>>
       SetBooleanField;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              ffi.Void Function(JObjectPtr, JFieldIDPtr, JByteMarker)>>
+              JThrowablePtr Function(
+                  JObjectPtr obj, JFieldIDPtr fieldID, JByteMarker val)>>
       SetByteField;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              ffi.Void Function(JObjectPtr, JFieldIDPtr, JCharMarker)>>
+              JThrowablePtr Function(
+                  JObjectPtr obj, JFieldIDPtr fieldID, JCharMarker val)>>
       SetCharField;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              ffi.Void Function(JObjectPtr, JFieldIDPtr, JShortMarker)>>
+              JThrowablePtr Function(
+                  JObjectPtr obj, JFieldIDPtr fieldID, JShortMarker val)>>
       SetShortField;
 
   external ffi.Pointer<
-      ffi.NativeFunction<
-          ffi.Void Function(JObjectPtr, JFieldIDPtr, JIntMarker)>> SetIntField;
+          ffi.NativeFunction<
+              JThrowablePtr Function(
+                  JObjectPtr obj, JFieldIDPtr fieldID, JIntMarker val)>>
+      SetIntField;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              ffi.Void Function(JObjectPtr, JFieldIDPtr, JLongMarker)>>
+              JThrowablePtr Function(
+                  JObjectPtr obj, JFieldIDPtr fieldID, JLongMarker val)>>
       SetLongField;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              ffi.Void Function(JObjectPtr, JFieldIDPtr, JFloatMarker)>>
+              JThrowablePtr Function(
+                  JObjectPtr obj, JFieldIDPtr fieldID, JFloatMarker val)>>
       SetFloatField;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              ffi.Void Function(JObjectPtr, JFieldIDPtr, JDoubleMarker)>>
+              JThrowablePtr Function(
+                  JObjectPtr obj, JFieldIDPtr fieldID, JDoubleMarker val)>>
       SetDoubleField;
 
   external ffi.Pointer<
-          ffi.NativeFunction<
-              JMethodIDPtr Function(
-                  JClassPtr, ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Char>)>>
-      GetStaticMethodID;
+      ffi.NativeFunction<
+          JniPointerResult Function(JClassPtr clazz, ffi.Pointer<ffi.Char> name,
+              ffi.Pointer<ffi.Char> sig)>> GetStaticMethodID;
 
   external ffi.Pointer<
-          ffi.NativeFunction<JObjectPtr Function(JClassPtr, JMethodIDPtr)>>
+          ffi.NativeFunction<
+              JniResult Function(JClassPtr clazz, JMethodIDPtr methodID)>>
       CallStaticObjectMethod;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              JObjectPtr Function(
-                  JClassPtr, JMethodIDPtr, ffi.Pointer<JValue>)>>
-      CallStaticObjectMethodA;
+              JniResult Function(
+                  JClassPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+      CallStaticObjectMethodV;
 
   external ffi.Pointer<
-          ffi.NativeFunction<JBooleanMarker Function(JClassPtr, JMethodIDPtr)>>
+      ffi.NativeFunction<
+          JniResult Function(JClassPtr clazz, JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallStaticObjectMethodA;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JniResult Function(JClassPtr clazz, JMethodIDPtr methodID)>>
       CallStaticBooleanMethod;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              JBooleanMarker Function(
-                  JClassPtr, JMethodIDPtr, ffi.Pointer<JValue>)>>
-      CallStaticBooleanMethodA;
+              JniResult Function(
+                  JClassPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+      CallStaticBooleanMethodV;
 
   external ffi.Pointer<
-          ffi.NativeFunction<JByteMarker Function(JClassPtr, JMethodIDPtr)>>
+      ffi.NativeFunction<
+          JniResult Function(JClassPtr clazz, JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallStaticBooleanMethodA;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JniResult Function(JClassPtr clazz, JMethodIDPtr methodID)>>
       CallStaticByteMethod;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              JByteMarker Function(
-                  JClassPtr, JMethodIDPtr, ffi.Pointer<JValue>)>>
-      CallStaticByteMethodA;
+              JniResult Function(
+                  JClassPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+      CallStaticByteMethodV;
 
   external ffi.Pointer<
-          ffi.NativeFunction<JCharMarker Function(JClassPtr, JMethodIDPtr)>>
+      ffi.NativeFunction<
+          JniResult Function(JClassPtr clazz, JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallStaticByteMethodA;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JniResult Function(JClassPtr clazz, JMethodIDPtr methodID)>>
       CallStaticCharMethod;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              JCharMarker Function(
-                  JClassPtr, JMethodIDPtr, ffi.Pointer<JValue>)>>
-      CallStaticCharMethodA;
+              JniResult Function(
+                  JClassPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+      CallStaticCharMethodV;
 
   external ffi.Pointer<
-          ffi.NativeFunction<JShortMarker Function(JClassPtr, JMethodIDPtr)>>
+      ffi.NativeFunction<
+          JniResult Function(JClassPtr clazz, JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallStaticCharMethodA;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JniResult Function(JClassPtr clazz, JMethodIDPtr methodID)>>
       CallStaticShortMethod;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              JShortMarker Function(
-                  JClassPtr, JMethodIDPtr, ffi.Pointer<JValue>)>>
-      CallStaticShortMethodA;
+              JniResult Function(
+                  JClassPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+      CallStaticShortMethodV;
 
   external ffi.Pointer<
-          ffi.NativeFunction<JIntMarker Function(JClassPtr, JMethodIDPtr)>>
+      ffi.NativeFunction<
+          JniResult Function(JClassPtr clazz, JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallStaticShortMethodA;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JniResult Function(JClassPtr clazz, JMethodIDPtr methodID)>>
       CallStaticIntMethod;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              JIntMarker Function(
-                  JClassPtr, JMethodIDPtr, ffi.Pointer<JValue>)>>
-      CallStaticIntMethodA;
+              JniResult Function(
+                  JClassPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+      CallStaticIntMethodV;
 
   external ffi.Pointer<
-          ffi.NativeFunction<JLongMarker Function(JClassPtr, JMethodIDPtr)>>
+      ffi.NativeFunction<
+          JniResult Function(JClassPtr clazz, JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallStaticIntMethodA;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JniResult Function(JClassPtr clazz, JMethodIDPtr methodID)>>
       CallStaticLongMethod;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              JLongMarker Function(
-                  JClassPtr, JMethodIDPtr, ffi.Pointer<JValue>)>>
-      CallStaticLongMethodA;
+              JniResult Function(
+                  JClassPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+      CallStaticLongMethodV;
 
   external ffi.Pointer<
-          ffi.NativeFunction<JFloatMarker Function(JClassPtr, JMethodIDPtr)>>
+      ffi.NativeFunction<
+          JniResult Function(JClassPtr clazz, JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallStaticLongMethodA;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JniResult Function(JClassPtr clazz, JMethodIDPtr methodID)>>
       CallStaticFloatMethod;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              JFloatMarker Function(
-                  JClassPtr, JMethodIDPtr, ffi.Pointer<JValue>)>>
-      CallStaticFloatMethodA;
+              JniResult Function(
+                  JClassPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+      CallStaticFloatMethodV;
 
   external ffi.Pointer<
-          ffi.NativeFunction<JDoubleMarker Function(JClassPtr, JMethodIDPtr)>>
+      ffi.NativeFunction<
+          JniResult Function(JClassPtr clazz, JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallStaticFloatMethodA;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JniResult Function(JClassPtr clazz, JMethodIDPtr methodID)>>
       CallStaticDoubleMethod;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              JDoubleMarker Function(
-                  JClassPtr, JMethodIDPtr, ffi.Pointer<JValue>)>>
-      CallStaticDoubleMethodA;
+              JniResult Function(
+                  JClassPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+      CallStaticDoubleMethodV;
 
   external ffi.Pointer<
-          ffi.NativeFunction<ffi.Void Function(JClassPtr, JMethodIDPtr)>>
+      ffi.NativeFunction<
+          JniResult Function(JClassPtr clazz, JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallStaticDoubleMethodA;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JThrowablePtr Function(JClassPtr clazz, JMethodIDPtr methodID)>>
       CallStaticVoidMethod;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              ffi.Void Function(JClassPtr, JMethodIDPtr, ffi.Pointer<JValue>)>>
-      CallStaticVoidMethodA;
+              JThrowablePtr Function(
+                  JClassPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+      CallStaticVoidMethodV;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JThrowablePtr Function(JClassPtr clazz, JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>> CallStaticVoidMethodA;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JniPointerResult Function(JClassPtr clazz, ffi.Pointer<ffi.Char> name,
+              ffi.Pointer<ffi.Char> sig)>> GetStaticFieldID;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              JFieldIDPtr Function(
-                  JClassPtr, ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Char>)>>
-      GetStaticFieldID;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<JObjectPtr Function(JClassPtr, JFieldIDPtr)>>
+              JniResult Function(JClassPtr clazz, JFieldIDPtr fieldID)>>
       GetStaticObjectField;
 
   external ffi.Pointer<
-          ffi.NativeFunction<JBooleanMarker Function(JClassPtr, JFieldIDPtr)>>
+          ffi.NativeFunction<
+              JniResult Function(JClassPtr clazz, JFieldIDPtr fieldID)>>
       GetStaticBooleanField;
 
   external ffi.Pointer<
-          ffi.NativeFunction<JByteMarker Function(JClassPtr, JFieldIDPtr)>>
+          ffi.NativeFunction<
+              JniResult Function(JClassPtr clazz, JFieldIDPtr fieldID)>>
       GetStaticByteField;
 
   external ffi.Pointer<
-          ffi.NativeFunction<JCharMarker Function(JClassPtr, JFieldIDPtr)>>
+          ffi.NativeFunction<
+              JniResult Function(JClassPtr clazz, JFieldIDPtr fieldID)>>
       GetStaticCharField;
 
   external ffi.Pointer<
-          ffi.NativeFunction<JShortMarker Function(JClassPtr, JFieldIDPtr)>>
+          ffi.NativeFunction<
+              JniResult Function(JClassPtr clazz, JFieldIDPtr fieldID)>>
       GetStaticShortField;
 
   external ffi.Pointer<
-          ffi.NativeFunction<JIntMarker Function(JClassPtr, JFieldIDPtr)>>
+          ffi.NativeFunction<
+              JniResult Function(JClassPtr clazz, JFieldIDPtr fieldID)>>
       GetStaticIntField;
 
   external ffi.Pointer<
-          ffi.NativeFunction<JLongMarker Function(JClassPtr, JFieldIDPtr)>>
+          ffi.NativeFunction<
+              JniResult Function(JClassPtr clazz, JFieldIDPtr fieldID)>>
       GetStaticLongField;
 
   external ffi.Pointer<
-          ffi.NativeFunction<JFloatMarker Function(JClassPtr, JFieldIDPtr)>>
+          ffi.NativeFunction<
+              JniResult Function(JClassPtr clazz, JFieldIDPtr fieldID)>>
       GetStaticFloatField;
 
   external ffi.Pointer<
-          ffi.NativeFunction<JDoubleMarker Function(JClassPtr, JFieldIDPtr)>>
+          ffi.NativeFunction<
+              JniResult Function(JClassPtr clazz, JFieldIDPtr fieldID)>>
       GetStaticDoubleField;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              ffi.Void Function(JClassPtr, JFieldIDPtr, JObjectPtr)>>
+              JThrowablePtr Function(
+                  JClassPtr clazz, JFieldIDPtr fieldID, JObjectPtr val)>>
       SetStaticObjectField;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              ffi.Void Function(JClassPtr, JFieldIDPtr, JBooleanMarker)>>
+              JThrowablePtr Function(
+                  JClassPtr clazz, JFieldIDPtr fieldID, JBooleanMarker val)>>
       SetStaticBooleanField;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              ffi.Void Function(JClassPtr, JFieldIDPtr, JByteMarker)>>
+              JThrowablePtr Function(
+                  JClassPtr clazz, JFieldIDPtr fieldID, JByteMarker val)>>
       SetStaticByteField;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              ffi.Void Function(JClassPtr, JFieldIDPtr, JCharMarker)>>
+              JThrowablePtr Function(
+                  JClassPtr clazz, JFieldIDPtr fieldID, JCharMarker val)>>
       SetStaticCharField;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              ffi.Void Function(JClassPtr, JFieldIDPtr, JShortMarker)>>
+              JThrowablePtr Function(
+                  JClassPtr clazz, JFieldIDPtr fieldID, JShortMarker val)>>
       SetStaticShortField;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              ffi.Void Function(JClassPtr, JFieldIDPtr, JIntMarker)>>
+              JThrowablePtr Function(
+                  JClassPtr clazz, JFieldIDPtr fieldID, JIntMarker val)>>
       SetStaticIntField;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              ffi.Void Function(JClassPtr, JFieldIDPtr, JLongMarker)>>
+              JThrowablePtr Function(
+                  JClassPtr clazz, JFieldIDPtr fieldID, JLongMarker val)>>
       SetStaticLongField;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              ffi.Void Function(JClassPtr, JFieldIDPtr, JFloatMarker)>>
+              JThrowablePtr Function(
+                  JClassPtr clazz, JFieldIDPtr fieldID, JFloatMarker val)>>
       SetStaticFloatField;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              ffi.Void Function(JClassPtr, JFieldIDPtr, JDoubleMarker)>>
+              JThrowablePtr Function(
+                  JClassPtr clazz, JFieldIDPtr fieldID, JDoubleMarker val)>>
       SetStaticDoubleField;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              JStringPtr Function(ffi.Pointer<JCharMarker>, JSizeMarker)>>
+              JniResult Function(
+                  ffi.Pointer<JCharMarker> unicodeChars, JSizeMarker len)>>
       NewString;
 
-  external ffi.Pointer<ffi.NativeFunction<JSizeMarker Function(JStringPtr)>>
+  external ffi
+          .Pointer<ffi.NativeFunction<JniResult Function(JStringPtr string)>>
       GetStringLength;
 
   external ffi.Pointer<
-      ffi.NativeFunction<
-          ffi.Pointer<JCharMarker> Function(
-              JStringPtr, ffi.Pointer<JBooleanMarker>)>> GetStringChars;
+          ffi.NativeFunction<
+              JniPointerResult Function(
+                  JStringPtr string, ffi.Pointer<JBooleanMarker> isCopy)>>
+      GetStringChars;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              ffi.Void Function(JStringPtr, ffi.Pointer<JCharMarker>)>>
+              JThrowablePtr Function(
+                  JStringPtr string, ffi.Pointer<JCharMarker> isCopy)>>
       ReleaseStringChars;
 
   external ffi.Pointer<
-          ffi.NativeFunction<JStringPtr Function(ffi.Pointer<ffi.Char>)>>
+          ffi.NativeFunction<JniResult Function(ffi.Pointer<ffi.Char> bytes)>>
       NewStringUTF;
 
-  external ffi.Pointer<ffi.NativeFunction<JSizeMarker Function(JStringPtr)>>
+  external ffi
+          .Pointer<ffi.NativeFunction<JniResult Function(JStringPtr string)>>
       GetStringUTFLength;
 
   external ffi.Pointer<
-      ffi.NativeFunction<
-          ffi.Pointer<ffi.Char> Function(
-              JStringPtr, ffi.Pointer<JBooleanMarker>)>> GetStringUTFChars;
+          ffi.NativeFunction<
+              JniPointerResult Function(
+                  JStringPtr string, ffi.Pointer<JBooleanMarker> isCopy)>>
+      GetStringUTFChars;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              ffi.Void Function(JStringPtr, ffi.Pointer<ffi.Char>)>>
+              JThrowablePtr Function(
+                  JStringPtr string, ffi.Pointer<ffi.Char> utf)>>
       ReleaseStringUTFChars;
 
-  external ffi.Pointer<ffi.NativeFunction<JSizeMarker Function(JArrayPtr)>>
+  external ffi.Pointer<ffi.NativeFunction<JniResult Function(JArrayPtr array)>>
       GetArrayLength;
 
   external ffi.Pointer<
-          ffi.NativeFunction<
-              JObjectArrayPtr Function(JSizeMarker, JClassPtr, JObjectPtr)>>
-      NewObjectArray;
+      ffi.NativeFunction<
+          JniResult Function(JSizeMarker length, JClassPtr elementClass,
+              JObjectPtr initialElement)>> NewObjectArray;
 
   external ffi.Pointer<
-          ffi.NativeFunction<JObjectPtr Function(JObjectArrayPtr, JSizeMarker)>>
+          ffi.NativeFunction<
+              JniResult Function(JObjectArrayPtr array, JSizeMarker index)>>
       GetObjectArrayElement;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              ffi.Void Function(JObjectArrayPtr, JSizeMarker, JObjectPtr)>>
+              JThrowablePtr Function(
+                  JObjectArrayPtr array, JSizeMarker index, JObjectPtr val)>>
       SetObjectArrayElement;
 
   external ffi
-          .Pointer<ffi.NativeFunction<JBooleanArrayPtr Function(JSizeMarker)>>
+          .Pointer<ffi.NativeFunction<JniResult Function(JSizeMarker length)>>
       NewBooleanArray;
 
-  external ffi.Pointer<ffi.NativeFunction<JByteArrayPtr Function(JSizeMarker)>>
+  external ffi
+          .Pointer<ffi.NativeFunction<JniResult Function(JSizeMarker length)>>
       NewByteArray;
 
-  external ffi.Pointer<ffi.NativeFunction<JCharArrayPtr Function(JSizeMarker)>>
+  external ffi
+          .Pointer<ffi.NativeFunction<JniResult Function(JSizeMarker length)>>
       NewCharArray;
 
-  external ffi.Pointer<ffi.NativeFunction<JShortArrayPtr Function(JSizeMarker)>>
+  external ffi
+          .Pointer<ffi.NativeFunction<JniResult Function(JSizeMarker length)>>
       NewShortArray;
 
-  external ffi.Pointer<ffi.NativeFunction<JIntArrayPtr Function(JSizeMarker)>>
+  external ffi
+          .Pointer<ffi.NativeFunction<JniResult Function(JSizeMarker length)>>
       NewIntArray;
 
-  external ffi.Pointer<ffi.NativeFunction<JLongArrayPtr Function(JSizeMarker)>>
+  external ffi
+          .Pointer<ffi.NativeFunction<JniResult Function(JSizeMarker length)>>
       NewLongArray;
 
-  external ffi.Pointer<ffi.NativeFunction<JFloatArrayPtr Function(JSizeMarker)>>
+  external ffi
+          .Pointer<ffi.NativeFunction<JniResult Function(JSizeMarker length)>>
       NewFloatArray;
 
   external ffi
-          .Pointer<ffi.NativeFunction<JDoubleArrayPtr Function(JSizeMarker)>>
+          .Pointer<ffi.NativeFunction<JniResult Function(JSizeMarker length)>>
       NewDoubleArray;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              ffi.Pointer<JBooleanMarker> Function(
-                  JBooleanArrayPtr, ffi.Pointer<JBooleanMarker>)>>
+              JniPointerResult Function(
+                  JBooleanArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy)>>
       GetBooleanArrayElements;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              ffi.Pointer<JByteMarker> Function(
-                  JByteArrayPtr, ffi.Pointer<JBooleanMarker>)>>
+              JniPointerResult Function(
+                  JByteArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy)>>
       GetByteArrayElements;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              ffi.Pointer<JCharMarker> Function(
-                  JCharArrayPtr, ffi.Pointer<JBooleanMarker>)>>
+              JniPointerResult Function(
+                  JCharArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy)>>
       GetCharArrayElements;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              ffi.Pointer<JShortMarker> Function(
-                  JShortArrayPtr, ffi.Pointer<JBooleanMarker>)>>
+              JniPointerResult Function(
+                  JShortArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy)>>
       GetShortArrayElements;
 
   external ffi.Pointer<
-      ffi.NativeFunction<
-          ffi.Pointer<JIntMarker> Function(
-              JIntArrayPtr, ffi.Pointer<JBooleanMarker>)>> GetIntArrayElements;
+          ffi.NativeFunction<
+              JniPointerResult Function(
+                  JIntArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy)>>
+      GetIntArrayElements;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              ffi.Pointer<JLongMarker> Function(
-                  JLongArrayPtr, ffi.Pointer<JBooleanMarker>)>>
+              JniPointerResult Function(
+                  JLongArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy)>>
       GetLongArrayElements;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              ffi.Pointer<JFloatMarker> Function(
-                  JFloatArrayPtr, ffi.Pointer<JBooleanMarker>)>>
+              JniPointerResult Function(
+                  JFloatArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy)>>
       GetFloatArrayElements;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              ffi.Pointer<JDoubleMarker> Function(
-                  JDoubleArrayPtr, ffi.Pointer<JBooleanMarker>)>>
+              JniPointerResult Function(
+                  JDoubleArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy)>>
       GetDoubleArrayElements;
 
   external ffi.Pointer<
-          ffi.NativeFunction<
-              ffi.Void Function(
-                  JBooleanArrayPtr, ffi.Pointer<JBooleanMarker>, JIntMarker)>>
-      ReleaseBooleanArrayElements;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              ffi.Void Function(
-                  JByteArrayPtr, ffi.Pointer<JByteMarker>, JIntMarker)>>
-      ReleaseByteArrayElements;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              ffi.Void Function(
-                  JCharArrayPtr, ffi.Pointer<JCharMarker>, JIntMarker)>>
-      ReleaseCharArrayElements;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              ffi.Void Function(
-                  JShortArrayPtr, ffi.Pointer<JShortMarker>, JIntMarker)>>
-      ReleaseShortArrayElements;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              ffi.Void Function(
-                  JIntArrayPtr, ffi.Pointer<JIntMarker>, JIntMarker)>>
-      ReleaseIntArrayElements;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              ffi.Void Function(
-                  JLongArrayPtr, ffi.Pointer<JLongMarker>, JIntMarker)>>
-      ReleaseLongArrayElements;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              ffi.Void Function(
-                  JFloatArrayPtr, ffi.Pointer<JFloatMarker>, JIntMarker)>>
-      ReleaseFloatArrayElements;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              ffi.Void Function(
-                  JDoubleArrayPtr, ffi.Pointer<JDoubleMarker>, JIntMarker)>>
-      ReleaseDoubleArrayElements;
+      ffi.NativeFunction<
+          JThrowablePtr Function(
+              JBooleanArrayPtr array,
+              ffi.Pointer<JBooleanMarker> elems,
+              JIntMarker mode)>> ReleaseBooleanArrayElements;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          ffi.Void Function(JBooleanArrayPtr, JSizeMarker, JSizeMarker,
-              ffi.Pointer<JBooleanMarker>)>> GetBooleanArrayRegion;
+          JThrowablePtr Function(
+              JByteArrayPtr array,
+              ffi.Pointer<JByteMarker> elems,
+              JIntMarker mode)>> ReleaseByteArrayElements;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          ffi.Void Function(JByteArrayPtr, JSizeMarker, JSizeMarker,
-              ffi.Pointer<JByteMarker>)>> GetByteArrayRegion;
+          JThrowablePtr Function(
+              JCharArrayPtr array,
+              ffi.Pointer<JCharMarker> elems,
+              JIntMarker mode)>> ReleaseCharArrayElements;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          ffi.Void Function(JCharArrayPtr, JSizeMarker, JSizeMarker,
-              ffi.Pointer<JCharMarker>)>> GetCharArrayRegion;
+          JThrowablePtr Function(
+              JShortArrayPtr array,
+              ffi.Pointer<JShortMarker> elems,
+              JIntMarker mode)>> ReleaseShortArrayElements;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          ffi.Void Function(JShortArrayPtr, JSizeMarker, JSizeMarker,
-              ffi.Pointer<JShortMarker>)>> GetShortArrayRegion;
+          JThrowablePtr Function(
+              JIntArrayPtr array,
+              ffi.Pointer<JIntMarker> elems,
+              JIntMarker mode)>> ReleaseIntArrayElements;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          ffi.Void Function(JIntArrayPtr, JSizeMarker, JSizeMarker,
-              ffi.Pointer<JIntMarker>)>> GetIntArrayRegion;
+          JThrowablePtr Function(
+              JLongArrayPtr array,
+              ffi.Pointer<JLongMarker> elems,
+              JIntMarker mode)>> ReleaseLongArrayElements;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          ffi.Void Function(JLongArrayPtr, JSizeMarker, JSizeMarker,
-              ffi.Pointer<JLongMarker>)>> GetLongArrayRegion;
+          JThrowablePtr Function(
+              JFloatArrayPtr array,
+              ffi.Pointer<JFloatMarker> elems,
+              JIntMarker mode)>> ReleaseFloatArrayElements;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          ffi.Void Function(JFloatArrayPtr, JSizeMarker, JSizeMarker,
-              ffi.Pointer<JFloatMarker>)>> GetFloatArrayRegion;
+          JThrowablePtr Function(
+              JDoubleArrayPtr array,
+              ffi.Pointer<JDoubleMarker> elems,
+              JIntMarker mode)>> ReleaseDoubleArrayElements;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          ffi.Void Function(JDoubleArrayPtr, JSizeMarker, JSizeMarker,
-              ffi.Pointer<JDoubleMarker>)>> GetDoubleArrayRegion;
+          JThrowablePtr Function(
+              JBooleanArrayPtr array,
+              JSizeMarker start,
+              JSizeMarker len,
+              ffi.Pointer<JBooleanMarker> buf)>> GetBooleanArrayRegion;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          ffi.Void Function(JBooleanArrayPtr, JSizeMarker, JSizeMarker,
-              ffi.Pointer<JBooleanMarker>)>> SetBooleanArrayRegion;
+          JThrowablePtr Function(
+              JByteArrayPtr array,
+              JSizeMarker start,
+              JSizeMarker len,
+              ffi.Pointer<JByteMarker> buf)>> GetByteArrayRegion;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          ffi.Void Function(JByteArrayPtr, JSizeMarker, JSizeMarker,
-              ffi.Pointer<JByteMarker>)>> SetByteArrayRegion;
+          JThrowablePtr Function(
+              JCharArrayPtr array,
+              JSizeMarker start,
+              JSizeMarker len,
+              ffi.Pointer<JCharMarker> buf)>> GetCharArrayRegion;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          ffi.Void Function(JCharArrayPtr, JSizeMarker, JSizeMarker,
-              ffi.Pointer<JCharMarker>)>> SetCharArrayRegion;
+          JThrowablePtr Function(
+              JShortArrayPtr array,
+              JSizeMarker start,
+              JSizeMarker len,
+              ffi.Pointer<JShortMarker> buf)>> GetShortArrayRegion;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          ffi.Void Function(JShortArrayPtr, JSizeMarker, JSizeMarker,
-              ffi.Pointer<JShortMarker>)>> SetShortArrayRegion;
+          JThrowablePtr Function(JIntArrayPtr array, JSizeMarker start,
+              JSizeMarker len, ffi.Pointer<JIntMarker> buf)>> GetIntArrayRegion;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          ffi.Void Function(JIntArrayPtr, JSizeMarker, JSizeMarker,
-              ffi.Pointer<JIntMarker>)>> SetIntArrayRegion;
+          JThrowablePtr Function(
+              JLongArrayPtr array,
+              JSizeMarker start,
+              JSizeMarker len,
+              ffi.Pointer<JLongMarker> buf)>> GetLongArrayRegion;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          ffi.Void Function(JLongArrayPtr, JSizeMarker, JSizeMarker,
-              ffi.Pointer<JLongMarker>)>> SetLongArrayRegion;
+          JThrowablePtr Function(
+              JFloatArrayPtr array,
+              JSizeMarker start,
+              JSizeMarker len,
+              ffi.Pointer<JFloatMarker> buf)>> GetFloatArrayRegion;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          ffi.Void Function(JFloatArrayPtr, JSizeMarker, JSizeMarker,
-              ffi.Pointer<JFloatMarker>)>> SetFloatArrayRegion;
+          JThrowablePtr Function(
+              JDoubleArrayPtr array,
+              JSizeMarker start,
+              JSizeMarker len,
+              ffi.Pointer<JDoubleMarker> buf)>> GetDoubleArrayRegion;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          ffi.Void Function(JDoubleArrayPtr, JSizeMarker, JSizeMarker,
-              ffi.Pointer<JDoubleMarker>)>> SetDoubleArrayRegion;
+          JThrowablePtr Function(
+              JBooleanArrayPtr array,
+              JSizeMarker start,
+              JSizeMarker len,
+              ffi.Pointer<JBooleanMarker> buf)>> SetBooleanArrayRegion;
 
   external ffi.Pointer<
-          ffi.NativeFunction<
-              JIntMarker Function(
-                  JClassPtr, ffi.Pointer<JNINativeMethod>, JIntMarker)>>
-      RegisterNatives;
+      ffi.NativeFunction<
+          JThrowablePtr Function(
+              JByteArrayPtr array,
+              JSizeMarker start,
+              JSizeMarker len,
+              ffi.Pointer<JByteMarker> buf)>> SetByteArrayRegion;
 
-  external ffi.Pointer<ffi.NativeFunction<JIntMarker Function(JClassPtr)>>
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JThrowablePtr Function(
+              JCharArrayPtr array,
+              JSizeMarker start,
+              JSizeMarker len,
+              ffi.Pointer<JCharMarker> buf)>> SetCharArrayRegion;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JThrowablePtr Function(
+              JShortArrayPtr array,
+              JSizeMarker start,
+              JSizeMarker len,
+              ffi.Pointer<JShortMarker> buf)>> SetShortArrayRegion;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JThrowablePtr Function(JIntArrayPtr array, JSizeMarker start,
+              JSizeMarker len, ffi.Pointer<JIntMarker> buf)>> SetIntArrayRegion;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JThrowablePtr Function(
+              JLongArrayPtr array,
+              JSizeMarker start,
+              JSizeMarker len,
+              ffi.Pointer<JLongMarker> buf)>> SetLongArrayRegion;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JThrowablePtr Function(
+              JFloatArrayPtr array,
+              JSizeMarker start,
+              JSizeMarker len,
+              ffi.Pointer<JFloatMarker> buf)>> SetFloatArrayRegion;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JThrowablePtr Function(
+              JDoubleArrayPtr array,
+              JSizeMarker start,
+              JSizeMarker len,
+              ffi.Pointer<JDoubleMarker> buf)>> SetDoubleArrayRegion;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JniResult Function(
+              JClassPtr clazz,
+              ffi.Pointer<JNINativeMethod> methods,
+              JIntMarker nMethods)>> RegisterNatives;
+
+  external ffi.Pointer<ffi.NativeFunction<JniResult Function(JClassPtr clazz)>>
       UnregisterNatives;
 
-  external ffi.Pointer<ffi.NativeFunction<JIntMarker Function(JObjectPtr)>>
+  external ffi.Pointer<ffi.NativeFunction<JniResult Function(JObjectPtr obj)>>
       MonitorEnter;
 
-  external ffi.Pointer<ffi.NativeFunction<JIntMarker Function(JObjectPtr)>>
+  external ffi.Pointer<ffi.NativeFunction<JniResult Function(JObjectPtr obj)>>
       MonitorExit;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          JIntMarker Function(ffi.Pointer<ffi.Pointer<JavaVM>>)>> GetJavaVM;
+          JniResult Function(ffi.Pointer<ffi.Pointer<JavaVM>> vm)>> GetJavaVM;
 
   external ffi.Pointer<
       ffi.NativeFunction<
-          ffi.Void Function(JStringPtr, JSizeMarker, JSizeMarker,
-              ffi.Pointer<JCharMarker>)>> GetStringRegion;
+          JThrowablePtr Function(JStringPtr str, JSizeMarker start,
+              JSizeMarker len, ffi.Pointer<JCharMarker> buf)>> GetStringRegion;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JThrowablePtr Function(JStringPtr str, JSizeMarker start,
+              JSizeMarker len, ffi.Pointer<ffi.Char> buf)>> GetStringUTFRegion;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              ffi.Void Function(
-                  JStringPtr, JSizeMarker, JSizeMarker, ffi.Pointer<ffi.Char>)>>
-      GetStringUTFRegion;
-
-  external ffi.Pointer<
-          ffi.NativeFunction<
-              ffi.Pointer<ffi.Void> Function(
-                  JArrayPtr, ffi.Pointer<JBooleanMarker>)>>
+              JniPointerResult Function(
+                  JArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy)>>
       GetPrimitiveArrayCritical;
 
   external ffi.Pointer<
-          ffi.NativeFunction<
-              ffi.Void Function(JArrayPtr, ffi.Pointer<ffi.Void>, JIntMarker)>>
-      ReleasePrimitiveArrayCritical;
-
-  external ffi.Pointer<
       ffi.NativeFunction<
-          ffi.Pointer<JCharMarker> Function(
-              JStringPtr, ffi.Pointer<JBooleanMarker>)>> GetStringCritical;
+          JThrowablePtr Function(JArrayPtr array, ffi.Pointer<ffi.Void> carray,
+              JIntMarker mode)>> ReleasePrimitiveArrayCritical;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              ffi.Void Function(JStringPtr, ffi.Pointer<JCharMarker>)>>
+              JniPointerResult Function(
+                  JStringPtr str, ffi.Pointer<JBooleanMarker> isCopy)>>
+      GetStringCritical;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JThrowablePtr Function(
+                  JStringPtr str, ffi.Pointer<JCharMarker> carray)>>
       ReleaseStringCritical;
 
-  external ffi.Pointer<ffi.NativeFunction<JWeakPtr Function(JObjectPtr)>>
+  external ffi.Pointer<ffi.NativeFunction<JniResult Function(JObjectPtr obj)>>
       NewWeakGlobalRef;
 
-  external ffi.Pointer<ffi.NativeFunction<ffi.Void Function(JWeakPtr)>>
+  external ffi.Pointer<ffi.NativeFunction<JThrowablePtr Function(JWeakPtr obj)>>
       DeleteWeakGlobalRef;
 
-  external ffi.Pointer<ffi.NativeFunction<JBooleanMarker Function()>>
-      ExceptionCheck;
+  external ffi.Pointer<ffi.NativeFunction<JniResult Function()>> ExceptionCheck;
 
   external ffi.Pointer<
           ffi.NativeFunction<
-              JObjectPtr Function(ffi.Pointer<ffi.Void>, JLongMarker)>>
+              JniResult Function(
+                  ffi.Pointer<ffi.Void> address, JLongMarker capacity)>>
       NewDirectByteBuffer;
 
   external ffi.Pointer<
-          ffi.NativeFunction<ffi.Pointer<ffi.Void> Function(JObjectPtr)>>
+          ffi.NativeFunction<JniPointerResult Function(JObjectPtr buf)>>
       GetDirectBufferAddress;
 
-  external ffi.Pointer<ffi.NativeFunction<JLongMarker Function(JObjectPtr)>>
+  external ffi.Pointer<ffi.NativeFunction<JniResult Function(JObjectPtr buf)>>
       GetDirectBufferCapacity;
 
-  external ffi.Pointer<ffi.NativeFunction<ffi.Int32 Function(JObjectPtr)>>
+  external ffi.Pointer<ffi.NativeFunction<JniResult Function(JObjectPtr obj)>>
       GetObjectRefType;
 }
 
-extension GlobalJniEnvExtension on ffi.Pointer<GlobalJniEnv> {
-  int GetVersion() {
-    return ref.GetVersion.asFunction<int Function()>()();
-  }
-
-  JClassPtr DefineClass(ffi.Pointer<ffi.Char> name, JObjectPtr loader,
-      ffi.Pointer<JByteMarker> buf, int bufLen) {
-    return ref.DefineClass.asFunction<
-        JClassPtr Function(ffi.Pointer<ffi.Char>, JObjectPtr,
-            ffi.Pointer<JByteMarker>, int)>()(name, loader, buf, bufLen);
-  }
-
-  JClassPtr FindClass(ffi.Pointer<ffi.Char> name) {
-    return ref.FindClass.asFunction<
-        JClassPtr Function(ffi.Pointer<ffi.Char>)>()(name);
-  }
-
-  JMethodIDPtr FromReflectedMethod(JObjectPtr method) {
-    return ref.FromReflectedMethod.asFunction<
-        JMethodIDPtr Function(JObjectPtr)>()(method);
-  }
-
-  JFieldIDPtr FromReflectedField(JObjectPtr field) {
-    return ref.FromReflectedField.asFunction<
-        JFieldIDPtr Function(JObjectPtr)>()(field);
-  }
-
-  JObjectPtr ToReflectedMethod(
-      JClassPtr cls, JMethodIDPtr methodId, int isStatic) {
-    return ref.ToReflectedMethod.asFunction<
-        JObjectPtr Function(
-            JClassPtr, JMethodIDPtr, int)>()(cls, methodId, isStatic);
-  }
-
-  JClassPtr GetSuperclass(JClassPtr clazz) {
-    return ref.GetSuperclass.asFunction<JClassPtr Function(JClassPtr)>()(clazz);
-  }
-
-  int IsAssignableFrom(JClassPtr clazz1, JClassPtr clazz2) {
-    return ref.IsAssignableFrom.asFunction<
-        int Function(JClassPtr, JClassPtr)>()(clazz1, clazz2);
-  }
-
-  JObjectPtr ToReflectedField(
-      JClassPtr cls, JFieldIDPtr fieldID, int isStatic) {
-    return ref.ToReflectedField.asFunction<
-        JObjectPtr Function(
-            JClassPtr, JFieldIDPtr, int)>()(cls, fieldID, isStatic);
-  }
-
-  int Throw(JThrowablePtr obj) {
-    return ref.Throw.asFunction<int Function(JThrowablePtr)>()(obj);
-  }
-
-  int ThrowNew(JClassPtr clazz, ffi.Pointer<ffi.Char> message) {
-    return ref.ThrowNew.asFunction<
-        int Function(JClassPtr, ffi.Pointer<ffi.Char>)>()(clazz, message);
-  }
-
-  JThrowablePtr ExceptionOccurred() {
-    return ref.ExceptionOccurred.asFunction<JThrowablePtr Function()>()();
-  }
-
-  void ExceptionDescribe() {
-    return ref.ExceptionDescribe.asFunction<void Function()>()();
-  }
-
-  void ExceptionClear() {
-    return ref.ExceptionClear.asFunction<void Function()>()();
-  }
-
-  void FatalError(ffi.Pointer<ffi.Char> msg) {
-    return ref.FatalError.asFunction<void Function(ffi.Pointer<ffi.Char>)>()(
-        msg);
-  }
-
-  int PushLocalFrame(int capacity) {
-    return ref.PushLocalFrame.asFunction<int Function(int)>()(capacity);
-  }
-
-  JObjectPtr PopLocalFrame(JObjectPtr result) {
-    return ref.PopLocalFrame.asFunction<JObjectPtr Function(JObjectPtr)>()(
-        result);
-  }
-
-  JObjectPtr NewGlobalRef(JObjectPtr obj) {
-    return ref.NewGlobalRef.asFunction<JObjectPtr Function(JObjectPtr)>()(obj);
-  }
-
-  void DeleteGlobalRef(JObjectPtr globalRef) {
-    return ref.DeleteGlobalRef.asFunction<void Function(JObjectPtr)>()(
-        globalRef);
-  }
-
-  int IsSameObject(JObjectPtr ref1, JObjectPtr ref2) {
-    return ref.IsSameObject.asFunction<int Function(JObjectPtr, JObjectPtr)>()(
-        ref1, ref2);
-  }
-
-  int EnsureLocalCapacity(int capacity) {
-    return ref.EnsureLocalCapacity.asFunction<int Function(int)>()(capacity);
-  }
-
-  JObjectPtr AllocObject(JClassPtr clazz) {
-    return ref.AllocObject.asFunction<JObjectPtr Function(JClassPtr)>()(clazz);
-  }
-
-  JObjectPtr NewObject(JClassPtr arg1, JMethodIDPtr arg2) {
-    return ref.NewObject.asFunction<
-        JObjectPtr Function(JClassPtr, JMethodIDPtr)>()(arg1, arg2);
-  }
-
-  JObjectPtr NewObjectA(
-      JClassPtr clazz, JMethodIDPtr methodID, ffi.Pointer<JValue> args) {
-    return ref.NewObjectA.asFunction<
-        JObjectPtr Function(JClassPtr, JMethodIDPtr,
-            ffi.Pointer<JValue>)>()(clazz, methodID, args);
-  }
-
-  JClassPtr GetObjectClass(JObjectPtr obj) {
-    return ref.GetObjectClass.asFunction<JClassPtr Function(JObjectPtr)>()(obj);
-  }
-
-  int IsInstanceOf(JObjectPtr obj, JClassPtr clazz) {
-    return ref.IsInstanceOf.asFunction<int Function(JObjectPtr, JClassPtr)>()(
-        obj, clazz);
-  }
-
-  JMethodIDPtr GetMethodID(
-      JClassPtr clazz, ffi.Pointer<ffi.Char> name, ffi.Pointer<ffi.Char> sig) {
-    return ref.GetMethodID.asFunction<
-        JMethodIDPtr Function(JClassPtr, ffi.Pointer<ffi.Char>,
-            ffi.Pointer<ffi.Char>)>()(clazz, name, sig);
-  }
-
-  JObjectPtr CallObjectMethod(JObjectPtr arg1, JMethodIDPtr arg2) {
-    return ref.CallObjectMethod.asFunction<
-        JObjectPtr Function(JObjectPtr, JMethodIDPtr)>()(arg1, arg2);
-  }
-
-  JObjectPtr CallObjectMethodA(
-      JObjectPtr obj, JMethodIDPtr methodID, ffi.Pointer<JValue> args) {
-    return ref.CallObjectMethodA.asFunction<
-        JObjectPtr Function(JObjectPtr, JMethodIDPtr,
-            ffi.Pointer<JValue>)>()(obj, methodID, args);
-  }
-
-  int CallBooleanMethod(JObjectPtr arg1, JMethodIDPtr arg2) {
-    return ref.CallBooleanMethod.asFunction<
-        int Function(JObjectPtr, JMethodIDPtr)>()(arg1, arg2);
-  }
-
-  int CallBooleanMethodA(
-      JObjectPtr obj, JMethodIDPtr methodId, ffi.Pointer<JValue> args) {
-    return ref.CallBooleanMethodA.asFunction<
-            int Function(JObjectPtr, JMethodIDPtr, ffi.Pointer<JValue>)>()(
-        obj, methodId, args);
-  }
-
-  int CallByteMethod(JObjectPtr arg1, JMethodIDPtr arg2) {
-    return ref.CallByteMethod.asFunction<
-        int Function(JObjectPtr, JMethodIDPtr)>()(arg1, arg2);
-  }
-
-  int CallByteMethodA(
-      JObjectPtr obj, JMethodIDPtr methodID, ffi.Pointer<JValue> args) {
-    return ref.CallByteMethodA.asFunction<
-            int Function(JObjectPtr, JMethodIDPtr, ffi.Pointer<JValue>)>()(
-        obj, methodID, args);
-  }
-
-  int CallCharMethod(JObjectPtr arg1, JMethodIDPtr arg2) {
-    return ref.CallCharMethod.asFunction<
-        int Function(JObjectPtr, JMethodIDPtr)>()(arg1, arg2);
-  }
-
-  int CallCharMethodA(
-      JObjectPtr obj, JMethodIDPtr methodID, ffi.Pointer<JValue> args) {
-    return ref.CallCharMethodA.asFunction<
-            int Function(JObjectPtr, JMethodIDPtr, ffi.Pointer<JValue>)>()(
-        obj, methodID, args);
-  }
-
-  int CallShortMethod(JObjectPtr arg1, JMethodIDPtr arg2) {
-    return ref.CallShortMethod.asFunction<
-        int Function(JObjectPtr, JMethodIDPtr)>()(arg1, arg2);
-  }
-
-  int CallShortMethodA(
-      JObjectPtr obj, JMethodIDPtr methodID, ffi.Pointer<JValue> args) {
-    return ref.CallShortMethodA.asFunction<
-            int Function(JObjectPtr, JMethodIDPtr, ffi.Pointer<JValue>)>()(
-        obj, methodID, args);
-  }
-
-  int CallIntMethod(JObjectPtr arg1, JMethodIDPtr arg2) {
-    return ref.CallIntMethod.asFunction<
-        int Function(JObjectPtr, JMethodIDPtr)>()(arg1, arg2);
-  }
-
-  int CallIntMethodA(
-      JObjectPtr obj, JMethodIDPtr methodID, ffi.Pointer<JValue> args) {
-    return ref.CallIntMethodA.asFunction<
-            int Function(JObjectPtr, JMethodIDPtr, ffi.Pointer<JValue>)>()(
-        obj, methodID, args);
-  }
-
-  int CallLongMethod(JObjectPtr arg1, JMethodIDPtr arg2) {
-    return ref.CallLongMethod.asFunction<
-        int Function(JObjectPtr, JMethodIDPtr)>()(arg1, arg2);
-  }
-
-  int CallLongMethodA(
-      JObjectPtr obj, JMethodIDPtr methodID, ffi.Pointer<JValue> args) {
-    return ref.CallLongMethodA.asFunction<
-            int Function(JObjectPtr, JMethodIDPtr, ffi.Pointer<JValue>)>()(
-        obj, methodID, args);
-  }
-
-  double CallFloatMethod(JObjectPtr arg1, JMethodIDPtr arg2) {
-    return ref.CallFloatMethod.asFunction<
-        double Function(JObjectPtr, JMethodIDPtr)>()(arg1, arg2);
-  }
-
-  double CallFloatMethodA(
-      JObjectPtr obj, JMethodIDPtr methodID, ffi.Pointer<JValue> args) {
-    return ref.CallFloatMethodA.asFunction<
-            double Function(JObjectPtr, JMethodIDPtr, ffi.Pointer<JValue>)>()(
-        obj, methodID, args);
-  }
-
-  double CallDoubleMethod(JObjectPtr arg1, JMethodIDPtr arg2) {
-    return ref.CallDoubleMethod.asFunction<
-        double Function(JObjectPtr, JMethodIDPtr)>()(arg1, arg2);
-  }
-
-  double CallDoubleMethodA(
-      JObjectPtr obj, JMethodIDPtr methodID, ffi.Pointer<JValue> args) {
-    return ref.CallDoubleMethodA.asFunction<
-            double Function(JObjectPtr, JMethodIDPtr, ffi.Pointer<JValue>)>()(
-        obj, methodID, args);
-  }
-
-  void CallVoidMethod(JObjectPtr arg1, JMethodIDPtr arg2) {
-    return ref.CallVoidMethod.asFunction<
-        void Function(JObjectPtr, JMethodIDPtr)>()(arg1, arg2);
-  }
-
-  void CallVoidMethodA(
-      JObjectPtr obj, JMethodIDPtr methodID, ffi.Pointer<JValue> args) {
-    return ref.CallVoidMethodA.asFunction<
-            void Function(JObjectPtr, JMethodIDPtr, ffi.Pointer<JValue>)>()(
-        obj, methodID, args);
-  }
-
-  JObjectPtr CallNonvirtualObjectMethod(
-      JObjectPtr arg1, JClassPtr arg2, JMethodIDPtr arg3) {
-    return ref.CallNonvirtualObjectMethod.asFunction<
-        JObjectPtr Function(
-            JObjectPtr, JClassPtr, JMethodIDPtr)>()(arg1, arg2, arg3);
-  }
-
-  JObjectPtr CallNonvirtualObjectMethodA(JObjectPtr obj, JClassPtr clazz,
-      JMethodIDPtr methodID, ffi.Pointer<JValue> args) {
-    return ref.CallNonvirtualObjectMethodA.asFunction<
-        JObjectPtr Function(JObjectPtr, JClassPtr, JMethodIDPtr,
-            ffi.Pointer<JValue>)>()(obj, clazz, methodID, args);
-  }
-
-  int CallNonvirtualBooleanMethod(
-      JObjectPtr arg1, JClassPtr arg2, JMethodIDPtr arg3) {
-    return ref.CallNonvirtualBooleanMethod.asFunction<
-        int Function(JObjectPtr, JClassPtr, JMethodIDPtr)>()(arg1, arg2, arg3);
-  }
-
-  int CallNonvirtualBooleanMethodA(JObjectPtr obj, JClassPtr clazz,
-      JMethodIDPtr methodID, ffi.Pointer<JValue> args) {
-    return ref.CallNonvirtualBooleanMethodA.asFunction<
-        int Function(JObjectPtr, JClassPtr, JMethodIDPtr,
-            ffi.Pointer<JValue>)>()(obj, clazz, methodID, args);
-  }
-
-  int CallNonvirtualByteMethod(
-      JObjectPtr arg1, JClassPtr arg2, JMethodIDPtr arg3) {
-    return ref.CallNonvirtualByteMethod.asFunction<
-        int Function(JObjectPtr, JClassPtr, JMethodIDPtr)>()(arg1, arg2, arg3);
-  }
-
-  int CallNonvirtualByteMethodA(JObjectPtr obj, JClassPtr clazz,
-      JMethodIDPtr methodID, ffi.Pointer<JValue> args) {
-    return ref.CallNonvirtualByteMethodA.asFunction<
-        int Function(JObjectPtr, JClassPtr, JMethodIDPtr,
-            ffi.Pointer<JValue>)>()(obj, clazz, methodID, args);
-  }
-
-  int CallNonvirtualCharMethod(
-      JObjectPtr arg1, JClassPtr arg2, JMethodIDPtr arg3) {
-    return ref.CallNonvirtualCharMethod.asFunction<
-        int Function(JObjectPtr, JClassPtr, JMethodIDPtr)>()(arg1, arg2, arg3);
-  }
-
-  int CallNonvirtualCharMethodA(JObjectPtr obj, JClassPtr clazz,
-      JMethodIDPtr methodID, ffi.Pointer<JValue> args) {
-    return ref.CallNonvirtualCharMethodA.asFunction<
-        int Function(JObjectPtr, JClassPtr, JMethodIDPtr,
-            ffi.Pointer<JValue>)>()(obj, clazz, methodID, args);
-  }
-
-  int CallNonvirtualShortMethod(
-      JObjectPtr arg1, JClassPtr arg2, JMethodIDPtr arg3) {
-    return ref.CallNonvirtualShortMethod.asFunction<
-        int Function(JObjectPtr, JClassPtr, JMethodIDPtr)>()(arg1, arg2, arg3);
-  }
-
-  int CallNonvirtualShortMethodA(JObjectPtr obj, JClassPtr clazz,
-      JMethodIDPtr methodID, ffi.Pointer<JValue> args) {
-    return ref.CallNonvirtualShortMethodA.asFunction<
-        int Function(JObjectPtr, JClassPtr, JMethodIDPtr,
-            ffi.Pointer<JValue>)>()(obj, clazz, methodID, args);
-  }
-
-  int CallNonvirtualIntMethod(
-      JObjectPtr arg1, JClassPtr arg2, JMethodIDPtr arg3) {
-    return ref.CallNonvirtualIntMethod.asFunction<
-        int Function(JObjectPtr, JClassPtr, JMethodIDPtr)>()(arg1, arg2, arg3);
-  }
-
-  int CallNonvirtualIntMethodA(JObjectPtr obj, JClassPtr clazz,
-      JMethodIDPtr methodID, ffi.Pointer<JValue> args) {
-    return ref.CallNonvirtualIntMethodA.asFunction<
-        int Function(JObjectPtr, JClassPtr, JMethodIDPtr,
-            ffi.Pointer<JValue>)>()(obj, clazz, methodID, args);
-  }
-
-  int CallNonvirtualLongMethod(
-      JObjectPtr arg1, JClassPtr arg2, JMethodIDPtr arg3) {
-    return ref.CallNonvirtualLongMethod.asFunction<
-        int Function(JObjectPtr, JClassPtr, JMethodIDPtr)>()(arg1, arg2, arg3);
-  }
-
-  int CallNonvirtualLongMethodA(JObjectPtr obj, JClassPtr clazz,
-      JMethodIDPtr methodID, ffi.Pointer<JValue> args) {
-    return ref.CallNonvirtualLongMethodA.asFunction<
-        int Function(JObjectPtr, JClassPtr, JMethodIDPtr,
-            ffi.Pointer<JValue>)>()(obj, clazz, methodID, args);
-  }
-
-  double CallNonvirtualFloatMethod(
-      JObjectPtr arg1, JClassPtr arg2, JMethodIDPtr arg3) {
-    return ref.CallNonvirtualFloatMethod.asFunction<
-        double Function(
-            JObjectPtr, JClassPtr, JMethodIDPtr)>()(arg1, arg2, arg3);
-  }
-
-  double CallNonvirtualFloatMethodA(JObjectPtr obj, JClassPtr clazz,
-      JMethodIDPtr methodID, ffi.Pointer<JValue> args) {
-    return ref.CallNonvirtualFloatMethodA.asFunction<
-        double Function(JObjectPtr, JClassPtr, JMethodIDPtr,
-            ffi.Pointer<JValue>)>()(obj, clazz, methodID, args);
-  }
-
-  double CallNonvirtualDoubleMethod(
-      JObjectPtr arg1, JClassPtr arg2, JMethodIDPtr arg3) {
-    return ref.CallNonvirtualDoubleMethod.asFunction<
-        double Function(
-            JObjectPtr, JClassPtr, JMethodIDPtr)>()(arg1, arg2, arg3);
-  }
-
-  double CallNonvirtualDoubleMethodA(JObjectPtr obj, JClassPtr clazz,
-      JMethodIDPtr methodID, ffi.Pointer<JValue> args) {
-    return ref.CallNonvirtualDoubleMethodA.asFunction<
-        double Function(JObjectPtr, JClassPtr, JMethodIDPtr,
-            ffi.Pointer<JValue>)>()(obj, clazz, methodID, args);
-  }
-
-  void CallNonvirtualVoidMethod(
-      JObjectPtr arg1, JClassPtr arg2, JMethodIDPtr arg3) {
-    return ref.CallNonvirtualVoidMethod.asFunction<
-        void Function(JObjectPtr, JClassPtr, JMethodIDPtr)>()(arg1, arg2, arg3);
-  }
-
-  void CallNonvirtualVoidMethodA(JObjectPtr obj, JClassPtr clazz,
-      JMethodIDPtr methodID, ffi.Pointer<JValue> args) {
-    return ref.CallNonvirtualVoidMethodA.asFunction<
-        void Function(JObjectPtr, JClassPtr, JMethodIDPtr,
-            ffi.Pointer<JValue>)>()(obj, clazz, methodID, args);
-  }
-
-  JFieldIDPtr GetFieldID(
-      JClassPtr clazz, ffi.Pointer<ffi.Char> name, ffi.Pointer<ffi.Char> sig) {
-    return ref.GetFieldID.asFunction<
-        JFieldIDPtr Function(JClassPtr, ffi.Pointer<ffi.Char>,
-            ffi.Pointer<ffi.Char>)>()(clazz, name, sig);
-  }
-
-  JObjectPtr GetObjectField(JObjectPtr obj, JFieldIDPtr fieldID) {
-    return ref.GetObjectField.asFunction<
-        JObjectPtr Function(JObjectPtr, JFieldIDPtr)>()(obj, fieldID);
-  }
-
-  int GetBooleanField(JObjectPtr obj, JFieldIDPtr fieldID) {
-    return ref.GetBooleanField.asFunction<
-        int Function(JObjectPtr, JFieldIDPtr)>()(obj, fieldID);
-  }
-
-  int GetByteField(JObjectPtr obj, JFieldIDPtr fieldID) {
-    return ref.GetByteField.asFunction<int Function(JObjectPtr, JFieldIDPtr)>()(
-        obj, fieldID);
-  }
-
-  int GetCharField(JObjectPtr obj, JFieldIDPtr fieldID) {
-    return ref.GetCharField.asFunction<int Function(JObjectPtr, JFieldIDPtr)>()(
-        obj, fieldID);
-  }
-
-  int GetShortField(JObjectPtr obj, JFieldIDPtr fieldID) {
-    return ref.GetShortField.asFunction<
-        int Function(JObjectPtr, JFieldIDPtr)>()(obj, fieldID);
-  }
-
-  int GetIntField(JObjectPtr obj, JFieldIDPtr fieldID) {
-    return ref.GetIntField.asFunction<int Function(JObjectPtr, JFieldIDPtr)>()(
-        obj, fieldID);
-  }
-
-  int GetLongField(JObjectPtr obj, JFieldIDPtr fieldID) {
-    return ref.GetLongField.asFunction<int Function(JObjectPtr, JFieldIDPtr)>()(
-        obj, fieldID);
-  }
-
-  double GetFloatField(JObjectPtr obj, JFieldIDPtr fieldID) {
-    return ref.GetFloatField.asFunction<
-        double Function(JObjectPtr, JFieldIDPtr)>()(obj, fieldID);
-  }
-
-  double GetDoubleField(JObjectPtr obj, JFieldIDPtr fieldID) {
-    return ref.GetDoubleField.asFunction<
-        double Function(JObjectPtr, JFieldIDPtr)>()(obj, fieldID);
-  }
-
-  void SetObjectField(JObjectPtr obj, JFieldIDPtr fieldID, JObjectPtr val) {
-    return ref.SetObjectField.asFunction<
-        void Function(
-            JObjectPtr, JFieldIDPtr, JObjectPtr)>()(obj, fieldID, val);
-  }
-
-  void SetBooleanField(JObjectPtr obj, JFieldIDPtr fieldID, int val) {
-    return ref.SetBooleanField.asFunction<
-        void Function(JObjectPtr, JFieldIDPtr, int)>()(obj, fieldID, val);
-  }
-
-  void SetByteField(JObjectPtr obj, JFieldIDPtr fieldID, int val) {
-    return ref.SetByteField.asFunction<
-        void Function(JObjectPtr, JFieldIDPtr, int)>()(obj, fieldID, val);
-  }
-
-  void SetCharField(JObjectPtr obj, JFieldIDPtr fieldID, int val) {
-    return ref.SetCharField.asFunction<
-        void Function(JObjectPtr, JFieldIDPtr, int)>()(obj, fieldID, val);
-  }
-
-  void SetShortField(JObjectPtr obj, JFieldIDPtr fieldID, int val) {
-    return ref.SetShortField.asFunction<
-        void Function(JObjectPtr, JFieldIDPtr, int)>()(obj, fieldID, val);
-  }
-
-  void SetIntField(JObjectPtr obj, JFieldIDPtr fieldID, int val) {
-    return ref.SetIntField.asFunction<
-        void Function(JObjectPtr, JFieldIDPtr, int)>()(obj, fieldID, val);
-  }
-
-  void SetLongField(JObjectPtr obj, JFieldIDPtr fieldID, int val) {
-    return ref.SetLongField.asFunction<
-        void Function(JObjectPtr, JFieldIDPtr, int)>()(obj, fieldID, val);
-  }
-
-  void SetFloatField(JObjectPtr obj, JFieldIDPtr fieldID, double val) {
-    return ref.SetFloatField.asFunction<
-        void Function(JObjectPtr, JFieldIDPtr, double)>()(obj, fieldID, val);
-  }
-
-  void SetDoubleField(JObjectPtr obj, JFieldIDPtr fieldID, double val) {
-    return ref.SetDoubleField.asFunction<
-        void Function(JObjectPtr, JFieldIDPtr, double)>()(obj, fieldID, val);
-  }
-
-  JMethodIDPtr GetStaticMethodID(
-      JClassPtr clazz, ffi.Pointer<ffi.Char> name, ffi.Pointer<ffi.Char> sig) {
-    return ref.GetStaticMethodID.asFunction<
-        JMethodIDPtr Function(JClassPtr, ffi.Pointer<ffi.Char>,
-            ffi.Pointer<ffi.Char>)>()(clazz, name, sig);
-  }
-
-  JObjectPtr CallStaticObjectMethod(JClassPtr arg1, JMethodIDPtr arg2) {
-    return ref.CallStaticObjectMethod.asFunction<
-        JObjectPtr Function(JClassPtr, JMethodIDPtr)>()(arg1, arg2);
-  }
-
-  JObjectPtr CallStaticObjectMethodA(
-      JClassPtr clazz, JMethodIDPtr methodID, ffi.Pointer<JValue> args) {
-    return ref.CallStaticObjectMethodA.asFunction<
-        JObjectPtr Function(JClassPtr, JMethodIDPtr,
-            ffi.Pointer<JValue>)>()(clazz, methodID, args);
-  }
-
-  int CallStaticBooleanMethod(JClassPtr arg1, JMethodIDPtr arg2) {
-    return ref.CallStaticBooleanMethod.asFunction<
-        int Function(JClassPtr, JMethodIDPtr)>()(arg1, arg2);
-  }
-
-  int CallStaticBooleanMethodA(
-      JClassPtr clazz, JMethodIDPtr methodID, ffi.Pointer<JValue> args) {
-    return ref.CallStaticBooleanMethodA.asFunction<
-            int Function(JClassPtr, JMethodIDPtr, ffi.Pointer<JValue>)>()(
-        clazz, methodID, args);
-  }
-
-  int CallStaticByteMethod(JClassPtr arg1, JMethodIDPtr arg2) {
-    return ref.CallStaticByteMethod.asFunction<
-        int Function(JClassPtr, JMethodIDPtr)>()(arg1, arg2);
-  }
-
-  int CallStaticByteMethodA(
-      JClassPtr clazz, JMethodIDPtr methodID, ffi.Pointer<JValue> args) {
-    return ref.CallStaticByteMethodA.asFunction<
-            int Function(JClassPtr, JMethodIDPtr, ffi.Pointer<JValue>)>()(
-        clazz, methodID, args);
-  }
-
-  int CallStaticCharMethod(JClassPtr arg1, JMethodIDPtr arg2) {
-    return ref.CallStaticCharMethod.asFunction<
-        int Function(JClassPtr, JMethodIDPtr)>()(arg1, arg2);
-  }
-
-  int CallStaticCharMethodA(
-      JClassPtr clazz, JMethodIDPtr methodID, ffi.Pointer<JValue> args) {
-    return ref.CallStaticCharMethodA.asFunction<
-            int Function(JClassPtr, JMethodIDPtr, ffi.Pointer<JValue>)>()(
-        clazz, methodID, args);
-  }
-
-  int CallStaticShortMethod(JClassPtr arg1, JMethodIDPtr arg2) {
-    return ref.CallStaticShortMethod.asFunction<
-        int Function(JClassPtr, JMethodIDPtr)>()(arg1, arg2);
-  }
-
-  int CallStaticShortMethodA(
-      JClassPtr clazz, JMethodIDPtr methodID, ffi.Pointer<JValue> args) {
-    return ref.CallStaticShortMethodA.asFunction<
-            int Function(JClassPtr, JMethodIDPtr, ffi.Pointer<JValue>)>()(
-        clazz, methodID, args);
-  }
-
-  int CallStaticIntMethod(JClassPtr arg1, JMethodIDPtr arg2) {
-    return ref.CallStaticIntMethod.asFunction<
-        int Function(JClassPtr, JMethodIDPtr)>()(arg1, arg2);
-  }
-
-  int CallStaticIntMethodA(
-      JClassPtr clazz, JMethodIDPtr methodID, ffi.Pointer<JValue> args) {
-    return ref.CallStaticIntMethodA.asFunction<
-            int Function(JClassPtr, JMethodIDPtr, ffi.Pointer<JValue>)>()(
-        clazz, methodID, args);
-  }
-
-  int CallStaticLongMethod(JClassPtr arg1, JMethodIDPtr arg2) {
-    return ref.CallStaticLongMethod.asFunction<
-        int Function(JClassPtr, JMethodIDPtr)>()(arg1, arg2);
-  }
-
-  int CallStaticLongMethodA(
-      JClassPtr clazz, JMethodIDPtr methodID, ffi.Pointer<JValue> args) {
-    return ref.CallStaticLongMethodA.asFunction<
-            int Function(JClassPtr, JMethodIDPtr, ffi.Pointer<JValue>)>()(
-        clazz, methodID, args);
-  }
-
-  double CallStaticFloatMethod(JClassPtr arg1, JMethodIDPtr arg2) {
-    return ref.CallStaticFloatMethod.asFunction<
-        double Function(JClassPtr, JMethodIDPtr)>()(arg1, arg2);
-  }
-
-  double CallStaticFloatMethodA(
-      JClassPtr clazz, JMethodIDPtr methodID, ffi.Pointer<JValue> args) {
-    return ref.CallStaticFloatMethodA.asFunction<
-            double Function(JClassPtr, JMethodIDPtr, ffi.Pointer<JValue>)>()(
-        clazz, methodID, args);
-  }
-
-  double CallStaticDoubleMethod(JClassPtr arg1, JMethodIDPtr arg2) {
-    return ref.CallStaticDoubleMethod.asFunction<
-        double Function(JClassPtr, JMethodIDPtr)>()(arg1, arg2);
-  }
-
-  double CallStaticDoubleMethodA(
-      JClassPtr clazz, JMethodIDPtr methodID, ffi.Pointer<JValue> args) {
-    return ref.CallStaticDoubleMethodA.asFunction<
-            double Function(JClassPtr, JMethodIDPtr, ffi.Pointer<JValue>)>()(
-        clazz, methodID, args);
-  }
-
-  void CallStaticVoidMethod(JClassPtr arg1, JMethodIDPtr arg2) {
-    return ref.CallStaticVoidMethod.asFunction<
-        void Function(JClassPtr, JMethodIDPtr)>()(arg1, arg2);
-  }
-
-  void CallStaticVoidMethodA(
-      JClassPtr clazz, JMethodIDPtr methodID, ffi.Pointer<JValue> args) {
-    return ref.CallStaticVoidMethodA.asFunction<
-            void Function(JClassPtr, JMethodIDPtr, ffi.Pointer<JValue>)>()(
-        clazz, methodID, args);
-  }
-
-  JFieldIDPtr GetStaticFieldID(
-      JClassPtr clazz, ffi.Pointer<ffi.Char> name, ffi.Pointer<ffi.Char> sig) {
-    return ref.GetStaticFieldID.asFunction<
-        JFieldIDPtr Function(JClassPtr, ffi.Pointer<ffi.Char>,
-            ffi.Pointer<ffi.Char>)>()(clazz, name, sig);
-  }
-
-  JObjectPtr GetStaticObjectField(JClassPtr clazz, JFieldIDPtr fieldID) {
-    return ref.GetStaticObjectField.asFunction<
-        JObjectPtr Function(JClassPtr, JFieldIDPtr)>()(clazz, fieldID);
-  }
-
-  int GetStaticBooleanField(JClassPtr clazz, JFieldIDPtr fieldID) {
-    return ref.GetStaticBooleanField.asFunction<
-        int Function(JClassPtr, JFieldIDPtr)>()(clazz, fieldID);
-  }
-
-  int GetStaticByteField(JClassPtr clazz, JFieldIDPtr fieldID) {
-    return ref.GetStaticByteField.asFunction<
-        int Function(JClassPtr, JFieldIDPtr)>()(clazz, fieldID);
-  }
-
-  int GetStaticCharField(JClassPtr clazz, JFieldIDPtr fieldID) {
-    return ref.GetStaticCharField.asFunction<
-        int Function(JClassPtr, JFieldIDPtr)>()(clazz, fieldID);
-  }
-
-  int GetStaticShortField(JClassPtr clazz, JFieldIDPtr fieldID) {
-    return ref.GetStaticShortField.asFunction<
-        int Function(JClassPtr, JFieldIDPtr)>()(clazz, fieldID);
-  }
-
-  int GetStaticIntField(JClassPtr clazz, JFieldIDPtr fieldID) {
-    return ref.GetStaticIntField.asFunction<
-        int Function(JClassPtr, JFieldIDPtr)>()(clazz, fieldID);
-  }
-
-  int GetStaticLongField(JClassPtr clazz, JFieldIDPtr fieldID) {
-    return ref.GetStaticLongField.asFunction<
-        int Function(JClassPtr, JFieldIDPtr)>()(clazz, fieldID);
-  }
-
-  double GetStaticFloatField(JClassPtr clazz, JFieldIDPtr fieldID) {
-    return ref.GetStaticFloatField.asFunction<
-        double Function(JClassPtr, JFieldIDPtr)>()(clazz, fieldID);
-  }
-
-  double GetStaticDoubleField(JClassPtr clazz, JFieldIDPtr fieldID) {
-    return ref.GetStaticDoubleField.asFunction<
-        double Function(JClassPtr, JFieldIDPtr)>()(clazz, fieldID);
-  }
-
-  void SetStaticObjectField(
-      JClassPtr clazz, JFieldIDPtr fieldID, JObjectPtr val) {
-    return ref.SetStaticObjectField.asFunction<
-        void Function(
-            JClassPtr, JFieldIDPtr, JObjectPtr)>()(clazz, fieldID, val);
-  }
-
-  void SetStaticBooleanField(JClassPtr clazz, JFieldIDPtr fieldID, int val) {
-    return ref.SetStaticBooleanField.asFunction<
-        void Function(JClassPtr, JFieldIDPtr, int)>()(clazz, fieldID, val);
-  }
-
-  void SetStaticByteField(JClassPtr clazz, JFieldIDPtr fieldID, int val) {
-    return ref.SetStaticByteField.asFunction<
-        void Function(JClassPtr, JFieldIDPtr, int)>()(clazz, fieldID, val);
-  }
-
-  void SetStaticCharField(JClassPtr clazz, JFieldIDPtr fieldID, int val) {
-    return ref.SetStaticCharField.asFunction<
-        void Function(JClassPtr, JFieldIDPtr, int)>()(clazz, fieldID, val);
-  }
-
-  void SetStaticShortField(JClassPtr clazz, JFieldIDPtr fieldID, int val) {
-    return ref.SetStaticShortField.asFunction<
-        void Function(JClassPtr, JFieldIDPtr, int)>()(clazz, fieldID, val);
-  }
-
-  void SetStaticIntField(JClassPtr clazz, JFieldIDPtr fieldID, int val) {
-    return ref.SetStaticIntField.asFunction<
-        void Function(JClassPtr, JFieldIDPtr, int)>()(clazz, fieldID, val);
-  }
-
-  void SetStaticLongField(JClassPtr clazz, JFieldIDPtr fieldID, int val) {
-    return ref.SetStaticLongField.asFunction<
-        void Function(JClassPtr, JFieldIDPtr, int)>()(clazz, fieldID, val);
-  }
-
-  void SetStaticFloatField(JClassPtr clazz, JFieldIDPtr fieldID, double val) {
-    return ref.SetStaticFloatField.asFunction<
-        void Function(JClassPtr, JFieldIDPtr, double)>()(clazz, fieldID, val);
-  }
-
-  void SetStaticDoubleField(JClassPtr clazz, JFieldIDPtr fieldID, double val) {
-    return ref.SetStaticDoubleField.asFunction<
-        void Function(JClassPtr, JFieldIDPtr, double)>()(clazz, fieldID, val);
-  }
-
-  JStringPtr NewString(ffi.Pointer<JCharMarker> unicodeChars, int len) {
-    return ref.NewString.asFunction<
-        JStringPtr Function(
-            ffi.Pointer<JCharMarker>, int)>()(unicodeChars, len);
-  }
-
-  int GetStringLength(JStringPtr string) {
-    return ref.GetStringLength.asFunction<int Function(JStringPtr)>()(string);
-  }
-
-  ffi.Pointer<JCharMarker> GetStringChars(
-      JStringPtr string, ffi.Pointer<JBooleanMarker> isCopy) {
-    return ref.GetStringChars.asFunction<
-        ffi.Pointer<JCharMarker> Function(
-            JStringPtr, ffi.Pointer<JBooleanMarker>)>()(string, isCopy);
-  }
-
-  void ReleaseStringChars(JStringPtr string, ffi.Pointer<JCharMarker> isCopy) {
-    return ref.ReleaseStringChars.asFunction<
-        void Function(JStringPtr, ffi.Pointer<JCharMarker>)>()(string, isCopy);
-  }
-
-  JStringPtr NewStringUTF(ffi.Pointer<ffi.Char> bytes) {
-    return ref.NewStringUTF.asFunction<
-        JStringPtr Function(ffi.Pointer<ffi.Char>)>()(bytes);
-  }
-
-  int GetStringUTFLength(JStringPtr string) {
-    return ref.GetStringUTFLength.asFunction<int Function(JStringPtr)>()(
-        string);
-  }
-
-  ffi.Pointer<ffi.Char> GetStringUTFChars(
-      JStringPtr string, ffi.Pointer<JBooleanMarker> isCopy) {
-    return ref.GetStringUTFChars.asFunction<
-        ffi.Pointer<ffi.Char> Function(
-            JStringPtr, ffi.Pointer<JBooleanMarker>)>()(string, isCopy);
-  }
-
-  void ReleaseStringUTFChars(JStringPtr string, ffi.Pointer<ffi.Char> utf) {
-    return ref.ReleaseStringUTFChars.asFunction<
-        void Function(JStringPtr, ffi.Pointer<ffi.Char>)>()(string, utf);
-  }
-
-  int GetArrayLength(JArrayPtr array) {
-    return ref.GetArrayLength.asFunction<int Function(JArrayPtr)>()(array);
-  }
-
-  JObjectArrayPtr NewObjectArray(
-      int length, JClassPtr elementClass, JObjectPtr initialElement) {
-    return ref.NewObjectArray.asFunction<
-            JObjectArrayPtr Function(int, JClassPtr, JObjectPtr)>()(
-        length, elementClass, initialElement);
-  }
-
-  JObjectPtr GetObjectArrayElement(JObjectArrayPtr array, int index) {
-    return ref.GetObjectArrayElement.asFunction<
-        JObjectPtr Function(JObjectArrayPtr, int)>()(array, index);
-  }
-
-  void SetObjectArrayElement(JObjectArrayPtr array, int index, JObjectPtr val) {
-    return ref.SetObjectArrayElement.asFunction<
-        void Function(JObjectArrayPtr, int, JObjectPtr)>()(array, index, val);
-  }
-
-  JBooleanArrayPtr NewBooleanArray(int length) {
-    return ref.NewBooleanArray.asFunction<JBooleanArrayPtr Function(int)>()(
-        length);
-  }
-
-  JByteArrayPtr NewByteArray(int length) {
-    return ref.NewByteArray.asFunction<JByteArrayPtr Function(int)>()(length);
-  }
-
-  JCharArrayPtr NewCharArray(int length) {
-    return ref.NewCharArray.asFunction<JCharArrayPtr Function(int)>()(length);
-  }
-
-  JShortArrayPtr NewShortArray(int length) {
-    return ref.NewShortArray.asFunction<JShortArrayPtr Function(int)>()(length);
-  }
-
-  JIntArrayPtr NewIntArray(int length) {
-    return ref.NewIntArray.asFunction<JIntArrayPtr Function(int)>()(length);
-  }
-
-  JLongArrayPtr NewLongArray(int length) {
-    return ref.NewLongArray.asFunction<JLongArrayPtr Function(int)>()(length);
-  }
-
-  JFloatArrayPtr NewFloatArray(int length) {
-    return ref.NewFloatArray.asFunction<JFloatArrayPtr Function(int)>()(length);
-  }
-
-  JDoubleArrayPtr NewDoubleArray(int length) {
-    return ref.NewDoubleArray.asFunction<JDoubleArrayPtr Function(int)>()(
-        length);
-  }
-
-  ffi.Pointer<JBooleanMarker> GetBooleanArrayElements(
-      JBooleanArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy) {
-    return ref.GetBooleanArrayElements.asFunction<
-        ffi.Pointer<JBooleanMarker> Function(
-            JBooleanArrayPtr, ffi.Pointer<JBooleanMarker>)>()(array, isCopy);
-  }
-
-  ffi.Pointer<JByteMarker> GetByteArrayElements(
-      JByteArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy) {
-    return ref.GetByteArrayElements.asFunction<
-        ffi.Pointer<JByteMarker> Function(
-            JByteArrayPtr, ffi.Pointer<JBooleanMarker>)>()(array, isCopy);
-  }
-
-  ffi.Pointer<JCharMarker> GetCharArrayElements(
-      JCharArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy) {
-    return ref.GetCharArrayElements.asFunction<
-        ffi.Pointer<JCharMarker> Function(
-            JCharArrayPtr, ffi.Pointer<JBooleanMarker>)>()(array, isCopy);
-  }
-
-  ffi.Pointer<JShortMarker> GetShortArrayElements(
-      JShortArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy) {
-    return ref.GetShortArrayElements.asFunction<
-        ffi.Pointer<JShortMarker> Function(
-            JShortArrayPtr, ffi.Pointer<JBooleanMarker>)>()(array, isCopy);
-  }
-
-  ffi.Pointer<JIntMarker> GetIntArrayElements(
-      JIntArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy) {
-    return ref.GetIntArrayElements.asFunction<
-        ffi.Pointer<JIntMarker> Function(
-            JIntArrayPtr, ffi.Pointer<JBooleanMarker>)>()(array, isCopy);
-  }
-
-  ffi.Pointer<JLongMarker> GetLongArrayElements(
-      JLongArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy) {
-    return ref.GetLongArrayElements.asFunction<
-        ffi.Pointer<JLongMarker> Function(
-            JLongArrayPtr, ffi.Pointer<JBooleanMarker>)>()(array, isCopy);
-  }
-
-  ffi.Pointer<JFloatMarker> GetFloatArrayElements(
-      JFloatArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy) {
-    return ref.GetFloatArrayElements.asFunction<
-        ffi.Pointer<JFloatMarker> Function(
-            JFloatArrayPtr, ffi.Pointer<JBooleanMarker>)>()(array, isCopy);
-  }
-
-  ffi.Pointer<JDoubleMarker> GetDoubleArrayElements(
-      JDoubleArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy) {
-    return ref.GetDoubleArrayElements.asFunction<
-        ffi.Pointer<JDoubleMarker> Function(
-            JDoubleArrayPtr, ffi.Pointer<JBooleanMarker>)>()(array, isCopy);
-  }
-
-  void ReleaseBooleanArrayElements(
-      JBooleanArrayPtr array, ffi.Pointer<JBooleanMarker> elems, int mode) {
-    return ref.ReleaseBooleanArrayElements.asFunction<
-        void Function(JBooleanArrayPtr, ffi.Pointer<JBooleanMarker>,
-            int)>()(array, elems, mode);
-  }
-
-  void ReleaseByteArrayElements(
-      JByteArrayPtr array, ffi.Pointer<JByteMarker> elems, int mode) {
-    return ref.ReleaseByteArrayElements.asFunction<
-            void Function(JByteArrayPtr, ffi.Pointer<JByteMarker>, int)>()(
-        array, elems, mode);
-  }
-
-  void ReleaseCharArrayElements(
-      JCharArrayPtr array, ffi.Pointer<JCharMarker> elems, int mode) {
-    return ref.ReleaseCharArrayElements.asFunction<
-            void Function(JCharArrayPtr, ffi.Pointer<JCharMarker>, int)>()(
-        array, elems, mode);
-  }
-
-  void ReleaseShortArrayElements(
-      JShortArrayPtr array, ffi.Pointer<JShortMarker> elems, int mode) {
-    return ref.ReleaseShortArrayElements.asFunction<
-            void Function(JShortArrayPtr, ffi.Pointer<JShortMarker>, int)>()(
-        array, elems, mode);
-  }
-
-  void ReleaseIntArrayElements(
-      JIntArrayPtr array, ffi.Pointer<JIntMarker> elems, int mode) {
-    return ref.ReleaseIntArrayElements.asFunction<
-        void Function(
-            JIntArrayPtr, ffi.Pointer<JIntMarker>, int)>()(array, elems, mode);
-  }
-
-  void ReleaseLongArrayElements(
-      JLongArrayPtr array, ffi.Pointer<JLongMarker> elems, int mode) {
-    return ref.ReleaseLongArrayElements.asFunction<
-            void Function(JLongArrayPtr, ffi.Pointer<JLongMarker>, int)>()(
-        array, elems, mode);
-  }
-
-  void ReleaseFloatArrayElements(
-      JFloatArrayPtr array, ffi.Pointer<JFloatMarker> elems, int mode) {
-    return ref.ReleaseFloatArrayElements.asFunction<
-            void Function(JFloatArrayPtr, ffi.Pointer<JFloatMarker>, int)>()(
-        array, elems, mode);
-  }
-
-  void ReleaseDoubleArrayElements(
-      JDoubleArrayPtr array, ffi.Pointer<JDoubleMarker> elems, int mode) {
-    return ref.ReleaseDoubleArrayElements.asFunction<
-            void Function(JDoubleArrayPtr, ffi.Pointer<JDoubleMarker>, int)>()(
-        array, elems, mode);
-  }
-
-  void GetBooleanArrayRegion(JBooleanArrayPtr array, int start, int len,
-      ffi.Pointer<JBooleanMarker> buf) {
-    return ref.GetBooleanArrayRegion.asFunction<
-        void Function(JBooleanArrayPtr, int, int,
-            ffi.Pointer<JBooleanMarker>)>()(array, start, len, buf);
-  }
-
-  void GetByteArrayRegion(
-      JByteArrayPtr array, int start, int len, ffi.Pointer<JByteMarker> buf) {
-    return ref.GetByteArrayRegion.asFunction<
-            void Function(JByteArrayPtr, int, int, ffi.Pointer<JByteMarker>)>()(
-        array, start, len, buf);
-  }
-
-  void GetCharArrayRegion(
-      JCharArrayPtr array, int start, int len, ffi.Pointer<JCharMarker> buf) {
-    return ref.GetCharArrayRegion.asFunction<
-            void Function(JCharArrayPtr, int, int, ffi.Pointer<JCharMarker>)>()(
-        array, start, len, buf);
-  }
-
-  void GetShortArrayRegion(
-      JShortArrayPtr array, int start, int len, ffi.Pointer<JShortMarker> buf) {
-    return ref.GetShortArrayRegion.asFunction<
-        void Function(JShortArrayPtr, int, int,
-            ffi.Pointer<JShortMarker>)>()(array, start, len, buf);
-  }
-
-  void GetIntArrayRegion(
-      JIntArrayPtr array, int start, int len, ffi.Pointer<JIntMarker> buf) {
-    return ref.GetIntArrayRegion.asFunction<
-            void Function(JIntArrayPtr, int, int, ffi.Pointer<JIntMarker>)>()(
-        array, start, len, buf);
-  }
-
-  void GetLongArrayRegion(
-      JLongArrayPtr array, int start, int len, ffi.Pointer<JLongMarker> buf) {
-    return ref.GetLongArrayRegion.asFunction<
-            void Function(JLongArrayPtr, int, int, ffi.Pointer<JLongMarker>)>()(
-        array, start, len, buf);
-  }
-
-  void GetFloatArrayRegion(
-      JFloatArrayPtr array, int start, int len, ffi.Pointer<JFloatMarker> buf) {
-    return ref.GetFloatArrayRegion.asFunction<
-        void Function(JFloatArrayPtr, int, int,
-            ffi.Pointer<JFloatMarker>)>()(array, start, len, buf);
-  }
-
-  void GetDoubleArrayRegion(JDoubleArrayPtr array, int start, int len,
-      ffi.Pointer<JDoubleMarker> buf) {
-    return ref.GetDoubleArrayRegion.asFunction<
-        void Function(JDoubleArrayPtr, int, int,
-            ffi.Pointer<JDoubleMarker>)>()(array, start, len, buf);
-  }
-
-  void SetBooleanArrayRegion(JBooleanArrayPtr array, int start, int len,
-      ffi.Pointer<JBooleanMarker> buf) {
-    return ref.SetBooleanArrayRegion.asFunction<
-        void Function(JBooleanArrayPtr, int, int,
-            ffi.Pointer<JBooleanMarker>)>()(array, start, len, buf);
-  }
-
-  void SetByteArrayRegion(
-      JByteArrayPtr array, int start, int len, ffi.Pointer<JByteMarker> buf) {
-    return ref.SetByteArrayRegion.asFunction<
-            void Function(JByteArrayPtr, int, int, ffi.Pointer<JByteMarker>)>()(
-        array, start, len, buf);
-  }
-
-  void SetCharArrayRegion(
-      JCharArrayPtr array, int start, int len, ffi.Pointer<JCharMarker> buf) {
-    return ref.SetCharArrayRegion.asFunction<
-            void Function(JCharArrayPtr, int, int, ffi.Pointer<JCharMarker>)>()(
-        array, start, len, buf);
-  }
-
-  void SetShortArrayRegion(
-      JShortArrayPtr array, int start, int len, ffi.Pointer<JShortMarker> buf) {
-    return ref.SetShortArrayRegion.asFunction<
-        void Function(JShortArrayPtr, int, int,
-            ffi.Pointer<JShortMarker>)>()(array, start, len, buf);
-  }
-
-  void SetIntArrayRegion(
-      JIntArrayPtr array, int start, int len, ffi.Pointer<JIntMarker> buf) {
-    return ref.SetIntArrayRegion.asFunction<
-            void Function(JIntArrayPtr, int, int, ffi.Pointer<JIntMarker>)>()(
-        array, start, len, buf);
-  }
-
-  void SetLongArrayRegion(
-      JLongArrayPtr array, int start, int len, ffi.Pointer<JLongMarker> buf) {
-    return ref.SetLongArrayRegion.asFunction<
-            void Function(JLongArrayPtr, int, int, ffi.Pointer<JLongMarker>)>()(
-        array, start, len, buf);
-  }
-
-  void SetFloatArrayRegion(
-      JFloatArrayPtr array, int start, int len, ffi.Pointer<JFloatMarker> buf) {
-    return ref.SetFloatArrayRegion.asFunction<
-        void Function(JFloatArrayPtr, int, int,
-            ffi.Pointer<JFloatMarker>)>()(array, start, len, buf);
-  }
-
-  void SetDoubleArrayRegion(JDoubleArrayPtr array, int start, int len,
-      ffi.Pointer<JDoubleMarker> buf) {
-    return ref.SetDoubleArrayRegion.asFunction<
-        void Function(JDoubleArrayPtr, int, int,
-            ffi.Pointer<JDoubleMarker>)>()(array, start, len, buf);
-  }
-
-  int RegisterNatives(
-      JClassPtr clazz, ffi.Pointer<JNINativeMethod> methods, int nMethods) {
-    return ref.RegisterNatives.asFunction<
-            int Function(JClassPtr, ffi.Pointer<JNINativeMethod>, int)>()(
-        clazz, methods, nMethods);
-  }
-
-  int UnregisterNatives(JClassPtr clazz) {
-    return ref.UnregisterNatives.asFunction<int Function(JClassPtr)>()(clazz);
-  }
-
-  int MonitorEnter(JObjectPtr obj) {
-    return ref.MonitorEnter.asFunction<int Function(JObjectPtr)>()(obj);
-  }
-
-  int MonitorExit(JObjectPtr obj) {
-    return ref.MonitorExit.asFunction<int Function(JObjectPtr)>()(obj);
-  }
-
-  int GetJavaVM(ffi.Pointer<ffi.Pointer<JavaVM>> vm) {
-    return ref.GetJavaVM.asFunction<
-        int Function(ffi.Pointer<ffi.Pointer<JavaVM>>)>()(vm);
-  }
-
-  void GetStringRegion(
-      JStringPtr str, int start, int len, ffi.Pointer<JCharMarker> buf) {
-    return ref.GetStringRegion.asFunction<
-            void Function(JStringPtr, int, int, ffi.Pointer<JCharMarker>)>()(
-        str, start, len, buf);
-  }
-
-  void GetStringUTFRegion(
-      JStringPtr str, int start, int len, ffi.Pointer<ffi.Char> buf) {
-    return ref.GetStringUTFRegion.asFunction<
-            void Function(JStringPtr, int, int, ffi.Pointer<ffi.Char>)>()(
-        str, start, len, buf);
-  }
-
-  ffi.Pointer<ffi.Void> GetPrimitiveArrayCritical(
-      JArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy) {
-    return ref.GetPrimitiveArrayCritical.asFunction<
-        ffi.Pointer<ffi.Void> Function(
-            JArrayPtr, ffi.Pointer<JBooleanMarker>)>()(array, isCopy);
-  }
-
-  void ReleasePrimitiveArrayCritical(
-      JArrayPtr array, ffi.Pointer<ffi.Void> carray, int mode) {
-    return ref.ReleasePrimitiveArrayCritical.asFunction<
-        void Function(
-            JArrayPtr, ffi.Pointer<ffi.Void>, int)>()(array, carray, mode);
-  }
-
-  ffi.Pointer<JCharMarker> GetStringCritical(
-      JStringPtr str, ffi.Pointer<JBooleanMarker> isCopy) {
-    return ref.GetStringCritical.asFunction<
-        ffi.Pointer<JCharMarker> Function(
-            JStringPtr, ffi.Pointer<JBooleanMarker>)>()(str, isCopy);
-  }
-
-  void ReleaseStringCritical(JStringPtr str, ffi.Pointer<JCharMarker> carray) {
-    return ref.ReleaseStringCritical.asFunction<
-        void Function(JStringPtr, ffi.Pointer<JCharMarker>)>()(str, carray);
-  }
-
-  JWeakPtr NewWeakGlobalRef(JObjectPtr obj) {
-    return ref.NewWeakGlobalRef.asFunction<JWeakPtr Function(JObjectPtr)>()(
-        obj);
-  }
-
-  void DeleteWeakGlobalRef(JWeakPtr obj) {
-    return ref.DeleteWeakGlobalRef.asFunction<void Function(JWeakPtr)>()(obj);
-  }
-
-  int ExceptionCheck() {
-    return ref.ExceptionCheck.asFunction<int Function()>()();
-  }
-
-  JObjectPtr NewDirectByteBuffer(ffi.Pointer<ffi.Void> address, int capacity) {
-    return ref.NewDirectByteBuffer.asFunction<
-        JObjectPtr Function(ffi.Pointer<ffi.Void>, int)>()(address, capacity);
-  }
-
-  ffi.Pointer<ffi.Void> GetDirectBufferAddress(JObjectPtr buf) {
-    return ref.GetDirectBufferAddress.asFunction<
-        ffi.Pointer<ffi.Void> Function(JObjectPtr)>()(buf);
-  }
-
-  int GetDirectBufferCapacity(JObjectPtr buf) {
-    return ref.GetDirectBufferCapacity.asFunction<int Function(JObjectPtr)>()(
-        buf);
-  }
-
-  int GetObjectRefType(JObjectPtr obj) {
-    return ref.GetObjectRefType.asFunction<int Function(JObjectPtr)>()(obj);
-  }
+/// This file re-exports some JNI constants as enum, because they are not
+/// currently being included when they are in macro form.
+abstract class JniBooleanValues {
+  static const int JNI_FALSE = 0;
+  static const int JNI_TRUE = 1;
 }
 
-const int JNI_FALSE = 0;
+abstract class JniVersions {
+  static const int JNI_VERSION_1_1 = 65537;
+  static const int JNI_VERSION_1_2 = 65538;
+  static const int JNI_VERSION_1_4 = 65540;
+  static const int JNI_VERSION_1_6 = 65542;
+}
 
-const int JNI_TRUE = 1;
+abstract class JniErrorCode {
+  /// no error
+  static const int JNI_OK = 0;
 
-const int JNI_VERSION_1_1 = 65537;
+  /// generic error
+  static const int JNI_ERR = -1;
 
-const int JNI_VERSION_1_2 = 65538;
+  /// thread detached from the VM
+  static const int JNI_EDETACHED = -2;
 
-const int JNI_VERSION_1_4 = 65540;
+  /// JNI version error
+  static const int JNI_EVERSION = -3;
 
-const int JNI_VERSION_1_6 = 65542;
+  /// Out of memory
+  static const int JNI_ENOMEM = -4;
 
-const int JNI_OK = 0;
+  /// VM already created
+  static const int JNI_EEXIST = -5;
 
-const int JNI_ERR = -1;
+  /// Invalid argument
+  static const int JNI_EINVAL = -6;
+}
 
-const int JNI_EDETACHED = -2;
+abstract class JniBufferWriteBack {
+  /// copy content, do not free buffer
+  static const int JNI_COMMIT = 1;
 
-const int JNI_EVERSION = -3;
+  /// free buffer w/o copying back
+  static const int JNI_ABORT = 2;
+}
 
-const int JNI_ENOMEM = -4;
-
-const int JNI_EEXIST = -5;
-
-const int JNI_EINVAL = -6;
-
-const int JNI_COMMIT = 1;
-
-const int JNI_ABORT = 2;
+const int DART_JNI_SINGLETON_EXISTS = -99;
diff --git a/pkgs/jni/lib/src/third_party/jnienv_javavm_extensions.dart b/pkgs/jni/lib/src/third_party/jnienv_javavm_extensions.dart
new file mode 100644
index 0000000..7c145f9
--- /dev/null
+++ b/pkgs/jni/lib/src/third_party/jnienv_javavm_extensions.dart
@@ -0,0 +1,1409 @@
+// Auto generated file. Do not edit.
+
+// This is generated from JNI header in Android NDK. License for the same is
+// provided below.
+
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * JNI specification, as defined by Sun:
+ * http://java.sun.com/javase/6/docs/technotes/guides/jni/spec/jniTOC.html
+ *
+ * Everything here is expected to be VM-neutral.
+ */
+
+// ignore_for_file: non_constant_identifier_names
+// coverage:ignore-file
+
+import "dart:ffi" as ffi;
+
+import "jni_bindings_generated.dart";
+
+extension JniEnvExtension on ffi.Pointer<JniEnv> {
+  int GetVersion() => value.ref.GetVersion
+      .asFunction<int Function(ffi.Pointer<JniEnv1> env)>()(this);
+
+  JClassPtr DefineClass(ffi.Pointer<ffi.Char> name, JObjectPtr loader,
+          ffi.Pointer<JByteMarker> buf, int bufLen) =>
+      value.ref.DefineClass.asFunction<
+          JClassPtr Function(
+              ffi.Pointer<JniEnv1> env,
+              ffi.Pointer<ffi.Char> name,
+              JObjectPtr loader,
+              ffi.Pointer<JByteMarker> buf,
+              int bufLen)>()(this, name, loader, buf, bufLen);
+
+  JClassPtr FindClass(ffi.Pointer<ffi.Char> name) => value.ref.FindClass
+      .asFunction<
+          JClassPtr Function(ffi.Pointer<JniEnv1> env,
+              ffi.Pointer<ffi.Char> name)>()(this, name);
+
+  JMethodIDPtr FromReflectedMethod(JObjectPtr method) =>
+      value.ref.FromReflectedMethod.asFunction<
+          JMethodIDPtr Function(
+              ffi.Pointer<JniEnv1> env, JObjectPtr method)>()(this, method);
+
+  JFieldIDPtr FromReflectedField(JObjectPtr field) =>
+      value.ref.FromReflectedField.asFunction<
+          JFieldIDPtr Function(
+              ffi.Pointer<JniEnv1> env, JObjectPtr field)>()(this, field);
+
+  JObjectPtr ToReflectedMethod(
+          JClassPtr cls, JMethodIDPtr methodId, int isStatic) =>
+      value.ref.ToReflectedMethod.asFunction<
+          JObjectPtr Function(
+              ffi.Pointer<JniEnv1> env,
+              JClassPtr cls,
+              JMethodIDPtr methodId,
+              int isStatic)>()(this, cls, methodId, isStatic);
+
+  JClassPtr GetSuperclass(JClassPtr clazz) =>
+      value.ref.GetSuperclass.asFunction<
+          JClassPtr Function(
+              ffi.Pointer<JniEnv1> env, JClassPtr clazz)>()(this, clazz);
+
+  int IsAssignableFrom(JClassPtr clazz1, JClassPtr clazz2) =>
+      value.ref.IsAssignableFrom.asFunction<
+          int Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz1,
+              JClassPtr clazz2)>()(this, clazz1, clazz2);
+
+  JObjectPtr ToReflectedField(
+          JClassPtr cls, JFieldIDPtr fieldID, int isStatic) =>
+      value.ref.ToReflectedField.asFunction<
+          JObjectPtr Function(
+              ffi.Pointer<JniEnv1> env,
+              JClassPtr cls,
+              JFieldIDPtr fieldID,
+              int isStatic)>()(this, cls, fieldID, isStatic);
+
+  int Throw(JThrowablePtr obj) => value.ref.Throw.asFunction<
+      int Function(ffi.Pointer<JniEnv1> env, JThrowablePtr obj)>()(this, obj);
+
+  int ThrowNew(JClassPtr clazz, ffi.Pointer<ffi.Char> message) =>
+      value.ref.ThrowNew.asFunction<
+          int Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              ffi.Pointer<ffi.Char> message)>()(this, clazz, message);
+
+  JThrowablePtr ExceptionOccurred() => value.ref.ExceptionOccurred
+      .asFunction<JThrowablePtr Function(ffi.Pointer<JniEnv1> env)>()(this);
+
+  void ExceptionDescribe() => value.ref.ExceptionDescribe
+      .asFunction<void Function(ffi.Pointer<JniEnv1> env)>()(this);
+
+  void ExceptionClear() => value.ref.ExceptionClear
+      .asFunction<void Function(ffi.Pointer<JniEnv1> env)>()(this);
+
+  void FatalError(ffi.Pointer<ffi.Char> msg) => value.ref.FatalError.asFunction<
+      void Function(
+          ffi.Pointer<JniEnv1> env, ffi.Pointer<ffi.Char> msg)>()(this, msg);
+
+  int PushLocalFrame(int capacity) => value.ref.PushLocalFrame
+          .asFunction<int Function(ffi.Pointer<JniEnv1> env, int capacity)>()(
+      this, capacity);
+
+  JObjectPtr PopLocalFrame(JObjectPtr result) => value.ref.PopLocalFrame
+      .asFunction<
+          JObjectPtr Function(
+              ffi.Pointer<JniEnv1> env, JObjectPtr result)>()(this, result);
+
+  JObjectPtr NewGlobalRef(JObjectPtr obj) => value.ref.NewGlobalRef.asFunction<
+      JObjectPtr Function(
+          ffi.Pointer<JniEnv1> env, JObjectPtr obj)>()(this, obj);
+
+  void DeleteGlobalRef(JObjectPtr globalRef) =>
+      value.ref.DeleteGlobalRef.asFunction<
+              void Function(ffi.Pointer<JniEnv1> env, JObjectPtr globalRef)>()(
+          this, globalRef);
+
+  void DeleteLocalRef(JObjectPtr localRef) =>
+      value.ref.DeleteLocalRef.asFunction<
+          void Function(
+              ffi.Pointer<JniEnv1> env, JObjectPtr localRef)>()(this, localRef);
+
+  int IsSameObject(JObjectPtr ref1, JObjectPtr ref2) =>
+      value.ref.IsSameObject.asFunction<
+          int Function(ffi.Pointer<JniEnv1> env, JObjectPtr ref1,
+              JObjectPtr ref2)>()(this, ref1, ref2);
+
+  JObjectPtr NewLocalRef(JObjectPtr obj) => value.ref.NewLocalRef.asFunction<
+      JObjectPtr Function(
+          ffi.Pointer<JniEnv1> env, JObjectPtr obj)>()(this, obj);
+
+  int EnsureLocalCapacity(int capacity) => value.ref.EnsureLocalCapacity
+          .asFunction<int Function(ffi.Pointer<JniEnv1> env, int capacity)>()(
+      this, capacity);
+
+  JObjectPtr AllocObject(JClassPtr clazz) => value.ref.AllocObject.asFunction<
+      JObjectPtr Function(
+          ffi.Pointer<JniEnv1> env, JClassPtr clazz)>()(this, clazz);
+
+  JObjectPtr NewObject(JClassPtr clazz, JMethodIDPtr methodID) =>
+      value.ref.NewObject.asFunction<
+          JObjectPtr Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JMethodIDPtr methodID)>()(this, clazz, methodID);
+
+  JObjectPtr NewObjectA(
+          JClassPtr clazz, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      value.ref.NewObjectA.asFunction<
+          JObjectPtr Function(
+              ffi.Pointer<JniEnv1> env,
+              JClassPtr clazz,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>()(this, clazz, methodID, args);
+
+  JClassPtr GetObjectClass(JObjectPtr obj) =>
+      value.ref.GetObjectClass.asFunction<
+          JClassPtr Function(
+              ffi.Pointer<JniEnv1> env, JObjectPtr obj)>()(this, obj);
+
+  int IsInstanceOf(JObjectPtr obj, JClassPtr clazz) =>
+      value.ref.IsInstanceOf.asFunction<
+          int Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JClassPtr clazz)>()(this, obj, clazz);
+
+  JMethodIDPtr GetMethodID(JClassPtr clazz, ffi.Pointer<ffi.Char> name,
+          ffi.Pointer<ffi.Char> sig) =>
+      value.ref.GetMethodID.asFunction<
+          JMethodIDPtr Function(
+              ffi.Pointer<JniEnv1> env,
+              JClassPtr clazz,
+              ffi.Pointer<ffi.Char> name,
+              ffi.Pointer<ffi.Char> sig)>()(this, clazz, name, sig);
+
+  JObjectPtr CallObjectMethod(JObjectPtr obj, JMethodIDPtr methodID) =>
+      value.ref.CallObjectMethod.asFunction<
+          JObjectPtr Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JMethodIDPtr methodID)>()(this, obj, methodID);
+
+  JObjectPtr CallObjectMethodA(
+          JObjectPtr obj, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      value.ref.CallObjectMethodA.asFunction<
+          JObjectPtr Function(
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>()(this, obj, methodID, args);
+
+  int CallBooleanMethod(JObjectPtr obj, JMethodIDPtr methodID) =>
+      value.ref.CallBooleanMethod.asFunction<
+          int Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JMethodIDPtr methodID)>()(this, obj, methodID);
+
+  int CallBooleanMethodA(
+          JObjectPtr obj, JMethodIDPtr methodId, ffi.Pointer<JValue> args) =>
+      value.ref.CallBooleanMethodA.asFunction<
+          int Function(
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JMethodIDPtr methodId,
+              ffi.Pointer<JValue> args)>()(this, obj, methodId, args);
+
+  int CallByteMethod(JObjectPtr obj, JMethodIDPtr methodID) =>
+      value.ref.CallByteMethod.asFunction<
+          int Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JMethodIDPtr methodID)>()(this, obj, methodID);
+
+  int CallByteMethodA(
+          JObjectPtr obj, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      value.ref.CallByteMethodA.asFunction<
+          int Function(
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>()(this, obj, methodID, args);
+
+  int CallCharMethod(JObjectPtr obj, JMethodIDPtr methodID) =>
+      value.ref.CallCharMethod.asFunction<
+          int Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JMethodIDPtr methodID)>()(this, obj, methodID);
+
+  int CallCharMethodA(
+          JObjectPtr obj, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      value.ref.CallCharMethodA.asFunction<
+          int Function(
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>()(this, obj, methodID, args);
+
+  int CallShortMethod(JObjectPtr obj, JMethodIDPtr methodID) =>
+      value.ref.CallShortMethod.asFunction<
+          int Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JMethodIDPtr methodID)>()(this, obj, methodID);
+
+  int CallShortMethodA(
+          JObjectPtr obj, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      value.ref.CallShortMethodA.asFunction<
+          int Function(
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>()(this, obj, methodID, args);
+
+  int CallIntMethod(JObjectPtr obj, JMethodIDPtr methodID) =>
+      value.ref.CallIntMethod.asFunction<
+          int Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JMethodIDPtr methodID)>()(this, obj, methodID);
+
+  int CallIntMethodA(
+          JObjectPtr obj, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      value.ref.CallIntMethodA.asFunction<
+          int Function(
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>()(this, obj, methodID, args);
+
+  int CallLongMethod(JObjectPtr obj, JMethodIDPtr methodID) =>
+      value.ref.CallLongMethod.asFunction<
+          int Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JMethodIDPtr methodID)>()(this, obj, methodID);
+
+  int CallLongMethodA(
+          JObjectPtr obj, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      value.ref.CallLongMethodA.asFunction<
+          int Function(
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>()(this, obj, methodID, args);
+
+  double CallFloatMethod(JObjectPtr obj, JMethodIDPtr methodID) =>
+      value.ref.CallFloatMethod.asFunction<
+          double Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JMethodIDPtr methodID)>()(this, obj, methodID);
+
+  double CallFloatMethodA(
+          JObjectPtr obj, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      value.ref.CallFloatMethodA.asFunction<
+          double Function(
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>()(this, obj, methodID, args);
+
+  double CallDoubleMethod(JObjectPtr obj, JMethodIDPtr methodID) =>
+      value.ref.CallDoubleMethod.asFunction<
+          double Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JMethodIDPtr methodID)>()(this, obj, methodID);
+
+  double CallDoubleMethodA(
+          JObjectPtr obj, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      value.ref.CallDoubleMethodA.asFunction<
+          double Function(
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>()(this, obj, methodID, args);
+
+  void CallVoidMethod(JObjectPtr obj, JMethodIDPtr methodID) =>
+      value.ref.CallVoidMethod.asFunction<
+          void Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JMethodIDPtr methodID)>()(this, obj, methodID);
+
+  void CallVoidMethodA(
+          JObjectPtr obj, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      value.ref.CallVoidMethodA.asFunction<
+          void Function(
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>()(this, obj, methodID, args);
+
+  JObjectPtr CallNonvirtualObjectMethod(
+          JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID) =>
+      value.ref.CallNonvirtualObjectMethod.asFunction<
+          JObjectPtr Function(
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JClassPtr clazz,
+              JMethodIDPtr methodID)>()(this, obj, clazz, methodID);
+
+  JObjectPtr CallNonvirtualObjectMethodA(JObjectPtr obj, JClassPtr clazz,
+          JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      value.ref.CallNonvirtualObjectMethodA.asFunction<
+          JObjectPtr Function(
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JClassPtr clazz,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>()(this, obj, clazz, methodID, args);
+
+  int CallNonvirtualBooleanMethod(
+          JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID) =>
+      value.ref.CallNonvirtualBooleanMethod.asFunction<
+          int Function(
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JClassPtr clazz,
+              JMethodIDPtr methodID)>()(this, obj, clazz, methodID);
+
+  int CallNonvirtualBooleanMethodA(JObjectPtr obj, JClassPtr clazz,
+          JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      value.ref.CallNonvirtualBooleanMethodA.asFunction<
+          int Function(
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JClassPtr clazz,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>()(this, obj, clazz, methodID, args);
+
+  int CallNonvirtualByteMethod(
+          JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID) =>
+      value.ref.CallNonvirtualByteMethod.asFunction<
+          int Function(
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JClassPtr clazz,
+              JMethodIDPtr methodID)>()(this, obj, clazz, methodID);
+
+  int CallNonvirtualByteMethodA(JObjectPtr obj, JClassPtr clazz,
+          JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      value.ref.CallNonvirtualByteMethodA.asFunction<
+          int Function(
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JClassPtr clazz,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>()(this, obj, clazz, methodID, args);
+
+  int CallNonvirtualCharMethod(
+          JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID) =>
+      value.ref.CallNonvirtualCharMethod.asFunction<
+          int Function(
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JClassPtr clazz,
+              JMethodIDPtr methodID)>()(this, obj, clazz, methodID);
+
+  int CallNonvirtualCharMethodA(JObjectPtr obj, JClassPtr clazz,
+          JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      value.ref.CallNonvirtualCharMethodA.asFunction<
+          int Function(
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JClassPtr clazz,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>()(this, obj, clazz, methodID, args);
+
+  int CallNonvirtualShortMethod(
+          JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID) =>
+      value.ref.CallNonvirtualShortMethod.asFunction<
+          int Function(
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JClassPtr clazz,
+              JMethodIDPtr methodID)>()(this, obj, clazz, methodID);
+
+  int CallNonvirtualShortMethodA(JObjectPtr obj, JClassPtr clazz,
+          JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      value.ref.CallNonvirtualShortMethodA.asFunction<
+          int Function(
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JClassPtr clazz,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>()(this, obj, clazz, methodID, args);
+
+  int CallNonvirtualIntMethod(
+          JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID) =>
+      value.ref.CallNonvirtualIntMethod.asFunction<
+          int Function(
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JClassPtr clazz,
+              JMethodIDPtr methodID)>()(this, obj, clazz, methodID);
+
+  int CallNonvirtualIntMethodA(JObjectPtr obj, JClassPtr clazz,
+          JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      value.ref.CallNonvirtualIntMethodA.asFunction<
+          int Function(
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JClassPtr clazz,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>()(this, obj, clazz, methodID, args);
+
+  int CallNonvirtualLongMethod(
+          JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID) =>
+      value.ref.CallNonvirtualLongMethod.asFunction<
+          int Function(
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JClassPtr clazz,
+              JMethodIDPtr methodID)>()(this, obj, clazz, methodID);
+
+  int CallNonvirtualLongMethodA(JObjectPtr obj, JClassPtr clazz,
+          JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      value.ref.CallNonvirtualLongMethodA.asFunction<
+          int Function(
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JClassPtr clazz,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>()(this, obj, clazz, methodID, args);
+
+  double CallNonvirtualFloatMethod(
+          JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID) =>
+      value.ref.CallNonvirtualFloatMethod.asFunction<
+          double Function(
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JClassPtr clazz,
+              JMethodIDPtr methodID)>()(this, obj, clazz, methodID);
+
+  double CallNonvirtualFloatMethodA(JObjectPtr obj, JClassPtr clazz,
+          JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      value.ref.CallNonvirtualFloatMethodA.asFunction<
+          double Function(
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JClassPtr clazz,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>()(this, obj, clazz, methodID, args);
+
+  double CallNonvirtualDoubleMethod(
+          JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID) =>
+      value.ref.CallNonvirtualDoubleMethod.asFunction<
+          double Function(
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JClassPtr clazz,
+              JMethodIDPtr methodID)>()(this, obj, clazz, methodID);
+
+  double CallNonvirtualDoubleMethodA(JObjectPtr obj, JClassPtr clazz,
+          JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      value.ref.CallNonvirtualDoubleMethodA.asFunction<
+          double Function(
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JClassPtr clazz,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>()(this, obj, clazz, methodID, args);
+
+  void CallNonvirtualVoidMethod(
+          JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID) =>
+      value.ref.CallNonvirtualVoidMethod.asFunction<
+          void Function(
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JClassPtr clazz,
+              JMethodIDPtr methodID)>()(this, obj, clazz, methodID);
+
+  void CallNonvirtualVoidMethodA(JObjectPtr obj, JClassPtr clazz,
+          JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      value.ref.CallNonvirtualVoidMethodA.asFunction<
+          void Function(
+              ffi.Pointer<JniEnv1> env,
+              JObjectPtr obj,
+              JClassPtr clazz,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>()(this, obj, clazz, methodID, args);
+
+  JFieldIDPtr GetFieldID(JClassPtr clazz, ffi.Pointer<ffi.Char> name,
+          ffi.Pointer<ffi.Char> sig) =>
+      value.ref.GetFieldID.asFunction<
+          JFieldIDPtr Function(
+              ffi.Pointer<JniEnv1> env,
+              JClassPtr clazz,
+              ffi.Pointer<ffi.Char> name,
+              ffi.Pointer<ffi.Char> sig)>()(this, clazz, name, sig);
+
+  JObjectPtr GetObjectField(JObjectPtr obj, JFieldIDPtr fieldID) =>
+      value.ref.GetObjectField.asFunction<
+          JObjectPtr Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JFieldIDPtr fieldID)>()(this, obj, fieldID);
+
+  int GetBooleanField(JObjectPtr obj, JFieldIDPtr fieldID) =>
+      value.ref.GetBooleanField.asFunction<
+          int Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JFieldIDPtr fieldID)>()(this, obj, fieldID);
+
+  int GetByteField(JObjectPtr obj, JFieldIDPtr fieldID) =>
+      value.ref.GetByteField.asFunction<
+          int Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JFieldIDPtr fieldID)>()(this, obj, fieldID);
+
+  int GetCharField(JObjectPtr obj, JFieldIDPtr fieldID) =>
+      value.ref.GetCharField.asFunction<
+          int Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JFieldIDPtr fieldID)>()(this, obj, fieldID);
+
+  int GetShortField(JObjectPtr obj, JFieldIDPtr fieldID) =>
+      value.ref.GetShortField.asFunction<
+          int Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JFieldIDPtr fieldID)>()(this, obj, fieldID);
+
+  int GetIntField(JObjectPtr obj, JFieldIDPtr fieldID) =>
+      value.ref.GetIntField.asFunction<
+          int Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JFieldIDPtr fieldID)>()(this, obj, fieldID);
+
+  int GetLongField(JObjectPtr obj, JFieldIDPtr fieldID) =>
+      value.ref.GetLongField.asFunction<
+          int Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JFieldIDPtr fieldID)>()(this, obj, fieldID);
+
+  double GetFloatField(JObjectPtr obj, JFieldIDPtr fieldID) =>
+      value.ref.GetFloatField.asFunction<
+          double Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JFieldIDPtr fieldID)>()(this, obj, fieldID);
+
+  double GetDoubleField(JObjectPtr obj, JFieldIDPtr fieldID) =>
+      value.ref.GetDoubleField.asFunction<
+          double Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JFieldIDPtr fieldID)>()(this, obj, fieldID);
+
+  void SetObjectField(JObjectPtr obj, JFieldIDPtr fieldID, JObjectPtr val) =>
+      value.ref.SetObjectField.asFunction<
+          void Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JFieldIDPtr fieldID, JObjectPtr val)>()(this, obj, fieldID, val);
+
+  void SetBooleanField(JObjectPtr obj, JFieldIDPtr fieldID, int val) =>
+      value.ref.SetBooleanField.asFunction<
+          void Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JFieldIDPtr fieldID, int val)>()(this, obj, fieldID, val);
+
+  void SetByteField(JObjectPtr obj, JFieldIDPtr fieldID, int val) =>
+      value.ref.SetByteField.asFunction<
+          void Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JFieldIDPtr fieldID, int val)>()(this, obj, fieldID, val);
+
+  void SetCharField(JObjectPtr obj, JFieldIDPtr fieldID, int val) =>
+      value.ref.SetCharField.asFunction<
+          void Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JFieldIDPtr fieldID, int val)>()(this, obj, fieldID, val);
+
+  void SetShortField(JObjectPtr obj, JFieldIDPtr fieldID, int val) =>
+      value.ref.SetShortField.asFunction<
+          void Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JFieldIDPtr fieldID, int val)>()(this, obj, fieldID, val);
+
+  void SetIntField(JObjectPtr obj, JFieldIDPtr fieldID, int val) =>
+      value.ref.SetIntField.asFunction<
+          void Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JFieldIDPtr fieldID, int val)>()(this, obj, fieldID, val);
+
+  void SetLongField(JObjectPtr obj, JFieldIDPtr fieldID, int val) =>
+      value.ref.SetLongField.asFunction<
+          void Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JFieldIDPtr fieldID, int val)>()(this, obj, fieldID, val);
+
+  void SetFloatField(JObjectPtr obj, JFieldIDPtr fieldID, double val) =>
+      value.ref.SetFloatField.asFunction<
+          void Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JFieldIDPtr fieldID, double val)>()(this, obj, fieldID, val);
+
+  void SetDoubleField(JObjectPtr obj, JFieldIDPtr fieldID, double val) =>
+      value.ref.SetDoubleField.asFunction<
+          void Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+              JFieldIDPtr fieldID, double val)>()(this, obj, fieldID, val);
+
+  JMethodIDPtr GetStaticMethodID(JClassPtr clazz, ffi.Pointer<ffi.Char> name,
+          ffi.Pointer<ffi.Char> sig) =>
+      value.ref.GetStaticMethodID.asFunction<
+          JMethodIDPtr Function(
+              ffi.Pointer<JniEnv1> env,
+              JClassPtr clazz,
+              ffi.Pointer<ffi.Char> name,
+              ffi.Pointer<ffi.Char> sig)>()(this, clazz, name, sig);
+
+  JObjectPtr CallStaticObjectMethod(JClassPtr clazz, JMethodIDPtr methodID) =>
+      value.ref.CallStaticObjectMethod.asFunction<
+          JObjectPtr Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JMethodIDPtr methodID)>()(this, clazz, methodID);
+
+  JObjectPtr CallStaticObjectMethodA(
+          JClassPtr clazz, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      value.ref.CallStaticObjectMethodA.asFunction<
+          JObjectPtr Function(
+              ffi.Pointer<JniEnv1> env,
+              JClassPtr clazz,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>()(this, clazz, methodID, args);
+
+  int CallStaticBooleanMethod(JClassPtr clazz, JMethodIDPtr methodID) =>
+      value.ref.CallStaticBooleanMethod.asFunction<
+          int Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JMethodIDPtr methodID)>()(this, clazz, methodID);
+
+  int CallStaticBooleanMethodA(
+          JClassPtr clazz, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      value.ref.CallStaticBooleanMethodA.asFunction<
+          int Function(
+              ffi.Pointer<JniEnv1> env,
+              JClassPtr clazz,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>()(this, clazz, methodID, args);
+
+  int CallStaticByteMethod(JClassPtr clazz, JMethodIDPtr methodID) =>
+      value.ref.CallStaticByteMethod.asFunction<
+          int Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JMethodIDPtr methodID)>()(this, clazz, methodID);
+
+  int CallStaticByteMethodA(
+          JClassPtr clazz, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      value.ref.CallStaticByteMethodA.asFunction<
+          int Function(
+              ffi.Pointer<JniEnv1> env,
+              JClassPtr clazz,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>()(this, clazz, methodID, args);
+
+  int CallStaticCharMethod(JClassPtr clazz, JMethodIDPtr methodID) =>
+      value.ref.CallStaticCharMethod.asFunction<
+          int Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JMethodIDPtr methodID)>()(this, clazz, methodID);
+
+  int CallStaticCharMethodA(
+          JClassPtr clazz, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      value.ref.CallStaticCharMethodA.asFunction<
+          int Function(
+              ffi.Pointer<JniEnv1> env,
+              JClassPtr clazz,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>()(this, clazz, methodID, args);
+
+  int CallStaticShortMethod(JClassPtr clazz, JMethodIDPtr methodID) =>
+      value.ref.CallStaticShortMethod.asFunction<
+          int Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JMethodIDPtr methodID)>()(this, clazz, methodID);
+
+  int CallStaticShortMethodA(
+          JClassPtr clazz, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      value.ref.CallStaticShortMethodA.asFunction<
+          int Function(
+              ffi.Pointer<JniEnv1> env,
+              JClassPtr clazz,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>()(this, clazz, methodID, args);
+
+  int CallStaticIntMethod(JClassPtr clazz, JMethodIDPtr methodID) =>
+      value.ref.CallStaticIntMethod.asFunction<
+          int Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JMethodIDPtr methodID)>()(this, clazz, methodID);
+
+  int CallStaticIntMethodA(
+          JClassPtr clazz, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      value.ref.CallStaticIntMethodA.asFunction<
+          int Function(
+              ffi.Pointer<JniEnv1> env,
+              JClassPtr clazz,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>()(this, clazz, methodID, args);
+
+  int CallStaticLongMethod(JClassPtr clazz, JMethodIDPtr methodID) =>
+      value.ref.CallStaticLongMethod.asFunction<
+          int Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JMethodIDPtr methodID)>()(this, clazz, methodID);
+
+  int CallStaticLongMethodA(
+          JClassPtr clazz, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      value.ref.CallStaticLongMethodA.asFunction<
+          int Function(
+              ffi.Pointer<JniEnv1> env,
+              JClassPtr clazz,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>()(this, clazz, methodID, args);
+
+  double CallStaticFloatMethod(JClassPtr clazz, JMethodIDPtr methodID) =>
+      value.ref.CallStaticFloatMethod.asFunction<
+          double Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JMethodIDPtr methodID)>()(this, clazz, methodID);
+
+  double CallStaticFloatMethodA(
+          JClassPtr clazz, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      value.ref.CallStaticFloatMethodA.asFunction<
+          double Function(
+              ffi.Pointer<JniEnv1> env,
+              JClassPtr clazz,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>()(this, clazz, methodID, args);
+
+  double CallStaticDoubleMethod(JClassPtr clazz, JMethodIDPtr methodID) =>
+      value.ref.CallStaticDoubleMethod.asFunction<
+          double Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JMethodIDPtr methodID)>()(this, clazz, methodID);
+
+  double CallStaticDoubleMethodA(
+          JClassPtr clazz, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      value.ref.CallStaticDoubleMethodA.asFunction<
+          double Function(
+              ffi.Pointer<JniEnv1> env,
+              JClassPtr clazz,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>()(this, clazz, methodID, args);
+
+  void CallStaticVoidMethod(JClassPtr clazz, JMethodIDPtr methodID) =>
+      value.ref.CallStaticVoidMethod.asFunction<
+          void Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JMethodIDPtr methodID)>()(this, clazz, methodID);
+
+  void CallStaticVoidMethodA(
+          JClassPtr clazz, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+      value.ref.CallStaticVoidMethodA.asFunction<
+          void Function(
+              ffi.Pointer<JniEnv1> env,
+              JClassPtr clazz,
+              JMethodIDPtr methodID,
+              ffi.Pointer<JValue> args)>()(this, clazz, methodID, args);
+
+  JFieldIDPtr GetStaticFieldID(JClassPtr clazz, ffi.Pointer<ffi.Char> name,
+          ffi.Pointer<ffi.Char> sig) =>
+      value.ref.GetStaticFieldID.asFunction<
+          JFieldIDPtr Function(
+              ffi.Pointer<JniEnv1> env,
+              JClassPtr clazz,
+              ffi.Pointer<ffi.Char> name,
+              ffi.Pointer<ffi.Char> sig)>()(this, clazz, name, sig);
+
+  JObjectPtr GetStaticObjectField(JClassPtr clazz, JFieldIDPtr fieldID) =>
+      value.ref.GetStaticObjectField.asFunction<
+          JObjectPtr Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JFieldIDPtr fieldID)>()(this, clazz, fieldID);
+
+  int GetStaticBooleanField(JClassPtr clazz, JFieldIDPtr fieldID) =>
+      value.ref.GetStaticBooleanField.asFunction<
+          int Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JFieldIDPtr fieldID)>()(this, clazz, fieldID);
+
+  int GetStaticByteField(JClassPtr clazz, JFieldIDPtr fieldID) =>
+      value.ref.GetStaticByteField.asFunction<
+          int Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JFieldIDPtr fieldID)>()(this, clazz, fieldID);
+
+  int GetStaticCharField(JClassPtr clazz, JFieldIDPtr fieldID) =>
+      value.ref.GetStaticCharField.asFunction<
+          int Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JFieldIDPtr fieldID)>()(this, clazz, fieldID);
+
+  int GetStaticShortField(JClassPtr clazz, JFieldIDPtr fieldID) =>
+      value.ref.GetStaticShortField.asFunction<
+          int Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JFieldIDPtr fieldID)>()(this, clazz, fieldID);
+
+  int GetStaticIntField(JClassPtr clazz, JFieldIDPtr fieldID) =>
+      value.ref.GetStaticIntField.asFunction<
+          int Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JFieldIDPtr fieldID)>()(this, clazz, fieldID);
+
+  int GetStaticLongField(JClassPtr clazz, JFieldIDPtr fieldID) =>
+      value.ref.GetStaticLongField.asFunction<
+          int Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JFieldIDPtr fieldID)>()(this, clazz, fieldID);
+
+  double GetStaticFloatField(JClassPtr clazz, JFieldIDPtr fieldID) =>
+      value.ref.GetStaticFloatField.asFunction<
+          double Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JFieldIDPtr fieldID)>()(this, clazz, fieldID);
+
+  double GetStaticDoubleField(JClassPtr clazz, JFieldIDPtr fieldID) =>
+      value.ref.GetStaticDoubleField.asFunction<
+          double Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JFieldIDPtr fieldID)>()(this, clazz, fieldID);
+
+  void SetStaticObjectField(
+          JClassPtr clazz, JFieldIDPtr fieldID, JObjectPtr val) =>
+      value.ref.SetStaticObjectField.asFunction<
+          void Function(
+              ffi.Pointer<JniEnv1> env,
+              JClassPtr clazz,
+              JFieldIDPtr fieldID,
+              JObjectPtr val)>()(this, clazz, fieldID, val);
+
+  void SetStaticBooleanField(JClassPtr clazz, JFieldIDPtr fieldID, int val) =>
+      value.ref.SetStaticBooleanField.asFunction<
+          void Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JFieldIDPtr fieldID, int val)>()(this, clazz, fieldID, val);
+
+  void SetStaticByteField(JClassPtr clazz, JFieldIDPtr fieldID, int val) =>
+      value.ref.SetStaticByteField.asFunction<
+          void Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JFieldIDPtr fieldID, int val)>()(this, clazz, fieldID, val);
+
+  void SetStaticCharField(JClassPtr clazz, JFieldIDPtr fieldID, int val) =>
+      value.ref.SetStaticCharField.asFunction<
+          void Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JFieldIDPtr fieldID, int val)>()(this, clazz, fieldID, val);
+
+  void SetStaticShortField(JClassPtr clazz, JFieldIDPtr fieldID, int val) =>
+      value.ref.SetStaticShortField.asFunction<
+          void Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JFieldIDPtr fieldID, int val)>()(this, clazz, fieldID, val);
+
+  void SetStaticIntField(JClassPtr clazz, JFieldIDPtr fieldID, int val) =>
+      value.ref.SetStaticIntField.asFunction<
+          void Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JFieldIDPtr fieldID, int val)>()(this, clazz, fieldID, val);
+
+  void SetStaticLongField(JClassPtr clazz, JFieldIDPtr fieldID, int val) =>
+      value.ref.SetStaticLongField.asFunction<
+          void Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JFieldIDPtr fieldID, int val)>()(this, clazz, fieldID, val);
+
+  void SetStaticFloatField(JClassPtr clazz, JFieldIDPtr fieldID, double val) =>
+      value.ref.SetStaticFloatField.asFunction<
+          void Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JFieldIDPtr fieldID, double val)>()(this, clazz, fieldID, val);
+
+  void SetStaticDoubleField(JClassPtr clazz, JFieldIDPtr fieldID, double val) =>
+      value.ref.SetStaticDoubleField.asFunction<
+          void Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+              JFieldIDPtr fieldID, double val)>()(this, clazz, fieldID, val);
+
+  JStringPtr NewString(ffi.Pointer<JCharMarker> unicodeChars, int len) =>
+      value.ref.NewString.asFunction<
+          JStringPtr Function(
+              ffi.Pointer<JniEnv1> env,
+              ffi.Pointer<JCharMarker> unicodeChars,
+              int len)>()(this, unicodeChars, len);
+
+  int GetStringLength(JStringPtr string) =>
+      value.ref.GetStringLength.asFunction<
+          int Function(
+              ffi.Pointer<JniEnv1> env, JStringPtr string)>()(this, string);
+
+  ffi.Pointer<JCharMarker> GetStringChars(
+          JStringPtr string, ffi.Pointer<JBooleanMarker> isCopy) =>
+      value.ref.GetStringChars.asFunction<
+          ffi.Pointer<JCharMarker> Function(
+              ffi.Pointer<JniEnv1> env,
+              JStringPtr string,
+              ffi.Pointer<JBooleanMarker> isCopy)>()(this, string, isCopy);
+
+  void ReleaseStringChars(JStringPtr string, ffi.Pointer<JCharMarker> isCopy) =>
+      value.ref.ReleaseStringChars.asFunction<
+          void Function(ffi.Pointer<JniEnv1> env, JStringPtr string,
+              ffi.Pointer<JCharMarker> isCopy)>()(this, string, isCopy);
+
+  JStringPtr NewStringUTF(ffi.Pointer<ffi.Char> bytes) =>
+      value.ref.NewStringUTF.asFunction<
+          JStringPtr Function(ffi.Pointer<JniEnv1> env,
+              ffi.Pointer<ffi.Char> bytes)>()(this, bytes);
+
+  int GetStringUTFLength(JStringPtr string) =>
+      value.ref.GetStringUTFLength.asFunction<
+          int Function(
+              ffi.Pointer<JniEnv1> env, JStringPtr string)>()(this, string);
+
+  ffi.Pointer<ffi.Char> GetStringUTFChars(
+          JStringPtr string, ffi.Pointer<JBooleanMarker> isCopy) =>
+      value.ref.GetStringUTFChars.asFunction<
+          ffi.Pointer<ffi.Char> Function(
+              ffi.Pointer<JniEnv1> env,
+              JStringPtr string,
+              ffi.Pointer<JBooleanMarker> isCopy)>()(this, string, isCopy);
+
+  void ReleaseStringUTFChars(JStringPtr string, ffi.Pointer<ffi.Char> utf) =>
+      value.ref.ReleaseStringUTFChars.asFunction<
+          void Function(ffi.Pointer<JniEnv1> env, JStringPtr string,
+              ffi.Pointer<ffi.Char> utf)>()(this, string, utf);
+
+  int GetArrayLength(JArrayPtr array) => value.ref.GetArrayLength.asFunction<
+      int Function(ffi.Pointer<JniEnv1> env, JArrayPtr array)>()(this, array);
+
+  JObjectArrayPtr NewObjectArray(
+          int length, JClassPtr elementClass, JObjectPtr initialElement) =>
+      value.ref.NewObjectArray.asFunction<
+              JObjectArrayPtr Function(ffi.Pointer<JniEnv1> env, int length,
+                  JClassPtr elementClass, JObjectPtr initialElement)>()(
+          this, length, elementClass, initialElement);
+
+  JObjectPtr GetObjectArrayElement(JObjectArrayPtr array, int index) =>
+      value.ref.GetObjectArrayElement.asFunction<
+          JObjectPtr Function(ffi.Pointer<JniEnv1> env, JObjectArrayPtr array,
+              int index)>()(this, array, index);
+
+  void SetObjectArrayElement(
+          JObjectArrayPtr array, int index, JObjectPtr val) =>
+      value.ref.SetObjectArrayElement.asFunction<
+          void Function(ffi.Pointer<JniEnv1> env, JObjectArrayPtr array,
+              int index, JObjectPtr val)>()(this, array, index, val);
+
+  JBooleanArrayPtr NewBooleanArray(int length) =>
+      value.ref.NewBooleanArray.asFunction<
+          JBooleanArrayPtr Function(
+              ffi.Pointer<JniEnv1> env, int length)>()(this, length);
+
+  JByteArrayPtr NewByteArray(int length) => value.ref.NewByteArray.asFunction<
+      JByteArrayPtr Function(
+          ffi.Pointer<JniEnv1> env, int length)>()(this, length);
+
+  JCharArrayPtr NewCharArray(int length) => value.ref.NewCharArray.asFunction<
+      JCharArrayPtr Function(
+          ffi.Pointer<JniEnv1> env, int length)>()(this, length);
+
+  JShortArrayPtr NewShortArray(int length) =>
+      value.ref.NewShortArray.asFunction<
+          JShortArrayPtr Function(
+              ffi.Pointer<JniEnv1> env, int length)>()(this, length);
+
+  JIntArrayPtr NewIntArray(int length) => value.ref.NewIntArray.asFunction<
+      JIntArrayPtr Function(
+          ffi.Pointer<JniEnv1> env, int length)>()(this, length);
+
+  JLongArrayPtr NewLongArray(int length) => value.ref.NewLongArray.asFunction<
+      JLongArrayPtr Function(
+          ffi.Pointer<JniEnv1> env, int length)>()(this, length);
+
+  JFloatArrayPtr NewFloatArray(int length) =>
+      value.ref.NewFloatArray.asFunction<
+          JFloatArrayPtr Function(
+              ffi.Pointer<JniEnv1> env, int length)>()(this, length);
+
+  JDoubleArrayPtr NewDoubleArray(int length) => value.ref.NewDoubleArray
+      .asFunction<
+          JDoubleArrayPtr Function(
+              ffi.Pointer<JniEnv1> env, int length)>()(this, length);
+
+  ffi.Pointer<JBooleanMarker> GetBooleanArrayElements(
+          JBooleanArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy) =>
+      value.ref.GetBooleanArrayElements.asFunction<
+          ffi.Pointer<JBooleanMarker> Function(
+              ffi.Pointer<JniEnv1> env,
+              JBooleanArrayPtr array,
+              ffi.Pointer<JBooleanMarker> isCopy)>()(this, array, isCopy);
+
+  ffi.Pointer<JByteMarker> GetByteArrayElements(
+          JByteArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy) =>
+      value.ref.GetByteArrayElements.asFunction<
+          ffi.Pointer<JByteMarker> Function(
+              ffi.Pointer<JniEnv1> env,
+              JByteArrayPtr array,
+              ffi.Pointer<JBooleanMarker> isCopy)>()(this, array, isCopy);
+
+  ffi.Pointer<JCharMarker> GetCharArrayElements(
+          JCharArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy) =>
+      value.ref.GetCharArrayElements.asFunction<
+          ffi.Pointer<JCharMarker> Function(
+              ffi.Pointer<JniEnv1> env,
+              JCharArrayPtr array,
+              ffi.Pointer<JBooleanMarker> isCopy)>()(this, array, isCopy);
+
+  ffi.Pointer<JShortMarker> GetShortArrayElements(
+          JShortArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy) =>
+      value.ref.GetShortArrayElements.asFunction<
+          ffi.Pointer<JShortMarker> Function(
+              ffi.Pointer<JniEnv1> env,
+              JShortArrayPtr array,
+              ffi.Pointer<JBooleanMarker> isCopy)>()(this, array, isCopy);
+
+  ffi.Pointer<JIntMarker> GetIntArrayElements(
+          JIntArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy) =>
+      value.ref.GetIntArrayElements.asFunction<
+          ffi.Pointer<JIntMarker> Function(
+              ffi.Pointer<JniEnv1> env,
+              JIntArrayPtr array,
+              ffi.Pointer<JBooleanMarker> isCopy)>()(this, array, isCopy);
+
+  ffi.Pointer<JLongMarker> GetLongArrayElements(
+          JLongArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy) =>
+      value.ref.GetLongArrayElements.asFunction<
+          ffi.Pointer<JLongMarker> Function(
+              ffi.Pointer<JniEnv1> env,
+              JLongArrayPtr array,
+              ffi.Pointer<JBooleanMarker> isCopy)>()(this, array, isCopy);
+
+  ffi.Pointer<JFloatMarker> GetFloatArrayElements(
+          JFloatArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy) =>
+      value.ref.GetFloatArrayElements.asFunction<
+          ffi.Pointer<JFloatMarker> Function(
+              ffi.Pointer<JniEnv1> env,
+              JFloatArrayPtr array,
+              ffi.Pointer<JBooleanMarker> isCopy)>()(this, array, isCopy);
+
+  ffi.Pointer<JDoubleMarker> GetDoubleArrayElements(
+          JDoubleArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy) =>
+      value.ref.GetDoubleArrayElements.asFunction<
+          ffi.Pointer<JDoubleMarker> Function(
+              ffi.Pointer<JniEnv1> env,
+              JDoubleArrayPtr array,
+              ffi.Pointer<JBooleanMarker> isCopy)>()(this, array, isCopy);
+
+  void ReleaseBooleanArrayElements(JBooleanArrayPtr array,
+          ffi.Pointer<JBooleanMarker> elems, int mode) =>
+      value.ref.ReleaseBooleanArrayElements.asFunction<
+          void Function(
+              ffi.Pointer<JniEnv1> env,
+              JBooleanArrayPtr array,
+              ffi.Pointer<JBooleanMarker> elems,
+              int mode)>()(this, array, elems, mode);
+
+  void ReleaseByteArrayElements(
+          JByteArrayPtr array, ffi.Pointer<JByteMarker> elems, int mode) =>
+      value.ref.ReleaseByteArrayElements.asFunction<
+          void Function(
+              ffi.Pointer<JniEnv1> env,
+              JByteArrayPtr array,
+              ffi.Pointer<JByteMarker> elems,
+              int mode)>()(this, array, elems, mode);
+
+  void ReleaseCharArrayElements(
+          JCharArrayPtr array, ffi.Pointer<JCharMarker> elems, int mode) =>
+      value.ref.ReleaseCharArrayElements.asFunction<
+          void Function(
+              ffi.Pointer<JniEnv1> env,
+              JCharArrayPtr array,
+              ffi.Pointer<JCharMarker> elems,
+              int mode)>()(this, array, elems, mode);
+
+  void ReleaseShortArrayElements(
+          JShortArrayPtr array, ffi.Pointer<JShortMarker> elems, int mode) =>
+      value.ref.ReleaseShortArrayElements.asFunction<
+          void Function(
+              ffi.Pointer<JniEnv1> env,
+              JShortArrayPtr array,
+              ffi.Pointer<JShortMarker> elems,
+              int mode)>()(this, array, elems, mode);
+
+  void ReleaseIntArrayElements(
+          JIntArrayPtr array, ffi.Pointer<JIntMarker> elems, int mode) =>
+      value.ref.ReleaseIntArrayElements.asFunction<
+          void Function(
+              ffi.Pointer<JniEnv1> env,
+              JIntArrayPtr array,
+              ffi.Pointer<JIntMarker> elems,
+              int mode)>()(this, array, elems, mode);
+
+  void ReleaseLongArrayElements(
+          JLongArrayPtr array, ffi.Pointer<JLongMarker> elems, int mode) =>
+      value.ref.ReleaseLongArrayElements.asFunction<
+          void Function(
+              ffi.Pointer<JniEnv1> env,
+              JLongArrayPtr array,
+              ffi.Pointer<JLongMarker> elems,
+              int mode)>()(this, array, elems, mode);
+
+  void ReleaseFloatArrayElements(
+          JFloatArrayPtr array, ffi.Pointer<JFloatMarker> elems, int mode) =>
+      value.ref.ReleaseFloatArrayElements.asFunction<
+          void Function(
+              ffi.Pointer<JniEnv1> env,
+              JFloatArrayPtr array,
+              ffi.Pointer<JFloatMarker> elems,
+              int mode)>()(this, array, elems, mode);
+
+  void ReleaseDoubleArrayElements(
+          JDoubleArrayPtr array, ffi.Pointer<JDoubleMarker> elems, int mode) =>
+      value.ref.ReleaseDoubleArrayElements.asFunction<
+          void Function(
+              ffi.Pointer<JniEnv1> env,
+              JDoubleArrayPtr array,
+              ffi.Pointer<JDoubleMarker> elems,
+              int mode)>()(this, array, elems, mode);
+
+  void GetBooleanArrayRegion(JBooleanArrayPtr array, int start, int len,
+          ffi.Pointer<JBooleanMarker> buf) =>
+      value.ref.GetBooleanArrayRegion.asFunction<
+          void Function(
+              ffi.Pointer<JniEnv1> env,
+              JBooleanArrayPtr array,
+              int start,
+              int len,
+              ffi.Pointer<JBooleanMarker> buf)>()(this, array, start, len, buf);
+
+  void GetByteArrayRegion(JByteArrayPtr array, int start, int len,
+          ffi.Pointer<JByteMarker> buf) =>
+      value.ref.GetByteArrayRegion.asFunction<
+          void Function(
+              ffi.Pointer<JniEnv1> env,
+              JByteArrayPtr array,
+              int start,
+              int len,
+              ffi.Pointer<JByteMarker> buf)>()(this, array, start, len, buf);
+
+  void GetCharArrayRegion(JCharArrayPtr array, int start, int len,
+          ffi.Pointer<JCharMarker> buf) =>
+      value.ref.GetCharArrayRegion.asFunction<
+          void Function(
+              ffi.Pointer<JniEnv1> env,
+              JCharArrayPtr array,
+              int start,
+              int len,
+              ffi.Pointer<JCharMarker> buf)>()(this, array, start, len, buf);
+
+  void GetShortArrayRegion(JShortArrayPtr array, int start, int len,
+          ffi.Pointer<JShortMarker> buf) =>
+      value.ref.GetShortArrayRegion.asFunction<
+          void Function(
+              ffi.Pointer<JniEnv1> env,
+              JShortArrayPtr array,
+              int start,
+              int len,
+              ffi.Pointer<JShortMarker> buf)>()(this, array, start, len, buf);
+
+  void GetIntArrayRegion(JIntArrayPtr array, int start, int len,
+          ffi.Pointer<JIntMarker> buf) =>
+      value.ref.GetIntArrayRegion.asFunction<
+          void Function(
+              ffi.Pointer<JniEnv1> env,
+              JIntArrayPtr array,
+              int start,
+              int len,
+              ffi.Pointer<JIntMarker> buf)>()(this, array, start, len, buf);
+
+  void GetLongArrayRegion(JLongArrayPtr array, int start, int len,
+          ffi.Pointer<JLongMarker> buf) =>
+      value.ref.GetLongArrayRegion.asFunction<
+          void Function(
+              ffi.Pointer<JniEnv1> env,
+              JLongArrayPtr array,
+              int start,
+              int len,
+              ffi.Pointer<JLongMarker> buf)>()(this, array, start, len, buf);
+
+  void GetFloatArrayRegion(JFloatArrayPtr array, int start, int len,
+          ffi.Pointer<JFloatMarker> buf) =>
+      value.ref.GetFloatArrayRegion.asFunction<
+          void Function(
+              ffi.Pointer<JniEnv1> env,
+              JFloatArrayPtr array,
+              int start,
+              int len,
+              ffi.Pointer<JFloatMarker> buf)>()(this, array, start, len, buf);
+
+  void GetDoubleArrayRegion(JDoubleArrayPtr array, int start, int len,
+          ffi.Pointer<JDoubleMarker> buf) =>
+      value.ref.GetDoubleArrayRegion.asFunction<
+          void Function(
+              ffi.Pointer<JniEnv1> env,
+              JDoubleArrayPtr array,
+              int start,
+              int len,
+              ffi.Pointer<JDoubleMarker> buf)>()(this, array, start, len, buf);
+
+  void SetBooleanArrayRegion(JBooleanArrayPtr array, int start, int len,
+          ffi.Pointer<JBooleanMarker> buf) =>
+      value.ref.SetBooleanArrayRegion.asFunction<
+          void Function(
+              ffi.Pointer<JniEnv1> env,
+              JBooleanArrayPtr array,
+              int start,
+              int len,
+              ffi.Pointer<JBooleanMarker> buf)>()(this, array, start, len, buf);
+
+  void SetByteArrayRegion(JByteArrayPtr array, int start, int len,
+          ffi.Pointer<JByteMarker> buf) =>
+      value.ref.SetByteArrayRegion.asFunction<
+          void Function(
+              ffi.Pointer<JniEnv1> env,
+              JByteArrayPtr array,
+              int start,
+              int len,
+              ffi.Pointer<JByteMarker> buf)>()(this, array, start, len, buf);
+
+  void SetCharArrayRegion(JCharArrayPtr array, int start, int len,
+          ffi.Pointer<JCharMarker> buf) =>
+      value.ref.SetCharArrayRegion.asFunction<
+          void Function(
+              ffi.Pointer<JniEnv1> env,
+              JCharArrayPtr array,
+              int start,
+              int len,
+              ffi.Pointer<JCharMarker> buf)>()(this, array, start, len, buf);
+
+  void SetShortArrayRegion(JShortArrayPtr array, int start, int len,
+          ffi.Pointer<JShortMarker> buf) =>
+      value.ref.SetShortArrayRegion.asFunction<
+          void Function(
+              ffi.Pointer<JniEnv1> env,
+              JShortArrayPtr array,
+              int start,
+              int len,
+              ffi.Pointer<JShortMarker> buf)>()(this, array, start, len, buf);
+
+  void SetIntArrayRegion(JIntArrayPtr array, int start, int len,
+          ffi.Pointer<JIntMarker> buf) =>
+      value.ref.SetIntArrayRegion.asFunction<
+          void Function(
+              ffi.Pointer<JniEnv1> env,
+              JIntArrayPtr array,
+              int start,
+              int len,
+              ffi.Pointer<JIntMarker> buf)>()(this, array, start, len, buf);
+
+  void SetLongArrayRegion(JLongArrayPtr array, int start, int len,
+          ffi.Pointer<JLongMarker> buf) =>
+      value.ref.SetLongArrayRegion.asFunction<
+          void Function(
+              ffi.Pointer<JniEnv1> env,
+              JLongArrayPtr array,
+              int start,
+              int len,
+              ffi.Pointer<JLongMarker> buf)>()(this, array, start, len, buf);
+
+  void SetFloatArrayRegion(JFloatArrayPtr array, int start, int len,
+          ffi.Pointer<JFloatMarker> buf) =>
+      value.ref.SetFloatArrayRegion.asFunction<
+          void Function(
+              ffi.Pointer<JniEnv1> env,
+              JFloatArrayPtr array,
+              int start,
+              int len,
+              ffi.Pointer<JFloatMarker> buf)>()(this, array, start, len, buf);
+
+  void SetDoubleArrayRegion(JDoubleArrayPtr array, int start, int len,
+          ffi.Pointer<JDoubleMarker> buf) =>
+      value.ref.SetDoubleArrayRegion.asFunction<
+          void Function(
+              ffi.Pointer<JniEnv1> env,
+              JDoubleArrayPtr array,
+              int start,
+              int len,
+              ffi.Pointer<JDoubleMarker> buf)>()(this, array, start, len, buf);
+
+  int RegisterNatives(JClassPtr clazz, ffi.Pointer<JNINativeMethod> methods,
+          int nMethods) =>
+      value.ref.RegisterNatives.asFunction<
+          int Function(
+              ffi.Pointer<JniEnv1> env,
+              JClassPtr clazz,
+              ffi.Pointer<JNINativeMethod> methods,
+              int nMethods)>()(this, clazz, methods, nMethods);
+
+  int UnregisterNatives(JClassPtr clazz) =>
+      value.ref.UnregisterNatives.asFunction<
+          int Function(
+              ffi.Pointer<JniEnv1> env, JClassPtr clazz)>()(this, clazz);
+
+  int MonitorEnter(JObjectPtr obj) => value.ref.MonitorEnter
+          .asFunction<int Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj)>()(
+      this, obj);
+
+  int MonitorExit(JObjectPtr obj) => value.ref.MonitorExit
+          .asFunction<int Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj)>()(
+      this, obj);
+
+  int GetJavaVM(ffi.Pointer<ffi.Pointer<JavaVM1>> vm) =>
+      value.ref.GetJavaVM.asFunction<
+          int Function(ffi.Pointer<JniEnv1> env,
+              ffi.Pointer<ffi.Pointer<JavaVM1>> vm)>()(this, vm);
+
+  void GetStringRegion(
+          JStringPtr str, int start, int len, ffi.Pointer<JCharMarker> buf) =>
+      value.ref.GetStringRegion.asFunction<
+          void Function(
+              ffi.Pointer<JniEnv1> env,
+              JStringPtr str,
+              int start,
+              int len,
+              ffi.Pointer<JCharMarker> buf)>()(this, str, start, len, buf);
+
+  void GetStringUTFRegion(
+          JStringPtr str, int start, int len, ffi.Pointer<ffi.Char> buf) =>
+      value.ref.GetStringUTFRegion.asFunction<
+          void Function(
+              ffi.Pointer<JniEnv1> env,
+              JStringPtr str,
+              int start,
+              int len,
+              ffi.Pointer<ffi.Char> buf)>()(this, str, start, len, buf);
+
+  ffi.Pointer<ffi.Void> GetPrimitiveArrayCritical(
+          JArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy) =>
+      value.ref.GetPrimitiveArrayCritical.asFunction<
+          ffi.Pointer<ffi.Void> Function(
+              ffi.Pointer<JniEnv1> env,
+              JArrayPtr array,
+              ffi.Pointer<JBooleanMarker> isCopy)>()(this, array, isCopy);
+
+  void ReleasePrimitiveArrayCritical(
+          JArrayPtr array, ffi.Pointer<ffi.Void> carray, int mode) =>
+      value.ref.ReleasePrimitiveArrayCritical.asFunction<
+          void Function(
+              ffi.Pointer<JniEnv1> env,
+              JArrayPtr array,
+              ffi.Pointer<ffi.Void> carray,
+              int mode)>()(this, array, carray, mode);
+
+  ffi.Pointer<JCharMarker> GetStringCritical(
+          JStringPtr str, ffi.Pointer<JBooleanMarker> isCopy) =>
+      value.ref.GetStringCritical.asFunction<
+          ffi.Pointer<JCharMarker> Function(
+              ffi.Pointer<JniEnv1> env,
+              JStringPtr str,
+              ffi.Pointer<JBooleanMarker> isCopy)>()(this, str, isCopy);
+
+  void ReleaseStringCritical(JStringPtr str, ffi.Pointer<JCharMarker> carray) =>
+      value.ref.ReleaseStringCritical.asFunction<
+          void Function(ffi.Pointer<JniEnv1> env, JStringPtr str,
+              ffi.Pointer<JCharMarker> carray)>()(this, str, carray);
+
+  JWeakPtr NewWeakGlobalRef(JObjectPtr obj) =>
+      value.ref.NewWeakGlobalRef.asFunction<
+          JWeakPtr Function(
+              ffi.Pointer<JniEnv1> env, JObjectPtr obj)>()(this, obj);
+
+  void DeleteWeakGlobalRef(JWeakPtr obj) => value.ref.DeleteWeakGlobalRef
+          .asFunction<void Function(ffi.Pointer<JniEnv1> env, JWeakPtr obj)>()(
+      this, obj);
+
+  int ExceptionCheck() => value.ref.ExceptionCheck
+      .asFunction<int Function(ffi.Pointer<JniEnv1> env)>()(this);
+
+  JObjectPtr NewDirectByteBuffer(ffi.Pointer<ffi.Void> address, int capacity) =>
+      value.ref.NewDirectByteBuffer.asFunction<
+          JObjectPtr Function(
+              ffi.Pointer<JniEnv1> env,
+              ffi.Pointer<ffi.Void> address,
+              int capacity)>()(this, address, capacity);
+
+  ffi.Pointer<ffi.Void> GetDirectBufferAddress(JObjectPtr buf) =>
+      value.ref.GetDirectBufferAddress.asFunction<
+          ffi.Pointer<ffi.Void> Function(
+              ffi.Pointer<JniEnv1> env, JObjectPtr buf)>()(this, buf);
+
+  int GetDirectBufferCapacity(JObjectPtr buf) => value
+          .ref.GetDirectBufferCapacity
+          .asFunction<int Function(ffi.Pointer<JniEnv1> env, JObjectPtr buf)>()(
+      this, buf);
+
+  int GetObjectRefType(JObjectPtr obj) => value.ref.GetObjectRefType
+          .asFunction<int Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj)>()(
+      this, obj);
+}
+
+extension JavaVMExtension on ffi.Pointer<JavaVM> {
+  int DestroyJavaVM() => value.ref.DestroyJavaVM
+      .asFunction<int Function(ffi.Pointer<JavaVM1> vm)>()(this);
+
+  int AttachCurrentThread(ffi.Pointer<ffi.Pointer<JniEnv>> p_env,
+          ffi.Pointer<ffi.Void> thr_args) =>
+      value.ref.AttachCurrentThread.asFunction<
+          int Function(
+              ffi.Pointer<JavaVM1> vm,
+              ffi.Pointer<ffi.Pointer<JniEnv>> p_env,
+              ffi.Pointer<ffi.Void> thr_args)>()(this, p_env, thr_args);
+
+  int DetachCurrentThread() => value.ref.DetachCurrentThread
+      .asFunction<int Function(ffi.Pointer<JavaVM1> vm)>()(this);
+
+  int GetEnv(ffi.Pointer<ffi.Pointer<ffi.Void>> p_env, int version) =>
+      value.ref.GetEnv.asFunction<
+          int Function(
+              ffi.Pointer<JavaVM1> vm,
+              ffi.Pointer<ffi.Pointer<ffi.Void>> p_env,
+              int version)>()(this, p_env, version);
+
+  int AttachCurrentThreadAsDaemon(ffi.Pointer<ffi.Pointer<JniEnv>> p_env,
+          ffi.Pointer<ffi.Void> thr_args) =>
+      value.ref.AttachCurrentThreadAsDaemon.asFunction<
+          int Function(
+              ffi.Pointer<JavaVM1> vm,
+              ffi.Pointer<ffi.Pointer<JniEnv>> p_env,
+              ffi.Pointer<ffi.Void> thr_args)>()(this, p_env, thr_args);
+}
diff --git a/pkgs/jni/lib/src/types.dart b/pkgs/jni/lib/src/types.dart
index 9c0cb49..cc2dbec 100644
--- a/pkgs/jni/lib/src/types.dart
+++ b/pkgs/jni/lib/src/types.dart
@@ -10,7 +10,7 @@
 import 'accessors.dart';
 import 'jni.dart';
 import 'jvalues.dart';
-import 'third_party/jni_bindings_generated.dart';
+import 'third_party/generated_bindings.dart';
 
 part 'jarray.dart';
 part 'jexceptions.dart';
@@ -47,11 +47,11 @@
   /// Creates an object from this type using the reference.
   T fromRef(Pointer<Void> ref);
 
-  JniClass getClass() {
+  JClass getClass() {
     if (signature.startsWith('L') && signature.endsWith(';')) {
-      return Jni.findJniClass(signature.substring(1, signature.length - 1));
+      return Jni.findJClass(signature.substring(1, signature.length - 1));
     }
-    return Jni.findJniClass(signature);
+    return Jni.findJClass(signature);
   }
 }
 
diff --git a/pkgs/jni/pubspec.yaml b/pkgs/jni/pubspec.yaml
index 40aa26c..e0a3771 100644
--- a/pkgs/jni/pubspec.yaml
+++ b/pkgs/jni/pubspec.yaml
@@ -4,24 +4,23 @@
 repository: https://github.com/dart-lang/jnigen/tree/main/jni
 
 environment:
-  sdk: ">=2.17.1 <4.0.0"
-  flutter: ">=2.11.0"
+  sdk: '>=2.17.1 <4.0.0'
+  flutter: '>=2.11.0'
 
 dependencies:
   collection: ^1.0.0
   plugin_platform_interface: ^2.0.2
-  ffi: ^2.0.0
+  ffi: ^2.0.1
   path: ^1.8.0
   package_config: ^2.1.0
   args: ^2.3.1
 
 dev_dependencies:
-  ## After running `dart run ffigen --config ffigen.yaml` there
-  ## should be no changes.
-  ffigen:
-    path: third_party/ffigen_patch_jni
+  ## Pin ffigen version because we are depending on internal APIs.
+  ffigen: 7.2.10
   flutter_lints: ^2.0.0
   test: ^1.21.1
+  logging: ^1.1.1
 
 # The following section is specific to Flutter packages.
 flutter:
@@ -37,4 +36,3 @@
         ffiPlugin: true
         package: com.github.dart_lang.jni
         pluginClass: JniPlugin
-
diff --git a/pkgs/jni/src/dartjni.c b/pkgs/jni/src/dartjni.c
index 6ef1dcf..74c4a11 100644
--- a/pkgs/jni/src/dartjni.c
+++ b/pkgs/jni/src/dartjni.c
@@ -10,6 +10,12 @@
 
 #include "include/dart_api_dl.h"
 
+void initAllLocks(JniLocks* locks) {
+  init_lock(&locks->classLoadingLock);
+  init_lock(&locks->fieldLoadingLock);
+  init_lock(&locks->methodLoadingLock);
+}
+
 /// Stores class and method references for obtaining exception details
 typedef struct JniExceptionMethods {
   jclass objectClass, exceptionClass, printStreamClass;
@@ -19,18 +25,26 @@
 } JniExceptionMethods;
 
 // Context and shared global state. Initialized once or if thread-local, initialized once in a thread.
-JniContext jni = {NULL, NULL, NULL, NULL, NULL};
+JniContext jni_context = {
+    .jvm = NULL,
+    .classLoader = NULL,
+    .loadClassMethod = NULL,
+    .appContext = NULL,
+    .currentActivity = NULL,
+};
+
+JniContext* jni = &jni_context;
 
 thread_local JNIEnv* jniEnv = NULL;
 
 JniExceptionMethods exceptionMethods;
 
-void initializeExceptionMethods(JniExceptionMethods* methods) {
-  methods->objectClass = LoadClass("java/lang/Object");
-  methods->exceptionClass = LoadClass("java/lang/Exception");
-  methods->printStreamClass = LoadClass("java/io/PrintStream");
+void initExceptionHandling(JniExceptionMethods* methods) {
+  methods->objectClass = FindClass("java/lang/Object");
+  methods->exceptionClass = FindClass("java/lang/Exception");
+  methods->printStreamClass = FindClass("java/io/PrintStream");
   methods->byteArrayOutputStreamClass =
-      LoadClass("java/io/ByteArrayOutputStream");
+      FindClass("java/io/ByteArrayOutputStream");
   load_method(methods->objectClass, &methods->toStringMethod, "toString",
               "()Ljava/lang/String;");
   load_method(methods->exceptionClass, &methods->printStackTraceMethod,
@@ -45,47 +59,35 @@
 /// Returns NULL if no JVM is running.
 FFI_PLUGIN_EXPORT
 JavaVM* GetJavaVM() {
-  return jni.jvm;
+  return jni_context.jvm;
 }
 
-/// Load class through platform-specific mechanism.
-///
-/// Currently uses application classloader on android,
-/// and JNIEnv->FindClass on other platforms.
 FFI_PLUGIN_EXPORT
-jclass LoadClass(const char* name) {
+jclass FindClass(const char* name) {
   jclass cls = NULL;
   attach_thread();
-  load_class(&cls, name);
-  return to_global_ref(cls);
+  load_class_global_ref(&cls, name);
+  return cls;
 };
 
 // Android specifics
 
-/// Returns Application classLoader (on Android),
-/// which can be used to load application and platform classes.
-/// ...
-/// On other platforms, NULL is returned.
 FFI_PLUGIN_EXPORT
 jobject GetClassLoader() {
   attach_thread();
-  return (*jniEnv)->NewGlobalRef(jniEnv, jni.classLoader);
+  return (*jniEnv)->NewGlobalRef(jniEnv, jni_context.classLoader);
 }
 
-/// Returns application context on Android.
-///
-/// On other platforms, NULL is returned.
 FFI_PLUGIN_EXPORT
 jobject GetApplicationContext() {
   attach_thread();
-  return (*jniEnv)->NewGlobalRef(jniEnv, jni.appContext);
+  return (*jniEnv)->NewGlobalRef(jniEnv, jni_context.appContext);
 }
 
-/// Returns current activity of the app
 FFI_PLUGIN_EXPORT
 jobject GetCurrentActivity() {
   attach_thread();
-  return (*jniEnv)->NewGlobalRef(jniEnv, jni.currentActivity);
+  return (*jniEnv)->NewGlobalRef(jniEnv, jni_context.currentActivity);
 }
 
 // JNI Initialization
@@ -97,14 +99,15 @@
                                                        jobject appContext,
                                                        jobject classLoader) {
   jniEnv = env;
-  (*env)->GetJavaVM(env, &jni.jvm);
-  jni.classLoader = (*env)->NewGlobalRef(env, classLoader);
-  jni.appContext = (*env)->NewGlobalRef(env, appContext);
+  (*env)->GetJavaVM(env, &jni_context.jvm);
+  jni_context.classLoader = (*env)->NewGlobalRef(env, classLoader);
+  jni_context.appContext = (*env)->NewGlobalRef(env, appContext);
   jclass classLoaderClass = (*env)->GetObjectClass(env, classLoader);
-  jni.loadClassMethod =
+  jni_context.loadClassMethod =
       (*env)->GetMethodID(env, classLoaderClass, "loadClass",
                           "(Ljava/lang/String;)Ljava/lang/Class;");
-  initializeExceptionMethods(&exceptionMethods);
+  initAllLocks(&jni_context.locks);
+  initExceptionHandling(&exceptionMethods);
 }
 
 JNIEXPORT void JNICALL
@@ -113,21 +116,24 @@
                                                         jobject activity,
                                                         jobject context) {
   jniEnv = env;
-  if (jni.currentActivity != NULL) {
-    (*env)->DeleteGlobalRef(env, jni.currentActivity);
+  if (jni_context.currentActivity != NULL) {
+    (*env)->DeleteGlobalRef(env, jni_context.currentActivity);
   }
-  jni.currentActivity = (*env)->NewGlobalRef(env, activity);
-  if (jni.appContext != NULL) {
-    (*env)->DeleteGlobalRef(env, jni.appContext);
+  jni_context.currentActivity = (*env)->NewGlobalRef(env, activity);
+  if (jni_context.appContext != NULL) {
+    (*env)->DeleteGlobalRef(env, jni_context.appContext);
   }
-  jni.appContext = (*env)->NewGlobalRef(env, context);
+  jni_context.appContext = (*env)->NewGlobalRef(env, context);
 }
 
 // Sometimes you may get linker error trying to link JNI_CreateJavaVM APIs
 // on Android NDK. So IFDEF is required.
 #else
 FFI_PLUGIN_EXPORT
-JNIEnv* SpawnJvm(JavaVMInitArgs* initArgs) {
+int SpawnJvm(JavaVMInitArgs* initArgs) {
+  if (jni_context.jvm != NULL) {
+    return DART_JNI_SINGLETON_EXISTS;
+  }
   JavaVMOption jvmopt[1];
   char class_path[] = "-Djava.class.path=.";
   jvmopt[0].optionString = class_path;
@@ -139,12 +145,14 @@
     vmArgs.ignoreUnrecognized = JNI_TRUE;
     initArgs = &vmArgs;
   }
-  const long flag = JNI_CreateJavaVM(&jni.jvm, __ENVP_CAST & jniEnv, initArgs);
-  if (flag == JNI_ERR) {
-    return NULL;
+  const long flag =
+      JNI_CreateJavaVM(&jni_context.jvm, __ENVP_CAST & jniEnv, initArgs);
+  if (flag != JNI_OK) {
+    return flag;
   }
-  initializeExceptionMethods(&exceptionMethods);
-  return jniEnv;
+  initAllLocks(&jni_context.locks);
+  initExceptionHandling(&exceptionMethods);
+  return JNI_OK;
 }
 #endif
 
@@ -153,37 +161,41 @@
 
 JniClassLookupResult getClass(char* internalName) {
   JniClassLookupResult result = {NULL, NULL};
-  result.classRef = LoadClass(internalName);
+  result.value = FindClass(internalName);
   result.exception = check_exception();
   return result;
 }
 
-static inline JniPointerResult _getId(
-    void* (*getter)(JNIEnv*, jclass, char*, char*),
-    jclass cls,
-    char* name,
-    char* sig) {
+typedef void* (*MemberGetter)(JNIEnv* env,
+                              jclass* clazz,
+                              char* name,
+                              char* sig);
+
+static inline JniPointerResult _getId(MemberGetter getter,
+                                      jclass cls,
+                                      char* name,
+                                      char* sig) {
   JniPointerResult result = {NULL, NULL};
   attach_thread();
-  result.id = getter(jniEnv, cls, name, sig);
+  result.value = getter(jniEnv, cls, name, sig);
   result.exception = check_exception();
   return result;
 }
 
 JniPointerResult getMethodID(jclass cls, char* name, char* sig) {
-  return _getId((*jniEnv)->GetMethodID, cls, name, sig);
+  return _getId((MemberGetter)(*jniEnv)->GetMethodID, cls, name, sig);
 }
 
 JniPointerResult getStaticMethodID(jclass cls, char* name, char* sig) {
-  return _getId((*jniEnv)->GetStaticMethodID, cls, name, sig);
+  return _getId((MemberGetter)(*jniEnv)->GetStaticMethodID, cls, name, sig);
 }
 
 JniPointerResult getFieldID(jclass cls, char* name, char* sig) {
-  return _getId((*jniEnv)->GetFieldID, cls, name, sig);
+  return _getId((MemberGetter)(*jniEnv)->GetFieldID, cls, name, sig);
 }
 
 JniPointerResult getStaticFieldID(jclass cls, char* name, char* sig) {
-  return _getId((*jniEnv)->GetStaticFieldID, cls, name, sig);
+  return _getId((MemberGetter)(*jniEnv)->GetStaticFieldID, cls, name, sig);
 }
 
 JniResult callMethod(jobject obj,
@@ -225,7 +237,7 @@
       (*jniEnv)->CallVoidMethodA(jniEnv, obj, fieldID, args);
       break;
   }
-  JniResult jniResult = {.result = result, .exception = NULL};
+  JniResult jniResult = {.value = result, .exception = NULL};
   jniResult.exception = check_exception();
   return jniResult;
 }
@@ -272,7 +284,7 @@
       (*jniEnv)->CallStaticVoidMethodA(jniEnv, cls, methodID, args);
       break;
   }
-  JniResult jniResult = {.result = result, .exception = NULL};
+  JniResult jniResult = {.value = result, .exception = NULL};
   jniResult.exception = check_exception();
   return jniResult;
 }
@@ -312,7 +324,7 @@
       // This error should have been handled in Dart.
       break;
   }
-  JniResult jniResult = {.result = result, .exception = NULL};
+  JniResult jniResult = {.value = result, .exception = NULL};
   jniResult.exception = check_exception();
   return jniResult;
 }
@@ -356,7 +368,7 @@
       // or throw exception in Dart using Dart's C API.
       break;
   }
-  JniResult jniResult = {.result = result, .exception = NULL};
+  JniResult jniResult = {.value = result, .exception = NULL};
   jniResult.exception = check_exception();
   return jniResult;
 }
@@ -364,7 +376,7 @@
 JniResult newObject(jclass cls, jmethodID ctor, jvalue* args) {
   attach_thread();
   JniResult jniResult;
-  jniResult.result.l =
+  jniResult.value.l =
       to_global_ref((*jniEnv)->NewObjectA(jniEnv, cls, ctor, args));
   jniResult.exception = check_exception();
   return jniResult;
@@ -405,7 +417,8 @@
       // or throw exception in Dart using Dart's C API.
       break;
   }
-  JniPointerResult result = {.id = to_global_ref(pointer), .exception = NULL};
+  JniPointerResult result = {.value = to_global_ref(pointer),
+                             .exception = NULL};
   result.exception = check_exception();
   return result;
 }
@@ -416,13 +429,13 @@
   attach_thread();
   jarray array = to_global_ref(
       (*jniEnv)->NewObjectArray(jniEnv, length, elementClass, initialElement));
-  JniPointerResult result = {.id = array, .exception = NULL};
+  JniPointerResult result = {.value = array, .exception = NULL};
   result.exception = check_exception();
   return result;
 }
 
 JniResult getArrayElement(jarray array, int index, int type) {
-  JniResult result = {NULL, NULL};
+  JniResult result = {{.l = NULL}, NULL};
   attach_thread();
   jvalue value;
   switch (type) {
@@ -459,7 +472,7 @@
       // or throw exception in Dart using Dart's C API.
       break;
   }
-  result.result = value;
+  result.value = value;
   result.exception = check_exception();
   return result;
 }
@@ -505,12 +518,12 @@
 }
 
 // These will not be required after migrating to Dart-only bindings.
-FFI_PLUGIN_EXPORT JniContext GetJniContext() {
+FFI_PLUGIN_EXPORT JniContext* GetJniContextPtr() {
   return jni;
 }
 
 FFI_PLUGIN_EXPORT JNIEnv* GetJniEnv() {
-  if (jni.jvm == NULL) {
+  if (jni_context.jvm == NULL) {
     return NULL;
   }
   attach_thread();
@@ -538,16 +551,16 @@
 jmethodID _m_PortContinuation__ctor = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PortContinuation__ctor(int64_t j) {
-  load_class_gr(&_c_PortContinuation,
-                "com/github/dart_lang/jni/PortContinuation");
+  load_class_global_ref(&_c_PortContinuation,
+                        "com/github/dart_lang/jni/PortContinuation");
   if (_c_PortContinuation == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PortContinuation, &_m_PortContinuation__ctor, "<init>",
               "(J)V");
   if (_m_PortContinuation__ctor == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->NewObject(jniEnv, _c_PortContinuation,
                                          _m_PortContinuation__ctor, j);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
diff --git a/pkgs/jni/src/dartjni.h b/pkgs/jni/src/dartjni.h
index 39b70bd..eb73318 100644
--- a/pkgs/jni/src/dartjni.h
+++ b/pkgs/jni/src/dartjni.h
@@ -39,6 +39,66 @@
 #define __ENVP_CAST (void**)
 #endif
 
+/// Locking functions for windows and pthread.
+
+#if defined _WIN32
+#include <windows.h>
+
+typedef CRITICAL_SECTION MutexLock;
+
+static inline void init_lock(MutexLock* lock) {
+  InitializeCriticalSection(lock);
+}
+
+static inline void acquire_lock(MutexLock* lock) {
+  EnterCriticalSection(lock);
+}
+
+static inline void release_lock(MutexLock* lock) {
+  LeaveCriticalSection(lock);
+}
+
+static inline void _destroyLock(MutexLock* lock) {
+  DeleteCriticalSection(lock);
+}
+
+#elif defined __DARWIN__ || defined __LINUX__ || defined __ANDROID__ ||        \
+    defined __GNUC__
+#include <pthread.h>
+
+typedef pthread_mutex_t MutexLock;
+
+static inline void init_lock(MutexLock* lock) {
+  pthread_mutex_init(lock, NULL);
+}
+
+static inline void acquire_lock(MutexLock* lock) {
+  pthread_mutex_lock(lock);
+}
+
+static inline void release_lock(MutexLock* lock) {
+  pthread_mutex_unlock(lock);
+}
+
+static inline void _destroyLock(MutexLock* lock) {
+  pthread_mutex_destroy(lock);
+}
+
+#else
+
+#error "No locking support; Possibly unsupported platform"
+
+#endif
+
+typedef struct JniLocks {
+  MutexLock classLoadingLock;
+  MutexLock methodLoadingLock;
+  MutexLock fieldLoadingLock;
+} JniLocks;
+
+/// Represents the error when dart-jni layer has already spawned singleton VM.
+#define DART_JNI_SINGLETON_EXISTS (-99);
+
 /// Stores the global state of the JNI.
 typedef struct JniContext {
   JavaVM* jvm;
@@ -46,13 +106,14 @@
   jmethodID loadClassMethod;
   jobject currentActivity;
   jobject appContext;
+  JniLocks locks;
 } JniContext;
 
 // jniEnv for this thread, used by inline functions in this header,
 // therefore declared as extern.
 extern thread_local JNIEnv* jniEnv;
 
-extern JniContext jni;
+extern JniContext* jni;
 
 /// Types used by JNI API to distinguish between primitive types.
 enum JniType {
@@ -73,19 +134,19 @@
 /// If [exception] is null, it means the result is valid.
 /// It's assumed that the caller knows the expected type in [result].
 typedef struct JniResult {
-  jvalue result;
+  jvalue value;
   jthrowable exception;
 } JniResult;
 
 /// Similar to [JniResult] but for class lookups.
 typedef struct JniClassLookupResult {
-  jclass classRef;
+  jclass value;
   jthrowable exception;
 } JniClassLookupResult;
 
 /// Similar to [JniResult] but for method/field ID lookups.
 typedef struct JniPointerResult {
-  void* id;
+  const void* value;
   jthrowable exception;
 } JniPointerResult;
 
@@ -139,54 +200,71 @@
 
 FFI_PLUGIN_EXPORT JNIEnv* GetJniEnv(void);
 
-FFI_PLUGIN_EXPORT JNIEnv* SpawnJvm(JavaVMInitArgs* args);
+/// Spawn a JVM with given arguments.
+///
+/// Returns JNI_OK on success, and one of the documented JNI error codes on
+/// failure. It returns DART_JNI_SINGLETON_EXISTS if an attempt to spawn multiple
+/// JVMs is made, even if the underlying API potentially supports multiple VMs.
+FFI_PLUGIN_EXPORT int SpawnJvm(JavaVMInitArgs* args);
 
-FFI_PLUGIN_EXPORT jclass LoadClass(const char* name);
+/// Load class through platform-specific mechanism.
+///
+/// Currently uses application classloader on android,
+/// and JNIEnv->FindClass on other platforms.
+FFI_PLUGIN_EXPORT jclass FindClass(const char* name);
 
+/// Returns Application classLoader (on Android),
+/// which can be used to load application and platform classes.
+///
+/// On other platforms, NULL is returned.
 FFI_PLUGIN_EXPORT jobject GetClassLoader(void);
 
+/// Returns application context on Android.
+///
+/// On other platforms, NULL is returned.
 FFI_PLUGIN_EXPORT jobject GetApplicationContext(void);
 
+/// Returns current activity of the app on Android.
 FFI_PLUGIN_EXPORT jobject GetCurrentActivity(void);
 
-// Migration note: Below inline functions are required by C bindings, but can be moved to dartjni.c
-// once migration to pure dart bindings is complete.
+static inline void attach_thread() {
+  if (jniEnv == NULL) {
+    (*jni->jvm)->AttachCurrentThread(jni->jvm, __ENVP_CAST & jniEnv, NULL);
+  }
+}
 
-// `static inline` because `inline` doesn't work, it may still not
-// inline the function in which case a linker error may be produced.
-//
-// There has to be a better way to do this. Either to force inlining on target
-// platforms, or just leave it as normal function.
-
-static inline void __load_class_into(jclass* cls, const char* name) {
+/// Load class into [cls] using platform specific mechanism
+static inline void load_class_platform(jclass* cls, const char* name) {
 #ifdef __ANDROID__
   jstring className = (*jniEnv)->NewStringUTF(jniEnv, name);
-  *cls = (*jniEnv)->CallObjectMethod(jniEnv, jni.classLoader,
-                                     jni.loadClassMethod, className);
+  *cls = (*jniEnv)->CallObjectMethod(jniEnv, jni->classLoader,
+                                     jni->loadClassMethod, className);
   (*jniEnv)->DeleteLocalRef(jniEnv, className);
 #else
   *cls = (*jniEnv)->FindClass(jniEnv, name);
 #endif
 }
 
-static inline void load_class(jclass* cls, const char* name) {
+static inline void load_class_local_ref(jclass* cls, const char* name) {
   if (*cls == NULL) {
-    __load_class_into(cls, name);
+    acquire_lock(&jni->locks.classLoadingLock);
+    if (*cls == NULL) {
+      load_class_platform(cls, name);
+    }
+    release_lock(&jni->locks.classLoadingLock);
   }
 }
 
-static inline void load_class_gr(jclass* cls, const char* name) {
+static inline void load_class_global_ref(jclass* cls, const char* name) {
   if (*cls == NULL) {
-    jclass tmp;
-    __load_class_into(&tmp, name);
-    *cls = (*jniEnv)->NewGlobalRef(jniEnv, tmp);
-    (*jniEnv)->DeleteLocalRef(jniEnv, tmp);
-  }
-}
-
-static inline void attach_thread() {
-  if (jniEnv == NULL) {
-    (*jni.jvm)->AttachCurrentThread(jni.jvm, __ENVP_CAST & jniEnv, NULL);
+    jclass tmp = NULL;
+    acquire_lock(&jni->locks.classLoadingLock);
+    if (*cls == NULL) {
+      load_class_platform(&tmp, name);
+      *cls = (*jniEnv)->NewGlobalRef(jniEnv, tmp);
+      (*jniEnv)->DeleteLocalRef(jniEnv, tmp);
+    }
+    release_lock(&jni->locks.classLoadingLock);
   }
 }
 
@@ -195,7 +273,11 @@
                                const char* name,
                                const char* sig) {
   if (*res == NULL) {
-    *res = (*jniEnv)->GetMethodID(jniEnv, cls, name, sig);
+    acquire_lock(&jni->locks.methodLoadingLock);
+    if (*res == NULL) {
+      *res = (*jniEnv)->GetMethodID(jniEnv, cls, name, sig);
+    }
+    release_lock(&jni->locks.methodLoadingLock);
   }
 }
 
@@ -204,7 +286,11 @@
                                       const char* name,
                                       const char* sig) {
   if (*res == NULL) {
-    *res = (*jniEnv)->GetStaticMethodID(jniEnv, cls, name, sig);
+    acquire_lock(&jni->locks.methodLoadingLock);
+    if (*res == NULL) {
+      *res = (*jniEnv)->GetStaticMethodID(jniEnv, cls, name, sig);
+    }
+    release_lock(&jni->locks.methodLoadingLock);
   }
 }
 
@@ -213,7 +299,11 @@
                               const char* name,
                               const char* sig) {
   if (*res == NULL) {
-    *res = (*jniEnv)->GetFieldID(jniEnv, cls, name, sig);
+    acquire_lock(&jni->locks.fieldLoadingLock);
+    if (*res == NULL) {
+      *res = (*jniEnv)->GetFieldID(jniEnv, cls, name, sig);
+    }
+    release_lock(&jni->locks.fieldLoadingLock);
   }
 }
 
@@ -222,7 +312,11 @@
                                      const char* name,
                                      const char* sig) {
   if (*res == NULL) {
-    *res = (*jniEnv)->GetStaticFieldID(jniEnv, cls, name, sig);
+    acquire_lock(&jni->locks.fieldLoadingLock);
+    if (*res == NULL) {
+      *res = (*jniEnv)->GetStaticFieldID(jniEnv, cls, name, sig);
+    }
+    release_lock(&jni->locks.fieldLoadingLock);
   }
 }
 
@@ -234,17 +328,18 @@
 
 // These functions are useful for C+Dart bindings, and not required for pure dart bindings.
 
-FFI_PLUGIN_EXPORT JniContext GetJniContext();
+FFI_PLUGIN_EXPORT JniContext* GetJniContextPtr();
+
 /// For use by jni_gen's generated code
 /// don't use these.
 
 // these 2 fn ptr vars will be defined by generated code library
-extern JniContext (*context_getter)(void);
+extern JniContext* (*context_getter)(void);
 extern JNIEnv* (*env_getter)(void);
 
 // this function will be exported by generated code library
 // it will set above 2 variables.
-FFI_PLUGIN_EXPORT void setJniGetters(struct JniContext (*cg)(void),
+FFI_PLUGIN_EXPORT void setJniGetters(struct JniContext* (*cg)(void),
                                      JNIEnv* (*eg)(void));
 
 static inline void load_env() {
diff --git a/pkgs/jni/src/jni_constants.h b/pkgs/jni/src/jni_constants.h
new file mode 100644
index 0000000..8423ca1
--- /dev/null
+++ b/pkgs/jni/src/jni_constants.h
@@ -0,0 +1,31 @@
+// 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.
+
+// This file re-exports some JNI constants as enum, because they are not
+// currently being included when they are in macro form.
+
+enum JniBooleanValues { JNI_FALSE = 0, JNI_TRUE = 1 };
+
+enum JniVersions {
+  JNI_VERSION_1_1 = 0x00010001,
+  JNI_VERSION_1_2 = 0x00010002,
+  JNI_VERSION_1_4 = 0x00010004,
+  JNI_VERSION_1_6 = 0x00010006,
+};
+
+enum JniErrorCode {
+  // Error codes from JNI
+  JNI_OK = 0,         /* no error */
+  JNI_ERR = -1,       /* generic error */
+  JNI_EDETACHED = -2, /* thread detached from the VM */
+  JNI_EVERSION = -3,  /* JNI version error */
+  JNI_ENOMEM = -4,    /* Out of memory */
+  JNI_EEXIST = -5,    /* VM already created */
+  JNI_EINVAL = -6,    /* Invalid argument */
+};
+
+enum JniBufferWriteBack {
+  JNI_COMMIT = 1, /* copy content, do not free buffer */
+  JNI_ABORT = 2,  /* free buffer w/o copying back */
+};
diff --git a/pkgs/jni/src/third_party/global_jni_env.c b/pkgs/jni/src/third_party/global_jni_env.c
index 961f16f..600b585 100644
--- a/pkgs/jni/src/third_party/global_jni_env.c
+++ b/pkgs/jni/src/third_party/global_jni_env.c
@@ -1,1215 +1,2279 @@
-// Generated from an annotated version of jni.h provided in Android NDK.
-// (NDK Version 23.1.7779620)
-// The license for original file is provided below:
+// Auto generated file. Do not edit.
+
+// This is generated from JNI header in Android NDK. License for the same is
+// provided below.
 
 /*
-   * Copyright (C) 2006 The Android Open Source Project
-   *
-   * Licensed under the Apache License, Version 2.0 (the "License");
-   * you may not use this file except in compliance with the License.
-   * You may obtain a copy of the License at
-   *
-   *      http://www.apache.org/licenses/LICENSE-2.0
-   *
-   * Unless required by applicable law or agreed to in writing, software
-   * distributed under the License is distributed on an "AS IS" BASIS,
-   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   * See the License for the specific language governing permissions and
-   * limitations under the License.
-   */
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * JNI specification, as defined by Sun:
+ * http://java.sun.com/javase/6/docs/technotes/guides/jni/spec/jniTOC.html
+ *
+ * Everything here is expected to be VM-neutral.
+ */
 
 #include "global_jni_env.h"
-#include "../dartjni.h"
 
-jint globalEnv_GetVersion() {
+JniResult globalEnv_GetVersion() {
   attach_thread();
-  return (*jniEnv)->GetVersion(jniEnv);
+  jint _result = (*jniEnv)->GetVersion(jniEnv);
+  return (JniResult){.value = {.i = _result}, .exception = NULL};
 }
 
-jclass globalEnv_DefineClass(const char* name,
-                             jobject loader,
-                             const jbyte* buf,
-                             jsize bufLen) {
+JniClassLookupResult globalEnv_DefineClass(char* name,
+                                           jobject loader,
+                                           jbyte* buf,
+                                           jsize bufLen) {
   attach_thread();
-  return to_global_ref(
-      (*jniEnv)->DefineClass(jniEnv, name, loader, buf, bufLen));
+  jclass _result = (*jniEnv)->DefineClass(jniEnv, name, loader, buf, bufLen);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniClassLookupResult){.value = NULL, .exception = _exception};
+  }
+  _result = to_global_ref(_result);
+  return (JniClassLookupResult){.value = _result, .exception = NULL};
 }
 
-jclass globalEnv_FindClass(const char* name) {
+JniClassLookupResult globalEnv_FindClass(char* name) {
   attach_thread();
-  return to_global_ref((*jniEnv)->FindClass(jniEnv, name));
+  jclass _result = (*jniEnv)->FindClass(jniEnv, name);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniClassLookupResult){.value = NULL, .exception = _exception};
+  }
+  _result = to_global_ref(_result);
+  return (JniClassLookupResult){.value = _result, .exception = NULL};
 }
 
-jmethodID globalEnv_FromReflectedMethod(jobject method) {
+JniPointerResult globalEnv_FromReflectedMethod(jobject method) {
   attach_thread();
-  return (*jniEnv)->FromReflectedMethod(jniEnv, method);
+  jmethodID _result = (*jniEnv)->FromReflectedMethod(jniEnv, method);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniPointerResult){.value = NULL, .exception = _exception};
+  }
+  return (JniPointerResult){.value = _result, .exception = NULL};
 }
 
-jfieldID globalEnv_FromReflectedField(jobject field) {
+JniPointerResult globalEnv_FromReflectedField(jobject field) {
   attach_thread();
-  return (*jniEnv)->FromReflectedField(jniEnv, field);
+  jfieldID _result = (*jniEnv)->FromReflectedField(jniEnv, field);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniPointerResult){.value = NULL, .exception = _exception};
+  }
+  return (JniPointerResult){.value = _result, .exception = NULL};
 }
 
-jobject globalEnv_ToReflectedMethod(jclass cls,
-                                    jmethodID methodId,
-                                    jboolean isStatic) {
+JniResult globalEnv_ToReflectedMethod(jclass cls,
+                                      jmethodID methodId,
+                                      jboolean isStatic) {
   attach_thread();
-  return to_global_ref(
-      (*jniEnv)->ToReflectedMethod(jniEnv, cls, methodId, isStatic));
+  jobject _result =
+      (*jniEnv)->ToReflectedMethod(jniEnv, cls, methodId, isStatic);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  _result = to_global_ref(_result);
+  return (JniResult){.value = {.l = _result}, .exception = NULL};
 }
 
-jclass globalEnv_GetSuperclass(jclass clazz) {
+JniClassLookupResult globalEnv_GetSuperclass(jclass clazz) {
   attach_thread();
-  return to_global_ref((*jniEnv)->GetSuperclass(jniEnv, clazz));
+  jclass _result = (*jniEnv)->GetSuperclass(jniEnv, clazz);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniClassLookupResult){.value = NULL, .exception = _exception};
+  }
+  _result = to_global_ref(_result);
+  return (JniClassLookupResult){.value = _result, .exception = NULL};
 }
 
-jboolean globalEnv_IsAssignableFrom(jclass clazz1, jclass clazz2) {
+JniResult globalEnv_IsAssignableFrom(jclass clazz1, jclass clazz2) {
   attach_thread();
-  return (*jniEnv)->IsAssignableFrom(jniEnv, clazz1, clazz2);
+  jboolean _result = (*jniEnv)->IsAssignableFrom(jniEnv, clazz1, clazz2);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.z = _result}, .exception = NULL};
 }
 
-jobject globalEnv_ToReflectedField(jclass cls,
-                                   jfieldID fieldID,
-                                   jboolean isStatic) {
+JniResult globalEnv_ToReflectedField(jclass cls,
+                                     jfieldID fieldID,
+                                     jboolean isStatic) {
   attach_thread();
-  return to_global_ref(
-      (*jniEnv)->ToReflectedField(jniEnv, cls, fieldID, isStatic));
+  jobject _result = (*jniEnv)->ToReflectedField(jniEnv, cls, fieldID, isStatic);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  _result = to_global_ref(_result);
+  return (JniResult){.value = {.l = _result}, .exception = NULL};
 }
 
-jint globalEnv_Throw(jthrowable obj) {
+JniResult globalEnv_Throw(jthrowable obj) {
   attach_thread();
-  return (*jniEnv)->Throw(jniEnv, obj);
+  jint _result = (*jniEnv)->Throw(jniEnv, obj);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.i = _result}, .exception = NULL};
 }
 
-jint globalEnv_ThrowNew(jclass clazz, const char* message) {
+JniResult globalEnv_ThrowNew(jclass clazz, char* message) {
   attach_thread();
-  return (*jniEnv)->ThrowNew(jniEnv, clazz, message);
+  jint _result = (*jniEnv)->ThrowNew(jniEnv, clazz, message);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.i = _result}, .exception = NULL};
 }
 
-jthrowable globalEnv_ExceptionOccurred() {
+JniResult globalEnv_ExceptionOccurred() {
   attach_thread();
-  return to_global_ref((*jniEnv)->ExceptionOccurred(jniEnv));
+  jthrowable _result = (*jniEnv)->ExceptionOccurred(jniEnv);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  _result = to_global_ref(_result);
+  return (JniResult){.value = {.l = _result}, .exception = NULL};
 }
 
-void globalEnv_ExceptionDescribe() {
+jthrowable globalEnv_ExceptionDescribe() {
   attach_thread();
   (*jniEnv)->ExceptionDescribe(jniEnv);
+  return NULL;
 }
 
-void globalEnv_ExceptionClear() {
+jthrowable globalEnv_ExceptionClear() {
   attach_thread();
   (*jniEnv)->ExceptionClear(jniEnv);
+  return NULL;
 }
 
-void globalEnv_FatalError(const char* msg) {
+jthrowable globalEnv_FatalError(char* msg) {
   attach_thread();
   (*jniEnv)->FatalError(jniEnv, msg);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
 }
 
-jint globalEnv_PushLocalFrame(jint capacity) {
+JniResult globalEnv_PushLocalFrame(jint capacity) {
   attach_thread();
-  return (*jniEnv)->PushLocalFrame(jniEnv, capacity);
+  jint _result = (*jniEnv)->PushLocalFrame(jniEnv, capacity);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.i = _result}, .exception = NULL};
 }
 
-jobject globalEnv_PopLocalFrame(jobject result) {
+JniResult globalEnv_PopLocalFrame(jobject result) {
   attach_thread();
-  return to_global_ref((*jniEnv)->PopLocalFrame(jniEnv, result));
+  jobject _result = (*jniEnv)->PopLocalFrame(jniEnv, result);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  _result = to_global_ref(_result);
+  return (JniResult){.value = {.l = _result}, .exception = NULL};
 }
 
-jobject globalEnv_NewGlobalRef(jobject obj) {
+JniResult globalEnv_NewGlobalRef(jobject obj) {
   attach_thread();
-  return to_global_ref((*jniEnv)->NewGlobalRef(jniEnv, obj));
+  jobject _result = (*jniEnv)->NewGlobalRef(jniEnv, obj);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.l = _result}, .exception = NULL};
 }
 
-void globalEnv_DeleteGlobalRef(jobject globalRef) {
+jthrowable globalEnv_DeleteGlobalRef(jobject globalRef) {
   attach_thread();
   (*jniEnv)->DeleteGlobalRef(jniEnv, globalRef);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
 }
 
-jboolean globalEnv_IsSameObject(jobject ref1, jobject ref2) {
+jthrowable globalEnv_DeleteLocalRef(jobject localRef) {
   attach_thread();
-  return (*jniEnv)->IsSameObject(jniEnv, ref1, ref2);
+  (*jniEnv)->DeleteLocalRef(jniEnv, localRef);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
 }
 
-jint globalEnv_EnsureLocalCapacity(jint capacity) {
+JniResult globalEnv_IsSameObject(jobject ref1, jobject ref2) {
   attach_thread();
-  return (*jniEnv)->EnsureLocalCapacity(jniEnv, capacity);
+  jboolean _result = (*jniEnv)->IsSameObject(jniEnv, ref1, ref2);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.z = _result}, .exception = NULL};
 }
 
-jobject globalEnv_AllocObject(jclass clazz) {
+JniResult globalEnv_NewLocalRef(jobject obj) {
   attach_thread();
-  return to_global_ref((*jniEnv)->AllocObject(jniEnv, clazz));
+  jobject _result = (*jniEnv)->NewLocalRef(jniEnv, obj);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.l = _result}, .exception = NULL};
 }
 
-jobject globalEnv_NewObject(jclass arg1, jmethodID arg2) {
+JniResult globalEnv_EnsureLocalCapacity(jint capacity) {
   attach_thread();
-  return to_global_ref((*jniEnv)->NewObject(jniEnv, arg1, arg2));
+  jint _result = (*jniEnv)->EnsureLocalCapacity(jniEnv, capacity);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.i = _result}, .exception = NULL};
 }
 
-jobject globalEnv_NewObjectA(jclass clazz,
-                             jmethodID methodID,
-                             const jvalue* args) {
+JniResult globalEnv_AllocObject(jclass clazz) {
   attach_thread();
-  return to_global_ref((*jniEnv)->NewObjectA(jniEnv, clazz, methodID, args));
+  jobject _result = (*jniEnv)->AllocObject(jniEnv, clazz);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  _result = to_global_ref(_result);
+  return (JniResult){.value = {.l = _result}, .exception = NULL};
 }
 
-jclass globalEnv_GetObjectClass(jobject obj) {
+JniResult globalEnv_NewObject(jclass clazz, jmethodID methodID) {
   attach_thread();
-  return to_global_ref((*jniEnv)->GetObjectClass(jniEnv, obj));
+  jobject _result = (*jniEnv)->NewObject(jniEnv, clazz, methodID);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  _result = to_global_ref(_result);
+  return (JniResult){.value = {.l = _result}, .exception = NULL};
 }
 
-jboolean globalEnv_IsInstanceOf(jobject obj, jclass clazz) {
+JniResult globalEnv_NewObjectA(jclass clazz, jmethodID methodID, jvalue* args) {
   attach_thread();
-  return (*jniEnv)->IsInstanceOf(jniEnv, obj, clazz);
+  jobject _result = (*jniEnv)->NewObjectA(jniEnv, clazz, methodID, args);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  _result = to_global_ref(_result);
+  return (JniResult){.value = {.l = _result}, .exception = NULL};
 }
 
-jmethodID globalEnv_GetMethodID(jclass clazz,
-                                const char* name,
-                                const char* sig) {
+JniClassLookupResult globalEnv_GetObjectClass(jobject obj) {
   attach_thread();
-  return (*jniEnv)->GetMethodID(jniEnv, clazz, name, sig);
+  jclass _result = (*jniEnv)->GetObjectClass(jniEnv, obj);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniClassLookupResult){.value = NULL, .exception = _exception};
+  }
+  _result = to_global_ref(_result);
+  return (JniClassLookupResult){.value = _result, .exception = NULL};
 }
 
-jobject globalEnv_CallObjectMethod(jobject arg1, jmethodID arg2) {
+JniResult globalEnv_IsInstanceOf(jobject obj, jclass clazz) {
   attach_thread();
-  return to_global_ref((*jniEnv)->CallObjectMethod(jniEnv, arg1, arg2));
+  jboolean _result = (*jniEnv)->IsInstanceOf(jniEnv, obj, clazz);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.z = _result}, .exception = NULL};
 }
 
-jobject globalEnv_CallObjectMethodA(jobject obj,
+JniPointerResult globalEnv_GetMethodID(jclass clazz, char* name, char* sig) {
+  attach_thread();
+  jmethodID _result = (*jniEnv)->GetMethodID(jniEnv, clazz, name, sig);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniPointerResult){.value = NULL, .exception = _exception};
+  }
+  return (JniPointerResult){.value = _result, .exception = NULL};
+}
+
+JniResult globalEnv_CallObjectMethod(jobject obj, jmethodID methodID) {
+  attach_thread();
+  jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, obj, methodID);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  _result = to_global_ref(_result);
+  return (JniResult){.value = {.l = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallObjectMethodA(jobject obj,
+                                      jmethodID methodID,
+                                      jvalue* args) {
+  attach_thread();
+  jobject _result = (*jniEnv)->CallObjectMethodA(jniEnv, obj, methodID, args);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  _result = to_global_ref(_result);
+  return (JniResult){.value = {.l = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallBooleanMethod(jobject obj, jmethodID methodID) {
+  attach_thread();
+  jboolean _result = (*jniEnv)->CallBooleanMethod(jniEnv, obj, methodID);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.z = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallBooleanMethodA(jobject obj,
+                                       jmethodID methodId,
+                                       jvalue* args) {
+  attach_thread();
+  jboolean _result = (*jniEnv)->CallBooleanMethodA(jniEnv, obj, methodId, args);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.z = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallByteMethod(jobject obj, jmethodID methodID) {
+  attach_thread();
+  jbyte _result = (*jniEnv)->CallByteMethod(jniEnv, obj, methodID);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.b = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallByteMethodA(jobject obj,
                                     jmethodID methodID,
-                                    const jvalue* args) {
+                                    jvalue* args) {
   attach_thread();
-  return to_global_ref(
-      (*jniEnv)->CallObjectMethodA(jniEnv, obj, methodID, args));
+  jbyte _result = (*jniEnv)->CallByteMethodA(jniEnv, obj, methodID, args);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.b = _result}, .exception = NULL};
 }
 
-jboolean globalEnv_CallBooleanMethod(jobject arg1, jmethodID arg2) {
+JniResult globalEnv_CallCharMethod(jobject obj, jmethodID methodID) {
   attach_thread();
-  return (*jniEnv)->CallBooleanMethod(jniEnv, arg1, arg2);
+  jchar _result = (*jniEnv)->CallCharMethod(jniEnv, obj, methodID);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.c = _result}, .exception = NULL};
 }
 
-jboolean globalEnv_CallBooleanMethodA(jobject obj,
-                                      jmethodID methodId,
-                                      const jvalue* args) {
-  attach_thread();
-  return (*jniEnv)->CallBooleanMethodA(jniEnv, obj, methodId, args);
-}
-
-jbyte globalEnv_CallByteMethod(jobject arg1, jmethodID arg2) {
-  attach_thread();
-  return (*jniEnv)->CallByteMethod(jniEnv, arg1, arg2);
-}
-
-jbyte globalEnv_CallByteMethodA(jobject obj,
-                                jmethodID methodID,
-                                const jvalue* args) {
-  attach_thread();
-  return (*jniEnv)->CallByteMethodA(jniEnv, obj, methodID, args);
-}
-
-jchar globalEnv_CallCharMethod(jobject arg1, jmethodID arg2) {
-  attach_thread();
-  return (*jniEnv)->CallCharMethod(jniEnv, arg1, arg2);
-}
-
-jchar globalEnv_CallCharMethodA(jobject obj,
-                                jmethodID methodID,
-                                const jvalue* args) {
-  attach_thread();
-  return (*jniEnv)->CallCharMethodA(jniEnv, obj, methodID, args);
-}
-
-jshort globalEnv_CallShortMethod(jobject arg1, jmethodID arg2) {
-  attach_thread();
-  return (*jniEnv)->CallShortMethod(jniEnv, arg1, arg2);
-}
-
-jshort globalEnv_CallShortMethodA(jobject obj,
-                                  jmethodID methodID,
-                                  const jvalue* args) {
-  attach_thread();
-  return (*jniEnv)->CallShortMethodA(jniEnv, obj, methodID, args);
-}
-
-jint globalEnv_CallIntMethod(jobject arg1, jmethodID arg2) {
-  attach_thread();
-  return (*jniEnv)->CallIntMethod(jniEnv, arg1, arg2);
-}
-
-jint globalEnv_CallIntMethodA(jobject obj,
-                              jmethodID methodID,
-                              const jvalue* args) {
-  attach_thread();
-  return (*jniEnv)->CallIntMethodA(jniEnv, obj, methodID, args);
-}
-
-jlong globalEnv_CallLongMethod(jobject arg1, jmethodID arg2) {
-  attach_thread();
-  return (*jniEnv)->CallLongMethod(jniEnv, arg1, arg2);
-}
-
-jlong globalEnv_CallLongMethodA(jobject obj,
-                                jmethodID methodID,
-                                const jvalue* args) {
-  attach_thread();
-  return (*jniEnv)->CallLongMethodA(jniEnv, obj, methodID, args);
-}
-
-jfloat globalEnv_CallFloatMethod(jobject arg1, jmethodID arg2) {
-  attach_thread();
-  return (*jniEnv)->CallFloatMethod(jniEnv, arg1, arg2);
-}
-
-jfloat globalEnv_CallFloatMethodA(jobject obj,
-                                  jmethodID methodID,
-                                  const jvalue* args) {
-  attach_thread();
-  return (*jniEnv)->CallFloatMethodA(jniEnv, obj, methodID, args);
-}
-
-jdouble globalEnv_CallDoubleMethod(jobject arg1, jmethodID arg2) {
-  attach_thread();
-  return (*jniEnv)->CallDoubleMethod(jniEnv, arg1, arg2);
-}
-
-jdouble globalEnv_CallDoubleMethodA(jobject obj,
+JniResult globalEnv_CallCharMethodA(jobject obj,
                                     jmethodID methodID,
-                                    const jvalue* args) {
+                                    jvalue* args) {
   attach_thread();
-  return (*jniEnv)->CallDoubleMethodA(jniEnv, obj, methodID, args);
+  jchar _result = (*jniEnv)->CallCharMethodA(jniEnv, obj, methodID, args);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.c = _result}, .exception = NULL};
 }
 
-void globalEnv_CallVoidMethod(jobject arg1, jmethodID arg2) {
+JniResult globalEnv_CallShortMethod(jobject obj, jmethodID methodID) {
   attach_thread();
-  (*jniEnv)->CallVoidMethod(jniEnv, arg1, arg2);
+  jshort _result = (*jniEnv)->CallShortMethod(jniEnv, obj, methodID);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.s = _result}, .exception = NULL};
 }
 
-void globalEnv_CallVoidMethodA(jobject obj,
-                               jmethodID methodID,
-                               const jvalue* args) {
+JniResult globalEnv_CallShortMethodA(jobject obj,
+                                     jmethodID methodID,
+                                     jvalue* args) {
+  attach_thread();
+  jshort _result = (*jniEnv)->CallShortMethodA(jniEnv, obj, methodID, args);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.s = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallIntMethod(jobject obj, jmethodID methodID) {
+  attach_thread();
+  jint _result = (*jniEnv)->CallIntMethod(jniEnv, obj, methodID);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.i = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallIntMethodA(jobject obj,
+                                   jmethodID methodID,
+                                   jvalue* args) {
+  attach_thread();
+  jint _result = (*jniEnv)->CallIntMethodA(jniEnv, obj, methodID, args);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.i = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallLongMethod(jobject obj, jmethodID methodID) {
+  attach_thread();
+  jlong _result = (*jniEnv)->CallLongMethod(jniEnv, obj, methodID);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.j = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallLongMethodA(jobject obj,
+                                    jmethodID methodID,
+                                    jvalue* args) {
+  attach_thread();
+  jlong _result = (*jniEnv)->CallLongMethodA(jniEnv, obj, methodID, args);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.j = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallFloatMethod(jobject obj, jmethodID methodID) {
+  attach_thread();
+  jfloat _result = (*jniEnv)->CallFloatMethod(jniEnv, obj, methodID);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.f = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallFloatMethodA(jobject obj,
+                                     jmethodID methodID,
+                                     jvalue* args) {
+  attach_thread();
+  jfloat _result = (*jniEnv)->CallFloatMethodA(jniEnv, obj, methodID, args);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.f = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallDoubleMethod(jobject obj, jmethodID methodID) {
+  attach_thread();
+  jdouble _result = (*jniEnv)->CallDoubleMethod(jniEnv, obj, methodID);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.d = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallDoubleMethodA(jobject obj,
+                                      jmethodID methodID,
+                                      jvalue* args) {
+  attach_thread();
+  jdouble _result = (*jniEnv)->CallDoubleMethodA(jniEnv, obj, methodID, args);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.d = _result}, .exception = NULL};
+}
+
+jthrowable globalEnv_CallVoidMethod(jobject obj, jmethodID methodID) {
+  attach_thread();
+  (*jniEnv)->CallVoidMethod(jniEnv, obj, methodID);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
+}
+
+jthrowable globalEnv_CallVoidMethodA(jobject obj,
+                                     jmethodID methodID,
+                                     jvalue* args) {
   attach_thread();
   (*jniEnv)->CallVoidMethodA(jniEnv, obj, methodID, args);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
 }
 
-jobject globalEnv_CallNonvirtualObjectMethod(jobject arg1,
-                                             jclass arg2,
-                                             jmethodID arg3) {
+JniResult globalEnv_CallNonvirtualObjectMethod(jobject obj,
+                                               jclass clazz,
+                                               jmethodID methodID) {
   attach_thread();
-  return to_global_ref(
-      (*jniEnv)->CallNonvirtualObjectMethod(jniEnv, arg1, arg2, arg3));
+  jobject _result =
+      (*jniEnv)->CallNonvirtualObjectMethod(jniEnv, obj, clazz, methodID);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  _result = to_global_ref(_result);
+  return (JniResult){.value = {.l = _result}, .exception = NULL};
 }
 
-jobject globalEnv_CallNonvirtualObjectMethodA(jobject obj,
-                                              jclass clazz,
-                                              jmethodID methodID,
-                                              const jvalue* args) {
-  attach_thread();
-  return to_global_ref((*jniEnv)->CallNonvirtualObjectMethodA(
-      jniEnv, obj, clazz, methodID, args));
-}
-
-jboolean globalEnv_CallNonvirtualBooleanMethod(jobject arg1,
-                                               jclass arg2,
-                                               jmethodID arg3) {
-  attach_thread();
-  return (*jniEnv)->CallNonvirtualBooleanMethod(jniEnv, arg1, arg2, arg3);
-}
-
-jboolean globalEnv_CallNonvirtualBooleanMethodA(jobject obj,
+JniResult globalEnv_CallNonvirtualObjectMethodA(jobject obj,
                                                 jclass clazz,
                                                 jmethodID methodID,
-                                                const jvalue* args) {
+                                                jvalue* args) {
   attach_thread();
-  return (*jniEnv)->CallNonvirtualBooleanMethodA(jniEnv, obj, clazz, methodID,
-                                                 args);
+  jobject _result = (*jniEnv)->CallNonvirtualObjectMethodA(jniEnv, obj, clazz,
+                                                           methodID, args);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  _result = to_global_ref(_result);
+  return (JniResult){.value = {.l = _result}, .exception = NULL};
 }
 
-jbyte globalEnv_CallNonvirtualByteMethod(jobject arg1,
-                                         jclass arg2,
-                                         jmethodID arg3) {
+JniResult globalEnv_CallNonvirtualBooleanMethod(jobject obj,
+                                                jclass clazz,
+                                                jmethodID methodID) {
   attach_thread();
-  return (*jniEnv)->CallNonvirtualByteMethod(jniEnv, arg1, arg2, arg3);
+  jboolean _result =
+      (*jniEnv)->CallNonvirtualBooleanMethod(jniEnv, obj, clazz, methodID);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.z = _result}, .exception = NULL};
 }
 
-jbyte globalEnv_CallNonvirtualByteMethodA(jobject obj,
-                                          jclass clazz,
-                                          jmethodID methodID,
-                                          const jvalue* args) {
+JniResult globalEnv_CallNonvirtualBooleanMethodA(jobject obj,
+                                                 jclass clazz,
+                                                 jmethodID methodID,
+                                                 jvalue* args) {
   attach_thread();
-  return (*jniEnv)->CallNonvirtualByteMethodA(jniEnv, obj, clazz, methodID,
-                                              args);
+  jboolean _result = (*jniEnv)->CallNonvirtualBooleanMethodA(jniEnv, obj, clazz,
+                                                             methodID, args);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.z = _result}, .exception = NULL};
 }
 
-jchar globalEnv_CallNonvirtualCharMethod(jobject arg1,
-                                         jclass arg2,
-                                         jmethodID arg3) {
+JniResult globalEnv_CallNonvirtualByteMethod(jobject obj,
+                                             jclass clazz,
+                                             jmethodID methodID) {
   attach_thread();
-  return (*jniEnv)->CallNonvirtualCharMethod(jniEnv, arg1, arg2, arg3);
+  jbyte _result =
+      (*jniEnv)->CallNonvirtualByteMethod(jniEnv, obj, clazz, methodID);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.b = _result}, .exception = NULL};
 }
 
-jchar globalEnv_CallNonvirtualCharMethodA(jobject obj,
-                                          jclass clazz,
-                                          jmethodID methodID,
-                                          const jvalue* args) {
-  attach_thread();
-  return (*jniEnv)->CallNonvirtualCharMethodA(jniEnv, obj, clazz, methodID,
-                                              args);
-}
-
-jshort globalEnv_CallNonvirtualShortMethod(jobject arg1,
-                                           jclass arg2,
-                                           jmethodID arg3) {
-  attach_thread();
-  return (*jniEnv)->CallNonvirtualShortMethod(jniEnv, arg1, arg2, arg3);
-}
-
-jshort globalEnv_CallNonvirtualShortMethodA(jobject obj,
-                                            jclass clazz,
-                                            jmethodID methodID,
-                                            const jvalue* args) {
-  attach_thread();
-  return (*jniEnv)->CallNonvirtualShortMethodA(jniEnv, obj, clazz, methodID,
-                                               args);
-}
-
-jint globalEnv_CallNonvirtualIntMethod(jobject arg1,
-                                       jclass arg2,
-                                       jmethodID arg3) {
-  attach_thread();
-  return (*jniEnv)->CallNonvirtualIntMethod(jniEnv, arg1, arg2, arg3);
-}
-
-jint globalEnv_CallNonvirtualIntMethodA(jobject obj,
-                                        jclass clazz,
-                                        jmethodID methodID,
-                                        const jvalue* args) {
-  attach_thread();
-  return (*jniEnv)->CallNonvirtualIntMethodA(jniEnv, obj, clazz, methodID,
-                                             args);
-}
-
-jlong globalEnv_CallNonvirtualLongMethod(jobject arg1,
-                                         jclass arg2,
-                                         jmethodID arg3) {
-  attach_thread();
-  return (*jniEnv)->CallNonvirtualLongMethod(jniEnv, arg1, arg2, arg3);
-}
-
-jlong globalEnv_CallNonvirtualLongMethodA(jobject obj,
-                                          jclass clazz,
-                                          jmethodID methodID,
-                                          const jvalue* args) {
-  attach_thread();
-  return (*jniEnv)->CallNonvirtualLongMethodA(jniEnv, obj, clazz, methodID,
-                                              args);
-}
-
-jfloat globalEnv_CallNonvirtualFloatMethod(jobject arg1,
-                                           jclass arg2,
-                                           jmethodID arg3) {
-  attach_thread();
-  return (*jniEnv)->CallNonvirtualFloatMethod(jniEnv, arg1, arg2, arg3);
-}
-
-jfloat globalEnv_CallNonvirtualFloatMethodA(jobject obj,
-                                            jclass clazz,
-                                            jmethodID methodID,
-                                            const jvalue* args) {
-  attach_thread();
-  return (*jniEnv)->CallNonvirtualFloatMethodA(jniEnv, obj, clazz, methodID,
-                                               args);
-}
-
-jdouble globalEnv_CallNonvirtualDoubleMethod(jobject arg1,
-                                             jclass arg2,
-                                             jmethodID arg3) {
-  attach_thread();
-  return (*jniEnv)->CallNonvirtualDoubleMethod(jniEnv, arg1, arg2, arg3);
-}
-
-jdouble globalEnv_CallNonvirtualDoubleMethodA(jobject obj,
+JniResult globalEnv_CallNonvirtualByteMethodA(jobject obj,
                                               jclass clazz,
                                               jmethodID methodID,
-                                              const jvalue* args) {
+                                              jvalue* args) {
   attach_thread();
-  return (*jniEnv)->CallNonvirtualDoubleMethodA(jniEnv, obj, clazz, methodID,
-                                                args);
+  jbyte _result =
+      (*jniEnv)->CallNonvirtualByteMethodA(jniEnv, obj, clazz, methodID, args);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.b = _result}, .exception = NULL};
 }
 
-void globalEnv_CallNonvirtualVoidMethod(jobject arg1,
-                                        jclass arg2,
-                                        jmethodID arg3) {
+JniResult globalEnv_CallNonvirtualCharMethod(jobject obj,
+                                             jclass clazz,
+                                             jmethodID methodID) {
   attach_thread();
-  (*jniEnv)->CallNonvirtualVoidMethod(jniEnv, arg1, arg2, arg3);
+  jchar _result =
+      (*jniEnv)->CallNonvirtualCharMethod(jniEnv, obj, clazz, methodID);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.c = _result}, .exception = NULL};
 }
 
-void globalEnv_CallNonvirtualVoidMethodA(jobject obj,
-                                         jclass clazz,
-                                         jmethodID methodID,
-                                         const jvalue* args) {
+JniResult globalEnv_CallNonvirtualCharMethodA(jobject obj,
+                                              jclass clazz,
+                                              jmethodID methodID,
+                                              jvalue* args) {
+  attach_thread();
+  jchar _result =
+      (*jniEnv)->CallNonvirtualCharMethodA(jniEnv, obj, clazz, methodID, args);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.c = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallNonvirtualShortMethod(jobject obj,
+                                              jclass clazz,
+                                              jmethodID methodID) {
+  attach_thread();
+  jshort _result =
+      (*jniEnv)->CallNonvirtualShortMethod(jniEnv, obj, clazz, methodID);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.s = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallNonvirtualShortMethodA(jobject obj,
+                                               jclass clazz,
+                                               jmethodID methodID,
+                                               jvalue* args) {
+  attach_thread();
+  jshort _result =
+      (*jniEnv)->CallNonvirtualShortMethodA(jniEnv, obj, clazz, methodID, args);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.s = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallNonvirtualIntMethod(jobject obj,
+                                            jclass clazz,
+                                            jmethodID methodID) {
+  attach_thread();
+  jint _result =
+      (*jniEnv)->CallNonvirtualIntMethod(jniEnv, obj, clazz, methodID);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.i = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallNonvirtualIntMethodA(jobject obj,
+                                             jclass clazz,
+                                             jmethodID methodID,
+                                             jvalue* args) {
+  attach_thread();
+  jint _result =
+      (*jniEnv)->CallNonvirtualIntMethodA(jniEnv, obj, clazz, methodID, args);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.i = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallNonvirtualLongMethod(jobject obj,
+                                             jclass clazz,
+                                             jmethodID methodID) {
+  attach_thread();
+  jlong _result =
+      (*jniEnv)->CallNonvirtualLongMethod(jniEnv, obj, clazz, methodID);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.j = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallNonvirtualLongMethodA(jobject obj,
+                                              jclass clazz,
+                                              jmethodID methodID,
+                                              jvalue* args) {
+  attach_thread();
+  jlong _result =
+      (*jniEnv)->CallNonvirtualLongMethodA(jniEnv, obj, clazz, methodID, args);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.j = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallNonvirtualFloatMethod(jobject obj,
+                                              jclass clazz,
+                                              jmethodID methodID) {
+  attach_thread();
+  jfloat _result =
+      (*jniEnv)->CallNonvirtualFloatMethod(jniEnv, obj, clazz, methodID);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.f = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallNonvirtualFloatMethodA(jobject obj,
+                                               jclass clazz,
+                                               jmethodID methodID,
+                                               jvalue* args) {
+  attach_thread();
+  jfloat _result =
+      (*jniEnv)->CallNonvirtualFloatMethodA(jniEnv, obj, clazz, methodID, args);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.f = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallNonvirtualDoubleMethod(jobject obj,
+                                               jclass clazz,
+                                               jmethodID methodID) {
+  attach_thread();
+  jdouble _result =
+      (*jniEnv)->CallNonvirtualDoubleMethod(jniEnv, obj, clazz, methodID);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.d = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallNonvirtualDoubleMethodA(jobject obj,
+                                                jclass clazz,
+                                                jmethodID methodID,
+                                                jvalue* args) {
+  attach_thread();
+  jdouble _result = (*jniEnv)->CallNonvirtualDoubleMethodA(jniEnv, obj, clazz,
+                                                           methodID, args);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.d = _result}, .exception = NULL};
+}
+
+jthrowable globalEnv_CallNonvirtualVoidMethod(jobject obj,
+                                              jclass clazz,
+                                              jmethodID methodID) {
+  attach_thread();
+  (*jniEnv)->CallNonvirtualVoidMethod(jniEnv, obj, clazz, methodID);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
+}
+
+jthrowable globalEnv_CallNonvirtualVoidMethodA(jobject obj,
+                                               jclass clazz,
+                                               jmethodID methodID,
+                                               jvalue* args) {
   attach_thread();
   (*jniEnv)->CallNonvirtualVoidMethodA(jniEnv, obj, clazz, methodID, args);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
 }
 
-jfieldID globalEnv_GetFieldID(jclass clazz, const char* name, const char* sig) {
+JniPointerResult globalEnv_GetFieldID(jclass clazz, char* name, char* sig) {
   attach_thread();
-  return (*jniEnv)->GetFieldID(jniEnv, clazz, name, sig);
+  jfieldID _result = (*jniEnv)->GetFieldID(jniEnv, clazz, name, sig);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniPointerResult){.value = NULL, .exception = _exception};
+  }
+  return (JniPointerResult){.value = _result, .exception = NULL};
 }
 
-jobject globalEnv_GetObjectField(jobject obj, jfieldID fieldID) {
+JniResult globalEnv_GetObjectField(jobject obj, jfieldID fieldID) {
   attach_thread();
-  return to_global_ref((*jniEnv)->GetObjectField(jniEnv, obj, fieldID));
+  jobject _result = (*jniEnv)->GetObjectField(jniEnv, obj, fieldID);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  _result = to_global_ref(_result);
+  return (JniResult){.value = {.l = _result}, .exception = NULL};
 }
 
-jboolean globalEnv_GetBooleanField(jobject obj, jfieldID fieldID) {
+JniResult globalEnv_GetBooleanField(jobject obj, jfieldID fieldID) {
   attach_thread();
-  return (*jniEnv)->GetBooleanField(jniEnv, obj, fieldID);
+  jboolean _result = (*jniEnv)->GetBooleanField(jniEnv, obj, fieldID);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.z = _result}, .exception = NULL};
 }
 
-jbyte globalEnv_GetByteField(jobject obj, jfieldID fieldID) {
+JniResult globalEnv_GetByteField(jobject obj, jfieldID fieldID) {
   attach_thread();
-  return (*jniEnv)->GetByteField(jniEnv, obj, fieldID);
+  jbyte _result = (*jniEnv)->GetByteField(jniEnv, obj, fieldID);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.b = _result}, .exception = NULL};
 }
 
-jchar globalEnv_GetCharField(jobject obj, jfieldID fieldID) {
+JniResult globalEnv_GetCharField(jobject obj, jfieldID fieldID) {
   attach_thread();
-  return (*jniEnv)->GetCharField(jniEnv, obj, fieldID);
+  jchar _result = (*jniEnv)->GetCharField(jniEnv, obj, fieldID);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.c = _result}, .exception = NULL};
 }
 
-jshort globalEnv_GetShortField(jobject obj, jfieldID fieldID) {
+JniResult globalEnv_GetShortField(jobject obj, jfieldID fieldID) {
   attach_thread();
-  return (*jniEnv)->GetShortField(jniEnv, obj, fieldID);
+  jshort _result = (*jniEnv)->GetShortField(jniEnv, obj, fieldID);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.s = _result}, .exception = NULL};
 }
 
-jint globalEnv_GetIntField(jobject obj, jfieldID fieldID) {
+JniResult globalEnv_GetIntField(jobject obj, jfieldID fieldID) {
   attach_thread();
-  return (*jniEnv)->GetIntField(jniEnv, obj, fieldID);
+  jint _result = (*jniEnv)->GetIntField(jniEnv, obj, fieldID);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.i = _result}, .exception = NULL};
 }
 
-jlong globalEnv_GetLongField(jobject obj, jfieldID fieldID) {
+JniResult globalEnv_GetLongField(jobject obj, jfieldID fieldID) {
   attach_thread();
-  return (*jniEnv)->GetLongField(jniEnv, obj, fieldID);
+  jlong _result = (*jniEnv)->GetLongField(jniEnv, obj, fieldID);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.j = _result}, .exception = NULL};
 }
 
-jfloat globalEnv_GetFloatField(jobject obj, jfieldID fieldID) {
+JniResult globalEnv_GetFloatField(jobject obj, jfieldID fieldID) {
   attach_thread();
-  return (*jniEnv)->GetFloatField(jniEnv, obj, fieldID);
+  jfloat _result = (*jniEnv)->GetFloatField(jniEnv, obj, fieldID);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.f = _result}, .exception = NULL};
 }
 
-jdouble globalEnv_GetDoubleField(jobject obj, jfieldID fieldID) {
+JniResult globalEnv_GetDoubleField(jobject obj, jfieldID fieldID) {
   attach_thread();
-  return (*jniEnv)->GetDoubleField(jniEnv, obj, fieldID);
+  jdouble _result = (*jniEnv)->GetDoubleField(jniEnv, obj, fieldID);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.d = _result}, .exception = NULL};
 }
 
-void globalEnv_SetObjectField(jobject obj, jfieldID fieldID, jobject val) {
-  attach_thread();
-  (*jniEnv)->SetObjectField(jniEnv, obj, fieldID, val);
-}
-
-void globalEnv_SetBooleanField(jobject obj, jfieldID fieldID, jboolean val) {
-  attach_thread();
-  (*jniEnv)->SetBooleanField(jniEnv, obj, fieldID, val);
-}
-
-void globalEnv_SetByteField(jobject obj, jfieldID fieldID, jbyte val) {
-  attach_thread();
-  (*jniEnv)->SetByteField(jniEnv, obj, fieldID, val);
-}
-
-void globalEnv_SetCharField(jobject obj, jfieldID fieldID, jchar val) {
-  attach_thread();
-  (*jniEnv)->SetCharField(jniEnv, obj, fieldID, val);
-}
-
-void globalEnv_SetShortField(jobject obj, jfieldID fieldID, jshort val) {
-  attach_thread();
-  (*jniEnv)->SetShortField(jniEnv, obj, fieldID, val);
-}
-
-void globalEnv_SetIntField(jobject obj, jfieldID fieldID, jint val) {
-  attach_thread();
-  (*jniEnv)->SetIntField(jniEnv, obj, fieldID, val);
-}
-
-void globalEnv_SetLongField(jobject obj, jfieldID fieldID, jlong val) {
-  attach_thread();
-  (*jniEnv)->SetLongField(jniEnv, obj, fieldID, val);
-}
-
-void globalEnv_SetFloatField(jobject obj, jfieldID fieldID, jfloat val) {
-  attach_thread();
-  (*jniEnv)->SetFloatField(jniEnv, obj, fieldID, val);
-}
-
-void globalEnv_SetDoubleField(jobject obj, jfieldID fieldID, jdouble val) {
-  attach_thread();
-  (*jniEnv)->SetDoubleField(jniEnv, obj, fieldID, val);
-}
-
-jmethodID globalEnv_GetStaticMethodID(jclass clazz,
-                                      const char* name,
-                                      const char* sig) {
-  attach_thread();
-  return (*jniEnv)->GetStaticMethodID(jniEnv, clazz, name, sig);
-}
-
-jobject globalEnv_CallStaticObjectMethod(jclass arg1, jmethodID arg2) {
-  attach_thread();
-  return to_global_ref((*jniEnv)->CallStaticObjectMethod(jniEnv, arg1, arg2));
-}
-
-jobject globalEnv_CallStaticObjectMethodA(jclass clazz,
-                                          jmethodID methodID,
-                                          const jvalue* args) {
-  attach_thread();
-  return to_global_ref(
-      (*jniEnv)->CallStaticObjectMethodA(jniEnv, clazz, methodID, args));
-}
-
-jboolean globalEnv_CallStaticBooleanMethod(jclass arg1, jmethodID arg2) {
-  attach_thread();
-  return (*jniEnv)->CallStaticBooleanMethod(jniEnv, arg1, arg2);
-}
-
-jboolean globalEnv_CallStaticBooleanMethodA(jclass clazz,
-                                            jmethodID methodID,
-                                            const jvalue* args) {
-  attach_thread();
-  return (*jniEnv)->CallStaticBooleanMethodA(jniEnv, clazz, methodID, args);
-}
-
-jbyte globalEnv_CallStaticByteMethod(jclass arg1, jmethodID arg2) {
-  attach_thread();
-  return (*jniEnv)->CallStaticByteMethod(jniEnv, arg1, arg2);
-}
-
-jbyte globalEnv_CallStaticByteMethodA(jclass clazz,
-                                      jmethodID methodID,
-                                      const jvalue* args) {
-  attach_thread();
-  return (*jniEnv)->CallStaticByteMethodA(jniEnv, clazz, methodID, args);
-}
-
-jchar globalEnv_CallStaticCharMethod(jclass arg1, jmethodID arg2) {
-  attach_thread();
-  return (*jniEnv)->CallStaticCharMethod(jniEnv, arg1, arg2);
-}
-
-jchar globalEnv_CallStaticCharMethodA(jclass clazz,
-                                      jmethodID methodID,
-                                      const jvalue* args) {
-  attach_thread();
-  return (*jniEnv)->CallStaticCharMethodA(jniEnv, clazz, methodID, args);
-}
-
-jshort globalEnv_CallStaticShortMethod(jclass arg1, jmethodID arg2) {
-  attach_thread();
-  return (*jniEnv)->CallStaticShortMethod(jniEnv, arg1, arg2);
-}
-
-jshort globalEnv_CallStaticShortMethodA(jclass clazz,
-                                        jmethodID methodID,
-                                        const jvalue* args) {
-  attach_thread();
-  return (*jniEnv)->CallStaticShortMethodA(jniEnv, clazz, methodID, args);
-}
-
-jint globalEnv_CallStaticIntMethod(jclass arg1, jmethodID arg2) {
-  attach_thread();
-  return (*jniEnv)->CallStaticIntMethod(jniEnv, arg1, arg2);
-}
-
-jint globalEnv_CallStaticIntMethodA(jclass clazz,
-                                    jmethodID methodID,
-                                    const jvalue* args) {
-  attach_thread();
-  return (*jniEnv)->CallStaticIntMethodA(jniEnv, clazz, methodID, args);
-}
-
-jlong globalEnv_CallStaticLongMethod(jclass arg1, jmethodID arg2) {
-  attach_thread();
-  return (*jniEnv)->CallStaticLongMethod(jniEnv, arg1, arg2);
-}
-
-jlong globalEnv_CallStaticLongMethodA(jclass clazz,
-                                      jmethodID methodID,
-                                      const jvalue* args) {
-  attach_thread();
-  return (*jniEnv)->CallStaticLongMethodA(jniEnv, clazz, methodID, args);
-}
-
-jfloat globalEnv_CallStaticFloatMethod(jclass arg1, jmethodID arg2) {
-  attach_thread();
-  return (*jniEnv)->CallStaticFloatMethod(jniEnv, arg1, arg2);
-}
-
-jfloat globalEnv_CallStaticFloatMethodA(jclass clazz,
-                                        jmethodID methodID,
-                                        const jvalue* args) {
-  attach_thread();
-  return (*jniEnv)->CallStaticFloatMethodA(jniEnv, clazz, methodID, args);
-}
-
-jdouble globalEnv_CallStaticDoubleMethod(jclass arg1, jmethodID arg2) {
-  attach_thread();
-  return (*jniEnv)->CallStaticDoubleMethod(jniEnv, arg1, arg2);
-}
-
-jdouble globalEnv_CallStaticDoubleMethodA(jclass clazz,
-                                          jmethodID methodID,
-                                          const jvalue* args) {
-  attach_thread();
-  return (*jniEnv)->CallStaticDoubleMethodA(jniEnv, clazz, methodID, args);
-}
-
-void globalEnv_CallStaticVoidMethod(jclass arg1, jmethodID arg2) {
-  attach_thread();
-  (*jniEnv)->CallStaticVoidMethod(jniEnv, arg1, arg2);
-}
-
-void globalEnv_CallStaticVoidMethodA(jclass clazz,
-                                     jmethodID methodID,
-                                     const jvalue* args) {
-  attach_thread();
-  (*jniEnv)->CallStaticVoidMethodA(jniEnv, clazz, methodID, args);
-}
-
-jfieldID globalEnv_GetStaticFieldID(jclass clazz,
-                                    const char* name,
-                                    const char* sig) {
-  attach_thread();
-  return (*jniEnv)->GetStaticFieldID(jniEnv, clazz, name, sig);
-}
-
-jobject globalEnv_GetStaticObjectField(jclass clazz, jfieldID fieldID) {
-  attach_thread();
-  return to_global_ref((*jniEnv)->GetStaticObjectField(jniEnv, clazz, fieldID));
-}
-
-jboolean globalEnv_GetStaticBooleanField(jclass clazz, jfieldID fieldID) {
-  attach_thread();
-  return (*jniEnv)->GetStaticBooleanField(jniEnv, clazz, fieldID);
-}
-
-jbyte globalEnv_GetStaticByteField(jclass clazz, jfieldID fieldID) {
-  attach_thread();
-  return (*jniEnv)->GetStaticByteField(jniEnv, clazz, fieldID);
-}
-
-jchar globalEnv_GetStaticCharField(jclass clazz, jfieldID fieldID) {
-  attach_thread();
-  return (*jniEnv)->GetStaticCharField(jniEnv, clazz, fieldID);
-}
-
-jshort globalEnv_GetStaticShortField(jclass clazz, jfieldID fieldID) {
-  attach_thread();
-  return (*jniEnv)->GetStaticShortField(jniEnv, clazz, fieldID);
-}
-
-jint globalEnv_GetStaticIntField(jclass clazz, jfieldID fieldID) {
-  attach_thread();
-  return (*jniEnv)->GetStaticIntField(jniEnv, clazz, fieldID);
-}
-
-jlong globalEnv_GetStaticLongField(jclass clazz, jfieldID fieldID) {
-  attach_thread();
-  return (*jniEnv)->GetStaticLongField(jniEnv, clazz, fieldID);
-}
-
-jfloat globalEnv_GetStaticFloatField(jclass clazz, jfieldID fieldID) {
-  attach_thread();
-  return (*jniEnv)->GetStaticFloatField(jniEnv, clazz, fieldID);
-}
-
-jdouble globalEnv_GetStaticDoubleField(jclass clazz, jfieldID fieldID) {
-  attach_thread();
-  return (*jniEnv)->GetStaticDoubleField(jniEnv, clazz, fieldID);
-}
-
-void globalEnv_SetStaticObjectField(jclass clazz,
+jthrowable globalEnv_SetObjectField(jobject obj,
                                     jfieldID fieldID,
                                     jobject val) {
   attach_thread();
-  (*jniEnv)->SetStaticObjectField(jniEnv, clazz, fieldID, val);
+  (*jniEnv)->SetObjectField(jniEnv, obj, fieldID, val);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
 }
 
-void globalEnv_SetStaticBooleanField(jclass clazz,
+jthrowable globalEnv_SetBooleanField(jobject obj,
                                      jfieldID fieldID,
                                      jboolean val) {
   attach_thread();
-  (*jniEnv)->SetStaticBooleanField(jniEnv, clazz, fieldID, val);
+  (*jniEnv)->SetBooleanField(jniEnv, obj, fieldID, val);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
 }
 
-void globalEnv_SetStaticByteField(jclass clazz, jfieldID fieldID, jbyte val) {
+jthrowable globalEnv_SetByteField(jobject obj, jfieldID fieldID, jbyte val) {
   attach_thread();
-  (*jniEnv)->SetStaticByteField(jniEnv, clazz, fieldID, val);
+  (*jniEnv)->SetByteField(jniEnv, obj, fieldID, val);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
 }
 
-void globalEnv_SetStaticCharField(jclass clazz, jfieldID fieldID, jchar val) {
+jthrowable globalEnv_SetCharField(jobject obj, jfieldID fieldID, jchar val) {
   attach_thread();
-  (*jniEnv)->SetStaticCharField(jniEnv, clazz, fieldID, val);
+  (*jniEnv)->SetCharField(jniEnv, obj, fieldID, val);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
 }
 
-void globalEnv_SetStaticShortField(jclass clazz, jfieldID fieldID, jshort val) {
+jthrowable globalEnv_SetShortField(jobject obj, jfieldID fieldID, jshort val) {
   attach_thread();
-  (*jniEnv)->SetStaticShortField(jniEnv, clazz, fieldID, val);
+  (*jniEnv)->SetShortField(jniEnv, obj, fieldID, val);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
 }
 
-void globalEnv_SetStaticIntField(jclass clazz, jfieldID fieldID, jint val) {
+jthrowable globalEnv_SetIntField(jobject obj, jfieldID fieldID, jint val) {
   attach_thread();
-  (*jniEnv)->SetStaticIntField(jniEnv, clazz, fieldID, val);
+  (*jniEnv)->SetIntField(jniEnv, obj, fieldID, val);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
 }
 
-void globalEnv_SetStaticLongField(jclass clazz, jfieldID fieldID, jlong val) {
+jthrowable globalEnv_SetLongField(jobject obj, jfieldID fieldID, jlong val) {
   attach_thread();
-  (*jniEnv)->SetStaticLongField(jniEnv, clazz, fieldID, val);
+  (*jniEnv)->SetLongField(jniEnv, obj, fieldID, val);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
 }
 
-void globalEnv_SetStaticFloatField(jclass clazz, jfieldID fieldID, jfloat val) {
+jthrowable globalEnv_SetFloatField(jobject obj, jfieldID fieldID, jfloat val) {
   attach_thread();
-  (*jniEnv)->SetStaticFloatField(jniEnv, clazz, fieldID, val);
+  (*jniEnv)->SetFloatField(jniEnv, obj, fieldID, val);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
 }
 
-void globalEnv_SetStaticDoubleField(jclass clazz,
+jthrowable globalEnv_SetDoubleField(jobject obj,
                                     jfieldID fieldID,
                                     jdouble val) {
   attach_thread();
+  (*jniEnv)->SetDoubleField(jniEnv, obj, fieldID, val);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
+}
+
+JniPointerResult globalEnv_GetStaticMethodID(jclass clazz,
+                                             char* name,
+                                             char* sig) {
+  attach_thread();
+  jmethodID _result = (*jniEnv)->GetStaticMethodID(jniEnv, clazz, name, sig);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniPointerResult){.value = NULL, .exception = _exception};
+  }
+  return (JniPointerResult){.value = _result, .exception = NULL};
+}
+
+JniResult globalEnv_CallStaticObjectMethod(jclass clazz, jmethodID methodID) {
+  attach_thread();
+  jobject _result = (*jniEnv)->CallStaticObjectMethod(jniEnv, clazz, methodID);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  _result = to_global_ref(_result);
+  return (JniResult){.value = {.l = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallStaticObjectMethodA(jclass clazz,
+                                            jmethodID methodID,
+                                            jvalue* args) {
+  attach_thread();
+  jobject _result =
+      (*jniEnv)->CallStaticObjectMethodA(jniEnv, clazz, methodID, args);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  _result = to_global_ref(_result);
+  return (JniResult){.value = {.l = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallStaticBooleanMethod(jclass clazz, jmethodID methodID) {
+  attach_thread();
+  jboolean _result =
+      (*jniEnv)->CallStaticBooleanMethod(jniEnv, clazz, methodID);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.z = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallStaticBooleanMethodA(jclass clazz,
+                                             jmethodID methodID,
+                                             jvalue* args) {
+  attach_thread();
+  jboolean _result =
+      (*jniEnv)->CallStaticBooleanMethodA(jniEnv, clazz, methodID, args);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.z = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallStaticByteMethod(jclass clazz, jmethodID methodID) {
+  attach_thread();
+  jbyte _result = (*jniEnv)->CallStaticByteMethod(jniEnv, clazz, methodID);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.b = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallStaticByteMethodA(jclass clazz,
+                                          jmethodID methodID,
+                                          jvalue* args) {
+  attach_thread();
+  jbyte _result =
+      (*jniEnv)->CallStaticByteMethodA(jniEnv, clazz, methodID, args);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.b = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallStaticCharMethod(jclass clazz, jmethodID methodID) {
+  attach_thread();
+  jchar _result = (*jniEnv)->CallStaticCharMethod(jniEnv, clazz, methodID);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.c = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallStaticCharMethodA(jclass clazz,
+                                          jmethodID methodID,
+                                          jvalue* args) {
+  attach_thread();
+  jchar _result =
+      (*jniEnv)->CallStaticCharMethodA(jniEnv, clazz, methodID, args);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.c = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallStaticShortMethod(jclass clazz, jmethodID methodID) {
+  attach_thread();
+  jshort _result = (*jniEnv)->CallStaticShortMethod(jniEnv, clazz, methodID);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.s = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallStaticShortMethodA(jclass clazz,
+                                           jmethodID methodID,
+                                           jvalue* args) {
+  attach_thread();
+  jshort _result =
+      (*jniEnv)->CallStaticShortMethodA(jniEnv, clazz, methodID, args);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.s = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallStaticIntMethod(jclass clazz, jmethodID methodID) {
+  attach_thread();
+  jint _result = (*jniEnv)->CallStaticIntMethod(jniEnv, clazz, methodID);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.i = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallStaticIntMethodA(jclass clazz,
+                                         jmethodID methodID,
+                                         jvalue* args) {
+  attach_thread();
+  jint _result = (*jniEnv)->CallStaticIntMethodA(jniEnv, clazz, methodID, args);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.i = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallStaticLongMethod(jclass clazz, jmethodID methodID) {
+  attach_thread();
+  jlong _result = (*jniEnv)->CallStaticLongMethod(jniEnv, clazz, methodID);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.j = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallStaticLongMethodA(jclass clazz,
+                                          jmethodID methodID,
+                                          jvalue* args) {
+  attach_thread();
+  jlong _result =
+      (*jniEnv)->CallStaticLongMethodA(jniEnv, clazz, methodID, args);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.j = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallStaticFloatMethod(jclass clazz, jmethodID methodID) {
+  attach_thread();
+  jfloat _result = (*jniEnv)->CallStaticFloatMethod(jniEnv, clazz, methodID);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.f = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallStaticFloatMethodA(jclass clazz,
+                                           jmethodID methodID,
+                                           jvalue* args) {
+  attach_thread();
+  jfloat _result =
+      (*jniEnv)->CallStaticFloatMethodA(jniEnv, clazz, methodID, args);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.f = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallStaticDoubleMethod(jclass clazz, jmethodID methodID) {
+  attach_thread();
+  jdouble _result = (*jniEnv)->CallStaticDoubleMethod(jniEnv, clazz, methodID);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.d = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallStaticDoubleMethodA(jclass clazz,
+                                            jmethodID methodID,
+                                            jvalue* args) {
+  attach_thread();
+  jdouble _result =
+      (*jniEnv)->CallStaticDoubleMethodA(jniEnv, clazz, methodID, args);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.d = _result}, .exception = NULL};
+}
+
+jthrowable globalEnv_CallStaticVoidMethod(jclass clazz, jmethodID methodID) {
+  attach_thread();
+  (*jniEnv)->CallStaticVoidMethod(jniEnv, clazz, methodID);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
+}
+
+jthrowable globalEnv_CallStaticVoidMethodA(jclass clazz,
+                                           jmethodID methodID,
+                                           jvalue* args) {
+  attach_thread();
+  (*jniEnv)->CallStaticVoidMethodA(jniEnv, clazz, methodID, args);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
+}
+
+JniPointerResult globalEnv_GetStaticFieldID(jclass clazz,
+                                            char* name,
+                                            char* sig) {
+  attach_thread();
+  jfieldID _result = (*jniEnv)->GetStaticFieldID(jniEnv, clazz, name, sig);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniPointerResult){.value = NULL, .exception = _exception};
+  }
+  return (JniPointerResult){.value = _result, .exception = NULL};
+}
+
+JniResult globalEnv_GetStaticObjectField(jclass clazz, jfieldID fieldID) {
+  attach_thread();
+  jobject _result = (*jniEnv)->GetStaticObjectField(jniEnv, clazz, fieldID);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  _result = to_global_ref(_result);
+  return (JniResult){.value = {.l = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_GetStaticBooleanField(jclass clazz, jfieldID fieldID) {
+  attach_thread();
+  jboolean _result = (*jniEnv)->GetStaticBooleanField(jniEnv, clazz, fieldID);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.z = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_GetStaticByteField(jclass clazz, jfieldID fieldID) {
+  attach_thread();
+  jbyte _result = (*jniEnv)->GetStaticByteField(jniEnv, clazz, fieldID);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.b = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_GetStaticCharField(jclass clazz, jfieldID fieldID) {
+  attach_thread();
+  jchar _result = (*jniEnv)->GetStaticCharField(jniEnv, clazz, fieldID);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.c = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_GetStaticShortField(jclass clazz, jfieldID fieldID) {
+  attach_thread();
+  jshort _result = (*jniEnv)->GetStaticShortField(jniEnv, clazz, fieldID);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.s = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_GetStaticIntField(jclass clazz, jfieldID fieldID) {
+  attach_thread();
+  jint _result = (*jniEnv)->GetStaticIntField(jniEnv, clazz, fieldID);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.i = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_GetStaticLongField(jclass clazz, jfieldID fieldID) {
+  attach_thread();
+  jlong _result = (*jniEnv)->GetStaticLongField(jniEnv, clazz, fieldID);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.j = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_GetStaticFloatField(jclass clazz, jfieldID fieldID) {
+  attach_thread();
+  jfloat _result = (*jniEnv)->GetStaticFloatField(jniEnv, clazz, fieldID);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.f = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_GetStaticDoubleField(jclass clazz, jfieldID fieldID) {
+  attach_thread();
+  jdouble _result = (*jniEnv)->GetStaticDoubleField(jniEnv, clazz, fieldID);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.d = _result}, .exception = NULL};
+}
+
+jthrowable globalEnv_SetStaticObjectField(jclass clazz,
+                                          jfieldID fieldID,
+                                          jobject val) {
+  attach_thread();
+  (*jniEnv)->SetStaticObjectField(jniEnv, clazz, fieldID, val);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
+}
+
+jthrowable globalEnv_SetStaticBooleanField(jclass clazz,
+                                           jfieldID fieldID,
+                                           jboolean val) {
+  attach_thread();
+  (*jniEnv)->SetStaticBooleanField(jniEnv, clazz, fieldID, val);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
+}
+
+jthrowable globalEnv_SetStaticByteField(jclass clazz,
+                                        jfieldID fieldID,
+                                        jbyte val) {
+  attach_thread();
+  (*jniEnv)->SetStaticByteField(jniEnv, clazz, fieldID, val);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
+}
+
+jthrowable globalEnv_SetStaticCharField(jclass clazz,
+                                        jfieldID fieldID,
+                                        jchar val) {
+  attach_thread();
+  (*jniEnv)->SetStaticCharField(jniEnv, clazz, fieldID, val);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
+}
+
+jthrowable globalEnv_SetStaticShortField(jclass clazz,
+                                         jfieldID fieldID,
+                                         jshort val) {
+  attach_thread();
+  (*jniEnv)->SetStaticShortField(jniEnv, clazz, fieldID, val);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
+}
+
+jthrowable globalEnv_SetStaticIntField(jclass clazz,
+                                       jfieldID fieldID,
+                                       jint val) {
+  attach_thread();
+  (*jniEnv)->SetStaticIntField(jniEnv, clazz, fieldID, val);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
+}
+
+jthrowable globalEnv_SetStaticLongField(jclass clazz,
+                                        jfieldID fieldID,
+                                        jlong val) {
+  attach_thread();
+  (*jniEnv)->SetStaticLongField(jniEnv, clazz, fieldID, val);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
+}
+
+jthrowable globalEnv_SetStaticFloatField(jclass clazz,
+                                         jfieldID fieldID,
+                                         jfloat val) {
+  attach_thread();
+  (*jniEnv)->SetStaticFloatField(jniEnv, clazz, fieldID, val);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
+}
+
+jthrowable globalEnv_SetStaticDoubleField(jclass clazz,
+                                          jfieldID fieldID,
+                                          jdouble val) {
+  attach_thread();
   (*jniEnv)->SetStaticDoubleField(jniEnv, clazz, fieldID, val);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
 }
 
-jstring globalEnv_NewString(const jchar* unicodeChars, jsize len) {
+JniResult globalEnv_NewString(jchar* unicodeChars, jsize len) {
   attach_thread();
-  return to_global_ref((*jniEnv)->NewString(jniEnv, unicodeChars, len));
+  jstring _result = (*jniEnv)->NewString(jniEnv, unicodeChars, len);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  _result = to_global_ref(_result);
+  return (JniResult){.value = {.l = _result}, .exception = NULL};
 }
 
-jsize globalEnv_GetStringLength(jstring string) {
+JniResult globalEnv_GetStringLength(jstring string) {
   attach_thread();
-  return (*jniEnv)->GetStringLength(jniEnv, string);
+  jsize _result = (*jniEnv)->GetStringLength(jniEnv, string);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.i = _result}, .exception = NULL};
 }
 
-const jchar* globalEnv_GetStringChars(jstring string, jboolean* isCopy) {
+JniPointerResult globalEnv_GetStringChars(jstring string, jboolean* isCopy) {
   attach_thread();
-  return (*jniEnv)->GetStringChars(jniEnv, string, isCopy);
+  const jchar* _result = (*jniEnv)->GetStringChars(jniEnv, string, isCopy);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniPointerResult){.value = NULL, .exception = _exception};
+  }
+  return (JniPointerResult){.value = _result, .exception = NULL};
 }
 
-void globalEnv_ReleaseStringChars(jstring string, const jchar* isCopy) {
+jthrowable globalEnv_ReleaseStringChars(jstring string, jchar* isCopy) {
   attach_thread();
   (*jniEnv)->ReleaseStringChars(jniEnv, string, isCopy);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
 }
 
-jstring globalEnv_NewStringUTF(const char* bytes) {
+JniResult globalEnv_NewStringUTF(char* bytes) {
   attach_thread();
-  return to_global_ref((*jniEnv)->NewStringUTF(jniEnv, bytes));
+  jstring _result = (*jniEnv)->NewStringUTF(jniEnv, bytes);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  _result = to_global_ref(_result);
+  return (JniResult){.value = {.l = _result}, .exception = NULL};
 }
 
-jsize globalEnv_GetStringUTFLength(jstring string) {
+JniResult globalEnv_GetStringUTFLength(jstring string) {
   attach_thread();
-  return (*jniEnv)->GetStringUTFLength(jniEnv, string);
+  jsize _result = (*jniEnv)->GetStringUTFLength(jniEnv, string);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.i = _result}, .exception = NULL};
 }
 
-const char* globalEnv_GetStringUTFChars(jstring string, jboolean* isCopy) {
+JniPointerResult globalEnv_GetStringUTFChars(jstring string, jboolean* isCopy) {
   attach_thread();
-  return (*jniEnv)->GetStringUTFChars(jniEnv, string, isCopy);
+  const char* _result = (*jniEnv)->GetStringUTFChars(jniEnv, string, isCopy);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniPointerResult){.value = NULL, .exception = _exception};
+  }
+  return (JniPointerResult){.value = _result, .exception = NULL};
 }
 
-void globalEnv_ReleaseStringUTFChars(jstring string, const char* utf) {
+jthrowable globalEnv_ReleaseStringUTFChars(jstring string, char* utf) {
   attach_thread();
   (*jniEnv)->ReleaseStringUTFChars(jniEnv, string, utf);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
 }
 
-jsize globalEnv_GetArrayLength(jarray array) {
+JniResult globalEnv_GetArrayLength(jarray array) {
   attach_thread();
-  return (*jniEnv)->GetArrayLength(jniEnv, array);
+  jsize _result = (*jniEnv)->GetArrayLength(jniEnv, array);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.i = _result}, .exception = NULL};
 }
 
-jobjectArray globalEnv_NewObjectArray(jsize length,
-                                      jclass elementClass,
-                                      jobject initialElement) {
+JniResult globalEnv_NewObjectArray(jsize length,
+                                   jclass elementClass,
+                                   jobject initialElement) {
   attach_thread();
-  return to_global_ref(
-      (*jniEnv)->NewObjectArray(jniEnv, length, elementClass, initialElement));
+  jobjectArray _result =
+      (*jniEnv)->NewObjectArray(jniEnv, length, elementClass, initialElement);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  _result = to_global_ref(_result);
+  return (JniResult){.value = {.l = _result}, .exception = NULL};
 }
 
-jobject globalEnv_GetObjectArrayElement(jobjectArray array, jsize index) {
+JniResult globalEnv_GetObjectArrayElement(jobjectArray array, jsize index) {
   attach_thread();
-  return to_global_ref((*jniEnv)->GetObjectArrayElement(jniEnv, array, index));
+  jobject _result = (*jniEnv)->GetObjectArrayElement(jniEnv, array, index);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  _result = to_global_ref(_result);
+  return (JniResult){.value = {.l = _result}, .exception = NULL};
 }
 
-void globalEnv_SetObjectArrayElement(jobjectArray array,
-                                     jsize index,
-                                     jobject val) {
+jthrowable globalEnv_SetObjectArrayElement(jobjectArray array,
+                                           jsize index,
+                                           jobject val) {
   attach_thread();
   (*jniEnv)->SetObjectArrayElement(jniEnv, array, index, val);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
 }
 
-jbooleanArray globalEnv_NewBooleanArray(jsize length) {
+JniResult globalEnv_NewBooleanArray(jsize length) {
   attach_thread();
-  return to_global_ref((*jniEnv)->NewBooleanArray(jniEnv, length));
+  jbooleanArray _result = (*jniEnv)->NewBooleanArray(jniEnv, length);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  _result = to_global_ref(_result);
+  return (JniResult){.value = {.l = _result}, .exception = NULL};
 }
 
-jbyteArray globalEnv_NewByteArray(jsize length) {
+JniResult globalEnv_NewByteArray(jsize length) {
   attach_thread();
-  return to_global_ref((*jniEnv)->NewByteArray(jniEnv, length));
+  jbyteArray _result = (*jniEnv)->NewByteArray(jniEnv, length);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  _result = to_global_ref(_result);
+  return (JniResult){.value = {.l = _result}, .exception = NULL};
 }
 
-jcharArray globalEnv_NewCharArray(jsize length) {
+JniResult globalEnv_NewCharArray(jsize length) {
   attach_thread();
-  return to_global_ref((*jniEnv)->NewCharArray(jniEnv, length));
+  jcharArray _result = (*jniEnv)->NewCharArray(jniEnv, length);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  _result = to_global_ref(_result);
+  return (JniResult){.value = {.l = _result}, .exception = NULL};
 }
 
-jshortArray globalEnv_NewShortArray(jsize length) {
+JniResult globalEnv_NewShortArray(jsize length) {
   attach_thread();
-  return to_global_ref((*jniEnv)->NewShortArray(jniEnv, length));
+  jshortArray _result = (*jniEnv)->NewShortArray(jniEnv, length);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  _result = to_global_ref(_result);
+  return (JniResult){.value = {.l = _result}, .exception = NULL};
 }
 
-jintArray globalEnv_NewIntArray(jsize length) {
+JniResult globalEnv_NewIntArray(jsize length) {
   attach_thread();
-  return to_global_ref((*jniEnv)->NewIntArray(jniEnv, length));
+  jintArray _result = (*jniEnv)->NewIntArray(jniEnv, length);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  _result = to_global_ref(_result);
+  return (JniResult){.value = {.l = _result}, .exception = NULL};
 }
 
-jlongArray globalEnv_NewLongArray(jsize length) {
+JniResult globalEnv_NewLongArray(jsize length) {
   attach_thread();
-  return to_global_ref((*jniEnv)->NewLongArray(jniEnv, length));
+  jlongArray _result = (*jniEnv)->NewLongArray(jniEnv, length);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  _result = to_global_ref(_result);
+  return (JniResult){.value = {.l = _result}, .exception = NULL};
 }
 
-jfloatArray globalEnv_NewFloatArray(jsize length) {
+JniResult globalEnv_NewFloatArray(jsize length) {
   attach_thread();
-  return to_global_ref((*jniEnv)->NewFloatArray(jniEnv, length));
+  jfloatArray _result = (*jniEnv)->NewFloatArray(jniEnv, length);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  _result = to_global_ref(_result);
+  return (JniResult){.value = {.l = _result}, .exception = NULL};
 }
 
-jdoubleArray globalEnv_NewDoubleArray(jsize length) {
+JniResult globalEnv_NewDoubleArray(jsize length) {
   attach_thread();
-  return to_global_ref((*jniEnv)->NewDoubleArray(jniEnv, length));
+  jdoubleArray _result = (*jniEnv)->NewDoubleArray(jniEnv, length);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  _result = to_global_ref(_result);
+  return (JniResult){.value = {.l = _result}, .exception = NULL};
 }
 
-jboolean* globalEnv_GetBooleanArrayElements(jbooleanArray array,
-                                            jboolean* isCopy) {
+JniPointerResult globalEnv_GetBooleanArrayElements(jbooleanArray array,
+                                                   jboolean* isCopy) {
   attach_thread();
-  return (*jniEnv)->GetBooleanArrayElements(jniEnv, array, isCopy);
+  jboolean* _result = (*jniEnv)->GetBooleanArrayElements(jniEnv, array, isCopy);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniPointerResult){.value = NULL, .exception = _exception};
+  }
+  return (JniPointerResult){.value = _result, .exception = NULL};
 }
 
-jbyte* globalEnv_GetByteArrayElements(jbyteArray array, jboolean* isCopy) {
+JniPointerResult globalEnv_GetByteArrayElements(jbyteArray array,
+                                                jboolean* isCopy) {
   attach_thread();
-  return (*jniEnv)->GetByteArrayElements(jniEnv, array, isCopy);
+  jbyte* _result = (*jniEnv)->GetByteArrayElements(jniEnv, array, isCopy);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniPointerResult){.value = NULL, .exception = _exception};
+  }
+  return (JniPointerResult){.value = _result, .exception = NULL};
 }
 
-jchar* globalEnv_GetCharArrayElements(jcharArray array, jboolean* isCopy) {
+JniPointerResult globalEnv_GetCharArrayElements(jcharArray array,
+                                                jboolean* isCopy) {
   attach_thread();
-  return (*jniEnv)->GetCharArrayElements(jniEnv, array, isCopy);
+  jchar* _result = (*jniEnv)->GetCharArrayElements(jniEnv, array, isCopy);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniPointerResult){.value = NULL, .exception = _exception};
+  }
+  return (JniPointerResult){.value = _result, .exception = NULL};
 }
 
-jshort* globalEnv_GetShortArrayElements(jshortArray array, jboolean* isCopy) {
+JniPointerResult globalEnv_GetShortArrayElements(jshortArray array,
+                                                 jboolean* isCopy) {
   attach_thread();
-  return (*jniEnv)->GetShortArrayElements(jniEnv, array, isCopy);
+  jshort* _result = (*jniEnv)->GetShortArrayElements(jniEnv, array, isCopy);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniPointerResult){.value = NULL, .exception = _exception};
+  }
+  return (JniPointerResult){.value = _result, .exception = NULL};
 }
 
-jint* globalEnv_GetIntArrayElements(jintArray array, jboolean* isCopy) {
+JniPointerResult globalEnv_GetIntArrayElements(jintArray array,
+                                               jboolean* isCopy) {
   attach_thread();
-  return (*jniEnv)->GetIntArrayElements(jniEnv, array, isCopy);
+  jint* _result = (*jniEnv)->GetIntArrayElements(jniEnv, array, isCopy);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniPointerResult){.value = NULL, .exception = _exception};
+  }
+  return (JniPointerResult){.value = _result, .exception = NULL};
 }
 
-jlong* globalEnv_GetLongArrayElements(jlongArray array, jboolean* isCopy) {
+JniPointerResult globalEnv_GetLongArrayElements(jlongArray array,
+                                                jboolean* isCopy) {
   attach_thread();
-  return (*jniEnv)->GetLongArrayElements(jniEnv, array, isCopy);
+  jlong* _result = (*jniEnv)->GetLongArrayElements(jniEnv, array, isCopy);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniPointerResult){.value = NULL, .exception = _exception};
+  }
+  return (JniPointerResult){.value = _result, .exception = NULL};
 }
 
-jfloat* globalEnv_GetFloatArrayElements(jfloatArray array, jboolean* isCopy) {
+JniPointerResult globalEnv_GetFloatArrayElements(jfloatArray array,
+                                                 jboolean* isCopy) {
   attach_thread();
-  return (*jniEnv)->GetFloatArrayElements(jniEnv, array, isCopy);
+  jfloat* _result = (*jniEnv)->GetFloatArrayElements(jniEnv, array, isCopy);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniPointerResult){.value = NULL, .exception = _exception};
+  }
+  return (JniPointerResult){.value = _result, .exception = NULL};
 }
 
-jdouble* globalEnv_GetDoubleArrayElements(jdoubleArray array,
-                                          jboolean* isCopy) {
+JniPointerResult globalEnv_GetDoubleArrayElements(jdoubleArray array,
+                                                  jboolean* isCopy) {
   attach_thread();
-  return (*jniEnv)->GetDoubleArrayElements(jniEnv, array, isCopy);
+  jdouble* _result = (*jniEnv)->GetDoubleArrayElements(jniEnv, array, isCopy);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniPointerResult){.value = NULL, .exception = _exception};
+  }
+  return (JniPointerResult){.value = _result, .exception = NULL};
 }
 
-void globalEnv_ReleaseBooleanArrayElements(jbooleanArray array,
-                                           jboolean* elems,
-                                           jint mode) {
+jthrowable globalEnv_ReleaseBooleanArrayElements(jbooleanArray array,
+                                                 jboolean* elems,
+                                                 jint mode) {
   attach_thread();
   (*jniEnv)->ReleaseBooleanArrayElements(jniEnv, array, elems, mode);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
 }
 
-void globalEnv_ReleaseByteArrayElements(jbyteArray array,
-                                        jbyte* elems,
-                                        jint mode) {
+jthrowable globalEnv_ReleaseByteArrayElements(jbyteArray array,
+                                              jbyte* elems,
+                                              jint mode) {
   attach_thread();
   (*jniEnv)->ReleaseByteArrayElements(jniEnv, array, elems, mode);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
 }
 
-void globalEnv_ReleaseCharArrayElements(jcharArray array,
-                                        jchar* elems,
-                                        jint mode) {
+jthrowable globalEnv_ReleaseCharArrayElements(jcharArray array,
+                                              jchar* elems,
+                                              jint mode) {
   attach_thread();
   (*jniEnv)->ReleaseCharArrayElements(jniEnv, array, elems, mode);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
 }
 
-void globalEnv_ReleaseShortArrayElements(jshortArray array,
-                                         jshort* elems,
-                                         jint mode) {
+jthrowable globalEnv_ReleaseShortArrayElements(jshortArray array,
+                                               jshort* elems,
+                                               jint mode) {
   attach_thread();
   (*jniEnv)->ReleaseShortArrayElements(jniEnv, array, elems, mode);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
 }
 
-void globalEnv_ReleaseIntArrayElements(jintArray array,
-                                       jint* elems,
-                                       jint mode) {
-  attach_thread();
-  (*jniEnv)->ReleaseIntArrayElements(jniEnv, array, elems, mode);
-}
-
-void globalEnv_ReleaseLongArrayElements(jlongArray array,
-                                        jlong* elems,
-                                        jint mode) {
-  attach_thread();
-  (*jniEnv)->ReleaseLongArrayElements(jniEnv, array, elems, mode);
-}
-
-void globalEnv_ReleaseFloatArrayElements(jfloatArray array,
-                                         jfloat* elems,
-                                         jint mode) {
-  attach_thread();
-  (*jniEnv)->ReleaseFloatArrayElements(jniEnv, array, elems, mode);
-}
-
-void globalEnv_ReleaseDoubleArrayElements(jdoubleArray array,
-                                          jdouble* elems,
-                                          jint mode) {
-  attach_thread();
-  (*jniEnv)->ReleaseDoubleArrayElements(jniEnv, array, elems, mode);
-}
-
-void globalEnv_GetBooleanArrayRegion(jbooleanArray array,
-                                     jsize start,
-                                     jsize len,
-                                     jboolean* buf) {
-  attach_thread();
-  (*jniEnv)->GetBooleanArrayRegion(jniEnv, array, start, len, buf);
-}
-
-void globalEnv_GetByteArrayRegion(jbyteArray array,
-                                  jsize start,
-                                  jsize len,
-                                  jbyte* buf) {
-  attach_thread();
-  (*jniEnv)->GetByteArrayRegion(jniEnv, array, start, len, buf);
-}
-
-void globalEnv_GetCharArrayRegion(jcharArray array,
-                                  jsize start,
-                                  jsize len,
-                                  jchar* buf) {
-  attach_thread();
-  (*jniEnv)->GetCharArrayRegion(jniEnv, array, start, len, buf);
-}
-
-void globalEnv_GetShortArrayRegion(jshortArray array,
-                                   jsize start,
-                                   jsize len,
-                                   jshort* buf) {
-  attach_thread();
-  (*jniEnv)->GetShortArrayRegion(jniEnv, array, start, len, buf);
-}
-
-void globalEnv_GetIntArrayRegion(jintArray array,
-                                 jsize start,
-                                 jsize len,
-                                 jint* buf) {
-  attach_thread();
-  (*jniEnv)->GetIntArrayRegion(jniEnv, array, start, len, buf);
-}
-
-void globalEnv_GetLongArrayRegion(jlongArray array,
-                                  jsize start,
-                                  jsize len,
-                                  jlong* buf) {
-  attach_thread();
-  (*jniEnv)->GetLongArrayRegion(jniEnv, array, start, len, buf);
-}
-
-void globalEnv_GetFloatArrayRegion(jfloatArray array,
-                                   jsize start,
-                                   jsize len,
-                                   jfloat* buf) {
-  attach_thread();
-  (*jniEnv)->GetFloatArrayRegion(jniEnv, array, start, len, buf);
-}
-
-void globalEnv_GetDoubleArrayRegion(jdoubleArray array,
-                                    jsize start,
-                                    jsize len,
-                                    jdouble* buf) {
-  attach_thread();
-  (*jniEnv)->GetDoubleArrayRegion(jniEnv, array, start, len, buf);
-}
-
-void globalEnv_SetBooleanArrayRegion(jbooleanArray array,
-                                     jsize start,
-                                     jsize len,
-                                     const jboolean* buf) {
-  attach_thread();
-  (*jniEnv)->SetBooleanArrayRegion(jniEnv, array, start, len, buf);
-}
-
-void globalEnv_SetByteArrayRegion(jbyteArray array,
-                                  jsize start,
-                                  jsize len,
-                                  const jbyte* buf) {
-  attach_thread();
-  (*jniEnv)->SetByteArrayRegion(jniEnv, array, start, len, buf);
-}
-
-void globalEnv_SetCharArrayRegion(jcharArray array,
-                                  jsize start,
-                                  jsize len,
-                                  const jchar* buf) {
-  attach_thread();
-  (*jniEnv)->SetCharArrayRegion(jniEnv, array, start, len, buf);
-}
-
-void globalEnv_SetShortArrayRegion(jshortArray array,
-                                   jsize start,
-                                   jsize len,
-                                   const jshort* buf) {
-  attach_thread();
-  (*jniEnv)->SetShortArrayRegion(jniEnv, array, start, len, buf);
-}
-
-void globalEnv_SetIntArrayRegion(jintArray array,
-                                 jsize start,
-                                 jsize len,
-                                 const jint* buf) {
-  attach_thread();
-  (*jniEnv)->SetIntArrayRegion(jniEnv, array, start, len, buf);
-}
-
-void globalEnv_SetLongArrayRegion(jlongArray array,
-                                  jsize start,
-                                  jsize len,
-                                  const jlong* buf) {
-  attach_thread();
-  (*jniEnv)->SetLongArrayRegion(jniEnv, array, start, len, buf);
-}
-
-void globalEnv_SetFloatArrayRegion(jfloatArray array,
-                                   jsize start,
-                                   jsize len,
-                                   const jfloat* buf) {
-  attach_thread();
-  (*jniEnv)->SetFloatArrayRegion(jniEnv, array, start, len, buf);
-}
-
-void globalEnv_SetDoubleArrayRegion(jdoubleArray array,
-                                    jsize start,
-                                    jsize len,
-                                    const jdouble* buf) {
-  attach_thread();
-  (*jniEnv)->SetDoubleArrayRegion(jniEnv, array, start, len, buf);
-}
-
-jint globalEnv_RegisterNatives(jclass clazz,
-                               const JNINativeMethod* methods,
-                               jint nMethods) {
-  attach_thread();
-  return (*jniEnv)->RegisterNatives(jniEnv, clazz, methods, nMethods);
-}
-
-jint globalEnv_UnregisterNatives(jclass clazz) {
-  attach_thread();
-  return (*jniEnv)->UnregisterNatives(jniEnv, clazz);
-}
-
-jint globalEnv_MonitorEnter(jobject obj) {
-  attach_thread();
-  return (*jniEnv)->MonitorEnter(jniEnv, obj);
-}
-
-jint globalEnv_MonitorExit(jobject obj) {
-  attach_thread();
-  return (*jniEnv)->MonitorExit(jniEnv, obj);
-}
-
-jint globalEnv_GetJavaVM(JavaVM** vm) {
-  attach_thread();
-  return (*jniEnv)->GetJavaVM(jniEnv, vm);
-}
-
-void globalEnv_GetStringRegion(jstring str,
-                               jsize start,
-                               jsize len,
-                               jchar* buf) {
-  attach_thread();
-  (*jniEnv)->GetStringRegion(jniEnv, str, start, len, buf);
-}
-
-void globalEnv_GetStringUTFRegion(jstring str,
-                                  jsize start,
-                                  jsize len,
-                                  char* buf) {
-  attach_thread();
-  (*jniEnv)->GetStringUTFRegion(jniEnv, str, start, len, buf);
-}
-
-void* globalEnv_GetPrimitiveArrayCritical(jarray array, jboolean* isCopy) {
-  attach_thread();
-  return (*jniEnv)->GetPrimitiveArrayCritical(jniEnv, array, isCopy);
-}
-
-void globalEnv_ReleasePrimitiveArrayCritical(jarray array,
-                                             void* carray,
+jthrowable globalEnv_ReleaseIntArrayElements(jintArray array,
+                                             jint* elems,
                                              jint mode) {
   attach_thread();
-  (*jniEnv)->ReleasePrimitiveArrayCritical(jniEnv, array, carray, mode);
+  (*jniEnv)->ReleaseIntArrayElements(jniEnv, array, elems, mode);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
 }
 
-const jchar* globalEnv_GetStringCritical(jstring str, jboolean* isCopy) {
+jthrowable globalEnv_ReleaseLongArrayElements(jlongArray array,
+                                              jlong* elems,
+                                              jint mode) {
   attach_thread();
-  return (*jniEnv)->GetStringCritical(jniEnv, str, isCopy);
+  (*jniEnv)->ReleaseLongArrayElements(jniEnv, array, elems, mode);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
 }
 
-void globalEnv_ReleaseStringCritical(jstring str, const jchar* carray) {
+jthrowable globalEnv_ReleaseFloatArrayElements(jfloatArray array,
+                                               jfloat* elems,
+                                               jint mode) {
+  attach_thread();
+  (*jniEnv)->ReleaseFloatArrayElements(jniEnv, array, elems, mode);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
+}
+
+jthrowable globalEnv_ReleaseDoubleArrayElements(jdoubleArray array,
+                                                jdouble* elems,
+                                                jint mode) {
+  attach_thread();
+  (*jniEnv)->ReleaseDoubleArrayElements(jniEnv, array, elems, mode);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
+}
+
+jthrowable globalEnv_GetBooleanArrayRegion(jbooleanArray array,
+                                           jsize start,
+                                           jsize len,
+                                           jboolean* buf) {
+  attach_thread();
+  (*jniEnv)->GetBooleanArrayRegion(jniEnv, array, start, len, buf);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
+}
+
+jthrowable globalEnv_GetByteArrayRegion(jbyteArray array,
+                                        jsize start,
+                                        jsize len,
+                                        jbyte* buf) {
+  attach_thread();
+  (*jniEnv)->GetByteArrayRegion(jniEnv, array, start, len, buf);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
+}
+
+jthrowable globalEnv_GetCharArrayRegion(jcharArray array,
+                                        jsize start,
+                                        jsize len,
+                                        jchar* buf) {
+  attach_thread();
+  (*jniEnv)->GetCharArrayRegion(jniEnv, array, start, len, buf);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
+}
+
+jthrowable globalEnv_GetShortArrayRegion(jshortArray array,
+                                         jsize start,
+                                         jsize len,
+                                         jshort* buf) {
+  attach_thread();
+  (*jniEnv)->GetShortArrayRegion(jniEnv, array, start, len, buf);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
+}
+
+jthrowable globalEnv_GetIntArrayRegion(jintArray array,
+                                       jsize start,
+                                       jsize len,
+                                       jint* buf) {
+  attach_thread();
+  (*jniEnv)->GetIntArrayRegion(jniEnv, array, start, len, buf);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
+}
+
+jthrowable globalEnv_GetLongArrayRegion(jlongArray array,
+                                        jsize start,
+                                        jsize len,
+                                        jlong* buf) {
+  attach_thread();
+  (*jniEnv)->GetLongArrayRegion(jniEnv, array, start, len, buf);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
+}
+
+jthrowable globalEnv_GetFloatArrayRegion(jfloatArray array,
+                                         jsize start,
+                                         jsize len,
+                                         jfloat* buf) {
+  attach_thread();
+  (*jniEnv)->GetFloatArrayRegion(jniEnv, array, start, len, buf);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
+}
+
+jthrowable globalEnv_GetDoubleArrayRegion(jdoubleArray array,
+                                          jsize start,
+                                          jsize len,
+                                          jdouble* buf) {
+  attach_thread();
+  (*jniEnv)->GetDoubleArrayRegion(jniEnv, array, start, len, buf);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
+}
+
+jthrowable globalEnv_SetBooleanArrayRegion(jbooleanArray array,
+                                           jsize start,
+                                           jsize len,
+                                           jboolean* buf) {
+  attach_thread();
+  (*jniEnv)->SetBooleanArrayRegion(jniEnv, array, start, len, buf);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
+}
+
+jthrowable globalEnv_SetByteArrayRegion(jbyteArray array,
+                                        jsize start,
+                                        jsize len,
+                                        jbyte* buf) {
+  attach_thread();
+  (*jniEnv)->SetByteArrayRegion(jniEnv, array, start, len, buf);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
+}
+
+jthrowable globalEnv_SetCharArrayRegion(jcharArray array,
+                                        jsize start,
+                                        jsize len,
+                                        jchar* buf) {
+  attach_thread();
+  (*jniEnv)->SetCharArrayRegion(jniEnv, array, start, len, buf);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
+}
+
+jthrowable globalEnv_SetShortArrayRegion(jshortArray array,
+                                         jsize start,
+                                         jsize len,
+                                         jshort* buf) {
+  attach_thread();
+  (*jniEnv)->SetShortArrayRegion(jniEnv, array, start, len, buf);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
+}
+
+jthrowable globalEnv_SetIntArrayRegion(jintArray array,
+                                       jsize start,
+                                       jsize len,
+                                       jint* buf) {
+  attach_thread();
+  (*jniEnv)->SetIntArrayRegion(jniEnv, array, start, len, buf);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
+}
+
+jthrowable globalEnv_SetLongArrayRegion(jlongArray array,
+                                        jsize start,
+                                        jsize len,
+                                        jlong* buf) {
+  attach_thread();
+  (*jniEnv)->SetLongArrayRegion(jniEnv, array, start, len, buf);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
+}
+
+jthrowable globalEnv_SetFloatArrayRegion(jfloatArray array,
+                                         jsize start,
+                                         jsize len,
+                                         jfloat* buf) {
+  attach_thread();
+  (*jniEnv)->SetFloatArrayRegion(jniEnv, array, start, len, buf);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
+}
+
+jthrowable globalEnv_SetDoubleArrayRegion(jdoubleArray array,
+                                          jsize start,
+                                          jsize len,
+                                          jdouble* buf) {
+  attach_thread();
+  (*jniEnv)->SetDoubleArrayRegion(jniEnv, array, start, len, buf);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
+}
+
+JniResult globalEnv_RegisterNatives(jclass clazz,
+                                    JNINativeMethod* methods,
+                                    jint nMethods) {
+  attach_thread();
+  jint _result = (*jniEnv)->RegisterNatives(jniEnv, clazz, methods, nMethods);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.i = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_UnregisterNatives(jclass clazz) {
+  attach_thread();
+  jint _result = (*jniEnv)->UnregisterNatives(jniEnv, clazz);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.i = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_MonitorEnter(jobject obj) {
+  attach_thread();
+  jint _result = (*jniEnv)->MonitorEnter(jniEnv, obj);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.i = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_MonitorExit(jobject obj) {
+  attach_thread();
+  jint _result = (*jniEnv)->MonitorExit(jniEnv, obj);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.i = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_GetJavaVM(JavaVM** vm) {
+  attach_thread();
+  jint _result = (*jniEnv)->GetJavaVM(jniEnv, vm);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.i = _result}, .exception = NULL};
+}
+
+jthrowable globalEnv_GetStringRegion(jstring str,
+                                     jsize start,
+                                     jsize len,
+                                     jchar* buf) {
+  attach_thread();
+  (*jniEnv)->GetStringRegion(jniEnv, str, start, len, buf);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
+}
+
+jthrowable globalEnv_GetStringUTFRegion(jstring str,
+                                        jsize start,
+                                        jsize len,
+                                        char* buf) {
+  attach_thread();
+  (*jniEnv)->GetStringUTFRegion(jniEnv, str, start, len, buf);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
+}
+
+JniPointerResult globalEnv_GetPrimitiveArrayCritical(jarray array,
+                                                     jboolean* isCopy) {
+  attach_thread();
+  void* _result = (*jniEnv)->GetPrimitiveArrayCritical(jniEnv, array, isCopy);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniPointerResult){.value = NULL, .exception = _exception};
+  }
+  return (JniPointerResult){.value = _result, .exception = NULL};
+}
+
+jthrowable globalEnv_ReleasePrimitiveArrayCritical(jarray array,
+                                                   void* carray,
+                                                   jint mode) {
+  attach_thread();
+  (*jniEnv)->ReleasePrimitiveArrayCritical(jniEnv, array, carray, mode);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
+}
+
+JniPointerResult globalEnv_GetStringCritical(jstring str, jboolean* isCopy) {
+  attach_thread();
+  const jchar* _result = (*jniEnv)->GetStringCritical(jniEnv, str, isCopy);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniPointerResult){.value = NULL, .exception = _exception};
+  }
+  return (JniPointerResult){.value = _result, .exception = NULL};
+}
+
+jthrowable globalEnv_ReleaseStringCritical(jstring str, jchar* carray) {
   attach_thread();
   (*jniEnv)->ReleaseStringCritical(jniEnv, str, carray);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
 }
 
-jweak globalEnv_NewWeakGlobalRef(jobject obj) {
+JniResult globalEnv_NewWeakGlobalRef(jobject obj) {
   attach_thread();
-  return to_global_ref((*jniEnv)->NewWeakGlobalRef(jniEnv, obj));
+  jweak _result = (*jniEnv)->NewWeakGlobalRef(jniEnv, obj);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.l = _result}, .exception = NULL};
 }
 
-void globalEnv_DeleteWeakGlobalRef(jweak obj) {
+jthrowable globalEnv_DeleteWeakGlobalRef(jweak obj) {
   attach_thread();
   (*jniEnv)->DeleteWeakGlobalRef(jniEnv, obj);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return _exception;
+  }
+  return NULL;
 }
 
-jboolean globalEnv_ExceptionCheck() {
+JniResult globalEnv_ExceptionCheck() {
   attach_thread();
-  return (*jniEnv)->ExceptionCheck(jniEnv);
+  jboolean _result = (*jniEnv)->ExceptionCheck(jniEnv);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.z = _result}, .exception = NULL};
 }
 
-jobject globalEnv_NewDirectByteBuffer(void* address, jlong capacity) {
+JniResult globalEnv_NewDirectByteBuffer(void* address, jlong capacity) {
   attach_thread();
-  return to_global_ref(
-      (*jniEnv)->NewDirectByteBuffer(jniEnv, address, capacity));
+  jobject _result = (*jniEnv)->NewDirectByteBuffer(jniEnv, address, capacity);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  _result = to_global_ref(_result);
+  return (JniResult){.value = {.l = _result}, .exception = NULL};
 }
 
-void* globalEnv_GetDirectBufferAddress(jobject buf) {
+JniPointerResult globalEnv_GetDirectBufferAddress(jobject buf) {
   attach_thread();
-  return (*jniEnv)->GetDirectBufferAddress(jniEnv, buf);
+  void* _result = (*jniEnv)->GetDirectBufferAddress(jniEnv, buf);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniPointerResult){.value = NULL, .exception = _exception};
+  }
+  return (JniPointerResult){.value = _result, .exception = NULL};
 }
 
-jlong globalEnv_GetDirectBufferCapacity(jobject buf) {
+JniResult globalEnv_GetDirectBufferCapacity(jobject buf) {
   attach_thread();
-  return (*jniEnv)->GetDirectBufferCapacity(jniEnv, buf);
+  jlong _result = (*jniEnv)->GetDirectBufferCapacity(jniEnv, buf);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.j = _result}, .exception = NULL};
 }
 
-jobjectRefType globalEnv_GetObjectRefType(jobject obj) {
+JniResult globalEnv_GetObjectRefType(jobject obj) {
   attach_thread();
-  return (*jniEnv)->GetObjectRefType(jniEnv, obj);
+  int32_t _result = (*jniEnv)->GetObjectRefType(jniEnv, obj);
+  jthrowable _exception = check_exception();
+  if (_exception != NULL) {
+    return (JniResult){.value = {.j = 0}, .exception = _exception};
+  }
+  return (JniResult){.value = {.i = _result}, .exception = NULL};
 }
 
 GlobalJniEnv globalJniEnv = {
+    .reserved0 = NULL,
+    .reserved1 = NULL,
+    .reserved2 = NULL,
+    .reserved3 = NULL,
     .GetVersion = globalEnv_GetVersion,
     .DefineClass = globalEnv_DefineClass,
     .FindClass = globalEnv_FindClass,
@@ -1229,53 +2293,76 @@
     .PopLocalFrame = globalEnv_PopLocalFrame,
     .NewGlobalRef = globalEnv_NewGlobalRef,
     .DeleteGlobalRef = globalEnv_DeleteGlobalRef,
+    .DeleteLocalRef = globalEnv_DeleteLocalRef,
     .IsSameObject = globalEnv_IsSameObject,
+    .NewLocalRef = globalEnv_NewLocalRef,
     .EnsureLocalCapacity = globalEnv_EnsureLocalCapacity,
     .AllocObject = globalEnv_AllocObject,
     .NewObject = globalEnv_NewObject,
+    .NewObjectV = NULL,
     .NewObjectA = globalEnv_NewObjectA,
     .GetObjectClass = globalEnv_GetObjectClass,
     .IsInstanceOf = globalEnv_IsInstanceOf,
     .GetMethodID = globalEnv_GetMethodID,
     .CallObjectMethod = globalEnv_CallObjectMethod,
+    .CallObjectMethodV = NULL,
     .CallObjectMethodA = globalEnv_CallObjectMethodA,
     .CallBooleanMethod = globalEnv_CallBooleanMethod,
+    .CallBooleanMethodV = NULL,
     .CallBooleanMethodA = globalEnv_CallBooleanMethodA,
     .CallByteMethod = globalEnv_CallByteMethod,
+    .CallByteMethodV = NULL,
     .CallByteMethodA = globalEnv_CallByteMethodA,
     .CallCharMethod = globalEnv_CallCharMethod,
+    .CallCharMethodV = NULL,
     .CallCharMethodA = globalEnv_CallCharMethodA,
     .CallShortMethod = globalEnv_CallShortMethod,
+    .CallShortMethodV = NULL,
     .CallShortMethodA = globalEnv_CallShortMethodA,
     .CallIntMethod = globalEnv_CallIntMethod,
+    .CallIntMethodV = NULL,
     .CallIntMethodA = globalEnv_CallIntMethodA,
     .CallLongMethod = globalEnv_CallLongMethod,
+    .CallLongMethodV = NULL,
     .CallLongMethodA = globalEnv_CallLongMethodA,
     .CallFloatMethod = globalEnv_CallFloatMethod,
+    .CallFloatMethodV = NULL,
     .CallFloatMethodA = globalEnv_CallFloatMethodA,
     .CallDoubleMethod = globalEnv_CallDoubleMethod,
+    .CallDoubleMethodV = NULL,
     .CallDoubleMethodA = globalEnv_CallDoubleMethodA,
     .CallVoidMethod = globalEnv_CallVoidMethod,
+    .CallVoidMethodV = NULL,
     .CallVoidMethodA = globalEnv_CallVoidMethodA,
     .CallNonvirtualObjectMethod = globalEnv_CallNonvirtualObjectMethod,
+    .CallNonvirtualObjectMethodV = NULL,
     .CallNonvirtualObjectMethodA = globalEnv_CallNonvirtualObjectMethodA,
     .CallNonvirtualBooleanMethod = globalEnv_CallNonvirtualBooleanMethod,
+    .CallNonvirtualBooleanMethodV = NULL,
     .CallNonvirtualBooleanMethodA = globalEnv_CallNonvirtualBooleanMethodA,
     .CallNonvirtualByteMethod = globalEnv_CallNonvirtualByteMethod,
+    .CallNonvirtualByteMethodV = NULL,
     .CallNonvirtualByteMethodA = globalEnv_CallNonvirtualByteMethodA,
     .CallNonvirtualCharMethod = globalEnv_CallNonvirtualCharMethod,
+    .CallNonvirtualCharMethodV = NULL,
     .CallNonvirtualCharMethodA = globalEnv_CallNonvirtualCharMethodA,
     .CallNonvirtualShortMethod = globalEnv_CallNonvirtualShortMethod,
+    .CallNonvirtualShortMethodV = NULL,
     .CallNonvirtualShortMethodA = globalEnv_CallNonvirtualShortMethodA,
     .CallNonvirtualIntMethod = globalEnv_CallNonvirtualIntMethod,
+    .CallNonvirtualIntMethodV = NULL,
     .CallNonvirtualIntMethodA = globalEnv_CallNonvirtualIntMethodA,
     .CallNonvirtualLongMethod = globalEnv_CallNonvirtualLongMethod,
+    .CallNonvirtualLongMethodV = NULL,
     .CallNonvirtualLongMethodA = globalEnv_CallNonvirtualLongMethodA,
     .CallNonvirtualFloatMethod = globalEnv_CallNonvirtualFloatMethod,
+    .CallNonvirtualFloatMethodV = NULL,
     .CallNonvirtualFloatMethodA = globalEnv_CallNonvirtualFloatMethodA,
     .CallNonvirtualDoubleMethod = globalEnv_CallNonvirtualDoubleMethod,
+    .CallNonvirtualDoubleMethodV = NULL,
     .CallNonvirtualDoubleMethodA = globalEnv_CallNonvirtualDoubleMethodA,
     .CallNonvirtualVoidMethod = globalEnv_CallNonvirtualVoidMethod,
+    .CallNonvirtualVoidMethodV = NULL,
     .CallNonvirtualVoidMethodA = globalEnv_CallNonvirtualVoidMethodA,
     .GetFieldID = globalEnv_GetFieldID,
     .GetObjectField = globalEnv_GetObjectField,
@@ -1298,24 +2385,34 @@
     .SetDoubleField = globalEnv_SetDoubleField,
     .GetStaticMethodID = globalEnv_GetStaticMethodID,
     .CallStaticObjectMethod = globalEnv_CallStaticObjectMethod,
+    .CallStaticObjectMethodV = NULL,
     .CallStaticObjectMethodA = globalEnv_CallStaticObjectMethodA,
     .CallStaticBooleanMethod = globalEnv_CallStaticBooleanMethod,
+    .CallStaticBooleanMethodV = NULL,
     .CallStaticBooleanMethodA = globalEnv_CallStaticBooleanMethodA,
     .CallStaticByteMethod = globalEnv_CallStaticByteMethod,
+    .CallStaticByteMethodV = NULL,
     .CallStaticByteMethodA = globalEnv_CallStaticByteMethodA,
     .CallStaticCharMethod = globalEnv_CallStaticCharMethod,
+    .CallStaticCharMethodV = NULL,
     .CallStaticCharMethodA = globalEnv_CallStaticCharMethodA,
     .CallStaticShortMethod = globalEnv_CallStaticShortMethod,
+    .CallStaticShortMethodV = NULL,
     .CallStaticShortMethodA = globalEnv_CallStaticShortMethodA,
     .CallStaticIntMethod = globalEnv_CallStaticIntMethod,
+    .CallStaticIntMethodV = NULL,
     .CallStaticIntMethodA = globalEnv_CallStaticIntMethodA,
     .CallStaticLongMethod = globalEnv_CallStaticLongMethod,
+    .CallStaticLongMethodV = NULL,
     .CallStaticLongMethodA = globalEnv_CallStaticLongMethodA,
     .CallStaticFloatMethod = globalEnv_CallStaticFloatMethod,
+    .CallStaticFloatMethodV = NULL,
     .CallStaticFloatMethodA = globalEnv_CallStaticFloatMethodA,
     .CallStaticDoubleMethod = globalEnv_CallStaticDoubleMethod,
+    .CallStaticDoubleMethodV = NULL,
     .CallStaticDoubleMethodA = globalEnv_CallStaticDoubleMethodA,
     .CallStaticVoidMethod = globalEnv_CallStaticVoidMethod,
+    .CallStaticVoidMethodV = NULL,
     .CallStaticVoidMethodA = globalEnv_CallStaticVoidMethodA,
     .GetStaticFieldID = globalEnv_GetStaticFieldID,
     .GetStaticObjectField = globalEnv_GetStaticObjectField,
@@ -1407,11 +2504,10 @@
     .GetDirectBufferCapacity = globalEnv_GetDirectBufferCapacity,
     .GetObjectRefType = globalEnv_GetObjectRefType,
 };
-
 FFI_PLUGIN_EXPORT
 GlobalJniEnv* GetGlobalEnv() {
-  if (jni.jvm == NULL) {
+  if (jni->jvm == NULL) {
     return NULL;
   }
   return &globalJniEnv;
-}
\ No newline at end of file
+}
diff --git a/pkgs/jni/src/third_party/global_jni_env.h b/pkgs/jni/src/third_party/global_jni_env.h
index e4229c6..8966d2b 100644
--- a/pkgs/jni/src/third_party/global_jni_env.h
+++ b/pkgs/jni/src/third_party/global_jni_env.h
@@ -1,375 +1,434 @@
-// Generated from an annotated version of jni.h provided in Android NDK.
-// (NDK Version 23.1.7779620)
-// The license for original file is provided below:
+// Auto generated file. Do not edit.
+
+// This is generated from JNI header in Android NDK. License for the same is
+// provided below.
 
 /*
-   * Copyright (C) 2006 The Android Open Source Project
-   *
-   * Licensed under the Apache License, Version 2.0 (the "License");
-   * you may not use this file except in compliance with the License.
-   * You may obtain a copy of the License at
-   *
-   *      http://www.apache.org/licenses/LICENSE-2.0
-   *
-   * Unless required by applicable law or agreed to in writing, software
-   * distributed under the License is distributed on an "AS IS" BASIS,
-   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   * See the License for the specific language governing permissions and
-   * limitations under the License.
-   */
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
-#include <jni.h>
-/// Wrapper over JNIEnv in the JNI API, which can be used from multiple Dart
-/// Threads.
-///
-/// It consists of wrappers to JNIEnv methods which manage the thread-local
-/// JNIEnv pointer in C code. Additionally, any returned local reference value
-/// is converted to global reference.
-///
-/// For the documentation on methods themselves, see the JNI Specification at
-/// https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html
-///
-/// Apart from the specification, the Android NDK's JNI page consists of useful
-/// information about using the JNI:
-/// https://developer.android.com/training/articles/perf-jni
+/*
+ * JNI specification, as defined by Sun:
+ * http://java.sun.com/javase/6/docs/technotes/guides/jni/spec/jniTOC.html
+ *
+ * Everything here is expected to be VM-neutral.
+ */
+
+#include <stdint.h>
+#include "../dartjni.h"
+
 typedef struct GlobalJniEnv {
-  jint (*GetVersion)();
-  jclass (*DefineClass)(const char* name,
-                        jobject loader,
-                        const jbyte* buf,
-                        jsize bufLen);
-  jclass (*FindClass)(const char* name);
-  jmethodID (*FromReflectedMethod)(jobject method);
-  jfieldID (*FromReflectedField)(jobject field);
-  jobject (*ToReflectedMethod)(jclass cls,
-                               jmethodID methodId,
-                               jboolean isStatic);
-  jclass (*GetSuperclass)(jclass clazz);
-  jboolean (*IsAssignableFrom)(jclass clazz1, jclass clazz2);
-  jobject (*ToReflectedField)(jclass cls, jfieldID fieldID, jboolean isStatic);
-  jint (*Throw)(jthrowable obj);
-  jint (*ThrowNew)(jclass clazz, const char* message);
-  jthrowable (*ExceptionOccurred)();
-  void (*ExceptionDescribe)();
-  void (*ExceptionClear)();
-  void (*FatalError)(const char* msg);
-  jint (*PushLocalFrame)(jint capacity);
-  jobject (*PopLocalFrame)(jobject result);
-  jobject (*NewGlobalRef)(jobject obj);
-  void (*DeleteGlobalRef)(jobject globalRef);
-  jboolean (*IsSameObject)(jobject ref1, jobject ref2);
-  jint (*EnsureLocalCapacity)(jint capacity);
-  jobject (*AllocObject)(jclass clazz);
-  jobject (*NewObject)(jclass arg1, jmethodID arg2);
-  jobject (*NewObjectA)(jclass clazz, jmethodID methodID, const jvalue* args);
-  jclass (*GetObjectClass)(jobject obj);
-  jboolean (*IsInstanceOf)(jobject obj, jclass clazz);
-  jmethodID (*GetMethodID)(jclass clazz, const char* name, const char* sig);
-  jobject (*CallObjectMethod)(jobject arg1, jmethodID arg2);
-  jobject (*CallObjectMethodA)(jobject obj,
-                               jmethodID methodID,
-                               const jvalue* args);
-  jboolean (*CallBooleanMethod)(jobject arg1, jmethodID arg2);
-  jboolean (*CallBooleanMethodA)(jobject obj,
+  void* reserved0;
+  void* reserved1;
+  void* reserved2;
+  void* reserved3;
+  JniResult (*GetVersion)();
+  JniClassLookupResult (*DefineClass)(char* name,
+                                      jobject loader,
+                                      jbyte* buf,
+                                      jsize bufLen);
+  JniClassLookupResult (*FindClass)(char* name);
+  JniPointerResult (*FromReflectedMethod)(jobject method);
+  JniPointerResult (*FromReflectedField)(jobject field);
+  JniResult (*ToReflectedMethod)(jclass cls,
                                  jmethodID methodId,
-                                 const jvalue* args);
-  jbyte (*CallByteMethod)(jobject arg1, jmethodID arg2);
-  jbyte (*CallByteMethodA)(jobject obj, jmethodID methodID, const jvalue* args);
-  jchar (*CallCharMethod)(jobject arg1, jmethodID arg2);
-  jchar (*CallCharMethodA)(jobject obj, jmethodID methodID, const jvalue* args);
-  jshort (*CallShortMethod)(jobject arg1, jmethodID arg2);
-  jshort (*CallShortMethodA)(jobject obj,
-                             jmethodID methodID,
-                             const jvalue* args);
-  jint (*CallIntMethod)(jobject arg1, jmethodID arg2);
-  jint (*CallIntMethodA)(jobject obj, jmethodID methodID, const jvalue* args);
-  jlong (*CallLongMethod)(jobject arg1, jmethodID arg2);
-  jlong (*CallLongMethodA)(jobject obj, jmethodID methodID, const jvalue* args);
-  jfloat (*CallFloatMethod)(jobject arg1, jmethodID arg2);
-  jfloat (*CallFloatMethodA)(jobject obj,
-                             jmethodID methodID,
-                             const jvalue* args);
-  jdouble (*CallDoubleMethod)(jobject arg1, jmethodID arg2);
-  jdouble (*CallDoubleMethodA)(jobject obj,
-                               jmethodID methodID,
-                               const jvalue* args);
-  void (*CallVoidMethod)(jobject arg1, jmethodID arg2);
-  void (*CallVoidMethodA)(jobject obj, jmethodID methodID, const jvalue* args);
-  jobject (*CallNonvirtualObjectMethod)(jobject arg1,
-                                        jclass arg2,
-                                        jmethodID arg3);
-  jobject (*CallNonvirtualObjectMethodA)(jobject obj,
-                                         jclass clazz,
-                                         jmethodID methodID,
-                                         const jvalue* args);
-  jboolean (*CallNonvirtualBooleanMethod)(jobject arg1,
-                                          jclass arg2,
-                                          jmethodID arg3);
-  jboolean (*CallNonvirtualBooleanMethodA)(jobject obj,
+                                 jboolean isStatic);
+  JniClassLookupResult (*GetSuperclass)(jclass clazz);
+  JniResult (*IsAssignableFrom)(jclass clazz1, jclass clazz2);
+  JniResult (*ToReflectedField)(jclass cls,
+                                jfieldID fieldID,
+                                jboolean isStatic);
+  JniResult (*Throw)(jthrowable obj);
+  JniResult (*ThrowNew)(jclass clazz, char* message);
+  JniResult (*ExceptionOccurred)();
+  jthrowable (*ExceptionDescribe)();
+  jthrowable (*ExceptionClear)();
+  jthrowable (*FatalError)(char* msg);
+  JniResult (*PushLocalFrame)(jint capacity);
+  JniResult (*PopLocalFrame)(jobject result);
+  JniResult (*NewGlobalRef)(jobject obj);
+  jthrowable (*DeleteGlobalRef)(jobject globalRef);
+  jthrowable (*DeleteLocalRef)(jobject localRef);
+  JniResult (*IsSameObject)(jobject ref1, jobject ref2);
+  JniResult (*NewLocalRef)(jobject obj);
+  JniResult (*EnsureLocalCapacity)(jint capacity);
+  JniResult (*AllocObject)(jclass clazz);
+  JniResult (*NewObject)(jclass clazz, jmethodID methodID);
+  JniResult (*NewObjectV)(jclass, jmethodID, void*);
+  JniResult (*NewObjectA)(jclass clazz, jmethodID methodID, jvalue* args);
+  JniClassLookupResult (*GetObjectClass)(jobject obj);
+  JniResult (*IsInstanceOf)(jobject obj, jclass clazz);
+  JniPointerResult (*GetMethodID)(jclass clazz, char* name, char* sig);
+  JniResult (*CallObjectMethod)(jobject obj, jmethodID methodID);
+  JniResult (*CallObjectMethodV)(jobject, jmethodID, void*);
+  JniResult (*CallObjectMethodA)(jobject obj, jmethodID methodID, jvalue* args);
+  JniResult (*CallBooleanMethod)(jobject obj, jmethodID methodID);
+  JniResult (*CallBooleanMethodV)(jobject, jmethodID, void*);
+  JniResult (*CallBooleanMethodA)(jobject obj,
+                                  jmethodID methodId,
+                                  jvalue* args);
+  JniResult (*CallByteMethod)(jobject obj, jmethodID methodID);
+  JniResult (*CallByteMethodV)(jobject, jmethodID, void*);
+  JniResult (*CallByteMethodA)(jobject obj, jmethodID methodID, jvalue* args);
+  JniResult (*CallCharMethod)(jobject obj, jmethodID methodID);
+  JniResult (*CallCharMethodV)(jobject, jmethodID, void*);
+  JniResult (*CallCharMethodA)(jobject obj, jmethodID methodID, jvalue* args);
+  JniResult (*CallShortMethod)(jobject obj, jmethodID methodID);
+  JniResult (*CallShortMethodV)(jobject, jmethodID, void*);
+  JniResult (*CallShortMethodA)(jobject obj, jmethodID methodID, jvalue* args);
+  JniResult (*CallIntMethod)(jobject obj, jmethodID methodID);
+  JniResult (*CallIntMethodV)(jobject, jmethodID, void*);
+  JniResult (*CallIntMethodA)(jobject obj, jmethodID methodID, jvalue* args);
+  JniResult (*CallLongMethod)(jobject obj, jmethodID methodID);
+  JniResult (*CallLongMethodV)(jobject, jmethodID, void*);
+  JniResult (*CallLongMethodA)(jobject obj, jmethodID methodID, jvalue* args);
+  JniResult (*CallFloatMethod)(jobject obj, jmethodID methodID);
+  JniResult (*CallFloatMethodV)(jobject, jmethodID, void*);
+  JniResult (*CallFloatMethodA)(jobject obj, jmethodID methodID, jvalue* args);
+  JniResult (*CallDoubleMethod)(jobject obj, jmethodID methodID);
+  JniResult (*CallDoubleMethodV)(jobject, jmethodID, void*);
+  JniResult (*CallDoubleMethodA)(jobject obj, jmethodID methodID, jvalue* args);
+  jthrowable (*CallVoidMethod)(jobject obj, jmethodID methodID);
+  jthrowable (*CallVoidMethodV)(jobject, jmethodID, void*);
+  jthrowable (*CallVoidMethodA)(jobject obj, jmethodID methodID, jvalue* args);
+  JniResult (*CallNonvirtualObjectMethod)(jobject obj,
+                                          jclass clazz,
+                                          jmethodID methodID);
+  JniResult (*CallNonvirtualObjectMethodV)(jobject, jclass, jmethodID, void*);
+  JniResult (*CallNonvirtualObjectMethodA)(jobject obj,
                                            jclass clazz,
                                            jmethodID methodID,
-                                           const jvalue* args);
-  jbyte (*CallNonvirtualByteMethod)(jobject arg1, jclass arg2, jmethodID arg3);
-  jbyte (*CallNonvirtualByteMethodA)(jobject obj,
-                                     jclass clazz,
-                                     jmethodID methodID,
-                                     const jvalue* args);
-  jchar (*CallNonvirtualCharMethod)(jobject arg1, jclass arg2, jmethodID arg3);
-  jchar (*CallNonvirtualCharMethodA)(jobject obj,
-                                     jclass clazz,
-                                     jmethodID methodID,
-                                     const jvalue* args);
-  jshort (*CallNonvirtualShortMethod)(jobject arg1,
-                                      jclass arg2,
-                                      jmethodID arg3);
-  jshort (*CallNonvirtualShortMethodA)(jobject obj,
-                                       jclass clazz,
-                                       jmethodID methodID,
-                                       const jvalue* args);
-  jint (*CallNonvirtualIntMethod)(jobject arg1, jclass arg2, jmethodID arg3);
-  jint (*CallNonvirtualIntMethodA)(jobject obj,
-                                   jclass clazz,
-                                   jmethodID methodID,
-                                   const jvalue* args);
-  jlong (*CallNonvirtualLongMethod)(jobject arg1, jclass arg2, jmethodID arg3);
-  jlong (*CallNonvirtualLongMethodA)(jobject obj,
-                                     jclass clazz,
-                                     jmethodID methodID,
-                                     const jvalue* args);
-  jfloat (*CallNonvirtualFloatMethod)(jobject arg1,
-                                      jclass arg2,
-                                      jmethodID arg3);
-  jfloat (*CallNonvirtualFloatMethodA)(jobject obj,
-                                       jclass clazz,
-                                       jmethodID methodID,
-                                       const jvalue* args);
-  jdouble (*CallNonvirtualDoubleMethod)(jobject arg1,
-                                        jclass arg2,
-                                        jmethodID arg3);
-  jdouble (*CallNonvirtualDoubleMethodA)(jobject obj,
+                                           jvalue* args);
+  JniResult (*CallNonvirtualBooleanMethod)(jobject obj,
+                                           jclass clazz,
+                                           jmethodID methodID);
+  JniResult (*CallNonvirtualBooleanMethodV)(jobject, jclass, jmethodID, void*);
+  JniResult (*CallNonvirtualBooleanMethodA)(jobject obj,
+                                            jclass clazz,
+                                            jmethodID methodID,
+                                            jvalue* args);
+  JniResult (*CallNonvirtualByteMethod)(jobject obj,
+                                        jclass clazz,
+                                        jmethodID methodID);
+  JniResult (*CallNonvirtualByteMethodV)(jobject, jclass, jmethodID, void*);
+  JniResult (*CallNonvirtualByteMethodA)(jobject obj,
                                          jclass clazz,
                                          jmethodID methodID,
-                                         const jvalue* args);
-  void (*CallNonvirtualVoidMethod)(jobject arg1, jclass arg2, jmethodID arg3);
-  void (*CallNonvirtualVoidMethodA)(jobject obj,
-                                    jclass clazz,
-                                    jmethodID methodID,
-                                    const jvalue* args);
-  jfieldID (*GetFieldID)(jclass clazz, const char* name, const char* sig);
-  jobject (*GetObjectField)(jobject obj, jfieldID fieldID);
-  jboolean (*GetBooleanField)(jobject obj, jfieldID fieldID);
-  jbyte (*GetByteField)(jobject obj, jfieldID fieldID);
-  jchar (*GetCharField)(jobject obj, jfieldID fieldID);
-  jshort (*GetShortField)(jobject obj, jfieldID fieldID);
-  jint (*GetIntField)(jobject obj, jfieldID fieldID);
-  jlong (*GetLongField)(jobject obj, jfieldID fieldID);
-  jfloat (*GetFloatField)(jobject obj, jfieldID fieldID);
-  jdouble (*GetDoubleField)(jobject obj, jfieldID fieldID);
-  void (*SetObjectField)(jobject obj, jfieldID fieldID, jobject val);
-  void (*SetBooleanField)(jobject obj, jfieldID fieldID, jboolean val);
-  void (*SetByteField)(jobject obj, jfieldID fieldID, jbyte val);
-  void (*SetCharField)(jobject obj, jfieldID fieldID, jchar val);
-  void (*SetShortField)(jobject obj, jfieldID fieldID, jshort val);
-  void (*SetIntField)(jobject obj, jfieldID fieldID, jint val);
-  void (*SetLongField)(jobject obj, jfieldID fieldID, jlong val);
-  void (*SetFloatField)(jobject obj, jfieldID fieldID, jfloat val);
-  void (*SetDoubleField)(jobject obj, jfieldID fieldID, jdouble val);
-  jmethodID (*GetStaticMethodID)(jclass clazz,
-                                 const char* name,
-                                 const char* sig);
-  jobject (*CallStaticObjectMethod)(jclass arg1, jmethodID arg2);
-  jobject (*CallStaticObjectMethodA)(jclass clazz,
-                                     jmethodID methodID,
-                                     const jvalue* args);
-  jboolean (*CallStaticBooleanMethod)(jclass arg1, jmethodID arg2);
-  jboolean (*CallStaticBooleanMethodA)(jclass clazz,
+                                         jvalue* args);
+  JniResult (*CallNonvirtualCharMethod)(jobject obj,
+                                        jclass clazz,
+                                        jmethodID methodID);
+  JniResult (*CallNonvirtualCharMethodV)(jobject, jclass, jmethodID, void*);
+  JniResult (*CallNonvirtualCharMethodA)(jobject obj,
+                                         jclass clazz,
+                                         jmethodID methodID,
+                                         jvalue* args);
+  JniResult (*CallNonvirtualShortMethod)(jobject obj,
+                                         jclass clazz,
+                                         jmethodID methodID);
+  JniResult (*CallNonvirtualShortMethodV)(jobject, jclass, jmethodID, void*);
+  JniResult (*CallNonvirtualShortMethodA)(jobject obj,
+                                          jclass clazz,
+                                          jmethodID methodID,
+                                          jvalue* args);
+  JniResult (*CallNonvirtualIntMethod)(jobject obj,
+                                       jclass clazz,
+                                       jmethodID methodID);
+  JniResult (*CallNonvirtualIntMethodV)(jobject, jclass, jmethodID, void*);
+  JniResult (*CallNonvirtualIntMethodA)(jobject obj,
+                                        jclass clazz,
+                                        jmethodID methodID,
+                                        jvalue* args);
+  JniResult (*CallNonvirtualLongMethod)(jobject obj,
+                                        jclass clazz,
+                                        jmethodID methodID);
+  JniResult (*CallNonvirtualLongMethodV)(jobject, jclass, jmethodID, void*);
+  JniResult (*CallNonvirtualLongMethodA)(jobject obj,
+                                         jclass clazz,
+                                         jmethodID methodID,
+                                         jvalue* args);
+  JniResult (*CallNonvirtualFloatMethod)(jobject obj,
+                                         jclass clazz,
+                                         jmethodID methodID);
+  JniResult (*CallNonvirtualFloatMethodV)(jobject, jclass, jmethodID, void*);
+  JniResult (*CallNonvirtualFloatMethodA)(jobject obj,
+                                          jclass clazz,
+                                          jmethodID methodID,
+                                          jvalue* args);
+  JniResult (*CallNonvirtualDoubleMethod)(jobject obj,
+                                          jclass clazz,
+                                          jmethodID methodID);
+  JniResult (*CallNonvirtualDoubleMethodV)(jobject, jclass, jmethodID, void*);
+  JniResult (*CallNonvirtualDoubleMethodA)(jobject obj,
+                                           jclass clazz,
+                                           jmethodID methodID,
+                                           jvalue* args);
+  jthrowable (*CallNonvirtualVoidMethod)(jobject obj,
+                                         jclass clazz,
+                                         jmethodID methodID);
+  jthrowable (*CallNonvirtualVoidMethodV)(jobject, jclass, jmethodID, void*);
+  jthrowable (*CallNonvirtualVoidMethodA)(jobject obj,
+                                          jclass clazz,
+                                          jmethodID methodID,
+                                          jvalue* args);
+  JniPointerResult (*GetFieldID)(jclass clazz, char* name, char* sig);
+  JniResult (*GetObjectField)(jobject obj, jfieldID fieldID);
+  JniResult (*GetBooleanField)(jobject obj, jfieldID fieldID);
+  JniResult (*GetByteField)(jobject obj, jfieldID fieldID);
+  JniResult (*GetCharField)(jobject obj, jfieldID fieldID);
+  JniResult (*GetShortField)(jobject obj, jfieldID fieldID);
+  JniResult (*GetIntField)(jobject obj, jfieldID fieldID);
+  JniResult (*GetLongField)(jobject obj, jfieldID fieldID);
+  JniResult (*GetFloatField)(jobject obj, jfieldID fieldID);
+  JniResult (*GetDoubleField)(jobject obj, jfieldID fieldID);
+  jthrowable (*SetObjectField)(jobject obj, jfieldID fieldID, jobject val);
+  jthrowable (*SetBooleanField)(jobject obj, jfieldID fieldID, jboolean val);
+  jthrowable (*SetByteField)(jobject obj, jfieldID fieldID, jbyte val);
+  jthrowable (*SetCharField)(jobject obj, jfieldID fieldID, jchar val);
+  jthrowable (*SetShortField)(jobject obj, jfieldID fieldID, jshort val);
+  jthrowable (*SetIntField)(jobject obj, jfieldID fieldID, jint val);
+  jthrowable (*SetLongField)(jobject obj, jfieldID fieldID, jlong val);
+  jthrowable (*SetFloatField)(jobject obj, jfieldID fieldID, jfloat val);
+  jthrowable (*SetDoubleField)(jobject obj, jfieldID fieldID, jdouble val);
+  JniPointerResult (*GetStaticMethodID)(jclass clazz, char* name, char* sig);
+  JniResult (*CallStaticObjectMethod)(jclass clazz, jmethodID methodID);
+  JniResult (*CallStaticObjectMethodV)(jclass, jmethodID, void*);
+  JniResult (*CallStaticObjectMethodA)(jclass clazz,
                                        jmethodID methodID,
-                                       const jvalue* args);
-  jbyte (*CallStaticByteMethod)(jclass arg1, jmethodID arg2);
-  jbyte (*CallStaticByteMethodA)(jclass clazz,
-                                 jmethodID methodID,
-                                 const jvalue* args);
-  jchar (*CallStaticCharMethod)(jclass arg1, jmethodID arg2);
-  jchar (*CallStaticCharMethodA)(jclass clazz,
-                                 jmethodID methodID,
-                                 const jvalue* args);
-  jshort (*CallStaticShortMethod)(jclass arg1, jmethodID arg2);
-  jshort (*CallStaticShortMethodA)(jclass clazz,
-                                   jmethodID methodID,
-                                   const jvalue* args);
-  jint (*CallStaticIntMethod)(jclass arg1, jmethodID arg2);
-  jint (*CallStaticIntMethodA)(jclass clazz,
-                               jmethodID methodID,
-                               const jvalue* args);
-  jlong (*CallStaticLongMethod)(jclass arg1, jmethodID arg2);
-  jlong (*CallStaticLongMethodA)(jclass clazz,
-                                 jmethodID methodID,
-                                 const jvalue* args);
-  jfloat (*CallStaticFloatMethod)(jclass arg1, jmethodID arg2);
-  jfloat (*CallStaticFloatMethodA)(jclass clazz,
-                                   jmethodID methodID,
-                                   const jvalue* args);
-  jdouble (*CallStaticDoubleMethod)(jclass arg1, jmethodID arg2);
-  jdouble (*CallStaticDoubleMethodA)(jclass clazz,
+                                       jvalue* args);
+  JniResult (*CallStaticBooleanMethod)(jclass clazz, jmethodID methodID);
+  JniResult (*CallStaticBooleanMethodV)(jclass, jmethodID, void*);
+  JniResult (*CallStaticBooleanMethodA)(jclass clazz,
+                                        jmethodID methodID,
+                                        jvalue* args);
+  JniResult (*CallStaticByteMethod)(jclass clazz, jmethodID methodID);
+  JniResult (*CallStaticByteMethodV)(jclass, jmethodID, void*);
+  JniResult (*CallStaticByteMethodA)(jclass clazz,
                                      jmethodID methodID,
-                                     const jvalue* args);
-  void (*CallStaticVoidMethod)(jclass arg1, jmethodID arg2);
-  void (*CallStaticVoidMethodA)(jclass clazz,
-                                jmethodID methodID,
-                                const jvalue* args);
-  jfieldID (*GetStaticFieldID)(jclass clazz, const char* name, const char* sig);
-  jobject (*GetStaticObjectField)(jclass clazz, jfieldID fieldID);
-  jboolean (*GetStaticBooleanField)(jclass clazz, jfieldID fieldID);
-  jbyte (*GetStaticByteField)(jclass clazz, jfieldID fieldID);
-  jchar (*GetStaticCharField)(jclass clazz, jfieldID fieldID);
-  jshort (*GetStaticShortField)(jclass clazz, jfieldID fieldID);
-  jint (*GetStaticIntField)(jclass clazz, jfieldID fieldID);
-  jlong (*GetStaticLongField)(jclass clazz, jfieldID fieldID);
-  jfloat (*GetStaticFloatField)(jclass clazz, jfieldID fieldID);
-  jdouble (*GetStaticDoubleField)(jclass clazz, jfieldID fieldID);
-  void (*SetStaticObjectField)(jclass clazz, jfieldID fieldID, jobject val);
-  void (*SetStaticBooleanField)(jclass clazz, jfieldID fieldID, jboolean val);
-  void (*SetStaticByteField)(jclass clazz, jfieldID fieldID, jbyte val);
-  void (*SetStaticCharField)(jclass clazz, jfieldID fieldID, jchar val);
-  void (*SetStaticShortField)(jclass clazz, jfieldID fieldID, jshort val);
-  void (*SetStaticIntField)(jclass clazz, jfieldID fieldID, jint val);
-  void (*SetStaticLongField)(jclass clazz, jfieldID fieldID, jlong val);
-  void (*SetStaticFloatField)(jclass clazz, jfieldID fieldID, jfloat val);
-  void (*SetStaticDoubleField)(jclass clazz, jfieldID fieldID, jdouble val);
-  jstring (*NewString)(const jchar* unicodeChars, jsize len);
-  jsize (*GetStringLength)(jstring string);
-  const jchar* (*GetStringChars)(jstring string, jboolean* isCopy);
-  void (*ReleaseStringChars)(jstring string, const jchar* isCopy);
-  jstring (*NewStringUTF)(const char* bytes);
-  jsize (*GetStringUTFLength)(jstring string);
-  const char* (*GetStringUTFChars)(jstring string, jboolean* isCopy);
-  void (*ReleaseStringUTFChars)(jstring string, const char* utf);
-  jsize (*GetArrayLength)(jarray array);
-  jobjectArray (*NewObjectArray)(jsize length,
-                                 jclass elementClass,
-                                 jobject initialElement);
-  jobject (*GetObjectArrayElement)(jobjectArray array, jsize index);
-  void (*SetObjectArrayElement)(jobjectArray array, jsize index, jobject val);
-  jbooleanArray (*NewBooleanArray)(jsize length);
-  jbyteArray (*NewByteArray)(jsize length);
-  jcharArray (*NewCharArray)(jsize length);
-  jshortArray (*NewShortArray)(jsize length);
-  jintArray (*NewIntArray)(jsize length);
-  jlongArray (*NewLongArray)(jsize length);
-  jfloatArray (*NewFloatArray)(jsize length);
-  jdoubleArray (*NewDoubleArray)(jsize length);
-  jboolean* (*GetBooleanArrayElements)(jbooleanArray array, jboolean* isCopy);
-  jbyte* (*GetByteArrayElements)(jbyteArray array, jboolean* isCopy);
-  jchar* (*GetCharArrayElements)(jcharArray array, jboolean* isCopy);
-  jshort* (*GetShortArrayElements)(jshortArray array, jboolean* isCopy);
-  jint* (*GetIntArrayElements)(jintArray array, jboolean* isCopy);
-  jlong* (*GetLongArrayElements)(jlongArray array, jboolean* isCopy);
-  jfloat* (*GetFloatArrayElements)(jfloatArray array, jboolean* isCopy);
-  jdouble* (*GetDoubleArrayElements)(jdoubleArray array, jboolean* isCopy);
-  void (*ReleaseBooleanArrayElements)(jbooleanArray array,
-                                      jboolean* elems,
-                                      jint mode);
-  void (*ReleaseByteArrayElements)(jbyteArray array, jbyte* elems, jint mode);
-  void (*ReleaseCharArrayElements)(jcharArray array, jchar* elems, jint mode);
-  void (*ReleaseShortArrayElements)(jshortArray array,
-                                    jshort* elems,
-                                    jint mode);
-  void (*ReleaseIntArrayElements)(jintArray array, jint* elems, jint mode);
-  void (*ReleaseLongArrayElements)(jlongArray array, jlong* elems, jint mode);
-  void (*ReleaseFloatArrayElements)(jfloatArray array,
-                                    jfloat* elems,
-                                    jint mode);
-  void (*ReleaseDoubleArrayElements)(jdoubleArray array,
-                                     jdouble* elems,
-                                     jint mode);
-  void (*GetBooleanArrayRegion)(jbooleanArray array,
+                                     jvalue* args);
+  JniResult (*CallStaticCharMethod)(jclass clazz, jmethodID methodID);
+  JniResult (*CallStaticCharMethodV)(jclass, jmethodID, void*);
+  JniResult (*CallStaticCharMethodA)(jclass clazz,
+                                     jmethodID methodID,
+                                     jvalue* args);
+  JniResult (*CallStaticShortMethod)(jclass clazz, jmethodID methodID);
+  JniResult (*CallStaticShortMethodV)(jclass, jmethodID, void*);
+  JniResult (*CallStaticShortMethodA)(jclass clazz,
+                                      jmethodID methodID,
+                                      jvalue* args);
+  JniResult (*CallStaticIntMethod)(jclass clazz, jmethodID methodID);
+  JniResult (*CallStaticIntMethodV)(jclass, jmethodID, void*);
+  JniResult (*CallStaticIntMethodA)(jclass clazz,
+                                    jmethodID methodID,
+                                    jvalue* args);
+  JniResult (*CallStaticLongMethod)(jclass clazz, jmethodID methodID);
+  JniResult (*CallStaticLongMethodV)(jclass, jmethodID, void*);
+  JniResult (*CallStaticLongMethodA)(jclass clazz,
+                                     jmethodID methodID,
+                                     jvalue* args);
+  JniResult (*CallStaticFloatMethod)(jclass clazz, jmethodID methodID);
+  JniResult (*CallStaticFloatMethodV)(jclass, jmethodID, void*);
+  JniResult (*CallStaticFloatMethodA)(jclass clazz,
+                                      jmethodID methodID,
+                                      jvalue* args);
+  JniResult (*CallStaticDoubleMethod)(jclass clazz, jmethodID methodID);
+  JniResult (*CallStaticDoubleMethodV)(jclass, jmethodID, void*);
+  JniResult (*CallStaticDoubleMethodA)(jclass clazz,
+                                       jmethodID methodID,
+                                       jvalue* args);
+  jthrowable (*CallStaticVoidMethod)(jclass clazz, jmethodID methodID);
+  jthrowable (*CallStaticVoidMethodV)(jclass, jmethodID, void*);
+  jthrowable (*CallStaticVoidMethodA)(jclass clazz,
+                                      jmethodID methodID,
+                                      jvalue* args);
+  JniPointerResult (*GetStaticFieldID)(jclass clazz, char* name, char* sig);
+  JniResult (*GetStaticObjectField)(jclass clazz, jfieldID fieldID);
+  JniResult (*GetStaticBooleanField)(jclass clazz, jfieldID fieldID);
+  JniResult (*GetStaticByteField)(jclass clazz, jfieldID fieldID);
+  JniResult (*GetStaticCharField)(jclass clazz, jfieldID fieldID);
+  JniResult (*GetStaticShortField)(jclass clazz, jfieldID fieldID);
+  JniResult (*GetStaticIntField)(jclass clazz, jfieldID fieldID);
+  JniResult (*GetStaticLongField)(jclass clazz, jfieldID fieldID);
+  JniResult (*GetStaticFloatField)(jclass clazz, jfieldID fieldID);
+  JniResult (*GetStaticDoubleField)(jclass clazz, jfieldID fieldID);
+  jthrowable (*SetStaticObjectField)(jclass clazz,
+                                     jfieldID fieldID,
+                                     jobject val);
+  jthrowable (*SetStaticBooleanField)(jclass clazz,
+                                      jfieldID fieldID,
+                                      jboolean val);
+  jthrowable (*SetStaticByteField)(jclass clazz, jfieldID fieldID, jbyte val);
+  jthrowable (*SetStaticCharField)(jclass clazz, jfieldID fieldID, jchar val);
+  jthrowable (*SetStaticShortField)(jclass clazz, jfieldID fieldID, jshort val);
+  jthrowable (*SetStaticIntField)(jclass clazz, jfieldID fieldID, jint val);
+  jthrowable (*SetStaticLongField)(jclass clazz, jfieldID fieldID, jlong val);
+  jthrowable (*SetStaticFloatField)(jclass clazz, jfieldID fieldID, jfloat val);
+  jthrowable (*SetStaticDoubleField)(jclass clazz,
+                                     jfieldID fieldID,
+                                     jdouble val);
+  JniResult (*NewString)(jchar* unicodeChars, jsize len);
+  JniResult (*GetStringLength)(jstring string);
+  JniPointerResult (*GetStringChars)(jstring string, jboolean* isCopy);
+  jthrowable (*ReleaseStringChars)(jstring string, jchar* isCopy);
+  JniResult (*NewStringUTF)(char* bytes);
+  JniResult (*GetStringUTFLength)(jstring string);
+  JniPointerResult (*GetStringUTFChars)(jstring string, jboolean* isCopy);
+  jthrowable (*ReleaseStringUTFChars)(jstring string, char* utf);
+  JniResult (*GetArrayLength)(jarray array);
+  JniResult (*NewObjectArray)(jsize length,
+                              jclass elementClass,
+                              jobject initialElement);
+  JniResult (*GetObjectArrayElement)(jobjectArray array, jsize index);
+  jthrowable (*SetObjectArrayElement)(jobjectArray array,
+                                      jsize index,
+                                      jobject val);
+  JniResult (*NewBooleanArray)(jsize length);
+  JniResult (*NewByteArray)(jsize length);
+  JniResult (*NewCharArray)(jsize length);
+  JniResult (*NewShortArray)(jsize length);
+  JniResult (*NewIntArray)(jsize length);
+  JniResult (*NewLongArray)(jsize length);
+  JniResult (*NewFloatArray)(jsize length);
+  JniResult (*NewDoubleArray)(jsize length);
+  JniPointerResult (*GetBooleanArrayElements)(jbooleanArray array,
+                                              jboolean* isCopy);
+  JniPointerResult (*GetByteArrayElements)(jbyteArray array, jboolean* isCopy);
+  JniPointerResult (*GetCharArrayElements)(jcharArray array, jboolean* isCopy);
+  JniPointerResult (*GetShortArrayElements)(jshortArray array,
+                                            jboolean* isCopy);
+  JniPointerResult (*GetIntArrayElements)(jintArray array, jboolean* isCopy);
+  JniPointerResult (*GetLongArrayElements)(jlongArray array, jboolean* isCopy);
+  JniPointerResult (*GetFloatArrayElements)(jfloatArray array,
+                                            jboolean* isCopy);
+  JniPointerResult (*GetDoubleArrayElements)(jdoubleArray array,
+                                             jboolean* isCopy);
+  jthrowable (*ReleaseBooleanArrayElements)(jbooleanArray array,
+                                            jboolean* elems,
+                                            jint mode);
+  jthrowable (*ReleaseByteArrayElements)(jbyteArray array,
+                                         jbyte* elems,
+                                         jint mode);
+  jthrowable (*ReleaseCharArrayElements)(jcharArray array,
+                                         jchar* elems,
+                                         jint mode);
+  jthrowable (*ReleaseShortArrayElements)(jshortArray array,
+                                          jshort* elems,
+                                          jint mode);
+  jthrowable (*ReleaseIntArrayElements)(jintArray array,
+                                        jint* elems,
+                                        jint mode);
+  jthrowable (*ReleaseLongArrayElements)(jlongArray array,
+                                         jlong* elems,
+                                         jint mode);
+  jthrowable (*ReleaseFloatArrayElements)(jfloatArray array,
+                                          jfloat* elems,
+                                          jint mode);
+  jthrowable (*ReleaseDoubleArrayElements)(jdoubleArray array,
+                                           jdouble* elems,
+                                           jint mode);
+  jthrowable (*GetBooleanArrayRegion)(jbooleanArray array,
+                                      jsize start,
+                                      jsize len,
+                                      jboolean* buf);
+  jthrowable (*GetByteArrayRegion)(jbyteArray array,
+                                   jsize start,
+                                   jsize len,
+                                   jbyte* buf);
+  jthrowable (*GetCharArrayRegion)(jcharArray array,
+                                   jsize start,
+                                   jsize len,
+                                   jchar* buf);
+  jthrowable (*GetShortArrayRegion)(jshortArray array,
+                                    jsize start,
+                                    jsize len,
+                                    jshort* buf);
+  jthrowable (*GetIntArrayRegion)(jintArray array,
+                                  jsize start,
+                                  jsize len,
+                                  jint* buf);
+  jthrowable (*GetLongArrayRegion)(jlongArray array,
+                                   jsize start,
+                                   jsize len,
+                                   jlong* buf);
+  jthrowable (*GetFloatArrayRegion)(jfloatArray array,
+                                    jsize start,
+                                    jsize len,
+                                    jfloat* buf);
+  jthrowable (*GetDoubleArrayRegion)(jdoubleArray array,
+                                     jsize start,
+                                     jsize len,
+                                     jdouble* buf);
+  jthrowable (*SetBooleanArrayRegion)(jbooleanArray array,
+                                      jsize start,
+                                      jsize len,
+                                      jboolean* buf);
+  jthrowable (*SetByteArrayRegion)(jbyteArray array,
+                                   jsize start,
+                                   jsize len,
+                                   jbyte* buf);
+  jthrowable (*SetCharArrayRegion)(jcharArray array,
+                                   jsize start,
+                                   jsize len,
+                                   jchar* buf);
+  jthrowable (*SetShortArrayRegion)(jshortArray array,
+                                    jsize start,
+                                    jsize len,
+                                    jshort* buf);
+  jthrowable (*SetIntArrayRegion)(jintArray array,
+                                  jsize start,
+                                  jsize len,
+                                  jint* buf);
+  jthrowable (*SetLongArrayRegion)(jlongArray array,
+                                   jsize start,
+                                   jsize len,
+                                   jlong* buf);
+  jthrowable (*SetFloatArrayRegion)(jfloatArray array,
+                                    jsize start,
+                                    jsize len,
+                                    jfloat* buf);
+  jthrowable (*SetDoubleArrayRegion)(jdoubleArray array,
+                                     jsize start,
+                                     jsize len,
+                                     jdouble* buf);
+  JniResult (*RegisterNatives)(jclass clazz,
+                               JNINativeMethod* methods,
+                               jint nMethods);
+  JniResult (*UnregisterNatives)(jclass clazz);
+  JniResult (*MonitorEnter)(jobject obj);
+  JniResult (*MonitorExit)(jobject obj);
+  JniResult (*GetJavaVM)(JavaVM** vm);
+  jthrowable (*GetStringRegion)(jstring str,
                                 jsize start,
                                 jsize len,
-                                jboolean* buf);
-  void (*GetByteArrayRegion)(jbyteArray array,
-                             jsize start,
-                             jsize len,
-                             jbyte* buf);
-  void (*GetCharArrayRegion)(jcharArray array,
-                             jsize start,
-                             jsize len,
-                             jchar* buf);
-  void (*GetShortArrayRegion)(jshortArray array,
-                              jsize start,
-                              jsize len,
-                              jshort* buf);
-  void (*GetIntArrayRegion)(jintArray array, jsize start, jsize len, jint* buf);
-  void (*GetLongArrayRegion)(jlongArray array,
-                             jsize start,
-                             jsize len,
-                             jlong* buf);
-  void (*GetFloatArrayRegion)(jfloatArray array,
-                              jsize start,
-                              jsize len,
-                              jfloat* buf);
-  void (*GetDoubleArrayRegion)(jdoubleArray array,
-                               jsize start,
-                               jsize len,
-                               jdouble* buf);
-  void (*SetBooleanArrayRegion)(jbooleanArray array,
-                                jsize start,
-                                jsize len,
-                                const jboolean* buf);
-  void (*SetByteArrayRegion)(jbyteArray array,
-                             jsize start,
-                             jsize len,
-                             const jbyte* buf);
-  void (*SetCharArrayRegion)(jcharArray array,
-                             jsize start,
-                             jsize len,
-                             const jchar* buf);
-  void (*SetShortArrayRegion)(jshortArray array,
-                              jsize start,
-                              jsize len,
-                              const jshort* buf);
-  void (*SetIntArrayRegion)(jintArray array,
-                            jsize start,
-                            jsize len,
-                            const jint* buf);
-  void (*SetLongArrayRegion)(jlongArray array,
-                             jsize start,
-                             jsize len,
-                             const jlong* buf);
-  void (*SetFloatArrayRegion)(jfloatArray array,
-                              jsize start,
-                              jsize len,
-                              const jfloat* buf);
-  void (*SetDoubleArrayRegion)(jdoubleArray array,
-                               jsize start,
-                               jsize len,
-                               const jdouble* buf);
-  jint (*RegisterNatives)(jclass clazz,
-                          const JNINativeMethod* methods,
-                          jint nMethods);
-  jint (*UnregisterNatives)(jclass clazz);
-  jint (*MonitorEnter)(jobject obj);
-  jint (*MonitorExit)(jobject obj);
-  jint (*GetJavaVM)(JavaVM** vm);
-  void (*GetStringRegion)(jstring str, jsize start, jsize len, jchar* buf);
-  void (*GetStringUTFRegion)(jstring str, jsize start, jsize len, char* buf);
-  void* (*GetPrimitiveArrayCritical)(jarray array, jboolean* isCopy);
-  void (*ReleasePrimitiveArrayCritical)(jarray array, void* carray, jint mode);
-  const jchar* (*GetStringCritical)(jstring str, jboolean* isCopy);
-  void (*ReleaseStringCritical)(jstring str, const jchar* carray);
-  jweak (*NewWeakGlobalRef)(jobject obj);
-  void (*DeleteWeakGlobalRef)(jweak obj);
-  jboolean (*ExceptionCheck)();
-  jobject (*NewDirectByteBuffer)(void* address, jlong capacity);
-  void* (*GetDirectBufferAddress)(jobject buf);
-  jlong (*GetDirectBufferCapacity)(jobject buf);
-  jobjectRefType (*GetObjectRefType)(jobject obj);
+                                jchar* buf);
+  jthrowable (*GetStringUTFRegion)(jstring str,
+                                   jsize start,
+                                   jsize len,
+                                   char* buf);
+  JniPointerResult (*GetPrimitiveArrayCritical)(jarray array, jboolean* isCopy);
+  jthrowable (*ReleasePrimitiveArrayCritical)(jarray array,
+                                              void* carray,
+                                              jint mode);
+  JniPointerResult (*GetStringCritical)(jstring str, jboolean* isCopy);
+  jthrowable (*ReleaseStringCritical)(jstring str, jchar* carray);
+  JniResult (*NewWeakGlobalRef)(jobject obj);
+  jthrowable (*DeleteWeakGlobalRef)(jweak obj);
+  JniResult (*ExceptionCheck)();
+  JniResult (*NewDirectByteBuffer)(void* address, jlong capacity);
+  JniPointerResult (*GetDirectBufferAddress)(jobject buf);
+  JniResult (*GetDirectBufferCapacity)(jobject buf);
+  JniResult (*GetObjectRefType)(jobject obj);
 } GlobalJniEnv;
-
-// Note(Mahesh): Redoing some work here, because I want these 2 files separate.
-// including dartjni.h for FFI_PLUGIN_EXPORT leads to more issues.
-
-#if _WIN32
-__declspec(dllexport) GlobalJniEnv* GetGlobalEnv();
-#else
-GlobalJniEnv* GetGlobalEnv();
-#endif
\ No newline at end of file
+FFI_PLUGIN_EXPORT GlobalJniEnv* GetGlobalEnv();
diff --git a/pkgs/jni/test/exception_test.dart b/pkgs/jni/test/exception_test.dart
index c277b01..4fb34ef 100644
--- a/pkgs/jni/test/exception_test.dart
+++ b/pkgs/jni/test/exception_test.dart
@@ -7,6 +7,8 @@
 import 'package:test/test.dart';
 import 'package:jni/jni.dart';
 
+import 'test_util/test_util.dart';
+
 void main() {
   if (!Platform.isAndroid) {
     bool caught = false;
@@ -31,21 +33,24 @@
           "Read exception_test.dart for details.";
     }
   }
+  run(testRunner: test);
+}
 
-  test("double free throws exception", () {
+void run({required TestRunnerCallback testRunner}) {
+  testRunner("double free throws exception", () {
     final r = Jni.newInstance("java/util/Random", "()V", []);
     r.delete();
     expect(r.delete, throwsA(isA<DoubleFreeException>()));
   });
 
-  test("Use after free throws exception", () {
+  testRunner("Use after free throws exception", () {
     final r = Jni.newInstance("java/util/Random", "()V", []);
     r.delete();
     expect(() => r.callMethodByName<int>("nextInt", "(I)I", [JValueInt(256)]),
         throwsA(isA<UseAfterFreeException>()));
   });
 
-  test("void fieldType throws exception", () {
+  testRunner("void fieldType throws exception", () {
     final r = Jni.newInstance("java/util/Random", "()V", []);
     expect(() => r.getField<void>(nullptr, JniCallType.voidType),
         throwsArgumentError);
@@ -53,7 +58,7 @@
         throwsArgumentError);
   });
 
-  test("Wrong callType throws exception", () {
+  testRunner("Wrong callType throws exception", () {
     final r = Jni.newInstance("java/util/Random", "()V", []);
     expect(
         () => r.callMethodByName<int>(
@@ -61,7 +66,7 @@
         throwsA(isA<InvalidCallTypeException>()));
   });
 
-  test("An exception in JNI throws JniException in Dart", () {
+  testRunner("An exception in JNI throws JniException in Dart", () {
     final r = Jni.newInstance("java/util/Random", "()V", []);
     expect(() => r.callMethodByName<int>("nextInt", "(I)I", [JValueInt(-1)]),
         throwsA(isA<JniException>()));
diff --git a/pkgs/jni/test/global_env_test.dart b/pkgs/jni/test/global_env_test.dart
new file mode 100644
index 0000000..8f65d34
--- /dev/null
+++ b/pkgs/jni/test/global_env_test.dart
@@ -0,0 +1,204 @@
+// 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.
+
+import 'dart:io';
+
+import 'package:jni/jni.dart';
+import 'package:jni/src/jvalues.dart';
+import 'package:test/test.dart';
+
+import 'test_util/test_util.dart';
+
+const maxLongInJava = 9223372036854775807;
+
+void main() {
+  // Running on Android through flutter, this plugin
+  // will bind to Android runtime's JVM.
+  // On other platforms eg Flutter desktop or Dart standalone
+  // You need to manually create a JVM at beginning.
+  //
+  // On flutter desktop, the C wrappers are bundled, and helperPath param
+  // is not required.
+  //
+  // On dart standalone, however, there's no way to bundle the wrappers.
+  // You have to manually pass the path to the `dartjni` dynamic library.
+
+  if (!Platform.isAndroid) {
+    try {
+      Jni.spawn(dylibDir: "build/jni_libs", jvmOptions: ["-Xmx128m"]);
+    } on JvmExistsException catch (_) {
+      // TODO(#51): Support destroying and reinstantiating JVM.
+    }
+  }
+  run(testRunner: test);
+}
+
+// We are factoring these tests into a run method which allows us to run same
+// tests with different environments. Eg: standalone and integration tests.
+void run({required TestRunnerCallback testRunner}) {
+  // Tests in this file demonstrate how to use `GlobalJniEnv`, a thin
+  // abstraction over JNIEnv in JNI C API. This can be used from multiple
+  // threads, and converts all returned object references to global references,
+  // so that you don't need to worry about whether your Dart code will be
+  // scheduled on another thread.
+  //
+  // GlobalJniEnv wraps all methods of JNIEnv (UpperCamelCase, reflecting the
+  // original name of the method) and provides few more extension methods
+  // (lowerCamelCase).
+  //
+  // For examples of a higher level API, see `jni_object_tests.dart`.
+  final env = Jni.env;
+  testRunner('initDLApi', () {
+    Jni.initDLApi();
+  });
+
+  testRunner('get JNI Version', () {
+    expect(Jni.env.GetVersion(), isNot(equals(0)));
+  });
+
+  testRunner(
+      'Manually lookup & call Integer.toHexString',
+      () => using((arena) {
+            // Method names on JniEnv* from C JNI API are capitalized
+            // like in original, while other extension methods
+            // follow Dart naming conventions.
+            final integerClass =
+                env.FindClass("java/lang/Integer".toNativeChars(arena));
+            // Refer JNI spec on how to construct method signatures
+            // Passing wrong signature leads to a segfault
+            final hexMethod = env.GetStaticMethodID(
+                integerClass,
+                "toHexString".toNativeChars(arena),
+                "(I)Ljava/lang/String;".toNativeChars(arena));
+
+            for (var i in [1, 80, 13, 76, 11344]) {
+              // if your argument is int, bool, or JObject (`Pointer<Void>`)
+              // it can be directly placed in the list. To convert into different primitive
+              // types, use JValue<Type> wrappers.
+              final jres = env.CallStaticObjectMethodA(integerClass, hexMethod,
+                  Jni.jvalues([JValueInt(i)], allocator: arena));
+
+              // use asDartString extension method on Pointer<JniEnv>
+              // to convert a String jobject result to string
+              final res = env.toDartString(jres);
+              expect(res, equals(i.toRadixString(16)));
+
+              // Any object or class result from java is a local reference
+              // and needs to be deleted explicitly.
+              // Note that method and field IDs aren't local references.
+              // But they are valid only until a reference to corresponding
+              // java class exists.
+              env.DeleteGlobalRef(jres);
+            }
+            env.DeleteGlobalRef(integerClass);
+          }));
+
+  testRunner("asJString extension method", () {
+    const str = "QWERTY QWERTY";
+    // convenience method that wraps
+    // converting dart string to native string,
+    // instantiating java string, and freeing the native string
+    final jstr = env.toJStringPtr(str);
+    expect(str, equals(env.toDartString(jstr)));
+    env.DeleteGlobalRef(jstr);
+  });
+
+  testRunner(
+      'GlobalJniEnv should catch exceptions',
+      () => using((arena) {
+            final integerClass =
+                env.FindClass("java/lang/Integer".toNativeChars(arena));
+            final parseIntMethod = env.GetStaticMethodID(
+                integerClass,
+                "parseInt".toNativeChars(arena),
+                "(Ljava/lang/String;)I".toNativeChars(arena));
+            final args = JValueArgs(["hello"], arena);
+            expect(
+                () => env.CallStaticIntMethodA(
+                    integerClass, parseIntMethod, args.values),
+                throwsA(isA<JniException>()));
+          }));
+
+  testRunner(
+      "Convert back & forth between Dart & Java strings",
+      () => using((arena) {
+            const str = "ABCD EFGH";
+            // This is what asJString and asDartString do internally
+            final jstr = env.NewStringUTF(str.toNativeChars(arena));
+            final jchars = env.GetStringUTFChars(jstr, nullptr);
+            final dstr = jchars.toDartString();
+            env.ReleaseStringUTFChars(jstr, jchars);
+            expect(str, equals(dstr));
+            env.DeleteGlobalRef(jstr);
+          }));
+
+  testRunner(
+      "Print something from Java",
+      () => using((arena) {
+            final system =
+                env.FindClass("java/lang/System".toNativeChars(arena));
+            final field = env.GetStaticFieldID(
+                system,
+                "out".toNativeChars(arena),
+                "Ljava/io/PrintStream;".toNativeChars(arena));
+            final out = env.GetStaticObjectField(system, field);
+            final printStream = env.GetObjectClass(out);
+            final println = env.GetMethodID(
+                printStream,
+                "println".toNativeChars(arena),
+                "(Ljava/lang/String;)V".toNativeChars(arena));
+            const str = "\nHello World from JNI!";
+            final jstr = env.toJStringPtr(str);
+            env.CallVoidMethodA(out, println, Jni.jvalues([jstr]));
+            env.deleteAllRefs([system, printStream, jstr]);
+          }));
+  testRunner(
+      'Env create reference methods should retain their default behavior', () {
+    final systemOut = Jni.retrieveStaticField<JObjectPtr>(
+        "java/lang/System", "out", "Ljava/io/PrintStream;");
+    var refType = env.GetObjectRefType(systemOut);
+    expect(refType, equals(JObjectRefType.JNIGlobalRefType));
+    final localRef = env.NewLocalRef(systemOut);
+    refType = env.GetObjectRefType(localRef);
+    expect(refType, equals(JObjectRefType.JNILocalRefType));
+    final weakRef = env.NewWeakGlobalRef(systemOut);
+    refType = env.GetObjectRefType(weakRef);
+    expect(refType, equals(JObjectRefType.JNIWeakGlobalRefType));
+    final globalRef = env.NewGlobalRef(localRef);
+    refType = env.GetObjectRefType(globalRef);
+    expect(refType, equals(JObjectRefType.JNIGlobalRefType));
+    env.DeleteGlobalRef(globalRef);
+    env.DeleteWeakGlobalRef(weakRef);
+    env.DeleteLocalRef(localRef);
+    env.DeleteGlobalRef(systemOut);
+  });
+  testRunner('long methods return long int without loss of precision', () {
+    using((arena) {
+      final longClass = env.FindClass("java/lang/Long".toNativeChars(arena));
+      final maxField = env.GetStaticFieldID(
+        longClass,
+        'MAX_VALUE'.toNativeChars(arena),
+        'J'.toNativeChars(arena),
+      );
+      final maxValue = env.GetStaticLongField(longClass, maxField);
+      expect(maxValue, equals(maxLongInJava));
+      env.DeleteGlobalRef(longClass);
+    });
+  });
+
+  testRunner('class <-> object methods', () {
+    using((arena) {
+      final systemOut = Jni.retrieveStaticField<JObjectPtr>(
+          "java/lang/System", "out", "Ljava/io/PrintStream;");
+      final systemErr = Jni.retrieveStaticField<JObjectPtr>(
+          "java/lang/System", "err", "Ljava/io/PrintStream;");
+      final outClass = env.GetObjectClass(systemOut);
+      expect(env.IsInstanceOf(systemOut, outClass), isTrue);
+      expect(env.IsInstanceOf(systemErr, outClass), isTrue);
+      final errClass = env.GetObjectClass(systemErr);
+      expect(env.IsSameObject(outClass, errClass), isTrue);
+      env.deleteAllRefs([systemOut, systemErr, outClass, errClass]);
+    });
+  });
+}
diff --git a/pkgs/jni/test/jarray_test.dart b/pkgs/jni/test/jarray_test.dart
index 9a75e41..4eca3d4 100644
--- a/pkgs/jni/test/jarray_test.dart
+++ b/pkgs/jni/test/jarray_test.dart
@@ -7,6 +7,8 @@
 import 'package:jni/jni.dart';
 import 'package:test/test.dart';
 
+import 'test_util/test_util.dart';
+
 void main() {
   // Don't forget to initialize JNI.
   if (!Platform.isAndroid) {
@@ -16,7 +18,11 @@
       // TODO(#51): Support destroying and reinstantiating JVM.
     }
   }
-  test("Java boolean array", () {
+  run(testRunner: test);
+}
+
+void run({required TestRunnerCallback testRunner}) {
+  testRunner("Java boolean array", () {
     using((arena) {
       final array = JArray(JBoolean.type, 3)..deletedIn(arena);
       expect(array.length, 3);
@@ -41,7 +47,7 @@
       }, throwsRangeError);
     });
   });
-  test("Java char array", () {
+  testRunner("Java char array", () {
     using((arena) {
       final array = JArray(JChar.type, 3)..deletedIn(arena);
       expect(array.length, 3);
@@ -66,7 +72,7 @@
       }, throwsRangeError);
     });
   });
-  test("Java byte array", () {
+  testRunner("Java byte array", () {
     using((arena) {
       final array = JArray(JByte.type, 3)..deletedIn(arena);
       expect(array.length, 3);
@@ -91,7 +97,7 @@
       }, throwsRangeError);
     });
   });
-  test("Java short array", () {
+  testRunner("Java short array", () {
     using((arena) {
       final array = JArray(JShort.type, 3)..deletedIn(arena);
       expect(array.length, 3);
@@ -116,7 +122,7 @@
       }, throwsRangeError);
     });
   });
-  test("Java int array", () {
+  testRunner("Java int array", () {
     using((arena) {
       final array = JArray(JInt.type, 3)..deletedIn(arena);
       expect(array.length, 3);
@@ -142,7 +148,7 @@
     });
   });
   const epsilon = 1e-6;
-  test("Java float array", () {
+  testRunner("Java float array", () {
     using((arena) {
       final array = JArray(JFloat.type, 3)..deletedIn(arena);
       expect(array.length, 3);
@@ -167,7 +173,7 @@
       }, throwsRangeError);
     });
   });
-  test("Java double array", () {
+  testRunner("Java double array", () {
     using((arena) {
       final array = JArray(JDouble.type, 3)..deletedIn(arena);
       expect(array.length, 3);
@@ -192,7 +198,7 @@
       }, throwsRangeError);
     });
   });
-  test("Java string array", () {
+  testRunner("Java string array", () {
     using((arena) {
       final array = JArray(JString.type, 3)..deletedIn(arena);
       expect(array.length, 3);
@@ -227,7 +233,7 @@
       }, throwsRangeError);
     });
   });
-  test("Java object array", () {
+  testRunner("Java object array", () {
     using((arena) {
       final array = JArray(JObject.type, 3)..deletedIn(arena);
       expect(array.length, 3);
@@ -236,7 +242,7 @@
       expect(array[2].reference, nullptr);
     });
   });
-  test("Java 2d array", () {
+  testRunner("Java 2d array", () {
     using((arena) {
       final array = JArray(JInt.type, 3)..deletedIn(arena);
       array[0] = 1;
@@ -256,7 +262,7 @@
       expect(twoDimArray[2][2], 4);
     });
   });
-  test("JArray.filled", () {
+  testRunner("JArray.filled", () {
     using((arena) {
       final string = "abc".toJString()..deletedIn(arena);
       final array = JArray.filled(3, string)..deletedIn(arena);
diff --git a/pkgs/jni/test/jni_test.dart b/pkgs/jni/test/jni_test.dart
deleted file mode 100644
index 19bae21..0000000
--- a/pkgs/jni/test/jni_test.dart
+++ /dev/null
@@ -1,131 +0,0 @@
-// 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.
-
-import 'dart:io';
-
-import 'package:jni/jni.dart';
-import 'package:test/test.dart';
-
-void main() {
-  // Running on Android through flutter, this plugin
-  // will bind to Android runtime's JVM.
-  // On other platforms eg Flutter desktop or Dart standalone
-  // You need to manually create a JVM at beginning.
-  //
-  // On flutter desktop, the C wrappers are bundled, and helperPath param
-  // is not required.
-  //
-  // On dart standalone, however, there's no way to bundle the wrappers.
-  // You have to manually pass the path to the `dartjni` dynamic library.
-
-  if (!Platform.isAndroid) {
-    try {
-      Jni.spawn(dylibDir: "build/jni_libs", jvmOptions: ["-Xmx128m"]);
-    } on JvmExistsException catch (_) {
-      // TODO(#51): Support destroying and reinstantiating JVM.
-    }
-  }
-
-  // Tests in this file demonstrate how to use `GlobalJniEnv`, a thin
-  // abstraction over JNIEnv in JNI C API. This can be used from multiple
-  // threads, and converts all returned object references to global references,
-  // so that you don't need to worry about whether your Dart code will be
-  // scheduled on another thread.
-  //
-  // GlobalJniEnv wraps all methods of JNIEnv (UpperCamelCase, reflecting the
-  // original name of the method) and provides few more extension methods
-  // (lowerCamelCase).
-  //
-  // For examples of a higher level API, see `jni_object_tests.dart`.
-  final env = Jni.env;
-
-  test('initDLApi', () {
-    Jni.initDLApi();
-  });
-
-  test('get JNI Version', () {
-    expect(Jni.env.GetVersion(), isNot(equals(0)));
-  });
-
-  test(
-      'Manually lookup & call Integer.toHexString',
-      () => using((arena) {
-            // Method names on JniEnv* from C JNI API are capitalized
-            // like in original, while other extension methods
-            // follow Dart naming conventions.
-            final integerClass =
-                env.FindClass("java/lang/Integer".toNativeChars(arena));
-            // Refer JNI spec on how to construct method signatures
-            // Passing wrong signature leads to a segfault
-            final hexMethod = env.GetStaticMethodID(
-                integerClass,
-                "toHexString".toNativeChars(arena),
-                "(I)Ljava/lang/String;".toNativeChars(arena));
-
-            for (var i in [1, 80, 13, 76, 11344]) {
-              // if your argument is int, bool, or JObject (`Pointer<Void>`)
-              // it can be directly placed in the list. To convert into different primitive
-              // types, use JValue<Type> wrappers.
-              final jres = env.CallStaticObjectMethodA(integerClass, hexMethod,
-                  Jni.jvalues([JValueInt(i)], allocator: arena));
-
-              // use asDartString extension method on Pointer<JniEnv>
-              // to convert a String jobject result to string
-              final res = env.asDartString(jres);
-              expect(res, equals(i.toRadixString(16)));
-
-              // Any object or class result from java is a local reference
-              // and needs to be deleted explicitly.
-              // Note that method and field IDs aren't local references.
-              // But they are valid only until a reference to corresponding
-              // java class exists.
-              env.DeleteGlobalRef(jres);
-            }
-            env.DeleteGlobalRef(integerClass);
-          }));
-
-  test("asJString extension method", () {
-    const str = "QWERTY QWERTY";
-    // convenience method that wraps
-    // converting dart string to native string,
-    // instantiating java string, and freeing the native string
-    final jstr = env.asJString(str);
-    expect(str, equals(env.asDartString(jstr)));
-    env.DeleteGlobalRef(jstr);
-  });
-
-  test(
-      "Convert back & forth between Dart & Java strings",
-      () => using((arena) {
-            const str = "ABCD EFGH";
-            // This is what asJString and asDartString do internally
-            final jstr = env.NewStringUTF(str.toNativeChars(arena));
-            final jchars = env.GetStringUTFChars(jstr, nullptr);
-            final dstr = jchars.toDartString();
-            env.ReleaseStringUTFChars(jstr, jchars);
-            expect(str, equals(dstr));
-            env.DeleteGlobalRef(jstr);
-          }));
-
-  test(
-      "Print something from Java",
-      () => using((arena) {
-            final system =
-                env.FindClass("java/lang/System".toNativeChars(arena));
-            final field = env.GetStaticFieldID(
-                system,
-                "out".toNativeChars(arena),
-                "Ljava/io/PrintStream;".toNativeChars(arena));
-            final out = env.GetStaticObjectField(system, field);
-            final printStream = env.GetObjectClass(out);
-            final println = env.GetMethodID(
-                printStream,
-                "println".toNativeChars(arena),
-                "(Ljava/lang/String;)V".toNativeChars(arena));
-            const str = "\nHello World from JNI!";
-            final jstr = env.asJString(str);
-            env.CallVoidMethodA(out, println, Jni.jvalues([jstr]));
-            env.deleteAllRefs([system, printStream, jstr]);
-          }));
-}
diff --git a/pkgs/jni/test/jobject_test.dart b/pkgs/jni/test/jobject_test.dart
index b055f7d..e951002 100644
--- a/pkgs/jni/test/jobject_test.dart
+++ b/pkgs/jni/test/jobject_test.dart
@@ -10,6 +10,10 @@
 
 import 'package:jni/jni.dart';
 
+import 'test_util/test_util.dart';
+
+const maxLongInJava = 9223372036854775807;
+
 void main() {
   // Don't forget to initialize JNI.
   if (!Platform.isAndroid) {
@@ -19,17 +23,20 @@
       // TODO(#51): Support destroying and reinstantiating JVM.
     }
   }
+  run(testRunner: test);
+}
 
+void run({required TestRunnerCallback testRunner}) {
   // The API based on JniEnv is intended to closely mimic C API of JNI,
   // And thus can be too verbose for simple experimenting and one-off uses
   // JObject API provides an easier way to perform some common operations.
   //
   // However, if binding generation using jnigen is possible, that should be
   // the first choice.
-  test("Long.intValue() using JObject", () {
-    // JniClass wraps a local class reference, and
+  testRunner("Long.intValue() using JObject", () {
+    // JClass wraps a local class reference, and
     // provides convenience functions.
-    final longClass = Jni.findJniClass("java/lang/Long");
+    final longClass = Jni.findJClass("java/lang/Long");
 
     // looks for a constructor with given signature.
     // equivalently you can lookup a method with name <init>
@@ -44,15 +51,15 @@
     final intValue = long.callMethodByName<int>("intValue", "()I", []);
     expect(intValue, equals(176));
 
-    // delete any JObject and JniClass instances using .delete() after use.
+    // delete any JObject and JClass instances using .delete() after use.
     // Deletion is not strictly required since JNI objects / classes have
     // a NativeFinalizer. But deleting them after use is a good practice.
     long.delete();
     longClass.delete();
   });
 
-  test("call a static method using JniClass APIs", () {
-    final integerClass = Jni.findJniClass("java/lang/Integer");
+  testRunner("call a static method using JClass APIs", () {
+    final integerClass = Jni.findJClass("java/lang/Integer");
     final result = integerClass.callStaticMethodByName<JString>(
         "toHexString", "(I)Ljava/lang/String;", [JValueInt(31)]);
 
@@ -68,8 +75,8 @@
     integerClass.delete();
   });
 
-  test("Call method with null argument, expect exception", () {
-    final integerClass = Jni.findJniClass("java/lang/Integer");
+  testRunner("Call method with null argument, expect exception", () {
+    final integerClass = Jni.findJClass("java/lang/Integer");
     expect(
         () => integerClass.callStaticMethodByName<int>(
             "parseInt", "(Ljava/lang/String;)I", [nullptr]),
@@ -77,21 +84,25 @@
     integerClass.delete();
   });
 
-  test("Try to find a non-exisiting class, expect exception", () {
-    expect(() => Jni.findJniClass("java/lang/NotExists"), throwsException);
-  });
+  // Skip this test on Android integration test because it fails there, possibly
+  // due to a CheckJNI precondition check.
+  if (!Platform.isAndroid) {
+    testRunner("Try to find a non-exisiting class, expect exception", () {
+      expect(() => Jni.findJClass("java/lang/NotExists"), throwsException);
+    });
+  }
 
   /// callMethodByName will be expensive if making same call many times
   /// Use getMethodID to get a method ID and use it in subsequent calls
-  test("Example for using getMethodID", () {
-    final longClass = Jni.findJniClass("java/lang/Long");
+  testRunner("Example for using getMethodID", () {
+    final longClass = Jni.findJClass("java/lang/Long");
     final bitCountMethod = longClass.getStaticMethodID("bitCount", "(J)I");
 
     // Use newInstance if you want only one instance.
     // It finds the class, gets constructor ID and constructs an instance.
     final random = Jni.newInstance("java/util/Random", "()V", []);
 
-    // You don't need a JniClass reference to get instance method IDs
+    // You don't need a JClass reference to get instance method IDs
     final nextIntMethod = random.getMethodID("nextInt", "(I)I");
 
     for (int i = 0; i < 100; i++) {
@@ -108,28 +119,28 @@
   });
 
   // One-off invocation of static method in single call.
-  test("invoke_", () {
+  testRunner("invoke_", () {
     final m = Jni.invokeStaticMethod<int>("java/lang/Short", "compare", "(SS)I",
         [JValueShort(1234), JValueShort(1324)]);
     expect(m, equals(1234 - 1324));
   });
 
-  test("Java char from string", () {
+  testRunner("Java char from string", () {
     final m = Jni.invokeStaticMethod<bool>("java/lang/Character", "isLowerCase",
         "(C)Z", [JValueChar.fromString('X')]);
     expect(m, isFalse);
   });
 
   // One-off access of static field in single call.
-  test("Get static field directly", () {
+  testRunner("Get static field directly", () {
     final maxLong = Jni.retrieveStaticField<int>(
         "java/lang/Short", "MAX_VALUE", "S", JniCallType.shortType);
     expect(maxLong, equals(32767));
   });
 
   // Use callStringMethod if all you care about is a string result
-  test("callStaticStringMethod", () {
-    final longClass = Jni.findJniClass("java/lang/Long");
+  testRunner("callStaticStringMethod", () {
+    final longClass = Jni.findJClass("java/lang/Long");
     const n = 1223334444;
     final strFromJava = longClass.callStaticMethodByName<String>(
         "toOctalString", "(J)Ljava/lang/String;", [n]);
@@ -137,11 +148,11 @@
     longClass.delete();
   });
 
-  // In JObject, JniClass, and retrieve_/invoke_ methods
+  // In JObject, JClass, and retrieve_/invoke_ methods
   // you can also pass Dart strings, apart from range of types
   // allowed by Jni.jvalues
   // They will be converted automatically.
-  test(
+  testRunner(
     "Passing strings in arguments",
     () {
       final out = Jni.retrieveStaticField<JObject>(
@@ -154,26 +165,26 @@
     },
   );
 
-  test("Passing strings in arguments 2", () {
+  testRunner("Passing strings in arguments 2", () {
     final twelve = Jni.invokeStaticMethod<int>("java/lang/Byte", "parseByte",
         "(Ljava/lang/String;)B", ["12"], JniCallType.byteType);
     expect(twelve, equals(12));
   });
 
   // You can use() method on JObject for using once and deleting.
-  test("use() method", () {
+  testRunner("use() method", () {
     final randomInt = Jni.newInstance("java/util/Random", "()V", []).use(
         (random) =>
             random.callMethodByName<int>("nextInt", "(I)I", [JValueInt(15)]));
     expect(randomInt, lessThan(15));
   });
 
-  // The JObject and JniClass have NativeFinalizer. However, it's possible to
+  // The JObject and JClass have NativeFinalizer. However, it's possible to
   // explicitly use `Arena`.
-  test('Using arena', () {
+  testRunner('Using arena', () {
     final objects = <JObject>[];
     using((arena) {
-      final r = Jni.findJniClass('java/util/Random')..deletedIn(arena);
+      final r = Jni.findJClass('java/util/Random')..deletedIn(arena);
       final ctor = r.getCtorID("()V");
       for (int i = 0; i < 10; i++) {
         objects.add(r.newInstance(ctor, [])..deletedIn(arena));
@@ -184,14 +195,15 @@
     }
   });
 
-  test("enums", () {
+  testRunner("enums", () {
     // Don't forget to escape $ in nested type names
     final ordinal = Jni.retrieveStaticField<JObject>(
             "java/net/Proxy\$Type", "HTTP", "Ljava/net/Proxy\$Type;")
         .use((f) => f.callMethodByName<int>("ordinal", "()I", []));
     expect(ordinal, equals(1));
   });
-  test("casting", () {
+
+  testRunner("casting", () {
     using((arena) {
       final str = "hello".toJString()..deletedIn(arena);
       final obj = str.castTo(JObject.type)..deletedIn(arena);
@@ -204,16 +216,44 @@
     });
   });
 
-  test("Isolate", () {
+  testRunner("Isolate", () {
     Isolate.spawn(doSomeWorkInIsolate, null);
   });
+
+  testRunner("Methods rethrow exceptions in Java as JniException", () {
+    expect(
+      () => Jni.invokeStaticMethod<int>(
+          "java/lang/Integer", "parseInt", "(Ljava/lang/String;)I", ["X"]),
+      throwsA(isA<JniException>()),
+    );
+  });
+
+  testRunner("Passing long integer values to JNI", () {
+    final maxLongStr = Jni.invokeStaticMethod<String>(
+      "java/lang/Long",
+      "toString",
+      "(J)Ljava/lang/String;",
+      [maxLongInJava],
+    );
+    expect(maxLongStr, equals('$maxLongInJava'));
+  });
+
+  testRunner('Returning long integers from JNI', () {
+    final maxLong = Jni.retrieveStaticField<int>(
+      "java/lang/Long",
+      "MAX_VALUE",
+      "J",
+      JniCallType.longType,
+    );
+    expect(maxLong, equals(maxLongInJava));
+  });
 }
 
 void doSomeWorkInIsolate(Void? _) {
   // On standalone target, make sure to call [setDylibDir] before accessing
-  // any JNI function.
+  // any JNI function in a new isolate.
   //
-  // otherwise getInstance will throw a "library not found" exception.
+  // otherwise subsequent JNI calls will throw a "library not found" exception.
   Jni.setDylibDir(dylibDir: "build/jni_libs");
   final random = Jni.newInstance("java/util/Random", "()V", []);
   // final r = random.callMethodByName<int>("nextInt", "(I)I", [256]);
diff --git a/pkgs/jni/test/test_util/test_util.dart b/pkgs/jni/test/test_util/test_util.dart
new file mode 100644
index 0000000..40d86eb
--- /dev/null
+++ b/pkgs/jni/test/test_util/test_util.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2023, 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.
+
+typedef TestCaseCallback = void Function();
+typedef TestRunnerCallback = void Function(
+  String description,
+  TestCaseCallback test,
+);
diff --git a/pkgs/jni/test/type_test.dart b/pkgs/jni/test/type_test.dart
index 0f7f5bf..ecdcf10 100644
--- a/pkgs/jni/test/type_test.dart
+++ b/pkgs/jni/test/type_test.dart
@@ -8,6 +8,8 @@
 import 'package:jni/jni.dart';
 import 'package:test/test.dart';
 
+import 'test_util/test_util.dart';
+
 // Mocking this type tree:
 //   JObject
 //      |  \
@@ -209,8 +211,11 @@
       // TODO(#51): Support destroying and reinstantiating JVM.
     }
   }
+  run(testRunner: test);
+}
 
-  test('lowestCommonSuperType', () {
+void run({required TestRunnerCallback testRunner}) {
+  testRunner('lowestCommonSuperType', () {
     expect(lowestCommonSuperType([JObject.type]), JObject.type);
     expect(lowestCommonSuperType([JString.type]), JString.type);
     expect(lowestCommonSuperType([JObject.type, JObject.type]), JObject.type);
@@ -219,7 +224,7 @@
         JObject.type);
   });
 
-  test('Mocked type tree', () {
+  testRunner('Mocked type tree', () {
     // As a reminder, this is how the type tree looks like:
     //   JObject
     //      |  \
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/.github/workflows/test-package.yml b/pkgs/jni/third_party/ffigen_patch_jni/.github/workflows/test-package.yml
deleted file mode 100644
index 1b6b494..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/.github/workflows/test-package.yml
+++ /dev/null
@@ -1,78 +0,0 @@
-name: Dart CI
-
-on:
-  # Run on PRs and pushes to the default branch.
-  push:
-    branches: [ master, stable]
-  pull_request:
-    branches: [ master, stable]
-  schedule:
-    - cron: "0 0 * * 0"
-
-env:
-  PUB_ENVIRONMENT: bot.github
-
-jobs:
-  # Check code formatting and static analysis on a single OS (macos).
-  analyze:
-    runs-on: macos-latest
-    strategy:
-      fail-fast: false
-      matrix:
-        sdk: [stable]
-    steps:
-      - uses: actions/checkout@v2
-      - uses: dart-lang/setup-dart@v1.0
-        with:
-          sdk: ${{ matrix.sdk }}
-      - id: install
-        name: Install dependencies
-        run: dart pub get
-      - name: Check formatting
-        run: dart format --output=none --set-exit-if-changed .
-        if: always() && steps.install.outcome == 'success'
-      - name: Build test dylib and bindings
-        run: dart test/setup.dart
-      - name: Analyze code
-        run: dart analyze --fatal-infos
-        if: always() && steps.install.outcome == 'success'
-
-  test:
-    needs: analyze
-    # This job requires clang-10 which is the default on 20.04
-    runs-on: ubuntu-20.04
-    steps:
-      - uses: actions/checkout@v2
-      - uses: dart-lang/setup-dart@v1.0
-        with:
-          sdk: stable
-      - name: Install dependencies
-        run: dart pub get
-      - name: Install libclang-10-dev
-        run: sudo apt-get install libclang-10-dev
-      - name: Build test dylib and bindings
-        run: dart test/setup.dart
-      - name: Run VM tests
-        run: dart test --platform vm
-
-  mac-test:
-    needs: analyze
-    runs-on: macos-latest
-    steps:
-      - uses: actions/checkout@v2
-      - uses: dart-lang/setup-dart@v1.0
-        with:
-          sdk: stable
-      - name: Install dependencies
-        run: dart pub get
-      - name: Build test dylib and bindings
-        run: dart test/setup.dart
-      - name: Run VM tests
-        run: dart test --platform vm
-      - name: Collect coverage
-        run: ./tool/coverage.sh
-      - name: Upload coverage
-        uses: coverallsapp/github-action@v1.1.2
-        with:
-          github-token: ${{ secrets.GITHUB_TOKEN }}
-          path-to-lcov: lcov.info
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/.gitignore b/pkgs/jni/third_party/ffigen_patch_jni/.gitignore
deleted file mode 100644
index 71c0ba1..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/.gitignore
+++ /dev/null
@@ -1,41 +0,0 @@
-# See https://dart.dev/guides/libraries/private-files
-
-# Files and directories created by pub.
-.dart_tool/
-.packages
-pubspec.lock
-
-# IDE and debugger files.
-.clangd
-.gdb_history
-.history
-.vscode
-compile_commands.json
-
-# Directory created by dartdoc.
-# If you don't generate documentation locally you can remove this line.
-doc/api/
-
-# Avoid committing generated Javascript files:
-*.dart.js
-*.info.json      # Produced by the --dump-info flag.
-*.js             # When generated by dart2js. Don't specify *.js if your
-                 # project includes source files written in JavaScript.
-*.js_
-*.js.deps
-*.js.map
-
-# Generated shared libraries.
-*.so
-*.so.*
-*.dylib
-*.dll
-
-# Directory for quick experiments.
-experiments/
-
-# Files generated by tests for debugging purposes.
-test/debug_generated/*
-!test/debug_generated/readme.md
-lcov.info
-coverage.json
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/AUTHORS b/pkgs/jni/third_party/ffigen_patch_jni/AUTHORS
deleted file mode 100644
index 4f334e8..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/AUTHORS
+++ /dev/null
@@ -1,8 +0,0 @@
-# Below is a list of people and organizations that have contributed
-# to the Dart project. Names should be added to the list like so:
-#
-#   Name/Organization <email address>
-
-Google LLC
-
-Prerak Mann <mannprerak2@gmail.com>
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/CHANGELOG.md b/pkgs/jni/third_party/ffigen_patch_jni/CHANGELOG.md
deleted file mode 100644
index 83edcb0..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/CHANGELOG.md
+++ /dev/null
@@ -1,291 +0,0 @@
-# 6.0.1
-
-- Replace path separators in `include-directives` before matching file names.
-
-# 6.0.0
-- Removed config `dart-bool`. Booleans are now always generated with `bool`
-and `ffi.Bool` as it's Dart and C Type respectively.
-
-# 5.0.1
-
-- Add a the xcode tools llvm as default path on MacOS.
-
-# 5.0.0
-
-- Stable release targeting Dart 2.17, supporting ABI-specific integer types.
-- _EXPERIMENTAL_ support for ObjectiveC on MacOS hosts. The API and output
-  might change at any point. Feel free to report bugs if encountered.
-
-# 5.0.0-dev.1
-- Fixed invalid default dart types being generated for `size_t` and `wchar_t`.
-
-# 5.0.0-dev.0
-- Added support for generating ABI Specific integers.
-- Breaking: removed config keys - `size-map` and `typedef-map`.
-- Added config keys - `library-imports` and `type-map`.
-
-# 4.1.3
-- Analyzer fixes.
-
-# 4.1.2
-- Added fix for empty include list to exclude all
-
-# 4.1.1
-- Added fix for errors due to name collision between member name
-and type name used internally in structs/unions.
-
-# 4.1.0
-- Add config key `functions -> leaf` for specifying `isLeaf:true` for functions.
-
-# 4.0.0
-- Release for Dart SDK `>=2.14`.
-
-# 4.0.0-dev.2
-- Added config key `functions -> expose-typedefs` to expose the typedef
-to Native and Dart type.
-- Config key `function`->`symbol-address` no longer exposes the typedef
-to Native type. Use `expose-typedefs` to get the native type.
-
-# 4.0.0-dev.1
-- This package now targets package:lints for the generated code. The generated
-code uses C symbol names as is. Use either `// ignore_for_file: lintRule1, lintRule2`
-in the `preamble`, or rename the symbols to make package:lints happy.
-- Name collisions are now resolved by suffixing `<int>` instead of `_<int>`.
-
-# 4.0.0-dev.0
-- Added support for generating typedefs (_referred_ typedefs only).
-<table>
-<tr>
-<td>Example C Code</td>
-<td>Generated Dart typedef</td>
-</tr>
-<tr>
-<td>
-
-```C++
-typedef struct A{
-    ...
-} TA, *PA;
-
-TA func(PA ptr);
-```
-</td>
-<td>
-
-```dart
-class A extends ffi.Struct {...}
-typedef TA = A;
-typedef PA = ffi.Pointer<A>;
-TA func(PA ptr){...}
-```
-</td>
-</tr>
-</table>
-
-- All declarations that are excluded by the user are now only included if being
-used somewhere.
-- Improved struct/union include/exclude. These declarations can now be targetted
-by their actual name, or if they are unnamed then by the name of the first
-typedef that refers to them.
-
-# 3.1.0-dev.1
-- Users can now specify exact path to dynamic library in `llvm-path`.
-
-# 3.1.0-dev.0
-- Added support for generating unions.
-
-# 3.0.0
-- Release for dart sdk `>=2.13` (Support for packed structs and inline arrays).
-
-# 3.0.0-beta.0
-- Added support for inline arrays in `Struct`s.
-- Remove config key `array-workaround`.
-- Remove deprecated key `llvm-lib` from config, Use `llvm-path` instead.
-
-# 2.5.0-beta.1
-- Added support for `Packed` structs. Packed annotations are generated
-automatically but can be overriden using `structs -> pack` config.
-- Updated sdk constraints to `>=2.13.0-211.6.beta`.
-
-# 2.4.2
-- Fix issues due to declarations having duplicate names.
-- Fix name conflict of declaration with ffi library prefix.
-- Fix `char` not being recognized on platforms where it's unsigned by default.
-
-# 2.4.1
-- Added `/usr/lib` to default dynamic library location for linux.
-
-# 2.4.0
-- Added new config key `llvm-path` that accepts a list of `path/to/llvm`.
-- Deprecated config key `llvm-lib`.
-
-# 2.3.0
-- Added config key `compiler-opts-automatic -> macos -> include-c-standard-library`
-(default: true) to automatically find and add C standard library on macOS.
-- Allow passing list of string to config key `compiler-opts`.
-
-# 2.2.5
-- Added new command line flag `--compiler-opts` to the command line tool.
-
-# 2.2.4
-- Fix `sort: true` not working.
-- Fix extra `//` or `///` in comments when using `comments -> style`: `full`.
-
-# 2.2.3
-- Added new subkey `dependency-only` (options - `full (default) | opaque`) under `structs`.
-When set to `opaque`, ffigen will generate empty `Opaque` structs if structs
-were excluded in config (i.e added because they were a dependency) and
-only passed by reference(pointer).
-
-# 2.2.2
-- Fixed generation of empty opaque structs due to forward declarations in header files.
-
-# 2.2.1
-- Fixed generation of duplicate constants suffixed with `_<int>` when using multiple entry points.
-
-# 2.2.0
-- Added subkey `symbol-address` to expose native symbol pointers for `functions` and `globals`.
-
-# 2.1.0
-- Added a new named constructor `NativeLibrary.fromLookup()` to support dynamic linking.
-- Updated dart SDK constraints to latest stable version `2.12.0`.
-
-# 2.0.3
-- Ignore typedef to struct pointer when possible.
-- Recursively create directories for output file.
-
-# 2.0.2
-- Fixed illegal use of `const` in name, crash due to unnamed inline structs and
-structs having `Opaque` members.
-
-# 2.0.1
-- Switch to preview release of `package:quiver`.
-
-# 2.0.0
-- Upgraded all dependencies. `package:ffigen` now runs with sound null safety.
-
-# 2.0.0-dev.6
-- Functions marked `inline` are now skipped.
-
-# 2.0.0-dev.5
-- Use `Opaque` for representing empty `Struct`s.
-
-# 2.0.0-dev.4
-- Add support for parsing and generating globals.
-
-# 2.0.0-dev.3
-- Removed the usage of `--no-sound-null-safety` flag.
-
-# 2.0.0-dev.2
-- Removed setup phase for ffigen. Added new optional config key `llvm-lib`
-to specify path to `llvm/lib` folder.
-
-# 2.0.0-dev.1
-- Added support for passing and returning struct by value in functions.
-
-# 2.0.0-dev.0
-- Added support for Nested structs.
-
-# 2.0.0-nullsafety.1
-- Removed the need for `--no-sound-null-safety` flag.
-
-# 2.0.0-nullsafety.0
-- Migrated to (unsound) null safety.
-
-# 1.2.0
-- Added support for `Dart_Handle` from `dart_api.h`.
-
-# 1.1.0
-- `typedef-map` can now be used to map a typedef name to a native type directly.
-
-# 1.0.6
-- Fixed missing typedefs nested in another typedef's return types.
-
-# 1.0.5
-- Fixed issues with generating macros of type `double.Infinity` and `double.NaN`.
-
-# 1.0.4
-- Updated code to use `dart format` instead of `dartfmt` for sdk version `>= 2.10.0`.
-
-# 1.0.3
-- Fixed errors due to extended ASCII and control characters in macro strings.
-
-# 1.0.2
-- Fix indentation for pub's readme.
-
-# 1.0.1
-- Fixed generation of `NativeFunction` parameters instead of `Pointer<NativeFunction>` in type signatures.
-
-# 1.0.0
-- Bump version to 1.0.0.
-- Handle unimplememnted function pointers causing errors.
-- Log lexical/semantic issues in headers as SEVERE.
-
-# 0.3.0
-- Added support for including/excluding/renaming _un-named enums_ using key `unnamed_enums`.
-
-# 0.2.4+1
-- Minor changes to dylib creation error log.
-
-# 0.2.4
-- Added support for C booleans as Uint8.
-- Added config `dart-bool` (default: true) to use dart bool instead of int in function parameters and return type.
-
-# 0.2.3+3
-- Wrapper dynamic library version now uses ffigen version from its pubspec.yaml file.
-
-# 0.2.3+2
-- Handle code formatting using dartfmt by finding dart-sdk.
-
-# 0.2.3+1
-- Fixed missing typedefs of nested function pointers.
-
-# 0.2.3
-- Fixed parsing structs with bitfields, all members of structs with bit field members will now be removed. See [#84](https://github.com/dart-lang/ffigen/issues/84)
-
-# 0.2.2+1
-- Updated `package:meta` version to `^1.1.8` for compatibility with flutter sdk.
-
-# 0.2.2
-- Fixed multiple generation/skipping of typedef enclosed declarations.
-- Typedef names are now given higher preference over inner names, See [#83](https://github.com/dart-lang/ffigen/pull/83).
-
-# 0.2.1+1
-- Added FAQ to readme.
-
-# 0.2.1
-- Fixed missing/duplicate typedef generation.
-
-# 0.2.0
-- Updated header config. Header `entry-points` and `include-directives` are now specified under `headers` key. Glob syntax is allowed.
-- Updated declaration `include`/`exclude` config. These are now specified as a list.
-- Added Regexp based declaration renaming using `rename` subkey.
-- Added Regexp based member renaming for structs, enums and functions using `member-rename` subkey. `prefix` and `prefix-replacement` subkeys have been removed.
-
-# 0.1.5
-- Added support for parsing macros and anonymous unnamed enums. These are generated as top level constants.
-
-# 0.1.4
-- Comments config now has a style and length sub keys - `style: doxygen(default) | any`, `length: brief | full(default)`, and can be disabled by passing `comments: false`.
-
-# 0.1.3
-- Handled function arguments - dart keyword name collision
-- Fix travis tests: the dynamic library is created using `pub run ffigen:setup` before running the tests.
-
-# 0.1.2
-- Fixed wrapper not found error when running `pub run ffigen`.
-
-# 0.1.1
-- Address pub score: follow dart File conventions, provide documentation, and pass static analysis.
-
-# 0.1.0
-- Support for Functions, Structs and Enums.
-- Glob support for specifying headers.
-- HeaderFilter - Include/Exclude declarations from specific header files using name matching.
-- Filters - Include/Exclude function, structs and enum declarations using Regexp or Name matching.
-- Prefixing - function, structs and enums can have a global prefix. Individual prefix Replacement support using Regexp.
-- Comment extraction: full/brief/none
-- Support for fixed size arrays in struct. `array-workaround` (if enabled) will generate helpers for accessing fixed size arrays in structs.
-- Size for ints can be specified using `size-map` in config.
-- Options to disable using supported typedefs (e.g `uint8_t => Uint8`), sort bindings.
-- Option to add a raw `preamble` which is included as is in the generated file.
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/LICENSE b/pkgs/jni/third_party/ffigen_patch_jni/LICENSE
deleted file mode 100644
index 467a982..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/LICENSE
+++ /dev/null
@@ -1,27 +0,0 @@
-Copyright 2020, the Dart project authors.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
-    * Redistributions of source code must retain the above copyright
-      notice, this list of conditions and the following disclaimer.
-    * Redistributions in binary form must reproduce the above
-      copyright notice, this list of conditions and the following
-      disclaimer in the documentation and/or other materials provided
-      with the distribution.
-    * Neither the name of Google LLC nor the names of its
-      contributors may be used to endorse or promote products derived
-      from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/README.md b/pkgs/jni/third_party/ffigen_patch_jni/README.md
deleted file mode 100644
index 7cd52bf..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/README.md
+++ /dev/null
@@ -1,8 +0,0 @@
-#### Developer's Note
-
-One-off patch of [ffigen](https://github.com/dart-lang/ffigen) for generating bindings of some JNI structs.
-
-Only changes to ffigen source are made in lib/src/code_generator/compound.dart file. The purpose of these changes is to write the extension methods along with certain types, which make calling function pointer fields easier.
-
-The modified FFIGEN is used to generate `lib/src/third_party/jni_bindings_generated.dart` using both header files in src/ and third_party/jni.h (the JNI header file from Android NDK). This provides bulk of our interface to JNI through FFI.
-
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/analysis_options.yaml b/pkgs/jni/third_party/ffigen_patch_jni/analysis_options.yaml
deleted file mode 100644
index 2948143..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/analysis_options.yaml
+++ /dev/null
@@ -1,24 +0,0 @@
-# Copyright (c) 2020, 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.
-
-include: package:lints/recommended.yaml
-
-analyzer:
-  exclude:
-    - 'test/**_expected*'
-    # Goldens cannot be generated outside MacOS causing analysis errors.
-    - test/native_objc_test/** 
-  language:
-    strict-casts: true
-    strict-inference: true
-
-linter:
-  rules:
-    # Enabled.
-    directives_ordering: true
-    prefer_final_locals: true
-    duplicate_import: false
-    prefer_final_in_for_each: true
-    # Disabled.
-    constant_identifier_names: false
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/bin/ffigen.dart b/pkgs/jni/third_party/ffigen_patch_jni/bin/ffigen.dart
deleted file mode 100644
index 6156ed0..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/bin/ffigen.dart
+++ /dev/null
@@ -1,6 +0,0 @@
-// Copyright (c) 2020, 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.
-//
-
-export 'package:ffigen/src/executables/ffigen.dart';
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/lib/ffigen.dart b/pkgs/jni/third_party/ffigen_patch_jni/lib/ffigen.dart
deleted file mode 100644
index 3425eec..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/lib/ffigen.dart
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright (c) 2020, 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.
-
-/// A bindings generator for dart.
-///
-/// See complete usage at - https://pub.dev/packages/ffigen.
-library ffigen;
-
-export 'src/code_generator.dart' show Library;
-export 'src/config_provider.dart' show Config;
-export 'src/header_parser.dart' show parse;
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/README.md b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/README.md
deleted file mode 100644
index 2b20f84..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/README.md
+++ /dev/null
@@ -1,41 +0,0 @@
-# **_package:ffigen_**: Internal Working
-## Table of Contents -
-1. [Overview](#overview)
-2. [LibClang](#LibClang)
-    1. [Bindings](#Bindings)
-3. [Scripts](#scripts)
-    1. [ffigen.dart](#ffigen.dart)
-4. [Components](#components)
-    1. [Config Provider](#Config-Provider)
-    2. [Header Parser](#Header-Parser)
-    3. [Code Generator](#Code-Generator)
-# Overview
-`package:ffigen` simplifies the process of generating `dart:ffi` bindings from C header files. It is simple to use, with the input being a small YAML config file. It requires LLVM (9+) to work. This document tries to give a complete overview of every component without going into too many details about every single class/file.
-# LibClang
-`package:ffigen` binds to LibClang using `dart:ffi` for parsing C header files. 
-## Bindings
-The config file for generating bindings is `tool/libclang_config.yaml`. The bindings are generated to `lib/src/header_parser/clang_bindings/clang_bindings.dart`. These are used by [Header Parser](#header-parser) for calling libclang functions.
-# Scripts
-## ffigen.dart
-This is the main entry point for the user-  `dart run ffigen`.
-- Command-line options:
-    - `--verbose`: Sets log level.
-    - `--config`: Specifies a config file.
-- The internal modules are called by `ffigen.dart` in the following way:
-- `ffigen.dart` will try to find dynamic library in default locations. If that fails, the user must excplicitly specify location in ffigen's config under the key `llvm-path`.
-    - It first creates a `Config` object from an input Yaml file. This is used by other modules.
-    - The `parse` method is then invoked to generate a `Library` object.
-    - Finally, the code is generated from the `Library` object to the specified file.
-# Components
-## Config Provider
-The Config Provider holds all the configurations required by other modules.
-- Config Provider handles validation and extraction of configurations from YAML files.
-- Config Provider converts configurations to the format required by other modules. This object is passed around to every other module.
-## Header Parser
-The Header Parser parses C header files and converts them into a `Library` object.
-- Header Parser handles including/excluding/renaming of declarations.
-- Header Parser also filters out any _unimplemented_ or _unsupported_ declarations before generating a `Library` object.
-## Code Generator
-The Code Generator generates the actual string bindings.
-- Code generator handles all external name collisions, while internal name conflicts are handled by each specific `Binding`.
-- Code Generator also handles how workarounds for arrays and bools are generated.
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator.dart b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator.dart
deleted file mode 100644
index 82b2ed6..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator.dart
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) 2020, 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.
-
-/// Generates FFI bindings for a given [Library].
-library code_generator;
-
-export 'code_generator/binding.dart';
-export 'code_generator/compound.dart';
-export 'code_generator/constant.dart';
-export 'code_generator/enum_class.dart';
-export 'code_generator/func.dart';
-export 'code_generator/func_type.dart';
-export 'code_generator/global.dart';
-export 'code_generator/handle.dart';
-export 'code_generator/imports.dart';
-export 'code_generator/library.dart';
-export 'code_generator/native_type.dart';
-export 'code_generator/objc_block.dart';
-export 'code_generator/objc_built_in_functions.dart';
-export 'code_generator/objc_interface.dart';
-export 'code_generator/pointer.dart';
-export 'code_generator/struct.dart';
-export 'code_generator/type.dart';
-export 'code_generator/typealias.dart';
-export 'code_generator/union.dart';
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/binding.dart b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/binding.dart
deleted file mode 100644
index 2e2f189..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/binding.dart
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright (c) 2020, 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.
-
-import 'binding_string.dart';
-import 'writer.dart';
-
-/// Base class for all Bindings.
-///
-/// Do not extend directly, use [LookUpBinding] or [NoLookUpBinding].
-abstract class Binding {
-  /// Holds the Unified Symbol Resolution string obtained from libclang.
-  final String usr;
-
-  /// The name as it was in C.
-  final String originalName;
-
-  /// Binding name to generate, may get changed to resolve name conflicts.
-  String name;
-
-  final String? dartDoc;
-  final bool isInternal;
-
-  Binding({
-    required this.usr,
-    required this.originalName,
-    required this.name,
-    this.dartDoc,
-    this.isInternal = false,
-  });
-
-  /// Get all dependencies, including itself and save them in [dependencies].
-  void addDependencies(Set<Binding> dependencies);
-
-  /// Converts a Binding to its actual string representation.
-  ///
-  /// Note: This does not print the typedef dependencies.
-  /// Must call [getTypedefDependencies] first.
-  BindingString toBindingString(Writer w);
-}
-
-/// Base class for bindings which look up symbols in dynamic library.
-abstract class LookUpBinding extends Binding {
-  LookUpBinding({
-    String? usr,
-    String? originalName,
-    required String name,
-    String? dartDoc,
-    bool isInternal = false,
-  }) : super(
-          usr: usr ?? name,
-          originalName: originalName ?? name,
-          name: name,
-          dartDoc: dartDoc,
-          isInternal: isInternal,
-        );
-}
-
-/// Base class for bindings which don't look up symbols in dynamic library.
-abstract class NoLookUpBinding extends Binding {
-  NoLookUpBinding({
-    String? usr,
-    String? originalName,
-    required String name,
-    String? dartDoc,
-    bool isInternal = false,
-  }) : super(
-          usr: usr ?? name,
-          originalName: originalName ?? name,
-          name: name,
-          dartDoc: dartDoc,
-          isInternal: isInternal,
-        );
-}
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/binding_string.dart b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/binding_string.dart
deleted file mode 100644
index decfd6f..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/binding_string.dart
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (c) 2020, 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.
-
-/// A Binding's String representation.
-class BindingString {
-  // Meta data, (not used for generation).
-  final BindingStringType type;
-  final String string;
-
-  const BindingString({required this.type, required this.string});
-
-  @override
-  String toString() => string;
-}
-
-/// A [BindingString]'s type.
-enum BindingStringType {
-  func,
-  struct,
-  union,
-  constant,
-  global,
-  enumClass,
-  typeDef,
-  objcInterface,
-  objcBlock,
-}
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/compound.dart b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/compound.dart
deleted file mode 100644
index 3d477e8..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/compound.dart
+++ /dev/null
@@ -1,279 +0,0 @@
-// Copyright (c) 2021, 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.
-
-import 'package:ffigen/src/code_generator.dart';
-
-import 'binding_string.dart';
-import 'utils.dart';
-import 'writer.dart';
-
-// Very specific to JNI: Here `X` is vtable class if X contains function pointer
-// members invoked with first argument of type `X**`.
-const vtableClasses = {"JNIInvokeInterface": "JavaVM"};
-
-// Y is extension class if it contains function pointer fields which are
-// otherwise equivalent to normal functions, and just packed in a structure
-// for convenience.
-const extensionClasses = {'GlobalJniEnv', 'JniAccessors'};
-
-const methodNameRenames = {"throw": "throwException"};
-
-enum CompoundType { struct, union }
-
-/// A binding for Compound type - Struct/Union.
-abstract class Compound extends BindingType {
-  /// Marker for if a struct definition is complete.
-  ///
-  /// A function can be safely pass this struct by value if it's complete.
-  bool isIncomplete;
-
-  List<Member> members;
-
-  bool get isOpaque => members.isEmpty;
-
-  /// Value for `@Packed(X)` annotation. Can be null (no packing), 1, 2, 4, 8,
-  /// or 16.
-  ///
-  /// Only supported for [CompoundType.struct].
-  int? pack;
-
-  /// Marker for checking if the dependencies are parsed.
-  bool parsedDependencies = false;
-
-  CompoundType compoundType;
-  bool get isStruct => compoundType == CompoundType.struct;
-  bool get isUnion => compoundType == CompoundType.union;
-
-  Compound({
-    String? usr,
-    String? originalName,
-    required String name,
-    required this.compoundType,
-    this.isIncomplete = false,
-    this.pack,
-    String? dartDoc,
-    List<Member>? members,
-    bool isInternal = false,
-  })  : members = members ?? [],
-        super(
-          usr: usr,
-          originalName: originalName,
-          name: name,
-          dartDoc: dartDoc,
-          isInternal: isInternal,
-        );
-
-  factory Compound.fromType({
-    required CompoundType type,
-    String? usr,
-    String? originalName,
-    required String name,
-    bool isIncomplete = false,
-    int? pack,
-    String? dartDoc,
-    List<Member>? members,
-  }) {
-    switch (type) {
-      case CompoundType.struct:
-        return Struct(
-          usr: usr,
-          originalName: originalName,
-          name: name,
-          isIncomplete: isIncomplete,
-          pack: pack,
-          dartDoc: dartDoc,
-          members: members,
-        );
-      case CompoundType.union:
-        return Union(
-          usr: usr,
-          originalName: originalName,
-          name: name,
-          isIncomplete: isIncomplete,
-          pack: pack,
-          dartDoc: dartDoc,
-          members: members,
-        );
-    }
-  }
-
-  List<int> _getArrayDimensionLengths(Type type) {
-    final array = <int>[];
-    var startType = type;
-    while (startType is ConstantArray) {
-      array.add(startType.length);
-      startType = startType.child;
-    }
-    return array;
-  }
-
-  String _getInlineArrayTypeString(Type type, Writer w) {
-    if (type is ConstantArray) {
-      return '${w.ffiLibraryPrefix}.Array<'
-          '${_getInlineArrayTypeString(type.child, w)}>';
-    }
-    return type.getCType(w);
-  }
-
-  @override
-  BindingString toBindingString(Writer w) {
-    final s = StringBuffer();
-    final es = StringBuffer();
-    final isVtable = vtableClasses.containsKey(name);
-    final isExt = extensionClasses.contains(name);
-    final toExtend = isVtable || isExt;
-    late String ptrTypeString; // need this later
-    final enclosingClassName = name;
-    if (toExtend) {
-      final ffi = w.ffiLibraryPrefix;
-      if (isVtable) {
-        final ptrType = vtableClasses[name]!;
-        ptrTypeString = "$ffi.Pointer<$ptrType>";
-      } else {
-        ptrTypeString = "$ffi.Pointer<$name>";
-      }
-      es.write(
-          "extension ${enclosingClassName}Extension on $ptrTypeString {\n");
-    }
-    if (dartDoc != null) {
-      s.write(makeDartDoc(dartDoc!));
-    }
-    final voidPointer =
-        "${w.ffiLibraryPrefix}.Pointer<${w.ffiLibraryPrefix}.Void>";
-
-    /// Adding [enclosingClassName] because dart doesn't allow class member
-    /// to have the same name as the class.
-    final localUniqueNamer = UniqueNamer({enclosingClassName});
-
-    /// Marking type names because dart doesn't allow class member to have the
-    /// same name as a type name used internally.
-    for (final m in members) {
-      localUniqueNamer.markUsed(m.type.getDartType(w));
-    }
-
-    /// Write @Packed(X) annotation if struct is packed.
-    if (isStruct && pack != null) {
-      s.write('@${w.ffiLibraryPrefix}.Packed($pack)\n');
-    }
-    final dartClassName = isStruct ? 'Struct' : 'Union';
-    // Write class declaration.
-    s.write('class $enclosingClassName extends ');
-    s.write('${w.ffiLibraryPrefix}.${isOpaque ? 'Opaque' : dartClassName}{\n');
-    const depth = '  ';
-    for (final m in members) {
-      m.name = localUniqueNamer.makeUnique(m.name);
-      if (m.type is ConstantArray) {
-        s.write('$depth@${w.ffiLibraryPrefix}.Array.multi(');
-        s.write('${_getArrayDimensionLengths(m.type)})\n');
-        s.write('${depth}external ${_getInlineArrayTypeString(m.type, w)} ');
-        s.write('${m.name};\n\n');
-      } else {
-        if (m.dartDoc != null) {
-          s.write(depth + '/// ');
-          s.writeAll(m.dartDoc!.split('\n'), '\n' + depth + '/// ');
-          s.write('\n');
-        }
-        if (!sameDartAndCType(m.type, w)) {
-          s.write('$depth@${m.type.getCType(w)}()\n');
-        }
-        final isPointer = (m.type is PointerType);
-        final isFunctionPointer =
-            isPointer && (m.type as PointerType).child is NativeFunc;
-
-        final hasVarArgListParam = isFunctionPointer && m.name.endsWith('V');
-
-        if (toExtend && isFunctionPointer) {
-          final nf = (m.type as PointerType).child as NativeFunc;
-          final fnType = nf.type as FunctionType;
-
-          if (hasVarArgListParam) {
-            s.write('${depth}external $voidPointer _${m.name};\n\n');
-            continue;
-          }
-
-          s.write('${depth}external ${m.type.getDartType(w)} ${m.name};\n\n');
-          final extensionParams = fnType.parameters.toList(); // copy
-          final implicitThis = isVtable;
-          if (implicitThis) {
-            extensionParams.removeAt(0);
-          }
-          if (m.dartDoc != null) {
-            es.write('$depth/// ');
-            es.writeAll(m.dartDoc!.split('\n'), '\n$depth/// ');
-            es.write('\n');
-            es.write("$depth///\n"
-                "$depth/// This is an automatically generated extension method\n");
-          }
-          es.write("$depth${fnType.returnType.getDartType(w)} ${m.name}(");
-          final visibleParams = <String>[];
-          final actualParams = <String>[if (implicitThis) "this"];
-          final callableFnType = fnType.getDartType(w);
-
-          for (int i = 0; i < extensionParams.length; i++) {
-            final p = extensionParams[i];
-            final paramName = p.name.isEmpty
-                ? (m.params != null
-                    ? m.params![i + (implicitThis ? 1 : 0)]
-                    : "arg$i")
-                : p.name;
-            visibleParams.add("${p.type.getDartType(w)} $paramName");
-            actualParams.add(paramName);
-          }
-
-          es.write("${visibleParams.join(', ')}) {\n");
-          final ref = isVtable ? 'value.ref' : 'ref';
-          es.write(
-              "$depth${depth}return $ref.${m.name}.asFunction<$callableFnType>()(");
-          es.write(actualParams.join(", "));
-          es.write(");\n$depth}\n\n");
-        } else {
-          final memberName = hasVarArgListParam ? '_${m.name}' : m.name;
-          final memberType =
-              hasVarArgListParam ? voidPointer : m.type.getDartType(w);
-          s.write('${depth}external $memberType $memberName;\n\n');
-        }
-      }
-    }
-    if (toExtend) {
-      es.write("}\n\n");
-    }
-    s.write('}\n\n');
-
-    return BindingString(
-        type: isStruct ? BindingStringType.struct : BindingStringType.union,
-        string: s.toString() + es.toString());
-  }
-
-  @override
-  void addDependencies(Set<Binding> dependencies) {
-    if (dependencies.contains(this)) return;
-
-    dependencies.add(this);
-    for (final m in members) {
-      m.type.addDependencies(dependencies);
-    }
-  }
-
-  @override
-  bool get isIncompleteCompound => isIncomplete;
-
-  @override
-  String getCType(Writer w) => name;
-}
-
-class Member {
-  final String? dartDoc;
-  final String originalName;
-  String name;
-  final Type type;
-  final List<String>? params;
-
-  Member({
-    String? originalName,
-    required this.name,
-    required this.type,
-    this.dartDoc,
-    this.params,
-  }) : originalName = originalName ?? name;
-}
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/constant.dart b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/constant.dart
deleted file mode 100644
index 8fd7191..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/constant.dart
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright (c) 2020, 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.
-
-import 'binding.dart';
-import 'binding_string.dart';
-import 'utils.dart';
-import 'writer.dart';
-
-/// A simple Constant.
-///
-/// Expands to -
-/// ```dart
-/// const <type> <name> = <rawValue>;
-/// ```
-///
-/// Example -
-/// ```dart
-/// const int name = 10;
-/// ```
-class Constant extends NoLookUpBinding {
-  /// The rawType is pasted as it is. E.g 'int', 'String', 'double'
-  final String rawType;
-
-  /// The rawValue is pasted as it is.
-  ///
-  /// Put quotes if type is a string.
-  final String rawValue;
-
-  Constant({
-    String? usr,
-    String? originalName,
-    required String name,
-    String? dartDoc,
-    required this.rawType,
-    required this.rawValue,
-  }) : super(
-          usr: usr,
-          originalName: originalName,
-          name: name,
-          dartDoc: dartDoc,
-        );
-
-  @override
-  BindingString toBindingString(Writer w) {
-    final s = StringBuffer();
-    final constantName = name;
-
-    if (dartDoc != null) {
-      s.write(makeDartDoc(dartDoc!));
-    }
-
-    s.write('\nconst $rawType $constantName = $rawValue;\n\n');
-
-    return BindingString(
-        type: BindingStringType.constant, string: s.toString());
-  }
-
-  @override
-  void addDependencies(Set<Binding> dependencies) {
-    if (dependencies.contains(this)) return;
-
-    dependencies.add(this);
-  }
-}
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/dart_keywords.dart b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/dart_keywords.dart
deleted file mode 100644
index 93d5877..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/dart_keywords.dart
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright (c) 2020, 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.
-
-/// Dart reserved keywords, used for resolving conflict with a name.
-///
-/// Source: https://dart.dev/guides/language/language-tour#keywords.
-const keywords = {
-  'abstract',
-  'as',
-  'assert',
-  'async',
-  'await',
-  'break',
-  'case',
-  'catch',
-  'class',
-  'const',
-  'continue',
-  'covariant',
-  'default',
-  'deferred',
-  'do',
-  'dynamic',
-  'else',
-  'enum',
-  'export',
-  'extends',
-  'extension',
-  'external',
-  'factory',
-  'false',
-  'final',
-  'finally',
-  'for',
-  'Function',
-  'get',
-  'hide',
-  'if',
-  'implements',
-  'import',
-  'in',
-  'interface',
-  'is',
-  'late',
-  'library',
-  'mixin',
-  'new',
-  'null',
-  'on',
-  'operator',
-  'part',
-  'required',
-  'rethrow',
-  'return',
-  'set',
-  'show',
-  'static',
-  'super',
-  'switch',
-  'sync',
-  'this',
-  'throw',
-  'true',
-  'try',
-  'typedef',
-  'var',
-  'void',
-  'while',
-  'with',
-  'yield',
-};
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/enum_class.dart b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/enum_class.dart
deleted file mode 100644
index 4e8ec3a..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/enum_class.dart
+++ /dev/null
@@ -1,105 +0,0 @@
-// Copyright (c) 2020, 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.
-
-import 'binding.dart';
-import 'binding_string.dart';
-import 'native_type.dart';
-import 'type.dart';
-import 'utils.dart';
-import 'writer.dart';
-
-/// A binding for enums in C.
-///
-/// For a C enum -
-/// ```c
-/// enum Fruits {apple, banana = 10};
-/// ```
-/// The generated dart code is
-///
-/// ```dart
-/// class Fruits {
-///   static const apple = 0;
-///   static const banana = 10;
-/// }
-/// ```
-class EnumClass extends BindingType {
-  static final nativeType = NativeType(SupportedNativeType.Int32);
-
-  final List<EnumConstant> enumConstants;
-
-  EnumClass({
-    String? usr,
-    String? originalName,
-    required String name,
-    String? dartDoc,
-    List<EnumConstant>? enumConstants,
-  })  : enumConstants = enumConstants ?? [],
-        super(
-          usr: usr,
-          originalName: originalName,
-          name: name,
-          dartDoc: dartDoc,
-        );
-
-  @override
-  BindingString toBindingString(Writer w) {
-    final s = StringBuffer();
-    final enclosingClassName = name;
-
-    if (dartDoc != null) {
-      s.write(makeDartDoc(dartDoc!));
-    }
-
-    /// Adding [enclosingClassName] because dart doesn't allow class member
-    /// to have the same name as the class.
-    final localUniqueNamer = UniqueNamer({enclosingClassName});
-
-    // Print enclosing class.
-    s.write('abstract class $enclosingClassName {\n');
-    const depth = '  ';
-    for (final ec in enumConstants) {
-      final enumValueName = localUniqueNamer.makeUnique(ec.name);
-      if (ec.dartDoc != null) {
-        s.write(depth + '/// ');
-        s.writeAll(ec.dartDoc!.split('\n'), '\n' + depth + '/// ');
-        s.write('\n');
-      }
-      s.write(depth + 'static const int $enumValueName = ${ec.value};\n');
-    }
-    s.write('}\n\n');
-
-    return BindingString(
-        type: BindingStringType.enumClass, string: s.toString());
-  }
-
-  @override
-  void addDependencies(Set<Binding> dependencies) {
-    if (dependencies.contains(this)) return;
-
-    dependencies.add(this);
-  }
-
-  @override
-  String getCType(Writer w) => nativeType.getCType(w);
-
-  @override
-  String getDartType(Writer w) => nativeType.getDartType(w);
-
-  @override
-  String? getDefaultValue(Writer w, String nativeLib) => '0';
-}
-
-/// Represents a single value in an enum.
-class EnumConstant {
-  final String? originalName;
-  final String? dartDoc;
-  final String name;
-  final int value;
-  const EnumConstant({
-    String? originalName,
-    required this.name,
-    required this.value,
-    this.dartDoc,
-  }) : originalName = originalName ?? name;
-}
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/func.dart b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/func.dart
deleted file mode 100644
index c10b0c8..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/func.dart
+++ /dev/null
@@ -1,165 +0,0 @@
-// Copyright (c) 2020, 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.
-
-import 'package:ffigen/src/code_generator.dart';
-
-import 'binding_string.dart';
-import 'utils.dart';
-import 'writer.dart';
-
-/// A binding for C function.
-///
-/// For a C function -
-/// ```c
-/// int sum(int a, int b);
-/// ```
-/// The Generated dart code is -
-/// ```dart
-/// int sum(int a, int b) {
-///   return _sum(a, b);
-/// }
-///
-/// final _dart_sum _sum = _dylib.lookupFunction<_c_sum, _dart_sum>('sum');
-///
-/// typedef _c_sum = ffi.Int32 Function(ffi.Int32 a, ffi.Int32 b);
-///
-/// typedef _dart_sum = int Function(int a, int b);
-/// ```
-class Func extends LookUpBinding {
-  final FunctionType functionType;
-  final bool exposeSymbolAddress;
-  final bool exposeFunctionTypedefs;
-  final bool isLeaf;
-  late final String funcPointerName;
-
-  /// Contains typealias for function type if [exposeFunctionTypedefs] is true.
-  Typealias? _exposedCFunctionTypealias;
-  Typealias? _exposedDartFunctionTypealias;
-
-  /// [originalName] is looked up in dynamic library, if not
-  /// provided, takes the value of [name].
-  Func({
-    String? usr,
-    required String name,
-    String? originalName,
-    String? dartDoc,
-    required Type returnType,
-    List<Parameter>? parameters,
-    this.exposeSymbolAddress = false,
-    this.exposeFunctionTypedefs = false,
-    this.isLeaf = false,
-    bool isInternal = false,
-  })  : functionType = FunctionType(
-          returnType: returnType,
-          parameters: parameters ?? const [],
-        ),
-        super(
-          usr: usr,
-          originalName: originalName,
-          name: name,
-          dartDoc: dartDoc,
-          isInternal: isInternal,
-        ) {
-    for (var i = 0; i < functionType.parameters.length; i++) {
-      if (functionType.parameters[i].name.trim() == '') {
-        functionType.parameters[i].name = 'arg$i';
-      }
-    }
-
-    // Get function name with first letter in upper case.
-    final upperCaseName = name[0].toUpperCase() + name.substring(1);
-    if (exposeFunctionTypedefs) {
-      _exposedCFunctionTypealias = Typealias(
-        name: 'Native$upperCaseName',
-        type: functionType,
-      );
-      _exposedDartFunctionTypealias = Typealias(
-        name: 'Dart$upperCaseName',
-        type: functionType,
-        useDartType: true,
-      );
-    }
-  }
-
-  @override
-  BindingString toBindingString(Writer w) {
-    final s = StringBuffer();
-    final enclosingFuncName = name;
-    final funcVarName = w.wrapperLevelUniqueNamer.makeUnique('_$name');
-    funcPointerName = w.wrapperLevelUniqueNamer.makeUnique('_${name}Ptr');
-
-    if (dartDoc != null) {
-      s.write(makeDartDoc(dartDoc!));
-    }
-    // Resolve name conflicts in function parameter names.
-    final paramNamer = UniqueNamer({});
-    for (final p in functionType.parameters) {
-      p.name = paramNamer.makeUnique(p.name);
-    }
-    // Write enclosing function.
-    s.write('${functionType.returnType.getDartType(w)} $enclosingFuncName(\n');
-    for (final p in functionType.parameters) {
-      s.write('  ${p.type.getDartType(w)} ${p.name},\n');
-    }
-    s.write(') {\n');
-    s.write('return $funcVarName');
-
-    s.write('(\n');
-    for (final p in functionType.parameters) {
-      s.write('    ${p.name},\n');
-    }
-    s.write('  );\n');
-    s.write('}\n');
-
-    final cType = exposeFunctionTypedefs
-        ? _exposedCFunctionTypealias!.name
-        : functionType.getCType(w, writeArgumentNames: false);
-    final dartType = exposeFunctionTypedefs
-        ? _exposedDartFunctionTypealias!.name
-        : functionType.getDartType(w, writeArgumentNames: false);
-
-    if (exposeSymbolAddress) {
-      // Add to SymbolAddress in writer.
-      w.symbolAddressWriter.addSymbol(
-        type:
-            '${w.ffiLibraryPrefix}.Pointer<${w.ffiLibraryPrefix}.NativeFunction<$cType>>',
-        name: name,
-        ptrName: funcPointerName,
-      );
-    }
-    // Write function pointer.
-    s.write(
-        "late final $funcPointerName = ${w.lookupFuncIdentifier}<${w.ffiLibraryPrefix}.NativeFunction<$cType>>('$originalName');\n");
-    final isLeafString = isLeaf ? 'isLeaf:true' : '';
-    s.write(
-        'late final $funcVarName = $funcPointerName.asFunction<$dartType>($isLeafString);\n\n');
-
-    return BindingString(type: BindingStringType.func, string: s.toString());
-  }
-
-  @override
-  void addDependencies(Set<Binding> dependencies) {
-    if (dependencies.contains(this)) return;
-
-    dependencies.add(this);
-    functionType.addDependencies(dependencies);
-    if (exposeFunctionTypedefs) {
-      _exposedCFunctionTypealias!.addDependencies(dependencies);
-      _exposedDartFunctionTypealias!.addDependencies(dependencies);
-    }
-  }
-}
-
-/// Represents a Parameter, used in [Func] and [Typealias].
-class Parameter {
-  final String? originalName;
-  String name;
-  final Type type;
-
-  Parameter({String? originalName, this.name = '', required Type type})
-      : originalName = originalName ?? name,
-        // A [NativeFunc] is wrapped with a pointer because this is a shorthand
-        // used in C for Pointer to function.
-        type = type.typealiasType is NativeFunc ? PointerType(type) : type;
-}
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/func_type.dart b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/func_type.dart
deleted file mode 100644
index 0b8abfd..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/func_type.dart
+++ /dev/null
@@ -1,83 +0,0 @@
-// 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.
-
-import 'package:ffigen/src/code_generator.dart';
-
-import 'writer.dart';
-
-/// Represents a function type.
-class FunctionType extends Type {
-  final Type returnType;
-  final List<Parameter> parameters;
-
-  FunctionType({
-    required this.returnType,
-    required this.parameters,
-  });
-
-  String _getTypeString(
-      bool writeArgumentNames, String Function(Type) typeToString) {
-    final sb = StringBuffer();
-
-    // Write return Type.
-    sb.write(typeToString(returnType));
-
-    // Write Function.
-    sb.write(' Function(');
-    sb.write(parameters.map<String>((p) {
-      return '${typeToString(p.type)} ${writeArgumentNames ? p.name : ""}';
-    }).join(', '));
-    sb.write(')');
-
-    return sb.toString();
-  }
-
-  @override
-  String getCType(Writer w, {bool writeArgumentNames = true}) =>
-      _getTypeString(writeArgumentNames, (Type t) => t.getCType(w));
-
-  @override
-  String getDartType(Writer w, {bool writeArgumentNames = true}) =>
-      _getTypeString(writeArgumentNames, (Type t) => t.getDartType(w));
-
-  @override
-  String toString() => _getTypeString(false, (Type t) => t.toString());
-
-  @override
-  String cacheKey() => _getTypeString(false, (Type t) => t.cacheKey());
-
-  @override
-  void addDependencies(Set<Binding> dependencies) {
-    returnType.addDependencies(dependencies);
-    for (final p in parameters) {
-      p.type.addDependencies(dependencies);
-    }
-  }
-}
-
-/// Represents a NativeFunction<Function>.
-class NativeFunc extends Type {
-  final Type type;
-
-  NativeFunc(this.type);
-
-  @override
-  void addDependencies(Set<Binding> dependencies) {
-    type.addDependencies(dependencies);
-  }
-
-  @override
-  String getCType(Writer w) =>
-      '${w.ffiLibraryPrefix}.NativeFunction<${type.getCType(w)}>';
-
-  @override
-  String getDartType(Writer w) =>
-      '${w.ffiLibraryPrefix}.NativeFunction<${type.getCType(w)}>';
-
-  @override
-  String toString() => 'NativeFunction<${type.toString()}>';
-
-  @override
-  String cacheKey() => 'NatFn(${type.cacheKey()})';
-}
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/global.dart b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/global.dart
deleted file mode 100644
index 579d8dd..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/global.dart
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright (c) 2020, 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.
-
-import 'binding.dart';
-import 'binding_string.dart';
-import 'compound.dart';
-import 'type.dart';
-import 'utils.dart';
-import 'writer.dart';
-
-/// A binding to a global variable
-///
-/// For a C global variable -
-/// ```c
-/// int a;
-/// ```
-/// The generated dart code is -
-/// ```dart
-/// final int a = _dylib.lookup<ffi.Int32>('a').value;
-/// ```
-class Global extends LookUpBinding {
-  final Type type;
-  final bool exposeSymbolAddress;
-
-  Global({
-    String? usr,
-    String? originalName,
-    required String name,
-    required this.type,
-    String? dartDoc,
-    this.exposeSymbolAddress = false,
-  }) : super(
-          usr: usr,
-          originalName: originalName,
-          name: name,
-          dartDoc: dartDoc,
-        );
-
-  @override
-  BindingString toBindingString(Writer w) {
-    final s = StringBuffer();
-    final globalVarName = name;
-    if (dartDoc != null) {
-      s.write(makeDartDoc(dartDoc!));
-    }
-    final pointerName = w.wrapperLevelUniqueNamer.makeUnique('_$globalVarName');
-    final dartType = type.getDartType(w);
-    final cType = type.getCType(w);
-
-    s.write(
-        "late final ${w.ffiLibraryPrefix}.Pointer<$cType> $pointerName = ${w.lookupFuncIdentifier}<$cType>('$originalName');\n\n");
-    final baseTypealiasType = type.typealiasType;
-    if (baseTypealiasType is Compound) {
-      if (baseTypealiasType.isOpaque) {
-        s.write(
-            '${w.ffiLibraryPrefix}.Pointer<$cType> get $globalVarName => $pointerName;\n\n');
-      } else {
-        s.write('$dartType get $globalVarName => $pointerName.ref;\n\n');
-      }
-    } else {
-      s.write('$dartType get $globalVarName => $pointerName.value;\n\n');
-      s.write(
-          'set $globalVarName($dartType value) => $pointerName.value = value;\n\n');
-    }
-
-    if (exposeSymbolAddress) {
-      // Add to SymbolAddress in writer.
-      w.symbolAddressWriter.addSymbol(
-        type: '${w.ffiLibraryPrefix}.Pointer<$cType>',
-        name: name,
-        ptrName: pointerName,
-      );
-    }
-
-    return BindingString(type: BindingStringType.global, string: s.toString());
-  }
-
-  @override
-  void addDependencies(Set<Binding> dependencies) {
-    if (dependencies.contains(this)) return;
-
-    dependencies.add(this);
-    type.addDependencies(dependencies);
-  }
-}
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/handle.dart b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/handle.dart
deleted file mode 100644
index a1b2d47..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/handle.dart
+++ /dev/null
@@ -1,23 +0,0 @@
-// 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.
-
-import 'package:ffigen/src/code_generator.dart';
-
-import 'writer.dart';
-
-/// Represents a Dart_Handle.
-class HandleType extends Type {
-  const HandleType._();
-  static const _handle = HandleType._();
-  factory HandleType() => _handle;
-
-  @override
-  String getCType(Writer w) => '${w.ffiLibraryPrefix}.Handle';
-
-  @override
-  String getDartType(Writer w) => 'Object';
-
-  @override
-  String toString() => 'Handle';
-}
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/imports.dart b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/imports.dart
deleted file mode 100644
index 41f7161..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/imports.dart
+++ /dev/null
@@ -1,77 +0,0 @@
-// 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.
-
-import 'struct.dart';
-import 'type.dart';
-import 'writer.dart';
-
-/// A library import which will be written as an import in the generated file.
-class LibraryImport {
-  final String name;
-  final String importPath;
-  String prefix;
-
-  LibraryImport(this.name, this.importPath) : prefix = name;
-
-  @override
-  bool operator ==(other) {
-    return other is LibraryImport && name == other.name;
-  }
-
-  @override
-  int get hashCode => name.hashCode;
-}
-
-/// An imported type which will be used in the generated code.
-class ImportedType extends Type {
-  final LibraryImport libraryImport;
-  final String cType;
-  final String dartType;
-  final String? defaultValue;
-
-  ImportedType(this.libraryImport, this.cType, this.dartType,
-      [this.defaultValue]);
-
-  @override
-  String getCType(Writer w) {
-    w.markImportUsed(libraryImport);
-    return '${libraryImport.prefix}.$cType';
-  }
-
-  @override
-  String getDartType(Writer w) => cType == dartType ? getCType(w) : dartType;
-
-  @override
-  String toString() => '${libraryImport.name}.$cType';
-
-  @override
-  String? getDefaultValue(Writer w, String nativeLib) => defaultValue;
-}
-
-final ffiImport = LibraryImport('ffi', 'dart:ffi');
-final ffiPkgImport = LibraryImport('pkg_ffi', 'package:ffi/ffi.dart');
-
-final voidType = ImportedType(ffiImport, 'Void', 'void');
-
-final unsignedCharType = ImportedType(ffiImport, 'UnsignedChar', 'int', '0');
-final signedCharType = ImportedType(ffiImport, 'SignedChar', 'int', '0');
-final charType = ImportedType(ffiImport, 'Char', 'int', '0');
-final unsignedShortType = ImportedType(ffiImport, 'UnsignedShort', 'int', '0');
-final shortType = ImportedType(ffiImport, 'Short', 'int', '0');
-final unsignedIntType = ImportedType(ffiImport, 'UnsignedInt', 'int', '0');
-final intType = ImportedType(ffiImport, 'Int', 'int', '0');
-final unsignedLongType = ImportedType(ffiImport, 'UnsignedLong', 'int', '0');
-final longType = ImportedType(ffiImport, 'Long', 'int', '0');
-final unsignedLongLongType =
-    ImportedType(ffiImport, 'UnsignedLongLong', 'int', '0');
-final longLongType = ImportedType(ffiImport, 'LongLong', 'int', '0');
-
-final floatType = ImportedType(ffiImport, 'Float', 'double', '0');
-final doubleType = ImportedType(ffiImport, 'Double', 'double', '0');
-
-final sizeType = ImportedType(ffiImport, 'Size', 'int', '0');
-final wCharType = ImportedType(ffiImport, 'WChar', 'int', '0');
-
-final objCObjectType = Struct(name: 'ObjCObject');
-final objCSelType = Struct(name: 'ObjCSel');
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/library.dart b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/library.dart
deleted file mode 100644
index a651871..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/library.dart
+++ /dev/null
@@ -1,141 +0,0 @@
-// Copyright (c) 2020, 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.
-
-import 'dart:io';
-
-import 'package:cli_util/cli_util.dart';
-import 'package:ffigen/src/config_provider/config_types.dart';
-import 'package:logging/logging.dart';
-import 'package:path/path.dart' as p;
-import 'binding.dart';
-import 'imports.dart';
-import 'struct.dart';
-import 'utils.dart';
-import 'writer.dart';
-
-final _logger = Logger('ffigen.code_generator.library');
-
-/// Container for all Bindings.
-class Library {
-  /// List of bindings in this library.
-  late List<Binding> bindings;
-
-  late Writer _writer;
-  Writer get writer => _writer;
-
-  Library({
-    required String name,
-    String? description,
-    required List<Binding> bindings,
-    String? header,
-    bool sort = false,
-    StructPackingOverride? packingOverride,
-    Set<LibraryImport>? libraryImports,
-  }) {
-    /// Get all dependencies (includes itself).
-    final dependencies = <Binding>{};
-    for (final b in bindings) {
-      b.addDependencies(dependencies);
-    }
-
-    /// Save bindings.
-    this.bindings = dependencies.toList();
-
-    if (sort) {
-      _sort();
-    }
-
-    /// Handle any declaration-declaration name conflicts.
-    final declConflictHandler = UniqueNamer({});
-    for (final b in this.bindings) {
-      _warnIfPrivateDeclaration(b);
-      _resolveIfNameConflicts(declConflictHandler, b);
-    }
-
-    // Override pack values according to config. We do this after declaration
-    // conflicts have been handled so that users can target the generated names.
-    if (packingOverride != null) {
-      for (final b in this.bindings) {
-        if (b is Struct && packingOverride.isOverriden(b.name)) {
-          b.pack = packingOverride.getOverridenPackValue(b.name);
-        }
-      }
-    }
-
-    // Seperate bindings which require lookup.
-    final lookUpBindings = this.bindings.whereType<LookUpBinding>().toList();
-    final noLookUpBindings =
-        this.bindings.whereType<NoLookUpBinding>().toList();
-
-    _writer = Writer(
-      lookUpBindings: lookUpBindings,
-      noLookUpBindings: noLookUpBindings,
-      className: name,
-      classDocComment: description,
-      header: header,
-      additionalImports: libraryImports,
-    );
-  }
-
-  /// Logs a warning if generated declaration will be private.
-  void _warnIfPrivateDeclaration(Binding b) {
-    if (b.name.startsWith('_') && !b.isInternal) {
-      _logger.warning(
-          "Generated declaration '${b.name}' start's with '_' and therefore will be private.");
-    }
-  }
-
-  /// Resolves name conflict(if any) and logs a warning.
-  void _resolveIfNameConflicts(UniqueNamer namer, Binding b) {
-    // Print warning if name was conflicting and has been changed.
-    if (namer.isUsed(b.name)) {
-      final oldName = b.name;
-      b.name = namer.makeUnique(b.name);
-
-      _logger.warning(
-          "Resolved name conflict: Declaration '$oldName' and has been renamed to '${b.name}'.");
-    } else {
-      namer.markUsed(b.name);
-    }
-  }
-
-  /// Sort all bindings in alphabetical order.
-  void _sort() {
-    bindings.sort((b1, b2) => b1.name.compareTo(b2.name));
-  }
-
-  /// Generates [file] by generating C bindings.
-  ///
-  /// If format is true(default), the formatter will be called to format the generated file.
-  void generateFile(File file, {bool format = true}) {
-    if (!file.existsSync()) file.createSync(recursive: true);
-    file.writeAsStringSync(generate());
-    if (format) {
-      _dartFormat(file.path);
-    }
-  }
-
-  /// Formats a file using the Dart formatter.
-  void _dartFormat(String path) {
-    final sdkPath = getSdkPath();
-    final result = Process.runSync(
-        p.join(sdkPath, 'bin', 'dart'), ['format', path],
-        runInShell: Platform.isWindows);
-    if (result.stderr.toString().isNotEmpty) {
-      _logger.severe(result.stderr);
-      throw FormatException('Unable to format generated file: $path.');
-    }
-  }
-
-  /// Generates the bindings.
-  String generate() {
-    return writer.generate();
-  }
-
-  @override
-  bool operator ==(other) => other is Library && other.generate() == generate();
-
-  @override
-  int get hashCode => bindings.hashCode;
-}
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/native_type.dart b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/native_type.dart
deleted file mode 100644
index 4be4b16..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/native_type.dart
+++ /dev/null
@@ -1,78 +0,0 @@
-// 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.
-
-import 'package:ffigen/src/code_generator.dart';
-
-import 'writer.dart';
-
-enum SupportedNativeType {
-  Void,
-  Char,
-  Int8,
-  Int16,
-  Int32,
-  Int64,
-  Uint8,
-  Uint16,
-  Uint32,
-  Uint64,
-  Float,
-  Double,
-  IntPtr,
-}
-
-/// Represents a primitive native type, such as float.
-class NativeType extends Type {
-  static const _primitives = <SupportedNativeType, NativeType>{
-    SupportedNativeType.Void: NativeType._('Void', 'void', null),
-    SupportedNativeType.Char: NativeType._('Uint8', 'int', '0'),
-    SupportedNativeType.Int8: NativeType._('Int8', 'int', '0'),
-    SupportedNativeType.Int16: NativeType._('Int16', 'int', '0'),
-    SupportedNativeType.Int32: NativeType._('Int32', 'int', '0'),
-    SupportedNativeType.Int64: NativeType._('Int64', 'int', '0'),
-    SupportedNativeType.Uint8: NativeType._('Uint8', 'int', '0'),
-    SupportedNativeType.Uint16: NativeType._('Uint16', 'int', '0'),
-    SupportedNativeType.Uint32: NativeType._('Uint32', 'int', '0'),
-    SupportedNativeType.Uint64: NativeType._('Uint64', 'int', '0'),
-    SupportedNativeType.Float: NativeType._('Float', 'double', '0'),
-    SupportedNativeType.Double: NativeType._('Double', 'double', '0'),
-    SupportedNativeType.IntPtr: NativeType._('IntPtr', 'int', '0'),
-  };
-
-  final String _cType;
-  final String _dartType;
-  final String? _defaultValue;
-
-  const NativeType._(this._cType, this._dartType, this._defaultValue);
-
-  factory NativeType(SupportedNativeType type) => _primitives[type]!;
-
-  @override
-  String getCType(Writer w) => '${w.ffiLibraryPrefix}.$_cType';
-
-  @override
-  String getDartType(Writer w) => _dartType;
-
-  @override
-  String toString() => _cType;
-
-  @override
-  String cacheKey() => _cType;
-
-  @override
-  String? getDefaultValue(Writer w, String nativeLib) => _defaultValue;
-}
-
-class BooleanType extends NativeType {
-  // Booleans are treated as uint8.
-  const BooleanType._() : super._('Bool', 'bool', 'false');
-  static const _boolean = BooleanType._();
-  factory BooleanType() => _boolean;
-
-  @override
-  String toString() => 'bool';
-
-  @override
-  String cacheKey() => 'bool';
-}
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/objc_block.dart b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/objc_block.dart
deleted file mode 100644
index 7ae7486..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/objc_block.dart
+++ /dev/null
@@ -1,151 +0,0 @@
-// 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.
-
-import 'package:ffigen/src/code_generator.dart';
-
-import 'binding_string.dart';
-import 'writer.dart';
-
-class ObjCBlock extends BindingType {
-  final Type returnType;
-  final List<Type> argTypes;
-  final ObjCBuiltInFunctions builtInFunctions;
-
-  ObjCBlock({
-    required String usr,
-    required String name,
-    required this.returnType,
-    required this.argTypes,
-    required this.builtInFunctions,
-  }) : super(
-          usr: usr,
-          originalName: name,
-          name: name,
-        );
-
-  @override
-  BindingString toBindingString(Writer w) {
-    final s = StringBuffer();
-
-    final params = <Parameter>[];
-    for (int i = 0; i < argTypes.length; ++i) {
-      params.add(Parameter(name: 'arg$i', type: argTypes[i]));
-    }
-
-    final isVoid = returnType == NativeType(SupportedNativeType.Void);
-    final voidPtr = PointerType(voidType).getCType(w);
-    final blockPtr = PointerType(builtInFunctions.blockStruct);
-    final funcType = FunctionType(returnType: returnType, parameters: params);
-    final natFnType = NativeFunc(funcType);
-    final natFnPtr = PointerType(natFnType).getCType(w);
-    final funcPtrTrampoline =
-        w.topLevelUniqueNamer.makeUnique('_${name}_fnPtrTrampoline');
-    final closureTrampoline =
-        w.topLevelUniqueNamer.makeUnique('_${name}_closureTrampoline');
-    final registerClosure =
-        w.topLevelUniqueNamer.makeUnique('_${name}_registerClosure');
-    final closureRegistry =
-        w.topLevelUniqueNamer.makeUnique('_${name}_closureRegistry');
-    final closureRegistryIndex =
-        w.topLevelUniqueNamer.makeUnique('_${name}_closureRegistryIndex');
-    final trampFuncType = FunctionType(
-        returnType: returnType,
-        parameters: [Parameter(type: blockPtr, name: 'block'), ...params]);
-
-    // Write the function pointer based trampoline function.
-    s.write(returnType.getDartType(w));
-    s.write(' $funcPtrTrampoline(${blockPtr.getCType(w)} block');
-    for (int i = 0; i < params.length; ++i) {
-      s.write(', ${params[i].type.getDartType(w)} ${params[i].name}');
-    }
-    s.write(') {\n');
-    s.write('  ${isVoid ? '' : 'return '}block.ref.target.cast<'
-        '${natFnType.getDartType(w)}>().asFunction<'
-        '${funcType.getDartType(w)}>()(');
-    for (int i = 0; i < params.length; ++i) {
-      s.write('${i == 0 ? '' : ', '}${params[i].name}');
-    }
-    s.write(');\n');
-    s.write('}\n');
-
-    // Write the closure registry function.
-    s.write('''
-final $closureRegistry = <int, Function>{};
-int $closureRegistryIndex = 0;
-$voidPtr $registerClosure(Function fn) {
-  final id = ++$closureRegistryIndex;
-  $closureRegistry[id] = fn;
-  return $voidPtr.fromAddress(id);
-}
-''');
-
-    // Write the closure based trampoline function.
-    s.write(returnType.getDartType(w));
-    s.write(' $closureTrampoline(${blockPtr.getCType(w)} block');
-    for (int i = 0; i < params.length; ++i) {
-      s.write(', ${params[i].type.getDartType(w)} ${params[i].name}');
-    }
-    s.write(') {\n');
-    s.write('  ${isVoid ? '' : 'return '}$closureRegistry['
-        'block.ref.target.address]!(');
-    for (int i = 0; i < params.length; ++i) {
-      s.write('${i == 0 ? '' : ', '}${params[i].name}');
-    }
-    s.write(');\n');
-    s.write('}\n');
-
-    // Write the wrapper class.
-    s.write('class $name {\n');
-    s.write('  final ${blockPtr.getCType(w)} _impl;\n');
-    s.write('  final ${w.className} _lib;\n');
-    s.write('  $name._(this._impl, this._lib);\n');
-
-    // Constructor from a function pointer.
-    final defaultValue = returnType.getDefaultValue(w, '_lib');
-    final exceptionalReturn = defaultValue == null ? '' : ', $defaultValue';
-    s.write('''
-  $name.fromFunctionPointer(this._lib, $natFnPtr ptr)
-      : _impl =  _lib.${builtInFunctions.newBlock.name}(
-          ${w.ffiLibraryPrefix}.Pointer.fromFunction<
-              ${trampFuncType.getCType(w)}>($funcPtrTrampoline
-                  $exceptionalReturn).cast(), ptr.cast());
-  $name.fromFunction(this._lib, ${funcType.getDartType(w)} fn)
-      : _impl =  _lib.${builtInFunctions.newBlock.name}(
-          ${w.ffiLibraryPrefix}.Pointer.fromFunction<
-              ${trampFuncType.getCType(w)}>($closureTrampoline
-                  $exceptionalReturn).cast(), $registerClosure(fn));
-''');
-
-    // Get the pointer to the underlying block.
-    s.write('  ${blockPtr.getCType(w)} get pointer => _impl;\n');
-
-    s.write('}\n');
-    return BindingString(
-        type: BindingStringType.objcBlock, string: s.toString());
-  }
-
-  @override
-  void addDependencies(Set<Binding> dependencies) {
-    if (dependencies.contains(this)) return;
-    dependencies.add(this);
-
-    returnType.addDependencies(dependencies);
-    for (final t in argTypes) {
-      t.addDependencies(dependencies);
-    }
-
-    builtInFunctions.newBlockDesc.addDependencies(dependencies);
-    builtInFunctions.blockDescSingleton.addDependencies(dependencies);
-    builtInFunctions.blockStruct.addDependencies(dependencies);
-    builtInFunctions.concreteGlobalBlock.addDependencies(dependencies);
-    builtInFunctions.newBlock.addDependencies(dependencies);
-  }
-
-  @override
-  String getCType(Writer w) =>
-      PointerType(builtInFunctions.blockStruct).getCType(w);
-
-  @override
-  String toString() => '($returnType (^)(${argTypes.join(', ')}))';
-}
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/objc_built_in_functions.dart b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/objc_built_in_functions.dart
deleted file mode 100644
index a92dbcb..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/objc_built_in_functions.dart
+++ /dev/null
@@ -1,305 +0,0 @@
-// 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.
-
-import 'package:ffigen/src/code_generator.dart';
-
-import 'binding_string.dart';
-import 'writer.dart';
-
-/// Built in functions used by the Objective C bindings.
-class ObjCBuiltInFunctions {
-  late final _registerNameFunc = Func(
-    name: '_sel_registerName',
-    originalName: 'sel_registerName',
-    returnType: PointerType(objCSelType),
-    parameters: [Parameter(name: 'str', type: PointerType(charType))],
-    isInternal: true,
-  );
-  late final registerName = ObjCInternalFunction(
-      '_registerName', _registerNameFunc, (Writer w, String name) {
-    final s = StringBuffer();
-    final selType = _registerNameFunc.functionType.returnType.getCType(w);
-    s.write('\n$selType $name(String name) {\n');
-    s.write('  final cstr = name.toNativeUtf8();\n');
-    s.write('  final sel = ${_registerNameFunc.name}(cstr.cast());\n');
-    s.write('  ${w.ffiPkgLibraryPrefix}.calloc.free(cstr);\n');
-    s.write('  return sel;\n');
-    s.write('}\n');
-    return s.toString();
-  });
-
-  late final _getClassFunc = Func(
-    name: '_objc_getClass',
-    originalName: 'objc_getClass',
-    returnType: PointerType(objCObjectType),
-    parameters: [Parameter(name: 'str', type: PointerType(charType))],
-    isInternal: true,
-  );
-  late final getClass =
-      ObjCInternalFunction('_getClass', _getClassFunc, (Writer w, String name) {
-    final s = StringBuffer();
-    final objType = _getClassFunc.functionType.returnType.getCType(w);
-    s.write('\n$objType $name(String name) {\n');
-    s.write('  final cstr = name.toNativeUtf8();\n');
-    s.write('  final clazz = ${_getClassFunc.name}(cstr.cast());\n');
-    s.write('  ${w.ffiPkgLibraryPrefix}.calloc.free(cstr);\n');
-    s.write('  return clazz;\n');
-    s.write('}\n');
-    return s.toString();
-  });
-
-  late final _retainFunc = Func(
-    name: '_objc_retain',
-    originalName: 'objc_retain',
-    returnType: PointerType(objCObjectType),
-    parameters: [Parameter(name: 'value', type: PointerType(objCObjectType))],
-    isInternal: true,
-  );
-  late final _releaseFunc = Func(
-    name: '_objc_release',
-    originalName: 'objc_release',
-    returnType: voidType,
-    parameters: [Parameter(name: 'value', type: PointerType(objCObjectType))],
-    isInternal: true,
-  );
-  late final _releaseFinalizer = ObjCInternalGlobal(
-    '_objc_releaseFinalizer',
-    (Writer w) => '${w.ffiLibraryPrefix}.NativeFinalizer('
-        '${_releaseFunc.funcPointerName}.cast())',
-    _releaseFunc,
-  );
-
-  // We need to load a separate instance of objc_msgSend for each signature.
-  final _msgSendFuncs = <String, Func>{};
-  Func getMsgSendFunc(Type returnType, List<ObjCMethodParam> params) {
-    var key = returnType.cacheKey();
-    for (final p in params) {
-      key += ' ' + p.type.cacheKey();
-    }
-    return _msgSendFuncs[key] ??= Func(
-      name: '_objc_msgSend_${_msgSendFuncs.length}',
-      originalName: 'objc_msgSend',
-      returnType: returnType,
-      parameters: [
-        Parameter(name: 'obj', type: PointerType(objCObjectType)),
-        Parameter(name: 'sel', type: PointerType(objCSelType)),
-        for (final p in params) Parameter(name: p.name, type: p.type),
-      ],
-      isInternal: true,
-    );
-  }
-
-  final _selObjects = <String, ObjCInternalGlobal>{};
-  ObjCInternalGlobal getSelObject(String methodName) {
-    return _selObjects[methodName] ??= ObjCInternalGlobal(
-      '_sel_${methodName.replaceAll(":", "_")}',
-      (Writer w) => '${registerName.name}("$methodName")',
-      registerName,
-    );
-  }
-
-  // See https://clang.llvm.org/docs/Block-ABI-Apple.html
-  late final blockStruct = Struct(
-    name: '_ObjCBlock',
-    isInternal: true,
-    members: [
-      Member(name: 'isa', type: PointerType(voidType)),
-      Member(name: 'flags', type: intType),
-      Member(name: 'reserved', type: intType),
-      Member(name: 'invoke', type: PointerType(voidType)),
-      Member(name: 'descriptor', type: PointerType(blockDescStruct)),
-      Member(name: 'target', type: PointerType(voidType)),
-    ],
-  );
-  late final blockDescStruct = Struct(
-    name: '_ObjCBlockDesc',
-    isInternal: true,
-    members: [
-      Member(name: 'reserved', type: unsignedLongType),
-      Member(name: 'size', type: unsignedLongType),
-      Member(name: 'copy_helper', type: PointerType(voidType)),
-      Member(name: 'dispose_helper', type: PointerType(voidType)),
-      Member(name: 'signature', type: PointerType(charType)),
-    ],
-  );
-  late final newBlockDesc =
-      ObjCInternalFunction('_newBlockDesc', null, (Writer w, String name) {
-    final s = StringBuffer();
-    final blockType = blockStruct.getCType(w);
-    final descType = blockDescStruct.getCType(w);
-    final descPtr = PointerType(blockDescStruct).getCType(w);
-    s.write('\n$descPtr $name() {\n');
-    s.write('  final d = ${w.ffiPkgLibraryPrefix}.calloc.allocate<$descType>('
-        '${w.ffiLibraryPrefix}.sizeOf<$descType>());\n');
-    s.write('  d.ref.size = ${w.ffiLibraryPrefix}.sizeOf<$blockType>();\n');
-    s.write('  return d;\n');
-    s.write('}\n');
-    return s.toString();
-  });
-  late final blockDescSingleton = ObjCInternalGlobal(
-    '_objc_block_desc',
-    (Writer w) => '${newBlockDesc.name}()',
-    blockDescStruct,
-  );
-  late final concreteGlobalBlock = ObjCInternalGlobal(
-    '_objc_concrete_global_block',
-    (Writer w) => '${w.lookupFuncIdentifier}<${voidType.getCType(w)}>('
-        "'_NSConcreteGlobalBlock')",
-  );
-  late final newBlock =
-      ObjCInternalFunction('_newBlock', null, (Writer w, String name) {
-    final s = StringBuffer();
-    final blockType = blockStruct.getCType(w);
-    final blockPtr = PointerType(blockStruct).getCType(w);
-    final voidPtr = PointerType(voidType).getCType(w);
-    s.write('\n$blockPtr $name($voidPtr invoke, $voidPtr target) {\n');
-    s.write('  final b = ${w.ffiPkgLibraryPrefix}.calloc.allocate<$blockType>('
-        '${w.ffiLibraryPrefix}.sizeOf<$blockType>());\n');
-    s.write('  b.ref.isa = ${concreteGlobalBlock.name};\n');
-    s.write('  b.ref.invoke = invoke;\n');
-    s.write('  b.ref.target = target;\n');
-    s.write('  b.ref.descriptor = ${blockDescSingleton.name};\n');
-    s.write('  return b;\n');
-    s.write('}\n');
-    return s.toString();
-  });
-
-  bool utilsExist = false;
-  void ensureUtilsExist(Writer w, StringBuffer s) {
-    if (utilsExist) return;
-    utilsExist = true;
-
-    final objType = PointerType(objCObjectType).getCType(w);
-    s.write('''
-class _ObjCWrapper implements ${w.ffiLibraryPrefix}.Finalizable {
-  final $objType _id;
-  final ${w.className} _lib;
-  bool _pendingRelease;
-
-  _ObjCWrapper._(this._id, this._lib,
-      {bool retain = false, bool release = false}) : _pendingRelease = release {
-    if (retain) {
-      _lib.${_retainFunc.name}(_id);
-    }
-    if (release) {
-      _lib.${_releaseFinalizer.name}.attach(this, _id.cast(), detach: this);
-    }
-  }
-
-  /// Releases the reference to the underlying ObjC object held by this wrapper.
-  /// Throws a StateError if this wrapper doesn't currently hold a reference.
-  void release() {
-    if (_pendingRelease) {
-      _pendingRelease = false;
-      _lib.${_releaseFunc.name}(_id);
-      _lib.${_releaseFinalizer.name}.detach(this);
-    } else {
-      throw StateError(
-          'Released an ObjC object that was unowned or already released.');
-    }
-  }
-
-  @override
-  bool operator ==(Object other) {
-    return other is _ObjCWrapper && _id == other._id;
-  }
-
-  @override
-  int get hashCode => _id.hashCode;
-}
-''');
-  }
-
-  void addDependencies(Set<Binding> dependencies) {
-    registerName.addDependencies(dependencies);
-    getClass.addDependencies(dependencies);
-    _retainFunc.addDependencies(dependencies);
-    _releaseFunc.addDependencies(dependencies);
-    _releaseFinalizer.addDependencies(dependencies);
-    for (final func in _msgSendFuncs.values) {
-      func.addDependencies(dependencies);
-    }
-    for (final sel in _selObjects.values) {
-      sel.addDependencies(dependencies);
-    }
-  }
-
-  final _interfaceRegistry = <String, ObjCInterface>{};
-  void registerInterface(ObjCInterface interface) {
-    _interfaceRegistry[interface.originalName] = interface;
-  }
-
-  void generateNSStringUtils(Writer w, StringBuffer s) {
-    // Generate a constructor that wraps stringWithCString.
-    s.write('  factory NSString(${w.className} _lib, String str) {\n');
-    s.write('    final cstr = str.toNativeUtf8();\n');
-    s.write('    final nsstr = stringWithCString_encoding_('
-        '_lib, cstr.cast(), 4 /* UTF8 */);\n');
-    s.write('    ${w.ffiPkgLibraryPrefix}.calloc.free(cstr);\n');
-    s.write('    return nsstr;\n');
-    s.write('  }\n\n');
-
-    // Generate a toString method that wraps UTF8String.
-    s.write('  @override\n');
-    s.write('  String toString() => (UTF8String).cast<'
-        '${w.ffiPkgLibraryPrefix}.Utf8>().toDartString();\n\n');
-  }
-
-  void generateStringUtils(Writer w, StringBuffer s) {
-    // Generate an extension on String to convert to NSString
-    s.write('extension StringToNSString on String {\n');
-    s.write('  NSString toNSString(${w.className} lib) => '
-        'NSString(lib, this);\n');
-    s.write('}\n\n');
-  }
-}
-
-/// Functions only used internally by ObjC bindings, which may or may not wrap a
-/// native function, such as getClass.
-class ObjCInternalFunction extends LookUpBinding {
-  final Func? _wrappedFunction;
-  final String Function(Writer, String) _toBindingString;
-
-  ObjCInternalFunction(
-      String name, this._wrappedFunction, this._toBindingString)
-      : super(originalName: name, name: name, isInternal: true);
-
-  @override
-  BindingString toBindingString(Writer w) {
-    name = w.wrapperLevelUniqueNamer.makeUnique(name);
-    return BindingString(
-        type: BindingStringType.func, string: _toBindingString(w, name));
-  }
-
-  @override
-  void addDependencies(Set<Binding> dependencies) {
-    if (dependencies.contains(this)) return;
-    dependencies.add(this);
-    _wrappedFunction?.addDependencies(dependencies);
-  }
-}
-
-/// Globals only used internally by ObjC bindings, such as classes and SELs.
-class ObjCInternalGlobal extends LookUpBinding {
-  final String Function(Writer) makeValue;
-  Binding? binding;
-
-  ObjCInternalGlobal(String name, this.makeValue, [this.binding])
-      : super(originalName: name, name: name, isInternal: true);
-
-  @override
-  BindingString toBindingString(Writer w) {
-    final s = StringBuffer();
-    name = w.wrapperLevelUniqueNamer.makeUnique(name);
-    s.write('late final $name = ${makeValue(w)};');
-    return BindingString(type: BindingStringType.global, string: s.toString());
-  }
-
-  @override
-  void addDependencies(Set<Binding> dependencies) {
-    if (dependencies.contains(this)) return;
-    dependencies.add(this);
-    binding?.addDependencies(dependencies);
-  }
-}
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/objc_interface.dart b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/objc_interface.dart
deleted file mode 100644
index 04eb6e5..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/objc_interface.dart
+++ /dev/null
@@ -1,477 +0,0 @@
-// 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.
-
-import 'package:ffigen/src/code_generator.dart';
-import 'package:logging/logging.dart';
-
-import 'binding_string.dart';
-import 'utils.dart';
-import 'writer.dart';
-
-// Class methods defined on NSObject that we don't want to copy to child objects
-// by default.
-const _excludedNSObjectClassMethods = {
-  'allocWithZone:',
-  'class',
-  'conformsToProtocol:',
-  'copyWithZone:',
-  'debugDescription',
-  'description',
-  'hash',
-  'initialize',
-  'instanceMethodForSelector:',
-  'instanceMethodSignatureForSelector:',
-  'instancesRespondToSelector:',
-  'isSubclassOfClass:',
-  'load',
-  'mutableCopyWithZone:',
-  'poseAsClass:',
-  'resolveClassMethod:',
-  'resolveInstanceMethod:',
-  'setVersion:',
-  'superclass',
-  'version',
-};
-
-final _logger = Logger('ffigen.code_generator.objc_interface');
-
-class ObjCInterface extends BindingType {
-  ObjCInterface? superType;
-  final methods = <String, ObjCMethod>{};
-  bool filled = false;
-
-  final ObjCBuiltInFunctions builtInFunctions;
-  final bool isBuiltIn;
-  late final ObjCInternalGlobal _classObject;
-  late final ObjCInternalGlobal _isKindOfClass;
-  late final Func _isKindOfClassMsgSend;
-
-  ObjCInterface({
-    String? usr,
-    required String originalName,
-    required String name,
-    String? dartDoc,
-    required this.builtInFunctions,
-    required this.isBuiltIn,
-  }) : super(
-          usr: usr,
-          originalName: originalName,
-          name: name,
-          dartDoc: dartDoc,
-        );
-
-  bool get isNSString => isBuiltIn && originalName == "NSString";
-
-  @override
-  BindingString toBindingString(Writer w) {
-    String paramsToString(List<ObjCMethodParam> params,
-        {required bool isStatic}) {
-      final List<String> stringParams = [];
-
-      if (isStatic) {
-        stringParams.add('${w.className} _lib');
-      }
-      stringParams.addAll(params.map((p) =>
-          (_getConvertedType(p.type, w, name) +
-              (p.isNullable ? "? " : " ") +
-              p.name)));
-      return '(' + stringParams.join(", ") + ')';
-    }
-
-    final s = StringBuffer();
-    if (dartDoc != null) {
-      s.write(makeDartDoc(dartDoc!));
-    }
-
-    final uniqueNamer = UniqueNamer({name, '_id', '_lib'});
-    final natLib = w.className;
-
-    builtInFunctions.ensureUtilsExist(w, s);
-    final objType = PointerType(objCObjectType).getCType(w);
-
-    // Class declaration.
-    s.write('''
-class $name extends ${superType?.name ?? '_ObjCWrapper'} {
-  $name._($objType id, $natLib lib,
-      {bool retain = false, bool release = false}) :
-          super._(id, lib, retain: retain, release: release);
-
-  /// Returns a [$name] that points to the same underlying object as [other].
-  static $name castFrom<T extends _ObjCWrapper>(T other) {
-    return $name._(other._id, other._lib, retain: true, release: true);
-  }
-
-  /// Returns a [$name] that wraps the given raw object pointer.
-  static $name castFromPointer($natLib lib, ffi.Pointer<ObjCObject> other,
-      {bool retain = false, bool release = false}) {
-    return $name._(other, lib, retain: retain, release: release);
-  }
-
-  /// Returns whether [obj] is an instance of [$name].
-  static bool isInstance(_ObjCWrapper obj) {
-    return obj._lib.${_isKindOfClassMsgSend.name}(
-        obj._id, obj._lib.${_isKindOfClass.name},
-        obj._lib.${_classObject.name});
-  }
-
-''');
-
-    if (isNSString) {
-      builtInFunctions.generateNSStringUtils(w, s);
-    }
-
-    // Methods.
-    for (final m in methods.values) {
-      final methodName = m._getDartMethodName(uniqueNamer);
-      final isStatic = m.isClass;
-      final returnType = m.returnType!;
-
-      // The method declaration.
-      if (m.dartDoc != null) {
-        s.write(makeDartDoc(m.dartDoc!));
-      }
-
-      s.write('  ');
-      if (isStatic) {
-        s.write('static ');
-        s.write(
-            _getConvertedReturnType(returnType, w, name, m.isNullableReturn));
-
-        switch (m.kind) {
-          case ObjCMethodKind.method:
-            // static returnType methodName(NativeLibrary _lib, ...)
-            s.write(' $methodName');
-            break;
-          case ObjCMethodKind.propertyGetter:
-            // static returnType getMethodName(NativeLibrary _lib)
-            s.write(' get');
-            s.write(methodName[0].toUpperCase() + methodName.substring(1));
-            break;
-          case ObjCMethodKind.propertySetter:
-            // static void setMethodName(NativeLibrary _lib, ...)
-            s.write(' set');
-            s.write(methodName[0].toUpperCase() + methodName.substring(1));
-            break;
-        }
-        s.write(paramsToString(m.params, isStatic: true));
-      } else {
-        if (superType?.methods[m.originalName]?.sameAs(m) ?? false) {
-          s.write('@override\n  ');
-        }
-        switch (m.kind) {
-          case ObjCMethodKind.method:
-            // returnType methodName(...)
-            s.write(_getConvertedReturnType(
-                returnType, w, name, m.isNullableReturn));
-            s.write(' $methodName');
-            s.write(paramsToString(m.params, isStatic: false));
-            break;
-          case ObjCMethodKind.propertyGetter:
-            // returnType get methodName
-            s.write(_getConvertedReturnType(
-                returnType, w, name, m.isNullableReturn));
-            s.write(' get $methodName');
-            break;
-          case ObjCMethodKind.propertySetter:
-            // set methodName(...)
-            s.write(' set $methodName');
-            s.write(paramsToString(m.params, isStatic: false));
-            break;
-        }
-      }
-
-      s.write(' {\n');
-
-      // Implementation.
-      final convertReturn = m.kind != ObjCMethodKind.propertySetter &&
-          _needsConverting(returnType);
-
-      if (returnType != NativeType(SupportedNativeType.Void)) {
-        s.write('    ${convertReturn ? 'final _ret = ' : 'return '}');
-      }
-      s.write('_lib.${m.msgSend!.name}(');
-      s.write(isStatic ? '_lib.${_classObject.name}' : '_id');
-      s.write(', _lib.${m.selObject!.name}');
-      for (final p in m.params) {
-        s.write(', ${_doArgConversion(p)}');
-      }
-      s.write(');\n');
-      if (convertReturn) {
-        final result = _doReturnConversion(returnType, '_ret', name, '_lib',
-            m.isNullableReturn, m.isOwnedReturn);
-        s.write('    return $result;');
-      }
-
-      s.write('  }\n\n');
-    }
-
-    s.write('}\n\n');
-
-    if (isNSString) {
-      builtInFunctions.generateStringUtils(w, s);
-    }
-
-    return BindingString(
-        type: BindingStringType.objcInterface, string: s.toString());
-  }
-
-  @override
-  void addDependencies(Set<Binding> dependencies) {
-    if (dependencies.contains(this)) return;
-    dependencies.add(this);
-    builtInFunctions.addDependencies(dependencies);
-
-    if (isBuiltIn) {
-      builtInFunctions.registerInterface(this);
-    }
-
-    _classObject = ObjCInternalGlobal(
-        '_class_$originalName',
-        (Writer w) => '${builtInFunctions.getClass.name}("$originalName")',
-        builtInFunctions.getClass)
-      ..addDependencies(dependencies);
-    _isKindOfClass = builtInFunctions.getSelObject('isKindOfClass:');
-    _isKindOfClassMsgSend = builtInFunctions.getMsgSendFunc(
-        BooleanType(), [ObjCMethodParam(PointerType(objCObjectType), 'clazz')]);
-
-    if (isNSString) {
-      _addNSStringMethods();
-    }
-
-    if (superType != null) {
-      superType!.addDependencies(dependencies);
-      _copyClassMethodsFromSuperType();
-    }
-
-    for (final m in methods.values) {
-      m.addDependencies(dependencies, builtInFunctions);
-    }
-  }
-
-  void _copyClassMethodsFromSuperType() {
-    // Copy class methods from the super type, because Dart classes don't
-    // inherit static methods.
-    for (final m in superType!.methods.values) {
-      if (m.isClass &&
-          !_excludedNSObjectClassMethods.contains(m.originalName)) {
-        addMethod(m);
-      }
-    }
-  }
-
-  void addMethod(ObjCMethod method) {
-    final oldMethod = methods[method.originalName];
-    if (oldMethod != null) {
-      // Typically we ignore duplicate methods. However, property setters and
-      // getters are duplicated in the AST. One copy is marked with
-      // ObjCMethodKind.propertyGetter/Setter. The other copy is missing
-      // important information, and is a plain old instanceMethod. So if the
-      // existing method is an instanceMethod, and the new one is a property,
-      // override it.
-      if (method.isProperty && !oldMethod.isProperty) {
-        // Fallthrough.
-      } else if (!method.isProperty && oldMethod.isProperty) {
-        // Don't override, but also skip the same method check below.
-        return;
-      } else {
-        // Check duplicate is the same method.
-        if (!method.sameAs(oldMethod)) {
-          _logger.severe('Duplicate methods with different signatures: '
-              '$originalName.${method.originalName}');
-        }
-        return;
-      }
-    }
-    methods[method.originalName] = method;
-  }
-
-  void _addNSStringMethods() {
-    addMethod(ObjCMethod(
-      originalName: 'stringWithCString:encoding:',
-      kind: ObjCMethodKind.method,
-      isClass: true,
-      returnType: this,
-      params_: [
-        ObjCMethodParam(PointerType(charType), 'cString'),
-        ObjCMethodParam(unsignedIntType, 'enc'),
-      ],
-    ));
-    addMethod(ObjCMethod(
-      originalName: 'UTF8String',
-      kind: ObjCMethodKind.propertyGetter,
-      isClass: false,
-      returnType: PointerType(charType),
-      params_: [],
-    ));
-  }
-
-  @override
-  String getCType(Writer w) => PointerType(objCObjectType).getCType(w);
-
-  bool _isObject(Type type) =>
-      type is PointerType && type.child == objCObjectType;
-
-  bool _isInstanceType(Type type) =>
-      type is Typealias &&
-      type.originalName == 'instancetype' &&
-      _isObject(type.type);
-
-  // Utils for converting between the internal types passed to native code, and
-  // the external types visible to the user. For example, ObjCInterfaces are
-  // passed to native as Pointer<ObjCObject>, but the user sees the Dart wrapper
-  // class. These methods need to be kept in sync.
-  bool _needsConverting(Type type) =>
-      type is ObjCInterface ||
-      type is ObjCBlock ||
-      _isObject(type) ||
-      _isInstanceType(type);
-
-  String _getConvertedType(Type type, Writer w, String enclosingClass) {
-    if (type is BooleanType) return 'bool';
-    if (type is ObjCInterface) return type.name;
-    if (type is ObjCBlock) return type.name;
-    if (_isObject(type)) return 'NSObject';
-    if (_isInstanceType(type)) return enclosingClass;
-    return type.getDartType(w);
-  }
-
-  String _getConvertedReturnType(
-      Type type, Writer w, String enclosingClass, bool isNullableReturn) {
-    final result = _getConvertedType(type, w, enclosingClass);
-    if (isNullableReturn) {
-      return result + "?";
-    }
-    return result;
-  }
-
-  String _doArgConversion(ObjCMethodParam arg) {
-    if (arg.type is ObjCInterface ||
-        _isObject(arg.type) ||
-        _isInstanceType(arg.type) ||
-        arg.type is ObjCBlock) {
-      final field = arg.type is ObjCBlock ? '_impl' : '_id';
-      if (arg.isNullable) {
-        return '${arg.name}?.$field ?? ffi.nullptr';
-      } else {
-        return '${arg.name}.$field';
-      }
-    }
-    return arg.name;
-  }
-
-  String _doReturnConversion(Type type, String value, String enclosingClass,
-      String library, bool isNullable, bool isOwnedReturn) {
-    final prefix = isNullable ? '$value.address == 0 ? null : ' : '';
-    final ownerFlags = 'retain: ${!isOwnedReturn}, release: true';
-    if (type is ObjCInterface) {
-      return '$prefix${type.name}._($value, $library, $ownerFlags)';
-    }
-    if (type is ObjCBlock) {
-      return '$prefix${type.name}._($value, $library)';
-    }
-    if (_isObject(type)) {
-      return '${prefix}NSObject._($value, $library, $ownerFlags)';
-    }
-    if (_isInstanceType(type)) {
-      return '$prefix$enclosingClass._($value, $library, $ownerFlags)';
-    }
-    return prefix + value;
-  }
-}
-
-enum ObjCMethodKind {
-  method,
-  propertyGetter,
-  propertySetter,
-}
-
-class ObjCProperty {
-  final String originalName;
-  String? dartName;
-
-  ObjCProperty(this.originalName);
-}
-
-class ObjCMethod {
-  final String? dartDoc;
-  final String originalName;
-  final ObjCProperty? property;
-  Type? returnType;
-  final bool isNullableReturn;
-  final List<ObjCMethodParam> params;
-  final ObjCMethodKind kind;
-  final bool isClass;
-  bool returnsRetained = false;
-  ObjCInternalGlobal? selObject;
-  Func? msgSend;
-
-  ObjCMethod({
-    required this.originalName,
-    this.property,
-    this.dartDoc,
-    required this.kind,
-    required this.isClass,
-    this.returnType,
-    this.isNullableReturn = false,
-    List<ObjCMethodParam>? params_,
-  }) : params = params_ ?? [];
-
-  bool get isProperty =>
-      kind == ObjCMethodKind.propertyGetter ||
-      kind == ObjCMethodKind.propertySetter;
-
-  void addDependencies(
-      Set<Binding> dependencies, ObjCBuiltInFunctions builtInFunctions) {
-    returnType ??= NativeType(SupportedNativeType.Void);
-    returnType!.addDependencies(dependencies);
-    for (final p in params) {
-      p.type.addDependencies(dependencies);
-    }
-    selObject ??= builtInFunctions.getSelObject(originalName)
-      ..addDependencies(dependencies);
-    msgSend ??= builtInFunctions.getMsgSendFunc(returnType!, params)
-      ..addDependencies(dependencies);
-  }
-
-  String _getDartMethodName(UniqueNamer uniqueNamer) {
-    if (property != null) {
-      // A getter and a setter are allowed to have the same name, so we can't
-      // just run the name through uniqueNamer. Instead they need to share
-      // the dartName, which is run through uniqueNamer.
-      if (property!.dartName == null) {
-        property!.dartName = uniqueNamer.makeUnique(property!.originalName);
-      }
-      return property!.dartName!;
-    }
-    // Objective C methods can look like:
-    // foo
-    // foo:
-    // foo:someArgName:
-    // So replace all ':' with '_'.
-    return uniqueNamer.makeUnique(originalName.replaceAll(":", "_"));
-  }
-
-  bool sameAs(ObjCMethod other) {
-    if (originalName != other.originalName) return false;
-    if (isNullableReturn != other.isNullableReturn) return false;
-    if (kind != other.kind) return false;
-    if (isClass != other.isClass) return false;
-    // msgSend is deduped by signature, so this check covers the signature.
-    return msgSend == other.msgSend;
-  }
-
-  static final _copyRegExp = RegExp('[cC]opy');
-  bool get isOwnedReturn =>
-      returnsRetained ||
-      originalName.startsWith('new') ||
-      originalName.startsWith('alloc') ||
-      originalName.contains(_copyRegExp);
-}
-
-class ObjCMethodParam {
-  final Type type;
-  final String name;
-  final bool isNullable;
-  ObjCMethodParam(this.type, this.name, {this.isNullable = false});
-}
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/pointer.dart b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/pointer.dart
deleted file mode 100644
index cacb5b2..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/pointer.dart
+++ /dev/null
@@ -1,63 +0,0 @@
-// 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.
-
-import 'package:ffigen/src/code_generator.dart';
-
-import 'writer.dart';
-
-/// Represents a pointer.
-class PointerType extends Type {
-  final Type child;
-  PointerType(this.child);
-
-  @override
-  void addDependencies(Set<Binding> dependencies) {
-    child.addDependencies(dependencies);
-  }
-
-  @override
-  Type get baseType => child.baseType;
-
-  @override
-  String getCType(Writer w) =>
-      '${w.ffiLibraryPrefix}.Pointer<${child.getCType(w)}>';
-
-  @override
-  String toString() => '$child*';
-
-  @override
-  String cacheKey() => '${child.cacheKey()}*';
-}
-
-/// Represents a constant array, which has a fixed size.
-class ConstantArray extends PointerType {
-  final int length;
-  ConstantArray(this.length, Type child) : super(child);
-
-  @override
-  Type get baseArrayType => child.baseArrayType;
-
-  @override
-  bool get isIncompleteCompound => baseArrayType.isIncompleteCompound;
-
-  @override
-  String toString() => '$child[$length]';
-
-  @override
-  String cacheKey() => '${child.cacheKey()}[$length]';
-}
-
-/// Represents an incomplete array, which has an unknown size.
-class IncompleteArray extends PointerType {
-  IncompleteArray(Type child) : super(child);
-
-  @override
-  Type get baseArrayType => child.baseArrayType;
-
-  @override
-  String toString() => '$child[]';
-
-  @override
-  String cacheKey() => '${child.cacheKey()}[]';
-}
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/struct.dart b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/struct.dart
deleted file mode 100644
index c65e04b..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/struct.dart
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright (c) 2020, 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.
-
-import 'package:ffigen/src/code_generator/compound.dart';
-
-/// A binding for C Struct.
-///
-/// For a C structure -
-/// ```c
-/// struct C {
-///   int a;
-///   double b;
-///   int c;
-/// };
-/// ```
-/// The generated dart code is -
-/// ```dart
-/// class Struct extends ffi.Struct{
-///  @ffi.Int32()
-///  int a;
-///
-///  @ffi.Double()
-///  double b;
-///
-///  @ffi.Uint8()
-///  int c;
-///
-/// }
-/// ```
-class Struct extends Compound {
-  Struct({
-    String? usr,
-    String? originalName,
-    required String name,
-    bool isIncomplete = false,
-    int? pack,
-    String? dartDoc,
-    List<Member>? members,
-    bool isInternal = false,
-  }) : super(
-          usr: usr,
-          originalName: originalName,
-          name: name,
-          dartDoc: dartDoc,
-          isIncomplete: isIncomplete,
-          members: members,
-          pack: pack,
-          compoundType: CompoundType.struct,
-          isInternal: isInternal,
-        );
-}
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/type.dart b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/type.dart
deleted file mode 100644
index 8468eca..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/type.dart
+++ /dev/null
@@ -1,120 +0,0 @@
-// Copyright (c) 2020, 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.
-
-import 'package:ffigen/src/code_generator.dart';
-
-import 'writer.dart';
-
-/// Type class for return types, variable types, etc.
-///
-/// Implementers should extend either Type, or BindingType if the type is also a
-/// binding, and override at least getCType and toString.
-abstract class Type {
-  const Type();
-
-  /// Get all dependencies of this type and save them in [dependencies].
-  void addDependencies(Set<Binding> dependencies) {}
-
-  /// Get base type for any type.
-  ///
-  /// E.g int** has base [Type] of int.
-  /// double[2][3] has base [Type] of double.
-  Type get baseType => this;
-
-  /// Get base Array type.
-  ///
-  /// Returns itself if it's not an Array Type.
-  Type get baseArrayType => this;
-
-  /// Get base typealias type.
-  ///
-  /// Returns itself if it's not a Typealias.
-  Type get typealiasType => this;
-
-  /// Returns true if the type is a [Compound] and is incomplete.
-  bool get isIncompleteCompound => false;
-
-  /// Returns the C type of the Type. This is the FFI compatible type that is
-  /// passed to native code.
-  String getCType(Writer w) => throw 'No mapping for type: $this';
-
-  /// Returns the Dart type of the Type. This is the user visible type that is
-  /// passed to Dart code.
-  String getDartType(Writer w) => getCType(w);
-
-  /// Returns the string representation of the Type, for debugging purposes
-  /// only. This string should not be printed as generated code.
-  @override
-  String toString();
-
-  /// Cache key used in various places to dedupe Types. By default this is just
-  /// the hash of the Type, but in many cases this does not dedupe sufficiently.
-  /// So Types that may be duplicated should override this to return a more
-  /// specific key. Types that are already deduped don't need to override this.
-  /// toString() is not a valid cache key as there may be name collisions.
-  String cacheKey() => hashCode.toRadixString(36);
-
-  /// Returns a string of code that creates a default value for this type. For
-  /// example, for int types this returns the string '0'. A null return means
-  /// that default values aren't supported for this type, eg void.
-  String? getDefaultValue(Writer w, String nativeLib) => null;
-}
-
-/// Function to check if the dart and C type string are same.
-bool sameDartAndCType(Type t, Writer w) => t.getCType(w) == t.getDartType(w);
-
-/// Base class for all Type bindings.
-///
-/// Since Dart doesn't have multiple inheritance, this type exists so that we
-/// don't have to reimplement the default methods in all the classes that want
-/// to extend both NoLookUpBinding and Type.
-abstract class BindingType extends NoLookUpBinding implements Type {
-  BindingType({
-    String? usr,
-    String? originalName,
-    required String name,
-    String? dartDoc,
-    bool isInternal = false,
-  }) : super(
-          usr: usr,
-          originalName: originalName,
-          name: name,
-          dartDoc: dartDoc,
-          isInternal: isInternal,
-        );
-
-  @override
-  Type get baseType => this;
-
-  @override
-  Type get baseArrayType => this;
-
-  @override
-  Type get typealiasType => this;
-
-  @override
-  bool get isIncompleteCompound => false;
-
-  @override
-  String getDartType(Writer w) => getCType(w);
-
-  @override
-  String toString() => originalName;
-
-  @override
-  String cacheKey() => hashCode.toRadixString(36);
-
-  @override
-  String? getDefaultValue(Writer w, String nativeLib) => null;
-}
-
-/// Represents an unimplemented type. Used as a marker, so that declarations
-/// having these can exclude them.
-class UnimplementedType extends Type {
-  String reason;
-  UnimplementedType(this.reason);
-
-  @override
-  String toString() => '(Unimplemented: $reason)';
-}
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/typealias.dart b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/typealias.dart
deleted file mode 100644
index f42e863..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/typealias.dart
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright (c) 2020, 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.
-
-import 'package:ffigen/src/code_generator.dart';
-
-import 'binding_string.dart';
-import 'utils.dart';
-import 'writer.dart';
-
-/// A simple Typealias, Expands to -
-///
-/// ```dart
-/// typedef $name = $type;
-/// );
-/// ```
-class Typealias extends BindingType {
-  final Type type;
-  final bool _useDartType;
-
-  Typealias({
-    String? usr,
-    String? originalName,
-    String? dartDoc,
-    required String name,
-    required this.type,
-
-    /// If true, the binding string uses Dart type instead of C type.
-    ///
-    /// E.g if C type is ffi.Void func(ffi.Int32), Dart type is void func(int).
-    bool useDartType = false,
-  })  : _useDartType = useDartType,
-        super(
-          usr: usr,
-          name: name,
-          dartDoc: dartDoc,
-          originalName: originalName,
-        );
-
-  @override
-  void addDependencies(Set<Binding> dependencies) {
-    if (dependencies.contains(this)) return;
-
-    dependencies.add(this);
-    type.addDependencies(dependencies);
-  }
-
-  @override
-  BindingString toBindingString(Writer w) {
-    final sb = StringBuffer();
-    if (dartDoc != null) {
-      sb.write(makeDartDoc(dartDoc!));
-    }
-    sb.write('typedef $name = ');
-    sb.write('${_useDartType ? type.getDartType(w) : type.getCType(w)};\n');
-    return BindingString(
-        type: BindingStringType.typeDef, string: sb.toString());
-  }
-
-  @override
-  Type get typealiasType => type.typealiasType;
-
-  @override
-  bool get isIncompleteCompound => type.isIncompleteCompound;
-
-  @override
-  String getCType(Writer w) => name;
-
-  @override
-  String getDartType(Writer w) {
-    // Typealias cannot be used by name in Dart types unless both the C and Dart
-    // type of the underlying types are same.
-    if (sameDartAndCType(type, w)) {
-      return name;
-    } else {
-      return type.getDartType(w);
-    }
-  }
-
-  @override
-  String cacheKey() => type.cacheKey();
-
-  @override
-  String? getDefaultValue(Writer w, String nativeLib) =>
-      type.getDefaultValue(w, nativeLib);
-}
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/union.dart b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/union.dart
deleted file mode 100644
index fc7be96..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/union.dart
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright (c) 2020, 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.
-
-import 'package:ffigen/src/code_generator/compound.dart';
-
-/// A binding for a C union -
-///
-/// ```c
-/// union C {
-///   int a;
-///   double b;
-///   float c;
-/// };
-/// ```
-/// The generated dart code is -
-/// ```dart
-/// class Union extends ffi.Union{
-///  @ffi.Int32()
-///  int a;
-///
-///  @ffi.Double()
-///  double b;
-///
-///  @ffi.Float()
-///  float c;
-///
-/// }
-/// ```
-class Union extends Compound {
-  Union({
-    String? usr,
-    String? originalName,
-    required String name,
-    bool isIncomplete = false,
-    int? pack,
-    String? dartDoc,
-    List<Member>? members,
-  }) : super(
-          usr: usr,
-          originalName: originalName,
-          name: name,
-          dartDoc: dartDoc,
-          isIncomplete: isIncomplete,
-          members: members,
-          pack: pack,
-          compoundType: CompoundType.union,
-        );
-}
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/utils.dart b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/utils.dart
deleted file mode 100644
index c000bdf..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/utils.dart
+++ /dev/null
@@ -1,72 +0,0 @@
-import 'dart_keywords.dart';
-
-class UniqueNamer {
-  final Set<String> _usedUpNames;
-
-  /// Creates a UniqueNamer with given [usedUpNames] and Dart reserved keywords.
-  UniqueNamer(Set<String> usedUpNames)
-      : assert(keywords.intersection(usedUpNames).isEmpty),
-        _usedUpNames = {...keywords, ...usedUpNames};
-
-  /// Creates a UniqueNamer with given [usedUpNames] only.
-  UniqueNamer._raw(this._usedUpNames);
-
-  /// Returns a unique name by appending `<int>` to it if necessary.
-  ///
-  /// Adds the resulting name to the used names by default.
-  String makeUnique(String name, [bool addToUsedUpNames = true]) {
-    var crName = name;
-    var i = 1;
-    while (_usedUpNames.contains(crName)) {
-      crName = '$name$i';
-      i++;
-    }
-    if (addToUsedUpNames) {
-      _usedUpNames.add(crName);
-    }
-    return crName;
-  }
-
-  /// Adds a name to used names.
-  ///
-  /// Note: [makeUnique] also adds the name by default.
-  void markUsed(String name) {
-    _usedUpNames.add(name);
-  }
-
-  /// Returns true if a name has been used before.
-  bool isUsed(String name) {
-    return _usedUpNames.contains(name);
-  }
-
-  /// Returns true if a name has not been used before.
-  bool isUnique(String name) {
-    return !_usedUpNames.contains(name);
-  }
-
-  UniqueNamer clone() => UniqueNamer._raw({..._usedUpNames});
-}
-
-/// Converts [text] to a dart doc comment(`///`).
-///
-/// Comment is split on new lines only.
-String makeDartDoc(String text) {
-  final s = StringBuffer();
-  s.write('/// ');
-  s.writeAll(text.split('\n'), '\n/// ');
-  s.write('\n');
-
-  return s.toString();
-}
-
-/// Converts [text] to a dart comment (`//`).
-///
-/// Comment is split on new lines only.
-String makeDoc(String text) {
-  final s = StringBuffer();
-  s.write('// ');
-  s.writeAll(text.split('\n'), '\n// ');
-  s.write('\n');
-
-  return s.toString();
-}
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/writer.dart b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/writer.dart
deleted file mode 100644
index 0bacf55..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/writer.dart
+++ /dev/null
@@ -1,300 +0,0 @@
-// Copyright (c) 2020, 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.
-
-import 'package:ffigen/src/code_generator/imports.dart';
-import 'package:ffigen/src/code_generator/utils.dart';
-
-import 'binding.dart';
-
-/// To store generated String bindings.
-class Writer {
-  final String? header;
-
-  /// Holds bindings, which lookup symbols.
-  final List<Binding> lookUpBindings;
-
-  /// Holds bindings which don't lookup symbols.
-  final List<Binding> noLookUpBindings;
-
-  /// Manages the `_SymbolAddress` class.
-  final symbolAddressWriter = SymbolAddressWriter();
-
-  late String _className;
-  String get className => _className;
-
-  final String? classDocComment;
-
-  String? _ffiLibraryPrefix;
-  String get ffiLibraryPrefix {
-    if (_ffiLibraryPrefix != null) {
-      return _ffiLibraryPrefix!;
-    }
-
-    final import = _usedImports.firstWhere(
-        (element) => element.name == ffiImport.name,
-        orElse: () => ffiImport);
-    _usedImports.add(import);
-    return _ffiLibraryPrefix = import.prefix;
-  }
-
-  String? _ffiPkgLibraryPrefix;
-  String get ffiPkgLibraryPrefix {
-    if (_ffiPkgLibraryPrefix != null) {
-      return _ffiPkgLibraryPrefix!;
-    }
-
-    final import = _usedImports.firstWhere(
-        (element) => element.name == ffiPkgImport.name,
-        orElse: () => ffiPkgImport);
-    _usedImports.add(import);
-    return _ffiPkgLibraryPrefix = import.prefix;
-  }
-
-  final Set<LibraryImport> _usedImports = {};
-
-  late String _lookupFuncIdentifier;
-  String get lookupFuncIdentifier => _lookupFuncIdentifier;
-
-  late String _symbolAddressClassName;
-  late String _symbolAddressVariableName;
-  late String _symbolAddressLibraryVarName;
-
-  /// Initial namers set after running constructor. Namers are reset to this
-  /// initial state everytime [generate] is called.
-  late UniqueNamer _initialTopLevelUniqueNamer, _initialWrapperLevelUniqueNamer;
-
-  /// Used by [Binding]s for generating required code.
-  late UniqueNamer _topLevelUniqueNamer, _wrapperLevelUniqueNamer;
-  UniqueNamer get topLevelUniqueNamer => _topLevelUniqueNamer;
-  UniqueNamer get wrapperLevelUniqueNamer => _wrapperLevelUniqueNamer;
-
-  late String _arrayHelperClassPrefix;
-
-  /// Guaranteed to be a unique prefix.
-  String get arrayHelperClassPrefix => _arrayHelperClassPrefix;
-
-  /// [_usedUpNames] should contain names of all the declarations which are
-  /// already used. This is used to avoid name collisions.
-  Writer({
-    required this.lookUpBindings,
-    required this.noLookUpBindings,
-    required String className,
-    Set<LibraryImport>? additionalImports,
-    this.classDocComment,
-    this.header,
-  }) {
-    final globalLevelNameSet = noLookUpBindings.map((e) => e.name).toSet();
-    final wrapperLevelNameSet = lookUpBindings.map((e) => e.name).toSet();
-    final allNameSet = <String>{}
-      ..addAll(globalLevelNameSet)
-      ..addAll(wrapperLevelNameSet);
-
-    _initialTopLevelUniqueNamer = UniqueNamer(globalLevelNameSet);
-    _initialWrapperLevelUniqueNamer = UniqueNamer(wrapperLevelNameSet);
-    final allLevelsUniqueNamer = UniqueNamer(allNameSet);
-
-    /// Wrapper class name must be unique among all names.
-    _className = _resolveNameConflict(
-      name: className,
-      makeUnique: allLevelsUniqueNamer,
-      markUsed: [_initialWrapperLevelUniqueNamer, _initialTopLevelUniqueNamer],
-    );
-
-    /// Library imports prefix should be unique unique among all names.
-    if (additionalImports != null) {
-      for (final lib in additionalImports) {
-        lib.prefix = _resolveNameConflict(
-          name: lib.prefix,
-          makeUnique: allLevelsUniqueNamer,
-          markUsed: [
-            _initialWrapperLevelUniqueNamer,
-            _initialTopLevelUniqueNamer
-          ],
-        );
-      }
-    }
-
-    /// [_lookupFuncIdentifier] should be unique in top level.
-    _lookupFuncIdentifier = _resolveNameConflict(
-      name: '_lookup',
-      makeUnique: _initialTopLevelUniqueNamer,
-      markUsed: [_initialTopLevelUniqueNamer],
-    );
-
-    /// Resolve name conflicts of identifiers used for SymbolAddresses.
-    _symbolAddressClassName = _resolveNameConflict(
-      name: '_SymbolAddresses',
-      makeUnique: allLevelsUniqueNamer,
-      markUsed: [_initialWrapperLevelUniqueNamer, _initialTopLevelUniqueNamer],
-    );
-    _symbolAddressVariableName = _resolveNameConflict(
-      name: 'addresses',
-      makeUnique: _initialWrapperLevelUniqueNamer,
-      markUsed: [_initialWrapperLevelUniqueNamer],
-    );
-    _symbolAddressLibraryVarName = _resolveNameConflict(
-      name: '_library',
-      makeUnique: _initialWrapperLevelUniqueNamer,
-      markUsed: [_initialWrapperLevelUniqueNamer],
-    );
-
-    /// Finding a unique prefix for Array Helper Classes and store into
-    /// [_arrayHelperClassPrefix].
-    final base = 'ArrayHelper';
-    _arrayHelperClassPrefix = base;
-    var suffixInt = 0;
-    for (var i = 0; i < allNameSet.length; i++) {
-      if (allNameSet.elementAt(i).startsWith(_arrayHelperClassPrefix)) {
-        // Not a unique prefix, start over with a new suffix.
-        i = -1;
-        suffixInt++;
-        _arrayHelperClassPrefix = '$base$suffixInt';
-      }
-    }
-
-    _resetUniqueNamersNamers();
-  }
-
-  /// Resolved name conflict using [makeUnique] and marks the result as used in
-  /// all [markUsed].
-  String _resolveNameConflict({
-    required String name,
-    required UniqueNamer makeUnique,
-    List<UniqueNamer> markUsed = const [],
-  }) {
-    final s = makeUnique.makeUnique(name);
-    for (final un in markUsed) {
-      un.markUsed(s);
-    }
-    return s;
-  }
-
-  /// Resets the namers to initial state. Namers are reset before generating.
-  void _resetUniqueNamersNamers() {
-    _topLevelUniqueNamer = _initialTopLevelUniqueNamer.clone();
-    _wrapperLevelUniqueNamer = _initialWrapperLevelUniqueNamer.clone();
-  }
-
-  void markImportUsed(LibraryImport import) {
-    _usedImports.add(import);
-  }
-
-  /// Writes all bindings to a String.
-  String generate() {
-    final s = StringBuffer();
-
-    // We write the source first to determine which imports are actually
-    // referenced. Headers and [s] are then combined into the final result.
-    final result = StringBuffer();
-
-    // Reset unique namers to initial state.
-    _resetUniqueNamersNamers();
-
-    // Write file header (if any).
-    if (header != null) {
-      result.writeln(header);
-    }
-
-    // Write auto generated declaration.
-    result.write(makeDoc(
-        'AUTO GENERATED FILE, DO NOT EDIT.\n\nGenerated by `package:ffigen`.'));
-
-    /// Write [lookUpBindings].
-    if (lookUpBindings.isNotEmpty) {
-      // Write doc comment for wrapper class.
-      if (classDocComment != null) {
-        s.write(makeDartDoc(classDocComment!));
-      }
-      // Write wrapper classs.
-      s.write('class $_className{\n');
-      // Write dylib.
-      s.write('/// Holds the symbol lookup function.\n');
-      s.write(
-          'final $ffiLibraryPrefix.Pointer<T> Function<T extends $ffiLibraryPrefix.NativeType>(String symbolName) $lookupFuncIdentifier;\n');
-      s.write('\n');
-      //Write doc comment for wrapper class constructor.
-      s.write(makeDartDoc('The symbols are looked up in [dynamicLibrary].'));
-      // Write wrapper class constructor.
-      s.write(
-          '$_className($ffiLibraryPrefix.DynamicLibrary dynamicLibrary): $lookupFuncIdentifier = dynamicLibrary.lookup;\n\n');
-      //Write doc comment for wrapper class named constructor.
-      s.write(makeDartDoc('The symbols are looked up with [lookup].'));
-      // Write wrapper class named constructor.
-      s.write(
-          '$_className.fromLookup($ffiLibraryPrefix.Pointer<T> Function<T extends $ffiLibraryPrefix.NativeType>(String symbolName) lookup): $lookupFuncIdentifier = lookup;\n\n');
-      for (final b in lookUpBindings) {
-        s.write(b.toBindingString(this).string);
-      }
-      if (symbolAddressWriter.shouldGenerate) {
-        s.write(symbolAddressWriter.writeObject(this));
-      }
-
-      s.write('}\n\n');
-    }
-
-    if (symbolAddressWriter.shouldGenerate) {
-      s.write(symbolAddressWriter.writeClass(this));
-    }
-
-    /// Write [noLookUpBindings].
-    for (final b in noLookUpBindings) {
-      if (b.name != '__va_list_tag') {
-        s.write(b.toBindingString(this).string);
-      }
-    }
-
-    // Write neccesary imports.
-    for (final lib in _usedImports) {
-      result
-        ..write("import '${lib.importPath}' as ${lib.prefix};")
-        ..write('\n');
-    }
-    result.write(s);
-
-    return result.toString();
-  }
-}
-
-/// Manages the generated `_SymbolAddress` class.
-class SymbolAddressWriter {
-  final List<_SymbolAddressUnit> _addresses = [];
-
-  /// Used to check if we need to generate `_SymbolAddress` class.
-  bool get shouldGenerate => _addresses.isNotEmpty;
-
-  void addSymbol({
-    required String type,
-    required String name,
-    required String ptrName,
-  }) {
-    _addresses.add(_SymbolAddressUnit(type, name, ptrName));
-  }
-
-  String writeObject(Writer w) {
-    return 'late final ${w._symbolAddressVariableName} = ${w._symbolAddressClassName}(this);';
-  }
-
-  String writeClass(Writer w) {
-    final sb = StringBuffer();
-    sb.write('class ${w._symbolAddressClassName} {\n');
-    // Write Library object.
-    sb.write('final ${w._className} ${w._symbolAddressLibraryVarName};\n');
-    // Write Constructor.
-    sb.write(
-        '${w._symbolAddressClassName}(this.${w._symbolAddressLibraryVarName});\n');
-    for (final address in _addresses) {
-      sb.write(
-          '${address.type} get ${address.name} => ${w._symbolAddressLibraryVarName}.${address.ptrName};\n');
-    }
-    sb.write('}\n');
-    return sb.toString();
-  }
-}
-
-/// Holds the data for a single symbol address.
-class _SymbolAddressUnit {
-  final String type, name, ptrName;
-
-  _SymbolAddressUnit(this.type, this.name, this.ptrName);
-}
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/config_provider.dart b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/config_provider.dart
deleted file mode 100644
index 990e137..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/config_provider.dart
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright (c) 2020, 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.
-
-/// Creates config object used by other sub_modules.
-library config_provider;
-
-export 'config_provider/config.dart';
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/config_provider/config.dart b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/config_provider/config.dart
deleted file mode 100644
index e9d1f97..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/config_provider/config.dart
+++ /dev/null
@@ -1,483 +0,0 @@
-// Copyright (c) 2020, 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.
-
-/// Validates the yaml input by the user, prints useful info for the user
-
-import 'package:ffigen/src/code_generator.dart';
-
-import 'package:logging/logging.dart';
-import 'package:yaml/yaml.dart';
-
-import '../strings.dart' as strings;
-import 'config_types.dart';
-import 'spec_utils.dart';
-
-final _logger = Logger('ffigen.config_provider.config');
-
-/// Provides configurations to other modules.
-///
-/// Handles validation, extraction of confiurations from yaml file.
-class Config {
-  /// Location for llvm/lib folder.
-  String get libclangDylib => _libclangDylib;
-  late String _libclangDylib;
-
-  /// Output file name.
-  String get output => _output;
-  late String _output;
-
-  /// Language that ffigen is consuming.
-  Language get language => _language;
-  late Language _language;
-
-  // Holds headers and filters for header.
-  Headers get headers => _headers;
-  late Headers _headers;
-
-  /// CommandLine Arguments to pass to clang_compiler.
-  List<String> get compilerOpts => _compilerOpts;
-  late List<String> _compilerOpts;
-
-  /// Declaration config for Functions.
-  Declaration get functionDecl => _functionDecl;
-  late Declaration _functionDecl;
-
-  /// Declaration config for Structs.
-  Declaration get structDecl => _structDecl;
-  late Declaration _structDecl;
-
-  /// Declaration config for Unions.
-  Declaration get unionDecl => _unionDecl;
-  late Declaration _unionDecl;
-
-  /// Declaration config for Enums.
-  Declaration get enumClassDecl => _enumClassDecl;
-  late Declaration _enumClassDecl;
-
-  /// Declaration config for Unnamed enum constants.
-  Declaration get unnamedEnumConstants => _unnamedEnumConstants;
-  late Declaration _unnamedEnumConstants;
-
-  /// Declaration config for Globals.
-  Declaration get globals => _globals;
-  late Declaration _globals;
-
-  /// Declaration config for Macro constants.
-  Declaration get macroDecl => _macroDecl;
-  late Declaration _macroDecl;
-
-  /// Declaration config for Typedefs.
-  Declaration get typedefs => _typedefs;
-  late Declaration _typedefs;
-
-  /// Declaration config for Objective C interfaces.
-  Declaration get objcInterfaces => _objcInterfaces;
-  late Declaration _objcInterfaces;
-
-  /// If generated bindings should be sorted alphabetically.
-  bool get sort => _sort;
-  late bool _sort;
-
-  /// If typedef of supported types(int8_t) should be directly used.
-  bool get useSupportedTypedefs => _useSupportedTypedefs;
-  late bool _useSupportedTypedefs;
-
-  /// Stores all the library imports specified by user including those for ffi and pkg_ffi.
-  Map<String, LibraryImport> get libraryImports => _libraryImports;
-  late Map<String, LibraryImport> _libraryImports;
-
-  /// Stores typedef name to ImportedType mappings specified by user.
-  Map<String, ImportedType> get typedefTypeMappings => _typedefTypeMappings;
-  late Map<String, ImportedType> _typedefTypeMappings;
-
-  /// Stores struct name to ImportedType mappings specified by user.
-  Map<String, ImportedType> get structTypeMappings => _structTypeMappings;
-  late Map<String, ImportedType> _structTypeMappings;
-
-  /// Stores union name to ImportedType mappings specified by user.
-  Map<String, ImportedType> get unionTypeMappings => _unionTypeMappings;
-  late Map<String, ImportedType> _unionTypeMappings;
-
-  /// Stores native int name to ImportedType mappings specified by user.
-  Map<String, ImportedType> get nativeTypeMappings => _nativeTypeMappings;
-  late Map<String, ImportedType> _nativeTypeMappings;
-
-  /// Extracted Doc comment type.
-  CommentType get commentType => _commentType;
-  late CommentType _commentType;
-
-  /// Whether structs that are dependencies should be included.
-  CompoundDependencies get structDependencies => _structDependencies;
-  late CompoundDependencies _structDependencies;
-
-  /// Whether unions that are dependencies should be included.
-  CompoundDependencies get unionDependencies => _unionDependencies;
-  late CompoundDependencies _unionDependencies;
-
-  /// Holds config for how struct packing should be overriden.
-  StructPackingOverride get structPackingOverride => _structPackingOverride;
-  late StructPackingOverride _structPackingOverride;
-
-  /// Name of the wrapper class.
-  String get wrapperName => _wrapperName;
-  late String _wrapperName;
-
-  /// Doc comment for the wrapper class.
-  String? get wrapperDocComment => _wrapperDocComment;
-  String? _wrapperDocComment;
-
-  /// Header of the generated bindings.
-  String? get preamble => _preamble;
-  String? _preamble;
-
-  /// If `Dart_Handle` should be mapped with Handle/Object.
-  bool get useDartHandle => _useDartHandle;
-  late bool _useDartHandle;
-
-  Includer get exposeFunctionTypedefs => _exposeFunctionTypedefs;
-  late Includer _exposeFunctionTypedefs;
-
-  Includer get leafFunctions => _leafFunctions;
-  late Includer _leafFunctions;
-
-  Config._();
-
-  /// Create config from Yaml map.
-  factory Config.fromYaml(YamlMap map) {
-    final configspecs = Config._();
-    _logger.finest('Config Map: ' + map.toString());
-
-    final specs = configspecs._getSpecs();
-
-    final result = configspecs._checkConfigs(map, specs);
-    if (!result) {
-      throw FormatException('Invalid configurations provided.');
-    }
-
-    configspecs._extract(map, specs);
-    return configspecs;
-  }
-
-  /// Add compiler options for clang. If [highPriority] is true these are added
-  /// to the front of the list.
-  void addCompilerOpts(String compilerOpts, {bool highPriority = false}) {
-    if (highPriority) {
-      _compilerOpts.insertAll(
-          0, compilerOptsToList(compilerOpts)); // Inserts at the front.
-    } else {
-      _compilerOpts.addAll(compilerOptsToList(compilerOpts));
-    }
-  }
-
-  /// Validates Yaml according to given specs.
-  bool _checkConfigs(YamlMap map, Map<List<String>, Specification> specs) {
-    var _result = true;
-    for (final key in specs.keys) {
-      final spec = specs[key];
-      if (checkKeyInYaml(key, map)) {
-        _result =
-            _result && spec!.validator(key, getKeyValueFromYaml(key, map));
-      } else if (spec!.requirement == Requirement.yes) {
-        _logger.severe("Key '$key' is required.");
-        _result = false;
-      } else if (spec.requirement == Requirement.prefer) {
-        _logger.warning("Prefer adding Key '$key' to your config.");
-      }
-    }
-    // Warn about unknown keys.
-    warnUnknownKeys(specs.keys.toList(), map);
-
-    return _result;
-  }
-
-  /// Extracts variables from Yaml according to given specs.
-  ///
-  /// Validation must be done beforehand, using [_checkConfigs].
-  void _extract(YamlMap map, Map<List<String>, Specification> specs) {
-    for (final key in specs.keys) {
-      final spec = specs[key];
-      if (checkKeyInYaml(key, map)) {
-        spec!.extractedResult(spec.extractor(getKeyValueFromYaml(key, map)));
-      } else {
-        spec!.extractedResult(spec.defaultValue?.call());
-      }
-    }
-  }
-
-  /// Returns map of various specifications avaialble for our tool.
-  ///
-  /// Key: Name, Value: [Specification]
-  Map<List<String>, Specification> _getSpecs() {
-    return <List<String>, Specification>{
-      [strings.llvmPath]: Specification<String>(
-        requirement: Requirement.no,
-        validator: llvmPathValidator,
-        extractor: llvmPathExtractor,
-        defaultValue: () => findDylibAtDefaultLocations(),
-        extractedResult: (dynamic result) {
-          _libclangDylib = result as String;
-        },
-      ),
-      [strings.output]: Specification<String>(
-        requirement: Requirement.yes,
-        validator: outputValidator,
-        extractor: outputExtractor,
-        extractedResult: (dynamic result) => _output = result as String,
-      ),
-      [strings.language]: Specification<Language>(
-        requirement: Requirement.no,
-        validator: languageValidator,
-        extractor: languageExtractor,
-        defaultValue: () => Language.c,
-        extractedResult: (dynamic result) => _language = result as Language,
-      ),
-      [strings.headers]: Specification<Headers>(
-        requirement: Requirement.yes,
-        validator: headersValidator,
-        extractor: headersExtractor,
-        extractedResult: (dynamic result) => _headers = result as Headers,
-      ),
-      [strings.compilerOpts]: Specification<List<String>>(
-        requirement: Requirement.no,
-        validator: compilerOptsValidator,
-        extractor: compilerOptsExtractor,
-        defaultValue: () => [],
-        extractedResult: (dynamic result) =>
-            _compilerOpts = result as List<String>,
-      ),
-      [strings.compilerOptsAuto]: Specification<CompilerOptsAuto>(
-          requirement: Requirement.no,
-          validator: compilerOptsAutoValidator,
-          extractor: compilerOptsAutoExtractor,
-          defaultValue: () => CompilerOptsAuto(),
-          extractedResult: (dynamic result) {
-            _compilerOpts
-                .addAll((result as CompilerOptsAuto).extractCompilerOpts());
-          }),
-      [strings.functions]: Specification<Declaration>(
-        requirement: Requirement.no,
-        validator: declarationConfigValidator,
-        extractor: declarationConfigExtractor,
-        defaultValue: () => Declaration(),
-        extractedResult: (dynamic result) {
-          _functionDecl = result as Declaration;
-        },
-      ),
-      [strings.structs]: Specification<Declaration>(
-        requirement: Requirement.no,
-        validator: declarationConfigValidator,
-        extractor: declarationConfigExtractor,
-        defaultValue: () => Declaration(),
-        extractedResult: (dynamic result) {
-          _structDecl = result as Declaration;
-        },
-      ),
-      [strings.unions]: Specification<Declaration>(
-        requirement: Requirement.no,
-        validator: declarationConfigValidator,
-        extractor: declarationConfigExtractor,
-        defaultValue: () => Declaration(),
-        extractedResult: (dynamic result) {
-          _unionDecl = result as Declaration;
-        },
-      ),
-      [strings.enums]: Specification<Declaration>(
-        requirement: Requirement.no,
-        validator: declarationConfigValidator,
-        extractor: declarationConfigExtractor,
-        defaultValue: () => Declaration(),
-        extractedResult: (dynamic result) {
-          _enumClassDecl = result as Declaration;
-        },
-      ),
-      [strings.unnamedEnums]: Specification<Declaration>(
-        requirement: Requirement.no,
-        validator: declarationConfigValidator,
-        extractor: declarationConfigExtractor,
-        defaultValue: () => Declaration(),
-        extractedResult: (dynamic result) =>
-            _unnamedEnumConstants = result as Declaration,
-      ),
-      [strings.globals]: Specification<Declaration>(
-        requirement: Requirement.no,
-        validator: declarationConfigValidator,
-        extractor: declarationConfigExtractor,
-        defaultValue: () => Declaration(),
-        extractedResult: (dynamic result) {
-          _globals = result as Declaration;
-        },
-      ),
-      [strings.macros]: Specification<Declaration>(
-        requirement: Requirement.no,
-        validator: declarationConfigValidator,
-        extractor: declarationConfigExtractor,
-        defaultValue: () => Declaration(),
-        extractedResult: (dynamic result) {
-          _macroDecl = result as Declaration;
-        },
-      ),
-      [strings.typedefs]: Specification<Declaration>(
-        requirement: Requirement.no,
-        validator: declarationConfigValidator,
-        extractor: declarationConfigExtractor,
-        defaultValue: () => Declaration(),
-        extractedResult: (dynamic result) {
-          _typedefs = result as Declaration;
-        },
-      ),
-      [strings.objcInterfaces]: Specification<Declaration>(
-        requirement: Requirement.no,
-        validator: declarationConfigValidator,
-        extractor: declarationConfigExtractor,
-        defaultValue: () => Declaration(),
-        extractedResult: (dynamic result) {
-          _objcInterfaces = result as Declaration;
-        },
-      ),
-      [strings.libraryImports]: Specification<Map<String, LibraryImport>>(
-        validator: libraryImportsValidator,
-        extractor: libraryImportsExtractor,
-        defaultValue: () => <String, LibraryImport>{},
-        extractedResult: (dynamic result) {
-          _libraryImports = result as Map<String, LibraryImport>;
-        },
-      ),
-      [strings.typeMap, strings.typeMapTypedefs]:
-          Specification<Map<String, List<String>>>(
-        validator: typeMapValidator,
-        extractor: typeMapExtractor,
-        defaultValue: () => <String, List<String>>{},
-        extractedResult: (dynamic result) {
-          _typedefTypeMappings = makeImportTypeMapping(
-              result as Map<String, List<String>>, _libraryImports);
-        },
-      ),
-      [strings.typeMap, strings.typeMapStructs]:
-          Specification<Map<String, List<String>>>(
-        validator: typeMapValidator,
-        extractor: typeMapExtractor,
-        defaultValue: () => <String, List<String>>{},
-        extractedResult: (dynamic result) {
-          _structTypeMappings = makeImportTypeMapping(
-              result as Map<String, List<String>>, _libraryImports);
-        },
-      ),
-      [strings.typeMap, strings.typeMapUnions]:
-          Specification<Map<String, List<String>>>(
-        validator: typeMapValidator,
-        extractor: typeMapExtractor,
-        defaultValue: () => <String, List<String>>{},
-        extractedResult: (dynamic result) {
-          _unionTypeMappings = makeImportTypeMapping(
-              result as Map<String, List<String>>, _libraryImports);
-        },
-      ),
-      [strings.typeMap, strings.typeMapNativeTypes]:
-          Specification<Map<String, List<String>>>(
-        validator: typeMapValidator,
-        extractor: typeMapExtractor,
-        defaultValue: () => <String, List<String>>{},
-        extractedResult: (dynamic result) {
-          _nativeTypeMappings = makeImportTypeMapping(
-              result as Map<String, List<String>>, _libraryImports);
-        },
-      ),
-      [strings.sort]: Specification<bool>(
-        requirement: Requirement.no,
-        validator: booleanValidator,
-        extractor: booleanExtractor,
-        defaultValue: () => false,
-        extractedResult: (dynamic result) => _sort = result as bool,
-      ),
-      [strings.useSupportedTypedefs]: Specification<bool>(
-        requirement: Requirement.no,
-        validator: booleanValidator,
-        extractor: booleanExtractor,
-        defaultValue: () => true,
-        extractedResult: (dynamic result) =>
-            _useSupportedTypedefs = result as bool,
-      ),
-      [strings.comments]: Specification<CommentType>(
-        requirement: Requirement.no,
-        validator: commentValidator,
-        extractor: commentExtractor,
-        defaultValue: () => CommentType.def(),
-        extractedResult: (dynamic result) =>
-            _commentType = result as CommentType,
-      ),
-      [strings.structs, strings.dependencyOnly]:
-          Specification<CompoundDependencies>(
-        requirement: Requirement.no,
-        validator: dependencyOnlyValidator,
-        extractor: dependencyOnlyExtractor,
-        defaultValue: () => CompoundDependencies.full,
-        extractedResult: (dynamic result) =>
-            _structDependencies = result as CompoundDependencies,
-      ),
-      [strings.unions, strings.dependencyOnly]:
-          Specification<CompoundDependencies>(
-        requirement: Requirement.no,
-        validator: dependencyOnlyValidator,
-        extractor: dependencyOnlyExtractor,
-        defaultValue: () => CompoundDependencies.full,
-        extractedResult: (dynamic result) =>
-            _unionDependencies = result as CompoundDependencies,
-      ),
-      [strings.structs, strings.structPack]:
-          Specification<StructPackingOverride>(
-        requirement: Requirement.no,
-        validator: structPackingOverrideValidator,
-        extractor: structPackingOverrideExtractor,
-        defaultValue: () => StructPackingOverride(),
-        extractedResult: (dynamic result) =>
-            _structPackingOverride = result as StructPackingOverride,
-      ),
-      [strings.name]: Specification<String>(
-        requirement: Requirement.prefer,
-        validator: dartClassNameValidator,
-        extractor: stringExtractor,
-        defaultValue: () => 'NativeLibrary',
-        extractedResult: (dynamic result) => _wrapperName = result as String,
-      ),
-      [strings.description]: Specification<String?>(
-        requirement: Requirement.prefer,
-        validator: nonEmptyStringValidator,
-        extractor: stringExtractor,
-        defaultValue: () => null,
-        extractedResult: (dynamic result) =>
-            _wrapperDocComment = result as String?,
-      ),
-      [strings.preamble]: Specification<String?>(
-        requirement: Requirement.no,
-        validator: nonEmptyStringValidator,
-        extractor: stringExtractor,
-        extractedResult: (dynamic result) => _preamble = result as String?,
-      ),
-      [strings.useDartHandle]: Specification<bool>(
-        requirement: Requirement.no,
-        validator: booleanValidator,
-        extractor: booleanExtractor,
-        defaultValue: () => true,
-        extractedResult: (dynamic result) => _useDartHandle = result as bool,
-      ),
-      [strings.functions, strings.exposeFunctionTypedefs]:
-          Specification<Includer>(
-        requirement: Requirement.no,
-        validator: exposeFunctionTypeValidator,
-        extractor: exposeFunctionTypeExtractor,
-        defaultValue: () => Includer.excludeByDefault(),
-        extractedResult: (dynamic result) =>
-            _exposeFunctionTypedefs = result as Includer,
-      ),
-      [strings.functions, strings.leafFunctions]: Specification<Includer>(
-        requirement: Requirement.no,
-        validator: leafFunctionValidator,
-        extractor: leafFunctionExtractor,
-        defaultValue: () => Includer.excludeByDefault(),
-        extractedResult: (dynamic result) =>
-            _leafFunctions = result as Includer,
-      ),
-    };
-  }
-}
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/config_provider/config_types.dart b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/config_provider/config_types.dart
deleted file mode 100644
index 6ba4f4e..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/config_provider/config_types.dart
+++ /dev/null
@@ -1,373 +0,0 @@
-// Copyright (c) 2020, 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.
-
-/// Contains all the neccesary classes required by config.
-import 'dart:io';
-
-import 'package:quiver/pattern.dart' as quiver;
-
-import 'path_finder.dart';
-
-enum Language { c, objc }
-
-class CommentType {
-  CommentStyle style;
-  CommentLength length;
-  CommentType(this.style, this.length);
-
-  /// Sets default style as [CommentStyle.doxygen], default length as
-  /// [CommentLength.full].
-  CommentType.def()
-      : style = CommentStyle.doxygen,
-        length = CommentLength.full;
-
-  /// Disables any comments.
-  CommentType.none()
-      : style = CommentStyle.doxygen,
-        length = CommentLength.none;
-}
-
-enum CommentStyle { doxygen, any }
-
-enum CommentLength { none, brief, full }
-
-enum CompoundDependencies { full, opaque }
-
-/// Holds config for how Structs Packing will be overriden.
-class StructPackingOverride {
-  final Map<RegExp, int?> _matcherMap;
-
-  StructPackingOverride({Map<RegExp, int?>? matcherMap})
-      : _matcherMap = matcherMap ?? {};
-
-  /// Returns true if the user has overriden the pack value.
-  bool isOverriden(String name) {
-    for (final key in _matcherMap.keys) {
-      if (quiver.matchesFull(key, name)) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  /// Returns pack value for [name]. Ensure that value [isOverriden] before
-  /// using the returned value.
-  int? getOverridenPackValue(String name) {
-    for (final opv in _matcherMap.entries) {
-      if (quiver.matchesFull(opv.key, name)) {
-        return opv.value;
-      }
-    }
-    return null;
-  }
-}
-
-/// Represents a single specification in configurations.
-///
-/// [E] is the return type of the extractedResult.
-class Specification<E> {
-  final bool Function(List<String> name, dynamic value) validator;
-  final E Function(dynamic map) extractor;
-  final E Function()? defaultValue;
-
-  final Requirement requirement;
-  final void Function(dynamic result) extractedResult;
-
-  Specification({
-    required this.extractedResult,
-    required this.validator,
-    required this.extractor,
-    this.defaultValue,
-    this.requirement = Requirement.no,
-  });
-}
-
-enum Requirement { yes, prefer, no }
-
-// Holds headers and filters for header.
-class Headers {
-  /// Path to headers.
-  ///
-  /// This contains all the headers, after extraction from Globs.
-  final List<String> entryPoints;
-
-  /// Include filter for headers.
-  final HeaderIncludeFilter includeFilter;
-
-  Headers({List<String>? entryPoints, HeaderIncludeFilter? includeFilter})
-      : entryPoints = entryPoints ?? [],
-        includeFilter = includeFilter ?? GlobHeaderFilter();
-}
-
-abstract class HeaderIncludeFilter {
-  bool shouldInclude(String headerSourceFile);
-}
-
-class GlobHeaderFilter extends HeaderIncludeFilter {
-  List<quiver.Glob>? includeGlobs = [];
-
-  GlobHeaderFilter({
-    this.includeGlobs,
-  });
-
-  @override
-  bool shouldInclude(String headerSourceFile) {
-    // Return true if header was included.
-    for (final globPattern in includeGlobs!) {
-      if (quiver.matchesFull(globPattern, headerSourceFile)) {
-        return true;
-      }
-    }
-
-    // If any includedInclusionHeaders is provided, return false.
-    if (includeGlobs!.isNotEmpty) {
-      return false;
-    } else {
-      return true;
-    }
-  }
-}
-
-/// A generic declaration config, used for Functions, Structs, Enums, Macros,
-/// unnamed Enums and Globals.
-class Declaration {
-  final Includer _includer;
-  final Renamer _renamer;
-  final MemberRenamer _memberRenamer;
-  final Includer _symbolAddressIncluder;
-
-  Declaration({
-    Includer? includer,
-    Renamer? renamer,
-    MemberRenamer? memberRenamer,
-    Includer? symbolAddressIncluder,
-  })  : _includer = includer ?? Includer(),
-        _renamer = renamer ?? Renamer(),
-        _memberRenamer = memberRenamer ?? MemberRenamer(),
-        _symbolAddressIncluder =
-            symbolAddressIncluder ?? Includer.excludeByDefault();
-
-  /// Applies renaming and returns the result.
-  String renameUsingConfig(String name) => _renamer.rename(name);
-
-  /// Applies member renaming and returns the result.
-  String renameMemberUsingConfig(String declaration, String member) =>
-      _memberRenamer.rename(declaration, member);
-
-  /// Checks if a name is allowed by a filter.
-  bool shouldInclude(String name) => _includer.shouldInclude(name);
-
-  /// Checks if the symbol address should be included for this name.
-  bool shouldIncludeSymbolAddress(String name) =>
-      _symbolAddressIncluder.shouldInclude(name);
-}
-
-/// Matches `$<single_digit_int>`, value can be accessed in group 1 of match.
-final replaceGroupRegexp = RegExp(r'\$([0-9])');
-
-/// Match/rename using [regExp].
-class RegExpRenamer {
-  final RegExp regExp;
-  final String replacementPattern;
-
-  RegExpRenamer(this.regExp, this.replacementPattern);
-
-  /// Returns true if [str] has a full match with [regExp].
-  bool matches(String str) => quiver.matchesFull(regExp, str);
-
-  /// Renames [str] according to [replacementPattern].
-  ///
-  /// Returns [str] if [regExp] doesn't have a full match.
-  String rename(String str) {
-    if (matches(str)) {
-      // Get match.
-      final regExpMatch = regExp.firstMatch(str)!;
-
-      /// Get group values.
-      /// E.g for `str`: `clang_dispose` and `regExp`: `clang_(.*)`
-      /// groups will be `0`: `clang_disponse`, `1`: `dispose`.
-      final groups = regExpMatch.groups(
-          List.generate(regExpMatch.groupCount, (index) => index) +
-              [regExpMatch.groupCount]);
-
-      /// Replace all `$<int>` symbols with respective groups (if any).
-      final result =
-          replacementPattern.replaceAllMapped(replaceGroupRegexp, (match) {
-        final groupInt = int.parse(match.group(1)!);
-        return groups[groupInt]!;
-      });
-      return result;
-    } else {
-      return str;
-    }
-  }
-
-  @override
-  String toString() {
-    return 'Regexp: $regExp, ReplacementPattern: $replacementPattern';
-  }
-}
-
-/// Handles `include/exclude` logic for a declaration.
-class Includer {
-  final List<RegExp> _includeMatchers;
-  final Set<String> _includeFull;
-  final List<RegExp> _excludeMatchers;
-  final Set<String> _excludeFull;
-
-  Includer({
-    List<RegExp>? includeMatchers,
-    Set<String>? includeFull,
-    List<RegExp>? excludeMatchers,
-    Set<String>? excludeFull,
-  })  : _includeMatchers = includeMatchers ?? [],
-        _includeFull = includeFull ?? {},
-        _excludeMatchers = excludeMatchers ?? [],
-        _excludeFull = excludeFull ?? {};
-
-  Includer.excludeByDefault()
-      : _includeMatchers = [],
-        _includeFull = {},
-        _excludeMatchers = [RegExp('.*', dotAll: true)],
-        _excludeFull = {};
-
-  /// Returns true if [name] is allowed.
-  ///
-  /// Exclude overrides include.
-  bool shouldInclude(String name) {
-    if (_excludeFull.contains(name)) {
-      return false;
-    }
-
-    for (final em in _excludeMatchers) {
-      if (quiver.matchesFull(em, name)) {
-        return false;
-      }
-    }
-
-    if (_includeFull.contains(name)) {
-      return true;
-    }
-
-    for (final im in _includeMatchers) {
-      if (quiver.matchesFull(im, name)) {
-        return true;
-      }
-    }
-
-    // If user has provided 'include' field in the filter, then default
-    // matching is false.
-    if (_includeMatchers.isNotEmpty || _includeFull.isNotEmpty) {
-      return false;
-    } else {
-      return true;
-    }
-  }
-}
-
-/// Handles `full/regexp` renaming logic.
-class Renamer {
-  final Map<String, String> _renameFull;
-  final List<RegExpRenamer> _renameMatchers;
-
-  Renamer({
-    List<RegExpRenamer>? renamePatterns,
-    Map<String, String>? renameFull,
-  })  : _renameMatchers = renamePatterns ?? [],
-        _renameFull = renameFull ?? {};
-
-  Renamer.noRename()
-      : _renameMatchers = [],
-        _renameFull = {};
-
-  String rename(String name) {
-    // Apply full rename (if any).
-    if (_renameFull.containsKey(name)) {
-      return _renameFull[name]!;
-    }
-
-    // Apply rename regexp (if matches).
-    for (final renamer in _renameMatchers) {
-      if (renamer.matches(name)) {
-        return renamer.rename(name);
-      }
-    }
-
-    // No renaming is provided for this declaration, return unchanged.
-    return name;
-  }
-}
-
-/// Match declaration name using [declarationRegExp].
-class RegExpMemberRenamer {
-  final RegExp declarationRegExp;
-  final Renamer memberRenamer;
-
-  RegExpMemberRenamer(this.declarationRegExp, this.memberRenamer);
-
-  /// Returns true if [declaration] has a full match with [regExp].
-  bool matchesDeclarationName(String declaration) =>
-      quiver.matchesFull(declarationRegExp, declaration);
-
-  @override
-  String toString() {
-    return 'DeclarationRegExp: $declarationRegExp, MemberRenamer: $memberRenamer';
-  }
-}
-
-/// Handles `full/regexp` member renaming.
-class MemberRenamer {
-  final Map<String, Renamer> _memberRenameFull;
-  final List<RegExpMemberRenamer> _memberRenameMatchers;
-
-  final Map<String, Renamer> _cache = {};
-
-  MemberRenamer({
-    Map<String, Renamer>? memberRenameFull,
-    List<RegExpMemberRenamer>? memberRenamePattern,
-  })  : _memberRenameFull = memberRenameFull ?? {},
-        _memberRenameMatchers = memberRenamePattern ?? [];
-
-  String rename(String declaration, String member) {
-    if (_cache.containsKey(declaration)) {
-      return _cache[declaration]!.rename(member);
-    }
-
-    // Apply full rename (if any).
-    if (_memberRenameFull.containsKey(declaration)) {
-      // Add to cache.
-      _cache[declaration] = _memberRenameFull[declaration]!;
-      return _cache[declaration]!.rename(member);
-    }
-
-    // Apply rename regexp (if matches).
-    for (final renamer in _memberRenameMatchers) {
-      if (renamer.matchesDeclarationName(declaration)) {
-        // Add to cache.
-        _cache[declaration] = renamer.memberRenamer;
-        return _cache[declaration]!.rename(member);
-      }
-    }
-
-    // No renaming is provided for this declaration, return unchanged.
-    return member;
-  }
-}
-
-/// Handles config for automatically added compiler options.
-class CompilerOptsAuto {
-  final bool macIncludeStdLib;
-
-  CompilerOptsAuto({bool? macIncludeStdLib})
-      : macIncludeStdLib = macIncludeStdLib ?? true;
-
-  /// Extracts compiler options based on OS and config.
-  List<String> extractCompilerOpts() {
-    if (Platform.isMacOS && macIncludeStdLib) {
-      return getCStandardLibraryHeadersForMac();
-    }
-
-    return [];
-  }
-}
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/config_provider/path_finder.dart b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/config_provider/path_finder.dart
deleted file mode 100644
index 3f6a597..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/config_provider/path_finder.dart
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright (c) 2021, 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.
-
-/// Utils for finding header paths on system.
-
-import 'dart:io';
-
-import 'package:logging/logging.dart';
-import 'package:path/path.dart' as p;
-
-final _logger = Logger('ffigen.config_provider.path_finder');
-
-/// This will return include path from either LLVM, XCode or CommandLineTools.
-List<String> getCStandardLibraryHeadersForMac() {
-  final includePaths = <String>[];
-
-  /// Add system headers.
-  const systemHeaders =
-      '/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include';
-  if (Directory(systemHeaders).existsSync()) {
-    _logger.fine('Added $systemHeaders to compiler-opts.');
-    includePaths.add('-I' + systemHeaders);
-  }
-
-  /// Find headers from XCode or LLVM installed via brew.
-  const brewLlvmPath = '/usr/local/opt/llvm/lib/clang';
-  const xcodeClangPath =
-      '/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/';
-  const searchPaths = [brewLlvmPath, xcodeClangPath];
-  for (final searchPath in searchPaths) {
-    if (!Directory(searchPath).existsSync()) continue;
-
-    final result = Process.runSync('ls', [searchPath]);
-    final stdout = result.stdout as String;
-    if (stdout != '') {
-      final versions = stdout.split('\n').where((s) => s != '');
-      for (final version in versions) {
-        final path = p.join(searchPath, version, 'include');
-        if (Directory(path).existsSync()) {
-          _logger.fine('Added stdlib path: $path to compiler-opts.');
-          includePaths.add('-I' + path);
-          return includePaths;
-        }
-      }
-    }
-  }
-
-  /// If CommandLineTools are installed use those headers.
-  const cmdLineToolHeaders =
-      '/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Kernel.framework/Headers/';
-  if (Directory(cmdLineToolHeaders).existsSync()) {
-    _logger.fine('Added stdlib path: $cmdLineToolHeaders to compiler-opts.');
-    includePaths.add('-I' + cmdLineToolHeaders);
-    return includePaths;
-  }
-
-  // Warnings for missing headers are printed by libclang while parsing.
-  _logger.fine('Couldn\'t find stdlib headers in default locations.');
-  _logger.fine('Paths searched: ${[cmdLineToolHeaders, ...searchPaths]}');
-
-  return [];
-}
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/config_provider/spec_utils.dart b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/config_provider/spec_utils.dart
deleted file mode 100644
index aaa4c08..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/config_provider/spec_utils.dart
+++ /dev/null
@@ -1,866 +0,0 @@
-// Copyright (c) 2020, 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.
-
-import 'dart:io';
-
-import 'package:ffigen/src/code_generator.dart';
-import 'package:file/local.dart';
-import 'package:glob/glob.dart';
-import 'package:logging/logging.dart';
-import 'package:path/path.dart' as p;
-import 'package:quiver/pattern.dart' as quiver;
-import 'package:yaml/yaml.dart';
-
-import '../strings.dart' as strings;
-import 'config_types.dart';
-
-final _logger = Logger('ffigen.config_provider.spec_utils');
-
-/// Replaces the path separators according to current platform.
-String _replaceSeparators(String path) {
-  if (Platform.isWindows) {
-    return path.replaceAll(p.posix.separator, p.windows.separator);
-  } else {
-    return path.replaceAll(p.windows.separator, p.posix.separator);
-  }
-}
-
-/// Checks if type of value is [T], logs an error if it's not.
-///
-/// [key] is printed as `'item1 -> item2 => item3'` in log message.
-bool checkType<T>(List<String> keys, dynamic value) {
-  if (value is! T) {
-    _logger.severe(
-        "Expected value of key '${keys.join(' -> ')}' to be of type '$T'.");
-    return false;
-  }
-  return true;
-}
-
-/// Checks if there are nested [key] in [map].
-bool checkKeyInYaml(List<String> key, YamlMap map) {
-  dynamic last = map;
-  for (final k in key) {
-    if (last is YamlMap) {
-      if (!last.containsKey(k)) return false;
-      last = last[k];
-    } else {
-      return false;
-    }
-  }
-  return last != null;
-}
-
-/// Extracts value of nested [key] from [map].
-dynamic getKeyValueFromYaml(List<String> key, YamlMap map) {
-  if (checkKeyInYaml(key, map)) {
-    dynamic last = map;
-    for (final k in key) {
-      last = last[k];
-    }
-    return last;
-  }
-
-  return null;
-}
-
-/// Recursively checks the keys in [configKeyMap] from [allowedKeyList].
-void warnUnknownKeys(List<List<String>> allowedKeyList, YamlMap configKeyMap) {
-  final allowedKeyMap = <String, dynamic>{};
-  for (final specKeys in allowedKeyList) {
-    var _item = allowedKeyMap;
-    for (final specSubKey in specKeys) {
-      _item.putIfAbsent(specSubKey, () => <String, dynamic>{});
-      _item = _item[specSubKey] as Map<String, dynamic>;
-    }
-    // Add empty key to mark that any sub-keys of this key are allowed.
-    _item[''] = <String, dynamic>{};
-  }
-  _warnUnknownKeysInMap(allowedKeyMap, configKeyMap, <dynamic>[]);
-}
-
-/// Recursive function to check a key set in a configKeyMap.
-void _warnUnknownKeysInMap(Map<String, dynamic> allowedKeyMap,
-    dynamic configKeyMap, List<dynamic> prev) {
-  if (allowedKeyMap.containsKey('') || configKeyMap is! YamlMap) {
-    return;
-  }
-  for (final key in configKeyMap.keys) {
-    if (allowedKeyMap.containsKey(key)) {
-      prev.add(key);
-      _warnUnknownKeysInMap(
-          allowedKeyMap[key] as Map<String, dynamic>, configKeyMap[key], prev);
-      prev.removeLast();
-    } else {
-      prev.add(key);
-      _logger.warning('Unknown key - ${prev.join(' -> ')}.');
-      prev.removeLast();
-    }
-  }
-}
-
-bool booleanExtractor(dynamic value) => value as bool;
-
-bool booleanValidator(List<String> name, dynamic value) =>
-    checkType<bool>(name, value);
-
-Map<String, LibraryImport> libraryImportsExtractor(dynamic yamlConfig) {
-  final resultMap = <String, LibraryImport>{};
-  final typeMap = yamlConfig as YamlMap?;
-  if (typeMap != null) {
-    for (final typeName in typeMap.keys) {
-      resultMap[typeName as String] =
-          LibraryImport(typeName, typeMap[typeName] as String);
-    }
-  }
-  return resultMap;
-}
-
-bool libraryImportsValidator(List<String> name, dynamic yamlConfig) {
-  if (!checkType<YamlMap>(name, yamlConfig)) {
-    return false;
-  }
-  for (final key in (yamlConfig as YamlMap).keys) {
-    if (!checkType<String>([...name, key as String], yamlConfig[key])) {
-      return false;
-    }
-    if (strings.predefinedLibraryImports.containsKey(key)) {
-      _logger.severe(
-          'library-import -> $key should not collide with any predefined imports - ${strings.predefinedLibraryImports.keys}.');
-      return false;
-    }
-  }
-  return true;
-}
-
-Map<String, List<String>> typeMapExtractor(dynamic yamlConfig) {
-  // Key - type_name, Value - [lib, cType, dartType].
-  final resultMap = <String, List<String>>{};
-  final typeMap = yamlConfig as YamlMap?;
-  if (typeMap != null) {
-    for (final typeName in typeMap.keys) {
-      final typeConfigItem = typeMap[typeName] as YamlMap;
-      resultMap[typeName as String] = [
-        typeConfigItem[strings.lib] as String,
-        typeConfigItem[strings.cType] as String,
-        typeConfigItem[strings.dartType] as String,
-      ];
-    }
-  }
-  return resultMap;
-}
-
-bool typeMapValidator(List<String> name, dynamic yamlConfig) {
-  if (!checkType<YamlMap>(name, yamlConfig)) {
-    return false;
-  }
-  var result = true;
-  for (final key in (yamlConfig as YamlMap).keys) {
-    if (!checkType<YamlMap>([...name, key as String], yamlConfig[key])) {
-      return false;
-    }
-    final lib = (yamlConfig[key] as YamlMap).containsKey(strings.lib);
-    if (!lib) {
-      _logger.severe("Key '${strings.lib}' in $name -> $key is required.");
-      result = false;
-    }
-    final cType = (yamlConfig[key] as YamlMap).containsKey(strings.cType);
-    if (!cType) {
-      _logger.severe("Key '${strings.cType}' in $name -> $key is required.");
-      result = false;
-    }
-    final dartType = (yamlConfig[key] as YamlMap).containsKey(strings.dartType);
-    if (!dartType) {
-      _logger.severe("Key '${strings.dartType}' in $name -> $key is required.");
-      result = false;
-    }
-  }
-  return result;
-}
-
-Map<String, ImportedType> makeImportTypeMapping(
-    Map<String, List<String>> rawTypeMappings,
-    Map<String, LibraryImport> libraryImportsMap) {
-  final typeMappings = <String, ImportedType>{};
-  for (final key in rawTypeMappings.keys) {
-    final lib = rawTypeMappings[key]![0];
-    final cType = rawTypeMappings[key]![1];
-    final dartType = rawTypeMappings[key]![2];
-    if (strings.predefinedLibraryImports.containsKey(lib)) {
-      typeMappings[key] =
-          ImportedType(strings.predefinedLibraryImports[lib]!, cType, dartType);
-    } else if (libraryImportsMap.containsKey(lib)) {
-      typeMappings[key] =
-          ImportedType(libraryImportsMap[lib]!, cType, dartType);
-    } else {
-      throw Exception("Please declare $lib under library-imports.");
-    }
-  }
-  return typeMappings;
-}
-
-final _quoteMatcher = RegExp(r'''^["'](.*)["']$''', dotAll: true);
-final _cmdlineArgMatcher = RegExp(r'''['"](\\"|[^"])*?['"]|[^ ]+''');
-List<String> compilerOptsToList(String compilerOpts) {
-  final list = <String>[];
-  _cmdlineArgMatcher.allMatches(compilerOpts).forEach((element) {
-    var match = element.group(0);
-    if (match != null) {
-      if (quiver.matchesFull(_quoteMatcher, match)) {
-        match = _quoteMatcher.allMatches(match).first.group(1)!;
-      }
-      list.add(match);
-    }
-  });
-
-  return list;
-}
-
-List<String> compilerOptsExtractor(dynamic value) {
-  if (value is String) {
-    return compilerOptsToList(value);
-  }
-
-  final list = <String>[];
-  for (final el in (value as YamlList)) {
-    if (el is String) {
-      list.addAll(compilerOptsToList(el));
-    }
-  }
-  return list;
-}
-
-bool compilerOptsValidator(List<String> name, dynamic value) {
-  if (value is String || value is YamlList) {
-    return true;
-  } else {
-    _logger.severe('Expected $name to be a String or List of String.');
-    return false;
-  }
-}
-
-CompilerOptsAuto compilerOptsAutoExtractor(dynamic value) {
-  return CompilerOptsAuto(
-    macIncludeStdLib: getKeyValueFromYaml(
-      [strings.macos, strings.includeCStdLib],
-      value as YamlMap,
-    ) as bool?,
-  );
-}
-
-bool compilerOptsAutoValidator(List<String> name, dynamic value) {
-  var _result = true;
-
-  if (!checkType<YamlMap>(name, value)) {
-    return false;
-  }
-
-  for (final oskey in (value as YamlMap).keys) {
-    if (oskey == strings.macos) {
-      if (!checkType<YamlMap>([...name, oskey as String], value[oskey])) {
-        return false;
-      }
-
-      for (final inckey in (value[oskey] as YamlMap).keys) {
-        if (inckey == strings.includeCStdLib) {
-          if (!checkType<bool>(
-              [...name, oskey, inckey as String], value[oskey][inckey])) {
-            _result = false;
-          }
-        } else {
-          _logger.severe("Unknown key '$inckey' in '$name -> $oskey.");
-          _result = false;
-        }
-      }
-    } else {
-      _logger.severe("Unknown key '$oskey' in '$name'.");
-      _result = false;
-    }
-  }
-  return _result;
-}
-
-Headers headersExtractor(dynamic yamlConfig) {
-  final entryPoints = <String>[];
-  final includeGlobs = <quiver.Glob>[];
-  for (final key in (yamlConfig as YamlMap).keys) {
-    if (key == strings.entryPoints) {
-      for (final h in (yamlConfig[key] as YamlList)) {
-        final headerGlob = h as String;
-        // Add file directly to header if it's not a Glob but a File.
-        if (File(headerGlob).existsSync()) {
-          final osSpecificPath = _replaceSeparators(headerGlob);
-          entryPoints.add(osSpecificPath);
-          _logger.fine('Adding header/file: $headerGlob');
-        } else {
-          final glob = Glob(headerGlob);
-          for (final file in glob.listFileSystemSync(const LocalFileSystem(),
-              followLinks: true)) {
-            final fixedPath = _replaceSeparators(file.path);
-            entryPoints.add(fixedPath);
-            _logger.fine('Adding header/file: $fixedPath');
-          }
-        }
-      }
-    }
-    if (key == strings.includeDirectives) {
-      for (final h in (yamlConfig[key] as YamlList)) {
-        final headerGlob = h as String;
-        final fixedGlob = _replaceSeparators(headerGlob);
-        includeGlobs.add(quiver.Glob(fixedGlob));
-      }
-    }
-  }
-  return Headers(
-    entryPoints: entryPoints,
-    includeFilter: GlobHeaderFilter(
-      includeGlobs: includeGlobs,
-    ),
-  );
-}
-
-bool headersValidator(List<String> name, dynamic value) {
-  if (!checkType<YamlMap>(name, value)) {
-    return false;
-  }
-  if (!(value as YamlMap).containsKey(strings.entryPoints)) {
-    _logger.severe("Required '$name -> ${strings.entryPoints}'.");
-    return false;
-  } else {
-    for (final key in value.keys) {
-      if (key == strings.entryPoints || key == strings.includeDirectives) {
-        if (!checkType<YamlList>([...name, key as String], value[key])) {
-          return false;
-        }
-      } else {
-        _logger.severe("Unknown key '$key' in '$name'.");
-        return false;
-      }
-    }
-    return true;
-  }
-}
-
-String libclangDylibExtractor(dynamic value) => getDylibPath(value as String);
-
-bool libclangDylibValidator(List<String> name, dynamic value) {
-  if (!checkType<String>(name, value)) {
-    return false;
-  } else {
-    final dylibPath = getDylibPath(value as String);
-    if (!File(dylibPath).existsSync()) {
-      _logger.severe(
-          'Dynamic library: $dylibPath does not exist or is corrupt, input folder: $value.');
-      return false;
-    } else {
-      return true;
-    }
-  }
-}
-
-String getDylibPath(String dylibParentFoler) {
-  dylibParentFoler = _replaceSeparators(dylibParentFoler);
-  String dylibPath;
-  if (Platform.isMacOS) {
-    dylibPath = p.join(dylibParentFoler, strings.libclang_dylib_macos);
-  } else if (Platform.isWindows) {
-    dylibPath = p.join(dylibParentFoler, strings.libclang_dylib_windows);
-  } else {
-    dylibPath = p.join(dylibParentFoler, strings.libclang_dylib_linux);
-  }
-  return dylibPath;
-}
-
-/// Returns location of dynamic library by searching default locations. Logs
-/// error and throws an Exception if not found.
-String findDylibAtDefaultLocations() {
-  String? k;
-  if (Platform.isLinux) {
-    for (final l in strings.linuxDylibLocations) {
-      k = findLibclangDylib(l);
-      if (k != null) return k;
-    }
-  } else if (Platform.isWindows) {
-    for (final l in strings.windowsDylibLocations) {
-      k = findLibclangDylib(l);
-      if (k != null) return k;
-    }
-  } else if (Platform.isMacOS) {
-    for (final l in strings.macOsDylibLocations) {
-      k = findLibclangDylib(l);
-      if (k != null) return k;
-    }
-  } else {
-    throw Exception('Unsupported Platform.');
-  }
-
-  _logger.severe("Couldn't find dynamic library in default locations.");
-  _logger.severe(
-      "Please supply one or more path/to/llvm in ffigen's config under the key '${strings.llvmPath}'.");
-  throw Exception("Couldn't find dynamic library in default locations.");
-}
-
-String? findLibclangDylib(String parentFolder) {
-  final location = p.join(parentFolder, strings.dylibFileName);
-  if (File(location).existsSync()) {
-    return location;
-  } else {
-    return null;
-  }
-}
-
-String llvmPathExtractor(dynamic value) {
-  // Extract libclang's dylib from user specified paths.
-  for (final path in (value as YamlList)) {
-    if (path is! String) continue;
-    final dylibPath =
-        findLibclangDylib(p.join(path, strings.dynamicLibParentName));
-    if (dylibPath != null) {
-      _logger.fine('Found dynamic library at: $dylibPath');
-      return dylibPath;
-    }
-    // Check if user has specified complete path to dylib.
-    final completeDylibPath = path;
-    if (p.extension(completeDylibPath).isNotEmpty &&
-        File(completeDylibPath).existsSync()) {
-      _logger.info(
-          'Using complete dylib path: $completeDylibPath from llvm-path.');
-      return completeDylibPath;
-    }
-  }
-  _logger.fine(
-      "Couldn't find dynamic library under paths specified by ${strings.llvmPath}.");
-  // Extract path from default locations.
-  try {
-    final res = findDylibAtDefaultLocations();
-    return res;
-  } catch (e) {
-    _logger.severe(
-        "Couldn't find ${p.join(strings.dynamicLibParentName, strings.dylibFileName)} in specified locations.");
-    exit(1);
-  }
-}
-
-bool llvmPathValidator(List<String> name, dynamic value) {
-  if (!checkType<YamlList>(name, value)) {
-    return false;
-  }
-  return true;
-}
-
-String outputExtractor(dynamic value) => _replaceSeparators(value as String);
-
-bool outputValidator(List<String> name, dynamic value) =>
-    checkType<String>(name, value);
-
-Language languageExtractor(dynamic value) {
-  if (value == strings.langC) {
-    return Language.c;
-  } else if (value == strings.langObjC) {
-    return Language.objc;
-  }
-  return Language.c;
-}
-
-bool languageValidator(List<String> name, dynamic value) {
-  if (value is String) {
-    if (value == strings.langC) {
-      return true;
-    }
-    if (value == strings.langObjC) {
-      _logger.severe('Objective C support is EXPERIMENTAL. The API may change '
-          'in a breaking way without notice.');
-      return true;
-    }
-    _logger.severe("'$name' must be one of the following - "
-        "{${strings.langC}, ${strings.langObjC}}");
-    return false;
-  }
-  _logger.severe("Expected value of key '$name' to be a String.");
-  return false;
-}
-
-/// Returns true if [str] is not a full name.
-///
-/// E.g `abc` is a full name, `abc.*` is not.
-bool isFullDeclarationName(String str) =>
-    quiver.matchesFull(RegExp('[a-zA-Z_0-9]*'), str);
-
-Includer _extractIncluderFromYaml(dynamic yamlMap) {
-  final includeMatchers = <RegExp>[],
-      includeFull = <String>{},
-      excludeMatchers = <RegExp>[],
-      excludeFull = <String>{};
-
-  final include = (yamlMap[strings.include] as YamlList?)?.cast<String>();
-  if (include != null) {
-    if (include.isEmpty) {
-      return Includer.excludeByDefault();
-    }
-    for (final str in include) {
-      if (isFullDeclarationName(str)) {
-        includeFull.add(str);
-      } else {
-        includeMatchers.add(RegExp(str, dotAll: true));
-      }
-    }
-  }
-
-  final exclude = (yamlMap[strings.exclude] as YamlList?)?.cast<String>();
-  if (exclude != null) {
-    for (final str in exclude) {
-      if (isFullDeclarationName(str)) {
-        excludeFull.add(str);
-      } else {
-        excludeMatchers.add(RegExp(str, dotAll: true));
-      }
-    }
-  }
-
-  return Includer(
-    includeMatchers: includeMatchers,
-    includeFull: includeFull,
-    excludeMatchers: excludeMatchers,
-    excludeFull: excludeFull,
-  );
-}
-
-Declaration declarationConfigExtractor(dynamic yamlMap) {
-  final renamePatterns = <RegExpRenamer>[];
-  final renameFull = <String, String>{};
-  final memberRenamePatterns = <RegExpMemberRenamer>[];
-  final memberRenamerFull = <String, Renamer>{};
-
-  final includer = _extractIncluderFromYaml(yamlMap);
-
-  Includer? symbolIncluder;
-  if (yamlMap[strings.symbolAddress] != null) {
-    symbolIncluder = _extractIncluderFromYaml(yamlMap[strings.symbolAddress]);
-  }
-
-  final rename = (yamlMap[strings.rename] as YamlMap?)?.cast<String, String>();
-
-  if (rename != null) {
-    for (final str in rename.keys) {
-      if (isFullDeclarationName(str)) {
-        renameFull[str] = rename[str]!;
-      } else {
-        renamePatterns
-            .add(RegExpRenamer(RegExp(str, dotAll: true), rename[str]!));
-      }
-    }
-  }
-
-  final memberRename =
-      (yamlMap[strings.memberRename] as YamlMap?)?.cast<String, YamlMap>();
-
-  if (memberRename != null) {
-    for (final decl in memberRename.keys) {
-      final renamePatterns = <RegExpRenamer>[];
-      final renameFull = <String, String>{};
-
-      final memberRenameMap = memberRename[decl]!.cast<String, String>();
-      for (final member in memberRenameMap.keys) {
-        if (isFullDeclarationName(member)) {
-          renameFull[member] = memberRenameMap[member]!;
-        } else {
-          renamePatterns.add(RegExpRenamer(
-              RegExp(member, dotAll: true), memberRenameMap[member]!));
-        }
-      }
-      if (isFullDeclarationName(decl)) {
-        memberRenamerFull[decl] = Renamer(
-          renameFull: renameFull,
-          renamePatterns: renamePatterns,
-        );
-      } else {
-        memberRenamePatterns.add(
-          RegExpMemberRenamer(
-            RegExp(decl, dotAll: true),
-            Renamer(
-              renameFull: renameFull,
-              renamePatterns: renamePatterns,
-            ),
-          ),
-        );
-      }
-    }
-  }
-
-  return Declaration(
-    includer: includer,
-    renamer: Renamer(
-      renameFull: renameFull,
-      renamePatterns: renamePatterns,
-    ),
-    memberRenamer: MemberRenamer(
-      memberRenameFull: memberRenamerFull,
-      memberRenamePattern: memberRenamePatterns,
-    ),
-    symbolAddressIncluder: symbolIncluder,
-  );
-}
-
-bool declarationConfigValidator(List<String> name, dynamic value) {
-  var _result = true;
-  if (value is YamlMap) {
-    for (final key in value.keys) {
-      if (key == strings.include || key == strings.exclude) {
-        if (!checkType<YamlList>([...name, key as String], value[key])) {
-          _result = false;
-        }
-      } else if (key == strings.rename) {
-        if (!checkType<YamlMap>([...name, key as String], value[key])) {
-          _result = false;
-        } else {
-          for (final subkey in (value[key] as YamlMap).keys) {
-            if (!checkType<String>(
-                [...name, key, subkey as String], value[key][subkey])) {
-              _result = false;
-            }
-          }
-        }
-      } else if (key == strings.memberRename) {
-        if (!checkType<YamlMap>([...name, key as String], value[key])) {
-          _result = false;
-        } else {
-          for (final declNameKey in (value[key] as YamlMap).keys) {
-            if (!checkType<YamlMap>([...name, key, declNameKey as String],
-                value[key][declNameKey])) {
-              _result = false;
-            } else {
-              for (final memberNameKey
-                  in ((value[key] as YamlMap)[declNameKey] as YamlMap).keys) {
-                if (!checkType<String>([
-                  ...name,
-                  key,
-                  declNameKey,
-                  memberNameKey as String,
-                ], value[key][declNameKey][memberNameKey])) {
-                  _result = false;
-                }
-              }
-            }
-          }
-        }
-      } else if (key == strings.symbolAddress) {
-        if (!checkType<YamlMap>([...name, key as String], value[key])) {
-          _result = false;
-        } else {
-          for (final subkey in (value[key] as YamlMap).keys) {
-            if (subkey == strings.include || subkey == strings.exclude) {
-              if (!checkType<YamlList>(
-                  [...name, key, subkey as String], value[key][subkey])) {
-                _result = false;
-              }
-            } else {
-              _logger.severe("Unknown key '$subkey' in '$name -> $key'.");
-              _result = false;
-            }
-          }
-        }
-      }
-    }
-  } else {
-    _logger.severe("Expected value '$name' to be a Map.");
-    _result = false;
-  }
-  return _result;
-}
-
-Includer exposeFunctionTypeExtractor(dynamic value) =>
-    _extractIncluderFromYaml(value);
-
-bool exposeFunctionTypeValidator(List<String> name, dynamic value) {
-  var _result = true;
-
-  if (!checkType<YamlMap>(name, value)) {
-    _result = false;
-  } else {
-    final mp = value as YamlMap;
-    for (final key in mp.keys) {
-      if (key == strings.include || key == strings.exclude) {
-        if (!checkType<YamlList>([...name, key as String], value[key])) {
-          _result = false;
-        }
-      } else {
-        _logger.severe("Unknown subkey '$key' in '$name'.");
-        _result = false;
-      }
-    }
-  }
-
-  return _result;
-}
-
-Includer leafFunctionExtractor(dynamic value) =>
-    _extractIncluderFromYaml(value);
-
-bool leafFunctionValidator(List<String> name, dynamic value) {
-  var _result = true;
-
-  if (!checkType<YamlMap>(name, value)) {
-    _result = false;
-  } else {
-    final mp = value as YamlMap;
-    for (final key in mp.keys) {
-      if (key == strings.include || key == strings.exclude) {
-        if (!checkType<YamlList>([...name, key as String], value[key])) {
-          _result = false;
-        }
-      } else {
-        _logger.severe("Unknown subkey '$key' in '$name'.");
-        _result = false;
-      }
-    }
-  }
-
-  return _result;
-}
-
-SupportedNativeType nativeSupportedType(int value, {bool signed = true}) {
-  switch (value) {
-    case 1:
-      return signed ? SupportedNativeType.Int8 : SupportedNativeType.Uint8;
-    case 2:
-      return signed ? SupportedNativeType.Int16 : SupportedNativeType.Uint16;
-    case 4:
-      return signed ? SupportedNativeType.Int32 : SupportedNativeType.Uint32;
-    case 8:
-      return signed ? SupportedNativeType.Int64 : SupportedNativeType.Uint64;
-    default:
-      throw Exception(
-          'Unsupported value given to sizemap, Allowed values for sizes are: 1, 2, 4, 8');
-  }
-}
-
-String stringExtractor(dynamic value) => value as String;
-
-bool nonEmptyStringValidator(List<String> name, dynamic value) {
-  if (value is String && value.isNotEmpty) {
-    return true;
-  } else {
-    _logger.severe("Expected value of key '$name' to be a non-empty String.");
-    return false;
-  }
-}
-
-bool dartClassNameValidator(List<String> name, dynamic value) {
-  if (value is String &&
-      quiver.matchesFull(RegExp('[a-zA-Z]+[_a-zA-Z0-9]*'), value)) {
-    return true;
-  } else {
-    _logger.severe(
-        "Expected value of key '$name' to be a valid public class name.");
-    return false;
-  }
-}
-
-CommentType commentExtractor(dynamic value) {
-  if (value is bool) {
-    if (value) {
-      return CommentType.def();
-    } else {
-      return CommentType.none();
-    }
-  }
-  final ct = CommentType.def();
-  if (value is YamlMap) {
-    for (final key in value.keys) {
-      if (key == strings.style) {
-        if (value[key] == strings.any) {
-          ct.style = CommentStyle.any;
-        } else if (value[key] == strings.doxygen) {
-          ct.style = CommentStyle.doxygen;
-        }
-      } else if (key == strings.length) {
-        if (value[key] == strings.full) {
-          ct.length = CommentLength.full;
-        } else if (value[key] == strings.brief) {
-          ct.length = CommentLength.brief;
-        }
-      }
-    }
-  }
-  return ct;
-}
-
-bool commentValidator(List<String> name, dynamic value) {
-  if (value is bool) {
-    return true;
-  } else if (value is YamlMap) {
-    var result = true;
-    for (final key in value.keys) {
-      if (key == strings.style) {
-        if (value[key] is! String ||
-            !(value[key] == strings.doxygen || value[key] == strings.any)) {
-          _logger.severe(
-              "'$name'>'${strings.style}' must be one of the following - {${strings.doxygen}, ${strings.any}}");
-          result = false;
-        }
-      } else if (key == strings.length) {
-        if (value[key] is! String ||
-            !(value[key] == strings.brief || value[key] == strings.full)) {
-          _logger.severe(
-              "'$name'>'${strings.length}' must be one of the following - {${strings.brief}, ${strings.full}}");
-          result = false;
-        }
-      } else {
-        _logger.severe("Unknown key '$key' in '$name'.");
-        result = false;
-      }
-    }
-    return result;
-  } else {
-    _logger.severe("Expected value of key '$name' to be a bool or a Map.");
-    return false;
-  }
-}
-
-CompoundDependencies dependencyOnlyExtractor(dynamic value) {
-  var result = CompoundDependencies.full;
-  if (value == strings.opaqueCompoundDependencies) {
-    result = CompoundDependencies.opaque;
-  }
-  return result;
-}
-
-bool dependencyOnlyValidator(List<String> name, dynamic value) {
-  var result = true;
-  if (value is! String ||
-      !(value == strings.fullCompoundDependencies ||
-          value == strings.opaqueCompoundDependencies)) {
-    _logger.severe(
-        "'$name' must be one of the following - {${strings.fullCompoundDependencies}, ${strings.opaqueCompoundDependencies}}");
-    result = false;
-  }
-  return result;
-}
-
-StructPackingOverride structPackingOverrideExtractor(dynamic value) {
-  final matcherMap = <RegExp, int?>{};
-  for (final key in (value as YamlMap).keys) {
-    matcherMap[RegExp(key as String, dotAll: true)] =
-        strings.packingValuesMap[value[key]];
-  }
-  return StructPackingOverride(matcherMap: matcherMap);
-}
-
-bool structPackingOverrideValidator(List<String> name, dynamic value) {
-  var _result = true;
-
-  if (!checkType<YamlMap>([...name], value)) {
-    _result = false;
-  } else {
-    for (final key in (value as YamlMap).keys) {
-      if (!(strings.packingValuesMap.keys.contains(value[key]))) {
-        _logger.severe(
-            "'$name -> $key' must be one of the following - ${strings.packingValuesMap.keys.toList()}");
-        _result = false;
-      }
-    }
-  }
-
-  return _result;
-}
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/executables/ffigen.dart b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/executables/ffigen.dart
deleted file mode 100644
index 12dd868..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/executables/ffigen.dart
+++ /dev/null
@@ -1,223 +0,0 @@
-// Copyright (c) 2021, 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.
-
-// Executable script to generate bindings for some C library.
-import 'dart:io';
-
-import 'package:args/args.dart';
-import 'package:cli_util/cli_logging.dart' show Ansi;
-import 'package:ffigen/ffigen.dart';
-import 'package:logging/logging.dart';
-import 'package:yaml/yaml.dart' as yaml;
-
-final _logger = Logger('ffigen.ffigen');
-final _ansi = Ansi(Ansi.terminalSupportsAnsi);
-
-const compilerOpts = 'compiler-opts';
-const conf = 'config';
-const help = 'help';
-const verbose = 'verbose';
-const pubspecName = 'pubspec.yaml';
-const configKey = 'ffigen';
-const logAll = 'all';
-const logFine = 'fine';
-const logInfo = 'info';
-const logWarning = 'warning';
-const logSevere = 'severe';
-
-String successPen(String str) {
-  return '${_ansi.green}$str${_ansi.none}';
-}
-
-String errorPen(String str) {
-  return '${_ansi.red}$str${_ansi.none}';
-}
-
-void main(List<String> args) {
-  // Parses the cmd args. This will print usage and exit if --help was passed.
-  final argResult = getArgResults(args);
-
-  // Setup logging level and printing.
-  setupLogger(argResult);
-
-  // Create a config object.
-  Config config;
-  try {
-    config = getConfig(argResult);
-  } on FormatException {
-    _logger.severe('Please fix configuration errors and re-run the tool.');
-    exit(1);
-  }
-
-  // Parse the bindings according to config object provided.
-  final library = parse(config);
-
-  // Generate file for the parsed bindings.
-  final gen = File(config.output);
-  library.generateFile(gen);
-  _logger
-      .info(successPen('Finished, Bindings generated in ${gen.absolute.path}'));
-}
-
-Config getConfig(ArgResults result) {
-  _logger.info('Running in ${Directory.current}');
-  Config config;
-
-  // Parse config from yaml.
-  if (result.wasParsed(conf)) {
-    config = getConfigFromCustomYaml(result[conf] as String);
-  } else {
-    config = getConfigFromPubspec();
-  }
-
-  // Add compiler options from command line.
-  if (result.wasParsed(compilerOpts)) {
-    _logger.fine('Passed compiler opts - "${result[compilerOpts]}"');
-    config.addCompilerOpts((result[compilerOpts] as String),
-        highPriority: true);
-  }
-
-  return config;
-}
-
-/// Extracts configuration from pubspec file.
-Config getConfigFromPubspec() {
-  final pubspecFile = File(pubspecName);
-
-  if (!pubspecFile.existsSync()) {
-    _logger.severe(
-        'Error: $pubspecName not found, please run this tool from the root of your package.');
-    exit(1);
-  }
-
-  // Casting this because pubspec is expected to be a YamlMap.
-
-  // Throws a [YamlException] if it's unable to parse the Yaml.
-  final bindingsConfigMap =
-      yaml.loadYaml(pubspecFile.readAsStringSync())[configKey] as yaml.YamlMap?;
-
-  if (bindingsConfigMap == null) {
-    _logger.severe("Couldn't find an entry for '$configKey' in $pubspecName.");
-    exit(1);
-  }
-  return Config.fromYaml(bindingsConfigMap);
-}
-
-/// Extracts configuration from a custom yaml file.
-Config getConfigFromCustomYaml(String yamlPath) {
-  final yamlFile = File(yamlPath);
-
-  if (!yamlFile.existsSync()) {
-    _logger.severe('Error: $yamlPath not found.');
-    exit(1);
-  }
-
-  // Throws a [YamlException] if it's unable to parse the Yaml.
-  final bindingsConfigMap =
-      yaml.loadYaml(yamlFile.readAsStringSync()) as yaml.YamlMap;
-
-  return Config.fromYaml(bindingsConfigMap);
-}
-
-/// Parses the cmd line arguments.
-ArgResults getArgResults(List<String> args) {
-  final parser = ArgParser(allowTrailingOptions: true);
-
-  parser.addSeparator(
-      'FFIGEN: Generate dart bindings from C header files\nUsage:');
-  parser.addOption(
-    conf,
-    help: 'Path to Yaml file containing configurations if not in pubspec.yaml',
-  );
-  parser.addOption(
-    verbose,
-    abbr: 'v',
-    defaultsTo: logInfo,
-    allowed: [
-      logAll,
-      logFine,
-      logInfo,
-      logWarning,
-      logSevere,
-    ],
-  );
-  parser.addFlag(
-    help,
-    abbr: 'h',
-    help: 'Prints this usage',
-    negatable: false,
-  );
-  parser.addOption(
-    compilerOpts,
-    help: 'Compiler options for clang. (E.g --$compilerOpts "-I/headers -W")',
-  );
-
-  ArgResults results;
-  try {
-    results = parser.parse(args);
-
-    if (results.wasParsed(help)) {
-      print(parser.usage);
-      exit(0);
-    }
-  } catch (e) {
-    print(e);
-    print(parser.usage);
-    exit(1);
-  }
-
-  return results;
-}
-
-/// Sets up the logging level and printing.
-void setupLogger(ArgResults result) {
-  if (result.wasParsed(verbose)) {
-    switch (result[verbose] as String?) {
-      case logAll:
-        // Logs everything, the entire AST touched by our parser.
-        Logger.root.level = Level.ALL;
-        break;
-      case logFine:
-        // Logs AST parts relevant to user (i.e those included in filters).
-        Logger.root.level = Level.FINE;
-        break;
-      case logInfo:
-        // Logs relevant info for general user (default).
-        Logger.root.level = Level.INFO;
-        break;
-      case logWarning:
-        // Logs warnings for relevant stuff.
-        Logger.root.level = Level.WARNING;
-        break;
-      case logSevere:
-        // Logs severe warnings and errors.
-        Logger.root.level = Level.SEVERE;
-        break;
-    }
-    // Setup logger for printing (if verbosity was set by user).
-    Logger.root.onRecord.listen((record) {
-      final level = '[${record.level.name}]'.padRight(9);
-      printLog('$level: ${record.message}', record.level);
-    });
-  } else {
-    // Setup logger for printing (if verbosity was not set by user).
-    Logger.root.onRecord.listen((record) {
-      if (record.level.value > Level.INFO.value) {
-        final level = '[${record.level.name}]'.padRight(9);
-        printLog('$level: ${record.message}', record.level);
-      } else {
-        printLog(record.message, record.level);
-      }
-    });
-  }
-}
-
-void printLog(String log, Level level) {
-  // Prints text in red for Severe logs only.
-  if (level < Level.SEVERE) {
-    print(log);
-  } else {
-    print(errorPen(log));
-  }
-}
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser.dart b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser.dart
deleted file mode 100644
index e4dc2c9..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser.dart
+++ /dev/null
@@ -1,10 +0,0 @@
-// Copyright (c) 2020, 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.
-
-/// Generates a [Library] (code_generator)
-///
-/// Parses the header files AST using clang_bindings.
-library header_parser;
-
-export 'header_parser/parser.dart' show parse;
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/clang_bindings/clang_bindings.dart b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/clang_bindings/clang_bindings.dart
deleted file mode 100644
index 58108aa..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/clang_bindings/clang_bindings.dart
+++ /dev/null
@@ -1,2569 +0,0 @@
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM
-// Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-
-// ignore_for_file: camel_case_types, non_constant_identifier_names
-
-// AUTO GENERATED FILE, DO NOT EDIT.
-//
-// Generated by `package:ffigen`.
-import 'dart:ffi' as ffi;
-
-/// Holds bindings to LibClang.
-class Clang {
-  /// Holds the symbol lookup function.
-  final ffi.Pointer<T> Function<T extends ffi.NativeType>(String symbolName)
-      _lookup;
-
-  /// The symbols are looked up in [dynamicLibrary].
-  Clang(ffi.DynamicLibrary dynamicLibrary) : _lookup = dynamicLibrary.lookup;
-
-  /// The symbols are looked up with [lookup].
-  Clang.fromLookup(
-      ffi.Pointer<T> Function<T extends ffi.NativeType>(String symbolName)
-          lookup)
-      : _lookup = lookup;
-
-  /// Retrieve the character data associated with the given string.
-  ffi.Pointer<ffi.Char> clang_getCString(
-    CXString string,
-  ) {
-    return _clang_getCString(
-      string,
-    );
-  }
-
-  late final _clang_getCStringPtr =
-      _lookup<ffi.NativeFunction<ffi.Pointer<ffi.Char> Function(CXString)>>(
-          'clang_getCString');
-  late final _clang_getCString = _clang_getCStringPtr
-      .asFunction<ffi.Pointer<ffi.Char> Function(CXString)>();
-
-  /// Free the given string.
-  void clang_disposeString(
-    CXString string,
-  ) {
-    return _clang_disposeString(
-      string,
-    );
-  }
-
-  late final _clang_disposeStringPtr =
-      _lookup<ffi.NativeFunction<ffi.Void Function(CXString)>>(
-          'clang_disposeString');
-  late final _clang_disposeString =
-      _clang_disposeStringPtr.asFunction<void Function(CXString)>();
-
-  /// Provides a shared context for creating translation units.
-  ///
-  /// It provides two options:
-  ///
-  /// - excludeDeclarationsFromPCH: When non-zero, allows enumeration of "local"
-  /// declarations (when loading any new translation units). A "local" declaration
-  /// is one that belongs in the translation unit itself and not in a precompiled
-  /// header that was used by the translation unit. If zero, all declarations
-  /// will be enumerated.
-  ///
-  /// Here is an example:
-  ///
-  /// \code
-  /// // excludeDeclsFromPCH = 1, displayDiagnostics=1
-  /// Idx = clang_createIndex(1, 1);
-  ///
-  /// // IndexTest.pch was produced with the following command:
-  /// // "clang -x c IndexTest.h -emit-ast -o IndexTest.pch"
-  /// TU = clang_createTranslationUnit(Idx, "IndexTest.pch");
-  ///
-  /// // This will load all the symbols from 'IndexTest.pch'
-  /// clang_visitChildren(clang_getTranslationUnitCursor(TU),
-  /// TranslationUnitVisitor, 0);
-  /// clang_disposeTranslationUnit(TU);
-  ///
-  /// // This will load all the symbols from 'IndexTest.c', excluding symbols
-  /// // from 'IndexTest.pch'.
-  /// char *args[] = { "-Xclang", "-include-pch=IndexTest.pch" };
-  /// TU = clang_createTranslationUnitFromSourceFile(Idx, "IndexTest.c", 2, args,
-  /// 0, 0);
-  /// clang_visitChildren(clang_getTranslationUnitCursor(TU),
-  /// TranslationUnitVisitor, 0);
-  /// clang_disposeTranslationUnit(TU);
-  /// \endcode
-  ///
-  /// This process of creating the 'pch', loading it separately, and using it (via
-  /// -include-pch) allows 'excludeDeclsFromPCH' to remove redundant callbacks
-  /// (which gives the indexer the same performance benefit as the compiler).
-  CXIndex clang_createIndex(
-    int excludeDeclarationsFromPCH,
-    int displayDiagnostics,
-  ) {
-    return _clang_createIndex(
-      excludeDeclarationsFromPCH,
-      displayDiagnostics,
-    );
-  }
-
-  late final _clang_createIndexPtr =
-      _lookup<ffi.NativeFunction<CXIndex Function(ffi.Int, ffi.Int)>>(
-          'clang_createIndex');
-  late final _clang_createIndex =
-      _clang_createIndexPtr.asFunction<CXIndex Function(int, int)>();
-
-  /// Destroy the given index.
-  ///
-  /// The index must not be destroyed until all of the translation units created
-  /// within that index have been destroyed.
-  void clang_disposeIndex(
-    CXIndex index,
-  ) {
-    return _clang_disposeIndex(
-      index,
-    );
-  }
-
-  late final _clang_disposeIndexPtr =
-      _lookup<ffi.NativeFunction<ffi.Void Function(CXIndex)>>(
-          'clang_disposeIndex');
-  late final _clang_disposeIndex =
-      _clang_disposeIndexPtr.asFunction<void Function(CXIndex)>();
-
-  /// Retrieve the complete file and path name of the given file.
-  CXString clang_getFileName(
-    CXFile SFile,
-  ) {
-    return _clang_getFileName(
-      SFile,
-    );
-  }
-
-  late final _clang_getFileNamePtr =
-      _lookup<ffi.NativeFunction<CXString Function(CXFile)>>(
-          'clang_getFileName');
-  late final _clang_getFileName =
-      _clang_getFileNamePtr.asFunction<CXString Function(CXFile)>();
-
-  /// Returns non-zero if the given source location is in a system header.
-  int clang_Location_isInSystemHeader(
-    CXSourceLocation location,
-  ) {
-    return _clang_Location_isInSystemHeader(
-      location,
-    );
-  }
-
-  late final _clang_Location_isInSystemHeaderPtr =
-      _lookup<ffi.NativeFunction<ffi.Int Function(CXSourceLocation)>>(
-          'clang_Location_isInSystemHeader');
-  late final _clang_Location_isInSystemHeader =
-      _clang_Location_isInSystemHeaderPtr
-          .asFunction<int Function(CXSourceLocation)>();
-
-  /// Determine whether two ranges are equivalent.
-  ///
-  /// \returns non-zero if the ranges are the same, zero if they differ.
-  int clang_equalRanges(
-    CXSourceRange range1,
-    CXSourceRange range2,
-  ) {
-    return _clang_equalRanges(
-      range1,
-      range2,
-    );
-  }
-
-  late final _clang_equalRangesPtr = _lookup<
-      ffi.NativeFunction<
-          ffi.UnsignedInt Function(
-              CXSourceRange, CXSourceRange)>>('clang_equalRanges');
-  late final _clang_equalRanges = _clang_equalRangesPtr
-      .asFunction<int Function(CXSourceRange, CXSourceRange)>();
-
-  /// Retrieve the file, line, column, and offset represented by
-  /// the given source location.
-  ///
-  /// If the location refers into a macro expansion, return where the macro was
-  /// expanded or where the macro argument was written, if the location points at
-  /// a macro argument.
-  ///
-  /// \param location the location within a source file that will be decomposed
-  /// into its parts.
-  ///
-  /// \param file [out] if non-NULL, will be set to the file to which the given
-  /// source location points.
-  ///
-  /// \param line [out] if non-NULL, will be set to the line to which the given
-  /// source location points.
-  ///
-  /// \param column [out] if non-NULL, will be set to the column to which the given
-  /// source location points.
-  ///
-  /// \param offset [out] if non-NULL, will be set to the offset into the
-  /// buffer to which the given source location points.
-  void clang_getFileLocation(
-    CXSourceLocation location,
-    ffi.Pointer<CXFile> file,
-    ffi.Pointer<ffi.UnsignedInt> line,
-    ffi.Pointer<ffi.UnsignedInt> column,
-    ffi.Pointer<ffi.UnsignedInt> offset,
-  ) {
-    return _clang_getFileLocation(
-      location,
-      file,
-      line,
-      column,
-      offset,
-    );
-  }
-
-  late final _clang_getFileLocationPtr = _lookup<
-      ffi.NativeFunction<
-          ffi.Void Function(
-              CXSourceLocation,
-              ffi.Pointer<CXFile>,
-              ffi.Pointer<ffi.UnsignedInt>,
-              ffi.Pointer<ffi.UnsignedInt>,
-              ffi.Pointer<ffi.UnsignedInt>)>>('clang_getFileLocation');
-  late final _clang_getFileLocation = _clang_getFileLocationPtr.asFunction<
-      void Function(
-          CXSourceLocation,
-          ffi.Pointer<CXFile>,
-          ffi.Pointer<ffi.UnsignedInt>,
-          ffi.Pointer<ffi.UnsignedInt>,
-          ffi.Pointer<ffi.UnsignedInt>)>();
-
-  /// Determine the number of diagnostics produced for the given
-  /// translation unit.
-  int clang_getNumDiagnostics(
-    CXTranslationUnit Unit,
-  ) {
-    return _clang_getNumDiagnostics(
-      Unit,
-    );
-  }
-
-  late final _clang_getNumDiagnosticsPtr =
-      _lookup<ffi.NativeFunction<ffi.UnsignedInt Function(CXTranslationUnit)>>(
-          'clang_getNumDiagnostics');
-  late final _clang_getNumDiagnostics =
-      _clang_getNumDiagnosticsPtr.asFunction<int Function(CXTranslationUnit)>();
-
-  /// Retrieve a diagnostic associated with the given translation unit.
-  ///
-  /// \param Unit the translation unit to query.
-  /// \param Index the zero-based diagnostic number to retrieve.
-  ///
-  /// \returns the requested diagnostic. This diagnostic must be freed
-  /// via a call to \c clang_disposeDiagnostic().
-  CXDiagnostic clang_getDiagnostic(
-    CXTranslationUnit Unit,
-    int Index,
-  ) {
-    return _clang_getDiagnostic(
-      Unit,
-      Index,
-    );
-  }
-
-  late final _clang_getDiagnosticPtr = _lookup<
-      ffi.NativeFunction<
-          CXDiagnostic Function(
-              CXTranslationUnit, ffi.UnsignedInt)>>('clang_getDiagnostic');
-  late final _clang_getDiagnostic = _clang_getDiagnosticPtr
-      .asFunction<CXDiagnostic Function(CXTranslationUnit, int)>();
-
-  /// Destroy a diagnostic.
-  void clang_disposeDiagnostic(
-    CXDiagnostic Diagnostic,
-  ) {
-    return _clang_disposeDiagnostic(
-      Diagnostic,
-    );
-  }
-
-  late final _clang_disposeDiagnosticPtr =
-      _lookup<ffi.NativeFunction<ffi.Void Function(CXDiagnostic)>>(
-          'clang_disposeDiagnostic');
-  late final _clang_disposeDiagnostic =
-      _clang_disposeDiagnosticPtr.asFunction<void Function(CXDiagnostic)>();
-
-  /// Format the given diagnostic in a manner that is suitable for display.
-  ///
-  /// This routine will format the given diagnostic to a string, rendering
-  /// the diagnostic according to the various options given. The
-  /// \c clang_defaultDiagnosticDisplayOptions() function returns the set of
-  /// options that most closely mimics the behavior of the clang compiler.
-  ///
-  /// \param Diagnostic The diagnostic to print.
-  ///
-  /// \param Options A set of options that control the diagnostic display,
-  /// created by combining \c CXDiagnosticDisplayOptions values.
-  ///
-  /// \returns A new string containing for formatted diagnostic.
-  CXString clang_formatDiagnostic(
-    CXDiagnostic Diagnostic,
-    int Options,
-  ) {
-    return _clang_formatDiagnostic(
-      Diagnostic,
-      Options,
-    );
-  }
-
-  late final _clang_formatDiagnosticPtr = _lookup<
-          ffi.NativeFunction<CXString Function(CXDiagnostic, ffi.UnsignedInt)>>(
-      'clang_formatDiagnostic');
-  late final _clang_formatDiagnostic = _clang_formatDiagnosticPtr
-      .asFunction<CXString Function(CXDiagnostic, int)>();
-
-  /// Same as \c clang_parseTranslationUnit2, but returns
-  /// the \c CXTranslationUnit instead of an error code.  In case of an error this
-  /// routine returns a \c NULL \c CXTranslationUnit, without further detailed
-  /// error codes.
-  CXTranslationUnit clang_parseTranslationUnit(
-    CXIndex CIdx,
-    ffi.Pointer<ffi.Char> source_filename,
-    ffi.Pointer<ffi.Pointer<ffi.Char>> command_line_args,
-    int num_command_line_args,
-    ffi.Pointer<CXUnsavedFile> unsaved_files,
-    int num_unsaved_files,
-    int options,
-  ) {
-    return _clang_parseTranslationUnit(
-      CIdx,
-      source_filename,
-      command_line_args,
-      num_command_line_args,
-      unsaved_files,
-      num_unsaved_files,
-      options,
-    );
-  }
-
-  late final _clang_parseTranslationUnitPtr = _lookup<
-      ffi.NativeFunction<
-          CXTranslationUnit Function(
-              CXIndex,
-              ffi.Pointer<ffi.Char>,
-              ffi.Pointer<ffi.Pointer<ffi.Char>>,
-              ffi.Int,
-              ffi.Pointer<CXUnsavedFile>,
-              ffi.UnsignedInt,
-              ffi.UnsignedInt)>>('clang_parseTranslationUnit');
-  late final _clang_parseTranslationUnit =
-      _clang_parseTranslationUnitPtr.asFunction<
-          CXTranslationUnit Function(
-              CXIndex,
-              ffi.Pointer<ffi.Char>,
-              ffi.Pointer<ffi.Pointer<ffi.Char>>,
-              int,
-              ffi.Pointer<CXUnsavedFile>,
-              int,
-              int)>();
-
-  /// Destroy the specified CXTranslationUnit object.
-  void clang_disposeTranslationUnit(
-    CXTranslationUnit arg0,
-  ) {
-    return _clang_disposeTranslationUnit(
-      arg0,
-    );
-  }
-
-  late final _clang_disposeTranslationUnitPtr =
-      _lookup<ffi.NativeFunction<ffi.Void Function(CXTranslationUnit)>>(
-          'clang_disposeTranslationUnit');
-  late final _clang_disposeTranslationUnit = _clang_disposeTranslationUnitPtr
-      .asFunction<void Function(CXTranslationUnit)>();
-
-  /// Retrieve the cursor that represents the given translation unit.
-  ///
-  /// The translation unit cursor can be used to start traversing the
-  /// various declarations within the given translation unit.
-  CXCursor clang_getTranslationUnitCursor(
-    CXTranslationUnit arg0,
-  ) {
-    return _clang_getTranslationUnitCursor(
-      arg0,
-    );
-  }
-
-  late final _clang_getTranslationUnitCursorPtr =
-      _lookup<ffi.NativeFunction<CXCursor Function(CXTranslationUnit)>>(
-          'clang_getTranslationUnitCursor');
-  late final _clang_getTranslationUnitCursor =
-      _clang_getTranslationUnitCursorPtr
-          .asFunction<CXCursor Function(CXTranslationUnit)>();
-
-  /// Returns non-zero if \p cursor is null.
-  int clang_Cursor_isNull(
-    CXCursor cursor,
-  ) {
-    return _clang_Cursor_isNull(
-      cursor,
-    );
-  }
-
-  late final _clang_Cursor_isNullPtr =
-      _lookup<ffi.NativeFunction<ffi.Int Function(CXCursor)>>(
-          'clang_Cursor_isNull');
-  late final _clang_Cursor_isNull =
-      _clang_Cursor_isNullPtr.asFunction<int Function(CXCursor)>();
-
-  /// Retrieve the kind of the given cursor.
-  int clang_getCursorKind(
-    CXCursor arg0,
-  ) {
-    return _clang_getCursorKind(
-      arg0,
-    );
-  }
-
-  late final _clang_getCursorKindPtr =
-      _lookup<ffi.NativeFunction<ffi.Int32 Function(CXCursor)>>(
-          'clang_getCursorKind');
-  late final _clang_getCursorKind =
-      _clang_getCursorKindPtr.asFunction<int Function(CXCursor)>();
-
-  /// Determine whether the given cursor has any attributes.
-  int clang_Cursor_hasAttrs(
-    CXCursor C,
-  ) {
-    return _clang_Cursor_hasAttrs(
-      C,
-    );
-  }
-
-  late final _clang_Cursor_hasAttrsPtr =
-      _lookup<ffi.NativeFunction<ffi.UnsignedInt Function(CXCursor)>>(
-          'clang_Cursor_hasAttrs');
-  late final _clang_Cursor_hasAttrs =
-      _clang_Cursor_hasAttrsPtr.asFunction<int Function(CXCursor)>();
-
-  /// Retrieve the physical location of the source constructor referenced
-  /// by the given cursor.
-  ///
-  /// The location of a declaration is typically the location of the name of that
-  /// declaration, where the name of that declaration would occur if it is
-  /// unnamed, or some keyword that introduces that particular declaration.
-  /// The location of a reference is where that reference occurs within the
-  /// source code.
-  CXSourceLocation clang_getCursorLocation(
-    CXCursor arg0,
-  ) {
-    return _clang_getCursorLocation(
-      arg0,
-    );
-  }
-
-  late final _clang_getCursorLocationPtr =
-      _lookup<ffi.NativeFunction<CXSourceLocation Function(CXCursor)>>(
-          'clang_getCursorLocation');
-  late final _clang_getCursorLocation = _clang_getCursorLocationPtr
-      .asFunction<CXSourceLocation Function(CXCursor)>();
-
-  /// Retrieve the type of a CXCursor (if any).
-  CXType clang_getCursorType(
-    CXCursor C,
-  ) {
-    return _clang_getCursorType(
-      C,
-    );
-  }
-
-  late final _clang_getCursorTypePtr =
-      _lookup<ffi.NativeFunction<CXType Function(CXCursor)>>(
-          'clang_getCursorType');
-  late final _clang_getCursorType =
-      _clang_getCursorTypePtr.asFunction<CXType Function(CXCursor)>();
-
-  /// Pretty-print the underlying type using the rules of the
-  /// language of the translation unit from which it came.
-  ///
-  /// If the type is invalid, an empty string is returned.
-  CXString clang_getTypeSpelling(
-    CXType CT,
-  ) {
-    return _clang_getTypeSpelling(
-      CT,
-    );
-  }
-
-  late final _clang_getTypeSpellingPtr =
-      _lookup<ffi.NativeFunction<CXString Function(CXType)>>(
-          'clang_getTypeSpelling');
-  late final _clang_getTypeSpelling =
-      _clang_getTypeSpellingPtr.asFunction<CXString Function(CXType)>();
-
-  /// Retrieve the underlying type of a typedef declaration.
-  ///
-  /// If the cursor does not reference a typedef declaration, an invalid type is
-  /// returned.
-  CXType clang_getTypedefDeclUnderlyingType(
-    CXCursor C,
-  ) {
-    return _clang_getTypedefDeclUnderlyingType(
-      C,
-    );
-  }
-
-  late final _clang_getTypedefDeclUnderlyingTypePtr =
-      _lookup<ffi.NativeFunction<CXType Function(CXCursor)>>(
-          'clang_getTypedefDeclUnderlyingType');
-  late final _clang_getTypedefDeclUnderlyingType =
-      _clang_getTypedefDeclUnderlyingTypePtr
-          .asFunction<CXType Function(CXCursor)>();
-
-  /// Retrieve the integer value of an enum constant declaration as a signed
-  /// long long.
-  ///
-  /// If the cursor does not reference an enum constant declaration, LLONG_MIN is returned.
-  /// Since this is also potentially a valid constant value, the kind of the cursor
-  /// must be verified before calling this function.
-  int clang_getEnumConstantDeclValue(
-    CXCursor C,
-  ) {
-    return _clang_getEnumConstantDeclValue(
-      C,
-    );
-  }
-
-  late final _clang_getEnumConstantDeclValuePtr =
-      _lookup<ffi.NativeFunction<ffi.LongLong Function(CXCursor)>>(
-          'clang_getEnumConstantDeclValue');
-  late final _clang_getEnumConstantDeclValue =
-      _clang_getEnumConstantDeclValuePtr.asFunction<int Function(CXCursor)>();
-
-  /// Retrieve the bit width of a bit field declaration as an integer.
-  ///
-  /// If a cursor that is not a bit field declaration is passed in, -1 is returned.
-  int clang_getFieldDeclBitWidth(
-    CXCursor C,
-  ) {
-    return _clang_getFieldDeclBitWidth(
-      C,
-    );
-  }
-
-  late final _clang_getFieldDeclBitWidthPtr =
-      _lookup<ffi.NativeFunction<ffi.Int Function(CXCursor)>>(
-          'clang_getFieldDeclBitWidth');
-  late final _clang_getFieldDeclBitWidth =
-      _clang_getFieldDeclBitWidthPtr.asFunction<int Function(CXCursor)>();
-
-  /// Retrieve the number of non-variadic arguments associated with a given
-  /// cursor.
-  ///
-  /// The number of arguments can be determined for calls as well as for
-  /// declarations of functions or methods. For other cursors -1 is returned.
-  int clang_Cursor_getNumArguments(
-    CXCursor C,
-  ) {
-    return _clang_Cursor_getNumArguments(
-      C,
-    );
-  }
-
-  late final _clang_Cursor_getNumArgumentsPtr =
-      _lookup<ffi.NativeFunction<ffi.Int Function(CXCursor)>>(
-          'clang_Cursor_getNumArguments');
-  late final _clang_Cursor_getNumArguments =
-      _clang_Cursor_getNumArgumentsPtr.asFunction<int Function(CXCursor)>();
-
-  /// Retrieve the argument cursor of a function or method.
-  ///
-  /// The argument cursor can be determined for calls as well as for declarations
-  /// of functions or methods. For other cursors and for invalid indices, an
-  /// invalid cursor is returned.
-  CXCursor clang_Cursor_getArgument(
-    CXCursor C,
-    int i,
-  ) {
-    return _clang_Cursor_getArgument(
-      C,
-      i,
-    );
-  }
-
-  late final _clang_Cursor_getArgumentPtr =
-      _lookup<ffi.NativeFunction<CXCursor Function(CXCursor, ffi.UnsignedInt)>>(
-          'clang_Cursor_getArgument');
-  late final _clang_Cursor_getArgument = _clang_Cursor_getArgumentPtr
-      .asFunction<CXCursor Function(CXCursor, int)>();
-
-  /// Return the canonical type for a CXType.
-  ///
-  /// Clang's type system explicitly models typedefs and all the ways
-  /// a specific type can be represented.  The canonical type is the underlying
-  /// type with all the "sugar" removed.  For example, if 'T' is a typedef
-  /// for 'int', the canonical type for 'T' would be 'int'.
-  CXType clang_getCanonicalType(
-    CXType T,
-  ) {
-    return _clang_getCanonicalType(
-      T,
-    );
-  }
-
-  late final _clang_getCanonicalTypePtr =
-      _lookup<ffi.NativeFunction<CXType Function(CXType)>>(
-          'clang_getCanonicalType');
-  late final _clang_getCanonicalType =
-      _clang_getCanonicalTypePtr.asFunction<CXType Function(CXType)>();
-
-  /// Determine whether a  CXCursor that is a macro, is
-  /// function like.
-  int clang_Cursor_isMacroFunctionLike(
-    CXCursor C,
-  ) {
-    return _clang_Cursor_isMacroFunctionLike(
-      C,
-    );
-  }
-
-  late final _clang_Cursor_isMacroFunctionLikePtr =
-      _lookup<ffi.NativeFunction<ffi.UnsignedInt Function(CXCursor)>>(
-          'clang_Cursor_isMacroFunctionLike');
-  late final _clang_Cursor_isMacroFunctionLike =
-      _clang_Cursor_isMacroFunctionLikePtr.asFunction<int Function(CXCursor)>();
-
-  /// Determine whether a  CXCursor that is a macro, is a
-  /// builtin one.
-  int clang_Cursor_isMacroBuiltin(
-    CXCursor C,
-  ) {
-    return _clang_Cursor_isMacroBuiltin(
-      C,
-    );
-  }
-
-  late final _clang_Cursor_isMacroBuiltinPtr =
-      _lookup<ffi.NativeFunction<ffi.UnsignedInt Function(CXCursor)>>(
-          'clang_Cursor_isMacroBuiltin');
-  late final _clang_Cursor_isMacroBuiltin =
-      _clang_Cursor_isMacroBuiltinPtr.asFunction<int Function(CXCursor)>();
-
-  /// Determine whether a  CXCursor that is a function declaration, is an
-  /// inline declaration.
-  int clang_Cursor_isFunctionInlined(
-    CXCursor C,
-  ) {
-    return _clang_Cursor_isFunctionInlined(
-      C,
-    );
-  }
-
-  late final _clang_Cursor_isFunctionInlinedPtr =
-      _lookup<ffi.NativeFunction<ffi.UnsignedInt Function(CXCursor)>>(
-          'clang_Cursor_isFunctionInlined');
-  late final _clang_Cursor_isFunctionInlined =
-      _clang_Cursor_isFunctionInlinedPtr.asFunction<int Function(CXCursor)>();
-
-  /// Returns the typedef name of the given type.
-  CXString clang_getTypedefName(
-    CXType CT,
-  ) {
-    return _clang_getTypedefName(
-      CT,
-    );
-  }
-
-  late final _clang_getTypedefNamePtr =
-      _lookup<ffi.NativeFunction<CXString Function(CXType)>>(
-          'clang_getTypedefName');
-  late final _clang_getTypedefName =
-      _clang_getTypedefNamePtr.asFunction<CXString Function(CXType)>();
-
-  /// For pointer types, returns the type of the pointee.
-  CXType clang_getPointeeType(
-    CXType T,
-  ) {
-    return _clang_getPointeeType(
-      T,
-    );
-  }
-
-  late final _clang_getPointeeTypePtr =
-      _lookup<ffi.NativeFunction<CXType Function(CXType)>>(
-          'clang_getPointeeType');
-  late final _clang_getPointeeType =
-      _clang_getPointeeTypePtr.asFunction<CXType Function(CXType)>();
-
-  /// Return the cursor for the declaration of the given type.
-  CXCursor clang_getTypeDeclaration(
-    CXType T,
-  ) {
-    return _clang_getTypeDeclaration(
-      T,
-    );
-  }
-
-  late final _clang_getTypeDeclarationPtr =
-      _lookup<ffi.NativeFunction<CXCursor Function(CXType)>>(
-          'clang_getTypeDeclaration');
-  late final _clang_getTypeDeclaration =
-      _clang_getTypeDeclarationPtr.asFunction<CXCursor Function(CXType)>();
-
-  /// Retrieve the spelling of a given CXTypeKind.
-  CXString clang_getTypeKindSpelling(
-    int K,
-  ) {
-    return _clang_getTypeKindSpelling(
-      K,
-    );
-  }
-
-  late final _clang_getTypeKindSpellingPtr =
-      _lookup<ffi.NativeFunction<CXString Function(ffi.Int32)>>(
-          'clang_getTypeKindSpelling');
-  late final _clang_getTypeKindSpelling =
-      _clang_getTypeKindSpellingPtr.asFunction<CXString Function(int)>();
-
-  /// Retrieve the return type associated with a function type.
-  ///
-  /// If a non-function type is passed in, an invalid type is returned.
-  CXType clang_getResultType(
-    CXType T,
-  ) {
-    return _clang_getResultType(
-      T,
-    );
-  }
-
-  late final _clang_getResultTypePtr =
-      _lookup<ffi.NativeFunction<CXType Function(CXType)>>(
-          'clang_getResultType');
-  late final _clang_getResultType =
-      _clang_getResultTypePtr.asFunction<CXType Function(CXType)>();
-
-  /// Retrieve the number of non-variadic parameters associated with a
-  /// function type.
-  ///
-  /// If a non-function type is passed in, -1 is returned.
-  int clang_getNumArgTypes(
-    CXType T,
-  ) {
-    return _clang_getNumArgTypes(
-      T,
-    );
-  }
-
-  late final _clang_getNumArgTypesPtr =
-      _lookup<ffi.NativeFunction<ffi.Int Function(CXType)>>(
-          'clang_getNumArgTypes');
-  late final _clang_getNumArgTypes =
-      _clang_getNumArgTypesPtr.asFunction<int Function(CXType)>();
-
-  /// Retrieve the type of a parameter of a function type.
-  ///
-  /// If a non-function type is passed in or the function does not have enough
-  /// parameters, an invalid type is returned.
-  CXType clang_getArgType(
-    CXType T,
-    int i,
-  ) {
-    return _clang_getArgType(
-      T,
-      i,
-    );
-  }
-
-  late final _clang_getArgTypePtr =
-      _lookup<ffi.NativeFunction<CXType Function(CXType, ffi.UnsignedInt)>>(
-          'clang_getArgType');
-  late final _clang_getArgType =
-      _clang_getArgTypePtr.asFunction<CXType Function(CXType, int)>();
-
-  /// Retrieves the base type of the ObjCObjectType.
-  ///
-  /// If the type is not an ObjC object, an invalid type is returned.
-  CXType clang_Type_getObjCObjectBaseType(
-    CXType T,
-  ) {
-    return _clang_Type_getObjCObjectBaseType(
-      T,
-    );
-  }
-
-  late final _clang_Type_getObjCObjectBaseTypePtr =
-      _lookup<ffi.NativeFunction<CXType Function(CXType)>>(
-          'clang_Type_getObjCObjectBaseType');
-  late final _clang_Type_getObjCObjectBaseType =
-      _clang_Type_getObjCObjectBaseTypePtr
-          .asFunction<CXType Function(CXType)>();
-
-  /// Return the number of elements of an array or vector type.
-  ///
-  /// If a type is passed in that is not an array or vector type,
-  /// -1 is returned.
-  int clang_getNumElements(
-    CXType T,
-  ) {
-    return _clang_getNumElements(
-      T,
-    );
-  }
-
-  late final _clang_getNumElementsPtr =
-      _lookup<ffi.NativeFunction<ffi.LongLong Function(CXType)>>(
-          'clang_getNumElements');
-  late final _clang_getNumElements =
-      _clang_getNumElementsPtr.asFunction<int Function(CXType)>();
-
-  /// Return the element type of an array type.
-  ///
-  /// If a non-array type is passed in, an invalid type is returned.
-  CXType clang_getArrayElementType(
-    CXType T,
-  ) {
-    return _clang_getArrayElementType(
-      T,
-    );
-  }
-
-  late final _clang_getArrayElementTypePtr =
-      _lookup<ffi.NativeFunction<CXType Function(CXType)>>(
-          'clang_getArrayElementType');
-  late final _clang_getArrayElementType =
-      _clang_getArrayElementTypePtr.asFunction<CXType Function(CXType)>();
-
-  /// Retrieve the type named by the qualified-id.
-  ///
-  /// If a non-elaborated type is passed in, an invalid type is returned.
-  CXType clang_Type_getNamedType(
-    CXType T,
-  ) {
-    return _clang_Type_getNamedType(
-      T,
-    );
-  }
-
-  late final _clang_Type_getNamedTypePtr =
-      _lookup<ffi.NativeFunction<CXType Function(CXType)>>(
-          'clang_Type_getNamedType');
-  late final _clang_Type_getNamedType =
-      _clang_Type_getNamedTypePtr.asFunction<CXType Function(CXType)>();
-
-  /// Retrieve the nullability kind of a pointer type.
-  int clang_Type_getNullability(
-    CXType T,
-  ) {
-    return _clang_Type_getNullability(
-      T,
-    );
-  }
-
-  late final _clang_Type_getNullabilityPtr =
-      _lookup<ffi.NativeFunction<ffi.Int32 Function(CXType)>>(
-          'clang_Type_getNullability');
-  late final _clang_Type_getNullability =
-      _clang_Type_getNullabilityPtr.asFunction<int Function(CXType)>();
-
-  /// Return the alignment of a type in bytes as per C++[expr.alignof]
-  /// standard.
-  ///
-  /// If the type declaration is invalid, CXTypeLayoutError_Invalid is returned.
-  /// If the type declaration is an incomplete type, CXTypeLayoutError_Incomplete
-  /// is returned.
-  /// If the type declaration is a dependent type, CXTypeLayoutError_Dependent is
-  /// returned.
-  /// If the type declaration is not a constant size type,
-  /// CXTypeLayoutError_NotConstantSize is returned.
-  int clang_Type_getAlignOf(
-    CXType T,
-  ) {
-    return _clang_Type_getAlignOf(
-      T,
-    );
-  }
-
-  late final _clang_Type_getAlignOfPtr =
-      _lookup<ffi.NativeFunction<ffi.LongLong Function(CXType)>>(
-          'clang_Type_getAlignOf');
-  late final _clang_Type_getAlignOf =
-      _clang_Type_getAlignOfPtr.asFunction<int Function(CXType)>();
-
-  /// Determine whether the given cursor represents an anonymous
-  /// tag or namespace
-  int clang_Cursor_isAnonymous(
-    CXCursor C,
-  ) {
-    return _clang_Cursor_isAnonymous(
-      C,
-    );
-  }
-
-  late final _clang_Cursor_isAnonymousPtr =
-      _lookup<ffi.NativeFunction<ffi.UnsignedInt Function(CXCursor)>>(
-          'clang_Cursor_isAnonymous');
-  late final _clang_Cursor_isAnonymous =
-      _clang_Cursor_isAnonymousPtr.asFunction<int Function(CXCursor)>();
-
-  /// Determine whether the given cursor represents an anonymous record
-  /// declaration.
-  int clang_Cursor_isAnonymousRecordDecl(
-    CXCursor C,
-  ) {
-    return _clang_Cursor_isAnonymousRecordDecl(
-      C,
-    );
-  }
-
-  late final _clang_Cursor_isAnonymousRecordDeclPtr =
-      _lookup<ffi.NativeFunction<ffi.UnsignedInt Function(CXCursor)>>(
-          'clang_Cursor_isAnonymousRecordDecl');
-  late final _clang_Cursor_isAnonymousRecordDecl =
-      _clang_Cursor_isAnonymousRecordDeclPtr
-          .asFunction<int Function(CXCursor)>();
-
-  /// Visit the children of a particular cursor.
-  ///
-  /// This function visits all the direct children of the given cursor,
-  /// invoking the given \p visitor function with the cursors of each
-  /// visited child. The traversal may be recursive, if the visitor returns
-  /// \c CXChildVisit_Recurse. The traversal may also be ended prematurely, if
-  /// the visitor returns \c CXChildVisit_Break.
-  ///
-  /// \param parent the cursor whose child may be visited. All kinds of
-  /// cursors can be visited, including invalid cursors (which, by
-  /// definition, have no children).
-  ///
-  /// \param visitor the visitor function that will be invoked for each
-  /// child of \p parent.
-  ///
-  /// \param client_data pointer data supplied by the client, which will
-  /// be passed to the visitor each time it is invoked.
-  ///
-  /// \returns a non-zero value if the traversal was terminated
-  /// prematurely by the visitor returning \c CXChildVisit_Break.
-  int clang_visitChildren(
-    CXCursor parent,
-    CXCursorVisitor visitor,
-    CXClientData client_data,
-  ) {
-    return _clang_visitChildren(
-      parent,
-      visitor,
-      client_data,
-    );
-  }
-
-  late final _clang_visitChildrenPtr = _lookup<
-      ffi.NativeFunction<
-          ffi.UnsignedInt Function(
-              CXCursor, CXCursorVisitor, CXClientData)>>('clang_visitChildren');
-  late final _clang_visitChildren = _clang_visitChildrenPtr
-      .asFunction<int Function(CXCursor, CXCursorVisitor, CXClientData)>();
-
-  /// Retrieve a Unified Symbol Resolution (USR) for the entity referenced
-  /// by the given cursor.
-  ///
-  /// A Unified Symbol Resolution (USR) is a string that identifies a particular
-  /// entity (function, class, variable, etc.) within a program. USRs can be
-  /// compared across translation units to determine, e.g., when references in
-  /// one translation refer to an entity defined in another translation unit.
-  CXString clang_getCursorUSR(
-    CXCursor arg0,
-  ) {
-    return _clang_getCursorUSR(
-      arg0,
-    );
-  }
-
-  late final _clang_getCursorUSRPtr =
-      _lookup<ffi.NativeFunction<CXString Function(CXCursor)>>(
-          'clang_getCursorUSR');
-  late final _clang_getCursorUSR =
-      _clang_getCursorUSRPtr.asFunction<CXString Function(CXCursor)>();
-
-  /// Retrieve a name for the entity referenced by this cursor.
-  CXString clang_getCursorSpelling(
-    CXCursor arg0,
-  ) {
-    return _clang_getCursorSpelling(
-      arg0,
-    );
-  }
-
-  late final _clang_getCursorSpellingPtr =
-      _lookup<ffi.NativeFunction<CXString Function(CXCursor)>>(
-          'clang_getCursorSpelling');
-  late final _clang_getCursorSpelling =
-      _clang_getCursorSpellingPtr.asFunction<CXString Function(CXCursor)>();
-
-  /// For a cursor that is either a reference to or a declaration
-  /// of some entity, retrieve a cursor that describes the definition of
-  /// that entity.
-  ///
-  /// Some entities can be declared multiple times within a translation
-  /// unit, but only one of those declarations can also be a
-  /// definition. For example, given:
-  ///
-  /// \code
-  /// int f(int, int);
-  /// int g(int x, int y) { return f(x, y); }
-  /// int f(int a, int b) { return a + b; }
-  /// int f(int, int);
-  /// \endcode
-  ///
-  /// there are three declarations of the function "f", but only the
-  /// second one is a definition. The clang_getCursorDefinition()
-  /// function will take any cursor pointing to a declaration of "f"
-  /// (the first or fourth lines of the example) or a cursor referenced
-  /// that uses "f" (the call to "f' inside "g") and will return a
-  /// declaration cursor pointing to the definition (the second "f"
-  /// declaration).
-  ///
-  /// If given a cursor for which there is no corresponding definition,
-  /// e.g., because there is no definition of that entity within this
-  /// translation unit, returns a NULL cursor.
-  CXCursor clang_getCursorDefinition(
-    CXCursor arg0,
-  ) {
-    return _clang_getCursorDefinition(
-      arg0,
-    );
-  }
-
-  late final _clang_getCursorDefinitionPtr =
-      _lookup<ffi.NativeFunction<CXCursor Function(CXCursor)>>(
-          'clang_getCursorDefinition');
-  late final _clang_getCursorDefinition =
-      _clang_getCursorDefinitionPtr.asFunction<CXCursor Function(CXCursor)>();
-
-  /// Given a cursor that represents a property declaration, return the
-  /// associated property attributes. The bits are formed from
-  /// \c CXObjCPropertyAttrKind.
-  ///
-  /// \param reserved Reserved for future use, pass 0.
-  int clang_Cursor_getObjCPropertyAttributes(
-    CXCursor C,
-    int reserved,
-  ) {
-    return _clang_Cursor_getObjCPropertyAttributes(
-      C,
-      reserved,
-    );
-  }
-
-  late final _clang_Cursor_getObjCPropertyAttributesPtr = _lookup<
-      ffi.NativeFunction<
-          ffi.UnsignedInt Function(CXCursor,
-              ffi.UnsignedInt)>>('clang_Cursor_getObjCPropertyAttributes');
-  late final _clang_Cursor_getObjCPropertyAttributes =
-      _clang_Cursor_getObjCPropertyAttributesPtr
-          .asFunction<int Function(CXCursor, int)>();
-
-  /// Given a cursor that represents a property declaration, return the
-  /// name of the method that implements the getter.
-  CXString clang_Cursor_getObjCPropertyGetterName(
-    CXCursor C,
-  ) {
-    return _clang_Cursor_getObjCPropertyGetterName(
-      C,
-    );
-  }
-
-  late final _clang_Cursor_getObjCPropertyGetterNamePtr =
-      _lookup<ffi.NativeFunction<CXString Function(CXCursor)>>(
-          'clang_Cursor_getObjCPropertyGetterName');
-  late final _clang_Cursor_getObjCPropertyGetterName =
-      _clang_Cursor_getObjCPropertyGetterNamePtr
-          .asFunction<CXString Function(CXCursor)>();
-
-  /// Given a cursor that represents a property declaration, return the
-  /// name of the method that implements the setter, if any.
-  CXString clang_Cursor_getObjCPropertySetterName(
-    CXCursor C,
-  ) {
-    return _clang_Cursor_getObjCPropertySetterName(
-      C,
-    );
-  }
-
-  late final _clang_Cursor_getObjCPropertySetterNamePtr =
-      _lookup<ffi.NativeFunction<CXString Function(CXCursor)>>(
-          'clang_Cursor_getObjCPropertySetterName');
-  late final _clang_Cursor_getObjCPropertySetterName =
-      _clang_Cursor_getObjCPropertySetterNamePtr
-          .asFunction<CXString Function(CXCursor)>();
-
-  /// Given a cursor that represents a declaration, return the associated
-  /// comment's source range.  The range may include multiple consecutive comments
-  /// with whitespace in between.
-  CXSourceRange clang_Cursor_getCommentRange(
-    CXCursor C,
-  ) {
-    return _clang_Cursor_getCommentRange(
-      C,
-    );
-  }
-
-  late final _clang_Cursor_getCommentRangePtr =
-      _lookup<ffi.NativeFunction<CXSourceRange Function(CXCursor)>>(
-          'clang_Cursor_getCommentRange');
-  late final _clang_Cursor_getCommentRange = _clang_Cursor_getCommentRangePtr
-      .asFunction<CXSourceRange Function(CXCursor)>();
-
-  /// Given a cursor that represents a declaration, return the associated
-  /// comment text, including comment markers.
-  CXString clang_Cursor_getRawCommentText(
-    CXCursor C,
-  ) {
-    return _clang_Cursor_getRawCommentText(
-      C,
-    );
-  }
-
-  late final _clang_Cursor_getRawCommentTextPtr =
-      _lookup<ffi.NativeFunction<CXString Function(CXCursor)>>(
-          'clang_Cursor_getRawCommentText');
-  late final _clang_Cursor_getRawCommentText =
-      _clang_Cursor_getRawCommentTextPtr
-          .asFunction<CXString Function(CXCursor)>();
-
-  /// Given a cursor that represents a documentable entity (e.g.,
-  /// declaration), return the associated \paragraph; otherwise return the
-  /// first paragraph.
-  CXString clang_Cursor_getBriefCommentText(
-    CXCursor C,
-  ) {
-    return _clang_Cursor_getBriefCommentText(
-      C,
-    );
-  }
-
-  late final _clang_Cursor_getBriefCommentTextPtr =
-      _lookup<ffi.NativeFunction<CXString Function(CXCursor)>>(
-          'clang_Cursor_getBriefCommentText');
-  late final _clang_Cursor_getBriefCommentText =
-      _clang_Cursor_getBriefCommentTextPtr
-          .asFunction<CXString Function(CXCursor)>();
-
-  /// \defgroup CINDEX_DEBUG Debugging facilities
-  ///
-  /// These routines are used for testing and debugging, only, and should not
-  /// be relied upon.
-  ///
-  /// @{
-  CXString clang_getCursorKindSpelling(
-    int Kind,
-  ) {
-    return _clang_getCursorKindSpelling(
-      Kind,
-    );
-  }
-
-  late final _clang_getCursorKindSpellingPtr =
-      _lookup<ffi.NativeFunction<CXString Function(ffi.Int32)>>(
-          'clang_getCursorKindSpelling');
-  late final _clang_getCursorKindSpelling =
-      _clang_getCursorKindSpellingPtr.asFunction<CXString Function(int)>();
-
-  /// If cursor is a statement declaration tries to evaluate the
-  /// statement and if its variable, tries to evaluate its initializer,
-  /// into its corresponding type.
-  CXEvalResult clang_Cursor_Evaluate(
-    CXCursor C,
-  ) {
-    return _clang_Cursor_Evaluate(
-      C,
-    );
-  }
-
-  late final _clang_Cursor_EvaluatePtr =
-      _lookup<ffi.NativeFunction<CXEvalResult Function(CXCursor)>>(
-          'clang_Cursor_Evaluate');
-  late final _clang_Cursor_Evaluate =
-      _clang_Cursor_EvaluatePtr.asFunction<CXEvalResult Function(CXCursor)>();
-
-  /// Returns the kind of the evaluated result.
-  int clang_EvalResult_getKind(
-    CXEvalResult E,
-  ) {
-    return _clang_EvalResult_getKind(
-      E,
-    );
-  }
-
-  late final _clang_EvalResult_getKindPtr =
-      _lookup<ffi.NativeFunction<ffi.Int32 Function(CXEvalResult)>>(
-          'clang_EvalResult_getKind');
-  late final _clang_EvalResult_getKind =
-      _clang_EvalResult_getKindPtr.asFunction<int Function(CXEvalResult)>();
-
-  /// Returns the evaluation result as integer if the
-  /// kind is Int.
-  int clang_EvalResult_getAsInt(
-    CXEvalResult E,
-  ) {
-    return _clang_EvalResult_getAsInt(
-      E,
-    );
-  }
-
-  late final _clang_EvalResult_getAsIntPtr =
-      _lookup<ffi.NativeFunction<ffi.Int Function(CXEvalResult)>>(
-          'clang_EvalResult_getAsInt');
-  late final _clang_EvalResult_getAsInt =
-      _clang_EvalResult_getAsIntPtr.asFunction<int Function(CXEvalResult)>();
-
-  /// Returns the evaluation result as a long long integer if the
-  /// kind is Int. This prevents overflows that may happen if the result is
-  /// returned with clang_EvalResult_getAsInt.
-  int clang_EvalResult_getAsLongLong(
-    CXEvalResult E,
-  ) {
-    return _clang_EvalResult_getAsLongLong(
-      E,
-    );
-  }
-
-  late final _clang_EvalResult_getAsLongLongPtr =
-      _lookup<ffi.NativeFunction<ffi.LongLong Function(CXEvalResult)>>(
-          'clang_EvalResult_getAsLongLong');
-  late final _clang_EvalResult_getAsLongLong =
-      _clang_EvalResult_getAsLongLongPtr
-          .asFunction<int Function(CXEvalResult)>();
-
-  /// Returns the evaluation result as double if the
-  /// kind is double.
-  double clang_EvalResult_getAsDouble(
-    CXEvalResult E,
-  ) {
-    return _clang_EvalResult_getAsDouble(
-      E,
-    );
-  }
-
-  late final _clang_EvalResult_getAsDoublePtr =
-      _lookup<ffi.NativeFunction<ffi.Double Function(CXEvalResult)>>(
-          'clang_EvalResult_getAsDouble');
-  late final _clang_EvalResult_getAsDouble = _clang_EvalResult_getAsDoublePtr
-      .asFunction<double Function(CXEvalResult)>();
-
-  /// Returns the evaluation result as a constant string if the
-  /// kind is other than Int or float. User must not free this pointer,
-  /// instead call clang_EvalResult_dispose on the CXEvalResult returned
-  /// by clang_Cursor_Evaluate.
-  ffi.Pointer<ffi.Char> clang_EvalResult_getAsStr(
-    CXEvalResult E,
-  ) {
-    return _clang_EvalResult_getAsStr(
-      E,
-    );
-  }
-
-  late final _clang_EvalResult_getAsStrPtr =
-      _lookup<ffi.NativeFunction<ffi.Pointer<ffi.Char> Function(CXEvalResult)>>(
-          'clang_EvalResult_getAsStr');
-  late final _clang_EvalResult_getAsStr = _clang_EvalResult_getAsStrPtr
-      .asFunction<ffi.Pointer<ffi.Char> Function(CXEvalResult)>();
-
-  /// Disposes the created Eval memory.
-  void clang_EvalResult_dispose(
-    CXEvalResult E,
-  ) {
-    return _clang_EvalResult_dispose(
-      E,
-    );
-  }
-
-  late final _clang_EvalResult_disposePtr =
-      _lookup<ffi.NativeFunction<ffi.Void Function(CXEvalResult)>>(
-          'clang_EvalResult_dispose');
-  late final _clang_EvalResult_dispose =
-      _clang_EvalResult_disposePtr.asFunction<void Function(CXEvalResult)>();
-}
-
-/// A character string.
-///
-/// The \c CXString type is used to return strings from the interface when
-/// the ownership of that string might differ from one call to the next.
-/// Use \c clang_getCString() to retrieve the string data and, once finished
-/// with the string data, call \c clang_disposeString() to free the string.
-class CXString extends ffi.Struct {
-  external ffi.Pointer<ffi.Void> data;
-
-  @ffi.UnsignedInt()
-  external int private_flags;
-}
-
-class CXTranslationUnitImpl extends ffi.Opaque {}
-
-/// Provides the contents of a file that has not yet been saved to disk.
-///
-/// Each CXUnsavedFile instance provides the name of a file on the
-/// system along with the current contents of that file that have not
-/// yet been saved to disk.
-class CXUnsavedFile extends ffi.Struct {
-  /// The file whose contents have not yet been saved.
-  ///
-  /// This file must already exist in the file system.
-  external ffi.Pointer<ffi.Char> Filename;
-
-  /// A buffer containing the unsaved contents of this file.
-  external ffi.Pointer<ffi.Char> Contents;
-
-  /// The length of the unsaved contents of this buffer.
-  @ffi.UnsignedLong()
-  external int Length;
-}
-
-/// An "index" that consists of a set of translation units that would
-/// typically be linked together into an executable or library.
-typedef CXIndex = ffi.Pointer<ffi.Void>;
-
-/// A particular source file that is part of a translation unit.
-typedef CXFile = ffi.Pointer<ffi.Void>;
-
-/// Identifies a specific source location within a translation
-/// unit.
-///
-/// Use clang_getExpansionLocation() or clang_getSpellingLocation()
-/// to map a source location to a particular file, line, and column.
-class CXSourceLocation extends ffi.Struct {
-  @ffi.Array.multi([2])
-  external ffi.Array<ffi.Pointer<ffi.Void>> ptr_data;
-
-  @ffi.UnsignedInt()
-  external int int_data;
-}
-
-/// Identifies a half-open character range in the source code.
-///
-/// Use clang_getRangeStart() and clang_getRangeEnd() to retrieve the
-/// starting and end locations from a source range, respectively.
-class CXSourceRange extends ffi.Struct {
-  @ffi.Array.multi([2])
-  external ffi.Array<ffi.Pointer<ffi.Void>> ptr_data;
-
-  @ffi.UnsignedInt()
-  external int begin_int_data;
-
-  @ffi.UnsignedInt()
-  external int end_int_data;
-}
-
-/// A single translation unit, which resides in an index.
-typedef CXTranslationUnit = ffi.Pointer<CXTranslationUnitImpl>;
-
-/// A single diagnostic, containing the diagnostic's severity,
-/// location, text, source ranges, and fix-it hints.
-typedef CXDiagnostic = ffi.Pointer<ffi.Void>;
-
-/// Options to control the display of diagnostics.
-///
-/// The values in this enum are meant to be combined to customize the
-/// behavior of \c clang_formatDiagnostic().
-abstract class CXDiagnosticDisplayOptions {
-  /// Display the source-location information where the
-  /// diagnostic was located.
-  ///
-  /// When set, diagnostics will be prefixed by the file, line, and
-  /// (optionally) column to which the diagnostic refers. For example,
-  ///
-  /// \code
-  /// test.c:28: warning: extra tokens at end of #endif directive
-  /// \endcode
-  ///
-  /// This option corresponds to the clang flag \c -fshow-source-location.
-  static const int CXDiagnostic_DisplaySourceLocation = 1;
-
-  /// If displaying the source-location information of the
-  /// diagnostic, also include the column number.
-  ///
-  /// This option corresponds to the clang flag \c -fshow-column.
-  static const int CXDiagnostic_DisplayColumn = 2;
-
-  /// If displaying the source-location information of the
-  /// diagnostic, also include information about source ranges in a
-  /// machine-parsable format.
-  ///
-  /// This option corresponds to the clang flag
-  /// \c -fdiagnostics-print-source-range-info.
-  static const int CXDiagnostic_DisplaySourceRanges = 4;
-
-  /// Display the option name associated with this diagnostic, if any.
-  ///
-  /// The option name displayed (e.g., -Wconversion) will be placed in brackets
-  /// after the diagnostic text. This option corresponds to the clang flag
-  /// \c -fdiagnostics-show-option.
-  static const int CXDiagnostic_DisplayOption = 8;
-
-  /// Display the category number associated with this diagnostic, if any.
-  ///
-  /// The category number is displayed within brackets after the diagnostic text.
-  /// This option corresponds to the clang flag
-  /// \c -fdiagnostics-show-category=id.
-  static const int CXDiagnostic_DisplayCategoryId = 16;
-
-  /// Display the category name associated with this diagnostic, if any.
-  ///
-  /// The category name is displayed within brackets after the diagnostic text.
-  /// This option corresponds to the clang flag
-  /// \c -fdiagnostics-show-category=name.
-  static const int CXDiagnostic_DisplayCategoryName = 32;
-}
-
-/// Flags that control the creation of translation units.
-///
-/// The enumerators in this enumeration type are meant to be bitwise
-/// ORed together to specify which options should be used when
-/// constructing the translation unit.
-abstract class CXTranslationUnit_Flags {
-  /// Used to indicate that no special translation-unit options are
-  /// needed.
-  static const int CXTranslationUnit_None = 0;
-
-  /// Used to indicate that the parser should construct a "detailed"
-  /// preprocessing record, including all macro definitions and instantiations.
-  ///
-  /// Constructing a detailed preprocessing record requires more memory
-  /// and time to parse, since the information contained in the record
-  /// is usually not retained. However, it can be useful for
-  /// applications that require more detailed information about the
-  /// behavior of the preprocessor.
-  static const int CXTranslationUnit_DetailedPreprocessingRecord = 1;
-
-  /// Used to indicate that the translation unit is incomplete.
-  ///
-  /// When a translation unit is considered "incomplete", semantic
-  /// analysis that is typically performed at the end of the
-  /// translation unit will be suppressed. For example, this suppresses
-  /// the completion of tentative declarations in C and of
-  /// instantiation of implicitly-instantiation function templates in
-  /// C++. This option is typically used when parsing a header with the
-  /// intent of producing a precompiled header.
-  static const int CXTranslationUnit_Incomplete = 2;
-
-  /// Used to indicate that the translation unit should be built with an
-  /// implicit precompiled header for the preamble.
-  ///
-  /// An implicit precompiled header is used as an optimization when a
-  /// particular translation unit is likely to be reparsed many times
-  /// when the sources aren't changing that often. In this case, an
-  /// implicit precompiled header will be built containing all of the
-  /// initial includes at the top of the main file (what we refer to as
-  /// the "preamble" of the file). In subsequent parses, if the
-  /// preamble or the files in it have not changed, \c
-  /// clang_reparseTranslationUnit() will re-use the implicit
-  /// precompiled header to improve parsing performance.
-  static const int CXTranslationUnit_PrecompiledPreamble = 4;
-
-  /// Used to indicate that the translation unit should cache some
-  /// code-completion results with each reparse of the source file.
-  ///
-  /// Caching of code-completion results is a performance optimization that
-  /// introduces some overhead to reparsing but improves the performance of
-  /// code-completion operations.
-  static const int CXTranslationUnit_CacheCompletionResults = 8;
-
-  /// Used to indicate that the translation unit will be serialized with
-  /// \c clang_saveTranslationUnit.
-  ///
-  /// This option is typically used when parsing a header with the intent of
-  /// producing a precompiled header.
-  static const int CXTranslationUnit_ForSerialization = 16;
-
-  /// DEPRECATED: Enabled chained precompiled preambles in C++.
-  ///
-  /// Note: this is a *temporary* option that is available only while
-  /// we are testing C++ precompiled preamble support. It is deprecated.
-  static const int CXTranslationUnit_CXXChainedPCH = 32;
-
-  /// Used to indicate that function/method bodies should be skipped while
-  /// parsing.
-  ///
-  /// This option can be used to search for declarations/definitions while
-  /// ignoring the usages.
-  static const int CXTranslationUnit_SkipFunctionBodies = 64;
-
-  /// Used to indicate that brief documentation comments should be
-  /// included into the set of code completions returned from this translation
-  /// unit.
-  static const int CXTranslationUnit_IncludeBriefCommentsInCodeCompletion = 128;
-
-  /// Used to indicate that the precompiled preamble should be created on
-  /// the first parse. Otherwise it will be created on the first reparse. This
-  /// trades runtime on the first parse (serializing the preamble takes time) for
-  /// reduced runtime on the second parse (can now reuse the preamble).
-  static const int CXTranslationUnit_CreatePreambleOnFirstParse = 256;
-
-  /// Do not stop processing when fatal errors are encountered.
-  ///
-  /// When fatal errors are encountered while parsing a translation unit,
-  /// semantic analysis is typically stopped early when compiling code. A common
-  /// source for fatal errors are unresolvable include files. For the
-  /// purposes of an IDE, this is undesirable behavior and as much information
-  /// as possible should be reported. Use this flag to enable this behavior.
-  static const int CXTranslationUnit_KeepGoing = 512;
-
-  /// Sets the preprocessor in a mode for parsing a single file only.
-  static const int CXTranslationUnit_SingleFileParse = 1024;
-
-  /// Used in combination with CXTranslationUnit_SkipFunctionBodies to
-  /// constrain the skipping of function bodies to the preamble.
-  ///
-  /// The function bodies of the main file are not skipped.
-  static const int CXTranslationUnit_LimitSkipFunctionBodiesToPreamble = 2048;
-
-  /// Used to indicate that attributed types should be included in CXType.
-  static const int CXTranslationUnit_IncludeAttributedTypes = 4096;
-
-  /// Used to indicate that implicit attributes should be visited.
-  static const int CXTranslationUnit_VisitImplicitAttributes = 8192;
-
-  /// Used to indicate that non-errors from included files should be ignored.
-  ///
-  /// If set, clang_getDiagnosticSetFromTU() will not report e.g. warnings from
-  /// included files anymore. This speeds up clang_getDiagnosticSetFromTU() for
-  /// the case where these warnings are not of interest, as for an IDE for
-  /// example, which typically shows only the diagnostics in the main file.
-  static const int CXTranslationUnit_IgnoreNonErrorsFromIncludedFiles = 16384;
-
-  /// Tells the preprocessor not to skip excluded conditional blocks.
-  static const int CXTranslationUnit_RetainExcludedConditionalBlocks = 32768;
-}
-
-/// Describes the kind of entity that a cursor refers to.
-abstract class CXCursorKind {
-  /// A declaration whose specific kind is not exposed via this
-  /// interface.
-  ///
-  /// Unexposed declarations have the same operations as any other kind
-  /// of declaration; one can extract their location information,
-  /// spelling, find their definitions, etc. However, the specific kind
-  /// of the declaration is not reported.
-  static const int CXCursor_UnexposedDecl = 1;
-
-  /// A C or C++ struct.
-  static const int CXCursor_StructDecl = 2;
-
-  /// A C or C++ union.
-  static const int CXCursor_UnionDecl = 3;
-
-  /// A C++ class.
-  static const int CXCursor_ClassDecl = 4;
-
-  /// An enumeration.
-  static const int CXCursor_EnumDecl = 5;
-
-  /// A field (in C) or non-static data member (in C++) in a
-  /// struct, union, or C++ class.
-  static const int CXCursor_FieldDecl = 6;
-
-  /// An enumerator constant.
-  static const int CXCursor_EnumConstantDecl = 7;
-
-  /// A function.
-  static const int CXCursor_FunctionDecl = 8;
-
-  /// A variable.
-  static const int CXCursor_VarDecl = 9;
-
-  /// A function or method parameter.
-  static const int CXCursor_ParmDecl = 10;
-
-  /// An Objective-C \@interface.
-  static const int CXCursor_ObjCInterfaceDecl = 11;
-
-  /// An Objective-C \@interface for a category.
-  static const int CXCursor_ObjCCategoryDecl = 12;
-
-  /// An Objective-C \@protocol declaration.
-  static const int CXCursor_ObjCProtocolDecl = 13;
-
-  /// An Objective-C \@property declaration.
-  static const int CXCursor_ObjCPropertyDecl = 14;
-
-  /// An Objective-C instance variable.
-  static const int CXCursor_ObjCIvarDecl = 15;
-
-  /// An Objective-C instance method.
-  static const int CXCursor_ObjCInstanceMethodDecl = 16;
-
-  /// An Objective-C class method.
-  static const int CXCursor_ObjCClassMethodDecl = 17;
-
-  /// An Objective-C \@implementation.
-  static const int CXCursor_ObjCImplementationDecl = 18;
-
-  /// An Objective-C \@implementation for a category.
-  static const int CXCursor_ObjCCategoryImplDecl = 19;
-
-  /// A typedef.
-  static const int CXCursor_TypedefDecl = 20;
-
-  /// A C++ class method.
-  static const int CXCursor_CXXMethod = 21;
-
-  /// A C++ namespace.
-  static const int CXCursor_Namespace = 22;
-
-  /// A linkage specification, e.g. 'extern "C"'.
-  static const int CXCursor_LinkageSpec = 23;
-
-  /// A C++ constructor.
-  static const int CXCursor_Constructor = 24;
-
-  /// A C++ destructor.
-  static const int CXCursor_Destructor = 25;
-
-  /// A C++ conversion function.
-  static const int CXCursor_ConversionFunction = 26;
-
-  /// A C++ template type parameter.
-  static const int CXCursor_TemplateTypeParameter = 27;
-
-  /// A C++ non-type template parameter.
-  static const int CXCursor_NonTypeTemplateParameter = 28;
-
-  /// A C++ template template parameter.
-  static const int CXCursor_TemplateTemplateParameter = 29;
-
-  /// A C++ function template.
-  static const int CXCursor_FunctionTemplate = 30;
-
-  /// A C++ class template.
-  static const int CXCursor_ClassTemplate = 31;
-
-  /// A C++ class template partial specialization.
-  static const int CXCursor_ClassTemplatePartialSpecialization = 32;
-
-  /// A C++ namespace alias declaration.
-  static const int CXCursor_NamespaceAlias = 33;
-
-  /// A C++ using directive.
-  static const int CXCursor_UsingDirective = 34;
-
-  /// A C++ using declaration.
-  static const int CXCursor_UsingDeclaration = 35;
-
-  /// A C++ alias declaration
-  static const int CXCursor_TypeAliasDecl = 36;
-
-  /// An Objective-C \@synthesize definition.
-  static const int CXCursor_ObjCSynthesizeDecl = 37;
-
-  /// An Objective-C \@dynamic definition.
-  static const int CXCursor_ObjCDynamicDecl = 38;
-
-  /// An access specifier.
-  static const int CXCursor_CXXAccessSpecifier = 39;
-  static const int CXCursor_FirstDecl = 1;
-  static const int CXCursor_LastDecl = 39;
-  static const int CXCursor_FirstRef = 40;
-  static const int CXCursor_ObjCSuperClassRef = 40;
-  static const int CXCursor_ObjCProtocolRef = 41;
-  static const int CXCursor_ObjCClassRef = 42;
-
-  /// A reference to a type declaration.
-  ///
-  /// A type reference occurs anywhere where a type is named but not
-  /// declared. For example, given:
-  ///
-  /// \code
-  /// typedef unsigned size_type;
-  /// size_type size;
-  /// \endcode
-  ///
-  /// The typedef is a declaration of size_type (CXCursor_TypedefDecl),
-  /// while the type of the variable "size" is referenced. The cursor
-  /// referenced by the type of size is the typedef for size_type.
-  static const int CXCursor_TypeRef = 43;
-  static const int CXCursor_CXXBaseSpecifier = 44;
-
-  /// A reference to a class template, function template, template
-  /// template parameter, or class template partial specialization.
-  static const int CXCursor_TemplateRef = 45;
-
-  /// A reference to a namespace or namespace alias.
-  static const int CXCursor_NamespaceRef = 46;
-
-  /// A reference to a member of a struct, union, or class that occurs in
-  /// some non-expression context, e.g., a designated initializer.
-  static const int CXCursor_MemberRef = 47;
-
-  /// A reference to a labeled statement.
-  ///
-  /// This cursor kind is used to describe the jump to "start_over" in the
-  /// goto statement in the following example:
-  ///
-  /// \code
-  /// start_over:
-  /// ++counter;
-  ///
-  /// goto start_over;
-  /// \endcode
-  ///
-  /// A label reference cursor refers to a label statement.
-  static const int CXCursor_LabelRef = 48;
-
-  /// A reference to a set of overloaded functions or function templates
-  /// that has not yet been resolved to a specific function or function template.
-  ///
-  /// An overloaded declaration reference cursor occurs in C++ templates where
-  /// a dependent name refers to a function. For example:
-  ///
-  /// \code
-  /// template<typename T> void swap(T&, T&);
-  ///
-  /// struct X { ... };
-  /// void swap(X&, X&);
-  ///
-  /// template<typename T>
-  /// void reverse(T* first, T* last) {
-  /// while (first < last - 1) {
-  /// swap(*first, *--last);
-  /// ++first;
-  /// }
-  /// }
-  ///
-  /// struct Y { };
-  /// void swap(Y&, Y&);
-  /// \endcode
-  ///
-  /// Here, the identifier "swap" is associated with an overloaded declaration
-  /// reference. In the template definition, "swap" refers to either of the two
-  /// "swap" functions declared above, so both results will be available. At
-  /// instantiation time, "swap" may also refer to other functions found via
-  /// argument-dependent lookup (e.g., the "swap" function at the end of the
-  /// example).
-  ///
-  /// The functions \c clang_getNumOverloadedDecls() and
-  /// \c clang_getOverloadedDecl() can be used to retrieve the definitions
-  /// referenced by this cursor.
-  static const int CXCursor_OverloadedDeclRef = 49;
-
-  /// A reference to a variable that occurs in some non-expression
-  /// context, e.g., a C++ lambda capture list.
-  static const int CXCursor_VariableRef = 50;
-  static const int CXCursor_LastRef = 50;
-  static const int CXCursor_FirstInvalid = 70;
-  static const int CXCursor_InvalidFile = 70;
-  static const int CXCursor_NoDeclFound = 71;
-  static const int CXCursor_NotImplemented = 72;
-  static const int CXCursor_InvalidCode = 73;
-  static const int CXCursor_LastInvalid = 73;
-  static const int CXCursor_FirstExpr = 100;
-
-  /// An expression whose specific kind is not exposed via this
-  /// interface.
-  ///
-  /// Unexposed expressions have the same operations as any other kind
-  /// of expression; one can extract their location information,
-  /// spelling, children, etc. However, the specific kind of the
-  /// expression is not reported.
-  static const int CXCursor_UnexposedExpr = 100;
-
-  /// An expression that refers to some value declaration, such
-  /// as a function, variable, or enumerator.
-  static const int CXCursor_DeclRefExpr = 101;
-
-  /// An expression that refers to a member of a struct, union,
-  /// class, Objective-C class, etc.
-  static const int CXCursor_MemberRefExpr = 102;
-
-  /// An expression that calls a function.
-  static const int CXCursor_CallExpr = 103;
-
-  /// An expression that sends a message to an Objective-C
-  /// object or class.
-  static const int CXCursor_ObjCMessageExpr = 104;
-
-  /// An expression that represents a block literal.
-  static const int CXCursor_BlockExpr = 105;
-
-  /// An integer literal.
-  static const int CXCursor_IntegerLiteral = 106;
-
-  /// A floating point number literal.
-  static const int CXCursor_FloatingLiteral = 107;
-
-  /// An imaginary number literal.
-  static const int CXCursor_ImaginaryLiteral = 108;
-
-  /// A string literal.
-  static const int CXCursor_StringLiteral = 109;
-
-  /// A character literal.
-  static const int CXCursor_CharacterLiteral = 110;
-
-  /// A parenthesized expression, e.g. "(1)".
-  ///
-  /// This AST node is only formed if full location information is requested.
-  static const int CXCursor_ParenExpr = 111;
-
-  /// This represents the unary-expression's (except sizeof and
-  /// alignof).
-  static const int CXCursor_UnaryOperator = 112;
-
-  /// [C99 6.5.2.1] Array Subscripting.
-  static const int CXCursor_ArraySubscriptExpr = 113;
-
-  /// A builtin binary operation expression such as "x + y" or
-  /// "x <= y".
-  static const int CXCursor_BinaryOperator = 114;
-
-  /// Compound assignment such as "+=".
-  static const int CXCursor_CompoundAssignOperator = 115;
-
-  /// The ?: ternary operator.
-  static const int CXCursor_ConditionalOperator = 116;
-
-  /// An explicit cast in C (C99 6.5.4) or a C-style cast in C++
-  /// (C++ [expr.cast]), which uses the syntax (Type)expr.
-  ///
-  /// For example: (int)f.
-  static const int CXCursor_CStyleCastExpr = 117;
-
-  /// [C99 6.5.2.5]
-  static const int CXCursor_CompoundLiteralExpr = 118;
-
-  /// Describes an C or C++ initializer list.
-  static const int CXCursor_InitListExpr = 119;
-
-  /// The GNU address of label extension, representing &&label.
-  static const int CXCursor_AddrLabelExpr = 120;
-
-  /// This is the GNU Statement Expression extension: ({int X=4; X;})
-  static const int CXCursor_StmtExpr = 121;
-
-  /// Represents a C11 generic selection.
-  static const int CXCursor_GenericSelectionExpr = 122;
-
-  /// Implements the GNU __null extension, which is a name for a null
-  /// pointer constant that has integral type (e.g., int or long) and is the same
-  /// size and alignment as a pointer.
-  ///
-  /// The __null extension is typically only used by system headers, which define
-  /// NULL as __null in C++ rather than using 0 (which is an integer that may not
-  /// match the size of a pointer).
-  static const int CXCursor_GNUNullExpr = 123;
-
-  /// C++'s static_cast<> expression.
-  static const int CXCursor_CXXStaticCastExpr = 124;
-
-  /// C++'s dynamic_cast<> expression.
-  static const int CXCursor_CXXDynamicCastExpr = 125;
-
-  /// C++'s reinterpret_cast<> expression.
-  static const int CXCursor_CXXReinterpretCastExpr = 126;
-
-  /// C++'s const_cast<> expression.
-  static const int CXCursor_CXXConstCastExpr = 127;
-
-  /// Represents an explicit C++ type conversion that uses "functional"
-  /// notion (C++ [expr.type.conv]).
-  ///
-  /// Example:
-  /// \code
-  /// x = int(0.5);
-  /// \endcode
-  static const int CXCursor_CXXFunctionalCastExpr = 128;
-
-  /// A C++ typeid expression (C++ [expr.typeid]).
-  static const int CXCursor_CXXTypeidExpr = 129;
-
-  /// [C++ 2.13.5] C++ Boolean Literal.
-  static const int CXCursor_CXXBoolLiteralExpr = 130;
-
-  /// [C++0x 2.14.7] C++ Pointer Literal.
-  static const int CXCursor_CXXNullPtrLiteralExpr = 131;
-
-  /// Represents the "this" expression in C++
-  static const int CXCursor_CXXThisExpr = 132;
-
-  /// [C++ 15] C++ Throw Expression.
-  ///
-  /// This handles 'throw' and 'throw' assignment-expression. When
-  /// assignment-expression isn't present, Op will be null.
-  static const int CXCursor_CXXThrowExpr = 133;
-
-  /// A new expression for memory allocation and constructor calls, e.g:
-  /// "new CXXNewExpr(foo)".
-  static const int CXCursor_CXXNewExpr = 134;
-
-  /// A delete expression for memory deallocation and destructor calls,
-  /// e.g. "delete[] pArray".
-  static const int CXCursor_CXXDeleteExpr = 135;
-
-  /// A unary expression. (noexcept, sizeof, or other traits)
-  static const int CXCursor_UnaryExpr = 136;
-
-  /// An Objective-C string literal i.e. @"foo".
-  static const int CXCursor_ObjCStringLiteral = 137;
-
-  /// An Objective-C \@encode expression.
-  static const int CXCursor_ObjCEncodeExpr = 138;
-
-  /// An Objective-C \@selector expression.
-  static const int CXCursor_ObjCSelectorExpr = 139;
-
-  /// An Objective-C \@protocol expression.
-  static const int CXCursor_ObjCProtocolExpr = 140;
-
-  /// An Objective-C "bridged" cast expression, which casts between
-  /// Objective-C pointers and C pointers, transferring ownership in the process.
-  ///
-  /// \code
-  /// NSString *str = (__bridge_transfer NSString *)CFCreateString();
-  /// \endcode
-  static const int CXCursor_ObjCBridgedCastExpr = 141;
-
-  /// Represents a C++0x pack expansion that produces a sequence of
-  /// expressions.
-  ///
-  /// A pack expansion expression contains a pattern (which itself is an
-  /// expression) followed by an ellipsis. For example:
-  ///
-  /// \code
-  /// template<typename F, typename ...Types>
-  /// void forward(F f, Types &&...args) {
-  /// f(static_cast<Types&&>(args)...);
-  /// }
-  /// \endcode
-  static const int CXCursor_PackExpansionExpr = 142;
-
-  /// Represents an expression that computes the length of a parameter
-  /// pack.
-  ///
-  /// \code
-  /// template<typename ...Types>
-  /// struct count {
-  /// static const unsigned value = sizeof...(Types);
-  /// };
-  /// \endcode
-  static const int CXCursor_SizeOfPackExpr = 143;
-  static const int CXCursor_LambdaExpr = 144;
-
-  /// Objective-c Boolean Literal.
-  static const int CXCursor_ObjCBoolLiteralExpr = 145;
-
-  /// Represents the "self" expression in an Objective-C method.
-  static const int CXCursor_ObjCSelfExpr = 146;
-
-  /// OpenMP 4.0 [2.4, Array Section].
-  static const int CXCursor_OMPArraySectionExpr = 147;
-
-  /// Represents an @available(...) check.
-  static const int CXCursor_ObjCAvailabilityCheckExpr = 148;
-
-  /// Fixed point literal
-  static const int CXCursor_FixedPointLiteral = 149;
-  static const int CXCursor_LastExpr = 149;
-  static const int CXCursor_FirstStmt = 200;
-
-  /// A statement whose specific kind is not exposed via this
-  /// interface.
-  ///
-  /// Unexposed statements have the same operations as any other kind of
-  /// statement; one can extract their location information, spelling,
-  /// children, etc. However, the specific kind of the statement is not
-  /// reported.
-  static const int CXCursor_UnexposedStmt = 200;
-
-  /// A labelled statement in a function.
-  ///
-  /// This cursor kind is used to describe the "start_over:" label statement in
-  /// the following example:
-  ///
-  /// \code
-  /// start_over:
-  /// ++counter;
-  /// \endcode
-  static const int CXCursor_LabelStmt = 201;
-
-  /// A group of statements like { stmt stmt }.
-  ///
-  /// This cursor kind is used to describe compound statements, e.g. function
-  /// bodies.
-  static const int CXCursor_CompoundStmt = 202;
-
-  /// A case statement.
-  static const int CXCursor_CaseStmt = 203;
-
-  /// A default statement.
-  static const int CXCursor_DefaultStmt = 204;
-
-  /// An if statement
-  static const int CXCursor_IfStmt = 205;
-
-  /// A switch statement.
-  static const int CXCursor_SwitchStmt = 206;
-
-  /// A while statement.
-  static const int CXCursor_WhileStmt = 207;
-
-  /// A do statement.
-  static const int CXCursor_DoStmt = 208;
-
-  /// A for statement.
-  static const int CXCursor_ForStmt = 209;
-
-  /// A goto statement.
-  static const int CXCursor_GotoStmt = 210;
-
-  /// An indirect goto statement.
-  static const int CXCursor_IndirectGotoStmt = 211;
-
-  /// A continue statement.
-  static const int CXCursor_ContinueStmt = 212;
-
-  /// A break statement.
-  static const int CXCursor_BreakStmt = 213;
-
-  /// A return statement.
-  static const int CXCursor_ReturnStmt = 214;
-
-  /// A GCC inline assembly statement extension.
-  static const int CXCursor_GCCAsmStmt = 215;
-  static const int CXCursor_AsmStmt = 215;
-
-  /// Objective-C's overall \@try-\@catch-\@finally statement.
-  static const int CXCursor_ObjCAtTryStmt = 216;
-
-  /// Objective-C's \@catch statement.
-  static const int CXCursor_ObjCAtCatchStmt = 217;
-
-  /// Objective-C's \@finally statement.
-  static const int CXCursor_ObjCAtFinallyStmt = 218;
-
-  /// Objective-C's \@throw statement.
-  static const int CXCursor_ObjCAtThrowStmt = 219;
-
-  /// Objective-C's \@synchronized statement.
-  static const int CXCursor_ObjCAtSynchronizedStmt = 220;
-
-  /// Objective-C's autorelease pool statement.
-  static const int CXCursor_ObjCAutoreleasePoolStmt = 221;
-
-  /// Objective-C's collection statement.
-  static const int CXCursor_ObjCForCollectionStmt = 222;
-
-  /// C++'s catch statement.
-  static const int CXCursor_CXXCatchStmt = 223;
-
-  /// C++'s try statement.
-  static const int CXCursor_CXXTryStmt = 224;
-
-  /// C++'s for (* : *) statement.
-  static const int CXCursor_CXXForRangeStmt = 225;
-
-  /// Windows Structured Exception Handling's try statement.
-  static const int CXCursor_SEHTryStmt = 226;
-
-  /// Windows Structured Exception Handling's except statement.
-  static const int CXCursor_SEHExceptStmt = 227;
-
-  /// Windows Structured Exception Handling's finally statement.
-  static const int CXCursor_SEHFinallyStmt = 228;
-
-  /// A MS inline assembly statement extension.
-  static const int CXCursor_MSAsmStmt = 229;
-
-  /// The null statement ";": C99 6.8.3p3.
-  ///
-  /// This cursor kind is used to describe the null statement.
-  static const int CXCursor_NullStmt = 230;
-
-  /// Adaptor class for mixing declarations with statements and
-  /// expressions.
-  static const int CXCursor_DeclStmt = 231;
-
-  /// OpenMP parallel directive.
-  static const int CXCursor_OMPParallelDirective = 232;
-
-  /// OpenMP SIMD directive.
-  static const int CXCursor_OMPSimdDirective = 233;
-
-  /// OpenMP for directive.
-  static const int CXCursor_OMPForDirective = 234;
-
-  /// OpenMP sections directive.
-  static const int CXCursor_OMPSectionsDirective = 235;
-
-  /// OpenMP section directive.
-  static const int CXCursor_OMPSectionDirective = 236;
-
-  /// OpenMP single directive.
-  static const int CXCursor_OMPSingleDirective = 237;
-
-  /// OpenMP parallel for directive.
-  static const int CXCursor_OMPParallelForDirective = 238;
-
-  /// OpenMP parallel sections directive.
-  static const int CXCursor_OMPParallelSectionsDirective = 239;
-
-  /// OpenMP task directive.
-  static const int CXCursor_OMPTaskDirective = 240;
-
-  /// OpenMP master directive.
-  static const int CXCursor_OMPMasterDirective = 241;
-
-  /// OpenMP critical directive.
-  static const int CXCursor_OMPCriticalDirective = 242;
-
-  /// OpenMP taskyield directive.
-  static const int CXCursor_OMPTaskyieldDirective = 243;
-
-  /// OpenMP barrier directive.
-  static const int CXCursor_OMPBarrierDirective = 244;
-
-  /// OpenMP taskwait directive.
-  static const int CXCursor_OMPTaskwaitDirective = 245;
-
-  /// OpenMP flush directive.
-  static const int CXCursor_OMPFlushDirective = 246;
-
-  /// Windows Structured Exception Handling's leave statement.
-  static const int CXCursor_SEHLeaveStmt = 247;
-
-  /// OpenMP ordered directive.
-  static const int CXCursor_OMPOrderedDirective = 248;
-
-  /// OpenMP atomic directive.
-  static const int CXCursor_OMPAtomicDirective = 249;
-
-  /// OpenMP for SIMD directive.
-  static const int CXCursor_OMPForSimdDirective = 250;
-
-  /// OpenMP parallel for SIMD directive.
-  static const int CXCursor_OMPParallelForSimdDirective = 251;
-
-  /// OpenMP target directive.
-  static const int CXCursor_OMPTargetDirective = 252;
-
-  /// OpenMP teams directive.
-  static const int CXCursor_OMPTeamsDirective = 253;
-
-  /// OpenMP taskgroup directive.
-  static const int CXCursor_OMPTaskgroupDirective = 254;
-
-  /// OpenMP cancellation point directive.
-  static const int CXCursor_OMPCancellationPointDirective = 255;
-
-  /// OpenMP cancel directive.
-  static const int CXCursor_OMPCancelDirective = 256;
-
-  /// OpenMP target data directive.
-  static const int CXCursor_OMPTargetDataDirective = 257;
-
-  /// OpenMP taskloop directive.
-  static const int CXCursor_OMPTaskLoopDirective = 258;
-
-  /// OpenMP taskloop simd directive.
-  static const int CXCursor_OMPTaskLoopSimdDirective = 259;
-
-  /// OpenMP distribute directive.
-  static const int CXCursor_OMPDistributeDirective = 260;
-
-  /// OpenMP target enter data directive.
-  static const int CXCursor_OMPTargetEnterDataDirective = 261;
-
-  /// OpenMP target exit data directive.
-  static const int CXCursor_OMPTargetExitDataDirective = 262;
-
-  /// OpenMP target parallel directive.
-  static const int CXCursor_OMPTargetParallelDirective = 263;
-
-  /// OpenMP target parallel for directive.
-  static const int CXCursor_OMPTargetParallelForDirective = 264;
-
-  /// OpenMP target update directive.
-  static const int CXCursor_OMPTargetUpdateDirective = 265;
-
-  /// OpenMP distribute parallel for directive.
-  static const int CXCursor_OMPDistributeParallelForDirective = 266;
-
-  /// OpenMP distribute parallel for simd directive.
-  static const int CXCursor_OMPDistributeParallelForSimdDirective = 267;
-
-  /// OpenMP distribute simd directive.
-  static const int CXCursor_OMPDistributeSimdDirective = 268;
-
-  /// OpenMP target parallel for simd directive.
-  static const int CXCursor_OMPTargetParallelForSimdDirective = 269;
-
-  /// OpenMP target simd directive.
-  static const int CXCursor_OMPTargetSimdDirective = 270;
-
-  /// OpenMP teams distribute directive.
-  static const int CXCursor_OMPTeamsDistributeDirective = 271;
-
-  /// OpenMP teams distribute simd directive.
-  static const int CXCursor_OMPTeamsDistributeSimdDirective = 272;
-
-  /// OpenMP teams distribute parallel for simd directive.
-  static const int CXCursor_OMPTeamsDistributeParallelForSimdDirective = 273;
-
-  /// OpenMP teams distribute parallel for directive.
-  static const int CXCursor_OMPTeamsDistributeParallelForDirective = 274;
-
-  /// OpenMP target teams directive.
-  static const int CXCursor_OMPTargetTeamsDirective = 275;
-
-  /// OpenMP target teams distribute directive.
-  static const int CXCursor_OMPTargetTeamsDistributeDirective = 276;
-
-  /// OpenMP target teams distribute parallel for directive.
-  static const int CXCursor_OMPTargetTeamsDistributeParallelForDirective = 277;
-
-  /// OpenMP target teams distribute parallel for simd directive.
-  static const int CXCursor_OMPTargetTeamsDistributeParallelForSimdDirective =
-      278;
-
-  /// OpenMP target teams distribute simd directive.
-  static const int CXCursor_OMPTargetTeamsDistributeSimdDirective = 279;
-
-  /// C++2a std::bit_cast expression.
-  static const int CXCursor_BuiltinBitCastExpr = 280;
-
-  /// OpenMP master taskloop directive.
-  static const int CXCursor_OMPMasterTaskLoopDirective = 281;
-
-  /// OpenMP parallel master taskloop directive.
-  static const int CXCursor_OMPParallelMasterTaskLoopDirective = 282;
-
-  /// OpenMP master taskloop simd directive.
-  static const int CXCursor_OMPMasterTaskLoopSimdDirective = 283;
-
-  /// OpenMP parallel master taskloop simd directive.
-  static const int CXCursor_OMPParallelMasterTaskLoopSimdDirective = 284;
-
-  /// OpenMP parallel master directive.
-  static const int CXCursor_OMPParallelMasterDirective = 285;
-  static const int CXCursor_LastStmt = 285;
-
-  /// Cursor that represents the translation unit itself.
-  ///
-  /// The translation unit cursor exists primarily to act as the root
-  /// cursor for traversing the contents of a translation unit.
-  static const int CXCursor_TranslationUnit = 300;
-  static const int CXCursor_FirstAttr = 400;
-
-  /// An attribute whose specific kind is not exposed via this
-  /// interface.
-  static const int CXCursor_UnexposedAttr = 400;
-  static const int CXCursor_IBActionAttr = 401;
-  static const int CXCursor_IBOutletAttr = 402;
-  static const int CXCursor_IBOutletCollectionAttr = 403;
-  static const int CXCursor_CXXFinalAttr = 404;
-  static const int CXCursor_CXXOverrideAttr = 405;
-  static const int CXCursor_AnnotateAttr = 406;
-  static const int CXCursor_AsmLabelAttr = 407;
-  static const int CXCursor_PackedAttr = 408;
-  static const int CXCursor_PureAttr = 409;
-  static const int CXCursor_ConstAttr = 410;
-  static const int CXCursor_NoDuplicateAttr = 411;
-  static const int CXCursor_CUDAConstantAttr = 412;
-  static const int CXCursor_CUDADeviceAttr = 413;
-  static const int CXCursor_CUDAGlobalAttr = 414;
-  static const int CXCursor_CUDAHostAttr = 415;
-  static const int CXCursor_CUDASharedAttr = 416;
-  static const int CXCursor_VisibilityAttr = 417;
-  static const int CXCursor_DLLExport = 418;
-  static const int CXCursor_DLLImport = 419;
-  static const int CXCursor_NSReturnsRetained = 420;
-  static const int CXCursor_NSReturnsNotRetained = 421;
-  static const int CXCursor_NSReturnsAutoreleased = 422;
-  static const int CXCursor_NSConsumesSelf = 423;
-  static const int CXCursor_NSConsumed = 424;
-  static const int CXCursor_ObjCException = 425;
-  static const int CXCursor_ObjCNSObject = 426;
-  static const int CXCursor_ObjCIndependentClass = 427;
-  static const int CXCursor_ObjCPreciseLifetime = 428;
-  static const int CXCursor_ObjCReturnsInnerPointer = 429;
-  static const int CXCursor_ObjCRequiresSuper = 430;
-  static const int CXCursor_ObjCRootClass = 431;
-  static const int CXCursor_ObjCSubclassingRestricted = 432;
-  static const int CXCursor_ObjCExplicitProtocolImpl = 433;
-  static const int CXCursor_ObjCDesignatedInitializer = 434;
-  static const int CXCursor_ObjCRuntimeVisible = 435;
-  static const int CXCursor_ObjCBoxable = 436;
-  static const int CXCursor_FlagEnum = 437;
-  static const int CXCursor_ConvergentAttr = 438;
-  static const int CXCursor_WarnUnusedAttr = 439;
-  static const int CXCursor_WarnUnusedResultAttr = 440;
-  static const int CXCursor_AlignedAttr = 441;
-  static const int CXCursor_LastAttr = 441;
-  static const int CXCursor_PreprocessingDirective = 500;
-  static const int CXCursor_MacroDefinition = 501;
-  static const int CXCursor_MacroExpansion = 502;
-  static const int CXCursor_MacroInstantiation = 502;
-  static const int CXCursor_InclusionDirective = 503;
-  static const int CXCursor_FirstPreprocessing = 500;
-  static const int CXCursor_LastPreprocessing = 503;
-
-  /// A module import declaration.
-  static const int CXCursor_ModuleImportDecl = 600;
-  static const int CXCursor_TypeAliasTemplateDecl = 601;
-
-  /// A static_assert or _Static_assert node
-  static const int CXCursor_StaticAssert = 602;
-
-  /// a friend declaration.
-  static const int CXCursor_FriendDecl = 603;
-  static const int CXCursor_FirstExtraDecl = 600;
-  static const int CXCursor_LastExtraDecl = 603;
-
-  /// A code completion overload candidate.
-  static const int CXCursor_OverloadCandidate = 700;
-}
-
-/// A cursor representing some element in the abstract syntax tree for
-/// a translation unit.
-///
-/// The cursor abstraction unifies the different kinds of entities in a
-/// program--declaration, statements, expressions, references to declarations,
-/// etc.--under a single "cursor" abstraction with a common set of operations.
-/// Common operation for a cursor include: getting the physical location in
-/// a source file where the cursor points, getting the name associated with a
-/// cursor, and retrieving cursors for any child nodes of a particular cursor.
-///
-/// Cursors can be produced in two specific ways.
-/// clang_getTranslationUnitCursor() produces a cursor for a translation unit,
-/// from which one can use clang_visitChildren() to explore the rest of the
-/// translation unit. clang_getCursor() maps from a physical source location
-/// to the entity that resides at that location, allowing one to map from the
-/// source code into the AST.
-class CXCursor extends ffi.Struct {
-  @ffi.Int32()
-  external int kind;
-
-  @ffi.Int()
-  external int xdata;
-
-  @ffi.Array.multi([3])
-  external ffi.Array<ffi.Pointer<ffi.Void>> data;
-}
-
-/// Describes the kind of type
-abstract class CXTypeKind {
-  /// Represents an invalid type (e.g., where no type is available).
-  static const int CXType_Invalid = 0;
-
-  /// A type whose specific kind is not exposed via this
-  /// interface.
-  static const int CXType_Unexposed = 1;
-  static const int CXType_Void = 2;
-  static const int CXType_Bool = 3;
-  static const int CXType_Char_U = 4;
-  static const int CXType_UChar = 5;
-  static const int CXType_Char16 = 6;
-  static const int CXType_Char32 = 7;
-  static const int CXType_UShort = 8;
-  static const int CXType_UInt = 9;
-  static const int CXType_ULong = 10;
-  static const int CXType_ULongLong = 11;
-  static const int CXType_UInt128 = 12;
-  static const int CXType_Char_S = 13;
-  static const int CXType_SChar = 14;
-  static const int CXType_WChar = 15;
-  static const int CXType_Short = 16;
-  static const int CXType_Int = 17;
-  static const int CXType_Long = 18;
-  static const int CXType_LongLong = 19;
-  static const int CXType_Int128 = 20;
-  static const int CXType_Float = 21;
-  static const int CXType_Double = 22;
-  static const int CXType_LongDouble = 23;
-  static const int CXType_NullPtr = 24;
-  static const int CXType_Overload = 25;
-  static const int CXType_Dependent = 26;
-  static const int CXType_ObjCId = 27;
-  static const int CXType_ObjCClass = 28;
-  static const int CXType_ObjCSel = 29;
-  static const int CXType_Float128 = 30;
-  static const int CXType_Half = 31;
-  static const int CXType_Float16 = 32;
-  static const int CXType_ShortAccum = 33;
-  static const int CXType_Accum = 34;
-  static const int CXType_LongAccum = 35;
-  static const int CXType_UShortAccum = 36;
-  static const int CXType_UAccum = 37;
-  static const int CXType_ULongAccum = 38;
-  static const int CXType_FirstBuiltin = 2;
-  static const int CXType_LastBuiltin = 38;
-  static const int CXType_Complex = 100;
-  static const int CXType_Pointer = 101;
-  static const int CXType_BlockPointer = 102;
-  static const int CXType_LValueReference = 103;
-  static const int CXType_RValueReference = 104;
-  static const int CXType_Record = 105;
-  static const int CXType_Enum = 106;
-  static const int CXType_Typedef = 107;
-  static const int CXType_ObjCInterface = 108;
-  static const int CXType_ObjCObjectPointer = 109;
-  static const int CXType_FunctionNoProto = 110;
-  static const int CXType_FunctionProto = 111;
-  static const int CXType_ConstantArray = 112;
-  static const int CXType_Vector = 113;
-  static const int CXType_IncompleteArray = 114;
-  static const int CXType_VariableArray = 115;
-  static const int CXType_DependentSizedArray = 116;
-  static const int CXType_MemberPointer = 117;
-  static const int CXType_Auto = 118;
-
-  /// Represents a type that was referred to using an elaborated type keyword.
-  ///
-  /// E.g., struct S, or via a qualified name, e.g., N::M::type, or both.
-  static const int CXType_Elaborated = 119;
-  static const int CXType_Pipe = 120;
-  static const int CXType_OCLImage1dRO = 121;
-  static const int CXType_OCLImage1dArrayRO = 122;
-  static const int CXType_OCLImage1dBufferRO = 123;
-  static const int CXType_OCLImage2dRO = 124;
-  static const int CXType_OCLImage2dArrayRO = 125;
-  static const int CXType_OCLImage2dDepthRO = 126;
-  static const int CXType_OCLImage2dArrayDepthRO = 127;
-  static const int CXType_OCLImage2dMSAARO = 128;
-  static const int CXType_OCLImage2dArrayMSAARO = 129;
-  static const int CXType_OCLImage2dMSAADepthRO = 130;
-  static const int CXType_OCLImage2dArrayMSAADepthRO = 131;
-  static const int CXType_OCLImage3dRO = 132;
-  static const int CXType_OCLImage1dWO = 133;
-  static const int CXType_OCLImage1dArrayWO = 134;
-  static const int CXType_OCLImage1dBufferWO = 135;
-  static const int CXType_OCLImage2dWO = 136;
-  static const int CXType_OCLImage2dArrayWO = 137;
-  static const int CXType_OCLImage2dDepthWO = 138;
-  static const int CXType_OCLImage2dArrayDepthWO = 139;
-  static const int CXType_OCLImage2dMSAAWO = 140;
-  static const int CXType_OCLImage2dArrayMSAAWO = 141;
-  static const int CXType_OCLImage2dMSAADepthWO = 142;
-  static const int CXType_OCLImage2dArrayMSAADepthWO = 143;
-  static const int CXType_OCLImage3dWO = 144;
-  static const int CXType_OCLImage1dRW = 145;
-  static const int CXType_OCLImage1dArrayRW = 146;
-  static const int CXType_OCLImage1dBufferRW = 147;
-  static const int CXType_OCLImage2dRW = 148;
-  static const int CXType_OCLImage2dArrayRW = 149;
-  static const int CXType_OCLImage2dDepthRW = 150;
-  static const int CXType_OCLImage2dArrayDepthRW = 151;
-  static const int CXType_OCLImage2dMSAARW = 152;
-  static const int CXType_OCLImage2dArrayMSAARW = 153;
-  static const int CXType_OCLImage2dMSAADepthRW = 154;
-  static const int CXType_OCLImage2dArrayMSAADepthRW = 155;
-  static const int CXType_OCLImage3dRW = 156;
-  static const int CXType_OCLSampler = 157;
-  static const int CXType_OCLEvent = 158;
-  static const int CXType_OCLQueue = 159;
-  static const int CXType_OCLReserveID = 160;
-  static const int CXType_ObjCObject = 161;
-  static const int CXType_ObjCTypeParam = 162;
-  static const int CXType_Attributed = 163;
-  static const int CXType_OCLIntelSubgroupAVCMcePayload = 164;
-  static const int CXType_OCLIntelSubgroupAVCImePayload = 165;
-  static const int CXType_OCLIntelSubgroupAVCRefPayload = 166;
-  static const int CXType_OCLIntelSubgroupAVCSicPayload = 167;
-  static const int CXType_OCLIntelSubgroupAVCMceResult = 168;
-  static const int CXType_OCLIntelSubgroupAVCImeResult = 169;
-  static const int CXType_OCLIntelSubgroupAVCRefResult = 170;
-  static const int CXType_OCLIntelSubgroupAVCSicResult = 171;
-  static const int CXType_OCLIntelSubgroupAVCImeResultSingleRefStreamout = 172;
-  static const int CXType_OCLIntelSubgroupAVCImeResultDualRefStreamout = 173;
-  static const int CXType_OCLIntelSubgroupAVCImeSingleRefStreamin = 174;
-  static const int CXType_OCLIntelSubgroupAVCImeDualRefStreamin = 175;
-  static const int CXType_ExtVector = 176;
-}
-
-/// The type of an element in the abstract syntax tree.
-class CXType extends ffi.Struct {
-  @ffi.Int32()
-  external int kind;
-
-  @ffi.Array.multi([2])
-  external ffi.Array<ffi.Pointer<ffi.Void>> data;
-}
-
-abstract class CXTypeNullabilityKind {
-  /// Values of this type can never be null.
-  static const int CXTypeNullability_NonNull = 0;
-
-  /// Values of this type can be null.
-  static const int CXTypeNullability_Nullable = 1;
-
-  /// Whether values of this type can be null is (explicitly)
-  /// unspecified. This captures a (fairly rare) case where we
-  /// can't conclude anything about the nullability of the type even
-  /// though it has been considered.
-  static const int CXTypeNullability_Unspecified = 2;
-
-  /// Nullability is not applicable to this type.
-  static const int CXTypeNullability_Invalid = 3;
-}
-
-/// Describes how the traversal of the children of a particular
-/// cursor should proceed after visiting a particular child cursor.
-///
-/// A value of this enumeration type should be returned by each
-/// \c CXCursorVisitor to indicate how clang_visitChildren() proceed.
-abstract class CXChildVisitResult {
-  /// Terminates the cursor traversal.
-  static const int CXChildVisit_Break = 0;
-
-  /// Continues the cursor traversal with the next sibling of
-  /// the cursor just visited, without visiting its children.
-  static const int CXChildVisit_Continue = 1;
-
-  /// Recursively traverse the children of this cursor, using
-  /// the same visitor and client data.
-  static const int CXChildVisit_Recurse = 2;
-}
-
-/// Visitor invoked for each cursor found by a traversal.
-///
-/// This visitor function will be invoked for each cursor found by
-/// clang_visitCursorChildren(). Its first argument is the cursor being
-/// visited, its second argument is the parent visitor for that cursor,
-/// and its third argument is the client data provided to
-/// clang_visitCursorChildren().
-///
-/// The visitor should return one of the \c CXChildVisitResult values
-/// to direct clang_visitCursorChildren().
-typedef CXCursorVisitor = ffi.Pointer<
-    ffi.NativeFunction<ffi.Int32 Function(CXCursor, CXCursor, CXClientData)>>;
-
-/// Opaque pointer representing client data that will be passed through
-/// to various callbacks and visitors.
-typedef CXClientData = ffi.Pointer<ffi.Void>;
-
-/// Property attributes for a \c CXCursor_ObjCPropertyDecl.
-abstract class CXObjCPropertyAttrKind {
-  static const int CXObjCPropertyAttr_noattr = 0;
-  static const int CXObjCPropertyAttr_readonly = 1;
-  static const int CXObjCPropertyAttr_getter = 2;
-  static const int CXObjCPropertyAttr_assign = 4;
-  static const int CXObjCPropertyAttr_readwrite = 8;
-  static const int CXObjCPropertyAttr_retain = 16;
-  static const int CXObjCPropertyAttr_copy = 32;
-  static const int CXObjCPropertyAttr_nonatomic = 64;
-  static const int CXObjCPropertyAttr_setter = 128;
-  static const int CXObjCPropertyAttr_atomic = 256;
-  static const int CXObjCPropertyAttr_weak = 512;
-  static const int CXObjCPropertyAttr_strong = 1024;
-  static const int CXObjCPropertyAttr_unsafe_unretained = 2048;
-  static const int CXObjCPropertyAttr_class = 4096;
-}
-
-abstract class CXEvalResultKind {
-  static const int CXEval_Int = 1;
-  static const int CXEval_Float = 2;
-  static const int CXEval_ObjCStrLiteral = 3;
-  static const int CXEval_StrLiteral = 4;
-  static const int CXEval_CFStr = 5;
-  static const int CXEval_Other = 6;
-  static const int CXEval_UnExposed = 0;
-}
-
-/// Evaluation result of a cursor
-typedef CXEvalResult = ffi.Pointer<ffi.Void>;
-
-const int CINDEX_VERSION_MAJOR = 0;
-
-const int CINDEX_VERSION_MINOR = 59;
-
-const int CINDEX_VERSION = 59;
-
-const String CINDEX_VERSION_STRING = '0.59';
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/data.dart b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/data.dart
deleted file mode 100644
index 1381fd3..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/data.dart
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright (c) 2020, 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.
-
-import 'dart:ffi';
-
-import 'package:ffigen/src/code_generator.dart'
-    show Constant, ObjCBuiltInFunctions;
-import 'package:ffigen/src/config_provider.dart' show Config;
-import 'clang_bindings/clang_bindings.dart' show Clang;
-
-import 'utils.dart';
-
-/// Holds all Global shared variables.
-
-/// Holds configurations.
-Config get config => _config;
-late Config _config;
-
-/// Holds clang functions.
-Clang get clang => _clang;
-late Clang _clang;
-
-// Tracks seen status for bindings
-BindingsIndex get bindingsIndex => _bindingsIndex;
-BindingsIndex _bindingsIndex = BindingsIndex();
-
-/// Used for naming typedefs.
-IncrementalNamer get incrementalNamer => _incrementalNamer;
-IncrementalNamer _incrementalNamer = IncrementalNamer();
-
-/// Saved macros, Key: prefixedName, Value originalName.
-Map<String, Macro> get savedMacros => _savedMacros;
-Map<String, Macro> _savedMacros = {};
-
-/// Saved unnamed EnumConstants.
-List<Constant> get unnamedEnumConstants => _unnamedEnumConstants;
-List<Constant> _unnamedEnumConstants = [];
-
-/// Built in functions used by the Objective C bindings.
-ObjCBuiltInFunctions get objCBuiltInFunctions => _objCBuiltInFunctions;
-late ObjCBuiltInFunctions _objCBuiltInFunctions;
-
-void initializeGlobals({required Config config}) {
-  _config = config;
-  _clang = Clang(DynamicLibrary.open(config.libclangDylib));
-  _incrementalNamer = IncrementalNamer();
-  _savedMacros = {};
-  _unnamedEnumConstants = [];
-  _bindingsIndex = BindingsIndex();
-  _objCBuiltInFunctions = ObjCBuiltInFunctions();
-}
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/includer.dart b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/includer.dart
deleted file mode 100644
index a9041a6..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/includer.dart
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright (c) 2020, 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.
-
-/// Utility functions to check whether a binding should be parsed or not
-/// based on filters.
-
-import '../config_provider/config_types.dart';
-import '../strings.dart' as strings;
-import 'data.dart';
-
-bool _shouldIncludeDecl(String usr, String name,
-    bool Function(String) isSeenDecl, bool Function(String) configIncludes) {
-  if (isSeenDecl(usr) || name == '') {
-    return false;
-  } else if (configIncludes(name)) {
-    return true;
-  } else {
-    return false;
-  }
-}
-
-bool shouldIncludeStruct(String usr, String name) {
-  return _shouldIncludeDecl(
-      usr, name, bindingsIndex.isSeenType, config.structDecl.shouldInclude);
-}
-
-bool shouldIncludeUnion(String usr, String name) {
-  return _shouldIncludeDecl(
-      usr, name, bindingsIndex.isSeenType, config.unionDecl.shouldInclude);
-}
-
-bool shouldIncludeFunc(String usr, String name) {
-  return _shouldIncludeDecl(
-      usr, name, bindingsIndex.isSeenType, config.functionDecl.shouldInclude);
-}
-
-bool shouldIncludeEnumClass(String usr, String name) {
-  return _shouldIncludeDecl(
-      usr, name, bindingsIndex.isSeenType, config.enumClassDecl.shouldInclude);
-}
-
-bool shouldIncludeUnnamedEnumConstant(String usr, String name) {
-  return _shouldIncludeDecl(usr, name, bindingsIndex.isSeenUnnamedEnumConstant,
-      config.unnamedEnumConstants.shouldInclude);
-}
-
-bool shouldIncludeGlobalVar(String usr, String name) {
-  return _shouldIncludeDecl(
-      usr, name, bindingsIndex.isSeenGlobalVar, config.globals.shouldInclude);
-}
-
-bool shouldIncludeMacro(String usr, String name) {
-  return _shouldIncludeDecl(
-      usr, name, bindingsIndex.isSeenMacro, config.macroDecl.shouldInclude);
-}
-
-bool shouldIncludeTypealias(String usr, String name) {
-  return _shouldIncludeDecl(
-      usr, name, bindingsIndex.isSeenType, config.typedefs.shouldInclude);
-}
-
-bool shouldIncludeObjCInterface(String usr, String name) {
-  return _shouldIncludeDecl(
-      usr, name, bindingsIndex.isSeenType, config.objcInterfaces.shouldInclude);
-}
-
-/// True if a cursor should be included based on headers config, used on root
-/// declarations.
-bool shouldIncludeRootCursor(String sourceFile) {
-  // Handle empty string in case of system headers or macros.
-  if (sourceFile.isEmpty) {
-    return false;
-  }
-
-  // Objective C has some extra system headers that have a non-empty sourceFile.
-  if (config.language == Language.objc &&
-      strings.objCInternalDirectories
-          .any((path) => sourceFile.startsWith(path))) {
-    return false;
-  }
-
-  // Add header to seen if it's not.
-  if (!bindingsIndex.isSeenHeader(sourceFile)) {
-    bindingsIndex.addHeaderToSeen(
-        sourceFile, config.headers.includeFilter.shouldInclude(sourceFile));
-  }
-
-  return bindingsIndex.getSeenHeaderStatus(sourceFile)!;
-}
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/parser.dart b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/parser.dart
deleted file mode 100644
index 2adbb0b..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/parser.dart
+++ /dev/null
@@ -1,121 +0,0 @@
-// Copyright (c) 2020, 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.
-
-import 'dart:ffi';
-
-import 'package:ffi/ffi.dart';
-import 'package:ffigen/src/code_generator.dart';
-import 'package:ffigen/src/config_provider.dart';
-import 'package:ffigen/src/config_provider/config_types.dart';
-import 'package:ffigen/src/header_parser/sub_parsers/macro_parser.dart';
-import 'package:ffigen/src/header_parser/translation_unit_parser.dart';
-import 'package:ffigen/src/strings.dart' as strings;
-import 'package:logging/logging.dart';
-
-import 'clang_bindings/clang_bindings.dart' as clang_types;
-import 'data.dart';
-import 'utils.dart';
-
-/// Main entrypoint for header_parser.
-Library parse(Config c) {
-  initParser(c);
-
-  final bindings = parseToBindings();
-
-  final library = Library(
-    bindings: bindings,
-    name: config.wrapperName,
-    description: config.wrapperDocComment,
-    header: config.preamble,
-    sort: config.sort,
-    packingOverride: config.structPackingOverride,
-    libraryImports: c.libraryImports.values.toSet(),
-  );
-
-  return library;
-}
-
-// ===================================================================================
-//           BELOW FUNCTIONS ARE MEANT FOR INTERNAL USE AND TESTING
-// ===================================================================================
-
-final _logger = Logger('ffigen.header_parser.parser');
-
-/// Initializes parser, clears any previous values.
-void initParser(Config c) {
-  // Initialize global variables.
-  initializeGlobals(
-    config: c,
-  );
-}
-
-/// Parses source files and adds generated bindings to [bindings].
-List<Binding> parseToBindings() {
-  final index = clang.clang_createIndex(0, 0);
-
-  Pointer<Pointer<Utf8>> clangCmdArgs = nullptr;
-  final compilerOpts = List<String>.from(config.compilerOpts);
-
-  /// Add compiler opt for comment parsing for clang based on config.
-  if (config.commentType.length != CommentLength.none &&
-      config.commentType.style == CommentStyle.any) {
-    compilerOpts.add(strings.fparseAllComments);
-  }
-
-  /// If the config targets Objective C, add a compiler opt for it.
-  if (config.language == Language.objc) {
-    compilerOpts.addAll(strings.clangLangObjC);
-  }
-
-  _logger.fine('CompilerOpts used: $compilerOpts');
-  clangCmdArgs = createDynamicStringArray(compilerOpts);
-  final cmdLen = compilerOpts.length;
-
-  // Contains all bindings. A set ensures we never have duplicates.
-  final bindings = <Binding>{};
-
-  // Log all headers for user.
-  _logger.info('Input Headers: ${config.headers.entryPoints}');
-
-  for (final headerLocation in config.headers.entryPoints) {
-    _logger.fine('Creating TranslationUnit for header: $headerLocation');
-
-    final tu = clang.clang_parseTranslationUnit(
-      index,
-      headerLocation.toNativeUtf8().cast(),
-      clangCmdArgs.cast(),
-      cmdLen,
-      nullptr,
-      0,
-      clang_types.CXTranslationUnit_Flags.CXTranslationUnit_SkipFunctionBodies |
-          clang_types.CXTranslationUnit_Flags
-              .CXTranslationUnit_DetailedPreprocessingRecord,
-    );
-
-    if (tu == nullptr) {
-      _logger.severe(
-          "Skipped header/file: $headerLocation, couldn't parse source.");
-      // Skip parsing this header.
-      continue;
-    }
-
-    logTuDiagnostics(tu, _logger, headerLocation);
-    final rootCursor = clang.clang_getTranslationUnitCursor(tu);
-
-    bindings.addAll(parseTranslationUnit(rootCursor));
-
-    // Cleanup.
-    clang.clang_disposeTranslationUnit(tu);
-  }
-
-  // Add all saved unnamed enums.
-  bindings.addAll(unnamedEnumConstants);
-
-  // Parse all saved macros.
-  bindings.addAll(parseSavedMacros()!);
-
-  clangCmdArgs.dispose(cmdLen);
-  clang.clang_disposeIndex(index);
-  return bindings.toList();
-}
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/sub_parsers/compounddecl_parser.dart b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/sub_parsers/compounddecl_parser.dart
deleted file mode 100644
index a21d6e2..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/sub_parsers/compounddecl_parser.dart
+++ /dev/null
@@ -1,318 +0,0 @@
-// Copyright (c) 2021, 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.
-
-import 'dart:ffi';
-
-import 'package:ffigen/src/code_generator.dart';
-import 'package:ffigen/src/config_provider/config_types.dart';
-import 'package:logging/logging.dart';
-
-import '../../strings.dart' as strings;
-import '../clang_bindings/clang_bindings.dart' as clang_types;
-import '../data.dart';
-import '../includer.dart';
-import '../utils.dart';
-
-final _logger = Logger('ffigen.header_parser.compounddecl_parser');
-
-/// Holds temporary information regarding [compound] while parsing.
-class _ParsedCompound {
-  Compound compound;
-  bool unimplementedMemberType = false;
-  bool flexibleArrayMember = false;
-  bool bitFieldMember = false;
-  bool dartHandleMember = false;
-  bool incompleteCompoundMember = false;
-
-  _ParsedCompound(this.compound);
-
-  bool get isIncomplete =>
-      unimplementedMemberType ||
-      flexibleArrayMember ||
-      bitFieldMember ||
-      (dartHandleMember && config.useDartHandle) ||
-      incompleteCompoundMember;
-
-  // A struct without any attribute is definitely not packed. #pragma pack(...)
-  // also adds an attribute, but it's unexposed and cannot be travesed.
-  bool hasAttr = false;
-  // A struct which as a __packed__ attribute is definitely packed.
-  bool hasPackedAttr = false;
-  // Stores the maximum alignment from all the children.
-  int maxChildAlignment = 0;
-  // Alignment of this struct.
-  int alignment = 0;
-
-  bool get _isPacked {
-    if (!hasAttr || isIncomplete) return false;
-    if (hasPackedAttr) return true;
-
-    return maxChildAlignment > alignment;
-  }
-
-  /// Returns pack value of a struct depending on config, returns null for no
-  /// packing.
-  int? get packValue {
-    if (compound.isStruct && _isPacked) {
-      if (strings.packingValuesMap.containsKey(alignment)) {
-        return alignment;
-      } else {
-        _logger.warning(
-            'Unsupported pack value "$alignment" for Struct "${compound.name}".');
-        return null;
-      }
-    } else {
-      return null;
-    }
-  }
-}
-
-final _stack = Stack<_ParsedCompound>();
-
-/// Parses a compound declaration.
-Compound? parseCompoundDeclaration(
-  clang_types.CXCursor cursor,
-  CompoundType compoundType, {
-  /// Option to ignore declaration filter (Useful in case of extracting
-  /// declarations when they are passed/returned by an included function.)
-  bool ignoreFilter = false,
-
-  /// To track if the declaration was used by reference(i.e T*). (Used to only
-  /// generate these as opaque if `dependency-only` was set to opaque).
-  bool pointerReference = false,
-}) {
-  // Set includer functions according to compoundType.
-  final bool Function(String, String) shouldIncludeDecl;
-  final Declaration configDecl;
-  final String className = _compoundTypeDebugName(compoundType);
-  switch (compoundType) {
-    case CompoundType.struct:
-      shouldIncludeDecl = shouldIncludeStruct;
-      configDecl = config.structDecl;
-      break;
-    case CompoundType.union:
-      shouldIncludeDecl = shouldIncludeUnion;
-      configDecl = config.unionDecl;
-      break;
-  }
-
-  // Parse the cursor definition instead, if this is a forward declaration.
-  if (isForwardDeclaration(cursor)) {
-    cursor = clang.clang_getCursorDefinition(cursor);
-  }
-  final declUsr = cursor.usr();
-  final String declName;
-
-  // Only set name using USR if the type is not Anonymous (A struct is anonymous
-  // if it has no name, is not inside any typedef and declared inline inside
-  // another declaration).
-  if (clang.clang_Cursor_isAnonymous(cursor) == 0) {
-    // This gives the significant name, i.e name of the struct if defined or
-    // name of the first typedef declaration that refers to it.
-    declName = declUsr.split('@').last;
-  } else {
-    // Empty names are treated as inline declarations.
-    declName = '';
-  }
-
-  if (declName.isEmpty) {
-    if (ignoreFilter) {
-      // This declaration is defined inside some other declaration and hence
-      // must be generated.
-      return Compound.fromType(
-        type: compoundType,
-        name: incrementalNamer.name('Unnamed$className'),
-        usr: declUsr,
-        dartDoc: getCursorDocComment(cursor),
-      );
-    } else {
-      _logger.finest('unnamed $className declaration');
-    }
-  } else if (ignoreFilter || shouldIncludeDecl(declUsr, declName)) {
-    _logger.fine(
-        '++++ Adding $className: Name: $declName, ${cursor.completeStringRepr()}');
-    return Compound.fromType(
-      type: compoundType,
-      usr: declUsr,
-      originalName: declName,
-      name: configDecl.renameUsingConfig(declName),
-      dartDoc: getCursorDocComment(cursor),
-    );
-  }
-  return null;
-}
-
-void fillCompoundMembersIfNeeded(
-  Compound compound,
-  clang_types.CXCursor cursor, {
-  /// Option to ignore declaration filter (Useful in case of extracting
-  /// declarations when they are passed/returned by an included function.)
-  bool ignoreFilter = false,
-
-  /// To track if the declaration was used by reference(i.e T*). (Used to only
-  /// generate these as opaque if `dependency-only` was set to opaque).
-  bool pointerReference = false,
-}) {
-  final compoundType = compound.compoundType;
-
-  // Skip dependencies if already seen OR user has specified `dependency-only`
-  // as opaque AND this is a pointer reference AND the declaration was not
-  // included according to config (ignoreFilter).
-  final skipDependencies = compound.parsedDependencies ||
-      (pointerReference &&
-          ignoreFilter &&
-          ((compoundType == CompoundType.struct &&
-                  config.structDependencies == CompoundDependencies.opaque) ||
-              (compoundType == CompoundType.union &&
-                  config.unionDependencies == CompoundDependencies.opaque)));
-  if (skipDependencies) return;
-
-  final parsed = _ParsedCompound(compound);
-  final String className = _compoundTypeDebugName(compoundType);
-  parsed.hasAttr = clang.clang_Cursor_hasAttrs(cursor) != 0;
-  parsed.alignment = cursor.type().alignment();
-  compound.parsedDependencies = true; // Break cycles.
-
-  _stack.push(parsed);
-  final resultCode = clang.clang_visitChildren(
-    cursor,
-    Pointer.fromFunction(_compoundMembersVisitor, exceptional_visitor_return),
-    nullptr,
-  );
-  _stack.pop();
-
-  _logger.finest(
-      'Opaque: ${parsed.isIncomplete}, HasAttr: ${parsed.hasAttr}, AlignValue: ${parsed.alignment}, MaxChildAlignValue: ${parsed.maxChildAlignment}, PackValue: ${parsed.packValue}.');
-  compound.pack = parsed.packValue;
-
-  visitChildrenResultChecker(resultCode);
-
-  if (parsed.unimplementedMemberType) {
-    _logger.fine(
-        '---- Removed $className members, reason: member with unimplementedtype ${cursor.completeStringRepr()}');
-    _logger.warning(
-        'Removed All $className Members from ${compound.name}(${compound.originalName}), struct member has an unsupported type.');
-  } else if (parsed.flexibleArrayMember) {
-    _logger.fine(
-        '---- Removed $className members, reason: incomplete array member ${cursor.completeStringRepr()}');
-    _logger.warning(
-        'Removed All $className Members from ${compound.name}(${compound.originalName}), Flexible array members not supported.');
-  } else if (parsed.bitFieldMember) {
-    _logger.fine(
-        '---- Removed $className members, reason: bitfield members ${cursor.completeStringRepr()}');
-    _logger.warning(
-        'Removed All $className Members from ${compound.name}(${compound.originalName}), Bit Field members not supported.');
-  } else if (parsed.dartHandleMember && config.useDartHandle) {
-    _logger.fine(
-        '---- Removed $className members, reason: Dart_Handle member. ${cursor.completeStringRepr()}');
-    _logger.warning(
-        'Removed All $className Members from ${compound.name}(${compound.originalName}), Dart_Handle member not supported.');
-  } else if (parsed.incompleteCompoundMember) {
-    _logger.fine(
-        '---- Removed $className members, reason: Incomplete Nested Struct member. ${cursor.completeStringRepr()}');
-    _logger.warning(
-        'Removed All $className Members from ${compound.name}(${compound.originalName}), Incomplete Nested Struct member not supported.');
-  }
-
-  // Clear all members if declaration is incomplete.
-  if (parsed.isIncomplete) {
-    compound.members.clear();
-  }
-
-  // C allows empty structs/union, but it's undefined behaviour at runtine.
-  // So we need to mark a declaration incomplete if it has no members.
-  compound.isIncomplete = parsed.isIncomplete || compound.members.isEmpty;
-}
-
-// I've written worse hacks than this
-final List<String> _paramNames = [];
-
-int _fnPtrFieldVisitor(clang_types.CXCursor cursor, clang_types.CXCursor parent,
-    Pointer<Void> clientData) {
-  if (cursor.kind == clang_types.CXCursorKind.CXCursor_ParmDecl) {
-    final spelling = cursor.spelling();
-    if (spelling.isNotEmpty) {
-      _paramNames.add(spelling);
-    }
-  }
-  return clang_types.CXChildVisitResult.CXChildVisit_Continue;
-}
-
-/// Visitor for the struct/union cursor [CXCursorKind.CXCursor_StructDecl]/
-/// [CXCursorKind.CXCursor_UnionDecl].
-///
-/// Child visitor invoked on struct/union cursor.
-int _compoundMembersVisitor(clang_types.CXCursor cursor,
-    clang_types.CXCursor parent, Pointer<Void> clientData) {
-  final parsed = _stack.top;
-  try {
-    if (cursor.kind == clang_types.CXCursorKind.CXCursor_FieldDecl) {
-      _logger.finer('===== member: ${cursor.completeStringRepr()}');
-      // Set maxChildAlignValue.
-      final align = cursor.type().alignment();
-      if (align > parsed.maxChildAlignment) {
-        parsed.maxChildAlignment = align;
-      }
-      final mt = cursor.type().toCodeGenType();
-      List<String>? params;
-      if (mt is PointerType && mt.child is NativeFunc) {
-        clang.clang_visitChildren(
-            cursor,
-            Pointer.fromFunction(
-                _fnPtrFieldVisitor, exceptional_visitor_return),
-            nullptr);
-        final natFn = mt.child as NativeFunc;
-        final fnType = natFn.type as FunctionType;
-        if (_paramNames.length == fnType.parameters.length) {
-          params = _paramNames.toList();
-        }
-        _paramNames.clear();
-      }
-      if (mt is IncompleteArray) {
-        // TODO(68): Structs with flexible Array Members are not supported.
-        parsed.flexibleArrayMember = true;
-      }
-      if (clang.clang_getFieldDeclBitWidth(cursor) != -1) {
-        // TODO(84): Struct with bitfields are not suppoorted.
-        parsed.bitFieldMember = true;
-      }
-      if (mt is HandleType) {
-        parsed.dartHandleMember = true;
-      }
-      if (mt.isIncompleteCompound) {
-        parsed.incompleteCompoundMember = true;
-      }
-      if (mt.baseType is UnimplementedType) {
-        parsed.unimplementedMemberType = true;
-      }
-
-      parsed.compound.members.add(
-        Member(
-          dartDoc: getCursorDocComment(
-            cursor,
-            nesting.length + commentPrefix.length,
-          ),
-          originalName: cursor.spelling(),
-          name: config.structDecl.renameMemberUsingConfig(
-            parsed.compound.originalName,
-            cursor.spelling(),
-          ),
-          type: mt,
-          params: params,
-        ),
-      );
-    } else if (cursor.kind == clang_types.CXCursorKind.CXCursor_PackedAttr) {
-      parsed.hasPackedAttr = true;
-    }
-  } catch (e, s) {
-    _logger.severe(e);
-    _logger.severe(s);
-    rethrow;
-  }
-  return clang_types.CXChildVisitResult.CXChildVisit_Continue;
-}
-
-String _compoundTypeDebugName(CompoundType compoundType) {
-  return compoundType == CompoundType.struct ? "Struct" : "Union";
-}
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/sub_parsers/enumdecl_parser.dart b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/sub_parsers/enumdecl_parser.dart
deleted file mode 100644
index 68012ed..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/sub_parsers/enumdecl_parser.dart
+++ /dev/null
@@ -1,118 +0,0 @@
-// Copyright (c) 2020, 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.
-
-import 'dart:ffi';
-
-import 'package:ffigen/src/code_generator.dart';
-import 'package:ffigen/src/header_parser/data.dart';
-import 'package:ffigen/src/header_parser/sub_parsers/unnamed_enumdecl_parser.dart';
-import 'package:logging/logging.dart';
-
-import '../clang_bindings/clang_bindings.dart' as clang_types;
-import '../data.dart';
-import '../includer.dart';
-import '../utils.dart';
-
-final _logger = Logger('ffigen.header_parser.enumdecl_parser');
-
-/// Holds temporary information regarding [EnumClass] while parsing.
-class _ParsedEnum {
-  EnumClass? enumClass;
-  _ParsedEnum();
-}
-
-final _stack = Stack<_ParsedEnum>();
-
-/// Parses an enum declaration.
-EnumClass? parseEnumDeclaration(
-  clang_types.CXCursor cursor, {
-  /// Option to ignore declaration filter (Useful in case of extracting
-  /// declarations when they are passed/returned by an included function.)
-  bool ignoreFilter = false,
-}) {
-  _stack.push(_ParsedEnum());
-
-  // Parse the cursor definition instead, if this is a forward declaration.
-  if (isForwardDeclaration(cursor)) {
-    cursor = clang.clang_getCursorDefinition(cursor);
-  }
-
-  final enumUsr = cursor.usr();
-  final String enumName;
-  // Only set name using USR if the type is not Anonymous (i.e not inside
-  // any typedef and declared inplace inside another type).
-  if (clang.clang_Cursor_isAnonymous(cursor) == 0) {
-    // This gives the significant name, i.e name of the enum if defined or
-    // name of the first typedef declaration that refers to it.
-    enumName = enumUsr.split('@').last;
-  } else {
-    enumName = '';
-  }
-
-  if (enumName.isEmpty) {
-    _logger.fine('Saving anonymous enum.');
-    saveUnNamedEnum(cursor);
-  } else if (ignoreFilter || shouldIncludeEnumClass(enumUsr, enumName)) {
-    _logger.fine('++++ Adding Enum: ${cursor.completeStringRepr()}');
-    _stack.top.enumClass = EnumClass(
-      usr: enumUsr,
-      dartDoc: getCursorDocComment(cursor),
-      originalName: enumName,
-      name: config.enumClassDecl.renameUsingConfig(enumName),
-    );
-    _addEnumConstant(cursor);
-  }
-
-  return _stack.pop().enumClass;
-}
-
-void _addEnumConstant(clang_types.CXCursor cursor) {
-  final resultCode = clang.clang_visitChildren(
-    cursor,
-    Pointer.fromFunction(_enumCursorVisitor, exceptional_visitor_return),
-    nullptr,
-  );
-
-  visitChildrenResultChecker(resultCode);
-}
-
-/// Visitor for a enum cursor [clang.CXCursorKind.CXCursor_EnumDecl].
-///
-/// Invoked on every enum directly under rootCursor.
-/// Used for for extracting enum values.
-int _enumCursorVisitor(clang_types.CXCursor cursor, clang_types.CXCursor parent,
-    Pointer<Void> clientData) {
-  try {
-    _logger.finest('  enumCursorVisitor: ${cursor.completeStringRepr()}');
-    switch (clang.clang_getCursorKind(cursor)) {
-      case clang_types.CXCursorKind.CXCursor_EnumConstantDecl:
-        _addEnumConstantToEnumClass(cursor);
-        break;
-      default:
-        _logger.fine('invalid enum constant');
-    }
-  } catch (e, s) {
-    _logger.severe(e);
-    _logger.severe(s);
-    rethrow;
-  }
-  return clang_types.CXChildVisitResult.CXChildVisit_Continue;
-}
-
-/// Adds the parameter to func in [functiondecl_parser.dart].
-void _addEnumConstantToEnumClass(clang_types.CXCursor cursor) {
-  _stack.top.enumClass!.enumConstants.add(
-    EnumConstant(
-        dartDoc: getCursorDocComment(
-          cursor,
-          nesting.length + commentPrefix.length,
-        ),
-        originalName: cursor.spelling(),
-        name: config.enumClassDecl.renameMemberUsingConfig(
-          _stack.top.enumClass!.originalName,
-          cursor.spelling(),
-        ),
-        value: clang.clang_getEnumConstantDeclValue(cursor)),
-  );
-}
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/sub_parsers/functiondecl_parser.dart b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/sub_parsers/functiondecl_parser.dart
deleted file mode 100644
index b4c40fc..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/sub_parsers/functiondecl_parser.dart
+++ /dev/null
@@ -1,130 +0,0 @@
-// Copyright (c) 2020, 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.
-
-import 'package:ffigen/src/code_generator.dart';
-import 'package:ffigen/src/header_parser/data.dart';
-import 'package:logging/logging.dart';
-
-import '../clang_bindings/clang_bindings.dart' as clang_types;
-import '../includer.dart';
-import '../utils.dart';
-
-final _logger = Logger('ffigen.header_parser.functiondecl_parser');
-
-/// Holds temporary information regarding [Func] while parsing.
-class _ParserFunc {
-  Func? func;
-  bool incompleteStructParameter = false;
-  bool unimplementedParameterType = false;
-  _ParserFunc();
-}
-
-final _stack = Stack<_ParserFunc>();
-
-/// Parses a function declaration.
-Func? parseFunctionDeclaration(clang_types.CXCursor cursor) {
-  _stack.push(_ParserFunc());
-
-  final funcUsr = cursor.usr();
-  final funcName = cursor.spelling();
-  if (shouldIncludeFunc(funcUsr, funcName)) {
-    _logger.fine('++++ Adding Function: ${cursor.completeStringRepr()}');
-
-    final rt = _getFunctionReturnType(cursor);
-    final parameters = _getParameters(cursor, funcName);
-
-    if (clang.clang_Cursor_isFunctionInlined(cursor) != 0) {
-      _logger.fine('---- Removed Function, reason: inline function: '
-          '${cursor.completeStringRepr()}');
-      _logger.warning(
-          "Skipped Function '$funcName', inline functions are not supported.");
-      // Returning null so that [addToBindings] function excludes this.
-      return _stack.pop().func;
-    }
-
-    if (rt.isIncompleteCompound || _stack.top.incompleteStructParameter) {
-      _logger.fine(
-          '---- Removed Function, reason: Incomplete struct pass/return by '
-          'value: ${cursor.completeStringRepr()}');
-      _logger.warning(
-          "Skipped Function '$funcName', Incomplete struct pass/return by "
-          'value not supported.');
-      // Returning null so that [addToBindings] function excludes this.
-      return _stack.pop().func;
-    }
-
-    if (rt.baseType is UnimplementedType ||
-        _stack.top.unimplementedParameterType) {
-      _logger.fine('---- Removed Function, reason: unsupported return type or '
-          'parameter type: ${cursor.completeStringRepr()}');
-      _logger.warning(
-          "Skipped Function '$funcName', function has unsupported return type "
-          'or parameter type.');
-      // Returning null so that [addToBindings] function excludes this.
-      return _stack.pop().func;
-    }
-
-    _stack.top.func = Func(
-      dartDoc: getCursorDocComment(
-        cursor,
-        nesting.length + commentPrefix.length,
-      ),
-      usr: funcUsr,
-      name: config.functionDecl.renameUsingConfig(funcName),
-      originalName: funcName,
-      returnType: rt,
-      parameters: parameters,
-      exposeSymbolAddress:
-          config.functionDecl.shouldIncludeSymbolAddress(funcName),
-      exposeFunctionTypedefs:
-          config.exposeFunctionTypedefs.shouldInclude(funcName),
-      isLeaf: config.leafFunctions.shouldInclude(funcName),
-    );
-    bindingsIndex.addFuncToSeen(funcUsr, _stack.top.func!);
-  } else if (bindingsIndex.isSeenFunc(funcUsr)) {
-    _stack.top.func = bindingsIndex.getSeenFunc(funcUsr);
-  }
-
-  return _stack.pop().func;
-}
-
-Type _getFunctionReturnType(clang_types.CXCursor cursor) {
-  return cursor.returnType().toCodeGenType();
-}
-
-List<Parameter> _getParameters(clang_types.CXCursor cursor, String funcName) {
-  final parameters = <Parameter>[];
-
-  final totalArgs = clang.clang_Cursor_getNumArguments(cursor);
-  for (var i = 0; i < totalArgs; i++) {
-    final paramCursor = clang.clang_Cursor_getArgument(cursor, i);
-
-    _logger.finer('===== parameter: ${paramCursor.completeStringRepr()}');
-
-    final pt = _getParameterType(paramCursor);
-    if (pt.isIncompleteCompound) {
-      _stack.top.incompleteStructParameter = true;
-    } else if (pt.baseType is UnimplementedType) {
-      _logger.finer('Unimplemented type: ${pt.baseType}');
-      _stack.top.unimplementedParameterType = true;
-    }
-
-    final pn = paramCursor.spelling();
-
-    /// If [pn] is null or empty, its set to `arg$i` by code_generator.
-    parameters.add(
-      Parameter(
-        originalName: pn,
-        name: config.functionDecl.renameMemberUsingConfig(funcName, pn),
-        type: pt,
-      ),
-    );
-  }
-
-  return parameters;
-}
-
-Type _getParameterType(clang_types.CXCursor cursor) {
-  return cursor.type().toCodeGenType();
-}
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/sub_parsers/macro_parser.dart b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/sub_parsers/macro_parser.dart
deleted file mode 100644
index cdfe078..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/sub_parsers/macro_parser.dart
+++ /dev/null
@@ -1,331 +0,0 @@
-// Copyright (c) 2020, 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.
-
-import 'dart:ffi';
-import 'dart:io';
-import 'dart:typed_data';
-
-import 'package:ffi/ffi.dart';
-import 'package:ffigen/src/code_generator.dart';
-import 'package:ffigen/src/header_parser/data.dart';
-import 'package:ffigen/src/header_parser/includer.dart';
-import 'package:ffigen/src/strings.dart' as strings;
-import 'package:logging/logging.dart';
-import 'package:path/path.dart' as p;
-
-import '../clang_bindings/clang_bindings.dart' as clang_types;
-import '../data.dart';
-import '../utils.dart';
-
-final _logger = Logger('ffigen.header_parser.macro_parser');
-
-/// Adds a macro definition to be parsed later.
-void saveMacroDefinition(clang_types.CXCursor cursor) {
-  final macroUsr = cursor.usr();
-  final originalMacroName = cursor.spelling();
-  if (clang.clang_Cursor_isMacroBuiltin(cursor) == 0 &&
-      clang.clang_Cursor_isMacroFunctionLike(cursor) == 0 &&
-      shouldIncludeMacro(macroUsr, originalMacroName)) {
-    // Parse macro only if it's not builtin or function-like.
-    _logger.fine(
-        "++++ Saved Macro '$originalMacroName' for later : ${cursor.completeStringRepr()}");
-    final prefixedName = config.macroDecl.renameUsingConfig(originalMacroName);
-    bindingsIndex.addMacroToSeen(macroUsr, prefixedName);
-    _saveMacro(prefixedName, macroUsr, originalMacroName);
-  }
-}
-
-/// Saves a macro to be parsed later.
-///
-/// Macros are parsed later in [parseSavedMacros()].
-void _saveMacro(String name, String usr, String originalName) {
-  savedMacros[name] = Macro(usr, originalName);
-}
-
-List<Constant>? _bindings;
-
-/// Macros cannot be parsed directly, so we create a new `.hpp` file in which
-/// they are assigned to a variable after which their value can be determined
-/// by evaluating the value of the variable.
-List<Constant>? parseSavedMacros() {
-  _bindings = [];
-
-  if (savedMacros.keys.isEmpty) {
-    return _bindings;
-  }
-
-  // Create a file for parsing macros;
-  final file = createFileForMacros();
-
-  final index = clang.clang_createIndex(0, 0);
-  Pointer<Pointer<Utf8>> clangCmdArgs = nullptr;
-  var cmdLen = 0;
-  clangCmdArgs = createDynamicStringArray(config.compilerOpts);
-  cmdLen = config.compilerOpts.length;
-  final tu = clang.clang_parseTranslationUnit(
-    index,
-    file.path.toNativeUtf8().cast(),
-    clangCmdArgs.cast(),
-    cmdLen,
-    nullptr,
-    0,
-    clang_types.CXTranslationUnit_Flags.CXTranslationUnit_KeepGoing,
-  );
-
-  if (tu == nullptr) {
-    _logger.severe('Unable to parse Macros.');
-  } else {
-    final rootCursor = clang.clang_getTranslationUnitCursor(tu);
-
-    final resultCode = clang.clang_visitChildren(
-      rootCursor,
-      Pointer.fromFunction(_macroVariablevisitor, exceptional_visitor_return),
-      nullptr,
-    );
-
-    visitChildrenResultChecker(resultCode);
-  }
-
-  clang.clang_disposeTranslationUnit(tu);
-  clang.clang_disposeIndex(index);
-  // Delete the temp file created for macros.
-  file.deleteSync();
-
-  return _bindings;
-}
-
-/// Child visitor invoked on translationUnitCursor for parsing macroVariables.
-int _macroVariablevisitor(clang_types.CXCursor cursor,
-    clang_types.CXCursor parent, Pointer<Void> clientData) {
-  Constant? constant;
-  try {
-    if (isFromGeneratedFile(cursor) &&
-        _macroVarNames.contains(cursor.spelling()) &&
-        cursor.kind == clang_types.CXCursorKind.CXCursor_VarDecl) {
-      final e = clang.clang_Cursor_Evaluate(cursor);
-      final k = clang.clang_EvalResult_getKind(e);
-      _logger.fine('macroVariablevisitor: ${cursor.completeStringRepr()}');
-
-      /// Get macro name, the variable name starts with '<macro-name>_'.
-      final macroName = MacroVariableString.decode(cursor.spelling());
-      switch (k) {
-        case clang_types.CXEvalResultKind.CXEval_Int:
-          constant = Constant(
-            usr: savedMacros[macroName]!.usr,
-            originalName: savedMacros[macroName]!.originalName,
-            name: macroName,
-            rawType: 'int',
-            rawValue: clang.clang_EvalResult_getAsLongLong(e).toString(),
-          );
-          break;
-        case clang_types.CXEvalResultKind.CXEval_Float:
-          constant = Constant(
-            usr: savedMacros[macroName]!.usr,
-            originalName: savedMacros[macroName]!.originalName,
-            name: macroName,
-            rawType: 'double',
-            rawValue:
-                _writeDoubleAsString(clang.clang_EvalResult_getAsDouble(e)),
-          );
-          break;
-        case clang_types.CXEvalResultKind.CXEval_StrLiteral:
-          final rawValue = _getWrittenRepresentation(
-            macroName,
-            clang.clang_EvalResult_getAsStr(e),
-          );
-          constant = Constant(
-            usr: savedMacros[macroName]!.usr,
-            originalName: savedMacros[macroName]!.originalName,
-            name: macroName,
-            rawType: 'String',
-            rawValue: "'$rawValue'",
-          );
-          break;
-      }
-      clang.clang_EvalResult_dispose(e);
-
-      if (constant != null) {
-        _bindings!.add(constant);
-      }
-    }
-  } catch (e, s) {
-    _logger.severe(e);
-    _logger.severe(s);
-    rethrow;
-  }
-  return clang_types.CXChildVisitResult.CXChildVisit_Continue;
-}
-
-/// Returns true if cursor is from generated file.
-bool isFromGeneratedFile(clang_types.CXCursor cursor) {
-  final s = cursor.sourceFileName();
-  return p.basename(s) == _generatedFileBaseName;
-}
-
-/// Base name of generated file.
-String? _generatedFileBaseName;
-
-/// Generated macro variable names.
-///
-/// Used to determine if macro should be included in bindings or not.
-late Set<String> _macroVarNames;
-
-/// Creates a temporary file for parsing macros in current directory.
-File createFileForMacros() {
-  final fileNameBase = 'temp_for_macros';
-  final fileExt = 'hpp';
-
-  // Find a filename which doesn't already exist.
-  var file = File('$fileNameBase.$fileExt');
-  var i = 0;
-  while (file.existsSync()) {
-    i++;
-    file = File('${fileNameBase.split('.')[0]}_$i.$fileExt');
-  }
-
-  // Create file.
-  file.createSync();
-  // Save generted name.
-  _generatedFileBaseName = p.basename(file.path);
-
-  // Write file contents.
-  final sb = StringBuffer();
-  for (final h in config.headers.entryPoints) {
-    sb.writeln('#include "$h"');
-  }
-
-  _macroVarNames = {};
-  for (final prefixedMacroName in savedMacros.keys) {
-    // Write macro.
-    final macroVarName = MacroVariableString.encode(prefixedMacroName);
-    sb.writeln(
-        'auto $macroVarName = ${savedMacros[prefixedMacroName]!.originalName};');
-    // Add to _macroVarNames.
-    _macroVarNames.add(macroVarName);
-  }
-  final macroFileContent = sb.toString();
-  // Log this generated file for debugging purpose.
-  // We use the finest log because this file may be very big.
-  _logger.finest('=====FILE FOR MACROS====');
-  _logger.finest(macroFileContent);
-  _logger.finest('========================');
-
-  file.writeAsStringSync(macroFileContent);
-  return file;
-}
-
-/// Deals with encoding/decoding name of the variable generated for a Macro.
-class MacroVariableString {
-  static String encode(String s) {
-    return '_${s.length}_${s}_generated_macro_variable';
-  }
-
-  static String decode(String s) {
-    // Remove underscore.
-    s = s.substring(1);
-    final intReg = RegExp('[0-9]+');
-    final lengthEnd = intReg.matchAsPrefix(s)!.end;
-    final len = int.parse(s.substring(0, lengthEnd));
-
-    // Name starts after an unerscore.
-    final nameStart = lengthEnd + 1;
-    return s.substring(nameStart, nameStart + len);
-  }
-}
-
-/// Gets a written representation string of a C string.
-///
-/// E.g- For a string "Hello\nWorld", The new line character is converted to \n.
-/// Note: The string is considered to be Utf8, but is treated as Extended ASCII,
-/// if the conversion fails.
-String _getWrittenRepresentation(String macroName, Pointer<Char> strPtr) {
-  final sb = StringBuffer();
-  try {
-    // Consider string to be Utf8 encoded by default.
-    sb.clear();
-    // This throws a Format Exception if string isn't Utf8 so that we handle it
-    // in the catch block.
-    final result = strPtr.cast<Utf8>().toDartString();
-    for (final s in result.runes) {
-      sb.write(_getWritableChar(s));
-    }
-  } catch (e) {
-    // Handle string if it isn't Utf8. String is considered to be
-    // Extended ASCII in this case.
-    _logger.warning(
-        "Couldn't decode Macro string '$macroName' as Utf8, using ASCII instead.");
-    sb.clear();
-    final length = strPtr.cast<Utf8>().length;
-    final charList = Uint8List.view(
-        strPtr.cast<Uint8>().asTypedList(length).buffer, 0, length);
-
-    for (final char in charList) {
-      sb.write(_getWritableChar(char, utf8: false));
-    }
-  }
-
-  return sb.toString();
-}
-
-/// Creates a writable char from [char] code.
-///
-/// E.g- `\` is converted to `\\`.
-String _getWritableChar(int char, {bool utf8 = true}) {
-  /// Handle control characters.
-  if (char >= 0 && char < 32 || char == 127) {
-    /// Handle these - `\b \t \n \v \f \r` as special cases.
-    switch (char) {
-      case 8: // \b
-        return r'\b';
-      case 9: // \t
-        return r'\t';
-      case 10: // \n
-        return r'\n';
-      case 11: // \v
-        return r'\v';
-      case 12: // \f
-        return r'\f';
-      case 13: // \r
-        return r'\r';
-      default:
-        final h = char.toRadixString(16).toUpperCase().padLeft(2, '0');
-        return '\\x$h';
-    }
-  }
-
-  /// Handle characters - `$ ' \` these need to be escaped when writing to file.
-  switch (char) {
-    case 36: // $
-      return r'\$';
-    case 39: // '
-      return r"\'";
-    case 92: // \
-      return r'\\';
-  }
-
-  /// In case encoding is not Utf8, we know all characters will fall in [0..255]
-  /// Print range [128..255] as `\xHH`.
-  if (!utf8) {
-    final h = char.toRadixString(16).toUpperCase().padLeft(2, '0');
-    return '\\x$h';
-  }
-
-  /// In all other cases, simply convert to string.
-  return String.fromCharCode(char);
-}
-
-/// Converts a double to a string, handling cases like Infinity and NaN.
-String _writeDoubleAsString(double d) {
-  if (d.isFinite) {
-    return d.toString();
-  } else {
-    // The only Non-Finite numbers are Infinity, NegativeInfinity and NaN.
-    if (d.isInfinite) {
-      return d.isNegative
-          ? strings.doubleNegativeInfinity
-          : strings.doubleInfinity;
-    }
-    return strings.doubleNaN;
-  }
-}
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/sub_parsers/objc_block_parser.dart b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/sub_parsers/objc_block_parser.dart
deleted file mode 100644
index 83f8223..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/sub_parsers/objc_block_parser.dart
+++ /dev/null
@@ -1,40 +0,0 @@
-// 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.
-
-import 'package:ffigen/src/code_generator.dart';
-import 'package:ffigen/src/header_parser/data.dart';
-import 'package:logging/logging.dart';
-
-import '../clang_bindings/clang_bindings.dart' as clang_types;
-import '../utils.dart';
-
-final _logger = Logger('ffigen.header_parser.objc_block_parser');
-
-ObjCBlock parseObjCBlock(clang_types.CXType cxtype) {
-  final blk = clang.clang_getPointeeType(cxtype);
-  final returnType = clang.clang_getResultType(blk).toCodeGenType();
-  final argTypes = <Type>[];
-  final int numArgs = clang.clang_getNumArgTypes(blk);
-  for (int i = 0; i < numArgs; ++i) {
-    argTypes.add(clang.clang_getArgType(blk, i).toCodeGenType());
-  }
-
-  // Create a fake USR code for the block. This code is used to dedupe blocks
-  // with the same signature.
-  var usr = 'objcBlock: ' + returnType.cacheKey();
-  for (final type in argTypes) {
-    usr += ' ' + type.cacheKey();
-  }
-
-  _logger.fine('++++ Adding ObjC block: '
-      '${cxtype.completeStringRepr()}, syntheticUsr: $usr');
-
-  return ObjCBlock(
-    usr: usr.toString(),
-    name: 'ObjCBlock',
-    returnType: returnType,
-    argTypes: argTypes,
-    builtInFunctions: objCBuiltInFunctions,
-  );
-}
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/sub_parsers/objcinterfacedecl_parser.dart b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/sub_parsers/objcinterfacedecl_parser.dart
deleted file mode 100644
index 94fff92..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/sub_parsers/objcinterfacedecl_parser.dart
+++ /dev/null
@@ -1,329 +0,0 @@
-// 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.
-
-import 'dart:ffi';
-
-import 'package:ffigen/src/code_generator.dart';
-import 'package:ffigen/src/header_parser/data.dart';
-import 'package:logging/logging.dart';
-
-import '../clang_bindings/clang_bindings.dart' as clang_types;
-import '../includer.dart';
-import '../utils.dart';
-
-final _logger = Logger('ffigen.header_parser.objcinterfacedecl_parser');
-
-class _ParsedObjCInterface {
-  ObjCInterface interface;
-  _ParsedObjCInterface(this.interface);
-}
-
-class _ParsedObjCMethod {
-  ObjCMethod method;
-  bool hasError = false;
-  _ParsedObjCMethod(this.method);
-}
-
-final _interfaceStack = Stack<_ParsedObjCInterface>();
-final _methodStack = Stack<_ParsedObjCMethod>();
-
-Type? parseObjCInterfaceDeclaration(
-  clang_types.CXCursor cursor, {
-  /// Option to ignore declaration filter (Useful in case of extracting
-  /// declarations when they are passed/returned by an included function.)
-  bool ignoreFilter = false,
-}) {
-  final itfUsr = cursor.usr();
-  final itfName = cursor.spelling();
-  if (!ignoreFilter && !shouldIncludeObjCInterface(itfUsr, itfName)) {
-    return null;
-  }
-
-  final t = cursor.type();
-  final name = t.spelling();
-
-  _logger.fine('++++ Adding ObjC interface: '
-      'Name: $name, ${cursor.completeStringRepr()}');
-
-  return ObjCInterface(
-    usr: itfUsr,
-    originalName: name,
-    name: config.objcInterfaces.renameUsingConfig(name),
-    dartDoc: getCursorDocComment(cursor),
-    builtInFunctions: objCBuiltInFunctions,
-    isBuiltIn: cursor.isInSystemHeader(),
-  );
-}
-
-void fillObjCInterfaceMethodsIfNeeded(
-    ObjCInterface itf, clang_types.CXCursor cursor) {
-  if (_isClassDeclaration(cursor)) {
-    // @class declarations are ObjC's way of forward declaring classes. In that
-    // case there's nothing to fill yet.
-    return;
-  }
-
-  if (itf.filled) return;
-  itf.filled = true; // Break cycles.
-
-  _logger.fine('++++ Filling ObjC interface: '
-      'Name: ${itf.originalName}, ${cursor.completeStringRepr()}');
-
-  _interfaceStack.push(_ParsedObjCInterface(itf));
-  clang.clang_visitChildren(
-      cursor,
-      Pointer.fromFunction(_parseInterfaceVisitor, exceptional_visitor_return),
-      nullptr);
-  _interfaceStack.pop();
-
-  _logger.fine('++++ Finished ObjC interface: '
-      'Name: ${itf.originalName}, ${cursor.completeStringRepr()}');
-}
-
-bool _isClassDeclarationResult = false;
-bool _isClassDeclaration(clang_types.CXCursor cursor) {
-  // It's a class declaration if it has no children other than ObjCClassRef.
-  _isClassDeclarationResult = true;
-  clang.clang_visitChildren(
-      cursor,
-      Pointer.fromFunction(
-          _isClassDeclarationVisitor, exceptional_visitor_return),
-      nullptr);
-  return _isClassDeclarationResult;
-}
-
-int _isClassDeclarationVisitor(clang_types.CXCursor cursor,
-    clang_types.CXCursor parent, Pointer<Void> clientData) {
-  if (cursor.kind == clang_types.CXCursorKind.CXCursor_ObjCClassRef) {
-    return clang_types.CXChildVisitResult.CXChildVisit_Continue;
-  }
-  _isClassDeclarationResult = false;
-  return clang_types.CXChildVisitResult.CXChildVisit_Break;
-}
-
-int _parseInterfaceVisitor(clang_types.CXCursor cursor,
-    clang_types.CXCursor parent, Pointer<Void> clientData) {
-  switch (cursor.kind) {
-    case clang_types.CXCursorKind.CXCursor_ObjCSuperClassRef:
-      _parseSuperType(cursor);
-      break;
-    case clang_types.CXCursorKind.CXCursor_ObjCPropertyDecl:
-      _parseProperty(cursor);
-      break;
-    case clang_types.CXCursorKind.CXCursor_ObjCInstanceMethodDecl:
-    case clang_types.CXCursorKind.CXCursor_ObjCClassMethodDecl:
-      _parseMethod(cursor);
-      break;
-  }
-  return clang_types.CXChildVisitResult.CXChildVisit_Continue;
-}
-
-void _parseSuperType(clang_types.CXCursor cursor) {
-  final superType = cursor.type().toCodeGenType();
-  _logger.fine('       > Super type: '
-      '$superType ${cursor.completeStringRepr()}');
-  final itf = _interfaceStack.top.interface;
-  if (superType is ObjCInterface) {
-    itf.superType = superType;
-  } else {
-    _logger.severe(
-        'Super type of $itf is $superType, which is not a valid interface.');
-  }
-}
-
-void _parseProperty(clang_types.CXCursor cursor) {
-  final itf = _interfaceStack.top.interface;
-  final fieldName = cursor.spelling();
-  final fieldType = cursor.type().toCodeGenType();
-  final dartDoc = getCursorDocComment(cursor);
-
-  final propertyAttributes =
-      clang.clang_Cursor_getObjCPropertyAttributes(cursor, 0);
-  final isClass = propertyAttributes &
-          clang_types.CXObjCPropertyAttrKind.CXObjCPropertyAttr_class >
-      0;
-  final isReadOnly = propertyAttributes &
-          clang_types.CXObjCPropertyAttrKind.CXObjCPropertyAttr_readonly >
-      0;
-  // TODO(#334): Use the nullable attribute to decide this.
-  final isNullable =
-      cursor.type().kind == clang_types.CXTypeKind.CXType_ObjCObjectPointer;
-
-  final property = ObjCProperty(fieldName);
-
-  _logger.fine('       > Property: '
-      '$fieldType $fieldName ${cursor.completeStringRepr()}');
-
-  final getterName =
-      clang.clang_Cursor_getObjCPropertyGetterName(cursor).toStringAndDispose();
-  final getter = ObjCMethod(
-    originalName: getterName,
-    property: property,
-    dartDoc: dartDoc,
-    kind: ObjCMethodKind.propertyGetter,
-    isClass: isClass,
-    returnType: fieldType,
-    isNullableReturn: isNullable,
-  );
-  itf.addMethod(getter);
-
-  if (!isReadOnly) {
-    final setterName = clang
-        .clang_Cursor_getObjCPropertySetterName(cursor)
-        .toStringAndDispose();
-    final setter = ObjCMethod(
-        originalName: setterName,
-        property: property,
-        dartDoc: dartDoc,
-        kind: ObjCMethodKind.propertySetter,
-        isClass: isClass);
-    setter.returnType = NativeType(SupportedNativeType.Void);
-    setter.params
-        .add(ObjCMethodParam(fieldType, 'value', isNullable: isNullable));
-    itf.addMethod(setter);
-  }
-}
-
-void _parseMethod(clang_types.CXCursor cursor) {
-  final methodName = cursor.spelling();
-  final isClassMethod =
-      cursor.kind == clang_types.CXCursorKind.CXCursor_ObjCClassMethodDecl;
-  final method = ObjCMethod(
-    originalName: methodName,
-    dartDoc: getCursorDocComment(cursor),
-    kind: ObjCMethodKind.method,
-    isClass: isClassMethod,
-  );
-  final parsed = _ParsedObjCMethod(method);
-  _logger.fine('       > ${isClassMethod ? 'Class' : 'Instance'} method: '
-      '${method.originalName} ${cursor.completeStringRepr()}');
-  _methodStack.push(parsed);
-  clang.clang_visitChildren(
-      cursor,
-      Pointer.fromFunction(_parseMethodVisitor, exceptional_visitor_return),
-      nullptr);
-  _methodStack.pop();
-  if (parsed.hasError) {
-    // Discard it.
-    return;
-  }
-  _interfaceStack.top.interface.addMethod(method);
-}
-
-int _parseMethodVisitor(clang_types.CXCursor cursor,
-    clang_types.CXCursor parent, Pointer<Void> clientData) {
-  switch (cursor.kind) {
-    case clang_types.CXCursorKind.CXCursor_TypeRef:
-    case clang_types.CXCursorKind.CXCursor_ObjCClassRef:
-      _parseMethodReturnType(cursor);
-      break;
-    case clang_types.CXCursorKind.CXCursor_ParmDecl:
-      _parseMethodParam(cursor);
-      break;
-    case clang_types.CXCursorKind.CXCursor_NSReturnsRetained:
-      _markMethodReturnsRetained(cursor);
-      break;
-    default:
-  }
-  return clang_types.CXChildVisitResult.CXChildVisit_Continue;
-}
-
-void _parseMethodReturnType(clang_types.CXCursor cursor) {
-  final parsed = _methodStack.top;
-  if (parsed.method.returnType != null) {
-    parsed.hasError = true;
-    _logger.fine(
-        '           >> Extra return type: ${cursor.completeStringRepr()}');
-    _logger.warning('Method "${parsed.method.originalName}" in instance '
-        '"${_interfaceStack.top.interface.originalName}" has multiple return '
-        'types.');
-  } else {
-    parsed.method.returnType = cursor.type().toCodeGenType();
-    _logger.fine('           >> Return type: '
-        '${parsed.method.returnType} ${cursor.completeStringRepr()}');
-  }
-}
-
-void _parseMethodParam(clang_types.CXCursor cursor) {
-  /*
-  TODO(#334): Change this to use:
-  
-  clang.clang_Type_getNullability(cursor.type()) ==
-      clang_types.CXTypeNullabilityKind.CXTypeNullability_Nullable;
-
-  NOTE: This will only work with the
-
-    clang_types
-      .CXTranslationUnit_Flags.CXTranslationUnit_IncludeAttributedTypes
-
-  option set.
-  */
-  final isNullable =
-      cursor.type().kind == clang_types.CXTypeKind.CXType_ObjCObjectPointer;
-  final name = cursor.spelling();
-  final type = cursor.type().toCodeGenType();
-  _logger.fine(
-      '           >> Parameter: $type $name ${cursor.completeStringRepr()}');
-  _methodStack.top.method.params
-      .add(ObjCMethodParam(type, name, isNullable: isNullable));
-}
-
-void _markMethodReturnsRetained(clang_types.CXCursor cursor) {
-  _methodStack.top.method.returnsRetained = true;
-}
-
-BindingType? parseObjCCategoryDeclaration(clang_types.CXCursor cursor) {
-  // Categories add methods to an existing interface, so first we run a visitor
-  // to find the interface, then we fully parse that interface, then we run the
-  // _parseInterfaceVisitor over the category to add its methods etc. Reusing
-  // the interface visitor relies on the fact that the structure of the category
-  // AST looks exactly the same as the interface AST, and that the category's
-  // interface is a different kind of node to the interface's super type (so is
-  // ignored by _parseInterfaceVisitor).
-  final name = cursor.spelling();
-  _logger.fine('++++ Adding ObjC category: '
-      'Name: $name, ${cursor.completeStringRepr()}');
-
-  _findCategoryInterfaceVisitorResult = null;
-  clang.clang_visitChildren(
-      cursor,
-      Pointer.fromFunction(
-          _findCategoryInterfaceVisitor, exceptional_visitor_return),
-      nullptr);
-  final itfCursor = _findCategoryInterfaceVisitorResult;
-  if (itfCursor == null) {
-    _logger.severe('Category $name has no interface.');
-    return null;
-  }
-
-  // TODO(#347): Currently any interface with a category bypasses the filters.
-  final itf = itfCursor.type().toCodeGenType();
-  if (itf is! ObjCInterface) {
-    _logger.severe(
-        'Interface of category $name is $itf, which is not a valid interface.');
-    return null;
-  }
-
-  _interfaceStack.push(_ParsedObjCInterface(itf));
-  clang.clang_visitChildren(
-      cursor,
-      Pointer.fromFunction(_parseInterfaceVisitor, exceptional_visitor_return),
-      nullptr);
-  _interfaceStack.pop();
-
-  _logger.fine('++++ Finished ObjC category: '
-      'Name: $name, ${cursor.completeStringRepr()}');
-
-  return itf;
-}
-
-clang_types.CXCursor? _findCategoryInterfaceVisitorResult;
-int _findCategoryInterfaceVisitor(clang_types.CXCursor cursor,
-    clang_types.CXCursor parent, Pointer<Void> clientData) {
-  if (cursor.kind == clang_types.CXCursorKind.CXCursor_ObjCClassRef) {
-    _findCategoryInterfaceVisitorResult = cursor;
-    return clang_types.CXChildVisitResult.CXChildVisit_Break;
-  }
-  return clang_types.CXChildVisitResult.CXChildVisit_Continue;
-}
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/sub_parsers/typedefdecl_parser.dart b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/sub_parsers/typedefdecl_parser.dart
deleted file mode 100644
index 988a45e..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/sub_parsers/typedefdecl_parser.dart
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright (c) 2020, 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.
-
-import 'package:ffigen/src/code_generator.dart';
-import 'package:ffigen/src/header_parser/includer.dart';
-import 'package:ffigen/src/header_parser/type_extractor/extractor.dart';
-import 'package:logging/logging.dart';
-
-import '../clang_bindings/clang_bindings.dart' as clang_types;
-import '../data.dart';
-import '../utils.dart';
-
-final _logger = Logger('ffigen.header_parser.typedefdecl_parser');
-
-/// Parses a typedef declaration.
-///
-/// Notes:
-/// - Pointer to Typedefs structs are skipped if the struct is seen.
-/// - If there are multiple typedefs for a declaration (struct/enum), the last
-/// seen name is used.
-/// - Typerefs are completely ignored.
-///
-/// Libclang marks them as following -
-/// ```C
-/// typedef struct A{
-///   int a
-/// } B, *pB; // Typedef(s).
-///
-/// typedef A D; // Typeref.
-/// ```
-///
-/// Returns `null` if the typedef could not be generated or has been excluded
-/// by the config.
-Typealias? parseTypedefDeclaration(
-  clang_types.CXCursor cursor, {
-  bool pointerReference = false,
-}) {
-  final typedefName = cursor.spelling();
-  final typedefUsr = cursor.usr();
-  if (shouldIncludeTypealias(typedefUsr, typedefName)) {
-    final ct = clang.clang_getTypedefDeclUnderlyingType(cursor);
-    final s = getCodeGenType(ct, pointerReference: pointerReference);
-
-    if (bindingsIndex.isSeenUnsupportedTypealias(typedefUsr)) {
-      // Do not process unsupported typealiases again.
-    } else if (s is UnimplementedType) {
-      _logger.fine("Skipped Typedef '$typedefName': "
-          'Unimplemented type referred.');
-      bindingsIndex.addUnsupportedTypealiasToSeen(typedefUsr);
-    } else if (s is Compound && s.originalName == typedefName) {
-      // Ignore typedef if it refers to a compound with the same original name.
-      bindingsIndex.addUnsupportedTypealiasToSeen(typedefUsr);
-      _logger.fine("Skipped Typedef '$typedefName': "
-          'Name matches with referred struct/union.');
-    } else if (s is EnumClass) {
-      // Ignore typedefs to Enum.
-      bindingsIndex.addUnsupportedTypealiasToSeen(typedefUsr);
-      _logger.fine("Skipped Typedef '$typedefName': typedef to enum.");
-    } else if (s is HandleType) {
-      // Ignore typedefs to Handle.
-      _logger.fine("Skipped Typedef '$typedefName': typedef to Dart Handle.");
-      bindingsIndex.addUnsupportedTypealiasToSeen(typedefUsr);
-    } else if (s is ConstantArray || s is IncompleteArray) {
-      // Ignore typedefs to Constant Array.
-      _logger.fine("Skipped Typedef '$typedefName': typedef to array.");
-      bindingsIndex.addUnsupportedTypealiasToSeen(typedefUsr);
-    } else if (s is BooleanType) {
-      // Ignore typedefs to Boolean.
-      _logger.fine("Skipped Typedef '$typedefName': typedef to bool.");
-      bindingsIndex.addUnsupportedTypealiasToSeen(typedefUsr);
-    } else {
-      // Create typealias.
-      return Typealias(
-        usr: typedefUsr,
-        originalName: typedefName,
-        name: config.typedefs.renameUsingConfig(typedefName),
-        type: s,
-        dartDoc: getCursorDocComment(cursor),
-      );
-    }
-  }
-  return null;
-}
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/sub_parsers/unnamed_enumdecl_parser.dart b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/sub_parsers/unnamed_enumdecl_parser.dart
deleted file mode 100644
index 940369a..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/sub_parsers/unnamed_enumdecl_parser.dart
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright (c) 2020, 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.
-
-import 'dart:ffi';
-
-import 'package:ffigen/src/code_generator.dart';
-import 'package:ffigen/src/header_parser/data.dart';
-import 'package:ffigen/src/header_parser/includer.dart';
-import 'package:logging/logging.dart';
-
-import '../clang_bindings/clang_bindings.dart' as clang_types;
-import '../data.dart';
-import '../utils.dart';
-
-final _logger = Logger('ffigen.header_parser.unnamed_enumdecl_parser');
-
-/// Saves unnamed enums.
-void saveUnNamedEnum(clang_types.CXCursor cursor) {
-  final resultCode = clang.clang_visitChildren(
-    cursor,
-    Pointer.fromFunction(_unnamedenumCursorVisitor, exceptional_visitor_return),
-    nullptr,
-  );
-
-  visitChildrenResultChecker(resultCode);
-}
-
-/// Visitor for a enum cursor [clang.CXCursorKind.CXCursor_EnumDecl].
-///
-/// Invoked on every enum directly under rootCursor.
-/// Used for for extracting enum values.
-int _unnamedenumCursorVisitor(clang_types.CXCursor cursor,
-    clang_types.CXCursor parent, Pointer<Void> clientData) {
-  try {
-    _logger
-        .finest('  unnamedenumCursorVisitor: ${cursor.completeStringRepr()}');
-    switch (clang.clang_getCursorKind(cursor)) {
-      case clang_types.CXCursorKind.CXCursor_EnumConstantDecl:
-        if (shouldIncludeUnnamedEnumConstant(cursor.usr(), cursor.spelling())) {
-          _addUnNamedEnumConstant(cursor);
-        }
-        break;
-      default:
-        _logger.severe('Invalid enum constant.');
-    }
-  } catch (e, s) {
-    _logger.severe(e);
-    _logger.severe(s);
-    rethrow;
-  }
-  return clang_types.CXChildVisitResult.CXChildVisit_Continue;
-}
-
-/// Adds the parameter to func in [functiondecl_parser.dart].
-void _addUnNamedEnumConstant(clang_types.CXCursor cursor) {
-  _logger.fine(
-      '++++ Adding Constant from unnamed enum: ${cursor.completeStringRepr()}');
-  final constant = Constant(
-    usr: cursor.usr(),
-    originalName: cursor.spelling(),
-    name: config.unnamedEnumConstants.renameUsingConfig(
-      cursor.spelling(),
-    ),
-    rawType: 'int',
-    rawValue: clang.clang_getEnumConstantDeclValue(cursor).toString(),
-  );
-  bindingsIndex.addUnnamedEnumConstantToSeen(cursor.usr(), constant);
-  unnamedEnumConstants.add(constant);
-}
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/sub_parsers/var_parser.dart b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/sub_parsers/var_parser.dart
deleted file mode 100644
index 8376199..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/sub_parsers/var_parser.dart
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright (c) 2021, 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.
-
-import 'package:ffigen/src/code_generator.dart';
-import 'package:ffigen/src/header_parser/data.dart';
-import 'package:ffigen/src/header_parser/includer.dart';
-import 'package:logging/logging.dart';
-
-import '../clang_bindings/clang_bindings.dart' as clang_types;
-import '../data.dart';
-import '../utils.dart';
-
-final _logger = Logger('ffigen.header_parser.var_parser');
-
-/// Parses a global variable
-Global? parseVarDeclaration(clang_types.CXCursor cursor) {
-  final name = cursor.spelling();
-  final usr = cursor.usr();
-  if (bindingsIndex.isSeenGlobalVar(usr)) {
-    return bindingsIndex.getSeenGlobalVar(usr);
-  }
-  if (!shouldIncludeGlobalVar(usr, name)) {
-    return null;
-  }
-
-  _logger.fine('++++ Adding Global: ${cursor.completeStringRepr()}');
-
-  final type = cursor.type().toCodeGenType();
-  if (type.baseType is UnimplementedType) {
-    _logger.fine('---- Removed Global, reason: unsupported type: '
-        '${cursor.completeStringRepr()}');
-    _logger.warning("Skipped global variable '$name', type not supported.");
-    return null;
-  }
-
-  final global = Global(
-    originalName: name,
-    name: config.globals.renameUsingConfig(name),
-    usr: usr,
-    type: type,
-    dartDoc: getCursorDocComment(cursor),
-    exposeSymbolAddress: config.functionDecl.shouldIncludeSymbolAddress(name),
-  );
-  bindingsIndex.addGlobalVarToSeen(usr, global);
-  return global;
-}
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/translation_unit_parser.dart b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/translation_unit_parser.dart
deleted file mode 100644
index 7831ae8..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/translation_unit_parser.dart
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright (c) 2020, 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.
-
-import 'dart:ffi';
-
-import 'package:ffigen/src/code_generator.dart';
-import 'package:ffigen/src/header_parser/sub_parsers/macro_parser.dart';
-import 'package:ffigen/src/header_parser/sub_parsers/objcinterfacedecl_parser.dart';
-import 'package:ffigen/src/header_parser/sub_parsers/var_parser.dart';
-import 'package:logging/logging.dart';
-
-import 'clang_bindings/clang_bindings.dart' as clang_types;
-import 'data.dart';
-import 'includer.dart';
-import 'sub_parsers/functiondecl_parser.dart';
-import 'type_extractor/extractor.dart';
-import 'utils.dart';
-
-final _logger = Logger('ffigen.header_parser.translation_unit_parser');
-
-late Set<Binding> _bindings;
-
-/// Parses the translation unit and returns the generated bindings.
-Set<Binding> parseTranslationUnit(clang_types.CXCursor translationUnitCursor) {
-  _bindings = {};
-  final resultCode = clang.clang_visitChildren(
-    translationUnitCursor,
-    Pointer.fromFunction(_rootCursorVisitor, exceptional_visitor_return),
-    nullptr,
-  );
-
-  visitChildrenResultChecker(resultCode);
-
-  return _bindings;
-}
-
-/// Child visitor invoked on translationUnitCursor [CXCursorKind.CXCursor_TranslationUnit].
-int _rootCursorVisitor(clang_types.CXCursor cursor, clang_types.CXCursor parent,
-    Pointer<Void> clientData) {
-  try {
-    if (shouldIncludeRootCursor(cursor.sourceFileName())) {
-      _logger.finest('rootCursorVisitor: ${cursor.completeStringRepr()}');
-      switch (clang.clang_getCursorKind(cursor)) {
-        case clang_types.CXCursorKind.CXCursor_FunctionDecl:
-          addToBindings(parseFunctionDeclaration(cursor));
-          break;
-        case clang_types.CXCursorKind.CXCursor_StructDecl:
-        case clang_types.CXCursorKind.CXCursor_UnionDecl:
-        case clang_types.CXCursorKind.CXCursor_EnumDecl:
-        case clang_types.CXCursorKind.CXCursor_ObjCInterfaceDecl:
-          addToBindings(_getCodeGenTypeFromCursor(cursor));
-          break;
-        case clang_types.CXCursorKind.CXCursor_ObjCCategoryDecl:
-          addToBindings(parseObjCCategoryDeclaration(cursor));
-          break;
-        case clang_types.CXCursorKind.CXCursor_MacroDefinition:
-          saveMacroDefinition(cursor);
-          break;
-        case clang_types.CXCursorKind.CXCursor_VarDecl:
-          addToBindings(parseVarDeclaration(cursor));
-          break;
-        default:
-          _logger.finer('rootCursorVisitor: CursorKind not implemented');
-      }
-    } else {
-      _logger.finest(
-          'rootCursorVisitor:(not included) ${cursor.completeStringRepr()}');
-    }
-  } catch (e, s) {
-    _logger.severe(e);
-    _logger.severe(s);
-    rethrow;
-  }
-  return clang_types.CXChildVisitResult.CXChildVisit_Continue;
-}
-
-/// Adds to binding if unseen and not null.
-void addToBindings(Binding? b) {
-  if (b != null) {
-    // This is a set, and hence will not have duplicates.
-    _bindings.add(b);
-  }
-}
-
-BindingType? _getCodeGenTypeFromCursor(clang_types.CXCursor cursor) {
-  final t = getCodeGenType(cursor.type(), ignoreFilter: false);
-  return t is BindingType ? t : null;
-}
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/type_extractor/cxtypekindmap.dart b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/type_extractor/cxtypekindmap.dart
deleted file mode 100644
index 41af99a..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/type_extractor/cxtypekindmap.dart
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (c) 2020, 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.
-
-import 'package:ffigen/src/code_generator.dart' show SupportedNativeType;
-import 'package:ffigen/src/code_generator/imports.dart';
-
-var cxTypeKindToImportedTypes = <String, ImportedType>{
-  'void': voidType,
-  'unsigned char': unsignedCharType,
-  'signed char': signedCharType,
-  'char': charType,
-  'unsigned short': unsignedShortType,
-  'short': shortType,
-  'unsigned int': unsignedIntType,
-  'int': intType,
-  'unsigned long': unsignedLongType,
-  'long': longType,
-  'unsigned long long': unsignedLongLongType,
-  'long long': longLongType,
-  'float': floatType,
-  'double': doubleType,
-};
-
-var suportedTypedefToSuportedNativeType = <String, SupportedNativeType>{
-  'uint8_t': SupportedNativeType.Uint8,
-  'uint16_t': SupportedNativeType.Uint16,
-  'uint32_t': SupportedNativeType.Uint32,
-  'uint64_t': SupportedNativeType.Uint64,
-  'int8_t': SupportedNativeType.Int8,
-  'int16_t': SupportedNativeType.Int16,
-  'int32_t': SupportedNativeType.Int32,
-  'int64_t': SupportedNativeType.Int64,
-  'intptr_t': SupportedNativeType.IntPtr,
-};
-
-var supportedTypedefToImportedType = <String, ImportedType>{
-  'size_t': sizeType,
-  'wchar_t': wCharType,
-};
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/type_extractor/extractor.dart b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/type_extractor/extractor.dart
deleted file mode 100644
index 7a497a3..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/type_extractor/extractor.dart
+++ /dev/null
@@ -1,304 +0,0 @@
-// Copyright (c) 2020, 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.
-
-/// Extracts code_gen Type from type.
-import 'package:ffigen/src/code_generator.dart';
-import 'package:ffigen/src/header_parser/sub_parsers/typedefdecl_parser.dart';
-import 'package:ffigen/src/strings.dart' as strings;
-import 'package:logging/logging.dart';
-
-import '../../config_provider/config_types.dart';
-import '../clang_bindings/clang_bindings.dart' as clang_types;
-import '../data.dart';
-import '../sub_parsers/compounddecl_parser.dart';
-import '../sub_parsers/enumdecl_parser.dart';
-import '../sub_parsers/objc_block_parser.dart';
-import '../sub_parsers/objcinterfacedecl_parser.dart';
-import '../type_extractor/cxtypekindmap.dart';
-import '../utils.dart';
-
-final _logger = Logger('ffigen.header_parser.extractor');
-const _padding = '  ';
-
-/// Converts cxtype to a typestring code_generator can accept.
-Type getCodeGenType(
-  clang_types.CXType cxtype, {
-  /// Option to ignore declaration filter (Useful in case of extracting
-  /// declarations when they are passed/returned by an included function.)
-  bool ignoreFilter = true,
-
-  /// Passed on if a value was marked as a pointer before this one.
-  bool pointerReference = false,
-}) {
-  _logger.fine('${_padding}getCodeGenType ${cxtype.completeStringRepr()}');
-
-  // Special case: Elaborated types just refer to another type.
-  if (cxtype.kind == clang_types.CXTypeKind.CXType_Elaborated) {
-    return getCodeGenType(clang.clang_Type_getNamedType(cxtype),
-        ignoreFilter: ignoreFilter, pointerReference: pointerReference);
-  }
-
-  // These basic Objective C types skip the cache, and are conditional on the
-  // language flag.
-  if (config.language == Language.objc) {
-    switch (cxtype.kind) {
-      case clang_types.CXTypeKind.CXType_ObjCObjectPointer:
-      case clang_types.CXTypeKind.CXType_ObjCId:
-      case clang_types.CXTypeKind.CXType_ObjCTypeParam:
-      case clang_types.CXTypeKind.CXType_ObjCClass:
-        return PointerType(objCObjectType);
-      case clang_types.CXTypeKind.CXType_ObjCSel:
-        return PointerType(objCSelType);
-      case clang_types.CXTypeKind.CXType_BlockPointer:
-        return _getOrCreateBlockType(cxtype);
-    }
-  }
-
-  // If the type has a declaration cursor, then use the BindingsIndex to break
-  // any potential cycles, and dedupe the Type.
-  final cursor = clang.clang_getTypeDeclaration(cxtype);
-  if (cursor.kind != clang_types.CXCursorKind.CXCursor_NoDeclFound) {
-    final usr = cursor.usr();
-    var type = bindingsIndex.getSeenType(usr);
-    if (type == null) {
-      final result =
-          _createTypeFromCursor(cxtype, cursor, ignoreFilter, pointerReference);
-      type = result.type;
-      if (type == null) {
-        return UnimplementedType('${cxtype.kindSpelling()} not implemented');
-      }
-      if (result.addToCache) {
-        bindingsIndex.addTypeToSeen(usr, type);
-      }
-    }
-    _fillFromCursorIfNeeded(type, cursor, ignoreFilter, pointerReference);
-    return type;
-  }
-
-  // If the type doesn't have a declaration cursor, then it's a basic type such
-  // as int, or a simple derived type like a pointer, so doesn't need to be
-  // cached.
-  switch (cxtype.kind) {
-    case clang_types.CXTypeKind.CXType_Pointer:
-      final pt = clang.clang_getPointeeType(cxtype);
-      final s = getCodeGenType(pt, pointerReference: true);
-
-      // Replace Pointer<_Dart_Handle> with Handle.
-      if (config.useDartHandle &&
-          s is Compound &&
-          s.compoundType == CompoundType.struct &&
-          s.usr == strings.dartHandleUsr) {
-        return HandleType();
-      }
-      return PointerType(s);
-    case clang_types.CXTypeKind.CXType_FunctionProto:
-      // Primarily used for function pointers.
-      return _extractFromFunctionProto(cxtype);
-    case clang_types.CXTypeKind.CXType_FunctionNoProto:
-      // Primarily used for function types with zero arguments.
-      return _extractFromFunctionProto(cxtype);
-    case clang_types.CXTypeKind
-        .CXType_ConstantArray: // Primarily used for constant array in struct members.
-      return ConstantArray(
-        clang.clang_getNumElements(cxtype),
-        clang.clang_getArrayElementType(cxtype).toCodeGenType(),
-      );
-    case clang_types.CXTypeKind
-        .CXType_IncompleteArray: // Primarily used for incomplete array in function parameters.
-      return IncompleteArray(
-        clang.clang_getArrayElementType(cxtype).toCodeGenType(),
-      );
-    case clang_types.CXTypeKind.CXType_Bool:
-      return BooleanType();
-    default:
-      var typeSpellKey =
-          clang.clang_getTypeSpelling(cxtype).toStringAndDispose();
-      if (typeSpellKey.startsWith('const ')) {
-        typeSpellKey = typeSpellKey.replaceFirst('const ', '');
-      }
-      if (config.nativeTypeMappings.containsKey(typeSpellKey)) {
-        _logger.fine('  Type $typeSpellKey mapped from type-map.');
-        return config.nativeTypeMappings[typeSpellKey]!;
-      } else if (cxTypeKindToImportedTypes.containsKey(typeSpellKey)) {
-        return cxTypeKindToImportedTypes[typeSpellKey]!;
-      } else {
-        _logger.fine('typedeclarationCursorVisitor: getCodeGenType: Type Not '
-            'Implemented, ${cxtype.completeStringRepr()}');
-        return UnimplementedType('${cxtype.kindSpelling()} not implemented');
-      }
-  }
-}
-
-Type _getOrCreateBlockType(clang_types.CXType cxtype) {
-  final block = parseObjCBlock(cxtype);
-  final key = block.usr;
-  final oldBlock = bindingsIndex.getSeenObjCBlock(key);
-  if (oldBlock != null) {
-    return oldBlock;
-  }
-  bindingsIndex.addObjCBlockToSeen(key, block);
-  return block;
-}
-
-class _CreateTypeFromCursorResult {
-  final Type? type;
-
-  // Flag that controls whether the type is added to the cache. It should not
-  // be added to the cache if it's just a fallback implementation, such as the
-  // int that is returned when an enum is excluded by the config. Later we might
-  // need to build the full enum type (eg if it's part of an included struct),
-  // and if we put the fallback int in the cache then the full enum will never
-  // be created.
-  final bool addToCache;
-
-  _CreateTypeFromCursorResult(this.type, {this.addToCache = true});
-}
-
-_CreateTypeFromCursorResult _createTypeFromCursor(clang_types.CXType cxtype,
-    clang_types.CXCursor cursor, bool ignoreFilter, bool pointerReference) {
-  switch (cxtype.kind) {
-    case clang_types.CXTypeKind.CXType_Typedef:
-      final spelling = clang.clang_getTypedefName(cxtype).toStringAndDispose();
-      if (config.language == Language.objc && spelling == strings.objcBOOL) {
-        // Objective C's BOOL type can be either bool or signed char, depending
-        // on the platform. We want to present a consistent API to the user, and
-        // those two types are ABI compatible, so just return bool regardless.
-        return _CreateTypeFromCursorResult(BooleanType());
-      }
-      if (config.typedefTypeMappings.containsKey(spelling)) {
-        _logger.fine('  Type $spelling mapped from type-map');
-        return _CreateTypeFromCursorResult(
-            config.typedefTypeMappings[spelling]!);
-      }
-      // Get name from supported typedef name if config allows.
-      if (config.useSupportedTypedefs) {
-        if (suportedTypedefToSuportedNativeType.containsKey(spelling)) {
-          _logger.fine('  Type Mapped from supported typedef');
-          return _CreateTypeFromCursorResult(
-              NativeType(suportedTypedefToSuportedNativeType[spelling]!));
-        } else if (supportedTypedefToImportedType.containsKey(spelling)) {
-          _logger.fine('  Type Mapped from supported typedef');
-          return _CreateTypeFromCursorResult(
-              supportedTypedefToImportedType[spelling]!);
-        }
-      }
-
-      final typealias =
-          parseTypedefDeclaration(cursor, pointerReference: pointerReference);
-
-      if (typealias != null) {
-        return _CreateTypeFromCursorResult(typealias);
-      } else {
-        // Use underlying type if typealias couldn't be created or if the user
-        // excluded this typedef.
-        final ct = clang.clang_getTypedefDeclUnderlyingType(cursor);
-        return _CreateTypeFromCursorResult(
-            getCodeGenType(ct, pointerReference: pointerReference),
-            addToCache: false);
-      }
-    case clang_types.CXTypeKind.CXType_Record:
-      return _CreateTypeFromCursorResult(
-          _extractfromRecord(cxtype, cursor, ignoreFilter, pointerReference));
-    case clang_types.CXTypeKind.CXType_Enum:
-      final enumClass = parseEnumDeclaration(
-        cursor,
-        ignoreFilter: ignoreFilter,
-      );
-      if (enumClass == null) {
-        // Handle anonymous enum declarations within another declaration.
-        return _CreateTypeFromCursorResult(EnumClass.nativeType,
-            addToCache: false);
-      } else {
-        return _CreateTypeFromCursorResult(enumClass);
-      }
-    case clang_types.CXTypeKind.CXType_ObjCInterface:
-      return _CreateTypeFromCursorResult(
-          parseObjCInterfaceDeclaration(cursor, ignoreFilter: ignoreFilter));
-    default:
-      throw UnimplementedError('Unknown type: ${cxtype.completeStringRepr()}');
-  }
-}
-
-void _fillFromCursorIfNeeded(Type? type, clang_types.CXCursor cursor,
-    bool ignoreFilter, bool pointerReference) {
-  if (type == null) return;
-  if (type is Compound) {
-    fillCompoundMembersIfNeeded(type, cursor,
-        ignoreFilter: ignoreFilter, pointerReference: pointerReference);
-  } else if (type is ObjCInterface) {
-    fillObjCInterfaceMethodsIfNeeded(type, cursor);
-  }
-}
-
-Type? _extractfromRecord(clang_types.CXType cxtype, clang_types.CXCursor cursor,
-    bool ignoreFilter, bool pointerReference) {
-  _logger.fine('${_padding}_extractfromRecord: ${cursor.completeStringRepr()}');
-
-  final cursorKind = clang.clang_getCursorKind(cursor);
-  if (cursorKind == clang_types.CXCursorKind.CXCursor_StructDecl ||
-      cursorKind == clang_types.CXCursorKind.CXCursor_UnionDecl) {
-    final declSpelling = cursor.spelling();
-
-    // Set includer functions according to compoundType.
-    final CompoundType compoundType;
-    final Map<String, ImportedType> compoundTypeMappings;
-
-    switch (cursorKind) {
-      case clang_types.CXCursorKind.CXCursor_StructDecl:
-        compoundType = CompoundType.struct;
-        compoundTypeMappings = config.structTypeMappings;
-        break;
-      case clang_types.CXCursorKind.CXCursor_UnionDecl:
-        compoundType = CompoundType.union;
-        compoundTypeMappings = config.unionTypeMappings;
-        break;
-      default:
-        throw Exception('Unhandled compound type cursorkind.');
-    }
-
-    // Also add a struct binding, if its unseen.
-    // TODO(23): Check if we should auto add compound declarations.
-    if (compoundTypeMappings.containsKey(declSpelling)) {
-      _logger.fine('  Type Mapped from type-map');
-      return compoundTypeMappings[declSpelling]!;
-    } else {
-      final struct = parseCompoundDeclaration(
-        cursor,
-        compoundType,
-        ignoreFilter: ignoreFilter,
-        pointerReference: pointerReference,
-      );
-      return struct;
-    }
-  }
-  _logger.fine('typedeclarationCursorVisitor: _extractfromRecord: '
-      'Not Implemented, ${cursor.completeStringRepr()}');
-  return UnimplementedType('${cxtype.kindSpelling()} not implemented');
-}
-
-// Used for function pointer arguments.
-Type _extractFromFunctionProto(clang_types.CXType cxtype) {
-  final _parameters = <Parameter>[];
-  final totalArgs = clang.clang_getNumArgTypes(cxtype);
-  for (var i = 0; i < totalArgs; i++) {
-    final t = clang.clang_getArgType(cxtype, i);
-    final pt = t.toCodeGenType();
-
-    if (pt.isIncompleteCompound) {
-      return UnimplementedType(
-          'Incomplete Struct by value in function parameter.');
-    } else if (pt.baseType is UnimplementedType) {
-      return UnimplementedType('Function parameter has an unsupported type.');
-    }
-
-    _parameters.add(
-      Parameter(name: '', type: pt),
-    );
-  }
-
-  return NativeFunc(FunctionType(
-    parameters: _parameters,
-    returnType: clang.clang_getResultType(cxtype).toCodeGenType(),
-  ));
-}
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/utils.dart b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/utils.dart
deleted file mode 100644
index 7352642..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/utils.dart
+++ /dev/null
@@ -1,395 +0,0 @@
-// Copyright (c) 2020, 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.
-
-import 'dart:ffi';
-
-import 'package:ffi/ffi.dart';
-import 'package:ffigen/src/code_generator.dart';
-import 'package:ffigen/src/config_provider/config_types.dart';
-import 'package:logging/logging.dart';
-
-import 'clang_bindings/clang_bindings.dart' as clang_types;
-import 'data.dart';
-import 'type_extractor/extractor.dart';
-
-const exceptional_visitor_return =
-    clang_types.CXChildVisitResult.CXChildVisit_Break;
-
-/// Check [resultCode] of [clang.clang_visitChildren_wrap].
-///
-/// Throws exception if resultCode is not [exceptional_visitor_return].
-void visitChildrenResultChecker(int resultCode) {
-  if (resultCode != exceptional_visitor_return) {
-    throw Exception(
-        'Exception thrown in a dart function called via C, use --verbose to see more details');
-  }
-}
-
-/// Logs the warnings/errors returned by clang for a translation unit.
-void logTuDiagnostics(
-  Pointer<clang_types.CXTranslationUnitImpl> tu,
-  Logger logger,
-  String header,
-) {
-  final total = clang.clang_getNumDiagnostics(tu);
-  if (total == 0) {
-    return;
-  }
-
-  logger.severe('Header $header: Total errors/warnings: $total.');
-  for (var i = 0; i < total; i++) {
-    final diag = clang.clang_getDiagnostic(tu, i);
-    final cxstring = clang.clang_formatDiagnostic(
-      diag,
-      clang_types
-              .CXDiagnosticDisplayOptions.CXDiagnostic_DisplaySourceLocation |
-          clang_types.CXDiagnosticDisplayOptions.CXDiagnostic_DisplayColumn |
-          clang_types
-              .CXDiagnosticDisplayOptions.CXDiagnostic_DisplayCategoryName,
-    );
-    logger.severe('    ' + cxstring.toStringAndDispose());
-    clang.clang_disposeDiagnostic(diag);
-  }
-}
-
-extension CXSourceRangeExt on Pointer<clang_types.CXSourceRange> {
-  void dispose() {
-    calloc.free(this);
-  }
-}
-
-extension CXCursorExt on clang_types.CXCursor {
-  String usr() {
-    return clang.clang_getCursorUSR(this).toStringAndDispose();
-  }
-
-  /// Returns the kind int from [clang_types.CXCursorKind].
-  int kind() {
-    return clang.clang_getCursorKind(this);
-  }
-
-  /// Name of the cursor (E.g function name, Struct name, Parameter name).
-  String spelling() {
-    return clang.clang_getCursorSpelling(this).toStringAndDispose();
-  }
-
-  /// Spelling for a [clang_types.CXCursorKind], useful for debug purposes.
-  String kindSpelling() {
-    return clang
-        .clang_getCursorKindSpelling(clang.clang_getCursorKind(this))
-        .toStringAndDispose();
-  }
-
-  /// for debug: returns [spelling] [kind] [kindSpelling] [type] [typeSpelling].
-  String completeStringRepr() {
-    final cxtype = type();
-    final s =
-        '(Cursor) spelling: ${spelling()}, kind: ${kind()}, kindSpelling: ${kindSpelling()}, type: ${cxtype.kind}, typeSpelling: ${cxtype.spelling()}, usr: ${usr()}';
-    return s;
-  }
-
-  /// Type associated with the pointer if any. Type will have kind
-  /// [clang.CXTypeKind.CXType_Invalid] otherwise.
-  clang_types.CXType type() {
-    return clang.clang_getCursorType(this);
-  }
-
-  /// Only valid for [clang.CXCursorKind.CXCursor_FunctionDecl]. Type will have
-  /// kind [clang.CXTypeKind.CXType_Invalid] otherwise.
-  clang_types.CXType returnType() {
-    return clang.clang_getResultType(type());
-  }
-
-  /// Returns the file name of the file that the cursor is inside.
-  String sourceFileName() {
-    final cxsource = clang.clang_getCursorLocation(this);
-    final cxfilePtr = calloc<Pointer<Void>>();
-
-    // Puts the values in these pointers.
-    clang.clang_getFileLocation(cxsource, cxfilePtr, nullptr, nullptr, nullptr);
-    final s = clang.clang_getFileName(cxfilePtr.value).toStringAndDispose();
-
-    calloc.free(cxfilePtr);
-    return s;
-  }
-
-  /// Returns whether the file that the cursor is inside is a system header.
-  bool isInSystemHeader() {
-    final location = clang.clang_getCursorLocation(this);
-    return clang.clang_Location_isInSystemHeader(location) != 0;
-  }
-
-  /// Recursively print the AST, for debugging.
-  void printAst([int maxDepth = 3]) {
-    _printAstVisitorMaxDepth = maxDepth;
-    _printAstVisitor(this, this, Pointer<Void>.fromAddress(0));
-  }
-}
-
-int _printAstVisitorMaxDepth = 0;
-int _printAstVisitor(clang_types.CXCursor cursor, clang_types.CXCursor parent,
-    Pointer<Void> clientData) {
-  final depth = clientData.address;
-  if (depth > _printAstVisitorMaxDepth) {
-    return clang_types.CXChildVisitResult.CXChildVisit_Break;
-  }
-  print(('  ' * depth) + cursor.completeStringRepr());
-  clang.clang_visitChildren(
-      cursor,
-      Pointer.fromFunction(_printAstVisitor, exceptional_visitor_return),
-      Pointer<Void>.fromAddress(depth + 1));
-  return clang_types.CXChildVisitResult.CXChildVisit_Continue;
-}
-
-const commentPrefix = '/// ';
-const nesting = '  ';
-
-/// Stores the [clang_types.CXSourceRange] of the last comment.
-clang_types.CXSourceRange? lastCommentRange;
-
-/// Returns a cursor's associated comment.
-///
-/// The given string is wrapped at line width = 80 - [indent]. The [indent] is
-/// [commentPrefix.dimensions] by default because a comment starts with
-/// [commentPrefix].
-String? getCursorDocComment(clang_types.CXCursor cursor,
-    [int indent = commentPrefix.length]) {
-  String? formattedDocComment;
-  final currentCommentRange = clang.clang_Cursor_getCommentRange(cursor);
-
-  // See if this comment and the last comment both point to the same source
-  // range.
-  if (lastCommentRange != null &&
-      clang.clang_equalRanges(lastCommentRange!, currentCommentRange) != 0) {
-    formattedDocComment = null;
-  } else {
-    switch (config.commentType.length) {
-      case CommentLength.full:
-        formattedDocComment = removeRawCommentMarkups(
-            clang.clang_Cursor_getRawCommentText(cursor).toStringAndDispose());
-        break;
-      case CommentLength.brief:
-        formattedDocComment = _wrapNoNewLineString(
-            clang.clang_Cursor_getBriefCommentText(cursor).toStringAndDispose(),
-            80 - indent);
-        break;
-      default:
-        formattedDocComment = null;
-    }
-  }
-  lastCommentRange = currentCommentRange;
-  return formattedDocComment;
-}
-
-/// Wraps [string] according to given [lineWidth].
-///
-/// Wrapping will work properly only when String has no new lines
-/// characters(\n).
-String? _wrapNoNewLineString(String? string, int lineWidth) {
-  if (string == null || string.isEmpty) {
-    return null;
-  }
-  final sb = StringBuffer();
-
-  final words = string.split(' ');
-
-  sb.write(words[0]);
-  var trackLineWidth = words[0].length;
-  for (var i = 1; i < words.length; i++) {
-    final word = words[i];
-    if (trackLineWidth + word.length < lineWidth) {
-      sb.write(' ');
-      sb.write(word);
-      trackLineWidth += word.length + 1;
-    } else {
-      sb.write('\n');
-      sb.write(word);
-      trackLineWidth = word.length;
-    }
-  }
-  return sb.toString();
-}
-
-/// Removes /*, */ and any *'s in the beginning of a line.
-String? removeRawCommentMarkups(String? string) {
-  if (string == null || string.isEmpty) {
-    return null;
-  }
-  final sb = StringBuffer();
-
-  // Remove comment identifiers (`/** * */`, `///`, `//`) from lines.
-  if (string.contains(RegExp(r'^\s*\/\*+'))) {
-    string = string.replaceFirst(RegExp(r'^\s*\/\*+\s*'), '');
-    string = string.replaceFirst(RegExp(r'\s*\*+\/$'), '');
-    string.split('\n').forEach((element) {
-      element = element.replaceFirst(RegExp(r'^\s*\**\s*'), '');
-      sb.writeln(element);
-    });
-  } else if (string.contains(RegExp(r'^\s*\/\/\/?\s*'))) {
-    string.split('\n').forEach((element) {
-      element = element.replaceFirst(RegExp(r'^\s*\/\/\/?\s*'), '');
-      sb.writeln(element);
-    });
-  }
-
-  return sb.toString().trim();
-}
-
-bool isForwardDeclaration(clang_types.CXCursor cursor) {
-  return clang.clang_Cursor_isNull(clang.clang_getCursorDefinition(cursor)) ==
-      0;
-}
-
-extension CXTypeExt on clang_types.CXType {
-  /// Get code_gen [Type] representation of [clang_types.CXType].
-  Type toCodeGenType() {
-    return getCodeGenType(this);
-  }
-
-  /// Spelling for a [clang_types.CXTypeKind], useful for debug purposes.
-  String spelling() {
-    return clang.clang_getTypeSpelling(this).toStringAndDispose();
-  }
-
-  /// Returns the typeKind int from [clang_types.CXTypeKind].
-  int kind() {
-    return this.kind;
-  }
-
-  String kindSpelling() {
-    return clang.clang_getTypeKindSpelling(kind()).toStringAndDispose();
-  }
-
-  int alignment() {
-    return clang.clang_Type_getAlignOf(this);
-  }
-
-  /// For debugging: returns [spelling] [kind] [kindSpelling].
-  String completeStringRepr() {
-    final s =
-        '(Type) spelling: ${spelling()}, kind: ${kind()}, kindSpelling: ${kindSpelling()}';
-    return s;
-  }
-}
-
-extension CXStringExt on clang_types.CXString {
-  /// Convert CXString to a Dart string
-  ///
-  /// Make sure to dispose CXstring using dispose method, or use the
-  /// [toStringAndDispose] method.
-  String string() {
-    final cstring = clang.clang_getCString(this);
-    if (cstring != nullptr) {
-      return cstring.cast<Utf8>().toDartString();
-    } else {
-      return '';
-    }
-  }
-
-  /// Converts CXString to dart string and disposes CXString.
-  String toStringAndDispose() {
-    // Note: clang_getCString_wrap returns a const char *, calling free will result in error.
-    final s = string();
-    clang.clang_disposeString(this);
-    return s;
-  }
-
-  void dispose() {
-    clang.clang_disposeString(this);
-  }
-}
-
-/// Converts a [List<String>] to [Pointer<Pointer<Utf8>>].
-Pointer<Pointer<Utf8>> createDynamicStringArray(List<String> list) {
-  final nativeCmdArgs = calloc<Pointer<Utf8>>(list.length);
-
-  for (var i = 0; i < list.length; i++) {
-    nativeCmdArgs[i] = list[i].toNativeUtf8();
-  }
-
-  return nativeCmdArgs;
-}
-
-extension DynamicCStringArray on Pointer<Pointer<Utf8>> {
-  // Properly disposes a Pointer<Pointer<Utf8>, ensure that sure length is correct.
-  void dispose(int length) {
-    for (var i = 0; i < length; i++) {
-      calloc.free(this[i]);
-    }
-    calloc.free(this);
-  }
-}
-
-class Stack<T> {
-  final _stack = <T>[];
-
-  T get top => _stack.last;
-  T pop() => _stack.removeLast();
-  void push(T item) => _stack.add(item);
-}
-
-class IncrementalNamer {
-  final _incrementedStringCounters = <String, int>{};
-
-  /// Appends `<int>` to base. <int> is incremented on every call.
-  String name(String base) {
-    var i = _incrementedStringCounters[base] ?? 0;
-    i++;
-    _incrementedStringCounters[base] = i;
-    return '$base$i';
-  }
-}
-
-class Macro {
-  final String usr;
-  final String? originalName;
-
-  Macro(this.usr, this.originalName);
-}
-
-/// Tracks if a binding is 'seen' or not.
-class BindingsIndex {
-  // Tracks if bindings are already seen, Map key is USR obtained from libclang.
-  final Map<String, Type> _declaredTypes = {};
-  final Map<String, Func> _functions = {};
-  final Map<String, Constant> _unnamedEnumConstants = {};
-  final Map<String, String> _macros = {};
-  final Map<String, Global> _globals = {};
-  final Map<String, ObjCBlock> _objcBlocks = {};
-
-  /// Contains usr for typedefs which cannot be generated.
-  final Set<String> _unsupportedTypealiases = {};
-
-  /// Index for headers.
-  final Map<String, bool> _headerCache = {};
-
-  bool isSeenType(String usr) => _declaredTypes.containsKey(usr);
-  void addTypeToSeen(String usr, Type type) => _declaredTypes[usr] = type;
-  Type? getSeenType(String usr) => _declaredTypes[usr];
-  bool isSeenFunc(String usr) => _functions.containsKey(usr);
-  void addFuncToSeen(String usr, Func func) => _functions[usr] = func;
-  Func? getSeenFunc(String usr) => _functions[usr];
-  bool isSeenUnnamedEnumConstant(String usr) =>
-      _unnamedEnumConstants.containsKey(usr);
-  void addUnnamedEnumConstantToSeen(String usr, Constant enumConstant) =>
-      _unnamedEnumConstants[usr] = enumConstant;
-  Constant? getSeenUnnamedEnumConstant(String usr) =>
-      _unnamedEnumConstants[usr];
-  bool isSeenGlobalVar(String usr) => _globals.containsKey(usr);
-  void addGlobalVarToSeen(String usr, Global global) => _globals[usr] = global;
-  Global? getSeenGlobalVar(String usr) => _globals[usr];
-  bool isSeenMacro(String usr) => _macros.containsKey(usr);
-  void addMacroToSeen(String usr, String macro) => _macros[usr] = macro;
-  String? getSeenMacro(String usr) => _macros[usr];
-  bool isSeenUnsupportedTypealias(String usr) =>
-      _unsupportedTypealiases.contains(usr);
-  void addUnsupportedTypealiasToSeen(String usr) =>
-      _unsupportedTypealiases.add(usr);
-  bool isSeenHeader(String source) => _headerCache.containsKey(source);
-  void addHeaderToSeen(String source, bool includeStatus) =>
-      _headerCache[source] = includeStatus;
-  bool? getSeenHeaderStatus(String source) => _headerCache[source];
-  void addObjCBlockToSeen(String key, ObjCBlock t) => _objcBlocks[key] = t;
-  ObjCBlock? getSeenObjCBlock(String key) => _objcBlocks[key];
-}
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/strings.dart b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/strings.dart
deleted file mode 100644
index aa2c2d8..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/lib/src/strings.dart
+++ /dev/null
@@ -1,223 +0,0 @@
-// Copyright (c) 2020, 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.
-import 'dart:io';
-
-import 'package:ffigen/src/code_generator.dart';
-import 'package:ffigen/src/header_parser/clang_bindings/clang_bindings.dart'
-    as clang;
-
-/// Name of the dynamic library file according to current platform.
-String get dylibFileName {
-  String name;
-  if (Platform.isLinux) {
-    name = libclang_dylib_linux;
-  } else if (Platform.isMacOS) {
-    name = libclang_dylib_macos;
-  } else if (Platform.isWindows) {
-    name = libclang_dylib_windows;
-  } else {
-    throw Exception('Unsupported Platform.');
-  }
-  return name;
-}
-
-const llvmPath = 'llvm-path';
-
-/// Name of the parent folder of dynamic library `lib` or `bin` (on windows).
-String get dynamicLibParentName => Platform.isWindows ? 'bin' : 'lib';
-
-const output = 'output';
-
-const language = 'language';
-
-// String mappings for the Language enum.
-const langC = 'c';
-const langObjC = 'objc';
-
-// Clang command line args for Objective C.
-const clangLangObjC = ['-x', 'objective-c'];
-const clangObjCBoolDefine = '__OBJC_BOOL_IS_BOOL';
-const clangInclude = '-include';
-const objcBOOL = 'BOOL';
-
-// Internal objective C directories that are automatically pulled in by clang,
-// and should be excluded from output (unless explicitly used).
-const objCInternalDirectories = [
-  '/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include',
-  '/Applications/Xcode.app/Contents/Developer',
-  '/usr/local/opt/llvm/lib',
-];
-
-const headers = 'headers';
-
-// Sub-fields of headers
-const entryPoints = 'entry-points';
-const includeDirectives = 'include-directives';
-
-const compilerOpts = 'compiler-opts';
-
-const compilerOptsAuto = 'compiler-opts-automatic';
-// Sub-fields of compilerOptsAuto.
-const macos = 'macos';
-// Sub-fields of macos.
-const includeCStdLib = 'include-c-standard-library';
-
-// Declarations.
-const functions = 'functions';
-const structs = 'structs';
-const unions = 'unions';
-const enums = 'enums';
-const unnamedEnums = 'unnamed-enums';
-const globals = 'globals';
-const macros = 'macros';
-const typedefs = 'typedefs';
-const objcInterfaces = 'objc-interfaces';
-
-// Sub-fields of Declarations.
-const include = 'include';
-const exclude = 'exclude';
-const rename = 'rename';
-const memberRename = 'member-rename';
-const symbolAddress = 'symbol-address';
-
-// Nested under `functions`
-const exposeFunctionTypedefs = 'expose-typedefs';
-const leafFunctions = 'leaf';
-
-const dependencyOnly = 'dependency-only';
-// Values for `compoundDependencies`.
-const fullCompoundDependencies = 'full';
-const opaqueCompoundDependencies = 'opaque';
-
-const structPack = 'pack';
-const Map<Object, int?> packingValuesMap = {
-  'none': null,
-  1: 1,
-  2: 2,
-  4: 4,
-  8: 8,
-  16: 16,
-};
-
-// Sizemap values.
-const SChar = 'char';
-const UChar = 'unsigned char';
-const Short = 'short';
-const UShort = 'unsigned short';
-const Int = 'int';
-const UInt = 'unsigned int';
-const Long = 'long';
-const ULong = 'unsigned long';
-const LongLong = 'long long';
-const ULongLong = 'unsigned long long';
-const Enum = 'enum';
-
-// Used for validation and extraction of sizemap.
-const sizemap_native_mapping = <String, int>{
-  SChar: clang.CXTypeKind.CXType_SChar,
-  UChar: clang.CXTypeKind.CXType_UChar,
-  Short: clang.CXTypeKind.CXType_Short,
-  UShort: clang.CXTypeKind.CXType_UShort,
-  Int: clang.CXTypeKind.CXType_Int,
-  UInt: clang.CXTypeKind.CXType_UInt,
-  Long: clang.CXTypeKind.CXType_Long,
-  ULong: clang.CXTypeKind.CXType_ULong,
-  LongLong: clang.CXTypeKind.CXType_LongLong,
-  ULongLong: clang.CXTypeKind.CXType_ULongLong,
-  Enum: clang.CXTypeKind.CXType_Enum
-};
-
-// Library imports.
-const libraryImports = 'library-imports';
-
-final predefinedLibraryImports = {
-  ffiImport.name: ffiImport,
-  ffiPkgImport.name: ffiPkgImport
-};
-
-const typeMap = 'type-map';
-
-// Sub-fields for type-map.
-const typeMapTypedefs = 'typedefs';
-const typeMapStructs = 'structs';
-const typeMapUnions = 'unions';
-const typeMapNativeTypes = 'native-types';
-
-// Sub-sub-keys for fields under typeMap.
-const lib = 'lib';
-const cType = 'c-type';
-const dartType = 'dart-type';
-
-const supportedNativeType_mappings = <String, SupportedNativeType>{
-  'Void': SupportedNativeType.Void,
-  'Uint8': SupportedNativeType.Uint8,
-  'Uint16': SupportedNativeType.Uint16,
-  'Uint32': SupportedNativeType.Uint32,
-  'Uint64': SupportedNativeType.Uint64,
-  'Int8': SupportedNativeType.Int8,
-  'Int16': SupportedNativeType.Int16,
-  'Int32': SupportedNativeType.Int32,
-  'Int64': SupportedNativeType.Int64,
-  'IntPtr': SupportedNativeType.IntPtr,
-  'Float': SupportedNativeType.Float,
-  'Double': SupportedNativeType.Double,
-};
-
-// Boolean flags.
-const sort = 'sort';
-const useSupportedTypedefs = 'use-supported-typedefs';
-const useDartHandle = 'use-dart-handle';
-
-const comments = 'comments';
-// Sub-fields of comments.
-const style = 'style';
-const length = 'length';
-
-// Sub-fields of style.
-const doxygen = 'doxygen';
-const any = 'any';
-// Sub-fields of length.
-const brief = 'brief';
-const full = 'full';
-// Cmd line comment option.
-const fparseAllComments = '-fparse-all-comments';
-
-// Library input.
-const name = 'name';
-const description = 'description';
-const preamble = 'preamble';
-
-// Dynamic library names.
-const libclang_dylib_linux = 'libclang.so';
-const libclang_dylib_macos = 'libclang.dylib';
-const libclang_dylib_windows = 'libclang.dll';
-
-// Dynamic library default locations.
-const linuxDylibLocations = {
-  '/usr/lib/llvm-9/lib/',
-  '/usr/lib/llvm-10/lib/',
-  '/usr/lib/llvm-11/lib/',
-  '/usr/lib/llvm-12/lib/',
-  '/usr/lib/llvm-13/lib/',
-  '/usr/lib/llvm-14/lib/',
-  '/usr/lib/llvm-15/lib/',
-  '/usr/lib/',
-  '/usr/lib64/',
-};
-const windowsDylibLocations = {
-  r'C:\Program Files\LLVM\bin\',
-};
-const macOsDylibLocations = {
-  '/usr/local/opt/llvm/lib/',
-  '/opt/homebrew/opt/llvm/lib/',
-  '/Library/Developer/CommandLineTools/usr/',
-};
-
-// Writen doubles.
-const doubleInfinity = 'double.infinity';
-const doubleNegativeInfinity = 'double.negativeInfinity';
-const doubleNaN = 'double.nan';
-
-/// USR for struct `_Dart_Handle`.
-const dartHandleUsr = 'c:@S@_Dart_Handle';
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/pubspec.yaml b/pkgs/jni/third_party/ffigen_patch_jni/pubspec.yaml
deleted file mode 100644
index 237c0fd..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/pubspec.yaml
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright (c) 2020, 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.
-
-name: ffigen
-version: 6.0.1
-description: Generator for FFI bindings, using LibClang to parse C header files.
-repository: https://github.com/dart-lang/ffigen
-
-environment:
-  sdk: '>=2.17.0 <4.0.0'
-
-dependencies:
-  ffi: ^2.0.0
-  yaml: ^3.0.0
-  path: ^1.8.0
-  quiver: ^3.0.0
-  args: ^2.0.0
-  logging: ^1.0.0
-  cli_util: ^0.3.0
-  glob: ^2.0.0
-  file: ^6.0.0
-
-dev_dependencies:
-  lints: ^1.0.1
-  test: ^1.16.2
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/tool/coverage.sh b/pkgs/jni/third_party/ffigen_patch_jni/tool/coverage.sh
deleted file mode 100755
index 02c8e2f..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/tool/coverage.sh
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/bash
-
-# Copyright (c) 2020, 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.
-
-# Fast fail the script on failures.
-set -e
-
-# Gather coverage.
-dart pub global activate coverage
-# Generate coverage report.
-dart run --pause-isolates-on-exit --disable-service-auth-codes --enable-vm-service=3000 test &
-dart pub global run coverage:collect_coverage --wait-paused --uri=http://127.0.0.1:3000/ -o coverage.json --resume-isolates --scope-output=ffigen
-dart pub global run coverage:format_coverage --packages=.dart_tool/package_config.json --lcov -i coverage.json -o lcov.info
diff --git a/pkgs/jni/third_party/ffigen_patch_jni/tool/libclang_config.yaml b/pkgs/jni/third_party/ffigen_patch_jni/tool/libclang_config.yaml
deleted file mode 100644
index ad0bfd0..0000000
--- a/pkgs/jni/third_party/ffigen_patch_jni/tool/libclang_config.yaml
+++ /dev/null
@@ -1,119 +0,0 @@
-# Copyright (c) 2020, 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.
-
-# Config file for generating the libclang bindings used by this package.
-
-# ===================== GENERATING BINDINGS =====================
-#    cd to project's root, and run -
-#    dart run ffigen --config tool/libclang_config.yaml
-# ===============================================================
-
-name: Clang
-description: Holds bindings to LibClang.
-output: 'lib/src/header_parser/clang_bindings/clang_bindings.dart'
-compiler-opts:
-  - '-Ithird_party/libclang/include'
-  - '-Wno-nullability-completeness'
-headers:
-  entry-points:
-    - 'third_party/libclang/include/clang-c/Index.h'
-  include-directives:
-    - '**wrapper.c'
-    - '**Index.h'
-    - '**CXString.h'
-
-preamble: |
-  // Part of the LLVM Project, under the Apache License v2.0 with LLVM
-  // Exceptions.
-  // See https://llvm.org/LICENSE.txt for license information.
-  // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-
-  // ignore_for_file: camel_case_types, non_constant_identifier_names
-
-enums:
-  include:
-    - CXChildVisitResult
-    - CXCursorKind
-    - CXTypeKind
-    - CXDiagnosticDisplayOptions
-    - CXTranslationUnit_Flags
-    - CXEvalResultKind
-    - CXObjCPropertyAttrKind
-    - CXTypeNullabilityKind
-
-structs:
-  include:
-    - CXCursor
-    - CXType
-    - CXSourceLocation
-    - CXString
-    - CXTranslationUnitImpl
-    - CXUnsavedFile
-    - CXSourceRange
-
-functions:
-  include:
-    - clang_createIndex
-    - clang_disposeIndex
-    - clang_getNumDiagnostics
-    - clang_getDiagnostic
-    - clang_disposeDiagnostic
-    - clang_parseTranslationUnit
-    - clang_disposeTranslationUnit
-    - clang_EvalResult_getKind
-    - clang_EvalResult_getAsInt
-    - clang_EvalResult_getAsLongLong
-    - clang_EvalResult_getAsDouble
-    - clang_EvalResult_getAsStr
-    - clang_EvalResult_dispose
-    - clang_getCString
-    - clang_disposeString
-    - clang_getCursorKind
-    - clang_getCursorKindSpelling
-    - clang_getCursorType
-    - clang_getTypeSpelling
-    - clang_getTypeKindSpelling
-    - clang_getResultType
-    - clang_getTypedefName
-    - clang_getPointeeType
-    - clang_getCanonicalType
-    - clang_Type_getNamedType
-    - clang_Type_getAlignOf
-    - clang_getTypeDeclaration
-    - clang_getTypedefDeclUnderlyingType
-    - clang_getCursorSpelling
-    - clang_getTranslationUnitCursor
-    - clang_formatDiagnostic
-    - clang_visitChildren
-    - clang_Cursor_getNumArguments
-    - clang_Cursor_getArgument
-    - clang_getNumArgTypes
-    - clang_getArgType
-    - clang_getEnumConstantDeclValue
-    - clang_equalRanges
-    - clang_Cursor_getCommentRange
-    - clang_Cursor_getRawCommentText
-    - clang_Cursor_getBriefCommentText
-    - clang_getCursorLocation
-    - clang_getFileLocation
-    - clang_getFileName
-    - clang_getNumElements
-    - clang_getArrayElementType
-    - clang_Cursor_isMacroFunctionLike
-    - clang_Cursor_isMacroBuiltin
-    - clang_Cursor_Evaluate
-    - clang_Cursor_isAnonymous
-    - clang_Cursor_isAnonymousRecordDecl
-    - clang_getCursorUSR
-    - clang_getFieldDeclBitWidth
-    - clang_Cursor_isFunctionInlined
-    - clang_getCursorDefinition
-    - clang_Cursor_isNull
-    - clang_Cursor_hasAttrs
-    - clang_Type_getObjCObjectBaseType
-    - clang_Cursor_getObjCPropertyAttributes
-    - clang_Cursor_getObjCPropertyGetterName
-    - clang_Cursor_getObjCPropertySetterName
-    - clang_Type_getNullability
-    - clang_Location_isInSystemHeader
diff --git a/pkgs/jni/third_party/jni.h b/pkgs/jni/third_party/jni.h
index 961dd09..b71105e 100644
--- a/pkgs/jni/third_party/jni.h
+++ b/pkgs/jni/third_party/jni.h
@@ -29,458 +29,489 @@
 #include <stdint.h>
 
 /* Primitive types that match up with Java equivalents. */
-typedef uint8_t  jboolean; /* unsigned 8 bits */
-typedef int8_t   jbyte;    /* signed 8 bits */
-typedef uint16_t jchar;    /* unsigned 16 bits */
-typedef int16_t  jshort;   /* signed 16 bits */
-typedef int32_t  jint;     /* signed 32 bits */
-typedef int64_t  jlong;    /* signed 64 bits */
-typedef float    jfloat;   /* 32-bit IEEE 754 */
-typedef double   jdouble;  /* 64-bit IEEE 754 */
+typedef uint8_t jboolean; /* unsigned 8 bits */
+typedef int8_t jbyte;     /* signed 8 bits */
+typedef uint16_t jchar;   /* unsigned 16 bits */
+typedef int16_t jshort;   /* signed 16 bits */
+typedef int32_t jint;     /* signed 32 bits */
+typedef int64_t jlong;    /* signed 64 bits */
+typedef float jfloat;     /* 32-bit IEEE 754 */
+typedef double jdouble;   /* 64-bit IEEE 754 */
 
 /* "cardinal indices and sizes" */
-typedef jint     jsize;
+typedef jint jsize;
 
 #ifdef __cplusplus
 /*
  * Reference types, in C++
  */
-class _jobject {};
-class _jclass : public _jobject {};
-class _jstring : public _jobject {};
-class _jarray : public _jobject {};
-class _jobjectArray : public _jarray {};
-class _jbooleanArray : public _jarray {};
-class _jbyteArray : public _jarray {};
-class _jcharArray : public _jarray {};
-class _jshortArray : public _jarray {};
-class _jintArray : public _jarray {};
-class _jlongArray : public _jarray {};
-class _jfloatArray : public _jarray {};
-class _jdoubleArray : public _jarray {};
-class _jthrowable : public _jobject {};
+class _jobject
+{
+};
+class _jclass : public _jobject
+{
+};
+class _jstring : public _jobject
+{
+};
+class _jarray : public _jobject
+{
+};
+class _jobjectArray : public _jarray
+{
+};
+class _jbooleanArray : public _jarray
+{
+};
+class _jbyteArray : public _jarray
+{
+};
+class _jcharArray : public _jarray
+{
+};
+class _jshortArray : public _jarray
+{
+};
+class _jintArray : public _jarray
+{
+};
+class _jlongArray : public _jarray
+{
+};
+class _jfloatArray : public _jarray
+{
+};
+class _jdoubleArray : public _jarray
+{
+};
+class _jthrowable : public _jobject
+{
+};
 
-typedef _jobject*       jobject;
-typedef _jclass*        jclass;
-typedef _jstring*       jstring;
-typedef _jarray*        jarray;
-typedef _jobjectArray*  jobjectArray;
-typedef _jbooleanArray* jbooleanArray;
-typedef _jbyteArray*    jbyteArray;
-typedef _jcharArray*    jcharArray;
-typedef _jshortArray*   jshortArray;
-typedef _jintArray*     jintArray;
-typedef _jlongArray*    jlongArray;
-typedef _jfloatArray*   jfloatArray;
-typedef _jdoubleArray*  jdoubleArray;
-typedef _jthrowable*    jthrowable;
-typedef _jobject*       jweak;
-
+typedef _jobject *jobject;
+typedef _jclass *jclass;
+typedef _jstring *jstring;
+typedef _jarray *jarray;
+typedef _jobjectArray *jobjectArray;
+typedef _jbooleanArray *jbooleanArray;
+typedef _jbyteArray *jbyteArray;
+typedef _jcharArray *jcharArray;
+typedef _jshortArray *jshortArray;
+typedef _jintArray *jintArray;
+typedef _jlongArray *jlongArray;
+typedef _jfloatArray *jfloatArray;
+typedef _jdoubleArray *jdoubleArray;
+typedef _jthrowable *jthrowable;
+typedef _jobject *jweak;
 
 #else /* not __cplusplus */
 
 /*
  * Reference types, in C.
  */
-typedef void*           jobject;
-typedef jobject         jclass;
-typedef jobject         jstring;
-typedef jobject         jarray;
-typedef jarray          jobjectArray;
-typedef jarray          jbooleanArray;
-typedef jarray          jbyteArray;
-typedef jarray          jcharArray;
-typedef jarray          jshortArray;
-typedef jarray          jintArray;
-typedef jarray          jlongArray;
-typedef jarray          jfloatArray;
-typedef jarray          jdoubleArray;
-typedef jobject         jthrowable;
-typedef jobject         jweak;
+typedef void *jobject;
+typedef jobject jclass;
+typedef jobject jstring;
+typedef jobject jarray;
+typedef jarray jobjectArray;
+typedef jarray jbooleanArray;
+typedef jarray jbyteArray;
+typedef jarray jcharArray;
+typedef jarray jshortArray;
+typedef jarray jintArray;
+typedef jarray jlongArray;
+typedef jarray jfloatArray;
+typedef jarray jdoubleArray;
+typedef jobject jthrowable;
+typedef jobject jweak;
 
 #endif /* not __cplusplus */
 
-struct _jfieldID;                       /* opaque structure */
-typedef struct _jfieldID* jfieldID;     /* field IDs */
+struct _jfieldID;                   /* opaque structure */
+typedef struct _jfieldID *jfieldID; /* field IDs */
 
-struct _jmethodID;                      /* opaque structure */
-typedef struct _jmethodID* jmethodID;   /* method IDs */
+struct _jmethodID;                    /* opaque structure */
+typedef struct _jmethodID *jmethodID; /* method IDs */
 
 struct JNIInvokeInterface;
 
-typedef union jvalue {
-    jboolean    z;
-    jbyte       b;
-    jchar       c;
-    jshort      s;
-    jint        i;
-    jlong       j;
-    jfloat      f;
-    jdouble     d;
-    jobject     l;
+typedef union jvalue
+{
+    jboolean z;
+    jbyte b;
+    jchar c;
+    jshort s;
+    jint i;
+    jlong j;
+    jfloat f;
+    jdouble d;
+    jobject l;
 } jvalue;
 
-typedef enum jobjectRefType {
+typedef enum jobjectRefType
+{
     JNIInvalidRefType = 0,
     JNILocalRefType = 1,
     JNIGlobalRefType = 2,
     JNIWeakGlobalRefType = 3
 } jobjectRefType;
 
-typedef struct {
-    const char* name;
-    const char* signature;
-    void*       fnPtr;
+typedef struct
+{
+    const char *name;
+    const char *signature;
+    void *fnPtr;
 } JNINativeMethod;
 
 struct _JNIEnv;
 struct _JavaVM;
-typedef const struct JNINativeInterface* C_JNIEnv;
+typedef const struct JNINativeInterface *C_JNIEnv;
 
 #if defined(__cplusplus)
 typedef _JNIEnv JNIEnv;
 typedef _JavaVM JavaVM;
 #else
-typedef const struct JNINativeInterface* JNIEnv;
-typedef const struct JNIInvokeInterface* JavaVM;
+typedef const struct JNINativeInterface *JNIEnv;
+typedef const struct JNIInvokeInterface *JavaVM;
 #endif
 
 /*
  * Table of interface function pointers.
  */
-struct JNINativeInterface {
-    void*       reserved0;
-    void*       reserved1;
-    void*       reserved2;
-    void*       reserved3;
+struct JNINativeInterface
+{
+    void *reserved0;
+    void *reserved1;
+    void *reserved2;
+    void *reserved3;
 
-    jint        (*GetVersion)(JNIEnv *env);
-    jclass      (*DefineClass)(JNIEnv *env, const char* name, jobject loader, const jbyte* buf,
-                        jsize bufLen);
-    jclass      (*FindClass)(JNIEnv* env, const char* name);
+    jint (*GetVersion)(JNIEnv *env);
+    jclass (*DefineClass)(JNIEnv *env, const char *name, jobject loader, const jbyte *buf,
+                          jsize bufLen);
+    jclass (*FindClass)(JNIEnv *env, const char *name);
 
-    jmethodID   (*FromReflectedMethod)(JNIEnv* env, jobject method);
-    jfieldID    (*FromReflectedField)(JNIEnv* env, jobject field);
+    jmethodID (*FromReflectedMethod)(JNIEnv *env, jobject method);
+    jfieldID (*FromReflectedField)(JNIEnv *env, jobject field);
 
     /* spec doesn't show jboolean parameter */
 
-    jobject     (*ToReflectedMethod)(JNIEnv* env, jclass cls, jmethodID methodId, jboolean isStatic);
+    jobject (*ToReflectedMethod)(JNIEnv *env, jclass cls, jmethodID methodId, jboolean isStatic);
 
-    jclass      (*GetSuperclass)(JNIEnv* env, jclass clazz);
-    jboolean    (*IsAssignableFrom)(JNIEnv* env, jclass clazz1, jclass clazz2);
+    jclass (*GetSuperclass)(JNIEnv *env, jclass clazz);
+    jboolean (*IsAssignableFrom)(JNIEnv *env, jclass clazz1, jclass clazz2);
 
     /* spec doesn't show jboolean parameter */
 
-    jobject     (*ToReflectedField)(JNIEnv* env, jclass cls, jfieldID fieldID, jboolean isStatic);
+    jobject (*ToReflectedField)(JNIEnv *env, jclass cls, jfieldID fieldID, jboolean isStatic);
 
-    jint        (*Throw)(JNIEnv* env, jthrowable obj);
-    jint        (*ThrowNew)(JNIEnv *env, jclass clazz, const char *message);
-    jthrowable  (*ExceptionOccurred)(JNIEnv* env);
-    void        (*ExceptionDescribe)(JNIEnv* env);
-    void        (*ExceptionClear)(JNIEnv* env);
-    void        (*FatalError)(JNIEnv* env, const char* msg);
+    jint (*Throw)(JNIEnv *env, jthrowable obj);
+    jint (*ThrowNew)(JNIEnv *env, jclass clazz, const char *message);
+    jthrowable (*ExceptionOccurred)(JNIEnv *env);
+    void (*ExceptionDescribe)(JNIEnv *env);
+    void (*ExceptionClear)(JNIEnv *env);
+    void (*FatalError)(JNIEnv *env, const char *msg);
 
-    jint        (*PushLocalFrame)(JNIEnv* env, jint capacity);
-    jobject     (*PopLocalFrame)(JNIEnv* env, jobject result);
+    jint (*PushLocalFrame)(JNIEnv *env, jint capacity);
+    jobject (*PopLocalFrame)(JNIEnv *env, jobject result);
 
-    jobject     (*NewGlobalRef)(JNIEnv* env, jobject obj);
-    void        (*DeleteGlobalRef)(JNIEnv* env, jobject globalRef);
-    void        (*DeleteLocalRef)(JNIEnv* env, jobject localRef);
-    jboolean    (*IsSameObject)(JNIEnv* env, jobject ref1, jobject ref2);
+    jobject (*NewGlobalRef)(JNIEnv *env, jobject obj);
+    void (*DeleteGlobalRef)(JNIEnv *env, jobject globalRef);
+    void (*DeleteLocalRef)(JNIEnv *env, jobject localRef);
+    jboolean (*IsSameObject)(JNIEnv *env, jobject ref1, jobject ref2);
 
-    jobject     (*NewLocalRef)(JNIEnv* env, jobject ref);
-    jint        (*EnsureLocalCapacity)(JNIEnv* env, jint capacity);
+    jobject (*NewLocalRef)(JNIEnv *env, jobject obj);
+    jint (*EnsureLocalCapacity)(JNIEnv *env, jint capacity);
 
-    jobject     (*AllocObject)(JNIEnv* env, jclass clazz);
-    jobject     (*NewObject)(JNIEnv*, jclass, jmethodID, ...);
-    jobject     (*NewObjectV)(JNIEnv*, jclass, jmethodID, va_list);
-    jobject     (*NewObjectA)(JNIEnv* env, jclass clazz, jmethodID methodID, const jvalue* args);
+    jobject (*AllocObject)(JNIEnv *env, jclass clazz);
+    jobject (*NewObject)(JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+    jobject (*NewObjectV)(JNIEnv *, jclass, jmethodID, void *);
+    jobject (*NewObjectA)(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
 
-    jclass      (*GetObjectClass)(JNIEnv* env, jobject obj);
-    jboolean    (*IsInstanceOf)(JNIEnv* env, jobject obj, jclass clazz);
-    jmethodID   (*GetMethodID)(JNIEnv* env, jclass clazz, const char* name, const char* sig);
+    jclass (*GetObjectClass)(JNIEnv *env, jobject obj);
+    jboolean (*IsInstanceOf)(JNIEnv *env, jobject obj, jclass clazz);
+    jmethodID (*GetMethodID)(JNIEnv *env, jclass clazz, const char *name, const char *sig);
 
-    jobject     (*CallObjectMethod)(JNIEnv*, jobject, jmethodID, ...);
-    jobject     (*CallObjectMethodV)(JNIEnv*, jobject, jmethodID, va_list);
-    jobject     (*CallObjectMethodA)(JNIEnv* env, jobject obj, jmethodID methodID, const jvalue* args);
-    jboolean    (*CallBooleanMethod)(JNIEnv*, jobject, jmethodID, ...);
-    jboolean    (*CallBooleanMethodV)(JNIEnv*, jobject, jmethodID, va_list);
-    jboolean    (*CallBooleanMethodA)(JNIEnv* env, jobject obj, jmethodID methodId, const jvalue* args);
-    jbyte       (*CallByteMethod)(JNIEnv*, jobject, jmethodID, ...);
-    jbyte       (*CallByteMethodV)(JNIEnv*, jobject, jmethodID, va_list);
-    jbyte       (*CallByteMethodA)(JNIEnv* env, jobject obj, jmethodID methodID, const jvalue* args);
-    jchar       (*CallCharMethod)(JNIEnv*, jobject, jmethodID, ...);
-    jchar       (*CallCharMethodV)(JNIEnv*, jobject, jmethodID, va_list);
-    jchar       (*CallCharMethodA)(JNIEnv* env, jobject obj, jmethodID methodID, const jvalue* args);
-    jshort      (*CallShortMethod)(JNIEnv*, jobject, jmethodID, ...);
-    jshort      (*CallShortMethodV)(JNIEnv*, jobject, jmethodID, va_list);
-    jshort      (*CallShortMethodA)(JNIEnv* env, jobject obj, jmethodID methodID, const jvalue* args);
-    jint        (*CallIntMethod)(JNIEnv*, jobject, jmethodID, ...);
-    jint        (*CallIntMethodV)(JNIEnv*, jobject, jmethodID, va_list);
-    jint        (*CallIntMethodA)(JNIEnv* env, jobject obj, jmethodID methodID, const jvalue* args);
-    jlong       (*CallLongMethod)(JNIEnv*, jobject, jmethodID, ...);
-    jlong       (*CallLongMethodV)(JNIEnv*, jobject, jmethodID, va_list);
-    jlong       (*CallLongMethodA)(JNIEnv* env, jobject obj, jmethodID methodID, const jvalue* args);
-    jfloat      (*CallFloatMethod)(JNIEnv*, jobject, jmethodID, ...);
-    jfloat      (*CallFloatMethodV)(JNIEnv*, jobject, jmethodID, va_list);
-    jfloat      (*CallFloatMethodA)(JNIEnv* env, jobject obj, jmethodID methodID, const jvalue* args);
-    jdouble     (*CallDoubleMethod)(JNIEnv*, jobject, jmethodID, ...);
-    jdouble     (*CallDoubleMethodV)(JNIEnv*, jobject, jmethodID, va_list);
-    jdouble     (*CallDoubleMethodA)(JNIEnv* env, jobject obj, jmethodID methodID, const jvalue* args);
-    void        (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);
-    void        (*CallVoidMethodV)(JNIEnv*, jobject, jmethodID, va_list);
-    void        (*CallVoidMethodA)(JNIEnv* env, jobject obj, jmethodID methodID, const jvalue* args);
+    jobject (*CallObjectMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...);
+    jobject (*CallObjectMethodV)(JNIEnv *, jobject, jmethodID, void *);
+    jobject (*CallObjectMethodA)(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+    jboolean (*CallBooleanMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...);
+    jboolean (*CallBooleanMethodV)(JNIEnv *, jobject, jmethodID, void *);
+    jboolean (*CallBooleanMethodA)(JNIEnv *env, jobject obj, jmethodID methodId, const jvalue *args);
+    jbyte (*CallByteMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...);
+    jbyte (*CallByteMethodV)(JNIEnv *, jobject, jmethodID, void *);
+    jbyte (*CallByteMethodA)(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+    jchar (*CallCharMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...);
+    jchar (*CallCharMethodV)(JNIEnv *, jobject, jmethodID, void *);
+    jchar (*CallCharMethodA)(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+    jshort (*CallShortMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...);
+    jshort (*CallShortMethodV)(JNIEnv *, jobject, jmethodID, void *);
+    jshort (*CallShortMethodA)(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+    jint (*CallIntMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...);
+    jint (*CallIntMethodV)(JNIEnv *, jobject, jmethodID, void *);
+    jint (*CallIntMethodA)(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+    jlong (*CallLongMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...);
+    jlong (*CallLongMethodV)(JNIEnv *, jobject, jmethodID, void *);
+    jlong (*CallLongMethodA)(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+    jfloat (*CallFloatMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...);
+    jfloat (*CallFloatMethodV)(JNIEnv *, jobject, jmethodID, void *);
+    jfloat (*CallFloatMethodA)(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+    jdouble (*CallDoubleMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...);
+    jdouble (*CallDoubleMethodV)(JNIEnv *, jobject, jmethodID, void *);
+    jdouble (*CallDoubleMethodA)(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+    void (*CallVoidMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...);
+    void (*CallVoidMethodV)(JNIEnv *, jobject, jmethodID, void *);
+    void (*CallVoidMethodA)(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
 
-    jobject     (*CallNonvirtualObjectMethod)(JNIEnv*, jobject, jclass,
-                        jmethodID, ...);
-    jobject     (*CallNonvirtualObjectMethodV)(JNIEnv*, jobject, jclass,
-                        jmethodID, va_list);
-    jobject     (*CallNonvirtualObjectMethodA)(JNIEnv* env, jobject obj, jclass clazz,
-                        jmethodID methodID, const jvalue* args);
-    jboolean    (*CallNonvirtualBooleanMethod)(JNIEnv*, jobject, jclass,
-                        jmethodID, ...);
-    jboolean    (*CallNonvirtualBooleanMethodV)(JNIEnv*, jobject, jclass,
-                         jmethodID, va_list);
-    jboolean    (*CallNonvirtualBooleanMethodA)(JNIEnv* env, jobject obj, jclass clazz,
-                         jmethodID methodID, const jvalue* args);
-    jbyte       (*CallNonvirtualByteMethod)(JNIEnv*, jobject, jclass,
-                        jmethodID, ...);
-    jbyte       (*CallNonvirtualByteMethodV)(JNIEnv*, jobject, jclass,
-                        jmethodID, va_list);
-    jbyte       (*CallNonvirtualByteMethodA)(JNIEnv* env, jobject obj, jclass clazz,
-                        jmethodID methodID, const jvalue* args);
-    jchar       (*CallNonvirtualCharMethod)(JNIEnv*, jobject, jclass,
-                        jmethodID, ...);
-    jchar       (*CallNonvirtualCharMethodV)(JNIEnv*, jobject, jclass,
-                        jmethodID, va_list);
-    jchar       (*CallNonvirtualCharMethodA)(JNIEnv* env, jobject obj, jclass clazz,
-                        jmethodID methodID, const jvalue* args);
-    jshort      (*CallNonvirtualShortMethod)(JNIEnv*, jobject, jclass,
-                        jmethodID, ...);
-    jshort      (*CallNonvirtualShortMethodV)(JNIEnv*, jobject, jclass,
-                        jmethodID, va_list);
-    jshort      (*CallNonvirtualShortMethodA)(JNIEnv* env, jobject obj, jclass clazz,
-                        jmethodID methodID, const jvalue* args);
-    jint        (*CallNonvirtualIntMethod)(JNIEnv*, jobject, jclass,
-                        jmethodID, ...);
-    jint        (*CallNonvirtualIntMethodV)(JNIEnv*, jobject, jclass,
-                        jmethodID, va_list);
-    jint        (*CallNonvirtualIntMethodA)(JNIEnv* env, jobject obj, jclass clazz,
-                        jmethodID methodID, const jvalue* args);
-    jlong       (*CallNonvirtualLongMethod)(JNIEnv*, jobject, jclass,
-                        jmethodID, ...);
-    jlong       (*CallNonvirtualLongMethodV)(JNIEnv*, jobject, jclass,
-                        jmethodID, va_list);
-    jlong       (*CallNonvirtualLongMethodA)(JNIEnv* env, jobject obj, jclass clazz,
-                        jmethodID methodID, const jvalue* args);
-    jfloat      (*CallNonvirtualFloatMethod)(JNIEnv*, jobject, jclass,
-                        jmethodID, ...);
-    jfloat      (*CallNonvirtualFloatMethodV)(JNIEnv*, jobject, jclass,
-                        jmethodID, va_list);
-    jfloat      (*CallNonvirtualFloatMethodA)(JNIEnv* env, jobject obj, jclass clazz,
-                        jmethodID methodID, const jvalue* args);
-    jdouble     (*CallNonvirtualDoubleMethod)(JNIEnv*, jobject, jclass,
-                        jmethodID, ...);
-    jdouble     (*CallNonvirtualDoubleMethodV)(JNIEnv*, jobject, jclass,
-                        jmethodID, va_list);
-    jdouble     (*CallNonvirtualDoubleMethodA)(JNIEnv* env, jobject obj, jclass clazz,
-                        jmethodID methodID, const jvalue* args);
-    void        (*CallNonvirtualVoidMethod)(JNIEnv*, jobject, jclass,
-                        jmethodID, ...);
-    void        (*CallNonvirtualVoidMethodV)(JNIEnv*, jobject, jclass,
-                        jmethodID, va_list);
-    void        (*CallNonvirtualVoidMethodA)(JNIEnv* env, jobject obj, jclass clazz,
-                        jmethodID methodID, const jvalue* args);
+    jobject (*CallNonvirtualObjectMethod)(JNIEnv *env, jobject obj, jclass clazz,
+                                          jmethodID methodID, ...);
+    jobject (*CallNonvirtualObjectMethodV)(JNIEnv *, jobject, jclass,
+                                           jmethodID, void *);
+    jobject (*CallNonvirtualObjectMethodA)(JNIEnv *env, jobject obj, jclass clazz,
+                                           jmethodID methodID, const jvalue *args);
+    jboolean (*CallNonvirtualBooleanMethod)(JNIEnv *env, jobject obj, jclass clazz,
+                                            jmethodID methodID, ...);
+    jboolean (*CallNonvirtualBooleanMethodV)(JNIEnv *, jobject, jclass,
+                                             jmethodID, void *);
+    jboolean (*CallNonvirtualBooleanMethodA)(JNIEnv *env, jobject obj, jclass clazz,
+                                             jmethodID methodID, const jvalue *args);
+    jbyte (*CallNonvirtualByteMethod)(JNIEnv *env, jobject obj, jclass clazz,
+                                      jmethodID methodID, ...);
+    jbyte (*CallNonvirtualByteMethodV)(JNIEnv *, jobject, jclass,
+                                       jmethodID, void *);
+    jbyte (*CallNonvirtualByteMethodA)(JNIEnv *env, jobject obj, jclass clazz,
+                                       jmethodID methodID, const jvalue *args);
+    jchar (*CallNonvirtualCharMethod)(JNIEnv *env, jobject obj, jclass clazz,
+                                      jmethodID methodID, ...);
+    jchar (*CallNonvirtualCharMethodV)(JNIEnv *, jobject, jclass,
+                                       jmethodID, void *);
+    jchar (*CallNonvirtualCharMethodA)(JNIEnv *env, jobject obj, jclass clazz,
+                                       jmethodID methodID, const jvalue *args);
+    jshort (*CallNonvirtualShortMethod)(JNIEnv *env, jobject obj, jclass clazz,
+                                        jmethodID methodID, ...);
+    jshort (*CallNonvirtualShortMethodV)(JNIEnv *, jobject, jclass,
+                                         jmethodID, void *);
+    jshort (*CallNonvirtualShortMethodA)(JNIEnv *env, jobject obj, jclass clazz,
+                                         jmethodID methodID, const jvalue *args);
+    jint (*CallNonvirtualIntMethod)(JNIEnv *env, jobject obj, jclass clazz,
+                                    jmethodID methodID, ...);
+    jint (*CallNonvirtualIntMethodV)(JNIEnv *, jobject, jclass,
+                                     jmethodID, void *);
+    jint (*CallNonvirtualIntMethodA)(JNIEnv *env, jobject obj, jclass clazz,
+                                     jmethodID methodID, const jvalue *args);
+    jlong (*CallNonvirtualLongMethod)(JNIEnv *env, jobject obj, jclass clazz,
+                                      jmethodID methodID, ...);
+    jlong (*CallNonvirtualLongMethodV)(JNIEnv *, jobject, jclass,
+                                       jmethodID, void *);
+    jlong (*CallNonvirtualLongMethodA)(JNIEnv *env, jobject obj, jclass clazz,
+                                       jmethodID methodID, const jvalue *args);
+    jfloat (*CallNonvirtualFloatMethod)(JNIEnv *env, jobject obj, jclass clazz,
+                                      jmethodID methodID, ...);
+    jfloat (*CallNonvirtualFloatMethodV)(JNIEnv *, jobject, jclass,
+                                         jmethodID, void *);
+    jfloat (*CallNonvirtualFloatMethodA)(JNIEnv *env, jobject obj, jclass clazz,
+                                         jmethodID methodID, const jvalue *args);
+    jdouble (*CallNonvirtualDoubleMethod)(JNIEnv *env, jobject obj, jclass clazz,
+                                      jmethodID methodID, ...);
+    jdouble (*CallNonvirtualDoubleMethodV)(JNIEnv *, jobject, jclass,
+                                           jmethodID, void *);
+    jdouble (*CallNonvirtualDoubleMethodA)(JNIEnv *env, jobject obj, jclass clazz,
+                                           jmethodID methodID, const jvalue *args);
+    void (*CallNonvirtualVoidMethod)(JNIEnv *env, jobject obj, jclass clazz,
+                                      jmethodID methodID, ...);
+    void (*CallNonvirtualVoidMethodV)(JNIEnv *, jobject, jclass,
+                                      jmethodID, void *);
+    void (*CallNonvirtualVoidMethodA)(JNIEnv *env, jobject obj, jclass clazz,
+                                      jmethodID methodID, const jvalue *args);
 
-    jfieldID    (*GetFieldID)(JNIEnv* env, jclass clazz, const char* name, const char* sig);
+    jfieldID (*GetFieldID)(JNIEnv *env, jclass clazz, const char *name, const char *sig);
 
-    jobject     (*GetObjectField)(JNIEnv* env, jobject obj, jfieldID fieldID);
-    jboolean    (*GetBooleanField)(JNIEnv* env, jobject obj, jfieldID fieldID);
-    jbyte       (*GetByteField)(JNIEnv* env, jobject obj, jfieldID fieldID);
-    jchar       (*GetCharField)(JNIEnv* env, jobject obj, jfieldID fieldID);
-    jshort      (*GetShortField)(JNIEnv* env, jobject obj, jfieldID fieldID);
-    jint        (*GetIntField)(JNIEnv* env, jobject obj, jfieldID fieldID);
-    jlong       (*GetLongField)(JNIEnv* env, jobject obj, jfieldID fieldID);
-    jfloat      (*GetFloatField)(JNIEnv* env, jobject obj, jfieldID fieldID);
-    jdouble     (*GetDoubleField)(JNIEnv* env, jobject obj, jfieldID fieldID);
+    jobject (*GetObjectField)(JNIEnv *env, jobject obj, jfieldID fieldID);
+    jboolean (*GetBooleanField)(JNIEnv *env, jobject obj, jfieldID fieldID);
+    jbyte (*GetByteField)(JNIEnv *env, jobject obj, jfieldID fieldID);
+    jchar (*GetCharField)(JNIEnv *env, jobject obj, jfieldID fieldID);
+    jshort (*GetShortField)(JNIEnv *env, jobject obj, jfieldID fieldID);
+    jint (*GetIntField)(JNIEnv *env, jobject obj, jfieldID fieldID);
+    jlong (*GetLongField)(JNIEnv *env, jobject obj, jfieldID fieldID);
+    jfloat (*GetFloatField)(JNIEnv *env, jobject obj, jfieldID fieldID);
+    jdouble (*GetDoubleField)(JNIEnv *env, jobject obj, jfieldID fieldID);
 
-    void        (*SetObjectField)(JNIEnv* env, jobject obj, jfieldID fieldID, jobject val);
-    void        (*SetBooleanField)(JNIEnv* env, jobject obj, jfieldID fieldID, jboolean val);
-    void        (*SetByteField)(JNIEnv* env, jobject obj, jfieldID fieldID, jbyte val);
-    void        (*SetCharField)(JNIEnv* env, jobject obj, jfieldID fieldID, jchar val);
-    void        (*SetShortField)(JNIEnv* env, jobject obj, jfieldID fieldID, jshort val);
-    void        (*SetIntField)(JNIEnv* env, jobject obj, jfieldID fieldID, jint val);
-    void        (*SetLongField)(JNIEnv* env, jobject obj, jfieldID fieldID, jlong val);
-    void        (*SetFloatField)(JNIEnv* env, jobject obj, jfieldID fieldID, jfloat val);
-    void        (*SetDoubleField)(JNIEnv* env, jobject obj, jfieldID fieldID, jdouble val);
+    void (*SetObjectField)(JNIEnv *env, jobject obj, jfieldID fieldID, jobject val);
+    void (*SetBooleanField)(JNIEnv *env, jobject obj, jfieldID fieldID, jboolean val);
+    void (*SetByteField)(JNIEnv *env, jobject obj, jfieldID fieldID, jbyte val);
+    void (*SetCharField)(JNIEnv *env, jobject obj, jfieldID fieldID, jchar val);
+    void (*SetShortField)(JNIEnv *env, jobject obj, jfieldID fieldID, jshort val);
+    void (*SetIntField)(JNIEnv *env, jobject obj, jfieldID fieldID, jint val);
+    void (*SetLongField)(JNIEnv *env, jobject obj, jfieldID fieldID, jlong val);
+    void (*SetFloatField)(JNIEnv *env, jobject obj, jfieldID fieldID, jfloat val);
+    void (*SetDoubleField)(JNIEnv *env, jobject obj, jfieldID fieldID, jdouble val);
 
-    jmethodID   (*GetStaticMethodID)(JNIEnv* env, jclass clazz, const char* name, const char* sig);
+    jmethodID (*GetStaticMethodID)(JNIEnv *env, jclass clazz, const char *name, const char *sig);
 
-    jobject     (*CallStaticObjectMethod)(JNIEnv*, jclass, jmethodID, ...);
-    jobject     (*CallStaticObjectMethodV)(JNIEnv*, jclass, jmethodID, va_list);
-    jobject     (*CallStaticObjectMethodA)(JNIEnv* env, jclass clazz, jmethodID methodID, const jvalue* args);
-    jboolean    (*CallStaticBooleanMethod)(JNIEnv*, jclass, jmethodID, ...);
-    jboolean    (*CallStaticBooleanMethodV)(JNIEnv*, jclass, jmethodID,
-                        va_list);
-    jboolean    (*CallStaticBooleanMethodA)(JNIEnv* env, jclass clazz, jmethodID methodID, const jvalue* args);
-    jbyte       (*CallStaticByteMethod)(JNIEnv*, jclass, jmethodID, ...);
-    jbyte       (*CallStaticByteMethodV)(JNIEnv*, jclass, jmethodID, va_list);
-    jbyte       (*CallStaticByteMethodA)(JNIEnv* env, jclass clazz, jmethodID methodID, const jvalue* args);
-    jchar       (*CallStaticCharMethod)(JNIEnv*, jclass, jmethodID, ...);
-    jchar       (*CallStaticCharMethodV)(JNIEnv*, jclass, jmethodID, va_list);
-    jchar       (*CallStaticCharMethodA)(JNIEnv* env, jclass clazz, jmethodID methodID, const jvalue* args);
-    jshort      (*CallStaticShortMethod)(JNIEnv*, jclass, jmethodID, ...);
-    jshort      (*CallStaticShortMethodV)(JNIEnv*, jclass, jmethodID, va_list);
-    jshort      (*CallStaticShortMethodA)(JNIEnv* env, jclass clazz, jmethodID methodID, const jvalue* args);
-    jint        (*CallStaticIntMethod)(JNIEnv*, jclass, jmethodID, ...);
-    jint        (*CallStaticIntMethodV)(JNIEnv*, jclass, jmethodID, va_list);
-    jint        (*CallStaticIntMethodA)(JNIEnv* env, jclass clazz, jmethodID methodID, const jvalue* args);
-    jlong       (*CallStaticLongMethod)(JNIEnv*, jclass, jmethodID, ...);
-    jlong       (*CallStaticLongMethodV)(JNIEnv*, jclass, jmethodID, va_list);
-    jlong       (*CallStaticLongMethodA)(JNIEnv* env, jclass clazz, jmethodID methodID, const jvalue* args);
-    jfloat      (*CallStaticFloatMethod)(JNIEnv*, jclass, jmethodID, ...);
-    jfloat      (*CallStaticFloatMethodV)(JNIEnv*, jclass, jmethodID, va_list);
-    jfloat      (*CallStaticFloatMethodA)(JNIEnv* env, jclass clazz, jmethodID methodID, const jvalue* args);
-    jdouble     (*CallStaticDoubleMethod)(JNIEnv*, jclass, jmethodID, ...);
-    jdouble     (*CallStaticDoubleMethodV)(JNIEnv*, jclass, jmethodID, va_list);
-    jdouble     (*CallStaticDoubleMethodA)(JNIEnv* env, jclass clazz, jmethodID methodID, const jvalue* args);
-    void        (*CallStaticVoidMethod)(JNIEnv*, jclass, jmethodID, ...);
-    void        (*CallStaticVoidMethodV)(JNIEnv*, jclass, jmethodID, va_list);
-    void        (*CallStaticVoidMethodA)(JNIEnv* env, jclass clazz, jmethodID methodID, const jvalue* args);
+    jobject (*CallStaticObjectMethod)(JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+    jobject (*CallStaticObjectMethodV)(JNIEnv *, jclass, jmethodID, void *);
+    jobject (*CallStaticObjectMethodA)(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+    jboolean (*CallStaticBooleanMethod)(JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+    jboolean (*CallStaticBooleanMethodV)(JNIEnv *, jclass, jmethodID,
+                                         void *);
+    jboolean (*CallStaticBooleanMethodA)(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+    jbyte (*CallStaticByteMethod)(JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+    jbyte (*CallStaticByteMethodV)(JNIEnv *, jclass, jmethodID, void *);
+    jbyte (*CallStaticByteMethodA)(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+    jchar (*CallStaticCharMethod)(JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+    jchar (*CallStaticCharMethodV)(JNIEnv *, jclass, jmethodID, void *);
+    jchar (*CallStaticCharMethodA)(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+    jshort (*CallStaticShortMethod)(JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+    jshort (*CallStaticShortMethodV)(JNIEnv *, jclass, jmethodID, void *);
+    jshort (*CallStaticShortMethodA)(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+    jint (*CallStaticIntMethod)(JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+    jint (*CallStaticIntMethodV)(JNIEnv *, jclass, jmethodID, void *);
+    jint (*CallStaticIntMethodA)(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+    jlong (*CallStaticLongMethod)(JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+    jlong (*CallStaticLongMethodV)(JNIEnv *, jclass, jmethodID, void *);
+    jlong (*CallStaticLongMethodA)(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+    jfloat (*CallStaticFloatMethod)(JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+    jfloat (*CallStaticFloatMethodV)(JNIEnv *, jclass, jmethodID, void *);
+    jfloat (*CallStaticFloatMethodA)(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+    jdouble (*CallStaticDoubleMethod)(JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+    jdouble (*CallStaticDoubleMethodV)(JNIEnv *, jclass, jmethodID, void *);
+    jdouble (*CallStaticDoubleMethodA)(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+    void (*CallStaticVoidMethod)(JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+    void (*CallStaticVoidMethodV)(JNIEnv *, jclass, jmethodID, void *);
+    void (*CallStaticVoidMethodA)(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
 
-    jfieldID    (*GetStaticFieldID)(JNIEnv* env, jclass clazz, const char* name,
-                        const char* sig);
+    jfieldID (*GetStaticFieldID)(JNIEnv *env, jclass clazz, const char *name,
+                                 const char *sig);
 
-    jobject     (*GetStaticObjectField)(JNIEnv* env, jclass clazz, jfieldID fieldID);
-    jboolean    (*GetStaticBooleanField)(JNIEnv* env, jclass clazz, jfieldID fieldID);
-    jbyte       (*GetStaticByteField)(JNIEnv* env, jclass clazz, jfieldID fieldID);
-    jchar       (*GetStaticCharField)(JNIEnv* env, jclass clazz, jfieldID fieldID);
-    jshort      (*GetStaticShortField)(JNIEnv* env, jclass clazz, jfieldID fieldID);
-    jint        (*GetStaticIntField)(JNIEnv* env, jclass clazz, jfieldID fieldID);
-    jlong       (*GetStaticLongField)(JNIEnv* env, jclass clazz, jfieldID fieldID);
-    jfloat      (*GetStaticFloatField)(JNIEnv* env, jclass clazz, jfieldID fieldID);
-    jdouble     (*GetStaticDoubleField)(JNIEnv* env, jclass clazz, jfieldID fieldID);
+    jobject (*GetStaticObjectField)(JNIEnv *env, jclass clazz, jfieldID fieldID);
+    jboolean (*GetStaticBooleanField)(JNIEnv *env, jclass clazz, jfieldID fieldID);
+    jbyte (*GetStaticByteField)(JNIEnv *env, jclass clazz, jfieldID fieldID);
+    jchar (*GetStaticCharField)(JNIEnv *env, jclass clazz, jfieldID fieldID);
+    jshort (*GetStaticShortField)(JNIEnv *env, jclass clazz, jfieldID fieldID);
+    jint (*GetStaticIntField)(JNIEnv *env, jclass clazz, jfieldID fieldID);
+    jlong (*GetStaticLongField)(JNIEnv *env, jclass clazz, jfieldID fieldID);
+    jfloat (*GetStaticFloatField)(JNIEnv *env, jclass clazz, jfieldID fieldID);
+    jdouble (*GetStaticDoubleField)(JNIEnv *env, jclass clazz, jfieldID fieldID);
 
-    void        (*SetStaticObjectField)(JNIEnv* env, jclass clazz, jfieldID fieldID, jobject val);
-    void        (*SetStaticBooleanField)(JNIEnv* env, jclass clazz, jfieldID fieldID, jboolean val);
-    void        (*SetStaticByteField)(JNIEnv* env, jclass clazz, jfieldID fieldID, jbyte val);
-    void        (*SetStaticCharField)(JNIEnv* env, jclass clazz, jfieldID fieldID, jchar val);
-    void        (*SetStaticShortField)(JNIEnv* env, jclass clazz, jfieldID fieldID, jshort val);
-    void        (*SetStaticIntField)(JNIEnv* env, jclass clazz, jfieldID fieldID, jint val);
-    void        (*SetStaticLongField)(JNIEnv* env, jclass clazz, jfieldID fieldID, jlong val);
-    void        (*SetStaticFloatField)(JNIEnv* env, jclass clazz, jfieldID fieldID, jfloat val);
-    void        (*SetStaticDoubleField)(JNIEnv* env, jclass clazz, jfieldID fieldID, jdouble val);
+    void (*SetStaticObjectField)(JNIEnv *env, jclass clazz, jfieldID fieldID, jobject val);
+    void (*SetStaticBooleanField)(JNIEnv *env, jclass clazz, jfieldID fieldID, jboolean val);
+    void (*SetStaticByteField)(JNIEnv *env, jclass clazz, jfieldID fieldID, jbyte val);
+    void (*SetStaticCharField)(JNIEnv *env, jclass clazz, jfieldID fieldID, jchar val);
+    void (*SetStaticShortField)(JNIEnv *env, jclass clazz, jfieldID fieldID, jshort val);
+    void (*SetStaticIntField)(JNIEnv *env, jclass clazz, jfieldID fieldID, jint val);
+    void (*SetStaticLongField)(JNIEnv *env, jclass clazz, jfieldID fieldID, jlong val);
+    void (*SetStaticFloatField)(JNIEnv *env, jclass clazz, jfieldID fieldID, jfloat val);
+    void (*SetStaticDoubleField)(JNIEnv *env, jclass clazz, jfieldID fieldID, jdouble val);
 
-    jstring     (*NewString)(JNIEnv* env, const jchar* unicodeChars, jsize len);
-    jsize       (*GetStringLength)(JNIEnv* env, jstring string);
-    const jchar* (*GetStringChars)(JNIEnv* env, jstring string, jboolean* isCopy);
-    void        (*ReleaseStringChars)(JNIEnv* env, jstring string, const jchar* isCopy);
-    jstring     (*NewStringUTF)(JNIEnv* env, const char* bytes);
-    jsize       (*GetStringUTFLength)(JNIEnv* env, jstring string);
-    const char* (*GetStringUTFChars)(JNIEnv* env, jstring string, jboolean* isCopy);
-    void        (*ReleaseStringUTFChars)(JNIEnv* env, jstring string, const char* utf);
-    jsize       (*GetArrayLength)(JNIEnv* env, jarray array);
-    jobjectArray (*NewObjectArray)(JNIEnv* env, jsize length, jclass elementClass, jobject initialElement);
-    jobject     (*GetObjectArrayElement)(JNIEnv* env, jobjectArray array, jsize index);
-    void        (*SetObjectArrayElement)(JNIEnv* env, jobjectArray array, jsize index, jobject val);
+    jstring (*NewString)(JNIEnv *env, const jchar *unicodeChars, jsize len);
+    jsize (*GetStringLength)(JNIEnv *env, jstring string);
+    const jchar *(*GetStringChars)(JNIEnv *env, jstring string, jboolean *isCopy);
+    void (*ReleaseStringChars)(JNIEnv *env, jstring string, const jchar *isCopy);
+    jstring (*NewStringUTF)(JNIEnv *env, const char *bytes);
+    jsize (*GetStringUTFLength)(JNIEnv *env, jstring string);
+    const char *(*GetStringUTFChars)(JNIEnv *env, jstring string, jboolean *isCopy);
+    void (*ReleaseStringUTFChars)(JNIEnv *env, jstring string, const char *utf);
+    jsize (*GetArrayLength)(JNIEnv *env, jarray array);
+    jobjectArray (*NewObjectArray)(JNIEnv *env, jsize length, jclass elementClass, jobject initialElement);
+    jobject (*GetObjectArrayElement)(JNIEnv *env, jobjectArray array, jsize index);
+    void (*SetObjectArrayElement)(JNIEnv *env, jobjectArray array, jsize index, jobject val);
 
-    jbooleanArray (*NewBooleanArray)(JNIEnv* env, jsize length);
-    jbyteArray    (*NewByteArray)(JNIEnv* env, jsize length);
-    jcharArray    (*NewCharArray)(JNIEnv* env, jsize length);
-    jshortArray   (*NewShortArray)(JNIEnv* env, jsize length);
-    jintArray     (*NewIntArray)(JNIEnv* env, jsize length);
-    jlongArray    (*NewLongArray)(JNIEnv* env, jsize length);
-    jfloatArray   (*NewFloatArray)(JNIEnv* env, jsize length);
-    jdoubleArray  (*NewDoubleArray)(JNIEnv* env, jsize length);
+    jbooleanArray (*NewBooleanArray)(JNIEnv *env, jsize length);
+    jbyteArray (*NewByteArray)(JNIEnv *env, jsize length);
+    jcharArray (*NewCharArray)(JNIEnv *env, jsize length);
+    jshortArray (*NewShortArray)(JNIEnv *env, jsize length);
+    jintArray (*NewIntArray)(JNIEnv *env, jsize length);
+    jlongArray (*NewLongArray)(JNIEnv *env, jsize length);
+    jfloatArray (*NewFloatArray)(JNIEnv *env, jsize length);
+    jdoubleArray (*NewDoubleArray)(JNIEnv *env, jsize length);
 
-    jboolean*   (*GetBooleanArrayElements)(JNIEnv* env, jbooleanArray array, jboolean* isCopy);
-    jbyte*      (*GetByteArrayElements)(JNIEnv* env, jbyteArray array, jboolean* isCopy);
-    jchar*      (*GetCharArrayElements)(JNIEnv* env, jcharArray array, jboolean* isCopy);
-    jshort*     (*GetShortArrayElements)(JNIEnv* env, jshortArray array, jboolean* isCopy);
-    jint*       (*GetIntArrayElements)(JNIEnv* env, jintArray array, jboolean* isCopy);
-    jlong*      (*GetLongArrayElements)(JNIEnv* env, jlongArray array, jboolean* isCopy);
-    jfloat*     (*GetFloatArrayElements)(JNIEnv* env, jfloatArray array, jboolean* isCopy);
-    jdouble*    (*GetDoubleArrayElements)(JNIEnv* env, jdoubleArray array, jboolean* isCopy);
+    jboolean *(*GetBooleanArrayElements)(JNIEnv *env, jbooleanArray array, jboolean *isCopy);
+    jbyte *(*GetByteArrayElements)(JNIEnv *env, jbyteArray array, jboolean *isCopy);
+    jchar *(*GetCharArrayElements)(JNIEnv *env, jcharArray array, jboolean *isCopy);
+    jshort *(*GetShortArrayElements)(JNIEnv *env, jshortArray array, jboolean *isCopy);
+    jint *(*GetIntArrayElements)(JNIEnv *env, jintArray array, jboolean *isCopy);
+    jlong *(*GetLongArrayElements)(JNIEnv *env, jlongArray array, jboolean *isCopy);
+    jfloat *(*GetFloatArrayElements)(JNIEnv *env, jfloatArray array, jboolean *isCopy);
+    jdouble *(*GetDoubleArrayElements)(JNIEnv *env, jdoubleArray array, jboolean *isCopy);
 
-    void        (*ReleaseBooleanArrayElements)(JNIEnv* env, jbooleanArray array,
-                        jboolean* elems, jint mode);
-    void        (*ReleaseByteArrayElements)(JNIEnv* env, jbyteArray array,
-                        jbyte* elems, jint mode);
-    void        (*ReleaseCharArrayElements)(JNIEnv* env, jcharArray array,
-                        jchar* elems, jint mode);
-    void        (*ReleaseShortArrayElements)(JNIEnv* env, jshortArray array,
-                        jshort* elems, jint mode);
-    void        (*ReleaseIntArrayElements)(JNIEnv* env, jintArray array,
-                        jint* elems, jint mode);
-    void        (*ReleaseLongArrayElements)(JNIEnv* env, jlongArray array,
-                        jlong* elems, jint mode);
-    void        (*ReleaseFloatArrayElements)(JNIEnv* env, jfloatArray array,
-                        jfloat* elems, jint mode);
-    void        (*ReleaseDoubleArrayElements)(JNIEnv* env, jdoubleArray array,
-                        jdouble* elems, jint mode);
+    void (*ReleaseBooleanArrayElements)(JNIEnv *env, jbooleanArray array,
+                                        jboolean *elems, jint mode);
+    void (*ReleaseByteArrayElements)(JNIEnv *env, jbyteArray array,
+                                     jbyte *elems, jint mode);
+    void (*ReleaseCharArrayElements)(JNIEnv *env, jcharArray array,
+                                     jchar *elems, jint mode);
+    void (*ReleaseShortArrayElements)(JNIEnv *env, jshortArray array,
+                                      jshort *elems, jint mode);
+    void (*ReleaseIntArrayElements)(JNIEnv *env, jintArray array,
+                                    jint *elems, jint mode);
+    void (*ReleaseLongArrayElements)(JNIEnv *env, jlongArray array,
+                                     jlong *elems, jint mode);
+    void (*ReleaseFloatArrayElements)(JNIEnv *env, jfloatArray array,
+                                      jfloat *elems, jint mode);
+    void (*ReleaseDoubleArrayElements)(JNIEnv *env, jdoubleArray array,
+                                       jdouble *elems, jint mode);
 
-    void        (*GetBooleanArrayRegion)(JNIEnv* env, jbooleanArray array,
-                        jsize start, jsize len, jboolean* buf);
-    void        (*GetByteArrayRegion)(JNIEnv* env, jbyteArray array,
-                        jsize start, jsize len, jbyte* buf);
-    void        (*GetCharArrayRegion)(JNIEnv* env, jcharArray array,
-                        jsize start, jsize len, jchar* buf);
-    void        (*GetShortArrayRegion)(JNIEnv* env, jshortArray array,
-                        jsize start, jsize len, jshort* buf);
-    void        (*GetIntArrayRegion)(JNIEnv* env, jintArray array,
-                        jsize start, jsize len, jint* buf);
-    void        (*GetLongArrayRegion)(JNIEnv* env, jlongArray array,
-                        jsize start, jsize len, jlong* buf);
-    void        (*GetFloatArrayRegion)(JNIEnv* env, jfloatArray array,
-                        jsize start, jsize len, jfloat* buf);
-    void        (*GetDoubleArrayRegion)(JNIEnv* env, jdoubleArray array,
-                        jsize start, jsize len, jdouble* buf);
+    void (*GetBooleanArrayRegion)(JNIEnv *env, jbooleanArray array,
+                                  jsize start, jsize len, jboolean *buf);
+    void (*GetByteArrayRegion)(JNIEnv *env, jbyteArray array,
+                               jsize start, jsize len, jbyte *buf);
+    void (*GetCharArrayRegion)(JNIEnv *env, jcharArray array,
+                               jsize start, jsize len, jchar *buf);
+    void (*GetShortArrayRegion)(JNIEnv *env, jshortArray array,
+                                jsize start, jsize len, jshort *buf);
+    void (*GetIntArrayRegion)(JNIEnv *env, jintArray array,
+                              jsize start, jsize len, jint *buf);
+    void (*GetLongArrayRegion)(JNIEnv *env, jlongArray array,
+                               jsize start, jsize len, jlong *buf);
+    void (*GetFloatArrayRegion)(JNIEnv *env, jfloatArray array,
+                                jsize start, jsize len, jfloat *buf);
+    void (*GetDoubleArrayRegion)(JNIEnv *env, jdoubleArray array,
+                                 jsize start, jsize len, jdouble *buf);
 
     /* spec shows these without const; some jni.h do, some don't */
-    void        (*SetBooleanArrayRegion)(JNIEnv* env, jbooleanArray array,
-                        jsize start, jsize len, const jboolean* buf);
-    void        (*SetByteArrayRegion)(JNIEnv* env, jbyteArray array,
-                        jsize start, jsize len, const jbyte* buf);
-    void        (*SetCharArrayRegion)(JNIEnv* env, jcharArray array,
-                        jsize start, jsize len, const jchar* buf);
-    void        (*SetShortArrayRegion)(JNIEnv* env, jshortArray array,
-                        jsize start, jsize len, const jshort* buf);
-    void        (*SetIntArrayRegion)(JNIEnv* env, jintArray array,
-                        jsize start, jsize len, const jint* buf);
-    void        (*SetLongArrayRegion)(JNIEnv* env, jlongArray array,
-                        jsize start, jsize len, const jlong* buf);
-    void        (*SetFloatArrayRegion)(JNIEnv* env, jfloatArray array,
-                        jsize start, jsize len, const jfloat* buf);
-    void        (*SetDoubleArrayRegion)(JNIEnv* env, jdoubleArray array,
-                        jsize start, jsize len, const jdouble* buf);
+    void (*SetBooleanArrayRegion)(JNIEnv *env, jbooleanArray array,
+                                  jsize start, jsize len, const jboolean *buf);
+    void (*SetByteArrayRegion)(JNIEnv *env, jbyteArray array,
+                               jsize start, jsize len, const jbyte *buf);
+    void (*SetCharArrayRegion)(JNIEnv *env, jcharArray array,
+                               jsize start, jsize len, const jchar *buf);
+    void (*SetShortArrayRegion)(JNIEnv *env, jshortArray array,
+                                jsize start, jsize len, const jshort *buf);
+    void (*SetIntArrayRegion)(JNIEnv *env, jintArray array,
+                              jsize start, jsize len, const jint *buf);
+    void (*SetLongArrayRegion)(JNIEnv *env, jlongArray array,
+                               jsize start, jsize len, const jlong *buf);
+    void (*SetFloatArrayRegion)(JNIEnv *env, jfloatArray array,
+                                jsize start, jsize len, const jfloat *buf);
+    void (*SetDoubleArrayRegion)(JNIEnv *env, jdoubleArray array,
+                                 jsize start, jsize len, const jdouble *buf);
 
-    jint        (*RegisterNatives)(JNIEnv* env, jclass clazz, const JNINativeMethod* methods,
-                        jint nMethods);
-    jint        (*UnregisterNatives)(JNIEnv* env, jclass clazz);
-    jint        (*MonitorEnter)(JNIEnv* env, jobject obj);
-    jint        (*MonitorExit)(JNIEnv* env, jobject obj);
-    jint        (*GetJavaVM)(JNIEnv* env, JavaVM** vm);
+    jint (*RegisterNatives)(JNIEnv *env, jclass clazz, const JNINativeMethod *methods,
+                            jint nMethods);
+    jint (*UnregisterNatives)(JNIEnv *env, jclass clazz);
+    jint (*MonitorEnter)(JNIEnv *env, jobject obj);
+    jint (*MonitorExit)(JNIEnv *env, jobject obj);
+    jint (*GetJavaVM)(JNIEnv *env, JavaVM **vm);
 
-    void        (*GetStringRegion)(JNIEnv* env, jstring str, jsize start, jsize len, jchar* buf);
-    void        (*GetStringUTFRegion)(JNIEnv* env, jstring str, jsize start, jsize len, char* buf);
+    void (*GetStringRegion)(JNIEnv *env, jstring str, jsize start, jsize len, jchar *buf);
+    void (*GetStringUTFRegion)(JNIEnv *env, jstring str, jsize start, jsize len, char *buf);
 
-    void*       (*GetPrimitiveArrayCritical)(JNIEnv* env, jarray array, jboolean* isCopy);
-    void        (*ReleasePrimitiveArrayCritical)(JNIEnv* env, jarray array, void* carray, jint mode);
+    void *(*GetPrimitiveArrayCritical)(JNIEnv *env, jarray array, jboolean *isCopy);
+    void (*ReleasePrimitiveArrayCritical)(JNIEnv *env, jarray array, void *carray, jint mode);
 
-    const jchar* (*GetStringCritical)(JNIEnv* env, jstring str, jboolean* isCopy);
-    void        (*ReleaseStringCritical)(JNIEnv* env, jstring str, const jchar* carray);
+    const jchar *(*GetStringCritical)(JNIEnv *env, jstring str, jboolean *isCopy);
+    void (*ReleaseStringCritical)(JNIEnv *env, jstring str, const jchar *carray);
 
-    jweak       (*NewWeakGlobalRef)(JNIEnv* env, jobject obj);
-    void        (*DeleteWeakGlobalRef)(JNIEnv* env, jweak obj);
+    jweak (*NewWeakGlobalRef)(JNIEnv *env, jobject obj);
+    void (*DeleteWeakGlobalRef)(JNIEnv *env, jweak obj);
 
-    jboolean    (*ExceptionCheck)(JNIEnv* env);
+    jboolean (*ExceptionCheck)(JNIEnv *env);
 
-    jobject     (*NewDirectByteBuffer)(JNIEnv* env, void* address, jlong capacity);
-    void*       (*GetDirectBufferAddress)(JNIEnv* env, jobject buf);
-    jlong       (*GetDirectBufferCapacity)(JNIEnv* env, jobject buf);
+    jobject (*NewDirectByteBuffer)(JNIEnv *env, void *address, jlong capacity);
+    void *(*GetDirectBufferAddress)(JNIEnv *env, jobject buf);
+    jlong (*GetDirectBufferCapacity)(JNIEnv *env, jobject buf);
 
     /* added in JNI 1.6 */
-    jobjectRefType (*GetObjectRefType)(JNIEnv* env, jobject obj);
+    jobjectRefType (*GetObjectRefType)(JNIEnv *env, jobject obj);
 };
 
 /*
@@ -489,84 +520,133 @@
  * This is usually overlaid on a C struct whose first element is a
  * JNINativeInterface*.  We rely somewhat on compiler behavior.
  */
-struct _JNIEnv {
+struct _JNIEnv
+{
     /* do not rename this; it does not seem to be entirely opaque */
-    const struct JNINativeInterface* functions;
+    const struct JNINativeInterface *functions;
 
 #if defined(__cplusplus)
 
     jint GetVersion()
-    { return functions->GetVersion(this); }
+    {
+        return functions->GetVersion(this);
+    }
 
-    jclass DefineClass(const char *name, jobject loader, const jbyte* buf,
-        jsize bufLen)
-    { return functions->DefineClass(this, name, loader, buf, bufLen); }
+    jclass DefineClass(const char *name, jobject loader, const jbyte *buf,
+                       jsize bufLen)
+    {
+        return functions->DefineClass(this, name, loader, buf, bufLen);
+    }
 
-    jclass FindClass(const char* name)
-    { return functions->FindClass(this, name); }
+    jclass FindClass(const char *name)
+    {
+        return functions->FindClass(this, name);
+    }
 
     jmethodID FromReflectedMethod(jobject method)
-    { return functions->FromReflectedMethod(this, method); }
+    {
+        return functions->FromReflectedMethod(this, method);
+    }
 
     jfieldID FromReflectedField(jobject field)
-    { return functions->FromReflectedField(this, field); }
+    {
+        return functions->FromReflectedField(this, field);
+    }
 
     jobject ToReflectedMethod(jclass cls, jmethodID methodID, jboolean isStatic)
-    { return functions->ToReflectedMethod(this, cls, methodID, isStatic); }
+    {
+        return functions->ToReflectedMethod(this, cls, methodID, isStatic);
+    }
 
     jclass GetSuperclass(jclass clazz)
-    { return functions->GetSuperclass(this, clazz); }
+    {
+        return functions->GetSuperclass(this, clazz);
+    }
 
     jboolean IsAssignableFrom(jclass clazz1, jclass clazz2)
-    { return functions->IsAssignableFrom(this, clazz1, clazz2); }
+    {
+        return functions->IsAssignableFrom(this, clazz1, clazz2);
+    }
 
     jobject ToReflectedField(jclass cls, jfieldID fieldID, jboolean isStatic)
-    { return functions->ToReflectedField(this, cls, fieldID, isStatic); }
+    {
+        return functions->ToReflectedField(this, cls, fieldID, isStatic);
+    }
 
     jint Throw(jthrowable obj)
-    { return functions->Throw(this, obj); }
+    {
+        return functions->Throw(this, obj);
+    }
 
-    jint ThrowNew(jclass clazz, const char* message)
-    { return functions->ThrowNew(this, clazz, message); }
+    jint ThrowNew(jclass clazz, const char *message)
+    {
+        return functions->ThrowNew(this, clazz, message);
+    }
 
     jthrowable ExceptionOccurred()
-    { return functions->ExceptionOccurred(this); }
+    {
+        return functions->ExceptionOccurred(this);
+    }
 
     void ExceptionDescribe()
-    { functions->ExceptionDescribe(this); }
+    {
+        functions->ExceptionDescribe(this);
+    }
 
     void ExceptionClear()
-    { functions->ExceptionClear(this); }
+    {
+        functions->ExceptionClear(this);
+    }
 
-    void FatalError(const char* msg)
-    { functions->FatalError(this, msg); }
+    void FatalError(const char *msg)
+    {
+        functions->FatalError(this, msg);
+    }
 
     jint PushLocalFrame(jint capacity)
-    { return functions->PushLocalFrame(this, capacity); }
+    {
+        return functions->PushLocalFrame(this, capacity);
+    }
 
     jobject PopLocalFrame(jobject result)
-    { return functions->PopLocalFrame(this, result); }
+    {
+        return functions->PopLocalFrame(this, result);
+    }
 
     jobject NewGlobalRef(jobject obj)
-    { return functions->NewGlobalRef(this, obj); }
+    {
+        return functions->NewGlobalRef(this, obj);
+    }
 
     void DeleteGlobalRef(jobject globalRef)
-    { functions->DeleteGlobalRef(this, globalRef); }
+    {
+        functions->DeleteGlobalRef(this, globalRef);
+    }
 
     void DeleteLocalRef(jobject localRef)
-    { functions->DeleteLocalRef(this, localRef); }
+    {
+        functions->DeleteLocalRef(this, localRef);
+    }
 
     jboolean IsSameObject(jobject ref1, jobject ref2)
-    { return functions->IsSameObject(this, ref1, ref2); }
+    {
+        return functions->IsSameObject(this, ref1, ref2);
+    }
 
-    jobject NewLocalRef(jobject ref)
-    { return functions->NewLocalRef(this, ref); }
+    jobject NewLocalRef(jobject obj)
+    {
+        return functions->NewLocalRef(this, ref);
+    }
 
     jint EnsureLocalCapacity(jint capacity)
-    { return functions->EnsureLocalCapacity(this, capacity); }
+    {
+        return functions->EnsureLocalCapacity(this, capacity);
+    }
 
     jobject AllocObject(jclass clazz)
-    { return functions->AllocObject(this, clazz); }
+    {
+        return functions->AllocObject(this, clazz);
+    }
 
     jobject NewObject(jclass clazz, jmethodID methodID, ...)
     {
@@ -578,43 +658,57 @@
     }
 
     jobject NewObjectV(jclass clazz, jmethodID methodID, va_list args)
-    { return functions->NewObjectV(this, clazz, methodID, args); }
+    {
+        return functions->NewObjectV(this, clazz, methodID, args);
+    }
 
-    jobject NewObjectA(jclass clazz, jmethodID methodID, const jvalue* args)
-    { return functions->NewObjectA(this, clazz, methodID, args); }
+    jobject NewObjectA(jclass clazz, jmethodID methodID, const jvalue *args)
+    {
+        return functions->NewObjectA(this, clazz, methodID, args);
+    }
 
     jclass GetObjectClass(jobject obj)
-    { return functions->GetObjectClass(this, obj); }
+    {
+        return functions->GetObjectClass(this, obj);
+    }
 
     jboolean IsInstanceOf(jobject obj, jclass clazz)
-    { return functions->IsInstanceOf(this, obj, clazz); }
+    {
+        return functions->IsInstanceOf(this, obj, clazz);
+    }
 
-    jmethodID GetMethodID(jclass clazz, const char* name, const char* sig)
-    { return functions->GetMethodID(this, clazz, name, sig); }
+    jmethodID GetMethodID(jclass clazz, const char *name, const char *sig)
+    {
+        return functions->GetMethodID(this, clazz, name, sig);
+    }
 
-#define CALL_TYPE_METHOD(_jtype, _jname)                                    \
-    _jtype Call##_jname##Method(jobject obj, jmethodID methodID, ...)       \
-    {                                                                       \
-        _jtype result;                                                      \
-        va_list args;                                                       \
-        va_start(args, methodID);                                           \
-        result = functions->Call##_jname##MethodV(this, obj, methodID,      \
-                    args);                                                  \
-        va_end(args);                                                       \
-        return result;                                                      \
+#define CALL_TYPE_METHOD(_jtype, _jname)                               \
+    _jtype Call##_jname##Method(jobject obj, jmethodID methodID, ...)  \
+    {                                                                  \
+        _jtype result;                                                 \
+        va_list args;                                                  \
+        va_start(args, methodID);                                      \
+        result = functions->Call##_jname##MethodV(this, obj, methodID, \
+                                                  args);               \
+        va_end(args);                                                  \
+        return result;                                                 \
     }
 #define CALL_TYPE_METHODV(_jtype, _jname)                                   \
     _jtype Call##_jname##MethodV(jobject obj, jmethodID methodID,           \
-        va_list args)                                                       \
-    { return functions->Call##_jname##MethodV(this, obj, methodID, args); }
+                                 va_list args)                              \
+    {                                                                       \
+        return functions->Call##_jname##MethodV(this, obj, methodID, args); \
+    }
 #define CALL_TYPE_METHODA(_jtype, _jname)                                   \
     _jtype Call##_jname##MethodA(jobject obj, jmethodID methodID,           \
-                                 const jvalue* args)                        \
-    { return functions->Call##_jname##MethodA(this, obj, methodID, args); }
+                                 const jvalue *args)                        \
+    {                                                                       \
+        return functions->Call##_jname##MethodA(this, obj, methodID, args); \
+    }
 
-#define CALL_TYPE(_jtype, _jname)                                           \
-    CALL_TYPE_METHOD(_jtype, _jname)                                        \
-    CALL_TYPE_METHODV(_jtype, _jname)                                       \
+#define CALL_TYPE(_jtype, _jname)     \
+    CALL_TYPE_METHOD(_jtype, _jname)  \
+    CALL_TYPE_METHODV(_jtype, _jname) \
     CALL_TYPE_METHODA(_jtype, _jname)
 
     CALL_TYPE(jobject, Object)
@@ -635,36 +729,44 @@
         va_end(args);
     }
     void CallVoidMethodV(jobject obj, jmethodID methodID, va_list args)
-    { functions->CallVoidMethodV(this, obj, methodID, args); }
-    void CallVoidMethodA(jobject obj, jmethodID methodID, const jvalue* args)
-    { functions->CallVoidMethodA(this, obj, methodID, args); }
-
-#define CALL_NONVIRT_TYPE_METHOD(_jtype, _jname)                            \
-    _jtype CallNonvirtual##_jname##Method(jobject obj, jclass clazz,        \
-        jmethodID methodID, ...)                                            \
-    {                                                                       \
-        _jtype result;                                                      \
-        va_list args;                                                       \
-        va_start(args, methodID);                                           \
-        result = functions->CallNonvirtual##_jname##MethodV(this, obj,      \
-                    clazz, methodID, args);                                 \
-        va_end(args);                                                       \
-        return result;                                                      \
+    {
+        functions->CallVoidMethodV(this, obj, methodID, args);
     }
-#define CALL_NONVIRT_TYPE_METHODV(_jtype, _jname)                           \
-    _jtype CallNonvirtual##_jname##MethodV(jobject obj, jclass clazz,       \
-        jmethodID methodID, va_list args)                                   \
-    { return functions->CallNonvirtual##_jname##MethodV(this, obj, clazz,   \
-        methodID, args); }
-#define CALL_NONVIRT_TYPE_METHODA(_jtype, _jname)                           \
-    _jtype CallNonvirtual##_jname##MethodA(jobject obj, jclass clazz,       \
-        jmethodID methodID, const jvalue* args)                             \
-    { return functions->CallNonvirtual##_jname##MethodA(this, obj, clazz,   \
-        methodID, args); }
+    void CallVoidMethodA(jobject obj, jmethodID methodID, const jvalue *args)
+    {
+        functions->CallVoidMethodA(this, obj, methodID, args);
+    }
 
-#define CALL_NONVIRT_TYPE(_jtype, _jname)                                   \
-    CALL_NONVIRT_TYPE_METHOD(_jtype, _jname)                                \
-    CALL_NONVIRT_TYPE_METHODV(_jtype, _jname)                               \
+#define CALL_NONVIRT_TYPE_METHOD(_jtype, _jname)                                    \
+    _jtype CallNonvirtual##_jname##Method(jobject obj, jclass clazz,                \
+                                          jmethodID methodID, ...)                  \
+    {                                                                               \
+        _jtype result;                                                              \
+        va_list args;                                                               \
+        va_start(args, methodID);                                                   \
+        result = functions->CallNonvirtual##_jname##MethodV(this, obj,              \
+                                                            clazz, methodID, args); \
+        va_end(args);                                                               \
+        return result;                                                              \
+    }
+#define CALL_NONVIRT_TYPE_METHODV(_jtype, _jname)                            \
+    _jtype CallNonvirtual##_jname##MethodV(jobject obj, jclass clazz,        \
+                                           jmethodID methodID, va_list args) \
+    {                                                                        \
+        return functions->CallNonvirtual##_jname##MethodV(this, obj, clazz,  \
+                                                          methodID, args);   \
+    }
+#define CALL_NONVIRT_TYPE_METHODA(_jtype, _jname)                                  \
+    _jtype CallNonvirtual##_jname##MethodA(jobject obj, jclass clazz,              \
+                                           jmethodID methodID, const jvalue *args) \
+    {                                                                              \
+        return functions->CallNonvirtual##_jname##MethodA(this, obj, clazz,        \
+                                                          methodID, args);         \
+    }
+
+#define CALL_NONVIRT_TYPE(_jtype, _jname)     \
+    CALL_NONVIRT_TYPE_METHOD(_jtype, _jname)  \
+    CALL_NONVIRT_TYPE_METHODV(_jtype, _jname) \
     CALL_NONVIRT_TYPE_METHODA(_jtype, _jname)
 
     CALL_NONVIRT_TYPE(jobject, Object)
@@ -678,7 +780,7 @@
     CALL_NONVIRT_TYPE(jdouble, Double)
 
     void CallNonvirtualVoidMethod(jobject obj, jclass clazz,
-        jmethodID methodID, ...)
+                                  jmethodID methodID, ...)
     {
         va_list args;
         va_start(args, methodID);
@@ -686,82 +788,130 @@
         va_end(args);
     }
     void CallNonvirtualVoidMethodV(jobject obj, jclass clazz,
-        jmethodID methodID, va_list args)
-    { functions->CallNonvirtualVoidMethodV(this, obj, clazz, methodID, args); }
+                                   jmethodID methodID, va_list args)
+    {
+        functions->CallNonvirtualVoidMethodV(this, obj, clazz, methodID, args);
+    }
     void CallNonvirtualVoidMethodA(jobject obj, jclass clazz,
-        jmethodID methodID, const jvalue* args)
-    { functions->CallNonvirtualVoidMethodA(this, obj, clazz, methodID, args); }
+                                   jmethodID methodID, const jvalue *args)
+    {
+        functions->CallNonvirtualVoidMethodA(this, obj, clazz, methodID, args);
+    }
 
-    jfieldID GetFieldID(jclass clazz, const char* name, const char* sig)
-    { return functions->GetFieldID(this, clazz, name, sig); }
+    jfieldID GetFieldID(jclass clazz, const char *name, const char *sig)
+    {
+        return functions->GetFieldID(this, clazz, name, sig);
+    }
 
     jobject GetObjectField(jobject obj, jfieldID fieldID)
-    { return functions->GetObjectField(this, obj, fieldID); }
+    {
+        return functions->GetObjectField(this, obj, fieldID);
+    }
     jboolean GetBooleanField(jobject obj, jfieldID fieldID)
-    { return functions->GetBooleanField(this, obj, fieldID); }
+    {
+        return functions->GetBooleanField(this, obj, fieldID);
+    }
     jbyte GetByteField(jobject obj, jfieldID fieldID)
-    { return functions->GetByteField(this, obj, fieldID); }
+    {
+        return functions->GetByteField(this, obj, fieldID);
+    }
     jchar GetCharField(jobject obj, jfieldID fieldID)
-    { return functions->GetCharField(this, obj, fieldID); }
+    {
+        return functions->GetCharField(this, obj, fieldID);
+    }
     jshort GetShortField(jobject obj, jfieldID fieldID)
-    { return functions->GetShortField(this, obj, fieldID); }
+    {
+        return functions->GetShortField(this, obj, fieldID);
+    }
     jint GetIntField(jobject obj, jfieldID fieldID)
-    { return functions->GetIntField(this, obj, fieldID); }
+    {
+        return functions->GetIntField(this, obj, fieldID);
+    }
     jlong GetLongField(jobject obj, jfieldID fieldID)
-    { return functions->GetLongField(this, obj, fieldID); }
+    {
+        return functions->GetLongField(this, obj, fieldID);
+    }
     jfloat GetFloatField(jobject obj, jfieldID fieldID)
-    { return functions->GetFloatField(this, obj, fieldID); }
+    {
+        return functions->GetFloatField(this, obj, fieldID);
+    }
     jdouble GetDoubleField(jobject obj, jfieldID fieldID)
-    { return functions->GetDoubleField(this, obj, fieldID); }
+    {
+        return functions->GetDoubleField(this, obj, fieldID);
+    }
 
     void SetObjectField(jobject obj, jfieldID fieldID, jobject val)
-    { functions->SetObjectField(this, obj, fieldID, val); }
-    void SetBooleanField(jobject obj, jfieldID fieldID, jboolean val)
-    { functions->SetBooleanField(this, obj, fieldID, val); }
-    void SetByteField(jobject obj, jfieldID fieldID, jbyte val)
-    { functions->SetByteField(this, obj, fieldID, val); }
-    void SetCharField(jobject obj, jfieldID fieldID, jchar val)
-    { functions->SetCharField(this, obj, fieldID, val); }
-    void SetShortField(jobject obj, jfieldID fieldID, jshort val)
-    { functions->SetShortField(this, obj, fieldID, val); }
-    void SetIntField(jobject obj, jfieldID fieldID, jint val)
-    { functions->SetIntField(this, obj, fieldID, val); }
-    void SetLongField(jobject obj, jfieldID fieldID, jlong val)
-    { functions->SetLongField(this, obj, fieldID, val); }
-    void SetFloatField(jobject obj, jfieldID fieldID, jfloat val)
-    { functions->SetFloatField(this, obj, fieldID, val); }
-    void SetDoubleField(jobject obj, jfieldID fieldID, jdouble val)
-    { functions->SetDoubleField(this, obj, fieldID, val); }
-
-    jmethodID GetStaticMethodID(jclass clazz, const char* name, const char* sig)
-    { return functions->GetStaticMethodID(this, clazz, name, sig); }
-
-#define CALL_STATIC_TYPE_METHOD(_jtype, _jname)                             \
-    _jtype CallStatic##_jname##Method(jclass clazz, jmethodID methodID,     \
-        ...)                                                                \
-    {                                                                       \
-        _jtype result;                                                      \
-        va_list args;                                                       \
-        va_start(args, methodID);                                           \
-        result = functions->CallStatic##_jname##MethodV(this, clazz,        \
-                    methodID, args);                                        \
-        va_end(args);                                                       \
-        return result;                                                      \
+    {
+        functions->SetObjectField(this, obj, fieldID, val);
     }
-#define CALL_STATIC_TYPE_METHODV(_jtype, _jname)                            \
-    _jtype CallStatic##_jname##MethodV(jclass clazz, jmethodID methodID,    \
-        va_list args)                                                       \
-    { return functions->CallStatic##_jname##MethodV(this, clazz, methodID,  \
-        args); }
-#define CALL_STATIC_TYPE_METHODA(_jtype, _jname)                            \
-    _jtype CallStatic##_jname##MethodA(jclass clazz, jmethodID methodID,    \
-                                       const jvalue* args)                  \
-    { return functions->CallStatic##_jname##MethodA(this, clazz, methodID,  \
-        args); }
+    void SetBooleanField(jobject obj, jfieldID fieldID, jboolean val)
+    {
+        functions->SetBooleanField(this, obj, fieldID, val);
+    }
+    void SetByteField(jobject obj, jfieldID fieldID, jbyte val)
+    {
+        functions->SetByteField(this, obj, fieldID, val);
+    }
+    void SetCharField(jobject obj, jfieldID fieldID, jchar val)
+    {
+        functions->SetCharField(this, obj, fieldID, val);
+    }
+    void SetShortField(jobject obj, jfieldID fieldID, jshort val)
+    {
+        functions->SetShortField(this, obj, fieldID, val);
+    }
+    void SetIntField(jobject obj, jfieldID fieldID, jint val)
+    {
+        functions->SetIntField(this, obj, fieldID, val);
+    }
+    void SetLongField(jobject obj, jfieldID fieldID, jlong val)
+    {
+        functions->SetLongField(this, obj, fieldID, val);
+    }
+    void SetFloatField(jobject obj, jfieldID fieldID, jfloat val)
+    {
+        functions->SetFloatField(this, obj, fieldID, val);
+    }
+    void SetDoubleField(jobject obj, jfieldID fieldID, jdouble val)
+    {
+        functions->SetDoubleField(this, obj, fieldID, val);
+    }
 
-#define CALL_STATIC_TYPE(_jtype, _jname)                                    \
-    CALL_STATIC_TYPE_METHOD(_jtype, _jname)                                 \
-    CALL_STATIC_TYPE_METHODV(_jtype, _jname)                                \
+    jmethodID GetStaticMethodID(jclass clazz, const char *name, const char *sig)
+    {
+        return functions->GetStaticMethodID(this, clazz, name, sig);
+    }
+
+#define CALL_STATIC_TYPE_METHOD(_jtype, _jname)                          \
+    _jtype CallStatic##_jname##Method(jclass clazz, jmethodID methodID,  \
+                                      ...)                               \
+    {                                                                    \
+        _jtype result;                                                   \
+        va_list args;                                                    \
+        va_start(args, methodID);                                        \
+        result = functions->CallStatic##_jname##MethodV(this, clazz,     \
+                                                        methodID, args); \
+        va_end(args);                                                    \
+        return result;                                                   \
+    }
+#define CALL_STATIC_TYPE_METHODV(_jtype, _jname)                             \
+    _jtype CallStatic##_jname##MethodV(jclass clazz, jmethodID methodID,     \
+                                       va_list args)                         \
+    {                                                                        \
+        return functions->CallStatic##_jname##MethodV(this, clazz, methodID, \
+                                                      args);                 \
+    }
+#define CALL_STATIC_TYPE_METHODA(_jtype, _jname)                             \
+    _jtype CallStatic##_jname##MethodA(jclass clazz, jmethodID methodID,     \
+                                       const jvalue *args)                   \
+    {                                                                        \
+        return functions->CallStatic##_jname##MethodA(this, clazz, methodID, \
+                                                      args);                 \
+    }
+
+#define CALL_STATIC_TYPE(_jtype, _jname)     \
+    CALL_STATIC_TYPE_METHOD(_jtype, _jname)  \
+    CALL_STATIC_TYPE_METHODV(_jtype, _jname) \
     CALL_STATIC_TYPE_METHODA(_jtype, _jname)
 
     CALL_STATIC_TYPE(jobject, Object)
@@ -782,296 +932,490 @@
         va_end(args);
     }
     void CallStaticVoidMethodV(jclass clazz, jmethodID methodID, va_list args)
-    { functions->CallStaticVoidMethodV(this, clazz, methodID, args); }
-    void CallStaticVoidMethodA(jclass clazz, jmethodID methodID, const jvalue* args)
-    { functions->CallStaticVoidMethodA(this, clazz, methodID, args); }
+    {
+        functions->CallStaticVoidMethodV(this, clazz, methodID, args);
+    }
+    void CallStaticVoidMethodA(jclass clazz, jmethodID methodID, const jvalue *args)
+    {
+        functions->CallStaticVoidMethodA(this, clazz, methodID, args);
+    }
 
-    jfieldID GetStaticFieldID(jclass clazz, const char* name, const char* sig)
-    { return functions->GetStaticFieldID(this, clazz, name, sig); }
+    jfieldID GetStaticFieldID(jclass clazz, const char *name, const char *sig)
+    {
+        return functions->GetStaticFieldID(this, clazz, name, sig);
+    }
 
     jobject GetStaticObjectField(jclass clazz, jfieldID fieldID)
-    { return functions->GetStaticObjectField(this, clazz, fieldID); }
+    {
+        return functions->GetStaticObjectField(this, clazz, fieldID);
+    }
     jboolean GetStaticBooleanField(jclass clazz, jfieldID fieldID)
-    { return functions->GetStaticBooleanField(this, clazz, fieldID); }
+    {
+        return functions->GetStaticBooleanField(this, clazz, fieldID);
+    }
     jbyte GetStaticByteField(jclass clazz, jfieldID fieldID)
-    { return functions->GetStaticByteField(this, clazz, fieldID); }
+    {
+        return functions->GetStaticByteField(this, clazz, fieldID);
+    }
     jchar GetStaticCharField(jclass clazz, jfieldID fieldID)
-    { return functions->GetStaticCharField(this, clazz, fieldID); }
+    {
+        return functions->GetStaticCharField(this, clazz, fieldID);
+    }
     jshort GetStaticShortField(jclass clazz, jfieldID fieldID)
-    { return functions->GetStaticShortField(this, clazz, fieldID); }
+    {
+        return functions->GetStaticShortField(this, clazz, fieldID);
+    }
     jint GetStaticIntField(jclass clazz, jfieldID fieldID)
-    { return functions->GetStaticIntField(this, clazz, fieldID); }
+    {
+        return functions->GetStaticIntField(this, clazz, fieldID);
+    }
     jlong GetStaticLongField(jclass clazz, jfieldID fieldID)
-    { return functions->GetStaticLongField(this, clazz, fieldID); }
+    {
+        return functions->GetStaticLongField(this, clazz, fieldID);
+    }
     jfloat GetStaticFloatField(jclass clazz, jfieldID fieldID)
-    { return functions->GetStaticFloatField(this, clazz, fieldID); }
+    {
+        return functions->GetStaticFloatField(this, clazz, fieldID);
+    }
     jdouble GetStaticDoubleField(jclass clazz, jfieldID fieldID)
-    { return functions->GetStaticDoubleField(this, clazz, fieldID); }
+    {
+        return functions->GetStaticDoubleField(this, clazz, fieldID);
+    }
 
     void SetStaticObjectField(jclass clazz, jfieldID fieldID, jobject val)
-    { functions->SetStaticObjectField(this, clazz, fieldID, val); }
+    {
+        functions->SetStaticObjectField(this, clazz, fieldID, val);
+    }
     void SetStaticBooleanField(jclass clazz, jfieldID fieldID, jboolean val)
-    { functions->SetStaticBooleanField(this, clazz, fieldID, val); }
+    {
+        functions->SetStaticBooleanField(this, clazz, fieldID, val);
+    }
     void SetStaticByteField(jclass clazz, jfieldID fieldID, jbyte val)
-    { functions->SetStaticByteField(this, clazz, fieldID, val); }
+    {
+        functions->SetStaticByteField(this, clazz, fieldID, val);
+    }
     void SetStaticCharField(jclass clazz, jfieldID fieldID, jchar val)
-    { functions->SetStaticCharField(this, clazz, fieldID, val); }
+    {
+        functions->SetStaticCharField(this, clazz, fieldID, val);
+    }
     void SetStaticShortField(jclass clazz, jfieldID fieldID, jshort val)
-    { functions->SetStaticShortField(this, clazz, fieldID, val); }
+    {
+        functions->SetStaticShortField(this, clazz, fieldID, val);
+    }
     void SetStaticIntField(jclass clazz, jfieldID fieldID, jint val)
-    { functions->SetStaticIntField(this, clazz, fieldID, val); }
+    {
+        functions->SetStaticIntField(this, clazz, fieldID, val);
+    }
     void SetStaticLongField(jclass clazz, jfieldID fieldID, jlong val)
-    { functions->SetStaticLongField(this, clazz, fieldID, val); }
+    {
+        functions->SetStaticLongField(this, clazz, fieldID, val);
+    }
     void SetStaticFloatField(jclass clazz, jfieldID fieldID, jfloat val)
-    { functions->SetStaticFloatField(this, clazz, fieldID, val); }
+    {
+        functions->SetStaticFloatField(this, clazz, fieldID, val);
+    }
     void SetStaticDoubleField(jclass clazz, jfieldID fieldID, jdouble val)
-    { functions->SetStaticDoubleField(this, clazz, fieldID, val); }
+    {
+        functions->SetStaticDoubleField(this, clazz, fieldID, val);
+    }
 
-    jstring NewString(const jchar* unicodeChars, jsize len)
-    { return functions->NewString(this, unicodeChars, len); }
+    jstring NewString(const jchar *unicodeChars, jsize len)
+    {
+        return functions->NewString(this, unicodeChars, len);
+    }
 
     jsize GetStringLength(jstring string)
-    { return functions->GetStringLength(this, string); }
+    {
+        return functions->GetStringLength(this, string);
+    }
 
-    const jchar* GetStringChars(jstring string, jboolean* isCopy)
-    { return functions->GetStringChars(this, string, isCopy); }
+    const jchar *GetStringChars(jstring string, jboolean *isCopy)
+    {
+        return functions->GetStringChars(this, string, isCopy);
+    }
 
-    void ReleaseStringChars(jstring string, const jchar* chars)
-    { functions->ReleaseStringChars(this, string, chars); }
+    void ReleaseStringChars(jstring string, const jchar *chars)
+    {
+        functions->ReleaseStringChars(this, string, chars);
+    }
 
-    jstring NewStringUTF(const char* bytes)
-    { return functions->NewStringUTF(this, bytes); }
+    jstring NewStringUTF(const char *bytes)
+    {
+        return functions->NewStringUTF(this, bytes);
+    }
 
     jsize GetStringUTFLength(jstring string)
-    { return functions->GetStringUTFLength(this, string); }
+    {
+        return functions->GetStringUTFLength(this, string);
+    }
 
-    const char* GetStringUTFChars(jstring string, jboolean* isCopy)
-    { return functions->GetStringUTFChars(this, string, isCopy); }
+    const char *GetStringUTFChars(jstring string, jboolean *isCopy)
+    {
+        return functions->GetStringUTFChars(this, string, isCopy);
+    }
 
-    void ReleaseStringUTFChars(jstring string, const char* utf)
-    { functions->ReleaseStringUTFChars(this, string, utf); }
+    void ReleaseStringUTFChars(jstring string, const char *utf)
+    {
+        functions->ReleaseStringUTFChars(this, string, utf);
+    }
 
     jsize GetArrayLength(jarray array)
-    { return functions->GetArrayLength(this, array); }
+    {
+        return functions->GetArrayLength(this, array);
+    }
 
     jobjectArray NewObjectArray(jsize length, jclass elementClass,
-        jobject initialElement)
-    { return functions->NewObjectArray(this, length, elementClass,
-        initialElement); }
+                                jobject initialElement)
+    {
+        return functions->NewObjectArray(this, length, elementClass,
+                                         initialElement);
+    }
 
     jobject GetObjectArrayElement(jobjectArray array, jsize index)
-    { return functions->GetObjectArrayElement(this, array, index); }
+    {
+        return functions->GetObjectArrayElement(this, array, index);
+    }
 
     void SetObjectArrayElement(jobjectArray array, jsize index, jobject val)
-    { functions->SetObjectArrayElement(this, array, index, val); }
+    {
+        functions->SetObjectArrayElement(this, array, index, val);
+    }
 
     jbooleanArray NewBooleanArray(jsize length)
-    { return functions->NewBooleanArray(this, length); }
+    {
+        return functions->NewBooleanArray(this, length);
+    }
     jbyteArray NewByteArray(jsize length)
-    { return functions->NewByteArray(this, length); }
+    {
+        return functions->NewByteArray(this, length);
+    }
     jcharArray NewCharArray(jsize length)
-    { return functions->NewCharArray(this, length); }
+    {
+        return functions->NewCharArray(this, length);
+    }
     jshortArray NewShortArray(jsize length)
-    { return functions->NewShortArray(this, length); }
+    {
+        return functions->NewShortArray(this, length);
+    }
     jintArray NewIntArray(jsize length)
-    { return functions->NewIntArray(this, length); }
+    {
+        return functions->NewIntArray(this, length);
+    }
     jlongArray NewLongArray(jsize length)
-    { return functions->NewLongArray(this, length); }
+    {
+        return functions->NewLongArray(this, length);
+    }
     jfloatArray NewFloatArray(jsize length)
-    { return functions->NewFloatArray(this, length); }
+    {
+        return functions->NewFloatArray(this, length);
+    }
     jdoubleArray NewDoubleArray(jsize length)
-    { return functions->NewDoubleArray(this, length); }
+    {
+        return functions->NewDoubleArray(this, length);
+    }
 
-    jboolean* GetBooleanArrayElements(jbooleanArray array, jboolean* isCopy)
-    { return functions->GetBooleanArrayElements(this, array, isCopy); }
-    jbyte* GetByteArrayElements(jbyteArray array, jboolean* isCopy)
-    { return functions->GetByteArrayElements(this, array, isCopy); }
-    jchar* GetCharArrayElements(jcharArray array, jboolean* isCopy)
-    { return functions->GetCharArrayElements(this, array, isCopy); }
-    jshort* GetShortArrayElements(jshortArray array, jboolean* isCopy)
-    { return functions->GetShortArrayElements(this, array, isCopy); }
-    jint* GetIntArrayElements(jintArray array, jboolean* isCopy)
-    { return functions->GetIntArrayElements(this, array, isCopy); }
-    jlong* GetLongArrayElements(jlongArray array, jboolean* isCopy)
-    { return functions->GetLongArrayElements(this, array, isCopy); }
-    jfloat* GetFloatArrayElements(jfloatArray array, jboolean* isCopy)
-    { return functions->GetFloatArrayElements(this, array, isCopy); }
-    jdouble* GetDoubleArrayElements(jdoubleArray array, jboolean* isCopy)
-    { return functions->GetDoubleArrayElements(this, array, isCopy); }
+    jboolean *GetBooleanArrayElements(jbooleanArray array, jboolean *isCopy)
+    {
+        return functions->GetBooleanArrayElements(this, array, isCopy);
+    }
+    jbyte *GetByteArrayElements(jbyteArray array, jboolean *isCopy)
+    {
+        return functions->GetByteArrayElements(this, array, isCopy);
+    }
+    jchar *GetCharArrayElements(jcharArray array, jboolean *isCopy)
+    {
+        return functions->GetCharArrayElements(this, array, isCopy);
+    }
+    jshort *GetShortArrayElements(jshortArray array, jboolean *isCopy)
+    {
+        return functions->GetShortArrayElements(this, array, isCopy);
+    }
+    jint *GetIntArrayElements(jintArray array, jboolean *isCopy)
+    {
+        return functions->GetIntArrayElements(this, array, isCopy);
+    }
+    jlong *GetLongArrayElements(jlongArray array, jboolean *isCopy)
+    {
+        return functions->GetLongArrayElements(this, array, isCopy);
+    }
+    jfloat *GetFloatArrayElements(jfloatArray array, jboolean *isCopy)
+    {
+        return functions->GetFloatArrayElements(this, array, isCopy);
+    }
+    jdouble *GetDoubleArrayElements(jdoubleArray array, jboolean *isCopy)
+    {
+        return functions->GetDoubleArrayElements(this, array, isCopy);
+    }
 
-    void ReleaseBooleanArrayElements(jbooleanArray array, jboolean* elems,
-        jint mode)
-    { functions->ReleaseBooleanArrayElements(this, array, elems, mode); }
-    void ReleaseByteArrayElements(jbyteArray array, jbyte* elems,
-        jint mode)
-    { functions->ReleaseByteArrayElements(this, array, elems, mode); }
-    void ReleaseCharArrayElements(jcharArray array, jchar* elems,
-        jint mode)
-    { functions->ReleaseCharArrayElements(this, array, elems, mode); }
-    void ReleaseShortArrayElements(jshortArray array, jshort* elems,
-        jint mode)
-    { functions->ReleaseShortArrayElements(this, array, elems, mode); }
-    void ReleaseIntArrayElements(jintArray array, jint* elems,
-        jint mode)
-    { functions->ReleaseIntArrayElements(this, array, elems, mode); }
-    void ReleaseLongArrayElements(jlongArray array, jlong* elems,
-        jint mode)
-    { functions->ReleaseLongArrayElements(this, array, elems, mode); }
-    void ReleaseFloatArrayElements(jfloatArray array, jfloat* elems,
-        jint mode)
-    { functions->ReleaseFloatArrayElements(this, array, elems, mode); }
-    void ReleaseDoubleArrayElements(jdoubleArray array, jdouble* elems,
-        jint mode)
-    { functions->ReleaseDoubleArrayElements(this, array, elems, mode); }
+    void ReleaseBooleanArrayElements(jbooleanArray array, jboolean *elems,
+                                     jint mode)
+    {
+        functions->ReleaseBooleanArrayElements(this, array, elems, mode);
+    }
+    void ReleaseByteArrayElements(jbyteArray array, jbyte *elems,
+                                  jint mode)
+    {
+        functions->ReleaseByteArrayElements(this, array, elems, mode);
+    }
+    void ReleaseCharArrayElements(jcharArray array, jchar *elems,
+                                  jint mode)
+    {
+        functions->ReleaseCharArrayElements(this, array, elems, mode);
+    }
+    void ReleaseShortArrayElements(jshortArray array, jshort *elems,
+                                   jint mode)
+    {
+        functions->ReleaseShortArrayElements(this, array, elems, mode);
+    }
+    void ReleaseIntArrayElements(jintArray array, jint *elems,
+                                 jint mode)
+    {
+        functions->ReleaseIntArrayElements(this, array, elems, mode);
+    }
+    void ReleaseLongArrayElements(jlongArray array, jlong *elems,
+                                  jint mode)
+    {
+        functions->ReleaseLongArrayElements(this, array, elems, mode);
+    }
+    void ReleaseFloatArrayElements(jfloatArray array, jfloat *elems,
+                                   jint mode)
+    {
+        functions->ReleaseFloatArrayElements(this, array, elems, mode);
+    }
+    void ReleaseDoubleArrayElements(jdoubleArray array, jdouble *elems,
+                                    jint mode)
+    {
+        functions->ReleaseDoubleArrayElements(this, array, elems, mode);
+    }
 
     void GetBooleanArrayRegion(jbooleanArray array, jsize start, jsize len,
-        jboolean* buf)
-    { functions->GetBooleanArrayRegion(this, array, start, len, buf); }
+                               jboolean *buf)
+    {
+        functions->GetBooleanArrayRegion(this, array, start, len, buf);
+    }
     void GetByteArrayRegion(jbyteArray array, jsize start, jsize len,
-        jbyte* buf)
-    { functions->GetByteArrayRegion(this, array, start, len, buf); }
+                            jbyte *buf)
+    {
+        functions->GetByteArrayRegion(this, array, start, len, buf);
+    }
     void GetCharArrayRegion(jcharArray array, jsize start, jsize len,
-        jchar* buf)
-    { functions->GetCharArrayRegion(this, array, start, len, buf); }
+                            jchar *buf)
+    {
+        functions->GetCharArrayRegion(this, array, start, len, buf);
+    }
     void GetShortArrayRegion(jshortArray array, jsize start, jsize len,
-        jshort* buf)
-    { functions->GetShortArrayRegion(this, array, start, len, buf); }
+                             jshort *buf)
+    {
+        functions->GetShortArrayRegion(this, array, start, len, buf);
+    }
     void GetIntArrayRegion(jintArray array, jsize start, jsize len,
-        jint* buf)
-    { functions->GetIntArrayRegion(this, array, start, len, buf); }
+                           jint *buf)
+    {
+        functions->GetIntArrayRegion(this, array, start, len, buf);
+    }
     void GetLongArrayRegion(jlongArray array, jsize start, jsize len,
-        jlong* buf)
-    { functions->GetLongArrayRegion(this, array, start, len, buf); }
+                            jlong *buf)
+    {
+        functions->GetLongArrayRegion(this, array, start, len, buf);
+    }
     void GetFloatArrayRegion(jfloatArray array, jsize start, jsize len,
-        jfloat* buf)
-    { functions->GetFloatArrayRegion(this, array, start, len, buf); }
+                             jfloat *buf)
+    {
+        functions->GetFloatArrayRegion(this, array, start, len, buf);
+    }
     void GetDoubleArrayRegion(jdoubleArray array, jsize start, jsize len,
-        jdouble* buf)
-    { functions->GetDoubleArrayRegion(this, array, start, len, buf); }
+                              jdouble *buf)
+    {
+        functions->GetDoubleArrayRegion(this, array, start, len, buf);
+    }
 
     void SetBooleanArrayRegion(jbooleanArray array, jsize start, jsize len,
-        const jboolean* buf)
-    { functions->SetBooleanArrayRegion(this, array, start, len, buf); }
+                               const jboolean *buf)
+    {
+        functions->SetBooleanArrayRegion(this, array, start, len, buf);
+    }
     void SetByteArrayRegion(jbyteArray array, jsize start, jsize len,
-        const jbyte* buf)
-    { functions->SetByteArrayRegion(this, array, start, len, buf); }
+                            const jbyte *buf)
+    {
+        functions->SetByteArrayRegion(this, array, start, len, buf);
+    }
     void SetCharArrayRegion(jcharArray array, jsize start, jsize len,
-        const jchar* buf)
-    { functions->SetCharArrayRegion(this, array, start, len, buf); }
+                            const jchar *buf)
+    {
+        functions->SetCharArrayRegion(this, array, start, len, buf);
+    }
     void SetShortArrayRegion(jshortArray array, jsize start, jsize len,
-        const jshort* buf)
-    { functions->SetShortArrayRegion(this, array, start, len, buf); }
+                             const jshort *buf)
+    {
+        functions->SetShortArrayRegion(this, array, start, len, buf);
+    }
     void SetIntArrayRegion(jintArray array, jsize start, jsize len,
-        const jint* buf)
-    { functions->SetIntArrayRegion(this, array, start, len, buf); }
+                           const jint *buf)
+    {
+        functions->SetIntArrayRegion(this, array, start, len, buf);
+    }
     void SetLongArrayRegion(jlongArray array, jsize start, jsize len,
-        const jlong* buf)
-    { functions->SetLongArrayRegion(this, array, start, len, buf); }
+                            const jlong *buf)
+    {
+        functions->SetLongArrayRegion(this, array, start, len, buf);
+    }
     void SetFloatArrayRegion(jfloatArray array, jsize start, jsize len,
-        const jfloat* buf)
-    { functions->SetFloatArrayRegion(this, array, start, len, buf); }
+                             const jfloat *buf)
+    {
+        functions->SetFloatArrayRegion(this, array, start, len, buf);
+    }
     void SetDoubleArrayRegion(jdoubleArray array, jsize start, jsize len,
-        const jdouble* buf)
-    { functions->SetDoubleArrayRegion(this, array, start, len, buf); }
+                              const jdouble *buf)
+    {
+        functions->SetDoubleArrayRegion(this, array, start, len, buf);
+    }
 
-    jint RegisterNatives(jclass clazz, const JNINativeMethod* methods,
-        jint nMethods)
-    { return functions->RegisterNatives(this, clazz, methods, nMethods); }
+    jint RegisterNatives(jclass clazz, const JNINativeMethod *methods,
+                         jint nMethods)
+    {
+        return functions->RegisterNatives(this, clazz, methods, nMethods);
+    }
 
     jint UnregisterNatives(jclass clazz)
-    { return functions->UnregisterNatives(this, clazz); }
+    {
+        return functions->UnregisterNatives(this, clazz);
+    }
 
     jint MonitorEnter(jobject obj)
-    { return functions->MonitorEnter(this, obj); }
+    {
+        return functions->MonitorEnter(this, obj);
+    }
 
     jint MonitorExit(jobject obj)
-    { return functions->MonitorExit(this, obj); }
+    {
+        return functions->MonitorExit(this, obj);
+    }
 
-    jint GetJavaVM(JavaVM** vm)
-    { return functions->GetJavaVM(this, vm); }
+    jint GetJavaVM(JavaVM **vm)
+    {
+        return functions->GetJavaVM(this, vm);
+    }
 
-    void GetStringRegion(jstring str, jsize start, jsize len, jchar* buf)
-    { functions->GetStringRegion(this, str, start, len, buf); }
+    void GetStringRegion(jstring str, jsize start, jsize len, jchar *buf)
+    {
+        functions->GetStringRegion(this, str, start, len, buf);
+    }
 
-    void GetStringUTFRegion(jstring str, jsize start, jsize len, char* buf)
-    { return functions->GetStringUTFRegion(this, str, start, len, buf); }
+    void GetStringUTFRegion(jstring str, jsize start, jsize len, char *buf)
+    {
+        return functions->GetStringUTFRegion(this, str, start, len, buf);
+    }
 
-    void* GetPrimitiveArrayCritical(jarray array, jboolean* isCopy)
-    { return functions->GetPrimitiveArrayCritical(this, array, isCopy); }
+    void *GetPrimitiveArrayCritical(jarray array, jboolean *isCopy)
+    {
+        return functions->GetPrimitiveArrayCritical(this, array, isCopy);
+    }
 
-    void ReleasePrimitiveArrayCritical(jarray array, void* carray, jint mode)
-    { functions->ReleasePrimitiveArrayCritical(this, array, carray, mode); }
+    void ReleasePrimitiveArrayCritical(jarray array, void *carray, jint mode)
+    {
+        functions->ReleasePrimitiveArrayCritical(this, array, carray, mode);
+    }
 
-    const jchar* GetStringCritical(jstring string, jboolean* isCopy)
-    { return functions->GetStringCritical(this, string, isCopy); }
+    const jchar *GetStringCritical(jstring string, jboolean *isCopy)
+    {
+        return functions->GetStringCritical(this, string, isCopy);
+    }
 
-    void ReleaseStringCritical(jstring string, const jchar* carray)
-    { functions->ReleaseStringCritical(this, string, carray); }
+    void ReleaseStringCritical(jstring string, const jchar *carray)
+    {
+        functions->ReleaseStringCritical(this, string, carray);
+    }
 
     jweak NewWeakGlobalRef(jobject obj)
-    { return functions->NewWeakGlobalRef(this, obj); }
+    {
+        return functions->NewWeakGlobalRef(this, obj);
+    }
 
     void DeleteWeakGlobalRef(jweak obj)
-    { functions->DeleteWeakGlobalRef(this, obj); }
+    {
+        functions->DeleteWeakGlobalRef(this, obj);
+    }
 
     jboolean ExceptionCheck()
-    { return functions->ExceptionCheck(this); }
+    {
+        return functions->ExceptionCheck(this);
+    }
 
-    jobject NewDirectByteBuffer(void* address, jlong capacity)
-    { return functions->NewDirectByteBuffer(this, address, capacity); }
+    jobject NewDirectByteBuffer(void *address, jlong capacity)
+    {
+        return functions->NewDirectByteBuffer(this, address, capacity);
+    }
 
-    void* GetDirectBufferAddress(jobject buf)
-    { return functions->GetDirectBufferAddress(this, buf); }
+    void *GetDirectBufferAddress(jobject buf)
+    {
+        return functions->GetDirectBufferAddress(this, buf);
+    }
 
     jlong GetDirectBufferCapacity(jobject buf)
-    { return functions->GetDirectBufferCapacity(this, buf); }
+    {
+        return functions->GetDirectBufferCapacity(this, buf);
+    }
 
     /* added in JNI 1.6 */
     jobjectRefType GetObjectRefType(jobject obj)
-    { return functions->GetObjectRefType(this, obj); }
+    {
+        return functions->GetObjectRefType(this, obj);
+    }
 #endif /*__cplusplus*/
 };
 
-
 /*
  * JNI invocation interface.
  */
-struct JNIInvokeInterface {
-    void*       reserved0;
-    void*       reserved1;
-    void*       reserved2;
+struct JNIInvokeInterface
+{
+    void *reserved0;
+    void *reserved1;
+    void *reserved2;
 
-    jint        (*DestroyJavaVM)(JavaVM* vm);
-    jint        (*AttachCurrentThread)(JavaVM* vm, JNIEnv** p_env, void* thr_args);
-    jint        (*DetachCurrentThread)(JavaVM* vm);
-    jint        (*GetEnv)(JavaVM* vm, void** p_env, jint version);
-    jint        (*AttachCurrentThreadAsDaemon)(JavaVM* vm, JNIEnv** p_env, void* thr_args);
+    jint (*DestroyJavaVM)(JavaVM *vm);
+    jint (*AttachCurrentThread)(JavaVM *vm, JNIEnv **p_env, void *thr_args);
+    jint (*DetachCurrentThread)(JavaVM *vm);
+    jint (*GetEnv)(JavaVM *vm, void **p_env, jint version);
+    jint (*AttachCurrentThreadAsDaemon)(JavaVM *vm, JNIEnv **p_env, void *thr_args);
 };
 
 /*
  * C++ version.
  */
-struct _JavaVM {
-    const struct JNIInvokeInterface* functions;
+struct _JavaVM
+{
+    const struct JNIInvokeInterface *functions;
 
 #if defined(__cplusplus)
     jint DestroyJavaVM()
-    { return functions->DestroyJavaVM(this); }
-    jint AttachCurrentThread(JNIEnv** p_env, void* thr_args)
-    { return functions->AttachCurrentThread(this, p_env, thr_args); }
+    {
+        return functions->DestroyJavaVM(this);
+    }
+    jint AttachCurrentThread(JNIEnv **p_env, void *thr_args)
+    {
+        return functions->AttachCurrentThread(this, p_env, thr_args);
+    }
     jint DetachCurrentThread()
-    { return functions->DetachCurrentThread(this); }
-    jint GetEnv(void** env, jint version)
-    { return functions->GetEnv(this, env, version); }
-    jint AttachCurrentThreadAsDaemon(JNIEnv** p_env, void* thr_args)
-    { return functions->AttachCurrentThreadAsDaemon(this, p_env, thr_args); }
+    {
+        return functions->DetachCurrentThread(this);
+    }
+    jint GetEnv(void **env, jint version)
+    {
+        return functions->GetEnv(this, env, version);
+    }
+    jint AttachCurrentThreadAsDaemon(JNIEnv **p_env, void *thr_args)
+    {
+        return functions->AttachCurrentThreadAsDaemon(this, p_env, thr_args);
+    }
 #endif /*__cplusplus*/
 };
 
-struct JavaVMAttachArgs {
-    jint        version;    /* must be >= JNI_VERSION_1_2 */
-    const char* name;       /* NULL or name of thread as modified UTF-8 str */
-    jobject     group;      /* global ref of a ThreadGroup object, or NULL */
+struct JavaVMAttachArgs
+{
+    jint version;     /* must be >= JNI_VERSION_1_2 */
+    const char *name; /* NULL or name of thread as modified UTF-8 str */
+    jobject group;    /* global ref of a ThreadGroup object, or NULL */
 };
 typedef struct JavaVMAttachArgs JavaVMAttachArgs;
 
@@ -1079,67 +1423,68 @@
  * JNI 1.2+ initialization.  (As of 1.6, the pre-1.2 structures are no
  * longer supported.)
  */
-typedef struct JavaVMOption {
-    const char* optionString;
-    void*       extraInfo;
+typedef struct JavaVMOption
+{
+    const char *optionString;
+    void *extraInfo;
 } JavaVMOption;
 
-typedef struct JavaVMInitArgs {
-    jint        version;    /* use JNI_VERSION_1_2 or later */
+typedef struct JavaVMInitArgs
+{
+    jint version; /* use JNI_VERSION_1_2 or later */
 
-    jint        nOptions;
-    JavaVMOption* options;
-    jboolean    ignoreUnrecognized;
+    jint nOptions;
+    JavaVMOption *options;
+    jboolean ignoreUnrecognized;
 } JavaVMInitArgs;
 
 #ifdef __cplusplus
-extern "C" {
+extern "C"
+{
 #endif
-/*
- * VM initialization functions.
- *
- * Note these are the only symbols exported for JNI by the VM.
- */
+    /*
+     * VM initialization functions.
+     *
+     * Note these are the only symbols exported for JNI by the VM.
+     */
 
-jint JNI_GetDefaultJavaVMInitArgs(void*);
-jint JNI_CreateJavaVM(JavaVM**, JNIEnv**, void*);
-jint JNI_GetCreatedJavaVMs(JavaVM**, jsize, jsize*);
+    jint JNI_GetDefaultJavaVMInitArgs(void *);
+    jint JNI_CreateJavaVM(JavaVM **, JNIEnv **, void *);
+    jint JNI_GetCreatedJavaVMs(JavaVM **, jsize, jsize *);
 
 #define JNIIMPORT
-#define JNIEXPORT  __attribute__ ((visibility ("default")))
+#define JNIEXPORT __attribute__((visibility("default")))
 #define JNICALL
 
-/*
- * Prototypes for functions exported by loadable shared libs.  These are
- * called by JNI, not provided by JNI.
- */
-JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved);
-JNIEXPORT void JNI_OnUnload(JavaVM* vm, void* reserved);
+    /*
+     * Prototypes for functions exported by loadable shared libs.  These are
+     * called by JNI, not provided by JNI.
+     */
+    JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved);
+    JNIEXPORT void JNI_OnUnload(JavaVM *vm, void *reserved);
 
 #ifdef __cplusplus
 }
 #endif
 
-
 /*
  * Manifest constants.
  */
-#define JNI_FALSE   0
-#define JNI_TRUE    1
+#define JNI_FALSE 0
+#define JNI_TRUE 1
 
 #define JNI_VERSION_1_1 0x00010001
 #define JNI_VERSION_1_2 0x00010002
 #define JNI_VERSION_1_4 0x00010004
 #define JNI_VERSION_1_6 0x00010006
 
-#define JNI_OK          (0)         /* no error */
-#define JNI_ERR         (-1)        /* generic error */
-#define JNI_EDETACHED   (-2)        /* thread detached from the VM */
-#define JNI_EVERSION    (-3)        /* JNI version error */
-#define JNI_ENOMEM      (-4)        /* Out of memory */
-#define JNI_EEXIST      (-5)        /* VM already created */
-#define JNI_EINVAL      (-6)        /* Invalid argument */
+#define JNI_OK (0)         /* no error */
+#define JNI_ERR (-1)       /* generic error */
+#define JNI_EDETACHED (-2) /* thread detached from the VM */
+#define JNI_EVERSION (-3)  /* JNI version error */
+#define JNI_ENOMEM (-4)    /* Out of memory */
+#define JNI_EEXIST (-5)    /* VM already created */
+#define JNI_EINVAL (-6)    /* Invalid argument */
 
-#define JNI_COMMIT      1           /* copy content, do not free buffer */
-#define JNI_ABORT       2           /* free buffer w/o copying back */
-
+#define JNI_COMMIT 1 /* copy content, do not free buffer */
+#define JNI_ABORT 2  /* free buffer w/o copying back */
diff --git a/pkgs/jni/tool/generate_ffi_bindings.dart b/pkgs/jni/tool/generate_ffi_bindings.dart
new file mode 100644
index 0000000..35b9db2
--- /dev/null
+++ b/pkgs/jni/tool/generate_ffi_bindings.dart
@@ -0,0 +1,68 @@
+// 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.
+
+// This script generates all FFIGEN-based bindings we require to use JNI, which
+// includes some C wrappers over `JNIEnv` type and some Dart extension methods.
+
+import 'dart:io';
+
+import 'package:logging/logging.dart';
+import 'package:args/args.dart';
+
+import 'wrapper_generators/logging.dart';
+import 'wrapper_generators/generate_c_extensions.dart';
+import 'wrapper_generators/generate_dart_extensions.dart';
+
+import 'package:ffigen/ffigen.dart' as ffigen;
+
+void main(List<String> args) {
+  final levels = Map.fromEntries(
+    Level.LEVELS.map((l) => MapEntry(l.name.toLowerCase(), l)),
+  );
+  final argParser = ArgParser()
+    ..addOption(
+      'verbose',
+      defaultsTo: 'severe',
+      help: 'set ffigen log verbosity',
+      allowed: levels.keys,
+    )
+    ..addFlag(
+      'help',
+      negatable: false,
+      abbr: 'h',
+      defaultsTo: false,
+      help: 'display this help message',
+    );
+
+  final argResults = argParser.parse(args);
+
+  if (argResults['help']) {
+    stderr.writeln('Generates FFI bindings required for package:jni');
+    stderr.writeln(argParser.usage);
+    exitCode = 1;
+    return;
+  }
+
+  hierarchicalLoggingEnabled = true;
+  Logger.root.level = levels[argResults['verbose']]!;
+  logger.level = Level.INFO;
+  Logger.root.onRecord.listen((record) {
+    stderr.writeln('${record.level.name}: ${record.message}');
+  });
+
+  logger.info("Generating C wrappers");
+  final minimalConfig = ffigen.Config.fromFile(File('ffigen_exts.yaml'));
+  final minimalLibrary = ffigen.parse(minimalConfig);
+  generateCWrappers(minimalLibrary);
+
+  logger.info("Generating FFI bindings for package:jni");
+
+  final config = ffigen.Config.fromFile(File('ffigen.yaml'));
+  final library = ffigen.parse(config);
+  final outputFile = File(config.output);
+  library.generateFile(outputFile);
+
+  logger.info("Generating Dart extensions");
+  generateDartExtensions(library);
+}
diff --git a/pkgs/jni/tool/wrapper_generators/ffigen_util.dart b/pkgs/jni/tool/wrapper_generators/ffigen_util.dart
new file mode 100644
index 0000000..2b234f6
--- /dev/null
+++ b/pkgs/jni/tool/wrapper_generators/ffigen_util.dart
@@ -0,0 +1,50 @@
+// Copyright (c) 2023, 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.
+
+import 'package:ffigen/src/code_generator/writer.dart';
+import 'package:ffigen/src/code_generator.dart';
+
+final dummyWriter = Writer(
+  lookUpBindings: [],
+  ffiNativeBindings: [],
+  noLookUpBindings: [],
+  className: 'unused',
+);
+
+/// Find compound having [name] in [library].
+Compound findCompound(library, String name) {
+  return library.bindings.firstWhere((element) => element.name == name)
+      as Compound;
+}
+
+const preamble = '''
+// Auto generated file. Do not edit.
+
+// This is generated from JNI header in Android NDK. License for the same is
+// provided below.
+
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * JNI specification, as defined by Sun:
+ * http://java.sun.com/javase/6/docs/technotes/guides/jni/spec/jniTOC.html
+ *
+ * Everything here is expected to be VM-neutral.
+ */
+
+''';
diff --git a/pkgs/jni/tool/wrapper_generators/generate_c_extensions.dart b/pkgs/jni/tool/wrapper_generators/generate_c_extensions.dart
new file mode 100644
index 0000000..ef907bf
--- /dev/null
+++ b/pkgs/jni/tool/wrapper_generators/generate_c_extensions.dart
@@ -0,0 +1,296 @@
+// Copyright (c) 2023, 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.
+
+import 'dart:io';
+
+import 'package:ffigen/src/code_generator.dart';
+
+import 'ffigen_util.dart';
+import 'logging.dart';
+
+class Paths {
+  static final currentDir = Directory.current.uri;
+  static final src = currentDir.resolve("src/");
+  static final thirdParty = src.resolve("third_party/");
+  static final globalJniEnvH = thirdParty.resolve("global_jni_env.h");
+  static final globalJniEnvC = thirdParty.resolve("global_jni_env.c");
+  static final bindingsDir = currentDir.resolve("lib/src/third_party/");
+  static final envExtensions = bindingsDir.resolve("env_extensions.dart");
+}
+
+/// Name of variable used in wrappers to hold the result.
+const resultVar = '_result';
+
+/// Name of variable used in wrappers to hold the exception.
+const errorVar = '_exception';
+
+/// Name of JNIEnv struct definition in JNI headers.
+const envType = 'JNINativeInterface';
+
+/// Name of wrapper to JNIEnv
+const wrapperName = 'GlobalJniEnv';
+
+const wrapperIncludes = '''
+#include "global_jni_env.h"
+
+''';
+
+const wrapperDeclIncludes = '''
+#include <stdint.h>
+#include "../dartjni.h"
+
+''';
+
+const wrapperGetter = '''
+FFI_PLUGIN_EXPORT
+$wrapperName* GetGlobalEnv() {
+  if (jni->jvm == NULL) {
+    return NULL;
+  }
+  return &globalJniEnv;
+}
+''';
+
+const wrapperGetterDecl = '''
+FFI_PLUGIN_EXPORT $wrapperName* GetGlobalEnv();
+''';
+
+/// Get C name of a type from its ffigen representation.
+String getCType(Type type) {
+  if (type is PointerType) {
+    return '${getCType(type.child)}*';
+  }
+  final cType = type.getCType(dummyWriter);
+  const specialCaseMappings = {
+    'JNIEnv1': 'JNIEnv',
+    'ffi.Char': 'char',
+    'ffi.Void': 'void',
+    'ffi.Int': 'int',
+    'ffi.Int32': 'int32_t',
+  };
+  return specialCaseMappings[cType] ?? cType;
+}
+
+/// Get type of wrapping function for a JNIEnv function.
+FunctionType getGlobalJniEnvFunctionType(FunctionType ft) {
+  return FunctionType(
+    returnType: ft.returnType,
+    parameters: ft.parameters.sublist(1),
+  );
+}
+
+// Returns declaration of function field in GlobalJniEnv struct
+String getFunctionFieldDecl(
+  Member field,
+) {
+  final fieldType = field.type;
+  if (fieldType is PointerType && fieldType.child is NativeFunc) {
+    final nativeFunc = fieldType.child as NativeFunc;
+    final functionType = getGlobalJniEnvFunctionType(nativeFunc.type);
+    final resultWrapper = getResultWrapper(getCType(functionType.returnType));
+    final name = field.name;
+    final params = functionType.parameters
+        .map((param) => '${getCType(param.type)} ${param.name}')
+        .join(', ');
+    return ('${resultWrapper.returnType} (*$name)($params);');
+  } else {
+    return 'void* ${field.name};';
+  }
+}
+
+String getWrapperFuncName(Member field) {
+  return 'globalEnv_${field.name}';
+}
+
+class ResultWrapper {
+  String returnType, onResult, onError;
+  ResultWrapper.withResultAndError(
+      this.returnType, this.onResult, this.onError);
+  ResultWrapper.unionType(
+    String returnType,
+    String defaultValue,
+  ) : this.withResultAndError(
+          returnType,
+          '($returnType){.value = $resultVar, .exception = NULL}',
+          '($returnType){.value = $defaultValue, .exception = $errorVar}',
+        );
+  ResultWrapper.forJValueField(String fieldChar)
+      : this.withResultAndError(
+          'JniResult',
+          '(JniResult){.value = {.$fieldChar = $resultVar}, .exception = NULL}',
+          '(JniResult){.value = {.j = 0}, .exception = $errorVar}',
+        );
+}
+
+ResultWrapper getResultWrapper(String returnType) {
+  if (returnType.endsWith("*")) {
+    return ResultWrapper.unionType('JniPointerResult', 'NULL');
+  }
+
+  final jobjectWrapper = ResultWrapper.forJValueField('l');
+  if (returnType.endsWith('Array')) {
+    return jobjectWrapper;
+  }
+
+  const jfields = {
+    'jboolean': 'z',
+    'jbyte': 'b',
+    'jshort': 's',
+    'jchar': 'c',
+    'jint': 'i',
+    'jsize': 'i', // jsize is an alias to jint
+    'jfloat': 'f',
+    'jlong': 'j',
+    'jdouble': 'd',
+    'jobject': 'l',
+    'jweak': 'l',
+    'jarray': 'l',
+    'jstring': 'l',
+    'jthrowable': 'l',
+  };
+
+  switch (returnType) {
+    case 'void':
+      return ResultWrapper.withResultAndError(
+        'jthrowable',
+        'NULL',
+        errorVar,
+      );
+    case 'jmethodID':
+    case 'jfieldID':
+      return ResultWrapper.unionType('JniPointerResult', 'NULL');
+    case 'jclass':
+      return ResultWrapper.unionType('JniClassLookupResult', 'NULL');
+    case 'int32_t':
+      return ResultWrapper.forJValueField('i');
+    default:
+      if (jfields.containsKey(returnType)) {
+        return ResultWrapper.forJValueField(jfields[returnType]!);
+      }
+      throw 'Unknown type $returnType for return type';
+  }
+}
+
+bool isJRefType(String type) {
+  // No need to include jweak here, its only returned by ref-related functions.
+  const refTypes = {
+    'jclass',
+    'jobject',
+    'jstring',
+    'jthrowable',
+    'jarray',
+    'jweak'
+  };
+  return (type.startsWith('j') && type.endsWith('Array')) ||
+      refTypes.contains(type);
+}
+
+const refFunctions = {
+  'NewGlobalRef',
+  'DeleteGlobalRef',
+  'NewLocalRef',
+  'DeleteLocalRef',
+  'NewWeakGlobalRef',
+  'DeleteWeakGlobalRef',
+};
+
+/// These return const ptrs so the assignment statement needs to be
+/// adjusted in the wrapper.
+const constBufferReturningFunctions = {
+  'GetStringChars',
+  'GetStringUTFChars',
+  'GetStringCritical',
+};
+
+/// Methods which do not throw exceptions, and thus not need to be checked
+const _noCheckException = {
+  'GetVersion',
+  'ExceptionClear',
+  'ExceptionDescribe',
+};
+
+String? getWrapperFunc(Member field) {
+  final fieldType = field.type;
+  if (fieldType is PointerType && fieldType.child is NativeFunc) {
+    final functionType = (fieldType.child as NativeFunc).type;
+    if (functionType.parameters.first.name.isEmpty) {
+      return null;
+    }
+
+    final outerFunctionType = getGlobalJniEnvFunctionType(functionType);
+    final wrapperName = getWrapperFuncName(field);
+    final returnType = getCType(outerFunctionType.returnType);
+    final params = outerFunctionType.parameters
+        .map((param) => '${getCType(param.type)} ${param.name}')
+        .join(', ');
+    var returnCapture = returnType == 'void' ? '' : '$returnType $resultVar =';
+    if (constBufferReturningFunctions.contains(field.name)) {
+      returnCapture = 'const $returnCapture';
+    }
+    final callParams = [
+      'jniEnv',
+      ...(outerFunctionType.parameters.map((param) => param.name).toList())
+    ].join(', ');
+    final resultWrapper = getResultWrapper(returnType);
+
+    var convertRef = '';
+    if (isJRefType(returnType) && !refFunctions.contains(field.name)) {
+      convertRef = '  $resultVar = to_global_ref($resultVar);\n';
+    }
+    final exceptionCheck = _noCheckException.contains(field.name)
+        ? ''
+        : '  jthrowable $errorVar = check_exception();\n'
+            '  if ($errorVar != NULL) {\n'
+            '    return ${resultWrapper.onError};\n'
+            '  }\n';
+    return '${resultWrapper.returnType} $wrapperName($params) {\n'
+        '  attach_thread();\n'
+        '  $returnCapture (*jniEnv)->${field.name}($callParams);\n'
+        '$exceptionCheck'
+        '$convertRef'
+        '  return ${resultWrapper.onResult};\n'
+        '}\n';
+  }
+  return null;
+}
+
+void writeGlobalJniEnvWrapper(Library library) {
+  final jniEnvType = findCompound(library, envType);
+
+  final fieldDecls = jniEnvType.members.map(getFunctionFieldDecl).join('\n');
+  final structDecl =
+      'typedef struct $wrapperName {\n$fieldDecls\n} $wrapperName;\n';
+  File.fromUri(Paths.globalJniEnvH).writeAsStringSync(
+      '$preamble$wrapperDeclIncludes$structDecl$wrapperGetterDecl');
+
+  final functionWrappers = StringBuffer();
+  final structInst = StringBuffer('$wrapperName globalJniEnv = {\n');
+  for (final member in jniEnvType.members) {
+    final wrapper = getWrapperFunc(member);
+    if (wrapper == null) {
+      structInst.write('.${member.name} = NULL,\n');
+    } else {
+      structInst.write('.${member.name} = ${getWrapperFuncName(member)},\n');
+      functionWrappers.write('$wrapper\n');
+    }
+  }
+  structInst.write('};');
+  File.fromUri(Paths.globalJniEnvC).writeAsStringSync(
+      '$preamble$wrapperIncludes$functionWrappers$structInst$wrapperGetter');
+}
+
+void executeClangFormat(List<Uri> files) {
+  final paths = files.map((u) => u.toFilePath()).toList();
+  logger.info('execute clang-format -i ${paths.join(" ")}');
+  final format = Process.runSync('clang-format', ['-i', ...paths]);
+  if (format.exitCode != 0) {
+    stderr.writeln('clang-format exited with ${format.exitCode}');
+    stderr.writeln(format.stderr);
+  }
+}
+
+void generateCWrappers(Library minimalLibrary) {
+  writeGlobalJniEnvWrapper(minimalLibrary);
+  executeClangFormat([Paths.globalJniEnvC, Paths.globalJniEnvH]);
+}
diff --git a/pkgs/jni/tool/wrapper_generators/generate_dart_extensions.dart b/pkgs/jni/tool/wrapper_generators/generate_dart_extensions.dart
new file mode 100644
index 0000000..1ec422d
--- /dev/null
+++ b/pkgs/jni/tool/wrapper_generators/generate_dart_extensions.dart
@@ -0,0 +1,215 @@
+// Copyright (c) 2023, 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.
+
+import 'dart:io';
+
+import 'package:collection/collection.dart';
+import 'package:ffigen/src/code_generator.dart';
+
+import 'ffigen_util.dart';
+import 'logging.dart';
+
+class Paths {
+  static final currentDir = Directory.current.uri;
+  static final bindingsDir = currentDir.resolve("lib/src/third_party/");
+  // Contains extensions for our C wrapper types.
+  static final globalEnvExts =
+      bindingsDir.resolve("global_env_extensions.dart");
+  // Contains extensions for JNI's struct types.
+  static final localEnvExts =
+      bindingsDir.resolve("jnienv_javavm_extensions.dart");
+}
+
+void executeDartFormat(List<Uri> files) {
+  final paths = files.map((u) => u.toFilePath()).toList();
+  logger.info('execute dart format ${paths.join(" ")}');
+  final format = Process.runSync('dart', ['format', ...paths]);
+  if (format.exitCode != 0) {
+    logger.severe('dart format exited with ${format.exitCode}');
+    stderr.writeln(format.stderr);
+  }
+}
+
+const globalEnvType = 'GlobalJniEnv';
+const localEnvType = 'JNINativeInterface';
+const jvmType = 'JNIInvokeInterface';
+
+String getCheckedGetter(Type returnType) {
+  if (returnType is PointerType) {
+    final child = returnType.child.getCType(dummyWriter);
+    return 'getPointer<$child>()';
+  }
+  final cType = returnType.getCType(dummyWriter);
+  if (cType.endsWith("ArrayPtr")) {
+    return 'object';
+  }
+  const mappings = {
+    'JBooleanMarker': 'boolean',
+    'JByteMarker': 'byte',
+    'JShortMarker': 'short',
+    'JCharMarker': 'char',
+    'JIntMarker': 'integer',
+    'JSizeMarker': 'integer', // jsize is aliased to jint
+    'JLongMarker': 'long',
+    'JFloatMarker': 'float',
+    'JDoubleMarker': 'doubleFloat',
+    'JObjectPtr': 'object',
+    'JThrowablePtr': 'object',
+    'JStringPtr': 'object',
+    'JClassPtr': 'value',
+    'JFieldIDPtr': 'fieldID',
+    'JMethodIDPtr': 'methodID',
+    'ffi.Int32': 'integer',
+    'ffi.Void': 'check()',
+    'JWeakPtr': 'object',
+  };
+  if (mappings.containsKey(cType)) {
+    return mappings[cType]!;
+  }
+  throw 'Unknown return type: $cType';
+}
+
+String? getGlobalEnvExtensionFunction(Member field, Type? checkedReturnType) {
+  final fieldType = field.type;
+  if (fieldType is PointerType && fieldType.child is NativeFunc) {
+    final nativeFunc = fieldType.child as NativeFunc;
+    final functionType = nativeFunc.type;
+    final returnType = functionType.returnType;
+    var params = functionType.parameters;
+    if (params.first.name.isEmpty) {
+      return null;
+    }
+
+    // Remove env parameter
+    params = params.sublist(1);
+
+    final signature = params
+        .map((p) => '${p.type.getDartType(dummyWriter)} ${p.name}')
+        .join(', ');
+
+    final dartType =
+        FunctionType(returnType: checkedReturnType!, parameters: params)
+            .getDartType(dummyWriter);
+    final callArgs = params.map((p) => p.name).join(', ');
+    final checkedGetter = getCheckedGetter(returnType);
+    var returns = returnType.getDartType(dummyWriter);
+    if (checkedGetter == 'boolean') {
+      returns = 'bool';
+    }
+    return '$returns ${field.name}($signature) => '
+        'ref.${field.name}.asFunction<$dartType>()($callArgs)'
+        '.$checkedGetter;\n';
+  }
+  return null;
+}
+
+void writeDartExtensions(Library library) {
+  const header = '''
+// ignore_for_file: non_constant_identifier_names
+// coverage:ignore-file
+
+import "dart:ffi" as ffi;\n
+import "jni_bindings_generated.dart";
+
+''';
+  const importAccessors = '''
+import "../accessors.dart";
+
+''';
+
+  final globalEnvExtension = getGlobalEnvExtension(library);
+  final accessorExtension =
+      getFunctionPointerExtension(library, 'JniAccessors');
+  final envExtension = getFunctionPointerExtension(
+    library,
+    'JniEnv',
+    indirect: true,
+    implicitThis: true,
+  );
+  final jvmExtension = getFunctionPointerExtension(
+    library,
+    'JavaVM',
+    indirect: true,
+    implicitThis: true,
+  );
+  File.fromUri(Paths.globalEnvExts).writeAsStringSync(preamble +
+      header +
+      importAccessors +
+      globalEnvExtension +
+      accessorExtension);
+  File.fromUri(Paths.localEnvExts)
+      .writeAsStringSync(preamble + header + envExtension + jvmExtension);
+}
+
+String getGlobalEnvExtension(
+  Library library,
+) {
+  final env = findCompound(library, localEnvType);
+  final globalEnv = findCompound(library, globalEnvType);
+  final checkedReturnTypes = {};
+  for (var field in globalEnv.members) {
+    final fieldType = field.type;
+    if (fieldType is PointerType && fieldType.child is NativeFunc) {
+      checkedReturnTypes[field.name] =
+          (fieldType.child as NativeFunc).type.returnType;
+    }
+  }
+  final extensionFunctions = env.members
+      .map((m) => getGlobalEnvExtensionFunction(m, checkedReturnTypes[m.name]))
+      .whereNotNull()
+      .join('\n');
+  return 'extension EnvExtension on ffi.Pointer<$globalEnvType> '
+      '{$extensionFunctions}';
+}
+
+String? getFunctionPointerExtensionFunction(Member field,
+    {bool indirect = false, bool implicitThis = false}) {
+  final fieldType = field.type;
+  if (fieldType is PointerType && fieldType.child is NativeFunc) {
+    final nativeFunc = fieldType.child as NativeFunc;
+    final functionType = nativeFunc.type;
+    final returnType = functionType.returnType;
+    final params = functionType.parameters;
+    if (params.first.name.isEmpty) {
+      return null;
+    }
+
+    final visibleParams = implicitThis ? params.sublist(1) : params;
+
+    final signature = visibleParams
+        .map((p) => '${p.type.getDartType(dummyWriter)} ${p.name}')
+        .join(', ');
+
+    final dartType = FunctionType(returnType: returnType, parameters: params)
+        .getDartType(dummyWriter);
+    final callArgs = [
+      if (implicitThis) 'this',
+      ...visibleParams.map((p) => p.name)
+    ].join(', ');
+    final returns = returnType.getDartType(dummyWriter);
+    final dereference = indirect ? 'value.ref' : 'ref';
+    return '$returns ${field.name}($signature) => '
+        '$dereference.${field.name}.asFunction<$dartType>()($callArgs);\n';
+  }
+  return null;
+}
+
+String getFunctionPointerExtension(Library library, String type,
+    {bool indirect = false, bool implicitThis = false}) {
+  final typeBinding =
+      library.bindings.firstWhere((b) => b.name == type) as Type;
+  final compound = typeBinding.typealiasType.baseType as Compound;
+  final extensionFunctions = compound.members
+      .map((f) => getFunctionPointerExtensionFunction(f,
+          indirect: indirect, implicitThis: implicitThis))
+      .whereNotNull()
+      .join('\n');
+  return 'extension ${type}Extension on ffi.Pointer<$type> '
+      '{$extensionFunctions}';
+}
+
+void generateDartExtensions(Library library) {
+  writeDartExtensions(library);
+  executeDartFormat([Paths.globalEnvExts, Paths.localEnvExts]);
+}
diff --git a/pkgs/jni/tool/wrapper_generators/logging.dart b/pkgs/jni/tool/wrapper_generators/logging.dart
new file mode 100644
index 0000000..386f5c6
--- /dev/null
+++ b/pkgs/jni/tool/wrapper_generators/logging.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2023, 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.
+
+import 'package:logging/logging.dart';
+
+final logger = Logger('ffi_wrappers_generator');
diff --git a/pkgs/jnigen/example/in_app_java/src/android_utils/android_utils.c b/pkgs/jnigen/example/in_app_java/src/android_utils/android_utils.c
index 65bbd7b..0fef652 100644
--- a/pkgs/jnigen/example/in_app_java/src/android_utils/android_utils.c
+++ b/pkgs/jnigen/example/in_app_java/src/android_utils/android_utils.c
@@ -5,12 +5,12 @@
 #include "jni.h"
 
 thread_local JNIEnv* jniEnv;
-JniContext jni;
+JniContext* jni;
 
-JniContext (*context_getter)(void);
+JniContext* (*context_getter)(void);
 JNIEnv* (*env_getter)(void);
 
-void setJniGetters(JniContext (*cg)(void), JNIEnv* (*eg)(void)) {
+void setJniGetters(JniContext* (*cg)(void), JNIEnv* (*eg)(void)) {
   context_getter = cg;
   env_getter = eg;
 }
@@ -24,17 +24,18 @@
                                   jobject text,
                                   int32_t duration) {
   load_env();
-  load_class_gr(&_c_AndroidUtils, "com/example/in_app_java/AndroidUtils");
+  load_class_global_ref(&_c_AndroidUtils,
+                        "com/example/in_app_java/AndroidUtils");
   if (_c_AndroidUtils == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_method(_c_AndroidUtils, &_m_AndroidUtils__showToast, "showToast",
                      "(Landroid/app/Activity;Ljava/lang/CharSequence;I)V");
   if (_m_AndroidUtils__showToast == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallStaticVoidMethod(jniEnv, _c_AndroidUtils,
                                   _m_AndroidUtils__showToast, mainActivity,
                                   text, duration);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 // androidx.emoji2.text.EmojiCompat
@@ -44,17 +45,17 @@
 FFI_PLUGIN_EXPORT
 JniResult EmojiCompat__init(jobject context) {
   load_env();
-  load_class_gr(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+  load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
   if (_c_EmojiCompat == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_method(
       _c_EmojiCompat, &_m_EmojiCompat__init, "init",
       "(Landroid/content/Context;)Landroidx/emoji2/text/EmojiCompat;");
   if (_m_EmojiCompat__init == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallStaticObjectMethod(
       jniEnv, _c_EmojiCompat, _m_EmojiCompat__init, context);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -62,18 +63,18 @@
 FFI_PLUGIN_EXPORT
 JniResult EmojiCompat__init1(jobject context, jobject defaultFactory) {
   load_env();
-  load_class_gr(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+  load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
   if (_c_EmojiCompat == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_method(_c_EmojiCompat, &_m_EmojiCompat__init1, "init",
                      "(Landroid/content/Context;Landroidx/emoji2/text/"
                      "DefaultEmojiCompatConfig$DefaultEmojiCompatConfigFactory;"
                      ")Landroidx/emoji2/text/EmojiCompat;");
   if (_m_EmojiCompat__init1 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallStaticObjectMethod(
       jniEnv, _c_EmojiCompat, _m_EmojiCompat__init1, context, defaultFactory);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -81,17 +82,17 @@
 FFI_PLUGIN_EXPORT
 JniResult EmojiCompat__init2(jobject config) {
   load_env();
-  load_class_gr(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+  load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
   if (_c_EmojiCompat == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_method(_c_EmojiCompat, &_m_EmojiCompat__init2, "init",
                      "(Landroidx/emoji2/text/EmojiCompat$Config;)Landroidx/"
                      "emoji2/text/EmojiCompat;");
   if (_m_EmojiCompat__init2 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallStaticObjectMethod(
       jniEnv, _c_EmojiCompat, _m_EmojiCompat__init2, config);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -99,33 +100,33 @@
 FFI_PLUGIN_EXPORT
 JniResult EmojiCompat__isConfigured() {
   load_env();
-  load_class_gr(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+  load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
   if (_c_EmojiCompat == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_method(_c_EmojiCompat, &_m_EmojiCompat__isConfigured,
                      "isConfigured", "()Z");
   if (_m_EmojiCompat__isConfigured == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   uint8_t _result = (*jniEnv)->CallStaticBooleanMethod(
       jniEnv, _c_EmojiCompat, _m_EmojiCompat__isConfigured);
-  return (JniResult){.result = {.z = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.z = _result}, .exception = check_exception()};
 }
 
 jmethodID _m_EmojiCompat__reset = NULL;
 FFI_PLUGIN_EXPORT
 JniResult EmojiCompat__reset(jobject config) {
   load_env();
-  load_class_gr(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+  load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
   if (_c_EmojiCompat == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_method(_c_EmojiCompat, &_m_EmojiCompat__reset, "reset",
                      "(Landroidx/emoji2/text/EmojiCompat$Config;)Landroidx/"
                      "emoji2/text/EmojiCompat;");
   if (_m_EmojiCompat__reset == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallStaticObjectMethod(
       jniEnv, _c_EmojiCompat, _m_EmojiCompat__reset, config);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -133,17 +134,17 @@
 FFI_PLUGIN_EXPORT
 JniResult EmojiCompat__reset1(jobject emojiCompat) {
   load_env();
-  load_class_gr(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+  load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
   if (_c_EmojiCompat == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_method(
       _c_EmojiCompat, &_m_EmojiCompat__reset1, "reset",
       "(Landroidx/emoji2/text/EmojiCompat;)Landroidx/emoji2/text/EmojiCompat;");
   if (_m_EmojiCompat__reset1 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallStaticObjectMethod(
       jniEnv, _c_EmojiCompat, _m_EmojiCompat__reset1, emojiCompat);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -151,34 +152,34 @@
 FFI_PLUGIN_EXPORT
 JniResult EmojiCompat__skipDefaultConfigurationLookup(uint8_t shouldSkip) {
   load_env();
-  load_class_gr(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+  load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
   if (_c_EmojiCompat == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_method(_c_EmojiCompat,
                      &_m_EmojiCompat__skipDefaultConfigurationLookup,
                      "skipDefaultConfigurationLookup", "(Z)V");
   if (_m_EmojiCompat__skipDefaultConfigurationLookup == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallStaticVoidMethod(
       jniEnv, _c_EmojiCompat, _m_EmojiCompat__skipDefaultConfigurationLookup,
       shouldSkip);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_EmojiCompat__get0 = NULL;
 FFI_PLUGIN_EXPORT
 JniResult EmojiCompat__get0() {
   load_env();
-  load_class_gr(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+  load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
   if (_c_EmojiCompat == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_method(_c_EmojiCompat, &_m_EmojiCompat__get0, "get",
                      "()Landroidx/emoji2/text/EmojiCompat;");
   if (_m_EmojiCompat__get0 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallStaticObjectMethod(jniEnv, _c_EmojiCompat,
                                                       _m_EmojiCompat__get0);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -186,14 +187,14 @@
 FFI_PLUGIN_EXPORT
 JniResult EmojiCompat__load(jobject self_) {
   load_env();
-  load_class_gr(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+  load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
   if (_c_EmojiCompat == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_EmojiCompat, &_m_EmojiCompat__load, "load", "()V");
   if (_m_EmojiCompat__load == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_EmojiCompat__load);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_EmojiCompat__registerInitCallback = NULL;
@@ -201,17 +202,17 @@
 JniResult EmojiCompat__registerInitCallback(jobject self_,
                                             jobject initCallback) {
   load_env();
-  load_class_gr(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+  load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
   if (_c_EmojiCompat == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_EmojiCompat, &_m_EmojiCompat__registerInitCallback,
               "registerInitCallback",
               "(Landroidx/emoji2/text/EmojiCompat$InitCallback;)V");
   if (_m_EmojiCompat__registerInitCallback == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_EmojiCompat__registerInitCallback,
                             initCallback);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_EmojiCompat__unregisterInitCallback = NULL;
@@ -219,65 +220,65 @@
 JniResult EmojiCompat__unregisterInitCallback(jobject self_,
                                               jobject initCallback) {
   load_env();
-  load_class_gr(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+  load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
   if (_c_EmojiCompat == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_EmojiCompat, &_m_EmojiCompat__unregisterInitCallback,
               "unregisterInitCallback",
               "(Landroidx/emoji2/text/EmojiCompat$InitCallback;)V");
   if (_m_EmojiCompat__unregisterInitCallback == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(
       jniEnv, self_, _m_EmojiCompat__unregisterInitCallback, initCallback);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_EmojiCompat__getLoadState = NULL;
 FFI_PLUGIN_EXPORT
 JniResult EmojiCompat__getLoadState(jobject self_) {
   load_env();
-  load_class_gr(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+  load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
   if (_c_EmojiCompat == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_EmojiCompat, &_m_EmojiCompat__getLoadState, "getLoadState",
               "()I");
   if (_m_EmojiCompat__getLoadState == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   int32_t _result =
       (*jniEnv)->CallIntMethod(jniEnv, self_, _m_EmojiCompat__getLoadState);
-  return (JniResult){.result = {.i = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.i = _result}, .exception = check_exception()};
 }
 
 jmethodID _m_EmojiCompat__isEmojiSpanIndicatorEnabled = NULL;
 FFI_PLUGIN_EXPORT
 JniResult EmojiCompat__isEmojiSpanIndicatorEnabled(jobject self_) {
   load_env();
-  load_class_gr(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+  load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
   if (_c_EmojiCompat == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_EmojiCompat, &_m_EmojiCompat__isEmojiSpanIndicatorEnabled,
               "isEmojiSpanIndicatorEnabled", "()Z");
   if (_m_EmojiCompat__isEmojiSpanIndicatorEnabled == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   uint8_t _result = (*jniEnv)->CallBooleanMethod(
       jniEnv, self_, _m_EmojiCompat__isEmojiSpanIndicatorEnabled);
-  return (JniResult){.result = {.z = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.z = _result}, .exception = check_exception()};
 }
 
 jmethodID _m_EmojiCompat__getEmojiSpanIndicatorColor = NULL;
 FFI_PLUGIN_EXPORT
 JniResult EmojiCompat__getEmojiSpanIndicatorColor(jobject self_) {
   load_env();
-  load_class_gr(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+  load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
   if (_c_EmojiCompat == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_EmojiCompat, &_m_EmojiCompat__getEmojiSpanIndicatorColor,
               "getEmojiSpanIndicatorColor", "()I");
   if (_m_EmojiCompat__getEmojiSpanIndicatorColor == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   int32_t _result = (*jniEnv)->CallIntMethod(
       jniEnv, self_, _m_EmojiCompat__getEmojiSpanIndicatorColor);
-  return (JniResult){.result = {.i = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.i = _result}, .exception = check_exception()};
 }
 
 jmethodID _m_EmojiCompat__getEmojiStart = NULL;
@@ -286,16 +287,16 @@
                                      jobject charSequence,
                                      int32_t offset) {
   load_env();
-  load_class_gr(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+  load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
   if (_c_EmojiCompat == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_EmojiCompat, &_m_EmojiCompat__getEmojiStart, "getEmojiStart",
               "(Ljava/lang/CharSequence;I)I");
   if (_m_EmojiCompat__getEmojiStart == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   int32_t _result = (*jniEnv)->CallIntMethod(
       jniEnv, self_, _m_EmojiCompat__getEmojiStart, charSequence, offset);
-  return (JniResult){.result = {.i = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.i = _result}, .exception = check_exception()};
 }
 
 jmethodID _m_EmojiCompat__getEmojiEnd = NULL;
@@ -304,16 +305,16 @@
                                    jobject charSequence,
                                    int32_t offset) {
   load_env();
-  load_class_gr(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+  load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
   if (_c_EmojiCompat == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_EmojiCompat, &_m_EmojiCompat__getEmojiEnd, "getEmojiEnd",
               "(Ljava/lang/CharSequence;I)I");
   if (_m_EmojiCompat__getEmojiEnd == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   int32_t _result = (*jniEnv)->CallIntMethod(
       jniEnv, self_, _m_EmojiCompat__getEmojiEnd, charSequence, offset);
-  return (JniResult){.result = {.i = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.i = _result}, .exception = check_exception()};
 }
 
 jmethodID _m_EmojiCompat__handleOnKeyDown = NULL;
@@ -322,18 +323,18 @@
                                        int32_t keyCode,
                                        jobject event) {
   load_env();
-  load_class_gr(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+  load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
   if (_c_EmojiCompat == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_method(_c_EmojiCompat, &_m_EmojiCompat__handleOnKeyDown,
                      "handleOnKeyDown",
                      "(Landroid/text/Editable;ILandroid/view/KeyEvent;)Z");
   if (_m_EmojiCompat__handleOnKeyDown == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   uint8_t _result = (*jniEnv)->CallStaticBooleanMethod(
       jniEnv, _c_EmojiCompat, _m_EmojiCompat__handleOnKeyDown, editable,
       keyCode, event);
-  return (JniResult){.result = {.z = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.z = _result}, .exception = check_exception()};
 }
 
 jmethodID _m_EmojiCompat__handleDeleteSurroundingText = NULL;
@@ -344,36 +345,36 @@
                                                    int32_t afterLength,
                                                    uint8_t inCodePoints) {
   load_env();
-  load_class_gr(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+  load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
   if (_c_EmojiCompat == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_method(_c_EmojiCompat,
                      &_m_EmojiCompat__handleDeleteSurroundingText,
                      "handleDeleteSurroundingText",
                      "(Landroid/view/inputmethod/InputConnection;Landroid/text/"
                      "Editable;IIZ)Z");
   if (_m_EmojiCompat__handleDeleteSurroundingText == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   uint8_t _result = (*jniEnv)->CallStaticBooleanMethod(
       jniEnv, _c_EmojiCompat, _m_EmojiCompat__handleDeleteSurroundingText,
       inputConnection, editable, beforeLength, afterLength, inCodePoints);
-  return (JniResult){.result = {.z = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.z = _result}, .exception = check_exception()};
 }
 
 jmethodID _m_EmojiCompat__hasEmojiGlyph = NULL;
 FFI_PLUGIN_EXPORT
 JniResult EmojiCompat__hasEmojiGlyph(jobject self_, jobject sequence) {
   load_env();
-  load_class_gr(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+  load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
   if (_c_EmojiCompat == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_EmojiCompat, &_m_EmojiCompat__hasEmojiGlyph, "hasEmojiGlyph",
               "(Ljava/lang/CharSequence;)Z");
   if (_m_EmojiCompat__hasEmojiGlyph == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   uint8_t _result = (*jniEnv)->CallBooleanMethod(
       jniEnv, self_, _m_EmojiCompat__hasEmojiGlyph, sequence);
-  return (JniResult){.result = {.z = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.z = _result}, .exception = check_exception()};
 }
 
 jmethodID _m_EmojiCompat__hasEmojiGlyph1 = NULL;
@@ -382,16 +383,16 @@
                                       jobject sequence,
                                       int32_t metadataVersion) {
   load_env();
-  load_class_gr(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+  load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
   if (_c_EmojiCompat == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_EmojiCompat, &_m_EmojiCompat__hasEmojiGlyph1, "hasEmojiGlyph",
               "(Ljava/lang/CharSequence;I)Z");
   if (_m_EmojiCompat__hasEmojiGlyph1 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   uint8_t _result = (*jniEnv)->CallBooleanMethod(
       jniEnv, self_, _m_EmojiCompat__hasEmojiGlyph1, sequence, metadataVersion);
-  return (JniResult){.result = {.z = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.z = _result}, .exception = check_exception()};
 }
 
 jmethodID _m_EmojiCompat__getEmojiMatch = NULL;
@@ -400,32 +401,32 @@
                                      jobject sequence,
                                      int32_t metadataVersion) {
   load_env();
-  load_class_gr(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+  load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
   if (_c_EmojiCompat == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_EmojiCompat, &_m_EmojiCompat__getEmojiMatch, "getEmojiMatch",
               "(Ljava/lang/CharSequence;I)I");
   if (_m_EmojiCompat__getEmojiMatch == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   int32_t _result = (*jniEnv)->CallIntMethod(
       jniEnv, self_, _m_EmojiCompat__getEmojiMatch, sequence, metadataVersion);
-  return (JniResult){.result = {.i = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.i = _result}, .exception = check_exception()};
 }
 
 jmethodID _m_EmojiCompat__process = NULL;
 FFI_PLUGIN_EXPORT
 JniResult EmojiCompat__process(jobject self_, jobject charSequence) {
   load_env();
-  load_class_gr(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+  load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
   if (_c_EmojiCompat == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_EmojiCompat, &_m_EmojiCompat__process, "process",
               "(Ljava/lang/CharSequence;)Ljava/lang/CharSequence;");
   if (_m_EmojiCompat__process == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_EmojiCompat__process, charSequence);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -436,16 +437,16 @@
                                 int32_t start,
                                 int32_t end) {
   load_env();
-  load_class_gr(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+  load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
   if (_c_EmojiCompat == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_EmojiCompat, &_m_EmojiCompat__process1, "process",
               "(Ljava/lang/CharSequence;II)Ljava/lang/CharSequence;");
   if (_m_EmojiCompat__process1 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_EmojiCompat__process1, charSequence, start, end);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -457,17 +458,17 @@
                                 int32_t end,
                                 int32_t maxEmojiCount) {
   load_env();
-  load_class_gr(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+  load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
   if (_c_EmojiCompat == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_EmojiCompat, &_m_EmojiCompat__process2, "process",
               "(Ljava/lang/CharSequence;III)Ljava/lang/CharSequence;");
   if (_m_EmojiCompat__process2 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result =
       (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_EmojiCompat__process2,
                                   charSequence, start, end, maxEmojiCount);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -480,17 +481,17 @@
                                 int32_t maxEmojiCount,
                                 int32_t replaceStrategy) {
   load_env();
-  load_class_gr(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+  load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
   if (_c_EmojiCompat == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_EmojiCompat, &_m_EmojiCompat__process3, "process",
               "(Ljava/lang/CharSequence;IIII)Ljava/lang/CharSequence;");
   if (_m_EmojiCompat__process3 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_EmojiCompat__process3, charSequence, start, end,
       maxEmojiCount, replaceStrategy);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -498,16 +499,16 @@
 FFI_PLUGIN_EXPORT
 JniResult EmojiCompat__getAssetSignature(jobject self_) {
   load_env();
-  load_class_gr(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+  load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
   if (_c_EmojiCompat == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_EmojiCompat, &_m_EmojiCompat__getAssetSignature,
               "getAssetSignature", "()Ljava/lang/String;");
   if (_m_EmojiCompat__getAssetSignature == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_EmojiCompat__getAssetSignature);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -515,16 +516,16 @@
 FFI_PLUGIN_EXPORT
 JniResult EmojiCompat__updateEditorInfo(jobject self_, jobject outAttrs) {
   load_env();
-  load_class_gr(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+  load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
   if (_c_EmojiCompat == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_EmojiCompat, &_m_EmojiCompat__updateEditorInfo,
               "updateEditorInfo", "(Landroid/view/inputmethod/EditorInfo;)V");
   if (_m_EmojiCompat__updateEditorInfo == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_EmojiCompat__updateEditorInfo,
                             outAttrs);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 // androidx.emoji2.text.EmojiCompat$Config
@@ -534,18 +535,18 @@
 FFI_PLUGIN_EXPORT
 JniResult EmojiCompat_Config__ctor(jobject metadataLoader) {
   load_env();
-  load_class_gr(&_c_EmojiCompat_Config,
-                "androidx/emoji2/text/EmojiCompat$Config");
+  load_class_global_ref(&_c_EmojiCompat_Config,
+                        "androidx/emoji2/text/EmojiCompat$Config");
   if (_c_EmojiCompat_Config == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_EmojiCompat_Config, &_m_EmojiCompat_Config__ctor, "<init>",
               "(Landroidx/emoji2/text/EmojiCompat$MetadataRepoLoader;)V");
   if (_m_EmojiCompat_Config__ctor == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result =
       (*jniEnv)->NewObject(jniEnv, _c_EmojiCompat_Config,
                            _m_EmojiCompat_Config__ctor, metadataLoader);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -554,20 +555,20 @@
 JniResult EmojiCompat_Config__registerInitCallback(jobject self_,
                                                    jobject initCallback) {
   load_env();
-  load_class_gr(&_c_EmojiCompat_Config,
-                "androidx/emoji2/text/EmojiCompat$Config");
+  load_class_global_ref(&_c_EmojiCompat_Config,
+                        "androidx/emoji2/text/EmojiCompat$Config");
   if (_c_EmojiCompat_Config == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_EmojiCompat_Config,
               &_m_EmojiCompat_Config__registerInitCallback,
               "registerInitCallback",
               "(Landroidx/emoji2/text/EmojiCompat$InitCallback;)Landroidx/"
               "emoji2/text/EmojiCompat$Config;");
   if (_m_EmojiCompat_Config__registerInitCallback == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_EmojiCompat_Config__registerInitCallback, initCallback);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -576,21 +577,21 @@
 JniResult EmojiCompat_Config__unregisterInitCallback(jobject self_,
                                                      jobject initCallback) {
   load_env();
-  load_class_gr(&_c_EmojiCompat_Config,
-                "androidx/emoji2/text/EmojiCompat$Config");
+  load_class_global_ref(&_c_EmojiCompat_Config,
+                        "androidx/emoji2/text/EmojiCompat$Config");
   if (_c_EmojiCompat_Config == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_EmojiCompat_Config,
               &_m_EmojiCompat_Config__unregisterInitCallback,
               "unregisterInitCallback",
               "(Landroidx/emoji2/text/EmojiCompat$InitCallback;)Landroidx/"
               "emoji2/text/EmojiCompat$Config;");
   if (_m_EmojiCompat_Config__unregisterInitCallback == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_EmojiCompat_Config__unregisterInitCallback,
       initCallback);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -598,17 +599,17 @@
 FFI_PLUGIN_EXPORT
 JniResult EmojiCompat_Config__setReplaceAll(jobject self_, uint8_t replaceAll) {
   load_env();
-  load_class_gr(&_c_EmojiCompat_Config,
-                "androidx/emoji2/text/EmojiCompat$Config");
+  load_class_global_ref(&_c_EmojiCompat_Config,
+                        "androidx/emoji2/text/EmojiCompat$Config");
   if (_c_EmojiCompat_Config == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_EmojiCompat_Config, &_m_EmojiCompat_Config__setReplaceAll,
               "setReplaceAll", "(Z)Landroidx/emoji2/text/EmojiCompat$Config;");
   if (_m_EmojiCompat_Config__setReplaceAll == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_EmojiCompat_Config__setReplaceAll, replaceAll);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -618,20 +619,20 @@
     jobject self_,
     uint8_t useEmojiAsDefaultStyle) {
   load_env();
-  load_class_gr(&_c_EmojiCompat_Config,
-                "androidx/emoji2/text/EmojiCompat$Config");
+  load_class_global_ref(&_c_EmojiCompat_Config,
+                        "androidx/emoji2/text/EmojiCompat$Config");
   if (_c_EmojiCompat_Config == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_EmojiCompat_Config,
               &_m_EmojiCompat_Config__setUseEmojiAsDefaultStyle,
               "setUseEmojiAsDefaultStyle",
               "(Z)Landroidx/emoji2/text/EmojiCompat$Config;");
   if (_m_EmojiCompat_Config__setUseEmojiAsDefaultStyle == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_EmojiCompat_Config__setUseEmojiAsDefaultStyle,
       useEmojiAsDefaultStyle);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -642,20 +643,20 @@
     uint8_t useEmojiAsDefaultStyle,
     jobject emojiAsDefaultStyleExceptions) {
   load_env();
-  load_class_gr(&_c_EmojiCompat_Config,
-                "androidx/emoji2/text/EmojiCompat$Config");
+  load_class_global_ref(&_c_EmojiCompat_Config,
+                        "androidx/emoji2/text/EmojiCompat$Config");
   if (_c_EmojiCompat_Config == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_EmojiCompat_Config,
               &_m_EmojiCompat_Config__setUseEmojiAsDefaultStyle1,
               "setUseEmojiAsDefaultStyle",
               "(ZLjava/util/List;)Landroidx/emoji2/text/EmojiCompat$Config;");
   if (_m_EmojiCompat_Config__setUseEmojiAsDefaultStyle1 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_EmojiCompat_Config__setUseEmojiAsDefaultStyle1,
       useEmojiAsDefaultStyle, emojiAsDefaultStyleExceptions);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -665,20 +666,20 @@
     jobject self_,
     uint8_t emojiSpanIndicatorEnabled) {
   load_env();
-  load_class_gr(&_c_EmojiCompat_Config,
-                "androidx/emoji2/text/EmojiCompat$Config");
+  load_class_global_ref(&_c_EmojiCompat_Config,
+                        "androidx/emoji2/text/EmojiCompat$Config");
   if (_c_EmojiCompat_Config == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_EmojiCompat_Config,
               &_m_EmojiCompat_Config__setEmojiSpanIndicatorEnabled,
               "setEmojiSpanIndicatorEnabled",
               "(Z)Landroidx/emoji2/text/EmojiCompat$Config;");
   if (_m_EmojiCompat_Config__setEmojiSpanIndicatorEnabled == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_EmojiCompat_Config__setEmojiSpanIndicatorEnabled,
       emojiSpanIndicatorEnabled);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -687,19 +688,19 @@
 JniResult EmojiCompat_Config__setEmojiSpanIndicatorColor(jobject self_,
                                                          int32_t color) {
   load_env();
-  load_class_gr(&_c_EmojiCompat_Config,
-                "androidx/emoji2/text/EmojiCompat$Config");
+  load_class_global_ref(&_c_EmojiCompat_Config,
+                        "androidx/emoji2/text/EmojiCompat$Config");
   if (_c_EmojiCompat_Config == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_EmojiCompat_Config,
               &_m_EmojiCompat_Config__setEmojiSpanIndicatorColor,
               "setEmojiSpanIndicatorColor",
               "(I)Landroidx/emoji2/text/EmojiCompat$Config;");
   if (_m_EmojiCompat_Config__setEmojiSpanIndicatorColor == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_EmojiCompat_Config__setEmojiSpanIndicatorColor, color);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -708,19 +709,19 @@
 JniResult EmojiCompat_Config__setMetadataLoadStrategy(jobject self_,
                                                       int32_t strategy) {
   load_env();
-  load_class_gr(&_c_EmojiCompat_Config,
-                "androidx/emoji2/text/EmojiCompat$Config");
+  load_class_global_ref(&_c_EmojiCompat_Config,
+                        "androidx/emoji2/text/EmojiCompat$Config");
   if (_c_EmojiCompat_Config == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_EmojiCompat_Config,
               &_m_EmojiCompat_Config__setMetadataLoadStrategy,
               "setMetadataLoadStrategy",
               "(I)Landroidx/emoji2/text/EmojiCompat$Config;");
   if (_m_EmojiCompat_Config__setMetadataLoadStrategy == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_EmojiCompat_Config__setMetadataLoadStrategy, strategy);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -728,19 +729,19 @@
 FFI_PLUGIN_EXPORT
 JniResult EmojiCompat_Config__setSpanFactory(jobject self_, jobject factory) {
   load_env();
-  load_class_gr(&_c_EmojiCompat_Config,
-                "androidx/emoji2/text/EmojiCompat$Config");
+  load_class_global_ref(&_c_EmojiCompat_Config,
+                        "androidx/emoji2/text/EmojiCompat$Config");
   if (_c_EmojiCompat_Config == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_EmojiCompat_Config, &_m_EmojiCompat_Config__setSpanFactory,
               "setSpanFactory",
               "(Landroidx/emoji2/text/EmojiCompat$SpanFactory;)Landroidx/"
               "emoji2/text/EmojiCompat$Config;");
   if (_m_EmojiCompat_Config__setSpanFactory == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_EmojiCompat_Config__setSpanFactory, factory);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -749,19 +750,19 @@
 JniResult EmojiCompat_Config__setGlyphChecker(jobject self_,
                                               jobject glyphChecker) {
   load_env();
-  load_class_gr(&_c_EmojiCompat_Config,
-                "androidx/emoji2/text/EmojiCompat$Config");
+  load_class_global_ref(&_c_EmojiCompat_Config,
+                        "androidx/emoji2/text/EmojiCompat$Config");
   if (_c_EmojiCompat_Config == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_EmojiCompat_Config, &_m_EmojiCompat_Config__setGlyphChecker,
               "setGlyphChecker",
               "(Landroidx/emoji2/text/EmojiCompat$GlyphChecker;)Landroidx/"
               "emoji2/text/EmojiCompat$Config;");
   if (_m_EmojiCompat_Config__setGlyphChecker == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_EmojiCompat_Config__setGlyphChecker, glyphChecker);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -769,19 +770,19 @@
 FFI_PLUGIN_EXPORT
 JniResult EmojiCompat_Config__getMetadataRepoLoader(jobject self_) {
   load_env();
-  load_class_gr(&_c_EmojiCompat_Config,
-                "androidx/emoji2/text/EmojiCompat$Config");
+  load_class_global_ref(&_c_EmojiCompat_Config,
+                        "androidx/emoji2/text/EmojiCompat$Config");
   if (_c_EmojiCompat_Config == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_EmojiCompat_Config,
               &_m_EmojiCompat_Config__getMetadataRepoLoader,
               "getMetadataRepoLoader",
               "()Landroidx/emoji2/text/EmojiCompat$MetadataRepoLoader;");
   if (_m_EmojiCompat_Config__getMetadataRepoLoader == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_EmojiCompat_Config__getMetadataRepoLoader);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -792,19 +793,20 @@
 FFI_PLUGIN_EXPORT
 JniResult EmojiCompat_MetadataRepoLoaderCallback__ctor() {
   load_env();
-  load_class_gr(&_c_EmojiCompat_MetadataRepoLoaderCallback,
-                "androidx/emoji2/text/EmojiCompat$MetadataRepoLoaderCallback");
+  load_class_global_ref(
+      &_c_EmojiCompat_MetadataRepoLoaderCallback,
+      "androidx/emoji2/text/EmojiCompat$MetadataRepoLoaderCallback");
   if (_c_EmojiCompat_MetadataRepoLoaderCallback == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_EmojiCompat_MetadataRepoLoaderCallback,
               &_m_EmojiCompat_MetadataRepoLoaderCallback__ctor, "<init>",
               "()V");
   if (_m_EmojiCompat_MetadataRepoLoaderCallback__ctor == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result =
       (*jniEnv)->NewObject(jniEnv, _c_EmojiCompat_MetadataRepoLoaderCallback,
                            _m_EmojiCompat_MetadataRepoLoaderCallback__ctor);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -814,19 +816,20 @@
     jobject self_,
     jobject metadataRepo) {
   load_env();
-  load_class_gr(&_c_EmojiCompat_MetadataRepoLoaderCallback,
-                "androidx/emoji2/text/EmojiCompat$MetadataRepoLoaderCallback");
+  load_class_global_ref(
+      &_c_EmojiCompat_MetadataRepoLoaderCallback,
+      "androidx/emoji2/text/EmojiCompat$MetadataRepoLoaderCallback");
   if (_c_EmojiCompat_MetadataRepoLoaderCallback == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_EmojiCompat_MetadataRepoLoaderCallback,
               &_m_EmojiCompat_MetadataRepoLoaderCallback__onLoaded, "onLoaded",
               "(Landroidx/emoji2/text/MetadataRepo;)V");
   if (_m_EmojiCompat_MetadataRepoLoaderCallback__onLoaded == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_,
                             _m_EmojiCompat_MetadataRepoLoaderCallback__onLoaded,
                             metadataRepo);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_EmojiCompat_MetadataRepoLoaderCallback__onFailed = NULL;
@@ -834,19 +837,20 @@
 JniResult EmojiCompat_MetadataRepoLoaderCallback__onFailed(jobject self_,
                                                            jobject throwable) {
   load_env();
-  load_class_gr(&_c_EmojiCompat_MetadataRepoLoaderCallback,
-                "androidx/emoji2/text/EmojiCompat$MetadataRepoLoaderCallback");
+  load_class_global_ref(
+      &_c_EmojiCompat_MetadataRepoLoaderCallback,
+      "androidx/emoji2/text/EmojiCompat$MetadataRepoLoaderCallback");
   if (_c_EmojiCompat_MetadataRepoLoaderCallback == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_EmojiCompat_MetadataRepoLoaderCallback,
               &_m_EmojiCompat_MetadataRepoLoaderCallback__onFailed, "onFailed",
               "(Ljava/lang/Throwable;)V");
   if (_m_EmojiCompat_MetadataRepoLoaderCallback__onFailed == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_,
                             _m_EmojiCompat_MetadataRepoLoaderCallback__onFailed,
                             throwable);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 // androidx.emoji2.text.EmojiCompat$GlyphChecker
@@ -860,19 +864,19 @@
                                              int32_t end,
                                              int32_t sdkAdded) {
   load_env();
-  load_class_gr(&_c_EmojiCompat_GlyphChecker,
-                "androidx/emoji2/text/EmojiCompat$GlyphChecker");
+  load_class_global_ref(&_c_EmojiCompat_GlyphChecker,
+                        "androidx/emoji2/text/EmojiCompat$GlyphChecker");
   if (_c_EmojiCompat_GlyphChecker == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_EmojiCompat_GlyphChecker,
               &_m_EmojiCompat_GlyphChecker__hasGlyph, "hasGlyph",
               "(Ljava/lang/CharSequence;III)Z");
   if (_m_EmojiCompat_GlyphChecker__hasGlyph == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   uint8_t _result = (*jniEnv)->CallBooleanMethod(
       jniEnv, self_, _m_EmojiCompat_GlyphChecker__hasGlyph, charSequence, start,
       end, sdkAdded);
-  return (JniResult){.result = {.z = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.z = _result}, .exception = check_exception()};
 }
 
 // androidx.emoji2.text.EmojiCompat$MetadataRepoLoader
@@ -883,19 +887,19 @@
 JniResult EmojiCompat_MetadataRepoLoader__load(jobject self_,
                                                jobject loaderCallback) {
   load_env();
-  load_class_gr(&_c_EmojiCompat_MetadataRepoLoader,
-                "androidx/emoji2/text/EmojiCompat$MetadataRepoLoader");
+  load_class_global_ref(&_c_EmojiCompat_MetadataRepoLoader,
+                        "androidx/emoji2/text/EmojiCompat$MetadataRepoLoader");
   if (_c_EmojiCompat_MetadataRepoLoader == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(
       _c_EmojiCompat_MetadataRepoLoader,
       &_m_EmojiCompat_MetadataRepoLoader__load, "load",
       "(Landroidx/emoji2/text/EmojiCompat$MetadataRepoLoaderCallback;)V");
   if (_m_EmojiCompat_MetadataRepoLoader__load == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(
       jniEnv, self_, _m_EmojiCompat_MetadataRepoLoader__load, loaderCallback);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 // androidx.emoji2.text.EmojiCompat$InitCallback
@@ -905,17 +909,17 @@
 FFI_PLUGIN_EXPORT
 JniResult EmojiCompat_InitCallback__ctor() {
   load_env();
-  load_class_gr(&_c_EmojiCompat_InitCallback,
-                "androidx/emoji2/text/EmojiCompat$InitCallback");
+  load_class_global_ref(&_c_EmojiCompat_InitCallback,
+                        "androidx/emoji2/text/EmojiCompat$InitCallback");
   if (_c_EmojiCompat_InitCallback == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_EmojiCompat_InitCallback, &_m_EmojiCompat_InitCallback__ctor,
               "<init>", "()V");
   if (_m_EmojiCompat_InitCallback__ctor == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->NewObject(jniEnv, _c_EmojiCompat_InitCallback,
                                          _m_EmojiCompat_InitCallback__ctor);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -923,36 +927,36 @@
 FFI_PLUGIN_EXPORT
 JniResult EmojiCompat_InitCallback__onInitialized(jobject self_) {
   load_env();
-  load_class_gr(&_c_EmojiCompat_InitCallback,
-                "androidx/emoji2/text/EmojiCompat$InitCallback");
+  load_class_global_ref(&_c_EmojiCompat_InitCallback,
+                        "androidx/emoji2/text/EmojiCompat$InitCallback");
   if (_c_EmojiCompat_InitCallback == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_EmojiCompat_InitCallback,
               &_m_EmojiCompat_InitCallback__onInitialized, "onInitialized",
               "()V");
   if (_m_EmojiCompat_InitCallback__onInitialized == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_,
                             _m_EmojiCompat_InitCallback__onInitialized);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_EmojiCompat_InitCallback__onFailed = NULL;
 FFI_PLUGIN_EXPORT
 JniResult EmojiCompat_InitCallback__onFailed(jobject self_, jobject throwable) {
   load_env();
-  load_class_gr(&_c_EmojiCompat_InitCallback,
-                "androidx/emoji2/text/EmojiCompat$InitCallback");
+  load_class_global_ref(&_c_EmojiCompat_InitCallback,
+                        "androidx/emoji2/text/EmojiCompat$InitCallback");
   if (_c_EmojiCompat_InitCallback == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_EmojiCompat_InitCallback,
               &_m_EmojiCompat_InitCallback__onFailed, "onFailed",
               "(Ljava/lang/Throwable;)V");
   if (_m_EmojiCompat_InitCallback__onFailed == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_,
                             _m_EmojiCompat_InitCallback__onFailed, throwable);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 // androidx.emoji2.text.EmojiCompat$DefaultSpanFactory
@@ -962,18 +966,18 @@
 FFI_PLUGIN_EXPORT
 JniResult EmojiCompat_DefaultSpanFactory__ctor() {
   load_env();
-  load_class_gr(&_c_EmojiCompat_DefaultSpanFactory,
-                "androidx/emoji2/text/EmojiCompat$DefaultSpanFactory");
+  load_class_global_ref(&_c_EmojiCompat_DefaultSpanFactory,
+                        "androidx/emoji2/text/EmojiCompat$DefaultSpanFactory");
   if (_c_EmojiCompat_DefaultSpanFactory == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_EmojiCompat_DefaultSpanFactory,
               &_m_EmojiCompat_DefaultSpanFactory__ctor, "<init>", "()V");
   if (_m_EmojiCompat_DefaultSpanFactory__ctor == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result =
       (*jniEnv)->NewObject(jniEnv, _c_EmojiCompat_DefaultSpanFactory,
                            _m_EmojiCompat_DefaultSpanFactory__ctor);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -982,19 +986,19 @@
 JniResult EmojiCompat_DefaultSpanFactory__createSpan(jobject self_,
                                                      jobject rasterizer) {
   load_env();
-  load_class_gr(&_c_EmojiCompat_DefaultSpanFactory,
-                "androidx/emoji2/text/EmojiCompat$DefaultSpanFactory");
+  load_class_global_ref(&_c_EmojiCompat_DefaultSpanFactory,
+                        "androidx/emoji2/text/EmojiCompat$DefaultSpanFactory");
   if (_c_EmojiCompat_DefaultSpanFactory == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_EmojiCompat_DefaultSpanFactory,
               &_m_EmojiCompat_DefaultSpanFactory__createSpan, "createSpan",
               "(Landroidx/emoji2/text/TypefaceEmojiRasterizer;)Landroidx/"
               "emoji2/text/EmojiSpan;");
   if (_m_EmojiCompat_DefaultSpanFactory__createSpan == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_EmojiCompat_DefaultSpanFactory__createSpan, rasterizer);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1006,19 +1010,19 @@
 JniResult EmojiCompat_SpanFactory__createSpan(jobject self_,
                                               jobject rasterizer) {
   load_env();
-  load_class_gr(&_c_EmojiCompat_SpanFactory,
-                "androidx/emoji2/text/EmojiCompat$SpanFactory");
+  load_class_global_ref(&_c_EmojiCompat_SpanFactory,
+                        "androidx/emoji2/text/EmojiCompat$SpanFactory");
   if (_c_EmojiCompat_SpanFactory == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_EmojiCompat_SpanFactory,
               &_m_EmojiCompat_SpanFactory__createSpan, "createSpan",
               "(Landroidx/emoji2/text/TypefaceEmojiRasterizer;)Landroidx/"
               "emoji2/text/EmojiSpan;");
   if (_m_EmojiCompat_SpanFactory__createSpan == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_EmojiCompat_SpanFactory__createSpan, rasterizer);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1029,20 +1033,20 @@
 FFI_PLUGIN_EXPORT
 JniResult DefaultEmojiCompatConfig__create(jobject context) {
   load_env();
-  load_class_gr(&_c_DefaultEmojiCompatConfig,
-                "androidx/emoji2/text/DefaultEmojiCompatConfig");
+  load_class_global_ref(&_c_DefaultEmojiCompatConfig,
+                        "androidx/emoji2/text/DefaultEmojiCompatConfig");
   if (_c_DefaultEmojiCompatConfig == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_method(_c_DefaultEmojiCompatConfig,
                      &_m_DefaultEmojiCompatConfig__create, "create",
                      "(Landroid/content/Context;)Landroidx/emoji2/text/"
                      "FontRequestEmojiCompatConfig;");
   if (_m_DefaultEmojiCompatConfig__create == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallStaticObjectMethod(
       jniEnv, _c_DefaultEmojiCompatConfig, _m_DefaultEmojiCompatConfig__create,
       context);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1056,23 +1060,23 @@
 JniResult
 DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28__ctor() {
   load_env();
-  load_class_gr(
+  load_class_global_ref(
       &_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28,
       "androidx/emoji2/text/"
       "DefaultEmojiCompatConfig$DefaultEmojiCompatConfigHelper_API28");
   if (_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(
       _c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28,
       &_m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28__ctor,
       "<init>", "()V");
   if (_m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28__ctor ==
       NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->NewObject(
       jniEnv, _c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28,
       _m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28__ctor);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1086,12 +1090,12 @@
     jobject packageManager,
     jobject providerPackage) {
   load_env();
-  load_class_gr(
+  load_class_global_ref(
       &_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28,
       "androidx/emoji2/text/"
       "DefaultEmojiCompatConfig$DefaultEmojiCompatConfigHelper_API28");
   if (_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(
       _c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28,
       &_m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28__getSigningSignatures1,
@@ -1100,12 +1104,12 @@
       "content/pm/Signature;");
   if (_m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28__getSigningSignatures1 ==
       NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_,
       _m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28__getSigningSignatures1,
       packageManager, providerPackage);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1119,23 +1123,23 @@
 JniResult
 DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19__ctor() {
   load_env();
-  load_class_gr(
+  load_class_global_ref(
       &_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19,
       "androidx/emoji2/text/"
       "DefaultEmojiCompatConfig$DefaultEmojiCompatConfigHelper_API19");
   if (_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(
       _c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19,
       &_m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19__ctor,
       "<init>", "()V");
   if (_m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19__ctor ==
       NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->NewObject(
       jniEnv, _c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19,
       _m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19__ctor);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1150,12 +1154,12 @@
     jobject intent,
     int32_t flags) {
   load_env();
-  load_class_gr(
+  load_class_global_ref(
       &_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19,
       "androidx/emoji2/text/"
       "DefaultEmojiCompatConfig$DefaultEmojiCompatConfigHelper_API19");
   if (_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(
       _c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19,
       &_m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19__queryIntentContentProviders,
@@ -1164,12 +1168,12 @@
       "util/List;");
   if (_m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19__queryIntentContentProviders ==
       NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_,
       _m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19__queryIntentContentProviders,
       packageManager, intent, flags);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1182,12 +1186,12 @@
     jobject self_,
     jobject resolveInfo) {
   load_env();
-  load_class_gr(
+  load_class_global_ref(
       &_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19,
       "androidx/emoji2/text/"
       "DefaultEmojiCompatConfig$DefaultEmojiCompatConfigHelper_API19");
   if (_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(
       _c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19,
       &_m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19__getProviderInfo,
@@ -1195,12 +1199,12 @@
       "(Landroid/content/pm/ResolveInfo;)Landroid/content/pm/ProviderInfo;");
   if (_m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19__getProviderInfo ==
       NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_,
       _m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19__getProviderInfo,
       resolveInfo);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1212,20 +1216,21 @@
 FFI_PLUGIN_EXPORT
 JniResult DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper__ctor() {
   load_env();
-  load_class_gr(&_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper,
-                "androidx/emoji2/text/"
-                "DefaultEmojiCompatConfig$DefaultEmojiCompatConfigHelper");
+  load_class_global_ref(
+      &_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper,
+      "androidx/emoji2/text/"
+      "DefaultEmojiCompatConfig$DefaultEmojiCompatConfigHelper");
   if (_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper,
               &_m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper__ctor,
               "<init>", "()V");
   if (_m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper__ctor == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->NewObject(
       jniEnv, _c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper,
       _m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper__ctor);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1239,11 +1244,12 @@
     jobject packageManager,
     jobject providerPackage) {
   load_env();
-  load_class_gr(&_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper,
-                "androidx/emoji2/text/"
-                "DefaultEmojiCompatConfig$DefaultEmojiCompatConfigHelper");
+  load_class_global_ref(
+      &_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper,
+      "androidx/emoji2/text/"
+      "DefaultEmojiCompatConfig$DefaultEmojiCompatConfigHelper");
   if (_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(
       _c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper,
       &_m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper__getSigningSignatures,
@@ -1252,12 +1258,12 @@
       "content/pm/Signature;");
   if (_m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper__getSigningSignatures ==
       NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_,
       _m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper__getSigningSignatures,
       packageManager, providerPackage);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1272,11 +1278,12 @@
     jobject intent,
     int32_t flags) {
   load_env();
-  load_class_gr(&_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper,
-                "androidx/emoji2/text/"
-                "DefaultEmojiCompatConfig$DefaultEmojiCompatConfigHelper");
+  load_class_global_ref(
+      &_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper,
+      "androidx/emoji2/text/"
+      "DefaultEmojiCompatConfig$DefaultEmojiCompatConfigHelper");
   if (_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(
       _c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper,
       &_m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper__queryIntentContentProviders,
@@ -1285,12 +1292,12 @@
       "util/List;");
   if (_m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper__queryIntentContentProviders ==
       NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_,
       _m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper__queryIntentContentProviders,
       packageManager, intent, flags);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1303,11 +1310,12 @@
     jobject self_,
     jobject resolveInfo) {
   load_env();
-  load_class_gr(&_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper,
-                "androidx/emoji2/text/"
-                "DefaultEmojiCompatConfig$DefaultEmojiCompatConfigHelper");
+  load_class_global_ref(
+      &_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper,
+      "androidx/emoji2/text/"
+      "DefaultEmojiCompatConfig$DefaultEmojiCompatConfigHelper");
   if (_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(
       _c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper,
       &_m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper__getProviderInfo,
@@ -1315,12 +1323,12 @@
       "(Landroid/content/pm/ResolveInfo;)Landroid/content/pm/ProviderInfo;");
   if (_m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper__getProviderInfo ==
       NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_,
       _m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper__getProviderInfo,
       resolveInfo);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1333,11 +1341,12 @@
 JniResult DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory__ctor(
     jobject helper) {
   load_env();
-  load_class_gr(&_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory,
-                "androidx/emoji2/text/"
-                "DefaultEmojiCompatConfig$DefaultEmojiCompatConfigFactory");
+  load_class_global_ref(
+      &_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory,
+      "androidx/emoji2/text/"
+      "DefaultEmojiCompatConfig$DefaultEmojiCompatConfigFactory");
   if (_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(
       _c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory,
       &_m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory__ctor,
@@ -1345,12 +1354,12 @@
       "(Landroidx/emoji2/text/"
       "DefaultEmojiCompatConfig$DefaultEmojiCompatConfigHelper;)V");
   if (_m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory__ctor == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->NewObject(
       jniEnv, _c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory,
       _m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory__ctor,
       helper);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1361,11 +1370,12 @@
     jobject self_,
     jobject context) {
   load_env();
-  load_class_gr(&_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory,
-                "androidx/emoji2/text/"
-                "DefaultEmojiCompatConfig$DefaultEmojiCompatConfigFactory");
+  load_class_global_ref(
+      &_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory,
+      "androidx/emoji2/text/"
+      "DefaultEmojiCompatConfig$DefaultEmojiCompatConfigFactory");
   if (_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(
       _c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory,
       &_m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory__create,
@@ -1373,12 +1383,12 @@
       "(Landroid/content/Context;)Landroidx/emoji2/text/EmojiCompat$Config;");
   if (_m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory__create ==
       NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_,
       _m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory__create,
       context);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1389,14 +1399,14 @@
 FFI_PLUGIN_EXPORT
 JniResult Build__ctor() {
   load_env();
-  load_class_gr(&_c_Build, "android/os/Build");
+  load_class_global_ref(&_c_Build, "android/os/Build");
   if (_c_Build == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_Build, &_m_Build__ctor, "<init>", "()V");
   if (_m_Build__ctor == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->NewObject(jniEnv, _c_Build, _m_Build__ctor);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1404,16 +1414,16 @@
 FFI_PLUGIN_EXPORT
 JniResult Build__getSerial() {
   load_env();
-  load_class_gr(&_c_Build, "android/os/Build");
+  load_class_global_ref(&_c_Build, "android/os/Build");
   if (_c_Build == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_method(_c_Build, &_m_Build__getSerial, "getSerial",
                      "()Ljava/lang/String;");
   if (_m_Build__getSerial == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result =
       (*jniEnv)->CallStaticObjectMethod(jniEnv, _c_Build, _m_Build__getSerial);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1421,16 +1431,16 @@
 FFI_PLUGIN_EXPORT
 JniResult Build__getFingerprintedPartitions() {
   load_env();
-  load_class_gr(&_c_Build, "android/os/Build");
+  load_class_global_ref(&_c_Build, "android/os/Build");
   if (_c_Build == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_method(_c_Build, &_m_Build__getFingerprintedPartitions,
                      "getFingerprintedPartitions", "()Ljava/util/List;");
   if (_m_Build__getFingerprintedPartitions == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallStaticObjectMethod(
       jniEnv, _c_Build, _m_Build__getFingerprintedPartitions);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1438,16 +1448,16 @@
 FFI_PLUGIN_EXPORT
 JniResult Build__getRadioVersion() {
   load_env();
-  load_class_gr(&_c_Build, "android/os/Build");
+  load_class_global_ref(&_c_Build, "android/os/Build");
   if (_c_Build == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_method(_c_Build, &_m_Build__getRadioVersion, "getRadioVersion",
                      "()Ljava/lang/String;");
   if (_m_Build__getRadioVersion == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallStaticObjectMethod(
       jniEnv, _c_Build, _m_Build__getRadioVersion);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1455,367 +1465,367 @@
 FFI_PLUGIN_EXPORT
 JniResult get_Build__BOARD() {
   load_env();
-  load_class_gr(&_c_Build, "android/os/Build");
+  load_class_global_ref(&_c_Build, "android/os/Build");
   if (_c_Build == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_field(_c_Build, &_f_Build__BOARD, "BOARD", "Ljava/lang/String;");
   jobject _result = to_global_ref(
       (*jniEnv)->GetStaticObjectField(jniEnv, _c_Build, _f_Build__BOARD));
-  return (JniResult){.result = {.l = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.l = _result}, .exception = check_exception()};
 }
 
 jfieldID _f_Build__BOOTLOADER = NULL;
 FFI_PLUGIN_EXPORT
 JniResult get_Build__BOOTLOADER() {
   load_env();
-  load_class_gr(&_c_Build, "android/os/Build");
+  load_class_global_ref(&_c_Build, "android/os/Build");
   if (_c_Build == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_field(_c_Build, &_f_Build__BOOTLOADER, "BOOTLOADER",
                     "Ljava/lang/String;");
   jobject _result = to_global_ref(
       (*jniEnv)->GetStaticObjectField(jniEnv, _c_Build, _f_Build__BOOTLOADER));
-  return (JniResult){.result = {.l = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.l = _result}, .exception = check_exception()};
 }
 
 jfieldID _f_Build__BRAND = NULL;
 FFI_PLUGIN_EXPORT
 JniResult get_Build__BRAND() {
   load_env();
-  load_class_gr(&_c_Build, "android/os/Build");
+  load_class_global_ref(&_c_Build, "android/os/Build");
   if (_c_Build == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_field(_c_Build, &_f_Build__BRAND, "BRAND", "Ljava/lang/String;");
   jobject _result = to_global_ref(
       (*jniEnv)->GetStaticObjectField(jniEnv, _c_Build, _f_Build__BRAND));
-  return (JniResult){.result = {.l = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.l = _result}, .exception = check_exception()};
 }
 
 jfieldID _f_Build__CPU_ABI = NULL;
 FFI_PLUGIN_EXPORT
 JniResult get_Build__CPU_ABI() {
   load_env();
-  load_class_gr(&_c_Build, "android/os/Build");
+  load_class_global_ref(&_c_Build, "android/os/Build");
   if (_c_Build == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_field(_c_Build, &_f_Build__CPU_ABI, "CPU_ABI",
                     "Ljava/lang/String;");
   jobject _result = to_global_ref(
       (*jniEnv)->GetStaticObjectField(jniEnv, _c_Build, _f_Build__CPU_ABI));
-  return (JniResult){.result = {.l = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.l = _result}, .exception = check_exception()};
 }
 
 jfieldID _f_Build__CPU_ABI2 = NULL;
 FFI_PLUGIN_EXPORT
 JniResult get_Build__CPU_ABI2() {
   load_env();
-  load_class_gr(&_c_Build, "android/os/Build");
+  load_class_global_ref(&_c_Build, "android/os/Build");
   if (_c_Build == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_field(_c_Build, &_f_Build__CPU_ABI2, "CPU_ABI2",
                     "Ljava/lang/String;");
   jobject _result = to_global_ref(
       (*jniEnv)->GetStaticObjectField(jniEnv, _c_Build, _f_Build__CPU_ABI2));
-  return (JniResult){.result = {.l = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.l = _result}, .exception = check_exception()};
 }
 
 jfieldID _f_Build__DEVICE = NULL;
 FFI_PLUGIN_EXPORT
 JniResult get_Build__DEVICE() {
   load_env();
-  load_class_gr(&_c_Build, "android/os/Build");
+  load_class_global_ref(&_c_Build, "android/os/Build");
   if (_c_Build == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_field(_c_Build, &_f_Build__DEVICE, "DEVICE",
                     "Ljava/lang/String;");
   jobject _result = to_global_ref(
       (*jniEnv)->GetStaticObjectField(jniEnv, _c_Build, _f_Build__DEVICE));
-  return (JniResult){.result = {.l = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.l = _result}, .exception = check_exception()};
 }
 
 jfieldID _f_Build__DISPLAY = NULL;
 FFI_PLUGIN_EXPORT
 JniResult get_Build__DISPLAY() {
   load_env();
-  load_class_gr(&_c_Build, "android/os/Build");
+  load_class_global_ref(&_c_Build, "android/os/Build");
   if (_c_Build == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_field(_c_Build, &_f_Build__DISPLAY, "DISPLAY",
                     "Ljava/lang/String;");
   jobject _result = to_global_ref(
       (*jniEnv)->GetStaticObjectField(jniEnv, _c_Build, _f_Build__DISPLAY));
-  return (JniResult){.result = {.l = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.l = _result}, .exception = check_exception()};
 }
 
 jfieldID _f_Build__FINGERPRINT = NULL;
 FFI_PLUGIN_EXPORT
 JniResult get_Build__FINGERPRINT() {
   load_env();
-  load_class_gr(&_c_Build, "android/os/Build");
+  load_class_global_ref(&_c_Build, "android/os/Build");
   if (_c_Build == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_field(_c_Build, &_f_Build__FINGERPRINT, "FINGERPRINT",
                     "Ljava/lang/String;");
   jobject _result = to_global_ref(
       (*jniEnv)->GetStaticObjectField(jniEnv, _c_Build, _f_Build__FINGERPRINT));
-  return (JniResult){.result = {.l = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.l = _result}, .exception = check_exception()};
 }
 
 jfieldID _f_Build__HARDWARE = NULL;
 FFI_PLUGIN_EXPORT
 JniResult get_Build__HARDWARE() {
   load_env();
-  load_class_gr(&_c_Build, "android/os/Build");
+  load_class_global_ref(&_c_Build, "android/os/Build");
   if (_c_Build == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_field(_c_Build, &_f_Build__HARDWARE, "HARDWARE",
                     "Ljava/lang/String;");
   jobject _result = to_global_ref(
       (*jniEnv)->GetStaticObjectField(jniEnv, _c_Build, _f_Build__HARDWARE));
-  return (JniResult){.result = {.l = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.l = _result}, .exception = check_exception()};
 }
 
 jfieldID _f_Build__HOST = NULL;
 FFI_PLUGIN_EXPORT
 JniResult get_Build__HOST() {
   load_env();
-  load_class_gr(&_c_Build, "android/os/Build");
+  load_class_global_ref(&_c_Build, "android/os/Build");
   if (_c_Build == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_field(_c_Build, &_f_Build__HOST, "HOST", "Ljava/lang/String;");
   jobject _result = to_global_ref(
       (*jniEnv)->GetStaticObjectField(jniEnv, _c_Build, _f_Build__HOST));
-  return (JniResult){.result = {.l = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.l = _result}, .exception = check_exception()};
 }
 
 jfieldID _f_Build__ID = NULL;
 FFI_PLUGIN_EXPORT
 JniResult get_Build__ID() {
   load_env();
-  load_class_gr(&_c_Build, "android/os/Build");
+  load_class_global_ref(&_c_Build, "android/os/Build");
   if (_c_Build == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_field(_c_Build, &_f_Build__ID, "ID", "Ljava/lang/String;");
   jobject _result = to_global_ref(
       (*jniEnv)->GetStaticObjectField(jniEnv, _c_Build, _f_Build__ID));
-  return (JniResult){.result = {.l = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.l = _result}, .exception = check_exception()};
 }
 
 jfieldID _f_Build__MANUFACTURER = NULL;
 FFI_PLUGIN_EXPORT
 JniResult get_Build__MANUFACTURER() {
   load_env();
-  load_class_gr(&_c_Build, "android/os/Build");
+  load_class_global_ref(&_c_Build, "android/os/Build");
   if (_c_Build == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_field(_c_Build, &_f_Build__MANUFACTURER, "MANUFACTURER",
                     "Ljava/lang/String;");
   jobject _result = to_global_ref((*jniEnv)->GetStaticObjectField(
       jniEnv, _c_Build, _f_Build__MANUFACTURER));
-  return (JniResult){.result = {.l = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.l = _result}, .exception = check_exception()};
 }
 
 jfieldID _f_Build__MODEL = NULL;
 FFI_PLUGIN_EXPORT
 JniResult get_Build__MODEL() {
   load_env();
-  load_class_gr(&_c_Build, "android/os/Build");
+  load_class_global_ref(&_c_Build, "android/os/Build");
   if (_c_Build == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_field(_c_Build, &_f_Build__MODEL, "MODEL", "Ljava/lang/String;");
   jobject _result = to_global_ref(
       (*jniEnv)->GetStaticObjectField(jniEnv, _c_Build, _f_Build__MODEL));
-  return (JniResult){.result = {.l = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.l = _result}, .exception = check_exception()};
 }
 
 jfieldID _f_Build__ODM_SKU = NULL;
 FFI_PLUGIN_EXPORT
 JniResult get_Build__ODM_SKU() {
   load_env();
-  load_class_gr(&_c_Build, "android/os/Build");
+  load_class_global_ref(&_c_Build, "android/os/Build");
   if (_c_Build == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_field(_c_Build, &_f_Build__ODM_SKU, "ODM_SKU",
                     "Ljava/lang/String;");
   jobject _result = to_global_ref(
       (*jniEnv)->GetStaticObjectField(jniEnv, _c_Build, _f_Build__ODM_SKU));
-  return (JniResult){.result = {.l = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.l = _result}, .exception = check_exception()};
 }
 
 jfieldID _f_Build__PRODUCT = NULL;
 FFI_PLUGIN_EXPORT
 JniResult get_Build__PRODUCT() {
   load_env();
-  load_class_gr(&_c_Build, "android/os/Build");
+  load_class_global_ref(&_c_Build, "android/os/Build");
   if (_c_Build == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_field(_c_Build, &_f_Build__PRODUCT, "PRODUCT",
                     "Ljava/lang/String;");
   jobject _result = to_global_ref(
       (*jniEnv)->GetStaticObjectField(jniEnv, _c_Build, _f_Build__PRODUCT));
-  return (JniResult){.result = {.l = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.l = _result}, .exception = check_exception()};
 }
 
 jfieldID _f_Build__RADIO = NULL;
 FFI_PLUGIN_EXPORT
 JniResult get_Build__RADIO() {
   load_env();
-  load_class_gr(&_c_Build, "android/os/Build");
+  load_class_global_ref(&_c_Build, "android/os/Build");
   if (_c_Build == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_field(_c_Build, &_f_Build__RADIO, "RADIO", "Ljava/lang/String;");
   jobject _result = to_global_ref(
       (*jniEnv)->GetStaticObjectField(jniEnv, _c_Build, _f_Build__RADIO));
-  return (JniResult){.result = {.l = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.l = _result}, .exception = check_exception()};
 }
 
 jfieldID _f_Build__SERIAL = NULL;
 FFI_PLUGIN_EXPORT
 JniResult get_Build__SERIAL() {
   load_env();
-  load_class_gr(&_c_Build, "android/os/Build");
+  load_class_global_ref(&_c_Build, "android/os/Build");
   if (_c_Build == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_field(_c_Build, &_f_Build__SERIAL, "SERIAL",
                     "Ljava/lang/String;");
   jobject _result = to_global_ref(
       (*jniEnv)->GetStaticObjectField(jniEnv, _c_Build, _f_Build__SERIAL));
-  return (JniResult){.result = {.l = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.l = _result}, .exception = check_exception()};
 }
 
 jfieldID _f_Build__SKU = NULL;
 FFI_PLUGIN_EXPORT
 JniResult get_Build__SKU() {
   load_env();
-  load_class_gr(&_c_Build, "android/os/Build");
+  load_class_global_ref(&_c_Build, "android/os/Build");
   if (_c_Build == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_field(_c_Build, &_f_Build__SKU, "SKU", "Ljava/lang/String;");
   jobject _result = to_global_ref(
       (*jniEnv)->GetStaticObjectField(jniEnv, _c_Build, _f_Build__SKU));
-  return (JniResult){.result = {.l = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.l = _result}, .exception = check_exception()};
 }
 
 jfieldID _f_Build__SOC_MANUFACTURER = NULL;
 FFI_PLUGIN_EXPORT
 JniResult get_Build__SOC_MANUFACTURER() {
   load_env();
-  load_class_gr(&_c_Build, "android/os/Build");
+  load_class_global_ref(&_c_Build, "android/os/Build");
   if (_c_Build == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_field(_c_Build, &_f_Build__SOC_MANUFACTURER, "SOC_MANUFACTURER",
                     "Ljava/lang/String;");
   jobject _result = to_global_ref((*jniEnv)->GetStaticObjectField(
       jniEnv, _c_Build, _f_Build__SOC_MANUFACTURER));
-  return (JniResult){.result = {.l = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.l = _result}, .exception = check_exception()};
 }
 
 jfieldID _f_Build__SOC_MODEL = NULL;
 FFI_PLUGIN_EXPORT
 JniResult get_Build__SOC_MODEL() {
   load_env();
-  load_class_gr(&_c_Build, "android/os/Build");
+  load_class_global_ref(&_c_Build, "android/os/Build");
   if (_c_Build == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_field(_c_Build, &_f_Build__SOC_MODEL, "SOC_MODEL",
                     "Ljava/lang/String;");
   jobject _result = to_global_ref(
       (*jniEnv)->GetStaticObjectField(jniEnv, _c_Build, _f_Build__SOC_MODEL));
-  return (JniResult){.result = {.l = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.l = _result}, .exception = check_exception()};
 }
 
 jfieldID _f_Build__SUPPORTED_32_BIT_ABIS = NULL;
 FFI_PLUGIN_EXPORT
 JniResult get_Build__SUPPORTED_32_BIT_ABIS() {
   load_env();
-  load_class_gr(&_c_Build, "android/os/Build");
+  load_class_global_ref(&_c_Build, "android/os/Build");
   if (_c_Build == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_field(_c_Build, &_f_Build__SUPPORTED_32_BIT_ABIS,
                     "SUPPORTED_32_BIT_ABIS", "[Ljava/lang/String;");
   jobject _result = to_global_ref((*jniEnv)->GetStaticObjectField(
       jniEnv, _c_Build, _f_Build__SUPPORTED_32_BIT_ABIS));
-  return (JniResult){.result = {.l = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.l = _result}, .exception = check_exception()};
 }
 
 jfieldID _f_Build__SUPPORTED_64_BIT_ABIS = NULL;
 FFI_PLUGIN_EXPORT
 JniResult get_Build__SUPPORTED_64_BIT_ABIS() {
   load_env();
-  load_class_gr(&_c_Build, "android/os/Build");
+  load_class_global_ref(&_c_Build, "android/os/Build");
   if (_c_Build == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_field(_c_Build, &_f_Build__SUPPORTED_64_BIT_ABIS,
                     "SUPPORTED_64_BIT_ABIS", "[Ljava/lang/String;");
   jobject _result = to_global_ref((*jniEnv)->GetStaticObjectField(
       jniEnv, _c_Build, _f_Build__SUPPORTED_64_BIT_ABIS));
-  return (JniResult){.result = {.l = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.l = _result}, .exception = check_exception()};
 }
 
 jfieldID _f_Build__SUPPORTED_ABIS = NULL;
 FFI_PLUGIN_EXPORT
 JniResult get_Build__SUPPORTED_ABIS() {
   load_env();
-  load_class_gr(&_c_Build, "android/os/Build");
+  load_class_global_ref(&_c_Build, "android/os/Build");
   if (_c_Build == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_field(_c_Build, &_f_Build__SUPPORTED_ABIS, "SUPPORTED_ABIS",
                     "[Ljava/lang/String;");
   jobject _result = to_global_ref((*jniEnv)->GetStaticObjectField(
       jniEnv, _c_Build, _f_Build__SUPPORTED_ABIS));
-  return (JniResult){.result = {.l = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.l = _result}, .exception = check_exception()};
 }
 
 jfieldID _f_Build__TAGS = NULL;
 FFI_PLUGIN_EXPORT
 JniResult get_Build__TAGS() {
   load_env();
-  load_class_gr(&_c_Build, "android/os/Build");
+  load_class_global_ref(&_c_Build, "android/os/Build");
   if (_c_Build == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_field(_c_Build, &_f_Build__TAGS, "TAGS", "Ljava/lang/String;");
   jobject _result = to_global_ref(
       (*jniEnv)->GetStaticObjectField(jniEnv, _c_Build, _f_Build__TAGS));
-  return (JniResult){.result = {.l = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.l = _result}, .exception = check_exception()};
 }
 
 jfieldID _f_Build__TIME = NULL;
 FFI_PLUGIN_EXPORT
 JniResult get_Build__TIME() {
   load_env();
-  load_class_gr(&_c_Build, "android/os/Build");
+  load_class_global_ref(&_c_Build, "android/os/Build");
   if (_c_Build == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_field(_c_Build, &_f_Build__TIME, "TIME", "J");
   int64_t _result =
       (*jniEnv)->GetStaticLongField(jniEnv, _c_Build, _f_Build__TIME);
-  return (JniResult){.result = {.j = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.j = _result}, .exception = check_exception()};
 }
 
 jfieldID _f_Build__TYPE = NULL;
 FFI_PLUGIN_EXPORT
 JniResult get_Build__TYPE() {
   load_env();
-  load_class_gr(&_c_Build, "android/os/Build");
+  load_class_global_ref(&_c_Build, "android/os/Build");
   if (_c_Build == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_field(_c_Build, &_f_Build__TYPE, "TYPE", "Ljava/lang/String;");
   jobject _result = to_global_ref(
       (*jniEnv)->GetStaticObjectField(jniEnv, _c_Build, _f_Build__TYPE));
-  return (JniResult){.result = {.l = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.l = _result}, .exception = check_exception()};
 }
 
 jfieldID _f_Build__USER = NULL;
 FFI_PLUGIN_EXPORT
 JniResult get_Build__USER() {
   load_env();
-  load_class_gr(&_c_Build, "android/os/Build");
+  load_class_global_ref(&_c_Build, "android/os/Build");
   if (_c_Build == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_field(_c_Build, &_f_Build__USER, "USER", "Ljava/lang/String;");
   jobject _result = to_global_ref(
       (*jniEnv)->GetStaticObjectField(jniEnv, _c_Build, _f_Build__USER));
-  return (JniResult){.result = {.l = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.l = _result}, .exception = check_exception()};
 }
 
 // java.util.HashMap
@@ -1825,15 +1835,15 @@
 FFI_PLUGIN_EXPORT
 JniResult HashMap__ctor(int32_t i, float f) {
   load_env();
-  load_class_gr(&_c_HashMap, "java/util/HashMap");
+  load_class_global_ref(&_c_HashMap, "java/util/HashMap");
   if (_c_HashMap == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_HashMap, &_m_HashMap__ctor, "<init>", "(IF)V");
   if (_m_HashMap__ctor == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result =
       (*jniEnv)->NewObject(jniEnv, _c_HashMap, _m_HashMap__ctor, i, f);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1841,15 +1851,15 @@
 FFI_PLUGIN_EXPORT
 JniResult HashMap__ctor1(int32_t i) {
   load_env();
-  load_class_gr(&_c_HashMap, "java/util/HashMap");
+  load_class_global_ref(&_c_HashMap, "java/util/HashMap");
   if (_c_HashMap == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_HashMap, &_m_HashMap__ctor1, "<init>", "(I)V");
   if (_m_HashMap__ctor1 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result =
       (*jniEnv)->NewObject(jniEnv, _c_HashMap, _m_HashMap__ctor1, i);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1857,14 +1867,14 @@
 FFI_PLUGIN_EXPORT
 JniResult HashMap__ctor2() {
   load_env();
-  load_class_gr(&_c_HashMap, "java/util/HashMap");
+  load_class_global_ref(&_c_HashMap, "java/util/HashMap");
   if (_c_HashMap == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_HashMap, &_m_HashMap__ctor2, "<init>", "()V");
   if (_m_HashMap__ctor2 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->NewObject(jniEnv, _c_HashMap, _m_HashMap__ctor2);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1872,15 +1882,15 @@
 FFI_PLUGIN_EXPORT
 JniResult HashMap__ctor3(jobject map) {
   load_env();
-  load_class_gr(&_c_HashMap, "java/util/HashMap");
+  load_class_global_ref(&_c_HashMap, "java/util/HashMap");
   if (_c_HashMap == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_HashMap, &_m_HashMap__ctor3, "<init>", "(Ljava/util/Map;)V");
   if (_m_HashMap__ctor3 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result =
       (*jniEnv)->NewObject(jniEnv, _c_HashMap, _m_HashMap__ctor3, map);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1888,45 +1898,45 @@
 FFI_PLUGIN_EXPORT
 JniResult HashMap__size(jobject self_) {
   load_env();
-  load_class_gr(&_c_HashMap, "java/util/HashMap");
+  load_class_global_ref(&_c_HashMap, "java/util/HashMap");
   if (_c_HashMap == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_HashMap, &_m_HashMap__size, "size", "()I");
   if (_m_HashMap__size == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   int32_t _result = (*jniEnv)->CallIntMethod(jniEnv, self_, _m_HashMap__size);
-  return (JniResult){.result = {.i = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.i = _result}, .exception = check_exception()};
 }
 
 jmethodID _m_HashMap__isEmpty = NULL;
 FFI_PLUGIN_EXPORT
 JniResult HashMap__isEmpty(jobject self_) {
   load_env();
-  load_class_gr(&_c_HashMap, "java/util/HashMap");
+  load_class_global_ref(&_c_HashMap, "java/util/HashMap");
   if (_c_HashMap == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_HashMap, &_m_HashMap__isEmpty, "isEmpty", "()Z");
   if (_m_HashMap__isEmpty == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   uint8_t _result =
       (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_HashMap__isEmpty);
-  return (JniResult){.result = {.z = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.z = _result}, .exception = check_exception()};
 }
 
 jmethodID _m_HashMap__get0 = NULL;
 FFI_PLUGIN_EXPORT
 JniResult HashMap__get0(jobject self_, jobject object) {
   load_env();
-  load_class_gr(&_c_HashMap, "java/util/HashMap");
+  load_class_global_ref(&_c_HashMap, "java/util/HashMap");
   if (_c_HashMap == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_HashMap, &_m_HashMap__get0, "get",
               "(Ljava/lang/Object;)Ljava/lang/Object;");
   if (_m_HashMap__get0 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result =
       (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_HashMap__get0, object);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1934,32 +1944,32 @@
 FFI_PLUGIN_EXPORT
 JniResult HashMap__containsKey(jobject self_, jobject object) {
   load_env();
-  load_class_gr(&_c_HashMap, "java/util/HashMap");
+  load_class_global_ref(&_c_HashMap, "java/util/HashMap");
   if (_c_HashMap == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_HashMap, &_m_HashMap__containsKey, "containsKey",
               "(Ljava/lang/Object;)Z");
   if (_m_HashMap__containsKey == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   uint8_t _result = (*jniEnv)->CallBooleanMethod(
       jniEnv, self_, _m_HashMap__containsKey, object);
-  return (JniResult){.result = {.z = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.z = _result}, .exception = check_exception()};
 }
 
 jmethodID _m_HashMap__put = NULL;
 FFI_PLUGIN_EXPORT
 JniResult HashMap__put(jobject self_, jobject object, jobject object1) {
   load_env();
-  load_class_gr(&_c_HashMap, "java/util/HashMap");
+  load_class_global_ref(&_c_HashMap, "java/util/HashMap");
   if (_c_HashMap == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_HashMap, &_m_HashMap__put, "put",
               "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
   if (_m_HashMap__put == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_HashMap__put,
                                                 object, object1);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1967,30 +1977,30 @@
 FFI_PLUGIN_EXPORT
 JniResult HashMap__putAll(jobject self_, jobject map) {
   load_env();
-  load_class_gr(&_c_HashMap, "java/util/HashMap");
+  load_class_global_ref(&_c_HashMap, "java/util/HashMap");
   if (_c_HashMap == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_HashMap, &_m_HashMap__putAll, "putAll", "(Ljava/util/Map;)V");
   if (_m_HashMap__putAll == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_HashMap__putAll, map);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_HashMap__remove = NULL;
 FFI_PLUGIN_EXPORT
 JniResult HashMap__remove(jobject self_, jobject object) {
   load_env();
-  load_class_gr(&_c_HashMap, "java/util/HashMap");
+  load_class_global_ref(&_c_HashMap, "java/util/HashMap");
   if (_c_HashMap == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_HashMap, &_m_HashMap__remove, "remove",
               "(Ljava/lang/Object;)Ljava/lang/Object;");
   if (_m_HashMap__remove == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result =
       (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_HashMap__remove, object);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1998,45 +2008,45 @@
 FFI_PLUGIN_EXPORT
 JniResult HashMap__clear(jobject self_) {
   load_env();
-  load_class_gr(&_c_HashMap, "java/util/HashMap");
+  load_class_global_ref(&_c_HashMap, "java/util/HashMap");
   if (_c_HashMap == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_HashMap, &_m_HashMap__clear, "clear", "()V");
   if (_m_HashMap__clear == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_HashMap__clear);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_HashMap__containsValue = NULL;
 FFI_PLUGIN_EXPORT
 JniResult HashMap__containsValue(jobject self_, jobject object) {
   load_env();
-  load_class_gr(&_c_HashMap, "java/util/HashMap");
+  load_class_global_ref(&_c_HashMap, "java/util/HashMap");
   if (_c_HashMap == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_HashMap, &_m_HashMap__containsValue, "containsValue",
               "(Ljava/lang/Object;)Z");
   if (_m_HashMap__containsValue == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   uint8_t _result = (*jniEnv)->CallBooleanMethod(
       jniEnv, self_, _m_HashMap__containsValue, object);
-  return (JniResult){.result = {.z = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.z = _result}, .exception = check_exception()};
 }
 
 jmethodID _m_HashMap__keySet = NULL;
 FFI_PLUGIN_EXPORT
 JniResult HashMap__keySet(jobject self_) {
   load_env();
-  load_class_gr(&_c_HashMap, "java/util/HashMap");
+  load_class_global_ref(&_c_HashMap, "java/util/HashMap");
   if (_c_HashMap == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_HashMap, &_m_HashMap__keySet, "keySet", "()Ljava/util/Set;");
   if (_m_HashMap__keySet == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result =
       (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_HashMap__keySet);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -2044,16 +2054,16 @@
 FFI_PLUGIN_EXPORT
 JniResult HashMap__values(jobject self_) {
   load_env();
-  load_class_gr(&_c_HashMap, "java/util/HashMap");
+  load_class_global_ref(&_c_HashMap, "java/util/HashMap");
   if (_c_HashMap == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_HashMap, &_m_HashMap__values, "values",
               "()Ljava/util/Collection;");
   if (_m_HashMap__values == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result =
       (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_HashMap__values);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -2061,16 +2071,16 @@
 FFI_PLUGIN_EXPORT
 JniResult HashMap__entrySet(jobject self_) {
   load_env();
-  load_class_gr(&_c_HashMap, "java/util/HashMap");
+  load_class_global_ref(&_c_HashMap, "java/util/HashMap");
   if (_c_HashMap == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_HashMap, &_m_HashMap__entrySet, "entrySet",
               "()Ljava/util/Set;");
   if (_m_HashMap__entrySet == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result =
       (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_HashMap__entrySet);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -2080,16 +2090,16 @@
                                 jobject object,
                                 jobject object1) {
   load_env();
-  load_class_gr(&_c_HashMap, "java/util/HashMap");
+  load_class_global_ref(&_c_HashMap, "java/util/HashMap");
   if (_c_HashMap == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_HashMap, &_m_HashMap__getOrDefault, "getOrDefault",
               "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
   if (_m_HashMap__getOrDefault == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_HashMap__getOrDefault, object, object1);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -2097,16 +2107,16 @@
 FFI_PLUGIN_EXPORT
 JniResult HashMap__putIfAbsent(jobject self_, jobject object, jobject object1) {
   load_env();
-  load_class_gr(&_c_HashMap, "java/util/HashMap");
+  load_class_global_ref(&_c_HashMap, "java/util/HashMap");
   if (_c_HashMap == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_HashMap, &_m_HashMap__putIfAbsent, "putIfAbsent",
               "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
   if (_m_HashMap__putIfAbsent == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_HashMap__putIfAbsent, object, object1);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -2114,16 +2124,16 @@
 FFI_PLUGIN_EXPORT
 JniResult HashMap__remove1(jobject self_, jobject object, jobject object1) {
   load_env();
-  load_class_gr(&_c_HashMap, "java/util/HashMap");
+  load_class_global_ref(&_c_HashMap, "java/util/HashMap");
   if (_c_HashMap == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_HashMap, &_m_HashMap__remove1, "remove",
               "(Ljava/lang/Object;Ljava/lang/Object;)Z");
   if (_m_HashMap__remove1 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   uint8_t _result = (*jniEnv)->CallBooleanMethod(
       jniEnv, self_, _m_HashMap__remove1, object, object1);
-  return (JniResult){.result = {.z = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.z = _result}, .exception = check_exception()};
 }
 
 jmethodID _m_HashMap__replace = NULL;
@@ -2133,32 +2143,32 @@
                            jobject object1,
                            jobject object2) {
   load_env();
-  load_class_gr(&_c_HashMap, "java/util/HashMap");
+  load_class_global_ref(&_c_HashMap, "java/util/HashMap");
   if (_c_HashMap == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_HashMap, &_m_HashMap__replace, "replace",
               "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Z");
   if (_m_HashMap__replace == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   uint8_t _result = (*jniEnv)->CallBooleanMethod(
       jniEnv, self_, _m_HashMap__replace, object, object1, object2);
-  return (JniResult){.result = {.z = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.z = _result}, .exception = check_exception()};
 }
 
 jmethodID _m_HashMap__replace1 = NULL;
 FFI_PLUGIN_EXPORT
 JniResult HashMap__replace1(jobject self_, jobject object, jobject object1) {
   load_env();
-  load_class_gr(&_c_HashMap, "java/util/HashMap");
+  load_class_global_ref(&_c_HashMap, "java/util/HashMap");
   if (_c_HashMap == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_HashMap, &_m_HashMap__replace1, "replace",
               "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
   if (_m_HashMap__replace1 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_HashMap__replace1, object, object1);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -2168,17 +2178,17 @@
                                    jobject object,
                                    jobject function) {
   load_env();
-  load_class_gr(&_c_HashMap, "java/util/HashMap");
+  load_class_global_ref(&_c_HashMap, "java/util/HashMap");
   if (_c_HashMap == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(
       _c_HashMap, &_m_HashMap__computeIfAbsent, "computeIfAbsent",
       "(Ljava/lang/Object;Ljava/util/function/Function;)Ljava/lang/Object;");
   if (_m_HashMap__computeIfAbsent == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_HashMap__computeIfAbsent, object, function);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -2188,17 +2198,17 @@
                                     jobject object,
                                     jobject biFunction) {
   load_env();
-  load_class_gr(&_c_HashMap, "java/util/HashMap");
+  load_class_global_ref(&_c_HashMap, "java/util/HashMap");
   if (_c_HashMap == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(
       _c_HashMap, &_m_HashMap__computeIfPresent, "computeIfPresent",
       "(Ljava/lang/Object;Ljava/util/function/BiFunction;)Ljava/lang/Object;");
   if (_m_HashMap__computeIfPresent == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_HashMap__computeIfPresent, object, biFunction);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -2206,17 +2216,17 @@
 FFI_PLUGIN_EXPORT
 JniResult HashMap__compute(jobject self_, jobject object, jobject biFunction) {
   load_env();
-  load_class_gr(&_c_HashMap, "java/util/HashMap");
+  load_class_global_ref(&_c_HashMap, "java/util/HashMap");
   if (_c_HashMap == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(
       _c_HashMap, &_m_HashMap__compute, "compute",
       "(Ljava/lang/Object;Ljava/util/function/BiFunction;)Ljava/lang/Object;");
   if (_m_HashMap__compute == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_HashMap__compute, object, biFunction);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -2227,17 +2237,17 @@
                          jobject object1,
                          jobject biFunction) {
   load_env();
-  load_class_gr(&_c_HashMap, "java/util/HashMap");
+  load_class_global_ref(&_c_HashMap, "java/util/HashMap");
   if (_c_HashMap == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_HashMap, &_m_HashMap__merge, "merge",
               "(Ljava/lang/Object;Ljava/lang/Object;Ljava/util/function/"
               "BiFunction;)Ljava/lang/Object;");
   if (_m_HashMap__merge == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_HashMap__merge, object, object1, biFunction);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -2245,44 +2255,44 @@
 FFI_PLUGIN_EXPORT
 JniResult HashMap__forEach(jobject self_, jobject biConsumer) {
   load_env();
-  load_class_gr(&_c_HashMap, "java/util/HashMap");
+  load_class_global_ref(&_c_HashMap, "java/util/HashMap");
   if (_c_HashMap == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_HashMap, &_m_HashMap__forEach, "forEach",
               "(Ljava/util/function/BiConsumer;)V");
   if (_m_HashMap__forEach == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_HashMap__forEach, biConsumer);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_HashMap__replaceAll = NULL;
 FFI_PLUGIN_EXPORT
 JniResult HashMap__replaceAll(jobject self_, jobject biFunction) {
   load_env();
-  load_class_gr(&_c_HashMap, "java/util/HashMap");
+  load_class_global_ref(&_c_HashMap, "java/util/HashMap");
   if (_c_HashMap == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_HashMap, &_m_HashMap__replaceAll, "replaceAll",
               "(Ljava/util/function/BiFunction;)V");
   if (_m_HashMap__replaceAll == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_HashMap__replaceAll, biFunction);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_HashMap__clone = NULL;
 FFI_PLUGIN_EXPORT
 JniResult HashMap__clone(jobject self_) {
   load_env();
-  load_class_gr(&_c_HashMap, "java/util/HashMap");
+  load_class_global_ref(&_c_HashMap, "java/util/HashMap");
   if (_c_HashMap == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_HashMap, &_m_HashMap__clone, "clone", "()Ljava/lang/Object;");
   if (_m_HashMap__clone == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result =
       (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_HashMap__clone);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
diff --git a/pkgs/jnigen/example/in_app_java/src/android_utils/dartjni.h b/pkgs/jnigen/example/in_app_java/src/android_utils/dartjni.h
index 39b70bd..eb73318 100644
--- a/pkgs/jnigen/example/in_app_java/src/android_utils/dartjni.h
+++ b/pkgs/jnigen/example/in_app_java/src/android_utils/dartjni.h
@@ -39,6 +39,66 @@
 #define __ENVP_CAST (void**)
 #endif
 
+/// Locking functions for windows and pthread.
+
+#if defined _WIN32
+#include <windows.h>
+
+typedef CRITICAL_SECTION MutexLock;
+
+static inline void init_lock(MutexLock* lock) {
+  InitializeCriticalSection(lock);
+}
+
+static inline void acquire_lock(MutexLock* lock) {
+  EnterCriticalSection(lock);
+}
+
+static inline void release_lock(MutexLock* lock) {
+  LeaveCriticalSection(lock);
+}
+
+static inline void _destroyLock(MutexLock* lock) {
+  DeleteCriticalSection(lock);
+}
+
+#elif defined __DARWIN__ || defined __LINUX__ || defined __ANDROID__ ||        \
+    defined __GNUC__
+#include <pthread.h>
+
+typedef pthread_mutex_t MutexLock;
+
+static inline void init_lock(MutexLock* lock) {
+  pthread_mutex_init(lock, NULL);
+}
+
+static inline void acquire_lock(MutexLock* lock) {
+  pthread_mutex_lock(lock);
+}
+
+static inline void release_lock(MutexLock* lock) {
+  pthread_mutex_unlock(lock);
+}
+
+static inline void _destroyLock(MutexLock* lock) {
+  pthread_mutex_destroy(lock);
+}
+
+#else
+
+#error "No locking support; Possibly unsupported platform"
+
+#endif
+
+typedef struct JniLocks {
+  MutexLock classLoadingLock;
+  MutexLock methodLoadingLock;
+  MutexLock fieldLoadingLock;
+} JniLocks;
+
+/// Represents the error when dart-jni layer has already spawned singleton VM.
+#define DART_JNI_SINGLETON_EXISTS (-99);
+
 /// Stores the global state of the JNI.
 typedef struct JniContext {
   JavaVM* jvm;
@@ -46,13 +106,14 @@
   jmethodID loadClassMethod;
   jobject currentActivity;
   jobject appContext;
+  JniLocks locks;
 } JniContext;
 
 // jniEnv for this thread, used by inline functions in this header,
 // therefore declared as extern.
 extern thread_local JNIEnv* jniEnv;
 
-extern JniContext jni;
+extern JniContext* jni;
 
 /// Types used by JNI API to distinguish between primitive types.
 enum JniType {
@@ -73,19 +134,19 @@
 /// If [exception] is null, it means the result is valid.
 /// It's assumed that the caller knows the expected type in [result].
 typedef struct JniResult {
-  jvalue result;
+  jvalue value;
   jthrowable exception;
 } JniResult;
 
 /// Similar to [JniResult] but for class lookups.
 typedef struct JniClassLookupResult {
-  jclass classRef;
+  jclass value;
   jthrowable exception;
 } JniClassLookupResult;
 
 /// Similar to [JniResult] but for method/field ID lookups.
 typedef struct JniPointerResult {
-  void* id;
+  const void* value;
   jthrowable exception;
 } JniPointerResult;
 
@@ -139,54 +200,71 @@
 
 FFI_PLUGIN_EXPORT JNIEnv* GetJniEnv(void);
 
-FFI_PLUGIN_EXPORT JNIEnv* SpawnJvm(JavaVMInitArgs* args);
+/// Spawn a JVM with given arguments.
+///
+/// Returns JNI_OK on success, and one of the documented JNI error codes on
+/// failure. It returns DART_JNI_SINGLETON_EXISTS if an attempt to spawn multiple
+/// JVMs is made, even if the underlying API potentially supports multiple VMs.
+FFI_PLUGIN_EXPORT int SpawnJvm(JavaVMInitArgs* args);
 
-FFI_PLUGIN_EXPORT jclass LoadClass(const char* name);
+/// Load class through platform-specific mechanism.
+///
+/// Currently uses application classloader on android,
+/// and JNIEnv->FindClass on other platforms.
+FFI_PLUGIN_EXPORT jclass FindClass(const char* name);
 
+/// Returns Application classLoader (on Android),
+/// which can be used to load application and platform classes.
+///
+/// On other platforms, NULL is returned.
 FFI_PLUGIN_EXPORT jobject GetClassLoader(void);
 
+/// Returns application context on Android.
+///
+/// On other platforms, NULL is returned.
 FFI_PLUGIN_EXPORT jobject GetApplicationContext(void);
 
+/// Returns current activity of the app on Android.
 FFI_PLUGIN_EXPORT jobject GetCurrentActivity(void);
 
-// Migration note: Below inline functions are required by C bindings, but can be moved to dartjni.c
-// once migration to pure dart bindings is complete.
+static inline void attach_thread() {
+  if (jniEnv == NULL) {
+    (*jni->jvm)->AttachCurrentThread(jni->jvm, __ENVP_CAST & jniEnv, NULL);
+  }
+}
 
-// `static inline` because `inline` doesn't work, it may still not
-// inline the function in which case a linker error may be produced.
-//
-// There has to be a better way to do this. Either to force inlining on target
-// platforms, or just leave it as normal function.
-
-static inline void __load_class_into(jclass* cls, const char* name) {
+/// Load class into [cls] using platform specific mechanism
+static inline void load_class_platform(jclass* cls, const char* name) {
 #ifdef __ANDROID__
   jstring className = (*jniEnv)->NewStringUTF(jniEnv, name);
-  *cls = (*jniEnv)->CallObjectMethod(jniEnv, jni.classLoader,
-                                     jni.loadClassMethod, className);
+  *cls = (*jniEnv)->CallObjectMethod(jniEnv, jni->classLoader,
+                                     jni->loadClassMethod, className);
   (*jniEnv)->DeleteLocalRef(jniEnv, className);
 #else
   *cls = (*jniEnv)->FindClass(jniEnv, name);
 #endif
 }
 
-static inline void load_class(jclass* cls, const char* name) {
+static inline void load_class_local_ref(jclass* cls, const char* name) {
   if (*cls == NULL) {
-    __load_class_into(cls, name);
+    acquire_lock(&jni->locks.classLoadingLock);
+    if (*cls == NULL) {
+      load_class_platform(cls, name);
+    }
+    release_lock(&jni->locks.classLoadingLock);
   }
 }
 
-static inline void load_class_gr(jclass* cls, const char* name) {
+static inline void load_class_global_ref(jclass* cls, const char* name) {
   if (*cls == NULL) {
-    jclass tmp;
-    __load_class_into(&tmp, name);
-    *cls = (*jniEnv)->NewGlobalRef(jniEnv, tmp);
-    (*jniEnv)->DeleteLocalRef(jniEnv, tmp);
-  }
-}
-
-static inline void attach_thread() {
-  if (jniEnv == NULL) {
-    (*jni.jvm)->AttachCurrentThread(jni.jvm, __ENVP_CAST & jniEnv, NULL);
+    jclass tmp = NULL;
+    acquire_lock(&jni->locks.classLoadingLock);
+    if (*cls == NULL) {
+      load_class_platform(&tmp, name);
+      *cls = (*jniEnv)->NewGlobalRef(jniEnv, tmp);
+      (*jniEnv)->DeleteLocalRef(jniEnv, tmp);
+    }
+    release_lock(&jni->locks.classLoadingLock);
   }
 }
 
@@ -195,7 +273,11 @@
                                const char* name,
                                const char* sig) {
   if (*res == NULL) {
-    *res = (*jniEnv)->GetMethodID(jniEnv, cls, name, sig);
+    acquire_lock(&jni->locks.methodLoadingLock);
+    if (*res == NULL) {
+      *res = (*jniEnv)->GetMethodID(jniEnv, cls, name, sig);
+    }
+    release_lock(&jni->locks.methodLoadingLock);
   }
 }
 
@@ -204,7 +286,11 @@
                                       const char* name,
                                       const char* sig) {
   if (*res == NULL) {
-    *res = (*jniEnv)->GetStaticMethodID(jniEnv, cls, name, sig);
+    acquire_lock(&jni->locks.methodLoadingLock);
+    if (*res == NULL) {
+      *res = (*jniEnv)->GetStaticMethodID(jniEnv, cls, name, sig);
+    }
+    release_lock(&jni->locks.methodLoadingLock);
   }
 }
 
@@ -213,7 +299,11 @@
                               const char* name,
                               const char* sig) {
   if (*res == NULL) {
-    *res = (*jniEnv)->GetFieldID(jniEnv, cls, name, sig);
+    acquire_lock(&jni->locks.fieldLoadingLock);
+    if (*res == NULL) {
+      *res = (*jniEnv)->GetFieldID(jniEnv, cls, name, sig);
+    }
+    release_lock(&jni->locks.fieldLoadingLock);
   }
 }
 
@@ -222,7 +312,11 @@
                                      const char* name,
                                      const char* sig) {
   if (*res == NULL) {
-    *res = (*jniEnv)->GetStaticFieldID(jniEnv, cls, name, sig);
+    acquire_lock(&jni->locks.fieldLoadingLock);
+    if (*res == NULL) {
+      *res = (*jniEnv)->GetStaticFieldID(jniEnv, cls, name, sig);
+    }
+    release_lock(&jni->locks.fieldLoadingLock);
   }
 }
 
@@ -234,17 +328,18 @@
 
 // These functions are useful for C+Dart bindings, and not required for pure dart bindings.
 
-FFI_PLUGIN_EXPORT JniContext GetJniContext();
+FFI_PLUGIN_EXPORT JniContext* GetJniContextPtr();
+
 /// For use by jni_gen's generated code
 /// don't use these.
 
 // these 2 fn ptr vars will be defined by generated code library
-extern JniContext (*context_getter)(void);
+extern JniContext* (*context_getter)(void);
 extern JNIEnv* (*env_getter)(void);
 
 // this function will be exported by generated code library
 // it will set above 2 variables.
-FFI_PLUGIN_EXPORT void setJniGetters(struct JniContext (*cg)(void),
+FFI_PLUGIN_EXPORT void setJniGetters(struct JniContext* (*cg)(void),
                                      JNIEnv* (*eg)(void));
 
 static inline void load_env() {
diff --git a/pkgs/jnigen/example/kotlin_plugin/lib/kotlin_bindings.dart b/pkgs/jnigen/example/kotlin_plugin/lib/kotlin_bindings.dart
index 3485f93..25cd604 100644
--- a/pkgs/jnigen/example/kotlin_plugin/lib/kotlin_bindings.dart
+++ b/pkgs/jnigen/example/kotlin_plugin/lib/kotlin_bindings.dart
@@ -61,7 +61,7 @@
     _thinkBeforeAnswering(reference, $c.reference).object;
     final $o = jni.JObjectPtr.fromAddress(await $p.first);
     final $k = const jni.JStringType().getClass().reference;
-    if (jni.Jni.env.IsInstanceOf($o, $k) == 0) {
+    if (!jni.Jni.env.IsInstanceOf($o, $k)) {
       throw "Failed";
     }
     return const jni.JStringType().fromRef($o);
diff --git a/pkgs/jnigen/example/kotlin_plugin/src/dartjni.h b/pkgs/jnigen/example/kotlin_plugin/src/dartjni.h
index 39b70bd..eb73318 100644
--- a/pkgs/jnigen/example/kotlin_plugin/src/dartjni.h
+++ b/pkgs/jnigen/example/kotlin_plugin/src/dartjni.h
@@ -39,6 +39,66 @@
 #define __ENVP_CAST (void**)
 #endif
 
+/// Locking functions for windows and pthread.
+
+#if defined _WIN32
+#include <windows.h>
+
+typedef CRITICAL_SECTION MutexLock;
+
+static inline void init_lock(MutexLock* lock) {
+  InitializeCriticalSection(lock);
+}
+
+static inline void acquire_lock(MutexLock* lock) {
+  EnterCriticalSection(lock);
+}
+
+static inline void release_lock(MutexLock* lock) {
+  LeaveCriticalSection(lock);
+}
+
+static inline void _destroyLock(MutexLock* lock) {
+  DeleteCriticalSection(lock);
+}
+
+#elif defined __DARWIN__ || defined __LINUX__ || defined __ANDROID__ ||        \
+    defined __GNUC__
+#include <pthread.h>
+
+typedef pthread_mutex_t MutexLock;
+
+static inline void init_lock(MutexLock* lock) {
+  pthread_mutex_init(lock, NULL);
+}
+
+static inline void acquire_lock(MutexLock* lock) {
+  pthread_mutex_lock(lock);
+}
+
+static inline void release_lock(MutexLock* lock) {
+  pthread_mutex_unlock(lock);
+}
+
+static inline void _destroyLock(MutexLock* lock) {
+  pthread_mutex_destroy(lock);
+}
+
+#else
+
+#error "No locking support; Possibly unsupported platform"
+
+#endif
+
+typedef struct JniLocks {
+  MutexLock classLoadingLock;
+  MutexLock methodLoadingLock;
+  MutexLock fieldLoadingLock;
+} JniLocks;
+
+/// Represents the error when dart-jni layer has already spawned singleton VM.
+#define DART_JNI_SINGLETON_EXISTS (-99);
+
 /// Stores the global state of the JNI.
 typedef struct JniContext {
   JavaVM* jvm;
@@ -46,13 +106,14 @@
   jmethodID loadClassMethod;
   jobject currentActivity;
   jobject appContext;
+  JniLocks locks;
 } JniContext;
 
 // jniEnv for this thread, used by inline functions in this header,
 // therefore declared as extern.
 extern thread_local JNIEnv* jniEnv;
 
-extern JniContext jni;
+extern JniContext* jni;
 
 /// Types used by JNI API to distinguish between primitive types.
 enum JniType {
@@ -73,19 +134,19 @@
 /// If [exception] is null, it means the result is valid.
 /// It's assumed that the caller knows the expected type in [result].
 typedef struct JniResult {
-  jvalue result;
+  jvalue value;
   jthrowable exception;
 } JniResult;
 
 /// Similar to [JniResult] but for class lookups.
 typedef struct JniClassLookupResult {
-  jclass classRef;
+  jclass value;
   jthrowable exception;
 } JniClassLookupResult;
 
 /// Similar to [JniResult] but for method/field ID lookups.
 typedef struct JniPointerResult {
-  void* id;
+  const void* value;
   jthrowable exception;
 } JniPointerResult;
 
@@ -139,54 +200,71 @@
 
 FFI_PLUGIN_EXPORT JNIEnv* GetJniEnv(void);
 
-FFI_PLUGIN_EXPORT JNIEnv* SpawnJvm(JavaVMInitArgs* args);
+/// Spawn a JVM with given arguments.
+///
+/// Returns JNI_OK on success, and one of the documented JNI error codes on
+/// failure. It returns DART_JNI_SINGLETON_EXISTS if an attempt to spawn multiple
+/// JVMs is made, even if the underlying API potentially supports multiple VMs.
+FFI_PLUGIN_EXPORT int SpawnJvm(JavaVMInitArgs* args);
 
-FFI_PLUGIN_EXPORT jclass LoadClass(const char* name);
+/// Load class through platform-specific mechanism.
+///
+/// Currently uses application classloader on android,
+/// and JNIEnv->FindClass on other platforms.
+FFI_PLUGIN_EXPORT jclass FindClass(const char* name);
 
+/// Returns Application classLoader (on Android),
+/// which can be used to load application and platform classes.
+///
+/// On other platforms, NULL is returned.
 FFI_PLUGIN_EXPORT jobject GetClassLoader(void);
 
+/// Returns application context on Android.
+///
+/// On other platforms, NULL is returned.
 FFI_PLUGIN_EXPORT jobject GetApplicationContext(void);
 
+/// Returns current activity of the app on Android.
 FFI_PLUGIN_EXPORT jobject GetCurrentActivity(void);
 
-// Migration note: Below inline functions are required by C bindings, but can be moved to dartjni.c
-// once migration to pure dart bindings is complete.
+static inline void attach_thread() {
+  if (jniEnv == NULL) {
+    (*jni->jvm)->AttachCurrentThread(jni->jvm, __ENVP_CAST & jniEnv, NULL);
+  }
+}
 
-// `static inline` because `inline` doesn't work, it may still not
-// inline the function in which case a linker error may be produced.
-//
-// There has to be a better way to do this. Either to force inlining on target
-// platforms, or just leave it as normal function.
-
-static inline void __load_class_into(jclass* cls, const char* name) {
+/// Load class into [cls] using platform specific mechanism
+static inline void load_class_platform(jclass* cls, const char* name) {
 #ifdef __ANDROID__
   jstring className = (*jniEnv)->NewStringUTF(jniEnv, name);
-  *cls = (*jniEnv)->CallObjectMethod(jniEnv, jni.classLoader,
-                                     jni.loadClassMethod, className);
+  *cls = (*jniEnv)->CallObjectMethod(jniEnv, jni->classLoader,
+                                     jni->loadClassMethod, className);
   (*jniEnv)->DeleteLocalRef(jniEnv, className);
 #else
   *cls = (*jniEnv)->FindClass(jniEnv, name);
 #endif
 }
 
-static inline void load_class(jclass* cls, const char* name) {
+static inline void load_class_local_ref(jclass* cls, const char* name) {
   if (*cls == NULL) {
-    __load_class_into(cls, name);
+    acquire_lock(&jni->locks.classLoadingLock);
+    if (*cls == NULL) {
+      load_class_platform(cls, name);
+    }
+    release_lock(&jni->locks.classLoadingLock);
   }
 }
 
-static inline void load_class_gr(jclass* cls, const char* name) {
+static inline void load_class_global_ref(jclass* cls, const char* name) {
   if (*cls == NULL) {
-    jclass tmp;
-    __load_class_into(&tmp, name);
-    *cls = (*jniEnv)->NewGlobalRef(jniEnv, tmp);
-    (*jniEnv)->DeleteLocalRef(jniEnv, tmp);
-  }
-}
-
-static inline void attach_thread() {
-  if (jniEnv == NULL) {
-    (*jni.jvm)->AttachCurrentThread(jni.jvm, __ENVP_CAST & jniEnv, NULL);
+    jclass tmp = NULL;
+    acquire_lock(&jni->locks.classLoadingLock);
+    if (*cls == NULL) {
+      load_class_platform(&tmp, name);
+      *cls = (*jniEnv)->NewGlobalRef(jniEnv, tmp);
+      (*jniEnv)->DeleteLocalRef(jniEnv, tmp);
+    }
+    release_lock(&jni->locks.classLoadingLock);
   }
 }
 
@@ -195,7 +273,11 @@
                                const char* name,
                                const char* sig) {
   if (*res == NULL) {
-    *res = (*jniEnv)->GetMethodID(jniEnv, cls, name, sig);
+    acquire_lock(&jni->locks.methodLoadingLock);
+    if (*res == NULL) {
+      *res = (*jniEnv)->GetMethodID(jniEnv, cls, name, sig);
+    }
+    release_lock(&jni->locks.methodLoadingLock);
   }
 }
 
@@ -204,7 +286,11 @@
                                       const char* name,
                                       const char* sig) {
   if (*res == NULL) {
-    *res = (*jniEnv)->GetStaticMethodID(jniEnv, cls, name, sig);
+    acquire_lock(&jni->locks.methodLoadingLock);
+    if (*res == NULL) {
+      *res = (*jniEnv)->GetStaticMethodID(jniEnv, cls, name, sig);
+    }
+    release_lock(&jni->locks.methodLoadingLock);
   }
 }
 
@@ -213,7 +299,11 @@
                               const char* name,
                               const char* sig) {
   if (*res == NULL) {
-    *res = (*jniEnv)->GetFieldID(jniEnv, cls, name, sig);
+    acquire_lock(&jni->locks.fieldLoadingLock);
+    if (*res == NULL) {
+      *res = (*jniEnv)->GetFieldID(jniEnv, cls, name, sig);
+    }
+    release_lock(&jni->locks.fieldLoadingLock);
   }
 }
 
@@ -222,7 +312,11 @@
                                      const char* name,
                                      const char* sig) {
   if (*res == NULL) {
-    *res = (*jniEnv)->GetStaticFieldID(jniEnv, cls, name, sig);
+    acquire_lock(&jni->locks.fieldLoadingLock);
+    if (*res == NULL) {
+      *res = (*jniEnv)->GetStaticFieldID(jniEnv, cls, name, sig);
+    }
+    release_lock(&jni->locks.fieldLoadingLock);
   }
 }
 
@@ -234,17 +328,18 @@
 
 // These functions are useful for C+Dart bindings, and not required for pure dart bindings.
 
-FFI_PLUGIN_EXPORT JniContext GetJniContext();
+FFI_PLUGIN_EXPORT JniContext* GetJniContextPtr();
+
 /// For use by jni_gen's generated code
 /// don't use these.
 
 // these 2 fn ptr vars will be defined by generated code library
-extern JniContext (*context_getter)(void);
+extern JniContext* (*context_getter)(void);
 extern JNIEnv* (*env_getter)(void);
 
 // this function will be exported by generated code library
 // it will set above 2 variables.
-FFI_PLUGIN_EXPORT void setJniGetters(struct JniContext (*cg)(void),
+FFI_PLUGIN_EXPORT void setJniGetters(struct JniContext* (*cg)(void),
                                      JNIEnv* (*eg)(void));
 
 static inline void load_env() {
diff --git a/pkgs/jnigen/example/kotlin_plugin/src/kotlin_plugin_bindings.c b/pkgs/jnigen/example/kotlin_plugin/src/kotlin_plugin_bindings.c
index 77075ce..d93599c 100644
--- a/pkgs/jnigen/example/kotlin_plugin/src/kotlin_plugin_bindings.c
+++ b/pkgs/jnigen/example/kotlin_plugin/src/kotlin_plugin_bindings.c
@@ -5,12 +5,12 @@
 #include "jni.h"
 
 thread_local JNIEnv* jniEnv;
-JniContext jni;
+JniContext* jni;
 
-JniContext (*context_getter)(void);
+JniContext* (*context_getter)(void);
 JNIEnv* (*env_getter)(void);
 
-void setJniGetters(JniContext (*cg)(void), JNIEnv* (*eg)(void)) {
+void setJniGetters(JniContext* (*cg)(void), JNIEnv* (*eg)(void)) {
   context_getter = cg;
   env_getter = eg;
 }
@@ -22,14 +22,14 @@
 FFI_PLUGIN_EXPORT
 JniResult Example__ctor() {
   load_env();
-  load_class_gr(&_c_Example, "Example");
+  load_class_global_ref(&_c_Example, "Example");
   if (_c_Example == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_Example, &_m_Example__ctor, "<init>", "()V");
   if (_m_Example__ctor == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->NewObject(jniEnv, _c_Example, _m_Example__ctor);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -37,16 +37,16 @@
 FFI_PLUGIN_EXPORT
 JniResult Example__thinkBeforeAnswering(jobject self_, jobject continuation) {
   load_env();
-  load_class_gr(&_c_Example, "Example");
+  load_class_global_ref(&_c_Example, "Example");
   if (_c_Example == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_Example, &_m_Example__thinkBeforeAnswering,
               "thinkBeforeAnswering",
               "(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;");
   if (_m_Example__thinkBeforeAnswering == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_Example__thinkBeforeAnswering, continuation);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
diff --git a/pkgs/jnigen/example/notification_plugin/src/dartjni.h b/pkgs/jnigen/example/notification_plugin/src/dartjni.h
index 39b70bd..eb73318 100644
--- a/pkgs/jnigen/example/notification_plugin/src/dartjni.h
+++ b/pkgs/jnigen/example/notification_plugin/src/dartjni.h
@@ -39,6 +39,66 @@
 #define __ENVP_CAST (void**)
 #endif
 
+/// Locking functions for windows and pthread.
+
+#if defined _WIN32
+#include <windows.h>
+
+typedef CRITICAL_SECTION MutexLock;
+
+static inline void init_lock(MutexLock* lock) {
+  InitializeCriticalSection(lock);
+}
+
+static inline void acquire_lock(MutexLock* lock) {
+  EnterCriticalSection(lock);
+}
+
+static inline void release_lock(MutexLock* lock) {
+  LeaveCriticalSection(lock);
+}
+
+static inline void _destroyLock(MutexLock* lock) {
+  DeleteCriticalSection(lock);
+}
+
+#elif defined __DARWIN__ || defined __LINUX__ || defined __ANDROID__ ||        \
+    defined __GNUC__
+#include <pthread.h>
+
+typedef pthread_mutex_t MutexLock;
+
+static inline void init_lock(MutexLock* lock) {
+  pthread_mutex_init(lock, NULL);
+}
+
+static inline void acquire_lock(MutexLock* lock) {
+  pthread_mutex_lock(lock);
+}
+
+static inline void release_lock(MutexLock* lock) {
+  pthread_mutex_unlock(lock);
+}
+
+static inline void _destroyLock(MutexLock* lock) {
+  pthread_mutex_destroy(lock);
+}
+
+#else
+
+#error "No locking support; Possibly unsupported platform"
+
+#endif
+
+typedef struct JniLocks {
+  MutexLock classLoadingLock;
+  MutexLock methodLoadingLock;
+  MutexLock fieldLoadingLock;
+} JniLocks;
+
+/// Represents the error when dart-jni layer has already spawned singleton VM.
+#define DART_JNI_SINGLETON_EXISTS (-99);
+
 /// Stores the global state of the JNI.
 typedef struct JniContext {
   JavaVM* jvm;
@@ -46,13 +106,14 @@
   jmethodID loadClassMethod;
   jobject currentActivity;
   jobject appContext;
+  JniLocks locks;
 } JniContext;
 
 // jniEnv for this thread, used by inline functions in this header,
 // therefore declared as extern.
 extern thread_local JNIEnv* jniEnv;
 
-extern JniContext jni;
+extern JniContext* jni;
 
 /// Types used by JNI API to distinguish between primitive types.
 enum JniType {
@@ -73,19 +134,19 @@
 /// If [exception] is null, it means the result is valid.
 /// It's assumed that the caller knows the expected type in [result].
 typedef struct JniResult {
-  jvalue result;
+  jvalue value;
   jthrowable exception;
 } JniResult;
 
 /// Similar to [JniResult] but for class lookups.
 typedef struct JniClassLookupResult {
-  jclass classRef;
+  jclass value;
   jthrowable exception;
 } JniClassLookupResult;
 
 /// Similar to [JniResult] but for method/field ID lookups.
 typedef struct JniPointerResult {
-  void* id;
+  const void* value;
   jthrowable exception;
 } JniPointerResult;
 
@@ -139,54 +200,71 @@
 
 FFI_PLUGIN_EXPORT JNIEnv* GetJniEnv(void);
 
-FFI_PLUGIN_EXPORT JNIEnv* SpawnJvm(JavaVMInitArgs* args);
+/// Spawn a JVM with given arguments.
+///
+/// Returns JNI_OK on success, and one of the documented JNI error codes on
+/// failure. It returns DART_JNI_SINGLETON_EXISTS if an attempt to spawn multiple
+/// JVMs is made, even if the underlying API potentially supports multiple VMs.
+FFI_PLUGIN_EXPORT int SpawnJvm(JavaVMInitArgs* args);
 
-FFI_PLUGIN_EXPORT jclass LoadClass(const char* name);
+/// Load class through platform-specific mechanism.
+///
+/// Currently uses application classloader on android,
+/// and JNIEnv->FindClass on other platforms.
+FFI_PLUGIN_EXPORT jclass FindClass(const char* name);
 
+/// Returns Application classLoader (on Android),
+/// which can be used to load application and platform classes.
+///
+/// On other platforms, NULL is returned.
 FFI_PLUGIN_EXPORT jobject GetClassLoader(void);
 
+/// Returns application context on Android.
+///
+/// On other platforms, NULL is returned.
 FFI_PLUGIN_EXPORT jobject GetApplicationContext(void);
 
+/// Returns current activity of the app on Android.
 FFI_PLUGIN_EXPORT jobject GetCurrentActivity(void);
 
-// Migration note: Below inline functions are required by C bindings, but can be moved to dartjni.c
-// once migration to pure dart bindings is complete.
+static inline void attach_thread() {
+  if (jniEnv == NULL) {
+    (*jni->jvm)->AttachCurrentThread(jni->jvm, __ENVP_CAST & jniEnv, NULL);
+  }
+}
 
-// `static inline` because `inline` doesn't work, it may still not
-// inline the function in which case a linker error may be produced.
-//
-// There has to be a better way to do this. Either to force inlining on target
-// platforms, or just leave it as normal function.
-
-static inline void __load_class_into(jclass* cls, const char* name) {
+/// Load class into [cls] using platform specific mechanism
+static inline void load_class_platform(jclass* cls, const char* name) {
 #ifdef __ANDROID__
   jstring className = (*jniEnv)->NewStringUTF(jniEnv, name);
-  *cls = (*jniEnv)->CallObjectMethod(jniEnv, jni.classLoader,
-                                     jni.loadClassMethod, className);
+  *cls = (*jniEnv)->CallObjectMethod(jniEnv, jni->classLoader,
+                                     jni->loadClassMethod, className);
   (*jniEnv)->DeleteLocalRef(jniEnv, className);
 #else
   *cls = (*jniEnv)->FindClass(jniEnv, name);
 #endif
 }
 
-static inline void load_class(jclass* cls, const char* name) {
+static inline void load_class_local_ref(jclass* cls, const char* name) {
   if (*cls == NULL) {
-    __load_class_into(cls, name);
+    acquire_lock(&jni->locks.classLoadingLock);
+    if (*cls == NULL) {
+      load_class_platform(cls, name);
+    }
+    release_lock(&jni->locks.classLoadingLock);
   }
 }
 
-static inline void load_class_gr(jclass* cls, const char* name) {
+static inline void load_class_global_ref(jclass* cls, const char* name) {
   if (*cls == NULL) {
-    jclass tmp;
-    __load_class_into(&tmp, name);
-    *cls = (*jniEnv)->NewGlobalRef(jniEnv, tmp);
-    (*jniEnv)->DeleteLocalRef(jniEnv, tmp);
-  }
-}
-
-static inline void attach_thread() {
-  if (jniEnv == NULL) {
-    (*jni.jvm)->AttachCurrentThread(jni.jvm, __ENVP_CAST & jniEnv, NULL);
+    jclass tmp = NULL;
+    acquire_lock(&jni->locks.classLoadingLock);
+    if (*cls == NULL) {
+      load_class_platform(&tmp, name);
+      *cls = (*jniEnv)->NewGlobalRef(jniEnv, tmp);
+      (*jniEnv)->DeleteLocalRef(jniEnv, tmp);
+    }
+    release_lock(&jni->locks.classLoadingLock);
   }
 }
 
@@ -195,7 +273,11 @@
                                const char* name,
                                const char* sig) {
   if (*res == NULL) {
-    *res = (*jniEnv)->GetMethodID(jniEnv, cls, name, sig);
+    acquire_lock(&jni->locks.methodLoadingLock);
+    if (*res == NULL) {
+      *res = (*jniEnv)->GetMethodID(jniEnv, cls, name, sig);
+    }
+    release_lock(&jni->locks.methodLoadingLock);
   }
 }
 
@@ -204,7 +286,11 @@
                                       const char* name,
                                       const char* sig) {
   if (*res == NULL) {
-    *res = (*jniEnv)->GetStaticMethodID(jniEnv, cls, name, sig);
+    acquire_lock(&jni->locks.methodLoadingLock);
+    if (*res == NULL) {
+      *res = (*jniEnv)->GetStaticMethodID(jniEnv, cls, name, sig);
+    }
+    release_lock(&jni->locks.methodLoadingLock);
   }
 }
 
@@ -213,7 +299,11 @@
                               const char* name,
                               const char* sig) {
   if (*res == NULL) {
-    *res = (*jniEnv)->GetFieldID(jniEnv, cls, name, sig);
+    acquire_lock(&jni->locks.fieldLoadingLock);
+    if (*res == NULL) {
+      *res = (*jniEnv)->GetFieldID(jniEnv, cls, name, sig);
+    }
+    release_lock(&jni->locks.fieldLoadingLock);
   }
 }
 
@@ -222,7 +312,11 @@
                                      const char* name,
                                      const char* sig) {
   if (*res == NULL) {
-    *res = (*jniEnv)->GetStaticFieldID(jniEnv, cls, name, sig);
+    acquire_lock(&jni->locks.fieldLoadingLock);
+    if (*res == NULL) {
+      *res = (*jniEnv)->GetStaticFieldID(jniEnv, cls, name, sig);
+    }
+    release_lock(&jni->locks.fieldLoadingLock);
   }
 }
 
@@ -234,17 +328,18 @@
 
 // These functions are useful for C+Dart bindings, and not required for pure dart bindings.
 
-FFI_PLUGIN_EXPORT JniContext GetJniContext();
+FFI_PLUGIN_EXPORT JniContext* GetJniContextPtr();
+
 /// For use by jni_gen's generated code
 /// don't use these.
 
 // these 2 fn ptr vars will be defined by generated code library
-extern JniContext (*context_getter)(void);
+extern JniContext* (*context_getter)(void);
 extern JNIEnv* (*env_getter)(void);
 
 // this function will be exported by generated code library
 // it will set above 2 variables.
-FFI_PLUGIN_EXPORT void setJniGetters(struct JniContext (*cg)(void),
+FFI_PLUGIN_EXPORT void setJniGetters(struct JniContext* (*cg)(void),
                                      JNIEnv* (*eg)(void));
 
 static inline void load_env() {
diff --git a/pkgs/jnigen/example/notification_plugin/src/notification_plugin.c b/pkgs/jnigen/example/notification_plugin/src/notification_plugin.c
index f4b384e..8eb077c 100644
--- a/pkgs/jnigen/example/notification_plugin/src/notification_plugin.c
+++ b/pkgs/jnigen/example/notification_plugin/src/notification_plugin.c
@@ -9,12 +9,12 @@
 #include "jni.h"
 
 thread_local JNIEnv* jniEnv;
-JniContext jni;
+JniContext* jni;
 
-JniContext (*context_getter)(void);
+JniContext* (*context_getter)(void);
 JNIEnv* (*env_getter)(void);
 
-void setJniGetters(JniContext (*cg)(void), JNIEnv* (*eg)(void)) {
+void setJniGetters(JniContext* (*cg)(void), JNIEnv* (*eg)(void)) {
   context_getter = cg;
   env_getter = eg;
 }
@@ -26,16 +26,16 @@
 FFI_PLUGIN_EXPORT
 JniResult Notifications__ctor() {
   load_env();
-  load_class_gr(&_c_Notifications,
-                "com/example/notification_plugin/Notifications");
+  load_class_global_ref(&_c_Notifications,
+                        "com/example/notification_plugin/Notifications");
   if (_c_Notifications == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_Notifications, &_m_Notifications__ctor, "<init>", "()V");
   if (_m_Notifications__ctor == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result =
       (*jniEnv)->NewObject(jniEnv, _c_Notifications, _m_Notifications__ctor);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -46,17 +46,17 @@
                                           jobject title,
                                           jobject text) {
   load_env();
-  load_class_gr(&_c_Notifications,
-                "com/example/notification_plugin/Notifications");
+  load_class_global_ref(&_c_Notifications,
+                        "com/example/notification_plugin/Notifications");
   if (_c_Notifications == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_method(
       _c_Notifications, &_m_Notifications__showNotification, "showNotification",
       "(Landroid/content/Context;ILjava/lang/String;Ljava/lang/String;)V");
   if (_m_Notifications__showNotification == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallStaticVoidMethod(jniEnv, _c_Notifications,
                                   _m_Notifications__showNotification, context,
                                   notificationID, title, text);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
diff --git a/pkgs/jnigen/example/pdfbox_plugin/src/third_party/dartjni.h b/pkgs/jnigen/example/pdfbox_plugin/src/third_party/dartjni.h
index 39b70bd..eb73318 100644
--- a/pkgs/jnigen/example/pdfbox_plugin/src/third_party/dartjni.h
+++ b/pkgs/jnigen/example/pdfbox_plugin/src/third_party/dartjni.h
@@ -39,6 +39,66 @@
 #define __ENVP_CAST (void**)
 #endif
 
+/// Locking functions for windows and pthread.
+
+#if defined _WIN32
+#include <windows.h>
+
+typedef CRITICAL_SECTION MutexLock;
+
+static inline void init_lock(MutexLock* lock) {
+  InitializeCriticalSection(lock);
+}
+
+static inline void acquire_lock(MutexLock* lock) {
+  EnterCriticalSection(lock);
+}
+
+static inline void release_lock(MutexLock* lock) {
+  LeaveCriticalSection(lock);
+}
+
+static inline void _destroyLock(MutexLock* lock) {
+  DeleteCriticalSection(lock);
+}
+
+#elif defined __DARWIN__ || defined __LINUX__ || defined __ANDROID__ ||        \
+    defined __GNUC__
+#include <pthread.h>
+
+typedef pthread_mutex_t MutexLock;
+
+static inline void init_lock(MutexLock* lock) {
+  pthread_mutex_init(lock, NULL);
+}
+
+static inline void acquire_lock(MutexLock* lock) {
+  pthread_mutex_lock(lock);
+}
+
+static inline void release_lock(MutexLock* lock) {
+  pthread_mutex_unlock(lock);
+}
+
+static inline void _destroyLock(MutexLock* lock) {
+  pthread_mutex_destroy(lock);
+}
+
+#else
+
+#error "No locking support; Possibly unsupported platform"
+
+#endif
+
+typedef struct JniLocks {
+  MutexLock classLoadingLock;
+  MutexLock methodLoadingLock;
+  MutexLock fieldLoadingLock;
+} JniLocks;
+
+/// Represents the error when dart-jni layer has already spawned singleton VM.
+#define DART_JNI_SINGLETON_EXISTS (-99);
+
 /// Stores the global state of the JNI.
 typedef struct JniContext {
   JavaVM* jvm;
@@ -46,13 +106,14 @@
   jmethodID loadClassMethod;
   jobject currentActivity;
   jobject appContext;
+  JniLocks locks;
 } JniContext;
 
 // jniEnv for this thread, used by inline functions in this header,
 // therefore declared as extern.
 extern thread_local JNIEnv* jniEnv;
 
-extern JniContext jni;
+extern JniContext* jni;
 
 /// Types used by JNI API to distinguish between primitive types.
 enum JniType {
@@ -73,19 +134,19 @@
 /// If [exception] is null, it means the result is valid.
 /// It's assumed that the caller knows the expected type in [result].
 typedef struct JniResult {
-  jvalue result;
+  jvalue value;
   jthrowable exception;
 } JniResult;
 
 /// Similar to [JniResult] but for class lookups.
 typedef struct JniClassLookupResult {
-  jclass classRef;
+  jclass value;
   jthrowable exception;
 } JniClassLookupResult;
 
 /// Similar to [JniResult] but for method/field ID lookups.
 typedef struct JniPointerResult {
-  void* id;
+  const void* value;
   jthrowable exception;
 } JniPointerResult;
 
@@ -139,54 +200,71 @@
 
 FFI_PLUGIN_EXPORT JNIEnv* GetJniEnv(void);
 
-FFI_PLUGIN_EXPORT JNIEnv* SpawnJvm(JavaVMInitArgs* args);
+/// Spawn a JVM with given arguments.
+///
+/// Returns JNI_OK on success, and one of the documented JNI error codes on
+/// failure. It returns DART_JNI_SINGLETON_EXISTS if an attempt to spawn multiple
+/// JVMs is made, even if the underlying API potentially supports multiple VMs.
+FFI_PLUGIN_EXPORT int SpawnJvm(JavaVMInitArgs* args);
 
-FFI_PLUGIN_EXPORT jclass LoadClass(const char* name);
+/// Load class through platform-specific mechanism.
+///
+/// Currently uses application classloader on android,
+/// and JNIEnv->FindClass on other platforms.
+FFI_PLUGIN_EXPORT jclass FindClass(const char* name);
 
+/// Returns Application classLoader (on Android),
+/// which can be used to load application and platform classes.
+///
+/// On other platforms, NULL is returned.
 FFI_PLUGIN_EXPORT jobject GetClassLoader(void);
 
+/// Returns application context on Android.
+///
+/// On other platforms, NULL is returned.
 FFI_PLUGIN_EXPORT jobject GetApplicationContext(void);
 
+/// Returns current activity of the app on Android.
 FFI_PLUGIN_EXPORT jobject GetCurrentActivity(void);
 
-// Migration note: Below inline functions are required by C bindings, but can be moved to dartjni.c
-// once migration to pure dart bindings is complete.
+static inline void attach_thread() {
+  if (jniEnv == NULL) {
+    (*jni->jvm)->AttachCurrentThread(jni->jvm, __ENVP_CAST & jniEnv, NULL);
+  }
+}
 
-// `static inline` because `inline` doesn't work, it may still not
-// inline the function in which case a linker error may be produced.
-//
-// There has to be a better way to do this. Either to force inlining on target
-// platforms, or just leave it as normal function.
-
-static inline void __load_class_into(jclass* cls, const char* name) {
+/// Load class into [cls] using platform specific mechanism
+static inline void load_class_platform(jclass* cls, const char* name) {
 #ifdef __ANDROID__
   jstring className = (*jniEnv)->NewStringUTF(jniEnv, name);
-  *cls = (*jniEnv)->CallObjectMethod(jniEnv, jni.classLoader,
-                                     jni.loadClassMethod, className);
+  *cls = (*jniEnv)->CallObjectMethod(jniEnv, jni->classLoader,
+                                     jni->loadClassMethod, className);
   (*jniEnv)->DeleteLocalRef(jniEnv, className);
 #else
   *cls = (*jniEnv)->FindClass(jniEnv, name);
 #endif
 }
 
-static inline void load_class(jclass* cls, const char* name) {
+static inline void load_class_local_ref(jclass* cls, const char* name) {
   if (*cls == NULL) {
-    __load_class_into(cls, name);
+    acquire_lock(&jni->locks.classLoadingLock);
+    if (*cls == NULL) {
+      load_class_platform(cls, name);
+    }
+    release_lock(&jni->locks.classLoadingLock);
   }
 }
 
-static inline void load_class_gr(jclass* cls, const char* name) {
+static inline void load_class_global_ref(jclass* cls, const char* name) {
   if (*cls == NULL) {
-    jclass tmp;
-    __load_class_into(&tmp, name);
-    *cls = (*jniEnv)->NewGlobalRef(jniEnv, tmp);
-    (*jniEnv)->DeleteLocalRef(jniEnv, tmp);
-  }
-}
-
-static inline void attach_thread() {
-  if (jniEnv == NULL) {
-    (*jni.jvm)->AttachCurrentThread(jni.jvm, __ENVP_CAST & jniEnv, NULL);
+    jclass tmp = NULL;
+    acquire_lock(&jni->locks.classLoadingLock);
+    if (*cls == NULL) {
+      load_class_platform(&tmp, name);
+      *cls = (*jniEnv)->NewGlobalRef(jniEnv, tmp);
+      (*jniEnv)->DeleteLocalRef(jniEnv, tmp);
+    }
+    release_lock(&jni->locks.classLoadingLock);
   }
 }
 
@@ -195,7 +273,11 @@
                                const char* name,
                                const char* sig) {
   if (*res == NULL) {
-    *res = (*jniEnv)->GetMethodID(jniEnv, cls, name, sig);
+    acquire_lock(&jni->locks.methodLoadingLock);
+    if (*res == NULL) {
+      *res = (*jniEnv)->GetMethodID(jniEnv, cls, name, sig);
+    }
+    release_lock(&jni->locks.methodLoadingLock);
   }
 }
 
@@ -204,7 +286,11 @@
                                       const char* name,
                                       const char* sig) {
   if (*res == NULL) {
-    *res = (*jniEnv)->GetStaticMethodID(jniEnv, cls, name, sig);
+    acquire_lock(&jni->locks.methodLoadingLock);
+    if (*res == NULL) {
+      *res = (*jniEnv)->GetStaticMethodID(jniEnv, cls, name, sig);
+    }
+    release_lock(&jni->locks.methodLoadingLock);
   }
 }
 
@@ -213,7 +299,11 @@
                               const char* name,
                               const char* sig) {
   if (*res == NULL) {
-    *res = (*jniEnv)->GetFieldID(jniEnv, cls, name, sig);
+    acquire_lock(&jni->locks.fieldLoadingLock);
+    if (*res == NULL) {
+      *res = (*jniEnv)->GetFieldID(jniEnv, cls, name, sig);
+    }
+    release_lock(&jni->locks.fieldLoadingLock);
   }
 }
 
@@ -222,7 +312,11 @@
                                      const char* name,
                                      const char* sig) {
   if (*res == NULL) {
-    *res = (*jniEnv)->GetStaticFieldID(jniEnv, cls, name, sig);
+    acquire_lock(&jni->locks.fieldLoadingLock);
+    if (*res == NULL) {
+      *res = (*jniEnv)->GetStaticFieldID(jniEnv, cls, name, sig);
+    }
+    release_lock(&jni->locks.fieldLoadingLock);
   }
 }
 
@@ -234,17 +328,18 @@
 
 // These functions are useful for C+Dart bindings, and not required for pure dart bindings.
 
-FFI_PLUGIN_EXPORT JniContext GetJniContext();
+FFI_PLUGIN_EXPORT JniContext* GetJniContextPtr();
+
 /// For use by jni_gen's generated code
 /// don't use these.
 
 // these 2 fn ptr vars will be defined by generated code library
-extern JniContext (*context_getter)(void);
+extern JniContext* (*context_getter)(void);
 extern JNIEnv* (*env_getter)(void);
 
 // this function will be exported by generated code library
 // it will set above 2 variables.
-FFI_PLUGIN_EXPORT void setJniGetters(struct JniContext (*cg)(void),
+FFI_PLUGIN_EXPORT void setJniGetters(struct JniContext* (*cg)(void),
                                      JNIEnv* (*eg)(void));
 
 static inline void load_env() {
diff --git a/pkgs/jnigen/example/pdfbox_plugin/src/third_party/pdfbox_plugin.c b/pkgs/jnigen/example/pdfbox_plugin/src/third_party/pdfbox_plugin.c
index 71dcd32..0ce1442 100644
--- a/pkgs/jnigen/example/pdfbox_plugin/src/third_party/pdfbox_plugin.c
+++ b/pkgs/jnigen/example/pdfbox_plugin/src/third_party/pdfbox_plugin.c
@@ -23,12 +23,12 @@
 #include "jni.h"
 
 thread_local JNIEnv* jniEnv;
-JniContext jni;
+JniContext* jni;
 
-JniContext (*context_getter)(void);
+JniContext* (*context_getter)(void);
 JNIEnv* (*env_getter)(void);
 
-void setJniGetters(JniContext (*cg)(void), JNIEnv* (*eg)(void)) {
+void setJniGetters(JniContext* (*cg)(void), JNIEnv* (*eg)(void)) {
   context_getter = cg;
   env_getter = eg;
 }
@@ -40,15 +40,15 @@
 FFI_PLUGIN_EXPORT
 JniResult PDDocument__ctor() {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocument, &_m_PDDocument__ctor, "<init>", "()V");
   if (_m_PDDocument__ctor == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result =
       (*jniEnv)->NewObject(jniEnv, _c_PDDocument, _m_PDDocument__ctor);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -56,16 +56,16 @@
 FFI_PLUGIN_EXPORT
 JniResult PDDocument__ctor1(jobject memUsageSetting) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocument, &_m_PDDocument__ctor1, "<init>",
               "(Lorg/apache/pdfbox/io/MemoryUsageSetting;)V");
   if (_m_PDDocument__ctor1 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->NewObject(jniEnv, _c_PDDocument,
                                          _m_PDDocument__ctor1, memUsageSetting);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -73,16 +73,16 @@
 FFI_PLUGIN_EXPORT
 JniResult PDDocument__ctor2(jobject doc) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocument, &_m_PDDocument__ctor2, "<init>",
               "(Lorg/apache/pdfbox/cos/COSDocument;)V");
   if (_m_PDDocument__ctor2 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result =
       (*jniEnv)->NewObject(jniEnv, _c_PDDocument, _m_PDDocument__ctor2, doc);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -90,17 +90,17 @@
 FFI_PLUGIN_EXPORT
 JniResult PDDocument__ctor3(jobject doc, jobject source) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocument, &_m_PDDocument__ctor3, "<init>",
               "(Lorg/apache/pdfbox/cos/COSDocument;Lorg/apache/pdfbox/io/"
               "RandomAccessRead;)V");
   if (_m_PDDocument__ctor3 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->NewObject(jniEnv, _c_PDDocument,
                                          _m_PDDocument__ctor3, doc, source);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -108,18 +108,18 @@
 FFI_PLUGIN_EXPORT
 JniResult PDDocument__ctor4(jobject doc, jobject source, jobject permission) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocument, &_m_PDDocument__ctor4, "<init>",
               "(Lorg/apache/pdfbox/cos/COSDocument;Lorg/apache/pdfbox/io/"
               "RandomAccessRead;Lorg/apache/pdfbox/pdmodel/encryption/"
               "AccessPermission;)V");
   if (_m_PDDocument__ctor4 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->NewObject(
       jniEnv, _c_PDDocument, _m_PDDocument__ctor4, doc, source, permission);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -127,32 +127,32 @@
 FFI_PLUGIN_EXPORT
 JniResult PDDocument__addPage(jobject self_, jobject page) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocument, &_m_PDDocument__addPage, "addPage",
               "(Lorg/apache/pdfbox/pdmodel/PDPage;)V");
   if (_m_PDDocument__addPage == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDDocument__addPage, page);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDDocument__addSignature = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDDocument__addSignature(jobject self_, jobject sigObject) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocument, &_m_PDDocument__addSignature, "addSignature",
               "(Lorg/apache/pdfbox/pdmodel/interactive/digitalsignature/"
               "PDSignature;)V");
   if (_m_PDDocument__addSignature == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDDocument__addSignature,
                             sigObject);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDDocument__addSignature1 = NULL;
@@ -161,18 +161,18 @@
                                     jobject sigObject,
                                     jobject options) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocument, &_m_PDDocument__addSignature1, "addSignature",
               "(Lorg/apache/pdfbox/pdmodel/interactive/digitalsignature/"
               "PDSignature;Lorg/apache/pdfbox/pdmodel/interactive/"
               "digitalsignature/SignatureOptions;)V");
   if (_m_PDDocument__addSignature1 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDDocument__addSignature1,
                             sigObject, options);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDDocument__addSignature2 = NULL;
@@ -181,18 +181,18 @@
                                     jobject sigObject,
                                     jobject signatureInterface) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocument, &_m_PDDocument__addSignature2, "addSignature",
               "(Lorg/apache/pdfbox/pdmodel/interactive/digitalsignature/"
               "PDSignature;Lorg/apache/pdfbox/pdmodel/interactive/"
               "digitalsignature/SignatureInterface;)V");
   if (_m_PDDocument__addSignature2 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDDocument__addSignature2,
                             sigObject, signatureInterface);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDDocument__addSignature3 = NULL;
@@ -202,19 +202,19 @@
                                     jobject signatureInterface,
                                     jobject options) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocument, &_m_PDDocument__addSignature3, "addSignature",
               "(Lorg/apache/pdfbox/pdmodel/interactive/digitalsignature/"
               "PDSignature;Lorg/apache/pdfbox/pdmodel/interactive/"
               "digitalsignature/SignatureInterface;Lorg/apache/pdfbox/pdmodel/"
               "interactive/digitalsignature/SignatureOptions;)V");
   if (_m_PDDocument__addSignature3 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDDocument__addSignature3,
                             sigObject, signatureInterface, options);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDDocument__addSignatureField = NULL;
@@ -224,66 +224,66 @@
                                         jobject signatureInterface,
                                         jobject options) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocument, &_m_PDDocument__addSignatureField,
               "addSignatureField",
               "(Ljava/util/List;Lorg/apache/pdfbox/pdmodel/interactive/"
               "digitalsignature/SignatureInterface;Lorg/apache/pdfbox/pdmodel/"
               "interactive/digitalsignature/SignatureOptions;)V");
   if (_m_PDDocument__addSignatureField == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDDocument__addSignatureField,
                             sigFields, signatureInterface, options);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDDocument__removePage = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDDocument__removePage(jobject self_, jobject page) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocument, &_m_PDDocument__removePage, "removePage",
               "(Lorg/apache/pdfbox/pdmodel/PDPage;)V");
   if (_m_PDDocument__removePage == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDDocument__removePage, page);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDDocument__removePage1 = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDDocument__removePage1(jobject self_, int32_t pageNumber) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocument, &_m_PDDocument__removePage1, "removePage", "(I)V");
   if (_m_PDDocument__removePage1 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDDocument__removePage1,
                             pageNumber);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDDocument__importPage = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDDocument__importPage(jobject self_, jobject page) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(
       _c_PDDocument, &_m_PDDocument__importPage, "importPage",
       "(Lorg/apache/pdfbox/pdmodel/PDPage;)Lorg/apache/pdfbox/pdmodel/PDPage;");
   if (_m_PDDocument__importPage == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_PDDocument__importPage, page);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -291,16 +291,16 @@
 FFI_PLUGIN_EXPORT
 JniResult PDDocument__getDocument(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocument, &_m_PDDocument__getDocument, "getDocument",
               "()Lorg/apache/pdfbox/cos/COSDocument;");
   if (_m_PDDocument__getDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result =
       (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_PDDocument__getDocument);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -308,17 +308,17 @@
 FFI_PLUGIN_EXPORT
 JniResult PDDocument__getDocumentInformation(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocument, &_m_PDDocument__getDocumentInformation,
               "getDocumentInformation",
               "()Lorg/apache/pdfbox/pdmodel/PDDocumentInformation;");
   if (_m_PDDocument__getDocumentInformation == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_PDDocument__getDocumentInformation);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -326,34 +326,34 @@
 FFI_PLUGIN_EXPORT
 JniResult PDDocument__setDocumentInformation(jobject self_, jobject info) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocument, &_m_PDDocument__setDocumentInformation,
               "setDocumentInformation",
               "(Lorg/apache/pdfbox/pdmodel/PDDocumentInformation;)V");
   if (_m_PDDocument__setDocumentInformation == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_,
                             _m_PDDocument__setDocumentInformation, info);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDDocument__getDocumentCatalog = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDDocument__getDocumentCatalog(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocument, &_m_PDDocument__getDocumentCatalog,
               "getDocumentCatalog",
               "()Lorg/apache/pdfbox/pdmodel/PDDocumentCatalog;");
   if (_m_PDDocument__getDocumentCatalog == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_PDDocument__getDocumentCatalog);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -361,31 +361,31 @@
 FFI_PLUGIN_EXPORT
 JniResult PDDocument__isEncrypted(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocument, &_m_PDDocument__isEncrypted, "isEncrypted", "()Z");
   if (_m_PDDocument__isEncrypted == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   uint8_t _result =
       (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_PDDocument__isEncrypted);
-  return (JniResult){.result = {.z = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.z = _result}, .exception = check_exception()};
 }
 
 jmethodID _m_PDDocument__getEncryption = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDDocument__getEncryption(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocument, &_m_PDDocument__getEncryption, "getEncryption",
               "()Lorg/apache/pdfbox/pdmodel/encryption/PDEncryption;");
   if (_m_PDDocument__getEncryption == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result =
       (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_PDDocument__getEncryption);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -394,35 +394,35 @@
 JniResult PDDocument__setEncryptionDictionary(jobject self_,
                                               jobject encryption) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocument, &_m_PDDocument__setEncryptionDictionary,
               "setEncryptionDictionary",
               "(Lorg/apache/pdfbox/pdmodel/encryption/PDEncryption;)V");
   if (_m_PDDocument__setEncryptionDictionary == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_,
                             _m_PDDocument__setEncryptionDictionary, encryption);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDDocument__getLastSignatureDictionary = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDDocument__getLastSignatureDictionary(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(
       _c_PDDocument, &_m_PDDocument__getLastSignatureDictionary,
       "getLastSignatureDictionary",
       "()Lorg/apache/pdfbox/pdmodel/interactive/digitalsignature/PDSignature;");
   if (_m_PDDocument__getLastSignatureDictionary == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_PDDocument__getLastSignatureDictionary);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -430,16 +430,16 @@
 FFI_PLUGIN_EXPORT
 JniResult PDDocument__getSignatureFields(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocument, &_m_PDDocument__getSignatureFields,
               "getSignatureFields", "()Ljava/util/List;");
   if (_m_PDDocument__getSignatureFields == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_PDDocument__getSignatureFields);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -447,16 +447,16 @@
 FFI_PLUGIN_EXPORT
 JniResult PDDocument__getSignatureDictionaries(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocument, &_m_PDDocument__getSignatureDictionaries,
               "getSignatureDictionaries", "()Ljava/util/List;");
   if (_m_PDDocument__getSignatureDictionaries == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_PDDocument__getSignatureDictionaries);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -465,33 +465,33 @@
 JniResult PDDocument__registerTrueTypeFontForClosing(jobject self_,
                                                      jobject ttf) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocument, &_m_PDDocument__registerTrueTypeFontForClosing,
               "registerTrueTypeFontForClosing",
               "(Lorg/apache/fontbox/ttf/TrueTypeFont;)V");
   if (_m_PDDocument__registerTrueTypeFontForClosing == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_,
                             _m_PDDocument__registerTrueTypeFontForClosing, ttf);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDDocument__load = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDDocument__load(jobject file) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_method(_c_PDDocument, &_m_PDDocument__load, "load",
                      "(Ljava/io/File;)Lorg/apache/pdfbox/pdmodel/PDDocument;");
   if (_m_PDDocument__load == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallStaticObjectMethod(
       jniEnv, _c_PDDocument, _m_PDDocument__load, file);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -499,18 +499,18 @@
 FFI_PLUGIN_EXPORT
 JniResult PDDocument__load1(jobject file, jobject memUsageSetting) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_method(
       _c_PDDocument, &_m_PDDocument__load1, "load",
       "(Ljava/io/File;Lorg/apache/pdfbox/io/MemoryUsageSetting;)Lorg/apache/"
       "pdfbox/pdmodel/PDDocument;");
   if (_m_PDDocument__load1 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallStaticObjectMethod(
       jniEnv, _c_PDDocument, _m_PDDocument__load1, file, memUsageSetting);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -518,17 +518,17 @@
 FFI_PLUGIN_EXPORT
 JniResult PDDocument__load2(jobject file, jobject password) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_method(_c_PDDocument, &_m_PDDocument__load2, "load",
                      "(Ljava/io/File;Ljava/lang/String;)Lorg/apache/pdfbox/"
                      "pdmodel/PDDocument;");
   if (_m_PDDocument__load2 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallStaticObjectMethod(
       jniEnv, _c_PDDocument, _m_PDDocument__load2, file, password);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -538,19 +538,19 @@
                             jobject password,
                             jobject memUsageSetting) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_method(
       _c_PDDocument, &_m_PDDocument__load3, "load",
       "(Ljava/io/File;Ljava/lang/String;Lorg/apache/pdfbox/io/"
       "MemoryUsageSetting;)Lorg/apache/pdfbox/pdmodel/PDDocument;");
   if (_m_PDDocument__load3 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallStaticObjectMethod(
       jniEnv, _c_PDDocument, _m_PDDocument__load3, file, password,
       memUsageSetting);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -561,19 +561,19 @@
                             jobject keyStore,
                             jobject alias) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_method(
       _c_PDDocument, &_m_PDDocument__load4, "load",
       "(Ljava/io/File;Ljava/lang/String;Ljava/io/InputStream;Ljava/lang/"
       "String;)Lorg/apache/pdfbox/pdmodel/PDDocument;");
   if (_m_PDDocument__load4 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallStaticObjectMethod(
       jniEnv, _c_PDDocument, _m_PDDocument__load4, file, password, keyStore,
       alias);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -585,20 +585,20 @@
                             jobject alias,
                             jobject memUsageSetting) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_method(
       _c_PDDocument, &_m_PDDocument__load5, "load",
       "(Ljava/io/File;Ljava/lang/String;Ljava/io/InputStream;Ljava/lang/"
       "String;Lorg/apache/pdfbox/io/MemoryUsageSetting;)Lorg/apache/pdfbox/"
       "pdmodel/PDDocument;");
   if (_m_PDDocument__load5 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallStaticObjectMethod(
       jniEnv, _c_PDDocument, _m_PDDocument__load5, file, password, keyStore,
       alias, memUsageSetting);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -606,17 +606,17 @@
 FFI_PLUGIN_EXPORT
 JniResult PDDocument__load6(jobject input) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_method(
       _c_PDDocument, &_m_PDDocument__load6, "load",
       "(Ljava/io/InputStream;)Lorg/apache/pdfbox/pdmodel/PDDocument;");
   if (_m_PDDocument__load6 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallStaticObjectMethod(
       jniEnv, _c_PDDocument, _m_PDDocument__load6, input);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -624,18 +624,18 @@
 FFI_PLUGIN_EXPORT
 JniResult PDDocument__load7(jobject input, jobject memUsageSetting) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_method(
       _c_PDDocument, &_m_PDDocument__load7, "load",
       "(Ljava/io/InputStream;Lorg/apache/pdfbox/io/MemoryUsageSetting;)Lorg/"
       "apache/pdfbox/pdmodel/PDDocument;");
   if (_m_PDDocument__load7 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallStaticObjectMethod(
       jniEnv, _c_PDDocument, _m_PDDocument__load7, input, memUsageSetting);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -643,17 +643,17 @@
 FFI_PLUGIN_EXPORT
 JniResult PDDocument__load8(jobject input, jobject password) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_method(_c_PDDocument, &_m_PDDocument__load8, "load",
                      "(Ljava/io/InputStream;Ljava/lang/String;)Lorg/apache/"
                      "pdfbox/pdmodel/PDDocument;");
   if (_m_PDDocument__load8 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallStaticObjectMethod(
       jniEnv, _c_PDDocument, _m_PDDocument__load8, input, password);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -664,19 +664,19 @@
                             jobject keyStore,
                             jobject alias) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_method(
       _c_PDDocument, &_m_PDDocument__load9, "load",
       "(Ljava/io/InputStream;Ljava/lang/String;Ljava/io/InputStream;Ljava/lang/"
       "String;)Lorg/apache/pdfbox/pdmodel/PDDocument;");
   if (_m_PDDocument__load9 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallStaticObjectMethod(
       jniEnv, _c_PDDocument, _m_PDDocument__load9, input, password, keyStore,
       alias);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -686,19 +686,19 @@
                              jobject password,
                              jobject memUsageSetting) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_method(
       _c_PDDocument, &_m_PDDocument__load10, "load",
       "(Ljava/io/InputStream;Ljava/lang/String;Lorg/apache/pdfbox/io/"
       "MemoryUsageSetting;)Lorg/apache/pdfbox/pdmodel/PDDocument;");
   if (_m_PDDocument__load10 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallStaticObjectMethod(
       jniEnv, _c_PDDocument, _m_PDDocument__load10, input, password,
       memUsageSetting);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -710,20 +710,20 @@
                              jobject alias,
                              jobject memUsageSetting) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_method(
       _c_PDDocument, &_m_PDDocument__load11, "load",
       "(Ljava/io/InputStream;Ljava/lang/String;Ljava/io/InputStream;Ljava/lang/"
       "String;Lorg/apache/pdfbox/io/MemoryUsageSetting;)Lorg/apache/pdfbox/"
       "pdmodel/PDDocument;");
   if (_m_PDDocument__load11 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallStaticObjectMethod(
       jniEnv, _c_PDDocument, _m_PDDocument__load11, input, password, keyStore,
       alias, memUsageSetting);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -731,16 +731,16 @@
 FFI_PLUGIN_EXPORT
 JniResult PDDocument__load12(jobject input) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_method(_c_PDDocument, &_m_PDDocument__load12, "load",
                      "([B)Lorg/apache/pdfbox/pdmodel/PDDocument;");
   if (_m_PDDocument__load12 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallStaticObjectMethod(
       jniEnv, _c_PDDocument, _m_PDDocument__load12, input);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -748,17 +748,17 @@
 FFI_PLUGIN_EXPORT
 JniResult PDDocument__load13(jobject input, jobject password) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_method(
       _c_PDDocument, &_m_PDDocument__load13, "load",
       "([BLjava/lang/String;)Lorg/apache/pdfbox/pdmodel/PDDocument;");
   if (_m_PDDocument__load13 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallStaticObjectMethod(
       jniEnv, _c_PDDocument, _m_PDDocument__load13, input, password);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -769,18 +769,18 @@
                              jobject keyStore,
                              jobject alias) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_method(_c_PDDocument, &_m_PDDocument__load14, "load",
                      "([BLjava/lang/String;Ljava/io/InputStream;Ljava/lang/"
                      "String;)Lorg/apache/pdfbox/pdmodel/PDDocument;");
   if (_m_PDDocument__load14 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallStaticObjectMethod(
       jniEnv, _c_PDDocument, _m_PDDocument__load14, input, password, keyStore,
       alias);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -792,19 +792,19 @@
                              jobject alias,
                              jobject memUsageSetting) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_method(
       _c_PDDocument, &_m_PDDocument__load15, "load",
       "([BLjava/lang/String;Ljava/io/InputStream;Ljava/lang/String;Lorg/apache/"
       "pdfbox/io/MemoryUsageSetting;)Lorg/apache/pdfbox/pdmodel/PDDocument;");
   if (_m_PDDocument__load15 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallStaticObjectMethod(
       jniEnv, _c_PDDocument, _m_PDDocument__load15, input, password, keyStore,
       alias, memUsageSetting);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -812,61 +812,61 @@
 FFI_PLUGIN_EXPORT
 JniResult PDDocument__save(jobject self_, jobject fileName) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocument, &_m_PDDocument__save, "save",
               "(Ljava/lang/String;)V");
   if (_m_PDDocument__save == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDDocument__save, fileName);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDDocument__save1 = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDDocument__save1(jobject self_, jobject file) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocument, &_m_PDDocument__save1, "save",
               "(Ljava/io/File;)V");
   if (_m_PDDocument__save1 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDDocument__save1, file);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDDocument__save2 = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDDocument__save2(jobject self_, jobject output) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocument, &_m_PDDocument__save2, "save",
               "(Ljava/io/OutputStream;)V");
   if (_m_PDDocument__save2 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDDocument__save2, output);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDDocument__saveIncremental = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDDocument__saveIncremental(jobject self_, jobject output) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocument, &_m_PDDocument__saveIncremental, "saveIncremental",
               "(Ljava/io/OutputStream;)V");
   if (_m_PDDocument__saveIncremental == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDDocument__saveIncremental,
                             output);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDDocument__saveIncremental1 = NULL;
@@ -875,16 +875,16 @@
                                        jobject output,
                                        jobject objectsToWrite) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocument, &_m_PDDocument__saveIncremental1,
               "saveIncremental", "(Ljava/io/OutputStream;Ljava/util/Set;)V");
   if (_m_PDDocument__saveIncremental1 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDDocument__saveIncremental1,
                             output, objectsToWrite);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDDocument__saveIncrementalForExternalSigning = NULL;
@@ -892,18 +892,18 @@
 JniResult PDDocument__saveIncrementalForExternalSigning(jobject self_,
                                                         jobject output) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocument, &_m_PDDocument__saveIncrementalForExternalSigning,
               "saveIncrementalForExternalSigning",
               "(Ljava/io/OutputStream;)Lorg/apache/pdfbox/pdmodel/interactive/"
               "digitalsignature/ExternalSigningSupport;");
   if (_m_PDDocument__saveIncrementalForExternalSigning == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_PDDocument__saveIncrementalForExternalSigning, output);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -911,16 +911,16 @@
 FFI_PLUGIN_EXPORT
 JniResult PDDocument__getPage(jobject self_, int32_t pageIndex) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocument, &_m_PDDocument__getPage, "getPage",
               "(I)Lorg/apache/pdfbox/pdmodel/PDPage;");
   if (_m_PDDocument__getPage == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_PDDocument__getPage, pageIndex);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -928,16 +928,16 @@
 FFI_PLUGIN_EXPORT
 JniResult PDDocument__getPages(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocument, &_m_PDDocument__getPages, "getPages",
               "()Lorg/apache/pdfbox/pdmodel/PDPageTree;");
   if (_m_PDDocument__getPages == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result =
       (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_PDDocument__getPages);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -945,62 +945,62 @@
 FFI_PLUGIN_EXPORT
 JniResult PDDocument__getNumberOfPages(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocument, &_m_PDDocument__getNumberOfPages,
               "getNumberOfPages", "()I");
   if (_m_PDDocument__getNumberOfPages == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   int32_t _result =
       (*jniEnv)->CallIntMethod(jniEnv, self_, _m_PDDocument__getNumberOfPages);
-  return (JniResult){.result = {.i = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.i = _result}, .exception = check_exception()};
 }
 
 jmethodID _m_PDDocument__close = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDDocument__close(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocument, &_m_PDDocument__close, "close", "()V");
   if (_m_PDDocument__close == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDDocument__close);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDDocument__protect = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDDocument__protect(jobject self_, jobject policy) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocument, &_m_PDDocument__protect, "protect",
               "(Lorg/apache/pdfbox/pdmodel/encryption/ProtectionPolicy;)V");
   if (_m_PDDocument__protect == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDDocument__protect, policy);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDDocument__getCurrentAccessPermission = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDDocument__getCurrentAccessPermission(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocument, &_m_PDDocument__getCurrentAccessPermission,
               "getCurrentAccessPermission",
               "()Lorg/apache/pdfbox/pdmodel/encryption/AccessPermission;");
   if (_m_PDDocument__getCurrentAccessPermission == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_PDDocument__getCurrentAccessPermission);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1008,16 +1008,16 @@
 FFI_PLUGIN_EXPORT
 JniResult PDDocument__isAllSecurityToBeRemoved(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocument, &_m_PDDocument__isAllSecurityToBeRemoved,
               "isAllSecurityToBeRemoved", "()Z");
   if (_m_PDDocument__isAllSecurityToBeRemoved == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   uint8_t _result = (*jniEnv)->CallBooleanMethod(
       jniEnv, self_, _m_PDDocument__isAllSecurityToBeRemoved);
-  return (JniResult){.result = {.z = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.z = _result}, .exception = check_exception()};
 }
 
 jmethodID _m_PDDocument__setAllSecurityToBeRemoved = NULL;
@@ -1025,33 +1025,33 @@
 JniResult PDDocument__setAllSecurityToBeRemoved(jobject self_,
                                                 uint8_t removeAllSecurity) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocument, &_m_PDDocument__setAllSecurityToBeRemoved,
               "setAllSecurityToBeRemoved", "(Z)V");
   if (_m_PDDocument__setAllSecurityToBeRemoved == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_,
                             _m_PDDocument__setAllSecurityToBeRemoved,
                             removeAllSecurity);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDDocument__getDocumentId = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDDocument__getDocumentId(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocument, &_m_PDDocument__getDocumentId, "getDocumentId",
               "()Ljava/lang/Long;");
   if (_m_PDDocument__getDocumentId == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result =
       (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_PDDocument__getDocumentId);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1059,62 +1059,62 @@
 FFI_PLUGIN_EXPORT
 JniResult PDDocument__setDocumentId(jobject self_, jobject docId) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocument, &_m_PDDocument__setDocumentId, "setDocumentId",
               "(Ljava/lang/Long;)V");
   if (_m_PDDocument__setDocumentId == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDDocument__setDocumentId, docId);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDDocument__getVersion = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDDocument__getVersion(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocument, &_m_PDDocument__getVersion, "getVersion", "()F");
   if (_m_PDDocument__getVersion == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   float _result =
       (*jniEnv)->CallFloatMethod(jniEnv, self_, _m_PDDocument__getVersion);
-  return (JniResult){.result = {.f = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.f = _result}, .exception = check_exception()};
 }
 
 jmethodID _m_PDDocument__setVersion = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDDocument__setVersion(jobject self_, float newVersion) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocument, &_m_PDDocument__setVersion, "setVersion", "(F)V");
   if (_m_PDDocument__setVersion == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDDocument__setVersion,
                             newVersion);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDDocument__getResourceCache = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDDocument__getResourceCache(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocument, &_m_PDDocument__getResourceCache,
               "getResourceCache",
               "()Lorg/apache/pdfbox/pdmodel/ResourceCache;");
   if (_m_PDDocument__getResourceCache == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_PDDocument__getResourceCache);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1122,17 +1122,17 @@
 FFI_PLUGIN_EXPORT
 JniResult PDDocument__setResourceCache(jobject self_, jobject resourceCache) {
   load_env();
-  load_class_gr(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+  load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
   if (_c_PDDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocument, &_m_PDDocument__setResourceCache,
               "setResourceCache",
               "(Lorg/apache/pdfbox/pdmodel/ResourceCache;)V");
   if (_m_PDDocument__setResourceCache == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDDocument__setResourceCache,
                             resourceCache);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 // org.apache.pdfbox.pdmodel.PDDocumentInformation
@@ -1142,17 +1142,17 @@
 FFI_PLUGIN_EXPORT
 JniResult PDDocumentInformation__ctor() {
   load_env();
-  load_class_gr(&_c_PDDocumentInformation,
-                "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+  load_class_global_ref(&_c_PDDocumentInformation,
+                        "org/apache/pdfbox/pdmodel/PDDocumentInformation");
   if (_c_PDDocumentInformation == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocumentInformation, &_m_PDDocumentInformation__ctor,
               "<init>", "()V");
   if (_m_PDDocumentInformation__ctor == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->NewObject(jniEnv, _c_PDDocumentInformation,
                                          _m_PDDocumentInformation__ctor);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1160,17 +1160,17 @@
 FFI_PLUGIN_EXPORT
 JniResult PDDocumentInformation__ctor1(jobject dic) {
   load_env();
-  load_class_gr(&_c_PDDocumentInformation,
-                "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+  load_class_global_ref(&_c_PDDocumentInformation,
+                        "org/apache/pdfbox/pdmodel/PDDocumentInformation");
   if (_c_PDDocumentInformation == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocumentInformation, &_m_PDDocumentInformation__ctor1,
               "<init>", "(Lorg/apache/pdfbox/cos/COSDictionary;)V");
   if (_m_PDDocumentInformation__ctor1 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->NewObject(jniEnv, _c_PDDocumentInformation,
                                          _m_PDDocumentInformation__ctor1, dic);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1178,17 +1178,17 @@
 FFI_PLUGIN_EXPORT
 JniResult PDDocumentInformation__getCOSObject(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDDocumentInformation,
-                "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+  load_class_global_ref(&_c_PDDocumentInformation,
+                        "org/apache/pdfbox/pdmodel/PDDocumentInformation");
   if (_c_PDDocumentInformation == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocumentInformation, &_m_PDDocumentInformation__getCOSObject,
               "getCOSObject", "()Lorg/apache/pdfbox/cos/COSDictionary;");
   if (_m_PDDocumentInformation__getCOSObject == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_PDDocumentInformation__getCOSObject);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1197,20 +1197,20 @@
 JniResult PDDocumentInformation__getPropertyStringValue(jobject self_,
                                                         jobject propertyKey) {
   load_env();
-  load_class_gr(&_c_PDDocumentInformation,
-                "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+  load_class_global_ref(&_c_PDDocumentInformation,
+                        "org/apache/pdfbox/pdmodel/PDDocumentInformation");
   if (_c_PDDocumentInformation == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocumentInformation,
               &_m_PDDocumentInformation__getPropertyStringValue,
               "getPropertyStringValue",
               "(Ljava/lang/String;)Ljava/lang/Object;");
   if (_m_PDDocumentInformation__getPropertyStringValue == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_PDDocumentInformation__getPropertyStringValue,
       propertyKey);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1218,17 +1218,17 @@
 FFI_PLUGIN_EXPORT
 JniResult PDDocumentInformation__getTitle(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDDocumentInformation,
-                "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+  load_class_global_ref(&_c_PDDocumentInformation,
+                        "org/apache/pdfbox/pdmodel/PDDocumentInformation");
   if (_c_PDDocumentInformation == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocumentInformation, &_m_PDDocumentInformation__getTitle,
               "getTitle", "()Ljava/lang/String;");
   if (_m_PDDocumentInformation__getTitle == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_PDDocumentInformation__getTitle);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1236,34 +1236,34 @@
 FFI_PLUGIN_EXPORT
 JniResult PDDocumentInformation__setTitle(jobject self_, jobject title) {
   load_env();
-  load_class_gr(&_c_PDDocumentInformation,
-                "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+  load_class_global_ref(&_c_PDDocumentInformation,
+                        "org/apache/pdfbox/pdmodel/PDDocumentInformation");
   if (_c_PDDocumentInformation == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocumentInformation, &_m_PDDocumentInformation__setTitle,
               "setTitle", "(Ljava/lang/String;)V");
   if (_m_PDDocumentInformation__setTitle == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDDocumentInformation__setTitle,
                             title);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDDocumentInformation__getAuthor = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDDocumentInformation__getAuthor(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDDocumentInformation,
-                "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+  load_class_global_ref(&_c_PDDocumentInformation,
+                        "org/apache/pdfbox/pdmodel/PDDocumentInformation");
   if (_c_PDDocumentInformation == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocumentInformation, &_m_PDDocumentInformation__getAuthor,
               "getAuthor", "()Ljava/lang/String;");
   if (_m_PDDocumentInformation__getAuthor == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_PDDocumentInformation__getAuthor);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1271,34 +1271,34 @@
 FFI_PLUGIN_EXPORT
 JniResult PDDocumentInformation__setAuthor(jobject self_, jobject author) {
   load_env();
-  load_class_gr(&_c_PDDocumentInformation,
-                "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+  load_class_global_ref(&_c_PDDocumentInformation,
+                        "org/apache/pdfbox/pdmodel/PDDocumentInformation");
   if (_c_PDDocumentInformation == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocumentInformation, &_m_PDDocumentInformation__setAuthor,
               "setAuthor", "(Ljava/lang/String;)V");
   if (_m_PDDocumentInformation__setAuthor == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDDocumentInformation__setAuthor,
                             author);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDDocumentInformation__getSubject = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDDocumentInformation__getSubject(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDDocumentInformation,
-                "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+  load_class_global_ref(&_c_PDDocumentInformation,
+                        "org/apache/pdfbox/pdmodel/PDDocumentInformation");
   if (_c_PDDocumentInformation == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocumentInformation, &_m_PDDocumentInformation__getSubject,
               "getSubject", "()Ljava/lang/String;");
   if (_m_PDDocumentInformation__getSubject == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_PDDocumentInformation__getSubject);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1306,34 +1306,34 @@
 FFI_PLUGIN_EXPORT
 JniResult PDDocumentInformation__setSubject(jobject self_, jobject subject) {
   load_env();
-  load_class_gr(&_c_PDDocumentInformation,
-                "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+  load_class_global_ref(&_c_PDDocumentInformation,
+                        "org/apache/pdfbox/pdmodel/PDDocumentInformation");
   if (_c_PDDocumentInformation == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocumentInformation, &_m_PDDocumentInformation__setSubject,
               "setSubject", "(Ljava/lang/String;)V");
   if (_m_PDDocumentInformation__setSubject == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDDocumentInformation__setSubject,
                             subject);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDDocumentInformation__getKeywords = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDDocumentInformation__getKeywords(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDDocumentInformation,
-                "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+  load_class_global_ref(&_c_PDDocumentInformation,
+                        "org/apache/pdfbox/pdmodel/PDDocumentInformation");
   if (_c_PDDocumentInformation == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocumentInformation, &_m_PDDocumentInformation__getKeywords,
               "getKeywords", "()Ljava/lang/String;");
   if (_m_PDDocumentInformation__getKeywords == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_PDDocumentInformation__getKeywords);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1341,34 +1341,34 @@
 FFI_PLUGIN_EXPORT
 JniResult PDDocumentInformation__setKeywords(jobject self_, jobject keywords) {
   load_env();
-  load_class_gr(&_c_PDDocumentInformation,
-                "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+  load_class_global_ref(&_c_PDDocumentInformation,
+                        "org/apache/pdfbox/pdmodel/PDDocumentInformation");
   if (_c_PDDocumentInformation == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocumentInformation, &_m_PDDocumentInformation__setKeywords,
               "setKeywords", "(Ljava/lang/String;)V");
   if (_m_PDDocumentInformation__setKeywords == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_,
                             _m_PDDocumentInformation__setKeywords, keywords);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDDocumentInformation__getCreator = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDDocumentInformation__getCreator(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDDocumentInformation,
-                "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+  load_class_global_ref(&_c_PDDocumentInformation,
+                        "org/apache/pdfbox/pdmodel/PDDocumentInformation");
   if (_c_PDDocumentInformation == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocumentInformation, &_m_PDDocumentInformation__getCreator,
               "getCreator", "()Ljava/lang/String;");
   if (_m_PDDocumentInformation__getCreator == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_PDDocumentInformation__getCreator);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1376,34 +1376,34 @@
 FFI_PLUGIN_EXPORT
 JniResult PDDocumentInformation__setCreator(jobject self_, jobject creator) {
   load_env();
-  load_class_gr(&_c_PDDocumentInformation,
-                "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+  load_class_global_ref(&_c_PDDocumentInformation,
+                        "org/apache/pdfbox/pdmodel/PDDocumentInformation");
   if (_c_PDDocumentInformation == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocumentInformation, &_m_PDDocumentInformation__setCreator,
               "setCreator", "(Ljava/lang/String;)V");
   if (_m_PDDocumentInformation__setCreator == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDDocumentInformation__setCreator,
                             creator);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDDocumentInformation__getProducer = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDDocumentInformation__getProducer(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDDocumentInformation,
-                "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+  load_class_global_ref(&_c_PDDocumentInformation,
+                        "org/apache/pdfbox/pdmodel/PDDocumentInformation");
   if (_c_PDDocumentInformation == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocumentInformation, &_m_PDDocumentInformation__getProducer,
               "getProducer", "()Ljava/lang/String;");
   if (_m_PDDocumentInformation__getProducer == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_PDDocumentInformation__getProducer);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1411,35 +1411,35 @@
 FFI_PLUGIN_EXPORT
 JniResult PDDocumentInformation__setProducer(jobject self_, jobject producer) {
   load_env();
-  load_class_gr(&_c_PDDocumentInformation,
-                "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+  load_class_global_ref(&_c_PDDocumentInformation,
+                        "org/apache/pdfbox/pdmodel/PDDocumentInformation");
   if (_c_PDDocumentInformation == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocumentInformation, &_m_PDDocumentInformation__setProducer,
               "setProducer", "(Ljava/lang/String;)V");
   if (_m_PDDocumentInformation__setProducer == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_,
                             _m_PDDocumentInformation__setProducer, producer);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDDocumentInformation__getCreationDate = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDDocumentInformation__getCreationDate(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDDocumentInformation,
-                "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+  load_class_global_ref(&_c_PDDocumentInformation,
+                        "org/apache/pdfbox/pdmodel/PDDocumentInformation");
   if (_c_PDDocumentInformation == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocumentInformation,
               &_m_PDDocumentInformation__getCreationDate, "getCreationDate",
               "()Ljava/util/Calendar;");
   if (_m_PDDocumentInformation__getCreationDate == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_PDDocumentInformation__getCreationDate);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1447,36 +1447,36 @@
 FFI_PLUGIN_EXPORT
 JniResult PDDocumentInformation__setCreationDate(jobject self_, jobject date) {
   load_env();
-  load_class_gr(&_c_PDDocumentInformation,
-                "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+  load_class_global_ref(&_c_PDDocumentInformation,
+                        "org/apache/pdfbox/pdmodel/PDDocumentInformation");
   if (_c_PDDocumentInformation == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocumentInformation,
               &_m_PDDocumentInformation__setCreationDate, "setCreationDate",
               "(Ljava/util/Calendar;)V");
   if (_m_PDDocumentInformation__setCreationDate == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_,
                             _m_PDDocumentInformation__setCreationDate, date);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDDocumentInformation__getModificationDate = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDDocumentInformation__getModificationDate(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDDocumentInformation,
-                "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+  load_class_global_ref(&_c_PDDocumentInformation,
+                        "org/apache/pdfbox/pdmodel/PDDocumentInformation");
   if (_c_PDDocumentInformation == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocumentInformation,
               &_m_PDDocumentInformation__getModificationDate,
               "getModificationDate", "()Ljava/util/Calendar;");
   if (_m_PDDocumentInformation__getModificationDate == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_PDDocumentInformation__getModificationDate);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1485,35 +1485,35 @@
 JniResult PDDocumentInformation__setModificationDate(jobject self_,
                                                      jobject date) {
   load_env();
-  load_class_gr(&_c_PDDocumentInformation,
-                "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+  load_class_global_ref(&_c_PDDocumentInformation,
+                        "org/apache/pdfbox/pdmodel/PDDocumentInformation");
   if (_c_PDDocumentInformation == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocumentInformation,
               &_m_PDDocumentInformation__setModificationDate,
               "setModificationDate", "(Ljava/util/Calendar;)V");
   if (_m_PDDocumentInformation__setModificationDate == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(
       jniEnv, self_, _m_PDDocumentInformation__setModificationDate, date);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDDocumentInformation__getTrapped = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDDocumentInformation__getTrapped(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDDocumentInformation,
-                "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+  load_class_global_ref(&_c_PDDocumentInformation,
+                        "org/apache/pdfbox/pdmodel/PDDocumentInformation");
   if (_c_PDDocumentInformation == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocumentInformation, &_m_PDDocumentInformation__getTrapped,
               "getTrapped", "()Ljava/lang/String;");
   if (_m_PDDocumentInformation__getTrapped == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_PDDocumentInformation__getTrapped);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1521,18 +1521,18 @@
 FFI_PLUGIN_EXPORT
 JniResult PDDocumentInformation__getMetadataKeys(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDDocumentInformation,
-                "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+  load_class_global_ref(&_c_PDDocumentInformation,
+                        "org/apache/pdfbox/pdmodel/PDDocumentInformation");
   if (_c_PDDocumentInformation == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocumentInformation,
               &_m_PDDocumentInformation__getMetadataKeys, "getMetadataKeys",
               "()Ljava/util/Set;");
   if (_m_PDDocumentInformation__getMetadataKeys == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_PDDocumentInformation__getMetadataKeys);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1541,20 +1541,20 @@
 JniResult PDDocumentInformation__getCustomMetadataValue(jobject self_,
                                                         jobject fieldName) {
   load_env();
-  load_class_gr(&_c_PDDocumentInformation,
-                "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+  load_class_global_ref(&_c_PDDocumentInformation,
+                        "org/apache/pdfbox/pdmodel/PDDocumentInformation");
   if (_c_PDDocumentInformation == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocumentInformation,
               &_m_PDDocumentInformation__getCustomMetadataValue,
               "getCustomMetadataValue",
               "(Ljava/lang/String;)Ljava/lang/String;");
   if (_m_PDDocumentInformation__getCustomMetadataValue == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_PDDocumentInformation__getCustomMetadataValue,
       fieldName);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1564,37 +1564,37 @@
                                                         jobject fieldName,
                                                         jobject fieldValue) {
   load_env();
-  load_class_gr(&_c_PDDocumentInformation,
-                "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+  load_class_global_ref(&_c_PDDocumentInformation,
+                        "org/apache/pdfbox/pdmodel/PDDocumentInformation");
   if (_c_PDDocumentInformation == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocumentInformation,
               &_m_PDDocumentInformation__setCustomMetadataValue,
               "setCustomMetadataValue",
               "(Ljava/lang/String;Ljava/lang/String;)V");
   if (_m_PDDocumentInformation__setCustomMetadataValue == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_,
                             _m_PDDocumentInformation__setCustomMetadataValue,
                             fieldName, fieldValue);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDDocumentInformation__setTrapped = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDDocumentInformation__setTrapped(jobject self_, jobject value) {
   load_env();
-  load_class_gr(&_c_PDDocumentInformation,
-                "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+  load_class_global_ref(&_c_PDDocumentInformation,
+                        "org/apache/pdfbox/pdmodel/PDDocumentInformation");
   if (_c_PDDocumentInformation == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDDocumentInformation, &_m_PDDocumentInformation__setTrapped,
               "setTrapped", "(Ljava/lang/String;)V");
   if (_m_PDDocumentInformation__setTrapped == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDDocumentInformation__setTrapped,
                             value);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 // org.apache.pdfbox.text.PDFTextStripper
@@ -1604,15 +1604,16 @@
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__ctor() {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__ctor, "<init>", "()V");
   if (_m_PDFTextStripper__ctor == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->NewObject(jniEnv, _c_PDFTextStripper,
                                          _m_PDFTextStripper__ctor);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1620,16 +1621,17 @@
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__getText(jobject self_, jobject doc) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__getText, "getText",
               "(Lorg/apache/pdfbox/pdmodel/PDDocument;)Ljava/lang/String;");
   if (_m_PDFTextStripper__getText == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_PDFTextStripper__getText, doc);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1639,219 +1641,233 @@
                                      jobject doc,
                                      jobject outputStream) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__writeText, "writeText",
               "(Lorg/apache/pdfbox/pdmodel/PDDocument;Ljava/io/Writer;)V");
   if (_m_PDFTextStripper__writeText == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__writeText, doc,
                             outputStream);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__processPages = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__processPages(jobject self_, jobject pages) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__processPages,
               "processPages", "(Lorg/apache/pdfbox/pdmodel/PDPageTree;)V");
   if (_m_PDFTextStripper__processPages == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__processPages,
                             pages);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__startDocument = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__startDocument(jobject self_, jobject document) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__startDocument,
               "startDocument", "(Lorg/apache/pdfbox/pdmodel/PDDocument;)V");
   if (_m_PDFTextStripper__startDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__startDocument,
                             document);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__endDocument = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__endDocument(jobject self_, jobject document) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__endDocument,
               "endDocument", "(Lorg/apache/pdfbox/pdmodel/PDDocument;)V");
   if (_m_PDFTextStripper__endDocument == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__endDocument,
                             document);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__processPage = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__processPage(jobject self_, jobject page) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__processPage,
               "processPage", "(Lorg/apache/pdfbox/pdmodel/PDPage;)V");
   if (_m_PDFTextStripper__processPage == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__processPage,
                             page);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__startArticle = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__startArticle(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__startArticle,
               "startArticle", "()V");
   if (_m_PDFTextStripper__startArticle == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__startArticle);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__startArticle1 = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__startArticle1(jobject self_, uint8_t isLTR) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__startArticle1,
               "startArticle", "(Z)V");
   if (_m_PDFTextStripper__startArticle1 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__startArticle1,
                             isLTR);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__endArticle = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__endArticle(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__endArticle, "endArticle",
               "()V");
   if (_m_PDFTextStripper__endArticle == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__endArticle);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__startPage = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__startPage(jobject self_, jobject page) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__startPage, "startPage",
               "(Lorg/apache/pdfbox/pdmodel/PDPage;)V");
   if (_m_PDFTextStripper__startPage == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__startPage, page);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__endPage = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__endPage(jobject self_, jobject page) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__endPage, "endPage",
               "(Lorg/apache/pdfbox/pdmodel/PDPage;)V");
   if (_m_PDFTextStripper__endPage == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__endPage, page);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__writePage = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__writePage(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__writePage, "writePage",
               "()V");
   if (_m_PDFTextStripper__writePage == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__writePage);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__writeLineSeparator = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__writeLineSeparator(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__writeLineSeparator,
               "writeLineSeparator", "()V");
   if (_m_PDFTextStripper__writeLineSeparator == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_,
                             _m_PDFTextStripper__writeLineSeparator);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__writeWordSeparator = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__writeWordSeparator(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__writeWordSeparator,
               "writeWordSeparator", "()V");
   if (_m_PDFTextStripper__writeWordSeparator == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_,
                             _m_PDFTextStripper__writeWordSeparator);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__writeCharacters = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__writeCharacters(jobject self_, jobject text) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__writeCharacters,
               "writeCharacters", "(Lorg/apache/pdfbox/text/TextPosition;)V");
   if (_m_PDFTextStripper__writeCharacters == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__writeCharacters,
                             text);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__writeString = NULL;
@@ -1860,145 +1876,154 @@
                                        jobject text,
                                        jobject textPositions) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__writeString,
               "writeString", "(Ljava/lang/String;Ljava/util/List;)V");
   if (_m_PDFTextStripper__writeString == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__writeString,
                             text, textPositions);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__writeString1 = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__writeString1(jobject self_, jobject text) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__writeString1,
               "writeString", "(Ljava/lang/String;)V");
   if (_m_PDFTextStripper__writeString1 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__writeString1,
                             text);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__processTextPosition = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__processTextPosition(jobject self_, jobject text) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__processTextPosition,
               "processTextPosition",
               "(Lorg/apache/pdfbox/text/TextPosition;)V");
   if (_m_PDFTextStripper__processTextPosition == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_,
                             _m_PDFTextStripper__processTextPosition, text);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__getStartPage = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__getStartPage(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__getStartPage,
               "getStartPage", "()I");
   if (_m_PDFTextStripper__getStartPage == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   int32_t _result =
       (*jniEnv)->CallIntMethod(jniEnv, self_, _m_PDFTextStripper__getStartPage);
-  return (JniResult){.result = {.i = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.i = _result}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__setStartPage = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__setStartPage(jobject self_, int32_t startPageValue) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__setStartPage,
               "setStartPage", "(I)V");
   if (_m_PDFTextStripper__setStartPage == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__setStartPage,
                             startPageValue);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__getEndPage = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__getEndPage(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__getEndPage, "getEndPage",
               "()I");
   if (_m_PDFTextStripper__getEndPage == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   int32_t _result =
       (*jniEnv)->CallIntMethod(jniEnv, self_, _m_PDFTextStripper__getEndPage);
-  return (JniResult){.result = {.i = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.i = _result}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__setEndPage = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__setEndPage(jobject self_, int32_t endPageValue) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__setEndPage, "setEndPage",
               "(I)V");
   if (_m_PDFTextStripper__setEndPage == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__setEndPage,
                             endPageValue);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__setLineSeparator = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__setLineSeparator(jobject self_, jobject separator) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__setLineSeparator,
               "setLineSeparator", "(Ljava/lang/String;)V");
   if (_m_PDFTextStripper__setLineSeparator == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__setLineSeparator,
                             separator);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__getLineSeparator = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__getLineSeparator(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__getLineSeparator,
               "getLineSeparator", "()Ljava/lang/String;");
   if (_m_PDFTextStripper__getLineSeparator == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_PDFTextStripper__getLineSeparator);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -2006,16 +2031,17 @@
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__getWordSeparator(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__getWordSeparator,
               "getWordSeparator", "()Ljava/lang/String;");
   if (_m_PDFTextStripper__getWordSeparator == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_PDFTextStripper__getWordSeparator);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -2023,65 +2049,69 @@
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__setWordSeparator(jobject self_, jobject separator) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__setWordSeparator,
               "setWordSeparator", "(Ljava/lang/String;)V");
   if (_m_PDFTextStripper__setWordSeparator == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__setWordSeparator,
                             separator);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__getSuppressDuplicateOverlappingText = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__getSuppressDuplicateOverlappingText(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper,
               &_m_PDFTextStripper__getSuppressDuplicateOverlappingText,
               "getSuppressDuplicateOverlappingText", "()Z");
   if (_m_PDFTextStripper__getSuppressDuplicateOverlappingText == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   uint8_t _result = (*jniEnv)->CallBooleanMethod(
       jniEnv, self_, _m_PDFTextStripper__getSuppressDuplicateOverlappingText);
-  return (JniResult){.result = {.z = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.z = _result}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__getCurrentPageNo = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__getCurrentPageNo(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__getCurrentPageNo,
               "getCurrentPageNo", "()I");
   if (_m_PDFTextStripper__getCurrentPageNo == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   int32_t _result = (*jniEnv)->CallIntMethod(
       jniEnv, self_, _m_PDFTextStripper__getCurrentPageNo);
-  return (JniResult){.result = {.i = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.i = _result}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__getOutput = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__getOutput(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__getOutput, "getOutput",
               "()Ljava/io/Writer;");
   if (_m_PDFTextStripper__getOutput == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result =
       (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_PDFTextStripper__getOutput);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -2089,16 +2119,17 @@
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__getCharactersByArticle(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__getCharactersByArticle,
               "getCharactersByArticle", "()Ljava/util/List;");
   if (_m_PDFTextStripper__getCharactersByArticle == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_PDFTextStripper__getCharactersByArticle);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -2108,34 +2139,36 @@
     jobject self_,
     uint8_t suppressDuplicateOverlappingTextValue) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper,
               &_m_PDFTextStripper__setSuppressDuplicateOverlappingText,
               "setSuppressDuplicateOverlappingText", "(Z)V");
   if (_m_PDFTextStripper__setSuppressDuplicateOverlappingText == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(
       jniEnv, self_, _m_PDFTextStripper__setSuppressDuplicateOverlappingText,
       suppressDuplicateOverlappingTextValue);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__getSeparateByBeads = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__getSeparateByBeads(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__getSeparateByBeads,
               "getSeparateByBeads", "()Z");
   if (_m_PDFTextStripper__getSeparateByBeads == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   uint8_t _result = (*jniEnv)->CallBooleanMethod(
       jniEnv, self_, _m_PDFTextStripper__getSeparateByBeads);
-  return (JniResult){.result = {.z = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.z = _result}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__setShouldSeparateByBeads = NULL;
@@ -2144,35 +2177,37 @@
     jobject self_,
     uint8_t aShouldSeparateByBeads) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__setShouldSeparateByBeads,
               "setShouldSeparateByBeads", "(Z)V");
   if (_m_PDFTextStripper__setShouldSeparateByBeads == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_,
                             _m_PDFTextStripper__setShouldSeparateByBeads,
                             aShouldSeparateByBeads);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__getEndBookmark = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__getEndBookmark(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__getEndBookmark,
               "getEndBookmark",
               "()Lorg/apache/pdfbox/pdmodel/interactive/documentnavigation/"
               "outline/PDOutlineItem;");
   if (_m_PDFTextStripper__getEndBookmark == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_PDFTextStripper__getEndBookmark);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -2180,36 +2215,38 @@
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__setEndBookmark(jobject self_, jobject aEndBookmark) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__setEndBookmark,
               "setEndBookmark",
               "(Lorg/apache/pdfbox/pdmodel/interactive/documentnavigation/"
               "outline/PDOutlineItem;)V");
   if (_m_PDFTextStripper__setEndBookmark == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__setEndBookmark,
                             aEndBookmark);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__getStartBookmark = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__getStartBookmark(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__getStartBookmark,
               "getStartBookmark",
               "()Lorg/apache/pdfbox/pdmodel/interactive/documentnavigation/"
               "outline/PDOutlineItem;");
   if (_m_PDFTextStripper__getStartBookmark == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_PDFTextStripper__getStartBookmark);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -2218,34 +2255,36 @@
 JniResult PDFTextStripper__setStartBookmark(jobject self_,
                                             jobject aStartBookmark) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__setStartBookmark,
               "setStartBookmark",
               "(Lorg/apache/pdfbox/pdmodel/interactive/documentnavigation/"
               "outline/PDOutlineItem;)V");
   if (_m_PDFTextStripper__setStartBookmark == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__setStartBookmark,
                             aStartBookmark);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__getAddMoreFormatting = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__getAddMoreFormatting(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__getAddMoreFormatting,
               "getAddMoreFormatting", "()Z");
   if (_m_PDFTextStripper__getAddMoreFormatting == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   uint8_t _result = (*jniEnv)->CallBooleanMethod(
       jniEnv, self_, _m_PDFTextStripper__getAddMoreFormatting);
-  return (JniResult){.result = {.z = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.z = _result}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__setAddMoreFormatting = NULL;
@@ -2253,33 +2292,35 @@
 JniResult PDFTextStripper__setAddMoreFormatting(jobject self_,
                                                 uint8_t newAddMoreFormatting) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__setAddMoreFormatting,
               "setAddMoreFormatting", "(Z)V");
   if (_m_PDFTextStripper__setAddMoreFormatting == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_,
                             _m_PDFTextStripper__setAddMoreFormatting,
                             newAddMoreFormatting);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__getSortByPosition = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__getSortByPosition(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__getSortByPosition,
               "getSortByPosition", "()Z");
   if (_m_PDFTextStripper__getSortByPosition == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   uint8_t _result = (*jniEnv)->CallBooleanMethod(
       jniEnv, self_, _m_PDFTextStripper__getSortByPosition);
-  return (JniResult){.result = {.z = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.z = _result}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__setSortByPosition = NULL;
@@ -2287,32 +2328,34 @@
 JniResult PDFTextStripper__setSortByPosition(jobject self_,
                                              uint8_t newSortByPosition) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__setSortByPosition,
               "setSortByPosition", "(Z)V");
   if (_m_PDFTextStripper__setSortByPosition == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(
       jniEnv, self_, _m_PDFTextStripper__setSortByPosition, newSortByPosition);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__getSpacingTolerance = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__getSpacingTolerance(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__getSpacingTolerance,
               "getSpacingTolerance", "()F");
   if (_m_PDFTextStripper__getSpacingTolerance == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   float _result = (*jniEnv)->CallFloatMethod(
       jniEnv, self_, _m_PDFTextStripper__getSpacingTolerance);
-  return (JniResult){.result = {.f = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.f = _result}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__setSpacingTolerance = NULL;
@@ -2320,33 +2363,35 @@
 JniResult PDFTextStripper__setSpacingTolerance(jobject self_,
                                                float spacingToleranceValue) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__setSpacingTolerance,
               "setSpacingTolerance", "(F)V");
   if (_m_PDFTextStripper__setSpacingTolerance == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_,
                             _m_PDFTextStripper__setSpacingTolerance,
                             spacingToleranceValue);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__getAverageCharTolerance = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__getAverageCharTolerance(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__getAverageCharTolerance,
               "getAverageCharTolerance", "()F");
   if (_m_PDFTextStripper__getAverageCharTolerance == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   float _result = (*jniEnv)->CallFloatMethod(
       jniEnv, self_, _m_PDFTextStripper__getAverageCharTolerance);
-  return (JniResult){.result = {.f = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.f = _result}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__setAverageCharTolerance = NULL;
@@ -2355,33 +2400,35 @@
     jobject self_,
     float averageCharToleranceValue) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__setAverageCharTolerance,
               "setAverageCharTolerance", "(F)V");
   if (_m_PDFTextStripper__setAverageCharTolerance == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_,
                             _m_PDFTextStripper__setAverageCharTolerance,
                             averageCharToleranceValue);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__getIndentThreshold = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__getIndentThreshold(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__getIndentThreshold,
               "getIndentThreshold", "()F");
   if (_m_PDFTextStripper__getIndentThreshold == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   float _result = (*jniEnv)->CallFloatMethod(
       jniEnv, self_, _m_PDFTextStripper__getIndentThreshold);
-  return (JniResult){.result = {.f = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.f = _result}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__setIndentThreshold = NULL;
@@ -2389,33 +2436,35 @@
 JniResult PDFTextStripper__setIndentThreshold(jobject self_,
                                               float indentThresholdValue) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__setIndentThreshold,
               "setIndentThreshold", "(F)V");
   if (_m_PDFTextStripper__setIndentThreshold == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_,
                             _m_PDFTextStripper__setIndentThreshold,
                             indentThresholdValue);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__getDropThreshold = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__getDropThreshold(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__getDropThreshold,
               "getDropThreshold", "()F");
   if (_m_PDFTextStripper__getDropThreshold == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   float _result = (*jniEnv)->CallFloatMethod(
       jniEnv, self_, _m_PDFTextStripper__getDropThreshold);
-  return (JniResult){.result = {.f = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.f = _result}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__setDropThreshold = NULL;
@@ -2423,32 +2472,34 @@
 JniResult PDFTextStripper__setDropThreshold(jobject self_,
                                             float dropThresholdValue) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__setDropThreshold,
               "setDropThreshold", "(F)V");
   if (_m_PDFTextStripper__setDropThreshold == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__setDropThreshold,
                             dropThresholdValue);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__getParagraphStart = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__getParagraphStart(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__getParagraphStart,
               "getParagraphStart", "()Ljava/lang/String;");
   if (_m_PDFTextStripper__getParagraphStart == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_PDFTextStripper__getParagraphStart);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -2456,32 +2507,34 @@
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__setParagraphStart(jobject self_, jobject s) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__setParagraphStart,
               "setParagraphStart", "(Ljava/lang/String;)V");
   if (_m_PDFTextStripper__setParagraphStart == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_,
                             _m_PDFTextStripper__setParagraphStart, s);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__getParagraphEnd = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__getParagraphEnd(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__getParagraphEnd,
               "getParagraphEnd", "()Ljava/lang/String;");
   if (_m_PDFTextStripper__getParagraphEnd == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_PDFTextStripper__getParagraphEnd);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -2489,32 +2542,34 @@
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__setParagraphEnd(jobject self_, jobject s) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__setParagraphEnd,
               "setParagraphEnd", "(Ljava/lang/String;)V");
   if (_m_PDFTextStripper__setParagraphEnd == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__setParagraphEnd,
                             s);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__getPageStart = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__getPageStart(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__getPageStart,
               "getPageStart", "()Ljava/lang/String;");
   if (_m_PDFTextStripper__getPageStart == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_PDFTextStripper__getPageStart);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -2522,32 +2577,34 @@
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__setPageStart(jobject self_, jobject pageStartValue) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__setPageStart,
               "setPageStart", "(Ljava/lang/String;)V");
   if (_m_PDFTextStripper__setPageStart == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__setPageStart,
                             pageStartValue);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__getPageEnd = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__getPageEnd(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__getPageEnd, "getPageEnd",
               "()Ljava/lang/String;");
   if (_m_PDFTextStripper__getPageEnd == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_,
                                                 _m_PDFTextStripper__getPageEnd);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -2555,32 +2612,34 @@
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__setPageEnd(jobject self_, jobject pageEndValue) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__setPageEnd, "setPageEnd",
               "(Ljava/lang/String;)V");
   if (_m_PDFTextStripper__setPageEnd == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__setPageEnd,
                             pageEndValue);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__getArticleStart = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__getArticleStart(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__getArticleStart,
               "getArticleStart", "()Ljava/lang/String;");
   if (_m_PDFTextStripper__getArticleStart == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_PDFTextStripper__getArticleStart);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -2589,32 +2648,34 @@
 JniResult PDFTextStripper__setArticleStart(jobject self_,
                                            jobject articleStartValue) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__setArticleStart,
               "setArticleStart", "(Ljava/lang/String;)V");
   if (_m_PDFTextStripper__setArticleStart == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__setArticleStart,
                             articleStartValue);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__getArticleEnd = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__getArticleEnd(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__getArticleEnd,
               "getArticleEnd", "()Ljava/lang/String;");
   if (_m_PDFTextStripper__getArticleEnd == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_PDFTextStripper__getArticleEnd);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -2623,94 +2684,100 @@
 JniResult PDFTextStripper__setArticleEnd(jobject self_,
                                          jobject articleEndValue) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__setArticleEnd,
               "setArticleEnd", "(Ljava/lang/String;)V");
   if (_m_PDFTextStripper__setArticleEnd == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__setArticleEnd,
                             articleEndValue);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__writeParagraphSeparator = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__writeParagraphSeparator(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__writeParagraphSeparator,
               "writeParagraphSeparator", "()V");
   if (_m_PDFTextStripper__writeParagraphSeparator == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_,
                             _m_PDFTextStripper__writeParagraphSeparator);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__writeParagraphStart = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__writeParagraphStart(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__writeParagraphStart,
               "writeParagraphStart", "()V");
   if (_m_PDFTextStripper__writeParagraphStart == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_,
                             _m_PDFTextStripper__writeParagraphStart);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__writeParagraphEnd = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__writeParagraphEnd(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__writeParagraphEnd,
               "writeParagraphEnd", "()V");
   if (_m_PDFTextStripper__writeParagraphEnd == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_,
                             _m_PDFTextStripper__writeParagraphEnd);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__writePageStart = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__writePageStart(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__writePageStart,
               "writePageStart", "()V");
   if (_m_PDFTextStripper__writePageStart == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__writePageStart);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__writePageEnd = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__writePageEnd(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__writePageEnd,
               "writePageEnd", "()V");
   if (_m_PDFTextStripper__writePageEnd == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__writePageEnd);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__setListItemPatterns = NULL;
@@ -2718,32 +2785,34 @@
 JniResult PDFTextStripper__setListItemPatterns(jobject self_,
                                                jobject patterns) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__setListItemPatterns,
               "setListItemPatterns", "(Ljava/util/List;)V");
   if (_m_PDFTextStripper__setListItemPatterns == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_,
                             _m_PDFTextStripper__setListItemPatterns, patterns);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_PDFTextStripper__getListItemPatterns = NULL;
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__getListItemPatterns(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_PDFTextStripper, &_m_PDFTextStripper__getListItemPatterns,
               "getListItemPatterns", "()Ljava/util/List;");
   if (_m_PDFTextStripper__getListItemPatterns == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_PDFTextStripper__getListItemPatterns);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -2751,18 +2820,19 @@
 FFI_PLUGIN_EXPORT
 JniResult PDFTextStripper__matchPattern(jobject string, jobject patterns) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_method(
       _c_PDFTextStripper, &_m_PDFTextStripper__matchPattern, "matchPattern",
       "(Ljava/lang/String;Ljava/util/List;)Ljava/util/regex/Pattern;");
   if (_m_PDFTextStripper__matchPattern == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallStaticObjectMethod(
       jniEnv, _c_PDFTextStripper, _m_PDFTextStripper__matchPattern, string,
       patterns);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -2770,92 +2840,99 @@
 FFI_PLUGIN_EXPORT
 JniResult get_PDFTextStripper__LINE_SEPARATOR(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_field(_c_PDFTextStripper, &_f_PDFTextStripper__LINE_SEPARATOR,
              "LINE_SEPARATOR", "Ljava/lang/String;");
   jobject _result = to_global_ref((*jniEnv)->GetObjectField(
       jniEnv, self_, _f_PDFTextStripper__LINE_SEPARATOR));
-  return (JniResult){.result = {.l = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.l = _result}, .exception = check_exception()};
 }
 
 jfieldID _f_PDFTextStripper__charactersByArticle = NULL;
 FFI_PLUGIN_EXPORT
 JniResult get_PDFTextStripper__charactersByArticle(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_field(_c_PDFTextStripper, &_f_PDFTextStripper__charactersByArticle,
              "charactersByArticle", "Ljava/util/ArrayList;");
   jobject _result = to_global_ref((*jniEnv)->GetObjectField(
       jniEnv, self_, _f_PDFTextStripper__charactersByArticle));
-  return (JniResult){.result = {.l = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.l = _result}, .exception = check_exception()};
 }
 
 FFI_PLUGIN_EXPORT
 JniResult set_PDFTextStripper__charactersByArticle(jobject self_,
                                                    jobject value) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_field(_c_PDFTextStripper, &_f_PDFTextStripper__charactersByArticle,
              "charactersByArticle", "Ljava/util/ArrayList;");
   (*jniEnv)->SetObjectField(jniEnv, self_,
                             _f_PDFTextStripper__charactersByArticle, value);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jfieldID _f_PDFTextStripper__document = NULL;
 FFI_PLUGIN_EXPORT
 JniResult get_PDFTextStripper__document(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_field(_c_PDFTextStripper, &_f_PDFTextStripper__document, "document",
              "Lorg/apache/pdfbox/pdmodel/PDDocument;");
   jobject _result = to_global_ref(
       (*jniEnv)->GetObjectField(jniEnv, self_, _f_PDFTextStripper__document));
-  return (JniResult){.result = {.l = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.l = _result}, .exception = check_exception()};
 }
 
 FFI_PLUGIN_EXPORT
 JniResult set_PDFTextStripper__document(jobject self_, jobject value) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_field(_c_PDFTextStripper, &_f_PDFTextStripper__document, "document",
              "Lorg/apache/pdfbox/pdmodel/PDDocument;");
   (*jniEnv)->SetObjectField(jniEnv, self_, _f_PDFTextStripper__document, value);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jfieldID _f_PDFTextStripper__output = NULL;
 FFI_PLUGIN_EXPORT
 JniResult get_PDFTextStripper__output(jobject self_) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_field(_c_PDFTextStripper, &_f_PDFTextStripper__output, "output",
              "Ljava/io/Writer;");
   jobject _result = to_global_ref(
       (*jniEnv)->GetObjectField(jniEnv, self_, _f_PDFTextStripper__output));
-  return (JniResult){.result = {.l = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.l = _result}, .exception = check_exception()};
 }
 
 FFI_PLUGIN_EXPORT
 JniResult set_PDFTextStripper__output(jobject self_, jobject value) {
   load_env();
-  load_class_gr(&_c_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+  load_class_global_ref(&_c_PDFTextStripper,
+                        "org/apache/pdfbox/text/PDFTextStripper");
   if (_c_PDFTextStripper == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_field(_c_PDFTextStripper, &_f_PDFTextStripper__output, "output",
              "Ljava/io/Writer;");
   (*jniEnv)->SetObjectField(jniEnv, self_, _f_PDFTextStripper__output, value);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
diff --git a/pkgs/jnigen/lib/src/bindings/c_bindings.dart b/pkgs/jnigen/lib/src/bindings/c_bindings.dart
index f57e79c..2e87e3d 100644
--- a/pkgs/jnigen/lib/src/bindings/c_bindings.dart
+++ b/pkgs/jnigen/lib/src/bindings/c_bindings.dart
@@ -13,7 +13,7 @@
   static final indent = ' ' * 4;
   static const jniResultType = 'JniResult';
   static const ifError =
-      '(JniResult){.result = {.j = 0}, .exception = check_exception()}';
+      '(JniResult){.value = {.j = 0}, .exception = check_exception()}';
 
   // These should be avoided in parameter names.
   static const _cTypeKeywords = {
@@ -171,7 +171,7 @@
         final cResultType = getCType(f.type.name);
         final unionField = getJValueField(f.type);
         accessorStatements = '$indent$cResultType _result = $getterExpr;\n'
-            '${indent}return (JniResult){.result = '
+            '${indent}return (JniResult){.value = '
             '{.$unionField = _result}, .exception = check_exception()};';
       }
 
@@ -197,7 +197,7 @@
   final String _loadEnvCall = '${indent}load_env();';
 
   String _loadClassCall(String classVar, String internalName) {
-    return '${indent}load_class_gr(&$classVar, "$internalName");\n'
+    return '${indent}load_class_global_ref(&$classVar, "$internalName");\n'
         '${indent}if ($classVar == NULL) return $ifError;';
   }
 
@@ -267,7 +267,7 @@
       valuePart = '_result';
     }
     const exceptionPart = 'check_exception()';
-    return '${indent}return (JniResult){.result = {.$unionField = $valuePart}, '
+    return '${indent}return (JniResult){.value = {.$unionField = $valuePart}, '
         '.exception = $exceptionPart};';
   }
 
@@ -289,11 +289,11 @@
       '#include "dartjni.h"\n'
       '\n';
   static const defines = 'thread_local JNIEnv *jniEnv;\n'
-      'JniContext jni;\n\n'
-      'JniContext (*context_getter)(void);\n'
+      'JniContext *jni;\n\n'
+      'JniContext *(*context_getter)(void);\n'
       'JNIEnv *(*env_getter)(void);\n'
       '\n';
-  static const initializers = 'void setJniGetters(JniContext (*cg)(void),\n'
+  static const initializers = 'void setJniGetters(JniContext *(*cg)(void),\n'
       '        JNIEnv *(*eg)(void)) {\n'
       '    context_getter = cg;\n'
       '    env_getter = eg;\n'
diff --git a/pkgs/jnigen/lib/src/bindings/dart_generator.dart b/pkgs/jnigen/lib/src/bindings/dart_generator.dart
index 58561f9..b238548 100644
--- a/pkgs/jnigen/lib/src/bindings/dart_generator.dart
+++ b/pkgs/jnigen/lib/src/bindings/dart_generator.dart
@@ -1119,7 +1119,7 @@
     $callExpr;
     final \$o = $_jPointer.fromAddress(await \$p.first);
     final \$k = $returnTypeClass.getClass().reference;
-    if ($_jni.Jni.env.IsInstanceOf(\$o, \$k) == 0) {
+    if (!$_jni.Jni.env.IsInstanceOf(\$o, \$k)) {
       throw "Failed";
     }
     return $returning;
diff --git a/pkgs/jnigen/lib/src/tools/build_summarizer.dart b/pkgs/jnigen/lib/src/tools/build_summarizer.dart
index 30ce426..5d5a7ef 100644
--- a/pkgs/jnigen/lib/src/tools/build_summarizer.dart
+++ b/pkgs/jnigen/lib/src/tools/build_summarizer.dart
@@ -67,8 +67,8 @@
   }
   if (!jarExists) {
     log.info('Building ApiSummarizer component. '
-        'This might take some time. \n'
-        'The build will be cached for subsequent runs\n');
+        'This might take some time. '
+        'The build will be cached for subsequent runs.');
   }
   if (!jarExists || isJarStale || force) {
     await buildApiSummarizer();
diff --git a/pkgs/jnigen/test/kotlin_test/lib/kotlin.dart b/pkgs/jnigen/test/kotlin_test/lib/kotlin.dart
index 094aa46..59119b4 100644
--- a/pkgs/jnigen/test/kotlin_test/lib/kotlin.dart
+++ b/pkgs/jnigen/test/kotlin_test/lib/kotlin.dart
@@ -65,7 +65,7 @@
     _sayHello(reference, $c.reference).object;
     final $o = jni.JObjectPtr.fromAddress(await $p.first);
     final $k = const jni.JStringType().getClass().reference;
-    if (jni.Jni.env.IsInstanceOf($o, $k) == 0) {
+    if (!jni.Jni.env.IsInstanceOf($o, $k)) {
       throw "Failed";
     }
     return const jni.JStringType().fromRef($o);
@@ -91,7 +91,7 @@
     _sayHello1(reference, string.reference, $c.reference).object;
     final $o = jni.JObjectPtr.fromAddress(await $p.first);
     final $k = const jni.JStringType().getClass().reference;
-    if (jni.Jni.env.IsInstanceOf($o, $k) == 0) {
+    if (!jni.Jni.env.IsInstanceOf($o, $k)) {
       throw "Failed";
     }
     return const jni.JStringType().fromRef($o);
diff --git a/pkgs/jnigen/test/kotlin_test/src/dartjni.h b/pkgs/jnigen/test/kotlin_test/src/dartjni.h
index 39b70bd..eb73318 100644
--- a/pkgs/jnigen/test/kotlin_test/src/dartjni.h
+++ b/pkgs/jnigen/test/kotlin_test/src/dartjni.h
@@ -39,6 +39,66 @@
 #define __ENVP_CAST (void**)
 #endif
 
+/// Locking functions for windows and pthread.
+
+#if defined _WIN32
+#include <windows.h>
+
+typedef CRITICAL_SECTION MutexLock;
+
+static inline void init_lock(MutexLock* lock) {
+  InitializeCriticalSection(lock);
+}
+
+static inline void acquire_lock(MutexLock* lock) {
+  EnterCriticalSection(lock);
+}
+
+static inline void release_lock(MutexLock* lock) {
+  LeaveCriticalSection(lock);
+}
+
+static inline void _destroyLock(MutexLock* lock) {
+  DeleteCriticalSection(lock);
+}
+
+#elif defined __DARWIN__ || defined __LINUX__ || defined __ANDROID__ ||        \
+    defined __GNUC__
+#include <pthread.h>
+
+typedef pthread_mutex_t MutexLock;
+
+static inline void init_lock(MutexLock* lock) {
+  pthread_mutex_init(lock, NULL);
+}
+
+static inline void acquire_lock(MutexLock* lock) {
+  pthread_mutex_lock(lock);
+}
+
+static inline void release_lock(MutexLock* lock) {
+  pthread_mutex_unlock(lock);
+}
+
+static inline void _destroyLock(MutexLock* lock) {
+  pthread_mutex_destroy(lock);
+}
+
+#else
+
+#error "No locking support; Possibly unsupported platform"
+
+#endif
+
+typedef struct JniLocks {
+  MutexLock classLoadingLock;
+  MutexLock methodLoadingLock;
+  MutexLock fieldLoadingLock;
+} JniLocks;
+
+/// Represents the error when dart-jni layer has already spawned singleton VM.
+#define DART_JNI_SINGLETON_EXISTS (-99);
+
 /// Stores the global state of the JNI.
 typedef struct JniContext {
   JavaVM* jvm;
@@ -46,13 +106,14 @@
   jmethodID loadClassMethod;
   jobject currentActivity;
   jobject appContext;
+  JniLocks locks;
 } JniContext;
 
 // jniEnv for this thread, used by inline functions in this header,
 // therefore declared as extern.
 extern thread_local JNIEnv* jniEnv;
 
-extern JniContext jni;
+extern JniContext* jni;
 
 /// Types used by JNI API to distinguish between primitive types.
 enum JniType {
@@ -73,19 +134,19 @@
 /// If [exception] is null, it means the result is valid.
 /// It's assumed that the caller knows the expected type in [result].
 typedef struct JniResult {
-  jvalue result;
+  jvalue value;
   jthrowable exception;
 } JniResult;
 
 /// Similar to [JniResult] but for class lookups.
 typedef struct JniClassLookupResult {
-  jclass classRef;
+  jclass value;
   jthrowable exception;
 } JniClassLookupResult;
 
 /// Similar to [JniResult] but for method/field ID lookups.
 typedef struct JniPointerResult {
-  void* id;
+  const void* value;
   jthrowable exception;
 } JniPointerResult;
 
@@ -139,54 +200,71 @@
 
 FFI_PLUGIN_EXPORT JNIEnv* GetJniEnv(void);
 
-FFI_PLUGIN_EXPORT JNIEnv* SpawnJvm(JavaVMInitArgs* args);
+/// Spawn a JVM with given arguments.
+///
+/// Returns JNI_OK on success, and one of the documented JNI error codes on
+/// failure. It returns DART_JNI_SINGLETON_EXISTS if an attempt to spawn multiple
+/// JVMs is made, even if the underlying API potentially supports multiple VMs.
+FFI_PLUGIN_EXPORT int SpawnJvm(JavaVMInitArgs* args);
 
-FFI_PLUGIN_EXPORT jclass LoadClass(const char* name);
+/// Load class through platform-specific mechanism.
+///
+/// Currently uses application classloader on android,
+/// and JNIEnv->FindClass on other platforms.
+FFI_PLUGIN_EXPORT jclass FindClass(const char* name);
 
+/// Returns Application classLoader (on Android),
+/// which can be used to load application and platform classes.
+///
+/// On other platforms, NULL is returned.
 FFI_PLUGIN_EXPORT jobject GetClassLoader(void);
 
+/// Returns application context on Android.
+///
+/// On other platforms, NULL is returned.
 FFI_PLUGIN_EXPORT jobject GetApplicationContext(void);
 
+/// Returns current activity of the app on Android.
 FFI_PLUGIN_EXPORT jobject GetCurrentActivity(void);
 
-// Migration note: Below inline functions are required by C bindings, but can be moved to dartjni.c
-// once migration to pure dart bindings is complete.
+static inline void attach_thread() {
+  if (jniEnv == NULL) {
+    (*jni->jvm)->AttachCurrentThread(jni->jvm, __ENVP_CAST & jniEnv, NULL);
+  }
+}
 
-// `static inline` because `inline` doesn't work, it may still not
-// inline the function in which case a linker error may be produced.
-//
-// There has to be a better way to do this. Either to force inlining on target
-// platforms, or just leave it as normal function.
-
-static inline void __load_class_into(jclass* cls, const char* name) {
+/// Load class into [cls] using platform specific mechanism
+static inline void load_class_platform(jclass* cls, const char* name) {
 #ifdef __ANDROID__
   jstring className = (*jniEnv)->NewStringUTF(jniEnv, name);
-  *cls = (*jniEnv)->CallObjectMethod(jniEnv, jni.classLoader,
-                                     jni.loadClassMethod, className);
+  *cls = (*jniEnv)->CallObjectMethod(jniEnv, jni->classLoader,
+                                     jni->loadClassMethod, className);
   (*jniEnv)->DeleteLocalRef(jniEnv, className);
 #else
   *cls = (*jniEnv)->FindClass(jniEnv, name);
 #endif
 }
 
-static inline void load_class(jclass* cls, const char* name) {
+static inline void load_class_local_ref(jclass* cls, const char* name) {
   if (*cls == NULL) {
-    __load_class_into(cls, name);
+    acquire_lock(&jni->locks.classLoadingLock);
+    if (*cls == NULL) {
+      load_class_platform(cls, name);
+    }
+    release_lock(&jni->locks.classLoadingLock);
   }
 }
 
-static inline void load_class_gr(jclass* cls, const char* name) {
+static inline void load_class_global_ref(jclass* cls, const char* name) {
   if (*cls == NULL) {
-    jclass tmp;
-    __load_class_into(&tmp, name);
-    *cls = (*jniEnv)->NewGlobalRef(jniEnv, tmp);
-    (*jniEnv)->DeleteLocalRef(jniEnv, tmp);
-  }
-}
-
-static inline void attach_thread() {
-  if (jniEnv == NULL) {
-    (*jni.jvm)->AttachCurrentThread(jni.jvm, __ENVP_CAST & jniEnv, NULL);
+    jclass tmp = NULL;
+    acquire_lock(&jni->locks.classLoadingLock);
+    if (*cls == NULL) {
+      load_class_platform(&tmp, name);
+      *cls = (*jniEnv)->NewGlobalRef(jniEnv, tmp);
+      (*jniEnv)->DeleteLocalRef(jniEnv, tmp);
+    }
+    release_lock(&jni->locks.classLoadingLock);
   }
 }
 
@@ -195,7 +273,11 @@
                                const char* name,
                                const char* sig) {
   if (*res == NULL) {
-    *res = (*jniEnv)->GetMethodID(jniEnv, cls, name, sig);
+    acquire_lock(&jni->locks.methodLoadingLock);
+    if (*res == NULL) {
+      *res = (*jniEnv)->GetMethodID(jniEnv, cls, name, sig);
+    }
+    release_lock(&jni->locks.methodLoadingLock);
   }
 }
 
@@ -204,7 +286,11 @@
                                       const char* name,
                                       const char* sig) {
   if (*res == NULL) {
-    *res = (*jniEnv)->GetStaticMethodID(jniEnv, cls, name, sig);
+    acquire_lock(&jni->locks.methodLoadingLock);
+    if (*res == NULL) {
+      *res = (*jniEnv)->GetStaticMethodID(jniEnv, cls, name, sig);
+    }
+    release_lock(&jni->locks.methodLoadingLock);
   }
 }
 
@@ -213,7 +299,11 @@
                               const char* name,
                               const char* sig) {
   if (*res == NULL) {
-    *res = (*jniEnv)->GetFieldID(jniEnv, cls, name, sig);
+    acquire_lock(&jni->locks.fieldLoadingLock);
+    if (*res == NULL) {
+      *res = (*jniEnv)->GetFieldID(jniEnv, cls, name, sig);
+    }
+    release_lock(&jni->locks.fieldLoadingLock);
   }
 }
 
@@ -222,7 +312,11 @@
                                      const char* name,
                                      const char* sig) {
   if (*res == NULL) {
-    *res = (*jniEnv)->GetStaticFieldID(jniEnv, cls, name, sig);
+    acquire_lock(&jni->locks.fieldLoadingLock);
+    if (*res == NULL) {
+      *res = (*jniEnv)->GetStaticFieldID(jniEnv, cls, name, sig);
+    }
+    release_lock(&jni->locks.fieldLoadingLock);
   }
 }
 
@@ -234,17 +328,18 @@
 
 // These functions are useful for C+Dart bindings, and not required for pure dart bindings.
 
-FFI_PLUGIN_EXPORT JniContext GetJniContext();
+FFI_PLUGIN_EXPORT JniContext* GetJniContextPtr();
+
 /// For use by jni_gen's generated code
 /// don't use these.
 
 // these 2 fn ptr vars will be defined by generated code library
-extern JniContext (*context_getter)(void);
+extern JniContext* (*context_getter)(void);
 extern JNIEnv* (*env_getter)(void);
 
 // this function will be exported by generated code library
 // it will set above 2 variables.
-FFI_PLUGIN_EXPORT void setJniGetters(struct JniContext (*cg)(void),
+FFI_PLUGIN_EXPORT void setJniGetters(struct JniContext* (*cg)(void),
                                      JNIEnv* (*eg)(void));
 
 static inline void load_env() {
diff --git a/pkgs/jnigen/test/kotlin_test/src/kotlin.c b/pkgs/jnigen/test/kotlin_test/src/kotlin.c
index 7b1426c..b70978e 100644
--- a/pkgs/jnigen/test/kotlin_test/src/kotlin.c
+++ b/pkgs/jnigen/test/kotlin_test/src/kotlin.c
@@ -9,12 +9,12 @@
 #include "jni.h"
 
 thread_local JNIEnv* jniEnv;
-JniContext jni;
+JniContext* jni;
 
-JniContext (*context_getter)(void);
+JniContext* (*context_getter)(void);
 JNIEnv* (*env_getter)(void);
 
-void setJniGetters(JniContext (*cg)(void), JNIEnv* (*eg)(void)) {
+void setJniGetters(JniContext* (*cg)(void), JNIEnv* (*eg)(void)) {
   context_getter = cg;
   env_getter = eg;
 }
@@ -26,15 +26,16 @@
 FFI_PLUGIN_EXPORT
 JniResult SuspendFun__ctor() {
   load_env();
-  load_class_gr(&_c_SuspendFun, "com/github/dart_lang/jnigen/SuspendFun");
+  load_class_global_ref(&_c_SuspendFun,
+                        "com/github/dart_lang/jnigen/SuspendFun");
   if (_c_SuspendFun == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_SuspendFun, &_m_SuspendFun__ctor, "<init>", "()V");
   if (_m_SuspendFun__ctor == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result =
       (*jniEnv)->NewObject(jniEnv, _c_SuspendFun, _m_SuspendFun__ctor);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -42,16 +43,17 @@
 FFI_PLUGIN_EXPORT
 JniResult SuspendFun__sayHello(jobject self_, jobject continuation) {
   load_env();
-  load_class_gr(&_c_SuspendFun, "com/github/dart_lang/jnigen/SuspendFun");
+  load_class_global_ref(&_c_SuspendFun,
+                        "com/github/dart_lang/jnigen/SuspendFun");
   if (_c_SuspendFun == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_SuspendFun, &_m_SuspendFun__sayHello, "sayHello",
               "(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;");
   if (_m_SuspendFun__sayHello == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_SuspendFun__sayHello, continuation);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -61,16 +63,17 @@
                                 jobject string,
                                 jobject continuation) {
   load_env();
-  load_class_gr(&_c_SuspendFun, "com/github/dart_lang/jnigen/SuspendFun");
+  load_class_global_ref(&_c_SuspendFun,
+                        "com/github/dart_lang/jnigen/SuspendFun");
   if (_c_SuspendFun == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(
       _c_SuspendFun, &_m_SuspendFun__sayHello1, "sayHello",
       "(Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;");
   if (_m_SuspendFun__sayHello1 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_SuspendFun__sayHello1, string, continuation);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
diff --git a/pkgs/jnigen/test/simple_package_test/src/dartjni.h b/pkgs/jnigen/test/simple_package_test/src/dartjni.h
index 39b70bd..eb73318 100644
--- a/pkgs/jnigen/test/simple_package_test/src/dartjni.h
+++ b/pkgs/jnigen/test/simple_package_test/src/dartjni.h
@@ -39,6 +39,66 @@
 #define __ENVP_CAST (void**)
 #endif
 
+/// Locking functions for windows and pthread.
+
+#if defined _WIN32
+#include <windows.h>
+
+typedef CRITICAL_SECTION MutexLock;
+
+static inline void init_lock(MutexLock* lock) {
+  InitializeCriticalSection(lock);
+}
+
+static inline void acquire_lock(MutexLock* lock) {
+  EnterCriticalSection(lock);
+}
+
+static inline void release_lock(MutexLock* lock) {
+  LeaveCriticalSection(lock);
+}
+
+static inline void _destroyLock(MutexLock* lock) {
+  DeleteCriticalSection(lock);
+}
+
+#elif defined __DARWIN__ || defined __LINUX__ || defined __ANDROID__ ||        \
+    defined __GNUC__
+#include <pthread.h>
+
+typedef pthread_mutex_t MutexLock;
+
+static inline void init_lock(MutexLock* lock) {
+  pthread_mutex_init(lock, NULL);
+}
+
+static inline void acquire_lock(MutexLock* lock) {
+  pthread_mutex_lock(lock);
+}
+
+static inline void release_lock(MutexLock* lock) {
+  pthread_mutex_unlock(lock);
+}
+
+static inline void _destroyLock(MutexLock* lock) {
+  pthread_mutex_destroy(lock);
+}
+
+#else
+
+#error "No locking support; Possibly unsupported platform"
+
+#endif
+
+typedef struct JniLocks {
+  MutexLock classLoadingLock;
+  MutexLock methodLoadingLock;
+  MutexLock fieldLoadingLock;
+} JniLocks;
+
+/// Represents the error when dart-jni layer has already spawned singleton VM.
+#define DART_JNI_SINGLETON_EXISTS (-99);
+
 /// Stores the global state of the JNI.
 typedef struct JniContext {
   JavaVM* jvm;
@@ -46,13 +106,14 @@
   jmethodID loadClassMethod;
   jobject currentActivity;
   jobject appContext;
+  JniLocks locks;
 } JniContext;
 
 // jniEnv for this thread, used by inline functions in this header,
 // therefore declared as extern.
 extern thread_local JNIEnv* jniEnv;
 
-extern JniContext jni;
+extern JniContext* jni;
 
 /// Types used by JNI API to distinguish between primitive types.
 enum JniType {
@@ -73,19 +134,19 @@
 /// If [exception] is null, it means the result is valid.
 /// It's assumed that the caller knows the expected type in [result].
 typedef struct JniResult {
-  jvalue result;
+  jvalue value;
   jthrowable exception;
 } JniResult;
 
 /// Similar to [JniResult] but for class lookups.
 typedef struct JniClassLookupResult {
-  jclass classRef;
+  jclass value;
   jthrowable exception;
 } JniClassLookupResult;
 
 /// Similar to [JniResult] but for method/field ID lookups.
 typedef struct JniPointerResult {
-  void* id;
+  const void* value;
   jthrowable exception;
 } JniPointerResult;
 
@@ -139,54 +200,71 @@
 
 FFI_PLUGIN_EXPORT JNIEnv* GetJniEnv(void);
 
-FFI_PLUGIN_EXPORT JNIEnv* SpawnJvm(JavaVMInitArgs* args);
+/// Spawn a JVM with given arguments.
+///
+/// Returns JNI_OK on success, and one of the documented JNI error codes on
+/// failure. It returns DART_JNI_SINGLETON_EXISTS if an attempt to spawn multiple
+/// JVMs is made, even if the underlying API potentially supports multiple VMs.
+FFI_PLUGIN_EXPORT int SpawnJvm(JavaVMInitArgs* args);
 
-FFI_PLUGIN_EXPORT jclass LoadClass(const char* name);
+/// Load class through platform-specific mechanism.
+///
+/// Currently uses application classloader on android,
+/// and JNIEnv->FindClass on other platforms.
+FFI_PLUGIN_EXPORT jclass FindClass(const char* name);
 
+/// Returns Application classLoader (on Android),
+/// which can be used to load application and platform classes.
+///
+/// On other platforms, NULL is returned.
 FFI_PLUGIN_EXPORT jobject GetClassLoader(void);
 
+/// Returns application context on Android.
+///
+/// On other platforms, NULL is returned.
 FFI_PLUGIN_EXPORT jobject GetApplicationContext(void);
 
+/// Returns current activity of the app on Android.
 FFI_PLUGIN_EXPORT jobject GetCurrentActivity(void);
 
-// Migration note: Below inline functions are required by C bindings, but can be moved to dartjni.c
-// once migration to pure dart bindings is complete.
+static inline void attach_thread() {
+  if (jniEnv == NULL) {
+    (*jni->jvm)->AttachCurrentThread(jni->jvm, __ENVP_CAST & jniEnv, NULL);
+  }
+}
 
-// `static inline` because `inline` doesn't work, it may still not
-// inline the function in which case a linker error may be produced.
-//
-// There has to be a better way to do this. Either to force inlining on target
-// platforms, or just leave it as normal function.
-
-static inline void __load_class_into(jclass* cls, const char* name) {
+/// Load class into [cls] using platform specific mechanism
+static inline void load_class_platform(jclass* cls, const char* name) {
 #ifdef __ANDROID__
   jstring className = (*jniEnv)->NewStringUTF(jniEnv, name);
-  *cls = (*jniEnv)->CallObjectMethod(jniEnv, jni.classLoader,
-                                     jni.loadClassMethod, className);
+  *cls = (*jniEnv)->CallObjectMethod(jniEnv, jni->classLoader,
+                                     jni->loadClassMethod, className);
   (*jniEnv)->DeleteLocalRef(jniEnv, className);
 #else
   *cls = (*jniEnv)->FindClass(jniEnv, name);
 #endif
 }
 
-static inline void load_class(jclass* cls, const char* name) {
+static inline void load_class_local_ref(jclass* cls, const char* name) {
   if (*cls == NULL) {
-    __load_class_into(cls, name);
+    acquire_lock(&jni->locks.classLoadingLock);
+    if (*cls == NULL) {
+      load_class_platform(cls, name);
+    }
+    release_lock(&jni->locks.classLoadingLock);
   }
 }
 
-static inline void load_class_gr(jclass* cls, const char* name) {
+static inline void load_class_global_ref(jclass* cls, const char* name) {
   if (*cls == NULL) {
-    jclass tmp;
-    __load_class_into(&tmp, name);
-    *cls = (*jniEnv)->NewGlobalRef(jniEnv, tmp);
-    (*jniEnv)->DeleteLocalRef(jniEnv, tmp);
-  }
-}
-
-static inline void attach_thread() {
-  if (jniEnv == NULL) {
-    (*jni.jvm)->AttachCurrentThread(jni.jvm, __ENVP_CAST & jniEnv, NULL);
+    jclass tmp = NULL;
+    acquire_lock(&jni->locks.classLoadingLock);
+    if (*cls == NULL) {
+      load_class_platform(&tmp, name);
+      *cls = (*jniEnv)->NewGlobalRef(jniEnv, tmp);
+      (*jniEnv)->DeleteLocalRef(jniEnv, tmp);
+    }
+    release_lock(&jni->locks.classLoadingLock);
   }
 }
 
@@ -195,7 +273,11 @@
                                const char* name,
                                const char* sig) {
   if (*res == NULL) {
-    *res = (*jniEnv)->GetMethodID(jniEnv, cls, name, sig);
+    acquire_lock(&jni->locks.methodLoadingLock);
+    if (*res == NULL) {
+      *res = (*jniEnv)->GetMethodID(jniEnv, cls, name, sig);
+    }
+    release_lock(&jni->locks.methodLoadingLock);
   }
 }
 
@@ -204,7 +286,11 @@
                                       const char* name,
                                       const char* sig) {
   if (*res == NULL) {
-    *res = (*jniEnv)->GetStaticMethodID(jniEnv, cls, name, sig);
+    acquire_lock(&jni->locks.methodLoadingLock);
+    if (*res == NULL) {
+      *res = (*jniEnv)->GetStaticMethodID(jniEnv, cls, name, sig);
+    }
+    release_lock(&jni->locks.methodLoadingLock);
   }
 }
 
@@ -213,7 +299,11 @@
                               const char* name,
                               const char* sig) {
   if (*res == NULL) {
-    *res = (*jniEnv)->GetFieldID(jniEnv, cls, name, sig);
+    acquire_lock(&jni->locks.fieldLoadingLock);
+    if (*res == NULL) {
+      *res = (*jniEnv)->GetFieldID(jniEnv, cls, name, sig);
+    }
+    release_lock(&jni->locks.fieldLoadingLock);
   }
 }
 
@@ -222,7 +312,11 @@
                                      const char* name,
                                      const char* sig) {
   if (*res == NULL) {
-    *res = (*jniEnv)->GetStaticFieldID(jniEnv, cls, name, sig);
+    acquire_lock(&jni->locks.fieldLoadingLock);
+    if (*res == NULL) {
+      *res = (*jniEnv)->GetStaticFieldID(jniEnv, cls, name, sig);
+    }
+    release_lock(&jni->locks.fieldLoadingLock);
   }
 }
 
@@ -234,17 +328,18 @@
 
 // These functions are useful for C+Dart bindings, and not required for pure dart bindings.
 
-FFI_PLUGIN_EXPORT JniContext GetJniContext();
+FFI_PLUGIN_EXPORT JniContext* GetJniContextPtr();
+
 /// For use by jni_gen's generated code
 /// don't use these.
 
 // these 2 fn ptr vars will be defined by generated code library
-extern JniContext (*context_getter)(void);
+extern JniContext* (*context_getter)(void);
 extern JNIEnv* (*env_getter)(void);
 
 // this function will be exported by generated code library
 // it will set above 2 variables.
-FFI_PLUGIN_EXPORT void setJniGetters(struct JniContext (*cg)(void),
+FFI_PLUGIN_EXPORT void setJniGetters(struct JniContext* (*cg)(void),
                                      JNIEnv* (*eg)(void));
 
 static inline void load_env() {
diff --git a/pkgs/jnigen/test/simple_package_test/src/simple_package.c b/pkgs/jnigen/test/simple_package_test/src/simple_package.c
index 0e85ae9..be68002 100644
--- a/pkgs/jnigen/test/simple_package_test/src/simple_package.c
+++ b/pkgs/jnigen/test/simple_package_test/src/simple_package.c
@@ -9,12 +9,12 @@
 #include "jni.h"
 
 thread_local JNIEnv* jniEnv;
-JniContext jni;
+JniContext* jni;
 
-JniContext (*context_getter)(void);
+JniContext* (*context_getter)(void);
 JNIEnv* (*env_getter)(void);
 
-void setJniGetters(JniContext (*cg)(void), JNIEnv* (*eg)(void)) {
+void setJniGetters(JniContext* (*cg)(void), JNIEnv* (*eg)(void)) {
   context_getter = cg;
   env_getter = eg;
 }
@@ -26,15 +26,15 @@
 FFI_PLUGIN_EXPORT
 JniResult Example__ctor() {
   load_env();
-  load_class_gr(&_c_Example,
-                "com/github/dart_lang/jnigen/simple_package/Example");
+  load_class_global_ref(&_c_Example,
+                        "com/github/dart_lang/jnigen/simple_package/Example");
   if (_c_Example == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_Example, &_m_Example__ctor, "<init>", "()V");
   if (_m_Example__ctor == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->NewObject(jniEnv, _c_Example, _m_Example__ctor);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -42,16 +42,16 @@
 FFI_PLUGIN_EXPORT
 JniResult Example__ctor1(int32_t internal) {
   load_env();
-  load_class_gr(&_c_Example,
-                "com/github/dart_lang/jnigen/simple_package/Example");
+  load_class_global_ref(&_c_Example,
+                        "com/github/dart_lang/jnigen/simple_package/Example");
   if (_c_Example == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_Example, &_m_Example__ctor1, "<init>", "(I)V");
   if (_m_Example__ctor1 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result =
       (*jniEnv)->NewObject(jniEnv, _c_Example, _m_Example__ctor1, internal);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -59,34 +59,34 @@
 FFI_PLUGIN_EXPORT
 JniResult Example__whichExample(jobject self_) {
   load_env();
-  load_class_gr(&_c_Example,
-                "com/github/dart_lang/jnigen/simple_package/Example");
+  load_class_global_ref(&_c_Example,
+                        "com/github/dart_lang/jnigen/simple_package/Example");
   if (_c_Example == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_Example, &_m_Example__whichExample, "whichExample", "()I");
   if (_m_Example__whichExample == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   int32_t _result =
       (*jniEnv)->CallIntMethod(jniEnv, self_, _m_Example__whichExample);
-  return (JniResult){.result = {.i = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.i = _result}, .exception = check_exception()};
 }
 
 jmethodID _m_Example__getAux = NULL;
 FFI_PLUGIN_EXPORT
 JniResult Example__getAux() {
   load_env();
-  load_class_gr(&_c_Example,
-                "com/github/dart_lang/jnigen/simple_package/Example");
+  load_class_global_ref(&_c_Example,
+                        "com/github/dart_lang/jnigen/simple_package/Example");
   if (_c_Example == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_method(
       _c_Example, &_m_Example__getAux, "getAux",
       "()Lcom/github/dart_lang/jnigen/simple_package/Example$Aux;");
   if (_m_Example__getAux == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result =
       (*jniEnv)->CallStaticObjectMethod(jniEnv, _c_Example, _m_Example__getAux);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -94,32 +94,32 @@
 FFI_PLUGIN_EXPORT
 JniResult Example__addInts(int32_t a, int32_t b) {
   load_env();
-  load_class_gr(&_c_Example,
-                "com/github/dart_lang/jnigen/simple_package/Example");
+  load_class_global_ref(&_c_Example,
+                        "com/github/dart_lang/jnigen/simple_package/Example");
   if (_c_Example == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_method(_c_Example, &_m_Example__addInts, "addInts", "(II)I");
   if (_m_Example__addInts == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   int32_t _result = (*jniEnv)->CallStaticIntMethod(jniEnv, _c_Example,
                                                    _m_Example__addInts, a, b);
-  return (JniResult){.result = {.i = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.i = _result}, .exception = check_exception()};
 }
 
 jmethodID _m_Example__getArr = NULL;
 FFI_PLUGIN_EXPORT
 JniResult Example__getArr() {
   load_env();
-  load_class_gr(&_c_Example,
-                "com/github/dart_lang/jnigen/simple_package/Example");
+  load_class_global_ref(&_c_Example,
+                        "com/github/dart_lang/jnigen/simple_package/Example");
   if (_c_Example == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_method(_c_Example, &_m_Example__getArr, "getArr", "()[I");
   if (_m_Example__getArr == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result =
       (*jniEnv)->CallStaticObjectMethod(jniEnv, _c_Example, _m_Example__getArr);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -127,33 +127,33 @@
 FFI_PLUGIN_EXPORT
 JniResult Example__addAll(jobject arr) {
   load_env();
-  load_class_gr(&_c_Example,
-                "com/github/dart_lang/jnigen/simple_package/Example");
+  load_class_global_ref(&_c_Example,
+                        "com/github/dart_lang/jnigen/simple_package/Example");
   if (_c_Example == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_method(_c_Example, &_m_Example__addAll, "addAll", "([I)I");
   if (_m_Example__addAll == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   int32_t _result = (*jniEnv)->CallStaticIntMethod(jniEnv, _c_Example,
                                                    _m_Example__addAll, arr);
-  return (JniResult){.result = {.i = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.i = _result}, .exception = check_exception()};
 }
 
 jmethodID _m_Example__getSelf = NULL;
 FFI_PLUGIN_EXPORT
 JniResult Example__getSelf(jobject self_) {
   load_env();
-  load_class_gr(&_c_Example,
-                "com/github/dart_lang/jnigen/simple_package/Example");
+  load_class_global_ref(&_c_Example,
+                        "com/github/dart_lang/jnigen/simple_package/Example");
   if (_c_Example == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_Example, &_m_Example__getSelf, "getSelf",
               "()Lcom/github/dart_lang/jnigen/simple_package/Example;");
   if (_m_Example__getSelf == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result =
       (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_Example__getSelf);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -161,132 +161,132 @@
 FFI_PLUGIN_EXPORT
 JniResult Example__getNum(jobject self_) {
   load_env();
-  load_class_gr(&_c_Example,
-                "com/github/dart_lang/jnigen/simple_package/Example");
+  load_class_global_ref(&_c_Example,
+                        "com/github/dart_lang/jnigen/simple_package/Example");
   if (_c_Example == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_Example, &_m_Example__getNum, "getNum", "()I");
   if (_m_Example__getNum == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   int32_t _result = (*jniEnv)->CallIntMethod(jniEnv, self_, _m_Example__getNum);
-  return (JniResult){.result = {.i = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.i = _result}, .exception = check_exception()};
 }
 
 jmethodID _m_Example__setNum = NULL;
 FFI_PLUGIN_EXPORT
 JniResult Example__setNum(jobject self_, int32_t num) {
   load_env();
-  load_class_gr(&_c_Example,
-                "com/github/dart_lang/jnigen/simple_package/Example");
+  load_class_global_ref(&_c_Example,
+                        "com/github/dart_lang/jnigen/simple_package/Example");
   if (_c_Example == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_Example, &_m_Example__setNum, "setNum", "(I)V");
   if (_m_Example__setNum == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_Example__setNum, num);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_Example__getInternal = NULL;
 FFI_PLUGIN_EXPORT
 JniResult Example__getInternal(jobject self_) {
   load_env();
-  load_class_gr(&_c_Example,
-                "com/github/dart_lang/jnigen/simple_package/Example");
+  load_class_global_ref(&_c_Example,
+                        "com/github/dart_lang/jnigen/simple_package/Example");
   if (_c_Example == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_Example, &_m_Example__getInternal, "getInternal", "()I");
   if (_m_Example__getInternal == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   int32_t _result =
       (*jniEnv)->CallIntMethod(jniEnv, self_, _m_Example__getInternal);
-  return (JniResult){.result = {.i = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.i = _result}, .exception = check_exception()};
 }
 
 jmethodID _m_Example__setInternal = NULL;
 FFI_PLUGIN_EXPORT
 JniResult Example__setInternal(jobject self_, int32_t internal) {
   load_env();
-  load_class_gr(&_c_Example,
-                "com/github/dart_lang/jnigen/simple_package/Example");
+  load_class_global_ref(&_c_Example,
+                        "com/github/dart_lang/jnigen/simple_package/Example");
   if (_c_Example == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_Example, &_m_Example__setInternal, "setInternal", "(I)V");
   if (_m_Example__setInternal == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_Example__setInternal, internal);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_Example__throwException = NULL;
 FFI_PLUGIN_EXPORT
 JniResult Example__throwException() {
   load_env();
-  load_class_gr(&_c_Example,
-                "com/github/dart_lang/jnigen/simple_package/Example");
+  load_class_global_ref(&_c_Example,
+                        "com/github/dart_lang/jnigen/simple_package/Example");
   if (_c_Example == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_method(_c_Example, &_m_Example__throwException, "throwException",
                      "()V");
   if (_m_Example__throwException == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallStaticVoidMethod(jniEnv, _c_Example,
                                   _m_Example__throwException);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jfieldID _f_Example__aux = NULL;
 FFI_PLUGIN_EXPORT
 JniResult get_Example__aux() {
   load_env();
-  load_class_gr(&_c_Example,
-                "com/github/dart_lang/jnigen/simple_package/Example");
+  load_class_global_ref(&_c_Example,
+                        "com/github/dart_lang/jnigen/simple_package/Example");
   if (_c_Example == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_field(_c_Example, &_f_Example__aux, "aux",
                     "Lcom/github/dart_lang/jnigen/simple_package/Example$Aux;");
   jobject _result = to_global_ref(
       (*jniEnv)->GetStaticObjectField(jniEnv, _c_Example, _f_Example__aux));
-  return (JniResult){.result = {.l = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.l = _result}, .exception = check_exception()};
 }
 
 FFI_PLUGIN_EXPORT
 JniResult set_Example__aux(jobject value) {
   load_env();
-  load_class_gr(&_c_Example,
-                "com/github/dart_lang/jnigen/simple_package/Example");
+  load_class_global_ref(&_c_Example,
+                        "com/github/dart_lang/jnigen/simple_package/Example");
   if (_c_Example == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_field(_c_Example, &_f_Example__aux, "aux",
                     "Lcom/github/dart_lang/jnigen/simple_package/Example$Aux;");
   (*jniEnv)->SetStaticObjectField(jniEnv, _c_Example, _f_Example__aux, value);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jfieldID _f_Example__num = NULL;
 FFI_PLUGIN_EXPORT
 JniResult get_Example__num() {
   load_env();
-  load_class_gr(&_c_Example,
-                "com/github/dart_lang/jnigen/simple_package/Example");
+  load_class_global_ref(&_c_Example,
+                        "com/github/dart_lang/jnigen/simple_package/Example");
   if (_c_Example == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_field(_c_Example, &_f_Example__num, "num", "I");
   int32_t _result =
       (*jniEnv)->GetStaticIntField(jniEnv, _c_Example, _f_Example__num);
-  return (JniResult){.result = {.i = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.i = _result}, .exception = check_exception()};
 }
 
 FFI_PLUGIN_EXPORT
 JniResult set_Example__num(int32_t value) {
   load_env();
-  load_class_gr(&_c_Example,
-                "com/github/dart_lang/jnigen/simple_package/Example");
+  load_class_global_ref(&_c_Example,
+                        "com/github/dart_lang/jnigen/simple_package/Example");
   if (_c_Example == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_field(_c_Example, &_f_Example__num, "num", "I");
   (*jniEnv)->SetStaticIntField(jniEnv, _c_Example, _f_Example__num, value);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 // com.github.dart_lang.jnigen.simple_package.Example$Aux
@@ -296,16 +296,17 @@
 FFI_PLUGIN_EXPORT
 JniResult Example_Aux__ctor(uint8_t value) {
   load_env();
-  load_class_gr(&_c_Example_Aux,
-                "com/github/dart_lang/jnigen/simple_package/Example$Aux");
+  load_class_global_ref(
+      &_c_Example_Aux,
+      "com/github/dart_lang/jnigen/simple_package/Example$Aux");
   if (_c_Example_Aux == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_Example_Aux, &_m_Example_Aux__ctor, "<init>", "(Z)V");
   if (_m_Example_Aux__ctor == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result =
       (*jniEnv)->NewObject(jniEnv, _c_Example_Aux, _m_Example_Aux__ctor, value);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -313,57 +314,61 @@
 FFI_PLUGIN_EXPORT
 JniResult Example_Aux__getValue(jobject self_) {
   load_env();
-  load_class_gr(&_c_Example_Aux,
-                "com/github/dart_lang/jnigen/simple_package/Example$Aux");
+  load_class_global_ref(
+      &_c_Example_Aux,
+      "com/github/dart_lang/jnigen/simple_package/Example$Aux");
   if (_c_Example_Aux == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_Example_Aux, &_m_Example_Aux__getValue, "getValue", "()Z");
   if (_m_Example_Aux__getValue == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   uint8_t _result =
       (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_Example_Aux__getValue);
-  return (JniResult){.result = {.z = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.z = _result}, .exception = check_exception()};
 }
 
 jmethodID _m_Example_Aux__setValue = NULL;
 FFI_PLUGIN_EXPORT
 JniResult Example_Aux__setValue(jobject self_, uint8_t value) {
   load_env();
-  load_class_gr(&_c_Example_Aux,
-                "com/github/dart_lang/jnigen/simple_package/Example$Aux");
+  load_class_global_ref(
+      &_c_Example_Aux,
+      "com/github/dart_lang/jnigen/simple_package/Example$Aux");
   if (_c_Example_Aux == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_Example_Aux, &_m_Example_Aux__setValue, "setValue", "(Z)V");
   if (_m_Example_Aux__setValue == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_Example_Aux__setValue, value);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jfieldID _f_Example_Aux__value = NULL;
 FFI_PLUGIN_EXPORT
 JniResult get_Example_Aux__value(jobject self_) {
   load_env();
-  load_class_gr(&_c_Example_Aux,
-                "com/github/dart_lang/jnigen/simple_package/Example$Aux");
+  load_class_global_ref(
+      &_c_Example_Aux,
+      "com/github/dart_lang/jnigen/simple_package/Example$Aux");
   if (_c_Example_Aux == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_field(_c_Example_Aux, &_f_Example_Aux__value, "value", "Z");
   uint8_t _result =
       (*jniEnv)->GetBooleanField(jniEnv, self_, _f_Example_Aux__value);
-  return (JniResult){.result = {.z = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.z = _result}, .exception = check_exception()};
 }
 
 FFI_PLUGIN_EXPORT
 JniResult set_Example_Aux__value(jobject self_, uint8_t value) {
   load_env();
-  load_class_gr(&_c_Example_Aux,
-                "com/github/dart_lang/jnigen/simple_package/Example$Aux");
+  load_class_global_ref(
+      &_c_Example_Aux,
+      "com/github/dart_lang/jnigen/simple_package/Example$Aux");
   if (_c_Example_Aux == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_field(_c_Example_Aux, &_f_Example_Aux__value, "value", "Z");
   (*jniEnv)->SetBooleanField(jniEnv, self_, _f_Example_Aux__value, value);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 // com.github.dart_lang.jnigen.pkg2.C2
@@ -373,14 +378,14 @@
 FFI_PLUGIN_EXPORT
 JniResult C2__ctor() {
   load_env();
-  load_class_gr(&_c_C2, "com/github/dart_lang/jnigen/pkg2/C2");
+  load_class_global_ref(&_c_C2, "com/github/dart_lang/jnigen/pkg2/C2");
   if (_c_C2 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_C2, &_m_C2__ctor, "<init>", "()V");
   if (_m_C2__ctor == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->NewObject(jniEnv, _c_C2, _m_C2__ctor);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -388,24 +393,24 @@
 FFI_PLUGIN_EXPORT
 JniResult get_C2__CONSTANT() {
   load_env();
-  load_class_gr(&_c_C2, "com/github/dart_lang/jnigen/pkg2/C2");
+  load_class_global_ref(&_c_C2, "com/github/dart_lang/jnigen/pkg2/C2");
   if (_c_C2 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_field(_c_C2, &_f_C2__CONSTANT, "CONSTANT", "I");
   int32_t _result =
       (*jniEnv)->GetStaticIntField(jniEnv, _c_C2, _f_C2__CONSTANT);
-  return (JniResult){.result = {.i = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.i = _result}, .exception = check_exception()};
 }
 
 FFI_PLUGIN_EXPORT
 JniResult set_C2__CONSTANT(int32_t value) {
   load_env();
-  load_class_gr(&_c_C2, "com/github/dart_lang/jnigen/pkg2/C2");
+  load_class_global_ref(&_c_C2, "com/github/dart_lang/jnigen/pkg2/C2");
   if (_c_C2 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_field(_c_C2, &_f_C2__CONSTANT, "CONSTANT", "I");
   (*jniEnv)->SetStaticIntField(jniEnv, _c_C2, _f_C2__CONSTANT, value);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 // com.github.dart_lang.jnigen.pkg2.Example
@@ -415,15 +420,16 @@
 FFI_PLUGIN_EXPORT
 JniResult Example1__ctor() {
   load_env();
-  load_class_gr(&_c_Example1, "com/github/dart_lang/jnigen/pkg2/Example");
+  load_class_global_ref(&_c_Example1,
+                        "com/github/dart_lang/jnigen/pkg2/Example");
   if (_c_Example1 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_Example1, &_m_Example1__ctor, "<init>", "()V");
   if (_m_Example1__ctor == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result =
       (*jniEnv)->NewObject(jniEnv, _c_Example1, _m_Example1__ctor);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -431,15 +437,16 @@
 FFI_PLUGIN_EXPORT
 JniResult Example1__whichExample(jobject self_) {
   load_env();
-  load_class_gr(&_c_Example1, "com/github/dart_lang/jnigen/pkg2/Example");
+  load_class_global_ref(&_c_Example1,
+                        "com/github/dart_lang/jnigen/pkg2/Example");
   if (_c_Example1 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_Example1, &_m_Example1__whichExample, "whichExample", "()I");
   if (_m_Example1__whichExample == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   int32_t _result =
       (*jniEnv)->CallIntMethod(jniEnv, self_, _m_Example1__whichExample);
-  return (JniResult){.result = {.i = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.i = _result}, .exception = check_exception()};
 }
 
 // com.github.dart_lang.jnigen.generics.GrandParent
@@ -449,17 +456,17 @@
 FFI_PLUGIN_EXPORT
 JniResult GrandParent__ctor(jobject value) {
   load_env();
-  load_class_gr(&_c_GrandParent,
-                "com/github/dart_lang/jnigen/generics/GrandParent");
+  load_class_global_ref(&_c_GrandParent,
+                        "com/github/dart_lang/jnigen/generics/GrandParent");
   if (_c_GrandParent == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_GrandParent, &_m_GrandParent__ctor, "<init>",
               "(Ljava/lang/Object;)V");
   if (_m_GrandParent__ctor == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result =
       (*jniEnv)->NewObject(jniEnv, _c_GrandParent, _m_GrandParent__ctor, value);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -467,17 +474,17 @@
 FFI_PLUGIN_EXPORT
 JniResult GrandParent__stringParent(jobject self_) {
   load_env();
-  load_class_gr(&_c_GrandParent,
-                "com/github/dart_lang/jnigen/generics/GrandParent");
+  load_class_global_ref(&_c_GrandParent,
+                        "com/github/dart_lang/jnigen/generics/GrandParent");
   if (_c_GrandParent == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_GrandParent, &_m_GrandParent__stringParent, "stringParent",
               "()Lcom/github/dart_lang/jnigen/generics/GrandParent$Parent;");
   if (_m_GrandParent__stringParent == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result =
       (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_GrandParent__stringParent);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -485,18 +492,18 @@
 FFI_PLUGIN_EXPORT
 JniResult GrandParent__varParent(jobject self_, jobject nestedValue) {
   load_env();
-  load_class_gr(&_c_GrandParent,
-                "com/github/dart_lang/jnigen/generics/GrandParent");
+  load_class_global_ref(&_c_GrandParent,
+                        "com/github/dart_lang/jnigen/generics/GrandParent");
   if (_c_GrandParent == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_GrandParent, &_m_GrandParent__varParent, "varParent",
               "(Ljava/lang/Object;)Lcom/github/dart_lang/jnigen/generics/"
               "GrandParent$Parent;");
   if (_m_GrandParent__varParent == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_GrandParent__varParent, nestedValue);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -504,18 +511,18 @@
 FFI_PLUGIN_EXPORT
 JniResult GrandParent__stringStaticParent() {
   load_env();
-  load_class_gr(&_c_GrandParent,
-                "com/github/dart_lang/jnigen/generics/GrandParent");
+  load_class_global_ref(&_c_GrandParent,
+                        "com/github/dart_lang/jnigen/generics/GrandParent");
   if (_c_GrandParent == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_method(
       _c_GrandParent, &_m_GrandParent__stringStaticParent, "stringStaticParent",
       "()Lcom/github/dart_lang/jnigen/generics/GrandParent$StaticParent;");
   if (_m_GrandParent__stringStaticParent == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallStaticObjectMethod(
       jniEnv, _c_GrandParent, _m_GrandParent__stringStaticParent);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -523,19 +530,19 @@
 FFI_PLUGIN_EXPORT
 JniResult GrandParent__varStaticParent(jobject value) {
   load_env();
-  load_class_gr(&_c_GrandParent,
-                "com/github/dart_lang/jnigen/generics/GrandParent");
+  load_class_global_ref(&_c_GrandParent,
+                        "com/github/dart_lang/jnigen/generics/GrandParent");
   if (_c_GrandParent == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_method(_c_GrandParent, &_m_GrandParent__varStaticParent,
                      "varStaticParent",
                      "(Ljava/lang/Object;)Lcom/github/dart_lang/jnigen/"
                      "generics/GrandParent$StaticParent;");
   if (_m_GrandParent__varStaticParent == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallStaticObjectMethod(
       jniEnv, _c_GrandParent, _m_GrandParent__varStaticParent, value);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -543,19 +550,19 @@
 FFI_PLUGIN_EXPORT
 JniResult GrandParent__staticParentWithSameType(jobject self_) {
   load_env();
-  load_class_gr(&_c_GrandParent,
-                "com/github/dart_lang/jnigen/generics/GrandParent");
+  load_class_global_ref(&_c_GrandParent,
+                        "com/github/dart_lang/jnigen/generics/GrandParent");
   if (_c_GrandParent == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(
       _c_GrandParent, &_m_GrandParent__staticParentWithSameType,
       "staticParentWithSameType",
       "()Lcom/github/dart_lang/jnigen/generics/GrandParent$StaticParent;");
   if (_m_GrandParent__staticParentWithSameType == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(
       jniEnv, self_, _m_GrandParent__staticParentWithSameType);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -563,28 +570,28 @@
 FFI_PLUGIN_EXPORT
 JniResult get_GrandParent__value(jobject self_) {
   load_env();
-  load_class_gr(&_c_GrandParent,
-                "com/github/dart_lang/jnigen/generics/GrandParent");
+  load_class_global_ref(&_c_GrandParent,
+                        "com/github/dart_lang/jnigen/generics/GrandParent");
   if (_c_GrandParent == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_field(_c_GrandParent, &_f_GrandParent__value, "value",
              "Ljava/lang/Object;");
   jobject _result = to_global_ref(
       (*jniEnv)->GetObjectField(jniEnv, self_, _f_GrandParent__value));
-  return (JniResult){.result = {.l = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.l = _result}, .exception = check_exception()};
 }
 
 FFI_PLUGIN_EXPORT
 JniResult set_GrandParent__value(jobject self_, jobject value) {
   load_env();
-  load_class_gr(&_c_GrandParent,
-                "com/github/dart_lang/jnigen/generics/GrandParent");
+  load_class_global_ref(&_c_GrandParent,
+                        "com/github/dart_lang/jnigen/generics/GrandParent");
   if (_c_GrandParent == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_field(_c_GrandParent, &_f_GrandParent__value, "value",
              "Ljava/lang/Object;");
   (*jniEnv)->SetObjectField(jniEnv, self_, _f_GrandParent__value, value);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 // com.github.dart_lang.jnigen.generics.GrandParent$Parent
@@ -594,18 +601,19 @@
 FFI_PLUGIN_EXPORT
 JniResult GrandParent_Parent__ctor(jobject parentValue, jobject value) {
   load_env();
-  load_class_gr(&_c_GrandParent_Parent,
-                "com/github/dart_lang/jnigen/generics/GrandParent$Parent");
+  load_class_global_ref(
+      &_c_GrandParent_Parent,
+      "com/github/dart_lang/jnigen/generics/GrandParent$Parent");
   if (_c_GrandParent_Parent == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_GrandParent_Parent, &_m_GrandParent_Parent__ctor, "<init>",
               "(Ljava/lang/Object;Ljava/lang/Object;)V");
   if (_m_GrandParent_Parent__ctor == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result =
       (*jniEnv)->NewObject(jniEnv, _c_GrandParent_Parent,
                            _m_GrandParent_Parent__ctor, parentValue, value);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -613,57 +621,61 @@
 FFI_PLUGIN_EXPORT
 JniResult get_GrandParent_Parent__parentValue(jobject self_) {
   load_env();
-  load_class_gr(&_c_GrandParent_Parent,
-                "com/github/dart_lang/jnigen/generics/GrandParent$Parent");
+  load_class_global_ref(
+      &_c_GrandParent_Parent,
+      "com/github/dart_lang/jnigen/generics/GrandParent$Parent");
   if (_c_GrandParent_Parent == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_field(_c_GrandParent_Parent, &_f_GrandParent_Parent__parentValue,
              "parentValue", "Ljava/lang/Object;");
   jobject _result = to_global_ref((*jniEnv)->GetObjectField(
       jniEnv, self_, _f_GrandParent_Parent__parentValue));
-  return (JniResult){.result = {.l = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.l = _result}, .exception = check_exception()};
 }
 
 FFI_PLUGIN_EXPORT
 JniResult set_GrandParent_Parent__parentValue(jobject self_, jobject value) {
   load_env();
-  load_class_gr(&_c_GrandParent_Parent,
-                "com/github/dart_lang/jnigen/generics/GrandParent$Parent");
+  load_class_global_ref(
+      &_c_GrandParent_Parent,
+      "com/github/dart_lang/jnigen/generics/GrandParent$Parent");
   if (_c_GrandParent_Parent == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_field(_c_GrandParent_Parent, &_f_GrandParent_Parent__parentValue,
              "parentValue", "Ljava/lang/Object;");
   (*jniEnv)->SetObjectField(jniEnv, self_, _f_GrandParent_Parent__parentValue,
                             value);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jfieldID _f_GrandParent_Parent__value = NULL;
 FFI_PLUGIN_EXPORT
 JniResult get_GrandParent_Parent__value(jobject self_) {
   load_env();
-  load_class_gr(&_c_GrandParent_Parent,
-                "com/github/dart_lang/jnigen/generics/GrandParent$Parent");
+  load_class_global_ref(
+      &_c_GrandParent_Parent,
+      "com/github/dart_lang/jnigen/generics/GrandParent$Parent");
   if (_c_GrandParent_Parent == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_field(_c_GrandParent_Parent, &_f_GrandParent_Parent__value, "value",
              "Ljava/lang/Object;");
   jobject _result = to_global_ref(
       (*jniEnv)->GetObjectField(jniEnv, self_, _f_GrandParent_Parent__value));
-  return (JniResult){.result = {.l = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.l = _result}, .exception = check_exception()};
 }
 
 FFI_PLUGIN_EXPORT
 JniResult set_GrandParent_Parent__value(jobject self_, jobject value) {
   load_env();
-  load_class_gr(&_c_GrandParent_Parent,
-                "com/github/dart_lang/jnigen/generics/GrandParent$Parent");
+  load_class_global_ref(
+      &_c_GrandParent_Parent,
+      "com/github/dart_lang/jnigen/generics/GrandParent$Parent");
   if (_c_GrandParent_Parent == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_field(_c_GrandParent_Parent, &_f_GrandParent_Parent__value, "value",
              "Ljava/lang/Object;");
   (*jniEnv)->SetObjectField(jniEnv, self_, _f_GrandParent_Parent__value, value);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 // com.github.dart_lang.jnigen.generics.GrandParent$Parent$Child
@@ -675,20 +687,20 @@
                                          jobject parentValue,
                                          jobject value) {
   load_env();
-  load_class_gr(
+  load_class_global_ref(
       &_c_GrandParent_Parent_Child,
       "com/github/dart_lang/jnigen/generics/GrandParent$Parent$Child");
   if (_c_GrandParent_Parent_Child == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_GrandParent_Parent_Child, &_m_GrandParent_Parent_Child__ctor,
               "<init>",
               "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V");
   if (_m_GrandParent_Parent_Child__ctor == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->NewObject(jniEnv, _c_GrandParent_Parent_Child,
                                          _m_GrandParent_Parent_Child__ctor,
                                          grandParentValue, parentValue, value);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -696,99 +708,99 @@
 FFI_PLUGIN_EXPORT
 JniResult get_GrandParent_Parent_Child__grandParentValue(jobject self_) {
   load_env();
-  load_class_gr(
+  load_class_global_ref(
       &_c_GrandParent_Parent_Child,
       "com/github/dart_lang/jnigen/generics/GrandParent$Parent$Child");
   if (_c_GrandParent_Parent_Child == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_field(_c_GrandParent_Parent_Child,
              &_f_GrandParent_Parent_Child__grandParentValue, "grandParentValue",
              "Ljava/lang/Object;");
   jobject _result = to_global_ref((*jniEnv)->GetObjectField(
       jniEnv, self_, _f_GrandParent_Parent_Child__grandParentValue));
-  return (JniResult){.result = {.l = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.l = _result}, .exception = check_exception()};
 }
 
 FFI_PLUGIN_EXPORT
 JniResult set_GrandParent_Parent_Child__grandParentValue(jobject self_,
                                                          jobject value) {
   load_env();
-  load_class_gr(
+  load_class_global_ref(
       &_c_GrandParent_Parent_Child,
       "com/github/dart_lang/jnigen/generics/GrandParent$Parent$Child");
   if (_c_GrandParent_Parent_Child == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_field(_c_GrandParent_Parent_Child,
              &_f_GrandParent_Parent_Child__grandParentValue, "grandParentValue",
              "Ljava/lang/Object;");
   (*jniEnv)->SetObjectField(
       jniEnv, self_, _f_GrandParent_Parent_Child__grandParentValue, value);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jfieldID _f_GrandParent_Parent_Child__parentValue = NULL;
 FFI_PLUGIN_EXPORT
 JniResult get_GrandParent_Parent_Child__parentValue(jobject self_) {
   load_env();
-  load_class_gr(
+  load_class_global_ref(
       &_c_GrandParent_Parent_Child,
       "com/github/dart_lang/jnigen/generics/GrandParent$Parent$Child");
   if (_c_GrandParent_Parent_Child == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_field(_c_GrandParent_Parent_Child,
              &_f_GrandParent_Parent_Child__parentValue, "parentValue",
              "Ljava/lang/Object;");
   jobject _result = to_global_ref((*jniEnv)->GetObjectField(
       jniEnv, self_, _f_GrandParent_Parent_Child__parentValue));
-  return (JniResult){.result = {.l = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.l = _result}, .exception = check_exception()};
 }
 
 FFI_PLUGIN_EXPORT
 JniResult set_GrandParent_Parent_Child__parentValue(jobject self_,
                                                     jobject value) {
   load_env();
-  load_class_gr(
+  load_class_global_ref(
       &_c_GrandParent_Parent_Child,
       "com/github/dart_lang/jnigen/generics/GrandParent$Parent$Child");
   if (_c_GrandParent_Parent_Child == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_field(_c_GrandParent_Parent_Child,
              &_f_GrandParent_Parent_Child__parentValue, "parentValue",
              "Ljava/lang/Object;");
   (*jniEnv)->SetObjectField(jniEnv, self_,
                             _f_GrandParent_Parent_Child__parentValue, value);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jfieldID _f_GrandParent_Parent_Child__value = NULL;
 FFI_PLUGIN_EXPORT
 JniResult get_GrandParent_Parent_Child__value(jobject self_) {
   load_env();
-  load_class_gr(
+  load_class_global_ref(
       &_c_GrandParent_Parent_Child,
       "com/github/dart_lang/jnigen/generics/GrandParent$Parent$Child");
   if (_c_GrandParent_Parent_Child == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_field(_c_GrandParent_Parent_Child, &_f_GrandParent_Parent_Child__value,
              "value", "Ljava/lang/Object;");
   jobject _result = to_global_ref((*jniEnv)->GetObjectField(
       jniEnv, self_, _f_GrandParent_Parent_Child__value));
-  return (JniResult){.result = {.l = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.l = _result}, .exception = check_exception()};
 }
 
 FFI_PLUGIN_EXPORT
 JniResult set_GrandParent_Parent_Child__value(jobject self_, jobject value) {
   load_env();
-  load_class_gr(
+  load_class_global_ref(
       &_c_GrandParent_Parent_Child,
       "com/github/dart_lang/jnigen/generics/GrandParent$Parent$Child");
   if (_c_GrandParent_Parent_Child == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_field(_c_GrandParent_Parent_Child, &_f_GrandParent_Parent_Child__value,
              "value", "Ljava/lang/Object;");
   (*jniEnv)->SetObjectField(jniEnv, self_, _f_GrandParent_Parent_Child__value,
                             value);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 // com.github.dart_lang.jnigen.generics.GrandParent$StaticParent
@@ -798,19 +810,19 @@
 FFI_PLUGIN_EXPORT
 JniResult GrandParent_StaticParent__ctor(jobject value) {
   load_env();
-  load_class_gr(
+  load_class_global_ref(
       &_c_GrandParent_StaticParent,
       "com/github/dart_lang/jnigen/generics/GrandParent$StaticParent");
   if (_c_GrandParent_StaticParent == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_GrandParent_StaticParent, &_m_GrandParent_StaticParent__ctor,
               "<init>", "(Ljava/lang/Object;)V");
   if (_m_GrandParent_StaticParent__ctor == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result =
       (*jniEnv)->NewObject(jniEnv, _c_GrandParent_StaticParent,
                            _m_GrandParent_StaticParent__ctor, value);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -818,31 +830,31 @@
 FFI_PLUGIN_EXPORT
 JniResult get_GrandParent_StaticParent__value(jobject self_) {
   load_env();
-  load_class_gr(
+  load_class_global_ref(
       &_c_GrandParent_StaticParent,
       "com/github/dart_lang/jnigen/generics/GrandParent$StaticParent");
   if (_c_GrandParent_StaticParent == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_field(_c_GrandParent_StaticParent, &_f_GrandParent_StaticParent__value,
              "value", "Ljava/lang/Object;");
   jobject _result = to_global_ref((*jniEnv)->GetObjectField(
       jniEnv, self_, _f_GrandParent_StaticParent__value));
-  return (JniResult){.result = {.l = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.l = _result}, .exception = check_exception()};
 }
 
 FFI_PLUGIN_EXPORT
 JniResult set_GrandParent_StaticParent__value(jobject self_, jobject value) {
   load_env();
-  load_class_gr(
+  load_class_global_ref(
       &_c_GrandParent_StaticParent,
       "com/github/dart_lang/jnigen/generics/GrandParent$StaticParent");
   if (_c_GrandParent_StaticParent == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_field(_c_GrandParent_StaticParent, &_f_GrandParent_StaticParent__value,
              "value", "Ljava/lang/Object;");
   (*jniEnv)->SetObjectField(jniEnv, self_, _f_GrandParent_StaticParent__value,
                             value);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 // com.github.dart_lang.jnigen.generics.GrandParent$StaticParent$Child
@@ -853,20 +865,20 @@
 JniResult GrandParent_StaticParent_Child__ctor(jobject parentValue,
                                                jobject value) {
   load_env();
-  load_class_gr(
+  load_class_global_ref(
       &_c_GrandParent_StaticParent_Child,
       "com/github/dart_lang/jnigen/generics/GrandParent$StaticParent$Child");
   if (_c_GrandParent_StaticParent_Child == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_GrandParent_StaticParent_Child,
               &_m_GrandParent_StaticParent_Child__ctor, "<init>",
               "(Ljava/lang/Object;Ljava/lang/Object;)V");
   if (_m_GrandParent_StaticParent_Child__ctor == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->NewObject(
       jniEnv, _c_GrandParent_StaticParent_Child,
       _m_GrandParent_StaticParent_Child__ctor, parentValue, value);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -874,68 +886,68 @@
 FFI_PLUGIN_EXPORT
 JniResult get_GrandParent_StaticParent_Child__parentValue(jobject self_) {
   load_env();
-  load_class_gr(
+  load_class_global_ref(
       &_c_GrandParent_StaticParent_Child,
       "com/github/dart_lang/jnigen/generics/GrandParent$StaticParent$Child");
   if (_c_GrandParent_StaticParent_Child == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_field(_c_GrandParent_StaticParent_Child,
              &_f_GrandParent_StaticParent_Child__parentValue, "parentValue",
              "Ljava/lang/Object;");
   jobject _result = to_global_ref((*jniEnv)->GetObjectField(
       jniEnv, self_, _f_GrandParent_StaticParent_Child__parentValue));
-  return (JniResult){.result = {.l = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.l = _result}, .exception = check_exception()};
 }
 
 FFI_PLUGIN_EXPORT
 JniResult set_GrandParent_StaticParent_Child__parentValue(jobject self_,
                                                           jobject value) {
   load_env();
-  load_class_gr(
+  load_class_global_ref(
       &_c_GrandParent_StaticParent_Child,
       "com/github/dart_lang/jnigen/generics/GrandParent$StaticParent$Child");
   if (_c_GrandParent_StaticParent_Child == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_field(_c_GrandParent_StaticParent_Child,
              &_f_GrandParent_StaticParent_Child__parentValue, "parentValue",
              "Ljava/lang/Object;");
   (*jniEnv)->SetObjectField(
       jniEnv, self_, _f_GrandParent_StaticParent_Child__parentValue, value);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jfieldID _f_GrandParent_StaticParent_Child__value = NULL;
 FFI_PLUGIN_EXPORT
 JniResult get_GrandParent_StaticParent_Child__value(jobject self_) {
   load_env();
-  load_class_gr(
+  load_class_global_ref(
       &_c_GrandParent_StaticParent_Child,
       "com/github/dart_lang/jnigen/generics/GrandParent$StaticParent$Child");
   if (_c_GrandParent_StaticParent_Child == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_field(_c_GrandParent_StaticParent_Child,
              &_f_GrandParent_StaticParent_Child__value, "value",
              "Ljava/lang/Object;");
   jobject _result = to_global_ref((*jniEnv)->GetObjectField(
       jniEnv, self_, _f_GrandParent_StaticParent_Child__value));
-  return (JniResult){.result = {.l = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.l = _result}, .exception = check_exception()};
 }
 
 FFI_PLUGIN_EXPORT
 JniResult set_GrandParent_StaticParent_Child__value(jobject self_,
                                                     jobject value) {
   load_env();
-  load_class_gr(
+  load_class_global_ref(
       &_c_GrandParent_StaticParent_Child,
       "com/github/dart_lang/jnigen/generics/GrandParent$StaticParent$Child");
   if (_c_GrandParent_StaticParent_Child == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_field(_c_GrandParent_StaticParent_Child,
              &_f_GrandParent_StaticParent_Child__value, "value",
              "Ljava/lang/Object;");
   (*jniEnv)->SetObjectField(jniEnv, self_,
                             _f_GrandParent_StaticParent_Child__value, value);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 // com.github.dart_lang.jnigen.generics.MyMap
@@ -945,14 +957,15 @@
 FFI_PLUGIN_EXPORT
 JniResult MyMap__ctor() {
   load_env();
-  load_class_gr(&_c_MyMap, "com/github/dart_lang/jnigen/generics/MyMap");
+  load_class_global_ref(&_c_MyMap,
+                        "com/github/dart_lang/jnigen/generics/MyMap");
   if (_c_MyMap == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_MyMap, &_m_MyMap__ctor, "<init>", "()V");
   if (_m_MyMap__ctor == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->NewObject(jniEnv, _c_MyMap, _m_MyMap__ctor);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -960,16 +973,17 @@
 FFI_PLUGIN_EXPORT
 JniResult MyMap__get0(jobject self_, jobject key) {
   load_env();
-  load_class_gr(&_c_MyMap, "com/github/dart_lang/jnigen/generics/MyMap");
+  load_class_global_ref(&_c_MyMap,
+                        "com/github/dart_lang/jnigen/generics/MyMap");
   if (_c_MyMap == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_MyMap, &_m_MyMap__get0, "get",
               "(Ljava/lang/Object;)Ljava/lang/Object;");
   if (_m_MyMap__get0 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result =
       (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_MyMap__get0, key);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -977,16 +991,17 @@
 FFI_PLUGIN_EXPORT
 JniResult MyMap__put(jobject self_, jobject key, jobject value) {
   load_env();
-  load_class_gr(&_c_MyMap, "com/github/dart_lang/jnigen/generics/MyMap");
+  load_class_global_ref(&_c_MyMap,
+                        "com/github/dart_lang/jnigen/generics/MyMap");
   if (_c_MyMap == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_MyMap, &_m_MyMap__put, "put",
               "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
   if (_m_MyMap__put == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result =
       (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_MyMap__put, key, value);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -994,16 +1009,17 @@
 FFI_PLUGIN_EXPORT
 JniResult MyMap__entryStack(jobject self_) {
   load_env();
-  load_class_gr(&_c_MyMap, "com/github/dart_lang/jnigen/generics/MyMap");
+  load_class_global_ref(&_c_MyMap,
+                        "com/github/dart_lang/jnigen/generics/MyMap");
   if (_c_MyMap == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_MyMap, &_m_MyMap__entryStack, "entryStack",
               "()Lcom/github/dart_lang/jnigen/generics/MyStack;");
   if (_m_MyMap__entryStack == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result =
       (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_MyMap__entryStack);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1014,17 +1030,17 @@
 FFI_PLUGIN_EXPORT
 JniResult MyMap_MyEntry__ctor(jobject key, jobject value) {
   load_env();
-  load_class_gr(&_c_MyMap_MyEntry,
-                "com/github/dart_lang/jnigen/generics/MyMap$MyEntry");
+  load_class_global_ref(&_c_MyMap_MyEntry,
+                        "com/github/dart_lang/jnigen/generics/MyMap$MyEntry");
   if (_c_MyMap_MyEntry == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_MyMap_MyEntry, &_m_MyMap_MyEntry__ctor, "<init>",
               "(Ljava/lang/Object;Ljava/lang/Object;)V");
   if (_m_MyMap_MyEntry__ctor == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->NewObject(jniEnv, _c_MyMap_MyEntry,
                                          _m_MyMap_MyEntry__ctor, key, value);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1032,56 +1048,56 @@
 FFI_PLUGIN_EXPORT
 JniResult get_MyMap_MyEntry__key(jobject self_) {
   load_env();
-  load_class_gr(&_c_MyMap_MyEntry,
-                "com/github/dart_lang/jnigen/generics/MyMap$MyEntry");
+  load_class_global_ref(&_c_MyMap_MyEntry,
+                        "com/github/dart_lang/jnigen/generics/MyMap$MyEntry");
   if (_c_MyMap_MyEntry == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_field(_c_MyMap_MyEntry, &_f_MyMap_MyEntry__key, "key",
              "Ljava/lang/Object;");
   jobject _result = to_global_ref(
       (*jniEnv)->GetObjectField(jniEnv, self_, _f_MyMap_MyEntry__key));
-  return (JniResult){.result = {.l = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.l = _result}, .exception = check_exception()};
 }
 
 FFI_PLUGIN_EXPORT
 JniResult set_MyMap_MyEntry__key(jobject self_, jobject value) {
   load_env();
-  load_class_gr(&_c_MyMap_MyEntry,
-                "com/github/dart_lang/jnigen/generics/MyMap$MyEntry");
+  load_class_global_ref(&_c_MyMap_MyEntry,
+                        "com/github/dart_lang/jnigen/generics/MyMap$MyEntry");
   if (_c_MyMap_MyEntry == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_field(_c_MyMap_MyEntry, &_f_MyMap_MyEntry__key, "key",
              "Ljava/lang/Object;");
   (*jniEnv)->SetObjectField(jniEnv, self_, _f_MyMap_MyEntry__key, value);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jfieldID _f_MyMap_MyEntry__value = NULL;
 FFI_PLUGIN_EXPORT
 JniResult get_MyMap_MyEntry__value(jobject self_) {
   load_env();
-  load_class_gr(&_c_MyMap_MyEntry,
-                "com/github/dart_lang/jnigen/generics/MyMap$MyEntry");
+  load_class_global_ref(&_c_MyMap_MyEntry,
+                        "com/github/dart_lang/jnigen/generics/MyMap$MyEntry");
   if (_c_MyMap_MyEntry == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_field(_c_MyMap_MyEntry, &_f_MyMap_MyEntry__value, "value",
              "Ljava/lang/Object;");
   jobject _result = to_global_ref(
       (*jniEnv)->GetObjectField(jniEnv, self_, _f_MyMap_MyEntry__value));
-  return (JniResult){.result = {.l = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.l = _result}, .exception = check_exception()};
 }
 
 FFI_PLUGIN_EXPORT
 JniResult set_MyMap_MyEntry__value(jobject self_, jobject value) {
   load_env();
-  load_class_gr(&_c_MyMap_MyEntry,
-                "com/github/dart_lang/jnigen/generics/MyMap$MyEntry");
+  load_class_global_ref(&_c_MyMap_MyEntry,
+                        "com/github/dart_lang/jnigen/generics/MyMap$MyEntry");
   if (_c_MyMap_MyEntry == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_field(_c_MyMap_MyEntry, &_f_MyMap_MyEntry__value, "value",
              "Ljava/lang/Object;");
   (*jniEnv)->SetObjectField(jniEnv, self_, _f_MyMap_MyEntry__value, value);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 // com.github.dart_lang.jnigen.generics.MyStack
@@ -1091,14 +1107,15 @@
 FFI_PLUGIN_EXPORT
 JniResult MyStack__ctor() {
   load_env();
-  load_class_gr(&_c_MyStack, "com/github/dart_lang/jnigen/generics/MyStack");
+  load_class_global_ref(&_c_MyStack,
+                        "com/github/dart_lang/jnigen/generics/MyStack");
   if (_c_MyStack == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_MyStack, &_m_MyStack__ctor, "<init>", "()V");
   if (_m_MyStack__ctor == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->NewObject(jniEnv, _c_MyStack, _m_MyStack__ctor);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1106,17 +1123,18 @@
 FFI_PLUGIN_EXPORT
 JniResult MyStack__fromArray(jobject arr) {
   load_env();
-  load_class_gr(&_c_MyStack, "com/github/dart_lang/jnigen/generics/MyStack");
+  load_class_global_ref(&_c_MyStack,
+                        "com/github/dart_lang/jnigen/generics/MyStack");
   if (_c_MyStack == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_method(
       _c_MyStack, &_m_MyStack__fromArray, "fromArray",
       "([Ljava/lang/Object;)Lcom/github/dart_lang/jnigen/generics/MyStack;");
   if (_m_MyStack__fromArray == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallStaticObjectMethod(
       jniEnv, _c_MyStack, _m_MyStack__fromArray, arr);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1124,19 +1142,20 @@
 FFI_PLUGIN_EXPORT
 JniResult MyStack__fromArrayOfArrayOfGrandParents(jobject arr) {
   load_env();
-  load_class_gr(&_c_MyStack, "com/github/dart_lang/jnigen/generics/MyStack");
+  load_class_global_ref(&_c_MyStack,
+                        "com/github/dart_lang/jnigen/generics/MyStack");
   if (_c_MyStack == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_method(
       _c_MyStack, &_m_MyStack__fromArrayOfArrayOfGrandParents,
       "fromArrayOfArrayOfGrandParents",
       "([[Lcom/github/dart_lang/jnigen/generics/GrandParent;)Lcom/github/"
       "dart_lang/jnigen/generics/MyStack;");
   if (_m_MyStack__fromArrayOfArrayOfGrandParents == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallStaticObjectMethod(
       jniEnv, _c_MyStack, _m_MyStack__fromArrayOfArrayOfGrandParents, arr);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1144,16 +1163,17 @@
 FFI_PLUGIN_EXPORT
 JniResult MyStack__of() {
   load_env();
-  load_class_gr(&_c_MyStack, "com/github/dart_lang/jnigen/generics/MyStack");
+  load_class_global_ref(&_c_MyStack,
+                        "com/github/dart_lang/jnigen/generics/MyStack");
   if (_c_MyStack == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_method(_c_MyStack, &_m_MyStack__of, "of",
                      "()Lcom/github/dart_lang/jnigen/generics/MyStack;");
   if (_m_MyStack__of == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result =
       (*jniEnv)->CallStaticObjectMethod(jniEnv, _c_MyStack, _m_MyStack__of);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1161,17 +1181,18 @@
 FFI_PLUGIN_EXPORT
 JniResult MyStack__of1(jobject obj) {
   load_env();
-  load_class_gr(&_c_MyStack, "com/github/dart_lang/jnigen/generics/MyStack");
+  load_class_global_ref(&_c_MyStack,
+                        "com/github/dart_lang/jnigen/generics/MyStack");
   if (_c_MyStack == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_method(
       _c_MyStack, &_m_MyStack__of1, "of",
       "(Ljava/lang/Object;)Lcom/github/dart_lang/jnigen/generics/MyStack;");
   if (_m_MyStack__of1 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallStaticObjectMethod(jniEnv, _c_MyStack,
                                                       _m_MyStack__of1, obj);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1179,17 +1200,18 @@
 FFI_PLUGIN_EXPORT
 JniResult MyStack__of2(jobject obj, jobject obj2) {
   load_env();
-  load_class_gr(&_c_MyStack, "com/github/dart_lang/jnigen/generics/MyStack");
+  load_class_global_ref(&_c_MyStack,
+                        "com/github/dart_lang/jnigen/generics/MyStack");
   if (_c_MyStack == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_method(_c_MyStack, &_m_MyStack__of2, "of",
                      "(Ljava/lang/Object;Ljava/lang/Object;)Lcom/github/"
                      "dart_lang/jnigen/generics/MyStack;");
   if (_m_MyStack__of2 == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallStaticObjectMethod(
       jniEnv, _c_MyStack, _m_MyStack__of2, obj, obj2);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1197,28 +1219,30 @@
 FFI_PLUGIN_EXPORT
 JniResult MyStack__push(jobject self_, jobject item) {
   load_env();
-  load_class_gr(&_c_MyStack, "com/github/dart_lang/jnigen/generics/MyStack");
+  load_class_global_ref(&_c_MyStack,
+                        "com/github/dart_lang/jnigen/generics/MyStack");
   if (_c_MyStack == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_MyStack, &_m_MyStack__push, "push", "(Ljava/lang/Object;)V");
   if (_m_MyStack__push == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_MyStack__push, item);
-  return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+  return (JniResult){.value = {.j = 0}, .exception = check_exception()};
 }
 
 jmethodID _m_MyStack__pop = NULL;
 FFI_PLUGIN_EXPORT
 JniResult MyStack__pop(jobject self_) {
   load_env();
-  load_class_gr(&_c_MyStack, "com/github/dart_lang/jnigen/generics/MyStack");
+  load_class_global_ref(&_c_MyStack,
+                        "com/github/dart_lang/jnigen/generics/MyStack");
   if (_c_MyStack == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_MyStack, &_m_MyStack__pop, "pop", "()Ljava/lang/Object;");
   if (_m_MyStack__pop == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_MyStack__pop);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1226,14 +1250,15 @@
 FFI_PLUGIN_EXPORT
 JniResult MyStack__size(jobject self_) {
   load_env();
-  load_class_gr(&_c_MyStack, "com/github/dart_lang/jnigen/generics/MyStack");
+  load_class_global_ref(&_c_MyStack,
+                        "com/github/dart_lang/jnigen/generics/MyStack");
   if (_c_MyStack == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_MyStack, &_m_MyStack__size, "size", "()I");
   if (_m_MyStack__size == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   int32_t _result = (*jniEnv)->CallIntMethod(jniEnv, self_, _m_MyStack__size);
-  return (JniResult){.result = {.i = _result}, .exception = check_exception()};
+  return (JniResult){.value = {.i = _result}, .exception = check_exception()};
 }
 
 // com.github.dart_lang.jnigen.generics.StringKeyedMap
@@ -1243,16 +1268,16 @@
 FFI_PLUGIN_EXPORT
 JniResult StringKeyedMap__ctor() {
   load_env();
-  load_class_gr(&_c_StringKeyedMap,
-                "com/github/dart_lang/jnigen/generics/StringKeyedMap");
+  load_class_global_ref(&_c_StringKeyedMap,
+                        "com/github/dart_lang/jnigen/generics/StringKeyedMap");
   if (_c_StringKeyedMap == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_StringKeyedMap, &_m_StringKeyedMap__ctor, "<init>", "()V");
   if (_m_StringKeyedMap__ctor == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result =
       (*jniEnv)->NewObject(jniEnv, _c_StringKeyedMap, _m_StringKeyedMap__ctor);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1263,16 +1288,16 @@
 FFI_PLUGIN_EXPORT
 JniResult StringMap__ctor() {
   load_env();
-  load_class_gr(&_c_StringMap,
-                "com/github/dart_lang/jnigen/generics/StringMap");
+  load_class_global_ref(&_c_StringMap,
+                        "com/github/dart_lang/jnigen/generics/StringMap");
   if (_c_StringMap == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_StringMap, &_m_StringMap__ctor, "<init>", "()V");
   if (_m_StringMap__ctor == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result =
       (*jniEnv)->NewObject(jniEnv, _c_StringMap, _m_StringMap__ctor);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1283,16 +1308,16 @@
 FFI_PLUGIN_EXPORT
 JniResult StringStack__ctor() {
   load_env();
-  load_class_gr(&_c_StringStack,
-                "com/github/dart_lang/jnigen/generics/StringStack");
+  load_class_global_ref(&_c_StringStack,
+                        "com/github/dart_lang/jnigen/generics/StringStack");
   if (_c_StringStack == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_StringStack, &_m_StringStack__ctor, "<init>", "()V");
   if (_m_StringStack__ctor == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result =
       (*jniEnv)->NewObject(jniEnv, _c_StringStack, _m_StringStack__ctor);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1303,16 +1328,16 @@
 FFI_PLUGIN_EXPORT
 JniResult StringValuedMap__ctor() {
   load_env();
-  load_class_gr(&_c_StringValuedMap,
-                "com/github/dart_lang/jnigen/generics/StringValuedMap");
+  load_class_global_ref(&_c_StringValuedMap,
+                        "com/github/dart_lang/jnigen/generics/StringValuedMap");
   if (_c_StringValuedMap == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_StringValuedMap, &_m_StringValuedMap__ctor, "<init>", "()V");
   if (_m_StringValuedMap__ctor == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->NewObject(jniEnv, _c_StringValuedMap,
                                          _m_StringValuedMap__ctor);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1323,19 +1348,19 @@
 FFI_PLUGIN_EXPORT
 JniResult JsonSerializable_Case__values() {
   load_env();
-  load_class_gr(
+  load_class_global_ref(
       &_c_JsonSerializable_Case,
       "com/github/dart_lang/jnigen/annotations/JsonSerializable$Case");
   if (_c_JsonSerializable_Case == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_method(
       _c_JsonSerializable_Case, &_m_JsonSerializable_Case__values, "values",
       "()[Lcom/github/dart_lang/jnigen/annotations/JsonSerializable$Case;");
   if (_m_JsonSerializable_Case__values == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallStaticObjectMethod(
       jniEnv, _c_JsonSerializable_Case, _m_JsonSerializable_Case__values);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1343,21 +1368,21 @@
 FFI_PLUGIN_EXPORT
 JniResult JsonSerializable_Case__valueOf(jobject name) {
   load_env();
-  load_class_gr(
+  load_class_global_ref(
       &_c_JsonSerializable_Case,
       "com/github/dart_lang/jnigen/annotations/JsonSerializable$Case");
   if (_c_JsonSerializable_Case == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_static_method(_c_JsonSerializable_Case,
                      &_m_JsonSerializable_Case__valueOf, "valueOf",
                      "(Ljava/lang/String;)Lcom/github/dart_lang/jnigen/"
                      "annotations/JsonSerializable$Case;");
   if (_m_JsonSerializable_Case__valueOf == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result = (*jniEnv)->CallStaticObjectMethod(
       jniEnv, _c_JsonSerializable_Case, _m_JsonSerializable_Case__valueOf,
       name);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
 
@@ -1368,15 +1393,15 @@
 FFI_PLUGIN_EXPORT
 JniResult MyDataClass__ctor() {
   load_env();
-  load_class_gr(&_c_MyDataClass,
-                "com/github/dart_lang/jnigen/annotations/MyDataClass");
+  load_class_global_ref(&_c_MyDataClass,
+                        "com/github/dart_lang/jnigen/annotations/MyDataClass");
   if (_c_MyDataClass == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   load_method(_c_MyDataClass, &_m_MyDataClass__ctor, "<init>", "()V");
   if (_m_MyDataClass__ctor == NULL)
-    return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+    return (JniResult){.value = {.j = 0}, .exception = check_exception()};
   jobject _result =
       (*jniEnv)->NewObject(jniEnv, _c_MyDataClass, _m_MyDataClass__ctor);
-  return (JniResult){.result = {.l = to_global_ref(_result)},
+  return (JniResult){.value = {.l = to_global_ref(_result)},
                      .exception = check_exception()};
 }
diff --git a/pkgs/jnigen/test/test_util/test_util.dart b/pkgs/jnigen/test/test_util/test_util.dart
index e48fd0a..6870701 100644
--- a/pkgs/jnigen/test/test_util/test_util.dart
+++ b/pkgs/jnigen/test/test_util/test_util.dart
@@ -9,7 +9,7 @@
 import 'package:test/test.dart';
 import 'package:logging/logging.dart' show Level;
 
-import 'package:jnigen/src/logging/logging.dart' show printError;
+import 'package:jnigen/src/logging/logging.dart' show printError, log;
 
 final _currentDirectory = Directory(".");
 
@@ -54,16 +54,22 @@
 
 /// Compares 2 hierarchies using `git diff --no-index`.
 void comparePaths(String path1, String path2) {
-  final proc = Process.runSync("git", [
+  final diffCommand = [
     "diff",
     "--no-index",
     if (stderr.supportsAnsiEscapes) "--color=always",
-    path1,
-    path2,
-  ]);
-  if (proc.exitCode != 0) {
-    stderr.writeln('\n${proc.stdout}');
-    throw Exception("Files differ: ($path1, $path2)");
+  ];
+  final diffProc = Process.runSync("git", [...diffCommand, path1, path2]);
+  if (diffProc.exitCode != 0) {
+    final originalDiff = diffProc.stdout;
+    log.warning(
+        "Paths $path1 and $path2 differ, comparing by ignoring space change");
+    final fallbackDiffProc = Process.runSync(
+        "git", [...diffCommand, '--ignore-space-change', path1, path2]);
+    if (fallbackDiffProc.exitCode != 0) {
+      stderr.writeln(originalDiff);
+      throw Exception("Paths $path1 and $path2 differ");
+    }
   }
 }