[jnigen] Jni refactor (https://github.com/dart-lang/jnigen/issues/53)

diff --git a/.github/workflows/test-package.yml b/.github/workflows/test-package.yml
index 80dba5c..dacfe94 100644
--- a/.github/workflows/test-package.yml
+++ b/.github/workflows/test-package.yml
@@ -36,9 +36,11 @@
         sdk: [stable]
     steps:
       - uses: actions/checkout@v2
-      - uses: dart-lang/setup-dart@v1.0
+      - uses: subosito/flutter-action@v2
         with:
-          sdk: ${{ matrix.sdk }}
+          channel: ${{ matrix.sdk }}
+          cache: true
+          cache-key: 'flutter-:os:-:channel:-:version:-:arch:-:hash:'
       - id: install
         name: Install dependencies
         run: dart pub get
@@ -60,12 +62,14 @@
       matrix:
         # Add macos-latest and/or windows-latest if relevant for this package.
         os: [ubuntu-latest]
-        sdk: [2.17.0, dev]
+        sdk: [stable, beta]
     steps:
       - uses: actions/checkout@v2
-      - uses: dart-lang/setup-dart@v1.0
+      - uses: subosito/flutter-action@v2
         with:
-          sdk: stable
+          channel: ${{ matrix.sdk }}
+          cache: true
+          cache-key: 'flutter-:os:-:channel:-:version:-:arch:-:hash:'
       - uses: actions/setup-java@v2
         with:
           distribution: 'zulu'
@@ -87,9 +91,8 @@
           parallel: true
           path-to-lcov: ./pkgs/jnigen/coverage/lcov.info
 
-  ## TODO: More minimal test on windows after fixing dev dependency.
+  ## TODO(#15): More minimal test on windows after fixing dev dependency.
   ## i.e do not rerun analyze and format steps, and do not require flutter.
-  ## IssueRef: https://github.com/dart-lang/jnigen/issues/15
 
   test_summarizer:
     runs-on: ubuntu-latest
@@ -125,7 +128,7 @@
           java-version: '11'
       - run: |
           sudo apt-get update -y
-          sudo apt-get install -y ninja-build libgtk-3-dev
+          sudo apt-get install -y ninja-build libgtk-3-dev libclang-dev
       - run: dart pub get
       - run: dart run bin/setup.dart
       - run: flutter pub get
@@ -148,6 +151,11 @@
           flag-name: jni_tests
           parallel: true
           path-to-lcov: ./pkgs/jni/coverage/lcov.info
+      - name: regenerate & compare ffigen bindings
+        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
 
   build_jni_example_linux:
     runs-on: ubuntu-latest
@@ -216,7 +224,7 @@
     runs-on: ubuntu-latest
     defaults:
       run:
-        working-directory: ./pkgs/jnigen/examples/notification_plugin
+        working-directory: ./pkgs/jnigen/example/notification_plugin
     steps:
       - uses: actions/checkout@v3
       - uses: actions/setup-java@v2
@@ -231,7 +239,7 @@
       - run: flutter pub get
       - run: flutter analyze
       - run: flutter build apk
-        working-directory: ./pkgs/jnigen/examples/notification_plugin/example
+        working-directory: ./pkgs/jnigen/example/notification_plugin/example
       - name: re-generate bindings
         run: flutter pub run jnigen -Ddart_root=_dart -Dc_root=_c --config jnigen.yaml
       - name: compare generated dart bindings
@@ -243,7 +251,7 @@
     runs-on: ubuntu-latest
     defaults:
       run:
-        working-directory: ./pkgs/jnigen/examples/in_app_java
+        working-directory: ./pkgs/jnigen/example/in_app_java
     steps:
       - uses: actions/checkout@v3
       - uses: actions/setup-java@v2
@@ -279,7 +287,7 @@
     runs-on: ubuntu-latest
     defaults:
       run:
-        working-directory: ./pkgs/jnigen/examples/pdfbox_plugin
+        working-directory: ./pkgs/jnigen/example/pdfbox_plugin
     steps:
       - uses: actions/checkout@v3
       - uses: subosito/flutter-action@v2
@@ -315,10 +323,10 @@
           dart run jni:setup && dart run jni:setup -p pdfbox_plugin
           wget 'https://dart.dev/guides/language/specifications/DartLangSpec-v2.2.pdf'
           dart run bin/pdf_info.dart DartLangSpec-v2.2.pdf
-        working-directory: ./pkgs/jnigen/examples/pdfbox_plugin/dart_example
+        working-directory: ./pkgs/jnigen/example/pdfbox_plugin/dart_example
       - name: Build flutter example for pdfbox_plugin
         run: |
           flutter pub get
           flutter build linux
-        working-directory: ./pkgs/jnigen/examples/pdfbox_plugin/example
+        working-directory: ./pkgs/jnigen/example/pdfbox_plugin/example
 
diff --git a/pkgs/jni/CHANGELOG.md b/pkgs/jni/CHANGELOG.md
index 41cc7d8..e61dbc4 100644
--- a/pkgs/jni/CHANGELOG.md
+++ b/pkgs/jni/CHANGELOG.md
@@ -1,3 +1,2 @@
-## 0.0.1
-
-* TODO: Describe initial release.
+## 0.1.0
+* Initial version: Android and Linux support, JniObject API
diff --git a/pkgs/jni/README.md b/pkgs/jni/README.md
index 12d41fb..4cd7927 100644
--- a/pkgs/jni/README.md
+++ b/pkgs/jni/README.md
@@ -4,22 +4,17 @@
 
 This library contains:
 
-* functions to access the JNIEnv and JavaVM variables from JNI, and wrapper functions to those provided by JNI. (`Jni.getEnv`, `Jni.getJavaVM`).
+* functions to access the JNIEnv and JavaVM variables from JNI, and wrapper functions to those provided by JNI. JNIEnv is exposed via `GlobalJniEnv` type which provides a thin abstraction over JNIEnv, so that it can be used from multiple threads.
 
 * Functions to spawn a JVM on desktop platforms (`Jni.spawn`).
 
-* Some utility functions to make it easier to work with JNI in Dart; eg: To convert a java string object to Dart string (mostly as extension methods on `Pointer<JniEnv>`).
-
 * Some Android-specific helpers (get application context and current activity references).
 
-* Some helper classes and functions to simplify one-off uses (`JniObject` and `JniClass` intended for calling functions by specifying the name and arguments. It will reduce some boilerplate when you're debugging. Note: this API is slightly incomplete).
+* `JniObject` class, which provides base class for classes generated by jnigen.
 
 This is intended for one-off / debugging uses of JNI, as well as providing a base library for code generated by jnigen. 
 
-__To interface a complete java library, look forward for `jnigen`.__
-
-## Platform support
-The focus of this project is Flutter Android, since Flutter Android apps already have a JVM, and JNI enables interop with existing Java code and Android Platform APIs. This project also (partially) supports Linux desktop by spawning a JVM through JNI.
+__To generate type-safe bindings from Java libraries, use `jnigen`.__
 
 ## Version note
 This library is at an early stage of development and we do not provide backwards compatibility of the API at this point.
diff --git a/pkgs/jni/analysis_options.yaml b/pkgs/jni/analysis_options.yaml
index 89f8ee9..e591be8 100644
--- a/pkgs/jni/analysis_options.yaml
+++ b/pkgs/jni/analysis_options.yaml
@@ -1,7 +1,7 @@
 include: package:flutter_lints/flutter.yaml
 
 analyzer:
-  exclude: [build/**]
+  exclude: [build/**, third_party/**]
   language:
     strict-raw-types: true
 
diff --git a/pkgs/jni/android/build.gradle b/pkgs/jni/android/build.gradle
index b91cb7b..13b25f6 100644
--- a/pkgs/jni/android/build.gradle
+++ b/pkgs/jni/android/build.gradle
@@ -1,6 +1,6 @@
 // The Android Gradle Plugin builds the native code with the Android NDK.
 
-group 'dev.dart.jni'
+group 'com.github.dart_lang.jni'
 version '1.0'
 
 buildscript {
diff --git a/pkgs/jni/android/src/main/AndroidManifest.xml b/pkgs/jni/android/src/main/AndroidManifest.xml
index 8055f58..9a6646f 100644
--- a/pkgs/jni/android/src/main/AndroidManifest.xml
+++ b/pkgs/jni/android/src/main/AndroidManifest.xml
@@ -1,3 +1,3 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-  package="dev.dart.jni">
+  package="com.github.dart_lang.jni">
 </manifest>
diff --git a/pkgs/jni/android/src/main/java/dev/dart/jni/JniPlugin.java b/pkgs/jni/android/src/main/java/com/github/dart_lang/jni/JniPlugin.java
similarity index 97%
rename from pkgs/jni/android/src/main/java/dev/dart/jni/JniPlugin.java
rename to pkgs/jni/android/src/main/java/com/github/dart_lang/jni/JniPlugin.java
index ffda30a..2a22dd8 100644
--- a/pkgs/jni/android/src/main/java/dev/dart/jni/JniPlugin.java
+++ b/pkgs/jni/android/src/main/java/com/github/dart_lang/jni/JniPlugin.java
@@ -2,7 +2,7 @@
 // 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.
 
-package dev.dart.jni;
+package com.github.dart_lang.jni;
 
 import android.app.Activity;
 import android.content.Context;
diff --git a/pkgs/jni/bin/setup.dart b/pkgs/jni/bin/setup.dart
index 1e7344a..38ed35c 100644
--- a/pkgs/jni/bin/setup.dart
+++ b/pkgs/jni/bin/setup.dart
@@ -35,9 +35,6 @@
   CommandRunner({this.printCmds = false});
   bool printCmds = false;
   int? time;
-  // TODO: time commands
-  // TODO: Run all commands in single shell instance
-  // IssueRef: https://github.com/dart-lang/jnigen/issues/14
   Future<CommandRunner> run(
       String exec, List<String> args, String workingDir) async {
     if (printCmds) {
@@ -168,8 +165,17 @@
   cmakeArgs.add(srcPath);
   await runner.run("cmake", cmakeArgs, buildPath);
   await runner.run("cmake", ["--build", "."], buildPath);
+  final buildPathUri = Uri.directory(buildPath);
   if (Platform.isWindows) {
-    await runner.run("move", ["Debug\\dartjni.dll", "."], buildPath);
+    final debugDir = buildPathUri.resolve('Debug');
+    for (var entry in Directory.fromUri(debugDir).listSync()) {
+      if (entry.path.endsWith('.dll')) {
+        final fileName = entry.uri.pathSegments.last;
+        final target = entry.parent.parent.uri.resolve(fileName);
+        log('rename ${entry.path} -> ${target.toFilePath()}');
+        entry.rename(target.toFilePath());
+      }
+    }
   }
   // delete cmakeTemporaryArtifacts
   deleteCMakeTemps(Uri.directory(buildPath));
diff --git a/pkgs/jni/example/README.md b/pkgs/jni/example/README.md
index 80af081..583f960 100644
--- a/pkgs/jni/example/README.md
+++ b/pkgs/jni/example/README.md
@@ -1,16 +1,3 @@
 # jni_example
-
 Demonstrates how to use the jni plugin.
 
-## Getting Started
-
-This project is a starting point for a Flutter application.
-
-A few resources to get you started if this is your first Flutter project:
-
-- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
-- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
-
-For help getting started with Flutter development, view the
-[online documentation](https://docs.flutter.dev/), which offers tutorials,
-samples, guidance on mobile development, and a full API reference.
diff --git a/pkgs/jni/example/android/app/build.gradle b/pkgs/jni/example/android/app/build.gradle
index ec13299..3c6742c 100644
--- a/pkgs/jni/example/android/app/build.gradle
+++ b/pkgs/jni/example/android/app/build.gradle
@@ -43,7 +43,7 @@
     }
 
     defaultConfig {
-        applicationId "dev.dart.jni_example"
+        applicationId "com.github.dart_lang.jni_example"
         // You can update the following values to match your application needs.
         // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration.
         minSdkVersion flutter.minSdkVersion
diff --git a/pkgs/jni/example/android/app/src/debug/AndroidManifest.xml b/pkgs/jni/example/android/app/src/debug/AndroidManifest.xml
index 2b66dc2..1a2af73 100644
--- a/pkgs/jni/example/android/app/src/debug/AndroidManifest.xml
+++ b/pkgs/jni/example/android/app/src/debug/AndroidManifest.xml
@@ -1,5 +1,5 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="dev.dart.jni_example">
+    package="com.github.dart_lang.jni_example">
     <!-- The INTERNET permission is required for development. Specifically,
          the Flutter tool needs it to communicate with the running application
          to allow setting breakpoints, to provide hot reload, etc.
diff --git a/pkgs/jni/example/android/app/src/main/AndroidManifest.xml b/pkgs/jni/example/android/app/src/main/AndroidManifest.xml
index 21d2c5c..5a849fc 100644
--- a/pkgs/jni/example/android/app/src/main/AndroidManifest.xml
+++ b/pkgs/jni/example/android/app/src/main/AndroidManifest.xml
@@ -1,5 +1,5 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="dev.dart.jni_example">
+    package="com.github.dart_lang.jni_example">
    <application
         android:label="jni_example"
         android:name="${applicationName}"
diff --git a/pkgs/jni/example/android/app/src/main/java/com/github/dart_lang/jni_example/Toaster.java b/pkgs/jni/example/android/app/src/main/java/com/github/dart_lang/jni_example/Toaster.java
new file mode 100644
index 0000000..ec61c8a
--- /dev/null
+++ b/pkgs/jni/example/android/app/src/main/java/com/github/dart_lang/jni_example/Toaster.java
@@ -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.
+
+package com.github.dart_lang.jni_example;
+
+import android.app.Activity;
+import android.content.Context;
+import android.widget.Toast;
+import androidx.annotation.Keep;
+
+@Keep
+class Toaster {
+  static Toaster makeText(Activity mainActivity, Context context, CharSequence text, int duration) {
+    Toaster toast = new Toaster();
+    toast.mainActivity = mainActivity;
+    toast.context = context;
+    toast.text = text;
+    toast.duration = duration;
+    return toast;
+  }
+
+  void show() {
+    mainActivity.runOnUiThread(() -> Toast.makeText(context, text, duration).show());
+  }
+
+  Activity mainActivity;
+  Context context;
+  CharSequence text;
+  int duration;
+}
diff --git a/pkgs/jni/example/android/app/src/main/java/dev/dart/jni_example/AnyToast.java b/pkgs/jni/example/android/app/src/main/java/dev/dart/jni_example/AnyToast.java
deleted file mode 100644
index 7de08d3..0000000
--- a/pkgs/jni/example/android/app/src/main/java/dev/dart/jni_example/AnyToast.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package dev.dart.jni_example;
-
-import android.app.Activity;
-import android.content.Context;
-import android.widget.Toast;
-import androidx.annotation.Keep;
-
-@Keep
-class AnyToast {
-  static AnyToast makeText(
-      Activity mainActivity, Context context, CharSequence text, int duration) {
-    AnyToast toast = new AnyToast();
-    toast.mainActivity = mainActivity;
-    toast.context = context;
-    toast.text = text;
-    toast.duration = duration;
-    return toast;
-  }
-
-  void show() {
-    mainActivity.runOnUiThread(() -> Toast.makeText(context, text, duration).show());
-  }
-
-  Activity mainActivity;
-  Context context;
-  CharSequence text;
-  int duration;
-}
diff --git a/pkgs/jni/example/android/app/src/main/kotlin/dev/dart/jni_example/MainActivity.kt b/pkgs/jni/example/android/app/src/main/kotlin/dev/dart/jni_example/MainActivity.kt
index 494cfa0..2aa0914 100644
--- a/pkgs/jni/example/android/app/src/main/kotlin/dev/dart/jni_example/MainActivity.kt
+++ b/pkgs/jni/example/android/app/src/main/kotlin/dev/dart/jni_example/MainActivity.kt
@@ -1,4 +1,4 @@
-package dev.dart.jni_example
+package com.github.dart_lang.jni_example
 
 import io.flutter.embedding.android.FlutterActivity
 
diff --git a/pkgs/jni/example/android/app/src/profile/AndroidManifest.xml b/pkgs/jni/example/android/app/src/profile/AndroidManifest.xml
index 2b66dc2..1a2af73 100644
--- a/pkgs/jni/example/android/app/src/profile/AndroidManifest.xml
+++ b/pkgs/jni/example/android/app/src/profile/AndroidManifest.xml
@@ -1,5 +1,5 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="dev.dart.jni_example">
+    package="com.github.dart_lang.jni_example">
     <!-- The INTERNET permission is required for development. Specifically,
          the Flutter tool needs it to communicate with the running application
          to allow setting breakpoints, to provide hot reload, etc.
diff --git a/pkgs/jni/example/integration_test/jni_object_test.dart b/pkgs/jni/example/integration_test/jni_object_test.dart
index 85086d9..aee60d9 100644
--- a/pkgs/jni/example/integration_test/jni_object_test.dart
+++ b/pkgs/jni/example/integration_test/jni_object_test.dart
@@ -1,107 +1,42 @@
+// 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 'dart:ffi';
-import 'dart:isolate';
 
 import 'package:flutter_test/flutter_test.dart';
-import 'package:ffi/ffi.dart';
 
 import 'package:jni/jni.dart';
-import 'package:jni/jni_object.dart';
 
 void main() {
   if (!Platform.isAndroid) {
-    Jni.spawn();
+    try {
+      Jni.spawn(dylibDir: "build/jni_libs");
+    } on JvmExistsException {
+      // TODO(#51): Support destroying and restarting JVM.
+    }
   }
 
-  final jni = Jni.getInstance();
-  testWidgets('get JNI Version', (tester) async {
-    final env = jni.getEnv();
-    expect(env.GetVersion(), isNot(equals(0)));
-  });
+  testWidgets("Long.intValue() using JniObject", (t) async {
+    final longClass = Jni.findJniClass("java/lang/Long");
 
-  testWidgets('Manually lookup & call Long.toHexString static method',
-      (tester) async {
-    final arena = Arena();
-    final env = jni.getEnv();
-    final longClass = env.FindClass("java/lang/Long".toNativeChars(arena));
-    final hexMethod = env.GetStaticMethodID(
-        longClass,
-        "toHexString".toNativeChars(arena),
-        "(J)Ljava/lang/String;".toNativeChars(arena));
+    final longCtor = longClass.getCtorID("(J)V");
 
-    for (var i in [1, 80, 13, 76, 1134453224145]) {
-      final jres = env.CallStaticObjectMethodA(
-          longClass, hexMethod, Jni.jvalues([JValueLong(i)], allocator: arena));
+    final long = longClass.newInstance(longCtor, [176]);
 
-      final res = env.asDartString(jres);
-      expect(res, equals(i.toRadixString(16)));
-      env.DeleteLocalRef(jres);
-    }
-    env.DeleteLocalRef(longClass);
-    arena.releaseAll();
-  });
-
-  testWidgets("asJString extension method", (tester) async {
-    final env = jni.getEnv();
-    const str = "QWERTY QWERTY";
-    final jstr = env.asJString(str);
-    expect(str, equals(env.asDartString(jstr)));
-    env.DeleteLocalRef(jstr);
-  });
-
-  testWidgets("Convert back and forth between dart and java string",
-      (tester) async {
-    final arena = Arena();
-    final env = jni.getEnv();
-    const str = "ABCD EFGH";
-    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.deleteAllLocalRefs([jstr]);
-    arena.releaseAll();
-  });
-
-  testWidgets("Print something from Java", (tester) async {
-    final arena = Arena();
-    final env = jni.getEnv();
-    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 JNI!";
-    final jstr = env.asJString(str);
-    env.deleteAllLocalRefs([system, printStream, jstr]);
-    arena.releaseAll();
-  });
-
-  testWidgets("Long.intValue() using JniObject", (tester) async {
-    final longClass = jni.findJniClass("java/lang/Long");
-
-    final longCtor = longClass.getConstructorID("(J)V");
-
-    final long = longClass.newObject(longCtor, [176]);
-
-    final intValue = long.callIntMethodByName("intValue", "()I", []);
+    final intValue = long.callMethodByName<int>("intValue", "()I", []);
     expect(intValue, equals(176));
 
     long.delete();
     longClass.delete();
   });
 
-  testWidgets("call a static method using JniClass APIs", (tester) async {
-    final integerClass = jni.wrapClass(jni.findClass("java/lang/Integer"));
-    final result = integerClass.callStaticObjectMethodByName(
+  testWidgets("call a static method using JniClass APIs", (t) async {
+    final integerClass = JniClass.fromRef(Jni.findClass("java/lang/Integer"));
+    final result = integerClass.callStaticMethodByName<JniString>(
         "toHexString", "(I)Ljava/lang/String;", [31]);
 
-    final resultString = result.asDartString();
+    final resultString = result.toDartString();
 
     result.delete();
     expect(resultString, equals("1f"));
@@ -109,119 +44,67 @@
     integerClass.delete();
   });
 
-  testWidgets("Example for using getMethodID", (tester) async {
-    final longClass = jni.findJniClass("java/lang/Long");
+  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 random = Jni.newInstance("java/util/Random", "()V", []);
 
     final nextIntMethod = random.getMethodID("nextInt", "(I)I");
 
     for (int i = 0; i < 100; i++) {
-      int r = random.callIntMethod(nextIntMethod, [256 * 256]);
+      int r = random.callMethod<int>(nextIntMethod, [256 * 256]);
       int bits = 0;
       final jbc =
-          longClass.callStaticIntMethod(bitCountMethod, [JValueLong(r)]);
+          longClass.callStaticMethod<int>(bitCountMethod, [JValueLong(r)]);
       while (r != 0) {
         bits += r % 2;
         r = (r / 2).floor();
       }
       expect(jbc, equals(bits));
     }
-
     random.delete();
     longClass.delete();
   });
 
-  testWidgets("invoke_", (tester) async {
-    final m = jni.invokeLongMethod(
-        "java/lang/Long", "min", "(JJ)J", [JValueLong(1234), JValueLong(1324)]);
+  // 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",
+        [JValueLong(1234), JValueLong(1324)], JniType.longType);
     expect(m, equals(1234));
   });
 
-  testWidgets("retrieve_", (tester) async {
-    final maxLong = jni.retrieveShortField("java/lang/Short", "MAX_VALUE", "S");
+  testWidgets("retrieve_", (t) async {
+    final maxLong = Jni.retrieveStaticField<int>(
+        "java/lang/Short", "MAX_VALUE", "S", JniType.shortType);
     expect(maxLong, equals(32767));
   });
 
-  testWidgets("callStaticStringMethod", (tester) async {
-    final longClass = jni.findJniClass("java/lang/Long");
+  testWidgets("callStaticStringMethod", (t) async {
+    final longClass = Jni.findJniClass("java/lang/Long");
     const n = 1223334444;
-    final strFromJava = longClass.callStaticStringMethodByName(
+    final strFromJava = longClass.callStaticMethodByName<String>(
         "toOctalString", "(J)Ljava/lang/String;", [JValueLong(n)]);
     expect(strFromJava, equals(n.toRadixString(8)));
     longClass.delete();
   });
 
-  testWidgets("Passing strings in arguments", (tester) async {
-    final out = jni.retrieveObjectField(
-        "java/lang/System", "out", "Ljava/io/PrintStream;");
-    // uncomment next line to see output
-    // (\n because test runner prints first char at end of the line)
-    //out.callVoidMethodByName(
-    //    "println", "(Ljava/lang/Object;)V", ["\nWorks (Apparently)"]);
-    out.delete();
-  });
-
-  testWidgets("Passing strings in arguments 2", (tester) async {
-    final twelve = jni.invokeByteMethod(
-        "java/lang/Byte", "parseByte", "(Ljava/lang/String;)B", ["12"]);
+  testWidgets("Passing strings in arguments", (t) async {
+    final twelve = Jni.invokeStaticMethod<int>("java/lang/Byte", "parseByte",
+        "(Ljava/lang/String;)B", ["12"], JniType.byteType);
     expect(twelve, equals(12));
   });
 
-  testWidgets("use() method", (tester) async {
-    final randomInt = jni.newInstance("java/util/Random", "()V", []).use(
-        (random) => random.callIntMethodByName("nextInt", "(I)I", [15]));
+  testWidgets("use() method", (t) async {
+    final randomInt = Jni.newInstance("java/util/Random", "()V", [])
+        .use((random) => random.callMethodByName<int>("nextInt", "(I)I", [15]));
     expect(randomInt, lessThan(15));
   });
 
-  testWidgets("enums", (tester) async {
-    final ordinal = jni
-        .retrieveObjectField(
+  testWidgets("enums", (t) async {
+    final ordinal = Jni.retrieveStaticField<JniObject>(
             "java/net/Proxy\$Type", "HTTP", "Ljava/net/Proxy\$Type;")
-        .use((f) => f.callIntMethodByName("ordinal", "()I", []));
+        .use((f) => f.callMethodByName<int>("ordinal", "()I", []));
     expect(ordinal, equals(1));
   });
-
-  testWidgets("Isolate", (tester) async {
-    Isolate.spawn(doSomeWorkInIsolate, null);
-  });
-
-  testWidgets("JniGlobalRef", (tester) async {
-    final uri = jni.invokeObjectMethod(
-        "java/net/URI",
-        "create",
-        "(Ljava/lang/String;)Ljava/net/URI;",
-        ["https://www.google.com/search"]);
-    final rg = uri.getGlobalRef();
-    await Future.delayed(const Duration(seconds: 1), () {
-      final env = jni.getEnv();
-      // Now comment this line & try to directly use uri local ref
-      // in outer scope.
-      //
-      // You will likely get a segfault, because Future computation is running
-      // in different thread.
-      //
-      // Therefore, don't share JniObjects across functions that can be
-      // scheduled across threads, including async callbacks.
-      final uri = JniObject.fromGlobalRef(env, rg);
-      final scheme =
-          uri.callStringMethodByName("getScheme", "()Ljava/lang/String;", []);
-      expect(scheme, "https");
-      uri.delete();
-      rg.deleteIn(env);
-    });
-    uri.delete();
-  });
-}
-
-void doSomeWorkInIsolate(Void? _) {
-  final jni = Jni.getInstance();
-  final random = jni.newInstance("java/util/Random", "()V", []);
-  // var r = random.callIntMethodByName("nextInt", "(I)I", [256]);
-  // expect(r, lessThan(256));
-  // Expect throws an OutsideTestException
-  // but you can uncomment below print and see it works
-  // print("\n$r");
-  random.delete();
 }
diff --git a/pkgs/jni/example/lib/main.dart b/pkgs/jni/example/lib/main.dart
index 0303900..aaa5341 100644
--- a/pkgs/jni/example/lib/main.dart
+++ b/pkgs/jni/example/lib/main.dart
@@ -9,104 +9,98 @@
 import 'dart:io';
 import 'dart:ffi';
 
-import 'package:ffi/ffi.dart';
 import 'package:jni/jni.dart';
-import 'package:jni/jni_object.dart';
 
-late Jni jni;
+// An example of calling JNI methods using low level primitives.
+// 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 JniObject and JniClass.
+String toJavaStringUsingEnv(int n) => using((arena) {
+      final env = Jni.env;
+      final cls = env.FindClass("java/lang/String".toNativeChars(arena));
+      final mId = env.GetStaticMethodID(cls, "valueOf".toNativeChars(),
+          "(I)Ljava/lang/String;".toNativeChars(arena));
+      final i = arena<JValue>();
+      i.ref.i = n;
+      final res = env.CallStaticObjectMethodA(cls, mId, i);
+      final str = env.asDartString(res);
+      env.deleteAllRefs([res, cls]);
+      return str;
+    });
 
-String localToJavaString(int n) {
-  final jniEnv = jni.getEnv();
-  final arena = Arena();
-  final cls = jniEnv.FindClass("java/lang/String".toNativeChars(arena));
-  final mId = jniEnv.GetStaticMethodID(cls, "valueOf".toNativeChars(),
-      "(I)Ljava/lang/String;".toNativeChars(arena));
-  final i = arena<JValue>();
-  i.ref.i = n;
-  final res = jniEnv.CallStaticObjectMethodA(cls, mId, i);
-  final str = jniEnv.asDartString(res);
-  jniEnv.deleteAllLocalRefs([res, cls]);
-  arena.releaseAll();
-  return str;
-}
-
-int random(int n) {
-  final arena = Arena();
-  final jniEnv = jni.getEnv();
-  final randomCls = jniEnv.FindClass("java/util/Random".toNativeChars(arena));
-  final ctor = jniEnv.GetMethodID(
-      randomCls, "<init>".toNativeChars(arena), "()V".toNativeChars(arena));
-  final random = jniEnv.NewObject(randomCls, ctor);
-  final nextInt = jniEnv.GetMethodID(
-      randomCls, "nextInt".toNativeChars(arena), "(I)I".toNativeChars(arena));
-  final res = jniEnv.CallIntMethodA(random, nextInt, Jni.jvalues([n]));
-  jniEnv.deleteAllLocalRefs([randomCls, random]);
-  return res;
-}
-
+int randomUsingEnv(int n) => using((arena) {
+      final env = Jni.env;
+      final randomCls = env.FindClass("java/util/Random".toNativeChars(arena));
+      final ctor = env.GetMethodID(
+          randomCls, "<init>".toNativeChars(arena), "()V".toNativeChars(arena));
+      final random = env.NewObject(randomCls, ctor);
+      final nextInt = env.GetMethodID(randomCls, "nextInt".toNativeChars(arena),
+          "(I)I".toNativeChars(arena));
+      final res = env.CallIntMethodA(random, nextInt, Jni.jvalues([n]));
+      env.deleteAllRefs([randomCls, random]);
+      return res;
+    });
 double randomDouble() {
-  final math = jni.findJniClass("java/lang/Math");
-  final random = math.callStaticDoubleMethodByName("random", "()D", []);
+  final math = Jni.findJniClass("java/lang/Math");
+  final random = math.callStaticMethodByName<double>("random", "()D", []);
   math.delete();
   return random;
 }
 
 int uptime() {
-  final systemClock = jni.findJniClass("android/os/SystemClock");
-  final uptime =
-      systemClock.callStaticLongMethodByName("uptimeMillis", "()J", []);
-  systemClock.delete();
-  return uptime;
+  return Jni.findJniClass("android/os/SystemClock").use(
+    (systemClock) => systemClock.callStaticMethodByName<int>(
+        "uptimeMillis", "()J", [], JniType.longType),
+  );
 }
 
 void quit() {
-  jni
-      .wrap(jni.getCurrentActivity())
-      .use((ac) => ac.callVoidMethodByName("finish", "()V", []));
+  JniObject.fromRef(Jni.getCurrentActivity())
+      .use((ac) => ac.callMethodByName<void>("finish", "()V", []));
 }
 
 void showToast(String text) {
-  // This is example for calling you app's custom java code.
-  // You place the AnyToast class in you app's android/ source
-  // Folder, with a Keep annotation or appropriate proguard rules
-  // to retain the class in release mode.
-  // In this example, AnyToast class is just a type of `Toast` that
+  // This is example for calling your app's custom java code.
+  // Place the Toaster class in the app's android/ source Folder, with a Keep
+  // annotation or appropriate proguard rules to retain classes in release mode.
+  //
+  // In this example, Toaster class wraps android.widget.Toast so that it
   // can be called from any thread. See
-  // android/app/src/main/java/dev/dart/jni_example/AnyToast.java
-  jni.invokeObjectMethod(
-      "dev/dart/jni_example/AnyToast",
+  // android/app/src/main/java/com/github/dart_lang/jni_example/Toaster.java
+  Jni.invokeStaticMethod<JniObject>(
+      "com/github/dart_lang/jni_example/Toaster",
       "makeText",
       "(Landroid/app/Activity;Landroid/content/Context;"
           "Ljava/lang/CharSequence;I)"
-          "Ldev/dart/jni_example/AnyToast;",
+          "Lcom/github/dart_lang/jni_example/Toaster;",
       [
-        jni.getCurrentActivity(),
-        jni.getCachedApplicationContext(),
-        ":-)",
-        0
-      ]).callVoidMethodByName("show", "()V", []);
+        Jni.getCurrentActivity(),
+        Jni.getCachedApplicationContext(),
+        "😀",
+        0,
+      ]).use((toast) => toast.callMethodByName("show", "()V", []));
 }
 
 void main() {
   if (!Platform.isAndroid) {
     Jni.spawn();
   }
-  jni = Jni.getInstance();
   final examples = [
-    Example("String.valueOf(1332)", () => localToJavaString(1332)),
-    Example("Generate random number", () => random(180), runInitially: false),
+    Example("String.valueOf(1332)", () => toJavaStringUsingEnv(1332)),
+    Example("Generate random number", () => randomUsingEnv(180),
+        runInitially: false),
     Example("Math.random()", () => randomDouble(), runInitially: false),
     if (Platform.isAndroid) ...[
       Example("Minutes of usage since reboot",
           () => (uptime() / (60 * 1000)).floor()),
       Example(
           "Device name",
-          () => jni.retrieveStringField(
+          () => Jni.retrieveStaticField<String>(
               "android/os/Build", "DEVICE", "Ljava/lang/String;")),
       Example(
         "Package name",
-        () => jni.wrap(jni.getCurrentActivity()).use((activity) => activity
-            .callStringMethodByName(
+        () => JniObject.fromRef(Jni.getCurrentActivity()).use((activity) =>
+            activity.callMethodByName<String>(
                 "getPackageName", "()Ljava/lang/String;", [])),
       ),
       Example("Show toast", () => showToast("Hello from JNI!"),
diff --git a/pkgs/jni/example/linux/CMakeLists.txt b/pkgs/jni/example/linux/CMakeLists.txt
index edcebfd..8df6c44 100644
--- a/pkgs/jni/example/linux/CMakeLists.txt
+++ b/pkgs/jni/example/linux/CMakeLists.txt
@@ -7,7 +7,7 @@
 set(BINARY_NAME "jni_example")
 # The unique GTK application identifier for this application. See:
 # https://wiki.gnome.org/HowDoI/ChooseApplicationID
-set(APPLICATION_ID "dev.dart.jni")
+set(APPLICATION_ID "com.github.dart_lang.jni")
 
 # Explicitly opt in to modern CMake behaviors to avoid warnings with recent
 # versions of CMake.
diff --git a/pkgs/jni/example/macos/Runner/Configs/AppInfo.xcconfig b/pkgs/jni/example/macos/Runner/Configs/AppInfo.xcconfig
index 92a02bd..acda531 100644
--- a/pkgs/jni/example/macos/Runner/Configs/AppInfo.xcconfig
+++ b/pkgs/jni/example/macos/Runner/Configs/AppInfo.xcconfig
@@ -8,7 +8,7 @@
 PRODUCT_NAME = jni_example
 
 // The application's bundle identifier
-PRODUCT_BUNDLE_IDENTIFIER = dev.dart.jniExample
+PRODUCT_BUNDLE_IDENTIFIER = com.github.dart_lang.jniExample
 
 // The copyright displayed in application information
-PRODUCT_COPYRIGHT = Copyright © 2022 dev.dart. All rights reserved.
+PRODUCT_COPYRIGHT = Copyright © 2022 com.github.dart_lang. All rights reserved.
diff --git a/pkgs/jni/example/test/widget_test.dart b/pkgs/jni/example/test/widget_test.dart
deleted file mode 100644
index def4482..0000000
--- a/pkgs/jni/example/test/widget_test.dart
+++ /dev/null
@@ -1,50 +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:flutter/material.dart';
-import 'package:flutter_test/flutter_test.dart';
-
-import 'package:jni/jni.dart';
-import 'package:jni/jni_object.dart';
-import 'package:jni_example/main.dart';
-
-// TODO(#38): This test is skipped because it broke for unknown reason in
-// in flutter 3.3.0
-
-// This test exists just to verify that
-// when everything is correct, JNI actually runs
-// However it's also kind of meaningless, because test environment
-// differs substantially from the device.
-
-void main() {
-  if (!Platform.isAndroid) {
-    Jni.spawn(helperDir: "build/jni_libs");
-  }
-  final jni = Jni.getInstance();
-  testWidgets("simple toString example", (tester) async {
-    await tester.pumpWidget(ExampleForTest(ExampleCard(Example(
-        "toString",
-        () => jni.findJniClass("java/lang/Long").use((long) => long
-            .callStaticStringMethodByName(
-                "toHexString", "(J)Ljava/lang/String;", [0x1876]))))));
-    expect(find.text("1876"), findsOneWidget);
-  });
-}
-
-class ExampleForTest extends StatelessWidget {
-  const ExampleForTest(this.widget, {Key? key}) : super(key: key);
-  final Widget widget;
-  @override
-  Widget build(BuildContext context) {
-    return MaterialApp(
-      title: '__TEST__',
-      home: Scaffold(
-        appBar: AppBar(title: const Text("__test__")),
-        body: Center(child: widget),
-      ),
-    );
-  }
-}
diff --git a/pkgs/jni/example/windows/runner/Runner.rc b/pkgs/jni/example/windows/runner/Runner.rc
index a4c901a..79c3952 100644
--- a/pkgs/jni/example/windows/runner/Runner.rc
+++ b/pkgs/jni/example/windows/runner/Runner.rc
@@ -89,11 +89,11 @@
     BEGIN
         BLOCK "040904e4"
         BEGIN
-            VALUE "CompanyName", "dev.dart" "\0"
+            VALUE "CompanyName", "com.github.dart_lang" "\0"
             VALUE "FileDescription", "jni_example" "\0"
             VALUE "FileVersion", VERSION_AS_STRING "\0"
             VALUE "InternalName", "jni_example" "\0"
-            VALUE "LegalCopyright", "Copyright (C) 2022 dev.dart. All rights reserved." "\0"
+            VALUE "LegalCopyright", "Copyright (C) 2022 Dart Project Authors. All rights reserved." "\0"
             VALUE "OriginalFilename", "jni_example.exe" "\0"
             VALUE "ProductName", "jni_example" "\0"
             VALUE "ProductVersion", VERSION_AS_STRING "\0"
diff --git a/pkgs/jni/ffigen.yaml b/pkgs/jni/ffigen.yaml
index f43903c..8fdb4f1 100644
--- a/pkgs/jni/ffigen.yaml
+++ b/pkgs/jni/ffigen.yaml
@@ -11,9 +11,10 @@
 output: 'lib/src/third_party/jni_bindings_generated.dart'
 headers:
   entry-points:
-    - 'src/dartjni.h'
+    - 'src/global_jni_env.h'
   include-directives:
     - 'src/dartjni.h'
+    - 'src/global_jni_env.h'
     - 'third_party/jni.h'
 compiler-opts:
   - '-Ithird_party/'
@@ -23,9 +24,15 @@
     - 'JNI_OnUnload'
     - 'JNI_OnLoad_L'
     - 'JNI_OnUnload_L'
+    - 'GetJniContext'
+    - 'setJniGetters'
+    - 'jni_log'
 structs:
   exclude:
-    - 'jni_context'
+    - 'JniContext'
+    - 'JNIEnv'
+    - '_JNIEnv'
+    - 'JNIInvokeInterface'
   rename:
     ## opaque struct definitions, base types of jfieldID and jmethodID
     '_jfieldID': 'jfieldID_'
@@ -41,6 +48,8 @@
   exclude:
     - 'jni'
     - 'jniEnv'
+    - 'context_getter'
+    - 'env_getter'
 typedefs:
   rename:
     'JNI(.*)': 'Jni$1'
@@ -73,7 +82,7 @@
     'jvalue': 'JValue'
 preamble: |
   // Autogenerated file. Do not edit.
-  // Generated from an annotated version of jni.h provided in Android NDK
+  // 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:
 
diff --git a/pkgs/jni/lib/internal_helpers_for_jnigen.dart b/pkgs/jni/lib/internal_helpers_for_jnigen.dart
new file mode 100644
index 0000000..fb0f36c
--- /dev/null
+++ b/pkgs/jni/lib/internal_helpers_for_jnigen.dart
@@ -0,0 +1,10 @@
+// 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 library exports the methods meant for use by generated code only, and
+/// not to be used directly.
+library internal_helpers_for_jnigen;
+
+export 'src/jni.dart' show ProtectedJniExtensions;
+export 'src/jni_object.dart' show JniReference;
diff --git a/pkgs/jni/lib/jni.dart b/pkgs/jni/lib/jni.dart
index 87049cb..bb5a5ae 100644
--- a/pkgs/jni/lib/jni.dart
+++ b/pkgs/jni/lib/jni.dart
@@ -5,13 +5,13 @@
 /// Package jni provides dart bindings for the Java Native Interface (JNI) on
 /// Android and desktop platforms.
 ///
-/// It's intended as a supplement to the (planned) jnigen tool, a Java wrapper
-/// generator using JNI. The goal is to provide sufficiently complete
+/// It's intended as a supplement to the jnigen tool, a Java wrapper generator
+/// using JNI. The goal of this package is to provide sufficiently complete
 /// and ergonomic access to underlying JNI APIs.
 ///
 /// Therefore, some understanding of JNI is required to use this module.
 ///
-/// __Java VM:__
+/// ## Java VM
 /// On Android, the existing JVM is used, a new JVM needs to be spawned on
 /// flutter desktop & standalone targets.
 ///
@@ -20,10 +20,9 @@
 ///   // Spin up a JVM instance with custom classpath etc..
 ///   Jni.spawn(/* options */);
 /// }
-/// Jni jni = Jni.getInstance();
 /// ```
 ///
-/// __Dart standalone support:__
+/// ## Dart standalone support
 /// On dart standalone target, we unfortunately have no mechanism to bundle
 /// the wrapper libraries with the executable. Thus it needs to be explicitly
 /// placed in a accessible directory and provided as an argument to Jni.spawn.
@@ -31,17 +30,21 @@
 /// This module depends on a shared library written in C. Therefore on dart
 /// standalone:
 ///
-///  * Build the library `libdartjni.so` in src/ directory of this plugin.
-///  * Bundle it appropriately with dart application.
-///  * Pass the path to library as a parameter to `Jni.spawn()`.
+/// * Run `dart run jni:setup` to build the shared library. The default output
+/// directory is build/jni_libs, which can be changed using `-B` switch.
 ///
-/// __JNIEnv:__
-/// The types `JNIEnv` and `JavaVM` in JNI are available as `JniEnv` and
-/// `JavaVM` respectively, with extension methods to conveniently invoke the
-/// function pointer members. Therefore the calling syntax will be similar to
-/// JNI in C++. The first `JniEnv *` parameter is implicit.
+/// * Provide the location of library to `Jni.spawn` call.
 ///
-/// __Debugging__:
+/// * If there are generated libraries (using jnigen), also build them using
+/// the command: `dart run jni:setup -p package_name` in the same directory.
+///
+/// ## JNIEnv
+/// `GlobalJniEnv` type provides a thin wrapper over `JNIEnv*` which can be used
+/// from across threads, and always returns JNI global references. This is
+/// needed because Dart doesn't make guarantees about even the straight-line
+/// code being scheduled on the same thread.
+///
+/// ## Debugging
 /// Debugging JNI errors hard in general.
 ///
 /// * On desktop platforms you can use JniEnv.ExceptionDescribe to print any
@@ -50,18 +53,20 @@
 /// in debug builds. If you are not getting clear stack traces on JNI errors,
 /// check the Android NDK page on how to enable CheckJNI using ADB.
 /// * As a rule of thumb, when there's a NoClassDefFound / NoMethodFound error,
-/// first check your class and method signatures for typos.
-///
+/// first check your class and method signatures for typos. Another common
+/// reason for NoClassDefFound error is missing classes in classpath.
 
-/// This file exports the minimum foundations of JNI.
-///
-/// For a higher level API, import `'package:jni/jni_object.dart'`.
+/// This library provides classes and functions for JNI interop from Dart.
 library jni;
 
-export 'src/third_party/jni_bindings_generated.dart' hide JNI_LOG_TAG;
-export 'src/jni.dart';
+export 'src/third_party/jni_bindings_generated.dart'
+    hide JNI_LOG_TAG, JniBindings, JniEnv, JniEnv1;
+export 'src/jni.dart' hide ProtectedJniExtensions;
 export 'src/jvalues.dart' hide JValueArgs, toJValues;
-export 'src/extensions.dart'
-    show StringMethodsForJni, CharPtrMethodsForJni, AdditionalJniEnvMethods;
+export 'src/env_extensions.dart'
+    show StringMethodsForJni, CharPtrMethodsForJni, AdditionalEnvMethods;
 export 'src/jni_exceptions.dart';
-export 'src/jl_object.dart';
+export 'src/jni_object.dart' hide JniReference;
+
+export 'package:ffi/ffi.dart' show using, Arena;
+export 'dart:ffi' show nullptr;
diff --git a/pkgs/jni/lib/jni_object.dart b/pkgs/jni/lib/jni_object.dart
deleted file mode 100644
index e0916f0..0000000
--- a/pkgs/jni/lib/jni_object.dart
+++ /dev/null
@@ -1,18 +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.
-
-/// jni_object library provides an easier interface to JNI's object references,
-/// providing various helper methods for one-off uses.
-///
-/// It consists of generated methods to access java objects and call functions
-/// on them, abstracting away most error checking and string conversions etc..
-///
-/// The important types are JniClass and JniObject, which are high level
-/// wrappers around JClass and JObject.
-///
-/// Import this library along with `jni.dart`.
-library jni_object;
-
-export 'src/jni_class.dart';
-export 'src/jni_object.dart';
diff --git a/pkgs/jni/lib/src/direct_methods_generated.dart b/pkgs/jni/lib/src/direct_methods_generated.dart
deleted file mode 100644
index d1f0191..0000000
--- a/pkgs/jni/lib/src/direct_methods_generated.dart
+++ /dev/null
@@ -1,634 +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.
-
-// Autogenerated; DO NOT EDIT
-// Generated by running the script in tool/gen_aux_methods.dart
-// coverage:ignore-file
-part of 'jni.dart';
-
-extension JniInvokeMethods on Jni {
-  String invokeStringMethod(String className, String methodName,
-      String signature, List<dynamic> args) {
-    return using((Arena arena) {
-      final env = getEnv();
-      final classNameChars = className.toNativeChars(arena);
-      final methodNameChars = methodName.toNativeChars(arena);
-      final signatureChars = signature.toNativeChars(arena);
-      final cls = _bindings.LoadClass(classNameChars);
-      if (cls == nullptr) {
-        env.checkException();
-      }
-      final methodID =
-          env.GetStaticMethodID(cls, methodNameChars, signatureChars);
-      if (methodID == nullptr) {
-        try {
-          env.checkException();
-        } catch (e) {
-          env.DeleteLocalRef(cls);
-          rethrow;
-        }
-      }
-      final jvArgs = JValueArgs(args, env, arena);
-      final result = env.CallStaticObjectMethodA(cls, methodID, jvArgs.values);
-      jvArgs.disposeIn(env);
-
-      final strRes = env.asDartString(result, deleteOriginal: true);
-      env.checkException();
-      return strRes;
-    });
-  }
-
-  String retrieveStringField(
-      String className, String fieldName, String signature) {
-    return using((Arena arena) {
-      final arena = Arena();
-      final env = getEnv();
-      final classNameChars = className.toNativeChars(arena);
-      final fieldNameChars = fieldName.toNativeChars(arena);
-      final signatueChars = signature.toNativeChars(arena);
-      final cls = _bindings.LoadClass(classNameChars);
-      if (cls == nullptr) {
-        env.checkException();
-      }
-      final fieldID = env.GetStaticFieldID(cls, fieldNameChars, signatueChars);
-      if (fieldID == nullptr) {
-        try {
-          env.checkException();
-        } catch (e) {
-          env.DeleteLocalRef(cls);
-          rethrow;
-        }
-      }
-      final result = env.GetStaticObjectField(cls, fieldID);
-
-      final strRes = env.asDartString(result, deleteOriginal: true);
-      env.checkException();
-      return strRes;
-    });
-  }
-
-  JniObject invokeObjectMethod(String className, String methodName,
-      String signature, List<dynamic> args) {
-    return using((Arena arena) {
-      final env = getEnv();
-      final classNameChars = className.toNativeChars(arena);
-      final methodNameChars = methodName.toNativeChars(arena);
-      final signatureChars = signature.toNativeChars(arena);
-      final cls = _bindings.LoadClass(classNameChars);
-      if (cls == nullptr) {
-        env.checkException();
-      }
-      final methodID =
-          env.GetStaticMethodID(cls, methodNameChars, signatureChars);
-      if (methodID == nullptr) {
-        try {
-          env.checkException();
-        } catch (e) {
-          env.DeleteLocalRef(cls);
-          rethrow;
-        }
-      }
-      final jvArgs = JValueArgs(args, env, arena);
-      final result = env.CallStaticObjectMethodA(cls, methodID, jvArgs.values);
-      jvArgs.disposeIn(env);
-
-      env.checkException();
-      return JniObject.of(env, result, nullptr);
-    });
-  }
-
-  JniObject retrieveObjectField(
-      String className, String fieldName, String signature) {
-    return using((Arena arena) {
-      final arena = Arena();
-      final env = getEnv();
-      final classNameChars = className.toNativeChars(arena);
-      final fieldNameChars = fieldName.toNativeChars(arena);
-      final signatueChars = signature.toNativeChars(arena);
-      final cls = _bindings.LoadClass(classNameChars);
-      if (cls == nullptr) {
-        env.checkException();
-      }
-      final fieldID = env.GetStaticFieldID(cls, fieldNameChars, signatueChars);
-      if (fieldID == nullptr) {
-        try {
-          env.checkException();
-        } catch (e) {
-          env.DeleteLocalRef(cls);
-          rethrow;
-        }
-      }
-      final result = env.GetStaticObjectField(cls, fieldID);
-
-      env.checkException();
-      return JniObject.of(env, result, nullptr);
-    });
-  }
-
-  bool invokeBooleanMethod(String className, String methodName,
-      String signature, List<dynamic> args) {
-    return using((Arena arena) {
-      final env = getEnv();
-      final classNameChars = className.toNativeChars(arena);
-      final methodNameChars = methodName.toNativeChars(arena);
-      final signatureChars = signature.toNativeChars(arena);
-      final cls = _bindings.LoadClass(classNameChars);
-      if (cls == nullptr) {
-        env.checkException();
-      }
-      final methodID =
-          env.GetStaticMethodID(cls, methodNameChars, signatureChars);
-      if (methodID == nullptr) {
-        try {
-          env.checkException();
-        } catch (e) {
-          env.DeleteLocalRef(cls);
-          rethrow;
-        }
-      }
-      final jvArgs = JValueArgs(args, env, arena);
-      final result = env.CallStaticBooleanMethodA(cls, methodID, jvArgs.values);
-      jvArgs.disposeIn(env);
-      env.DeleteLocalRef(cls);
-
-      env.checkException();
-      return result != 0;
-    });
-  }
-
-  bool retrieveBooleanField(
-      String className, String fieldName, String signature) {
-    return using((Arena arena) {
-      final arena = Arena();
-      final env = getEnv();
-      final classNameChars = className.toNativeChars(arena);
-      final fieldNameChars = fieldName.toNativeChars(arena);
-      final signatueChars = signature.toNativeChars(arena);
-      final cls = _bindings.LoadClass(classNameChars);
-      if (cls == nullptr) {
-        env.checkException();
-      }
-      final fieldID = env.GetStaticFieldID(cls, fieldNameChars, signatueChars);
-      if (fieldID == nullptr) {
-        try {
-          env.checkException();
-        } catch (e) {
-          env.DeleteLocalRef(cls);
-          rethrow;
-        }
-      }
-      final result = env.GetStaticBooleanField(cls, fieldID);
-      env.DeleteLocalRef(cls);
-
-      env.checkException();
-      return result != 0;
-    });
-  }
-
-  int invokeByteMethod(String className, String methodName, String signature,
-      List<dynamic> args) {
-    return using((Arena arena) {
-      final env = getEnv();
-      final classNameChars = className.toNativeChars(arena);
-      final methodNameChars = methodName.toNativeChars(arena);
-      final signatureChars = signature.toNativeChars(arena);
-      final cls = _bindings.LoadClass(classNameChars);
-      if (cls == nullptr) {
-        env.checkException();
-      }
-      final methodID =
-          env.GetStaticMethodID(cls, methodNameChars, signatureChars);
-      if (methodID == nullptr) {
-        try {
-          env.checkException();
-        } catch (e) {
-          env.DeleteLocalRef(cls);
-          rethrow;
-        }
-      }
-      final jvArgs = JValueArgs(args, env, arena);
-      final result = env.CallStaticByteMethodA(cls, methodID, jvArgs.values);
-      jvArgs.disposeIn(env);
-      env.DeleteLocalRef(cls);
-
-      env.checkException();
-      return result;
-    });
-  }
-
-  int retrieveByteField(String className, String fieldName, String signature) {
-    return using((Arena arena) {
-      final arena = Arena();
-      final env = getEnv();
-      final classNameChars = className.toNativeChars(arena);
-      final fieldNameChars = fieldName.toNativeChars(arena);
-      final signatueChars = signature.toNativeChars(arena);
-      final cls = _bindings.LoadClass(classNameChars);
-      if (cls == nullptr) {
-        env.checkException();
-      }
-      final fieldID = env.GetStaticFieldID(cls, fieldNameChars, signatueChars);
-      if (fieldID == nullptr) {
-        try {
-          env.checkException();
-        } catch (e) {
-          env.DeleteLocalRef(cls);
-          rethrow;
-        }
-      }
-      final result = env.GetStaticByteField(cls, fieldID);
-      env.DeleteLocalRef(cls);
-
-      env.checkException();
-      return result;
-    });
-  }
-
-  int invokeCharMethod(String className, String methodName, String signature,
-      List<dynamic> args) {
-    return using((Arena arena) {
-      final env = getEnv();
-      final classNameChars = className.toNativeChars(arena);
-      final methodNameChars = methodName.toNativeChars(arena);
-      final signatureChars = signature.toNativeChars(arena);
-      final cls = _bindings.LoadClass(classNameChars);
-      if (cls == nullptr) {
-        env.checkException();
-      }
-      final methodID =
-          env.GetStaticMethodID(cls, methodNameChars, signatureChars);
-      if (methodID == nullptr) {
-        try {
-          env.checkException();
-        } catch (e) {
-          env.DeleteLocalRef(cls);
-          rethrow;
-        }
-      }
-      final jvArgs = JValueArgs(args, env, arena);
-      final result = env.CallStaticCharMethodA(cls, methodID, jvArgs.values);
-      jvArgs.disposeIn(env);
-      env.DeleteLocalRef(cls);
-
-      env.checkException();
-      return result;
-    });
-  }
-
-  int retrieveCharField(String className, String fieldName, String signature) {
-    return using((Arena arena) {
-      final arena = Arena();
-      final env = getEnv();
-      final classNameChars = className.toNativeChars(arena);
-      final fieldNameChars = fieldName.toNativeChars(arena);
-      final signatueChars = signature.toNativeChars(arena);
-      final cls = _bindings.LoadClass(classNameChars);
-      if (cls == nullptr) {
-        env.checkException();
-      }
-      final fieldID = env.GetStaticFieldID(cls, fieldNameChars, signatueChars);
-      if (fieldID == nullptr) {
-        try {
-          env.checkException();
-        } catch (e) {
-          env.DeleteLocalRef(cls);
-          rethrow;
-        }
-      }
-      final result = env.GetStaticCharField(cls, fieldID);
-      env.DeleteLocalRef(cls);
-
-      env.checkException();
-      return result;
-    });
-  }
-
-  int invokeShortMethod(String className, String methodName, String signature,
-      List<dynamic> args) {
-    return using((Arena arena) {
-      final env = getEnv();
-      final classNameChars = className.toNativeChars(arena);
-      final methodNameChars = methodName.toNativeChars(arena);
-      final signatureChars = signature.toNativeChars(arena);
-      final cls = _bindings.LoadClass(classNameChars);
-      if (cls == nullptr) {
-        env.checkException();
-      }
-      final methodID =
-          env.GetStaticMethodID(cls, methodNameChars, signatureChars);
-      if (methodID == nullptr) {
-        try {
-          env.checkException();
-        } catch (e) {
-          env.DeleteLocalRef(cls);
-          rethrow;
-        }
-      }
-      final jvArgs = JValueArgs(args, env, arena);
-      final result = env.CallStaticShortMethodA(cls, methodID, jvArgs.values);
-      jvArgs.disposeIn(env);
-      env.DeleteLocalRef(cls);
-
-      env.checkException();
-      return result;
-    });
-  }
-
-  int retrieveShortField(String className, String fieldName, String signature) {
-    return using((Arena arena) {
-      final arena = Arena();
-      final env = getEnv();
-      final classNameChars = className.toNativeChars(arena);
-      final fieldNameChars = fieldName.toNativeChars(arena);
-      final signatueChars = signature.toNativeChars(arena);
-      final cls = _bindings.LoadClass(classNameChars);
-      if (cls == nullptr) {
-        env.checkException();
-      }
-      final fieldID = env.GetStaticFieldID(cls, fieldNameChars, signatueChars);
-      if (fieldID == nullptr) {
-        try {
-          env.checkException();
-        } catch (e) {
-          env.DeleteLocalRef(cls);
-          rethrow;
-        }
-      }
-      final result = env.GetStaticShortField(cls, fieldID);
-      env.DeleteLocalRef(cls);
-
-      env.checkException();
-      return result;
-    });
-  }
-
-  int invokeIntMethod(String className, String methodName, String signature,
-      List<dynamic> args) {
-    return using((Arena arena) {
-      final env = getEnv();
-      final classNameChars = className.toNativeChars(arena);
-      final methodNameChars = methodName.toNativeChars(arena);
-      final signatureChars = signature.toNativeChars(arena);
-      final cls = _bindings.LoadClass(classNameChars);
-      if (cls == nullptr) {
-        env.checkException();
-      }
-      final methodID =
-          env.GetStaticMethodID(cls, methodNameChars, signatureChars);
-      if (methodID == nullptr) {
-        try {
-          env.checkException();
-        } catch (e) {
-          env.DeleteLocalRef(cls);
-          rethrow;
-        }
-      }
-      final jvArgs = JValueArgs(args, env, arena);
-      final result = env.CallStaticIntMethodA(cls, methodID, jvArgs.values);
-      jvArgs.disposeIn(env);
-      env.DeleteLocalRef(cls);
-
-      env.checkException();
-      return result;
-    });
-  }
-
-  int retrieveIntField(String className, String fieldName, String signature) {
-    return using((Arena arena) {
-      final arena = Arena();
-      final env = getEnv();
-      final classNameChars = className.toNativeChars(arena);
-      final fieldNameChars = fieldName.toNativeChars(arena);
-      final signatueChars = signature.toNativeChars(arena);
-      final cls = _bindings.LoadClass(classNameChars);
-      if (cls == nullptr) {
-        env.checkException();
-      }
-      final fieldID = env.GetStaticFieldID(cls, fieldNameChars, signatueChars);
-      if (fieldID == nullptr) {
-        try {
-          env.checkException();
-        } catch (e) {
-          env.DeleteLocalRef(cls);
-          rethrow;
-        }
-      }
-      final result = env.GetStaticIntField(cls, fieldID);
-      env.DeleteLocalRef(cls);
-
-      env.checkException();
-      return result;
-    });
-  }
-
-  int invokeLongMethod(String className, String methodName, String signature,
-      List<dynamic> args) {
-    return using((Arena arena) {
-      final env = getEnv();
-      final classNameChars = className.toNativeChars(arena);
-      final methodNameChars = methodName.toNativeChars(arena);
-      final signatureChars = signature.toNativeChars(arena);
-      final cls = _bindings.LoadClass(classNameChars);
-      if (cls == nullptr) {
-        env.checkException();
-      }
-      final methodID =
-          env.GetStaticMethodID(cls, methodNameChars, signatureChars);
-      if (methodID == nullptr) {
-        try {
-          env.checkException();
-        } catch (e) {
-          env.DeleteLocalRef(cls);
-          rethrow;
-        }
-      }
-      final jvArgs = JValueArgs(args, env, arena);
-      final result = env.CallStaticLongMethodA(cls, methodID, jvArgs.values);
-      jvArgs.disposeIn(env);
-      env.DeleteLocalRef(cls);
-
-      env.checkException();
-      return result;
-    });
-  }
-
-  int retrieveLongField(String className, String fieldName, String signature) {
-    return using((Arena arena) {
-      final arena = Arena();
-      final env = getEnv();
-      final classNameChars = className.toNativeChars(arena);
-      final fieldNameChars = fieldName.toNativeChars(arena);
-      final signatueChars = signature.toNativeChars(arena);
-      final cls = _bindings.LoadClass(classNameChars);
-      if (cls == nullptr) {
-        env.checkException();
-      }
-      final fieldID = env.GetStaticFieldID(cls, fieldNameChars, signatueChars);
-      if (fieldID == nullptr) {
-        try {
-          env.checkException();
-        } catch (e) {
-          env.DeleteLocalRef(cls);
-          rethrow;
-        }
-      }
-      final result = env.GetStaticLongField(cls, fieldID);
-      env.DeleteLocalRef(cls);
-
-      env.checkException();
-      return result;
-    });
-  }
-
-  double invokeFloatMethod(String className, String methodName,
-      String signature, List<dynamic> args) {
-    return using((Arena arena) {
-      final env = getEnv();
-      final classNameChars = className.toNativeChars(arena);
-      final methodNameChars = methodName.toNativeChars(arena);
-      final signatureChars = signature.toNativeChars(arena);
-      final cls = _bindings.LoadClass(classNameChars);
-      if (cls == nullptr) {
-        env.checkException();
-      }
-      final methodID =
-          env.GetStaticMethodID(cls, methodNameChars, signatureChars);
-      if (methodID == nullptr) {
-        try {
-          env.checkException();
-        } catch (e) {
-          env.DeleteLocalRef(cls);
-          rethrow;
-        }
-      }
-      final jvArgs = JValueArgs(args, env, arena);
-      final result = env.CallStaticFloatMethodA(cls, methodID, jvArgs.values);
-      jvArgs.disposeIn(env);
-      env.DeleteLocalRef(cls);
-
-      env.checkException();
-      return result;
-    });
-  }
-
-  double retrieveFloatField(
-      String className, String fieldName, String signature) {
-    return using((Arena arena) {
-      final arena = Arena();
-      final env = getEnv();
-      final classNameChars = className.toNativeChars(arena);
-      final fieldNameChars = fieldName.toNativeChars(arena);
-      final signatueChars = signature.toNativeChars(arena);
-      final cls = _bindings.LoadClass(classNameChars);
-      if (cls == nullptr) {
-        env.checkException();
-      }
-      final fieldID = env.GetStaticFieldID(cls, fieldNameChars, signatueChars);
-      if (fieldID == nullptr) {
-        try {
-          env.checkException();
-        } catch (e) {
-          env.DeleteLocalRef(cls);
-          rethrow;
-        }
-      }
-      final result = env.GetStaticFloatField(cls, fieldID);
-      env.DeleteLocalRef(cls);
-
-      env.checkException();
-      return result;
-    });
-  }
-
-  double invokeDoubleMethod(String className, String methodName,
-      String signature, List<dynamic> args) {
-    return using((Arena arena) {
-      final env = getEnv();
-      final classNameChars = className.toNativeChars(arena);
-      final methodNameChars = methodName.toNativeChars(arena);
-      final signatureChars = signature.toNativeChars(arena);
-      final cls = _bindings.LoadClass(classNameChars);
-      if (cls == nullptr) {
-        env.checkException();
-      }
-      final methodID =
-          env.GetStaticMethodID(cls, methodNameChars, signatureChars);
-      if (methodID == nullptr) {
-        try {
-          env.checkException();
-        } catch (e) {
-          env.DeleteLocalRef(cls);
-          rethrow;
-        }
-      }
-      final jvArgs = JValueArgs(args, env, arena);
-      final result = env.CallStaticDoubleMethodA(cls, methodID, jvArgs.values);
-      jvArgs.disposeIn(env);
-      env.DeleteLocalRef(cls);
-
-      env.checkException();
-      return result;
-    });
-  }
-
-  double retrieveDoubleField(
-      String className, String fieldName, String signature) {
-    return using((Arena arena) {
-      final arena = Arena();
-      final env = getEnv();
-      final classNameChars = className.toNativeChars(arena);
-      final fieldNameChars = fieldName.toNativeChars(arena);
-      final signatueChars = signature.toNativeChars(arena);
-      final cls = _bindings.LoadClass(classNameChars);
-      if (cls == nullptr) {
-        env.checkException();
-      }
-      final fieldID = env.GetStaticFieldID(cls, fieldNameChars, signatueChars);
-      if (fieldID == nullptr) {
-        try {
-          env.checkException();
-        } catch (e) {
-          env.DeleteLocalRef(cls);
-          rethrow;
-        }
-      }
-      final result = env.GetStaticDoubleField(cls, fieldID);
-      env.DeleteLocalRef(cls);
-
-      env.checkException();
-      return result;
-    });
-  }
-
-  void invokeVoidMethod(String className, String methodName, String signature,
-      List<dynamic> args) {
-    return using((Arena arena) {
-      final env = getEnv();
-      final classNameChars = className.toNativeChars(arena);
-      final methodNameChars = methodName.toNativeChars(arena);
-      final signatureChars = signature.toNativeChars(arena);
-      final cls = _bindings.LoadClass(classNameChars);
-      if (cls == nullptr) {
-        env.checkException();
-      }
-      final methodID =
-          env.GetStaticMethodID(cls, methodNameChars, signatureChars);
-      if (methodID == nullptr) {
-        try {
-          env.checkException();
-        } catch (e) {
-          env.DeleteLocalRef(cls);
-          rethrow;
-        }
-      }
-      final jvArgs = JValueArgs(args, env, arena);
-      final result = env.CallStaticVoidMethodA(cls, methodID, jvArgs.values);
-      jvArgs.disposeIn(env);
-      env.DeleteLocalRef(cls);
-
-      env.checkException();
-      return result;
-    });
-  }
-}
diff --git a/pkgs/jni/lib/src/extensions.dart b/pkgs/jni/lib/src/env_extensions.dart
similarity index 83%
rename from pkgs/jni/lib/src/extensions.dart
rename to pkgs/jni/lib/src/env_extensions.dart
index 281460e..63fddd1 100644
--- a/pkgs/jni/lib/src/extensions.dart
+++ b/pkgs/jni/lib/src/env_extensions.dart
@@ -10,21 +10,7 @@
 
 import 'jni_exceptions.dart';
 
-extension StringMethodsForJni on String {
-  /// Returns a Utf-8 encoded Pointer<Char> with contents same as this string.
-  Pointer<Char> toNativeChars([Allocator allocator = malloc]) {
-    return toNativeUtf8(allocator: allocator).cast<Char>();
-  }
-}
-
-extension CharPtrMethodsForJni on Pointer<Char> {
-  /// Same as calling `cast<Utf8>` followed by `toDartString`.
-  String toDartString() {
-    return cast<Utf8>().toDartString();
-  }
-}
-
-extension AdditionalJniEnvMethods on Pointer<JniEnv> {
+extension AdditionalEnvMethods on Pointer<GlobalJniEnv> {
   /// Convenience method for converting a [JString]
   /// to dart string.
   /// if [deleteOriginal] is specified, jstring passed will be deleted using
@@ -37,23 +23,23 @@
     final result = chars.cast<Utf8>().toDartString();
     ReleaseStringUTFChars(jstring, chars);
     if (deleteOriginal) {
-      DeleteLocalRef(jstring);
+      DeleteGlobalRef(jstring);
     }
     return result;
   }
 
   /// Return a new [JString] from contents of [s].
-  JString asJString(String s) {
-    final utf = s.toNativeUtf8().cast<Char>();
-    final result = NewStringUTF(utf);
-    malloc.free(utf);
-    return result;
-  }
+  JString asJString(String s) => using((arena) {
+        final utf = s.toNativeUtf8().cast<Char>();
+        final result = NewStringUTF(utf);
+        malloc.free(utf);
+        return result;
+      });
 
-  /// Deletes all local references in [refs].
-  void deleteAllLocalRefs(List<JObject> refs) {
+  /// Deletes all references in [refs].
+  void deleteAllRefs(List<JObject> refs) {
     for (final ref in refs) {
-      DeleteLocalRef(ref);
+      DeleteGlobalRef(ref);
     }
   }
 
@@ -64,16 +50,15 @@
   void checkException({bool describe = false}) {
     final exc = ExceptionOccurred();
     if (exc != nullptr) {
-      // TODO: Doing this every time is expensive.
+      // TODO(#13): Doing this every time is expensive.
       // Should lookup and cache method reference,
       // and keep it alive by keeping a reference to Exception class.
-      // IssueRef: https://github.com/dart-lang/jnigen/issues/13
       final ecls = GetObjectClass(exc);
       final toStr = GetMethodID(ecls, _toString, _toStringSig);
       final jstr = CallObjectMethod(exc, toStr);
       final dstr = asDartString(jstr);
       for (final i in [jstr, ecls]) {
-        DeleteLocalRef(i);
+        DeleteGlobalRef(i);
       }
       if (describe) {
         ExceptionDescribe();
@@ -91,7 +76,21 @@
     final printStackTrace =
         GetMethodID(ecls, _printStackTrace, _printStackTraceSig);
     CallVoidMethod(je.err, printStackTrace);
-    DeleteLocalRef(ecls);
+    DeleteGlobalRef(ecls);
+  }
+}
+
+extension StringMethodsForJni on String {
+  /// Returns a Utf-8 encoded Pointer<Char> with contents same as this string.
+  Pointer<Char> toNativeChars([Allocator allocator = malloc]) {
+    return toNativeUtf8(allocator: allocator).cast<Char>();
+  }
+}
+
+extension CharPtrMethodsForJni on Pointer<Char> {
+  /// Same as calling `cast<Utf8>` followed by `toDartString`.
+  String toDartString() {
+    return cast<Utf8>().toDartString();
   }
 }
 
diff --git a/pkgs/jni/lib/src/jl_object.dart b/pkgs/jni/lib/src/jl_object.dart
deleted file mode 100644
index 2778dfc..0000000
--- a/pkgs/jni/lib/src/jl_object.dart
+++ /dev/null
@@ -1,65 +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:ffi/ffi.dart';
-
-import 'third_party/jni_bindings_generated.dart';
-import 'jni_exceptions.dart';
-import 'jni.dart';
-
-/// A container for a global [JObject] reference.
-class JlObject {
-  /// Constructs a `JlObject` from JNI reference.
-  JlObject.fromRef(this.reference);
-
-  /// Stored JNI global reference to the object.
-  JObject reference;
-
-  bool _deleted = false;
-
-  /// Deletes the underlying JNI reference.
-  ///
-  /// Must be called after this object is no longer needed.
-  void delete() {
-    if (_deleted) {
-      throw DoubleFreeException(this, reference);
-    }
-    _deleted = true;
-    // TODO(#12): this should be done in jni-thread-safe way
-    // will be solved when #12 is implemented.
-    Jni.getInstance().getEnv().DeleteGlobalRef(reference);
-  }
-}
-
-/// A container for JNI strings, with convertion to & from dart strings.
-class JlString extends JlObject {
-  JlString.fromRef(JString reference) : super.fromRef(reference);
-
-  static JString _toJavaString(String s) {
-    final chars = s.toNativeUtf8().cast<Char>();
-    final jstr = Jni.getInstance().toJavaString(chars);
-    malloc.free(chars);
-    return jstr;
-  }
-
-  JlString.fromString(String s) : super.fromRef(_toJavaString(s));
-
-  String toDartString() {
-    final jni = Jni.getInstance();
-    if (reference == nullptr) {
-      throw NullJlStringException();
-    }
-    final chars = jni.getJavaStringChars(reference);
-    final result = chars.cast<Utf8>().toDartString();
-    jni.releaseJavaStringChars(reference, chars);
-    return result;
-  }
-
-  late final _dartString = toDartString();
-
-  @override
-  String toString() => _dartString;
-}
diff --git a/pkgs/jni/lib/src/jni.dart b/pkgs/jni/lib/src/jni.dart
index a188d86..115a74a 100644
--- a/pkgs/jni/lib/src/jni.dart
+++ b/pkgs/jni/lib/src/jni.dart
@@ -9,14 +9,10 @@
 import 'package:path/path.dart';
 
 import 'third_party/jni_bindings_generated.dart';
-import 'extensions.dart';
+import 'env_extensions.dart';
 import 'jvalues.dart';
-
-import 'jni_object.dart';
-import 'jni_class.dart';
 import 'jni_exceptions.dart';
-
-part 'direct_methods_generated.dart';
+import 'jni_object.dart';
 
 String _getLibraryFileName(String base) {
   if (Platform.isLinux || Platform.isAndroid) {
@@ -34,8 +30,7 @@
 ///
 /// If path is provided, it's used to load the library.
 /// Else just the platform-specific filename is passed to DynamicLibrary.open
-DynamicLibrary _loadJniHelpersLibrary(
-    {String? dir, String baseName = "dartjni"}) {
+DynamicLibrary _loadDartJniLibrary({String? dir, String baseName = "dartjni"}) {
   final fileName = _getLibraryFileName(baseName);
   final libPath = (dir != null) ? join(dir, fileName) : fileName;
   try {
@@ -46,123 +41,81 @@
   }
 }
 
-/// Jni represents a single running JNI instance.
-///
-/// It provides convenience functions for looking up and invoking functions
-/// without several FFI conversions.
-///
-/// You can also get access to instance of underlying JavaVM and JniEnv, and
-/// then use them in a way similar to JNI C++ API.
-class Jni {
-  final JniBindings _bindings;
+/// Utilities to spawn and manage JNI.
+abstract class Jni {
+  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');
 
-  Jni._(DynamicLibrary library, [this._helperDir])
-      : _bindings = JniBindings(library),
-        _getJniEnvFn = library.lookup<Void>('GetJniEnv'),
-        _getJniContextFn = library.lookup<Void>('GetJniContext');
+  /// Store dylibDir if any was used.
+  static String? _dylibDir;
 
-  static Jni? _instance;
-
-  /// Stores helperDir if any was used.
-  final String? _helperDir;
-
-  /// Returns the existing Jni object.
-  ///
-  /// If not running on Android and no Jni is spawned
-  /// using Jni.spawn(), throws an exception.
-  ///
-  /// On Dart standalone, when calling for the first time from
-  /// a new isolate, make sure to pass the library path.
-  final Pointer<Void> _getJniEnvFn, _getJniContextFn;
-
-  static Jni getInstance() {
-    if (_instance == null) {
-      final dylib = _loadJniHelpersLibrary();
-      final inst = Jni._(dylib);
-      if (inst.getJavaVM() == nullptr) {
-        throw StateError("Fatal: No JVM associated with this process!"
-            " Did you call Jni.spawn?");
-      }
-      // If no error, save this singleton.
-      _instance = inst;
-    }
-    return _instance!;
-  }
-
-  /// Initialize instance from custom helper library path.
-  ///
-  /// On dart standalone, call this in new isolate before
-  /// doing getInstance().
+  /// Sets the directory where dynamic libraries are looked for.
+  /// On dart standalone, call this in new isolate before doing
+  /// any JNI operation.
   ///
   /// (The reason is that dylibs need to be loaded in every isolate.
   /// On flutter it's done by library. On dart standalone we don't
   /// know the library path.)
-  static void load({required String helperDir}) {
-    if (_instance != null) {
-      throw StateError('Fatal: a JNI instance already exists in this isolate');
-    }
-    final inst = Jni._(_loadJniHelpersLibrary(dir: helperDir), helperDir);
-    if (inst.getJavaVM() == nullptr) {
-      throw StateError("Fatal: No JVM associated with this process");
-    }
-    _instance = inst;
+  static void setDylibDir({required String dylibDir}) {
+    _dylibDir = dylibDir;
   }
 
-  /// Spawn an instance of JVM using JNI.
-  /// This instance will be returned by future calls to [getInstance]
+  /// Spawn an instance of JVM using JNI. This method should be called at the
+  /// beginning of the program with appropriate options, before other isolates
+  /// are spawned.
   ///
-  /// [helperDir] is path of the directory where the wrapper library is found.
+  /// [dylibDir] is path of the directory where the wrapper library is found.
   /// This parameter needs to be passed manually on __Dart standalone target__,
   /// since we have no reliable way to bundle it with the package.
   ///
   /// [jvmOptions], [ignoreUnrecognized], & [jniVersion] are passed to the JVM.
   /// Strings in [classPath], if any, are used to construct an additional
   /// JVM option of the form "-Djava.class.path={paths}".
-  static Jni spawn({
-    String? helperDir,
-    int logLevel = JniLogLevel.JNI_INFO,
+  static void spawn({
+    String? dylibDir,
     List<String> jvmOptions = const [],
     List<String> classPath = const [],
     bool ignoreUnrecognized = false,
     int jniVersion = JNI_VERSION_1_6,
-  }) {
-    if (_instance != null) {
-      throw UnsupportedError("Currently only 1 VM is supported.");
-    }
-    final dylib = _loadJniHelpersLibrary(dir: helperDir);
-    final inst = Jni._(dylib, helperDir);
-    _instance = inst;
-    inst._bindings.SetJNILogging(logLevel);
-    final jArgs = _createVMArgs(
-      options: jvmOptions,
-      classPath: classPath,
-      version: jniVersion,
-      ignoreUnrecognized: ignoreUnrecognized,
-    );
-    inst._bindings.SpawnJvm(jArgs);
-    _freeVMArgs(jArgs);
-    return inst;
-  }
+  }) =>
+      using((arena) {
+        _dylibDir = dylibDir;
+        final existVm = _bindings.GetJavaVM();
+        if (existVm != nullptr) {
+          throw JvmExistsException();
+        }
+        final jvmArgs = _createVMArgs(
+          options: jvmOptions,
+          classPath: classPath,
+          version: jniVersion,
+          ignoreUnrecognized: ignoreUnrecognized,
+          allocator: arena,
+        );
+        _bindings.SpawnJvm(jvmArgs);
+      });
 
   static Pointer<JavaVMInitArgs> _createVMArgs({
     List<String> options = const [],
     List<String> classPath = const [],
     bool ignoreUnrecognized = false,
     int version = JNI_VERSION_1_6,
+    required Allocator allocator,
   }) {
-    final args = calloc<JavaVMInitArgs>();
+    final args = allocator<JavaVMInitArgs>();
     if (options.isNotEmpty || classPath.isNotEmpty) {
       final count = options.length + (classPath.isNotEmpty ? 1 : 0);
-
-      final optsPtr = (count != 0) ? calloc<JavaVMOption>(count) : nullptr;
+      final optsPtr = (count != 0) ? allocator<JavaVMOption>(count) : nullptr;
       args.ref.options = optsPtr;
       for (int i = 0; i < options.length; i++) {
-        optsPtr.elementAt(i).ref.optionString = options[i].toNativeChars();
+        optsPtr.elementAt(i).ref.optionString =
+            options[i].toNativeChars(allocator);
       }
       if (classPath.isNotEmpty) {
         final classPathString = classPath.join(Platform.isWindows ? ';' : ":");
         optsPtr.elementAt(count - 1).ref.optionString =
-            "-Djava.class.path=$classPathString".toNativeChars();
+            "-Djava.class.path=$classPathString".toNativeChars(allocator);
       }
       args.ref.nOptions = count;
     }
@@ -171,137 +124,140 @@
     return args;
   }
 
-  static void _freeVMArgs(Pointer<JavaVMInitArgs> argPtr) {
-    final nOptions = argPtr.ref.nOptions;
-    final options = argPtr.ref.options;
-    if (nOptions != 0) {
-      for (var i = 0; i < nOptions; i++) {
-        calloc.free(options.elementAt(i).ref.optionString);
-      }
-      calloc.free(argPtr.ref.options);
-    }
-    calloc.free(argPtr);
-  }
-
   /// Returns pointer to current JNI JavaVM instance
   Pointer<JavaVM> getJavaVM() {
     return _bindings.GetJavaVM();
   }
 
-  /// Returns JniEnv* associated with current thread.
-  ///
-  /// Do not reuse JniEnv between threads, it's only valid
-  /// in the thread it is obtained.
-  Pointer<JniEnv> getEnv() {
-    return _bindings.GetJniEnv();
+  /// Returns the instance of [GlobalJniEnv], which is an abstraction over JNIEnv
+  /// without the same-thread restriction.
+  static Pointer<GlobalJniEnv> _fetchGlobalEnv() {
+    final env = _bindings.GetGlobalEnv();
+    if (env == nullptr) {
+      throw NoJvmInstanceException();
+    }
+    return env;
   }
 
-  void setJniLogging(int loggingLevel) {
-    _bindings.SetJNILogging(loggingLevel);
+  static Pointer<GlobalJniEnv>? _env;
+
+  /// Points to a process-wide shared instance of [GlobalJniEnv].
+  ///
+  /// It provides an indirection over [JniEnv] so that it can be used from
+  /// any thread, and always returns global object references.
+  static Pointer<GlobalJniEnv> get env {
+    _env ??= _fetchGlobalEnv();
+    return _env!;
   }
 
   /// Returns current application context on Android.
-  JObject getCachedApplicationContext() {
+  static JObject getCachedApplicationContext() {
     return _bindings.GetApplicationContext();
   }
 
   /// Returns current activity
-  JObject getCurrentActivity() {
-    return _bindings.GetCurrentActivity();
-  }
+  static JObject getCurrentActivity() => _bindings.GetCurrentActivity();
 
   /// Get the initial classLoader of the application.
   ///
   /// This is especially useful on Android, where
   /// JNI threads cannot access application classes using
   /// the usual `JniEnv.FindClass` method.
-  JObject getApplicationClassLoader() {
-    return _bindings.GetClassLoader();
-  }
+  static JObject getApplicationClassLoader() => _bindings.GetClassLoader();
 
   /// Returns class reference found through system-specific mechanism
-  JClass findClass(String qualifiedName) {
-    final nameChars = qualifiedName.toNativeChars();
-    final cls = _bindings.LoadClass(nameChars);
-    calloc.free(nameChars);
-    if (cls == nullptr) {
-      getEnv().checkException();
-    }
-    return cls;
-  }
+  static JClass findClass(String qualifiedName) => using((arena) {
+        final nameChars = qualifiedName.toNativeChars(arena);
+        final cls = _bindings.LoadClass(nameChars);
+        if (cls == nullptr) {
+          env.checkException();
+        }
+        return cls;
+      });
 
   /// Returns class for [qualifiedName] found by platform-specific mechanism,
-  /// wrapped in a `JniClass`.
-  JniClass findJniClass(String qualifiedName) {
-    return JniClass.of(getEnv(), findClass(qualifiedName));
-  }
+  /// wrapped in a [JniClass].
+  static JniClass findJniClass(String qualifiedName) =>
+      JniClass.fromRef(findClass(qualifiedName));
 
-  /// Constructs an instance of class with given args.
+  /// Constructs an instance of class with given arguments.
   ///
-  /// Use it when you only need one instance, but not the actual class
-  /// nor any constructor / static methods.
-  JniObject newInstance(
+  /// Use it when one instance is needed, but the constructor or class aren't
+  /// required themselves.
+  static JniObject newInstance(
       String qualifiedName, String ctorSignature, List<dynamic> args) {
     final cls = findJniClass(qualifiedName);
-    final ctor = cls.getMethodID("<init>", ctorSignature);
-    final obj = cls.newObject(ctor, args);
+    final ctor = cls.getCtorID(ctorSignature);
+    final obj = cls.newInstance(ctor, args);
     cls.delete();
     return obj;
   }
 
-  /// Wraps a JObject ref in a JniObject.
-  /// The original ref is stored in JniObject, and
-  /// deleted with the latter's [delete] method.
-  ///
-  /// It takes the ownership of the jobject so that it can be used like this:
-  ///
-  /// ```dart
-  /// final result = jni.wrap(long_expr_returning_jobject)
-  /// ```
-  JniObject wrap(JObject obj) {
-    return JniObject.of(getEnv(), obj, nullptr);
-  }
-
-  /// Wraps a JObject ref in a JniObject.
-  /// The original ref is stored in JniObject, and
-  /// deleted with the latter's [delete] method.
-  JniClass wrapClass(JClass cls) {
-    return JniClass.of(getEnv(), cls);
-  }
-
-  Pointer<T> Function<T extends NativeType>(String) initGeneratedLibrary(
-      String name) {
-    var path = _getLibraryFileName(name);
-    if (_helperDir != null) {
-      path = join(_helperDir!, path);
-    }
-    final dl = DynamicLibrary.open(path);
-    final setJniGetters =
-        dl.lookupFunction<SetJniGettersNativeType, SetJniGettersDartType>(
-            'setJniGetters');
-    setJniGetters(_getJniContextFn, _getJniEnvFn);
-    final lookup = dl.lookup;
-    return lookup;
-  }
-
-  /// Converts passed arguments to JValue array
-  /// for use in methods that take arguments.
+  /// Converts passed arguments to JValue array.
   ///
   /// int, bool, double and JObject types are converted out of the box.
-  /// wrap values in types such as [JValueLong]
-  /// to convert to other primitive types instead.
+  /// Wrap values in types such as [JValueLong] to convert to other primitive
+  /// types such as `long`, `short` and `char`.
   static Pointer<JValue> jvalues(List<dynamic> args,
       {Allocator allocator = calloc}) {
     return toJValues(args, allocator: allocator);
   }
 
-  // Temporarily for JlString.
-  // A future idea is to unify JlObject and JniObject, and use global refs
-  // everywhere for simplicity.
-  late final toJavaString = _bindings.ToJavaString;
-  late final getJavaStringChars = _bindings.GetJavaStringChars;
-  late final releaseJavaStringChars = _bindings.ReleaseJavaStringChars;
+  /// Returns the value of static field identified by [fieldName] & [signature].
+  ///
+  /// See [JniObject.getField] for more explanations about [callType] and [T].
+  static T retrieveStaticField<T>(
+      String className, String fieldName, String signature,
+      [int? callType]) {
+    final cls = findJniClass(className);
+    final result = cls.getStaticFieldByName<T>(fieldName, signature, callType);
+    cls.delete();
+    return result;
+  }
+
+  /// Calls static method identified by [methodName] and [signature]
+  /// on [className] with [args] as and [callType].
+  ///
+  /// For more explanation on [args] and [callType], see [JniObject.getField]
+  /// and [JniObject.callMethod] respectively.
+  static T invokeStaticMethod<T>(
+      String className, String methodName, String signature, List<dynamic> args,
+      [int? callType]) {
+    final cls = findJniClass(className);
+    final result =
+        cls.callStaticMethodByName<T>(methodName, signature, args, callType);
+    cls.delete();
+    return result;
+  }
+
+  /// Delete all references in [objects].
+  static void deleteAll(List<JniReference> objects) {
+    for (var object in objects) {
+      object.delete();
+    }
+  }
 }
 
-typedef SetJniGettersNativeType = Void Function(Pointer<Void>, Pointer<Void>);
-typedef SetJniGettersDartType = void Function(Pointer<Void>, Pointer<Void>);
+typedef _SetJniGettersNativeType = Void Function(Pointer<Void>, Pointer<Void>);
+typedef _SetJniGettersDartType = void Function(Pointer<Void>, Pointer<Void>);
+
+/// Extensions for use by `jnigen` generated code.
+extension ProtectedJniExtensions on Jni {
+  static Pointer<T> Function<T extends NativeType>(String) initGeneratedLibrary(
+      String name) {
+    var path = _getLibraryFileName(name);
+    if (Jni._dylibDir != null) {
+      path = join(Jni._dylibDir!, path);
+    }
+    final dl = DynamicLibrary.open(path);
+    final setJniGetters =
+        dl.lookupFunction<_SetJniGettersNativeType, _SetJniGettersDartType>(
+            'setJniGetters');
+    setJniGetters(Jni._getJniContextFn, Jni._getJniEnvFn);
+    final lookup = dl.lookup;
+    return lookup;
+  }
+
+  /// Checks for and rethrows any pending exception in JNI as a [JniException].
+  static void checkException() => Jni.env.checkException();
+}
diff --git a/pkgs/jni/lib/src/jni_class.dart b/pkgs/jni/lib/src/jni_class.dart
deleted file mode 100644
index 308981a..0000000
--- a/pkgs/jni/lib/src/jni_class.dart
+++ /dev/null
@@ -1,157 +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:ffi/ffi.dart';
-
-import 'third_party/jni_bindings_generated.dart';
-import 'extensions.dart';
-import 'jvalues.dart';
-import 'jni_exceptions.dart';
-import 'jni_object.dart';
-
-part 'jni_class_methods_generated.dart';
-
-final ctorLookupChars = "<init>".toNativeChars();
-
-/// Convenience wrapper around a JNI local class reference.
-///
-/// Reference lifetime semantics are same as [JniObject].
-class JniClass {
-  final JClass _cls;
-  final Pointer<JniEnv> _env;
-  bool _deleted = false;
-  JniClass.of(this._env, this._cls);
-
-  JniClass.fromJClass(Pointer<JniEnv> env, JClass cls)
-      : _env = env,
-        _cls = cls;
-
-  JniClass.fromGlobalRef(Pointer<JniEnv> env, JniGlobalClassRef r)
-      : _env = env,
-        _cls = env.NewLocalRef(r._cls) {
-    if (r._deleted) {
-      throw UseAfterFreeException(r, r._cls);
-    }
-  }
-
-  @pragma('vm:prefer-inline')
-  void _checkDeleted() {
-    if (_deleted) {
-      throw UseAfterFreeException(this, _cls);
-    }
-  }
-
-  JMethodID getConstructorID(String signature) {
-    return _getMethodID("<init>", signature, false);
-  }
-
-  /// Construct new object using [ctor].
-  JniObject newObject(JMethodID ctor, List<dynamic> args) {
-    _checkDeleted();
-    final jvArgs = JValueArgs(args, _env);
-    final newObj = _env.NewObjectA(_cls, ctor, jvArgs.values);
-    jvArgs.disposeIn(_env);
-    calloc.free(jvArgs.values);
-    _env.checkException();
-    return JniObject.of(_env, newObj, nullptr);
-  }
-
-  JMethodID _getMethodID(String name, String signature, bool isStatic) {
-    _checkDeleted();
-    final methodName = name.toNativeChars();
-    final methodSig = signature.toNativeChars();
-    final result = isStatic
-        ? _env.GetStaticMethodID(_cls, methodName, methodSig)
-        : _env.GetMethodID(_cls, methodName, methodSig);
-    calloc.free(methodName);
-    calloc.free(methodSig);
-    _env.checkException();
-    return result;
-  }
-
-  JFieldID _getFieldID(String name, String signature, bool isStatic) {
-    _checkDeleted();
-    final methodName = name.toNativeChars();
-    final methodSig = signature.toNativeChars();
-    final result = isStatic
-        ? _env.GetStaticFieldID(_cls, methodName, methodSig)
-        : _env.GetFieldID(_cls, methodName, methodSig);
-    calloc.free(methodName);
-    calloc.free(methodSig);
-    _env.checkException();
-    return result;
-  }
-
-  @pragma('vm:prefer-inline')
-  JMethodID getMethodID(String name, String signature) {
-    return _getMethodID(name, signature, false);
-  }
-
-  @pragma('vm:prefer-inline')
-  JMethodID getStaticMethodID(String name, String signature) {
-    return _getMethodID(name, signature, true);
-  }
-
-  @pragma('vm:prefer-inline')
-  JFieldID getFieldID(String name, String signature) {
-    return _getFieldID(name, signature, false);
-  }
-
-  @pragma('vm:prefer-inline')
-  JFieldID getStaticFieldID(String name, String signature) {
-    return _getFieldID(name, signature, true);
-  }
-
-  /// Returns the underlying [JClass].
-  JClass get jclass {
-    _checkDeleted();
-    return _cls;
-  }
-
-  JniGlobalClassRef getGlobalRef() {
-    _checkDeleted();
-    return JniGlobalClassRef._(_env.NewGlobalRef(_cls));
-  }
-
-  void delete() {
-    if (_deleted) {
-      throw DoubleFreeException(this, _cls);
-    }
-    _env.DeleteLocalRef(_cls);
-    _deleted = true;
-  }
-
-  /// Use this [JniClass] to execute callback, then delete.
-  ///
-  /// Useful in expression chains.
-  T use<T>(T Function(JniClass) callback) {
-    _checkDeleted();
-    final result = callback(this);
-    delete();
-    return result;
-  }
-}
-
-/// Global reference type for JniClasses
-///
-/// Instead of passing local references between functions
-/// that may be run on different threads, convert it
-/// using [JniClass.getGlobalRef] and reconstruct using
-/// [JniClass.fromGlobalRef]
-class JniGlobalClassRef {
-  JniGlobalClassRef._(this._cls);
-  final JClass _cls;
-  JClass get jclass => _cls;
-  bool _deleted = false;
-
-  void deleteIn(Pointer<JniEnv> env) {
-    if (_deleted) {
-      throw DoubleFreeException(this, _cls);
-    }
-    env.DeleteGlobalRef(_cls);
-    _deleted = true;
-  }
-}
diff --git a/pkgs/jni/lib/src/jni_class_methods_generated.dart b/pkgs/jni/lib/src/jni_class_methods_generated.dart
deleted file mode 100644
index 195deef..0000000
--- a/pkgs/jni/lib/src/jni_class_methods_generated.dart
+++ /dev/null
@@ -1,412 +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.
-
-// Autogenerated; DO NOT EDIT
-// Generated by running the script in tool/gen_aux_methods.dart
-// coverage:ignore-file
-part of 'jni_class.dart';
-
-extension JniClassCallMethods on JniClass {
-  /// Calls method pointed to by [methodID] with [args] as arguments
-  String callStaticStringMethod(JMethodID methodID, List<dynamic> args) {
-    _checkDeleted();
-    final jvArgs = JValueArgs(args, _env);
-    final result = _env.CallStaticObjectMethodA(_cls, methodID, jvArgs.values);
-    jvArgs.disposeIn(_env);
-    calloc.free(jvArgs.values);
-    final strRes = _env.asDartString(result, deleteOriginal: true);
-    _env.checkException();
-    return strRes;
-  }
-
-  /// Looks up method with [name] and [signature], calls it with [args] as arguments.
-  /// If calling the same method multiple times, consider using [getStaticMethodID]
-  /// and [callStaticStringMethod].
-  String callStaticStringMethodByName(
-      String name, String signature, List<dynamic> args) {
-    final mID = getStaticMethodID(name, signature);
-    final result = callStaticStringMethod(mID, args);
-    return result;
-  }
-
-  /// Retrieves the value of the field denoted by [fieldID]
-  String getStaticStringField(JFieldID fieldID) {
-    _checkDeleted();
-    final result = _env.GetStaticObjectField(_cls, fieldID);
-    final strRes = _env.asDartString(result, deleteOriginal: true);
-    _env.checkException();
-    return strRes;
-  }
-
-  /// Retrieve field of given [name] and [signature]
-  String getStaticStringFieldByName(String name, String signature) {
-    final fID = getStaticFieldID(name, signature);
-    final result = getStaticStringField(fID);
-    return result;
-  }
-
-  /// Calls method pointed to by [methodID] with [args] as arguments
-  JniObject callStaticObjectMethod(JMethodID methodID, List<dynamic> args) {
-    _checkDeleted();
-    final jvArgs = JValueArgs(args, _env);
-    final result = _env.CallStaticObjectMethodA(_cls, methodID, jvArgs.values);
-    jvArgs.disposeIn(_env);
-    calloc.free(jvArgs.values);
-
-    _env.checkException();
-    return JniObject.of(_env, result, nullptr);
-  }
-
-  /// Looks up method with [name] and [signature], calls it with [args] as arguments.
-  /// If calling the same method multiple times, consider using [getStaticMethodID]
-  /// and [callStaticObjectMethod].
-  JniObject callStaticObjectMethodByName(
-      String name, String signature, List<dynamic> args) {
-    final mID = getStaticMethodID(name, signature);
-    final result = callStaticObjectMethod(mID, args);
-    return result;
-  }
-
-  /// Retrieves the value of the field denoted by [fieldID]
-  JniObject getStaticObjectField(JFieldID fieldID) {
-    _checkDeleted();
-    final result = _env.GetStaticObjectField(_cls, fieldID);
-
-    _env.checkException();
-    return JniObject.of(_env, result, nullptr);
-  }
-
-  /// Retrieve field of given [name] and [signature]
-  JniObject getStaticObjectFieldByName(String name, String signature) {
-    final fID = getStaticFieldID(name, signature);
-    final result = getStaticObjectField(fID);
-    return result;
-  }
-
-  /// Calls method pointed to by [methodID] with [args] as arguments
-  bool callStaticBooleanMethod(JMethodID methodID, List<dynamic> args) {
-    _checkDeleted();
-    final jvArgs = JValueArgs(args, _env);
-    final result = _env.CallStaticBooleanMethodA(_cls, methodID, jvArgs.values);
-    jvArgs.disposeIn(_env);
-    calloc.free(jvArgs.values);
-
-    _env.checkException();
-    return result != 0;
-  }
-
-  /// Looks up method with [name] and [signature], calls it with [args] as arguments.
-  /// If calling the same method multiple times, consider using [getStaticMethodID]
-  /// and [callStaticBooleanMethod].
-  bool callStaticBooleanMethodByName(
-      String name, String signature, List<dynamic> args) {
-    final mID = getStaticMethodID(name, signature);
-    final result = callStaticBooleanMethod(mID, args);
-    return result;
-  }
-
-  /// Retrieves the value of the field denoted by [fieldID]
-  bool getStaticBooleanField(JFieldID fieldID) {
-    _checkDeleted();
-    final result = _env.GetStaticBooleanField(_cls, fieldID);
-
-    _env.checkException();
-    return result != 0;
-  }
-
-  /// Retrieve field of given [name] and [signature]
-  bool getStaticBooleanFieldByName(String name, String signature) {
-    final fID = getStaticFieldID(name, signature);
-    final result = getStaticBooleanField(fID);
-    return result;
-  }
-
-  /// Calls method pointed to by [methodID] with [args] as arguments
-  int callStaticByteMethod(JMethodID methodID, List<dynamic> args) {
-    _checkDeleted();
-    final jvArgs = JValueArgs(args, _env);
-    final result = _env.CallStaticByteMethodA(_cls, methodID, jvArgs.values);
-    jvArgs.disposeIn(_env);
-    calloc.free(jvArgs.values);
-
-    _env.checkException();
-    return result;
-  }
-
-  /// Looks up method with [name] and [signature], calls it with [args] as arguments.
-  /// If calling the same method multiple times, consider using [getStaticMethodID]
-  /// and [callStaticByteMethod].
-  int callStaticByteMethodByName(
-      String name, String signature, List<dynamic> args) {
-    final mID = getStaticMethodID(name, signature);
-    final result = callStaticByteMethod(mID, args);
-    return result;
-  }
-
-  /// Retrieves the value of the field denoted by [fieldID]
-  int getStaticByteField(JFieldID fieldID) {
-    _checkDeleted();
-    final result = _env.GetStaticByteField(_cls, fieldID);
-
-    _env.checkException();
-    return result;
-  }
-
-  /// Retrieve field of given [name] and [signature]
-  int getStaticByteFieldByName(String name, String signature) {
-    final fID = getStaticFieldID(name, signature);
-    final result = getStaticByteField(fID);
-    return result;
-  }
-
-  /// Calls method pointed to by [methodID] with [args] as arguments
-  int callStaticCharMethod(JMethodID methodID, List<dynamic> args) {
-    _checkDeleted();
-    final jvArgs = JValueArgs(args, _env);
-    final result = _env.CallStaticCharMethodA(_cls, methodID, jvArgs.values);
-    jvArgs.disposeIn(_env);
-    calloc.free(jvArgs.values);
-
-    _env.checkException();
-    return result;
-  }
-
-  /// Looks up method with [name] and [signature], calls it with [args] as arguments.
-  /// If calling the same method multiple times, consider using [getStaticMethodID]
-  /// and [callStaticCharMethod].
-  int callStaticCharMethodByName(
-      String name, String signature, List<dynamic> args) {
-    final mID = getStaticMethodID(name, signature);
-    final result = callStaticCharMethod(mID, args);
-    return result;
-  }
-
-  /// Retrieves the value of the field denoted by [fieldID]
-  int getStaticCharField(JFieldID fieldID) {
-    _checkDeleted();
-    final result = _env.GetStaticCharField(_cls, fieldID);
-
-    _env.checkException();
-    return result;
-  }
-
-  /// Retrieve field of given [name] and [signature]
-  int getStaticCharFieldByName(String name, String signature) {
-    final fID = getStaticFieldID(name, signature);
-    final result = getStaticCharField(fID);
-    return result;
-  }
-
-  /// Calls method pointed to by [methodID] with [args] as arguments
-  int callStaticShortMethod(JMethodID methodID, List<dynamic> args) {
-    _checkDeleted();
-    final jvArgs = JValueArgs(args, _env);
-    final result = _env.CallStaticShortMethodA(_cls, methodID, jvArgs.values);
-    jvArgs.disposeIn(_env);
-    calloc.free(jvArgs.values);
-
-    _env.checkException();
-    return result;
-  }
-
-  /// Looks up method with [name] and [signature], calls it with [args] as arguments.
-  /// If calling the same method multiple times, consider using [getStaticMethodID]
-  /// and [callStaticShortMethod].
-  int callStaticShortMethodByName(
-      String name, String signature, List<dynamic> args) {
-    final mID = getStaticMethodID(name, signature);
-    final result = callStaticShortMethod(mID, args);
-    return result;
-  }
-
-  /// Retrieves the value of the field denoted by [fieldID]
-  int getStaticShortField(JFieldID fieldID) {
-    _checkDeleted();
-    final result = _env.GetStaticShortField(_cls, fieldID);
-
-    _env.checkException();
-    return result;
-  }
-
-  /// Retrieve field of given [name] and [signature]
-  int getStaticShortFieldByName(String name, String signature) {
-    final fID = getStaticFieldID(name, signature);
-    final result = getStaticShortField(fID);
-    return result;
-  }
-
-  /// Calls method pointed to by [methodID] with [args] as arguments
-  int callStaticIntMethod(JMethodID methodID, List<dynamic> args) {
-    _checkDeleted();
-    final jvArgs = JValueArgs(args, _env);
-    final result = _env.CallStaticIntMethodA(_cls, methodID, jvArgs.values);
-    jvArgs.disposeIn(_env);
-    calloc.free(jvArgs.values);
-
-    _env.checkException();
-    return result;
-  }
-
-  /// Looks up method with [name] and [signature], calls it with [args] as arguments.
-  /// If calling the same method multiple times, consider using [getStaticMethodID]
-  /// and [callStaticIntMethod].
-  int callStaticIntMethodByName(
-      String name, String signature, List<dynamic> args) {
-    final mID = getStaticMethodID(name, signature);
-    final result = callStaticIntMethod(mID, args);
-    return result;
-  }
-
-  /// Retrieves the value of the field denoted by [fieldID]
-  int getStaticIntField(JFieldID fieldID) {
-    _checkDeleted();
-    final result = _env.GetStaticIntField(_cls, fieldID);
-
-    _env.checkException();
-    return result;
-  }
-
-  /// Retrieve field of given [name] and [signature]
-  int getStaticIntFieldByName(String name, String signature) {
-    final fID = getStaticFieldID(name, signature);
-    final result = getStaticIntField(fID);
-    return result;
-  }
-
-  /// Calls method pointed to by [methodID] with [args] as arguments
-  int callStaticLongMethod(JMethodID methodID, List<dynamic> args) {
-    _checkDeleted();
-    final jvArgs = JValueArgs(args, _env);
-    final result = _env.CallStaticLongMethodA(_cls, methodID, jvArgs.values);
-    jvArgs.disposeIn(_env);
-    calloc.free(jvArgs.values);
-
-    _env.checkException();
-    return result;
-  }
-
-  /// Looks up method with [name] and [signature], calls it with [args] as arguments.
-  /// If calling the same method multiple times, consider using [getStaticMethodID]
-  /// and [callStaticLongMethod].
-  int callStaticLongMethodByName(
-      String name, String signature, List<dynamic> args) {
-    final mID = getStaticMethodID(name, signature);
-    final result = callStaticLongMethod(mID, args);
-    return result;
-  }
-
-  /// Retrieves the value of the field denoted by [fieldID]
-  int getStaticLongField(JFieldID fieldID) {
-    _checkDeleted();
-    final result = _env.GetStaticLongField(_cls, fieldID);
-
-    _env.checkException();
-    return result;
-  }
-
-  /// Retrieve field of given [name] and [signature]
-  int getStaticLongFieldByName(String name, String signature) {
-    final fID = getStaticFieldID(name, signature);
-    final result = getStaticLongField(fID);
-    return result;
-  }
-
-  /// Calls method pointed to by [methodID] with [args] as arguments
-  double callStaticFloatMethod(JMethodID methodID, List<dynamic> args) {
-    _checkDeleted();
-    final jvArgs = JValueArgs(args, _env);
-    final result = _env.CallStaticFloatMethodA(_cls, methodID, jvArgs.values);
-    jvArgs.disposeIn(_env);
-    calloc.free(jvArgs.values);
-
-    _env.checkException();
-    return result;
-  }
-
-  /// Looks up method with [name] and [signature], calls it with [args] as arguments.
-  /// If calling the same method multiple times, consider using [getStaticMethodID]
-  /// and [callStaticFloatMethod].
-  double callStaticFloatMethodByName(
-      String name, String signature, List<dynamic> args) {
-    final mID = getStaticMethodID(name, signature);
-    final result = callStaticFloatMethod(mID, args);
-    return result;
-  }
-
-  /// Retrieves the value of the field denoted by [fieldID]
-  double getStaticFloatField(JFieldID fieldID) {
-    _checkDeleted();
-    final result = _env.GetStaticFloatField(_cls, fieldID);
-
-    _env.checkException();
-    return result;
-  }
-
-  /// Retrieve field of given [name] and [signature]
-  double getStaticFloatFieldByName(String name, String signature) {
-    final fID = getStaticFieldID(name, signature);
-    final result = getStaticFloatField(fID);
-    return result;
-  }
-
-  /// Calls method pointed to by [methodID] with [args] as arguments
-  double callStaticDoubleMethod(JMethodID methodID, List<dynamic> args) {
-    _checkDeleted();
-    final jvArgs = JValueArgs(args, _env);
-    final result = _env.CallStaticDoubleMethodA(_cls, methodID, jvArgs.values);
-    jvArgs.disposeIn(_env);
-    calloc.free(jvArgs.values);
-
-    _env.checkException();
-    return result;
-  }
-
-  /// Looks up method with [name] and [signature], calls it with [args] as arguments.
-  /// If calling the same method multiple times, consider using [getStaticMethodID]
-  /// and [callStaticDoubleMethod].
-  double callStaticDoubleMethodByName(
-      String name, String signature, List<dynamic> args) {
-    final mID = getStaticMethodID(name, signature);
-    final result = callStaticDoubleMethod(mID, args);
-    return result;
-  }
-
-  /// Retrieves the value of the field denoted by [fieldID]
-  double getStaticDoubleField(JFieldID fieldID) {
-    _checkDeleted();
-    final result = _env.GetStaticDoubleField(_cls, fieldID);
-
-    _env.checkException();
-    return result;
-  }
-
-  /// Retrieve field of given [name] and [signature]
-  double getStaticDoubleFieldByName(String name, String signature) {
-    final fID = getStaticFieldID(name, signature);
-    final result = getStaticDoubleField(fID);
-    return result;
-  }
-
-  /// Calls method pointed to by [methodID] with [args] as arguments
-  void callStaticVoidMethod(JMethodID methodID, List<dynamic> args) {
-    _checkDeleted();
-    final jvArgs = JValueArgs(args, _env);
-    final result = _env.CallStaticVoidMethodA(_cls, methodID, jvArgs.values);
-    jvArgs.disposeIn(_env);
-    calloc.free(jvArgs.values);
-
-    _env.checkException();
-    return result;
-  }
-
-  /// Looks up method with [name] and [signature], calls it with [args] as arguments.
-  /// If calling the same method multiple times, consider using [getStaticMethodID]
-  /// and [callStaticVoidMethod].
-  void callStaticVoidMethodByName(
-      String name, String signature, List<dynamic> args) {
-    final mID = getStaticMethodID(name, signature);
-    final result = callStaticVoidMethod(mID, args);
-    return result;
-  }
-}
diff --git a/pkgs/jni/lib/src/jni_exceptions.dart b/pkgs/jni/lib/src/jni_exceptions.dart
index a9cb639..0cb5806 100644
--- a/pkgs/jni/lib/src/jni_exceptions.dart
+++ b/pkgs/jni/lib/src/jni_exceptions.dart
@@ -17,9 +17,9 @@
   }
 }
 
-class NullJlStringException implements Exception {
+class NullJniStringException implements Exception {
   @override
-  String toString() => 'toDartString called on null JlString reference';
+  String toString() => 'toDartString called on null JniString reference';
 }
 
 class DoubleFreeException implements Exception {
@@ -29,10 +29,45 @@
 
   @override
   String toString() {
-    return "double on $ptr through $object";
+    return "double free on $ptr through $object";
   }
 }
 
+class JvmExistsException implements Exception {
+  @override
+  String toString() => 'A JVM already exists';
+}
+
+class NoJvmInstanceException implements Exception {
+  @override
+  String toString() => 'No JNI instance is available';
+}
+
+extension JniTypeNames on int {
+  static const _names = {
+    JniType.boolType: 'bool',
+    JniType.byteType: 'byte',
+    JniType.shortType: 'short',
+    JniType.charType: 'char',
+    JniType.intType: 'int',
+    JniType.longType: 'long',
+    JniType.floatType: 'float',
+    JniType.doubleType: 'double',
+    JniType.objectType: 'object',
+    JniType.voidType: 'void',
+  };
+  String str() => _names[this]!;
+}
+
+class InvalidCallTypeException implements Exception {
+  int type;
+  Set<int> allowed;
+  InvalidCallTypeException(this.type, this.allowed);
+  @override
+  String toString() => 'Invalid type for call ${type.str()}. '
+      'Allowed types are ${allowed.map((t) => t.str()).toSet()}';
+}
+
 class JniException implements Exception {
   /// Exception object pointer from JNI.
   final JObject err;
@@ -43,8 +78,6 @@
 
   @override
   String toString() => msg;
-
-  void deleteIn(Pointer<JniEnv> env) => env.DeleteLocalRef(err);
 }
 
 class HelperNotFoundException implements Exception {
@@ -54,5 +87,6 @@
   @override
   String toString() => "Lookup for helper library $path failed.\n"
       "Please ensure that `dartjni` shared library is built.\n"
+      "Provided jni:setup script can be used to build the shared library."
       "If the library is already built, double check the path.";
 }
diff --git a/pkgs/jni/lib/src/jni_object.dart b/pkgs/jni/lib/src/jni_object.dart
index 47d480a..fc66c6a 100644
--- a/pkgs/jni/lib/src/jni_object.dart
+++ b/pkgs/jni/lib/src/jni_object.dart
@@ -7,144 +7,59 @@
 import 'package:ffi/ffi.dart';
 
 import 'third_party/jni_bindings_generated.dart';
-import 'extensions.dart';
-import 'jni_class.dart';
-import 'jvalues.dart';
 import 'jni_exceptions.dart';
+import 'jni.dart';
+import 'env_extensions.dart';
+import 'jvalues.dart';
 
-part 'jni_object_methods_generated.dart';
+// This typedef is needed because void is a keyword and cannot be used in
+// type switch like a regular type.
+typedef _VoidType = void;
 
-/// JniObject is a convenience wrapper around a JNI local object reference.
-///
-/// It holds the object, its associated associated jniEnv etc..
-/// It should be distroyed with [delete] method after done.
-///
-/// It's valid only in the thread it was created.
-/// When passing to code that might run in a different thread (eg: a callback),
-/// consider obtaining a global reference and reconstructing the object.
-class JniObject {
-  JClass _cls;
-  final JObject _obj;
-  final Pointer<JniEnv> _env;
+/// A class which holds one or more JNI references, and has a `delete` operation
+/// which disposes the reference(s).
+abstract class JniReference implements Finalizable {
+  static final _finalizer = NativeFinalizer(_env.ref.DeleteGlobalRef);
+
+  JniReference.fromRef(this.reference) {
+    _finalizer.attach(this, reference, detach: this);
+  }
+
   bool _deleted = false;
-  JniObject.of(this._env, this._obj, this._cls);
 
-  @pragma('vm:prefer-inline')
-  void _checkDeleted() {
-    if (_deleted) {
-      throw UseAfterFreeException(this, _obj);
-    }
+  void _ensureNotDeleted() {
+    if (_deleted) throw UseAfterFreeException(this, reference);
   }
 
-  JniObject.fromJObject(Pointer<JniEnv> env, JObject obj)
-      : _env = env,
-        _obj = obj,
-        _cls = nullptr;
+  /// Check whether the underlying JNI reference is `null`.
+  bool get isNull => reference == nullptr;
 
-  /// Reconstructs a JniObject from [r]
-  ///
-  /// [r] still needs to be explicitly deleted when
-  /// it's no longer needed to construct any JniObjects.
-  JniObject.fromGlobalRef(Pointer<JniEnv> env, JniGlobalObjectRef r)
-      : _env = env,
-        _obj = env.NewLocalRef(r._obj),
-        _cls = env.NewLocalRef(r._cls) {
-    if (r._deleted) {
-      throw UseAfterFreeException(r, r._obj);
-    }
-  }
+  /// Returns whether this object is deleted.
+  bool get isDeleted => _deleted;
 
-  /// Delete the local reference contained by this object.
-  ///
-  /// Do not use a JniObject after calling [delete].
+  /// Deletes the underlying JNI reference. Further uses will throw
+  /// [UseAfterFreeException].
   void delete() {
-    if (_deleted == true) {
-      throw DoubleFreeException(this, _obj);
-    }
-    _env.DeleteLocalRef(_obj);
-    if (_cls != nullptr) {
-      _env.DeleteLocalRef(_cls);
+    if (_deleted) {
+      throw DoubleFreeException(this, reference);
     }
     _deleted = true;
+    _finalizer.detach(this);
+    _env.DeleteGlobalRef(reference);
   }
 
-  /// Returns underlying [JObject] of this [JniObject].
-  JObject get jobject {
-    _checkDeleted();
-    return _obj;
-  }
+  /// The underlying JNI global object reference.
+  final JObject reference;
 
-  /// Returns underlying [JClass] of this [JniObject].
-  JObject get jclass {
-    _checkDeleted();
-    if (_cls == nullptr) {
-      _cls = _env.GetObjectClass(_obj);
-    }
-    return _cls;
-  }
+  /// Registers this object to be deleted at the end of [arena]'s lifetime.
+  void deletedIn(Arena arena) => arena.onReleaseAll(delete);
+}
 
-  /// Get a JniClass of this object's class.
-  JniClass getClass() {
-    _checkDeleted();
-    if (_cls == nullptr) {
-      return JniClass.of(_env, _env.GetObjectClass(_obj));
-    }
-    return JniClass.of(_env, _env.NewLocalRef(_cls));
-  }
-
-  /// if the underlying JObject is string
-  /// converts it to string representation.
-  String asDartString() {
-    _checkDeleted();
-    return _env.asDartString(_obj);
-  }
-
-  /// Returns method id for [name] on this object.
-  JMethodID getMethodID(String name, String signature) {
-    _checkDeleted();
-    if (_cls == nullptr) {
-      _cls = _env.GetObjectClass(_obj);
-    }
-    final methodName = name.toNativeChars();
-    final methodSig = signature.toNativeChars();
-    final result = _env.GetMethodID(_cls, methodName, methodSig);
-    calloc.free(methodName);
-    calloc.free(methodSig);
-    _env.checkException();
-    return result;
-  }
-
-  /// Returns field id for [name] on this object.
-  JFieldID getFieldID(String name, String signature) {
-    _checkDeleted();
-    if (_cls == nullptr) {
-      _cls = _env.GetObjectClass(_obj);
-    }
-    final methodName = name.toNativeChars();
-    final methodSig = signature.toNativeChars();
-    final result = _env.GetFieldID(_cls, methodName, methodSig);
-    calloc.free(methodName);
-    calloc.free(methodSig);
-    _env.checkException();
-    return result;
-  }
-
-  /// Get a global reference.
-  ///
-  /// This is useful for passing a JniObject between threads.
-  JniGlobalObjectRef getGlobalRef() {
-    _checkDeleted();
-    return JniGlobalObjectRef._(
-      _env.NewGlobalRef(_obj),
-      _env.NewGlobalRef(_cls),
-    );
-  }
-
-  /// Use this [JniObject] to execute callback, then delete.
-  ///
-  /// Useful in expression chains.
-  T use<T>(T Function(JniObject) callback) {
-    _checkDeleted();
+extension JniReferenceUseExtension<T extends JniReference> on T {
+  /// Applies [callback] on [this] object and then delete the underlying JNI
+  /// reference, returning the result of [callback].
+  R use<R>(R Function(T) callback) {
+    _ensureNotDeleted();
     try {
       final result = callback(this);
       delete();
@@ -156,29 +71,434 @@
   }
 }
 
-/// High level wrapper to a JNI global reference.
-/// which is safe to be passed through threads.
-///
-/// In a different thread, actual object can be reconstructed
-/// using [JniObject.fromGlobalRef]
-///
-/// It should be explicitly deleted after done, using
-/// [deleteIn] method, passing some env, eg: obtained using [Jni.getEnv].
-class JniGlobalObjectRef {
-  final JObject _obj;
-  final JClass _cls;
-  bool _deleted = false;
-  JniGlobalObjectRef._(this._obj, this._cls);
+class _CallGetMethods {
+  _CallGetMethods(this.getField, this.getStaticField, this.callMethod,
+      this.callStaticMethod);
+  Function(JObject, JFieldID) getField;
+  Function(JClass, JFieldID) getStaticField;
+  Function(JObject, JMethodID, Pointer<JValue>) callMethod;
+  Function(JClass, JMethodID, Pointer<JValue>) callStaticMethod;
+}
 
-  JObject get jobject => _obj;
-  JObject get jclass => _cls;
+final Pointer<GlobalJniEnv> _env = Jni.env;
 
-  void deleteIn(Pointer<JniEnv> env) {
-    if (_deleted == true) {
-      throw DoubleFreeException(this, _obj);
+final Map<int, _CallGetMethods> _accessors = {
+  JniType.boolType: _CallGetMethods(
+    _env.GetBooleanField,
+    _env.GetStaticBooleanField,
+    _env.CallBooleanMethodA,
+    _env.CallStaticBooleanMethodA,
+  ),
+  JniType.byteType: _CallGetMethods(
+    _env.GetByteField,
+    _env.GetStaticByteField,
+    _env.CallByteMethodA,
+    _env.CallStaticByteMethodA,
+  ),
+  JniType.shortType: _CallGetMethods(
+    _env.GetShortField,
+    _env.GetStaticShortField,
+    _env.CallShortMethodA,
+    _env.CallStaticShortMethodA,
+  ),
+  JniType.charType: _CallGetMethods(
+    _env.GetCharField,
+    _env.GetStaticCharField,
+    _env.CallCharMethodA,
+    _env.CallStaticCharMethodA,
+  ),
+  JniType.intType: _CallGetMethods(
+    _env.GetIntField,
+    _env.GetStaticIntField,
+    _env.CallIntMethodA,
+    _env.CallStaticIntMethodA,
+  ),
+  JniType.longType: _CallGetMethods(
+    _env.GetLongField,
+    _env.GetStaticLongField,
+    _env.CallLongMethodA,
+    _env.CallStaticLongMethodA,
+  ),
+  JniType.floatType: _CallGetMethods(
+    _env.GetFloatField,
+    _env.GetStaticFloatField,
+    _env.CallFloatMethodA,
+    _env.CallStaticFloatMethodA,
+  ),
+  JniType.doubleType: _CallGetMethods(
+    _env.GetDoubleField,
+    _env.GetStaticDoubleField,
+    _env.CallDoubleMethodA,
+    _env.CallStaticDoubleMethodA,
+  ),
+  JniType.objectType: _CallGetMethods(
+    _env.GetObjectField,
+    _env.GetStaticObjectField,
+    _env.CallObjectMethodA,
+    _env.CallStaticObjectMethodA,
+  ),
+  JniType.voidType: _CallGetMethods(
+    (x, y) => throw ArgumentError('void passed as field type'),
+    (x, y) => throw ArgumentError('void passed as static field type'),
+    _env.CallVoidMethodA,
+    _env.CallStaticVoidMethodA,
+  ),
+};
+
+T _getID<T>(
+    T Function(Pointer<Void> ptr, Pointer<Char> name, Pointer<Char> sig) f,
+    Pointer<Void> ptr,
+    String name,
+    String sig) {
+  final result = using(
+      (arena) => f(ptr, name.toNativeChars(arena), sig.toNativeChars(arena)));
+  _env.checkException();
+  return result;
+}
+
+int _getCallType(int? callType, int defaultType, Set<int> allowed) {
+  if (callType == null) return defaultType;
+  if (allowed.contains(callType)) return callType;
+  throw InvalidCallTypeException(callType, allowed);
+}
+
+T _callOrGet<T>(int? callType, Function(int) f) {
+  final int finalCallType;
+  T result;
+  switch (T) {
+    case bool:
+      finalCallType =
+          _getCallType(callType, JniType.boolType, {JniType.boolType});
+      result = (f(finalCallType) as int != 0) as T;
+      break;
+    case int:
+      finalCallType = _getCallType(callType, JniType.intType, {
+        JniType.byteType,
+        JniType.charType,
+        JniType.shortType,
+        JniType.intType,
+        JniType.longType,
+      });
+      result = f(finalCallType) as T;
+      break;
+    case double:
+      finalCallType = _getCallType(callType, JniType.doubleType,
+          {JniType.floatType, JniType.doubleType});
+      result = f(finalCallType) as T;
+      break;
+    case String:
+    case JniObject:
+    case JniString:
+      finalCallType =
+          _getCallType(callType, JniType.objectType, {JniType.objectType});
+      final ref = f(finalCallType) as JObject;
+      if (ref == nullptr) {
+        _env.checkException();
+      }
+      final ctor = T == String
+          ? (ref) => _env.asDartString(ref, deleteOriginal: true)
+          : (T == JniObject ? JniObject.fromRef : JniString.fromRef);
+      result = ctor(ref) as T;
+      break;
+    case _VoidType:
+      finalCallType =
+          _getCallType(callType, JniType.voidType, {JniType.voidType});
+      f(finalCallType);
+      result = null as T;
+      break;
+    case dynamic:
+      result = f(callType ?? JniType.voidType) as T;
+      break;
+    default:
+      throw UnsupportedError('Unknown type $T');
+  }
+  return result;
+}
+
+T _callMethod<T>(
+        int? callType, List<dynamic> args, Function(int, Pointer<JValue>) f) =>
+    using((arena) {
+      final jArgs = JValueArgs(args, arena);
+      final result = _callOrGet<T>(callType, (ct) => f(ct, jArgs.values));
+      jArgs.dispose();
+      if (result == 0 || result == 0.0 || result == null) {
+        _env.checkException();
+      }
+      return result;
+    });
+
+T _getField<T>(int? callType, Function(int) f) {
+  final result = _callOrGet<T>(callType, f);
+  _env.checkException();
+  return result;
+}
+
+/// A high-level wrapper for JNI global object reference.
+///
+/// This is the base class for classes generated by `jnigen`.
+class JniObject extends JniReference {
+  /// Construct a new [JniObject] with [reference] as its underlying reference.
+  JniObject.fromRef(JObject reference) : super.fromRef(reference);
+
+  JniClass? _jniClass;
+
+  JniClass get _class {
+    _jniClass ??= getClass();
+    return _jniClass!;
+  }
+
+  /// Deletes the JNI reference and marks this object as deleted. Any further
+  /// uses will throw [UseAfterFreeException].
+  @override
+  void delete() {
+    _jniClass?.delete();
+    super.delete();
+  }
+
+  // TODO(#55): Support casting JniObject subclasses
+
+  /// Returns [JniClass] corresponding to concrete class of this object.
+  ///
+  /// This may be a subclass of compile-time class.
+  JniClass getClass() {
+    _ensureNotDeleted();
+    final classRef = _env.GetObjectClass(reference);
+    if (classRef == nullptr) _env.checkException();
+    return JniClass.fromRef(classRef);
+  }
+
+  /// Get [JFieldID] of instance field identified by [fieldName] & [signature].
+  JFieldID getFieldID(String fieldName, String signature) {
+    _ensureNotDeleted();
+    return _getID(_env.GetFieldID, _class.reference, fieldName, signature);
+  }
+
+  /// Get [JFieldID] of static field identified by [fieldName] & [signature].
+  JFieldID getStaticFieldID(String fieldName, String signature) {
+    _ensureNotDeleted();
+    return _getID(
+        _env.GetStaticFieldID, _class.reference, fieldName, signature);
+  }
+
+  /// Get [JMethodID] of instance method [methodName] with [signature].
+  JMethodID getMethodID(String methodName, String signature) {
+    _ensureNotDeleted();
+    return _getID(_env.GetMethodID, _class.reference, methodName, signature);
+  }
+
+  /// Get [JMethodID] of static method [methodName] with [signature].
+  JMethodID getStaticMethodID(String methodName, String signature) {
+    _ensureNotDeleted();
+    return _getID(
+        _env.GetStaticMethodID, _class.reference, methodName, signature);
+  }
+
+  /// Retrieve the value of the field using [fieldID].
+  ///
+  /// [callType] determines the return type of the underlying JNI call made.
+  /// If the Java field is of `long` type, this must be [JniType.longType] and
+  /// so on. Default is chosen based on return type [T], which maps int -> int,
+  /// double -> double, void -> void, and JniObject types to `Object`.
+  ///
+  /// If [T] is String or [JniObject], required conversions are performed and
+  /// final value is returned.
+  T getField<T>(JFieldID fieldID, [int? callType]) {
+    _ensureNotDeleted();
+    return _getField<T>(
+        callType, (ct) => _accessors[ct]!.getField(reference, fieldID));
+  }
+
+  /// Get value of the field identified by [name] and [signature].
+  ///
+  /// See [getField] for an explanation about [callType] parameter.
+  T getFieldByName<T>(String name, String signature, [int? callType]) {
+    final id = getFieldID(name, signature);
+    return getField<T>(id, callType);
+  }
+
+  /// Get value of the static field using [fieldID].
+  ///
+  /// See [getField] for an explanation about [callType] parameter.
+  T getStaticField<T>(JFieldID fieldID, [int? callType]) {
+    _ensureNotDeleted();
+    return _getField<T>(callType,
+        (ct) => _accessors[ct]!.getStaticField(_class.reference, fieldID));
+  }
+
+  /// Get value of the static field identified by [name] and [signature].
+  ///
+  /// See [getField] for an explanation about [callType] parameter.
+  T getStaticFieldByName<T>(String name, String signature, [int? callType]) {
+    final id = getStaticFieldID(name, signature);
+    return getStaticField<T>(id, callType);
+  }
+
+  /// Call the method using [methodID],
+  ///
+  /// [args] can consist of primitive types, JNI primitive wrappers such as
+  /// [JValueLong], strings, and subclasses of [JniObject].
+  ///
+  /// See [getField] for an explanation about [callType] and return type [T].
+  T callMethod<T>(JMethodID methodID, List<dynamic> args, [int? callType]) {
+    _ensureNotDeleted();
+    return _callMethod<T>(callType, args,
+        (ct, jvs) => _accessors[ct]!.callMethod(reference, methodID, jvs));
+  }
+
+  /// Call instance method identified by [name] and [signature].
+  ///
+  /// This implementation looks up the method and calls it using [callMethod].
+  T callMethodByName<T>(String name, String signature, List<dynamic> args,
+      [int? callType]) {
+    final id = getMethodID(name, signature);
+    return callMethod<T>(id, args, callType);
+  }
+
+  /// Call static method using [methodID]. See [callMethod] and [getField] for
+  /// more details about [args] and [callType].
+  T callStaticMethod<T>(JMethodID methodID, List<dynamic> args,
+      [int? callType]) {
+    _ensureNotDeleted();
+    return _callMethod<T>(
+        callType,
+        args,
+        (ct, jvs) =>
+            _accessors[ct]!.callStaticMethod(reference, methodID, jvs));
+  }
+
+  /// Call static method identified by [name] and [signature].
+  ///
+  /// This implementation looks up the method and calls [callStaticMethod].
+  T callStaticMethodByName<T>(String name, String signature, List<dynamic> args,
+      [int? callType]) {
+    final id = getStaticMethodID(name, signature);
+    return callStaticMethod<T>(id, args, callType);
+  }
+}
+
+/// A high level wrapper over a JNI class reference.
+class JniClass extends JniReference {
+  /// Construct a new [JniClass] with [reference] as its underlying reference.
+  JniClass.fromRef(JObject reference) : super.fromRef(reference);
+
+  /// Get [JFieldID] of static field [fieldName] with [signature].
+  JFieldID getStaticFieldID(String fieldName, String signature) {
+    _ensureNotDeleted();
+    return _getID(_env.GetStaticFieldID, reference, fieldName, signature);
+  }
+
+  /// Get [JMethodID] of static method [methodName] with [signature].
+  JMethodID getStaticMethodID(String methodName, String signature) {
+    _ensureNotDeleted();
+    return _getID(_env.GetStaticMethodID, reference, methodName, signature);
+  }
+
+  /// Get [JFieldID] of field [fieldName] with [signature].
+  JFieldID getFieldID(String fieldName, String signature) {
+    _ensureNotDeleted();
+    return _getID(_env.GetFieldID, reference, fieldName, signature);
+  }
+
+  /// Get [JMethodID] of method [methodName] with [signature].
+  JMethodID getMethodID(String methodName, String signature) {
+    _ensureNotDeleted();
+    return _getID(_env.GetMethodID, reference, methodName, signature);
+  }
+
+  /// Get [JMethodID] of constructor with [signature].
+  JMethodID getCtorID(String signature) => getMethodID("<init>", signature);
+
+  /// Get the value of static field using [fieldID].
+  ///
+  /// See [JniObject.getField] for more explanation about [callType].
+  T getStaticField<T>(JFieldID fieldID, [int? callType]) {
+    _ensureNotDeleted();
+    return _getField<T>(
+        callType, (ct) => _accessors[ct]!.getStaticField(reference, fieldID));
+  }
+
+  /// Get the value of static field identified by [name] and [signature].
+  ///
+  /// This implementation looks up the field ID and calls [getStaticField].
+  T getStaticFieldByName<T>(String name, String signature, [int? callType]) {
+    final id = getStaticFieldID(name, signature);
+    return getStaticField<T>(id, callType);
+  }
+
+  /// Call the static method using [methodID].
+  ///
+  /// See [JniObject.callMethod] and [JniObject.getField] for more explanation
+  /// about [args] and [callType].
+  T callStaticMethod<T>(JMethodID methodID, List<dynamic> args,
+      [int? callType]) {
+    _ensureNotDeleted();
+    return _callMethod<T>(
+        callType,
+        args,
+        (ct, jvs) =>
+            _accessors[ct]!.callStaticMethod(reference, methodID, jvs));
+  }
+
+  /// Call the static method identified by [name] and [signature].
+  ///
+  /// This implementation looks up the method ID and calls [callStaticMethod].
+  T callStaticMethodByName<T>(String name, String signature, List<dynamic> args,
+      [int? callType]) {
+    final id = getStaticMethodID(name, signature);
+    return callStaticMethod<T>(id, args, callType);
+  }
+
+  /// Create a new instance of this class with [ctor] and [args].
+  JniObject newInstance(JMethodID ctor, List<dynamic> args) => using((arena) {
+        _ensureNotDeleted();
+        final jArgs = JValueArgs(args, arena);
+        final res = _env.NewObjectA(reference, ctor, jArgs.values);
+        jArgs.dispose();
+        if (res == nullptr) {
+          _env.checkException();
+        }
+        return JniObject.fromRef(res);
+      });
+}
+
+class JniString extends JniObject {
+  /// Construct a new [JniString] with [reference] as its underlying reference.
+  JniString.fromRef(JString reference) : super.fromRef(reference);
+
+  static JString _toJavaString(String s) => using((arena) {
+        final chars = s.toNativeUtf8(allocator: arena).cast<Char>();
+        final jstr = _env.NewStringUTF(chars);
+        if (jstr == nullptr) {
+          _env.checkException();
+        }
+        return jstr;
+      });
+
+  /// Construct a [JniString] from the contents of Dart string [s].
+  JniString.fromString(String s) : super.fromRef(_toJavaString(s));
+
+  /// Returns the contents as a Dart String.
+  ///
+  /// If [deleteOriginal] is true, the underlying reference is deleted
+  /// after conversion and this object will be marked as deleted.
+  String toDartString({bool deleteOriginal = false}) {
+    _ensureNotDeleted();
+    if (reference == nullptr) {
+      throw NullJniStringException();
     }
-    env.DeleteGlobalRef(_obj);
-    env.DeleteGlobalRef(_cls);
-    _deleted = true;
+    final chars = _env.GetStringUTFChars(reference, nullptr);
+    final result = chars.cast<Utf8>().toDartString();
+    _env.ReleaseStringUTFChars(reference, chars);
+    if (deleteOriginal) {
+      delete();
+    }
+    return result;
+  }
+}
+
+extension ToJniStringMethod on String {
+  /// Returns a [JniString] with the contents of this String.
+  JniString jniString() {
+    return JniString.fromString(this);
   }
 }
diff --git a/pkgs/jni/lib/src/jni_object_methods_generated.dart b/pkgs/jni/lib/src/jni_object_methods_generated.dart
deleted file mode 100644
index 3c41707..0000000
--- a/pkgs/jni/lib/src/jni_object_methods_generated.dart
+++ /dev/null
@@ -1,406 +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.
-
-// Autogenerated; DO NOT EDIT
-// Generated by running the script in tool/gen_aux_methods.dart
-// coverage:ignore-file
-part of 'jni_object.dart';
-
-extension JniObjectCallMethods on JniObject {
-  /// Calls method pointed to by [methodID] with [args] as arguments
-  String callStringMethod(JMethodID methodID, List<dynamic> args) {
-    _checkDeleted();
-    final jvArgs = JValueArgs(args, _env);
-    final result = _env.CallObjectMethodA(_obj, methodID, jvArgs.values);
-    jvArgs.disposeIn(_env);
-    calloc.free(jvArgs.values);
-    final strRes = _env.asDartString(result, deleteOriginal: true);
-    _env.checkException();
-    return strRes;
-  }
-
-  /// Looks up method with [name] and [signature], calls it with [args] as arguments.
-  /// If calling the same method multiple times, consider using [getMethodID]
-  /// and [callStringMethod].
-  String callStringMethodByName(
-      String name, String signature, List<dynamic> args) {
-    final mID = getMethodID(name, signature);
-    final result = callStringMethod(mID, args);
-    return result;
-  }
-
-  /// Retrieves the value of the field denoted by [fieldID]
-  String getStringField(JFieldID fieldID) {
-    _checkDeleted();
-    final result = _env.GetObjectField(_obj, fieldID);
-    final strRes = _env.asDartString(result, deleteOriginal: true);
-    _env.checkException();
-    return strRes;
-  }
-
-  /// Retrieve field of given [name] and [signature]
-  String getStringFieldByName(String name, String signature) {
-    final fID = getFieldID(name, signature);
-    final result = getStringField(fID);
-    return result;
-  }
-
-  /// Calls method pointed to by [methodID] with [args] as arguments
-  JniObject callObjectMethod(JMethodID methodID, List<dynamic> args) {
-    _checkDeleted();
-    final jvArgs = JValueArgs(args, _env);
-    final result = _env.CallObjectMethodA(_obj, methodID, jvArgs.values);
-    jvArgs.disposeIn(_env);
-    calloc.free(jvArgs.values);
-
-    _env.checkException();
-    return JniObject.of(_env, result, nullptr);
-  }
-
-  /// Looks up method with [name] and [signature], calls it with [args] as arguments.
-  /// If calling the same method multiple times, consider using [getMethodID]
-  /// and [callObjectMethod].
-  JniObject callObjectMethodByName(
-      String name, String signature, List<dynamic> args) {
-    final mID = getMethodID(name, signature);
-    final result = callObjectMethod(mID, args);
-    return result;
-  }
-
-  /// Retrieves the value of the field denoted by [fieldID]
-  JniObject getObjectField(JFieldID fieldID) {
-    _checkDeleted();
-    final result = _env.GetObjectField(_obj, fieldID);
-
-    _env.checkException();
-    return JniObject.of(_env, result, nullptr);
-  }
-
-  /// Retrieve field of given [name] and [signature]
-  JniObject getObjectFieldByName(String name, String signature) {
-    final fID = getFieldID(name, signature);
-    final result = getObjectField(fID);
-    return result;
-  }
-
-  /// Calls method pointed to by [methodID] with [args] as arguments
-  bool callBooleanMethod(JMethodID methodID, List<dynamic> args) {
-    _checkDeleted();
-    final jvArgs = JValueArgs(args, _env);
-    final result = _env.CallBooleanMethodA(_obj, methodID, jvArgs.values);
-    jvArgs.disposeIn(_env);
-    calloc.free(jvArgs.values);
-
-    _env.checkException();
-    return result != 0;
-  }
-
-  /// Looks up method with [name] and [signature], calls it with [args] as arguments.
-  /// If calling the same method multiple times, consider using [getMethodID]
-  /// and [callBooleanMethod].
-  bool callBooleanMethodByName(
-      String name, String signature, List<dynamic> args) {
-    final mID = getMethodID(name, signature);
-    final result = callBooleanMethod(mID, args);
-    return result;
-  }
-
-  /// Retrieves the value of the field denoted by [fieldID]
-  bool getBooleanField(JFieldID fieldID) {
-    _checkDeleted();
-    final result = _env.GetBooleanField(_obj, fieldID);
-
-    _env.checkException();
-    return result != 0;
-  }
-
-  /// Retrieve field of given [name] and [signature]
-  bool getBooleanFieldByName(String name, String signature) {
-    final fID = getFieldID(name, signature);
-    final result = getBooleanField(fID);
-    return result;
-  }
-
-  /// Calls method pointed to by [methodID] with [args] as arguments
-  int callByteMethod(JMethodID methodID, List<dynamic> args) {
-    _checkDeleted();
-    final jvArgs = JValueArgs(args, _env);
-    final result = _env.CallByteMethodA(_obj, methodID, jvArgs.values);
-    jvArgs.disposeIn(_env);
-    calloc.free(jvArgs.values);
-
-    _env.checkException();
-    return result;
-  }
-
-  /// Looks up method with [name] and [signature], calls it with [args] as arguments.
-  /// If calling the same method multiple times, consider using [getMethodID]
-  /// and [callByteMethod].
-  int callByteMethodByName(String name, String signature, List<dynamic> args) {
-    final mID = getMethodID(name, signature);
-    final result = callByteMethod(mID, args);
-    return result;
-  }
-
-  /// Retrieves the value of the field denoted by [fieldID]
-  int getByteField(JFieldID fieldID) {
-    _checkDeleted();
-    final result = _env.GetByteField(_obj, fieldID);
-
-    _env.checkException();
-    return result;
-  }
-
-  /// Retrieve field of given [name] and [signature]
-  int getByteFieldByName(String name, String signature) {
-    final fID = getFieldID(name, signature);
-    final result = getByteField(fID);
-    return result;
-  }
-
-  /// Calls method pointed to by [methodID] with [args] as arguments
-  int callCharMethod(JMethodID methodID, List<dynamic> args) {
-    _checkDeleted();
-    final jvArgs = JValueArgs(args, _env);
-    final result = _env.CallCharMethodA(_obj, methodID, jvArgs.values);
-    jvArgs.disposeIn(_env);
-    calloc.free(jvArgs.values);
-
-    _env.checkException();
-    return result;
-  }
-
-  /// Looks up method with [name] and [signature], calls it with [args] as arguments.
-  /// If calling the same method multiple times, consider using [getMethodID]
-  /// and [callCharMethod].
-  int callCharMethodByName(String name, String signature, List<dynamic> args) {
-    final mID = getMethodID(name, signature);
-    final result = callCharMethod(mID, args);
-    return result;
-  }
-
-  /// Retrieves the value of the field denoted by [fieldID]
-  int getCharField(JFieldID fieldID) {
-    _checkDeleted();
-    final result = _env.GetCharField(_obj, fieldID);
-
-    _env.checkException();
-    return result;
-  }
-
-  /// Retrieve field of given [name] and [signature]
-  int getCharFieldByName(String name, String signature) {
-    final fID = getFieldID(name, signature);
-    final result = getCharField(fID);
-    return result;
-  }
-
-  /// Calls method pointed to by [methodID] with [args] as arguments
-  int callShortMethod(JMethodID methodID, List<dynamic> args) {
-    _checkDeleted();
-    final jvArgs = JValueArgs(args, _env);
-    final result = _env.CallShortMethodA(_obj, methodID, jvArgs.values);
-    jvArgs.disposeIn(_env);
-    calloc.free(jvArgs.values);
-
-    _env.checkException();
-    return result;
-  }
-
-  /// Looks up method with [name] and [signature], calls it with [args] as arguments.
-  /// If calling the same method multiple times, consider using [getMethodID]
-  /// and [callShortMethod].
-  int callShortMethodByName(String name, String signature, List<dynamic> args) {
-    final mID = getMethodID(name, signature);
-    final result = callShortMethod(mID, args);
-    return result;
-  }
-
-  /// Retrieves the value of the field denoted by [fieldID]
-  int getShortField(JFieldID fieldID) {
-    _checkDeleted();
-    final result = _env.GetShortField(_obj, fieldID);
-
-    _env.checkException();
-    return result;
-  }
-
-  /// Retrieve field of given [name] and [signature]
-  int getShortFieldByName(String name, String signature) {
-    final fID = getFieldID(name, signature);
-    final result = getShortField(fID);
-    return result;
-  }
-
-  /// Calls method pointed to by [methodID] with [args] as arguments
-  int callIntMethod(JMethodID methodID, List<dynamic> args) {
-    _checkDeleted();
-    final jvArgs = JValueArgs(args, _env);
-    final result = _env.CallIntMethodA(_obj, methodID, jvArgs.values);
-    jvArgs.disposeIn(_env);
-    calloc.free(jvArgs.values);
-
-    _env.checkException();
-    return result;
-  }
-
-  /// Looks up method with [name] and [signature], calls it with [args] as arguments.
-  /// If calling the same method multiple times, consider using [getMethodID]
-  /// and [callIntMethod].
-  int callIntMethodByName(String name, String signature, List<dynamic> args) {
-    final mID = getMethodID(name, signature);
-    final result = callIntMethod(mID, args);
-    return result;
-  }
-
-  /// Retrieves the value of the field denoted by [fieldID]
-  int getIntField(JFieldID fieldID) {
-    _checkDeleted();
-    final result = _env.GetIntField(_obj, fieldID);
-
-    _env.checkException();
-    return result;
-  }
-
-  /// Retrieve field of given [name] and [signature]
-  int getIntFieldByName(String name, String signature) {
-    final fID = getFieldID(name, signature);
-    final result = getIntField(fID);
-    return result;
-  }
-
-  /// Calls method pointed to by [methodID] with [args] as arguments
-  int callLongMethod(JMethodID methodID, List<dynamic> args) {
-    _checkDeleted();
-    final jvArgs = JValueArgs(args, _env);
-    final result = _env.CallLongMethodA(_obj, methodID, jvArgs.values);
-    jvArgs.disposeIn(_env);
-    calloc.free(jvArgs.values);
-
-    _env.checkException();
-    return result;
-  }
-
-  /// Looks up method with [name] and [signature], calls it with [args] as arguments.
-  /// If calling the same method multiple times, consider using [getMethodID]
-  /// and [callLongMethod].
-  int callLongMethodByName(String name, String signature, List<dynamic> args) {
-    final mID = getMethodID(name, signature);
-    final result = callLongMethod(mID, args);
-    return result;
-  }
-
-  /// Retrieves the value of the field denoted by [fieldID]
-  int getLongField(JFieldID fieldID) {
-    _checkDeleted();
-    final result = _env.GetLongField(_obj, fieldID);
-
-    _env.checkException();
-    return result;
-  }
-
-  /// Retrieve field of given [name] and [signature]
-  int getLongFieldByName(String name, String signature) {
-    final fID = getFieldID(name, signature);
-    final result = getLongField(fID);
-    return result;
-  }
-
-  /// Calls method pointed to by [methodID] with [args] as arguments
-  double callFloatMethod(JMethodID methodID, List<dynamic> args) {
-    _checkDeleted();
-    final jvArgs = JValueArgs(args, _env);
-    final result = _env.CallFloatMethodA(_obj, methodID, jvArgs.values);
-    jvArgs.disposeIn(_env);
-    calloc.free(jvArgs.values);
-
-    _env.checkException();
-    return result;
-  }
-
-  /// Looks up method with [name] and [signature], calls it with [args] as arguments.
-  /// If calling the same method multiple times, consider using [getMethodID]
-  /// and [callFloatMethod].
-  double callFloatMethodByName(
-      String name, String signature, List<dynamic> args) {
-    final mID = getMethodID(name, signature);
-    final result = callFloatMethod(mID, args);
-    return result;
-  }
-
-  /// Retrieves the value of the field denoted by [fieldID]
-  double getFloatField(JFieldID fieldID) {
-    _checkDeleted();
-    final result = _env.GetFloatField(_obj, fieldID);
-
-    _env.checkException();
-    return result;
-  }
-
-  /// Retrieve field of given [name] and [signature]
-  double getFloatFieldByName(String name, String signature) {
-    final fID = getFieldID(name, signature);
-    final result = getFloatField(fID);
-    return result;
-  }
-
-  /// Calls method pointed to by [methodID] with [args] as arguments
-  double callDoubleMethod(JMethodID methodID, List<dynamic> args) {
-    _checkDeleted();
-    final jvArgs = JValueArgs(args, _env);
-    final result = _env.CallDoubleMethodA(_obj, methodID, jvArgs.values);
-    jvArgs.disposeIn(_env);
-    calloc.free(jvArgs.values);
-
-    _env.checkException();
-    return result;
-  }
-
-  /// Looks up method with [name] and [signature], calls it with [args] as arguments.
-  /// If calling the same method multiple times, consider using [getMethodID]
-  /// and [callDoubleMethod].
-  double callDoubleMethodByName(
-      String name, String signature, List<dynamic> args) {
-    final mID = getMethodID(name, signature);
-    final result = callDoubleMethod(mID, args);
-    return result;
-  }
-
-  /// Retrieves the value of the field denoted by [fieldID]
-  double getDoubleField(JFieldID fieldID) {
-    _checkDeleted();
-    final result = _env.GetDoubleField(_obj, fieldID);
-
-    _env.checkException();
-    return result;
-  }
-
-  /// Retrieve field of given [name] and [signature]
-  double getDoubleFieldByName(String name, String signature) {
-    final fID = getFieldID(name, signature);
-    final result = getDoubleField(fID);
-    return result;
-  }
-
-  /// Calls method pointed to by [methodID] with [args] as arguments
-  void callVoidMethod(JMethodID methodID, List<dynamic> args) {
-    _checkDeleted();
-    final jvArgs = JValueArgs(args, _env);
-    final result = _env.CallVoidMethodA(_obj, methodID, jvArgs.values);
-    jvArgs.disposeIn(_env);
-    calloc.free(jvArgs.values);
-
-    _env.checkException();
-    return result;
-  }
-
-  /// Looks up method with [name] and [signature], calls it with [args] as arguments.
-  /// If calling the same method multiple times, consider using [getMethodID]
-  /// and [callVoidMethod].
-  void callVoidMethodByName(String name, String signature, List<dynamic> args) {
-    final mID = getMethodID(name, signature);
-    final result = callVoidMethod(mID, args);
-    return result;
-  }
-}
diff --git a/pkgs/jni/lib/src/jvalues.dart b/pkgs/jni/lib/src/jvalues.dart
index 94a9cbe..33946b8 100644
--- a/pkgs/jni/lib/src/jvalues.dart
+++ b/pkgs/jni/lib/src/jvalues.dart
@@ -6,11 +6,16 @@
 import 'package:ffi/ffi.dart';
 
 import 'third_party/jni_bindings_generated.dart';
-import 'extensions.dart';
+import 'jni.dart';
 import 'jni_object.dart';
+import 'env_extensions.dart';
 
 void _fillJValue(Pointer<JValue> pos, dynamic arg) {
-  // switch on runtimeType is not guaranteed to work?
+  if (arg is JniObject) {
+    pos.ref.l = arg.reference;
+    return;
+  }
+
   switch (arg.runtimeType) {
     case int:
       pos.ref.i = arg;
@@ -19,7 +24,7 @@
       pos.ref.z = arg ? 1 : 0;
       break;
     case Pointer<Void>:
-    case Pointer<Never>:
+    case Pointer<Never>: // for nullptr
       pos.ref.l = arg;
       break;
     case double:
@@ -41,7 +46,7 @@
       pos.ref.b = (arg as JValueByte).value;
       break;
     default:
-      throw "cannot convert ${arg.runtimeType} to jvalue";
+      throw UnsupportedError("cannot convert ${arg.runtimeType} to jvalue");
   }
 }
 
@@ -114,28 +119,27 @@
 class JValueArgs {
   late Pointer<JValue> values;
   final List<JObject> createdRefs = [];
+  final _env = Jni.env;
 
-  JValueArgs(List<dynamic> args, Pointer<JniEnv> env,
-      [Allocator allocator = malloc]) {
+  JValueArgs(List<dynamic> args, [Allocator allocator = malloc]) {
     values = allocator<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.asJString(arg);
         ptr.ref.l = jstr;
         createdRefs.add(jstr);
-      } else if (arg is JniObject) {
-        ptr.ref.l = arg.jobject;
       } else {
         _fillJValue(ptr, arg);
       }
     }
   }
 
-  void disposeIn(Pointer<JniEnv> env) {
+  /// Deletes temporary references such as [JString]s.
+  void dispose() {
     for (var ref in createdRefs) {
-      env.DeleteLocalRef(ref);
+      _env.DeleteGlobalRef(ref);
     }
   }
 }
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 77a1700..9b95e21 100644
--- a/pkgs/jni/lib/src/third_party/jni_bindings_generated.dart
+++ b/pkgs/jni/lib/src/third_party/jni_bindings_generated.dart
@@ -1,5 +1,5 @@
 // Autogenerated file. Do not edit.
-// Generated from an annotated version of jni.h provided in Android NDK
+// 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:
 
@@ -130,6 +130,14 @@
   late final _GetJavaVM =
       _GetJavaVMPtr.asFunction<ffi.Pointer<JavaVM> Function()>();
 
+  int DestroyJavaVM() {
+    return _DestroyJavaVM();
+  }
+
+  late final _DestroyJavaVMPtr =
+      _lookup<ffi.NativeFunction<ffi.Int Function()>>('DestroyJavaVM');
+  late final _DestroyJavaVM = _DestroyJavaVMPtr.asFunction<int Function()>();
+
   ffi.Pointer<JniEnv> GetJniEnv() {
     return _GetJniEnv();
   }
@@ -195,69 +203,87 @@
   late final _GetCurrentActivity =
       _GetCurrentActivityPtr.asFunction<JObject Function()>();
 
-  void SetJNILogging(
-    int level,
-  ) {
-    return _SetJNILogging(
-      level,
-    );
+  late final ffi.Pointer<GlobalJniEnv> _globalEnv =
+      _lookup<GlobalJniEnv>('globalEnv');
+
+  GlobalJniEnv get globalEnv => _globalEnv.ref;
+
+  ffi.Pointer<GlobalJniEnv> GetGlobalEnv() {
+    return _GetGlobalEnv();
   }
 
-  late final _SetJNILoggingPtr =
-      _lookup<ffi.NativeFunction<ffi.Void Function(ffi.Int)>>('SetJNILogging');
-  late final _SetJNILogging =
-      _SetJNILoggingPtr.asFunction<void Function(int)>();
-
-  JString ToJavaString(
-    ffi.Pointer<ffi.Char> str,
-  ) {
-    return _ToJavaString(
-      str,
-    );
-  }
-
-  late final _ToJavaStringPtr =
-      _lookup<ffi.NativeFunction<JString Function(ffi.Pointer<ffi.Char>)>>(
-          'ToJavaString');
-  late final _ToJavaString =
-      _ToJavaStringPtr.asFunction<JString Function(ffi.Pointer<ffi.Char>)>();
-
-  ffi.Pointer<ffi.Char> GetJavaStringChars(
-    JString jstr,
-  ) {
-    return _GetJavaStringChars(
-      jstr,
-    );
-  }
-
-  late final _GetJavaStringCharsPtr =
-      _lookup<ffi.NativeFunction<ffi.Pointer<ffi.Char> Function(JString)>>(
-          'GetJavaStringChars');
-  late final _GetJavaStringChars = _GetJavaStringCharsPtr.asFunction<
-      ffi.Pointer<ffi.Char> Function(JString)>();
-
-  void ReleaseJavaStringChars(
-    JString jstr,
-    ffi.Pointer<ffi.Char> buf,
-  ) {
-    return _ReleaseJavaStringChars(
-      jstr,
-      buf,
-    );
-  }
-
-  late final _ReleaseJavaStringCharsPtr = _lookup<
-      ffi.NativeFunction<
-          ffi.Void Function(
-              JString, ffi.Pointer<ffi.Char>)>>('ReleaseJavaStringChars');
-  late final _ReleaseJavaStringChars = _ReleaseJavaStringCharsPtr.asFunction<
-      void Function(JString, ffi.Pointer<ffi.Char>)>();
+  late final _GetGlobalEnvPtr =
+      _lookup<ffi.NativeFunction<ffi.Pointer<GlobalJniEnv> Function()>>(
+          'GetGlobalEnv');
+  late final _GetGlobalEnv =
+      _GetGlobalEnvPtr.asFunction<ffi.Pointer<GlobalJniEnv> Function()>();
 }
 
 class jfieldID_ extends ffi.Opaque {}
 
 class jmethodID_ extends ffi.Opaque {}
 
+class JValue extends ffi.Union {
+  @JBoolean()
+  external int z;
+
+  @JByte()
+  external int b;
+
+  @JChar()
+  external int c;
+
+  @JShort()
+  external int s;
+
+  @JInt()
+  external int i;
+
+  @JLong()
+  external int j;
+
+  @JFloat()
+  external double f;
+
+  @JDouble()
+  external double d;
+
+  external JObject l;
+}
+
+/// Primitive types that match up with Java equivalents.
+typedef JBoolean = ffi.Uint8;
+typedef JByte = ffi.Int8;
+typedef JChar = ffi.Uint16;
+typedef JShort = ffi.Int16;
+typedef JInt = ffi.Int32;
+typedef JLong = ffi.Int64;
+typedef JFloat = ffi.Float;
+typedef JDouble = ffi.Double;
+
+/// Reference types, in C.
+typedef JObject = ffi.Pointer<ffi.Void>;
+
+abstract class jobjectRefType {
+  static const int JNIInvalidRefType = 0;
+  static const int JNILocalRefType = 1;
+  static const int JNIGlobalRefType = 2;
+  static const int JNIWeakGlobalRefType = 3;
+}
+
+class JNINativeMethod extends ffi.Struct {
+  external ffi.Pointer<ffi.Char> name;
+
+  external ffi.Pointer<ffi.Char> signature;
+
+  external ffi.Pointer<ffi.Void> fnPtr;
+}
+
+/// C++ version.
+class _JavaVM extends ffi.Struct {
+  external ffi.Pointer<JNIInvokeInterface> functions;
+}
+
 /// JNI invocation interface.
 class JNIInvokeInterface extends ffi.Struct {
   external ffi.Pointer<ffi.Void> reserved0;
@@ -289,13 +315,11 @@
 }
 
 extension JNIInvokeInterfaceExtension on ffi.Pointer<JavaVM> {
-  @pragma('vm:prefer-inline')
   int DestroyJavaVM() {
     return value.ref.DestroyJavaVM
         .asFunction<int Function(ffi.Pointer<JavaVM>)>()(this);
   }
 
-  @pragma('vm:prefer-inline')
   int AttachCurrentThread(
       ffi.Pointer<ffi.Pointer<JniEnv>> p_env, ffi.Pointer<ffi.Void> thr_args) {
     return value.ref.AttachCurrentThread.asFunction<
@@ -303,20 +327,17 @@
             ffi.Pointer<ffi.Void>)>()(this, p_env, thr_args);
   }
 
-  @pragma('vm:prefer-inline')
   int DetachCurrentThread() {
     return value.ref.DetachCurrentThread
         .asFunction<int Function(ffi.Pointer<JavaVM>)>()(this);
   }
 
-  @pragma('vm:prefer-inline')
   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);
   }
 
-  @pragma('vm:prefer-inline')
   int AttachCurrentThreadAsDaemon(
       ffi.Pointer<ffi.Pointer<JniEnv>> p_env, ffi.Pointer<ffi.Void> thr_args) {
     return value.ref.AttachCurrentThreadAsDaemon.asFunction<
@@ -325,7 +346,6 @@
   }
 }
 
-typedef JInt = ffi.Int32;
 typedef JavaVM = ffi.Pointer<JNIInvokeInterface>;
 typedef JniEnv = ffi.Pointer<JNINativeInterface>;
 
@@ -1489,1483 +1509,13 @@
       GetObjectRefType;
 }
 
-extension JNINativeInterfaceExtension on ffi.Pointer<JniEnv> {
-  @pragma('vm:prefer-inline')
-  int GetVersion() {
-    return value.ref.GetVersion
-        .asFunction<int Function(ffi.Pointer<JniEnv1>)>()(this);
-  }
-
-  @pragma('vm:prefer-inline')
-  JClass DefineClass(ffi.Pointer<ffi.Char> name, JObject loader,
-      ffi.Pointer<JByte> buf, int bufLen) {
-    return value.ref.DefineClass.asFunction<
-        JClass Function(ffi.Pointer<JniEnv1>, ffi.Pointer<ffi.Char>, JObject,
-            ffi.Pointer<JByte>, int)>()(this, name, loader, buf, bufLen);
-  }
-
-  @pragma('vm:prefer-inline')
-  JClass FindClass(ffi.Pointer<ffi.Char> name) {
-    return value.ref.FindClass.asFunction<
-        JClass Function(
-            ffi.Pointer<JniEnv1>, ffi.Pointer<ffi.Char>)>()(this, name);
-  }
-
-  @pragma('vm:prefer-inline')
-  JMethodID FromReflectedMethod(JObject method) {
-    return value.ref.FromReflectedMethod
-            .asFunction<JMethodID Function(ffi.Pointer<JniEnv1>, JObject)>()(
-        this, method);
-  }
-
-  @pragma('vm:prefer-inline')
-  JFieldID FromReflectedField(JObject field) {
-    return value.ref.FromReflectedField
-            .asFunction<JFieldID Function(ffi.Pointer<JniEnv1>, JObject)>()(
-        this, field);
-  }
-
-  /// spec doesn't show jboolean parameter
-  ///
-  /// This is an automatically generated extension method
-  @pragma('vm:prefer-inline')
-  JObject ToReflectedMethod(JClass cls, JMethodID methodId, int isStatic) {
-    return value.ref.ToReflectedMethod.asFunction<
-            JObject Function(ffi.Pointer<JniEnv1>, JClass, JMethodID, int)>()(
-        this, cls, methodId, isStatic);
-  }
-
-  @pragma('vm:prefer-inline')
-  JClass GetSuperclass(JClass clazz) {
-    return value.ref.GetSuperclass
-            .asFunction<JClass Function(ffi.Pointer<JniEnv1>, JClass)>()(
-        this, clazz);
-  }
-
-  @pragma('vm:prefer-inline')
-  int IsAssignableFrom(JClass clazz1, JClass clazz2) {
-    return value.ref.IsAssignableFrom
-            .asFunction<int Function(ffi.Pointer<JniEnv1>, JClass, JClass)>()(
-        this, clazz1, clazz2);
-  }
-
-  /// spec doesn't show jboolean parameter
-  ///
-  /// This is an automatically generated extension method
-  @pragma('vm:prefer-inline')
-  JObject ToReflectedField(JClass cls, JFieldID fieldID, int isStatic) {
-    return value.ref.ToReflectedField.asFunction<
-            JObject Function(ffi.Pointer<JniEnv1>, JClass, JFieldID, int)>()(
-        this, cls, fieldID, isStatic);
-  }
-
-  @pragma('vm:prefer-inline')
-  int Throw(JThrowable obj) {
-    return value.ref.Throw
-            .asFunction<int Function(ffi.Pointer<JniEnv1>, JThrowable)>()(
-        this, obj);
-  }
-
-  @pragma('vm:prefer-inline')
-  int ThrowNew(JClass clazz, ffi.Pointer<ffi.Char> message) {
-    return value.ref.ThrowNew.asFunction<
-        int Function(ffi.Pointer<JniEnv1>, JClass,
-            ffi.Pointer<ffi.Char>)>()(this, clazz, message);
-  }
-
-  @pragma('vm:prefer-inline')
-  JThrowable ExceptionOccurred() {
-    return value.ref.ExceptionOccurred
-        .asFunction<JThrowable Function(ffi.Pointer<JniEnv1>)>()(this);
-  }
-
-  @pragma('vm:prefer-inline')
-  void ExceptionDescribe() {
-    return value.ref.ExceptionDescribe
-        .asFunction<void Function(ffi.Pointer<JniEnv1>)>()(this);
-  }
-
-  @pragma('vm:prefer-inline')
-  void ExceptionClear() {
-    return value.ref.ExceptionClear
-        .asFunction<void Function(ffi.Pointer<JniEnv1>)>()(this);
-  }
-
-  @pragma('vm:prefer-inline')
-  void FatalError(ffi.Pointer<ffi.Char> msg) {
-    return value.ref.FatalError.asFunction<
-        void Function(
-            ffi.Pointer<JniEnv1>, ffi.Pointer<ffi.Char>)>()(this, msg);
-  }
-
-  @pragma('vm:prefer-inline')
-  int PushLocalFrame(int capacity) {
-    return value.ref.PushLocalFrame
-        .asFunction<int Function(ffi.Pointer<JniEnv1>, int)>()(this, capacity);
-  }
-
-  @pragma('vm:prefer-inline')
-  JObject PopLocalFrame(JObject result) {
-    return value.ref.PopLocalFrame
-            .asFunction<JObject Function(ffi.Pointer<JniEnv1>, JObject)>()(
-        this, result);
-  }
-
-  @pragma('vm:prefer-inline')
-  JObject NewGlobalRef(JObject obj) {
-    return value.ref.NewGlobalRef
-            .asFunction<JObject Function(ffi.Pointer<JniEnv1>, JObject)>()(
-        this, obj);
-  }
-
-  @pragma('vm:prefer-inline')
-  void DeleteGlobalRef(JObject globalRef) {
-    return value.ref.DeleteGlobalRef
-            .asFunction<void Function(ffi.Pointer<JniEnv1>, JObject)>()(
-        this, globalRef);
-  }
-
-  @pragma('vm:prefer-inline')
-  void DeleteLocalRef(JObject localRef) {
-    return value.ref.DeleteLocalRef
-            .asFunction<void Function(ffi.Pointer<JniEnv1>, JObject)>()(
-        this, localRef);
-  }
-
-  @pragma('vm:prefer-inline')
-  int IsSameObject(JObject ref1, JObject ref2) {
-    return value.ref.IsSameObject
-            .asFunction<int Function(ffi.Pointer<JniEnv1>, JObject, JObject)>()(
-        this, ref1, ref2);
-  }
-
-  @pragma('vm:prefer-inline')
-  JObject NewLocalRef(JObject ref) {
-    return value.ref.NewLocalRef
-            .asFunction<JObject Function(ffi.Pointer<JniEnv1>, JObject)>()(
-        this, ref);
-  }
-
-  @pragma('vm:prefer-inline')
-  int EnsureLocalCapacity(int capacity) {
-    return value.ref.EnsureLocalCapacity
-        .asFunction<int Function(ffi.Pointer<JniEnv1>, int)>()(this, capacity);
-  }
-
-  @pragma('vm:prefer-inline')
-  JObject AllocObject(JClass clazz) {
-    return value.ref.AllocObject
-            .asFunction<JObject Function(ffi.Pointer<JniEnv1>, JClass)>()(
-        this, clazz);
-  }
-
-  @pragma('vm:prefer-inline')
-  JObject NewObject(JClass arg0, JMethodID arg1) {
-    return value.ref.NewObject.asFunction<
-        JObject Function(
-            ffi.Pointer<JniEnv1>, JClass, JMethodID)>()(this, arg0, arg1);
-  }
-
-  @pragma('vm:prefer-inline')
-  JObject NewObjectA(
-      JClass clazz, JMethodID methodID, ffi.Pointer<JValue> args) {
-    return value.ref.NewObjectA.asFunction<
-        JObject Function(ffi.Pointer<JniEnv1>, JClass, JMethodID,
-            ffi.Pointer<JValue>)>()(this, clazz, methodID, args);
-  }
-
-  @pragma('vm:prefer-inline')
-  JClass GetObjectClass(JObject obj) {
-    return value.ref.GetObjectClass
-            .asFunction<JClass Function(ffi.Pointer<JniEnv1>, JObject)>()(
-        this, obj);
-  }
-
-  @pragma('vm:prefer-inline')
-  int IsInstanceOf(JObject obj, JClass clazz) {
-    return value.ref.IsInstanceOf
-            .asFunction<int Function(ffi.Pointer<JniEnv1>, JObject, JClass)>()(
-        this, obj, clazz);
-  }
-
-  @pragma('vm:prefer-inline')
-  JMethodID GetMethodID(
-      JClass clazz, ffi.Pointer<ffi.Char> name, ffi.Pointer<ffi.Char> sig) {
-    return value.ref.GetMethodID.asFunction<
-        JMethodID Function(ffi.Pointer<JniEnv1>, JClass, ffi.Pointer<ffi.Char>,
-            ffi.Pointer<ffi.Char>)>()(this, clazz, name, sig);
-  }
-
-  @pragma('vm:prefer-inline')
-  JObject CallObjectMethod(JObject arg0, JMethodID arg1) {
-    return value.ref.CallObjectMethod.asFunction<
-        JObject Function(
-            ffi.Pointer<JniEnv1>, JObject, JMethodID)>()(this, arg0, arg1);
-  }
-
-  @pragma('vm:prefer-inline')
-  JObject CallObjectMethodA(
-      JObject obj, JMethodID methodID, ffi.Pointer<JValue> args) {
-    return value.ref.CallObjectMethodA.asFunction<
-        JObject Function(ffi.Pointer<JniEnv1>, JObject, JMethodID,
-            ffi.Pointer<JValue>)>()(this, obj, methodID, args);
-  }
-
-  @pragma('vm:prefer-inline')
-  int CallBooleanMethod(JObject arg0, JMethodID arg1) {
-    return value.ref.CallBooleanMethod.asFunction<
-        int Function(
-            ffi.Pointer<JniEnv1>, JObject, JMethodID)>()(this, arg0, arg1);
-  }
-
-  @pragma('vm:prefer-inline')
-  int CallBooleanMethodA(
-      JObject obj, JMethodID methodId, ffi.Pointer<JValue> args) {
-    return value.ref.CallBooleanMethodA.asFunction<
-        int Function(ffi.Pointer<JniEnv1>, JObject, JMethodID,
-            ffi.Pointer<JValue>)>()(this, obj, methodId, args);
-  }
-
-  @pragma('vm:prefer-inline')
-  int CallByteMethod(JObject arg0, JMethodID arg1) {
-    return value.ref.CallByteMethod.asFunction<
-        int Function(
-            ffi.Pointer<JniEnv1>, JObject, JMethodID)>()(this, arg0, arg1);
-  }
-
-  @pragma('vm:prefer-inline')
-  int CallByteMethodA(
-      JObject obj, JMethodID methodID, ffi.Pointer<JValue> args) {
-    return value.ref.CallByteMethodA.asFunction<
-        int Function(ffi.Pointer<JniEnv1>, JObject, JMethodID,
-            ffi.Pointer<JValue>)>()(this, obj, methodID, args);
-  }
-
-  @pragma('vm:prefer-inline')
-  int CallCharMethod(JObject arg0, JMethodID arg1) {
-    return value.ref.CallCharMethod.asFunction<
-        int Function(
-            ffi.Pointer<JniEnv1>, JObject, JMethodID)>()(this, arg0, arg1);
-  }
-
-  @pragma('vm:prefer-inline')
-  int CallCharMethodA(
-      JObject obj, JMethodID methodID, ffi.Pointer<JValue> args) {
-    return value.ref.CallCharMethodA.asFunction<
-        int Function(ffi.Pointer<JniEnv1>, JObject, JMethodID,
-            ffi.Pointer<JValue>)>()(this, obj, methodID, args);
-  }
-
-  @pragma('vm:prefer-inline')
-  int CallShortMethod(JObject arg0, JMethodID arg1) {
-    return value.ref.CallShortMethod.asFunction<
-        int Function(
-            ffi.Pointer<JniEnv1>, JObject, JMethodID)>()(this, arg0, arg1);
-  }
-
-  @pragma('vm:prefer-inline')
-  int CallShortMethodA(
-      JObject obj, JMethodID methodID, ffi.Pointer<JValue> args) {
-    return value.ref.CallShortMethodA.asFunction<
-        int Function(ffi.Pointer<JniEnv1>, JObject, JMethodID,
-            ffi.Pointer<JValue>)>()(this, obj, methodID, args);
-  }
-
-  @pragma('vm:prefer-inline')
-  int CallIntMethod(JObject arg0, JMethodID arg1) {
-    return value.ref.CallIntMethod.asFunction<
-        int Function(
-            ffi.Pointer<JniEnv1>, JObject, JMethodID)>()(this, arg0, arg1);
-  }
-
-  @pragma('vm:prefer-inline')
-  int CallIntMethodA(
-      JObject obj, JMethodID methodID, ffi.Pointer<JValue> args) {
-    return value.ref.CallIntMethodA.asFunction<
-        int Function(ffi.Pointer<JniEnv1>, JObject, JMethodID,
-            ffi.Pointer<JValue>)>()(this, obj, methodID, args);
-  }
-
-  @pragma('vm:prefer-inline')
-  int CallLongMethod(JObject arg0, JMethodID arg1) {
-    return value.ref.CallLongMethod.asFunction<
-        int Function(
-            ffi.Pointer<JniEnv1>, JObject, JMethodID)>()(this, arg0, arg1);
-  }
-
-  @pragma('vm:prefer-inline')
-  int CallLongMethodA(
-      JObject obj, JMethodID methodID, ffi.Pointer<JValue> args) {
-    return value.ref.CallLongMethodA.asFunction<
-        int Function(ffi.Pointer<JniEnv1>, JObject, JMethodID,
-            ffi.Pointer<JValue>)>()(this, obj, methodID, args);
-  }
-
-  @pragma('vm:prefer-inline')
-  double CallFloatMethod(JObject arg0, JMethodID arg1) {
-    return value.ref.CallFloatMethod.asFunction<
-        double Function(
-            ffi.Pointer<JniEnv1>, JObject, JMethodID)>()(this, arg0, arg1);
-  }
-
-  @pragma('vm:prefer-inline')
-  double CallFloatMethodA(
-      JObject obj, JMethodID methodID, ffi.Pointer<JValue> args) {
-    return value.ref.CallFloatMethodA.asFunction<
-        double Function(ffi.Pointer<JniEnv1>, JObject, JMethodID,
-            ffi.Pointer<JValue>)>()(this, obj, methodID, args);
-  }
-
-  @pragma('vm:prefer-inline')
-  double CallDoubleMethod(JObject arg0, JMethodID arg1) {
-    return value.ref.CallDoubleMethod.asFunction<
-        double Function(
-            ffi.Pointer<JniEnv1>, JObject, JMethodID)>()(this, arg0, arg1);
-  }
-
-  @pragma('vm:prefer-inline')
-  double CallDoubleMethodA(
-      JObject obj, JMethodID methodID, ffi.Pointer<JValue> args) {
-    return value.ref.CallDoubleMethodA.asFunction<
-        double Function(ffi.Pointer<JniEnv1>, JObject, JMethodID,
-            ffi.Pointer<JValue>)>()(this, obj, methodID, args);
-  }
-
-  @pragma('vm:prefer-inline')
-  void CallVoidMethod(JObject arg0, JMethodID arg1) {
-    return value.ref.CallVoidMethod.asFunction<
-        void Function(
-            ffi.Pointer<JniEnv1>, JObject, JMethodID)>()(this, arg0, arg1);
-  }
-
-  @pragma('vm:prefer-inline')
-  void CallVoidMethodA(
-      JObject obj, JMethodID methodID, ffi.Pointer<JValue> args) {
-    return value.ref.CallVoidMethodA.asFunction<
-        void Function(ffi.Pointer<JniEnv1>, JObject, JMethodID,
-            ffi.Pointer<JValue>)>()(this, obj, methodID, args);
-  }
-
-  @pragma('vm:prefer-inline')
-  JObject CallNonvirtualObjectMethod(
-      JObject arg0, JClass arg1, JMethodID arg2) {
-    return value.ref.CallNonvirtualObjectMethod.asFunction<
-        JObject Function(ffi.Pointer<JniEnv1>, JObject, JClass,
-            JMethodID)>()(this, arg0, arg1, arg2);
-  }
-
-  @pragma('vm:prefer-inline')
-  JObject CallNonvirtualObjectMethodA(
-      JObject obj, JClass clazz, JMethodID methodID, ffi.Pointer<JValue> args) {
-    return value.ref.CallNonvirtualObjectMethodA.asFunction<
-        JObject Function(ffi.Pointer<JniEnv1>, JObject, JClass, JMethodID,
-            ffi.Pointer<JValue>)>()(this, obj, clazz, methodID, args);
-  }
-
-  @pragma('vm:prefer-inline')
-  int CallNonvirtualBooleanMethod(JObject arg0, JClass arg1, JMethodID arg2) {
-    return value.ref.CallNonvirtualBooleanMethod.asFunction<
-            int Function(ffi.Pointer<JniEnv1>, JObject, JClass, JMethodID)>()(
-        this, arg0, arg1, arg2);
-  }
-
-  @pragma('vm:prefer-inline')
-  int CallNonvirtualBooleanMethodA(
-      JObject obj, JClass clazz, JMethodID methodID, ffi.Pointer<JValue> args) {
-    return value.ref.CallNonvirtualBooleanMethodA.asFunction<
-        int Function(ffi.Pointer<JniEnv1>, JObject, JClass, JMethodID,
-            ffi.Pointer<JValue>)>()(this, obj, clazz, methodID, args);
-  }
-
-  @pragma('vm:prefer-inline')
-  int CallNonvirtualByteMethod(JObject arg0, JClass arg1, JMethodID arg2) {
-    return value.ref.CallNonvirtualByteMethod.asFunction<
-            int Function(ffi.Pointer<JniEnv1>, JObject, JClass, JMethodID)>()(
-        this, arg0, arg1, arg2);
-  }
-
-  @pragma('vm:prefer-inline')
-  int CallNonvirtualByteMethodA(
-      JObject obj, JClass clazz, JMethodID methodID, ffi.Pointer<JValue> args) {
-    return value.ref.CallNonvirtualByteMethodA.asFunction<
-        int Function(ffi.Pointer<JniEnv1>, JObject, JClass, JMethodID,
-            ffi.Pointer<JValue>)>()(this, obj, clazz, methodID, args);
-  }
-
-  @pragma('vm:prefer-inline')
-  int CallNonvirtualCharMethod(JObject arg0, JClass arg1, JMethodID arg2) {
-    return value.ref.CallNonvirtualCharMethod.asFunction<
-            int Function(ffi.Pointer<JniEnv1>, JObject, JClass, JMethodID)>()(
-        this, arg0, arg1, arg2);
-  }
-
-  @pragma('vm:prefer-inline')
-  int CallNonvirtualCharMethodA(
-      JObject obj, JClass clazz, JMethodID methodID, ffi.Pointer<JValue> args) {
-    return value.ref.CallNonvirtualCharMethodA.asFunction<
-        int Function(ffi.Pointer<JniEnv1>, JObject, JClass, JMethodID,
-            ffi.Pointer<JValue>)>()(this, obj, clazz, methodID, args);
-  }
-
-  @pragma('vm:prefer-inline')
-  int CallNonvirtualShortMethod(JObject arg0, JClass arg1, JMethodID arg2) {
-    return value.ref.CallNonvirtualShortMethod.asFunction<
-            int Function(ffi.Pointer<JniEnv1>, JObject, JClass, JMethodID)>()(
-        this, arg0, arg1, arg2);
-  }
-
-  @pragma('vm:prefer-inline')
-  int CallNonvirtualShortMethodA(
-      JObject obj, JClass clazz, JMethodID methodID, ffi.Pointer<JValue> args) {
-    return value.ref.CallNonvirtualShortMethodA.asFunction<
-        int Function(ffi.Pointer<JniEnv1>, JObject, JClass, JMethodID,
-            ffi.Pointer<JValue>)>()(this, obj, clazz, methodID, args);
-  }
-
-  @pragma('vm:prefer-inline')
-  int CallNonvirtualIntMethod(JObject arg0, JClass arg1, JMethodID arg2) {
-    return value.ref.CallNonvirtualIntMethod.asFunction<
-            int Function(ffi.Pointer<JniEnv1>, JObject, JClass, JMethodID)>()(
-        this, arg0, arg1, arg2);
-  }
-
-  @pragma('vm:prefer-inline')
-  int CallNonvirtualIntMethodA(
-      JObject obj, JClass clazz, JMethodID methodID, ffi.Pointer<JValue> args) {
-    return value.ref.CallNonvirtualIntMethodA.asFunction<
-        int Function(ffi.Pointer<JniEnv1>, JObject, JClass, JMethodID,
-            ffi.Pointer<JValue>)>()(this, obj, clazz, methodID, args);
-  }
-
-  @pragma('vm:prefer-inline')
-  int CallNonvirtualLongMethod(JObject arg0, JClass arg1, JMethodID arg2) {
-    return value.ref.CallNonvirtualLongMethod.asFunction<
-            int Function(ffi.Pointer<JniEnv1>, JObject, JClass, JMethodID)>()(
-        this, arg0, arg1, arg2);
-  }
-
-  @pragma('vm:prefer-inline')
-  int CallNonvirtualLongMethodA(
-      JObject obj, JClass clazz, JMethodID methodID, ffi.Pointer<JValue> args) {
-    return value.ref.CallNonvirtualLongMethodA.asFunction<
-        int Function(ffi.Pointer<JniEnv1>, JObject, JClass, JMethodID,
-            ffi.Pointer<JValue>)>()(this, obj, clazz, methodID, args);
-  }
-
-  @pragma('vm:prefer-inline')
-  double CallNonvirtualFloatMethod(JObject arg0, JClass arg1, JMethodID arg2) {
-    return value.ref.CallNonvirtualFloatMethod.asFunction<
-        double Function(ffi.Pointer<JniEnv1>, JObject, JClass,
-            JMethodID)>()(this, arg0, arg1, arg2);
-  }
-
-  @pragma('vm:prefer-inline')
-  double CallNonvirtualFloatMethodA(
-      JObject obj, JClass clazz, JMethodID methodID, ffi.Pointer<JValue> args) {
-    return value.ref.CallNonvirtualFloatMethodA.asFunction<
-        double Function(ffi.Pointer<JniEnv1>, JObject, JClass, JMethodID,
-            ffi.Pointer<JValue>)>()(this, obj, clazz, methodID, args);
-  }
-
-  @pragma('vm:prefer-inline')
-  double CallNonvirtualDoubleMethod(JObject arg0, JClass arg1, JMethodID arg2) {
-    return value.ref.CallNonvirtualDoubleMethod.asFunction<
-        double Function(ffi.Pointer<JniEnv1>, JObject, JClass,
-            JMethodID)>()(this, arg0, arg1, arg2);
-  }
-
-  @pragma('vm:prefer-inline')
-  double CallNonvirtualDoubleMethodA(
-      JObject obj, JClass clazz, JMethodID methodID, ffi.Pointer<JValue> args) {
-    return value.ref.CallNonvirtualDoubleMethodA.asFunction<
-        double Function(ffi.Pointer<JniEnv1>, JObject, JClass, JMethodID,
-            ffi.Pointer<JValue>)>()(this, obj, clazz, methodID, args);
-  }
-
-  @pragma('vm:prefer-inline')
-  void CallNonvirtualVoidMethod(JObject arg0, JClass arg1, JMethodID arg2) {
-    return value.ref.CallNonvirtualVoidMethod.asFunction<
-            void Function(ffi.Pointer<JniEnv1>, JObject, JClass, JMethodID)>()(
-        this, arg0, arg1, arg2);
-  }
-
-  @pragma('vm:prefer-inline')
-  void CallNonvirtualVoidMethodA(
-      JObject obj, JClass clazz, JMethodID methodID, ffi.Pointer<JValue> args) {
-    return value.ref.CallNonvirtualVoidMethodA.asFunction<
-        void Function(ffi.Pointer<JniEnv1>, JObject, JClass, JMethodID,
-            ffi.Pointer<JValue>)>()(this, obj, clazz, methodID, args);
-  }
-
-  @pragma('vm:prefer-inline')
-  JFieldID GetFieldID(
-      JClass clazz, ffi.Pointer<ffi.Char> name, ffi.Pointer<ffi.Char> sig) {
-    return value.ref.GetFieldID.asFunction<
-        JFieldID Function(ffi.Pointer<JniEnv1>, JClass, ffi.Pointer<ffi.Char>,
-            ffi.Pointer<ffi.Char>)>()(this, clazz, name, sig);
-  }
-
-  @pragma('vm:prefer-inline')
-  JObject GetObjectField(JObject obj, JFieldID fieldID) {
-    return value.ref.GetObjectField.asFunction<
-        JObject Function(
-            ffi.Pointer<JniEnv1>, JObject, JFieldID)>()(this, obj, fieldID);
-  }
-
-  @pragma('vm:prefer-inline')
-  int GetBooleanField(JObject obj, JFieldID fieldID) {
-    return value.ref.GetBooleanField.asFunction<
-        int Function(
-            ffi.Pointer<JniEnv1>, JObject, JFieldID)>()(this, obj, fieldID);
-  }
-
-  @pragma('vm:prefer-inline')
-  int GetByteField(JObject obj, JFieldID fieldID) {
-    return value.ref.GetByteField.asFunction<
-        int Function(
-            ffi.Pointer<JniEnv1>, JObject, JFieldID)>()(this, obj, fieldID);
-  }
-
-  @pragma('vm:prefer-inline')
-  int GetCharField(JObject obj, JFieldID fieldID) {
-    return value.ref.GetCharField.asFunction<
-        int Function(
-            ffi.Pointer<JniEnv1>, JObject, JFieldID)>()(this, obj, fieldID);
-  }
-
-  @pragma('vm:prefer-inline')
-  int GetShortField(JObject obj, JFieldID fieldID) {
-    return value.ref.GetShortField.asFunction<
-        int Function(
-            ffi.Pointer<JniEnv1>, JObject, JFieldID)>()(this, obj, fieldID);
-  }
-
-  @pragma('vm:prefer-inline')
-  int GetIntField(JObject obj, JFieldID fieldID) {
-    return value.ref.GetIntField.asFunction<
-        int Function(
-            ffi.Pointer<JniEnv1>, JObject, JFieldID)>()(this, obj, fieldID);
-  }
-
-  @pragma('vm:prefer-inline')
-  int GetLongField(JObject obj, JFieldID fieldID) {
-    return value.ref.GetLongField.asFunction<
-        int Function(
-            ffi.Pointer<JniEnv1>, JObject, JFieldID)>()(this, obj, fieldID);
-  }
-
-  @pragma('vm:prefer-inline')
-  double GetFloatField(JObject obj, JFieldID fieldID) {
-    return value.ref.GetFloatField.asFunction<
-        double Function(
-            ffi.Pointer<JniEnv1>, JObject, JFieldID)>()(this, obj, fieldID);
-  }
-
-  @pragma('vm:prefer-inline')
-  double GetDoubleField(JObject obj, JFieldID fieldID) {
-    return value.ref.GetDoubleField.asFunction<
-        double Function(
-            ffi.Pointer<JniEnv1>, JObject, JFieldID)>()(this, obj, fieldID);
-  }
-
-  @pragma('vm:prefer-inline')
-  void SetObjectField(JObject obj, JFieldID fieldID, JObject val) {
-    return value.ref.SetObjectField.asFunction<
-            void Function(ffi.Pointer<JniEnv1>, JObject, JFieldID, JObject)>()(
-        this, obj, fieldID, val);
-  }
-
-  @pragma('vm:prefer-inline')
-  void SetBooleanField(JObject obj, JFieldID fieldID, int val) {
-    return value.ref.SetBooleanField.asFunction<
-            void Function(ffi.Pointer<JniEnv1>, JObject, JFieldID, int)>()(
-        this, obj, fieldID, val);
-  }
-
-  @pragma('vm:prefer-inline')
-  void SetByteField(JObject obj, JFieldID fieldID, int val) {
-    return value.ref.SetByteField.asFunction<
-            void Function(ffi.Pointer<JniEnv1>, JObject, JFieldID, int)>()(
-        this, obj, fieldID, val);
-  }
-
-  @pragma('vm:prefer-inline')
-  void SetCharField(JObject obj, JFieldID fieldID, int val) {
-    return value.ref.SetCharField.asFunction<
-            void Function(ffi.Pointer<JniEnv1>, JObject, JFieldID, int)>()(
-        this, obj, fieldID, val);
-  }
-
-  @pragma('vm:prefer-inline')
-  void SetShortField(JObject obj, JFieldID fieldID, int val) {
-    return value.ref.SetShortField.asFunction<
-            void Function(ffi.Pointer<JniEnv1>, JObject, JFieldID, int)>()(
-        this, obj, fieldID, val);
-  }
-
-  @pragma('vm:prefer-inline')
-  void SetIntField(JObject obj, JFieldID fieldID, int val) {
-    return value.ref.SetIntField.asFunction<
-            void Function(ffi.Pointer<JniEnv1>, JObject, JFieldID, int)>()(
-        this, obj, fieldID, val);
-  }
-
-  @pragma('vm:prefer-inline')
-  void SetLongField(JObject obj, JFieldID fieldID, int val) {
-    return value.ref.SetLongField.asFunction<
-            void Function(ffi.Pointer<JniEnv1>, JObject, JFieldID, int)>()(
-        this, obj, fieldID, val);
-  }
-
-  @pragma('vm:prefer-inline')
-  void SetFloatField(JObject obj, JFieldID fieldID, double val) {
-    return value.ref.SetFloatField.asFunction<
-            void Function(ffi.Pointer<JniEnv1>, JObject, JFieldID, double)>()(
-        this, obj, fieldID, val);
-  }
-
-  @pragma('vm:prefer-inline')
-  void SetDoubleField(JObject obj, JFieldID fieldID, double val) {
-    return value.ref.SetDoubleField.asFunction<
-            void Function(ffi.Pointer<JniEnv1>, JObject, JFieldID, double)>()(
-        this, obj, fieldID, val);
-  }
-
-  @pragma('vm:prefer-inline')
-  JMethodID GetStaticMethodID(
-      JClass clazz, ffi.Pointer<ffi.Char> name, ffi.Pointer<ffi.Char> sig) {
-    return value.ref.GetStaticMethodID.asFunction<
-        JMethodID Function(ffi.Pointer<JniEnv1>, JClass, ffi.Pointer<ffi.Char>,
-            ffi.Pointer<ffi.Char>)>()(this, clazz, name, sig);
-  }
-
-  @pragma('vm:prefer-inline')
-  JObject CallStaticObjectMethod(JClass arg0, JMethodID arg1) {
-    return value.ref.CallStaticObjectMethod.asFunction<
-        JObject Function(
-            ffi.Pointer<JniEnv1>, JClass, JMethodID)>()(this, arg0, arg1);
-  }
-
-  @pragma('vm:prefer-inline')
-  JObject CallStaticObjectMethodA(
-      JClass clazz, JMethodID methodID, ffi.Pointer<JValue> args) {
-    return value.ref.CallStaticObjectMethodA.asFunction<
-        JObject Function(ffi.Pointer<JniEnv1>, JClass, JMethodID,
-            ffi.Pointer<JValue>)>()(this, clazz, methodID, args);
-  }
-
-  @pragma('vm:prefer-inline')
-  int CallStaticBooleanMethod(JClass arg0, JMethodID arg1) {
-    return value.ref.CallStaticBooleanMethod.asFunction<
-        int Function(
-            ffi.Pointer<JniEnv1>, JClass, JMethodID)>()(this, arg0, arg1);
-  }
-
-  @pragma('vm:prefer-inline')
-  int CallStaticBooleanMethodA(
-      JClass clazz, JMethodID methodID, ffi.Pointer<JValue> args) {
-    return value.ref.CallStaticBooleanMethodA.asFunction<
-        int Function(ffi.Pointer<JniEnv1>, JClass, JMethodID,
-            ffi.Pointer<JValue>)>()(this, clazz, methodID, args);
-  }
-
-  @pragma('vm:prefer-inline')
-  int CallStaticByteMethod(JClass arg0, JMethodID arg1) {
-    return value.ref.CallStaticByteMethod.asFunction<
-        int Function(
-            ffi.Pointer<JniEnv1>, JClass, JMethodID)>()(this, arg0, arg1);
-  }
-
-  @pragma('vm:prefer-inline')
-  int CallStaticByteMethodA(
-      JClass clazz, JMethodID methodID, ffi.Pointer<JValue> args) {
-    return value.ref.CallStaticByteMethodA.asFunction<
-        int Function(ffi.Pointer<JniEnv1>, JClass, JMethodID,
-            ffi.Pointer<JValue>)>()(this, clazz, methodID, args);
-  }
-
-  @pragma('vm:prefer-inline')
-  int CallStaticCharMethod(JClass arg0, JMethodID arg1) {
-    return value.ref.CallStaticCharMethod.asFunction<
-        int Function(
-            ffi.Pointer<JniEnv1>, JClass, JMethodID)>()(this, arg0, arg1);
-  }
-
-  @pragma('vm:prefer-inline')
-  int CallStaticCharMethodA(
-      JClass clazz, JMethodID methodID, ffi.Pointer<JValue> args) {
-    return value.ref.CallStaticCharMethodA.asFunction<
-        int Function(ffi.Pointer<JniEnv1>, JClass, JMethodID,
-            ffi.Pointer<JValue>)>()(this, clazz, methodID, args);
-  }
-
-  @pragma('vm:prefer-inline')
-  int CallStaticShortMethod(JClass arg0, JMethodID arg1) {
-    return value.ref.CallStaticShortMethod.asFunction<
-        int Function(
-            ffi.Pointer<JniEnv1>, JClass, JMethodID)>()(this, arg0, arg1);
-  }
-
-  @pragma('vm:prefer-inline')
-  int CallStaticShortMethodA(
-      JClass clazz, JMethodID methodID, ffi.Pointer<JValue> args) {
-    return value.ref.CallStaticShortMethodA.asFunction<
-        int Function(ffi.Pointer<JniEnv1>, JClass, JMethodID,
-            ffi.Pointer<JValue>)>()(this, clazz, methodID, args);
-  }
-
-  @pragma('vm:prefer-inline')
-  int CallStaticIntMethod(JClass arg0, JMethodID arg1) {
-    return value.ref.CallStaticIntMethod.asFunction<
-        int Function(
-            ffi.Pointer<JniEnv1>, JClass, JMethodID)>()(this, arg0, arg1);
-  }
-
-  @pragma('vm:prefer-inline')
-  int CallStaticIntMethodA(
-      JClass clazz, JMethodID methodID, ffi.Pointer<JValue> args) {
-    return value.ref.CallStaticIntMethodA.asFunction<
-        int Function(ffi.Pointer<JniEnv1>, JClass, JMethodID,
-            ffi.Pointer<JValue>)>()(this, clazz, methodID, args);
-  }
-
-  @pragma('vm:prefer-inline')
-  int CallStaticLongMethod(JClass arg0, JMethodID arg1) {
-    return value.ref.CallStaticLongMethod.asFunction<
-        int Function(
-            ffi.Pointer<JniEnv1>, JClass, JMethodID)>()(this, arg0, arg1);
-  }
-
-  @pragma('vm:prefer-inline')
-  int CallStaticLongMethodA(
-      JClass clazz, JMethodID methodID, ffi.Pointer<JValue> args) {
-    return value.ref.CallStaticLongMethodA.asFunction<
-        int Function(ffi.Pointer<JniEnv1>, JClass, JMethodID,
-            ffi.Pointer<JValue>)>()(this, clazz, methodID, args);
-  }
-
-  @pragma('vm:prefer-inline')
-  double CallStaticFloatMethod(JClass arg0, JMethodID arg1) {
-    return value.ref.CallStaticFloatMethod.asFunction<
-        double Function(
-            ffi.Pointer<JniEnv1>, JClass, JMethodID)>()(this, arg0, arg1);
-  }
-
-  @pragma('vm:prefer-inline')
-  double CallStaticFloatMethodA(
-      JClass clazz, JMethodID methodID, ffi.Pointer<JValue> args) {
-    return value.ref.CallStaticFloatMethodA.asFunction<
-        double Function(ffi.Pointer<JniEnv1>, JClass, JMethodID,
-            ffi.Pointer<JValue>)>()(this, clazz, methodID, args);
-  }
-
-  @pragma('vm:prefer-inline')
-  double CallStaticDoubleMethod(JClass arg0, JMethodID arg1) {
-    return value.ref.CallStaticDoubleMethod.asFunction<
-        double Function(
-            ffi.Pointer<JniEnv1>, JClass, JMethodID)>()(this, arg0, arg1);
-  }
-
-  @pragma('vm:prefer-inline')
-  double CallStaticDoubleMethodA(
-      JClass clazz, JMethodID methodID, ffi.Pointer<JValue> args) {
-    return value.ref.CallStaticDoubleMethodA.asFunction<
-        double Function(ffi.Pointer<JniEnv1>, JClass, JMethodID,
-            ffi.Pointer<JValue>)>()(this, clazz, methodID, args);
-  }
-
-  @pragma('vm:prefer-inline')
-  void CallStaticVoidMethod(JClass arg0, JMethodID arg1) {
-    return value.ref.CallStaticVoidMethod.asFunction<
-        void Function(
-            ffi.Pointer<JniEnv1>, JClass, JMethodID)>()(this, arg0, arg1);
-  }
-
-  @pragma('vm:prefer-inline')
-  void CallStaticVoidMethodA(
-      JClass clazz, JMethodID methodID, ffi.Pointer<JValue> args) {
-    return value.ref.CallStaticVoidMethodA.asFunction<
-        void Function(ffi.Pointer<JniEnv1>, JClass, JMethodID,
-            ffi.Pointer<JValue>)>()(this, clazz, methodID, args);
-  }
-
-  @pragma('vm:prefer-inline')
-  JFieldID GetStaticFieldID(
-      JClass clazz, ffi.Pointer<ffi.Char> name, ffi.Pointer<ffi.Char> sig) {
-    return value.ref.GetStaticFieldID.asFunction<
-        JFieldID Function(ffi.Pointer<JniEnv1>, JClass, ffi.Pointer<ffi.Char>,
-            ffi.Pointer<ffi.Char>)>()(this, clazz, name, sig);
-  }
-
-  @pragma('vm:prefer-inline')
-  JObject GetStaticObjectField(JClass clazz, JFieldID fieldID) {
-    return value.ref.GetStaticObjectField.asFunction<
-        JObject Function(
-            ffi.Pointer<JniEnv1>, JClass, JFieldID)>()(this, clazz, fieldID);
-  }
-
-  @pragma('vm:prefer-inline')
-  int GetStaticBooleanField(JClass clazz, JFieldID fieldID) {
-    return value.ref.GetStaticBooleanField
-            .asFunction<int Function(ffi.Pointer<JniEnv1>, JClass, JFieldID)>()(
-        this, clazz, fieldID);
-  }
-
-  @pragma('vm:prefer-inline')
-  int GetStaticByteField(JClass clazz, JFieldID fieldID) {
-    return value.ref.GetStaticByteField
-            .asFunction<int Function(ffi.Pointer<JniEnv1>, JClass, JFieldID)>()(
-        this, clazz, fieldID);
-  }
-
-  @pragma('vm:prefer-inline')
-  int GetStaticCharField(JClass clazz, JFieldID fieldID) {
-    return value.ref.GetStaticCharField
-            .asFunction<int Function(ffi.Pointer<JniEnv1>, JClass, JFieldID)>()(
-        this, clazz, fieldID);
-  }
-
-  @pragma('vm:prefer-inline')
-  int GetStaticShortField(JClass clazz, JFieldID fieldID) {
-    return value.ref.GetStaticShortField
-            .asFunction<int Function(ffi.Pointer<JniEnv1>, JClass, JFieldID)>()(
-        this, clazz, fieldID);
-  }
-
-  @pragma('vm:prefer-inline')
-  int GetStaticIntField(JClass clazz, JFieldID fieldID) {
-    return value.ref.GetStaticIntField
-            .asFunction<int Function(ffi.Pointer<JniEnv1>, JClass, JFieldID)>()(
-        this, clazz, fieldID);
-  }
-
-  @pragma('vm:prefer-inline')
-  int GetStaticLongField(JClass clazz, JFieldID fieldID) {
-    return value.ref.GetStaticLongField
-            .asFunction<int Function(ffi.Pointer<JniEnv1>, JClass, JFieldID)>()(
-        this, clazz, fieldID);
-  }
-
-  @pragma('vm:prefer-inline')
-  double GetStaticFloatField(JClass clazz, JFieldID fieldID) {
-    return value.ref.GetStaticFloatField.asFunction<
-        double Function(
-            ffi.Pointer<JniEnv1>, JClass, JFieldID)>()(this, clazz, fieldID);
-  }
-
-  @pragma('vm:prefer-inline')
-  double GetStaticDoubleField(JClass clazz, JFieldID fieldID) {
-    return value.ref.GetStaticDoubleField.asFunction<
-        double Function(
-            ffi.Pointer<JniEnv1>, JClass, JFieldID)>()(this, clazz, fieldID);
-  }
-
-  @pragma('vm:prefer-inline')
-  void SetStaticObjectField(JClass clazz, JFieldID fieldID, JObject val) {
-    return value.ref.SetStaticObjectField.asFunction<
-            void Function(ffi.Pointer<JniEnv1>, JClass, JFieldID, JObject)>()(
-        this, clazz, fieldID, val);
-  }
-
-  @pragma('vm:prefer-inline')
-  void SetStaticBooleanField(JClass clazz, JFieldID fieldID, int val) {
-    return value.ref.SetStaticBooleanField.asFunction<
-            void Function(ffi.Pointer<JniEnv1>, JClass, JFieldID, int)>()(
-        this, clazz, fieldID, val);
-  }
-
-  @pragma('vm:prefer-inline')
-  void SetStaticByteField(JClass clazz, JFieldID fieldID, int val) {
-    return value.ref.SetStaticByteField.asFunction<
-            void Function(ffi.Pointer<JniEnv1>, JClass, JFieldID, int)>()(
-        this, clazz, fieldID, val);
-  }
-
-  @pragma('vm:prefer-inline')
-  void SetStaticCharField(JClass clazz, JFieldID fieldID, int val) {
-    return value.ref.SetStaticCharField.asFunction<
-            void Function(ffi.Pointer<JniEnv1>, JClass, JFieldID, int)>()(
-        this, clazz, fieldID, val);
-  }
-
-  @pragma('vm:prefer-inline')
-  void SetStaticShortField(JClass clazz, JFieldID fieldID, int val) {
-    return value.ref.SetStaticShortField.asFunction<
-            void Function(ffi.Pointer<JniEnv1>, JClass, JFieldID, int)>()(
-        this, clazz, fieldID, val);
-  }
-
-  @pragma('vm:prefer-inline')
-  void SetStaticIntField(JClass clazz, JFieldID fieldID, int val) {
-    return value.ref.SetStaticIntField.asFunction<
-            void Function(ffi.Pointer<JniEnv1>, JClass, JFieldID, int)>()(
-        this, clazz, fieldID, val);
-  }
-
-  @pragma('vm:prefer-inline')
-  void SetStaticLongField(JClass clazz, JFieldID fieldID, int val) {
-    return value.ref.SetStaticLongField.asFunction<
-            void Function(ffi.Pointer<JniEnv1>, JClass, JFieldID, int)>()(
-        this, clazz, fieldID, val);
-  }
-
-  @pragma('vm:prefer-inline')
-  void SetStaticFloatField(JClass clazz, JFieldID fieldID, double val) {
-    return value.ref.SetStaticFloatField.asFunction<
-            void Function(ffi.Pointer<JniEnv1>, JClass, JFieldID, double)>()(
-        this, clazz, fieldID, val);
-  }
-
-  @pragma('vm:prefer-inline')
-  void SetStaticDoubleField(JClass clazz, JFieldID fieldID, double val) {
-    return value.ref.SetStaticDoubleField.asFunction<
-            void Function(ffi.Pointer<JniEnv1>, JClass, JFieldID, double)>()(
-        this, clazz, fieldID, val);
-  }
-
-  @pragma('vm:prefer-inline')
-  JString NewString(ffi.Pointer<JChar> unicodeChars, int len) {
-    return value.ref.NewString.asFunction<
-            JString Function(ffi.Pointer<JniEnv1>, ffi.Pointer<JChar>, int)>()(
-        this, unicodeChars, len);
-  }
-
-  @pragma('vm:prefer-inline')
-  int GetStringLength(JString string) {
-    return value.ref.GetStringLength
-            .asFunction<int Function(ffi.Pointer<JniEnv1>, JString)>()(
-        this, string);
-  }
-
-  @pragma('vm:prefer-inline')
-  ffi.Pointer<JChar> GetStringChars(
-      JString string, ffi.Pointer<JBoolean> isCopy) {
-    return value.ref.GetStringChars.asFunction<
-        ffi.Pointer<JChar> Function(ffi.Pointer<JniEnv1>, JString,
-            ffi.Pointer<JBoolean>)>()(this, string, isCopy);
-  }
-
-  @pragma('vm:prefer-inline')
-  void ReleaseStringChars(JString string, ffi.Pointer<JChar> isCopy) {
-    return value.ref.ReleaseStringChars.asFunction<
-            void Function(ffi.Pointer<JniEnv1>, JString, ffi.Pointer<JChar>)>()(
-        this, string, isCopy);
-  }
-
-  @pragma('vm:prefer-inline')
-  JString NewStringUTF(ffi.Pointer<ffi.Char> bytes) {
-    return value.ref.NewStringUTF.asFunction<
-        JString Function(
-            ffi.Pointer<JniEnv1>, ffi.Pointer<ffi.Char>)>()(this, bytes);
-  }
-
-  @pragma('vm:prefer-inline')
-  int GetStringUTFLength(JString string) {
-    return value.ref.GetStringUTFLength
-            .asFunction<int Function(ffi.Pointer<JniEnv1>, JString)>()(
-        this, string);
-  }
-
-  @pragma('vm:prefer-inline')
-  ffi.Pointer<ffi.Char> GetStringUTFChars(
-      JString string, ffi.Pointer<JBoolean> isCopy) {
-    return value.ref.GetStringUTFChars.asFunction<
-        ffi.Pointer<ffi.Char> Function(ffi.Pointer<JniEnv1>, JString,
-            ffi.Pointer<JBoolean>)>()(this, string, isCopy);
-  }
-
-  @pragma('vm:prefer-inline')
-  void ReleaseStringUTFChars(JString string, ffi.Pointer<ffi.Char> utf) {
-    return value.ref.ReleaseStringUTFChars.asFunction<
-        void Function(ffi.Pointer<JniEnv1>, JString,
-            ffi.Pointer<ffi.Char>)>()(this, string, utf);
-  }
-
-  @pragma('vm:prefer-inline')
-  int GetArrayLength(JArray array) {
-    return value.ref.GetArrayLength
-        .asFunction<int Function(ffi.Pointer<JniEnv1>, JArray)>()(this, array);
-  }
-
-  @pragma('vm:prefer-inline')
-  JObjectArray NewObjectArray(
-      int length, JClass elementClass, JObject initialElement) {
-    return value.ref.NewObjectArray.asFunction<
-        JObjectArray Function(ffi.Pointer<JniEnv1>, int, JClass,
-            JObject)>()(this, length, elementClass, initialElement);
-  }
-
-  @pragma('vm:prefer-inline')
-  JObject GetObjectArrayElement(JObjectArray array, int index) {
-    return value.ref.GetObjectArrayElement.asFunction<
-        JObject Function(
-            ffi.Pointer<JniEnv1>, JObjectArray, int)>()(this, array, index);
-  }
-
-  @pragma('vm:prefer-inline')
-  void SetObjectArrayElement(JObjectArray array, int index, JObject val) {
-    return value.ref.SetObjectArrayElement.asFunction<
-            void Function(ffi.Pointer<JniEnv1>, JObjectArray, int, JObject)>()(
-        this, array, index, val);
-  }
-
-  @pragma('vm:prefer-inline')
-  JBooleanArray NewBooleanArray(int length) {
-    return value.ref.NewBooleanArray
-            .asFunction<JBooleanArray Function(ffi.Pointer<JniEnv1>, int)>()(
-        this, length);
-  }
-
-  @pragma('vm:prefer-inline')
-  JByteArray NewByteArray(int length) {
-    return value.ref.NewByteArray
-            .asFunction<JByteArray Function(ffi.Pointer<JniEnv1>, int)>()(
-        this, length);
-  }
-
-  @pragma('vm:prefer-inline')
-  JCharArray NewCharArray(int length) {
-    return value.ref.NewCharArray
-            .asFunction<JCharArray Function(ffi.Pointer<JniEnv1>, int)>()(
-        this, length);
-  }
-
-  @pragma('vm:prefer-inline')
-  JShortArray NewShortArray(int length) {
-    return value.ref.NewShortArray
-            .asFunction<JShortArray Function(ffi.Pointer<JniEnv1>, int)>()(
-        this, length);
-  }
-
-  @pragma('vm:prefer-inline')
-  JIntArray NewIntArray(int length) {
-    return value.ref.NewIntArray
-            .asFunction<JIntArray Function(ffi.Pointer<JniEnv1>, int)>()(
-        this, length);
-  }
-
-  @pragma('vm:prefer-inline')
-  JLongArray NewLongArray(int length) {
-    return value.ref.NewLongArray
-            .asFunction<JLongArray Function(ffi.Pointer<JniEnv1>, int)>()(
-        this, length);
-  }
-
-  @pragma('vm:prefer-inline')
-  JFloatArray NewFloatArray(int length) {
-    return value.ref.NewFloatArray
-            .asFunction<JFloatArray Function(ffi.Pointer<JniEnv1>, int)>()(
-        this, length);
-  }
-
-  @pragma('vm:prefer-inline')
-  JDoubleArray NewDoubleArray(int length) {
-    return value.ref.NewDoubleArray
-            .asFunction<JDoubleArray Function(ffi.Pointer<JniEnv1>, int)>()(
-        this, length);
-  }
-
-  @pragma('vm:prefer-inline')
-  ffi.Pointer<JBoolean> GetBooleanArrayElements(
-      JBooleanArray array, ffi.Pointer<JBoolean> isCopy) {
-    return value.ref.GetBooleanArrayElements.asFunction<
-        ffi.Pointer<JBoolean> Function(ffi.Pointer<JniEnv1>, JBooleanArray,
-            ffi.Pointer<JBoolean>)>()(this, array, isCopy);
-  }
-
-  @pragma('vm:prefer-inline')
-  ffi.Pointer<JByte> GetByteArrayElements(
-      JByteArray array, ffi.Pointer<JBoolean> isCopy) {
-    return value.ref.GetByteArrayElements.asFunction<
-        ffi.Pointer<JByte> Function(ffi.Pointer<JniEnv1>, JByteArray,
-            ffi.Pointer<JBoolean>)>()(this, array, isCopy);
-  }
-
-  @pragma('vm:prefer-inline')
-  ffi.Pointer<JChar> GetCharArrayElements(
-      JCharArray array, ffi.Pointer<JBoolean> isCopy) {
-    return value.ref.GetCharArrayElements.asFunction<
-        ffi.Pointer<JChar> Function(ffi.Pointer<JniEnv1>, JCharArray,
-            ffi.Pointer<JBoolean>)>()(this, array, isCopy);
-  }
-
-  @pragma('vm:prefer-inline')
-  ffi.Pointer<JShort> GetShortArrayElements(
-      JShortArray array, ffi.Pointer<JBoolean> isCopy) {
-    return value.ref.GetShortArrayElements.asFunction<
-        ffi.Pointer<JShort> Function(ffi.Pointer<JniEnv1>, JShortArray,
-            ffi.Pointer<JBoolean>)>()(this, array, isCopy);
-  }
-
-  @pragma('vm:prefer-inline')
-  ffi.Pointer<JInt> GetIntArrayElements(
-      JIntArray array, ffi.Pointer<JBoolean> isCopy) {
-    return value.ref.GetIntArrayElements.asFunction<
-        ffi.Pointer<JInt> Function(ffi.Pointer<JniEnv1>, JIntArray,
-            ffi.Pointer<JBoolean>)>()(this, array, isCopy);
-  }
-
-  @pragma('vm:prefer-inline')
-  ffi.Pointer<JLong> GetLongArrayElements(
-      JLongArray array, ffi.Pointer<JBoolean> isCopy) {
-    return value.ref.GetLongArrayElements.asFunction<
-        ffi.Pointer<JLong> Function(ffi.Pointer<JniEnv1>, JLongArray,
-            ffi.Pointer<JBoolean>)>()(this, array, isCopy);
-  }
-
-  @pragma('vm:prefer-inline')
-  ffi.Pointer<JFloat> GetFloatArrayElements(
-      JFloatArray array, ffi.Pointer<JBoolean> isCopy) {
-    return value.ref.GetFloatArrayElements.asFunction<
-        ffi.Pointer<JFloat> Function(ffi.Pointer<JniEnv1>, JFloatArray,
-            ffi.Pointer<JBoolean>)>()(this, array, isCopy);
-  }
-
-  @pragma('vm:prefer-inline')
-  ffi.Pointer<JDouble> GetDoubleArrayElements(
-      JDoubleArray array, ffi.Pointer<JBoolean> isCopy) {
-    return value.ref.GetDoubleArrayElements.asFunction<
-        ffi.Pointer<JDouble> Function(ffi.Pointer<JniEnv1>, JDoubleArray,
-            ffi.Pointer<JBoolean>)>()(this, array, isCopy);
-  }
-
-  @pragma('vm:prefer-inline')
-  void ReleaseBooleanArrayElements(
-      JBooleanArray array, ffi.Pointer<JBoolean> elems, int mode) {
-    return value.ref.ReleaseBooleanArrayElements.asFunction<
-        void Function(ffi.Pointer<JniEnv1>, JBooleanArray,
-            ffi.Pointer<JBoolean>, int)>()(this, array, elems, mode);
-  }
-
-  @pragma('vm:prefer-inline')
-  void ReleaseByteArrayElements(
-      JByteArray array, ffi.Pointer<JByte> elems, int mode) {
-    return value.ref.ReleaseByteArrayElements.asFunction<
-        void Function(ffi.Pointer<JniEnv1>, JByteArray, ffi.Pointer<JByte>,
-            int)>()(this, array, elems, mode);
-  }
-
-  @pragma('vm:prefer-inline')
-  void ReleaseCharArrayElements(
-      JCharArray array, ffi.Pointer<JChar> elems, int mode) {
-    return value.ref.ReleaseCharArrayElements.asFunction<
-        void Function(ffi.Pointer<JniEnv1>, JCharArray, ffi.Pointer<JChar>,
-            int)>()(this, array, elems, mode);
-  }
-
-  @pragma('vm:prefer-inline')
-  void ReleaseShortArrayElements(
-      JShortArray array, ffi.Pointer<JShort> elems, int mode) {
-    return value.ref.ReleaseShortArrayElements.asFunction<
-        void Function(ffi.Pointer<JniEnv1>, JShortArray, ffi.Pointer<JShort>,
-            int)>()(this, array, elems, mode);
-  }
-
-  @pragma('vm:prefer-inline')
-  void ReleaseIntArrayElements(
-      JIntArray array, ffi.Pointer<JInt> elems, int mode) {
-    return value.ref.ReleaseIntArrayElements.asFunction<
-        void Function(ffi.Pointer<JniEnv1>, JIntArray, ffi.Pointer<JInt>,
-            int)>()(this, array, elems, mode);
-  }
-
-  @pragma('vm:prefer-inline')
-  void ReleaseLongArrayElements(
-      JLongArray array, ffi.Pointer<JLong> elems, int mode) {
-    return value.ref.ReleaseLongArrayElements.asFunction<
-        void Function(ffi.Pointer<JniEnv1>, JLongArray, ffi.Pointer<JLong>,
-            int)>()(this, array, elems, mode);
-  }
-
-  @pragma('vm:prefer-inline')
-  void ReleaseFloatArrayElements(
-      JFloatArray array, ffi.Pointer<JFloat> elems, int mode) {
-    return value.ref.ReleaseFloatArrayElements.asFunction<
-        void Function(ffi.Pointer<JniEnv1>, JFloatArray, ffi.Pointer<JFloat>,
-            int)>()(this, array, elems, mode);
-  }
-
-  @pragma('vm:prefer-inline')
-  void ReleaseDoubleArrayElements(
-      JDoubleArray array, ffi.Pointer<JDouble> elems, int mode) {
-    return value.ref.ReleaseDoubleArrayElements.asFunction<
-        void Function(ffi.Pointer<JniEnv1>, JDoubleArray, ffi.Pointer<JDouble>,
-            int)>()(this, array, elems, mode);
-  }
-
-  @pragma('vm:prefer-inline')
-  void GetBooleanArrayRegion(
-      JBooleanArray array, int start, int len, ffi.Pointer<JBoolean> buf) {
-    return value.ref.GetBooleanArrayRegion.asFunction<
-        void Function(ffi.Pointer<JniEnv1>, JBooleanArray, int, int,
-            ffi.Pointer<JBoolean>)>()(this, array, start, len, buf);
-  }
-
-  @pragma('vm:prefer-inline')
-  void GetByteArrayRegion(
-      JByteArray array, int start, int len, ffi.Pointer<JByte> buf) {
-    return value.ref.GetByteArrayRegion.asFunction<
-        void Function(ffi.Pointer<JniEnv1>, JByteArray, int, int,
-            ffi.Pointer<JByte>)>()(this, array, start, len, buf);
-  }
-
-  @pragma('vm:prefer-inline')
-  void GetCharArrayRegion(
-      JCharArray array, int start, int len, ffi.Pointer<JChar> buf) {
-    return value.ref.GetCharArrayRegion.asFunction<
-        void Function(ffi.Pointer<JniEnv1>, JCharArray, int, int,
-            ffi.Pointer<JChar>)>()(this, array, start, len, buf);
-  }
-
-  @pragma('vm:prefer-inline')
-  void GetShortArrayRegion(
-      JShortArray array, int start, int len, ffi.Pointer<JShort> buf) {
-    return value.ref.GetShortArrayRegion.asFunction<
-        void Function(ffi.Pointer<JniEnv1>, JShortArray, int, int,
-            ffi.Pointer<JShort>)>()(this, array, start, len, buf);
-  }
-
-  @pragma('vm:prefer-inline')
-  void GetIntArrayRegion(
-      JIntArray array, int start, int len, ffi.Pointer<JInt> buf) {
-    return value.ref.GetIntArrayRegion.asFunction<
-        void Function(ffi.Pointer<JniEnv1>, JIntArray, int, int,
-            ffi.Pointer<JInt>)>()(this, array, start, len, buf);
-  }
-
-  @pragma('vm:prefer-inline')
-  void GetLongArrayRegion(
-      JLongArray array, int start, int len, ffi.Pointer<JLong> buf) {
-    return value.ref.GetLongArrayRegion.asFunction<
-        void Function(ffi.Pointer<JniEnv1>, JLongArray, int, int,
-            ffi.Pointer<JLong>)>()(this, array, start, len, buf);
-  }
-
-  @pragma('vm:prefer-inline')
-  void GetFloatArrayRegion(
-      JFloatArray array, int start, int len, ffi.Pointer<JFloat> buf) {
-    return value.ref.GetFloatArrayRegion.asFunction<
-        void Function(ffi.Pointer<JniEnv1>, JFloatArray, int, int,
-            ffi.Pointer<JFloat>)>()(this, array, start, len, buf);
-  }
-
-  @pragma('vm:prefer-inline')
-  void GetDoubleArrayRegion(
-      JDoubleArray array, int start, int len, ffi.Pointer<JDouble> buf) {
-    return value.ref.GetDoubleArrayRegion.asFunction<
-        void Function(ffi.Pointer<JniEnv1>, JDoubleArray, int, int,
-            ffi.Pointer<JDouble>)>()(this, array, start, len, buf);
-  }
-
-  /// spec shows these without const; some jni.h do, some don't
-  ///
-  /// This is an automatically generated extension method
-  @pragma('vm:prefer-inline')
-  void SetBooleanArrayRegion(
-      JBooleanArray array, int start, int len, ffi.Pointer<JBoolean> buf) {
-    return value.ref.SetBooleanArrayRegion.asFunction<
-        void Function(ffi.Pointer<JniEnv1>, JBooleanArray, int, int,
-            ffi.Pointer<JBoolean>)>()(this, array, start, len, buf);
-  }
-
-  @pragma('vm:prefer-inline')
-  void SetByteArrayRegion(
-      JByteArray array, int start, int len, ffi.Pointer<JByte> buf) {
-    return value.ref.SetByteArrayRegion.asFunction<
-        void Function(ffi.Pointer<JniEnv1>, JByteArray, int, int,
-            ffi.Pointer<JByte>)>()(this, array, start, len, buf);
-  }
-
-  @pragma('vm:prefer-inline')
-  void SetCharArrayRegion(
-      JCharArray array, int start, int len, ffi.Pointer<JChar> buf) {
-    return value.ref.SetCharArrayRegion.asFunction<
-        void Function(ffi.Pointer<JniEnv1>, JCharArray, int, int,
-            ffi.Pointer<JChar>)>()(this, array, start, len, buf);
-  }
-
-  @pragma('vm:prefer-inline')
-  void SetShortArrayRegion(
-      JShortArray array, int start, int len, ffi.Pointer<JShort> buf) {
-    return value.ref.SetShortArrayRegion.asFunction<
-        void Function(ffi.Pointer<JniEnv1>, JShortArray, int, int,
-            ffi.Pointer<JShort>)>()(this, array, start, len, buf);
-  }
-
-  @pragma('vm:prefer-inline')
-  void SetIntArrayRegion(
-      JIntArray array, int start, int len, ffi.Pointer<JInt> buf) {
-    return value.ref.SetIntArrayRegion.asFunction<
-        void Function(ffi.Pointer<JniEnv1>, JIntArray, int, int,
-            ffi.Pointer<JInt>)>()(this, array, start, len, buf);
-  }
-
-  @pragma('vm:prefer-inline')
-  void SetLongArrayRegion(
-      JLongArray array, int start, int len, ffi.Pointer<JLong> buf) {
-    return value.ref.SetLongArrayRegion.asFunction<
-        void Function(ffi.Pointer<JniEnv1>, JLongArray, int, int,
-            ffi.Pointer<JLong>)>()(this, array, start, len, buf);
-  }
-
-  @pragma('vm:prefer-inline')
-  void SetFloatArrayRegion(
-      JFloatArray array, int start, int len, ffi.Pointer<JFloat> buf) {
-    return value.ref.SetFloatArrayRegion.asFunction<
-        void Function(ffi.Pointer<JniEnv1>, JFloatArray, int, int,
-            ffi.Pointer<JFloat>)>()(this, array, start, len, buf);
-  }
-
-  @pragma('vm:prefer-inline')
-  void SetDoubleArrayRegion(
-      JDoubleArray array, int start, int len, ffi.Pointer<JDouble> buf) {
-    return value.ref.SetDoubleArrayRegion.asFunction<
-        void Function(ffi.Pointer<JniEnv1>, JDoubleArray, int, int,
-            ffi.Pointer<JDouble>)>()(this, array, start, len, buf);
-  }
-
-  @pragma('vm:prefer-inline')
-  int RegisterNatives(
-      JClass clazz, ffi.Pointer<JNINativeMethod> methods, int nMethods) {
-    return value.ref.RegisterNatives.asFunction<
-        int Function(ffi.Pointer<JniEnv1>, JClass, ffi.Pointer<JNINativeMethod>,
-            int)>()(this, clazz, methods, nMethods);
-  }
-
-  @pragma('vm:prefer-inline')
-  int UnregisterNatives(JClass clazz) {
-    return value.ref.UnregisterNatives
-        .asFunction<int Function(ffi.Pointer<JniEnv1>, JClass)>()(this, clazz);
-  }
-
-  @pragma('vm:prefer-inline')
-  int MonitorEnter(JObject obj) {
-    return value.ref.MonitorEnter
-        .asFunction<int Function(ffi.Pointer<JniEnv1>, JObject)>()(this, obj);
-  }
-
-  @pragma('vm:prefer-inline')
-  int MonitorExit(JObject obj) {
-    return value.ref.MonitorExit
-        .asFunction<int Function(ffi.Pointer<JniEnv1>, JObject)>()(this, obj);
-  }
-
-  @pragma('vm:prefer-inline')
-  int GetJavaVM(ffi.Pointer<ffi.Pointer<JavaVM>> vm) {
-    return value.ref.GetJavaVM.asFunction<
-        int Function(ffi.Pointer<JniEnv1>,
-            ffi.Pointer<ffi.Pointer<JavaVM>>)>()(this, vm);
-  }
-
-  @pragma('vm:prefer-inline')
-  void GetStringRegion(
-      JString str, int start, int len, ffi.Pointer<JChar> buf) {
-    return value.ref.GetStringRegion.asFunction<
-        void Function(ffi.Pointer<JniEnv1>, JString, int, int,
-            ffi.Pointer<JChar>)>()(this, str, start, len, buf);
-  }
-
-  @pragma('vm:prefer-inline')
-  void GetStringUTFRegion(
-      JString str, int start, int len, ffi.Pointer<ffi.Char> buf) {
-    return value.ref.GetStringUTFRegion.asFunction<
-        void Function(ffi.Pointer<JniEnv1>, JString, int, int,
-            ffi.Pointer<ffi.Char>)>()(this, str, start, len, buf);
-  }
-
-  @pragma('vm:prefer-inline')
-  ffi.Pointer<ffi.Void> GetPrimitiveArrayCritical(
-      JArray array, ffi.Pointer<JBoolean> isCopy) {
-    return value.ref.GetPrimitiveArrayCritical.asFunction<
-        ffi.Pointer<ffi.Void> Function(ffi.Pointer<JniEnv1>, JArray,
-            ffi.Pointer<JBoolean>)>()(this, array, isCopy);
-  }
-
-  @pragma('vm:prefer-inline')
-  void ReleasePrimitiveArrayCritical(
-      JArray array, ffi.Pointer<ffi.Void> carray, int mode) {
-    return value.ref.ReleasePrimitiveArrayCritical.asFunction<
-        void Function(ffi.Pointer<JniEnv1>, JArray, ffi.Pointer<ffi.Void>,
-            int)>()(this, array, carray, mode);
-  }
-
-  @pragma('vm:prefer-inline')
-  ffi.Pointer<JChar> GetStringCritical(
-      JString str, ffi.Pointer<JBoolean> isCopy) {
-    return value.ref.GetStringCritical.asFunction<
-        ffi.Pointer<JChar> Function(ffi.Pointer<JniEnv1>, JString,
-            ffi.Pointer<JBoolean>)>()(this, str, isCopy);
-  }
-
-  @pragma('vm:prefer-inline')
-  void ReleaseStringCritical(JString str, ffi.Pointer<JChar> carray) {
-    return value.ref.ReleaseStringCritical.asFunction<
-            void Function(ffi.Pointer<JniEnv1>, JString, ffi.Pointer<JChar>)>()(
-        this, str, carray);
-  }
-
-  @pragma('vm:prefer-inline')
-  JWeak NewWeakGlobalRef(JObject obj) {
-    return value.ref.NewWeakGlobalRef
-        .asFunction<JWeak Function(ffi.Pointer<JniEnv1>, JObject)>()(this, obj);
-  }
-
-  @pragma('vm:prefer-inline')
-  void DeleteWeakGlobalRef(JWeak obj) {
-    return value.ref.DeleteWeakGlobalRef
-        .asFunction<void Function(ffi.Pointer<JniEnv1>, JWeak)>()(this, obj);
-  }
-
-  @pragma('vm:prefer-inline')
-  int ExceptionCheck() {
-    return value.ref.ExceptionCheck
-        .asFunction<int Function(ffi.Pointer<JniEnv1>)>()(this);
-  }
-
-  @pragma('vm:prefer-inline')
-  JObject NewDirectByteBuffer(ffi.Pointer<ffi.Void> address, int capacity) {
-    return value.ref.NewDirectByteBuffer.asFunction<
-        JObject Function(ffi.Pointer<JniEnv1>, ffi.Pointer<ffi.Void>,
-            int)>()(this, address, capacity);
-  }
-
-  @pragma('vm:prefer-inline')
-  ffi.Pointer<ffi.Void> GetDirectBufferAddress(JObject buf) {
-    return value.ref.GetDirectBufferAddress.asFunction<
-        ffi.Pointer<ffi.Void> Function(
-            ffi.Pointer<JniEnv1>, JObject)>()(this, buf);
-  }
-
-  @pragma('vm:prefer-inline')
-  int GetDirectBufferCapacity(JObject buf) {
-    return value.ref.GetDirectBufferCapacity
-        .asFunction<int Function(ffi.Pointer<JniEnv1>, JObject)>()(this, buf);
-  }
-
-  /// added in JNI 1.6
-  ///
-  /// This is an automatically generated extension method
-  @pragma('vm:prefer-inline')
-  int GetObjectRefType(JObject obj) {
-    return value.ref.GetObjectRefType
-        .asFunction<int Function(ffi.Pointer<JniEnv1>, JObject)>()(this, obj);
-  }
-}
-
 typedef JniEnv1 = ffi.Pointer<JNINativeInterface>;
 typedef JClass = JObject;
 
-/// Reference types, in C.
-typedef JObject = ffi.Pointer<ffi.Void>;
-typedef JByte = ffi.Int8;
-
 /// "cardinal indices and sizes"
 typedef JSize = JInt;
 typedef JMethodID = ffi.Pointer<jmethodID_>;
 typedef JFieldID = ffi.Pointer<jfieldID_>;
-
-/// Primitive types that match up with Java equivalents.
-typedef JBoolean = ffi.Uint8;
 typedef JThrowable = JObject;
 
 class __va_list_tag extends ffi.Struct {
@@ -2980,39 +1530,6 @@
   external ffi.Pointer<ffi.Void> reg_save_area;
 }
 
-class JValue extends ffi.Union {
-  @JBoolean()
-  external int z;
-
-  @JByte()
-  external int b;
-
-  @JChar()
-  external int c;
-
-  @JShort()
-  external int s;
-
-  @JInt()
-  external int i;
-
-  @JLong()
-  external int j;
-
-  @JFloat()
-  external double f;
-
-  @JDouble()
-  external double d;
-
-  external JObject l;
-}
-
-typedef JChar = ffi.Uint16;
-typedef JShort = ffi.Int16;
-typedef JLong = ffi.Int64;
-typedef JFloat = ffi.Float;
-typedef JDouble = ffi.Double;
 typedef JString = JObject;
 typedef JArray = JObject;
 typedef JObjectArray = JArray;
@@ -3024,38 +1541,8 @@
 typedef JLongArray = JArray;
 typedef JFloatArray = JArray;
 typedef JDoubleArray = JArray;
-
-class JNINativeMethod extends ffi.Struct {
-  external ffi.Pointer<ffi.Char> name;
-
-  external ffi.Pointer<ffi.Char> signature;
-
-  external ffi.Pointer<ffi.Void> fnPtr;
-}
-
 typedef JWeak = JObject;
 
-abstract class jobjectRefType {
-  static const int JNIInvalidRefType = 0;
-  static const int JNILocalRefType = 1;
-  static const int JNIGlobalRefType = 2;
-  static const int JNIWeakGlobalRefType = 3;
-}
-
-/// C++ object wrapper.
-///
-/// This is usually overlaid on a C struct whose first element is a
-/// JNINativeInterface*.  We rely somewhat on compiler behavior.
-class _JNIEnv extends ffi.Struct {
-  /// do not rename this; it does not seem to be entirely opaque
-  external ffi.Pointer<JNINativeInterface> functions;
-}
-
-/// C++ version.
-class _JavaVM extends ffi.Struct {
-  external ffi.Pointer<JNIInvokeInterface> functions;
-}
-
 class JavaVMAttachArgs extends ffi.Struct {
   /// must be >= JNI_VERSION_1_2
   @JInt()
@@ -3098,6 +1585,1934 @@
   static const int JNI_ERROR = 6;
 }
 
+abstract class JniType {
+  static const int boolType = 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;
+}
+
+/// 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<JInt Function()>> GetVersion;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JClass Function(
+                  ffi.Pointer<ffi.Char>, JObject, ffi.Pointer<JByte>, JSize)>>
+      DefineClass;
+
+  external ffi
+          .Pointer<ffi.NativeFunction<JClass Function(ffi.Pointer<ffi.Char>)>>
+      FindClass;
+
+  external ffi.Pointer<ffi.NativeFunction<JMethodID Function(JObject)>>
+      FromReflectedMethod;
+
+  external ffi.Pointer<ffi.NativeFunction<JFieldID Function(JObject)>>
+      FromReflectedField;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<JObject Function(JClass, JMethodID, JBoolean)>>
+      ToReflectedMethod;
+
+  external ffi.Pointer<ffi.NativeFunction<JClass Function(JClass)>>
+      GetSuperclass;
+
+  external ffi.Pointer<ffi.NativeFunction<JBoolean Function(JClass, JClass)>>
+      IsAssignableFrom;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<JObject Function(JClass, JFieldID, JBoolean)>>
+      ToReflectedField;
+
+  external ffi.Pointer<ffi.NativeFunction<JInt Function(JThrowable)>> Throw;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<JInt Function(JClass, ffi.Pointer<ffi.Char>)>>
+      ThrowNew;
+
+  external ffi.Pointer<ffi.NativeFunction<JThrowable Function()>>
+      ExceptionOccurred;
+
+  external ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>
+      ExceptionDescribe;
+
+  external ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> ExceptionClear;
+
+  external ffi
+          .Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Char>)>>
+      FatalError;
+
+  external ffi.Pointer<ffi.NativeFunction<JInt Function(JInt)>> PushLocalFrame;
+
+  external ffi.Pointer<ffi.NativeFunction<JObject Function(JObject)>>
+      PopLocalFrame;
+
+  external ffi.Pointer<ffi.NativeFunction<JObject Function(JObject)>>
+      NewGlobalRef;
+
+  external ffi.Pointer<ffi.NativeFunction<ffi.Void Function(JObject)>>
+      DeleteGlobalRef;
+
+  external ffi.Pointer<ffi.NativeFunction<JBoolean Function(JObject, JObject)>>
+      IsSameObject;
+
+  external ffi.Pointer<ffi.NativeFunction<JInt Function(JInt)>>
+      EnsureLocalCapacity;
+
+  external ffi.Pointer<ffi.NativeFunction<JObject Function(JClass)>>
+      AllocObject;
+
+  external ffi.Pointer<ffi.NativeFunction<JObject Function(JClass, JMethodID)>>
+      NewObject;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          JObject Function(JClass, JMethodID, ffi.Pointer<JValue>)>> NewObjectA;
+
+  external ffi.Pointer<ffi.NativeFunction<JClass Function(JObject)>>
+      GetObjectClass;
+
+  external ffi.Pointer<ffi.NativeFunction<JBoolean Function(JObject, JClass)>>
+      IsInstanceOf;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JMethodID Function(
+                  JClass, ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Char>)>>
+      GetMethodID;
+
+  external ffi.Pointer<ffi.NativeFunction<JObject Function(JObject, JMethodID)>>
+      CallObjectMethod;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JObject Function(JObject, JMethodID, ffi.Pointer<JValue>)>>
+      CallObjectMethodA;
+
+  external ffi
+          .Pointer<ffi.NativeFunction<JBoolean Function(JObject, JMethodID)>>
+      CallBooleanMethod;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JBoolean Function(JObject, JMethodID, ffi.Pointer<JValue>)>>
+      CallBooleanMethodA;
+
+  external ffi.Pointer<ffi.NativeFunction<JByte Function(JObject, JMethodID)>>
+      CallByteMethod;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JByte Function(JObject, JMethodID, ffi.Pointer<JValue>)>>
+      CallByteMethodA;
+
+  external ffi.Pointer<ffi.NativeFunction<JChar Function(JObject, JMethodID)>>
+      CallCharMethod;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JChar Function(JObject, JMethodID, ffi.Pointer<JValue>)>>
+      CallCharMethodA;
+
+  external ffi.Pointer<ffi.NativeFunction<JShort Function(JObject, JMethodID)>>
+      CallShortMethod;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JShort Function(JObject, JMethodID, ffi.Pointer<JValue>)>>
+      CallShortMethodA;
+
+  external ffi.Pointer<ffi.NativeFunction<JInt Function(JObject, JMethodID)>>
+      CallIntMethod;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JInt Function(JObject, JMethodID, ffi.Pointer<JValue>)>>
+      CallIntMethodA;
+
+  external ffi.Pointer<ffi.NativeFunction<JLong Function(JObject, JMethodID)>>
+      CallLongMethod;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JLong Function(JObject, JMethodID, ffi.Pointer<JValue>)>>
+      CallLongMethodA;
+
+  external ffi.Pointer<ffi.NativeFunction<JFloat Function(JObject, JMethodID)>>
+      CallFloatMethod;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JFloat Function(JObject, JMethodID, ffi.Pointer<JValue>)>>
+      CallFloatMethodA;
+
+  external ffi.Pointer<ffi.NativeFunction<JDouble Function(JObject, JMethodID)>>
+      CallDoubleMethod;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JDouble Function(JObject, JMethodID, ffi.Pointer<JValue>)>>
+      CallDoubleMethodA;
+
+  external ffi
+          .Pointer<ffi.NativeFunction<ffi.Void Function(JObject, JMethodID)>>
+      CallVoidMethod;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              ffi.Void Function(JObject, JMethodID, ffi.Pointer<JValue>)>>
+      CallVoidMethodA;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<JObject Function(JObject, JClass, JMethodID)>>
+      CallNonvirtualObjectMethod;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JObject Function(
+                  JObject, JClass, JMethodID, ffi.Pointer<JValue>)>>
+      CallNonvirtualObjectMethodA;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<JBoolean Function(JObject, JClass, JMethodID)>>
+      CallNonvirtualBooleanMethod;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JBoolean Function(
+                  JObject, JClass, JMethodID, ffi.Pointer<JValue>)>>
+      CallNonvirtualBooleanMethodA;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<JByte Function(JObject, JClass, JMethodID)>>
+      CallNonvirtualByteMethod;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JByte Function(JObject, JClass, JMethodID, ffi.Pointer<JValue>)>>
+      CallNonvirtualByteMethodA;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<JChar Function(JObject, JClass, JMethodID)>>
+      CallNonvirtualCharMethod;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JChar Function(JObject, JClass, JMethodID, ffi.Pointer<JValue>)>>
+      CallNonvirtualCharMethodA;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<JShort Function(JObject, JClass, JMethodID)>>
+      CallNonvirtualShortMethod;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JShort Function(JObject, JClass, JMethodID, ffi.Pointer<JValue>)>>
+      CallNonvirtualShortMethodA;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<JInt Function(JObject, JClass, JMethodID)>>
+      CallNonvirtualIntMethod;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JInt Function(JObject, JClass, JMethodID, ffi.Pointer<JValue>)>>
+      CallNonvirtualIntMethodA;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<JLong Function(JObject, JClass, JMethodID)>>
+      CallNonvirtualLongMethod;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JLong Function(JObject, JClass, JMethodID, ffi.Pointer<JValue>)>>
+      CallNonvirtualLongMethodA;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<JFloat Function(JObject, JClass, JMethodID)>>
+      CallNonvirtualFloatMethod;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JFloat Function(JObject, JClass, JMethodID, ffi.Pointer<JValue>)>>
+      CallNonvirtualFloatMethodA;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<JDouble Function(JObject, JClass, JMethodID)>>
+      CallNonvirtualDoubleMethod;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JDouble Function(
+                  JObject, JClass, JMethodID, ffi.Pointer<JValue>)>>
+      CallNonvirtualDoubleMethodA;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<ffi.Void Function(JObject, JClass, JMethodID)>>
+      CallNonvirtualVoidMethod;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              ffi.Void Function(
+                  JObject, JClass, JMethodID, ffi.Pointer<JValue>)>>
+      CallNonvirtualVoidMethodA;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JFieldID Function(
+                  JClass, ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Char>)>>
+      GetFieldID;
+
+  external ffi.Pointer<ffi.NativeFunction<JObject Function(JObject, JFieldID)>>
+      GetObjectField;
+
+  external ffi.Pointer<ffi.NativeFunction<JBoolean Function(JObject, JFieldID)>>
+      GetBooleanField;
+
+  external ffi.Pointer<ffi.NativeFunction<JByte Function(JObject, JFieldID)>>
+      GetByteField;
+
+  external ffi.Pointer<ffi.NativeFunction<JChar Function(JObject, JFieldID)>>
+      GetCharField;
+
+  external ffi.Pointer<ffi.NativeFunction<JShort Function(JObject, JFieldID)>>
+      GetShortField;
+
+  external ffi.Pointer<ffi.NativeFunction<JInt Function(JObject, JFieldID)>>
+      GetIntField;
+
+  external ffi.Pointer<ffi.NativeFunction<JLong Function(JObject, JFieldID)>>
+      GetLongField;
+
+  external ffi.Pointer<ffi.NativeFunction<JFloat Function(JObject, JFieldID)>>
+      GetFloatField;
+
+  external ffi.Pointer<ffi.NativeFunction<JDouble Function(JObject, JFieldID)>>
+      GetDoubleField;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<ffi.Void Function(JObject, JFieldID, JObject)>>
+      SetObjectField;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<ffi.Void Function(JObject, JFieldID, JBoolean)>>
+      SetBooleanField;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<ffi.Void Function(JObject, JFieldID, JByte)>>
+      SetByteField;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<ffi.Void Function(JObject, JFieldID, JChar)>>
+      SetCharField;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<ffi.Void Function(JObject, JFieldID, JShort)>>
+      SetShortField;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<ffi.Void Function(JObject, JFieldID, JInt)>>
+      SetIntField;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<ffi.Void Function(JObject, JFieldID, JLong)>>
+      SetLongField;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<ffi.Void Function(JObject, JFieldID, JFloat)>>
+      SetFloatField;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<ffi.Void Function(JObject, JFieldID, JDouble)>>
+      SetDoubleField;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JMethodID Function(
+                  JClass, ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Char>)>>
+      GetStaticMethodID;
+
+  external ffi.Pointer<ffi.NativeFunction<JObject Function(JClass, JMethodID)>>
+      CallStaticObjectMethod;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JObject Function(JClass, JMethodID, ffi.Pointer<JValue>)>>
+      CallStaticObjectMethodA;
+
+  external ffi.Pointer<ffi.NativeFunction<JBoolean Function(JClass, JMethodID)>>
+      CallStaticBooleanMethod;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JBoolean Function(JClass, JMethodID, ffi.Pointer<JValue>)>>
+      CallStaticBooleanMethodA;
+
+  external ffi.Pointer<ffi.NativeFunction<JByte Function(JClass, JMethodID)>>
+      CallStaticByteMethod;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JByte Function(JClass, JMethodID, ffi.Pointer<JValue>)>>
+      CallStaticByteMethodA;
+
+  external ffi.Pointer<ffi.NativeFunction<JChar Function(JClass, JMethodID)>>
+      CallStaticCharMethod;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JChar Function(JClass, JMethodID, ffi.Pointer<JValue>)>>
+      CallStaticCharMethodA;
+
+  external ffi.Pointer<ffi.NativeFunction<JShort Function(JClass, JMethodID)>>
+      CallStaticShortMethod;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JShort Function(JClass, JMethodID, ffi.Pointer<JValue>)>>
+      CallStaticShortMethodA;
+
+  external ffi.Pointer<ffi.NativeFunction<JInt Function(JClass, JMethodID)>>
+      CallStaticIntMethod;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JInt Function(JClass, JMethodID, ffi.Pointer<JValue>)>>
+      CallStaticIntMethodA;
+
+  external ffi.Pointer<ffi.NativeFunction<JLong Function(JClass, JMethodID)>>
+      CallStaticLongMethod;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JLong Function(JClass, JMethodID, ffi.Pointer<JValue>)>>
+      CallStaticLongMethodA;
+
+  external ffi.Pointer<ffi.NativeFunction<JFloat Function(JClass, JMethodID)>>
+      CallStaticFloatMethod;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JFloat Function(JClass, JMethodID, ffi.Pointer<JValue>)>>
+      CallStaticFloatMethodA;
+
+  external ffi.Pointer<ffi.NativeFunction<JDouble Function(JClass, JMethodID)>>
+      CallStaticDoubleMethod;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JDouble Function(JClass, JMethodID, ffi.Pointer<JValue>)>>
+      CallStaticDoubleMethodA;
+
+  external ffi.Pointer<ffi.NativeFunction<ffi.Void Function(JClass, JMethodID)>>
+      CallStaticVoidMethod;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              ffi.Void Function(JClass, JMethodID, ffi.Pointer<JValue>)>>
+      CallStaticVoidMethodA;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JFieldID Function(
+                  JClass, ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Char>)>>
+      GetStaticFieldID;
+
+  external ffi.Pointer<ffi.NativeFunction<JObject Function(JClass, JFieldID)>>
+      GetStaticObjectField;
+
+  external ffi.Pointer<ffi.NativeFunction<JBoolean Function(JClass, JFieldID)>>
+      GetStaticBooleanField;
+
+  external ffi.Pointer<ffi.NativeFunction<JByte Function(JClass, JFieldID)>>
+      GetStaticByteField;
+
+  external ffi.Pointer<ffi.NativeFunction<JChar Function(JClass, JFieldID)>>
+      GetStaticCharField;
+
+  external ffi.Pointer<ffi.NativeFunction<JShort Function(JClass, JFieldID)>>
+      GetStaticShortField;
+
+  external ffi.Pointer<ffi.NativeFunction<JInt Function(JClass, JFieldID)>>
+      GetStaticIntField;
+
+  external ffi.Pointer<ffi.NativeFunction<JLong Function(JClass, JFieldID)>>
+      GetStaticLongField;
+
+  external ffi.Pointer<ffi.NativeFunction<JFloat Function(JClass, JFieldID)>>
+      GetStaticFloatField;
+
+  external ffi.Pointer<ffi.NativeFunction<JDouble Function(JClass, JFieldID)>>
+      GetStaticDoubleField;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<ffi.Void Function(JClass, JFieldID, JObject)>>
+      SetStaticObjectField;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<ffi.Void Function(JClass, JFieldID, JBoolean)>>
+      SetStaticBooleanField;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<ffi.Void Function(JClass, JFieldID, JByte)>>
+      SetStaticByteField;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<ffi.Void Function(JClass, JFieldID, JChar)>>
+      SetStaticCharField;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<ffi.Void Function(JClass, JFieldID, JShort)>>
+      SetStaticShortField;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<ffi.Void Function(JClass, JFieldID, JInt)>>
+      SetStaticIntField;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<ffi.Void Function(JClass, JFieldID, JLong)>>
+      SetStaticLongField;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<ffi.Void Function(JClass, JFieldID, JFloat)>>
+      SetStaticFloatField;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<ffi.Void Function(JClass, JFieldID, JDouble)>>
+      SetStaticDoubleField;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<JString Function(ffi.Pointer<JChar>, JSize)>>
+      NewString;
+
+  external ffi.Pointer<ffi.NativeFunction<JSize Function(JString)>>
+      GetStringLength;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              ffi.Pointer<JChar> Function(JString, ffi.Pointer<JBoolean>)>>
+      GetStringChars;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<ffi.Void Function(JString, ffi.Pointer<JChar>)>>
+      ReleaseStringChars;
+
+  external ffi
+          .Pointer<ffi.NativeFunction<JString Function(ffi.Pointer<ffi.Char>)>>
+      NewStringUTF;
+
+  external ffi.Pointer<ffi.NativeFunction<JSize Function(JString)>>
+      GetStringUTFLength;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              ffi.Pointer<ffi.Char> Function(JString, ffi.Pointer<JBoolean>)>>
+      GetStringUTFChars;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<ffi.Void Function(JString, ffi.Pointer<ffi.Char>)>>
+      ReleaseStringUTFChars;
+
+  external ffi.Pointer<ffi.NativeFunction<JSize Function(JArray)>>
+      GetArrayLength;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<JObjectArray Function(JSize, JClass, JObject)>>
+      NewObjectArray;
+
+  external ffi
+          .Pointer<ffi.NativeFunction<JObject Function(JObjectArray, JSize)>>
+      GetObjectArrayElement;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<ffi.Void Function(JObjectArray, JSize, JObject)>>
+      SetObjectArrayElement;
+
+  external ffi.Pointer<ffi.NativeFunction<JBooleanArray Function(JSize)>>
+      NewBooleanArray;
+
+  external ffi.Pointer<ffi.NativeFunction<JByteArray Function(JSize)>>
+      NewByteArray;
+
+  external ffi.Pointer<ffi.NativeFunction<JCharArray Function(JSize)>>
+      NewCharArray;
+
+  external ffi.Pointer<ffi.NativeFunction<JShortArray Function(JSize)>>
+      NewShortArray;
+
+  external ffi.Pointer<ffi.NativeFunction<JIntArray Function(JSize)>>
+      NewIntArray;
+
+  external ffi.Pointer<ffi.NativeFunction<JLongArray Function(JSize)>>
+      NewLongArray;
+
+  external ffi.Pointer<ffi.NativeFunction<JFloatArray Function(JSize)>>
+      NewFloatArray;
+
+  external ffi.Pointer<ffi.NativeFunction<JDoubleArray Function(JSize)>>
+      NewDoubleArray;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          ffi.Pointer<JBoolean> Function(
+              JBooleanArray, ffi.Pointer<JBoolean>)>> GetBooleanArrayElements;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              ffi.Pointer<JByte> Function(JByteArray, ffi.Pointer<JBoolean>)>>
+      GetByteArrayElements;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              ffi.Pointer<JChar> Function(JCharArray, ffi.Pointer<JBoolean>)>>
+      GetCharArrayElements;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              ffi.Pointer<JShort> Function(JShortArray, ffi.Pointer<JBoolean>)>>
+      GetShortArrayElements;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              ffi.Pointer<JInt> Function(JIntArray, ffi.Pointer<JBoolean>)>>
+      GetIntArrayElements;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              ffi.Pointer<JLong> Function(JLongArray, ffi.Pointer<JBoolean>)>>
+      GetLongArrayElements;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              ffi.Pointer<JFloat> Function(JFloatArray, ffi.Pointer<JBoolean>)>>
+      GetFloatArrayElements;
+
+  external ffi.Pointer<
+      ffi.NativeFunction<
+          ffi.Pointer<JDouble> Function(
+              JDoubleArray, ffi.Pointer<JBoolean>)>> GetDoubleArrayElements;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              ffi.Void Function(JBooleanArray, ffi.Pointer<JBoolean>, JInt)>>
+      ReleaseBooleanArrayElements;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              ffi.Void Function(JByteArray, ffi.Pointer<JByte>, JInt)>>
+      ReleaseByteArrayElements;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              ffi.Void Function(JCharArray, ffi.Pointer<JChar>, JInt)>>
+      ReleaseCharArrayElements;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              ffi.Void Function(JShortArray, ffi.Pointer<JShort>, JInt)>>
+      ReleaseShortArrayElements;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              ffi.Void Function(JIntArray, ffi.Pointer<JInt>, JInt)>>
+      ReleaseIntArrayElements;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              ffi.Void Function(JLongArray, ffi.Pointer<JLong>, JInt)>>
+      ReleaseLongArrayElements;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              ffi.Void Function(JFloatArray, ffi.Pointer<JFloat>, JInt)>>
+      ReleaseFloatArrayElements;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              ffi.Void Function(JDoubleArray, ffi.Pointer<JDouble>, JInt)>>
+      ReleaseDoubleArrayElements;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              ffi.Void Function(
+                  JBooleanArray, JSize, JSize, ffi.Pointer<JBoolean>)>>
+      GetBooleanArrayRegion;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              ffi.Void Function(JByteArray, JSize, JSize, ffi.Pointer<JByte>)>>
+      GetByteArrayRegion;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              ffi.Void Function(JCharArray, JSize, JSize, ffi.Pointer<JChar>)>>
+      GetCharArrayRegion;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              ffi.Void Function(
+                  JShortArray, JSize, JSize, ffi.Pointer<JShort>)>>
+      GetShortArrayRegion;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              ffi.Void Function(JIntArray, JSize, JSize, ffi.Pointer<JInt>)>>
+      GetIntArrayRegion;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              ffi.Void Function(JLongArray, JSize, JSize, ffi.Pointer<JLong>)>>
+      GetLongArrayRegion;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              ffi.Void Function(
+                  JFloatArray, JSize, JSize, ffi.Pointer<JFloat>)>>
+      GetFloatArrayRegion;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              ffi.Void Function(
+                  JDoubleArray, JSize, JSize, ffi.Pointer<JDouble>)>>
+      GetDoubleArrayRegion;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              ffi.Void Function(
+                  JBooleanArray, JSize, JSize, ffi.Pointer<JBoolean>)>>
+      SetBooleanArrayRegion;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              ffi.Void Function(JByteArray, JSize, JSize, ffi.Pointer<JByte>)>>
+      SetByteArrayRegion;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              ffi.Void Function(JCharArray, JSize, JSize, ffi.Pointer<JChar>)>>
+      SetCharArrayRegion;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              ffi.Void Function(
+                  JShortArray, JSize, JSize, ffi.Pointer<JShort>)>>
+      SetShortArrayRegion;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              ffi.Void Function(JIntArray, JSize, JSize, ffi.Pointer<JInt>)>>
+      SetIntArrayRegion;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              ffi.Void Function(JLongArray, JSize, JSize, ffi.Pointer<JLong>)>>
+      SetLongArrayRegion;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              ffi.Void Function(
+                  JFloatArray, JSize, JSize, ffi.Pointer<JFloat>)>>
+      SetFloatArrayRegion;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              ffi.Void Function(
+                  JDoubleArray, JSize, JSize, ffi.Pointer<JDouble>)>>
+      SetDoubleArrayRegion;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              JInt Function(JClass, ffi.Pointer<JNINativeMethod>, JInt)>>
+      RegisterNatives;
+
+  external ffi.Pointer<ffi.NativeFunction<JInt Function(JClass)>>
+      UnregisterNatives;
+
+  external ffi.Pointer<ffi.NativeFunction<JInt Function(JObject)>> MonitorEnter;
+
+  external ffi.Pointer<ffi.NativeFunction<JInt Function(JObject)>> MonitorExit;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<JInt Function(ffi.Pointer<ffi.Pointer<JavaVM>>)>>
+      GetJavaVM;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              ffi.Void Function(JString, JSize, JSize, ffi.Pointer<JChar>)>>
+      GetStringRegion;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              ffi.Void Function(JString, JSize, JSize, ffi.Pointer<ffi.Char>)>>
+      GetStringUTFRegion;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              ffi.Pointer<ffi.Void> Function(JArray, ffi.Pointer<JBoolean>)>>
+      GetPrimitiveArrayCritical;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              ffi.Void Function(JArray, ffi.Pointer<ffi.Void>, JInt)>>
+      ReleasePrimitiveArrayCritical;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<
+              ffi.Pointer<JChar> Function(JString, ffi.Pointer<JBoolean>)>>
+      GetStringCritical;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<ffi.Void Function(JString, ffi.Pointer<JChar>)>>
+      ReleaseStringCritical;
+
+  external ffi.Pointer<ffi.NativeFunction<JWeak Function(JObject)>>
+      NewWeakGlobalRef;
+
+  external ffi.Pointer<ffi.NativeFunction<ffi.Void Function(JWeak)>>
+      DeleteWeakGlobalRef;
+
+  external ffi.Pointer<ffi.NativeFunction<JBoolean Function()>> ExceptionCheck;
+
+  external ffi.Pointer<
+          ffi.NativeFunction<JObject Function(ffi.Pointer<ffi.Void>, JLong)>>
+      NewDirectByteBuffer;
+
+  external ffi
+          .Pointer<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function(JObject)>>
+      GetDirectBufferAddress;
+
+  external ffi.Pointer<ffi.NativeFunction<JLong Function(JObject)>>
+      GetDirectBufferCapacity;
+
+  external ffi.Pointer<ffi.NativeFunction<ffi.Int32 Function(JObject)>>
+      GetObjectRefType;
+}
+
+extension GlobalJniEnvExtension on ffi.Pointer<GlobalJniEnv> {
+  int GetVersion() {
+    return ref.GetVersion.asFunction<int Function()>()();
+  }
+
+  JClass DefineClass(ffi.Pointer<ffi.Char> name, JObject loader,
+      ffi.Pointer<JByte> buf, int bufLen) {
+    return ref.DefineClass.asFunction<
+        JClass Function(ffi.Pointer<ffi.Char>, JObject, ffi.Pointer<JByte>,
+            int)>()(name, loader, buf, bufLen);
+  }
+
+  JClass FindClass(ffi.Pointer<ffi.Char> name) {
+    return ref.FindClass.asFunction<JClass Function(ffi.Pointer<ffi.Char>)>()(
+        name);
+  }
+
+  JMethodID FromReflectedMethod(JObject method) {
+    return ref.FromReflectedMethod.asFunction<JMethodID Function(JObject)>()(
+        method);
+  }
+
+  JFieldID FromReflectedField(JObject field) {
+    return ref.FromReflectedField.asFunction<JFieldID Function(JObject)>()(
+        field);
+  }
+
+  JObject ToReflectedMethod(JClass cls, JMethodID methodId, int isStatic) {
+    return ref.ToReflectedMethod.asFunction<
+        JObject Function(JClass, JMethodID, int)>()(cls, methodId, isStatic);
+  }
+
+  JClass GetSuperclass(JClass clazz) {
+    return ref.GetSuperclass.asFunction<JClass Function(JClass)>()(clazz);
+  }
+
+  int IsAssignableFrom(JClass clazz1, JClass clazz2) {
+    return ref.IsAssignableFrom.asFunction<int Function(JClass, JClass)>()(
+        clazz1, clazz2);
+  }
+
+  JObject ToReflectedField(JClass cls, JFieldID fieldID, int isStatic) {
+    return ref.ToReflectedField.asFunction<
+        JObject Function(JClass, JFieldID, int)>()(cls, fieldID, isStatic);
+  }
+
+  int Throw(JThrowable obj) {
+    return ref.Throw.asFunction<int Function(JThrowable)>()(obj);
+  }
+
+  int ThrowNew(JClass clazz, ffi.Pointer<ffi.Char> message) {
+    return ref.ThrowNew.asFunction<
+        int Function(JClass, ffi.Pointer<ffi.Char>)>()(clazz, message);
+  }
+
+  JThrowable ExceptionOccurred() {
+    return ref.ExceptionOccurred.asFunction<JThrowable 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);
+  }
+
+  JObject PopLocalFrame(JObject result) {
+    return ref.PopLocalFrame.asFunction<JObject Function(JObject)>()(result);
+  }
+
+  JObject NewGlobalRef(JObject obj) {
+    return ref.NewGlobalRef.asFunction<JObject Function(JObject)>()(obj);
+  }
+
+  void DeleteGlobalRef(JObject globalRef) {
+    return ref.DeleteGlobalRef.asFunction<void Function(JObject)>()(globalRef);
+  }
+
+  int IsSameObject(JObject ref1, JObject ref2) {
+    return ref.IsSameObject.asFunction<int Function(JObject, JObject)>()(
+        ref1, ref2);
+  }
+
+  int EnsureLocalCapacity(int capacity) {
+    return ref.EnsureLocalCapacity.asFunction<int Function(int)>()(capacity);
+  }
+
+  JObject AllocObject(JClass clazz) {
+    return ref.AllocObject.asFunction<JObject Function(JClass)>()(clazz);
+  }
+
+  JObject NewObject(JClass arg1, JMethodID arg2) {
+    return ref.NewObject.asFunction<JObject Function(JClass, JMethodID)>()(
+        arg1, arg2);
+  }
+
+  JObject NewObjectA(
+      JClass clazz, JMethodID methodID, ffi.Pointer<JValue> args) {
+    return ref.NewObjectA.asFunction<
+        JObject Function(
+            JClass, JMethodID, ffi.Pointer<JValue>)>()(clazz, methodID, args);
+  }
+
+  JClass GetObjectClass(JObject obj) {
+    return ref.GetObjectClass.asFunction<JClass Function(JObject)>()(obj);
+  }
+
+  int IsInstanceOf(JObject obj, JClass clazz) {
+    return ref.IsInstanceOf.asFunction<int Function(JObject, JClass)>()(
+        obj, clazz);
+  }
+
+  JMethodID GetMethodID(
+      JClass clazz, ffi.Pointer<ffi.Char> name, ffi.Pointer<ffi.Char> sig) {
+    return ref.GetMethodID.asFunction<
+        JMethodID Function(JClass, ffi.Pointer<ffi.Char>,
+            ffi.Pointer<ffi.Char>)>()(clazz, name, sig);
+  }
+
+  JObject CallObjectMethod(JObject arg1, JMethodID arg2) {
+    return ref.CallObjectMethod.asFunction<
+        JObject Function(JObject, JMethodID)>()(arg1, arg2);
+  }
+
+  JObject CallObjectMethodA(
+      JObject obj, JMethodID methodID, ffi.Pointer<JValue> args) {
+    return ref.CallObjectMethodA.asFunction<
+        JObject Function(
+            JObject, JMethodID, ffi.Pointer<JValue>)>()(obj, methodID, args);
+  }
+
+  int CallBooleanMethod(JObject arg1, JMethodID arg2) {
+    return ref.CallBooleanMethod.asFunction<int Function(JObject, JMethodID)>()(
+        arg1, arg2);
+  }
+
+  int CallBooleanMethodA(
+      JObject obj, JMethodID methodId, ffi.Pointer<JValue> args) {
+    return ref.CallBooleanMethodA.asFunction<
+        int Function(
+            JObject, JMethodID, ffi.Pointer<JValue>)>()(obj, methodId, args);
+  }
+
+  int CallByteMethod(JObject arg1, JMethodID arg2) {
+    return ref.CallByteMethod.asFunction<int Function(JObject, JMethodID)>()(
+        arg1, arg2);
+  }
+
+  int CallByteMethodA(
+      JObject obj, JMethodID methodID, ffi.Pointer<JValue> args) {
+    return ref.CallByteMethodA.asFunction<
+        int Function(
+            JObject, JMethodID, ffi.Pointer<JValue>)>()(obj, methodID, args);
+  }
+
+  int CallCharMethod(JObject arg1, JMethodID arg2) {
+    return ref.CallCharMethod.asFunction<int Function(JObject, JMethodID)>()(
+        arg1, arg2);
+  }
+
+  int CallCharMethodA(
+      JObject obj, JMethodID methodID, ffi.Pointer<JValue> args) {
+    return ref.CallCharMethodA.asFunction<
+        int Function(
+            JObject, JMethodID, ffi.Pointer<JValue>)>()(obj, methodID, args);
+  }
+
+  int CallShortMethod(JObject arg1, JMethodID arg2) {
+    return ref.CallShortMethod.asFunction<int Function(JObject, JMethodID)>()(
+        arg1, arg2);
+  }
+
+  int CallShortMethodA(
+      JObject obj, JMethodID methodID, ffi.Pointer<JValue> args) {
+    return ref.CallShortMethodA.asFunction<
+        int Function(
+            JObject, JMethodID, ffi.Pointer<JValue>)>()(obj, methodID, args);
+  }
+
+  int CallIntMethod(JObject arg1, JMethodID arg2) {
+    return ref.CallIntMethod.asFunction<int Function(JObject, JMethodID)>()(
+        arg1, arg2);
+  }
+
+  int CallIntMethodA(
+      JObject obj, JMethodID methodID, ffi.Pointer<JValue> args) {
+    return ref.CallIntMethodA.asFunction<
+        int Function(
+            JObject, JMethodID, ffi.Pointer<JValue>)>()(obj, methodID, args);
+  }
+
+  int CallLongMethod(JObject arg1, JMethodID arg2) {
+    return ref.CallLongMethod.asFunction<int Function(JObject, JMethodID)>()(
+        arg1, arg2);
+  }
+
+  int CallLongMethodA(
+      JObject obj, JMethodID methodID, ffi.Pointer<JValue> args) {
+    return ref.CallLongMethodA.asFunction<
+        int Function(
+            JObject, JMethodID, ffi.Pointer<JValue>)>()(obj, methodID, args);
+  }
+
+  double CallFloatMethod(JObject arg1, JMethodID arg2) {
+    return ref.CallFloatMethod.asFunction<
+        double Function(JObject, JMethodID)>()(arg1, arg2);
+  }
+
+  double CallFloatMethodA(
+      JObject obj, JMethodID methodID, ffi.Pointer<JValue> args) {
+    return ref.CallFloatMethodA.asFunction<
+        double Function(
+            JObject, JMethodID, ffi.Pointer<JValue>)>()(obj, methodID, args);
+  }
+
+  double CallDoubleMethod(JObject arg1, JMethodID arg2) {
+    return ref.CallDoubleMethod.asFunction<
+        double Function(JObject, JMethodID)>()(arg1, arg2);
+  }
+
+  double CallDoubleMethodA(
+      JObject obj, JMethodID methodID, ffi.Pointer<JValue> args) {
+    return ref.CallDoubleMethodA.asFunction<
+        double Function(
+            JObject, JMethodID, ffi.Pointer<JValue>)>()(obj, methodID, args);
+  }
+
+  void CallVoidMethod(JObject arg1, JMethodID arg2) {
+    return ref.CallVoidMethod.asFunction<void Function(JObject, JMethodID)>()(
+        arg1, arg2);
+  }
+
+  void CallVoidMethodA(
+      JObject obj, JMethodID methodID, ffi.Pointer<JValue> args) {
+    return ref.CallVoidMethodA.asFunction<
+        void Function(
+            JObject, JMethodID, ffi.Pointer<JValue>)>()(obj, methodID, args);
+  }
+
+  JObject CallNonvirtualObjectMethod(
+      JObject arg1, JClass arg2, JMethodID arg3) {
+    return ref.CallNonvirtualObjectMethod.asFunction<
+        JObject Function(JObject, JClass, JMethodID)>()(arg1, arg2, arg3);
+  }
+
+  JObject CallNonvirtualObjectMethodA(
+      JObject obj, JClass clazz, JMethodID methodID, ffi.Pointer<JValue> args) {
+    return ref.CallNonvirtualObjectMethodA.asFunction<
+        JObject Function(JObject, JClass, JMethodID,
+            ffi.Pointer<JValue>)>()(obj, clazz, methodID, args);
+  }
+
+  int CallNonvirtualBooleanMethod(JObject arg1, JClass arg2, JMethodID arg3) {
+    return ref.CallNonvirtualBooleanMethod.asFunction<
+        int Function(JObject, JClass, JMethodID)>()(arg1, arg2, arg3);
+  }
+
+  int CallNonvirtualBooleanMethodA(
+      JObject obj, JClass clazz, JMethodID methodID, ffi.Pointer<JValue> args) {
+    return ref.CallNonvirtualBooleanMethodA.asFunction<
+            int Function(JObject, JClass, JMethodID, ffi.Pointer<JValue>)>()(
+        obj, clazz, methodID, args);
+  }
+
+  int CallNonvirtualByteMethod(JObject arg1, JClass arg2, JMethodID arg3) {
+    return ref.CallNonvirtualByteMethod.asFunction<
+        int Function(JObject, JClass, JMethodID)>()(arg1, arg2, arg3);
+  }
+
+  int CallNonvirtualByteMethodA(
+      JObject obj, JClass clazz, JMethodID methodID, ffi.Pointer<JValue> args) {
+    return ref.CallNonvirtualByteMethodA.asFunction<
+            int Function(JObject, JClass, JMethodID, ffi.Pointer<JValue>)>()(
+        obj, clazz, methodID, args);
+  }
+
+  int CallNonvirtualCharMethod(JObject arg1, JClass arg2, JMethodID arg3) {
+    return ref.CallNonvirtualCharMethod.asFunction<
+        int Function(JObject, JClass, JMethodID)>()(arg1, arg2, arg3);
+  }
+
+  int CallNonvirtualCharMethodA(
+      JObject obj, JClass clazz, JMethodID methodID, ffi.Pointer<JValue> args) {
+    return ref.CallNonvirtualCharMethodA.asFunction<
+            int Function(JObject, JClass, JMethodID, ffi.Pointer<JValue>)>()(
+        obj, clazz, methodID, args);
+  }
+
+  int CallNonvirtualShortMethod(JObject arg1, JClass arg2, JMethodID arg3) {
+    return ref.CallNonvirtualShortMethod.asFunction<
+        int Function(JObject, JClass, JMethodID)>()(arg1, arg2, arg3);
+  }
+
+  int CallNonvirtualShortMethodA(
+      JObject obj, JClass clazz, JMethodID methodID, ffi.Pointer<JValue> args) {
+    return ref.CallNonvirtualShortMethodA.asFunction<
+            int Function(JObject, JClass, JMethodID, ffi.Pointer<JValue>)>()(
+        obj, clazz, methodID, args);
+  }
+
+  int CallNonvirtualIntMethod(JObject arg1, JClass arg2, JMethodID arg3) {
+    return ref.CallNonvirtualIntMethod.asFunction<
+        int Function(JObject, JClass, JMethodID)>()(arg1, arg2, arg3);
+  }
+
+  int CallNonvirtualIntMethodA(
+      JObject obj, JClass clazz, JMethodID methodID, ffi.Pointer<JValue> args) {
+    return ref.CallNonvirtualIntMethodA.asFunction<
+            int Function(JObject, JClass, JMethodID, ffi.Pointer<JValue>)>()(
+        obj, clazz, methodID, args);
+  }
+
+  int CallNonvirtualLongMethod(JObject arg1, JClass arg2, JMethodID arg3) {
+    return ref.CallNonvirtualLongMethod.asFunction<
+        int Function(JObject, JClass, JMethodID)>()(arg1, arg2, arg3);
+  }
+
+  int CallNonvirtualLongMethodA(
+      JObject obj, JClass clazz, JMethodID methodID, ffi.Pointer<JValue> args) {
+    return ref.CallNonvirtualLongMethodA.asFunction<
+            int Function(JObject, JClass, JMethodID, ffi.Pointer<JValue>)>()(
+        obj, clazz, methodID, args);
+  }
+
+  double CallNonvirtualFloatMethod(JObject arg1, JClass arg2, JMethodID arg3) {
+    return ref.CallNonvirtualFloatMethod.asFunction<
+        double Function(JObject, JClass, JMethodID)>()(arg1, arg2, arg3);
+  }
+
+  double CallNonvirtualFloatMethodA(
+      JObject obj, JClass clazz, JMethodID methodID, ffi.Pointer<JValue> args) {
+    return ref.CallNonvirtualFloatMethodA.asFunction<
+            double Function(JObject, JClass, JMethodID, ffi.Pointer<JValue>)>()(
+        obj, clazz, methodID, args);
+  }
+
+  double CallNonvirtualDoubleMethod(JObject arg1, JClass arg2, JMethodID arg3) {
+    return ref.CallNonvirtualDoubleMethod.asFunction<
+        double Function(JObject, JClass, JMethodID)>()(arg1, arg2, arg3);
+  }
+
+  double CallNonvirtualDoubleMethodA(
+      JObject obj, JClass clazz, JMethodID methodID, ffi.Pointer<JValue> args) {
+    return ref.CallNonvirtualDoubleMethodA.asFunction<
+            double Function(JObject, JClass, JMethodID, ffi.Pointer<JValue>)>()(
+        obj, clazz, methodID, args);
+  }
+
+  void CallNonvirtualVoidMethod(JObject arg1, JClass arg2, JMethodID arg3) {
+    return ref.CallNonvirtualVoidMethod.asFunction<
+        void Function(JObject, JClass, JMethodID)>()(arg1, arg2, arg3);
+  }
+
+  void CallNonvirtualVoidMethodA(
+      JObject obj, JClass clazz, JMethodID methodID, ffi.Pointer<JValue> args) {
+    return ref.CallNonvirtualVoidMethodA.asFunction<
+            void Function(JObject, JClass, JMethodID, ffi.Pointer<JValue>)>()(
+        obj, clazz, methodID, args);
+  }
+
+  JFieldID GetFieldID(
+      JClass clazz, ffi.Pointer<ffi.Char> name, ffi.Pointer<ffi.Char> sig) {
+    return ref.GetFieldID.asFunction<
+        JFieldID Function(JClass, ffi.Pointer<ffi.Char>,
+            ffi.Pointer<ffi.Char>)>()(clazz, name, sig);
+  }
+
+  JObject GetObjectField(JObject obj, JFieldID fieldID) {
+    return ref.GetObjectField.asFunction<JObject Function(JObject, JFieldID)>()(
+        obj, fieldID);
+  }
+
+  int GetBooleanField(JObject obj, JFieldID fieldID) {
+    return ref.GetBooleanField.asFunction<int Function(JObject, JFieldID)>()(
+        obj, fieldID);
+  }
+
+  int GetByteField(JObject obj, JFieldID fieldID) {
+    return ref.GetByteField.asFunction<int Function(JObject, JFieldID)>()(
+        obj, fieldID);
+  }
+
+  int GetCharField(JObject obj, JFieldID fieldID) {
+    return ref.GetCharField.asFunction<int Function(JObject, JFieldID)>()(
+        obj, fieldID);
+  }
+
+  int GetShortField(JObject obj, JFieldID fieldID) {
+    return ref.GetShortField.asFunction<int Function(JObject, JFieldID)>()(
+        obj, fieldID);
+  }
+
+  int GetIntField(JObject obj, JFieldID fieldID) {
+    return ref.GetIntField.asFunction<int Function(JObject, JFieldID)>()(
+        obj, fieldID);
+  }
+
+  int GetLongField(JObject obj, JFieldID fieldID) {
+    return ref.GetLongField.asFunction<int Function(JObject, JFieldID)>()(
+        obj, fieldID);
+  }
+
+  double GetFloatField(JObject obj, JFieldID fieldID) {
+    return ref.GetFloatField.asFunction<double Function(JObject, JFieldID)>()(
+        obj, fieldID);
+  }
+
+  double GetDoubleField(JObject obj, JFieldID fieldID) {
+    return ref.GetDoubleField.asFunction<double Function(JObject, JFieldID)>()(
+        obj, fieldID);
+  }
+
+  void SetObjectField(JObject obj, JFieldID fieldID, JObject val) {
+    return ref.SetObjectField.asFunction<
+        void Function(JObject, JFieldID, JObject)>()(obj, fieldID, val);
+  }
+
+  void SetBooleanField(JObject obj, JFieldID fieldID, int val) {
+    return ref.SetBooleanField.asFunction<
+        void Function(JObject, JFieldID, int)>()(obj, fieldID, val);
+  }
+
+  void SetByteField(JObject obj, JFieldID fieldID, int val) {
+    return ref.SetByteField.asFunction<void Function(JObject, JFieldID, int)>()(
+        obj, fieldID, val);
+  }
+
+  void SetCharField(JObject obj, JFieldID fieldID, int val) {
+    return ref.SetCharField.asFunction<void Function(JObject, JFieldID, int)>()(
+        obj, fieldID, val);
+  }
+
+  void SetShortField(JObject obj, JFieldID fieldID, int val) {
+    return ref.SetShortField.asFunction<
+        void Function(JObject, JFieldID, int)>()(obj, fieldID, val);
+  }
+
+  void SetIntField(JObject obj, JFieldID fieldID, int val) {
+    return ref.SetIntField.asFunction<void Function(JObject, JFieldID, int)>()(
+        obj, fieldID, val);
+  }
+
+  void SetLongField(JObject obj, JFieldID fieldID, int val) {
+    return ref.SetLongField.asFunction<void Function(JObject, JFieldID, int)>()(
+        obj, fieldID, val);
+  }
+
+  void SetFloatField(JObject obj, JFieldID fieldID, double val) {
+    return ref.SetFloatField.asFunction<
+        void Function(JObject, JFieldID, double)>()(obj, fieldID, val);
+  }
+
+  void SetDoubleField(JObject obj, JFieldID fieldID, double val) {
+    return ref.SetDoubleField.asFunction<
+        void Function(JObject, JFieldID, double)>()(obj, fieldID, val);
+  }
+
+  JMethodID GetStaticMethodID(
+      JClass clazz, ffi.Pointer<ffi.Char> name, ffi.Pointer<ffi.Char> sig) {
+    return ref.GetStaticMethodID.asFunction<
+        JMethodID Function(JClass, ffi.Pointer<ffi.Char>,
+            ffi.Pointer<ffi.Char>)>()(clazz, name, sig);
+  }
+
+  JObject CallStaticObjectMethod(JClass arg1, JMethodID arg2) {
+    return ref.CallStaticObjectMethod.asFunction<
+        JObject Function(JClass, JMethodID)>()(arg1, arg2);
+  }
+
+  JObject CallStaticObjectMethodA(
+      JClass clazz, JMethodID methodID, ffi.Pointer<JValue> args) {
+    return ref.CallStaticObjectMethodA.asFunction<
+        JObject Function(
+            JClass, JMethodID, ffi.Pointer<JValue>)>()(clazz, methodID, args);
+  }
+
+  int CallStaticBooleanMethod(JClass arg1, JMethodID arg2) {
+    return ref.CallStaticBooleanMethod.asFunction<
+        int Function(JClass, JMethodID)>()(arg1, arg2);
+  }
+
+  int CallStaticBooleanMethodA(
+      JClass clazz, JMethodID methodID, ffi.Pointer<JValue> args) {
+    return ref.CallStaticBooleanMethodA.asFunction<
+        int Function(
+            JClass, JMethodID, ffi.Pointer<JValue>)>()(clazz, methodID, args);
+  }
+
+  int CallStaticByteMethod(JClass arg1, JMethodID arg2) {
+    return ref.CallStaticByteMethod.asFunction<
+        int Function(JClass, JMethodID)>()(arg1, arg2);
+  }
+
+  int CallStaticByteMethodA(
+      JClass clazz, JMethodID methodID, ffi.Pointer<JValue> args) {
+    return ref.CallStaticByteMethodA.asFunction<
+        int Function(
+            JClass, JMethodID, ffi.Pointer<JValue>)>()(clazz, methodID, args);
+  }
+
+  int CallStaticCharMethod(JClass arg1, JMethodID arg2) {
+    return ref.CallStaticCharMethod.asFunction<
+        int Function(JClass, JMethodID)>()(arg1, arg2);
+  }
+
+  int CallStaticCharMethodA(
+      JClass clazz, JMethodID methodID, ffi.Pointer<JValue> args) {
+    return ref.CallStaticCharMethodA.asFunction<
+        int Function(
+            JClass, JMethodID, ffi.Pointer<JValue>)>()(clazz, methodID, args);
+  }
+
+  int CallStaticShortMethod(JClass arg1, JMethodID arg2) {
+    return ref.CallStaticShortMethod.asFunction<
+        int Function(JClass, JMethodID)>()(arg1, arg2);
+  }
+
+  int CallStaticShortMethodA(
+      JClass clazz, JMethodID methodID, ffi.Pointer<JValue> args) {
+    return ref.CallStaticShortMethodA.asFunction<
+        int Function(
+            JClass, JMethodID, ffi.Pointer<JValue>)>()(clazz, methodID, args);
+  }
+
+  int CallStaticIntMethod(JClass arg1, JMethodID arg2) {
+    return ref.CallStaticIntMethod.asFunction<
+        int Function(JClass, JMethodID)>()(arg1, arg2);
+  }
+
+  int CallStaticIntMethodA(
+      JClass clazz, JMethodID methodID, ffi.Pointer<JValue> args) {
+    return ref.CallStaticIntMethodA.asFunction<
+        int Function(
+            JClass, JMethodID, ffi.Pointer<JValue>)>()(clazz, methodID, args);
+  }
+
+  int CallStaticLongMethod(JClass arg1, JMethodID arg2) {
+    return ref.CallStaticLongMethod.asFunction<
+        int Function(JClass, JMethodID)>()(arg1, arg2);
+  }
+
+  int CallStaticLongMethodA(
+      JClass clazz, JMethodID methodID, ffi.Pointer<JValue> args) {
+    return ref.CallStaticLongMethodA.asFunction<
+        int Function(
+            JClass, JMethodID, ffi.Pointer<JValue>)>()(clazz, methodID, args);
+  }
+
+  double CallStaticFloatMethod(JClass arg1, JMethodID arg2) {
+    return ref.CallStaticFloatMethod.asFunction<
+        double Function(JClass, JMethodID)>()(arg1, arg2);
+  }
+
+  double CallStaticFloatMethodA(
+      JClass clazz, JMethodID methodID, ffi.Pointer<JValue> args) {
+    return ref.CallStaticFloatMethodA.asFunction<
+        double Function(
+            JClass, JMethodID, ffi.Pointer<JValue>)>()(clazz, methodID, args);
+  }
+
+  double CallStaticDoubleMethod(JClass arg1, JMethodID arg2) {
+    return ref.CallStaticDoubleMethod.asFunction<
+        double Function(JClass, JMethodID)>()(arg1, arg2);
+  }
+
+  double CallStaticDoubleMethodA(
+      JClass clazz, JMethodID methodID, ffi.Pointer<JValue> args) {
+    return ref.CallStaticDoubleMethodA.asFunction<
+        double Function(
+            JClass, JMethodID, ffi.Pointer<JValue>)>()(clazz, methodID, args);
+  }
+
+  void CallStaticVoidMethod(JClass arg1, JMethodID arg2) {
+    return ref.CallStaticVoidMethod.asFunction<
+        void Function(JClass, JMethodID)>()(arg1, arg2);
+  }
+
+  void CallStaticVoidMethodA(
+      JClass clazz, JMethodID methodID, ffi.Pointer<JValue> args) {
+    return ref.CallStaticVoidMethodA.asFunction<
+        void Function(
+            JClass, JMethodID, ffi.Pointer<JValue>)>()(clazz, methodID, args);
+  }
+
+  JFieldID GetStaticFieldID(
+      JClass clazz, ffi.Pointer<ffi.Char> name, ffi.Pointer<ffi.Char> sig) {
+    return ref.GetStaticFieldID.asFunction<
+        JFieldID Function(JClass, ffi.Pointer<ffi.Char>,
+            ffi.Pointer<ffi.Char>)>()(clazz, name, sig);
+  }
+
+  JObject GetStaticObjectField(JClass clazz, JFieldID fieldID) {
+    return ref.GetStaticObjectField.asFunction<
+        JObject Function(JClass, JFieldID)>()(clazz, fieldID);
+  }
+
+  int GetStaticBooleanField(JClass clazz, JFieldID fieldID) {
+    return ref.GetStaticBooleanField.asFunction<
+        int Function(JClass, JFieldID)>()(clazz, fieldID);
+  }
+
+  int GetStaticByteField(JClass clazz, JFieldID fieldID) {
+    return ref.GetStaticByteField.asFunction<int Function(JClass, JFieldID)>()(
+        clazz, fieldID);
+  }
+
+  int GetStaticCharField(JClass clazz, JFieldID fieldID) {
+    return ref.GetStaticCharField.asFunction<int Function(JClass, JFieldID)>()(
+        clazz, fieldID);
+  }
+
+  int GetStaticShortField(JClass clazz, JFieldID fieldID) {
+    return ref.GetStaticShortField.asFunction<int Function(JClass, JFieldID)>()(
+        clazz, fieldID);
+  }
+
+  int GetStaticIntField(JClass clazz, JFieldID fieldID) {
+    return ref.GetStaticIntField.asFunction<int Function(JClass, JFieldID)>()(
+        clazz, fieldID);
+  }
+
+  int GetStaticLongField(JClass clazz, JFieldID fieldID) {
+    return ref.GetStaticLongField.asFunction<int Function(JClass, JFieldID)>()(
+        clazz, fieldID);
+  }
+
+  double GetStaticFloatField(JClass clazz, JFieldID fieldID) {
+    return ref.GetStaticFloatField.asFunction<
+        double Function(JClass, JFieldID)>()(clazz, fieldID);
+  }
+
+  double GetStaticDoubleField(JClass clazz, JFieldID fieldID) {
+    return ref.GetStaticDoubleField.asFunction<
+        double Function(JClass, JFieldID)>()(clazz, fieldID);
+  }
+
+  void SetStaticObjectField(JClass clazz, JFieldID fieldID, JObject val) {
+    return ref.SetStaticObjectField.asFunction<
+        void Function(JClass, JFieldID, JObject)>()(clazz, fieldID, val);
+  }
+
+  void SetStaticBooleanField(JClass clazz, JFieldID fieldID, int val) {
+    return ref.SetStaticBooleanField.asFunction<
+        void Function(JClass, JFieldID, int)>()(clazz, fieldID, val);
+  }
+
+  void SetStaticByteField(JClass clazz, JFieldID fieldID, int val) {
+    return ref.SetStaticByteField.asFunction<
+        void Function(JClass, JFieldID, int)>()(clazz, fieldID, val);
+  }
+
+  void SetStaticCharField(JClass clazz, JFieldID fieldID, int val) {
+    return ref.SetStaticCharField.asFunction<
+        void Function(JClass, JFieldID, int)>()(clazz, fieldID, val);
+  }
+
+  void SetStaticShortField(JClass clazz, JFieldID fieldID, int val) {
+    return ref.SetStaticShortField.asFunction<
+        void Function(JClass, JFieldID, int)>()(clazz, fieldID, val);
+  }
+
+  void SetStaticIntField(JClass clazz, JFieldID fieldID, int val) {
+    return ref.SetStaticIntField.asFunction<
+        void Function(JClass, JFieldID, int)>()(clazz, fieldID, val);
+  }
+
+  void SetStaticLongField(JClass clazz, JFieldID fieldID, int val) {
+    return ref.SetStaticLongField.asFunction<
+        void Function(JClass, JFieldID, int)>()(clazz, fieldID, val);
+  }
+
+  void SetStaticFloatField(JClass clazz, JFieldID fieldID, double val) {
+    return ref.SetStaticFloatField.asFunction<
+        void Function(JClass, JFieldID, double)>()(clazz, fieldID, val);
+  }
+
+  void SetStaticDoubleField(JClass clazz, JFieldID fieldID, double val) {
+    return ref.SetStaticDoubleField.asFunction<
+        void Function(JClass, JFieldID, double)>()(clazz, fieldID, val);
+  }
+
+  JString NewString(ffi.Pointer<JChar> unicodeChars, int len) {
+    return ref.NewString.asFunction<
+        JString Function(ffi.Pointer<JChar>, int)>()(unicodeChars, len);
+  }
+
+  int GetStringLength(JString string) {
+    return ref.GetStringLength.asFunction<int Function(JString)>()(string);
+  }
+
+  ffi.Pointer<JChar> GetStringChars(
+      JString string, ffi.Pointer<JBoolean> isCopy) {
+    return ref.GetStringChars.asFunction<
+        ffi.Pointer<JChar> Function(
+            JString, ffi.Pointer<JBoolean>)>()(string, isCopy);
+  }
+
+  void ReleaseStringChars(JString string, ffi.Pointer<JChar> isCopy) {
+    return ref.ReleaseStringChars.asFunction<
+        void Function(JString, ffi.Pointer<JChar>)>()(string, isCopy);
+  }
+
+  JString NewStringUTF(ffi.Pointer<ffi.Char> bytes) {
+    return ref.NewStringUTF.asFunction<
+        JString Function(ffi.Pointer<ffi.Char>)>()(bytes);
+  }
+
+  int GetStringUTFLength(JString string) {
+    return ref.GetStringUTFLength.asFunction<int Function(JString)>()(string);
+  }
+
+  ffi.Pointer<ffi.Char> GetStringUTFChars(
+      JString string, ffi.Pointer<JBoolean> isCopy) {
+    return ref.GetStringUTFChars.asFunction<
+        ffi.Pointer<ffi.Char> Function(
+            JString, ffi.Pointer<JBoolean>)>()(string, isCopy);
+  }
+
+  void ReleaseStringUTFChars(JString string, ffi.Pointer<ffi.Char> utf) {
+    return ref.ReleaseStringUTFChars.asFunction<
+        void Function(JString, ffi.Pointer<ffi.Char>)>()(string, utf);
+  }
+
+  int GetArrayLength(JArray array) {
+    return ref.GetArrayLength.asFunction<int Function(JArray)>()(array);
+  }
+
+  JObjectArray NewObjectArray(
+      int length, JClass elementClass, JObject initialElement) {
+    return ref.NewObjectArray.asFunction<
+        JObjectArray Function(
+            int, JClass, JObject)>()(length, elementClass, initialElement);
+  }
+
+  JObject GetObjectArrayElement(JObjectArray array, int index) {
+    return ref.GetObjectArrayElement.asFunction<
+        JObject Function(JObjectArray, int)>()(array, index);
+  }
+
+  void SetObjectArrayElement(JObjectArray array, int index, JObject val) {
+    return ref.SetObjectArrayElement.asFunction<
+        void Function(JObjectArray, int, JObject)>()(array, index, val);
+  }
+
+  JBooleanArray NewBooleanArray(int length) {
+    return ref.NewBooleanArray.asFunction<JBooleanArray Function(int)>()(
+        length);
+  }
+
+  JByteArray NewByteArray(int length) {
+    return ref.NewByteArray.asFunction<JByteArray Function(int)>()(length);
+  }
+
+  JCharArray NewCharArray(int length) {
+    return ref.NewCharArray.asFunction<JCharArray Function(int)>()(length);
+  }
+
+  JShortArray NewShortArray(int length) {
+    return ref.NewShortArray.asFunction<JShortArray Function(int)>()(length);
+  }
+
+  JIntArray NewIntArray(int length) {
+    return ref.NewIntArray.asFunction<JIntArray Function(int)>()(length);
+  }
+
+  JLongArray NewLongArray(int length) {
+    return ref.NewLongArray.asFunction<JLongArray Function(int)>()(length);
+  }
+
+  JFloatArray NewFloatArray(int length) {
+    return ref.NewFloatArray.asFunction<JFloatArray Function(int)>()(length);
+  }
+
+  JDoubleArray NewDoubleArray(int length) {
+    return ref.NewDoubleArray.asFunction<JDoubleArray Function(int)>()(length);
+  }
+
+  ffi.Pointer<JBoolean> GetBooleanArrayElements(
+      JBooleanArray array, ffi.Pointer<JBoolean> isCopy) {
+    return ref.GetBooleanArrayElements.asFunction<
+        ffi.Pointer<JBoolean> Function(
+            JBooleanArray, ffi.Pointer<JBoolean>)>()(array, isCopy);
+  }
+
+  ffi.Pointer<JByte> GetByteArrayElements(
+      JByteArray array, ffi.Pointer<JBoolean> isCopy) {
+    return ref.GetByteArrayElements.asFunction<
+        ffi.Pointer<JByte> Function(
+            JByteArray, ffi.Pointer<JBoolean>)>()(array, isCopy);
+  }
+
+  ffi.Pointer<JChar> GetCharArrayElements(
+      JCharArray array, ffi.Pointer<JBoolean> isCopy) {
+    return ref.GetCharArrayElements.asFunction<
+        ffi.Pointer<JChar> Function(
+            JCharArray, ffi.Pointer<JBoolean>)>()(array, isCopy);
+  }
+
+  ffi.Pointer<JShort> GetShortArrayElements(
+      JShortArray array, ffi.Pointer<JBoolean> isCopy) {
+    return ref.GetShortArrayElements.asFunction<
+        ffi.Pointer<JShort> Function(
+            JShortArray, ffi.Pointer<JBoolean>)>()(array, isCopy);
+  }
+
+  ffi.Pointer<JInt> GetIntArrayElements(
+      JIntArray array, ffi.Pointer<JBoolean> isCopy) {
+    return ref.GetIntArrayElements.asFunction<
+        ffi.Pointer<JInt> Function(
+            JIntArray, ffi.Pointer<JBoolean>)>()(array, isCopy);
+  }
+
+  ffi.Pointer<JLong> GetLongArrayElements(
+      JLongArray array, ffi.Pointer<JBoolean> isCopy) {
+    return ref.GetLongArrayElements.asFunction<
+        ffi.Pointer<JLong> Function(
+            JLongArray, ffi.Pointer<JBoolean>)>()(array, isCopy);
+  }
+
+  ffi.Pointer<JFloat> GetFloatArrayElements(
+      JFloatArray array, ffi.Pointer<JBoolean> isCopy) {
+    return ref.GetFloatArrayElements.asFunction<
+        ffi.Pointer<JFloat> Function(
+            JFloatArray, ffi.Pointer<JBoolean>)>()(array, isCopy);
+  }
+
+  ffi.Pointer<JDouble> GetDoubleArrayElements(
+      JDoubleArray array, ffi.Pointer<JBoolean> isCopy) {
+    return ref.GetDoubleArrayElements.asFunction<
+        ffi.Pointer<JDouble> Function(
+            JDoubleArray, ffi.Pointer<JBoolean>)>()(array, isCopy);
+  }
+
+  void ReleaseBooleanArrayElements(
+      JBooleanArray array, ffi.Pointer<JBoolean> elems, int mode) {
+    return ref.ReleaseBooleanArrayElements.asFunction<
+        void Function(
+            JBooleanArray, ffi.Pointer<JBoolean>, int)>()(array, elems, mode);
+  }
+
+  void ReleaseByteArrayElements(
+      JByteArray array, ffi.Pointer<JByte> elems, int mode) {
+    return ref.ReleaseByteArrayElements.asFunction<
+        void Function(
+            JByteArray, ffi.Pointer<JByte>, int)>()(array, elems, mode);
+  }
+
+  void ReleaseCharArrayElements(
+      JCharArray array, ffi.Pointer<JChar> elems, int mode) {
+    return ref.ReleaseCharArrayElements.asFunction<
+        void Function(
+            JCharArray, ffi.Pointer<JChar>, int)>()(array, elems, mode);
+  }
+
+  void ReleaseShortArrayElements(
+      JShortArray array, ffi.Pointer<JShort> elems, int mode) {
+    return ref.ReleaseShortArrayElements.asFunction<
+        void Function(
+            JShortArray, ffi.Pointer<JShort>, int)>()(array, elems, mode);
+  }
+
+  void ReleaseIntArrayElements(
+      JIntArray array, ffi.Pointer<JInt> elems, int mode) {
+    return ref.ReleaseIntArrayElements.asFunction<
+        void Function(JIntArray, ffi.Pointer<JInt>, int)>()(array, elems, mode);
+  }
+
+  void ReleaseLongArrayElements(
+      JLongArray array, ffi.Pointer<JLong> elems, int mode) {
+    return ref.ReleaseLongArrayElements.asFunction<
+        void Function(
+            JLongArray, ffi.Pointer<JLong>, int)>()(array, elems, mode);
+  }
+
+  void ReleaseFloatArrayElements(
+      JFloatArray array, ffi.Pointer<JFloat> elems, int mode) {
+    return ref.ReleaseFloatArrayElements.asFunction<
+        void Function(
+            JFloatArray, ffi.Pointer<JFloat>, int)>()(array, elems, mode);
+  }
+
+  void ReleaseDoubleArrayElements(
+      JDoubleArray array, ffi.Pointer<JDouble> elems, int mode) {
+    return ref.ReleaseDoubleArrayElements.asFunction<
+        void Function(
+            JDoubleArray, ffi.Pointer<JDouble>, int)>()(array, elems, mode);
+  }
+
+  void GetBooleanArrayRegion(
+      JBooleanArray array, int start, int len, ffi.Pointer<JBoolean> buf) {
+    return ref.GetBooleanArrayRegion.asFunction<
+            void Function(JBooleanArray, int, int, ffi.Pointer<JBoolean>)>()(
+        array, start, len, buf);
+  }
+
+  void GetByteArrayRegion(
+      JByteArray array, int start, int len, ffi.Pointer<JByte> buf) {
+    return ref.GetByteArrayRegion.asFunction<
+            void Function(JByteArray, int, int, ffi.Pointer<JByte>)>()(
+        array, start, len, buf);
+  }
+
+  void GetCharArrayRegion(
+      JCharArray array, int start, int len, ffi.Pointer<JChar> buf) {
+    return ref.GetCharArrayRegion.asFunction<
+            void Function(JCharArray, int, int, ffi.Pointer<JChar>)>()(
+        array, start, len, buf);
+  }
+
+  void GetShortArrayRegion(
+      JShortArray array, int start, int len, ffi.Pointer<JShort> buf) {
+    return ref.GetShortArrayRegion.asFunction<
+            void Function(JShortArray, int, int, ffi.Pointer<JShort>)>()(
+        array, start, len, buf);
+  }
+
+  void GetIntArrayRegion(
+      JIntArray array, int start, int len, ffi.Pointer<JInt> buf) {
+    return ref.GetIntArrayRegion.asFunction<
+        void Function(
+            JIntArray, int, int, ffi.Pointer<JInt>)>()(array, start, len, buf);
+  }
+
+  void GetLongArrayRegion(
+      JLongArray array, int start, int len, ffi.Pointer<JLong> buf) {
+    return ref.GetLongArrayRegion.asFunction<
+            void Function(JLongArray, int, int, ffi.Pointer<JLong>)>()(
+        array, start, len, buf);
+  }
+
+  void GetFloatArrayRegion(
+      JFloatArray array, int start, int len, ffi.Pointer<JFloat> buf) {
+    return ref.GetFloatArrayRegion.asFunction<
+            void Function(JFloatArray, int, int, ffi.Pointer<JFloat>)>()(
+        array, start, len, buf);
+  }
+
+  void GetDoubleArrayRegion(
+      JDoubleArray array, int start, int len, ffi.Pointer<JDouble> buf) {
+    return ref.GetDoubleArrayRegion.asFunction<
+            void Function(JDoubleArray, int, int, ffi.Pointer<JDouble>)>()(
+        array, start, len, buf);
+  }
+
+  void SetBooleanArrayRegion(
+      JBooleanArray array, int start, int len, ffi.Pointer<JBoolean> buf) {
+    return ref.SetBooleanArrayRegion.asFunction<
+            void Function(JBooleanArray, int, int, ffi.Pointer<JBoolean>)>()(
+        array, start, len, buf);
+  }
+
+  void SetByteArrayRegion(
+      JByteArray array, int start, int len, ffi.Pointer<JByte> buf) {
+    return ref.SetByteArrayRegion.asFunction<
+            void Function(JByteArray, int, int, ffi.Pointer<JByte>)>()(
+        array, start, len, buf);
+  }
+
+  void SetCharArrayRegion(
+      JCharArray array, int start, int len, ffi.Pointer<JChar> buf) {
+    return ref.SetCharArrayRegion.asFunction<
+            void Function(JCharArray, int, int, ffi.Pointer<JChar>)>()(
+        array, start, len, buf);
+  }
+
+  void SetShortArrayRegion(
+      JShortArray array, int start, int len, ffi.Pointer<JShort> buf) {
+    return ref.SetShortArrayRegion.asFunction<
+            void Function(JShortArray, int, int, ffi.Pointer<JShort>)>()(
+        array, start, len, buf);
+  }
+
+  void SetIntArrayRegion(
+      JIntArray array, int start, int len, ffi.Pointer<JInt> buf) {
+    return ref.SetIntArrayRegion.asFunction<
+        void Function(
+            JIntArray, int, int, ffi.Pointer<JInt>)>()(array, start, len, buf);
+  }
+
+  void SetLongArrayRegion(
+      JLongArray array, int start, int len, ffi.Pointer<JLong> buf) {
+    return ref.SetLongArrayRegion.asFunction<
+            void Function(JLongArray, int, int, ffi.Pointer<JLong>)>()(
+        array, start, len, buf);
+  }
+
+  void SetFloatArrayRegion(
+      JFloatArray array, int start, int len, ffi.Pointer<JFloat> buf) {
+    return ref.SetFloatArrayRegion.asFunction<
+            void Function(JFloatArray, int, int, ffi.Pointer<JFloat>)>()(
+        array, start, len, buf);
+  }
+
+  void SetDoubleArrayRegion(
+      JDoubleArray array, int start, int len, ffi.Pointer<JDouble> buf) {
+    return ref.SetDoubleArrayRegion.asFunction<
+            void Function(JDoubleArray, int, int, ffi.Pointer<JDouble>)>()(
+        array, start, len, buf);
+  }
+
+  int RegisterNatives(
+      JClass clazz, ffi.Pointer<JNINativeMethod> methods, int nMethods) {
+    return ref.RegisterNatives.asFunction<
+            int Function(JClass, ffi.Pointer<JNINativeMethod>, int)>()(
+        clazz, methods, nMethods);
+  }
+
+  int UnregisterNatives(JClass clazz) {
+    return ref.UnregisterNatives.asFunction<int Function(JClass)>()(clazz);
+  }
+
+  int MonitorEnter(JObject obj) {
+    return ref.MonitorEnter.asFunction<int Function(JObject)>()(obj);
+  }
+
+  int MonitorExit(JObject obj) {
+    return ref.MonitorExit.asFunction<int Function(JObject)>()(obj);
+  }
+
+  int GetJavaVM(ffi.Pointer<ffi.Pointer<JavaVM>> vm) {
+    return ref.GetJavaVM.asFunction<
+        int Function(ffi.Pointer<ffi.Pointer<JavaVM>>)>()(vm);
+  }
+
+  void GetStringRegion(
+      JString str, int start, int len, ffi.Pointer<JChar> buf) {
+    return ref.GetStringRegion.asFunction<
+        void Function(
+            JString, int, int, ffi.Pointer<JChar>)>()(str, start, len, buf);
+  }
+
+  void GetStringUTFRegion(
+      JString str, int start, int len, ffi.Pointer<ffi.Char> buf) {
+    return ref.GetStringUTFRegion.asFunction<
+        void Function(
+            JString, int, int, ffi.Pointer<ffi.Char>)>()(str, start, len, buf);
+  }
+
+  ffi.Pointer<ffi.Void> GetPrimitiveArrayCritical(
+      JArray array, ffi.Pointer<JBoolean> isCopy) {
+    return ref.GetPrimitiveArrayCritical.asFunction<
+        ffi.Pointer<ffi.Void> Function(
+            JArray, ffi.Pointer<JBoolean>)>()(array, isCopy);
+  }
+
+  void ReleasePrimitiveArrayCritical(
+      JArray array, ffi.Pointer<ffi.Void> carray, int mode) {
+    return ref.ReleasePrimitiveArrayCritical.asFunction<
+        void Function(
+            JArray, ffi.Pointer<ffi.Void>, int)>()(array, carray, mode);
+  }
+
+  ffi.Pointer<JChar> GetStringCritical(
+      JString str, ffi.Pointer<JBoolean> isCopy) {
+    return ref.GetStringCritical.asFunction<
+        ffi.Pointer<JChar> Function(
+            JString, ffi.Pointer<JBoolean>)>()(str, isCopy);
+  }
+
+  void ReleaseStringCritical(JString str, ffi.Pointer<JChar> carray) {
+    return ref.ReleaseStringCritical.asFunction<
+        void Function(JString, ffi.Pointer<JChar>)>()(str, carray);
+  }
+
+  JWeak NewWeakGlobalRef(JObject obj) {
+    return ref.NewWeakGlobalRef.asFunction<JWeak Function(JObject)>()(obj);
+  }
+
+  void DeleteWeakGlobalRef(JWeak obj) {
+    return ref.DeleteWeakGlobalRef.asFunction<void Function(JWeak)>()(obj);
+  }
+
+  int ExceptionCheck() {
+    return ref.ExceptionCheck.asFunction<int Function()>()();
+  }
+
+  JObject NewDirectByteBuffer(ffi.Pointer<ffi.Void> address, int capacity) {
+    return ref.NewDirectByteBuffer.asFunction<
+        JObject Function(ffi.Pointer<ffi.Void>, int)>()(address, capacity);
+  }
+
+  ffi.Pointer<ffi.Void> GetDirectBufferAddress(JObject buf) {
+    return ref.GetDirectBufferAddress.asFunction<
+        ffi.Pointer<ffi.Void> Function(JObject)>()(buf);
+  }
+
+  int GetDirectBufferCapacity(JObject buf) {
+    return ref.GetDirectBufferCapacity.asFunction<int Function(JObject)>()(buf);
+  }
+
+  int GetObjectRefType(JObject obj) {
+    return ref.GetObjectRefType.asFunction<int Function(JObject)>()(obj);
+  }
+}
+
 const int JNI_FALSE = 0;
 
 const int JNI_TRUE = 1;
diff --git a/pkgs/jni/pubspec.yaml b/pkgs/jni/pubspec.yaml
index 5d057a4..2a65d6b 100644
--- a/pkgs/jni/pubspec.yaml
+++ b/pkgs/jni/pubspec.yaml
@@ -1,16 +1,13 @@
 name: jni
 description: Library to access JNI from dart and flutter
-version: 0.0.1
+version: 0.1.0
 homepage: https://github.com/dart-lang/jnigen
 
 environment:
   sdk: ">=2.17.1 <3.0.0"
-  #flutter: ">=2.11.0"
+  flutter: ">=2.11.0"
 
 dependencies:
-  ## Commented out to support dart standalone
-  # flutter:
-    #  sdk: flutter
   plugin_platform_interface: ^2.0.2
   ffi: ^2.0.0
   path: ^1.8.0
@@ -18,21 +15,10 @@
   args: ^2.3.1
 
 dev_dependencies:
-  ## Temporarily linking to a personal fork of ffigen
-  ## so that changes in FFIGen can be reviewed.
-  #
-  ## If this is vendored directly, it will not be possible to
-  ## review changes in ffigen.
-  #
-  ## Will be removed in a later PR by vendoring the patched ffigen.
-  #
   ## After running `dart run ffigen --config ffigen.yaml` there
   ## should be no changes.
-  ##
-  ## TODO: vendor ffigen fork
   ffigen:
-    git: https://github.com/mahesh-hegde/ffigen_patch_jni.git
-    #path: third_party/ffigen_patch
+    path: third_party/ffigen_patch_jni
   flutter_lints: ^2.0.0
   test: ^1.21.1
 
@@ -48,6 +34,6 @@
         ffiPlugin: true
       android:
         ffiPlugin: true
-        package: dev.dart.jni
+        package: com.github.dart_lang.jni
         pluginClass: JniPlugin
 
diff --git a/pkgs/jni/src/CMakeLists.txt b/pkgs/jni/src/CMakeLists.txt
index e9cfd80..3b4739e 100644
--- a/pkgs/jni/src/CMakeLists.txt
+++ b/pkgs/jni/src/CMakeLists.txt
@@ -7,6 +7,7 @@
 
 add_library(jni SHARED
   "dartjni.c"
+  "global_jni_env.c"
 )
 
 set_target_properties(jni PROPERTIES
diff --git a/pkgs/jni/src/dartjni.c b/pkgs/jni/src/dartjni.c
index 8ba5a89..d30689d 100644
--- a/pkgs/jni/src/dartjni.c
+++ b/pkgs/jni/src/dartjni.c
@@ -7,39 +7,27 @@
 
 #include "dartjni.h"
 
-struct jni_context jni = {NULL, NULL, NULL, NULL, NULL};
+JniContext jni = {NULL, NULL, NULL, NULL, NULL};
 
 thread_local JNIEnv *jniEnv = NULL;
 
-int jni_log_level = JNI_INFO;
-
-FFI_PLUGIN_EXPORT
-void SetJNILogging(int level) {
-	jni_log_level = level;
-}
-
-void jni_log(int level, const char *format, ...) {
-	// TODO(#16): This is not working.
-	if (level >= jni_log_level) {
-		va_list args;
-        va_start(args, format);
-#ifdef __ANDROID__
-		__android_log_print(level, JNI_LOG_TAG, format, args);
-#else
-		// fprintf(stderr, "%s: ", JNI_LOG_TAG);
-		vfprintf(stderr, format, args);
-#endif
-        va_end(args);
-	}
-}
-
-FFI_PLUGIN_EXPORT struct jni_context GetJniContext() { return jni; }
+FFI_PLUGIN_EXPORT JniContext GetJniContext() { return jni; }
 
 /// Get JVM associated with current process.
 /// Returns NULL if no JVM is running.
 FFI_PLUGIN_EXPORT
 JavaVM *GetJavaVM() { return jni.jvm; }
 
+/// Destroys the JVM.
+///
+/// Returns 0 on success and appropriate error code on failure.
+FFI_PLUGIN_EXPORT
+int DestroyJavaVM() {
+	int result = (*jni.jvm)->DestroyJavaVM(jni.jvm);
+	jni.jvm = NULL;
+	return result;
+}
+
 /// Returns Application classLoader (on Android), 
 /// which can be used to load application and platform classes.
 /// ...
@@ -50,9 +38,8 @@
 	return (*jniEnv)->NewLocalRef(jniEnv, jni.classLoader);
 }
 
-
-/// Load class through platform-specific mechanism
-/// ...
+/// Load class through platform-specific mechanism.
+///
 /// Currently uses application classloader on android,
 /// and JNIEnv->FindClass on other platforms.
 FFI_PLUGIN_EXPORT
@@ -60,7 +47,7 @@
 	jclass cls = NULL;
 	attach_thread();
 	load_class(&cls, name);
-	return cls;
+	return to_global_ref(cls);
 };
 
 FFI_PLUGIN_EXPORT
@@ -77,42 +64,19 @@
 /// On other platforms, NULL is returned.
 FFI_PLUGIN_EXPORT
 jobject GetApplicationContext() {
-	// Any publicly callable method
-	// can be called from an unattached thread.
-	// I Learned this the hard way.
 	attach_thread();
-	return (*jniEnv)->NewLocalRef(jniEnv, jni.appContext);
+	return (*jniEnv)->NewGlobalRef(jniEnv, jni.appContext);
 }
 
 /// Returns current activity of the app
 FFI_PLUGIN_EXPORT
 jobject GetCurrentActivity() {
 	attach_thread();
-	return (*jniEnv)->NewLocalRef(jniEnv, jni.currentActivity);
-}
-
-FFI_PLUGIN_EXPORT
-jstring ToJavaString(char *str) {
-	attach_thread();
-	jstring s = (*jniEnv)->NewStringUTF(jniEnv, str);
-	jstring g = (*jniEnv)->NewGlobalRef(jniEnv, s);
-	(*jniEnv)->DeleteLocalRef(jniEnv, s);
-	return g;
-}
-
-FFI_PLUGIN_EXPORT
-const char *GetJavaStringChars(jstring jstr) {
-	const char *buf = (*jniEnv)->GetStringUTFChars(jniEnv, jstr, NULL);
-	return buf;
-}
-
-FFI_PLUGIN_EXPORT
-void ReleaseJavaStringChars(jstring jstr, const char *buf) {
-	(*jniEnv)->ReleaseStringUTFChars(jniEnv, jstr, buf);
+	return (*jniEnv)->NewGlobalRef(jniEnv, jni.currentActivity);
 }
 
 #ifdef __ANDROID__
-JNIEXPORT void JNICALL Java_dev_dart_jni_JniPlugin_initializeJni(
+JNIEXPORT void JNICALL Java_com_github_dart_1lang_jni_JniPlugin_initializeJni(
     JNIEnv *env, jobject obj, jobject appContext, jobject classLoader) {
 	jniEnv = env;
 	(*env)->GetJavaVM(env, &jni.jvm);
@@ -124,7 +88,7 @@
 	                        "(Ljava/lang/String;)Ljava/lang/Class;");
 }
 
-JNIEXPORT void JNICALL Java_dev_dart_jni_JniPlugin_setJniActivity(JNIEnv *env, jobject obj, jobject activity, jobject context) {
+JNIEXPORT void JNICALL Java_com_github_dart_1lang_jni_JniPlugin_setJniActivity(JNIEnv *env, jobject obj, jobject activity, jobject context) {
 	jniEnv = env;
 	if (jni.currentActivity != NULL) {
 		(*env)->DeleteGlobalRef(env, jni.currentActivity);
@@ -152,7 +116,6 @@
 		vmArgs.ignoreUnrecognized = JNI_TRUE;
 		initArgs = &vmArgs;
 	}
-	jni_log(JNI_DEBUG, "JNI Version: %d\n", initArgs->version);
 	const long flag =
 	    JNI_CreateJavaVM(&jni.jvm, __ENVP_CAST &jniEnv, initArgs);
 	if (flag == JNI_ERR) {
diff --git a/pkgs/jni/src/dartjni.h b/pkgs/jni/src/dartjni.h
index cd94b15..0ce5069 100644
--- a/pkgs/jni/src/dartjni.h
+++ b/pkgs/jni/src/dartjni.h
@@ -2,6 +2,8 @@
 // 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.
 
+#pragma once
+
 #include <jni.h>
 #include <stdint.h>
 #include <stdio.h>
@@ -38,17 +40,17 @@
 #define __ENVP_CAST (void **)
 #endif
 
-struct jni_context {
+typedef struct JniContext {
 	JavaVM *jvm;
 	jobject classLoader;
 	jmethodID loadClassMethod;
 	jobject currentActivity;
 	jobject appContext;
-};
+} JniContext;
 
 extern thread_local JNIEnv *jniEnv;
 
-extern struct jni_context jni;
+extern JniContext jni;
 
 enum DartJniLogLevel {
 	JNI_VERBOSE = 2,
@@ -58,10 +60,25 @@
 	JNI_ERROR
 };
 
-FFI_PLUGIN_EXPORT struct jni_context GetJniContext();
+enum JniType {
+	boolType = 0,
+	byteType = 1,
+	shortType = 2,
+	charType = 3,
+	intType = 4,
+	longType = 5,
+	floatType = 6,
+	doubleType = 7,
+	objectType = 8,
+	voidType = 9,
+};
+
+FFI_PLUGIN_EXPORT JniContext GetJniContext();
 
 FFI_PLUGIN_EXPORT JavaVM *GetJavaVM(void);
 
+FFI_PLUGIN_EXPORT int DestroyJavaVM();
+
 FFI_PLUGIN_EXPORT JNIEnv *GetJniEnv(void);
 
 FFI_PLUGIN_EXPORT JNIEnv *SpawnJvm(JavaVMInitArgs *args);
@@ -74,26 +91,16 @@
 
 FFI_PLUGIN_EXPORT jobject GetCurrentActivity(void);
 
-FFI_PLUGIN_EXPORT void SetJNILogging(int level);
+/// For use by jni_gen's generated code
+/// don't use these.
 
-FFI_PLUGIN_EXPORT jstring ToJavaString(char *str);
-
-FFI_PLUGIN_EXPORT const char *GetJavaStringChars(jstring jstr);
-
-FFI_PLUGIN_EXPORT void ReleaseJavaStringChars(jstring jstr, const char *buf);
-
-// These 2 are the function pointer variables defined and exported by
-// the generated C files.
-//
-// initGeneratedLibrary function in Jni class will set these to
-// corresponding functions to the implementations from `dartjni` base library
-// which initializes and manages the JNI.
-extern struct jni_context (*context_getter)(void);
+// these 2 fn ptr vars will be defined by generated code library
+extern JniContext (*context_getter)(void);
 extern JNIEnv *(*env_getter)(void);
 
-// This function will be exported by generated code library and will set the
-// above 2 variables.
-FFI_PLUGIN_EXPORT void setJniGetters(struct jni_context (*cg)(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),
 		JNIEnv *(*eg)(void));
 
 // `static inline` because `inline` doesn't work, it may still not
@@ -101,6 +108,7 @@
 //
 // 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) {
 #ifdef __ANDROID__
 	jstring className = (*jniEnv)->NewStringUTF(jniEnv, name);
diff --git a/pkgs/jni/src/global_jni_env.c b/pkgs/jni/src/global_jni_env.c
new file mode 100644
index 0000000..d7da0af
--- /dev/null
+++ b/pkgs/jni/src/global_jni_env.c
@@ -0,0 +1,1188 @@
+// 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.
+
+#include "global_jni_env.h"
+jint globalEnv_GetVersion() {
+    attach_thread();
+    return (*jniEnv)->GetVersion(jniEnv);
+}
+
+jclass globalEnv_DefineClass(const char * name, jobject loader, const jbyte * buf, jsize bufLen) {
+    attach_thread();
+    return to_global_ref((*jniEnv)->DefineClass(jniEnv, name, loader, buf, bufLen));
+}
+
+jclass globalEnv_FindClass(const char * name) {
+    attach_thread();
+    return to_global_ref((*jniEnv)->FindClass(jniEnv, name));
+}
+
+jmethodID globalEnv_FromReflectedMethod(jobject method) {
+    attach_thread();
+    return (*jniEnv)->FromReflectedMethod(jniEnv, method);
+}
+
+jfieldID globalEnv_FromReflectedField(jobject field) {
+    attach_thread();
+    return (*jniEnv)->FromReflectedField(jniEnv, field);
+}
+
+jobject globalEnv_ToReflectedMethod(jclass cls, jmethodID methodId, jboolean isStatic) {
+    attach_thread();
+    return to_global_ref((*jniEnv)->ToReflectedMethod(jniEnv, cls, methodId, isStatic));
+}
+
+jclass globalEnv_GetSuperclass(jclass clazz) {
+    attach_thread();
+    return to_global_ref((*jniEnv)->GetSuperclass(jniEnv, clazz));
+}
+
+jboolean globalEnv_IsAssignableFrom(jclass clazz1, jclass clazz2) {
+    attach_thread();
+    return (*jniEnv)->IsAssignableFrom(jniEnv, clazz1, clazz2);
+}
+
+jobject globalEnv_ToReflectedField(jclass cls, jfieldID fieldID, jboolean isStatic) {
+    attach_thread();
+    return to_global_ref((*jniEnv)->ToReflectedField(jniEnv, cls, fieldID, isStatic));
+}
+
+jint globalEnv_Throw(jthrowable obj) {
+    attach_thread();
+    return (*jniEnv)->Throw(jniEnv, obj);
+}
+
+jint globalEnv_ThrowNew(jclass clazz, const char * message) {
+    attach_thread();
+    return (*jniEnv)->ThrowNew(jniEnv, clazz, message);
+}
+
+jthrowable globalEnv_ExceptionOccurred() {
+    attach_thread();
+    return to_global_ref((*jniEnv)->ExceptionOccurred(jniEnv));
+}
+
+void globalEnv_ExceptionDescribe() {
+    attach_thread();
+    (*jniEnv)->ExceptionDescribe(jniEnv);
+}
+
+void globalEnv_ExceptionClear() {
+    attach_thread();
+    (*jniEnv)->ExceptionClear(jniEnv);
+}
+
+void globalEnv_FatalError(const char * msg) {
+    attach_thread();
+    (*jniEnv)->FatalError(jniEnv, msg);
+}
+
+jint globalEnv_PushLocalFrame(jint capacity) {
+    attach_thread();
+    return (*jniEnv)->PushLocalFrame(jniEnv, capacity);
+}
+
+jobject globalEnv_PopLocalFrame(jobject result) {
+    attach_thread();
+    return to_global_ref((*jniEnv)->PopLocalFrame(jniEnv, result));
+}
+
+jobject globalEnv_NewGlobalRef(jobject obj) {
+    attach_thread();
+    return to_global_ref((*jniEnv)->NewGlobalRef(jniEnv, obj));
+}
+
+void globalEnv_DeleteGlobalRef(jobject globalRef) {
+    attach_thread();
+    (*jniEnv)->DeleteGlobalRef(jniEnv, globalRef);
+}
+
+jboolean globalEnv_IsSameObject(jobject ref1, jobject ref2) {
+    attach_thread();
+    return (*jniEnv)->IsSameObject(jniEnv, ref1, ref2);
+}
+
+jint globalEnv_EnsureLocalCapacity(jint capacity) {
+    attach_thread();
+    return (*jniEnv)->EnsureLocalCapacity(jniEnv, capacity);
+}
+
+jobject globalEnv_AllocObject(jclass clazz) {
+    attach_thread();
+    return to_global_ref((*jniEnv)->AllocObject(jniEnv, clazz));
+}
+
+jobject globalEnv_NewObject(jclass arg1, jmethodID arg2) {
+    attach_thread();
+    return to_global_ref((*jniEnv)->NewObject(jniEnv, arg1, arg2));
+}
+
+jobject globalEnv_NewObjectA(jclass clazz, jmethodID methodID, const jvalue * args) {
+    attach_thread();
+    return to_global_ref((*jniEnv)->NewObjectA(jniEnv, clazz, methodID, args));
+}
+
+jclass globalEnv_GetObjectClass(jobject obj) {
+    attach_thread();
+    return to_global_ref((*jniEnv)->GetObjectClass(jniEnv, obj));
+}
+
+jboolean globalEnv_IsInstanceOf(jobject obj, jclass clazz) {
+    attach_thread();
+    return (*jniEnv)->IsInstanceOf(jniEnv, obj, clazz);
+}
+
+jmethodID globalEnv_GetMethodID(jclass clazz, const char * name, const char * sig) {
+    attach_thread();
+    return (*jniEnv)->GetMethodID(jniEnv, clazz, name, sig);
+}
+
+jobject globalEnv_CallObjectMethod(jobject arg1, jmethodID arg2) {
+    attach_thread();
+    return to_global_ref((*jniEnv)->CallObjectMethod(jniEnv, arg1, arg2));
+}
+
+jobject globalEnv_CallObjectMethodA(jobject obj, jmethodID methodID, const jvalue * args) {
+    attach_thread();
+    return to_global_ref((*jniEnv)->CallObjectMethodA(jniEnv, obj, methodID, args));
+}
+
+jboolean globalEnv_CallBooleanMethod(jobject arg1, jmethodID arg2) {
+    attach_thread();
+    return (*jniEnv)->CallBooleanMethod(jniEnv, arg1, arg2);
+}
+
+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, jmethodID methodID, const jvalue * args) {
+    attach_thread();
+    return (*jniEnv)->CallDoubleMethodA(jniEnv, obj, methodID, args);
+}
+
+void globalEnv_CallVoidMethod(jobject arg1, jmethodID arg2) {
+    attach_thread();
+    (*jniEnv)->CallVoidMethod(jniEnv, arg1, arg2);
+}
+
+void globalEnv_CallVoidMethodA(jobject obj, jmethodID methodID, const jvalue * args) {
+    attach_thread();
+    (*jniEnv)->CallVoidMethodA(jniEnv, obj, methodID, args);
+}
+
+jobject globalEnv_CallNonvirtualObjectMethod(jobject arg1, jclass arg2, jmethodID arg3) {
+    attach_thread();
+    return to_global_ref((*jniEnv)->CallNonvirtualObjectMethod(jniEnv, arg1, arg2, arg3));
+}
+
+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, jclass clazz, jmethodID methodID, const jvalue * args) {
+    attach_thread();
+    return (*jniEnv)->CallNonvirtualBooleanMethodA(jniEnv, obj, clazz, methodID, args);
+}
+
+jbyte globalEnv_CallNonvirtualByteMethod(jobject arg1, jclass arg2, jmethodID arg3) {
+    attach_thread();
+    return (*jniEnv)->CallNonvirtualByteMethod(jniEnv, arg1, arg2, arg3);
+}
+
+jbyte globalEnv_CallNonvirtualByteMethodA(jobject obj, jclass clazz, jmethodID methodID, const jvalue * args) {
+    attach_thread();
+    return (*jniEnv)->CallNonvirtualByteMethodA(jniEnv, obj, clazz, methodID, args);
+}
+
+jchar globalEnv_CallNonvirtualCharMethod(jobject arg1, jclass arg2, jmethodID arg3) {
+    attach_thread();
+    return (*jniEnv)->CallNonvirtualCharMethod(jniEnv, arg1, arg2, arg3);
+}
+
+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, jclass clazz, jmethodID methodID, const jvalue * args) {
+    attach_thread();
+    return (*jniEnv)->CallNonvirtualDoubleMethodA(jniEnv, obj, clazz, methodID, args);
+}
+
+void globalEnv_CallNonvirtualVoidMethod(jobject arg1, jclass arg2, jmethodID arg3) {
+    attach_thread();
+    (*jniEnv)->CallNonvirtualVoidMethod(jniEnv, arg1, arg2, arg3);
+}
+
+void globalEnv_CallNonvirtualVoidMethodA(jobject obj, jclass clazz, jmethodID methodID, const jvalue * args) {
+    attach_thread();
+    (*jniEnv)->CallNonvirtualVoidMethodA(jniEnv, obj, clazz, methodID, args);
+}
+
+jfieldID globalEnv_GetFieldID(jclass clazz, const char * name, const char * sig) {
+    attach_thread();
+    return (*jniEnv)->GetFieldID(jniEnv, clazz, name, sig);
+}
+
+jobject globalEnv_GetObjectField(jobject obj, jfieldID fieldID) {
+    attach_thread();
+    return to_global_ref((*jniEnv)->GetObjectField(jniEnv, obj, fieldID));
+}
+
+jboolean globalEnv_GetBooleanField(jobject obj, jfieldID fieldID) {
+    attach_thread();
+    return (*jniEnv)->GetBooleanField(jniEnv, obj, fieldID);
+}
+
+jbyte globalEnv_GetByteField(jobject obj, jfieldID fieldID) {
+    attach_thread();
+    return (*jniEnv)->GetByteField(jniEnv, obj, fieldID);
+}
+
+jchar globalEnv_GetCharField(jobject obj, jfieldID fieldID) {
+    attach_thread();
+    return (*jniEnv)->GetCharField(jniEnv, obj, fieldID);
+}
+
+jshort globalEnv_GetShortField(jobject obj, jfieldID fieldID) {
+    attach_thread();
+    return (*jniEnv)->GetShortField(jniEnv, obj, fieldID);
+}
+
+jint globalEnv_GetIntField(jobject obj, jfieldID fieldID) {
+    attach_thread();
+    return (*jniEnv)->GetIntField(jniEnv, obj, fieldID);
+}
+
+jlong globalEnv_GetLongField(jobject obj, jfieldID fieldID) {
+    attach_thread();
+    return (*jniEnv)->GetLongField(jniEnv, obj, fieldID);
+}
+
+jfloat globalEnv_GetFloatField(jobject obj, jfieldID fieldID) {
+    attach_thread();
+    return (*jniEnv)->GetFloatField(jniEnv, obj, fieldID);
+}
+
+jdouble globalEnv_GetDoubleField(jobject obj, jfieldID fieldID) {
+    attach_thread();
+    return (*jniEnv)->GetDoubleField(jniEnv, obj, fieldID);
+}
+
+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, jfieldID fieldID, jobject val) {
+    attach_thread();
+    (*jniEnv)->SetStaticObjectField(jniEnv, clazz, fieldID, val);
+}
+
+void globalEnv_SetStaticBooleanField(jclass clazz, jfieldID fieldID, jboolean val) {
+    attach_thread();
+    (*jniEnv)->SetStaticBooleanField(jniEnv, clazz, fieldID, val);
+}
+
+void globalEnv_SetStaticByteField(jclass clazz, jfieldID fieldID, jbyte val) {
+    attach_thread();
+    (*jniEnv)->SetStaticByteField(jniEnv, clazz, fieldID, val);
+}
+
+void globalEnv_SetStaticCharField(jclass clazz, jfieldID fieldID, jchar val) {
+    attach_thread();
+    (*jniEnv)->SetStaticCharField(jniEnv, clazz, fieldID, val);
+}
+
+void globalEnv_SetStaticShortField(jclass clazz, jfieldID fieldID, jshort val) {
+    attach_thread();
+    (*jniEnv)->SetStaticShortField(jniEnv, clazz, fieldID, val);
+}
+
+void globalEnv_SetStaticIntField(jclass clazz, jfieldID fieldID, jint val) {
+    attach_thread();
+    (*jniEnv)->SetStaticIntField(jniEnv, clazz, fieldID, val);
+}
+
+void globalEnv_SetStaticLongField(jclass clazz, jfieldID fieldID, jlong val) {
+    attach_thread();
+    (*jniEnv)->SetStaticLongField(jniEnv, clazz, fieldID, val);
+}
+
+void globalEnv_SetStaticFloatField(jclass clazz, jfieldID fieldID, jfloat val) {
+    attach_thread();
+    (*jniEnv)->SetStaticFloatField(jniEnv, clazz, fieldID, val);
+}
+
+void globalEnv_SetStaticDoubleField(jclass clazz, jfieldID fieldID, jdouble val) {
+    attach_thread();
+    (*jniEnv)->SetStaticDoubleField(jniEnv, clazz, fieldID, val);
+}
+
+jstring globalEnv_NewString(const jchar * unicodeChars, jsize len) {
+    attach_thread();
+    return to_global_ref((*jniEnv)->NewString(jniEnv, unicodeChars, len));
+}
+
+jsize globalEnv_GetStringLength(jstring string) {
+    attach_thread();
+    return (*jniEnv)->GetStringLength(jniEnv, string);
+}
+
+const jchar * globalEnv_GetStringChars(jstring string, jboolean * isCopy) {
+    attach_thread();
+    return (*jniEnv)->GetStringChars(jniEnv, string, isCopy);
+}
+
+void globalEnv_ReleaseStringChars(jstring string, const jchar * isCopy) {
+    attach_thread();
+    (*jniEnv)->ReleaseStringChars(jniEnv, string, isCopy);
+}
+
+jstring globalEnv_NewStringUTF(const char * bytes) {
+    attach_thread();
+    return to_global_ref((*jniEnv)->NewStringUTF(jniEnv, bytes));
+}
+
+jsize globalEnv_GetStringUTFLength(jstring string) {
+    attach_thread();
+    return (*jniEnv)->GetStringUTFLength(jniEnv, string);
+}
+
+const char * globalEnv_GetStringUTFChars(jstring string, jboolean * isCopy) {
+    attach_thread();
+    return (*jniEnv)->GetStringUTFChars(jniEnv, string, isCopy);
+}
+
+void globalEnv_ReleaseStringUTFChars(jstring string, const char * utf) {
+    attach_thread();
+    (*jniEnv)->ReleaseStringUTFChars(jniEnv, string, utf);
+}
+
+jsize globalEnv_GetArrayLength(jarray array) {
+    attach_thread();
+    return (*jniEnv)->GetArrayLength(jniEnv, array);
+}
+
+jobjectArray globalEnv_NewObjectArray(jsize length, jclass elementClass, jobject initialElement) {
+    attach_thread();
+    return to_global_ref((*jniEnv)->NewObjectArray(jniEnv, length, elementClass, initialElement));
+}
+
+jobject globalEnv_GetObjectArrayElement(jobjectArray array, jsize index) {
+    attach_thread();
+    return to_global_ref((*jniEnv)->GetObjectArrayElement(jniEnv, array, index));
+}
+
+void globalEnv_SetObjectArrayElement(jobjectArray array, jsize index, jobject val) {
+    attach_thread();
+    (*jniEnv)->SetObjectArrayElement(jniEnv, array, index, val);
+}
+
+jbooleanArray globalEnv_NewBooleanArray(jsize length) {
+    attach_thread();
+    return to_global_ref((*jniEnv)->NewBooleanArray(jniEnv, length));
+}
+
+jbyteArray globalEnv_NewByteArray(jsize length) {
+    attach_thread();
+    return to_global_ref((*jniEnv)->NewByteArray(jniEnv, length));
+}
+
+jcharArray globalEnv_NewCharArray(jsize length) {
+    attach_thread();
+    return to_global_ref((*jniEnv)->NewCharArray(jniEnv, length));
+}
+
+jshortArray globalEnv_NewShortArray(jsize length) {
+    attach_thread();
+    return to_global_ref((*jniEnv)->NewShortArray(jniEnv, length));
+}
+
+jintArray globalEnv_NewIntArray(jsize length) {
+    attach_thread();
+    return to_global_ref((*jniEnv)->NewIntArray(jniEnv, length));
+}
+
+jlongArray globalEnv_NewLongArray(jsize length) {
+    attach_thread();
+    return to_global_ref((*jniEnv)->NewLongArray(jniEnv, length));
+}
+
+jfloatArray globalEnv_NewFloatArray(jsize length) {
+    attach_thread();
+    return to_global_ref((*jniEnv)->NewFloatArray(jniEnv, length));
+}
+
+jdoubleArray globalEnv_NewDoubleArray(jsize length) {
+    attach_thread();
+    return to_global_ref((*jniEnv)->NewDoubleArray(jniEnv, length));
+}
+
+jboolean * globalEnv_GetBooleanArrayElements(jbooleanArray array, jboolean * isCopy) {
+    attach_thread();
+    return (*jniEnv)->GetBooleanArrayElements(jniEnv, array, isCopy);
+}
+
+jbyte * globalEnv_GetByteArrayElements(jbyteArray array, jboolean * isCopy) {
+    attach_thread();
+    return (*jniEnv)->GetByteArrayElements(jniEnv, array, isCopy);
+}
+
+jchar * globalEnv_GetCharArrayElements(jcharArray array, jboolean * isCopy) {
+    attach_thread();
+    return (*jniEnv)->GetCharArrayElements(jniEnv, array, isCopy);
+}
+
+jshort * globalEnv_GetShortArrayElements(jshortArray array, jboolean * isCopy) {
+    attach_thread();
+    return (*jniEnv)->GetShortArrayElements(jniEnv, array, isCopy);
+}
+
+jint * globalEnv_GetIntArrayElements(jintArray array, jboolean * isCopy) {
+    attach_thread();
+    return (*jniEnv)->GetIntArrayElements(jniEnv, array, isCopy);
+}
+
+jlong * globalEnv_GetLongArrayElements(jlongArray array, jboolean * isCopy) {
+    attach_thread();
+    return (*jniEnv)->GetLongArrayElements(jniEnv, array, isCopy);
+}
+
+jfloat * globalEnv_GetFloatArrayElements(jfloatArray array, jboolean * isCopy) {
+    attach_thread();
+    return (*jniEnv)->GetFloatArrayElements(jniEnv, array, isCopy);
+}
+
+jdouble * globalEnv_GetDoubleArrayElements(jdoubleArray array, jboolean * isCopy) {
+    attach_thread();
+    return (*jniEnv)->GetDoubleArrayElements(jniEnv, array, isCopy);
+}
+
+void globalEnv_ReleaseBooleanArrayElements(jbooleanArray array, jboolean * elems, jint mode) {
+    attach_thread();
+    (*jniEnv)->ReleaseBooleanArrayElements(jniEnv, array, elems, mode);
+}
+
+void globalEnv_ReleaseByteArrayElements(jbyteArray array, jbyte * elems, jint mode) {
+    attach_thread();
+    (*jniEnv)->ReleaseByteArrayElements(jniEnv, array, elems, mode);
+}
+
+void globalEnv_ReleaseCharArrayElements(jcharArray array, jchar * elems, jint mode) {
+    attach_thread();
+    (*jniEnv)->ReleaseCharArrayElements(jniEnv, array, elems, mode);
+}
+
+void globalEnv_ReleaseShortArrayElements(jshortArray array, jshort * elems, jint mode) {
+    attach_thread();
+    (*jniEnv)->ReleaseShortArrayElements(jniEnv, array, elems, mode);
+}
+
+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, jint mode) {
+    attach_thread();
+    (*jniEnv)->ReleasePrimitiveArrayCritical(jniEnv, array, carray, mode);
+}
+
+const jchar * globalEnv_GetStringCritical(jstring str, jboolean * isCopy) {
+    attach_thread();
+    return (*jniEnv)->GetStringCritical(jniEnv, str, isCopy);
+}
+
+void globalEnv_ReleaseStringCritical(jstring str, const jchar * carray) {
+    attach_thread();
+    (*jniEnv)->ReleaseStringCritical(jniEnv, str, carray);
+}
+
+jweak globalEnv_NewWeakGlobalRef(jobject obj) {
+    attach_thread();
+    return to_global_ref((*jniEnv)->NewWeakGlobalRef(jniEnv, obj));
+}
+
+void globalEnv_DeleteWeakGlobalRef(jweak obj) {
+    attach_thread();
+    (*jniEnv)->DeleteWeakGlobalRef(jniEnv, obj);
+}
+
+jboolean globalEnv_ExceptionCheck() {
+    attach_thread();
+    return (*jniEnv)->ExceptionCheck(jniEnv);
+}
+
+jobject globalEnv_NewDirectByteBuffer(void * address, jlong capacity) {
+    attach_thread();
+    return to_global_ref((*jniEnv)->NewDirectByteBuffer(jniEnv, address, capacity));
+}
+
+void * globalEnv_GetDirectBufferAddress(jobject buf) {
+    attach_thread();
+    return (*jniEnv)->GetDirectBufferAddress(jniEnv, buf);
+}
+
+jlong globalEnv_GetDirectBufferCapacity(jobject buf) {
+    attach_thread();
+    return (*jniEnv)->GetDirectBufferCapacity(jniEnv, buf);
+}
+
+jobjectRefType globalEnv_GetObjectRefType(jobject obj) {
+    attach_thread();
+    return (*jniEnv)->GetObjectRefType(jniEnv, obj);
+}
+
+struct GlobalJniEnv globalEnv = {
+    .GetVersion = globalEnv_GetVersion,
+    .DefineClass = globalEnv_DefineClass,
+    .FindClass = globalEnv_FindClass,
+    .FromReflectedMethod = globalEnv_FromReflectedMethod,
+    .FromReflectedField = globalEnv_FromReflectedField,
+    .ToReflectedMethod = globalEnv_ToReflectedMethod,
+    .GetSuperclass = globalEnv_GetSuperclass,
+    .IsAssignableFrom = globalEnv_IsAssignableFrom,
+    .ToReflectedField = globalEnv_ToReflectedField,
+    .Throw = globalEnv_Throw,
+    .ThrowNew = globalEnv_ThrowNew,
+    .ExceptionOccurred = globalEnv_ExceptionOccurred,
+    .ExceptionDescribe = globalEnv_ExceptionDescribe,
+    .ExceptionClear = globalEnv_ExceptionClear,
+    .FatalError = globalEnv_FatalError,
+    .PushLocalFrame = globalEnv_PushLocalFrame,
+    .PopLocalFrame = globalEnv_PopLocalFrame,
+    .NewGlobalRef = globalEnv_NewGlobalRef,
+    .DeleteGlobalRef = globalEnv_DeleteGlobalRef,
+    .IsSameObject = globalEnv_IsSameObject,
+    .EnsureLocalCapacity = globalEnv_EnsureLocalCapacity,
+    .AllocObject = globalEnv_AllocObject,
+    .NewObject = globalEnv_NewObject,
+    .NewObjectA = globalEnv_NewObjectA,
+    .GetObjectClass = globalEnv_GetObjectClass,
+    .IsInstanceOf = globalEnv_IsInstanceOf,
+    .GetMethodID = globalEnv_GetMethodID,
+    .CallObjectMethod = globalEnv_CallObjectMethod,
+    .CallObjectMethodA = globalEnv_CallObjectMethodA,
+    .CallBooleanMethod = globalEnv_CallBooleanMethod,
+    .CallBooleanMethodA = globalEnv_CallBooleanMethodA,
+    .CallByteMethod = globalEnv_CallByteMethod,
+    .CallByteMethodA = globalEnv_CallByteMethodA,
+    .CallCharMethod = globalEnv_CallCharMethod,
+    .CallCharMethodA = globalEnv_CallCharMethodA,
+    .CallShortMethod = globalEnv_CallShortMethod,
+    .CallShortMethodA = globalEnv_CallShortMethodA,
+    .CallIntMethod = globalEnv_CallIntMethod,
+    .CallIntMethodA = globalEnv_CallIntMethodA,
+    .CallLongMethod = globalEnv_CallLongMethod,
+    .CallLongMethodA = globalEnv_CallLongMethodA,
+    .CallFloatMethod = globalEnv_CallFloatMethod,
+    .CallFloatMethodA = globalEnv_CallFloatMethodA,
+    .CallDoubleMethod = globalEnv_CallDoubleMethod,
+    .CallDoubleMethodA = globalEnv_CallDoubleMethodA,
+    .CallVoidMethod = globalEnv_CallVoidMethod,
+    .CallVoidMethodA = globalEnv_CallVoidMethodA,
+    .CallNonvirtualObjectMethod = globalEnv_CallNonvirtualObjectMethod,
+    .CallNonvirtualObjectMethodA = globalEnv_CallNonvirtualObjectMethodA,
+    .CallNonvirtualBooleanMethod = globalEnv_CallNonvirtualBooleanMethod,
+    .CallNonvirtualBooleanMethodA = globalEnv_CallNonvirtualBooleanMethodA,
+    .CallNonvirtualByteMethod = globalEnv_CallNonvirtualByteMethod,
+    .CallNonvirtualByteMethodA = globalEnv_CallNonvirtualByteMethodA,
+    .CallNonvirtualCharMethod = globalEnv_CallNonvirtualCharMethod,
+    .CallNonvirtualCharMethodA = globalEnv_CallNonvirtualCharMethodA,
+    .CallNonvirtualShortMethod = globalEnv_CallNonvirtualShortMethod,
+    .CallNonvirtualShortMethodA = globalEnv_CallNonvirtualShortMethodA,
+    .CallNonvirtualIntMethod = globalEnv_CallNonvirtualIntMethod,
+    .CallNonvirtualIntMethodA = globalEnv_CallNonvirtualIntMethodA,
+    .CallNonvirtualLongMethod = globalEnv_CallNonvirtualLongMethod,
+    .CallNonvirtualLongMethodA = globalEnv_CallNonvirtualLongMethodA,
+    .CallNonvirtualFloatMethod = globalEnv_CallNonvirtualFloatMethod,
+    .CallNonvirtualFloatMethodA = globalEnv_CallNonvirtualFloatMethodA,
+    .CallNonvirtualDoubleMethod = globalEnv_CallNonvirtualDoubleMethod,
+    .CallNonvirtualDoubleMethodA = globalEnv_CallNonvirtualDoubleMethodA,
+    .CallNonvirtualVoidMethod = globalEnv_CallNonvirtualVoidMethod,
+    .CallNonvirtualVoidMethodA = globalEnv_CallNonvirtualVoidMethodA,
+    .GetFieldID = globalEnv_GetFieldID,
+    .GetObjectField = globalEnv_GetObjectField,
+    .GetBooleanField = globalEnv_GetBooleanField,
+    .GetByteField = globalEnv_GetByteField,
+    .GetCharField = globalEnv_GetCharField,
+    .GetShortField = globalEnv_GetShortField,
+    .GetIntField = globalEnv_GetIntField,
+    .GetLongField = globalEnv_GetLongField,
+    .GetFloatField = globalEnv_GetFloatField,
+    .GetDoubleField = globalEnv_GetDoubleField,
+    .SetObjectField = globalEnv_SetObjectField,
+    .SetBooleanField = globalEnv_SetBooleanField,
+    .SetByteField = globalEnv_SetByteField,
+    .SetCharField = globalEnv_SetCharField,
+    .SetShortField = globalEnv_SetShortField,
+    .SetIntField = globalEnv_SetIntField,
+    .SetLongField = globalEnv_SetLongField,
+    .SetFloatField = globalEnv_SetFloatField,
+    .SetDoubleField = globalEnv_SetDoubleField,
+    .GetStaticMethodID = globalEnv_GetStaticMethodID,
+    .CallStaticObjectMethod = globalEnv_CallStaticObjectMethod,
+    .CallStaticObjectMethodA = globalEnv_CallStaticObjectMethodA,
+    .CallStaticBooleanMethod = globalEnv_CallStaticBooleanMethod,
+    .CallStaticBooleanMethodA = globalEnv_CallStaticBooleanMethodA,
+    .CallStaticByteMethod = globalEnv_CallStaticByteMethod,
+    .CallStaticByteMethodA = globalEnv_CallStaticByteMethodA,
+    .CallStaticCharMethod = globalEnv_CallStaticCharMethod,
+    .CallStaticCharMethodA = globalEnv_CallStaticCharMethodA,
+    .CallStaticShortMethod = globalEnv_CallStaticShortMethod,
+    .CallStaticShortMethodA = globalEnv_CallStaticShortMethodA,
+    .CallStaticIntMethod = globalEnv_CallStaticIntMethod,
+    .CallStaticIntMethodA = globalEnv_CallStaticIntMethodA,
+    .CallStaticLongMethod = globalEnv_CallStaticLongMethod,
+    .CallStaticLongMethodA = globalEnv_CallStaticLongMethodA,
+    .CallStaticFloatMethod = globalEnv_CallStaticFloatMethod,
+    .CallStaticFloatMethodA = globalEnv_CallStaticFloatMethodA,
+    .CallStaticDoubleMethod = globalEnv_CallStaticDoubleMethod,
+    .CallStaticDoubleMethodA = globalEnv_CallStaticDoubleMethodA,
+    .CallStaticVoidMethod = globalEnv_CallStaticVoidMethod,
+    .CallStaticVoidMethodA = globalEnv_CallStaticVoidMethodA,
+    .GetStaticFieldID = globalEnv_GetStaticFieldID,
+    .GetStaticObjectField = globalEnv_GetStaticObjectField,
+    .GetStaticBooleanField = globalEnv_GetStaticBooleanField,
+    .GetStaticByteField = globalEnv_GetStaticByteField,
+    .GetStaticCharField = globalEnv_GetStaticCharField,
+    .GetStaticShortField = globalEnv_GetStaticShortField,
+    .GetStaticIntField = globalEnv_GetStaticIntField,
+    .GetStaticLongField = globalEnv_GetStaticLongField,
+    .GetStaticFloatField = globalEnv_GetStaticFloatField,
+    .GetStaticDoubleField = globalEnv_GetStaticDoubleField,
+    .SetStaticObjectField = globalEnv_SetStaticObjectField,
+    .SetStaticBooleanField = globalEnv_SetStaticBooleanField,
+    .SetStaticByteField = globalEnv_SetStaticByteField,
+    .SetStaticCharField = globalEnv_SetStaticCharField,
+    .SetStaticShortField = globalEnv_SetStaticShortField,
+    .SetStaticIntField = globalEnv_SetStaticIntField,
+    .SetStaticLongField = globalEnv_SetStaticLongField,
+    .SetStaticFloatField = globalEnv_SetStaticFloatField,
+    .SetStaticDoubleField = globalEnv_SetStaticDoubleField,
+    .NewString = globalEnv_NewString,
+    .GetStringLength = globalEnv_GetStringLength,
+    .GetStringChars = globalEnv_GetStringChars,
+    .ReleaseStringChars = globalEnv_ReleaseStringChars,
+    .NewStringUTF = globalEnv_NewStringUTF,
+    .GetStringUTFLength = globalEnv_GetStringUTFLength,
+    .GetStringUTFChars = globalEnv_GetStringUTFChars,
+    .ReleaseStringUTFChars = globalEnv_ReleaseStringUTFChars,
+    .GetArrayLength = globalEnv_GetArrayLength,
+    .NewObjectArray = globalEnv_NewObjectArray,
+    .GetObjectArrayElement = globalEnv_GetObjectArrayElement,
+    .SetObjectArrayElement = globalEnv_SetObjectArrayElement,
+    .NewBooleanArray = globalEnv_NewBooleanArray,
+    .NewByteArray = globalEnv_NewByteArray,
+    .NewCharArray = globalEnv_NewCharArray,
+    .NewShortArray = globalEnv_NewShortArray,
+    .NewIntArray = globalEnv_NewIntArray,
+    .NewLongArray = globalEnv_NewLongArray,
+    .NewFloatArray = globalEnv_NewFloatArray,
+    .NewDoubleArray = globalEnv_NewDoubleArray,
+    .GetBooleanArrayElements = globalEnv_GetBooleanArrayElements,
+    .GetByteArrayElements = globalEnv_GetByteArrayElements,
+    .GetCharArrayElements = globalEnv_GetCharArrayElements,
+    .GetShortArrayElements = globalEnv_GetShortArrayElements,
+    .GetIntArrayElements = globalEnv_GetIntArrayElements,
+    .GetLongArrayElements = globalEnv_GetLongArrayElements,
+    .GetFloatArrayElements = globalEnv_GetFloatArrayElements,
+    .GetDoubleArrayElements = globalEnv_GetDoubleArrayElements,
+    .ReleaseBooleanArrayElements = globalEnv_ReleaseBooleanArrayElements,
+    .ReleaseByteArrayElements = globalEnv_ReleaseByteArrayElements,
+    .ReleaseCharArrayElements = globalEnv_ReleaseCharArrayElements,
+    .ReleaseShortArrayElements = globalEnv_ReleaseShortArrayElements,
+    .ReleaseIntArrayElements = globalEnv_ReleaseIntArrayElements,
+    .ReleaseLongArrayElements = globalEnv_ReleaseLongArrayElements,
+    .ReleaseFloatArrayElements = globalEnv_ReleaseFloatArrayElements,
+    .ReleaseDoubleArrayElements = globalEnv_ReleaseDoubleArrayElements,
+    .GetBooleanArrayRegion = globalEnv_GetBooleanArrayRegion,
+    .GetByteArrayRegion = globalEnv_GetByteArrayRegion,
+    .GetCharArrayRegion = globalEnv_GetCharArrayRegion,
+    .GetShortArrayRegion = globalEnv_GetShortArrayRegion,
+    .GetIntArrayRegion = globalEnv_GetIntArrayRegion,
+    .GetLongArrayRegion = globalEnv_GetLongArrayRegion,
+    .GetFloatArrayRegion = globalEnv_GetFloatArrayRegion,
+    .GetDoubleArrayRegion = globalEnv_GetDoubleArrayRegion,
+    .SetBooleanArrayRegion = globalEnv_SetBooleanArrayRegion,
+    .SetByteArrayRegion = globalEnv_SetByteArrayRegion,
+    .SetCharArrayRegion = globalEnv_SetCharArrayRegion,
+    .SetShortArrayRegion = globalEnv_SetShortArrayRegion,
+    .SetIntArrayRegion = globalEnv_SetIntArrayRegion,
+    .SetLongArrayRegion = globalEnv_SetLongArrayRegion,
+    .SetFloatArrayRegion = globalEnv_SetFloatArrayRegion,
+    .SetDoubleArrayRegion = globalEnv_SetDoubleArrayRegion,
+    .RegisterNatives = globalEnv_RegisterNatives,
+    .UnregisterNatives = globalEnv_UnregisterNatives,
+    .MonitorEnter = globalEnv_MonitorEnter,
+    .MonitorExit = globalEnv_MonitorExit,
+    .GetJavaVM = globalEnv_GetJavaVM,
+    .GetStringRegion = globalEnv_GetStringRegion,
+    .GetStringUTFRegion = globalEnv_GetStringUTFRegion,
+    .GetPrimitiveArrayCritical = globalEnv_GetPrimitiveArrayCritical,
+    .ReleasePrimitiveArrayCritical = globalEnv_ReleasePrimitiveArrayCritical,
+    .GetStringCritical = globalEnv_GetStringCritical,
+    .ReleaseStringCritical = globalEnv_ReleaseStringCritical,
+    .NewWeakGlobalRef = globalEnv_NewWeakGlobalRef,
+    .DeleteWeakGlobalRef = globalEnv_DeleteWeakGlobalRef,
+    .ExceptionCheck = globalEnv_ExceptionCheck,
+    .NewDirectByteBuffer = globalEnv_NewDirectByteBuffer,
+    .GetDirectBufferAddress = globalEnv_GetDirectBufferAddress,
+    .GetDirectBufferCapacity = globalEnv_GetDirectBufferCapacity,
+    .GetObjectRefType = globalEnv_GetObjectRefType,
+};
+
+FFI_PLUGIN_EXPORT struct GlobalJniEnv *GetGlobalEnv(void) {
+    if (jni.jvm == NULL) return NULL;
+    return &globalEnv;
+}
diff --git a/pkgs/jni/src/global_jni_env.h b/pkgs/jni/src/global_jni_env.h
new file mode 100644
index 0000000..befaf4b
--- /dev/null
+++ b/pkgs/jni/src/global_jni_env.h
@@ -0,0 +1,219 @@
+// 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.
+
+#include "dartjni.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
+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, 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, 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, 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, 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, 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, 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);
+} GlobalJniEnv;
+
+extern GlobalJniEnv globalEnv;
+FFI_PLUGIN_EXPORT struct GlobalJniEnv *GetGlobalEnv(void);
diff --git a/pkgs/jni/test/exception_test.dart b/pkgs/jni/test/exception_test.dart
index 0e86ec9..a2538e1 100644
--- a/pkgs/jni/test/exception_test.dart
+++ b/pkgs/jni/test/exception_test.dart
@@ -5,9 +5,7 @@
 import 'dart:io';
 
 import 'package:test/test.dart';
-
 import 'package:jni/jni.dart';
-import 'package:jni/jni_object.dart';
 
 void main() {
   if (!Platform.isAndroid) {
@@ -16,47 +14,56 @@
       // If library does not exist, a helpful exception should be thrown.
       // we can't test this directly because
       // `test` schedules functions asynchronously
-      Jni.spawn(helperDir: "wrong_dir");
+      Jni.spawn(dylibDir: "wrong_dir");
     } on HelperNotFoundException catch (_) {
       // stderr.write("\n$_\n");
-      Jni.spawn(helperDir: "build/jni_libs");
+      try {
+        Jni.spawn(dylibDir: "build/jni_libs", jvmOptions: ["-Xmx128m"]);
+      } on JvmExistsException catch (_) {
+        // TODO(#51): Support destroying and reinstantiating JVM.
+      }
       caught = true;
+    } on JvmExistsException {
+      stderr.writeln('cannot verify: HelperNotFoundException thrown');
     }
     if (!caught) {
       throw "Expected HelperNotFoundException\n"
           "Read exception_test.dart for details.";
     }
   }
-  final jni = Jni.getInstance();
 
   test("double free throws exception", () {
-    final r = jni.newInstance("java/util/Random", "()V", []);
+    final r = Jni.newInstance("java/util/Random", "()V", []);
     r.delete();
     expect(r.delete, throwsA(isA<DoubleFreeException>()));
   });
 
   test("Use after free throws exception", () {
-    final r = jni.newInstance("java/util/Random", "()V", []);
+    final r = Jni.newInstance("java/util/Random", "()V", []);
     r.delete();
-    expect(() => r.callIntMethodByName("nextInt", "(I)I", [256]),
+    expect(() => r.callMethodByName<int>("nextInt", "(I)I", [256]),
         throwsA(isA<UseAfterFreeException>()));
   });
 
+  test("void fieldType throws exception", () {
+    final r = Jni.newInstance("java/util/Random", "()V", []);
+    expect(
+        () => r.getField<void>(nullptr, JniType.voidType), throwsArgumentError);
+    expect(() => r.getStaticField<void>(nullptr, JniType.voidType),
+        throwsArgumentError);
+  });
+
+  test("Wrong callType throws exception", () {
+    final r = Jni.newInstance("java/util/Random", "()V", []);
+    expect(
+        () => r.callMethodByName<int>(
+            "nextInt", "(I)I", [256], JniType.doubleType),
+        throwsA(isA<InvalidCallTypeException>()));
+  });
+
   test("An exception in JNI throws JniException in Dart", () {
-    final r = jni.newInstance("java/util/Random", "()V", []);
-    expect(() => r.callIntMethodByName("nextInt", "(I)I", [-1]),
+    final r = Jni.newInstance("java/util/Random", "()V", []);
+    expect(() => r.callMethodByName<int>("nextInt", "(I)I", [-1]),
         throwsA(isA<JniException>()));
   });
-  // Using printStackTrace from env
-  /*
-  test("uncommented to print java stack trace", () {
-    final r = jni.newInstance("java/util/Random", "()V", []);
-    try {
-      r.callIntMethodByName("nextInt", "(I)I", [-1]);
-    } on JniException catch (e) {
-      jni.getEnv().printStackTrace(e);
-      // optionally rethrow error
-    }
-  });
-  */
 }
diff --git a/pkgs/jni/test/jni_object_test.dart b/pkgs/jni/test/jni_object_test.dart
index d234101..1cca591 100644
--- a/pkgs/jni/test/jni_object_test.dart
+++ b/pkgs/jni/test/jni_object_test.dart
@@ -9,55 +9,56 @@
 import 'package:test/test.dart';
 
 import 'package:jni/jni.dart';
-import 'package:jni/jni_object.dart';
 
 void main() {
   // Don't forget to initialize JNI.
   if (!Platform.isAndroid) {
-    Jni.spawn(helperDir: "build/jni_libs");
+    try {
+      Jni.spawn(dylibDir: "build/jni_libs", jvmOptions: ["-Xmx128m"]);
+    } on JvmExistsException catch (_) {
+      // TODO(#51): Support destroying and reinstantiating JVM.
+    }
   }
 
-  final jni = Jni.getInstance();
-
-  // The API based on JniEnv is intended to closely mimic C API
+  // 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
   // JniObject API provides an easier way to perform some common operations.
   //
-  // However, this is only meant for experimenting and very simple uses.
-  // For anything complicated, use JNIGen (The main part of this GSoC project)
-  // which will be both more efficient and ergonomic.
+  // However, if binding generation using jnigen is possible, that should be
+  // the first choice.
   test("Long.intValue() using JniObject", () {
-    // findJniClass on a Jni object returns a JniClass
-    // which wraps a local class reference and env, and
+    // JniClass wraps a local class reference, and
     // provides convenience functions.
-    final longClass = jni.findJniClass("java/lang/Long");
+    final longClass = Jni.findJniClass("java/lang/Long");
 
     // looks for a constructor with given signature.
     // equivalently you can lookup a method with name <init>
-    final longCtor = longClass.getConstructorID("(J)V");
+    final longCtor = longClass.getCtorID("(J)V");
 
-    // note that the arguments are just passed as a list
-    final long = longClass.newObject(longCtor, [176]);
+    // note that the arguments are just passed as a list.
+    // allowed argument types are primitive types, JniObject and its subclasses,
+    // and raw JNI references (JObject). Strings will be automatically converted
+    // to JNI strings.
+    final long = longClass.newInstance(longCtor, [176]);
 
-    final intValue = long.callIntMethodByName("intValue", "()I", []);
+    final intValue = long.callMethodByName<int>("intValue", "()I", []);
     expect(intValue, equals(176));
 
     // delete any JniObject and JniClass 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", () {
-    // you can use wrapClass to wrap a raw JClass (which is basically void*)
-    // Original ref is saved & will be deleted when you delete the
-    // wrapped JniClass.
-    final integerClass = jni.wrapClass(jni.findClass("java/lang/Integer"));
-    final result = integerClass.callStaticObjectMethodByName(
+    final integerClass = Jni.findJniClass("java/lang/Integer");
+    final result = integerClass.callStaticMethodByName<JniString>(
         "toHexString", "(I)Ljava/lang/String;", [31]);
 
     // if the object is supposed to be a Java string
-    // you can call asDartString on it.
-    final resultString = result.asDartString();
+    // you can call toDartString on it.
+    final resultString = result.toDartString();
 
     // Dart string is a copy, original object can be deleted.
     result.delete();
@@ -68,64 +69,70 @@
   });
 
   test("Call method with null argument, expect exception", () {
-    final integerClass = jni.findJniClass("java/lang/Integer");
+    final integerClass = Jni.findJniClass("java/lang/Integer");
     expect(
-        () => integerClass.callStaticIntMethodByName(
+        () => integerClass.callStaticMethodByName<int>(
             "parseInt", "(Ljava/lang/String;)I", [nullptr]),
         throwsException);
     integerClass.delete();
   });
 
   test("Try to find a non-exisiting class, expect exception", () {
-    expect(() => jni.findJniClass("java/lang/NotExists"), throwsException);
+    expect(() => Jni.findJniClass("java/lang/NotExists"), throwsException);
   });
 
-  /// call<Type>MethodByName will be expensive if making same call many times
+  /// 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");
+    final longClass = Jni.findJniClass("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", []);
+    final random = Jni.newInstance("java/util/Random", "()V", []);
 
     // You don't need a JniClass reference to get instance method IDs
     final nextIntMethod = random.getMethodID("nextInt", "(I)I");
 
     for (int i = 0; i < 100; i++) {
-      int r = random.callIntMethod(nextIntMethod, [256 * 256]);
+      int r = random.callMethod<int>(nextIntMethod, [256 * 256]);
       int bits = 0;
       final jbc =
-          longClass.callStaticIntMethod(bitCountMethod, [JValueLong(r)]);
+          longClass.callStaticMethod<int>(bitCountMethod, [JValueLong(r)]);
       while (r != 0) {
         bits += r % 2;
         r = (r / 2).floor();
       }
       expect(jbc, equals(bits));
     }
-
-    random.delete();
-    longClass.delete();
+    Jni.deleteAll([random, longClass]);
   });
 
-  // Actually it's not even required to get a reference to class
+  // One-off invocation of static method in single call.
   test("invoke_", () {
-    final m = jni.invokeLongMethod(
-        "java/lang/Long", "min", "(JJ)J", [JValueLong(1234), JValueLong(1324)]);
-    expect(m, equals(1234));
+    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", () {
+    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("retrieve_", () {
-    final maxLong = jni.retrieveShortField("java/lang/Short", "MAX_VALUE", "S");
+    final maxLong = Jni.retrieveStaticField<int>(
+        "java/lang/Short", "MAX_VALUE", "S", JniType.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");
+    final longClass = Jni.findJniClass("java/lang/Long");
     const n = 1223334444;
-    final strFromJava = longClass.callStaticStringMethodByName(
+    final strFromJava = longClass.callStaticMethodByName<String>(
         "toOctalString", "(J)Ljava/lang/String;", [JValueLong(n)]);
     expect(strFromJava, equals(n.toRadixString(8)));
     longClass.delete();
@@ -136,77 +143,55 @@
   // allowed by Jni.jvalues
   // They will be converted automatically.
   test("Passing strings in arguments", () {
-    final out = jni.retrieveObjectField(
+    final out = Jni.retrieveStaticField<JniObject>(
         "java/lang/System", "out", "Ljava/io/PrintStream;");
     // uncomment next line to see output
     // (\n because test runner prints first char at end of the line)
-    //out.callVoidMethodByName(
+    //out.callMethodByName<Null>(
     //    "println", "(Ljava/lang/Object;)V", ["\nWorks (Apparently)"]);
     out.delete();
   });
 
   test("Passing strings in arguments 2", () {
-    final twelve = jni.invokeByteMethod(
-        "java/lang/Byte", "parseByte", "(Ljava/lang/String;)B", ["12"]);
+    final twelve = Jni.invokeStaticMethod<int>("java/lang/Byte", "parseByte",
+        "(Ljava/lang/String;)B", ["12"], JniType.byteType);
     expect(twelve, equals(12));
   });
 
-  // You can use() method on JniObject for using once and deleting
+  // You can use() method on JniObject for using once and deleting.
   test("use() method", () {
-    final randomInt = jni.newInstance("java/util/Random", "()V", []).use(
-        (random) => random.callIntMethodByName("nextInt", "(I)I", [15]));
+    final randomInt = Jni.newInstance("java/util/Random", "()V", [])
+        .use((random) => random.callMethodByName<int>("nextInt", "(I)I", [15]));
     expect(randomInt, lessThan(15));
   });
 
+  // The JniObject and JniClass have NativeFinalizer. However, it's possible to
+  // explicitly use `Arena`.
+  test('Using arena', () {
+    final objects = <JniObject>[];
+    using((arena) {
+      final r = Jni.findJniClass('java/util/Random')..deletedIn(arena);
+      final ctor = r.getCtorID("()V");
+      for (int i = 0; i < 10; i++) {
+        objects.add(r.newInstance(ctor, [])..deletedIn(arena));
+      }
+    });
+    for (var object in objects) {
+      expect(object.isDeleted, isTrue);
+    }
+  });
+
   test("enums", () {
     // Don't forget to escape $ in nested type names
-    final ordinal = jni
-        .retrieveObjectField(
+    final ordinal = Jni.retrieveStaticField<JniObject>(
             "java/net/Proxy\$Type", "HTTP", "Ljava/net/Proxy\$Type;")
-        .use((f) => f.callIntMethodByName("ordinal", "()I", []));
+        .use((f) => f.callMethodByName<int>("ordinal", "()I", []));
     expect(ordinal, equals(1));
   });
 
   test("Isolate", () {
     Isolate.spawn(doSomeWorkInIsolate, null);
   });
-
-  // JniObject is valid only in thread it is obtained
-  // so it can be safely shared with a function that can run in
-  // different thread.
-  //
-  // Eg: Dart has a thread pool, which means async methods may get scheduled
-  // in different thread.
-  //
-  // In that case, convert the JniObject into `JniGlobalObjectRef` using
-  // getGlobalRef() and reconstruct the object in use site using fromJniObject
-  // constructor.
-  test("JniGlobalRef", () async {
-    final uri = jni.invokeObjectMethod(
-        "java/net/URI",
-        "create",
-        "(Ljava/lang/String;)Ljava/net/URI;",
-        ["https://www.google.com/search"]);
-    final rg = uri.getGlobalRef();
-    await Future.delayed(const Duration(seconds: 1), () {
-      final env = jni.getEnv();
-      // Now comment this line & try to directly use uri local ref
-      // in outer scope.
-      //
-      // You will likely get a segfault, because Future computation is running
-      // in different thread.
-      //
-      // Therefore, don't share JniObjects across functions that can be
-      // scheduled across threads, including async callbacks.
-      final uri = JniObject.fromGlobalRef(env, rg);
-      final scheme =
-          uri.callStringMethodByName("getScheme", "()Ljava/lang/String;", []);
-      expect(scheme, "https");
-      uri.delete();
-      rg.deleteIn(env);
-    });
-    uri.delete();
-  });
 }
 
 void doSomeWorkInIsolate(Void? _) {
@@ -214,9 +199,8 @@
   // when doing getInstance first time in a new isolate.
   //
   // otherwise getInstance will throw a "library not found" exception.
-  Jni.load(helperDir: "build/jni_libs");
-  final jni = Jni.getInstance();
-  final random = jni.newInstance("java/util/Random", "()V", []);
+  Jni.setDylibDir(dylibDir: "build/jni_libs");
+  final random = Jni.newInstance("java/util/Random", "()V", []);
   // final r = random.callIntMethodByName("nextInt", "(I)I", [256]);
   // expect(r, lessThan(256));
   // Expect throws an OutsideTestException
diff --git a/pkgs/jni/test/jni_test.dart b/pkgs/jni/test/jni_test.dart
index ce31fc4..bbf437b 100644
--- a/pkgs/jni/test/jni_test.dart
+++ b/pkgs/jni/test/jni_test.dart
@@ -3,11 +3,9 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:io';
-import 'dart:ffi';
 
-import 'package:test/test.dart';
-import 'package:ffi/ffi.dart';
 import 'package:jni/jni.dart';
+import 'package:test/test.dart';
 
 void main() {
   // Running on Android through flutter, this plugin
@@ -22,106 +20,108 @@
   // You have to manually pass the path to the `dartjni` dynamic library.
 
   if (!Platform.isAndroid) {
-    Jni.spawn(helperDir: "build/jni_libs");
+    try {
+      Jni.spawn(dylibDir: "build/jni_libs", jvmOptions: ["-Xmx128m"]);
+    } on JvmExistsException catch (_) {
+      // TODO(#51): Support destroying and reinstantiating JVM.
+    }
   }
 
-  final jni = Jni.getInstance();
+  // 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('get JNI Version', () {
-    // get a dart binding of JNIEnv object
-    // It's a thin wrapper over C's JNIEnv*, and provides
-    // all methods of it (without need to pass the first self parameter),
-    // plus few extension methods to make working in dart easier.
-    final env = jni.getEnv();
-    expect(env.GetVersion(), isNot(equals(0)));
+    expect(Jni.env.GetVersion(), isNot(equals(0)));
   });
 
-  test('Manually lookup & call Long.toHexString static method', () {
-    // create an arena for allocating anything native
-    // it's convenient way to release all natively allocated strings
-    // and values at once.
-    final arena = Arena();
-    final env = jni.getEnv();
+  test(
+      'Manually lookup & call Long.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 longClass =
+                env.FindClass("java/lang/Long".toNativeChars(arena));
+            // Refer JNI spec on how to construct method signatures
+            // Passing wrong signature leads to a segfault
+            final hexMethod = env.GetStaticMethodID(
+                longClass,
+                "toHexString".toNativeChars(arena),
+                "(J)Ljava/lang/String;".toNativeChars(arena));
 
-    // Method names on JniEnv* from C JNI API are capitalized
-    // like in original, while other extension methods
-    // follow Dart naming conventions.
-    final longClass = env.FindClass("java/lang/Long".toNativeChars(arena));
-    // Refer JNI spec on how to construct method signatures
-    // Passing wrong signature leads to a segfault
-    final hexMethod = env.GetStaticMethodID(
-        longClass,
-        "toHexString".toNativeChars(arena),
-        "(J)Ljava/lang/String;".toNativeChars(arena));
+            for (var i in [1, 80, 13, 76, 1134453224145]) {
+              // 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(longClass, hexMethod,
+                  Jni.jvalues([JValueLong(i)], allocator: arena));
 
-    for (var i in [1, 80, 13, 76, 1134453224145]) {
-      // Use Jni.jvalues method to easily construct native argument arrays
-      // 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(
-          longClass, hexMethod, Jni.jvalues([JValueLong(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)));
 
-      // 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.DeleteLocalRef(jres);
-    }
-    env.DeleteLocalRef(longClass);
-    arena.releaseAll();
-  });
+              // 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(longClass);
+          }));
 
   test("asJString extension method", () {
-    final env = jni.getEnv();
     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.DeleteLocalRef(jstr);
+    env.DeleteGlobalRef(jstr);
   });
 
-  test("Convert back and forth between dart and java string", () {
-    final arena = Arena();
-    final env = jni.getEnv();
-    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));
+  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);
+          }));
 
-    // delete multiple local references using this method
-    env.deleteAllLocalRefs([jstr]);
-    arena.releaseAll();
-  });
-
-  test("Print something from Java", () {
-    final arena = Arena();
-    final env = jni.getEnv();
-    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 JNI!";
-    final jstr = env.asJString(str);
-    // test runner can't compare what's printed by Java, leaving it
-    // env.CallVoidMethodA(out, println, Jni.jvalues([jstr]));
-    env.deleteAllLocalRefs([system, printStream, jstr]);
-    arena.releaseAll();
-  });
+  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/third_party/ffigen_patch_jni/.github/workflows/test-package.yml b/pkgs/jni/third_party/ffigen_patch_jni/.github/workflows/test-package.yml
new file mode 100644
index 0000000..1b6b494
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/.github/workflows/test-package.yml
@@ -0,0 +1,78 @@
+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
new file mode 100644
index 0000000..71c0ba1
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/.gitignore
@@ -0,0 +1,41 @@
+# 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
new file mode 100644
index 0000000..4f334e8
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/AUTHORS
@@ -0,0 +1,8 @@
+# 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
new file mode 100644
index 0000000..83edcb0
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/CHANGELOG.md
@@ -0,0 +1,291 @@
+# 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
new file mode 100644
index 0000000..467a982
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/LICENSE
@@ -0,0 +1,27 @@
+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
new file mode 100644
index 0000000..7cd52bf
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/README.md
@@ -0,0 +1,8 @@
+#### 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
new file mode 100644
index 0000000..2948143
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/analysis_options.yaml
@@ -0,0 +1,24 @@
+# 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
new file mode 100644
index 0000000..6156ed0
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/bin/ffigen.dart
@@ -0,0 +1,6 @@
+// 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
new file mode 100644
index 0000000..3425eec
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/lib/ffigen.dart
@@ -0,0 +1,12 @@
+// 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
new file mode 100644
index 0000000..2b20f84
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/README.md
@@ -0,0 +1,41 @@
+# **_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
new file mode 100644
index 0000000..82b2ed6
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator.dart
@@ -0,0 +1,26 @@
+// 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
new file mode 100644
index 0000000..2e2f189
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/binding.dart
@@ -0,0 +1,74 @@
+// 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
new file mode 100644
index 0000000..decfd6f
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/binding_string.dart
@@ -0,0 +1,28 @@
+// 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
new file mode 100644
index 0000000..66592e2
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/compound.dart
@@ -0,0 +1,276 @@
+// 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', 'JniNativeExtensions'};
+
+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!));
+    }
+
+    /// 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 ${m.type.getDartType(w)} _${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;
+          s.write('${depth}external ${m.type.getDartType(w)} $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
new file mode 100644
index 0000000..8fd7191
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/constant.dart
@@ -0,0 +1,65 @@
+// 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
new file mode 100644
index 0000000..93d5877
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/dart_keywords.dart
@@ -0,0 +1,72 @@
+// 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
new file mode 100644
index 0000000..4e8ec3a
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/enum_class.dart
@@ -0,0 +1,105 @@
+// 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
new file mode 100644
index 0000000..c10b0c8
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/func.dart
@@ -0,0 +1,165 @@
+// 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
new file mode 100644
index 0000000..0b8abfd
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/func_type.dart
@@ -0,0 +1,83 @@
+// 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
new file mode 100644
index 0000000..579d8dd
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/global.dart
@@ -0,0 +1,86 @@
+// 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
new file mode 100644
index 0000000..a1b2d47
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/handle.dart
@@ -0,0 +1,23 @@
+// 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
new file mode 100644
index 0000000..41f7161
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/imports.dart
@@ -0,0 +1,77 @@
+// 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
new file mode 100644
index 0000000..a651871
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/library.dart
@@ -0,0 +1,141 @@
+// 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
new file mode 100644
index 0000000..4be4b16
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/native_type.dart
@@ -0,0 +1,78 @@
+// 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
new file mode 100644
index 0000000..7ae7486
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/objc_block.dart
@@ -0,0 +1,151 @@
+// 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
new file mode 100644
index 0000000..a92dbcb
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/objc_built_in_functions.dart
@@ -0,0 +1,305 @@
+// 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
new file mode 100644
index 0000000..04eb6e5
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/objc_interface.dart
@@ -0,0 +1,477 @@
+// 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
new file mode 100644
index 0000000..cacb5b2
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/pointer.dart
@@ -0,0 +1,63 @@
+// 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
new file mode 100644
index 0000000..c65e04b
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/struct.dart
@@ -0,0 +1,52 @@
+// 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
new file mode 100644
index 0000000..8468eca
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/type.dart
@@ -0,0 +1,120 @@
+// 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
new file mode 100644
index 0000000..f42e863
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/typealias.dart
@@ -0,0 +1,86 @@
+// 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
new file mode 100644
index 0000000..fc7be96
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/union.dart
@@ -0,0 +1,49 @@
+// 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
new file mode 100644
index 0000000..c000bdf
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/utils.dart
@@ -0,0 +1,72 @@
+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
new file mode 100644
index 0000000..77e9e83
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/code_generator/writer.dart
@@ -0,0 +1,298 @@
+// 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) {
+      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
new file mode 100644
index 0000000..990e137
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/config_provider.dart
@@ -0,0 +1,8 @@
+// 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
new file mode 100644
index 0000000..e9d1f97
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/config_provider/config.dart
@@ -0,0 +1,483 @@
+// 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
new file mode 100644
index 0000000..6ba4f4e
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/config_provider/config_types.dart
@@ -0,0 +1,373 @@
+// 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
new file mode 100644
index 0000000..3f6a597
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/config_provider/path_finder.dart
@@ -0,0 +1,63 @@
+// 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
new file mode 100644
index 0000000..aaa4c08
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/config_provider/spec_utils.dart
@@ -0,0 +1,866 @@
+// 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
new file mode 100644
index 0000000..12dd868
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/executables/ffigen.dart
@@ -0,0 +1,223 @@
+// 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
new file mode 100644
index 0000000..e4dc2c9
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser.dart
@@ -0,0 +1,10 @@
+// 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
new file mode 100644
index 0000000..58108aa
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/clang_bindings/clang_bindings.dart
@@ -0,0 +1,2569 @@
+// 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
new file mode 100644
index 0000000..1381fd3
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/data.dart
@@ -0,0 +1,52 @@
+// 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
new file mode 100644
index 0000000..a9041a6
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/includer.dart
@@ -0,0 +1,90 @@
+// 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
new file mode 100644
index 0000000..2adbb0b
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/parser.dart
@@ -0,0 +1,121 @@
+// 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
new file mode 100644
index 0000000..6c7916f
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/sub_parsers/compounddecl_parser.dart
@@ -0,0 +1,320 @@
+// 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
new file mode 100644
index 0000000..4e5e150
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/sub_parsers/enumdecl_parser.dart
@@ -0,0 +1,119 @@
+// 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
new file mode 100644
index 0000000..b4c40fc
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/sub_parsers/functiondecl_parser.dart
@@ -0,0 +1,130 @@
+// 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
new file mode 100644
index 0000000..cdfe078
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/sub_parsers/macro_parser.dart
@@ -0,0 +1,331 @@
+// 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
new file mode 100644
index 0000000..83f8223
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/sub_parsers/objc_block_parser.dart
@@ -0,0 +1,40 @@
+// 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
new file mode 100644
index 0000000..bf9d038
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/sub_parsers/objcinterfacedecl_parser.dart
@@ -0,0 +1,330 @@
+// 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
new file mode 100644
index 0000000..988a45e
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/sub_parsers/typedefdecl_parser.dart
@@ -0,0 +1,84 @@
+// 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
new file mode 100644
index 0000000..940369a
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/sub_parsers/unnamed_enumdecl_parser.dart
@@ -0,0 +1,70 @@
+// 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
new file mode 100644
index 0000000..8376199
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/sub_parsers/var_parser.dart
@@ -0,0 +1,47 @@
+// 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
new file mode 100644
index 0000000..7831ae8
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/translation_unit_parser.dart
@@ -0,0 +1,89 @@
+// 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
new file mode 100644
index 0000000..41af99a
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/type_extractor/cxtypekindmap.dart
@@ -0,0 +1,40 @@
+// 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
new file mode 100644
index 0000000..1a69715
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/type_extractor/extractor.dart
@@ -0,0 +1,305 @@
+// 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
new file mode 100644
index 0000000..7352642
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/header_parser/utils.dart
@@ -0,0 +1,395 @@
+// 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
new file mode 100644
index 0000000..8186221
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/lib/src/strings.dart
@@ -0,0 +1,221 @@
+// 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/',
+  '/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
new file mode 100644
index 0000000..ffe24d0
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/pubspec.yaml
@@ -0,0 +1,26 @@
+# 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 <3.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
new file mode 100755
index 0000000..02c8e2f
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/tool/coverage.sh
@@ -0,0 +1,15 @@
+#!/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
new file mode 100644
index 0000000..ad0bfd0
--- /dev/null
+++ b/pkgs/jni/third_party/ffigen_patch_jni/tool/libclang_config.yaml
@@ -0,0 +1,119 @@
+# 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 1e46927..961dd09 100644
--- a/pkgs/jni/third_party/jni.h
+++ b/pkgs/jni/third_party/jni.h
@@ -155,7 +155,6 @@
     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);
diff --git a/pkgs/jni/tool/gen_aux_methods.dart b/pkgs/jni/tool/gen_aux_methods.dart
deleted file mode 100644
index a30f54db32..0000000
--- a/pkgs/jni/tool/gen_aux_methods.dart
+++ /dev/null
@@ -1,138 +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' as io;
-import 'package:path/path.dart';
-
-const _license = '''
-// 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.
-
-''';
-final targetTypes = {
-  "String": "String",
-  "Object": "JniObject",
-  "Boolean": "bool",
-  "Byte": "int",
-  "Char": "int",
-  "Short": "int",
-  "Int": "int",
-  "Long": "int",
-  "Float": "double",
-  "Double": "double",
-  "Void": "void"
-};
-
-final resultConverters = {
-  "String": (String resultVar) => "return strRes",
-  "Object": (String resultVar) =>
-      "return JniObject.of(_env, $resultVar, nullptr)",
-  "Boolean": (String resultVar) => "return $resultVar != 0",
-};
-
-final invokeResultConverters = {
-  "String": (String resultVar) => "return strRes",
-  "Object": (String resultVar) =>
-      "return JniObject.of(env, $resultVar, nullptr)",
-  "Boolean": (String resultVar) => "return $resultVar != 0",
-};
-
-void main(List<String> args) {
-  final script = io.Platform.script;
-  final scriptDir = dirname(script.toFilePath(windows: io.Platform.isWindows));
-  String getTemplate(String name) {
-    return io.File(join(scriptDir, 'templates', name)).readAsStringSync();
-  }
-
-  final methodTemplates = getTemplate('jni_object_methods.dart.tmpl');
-  final fieldTemplates = getTemplate('jni_object_fields.dart.tmpl');
-  final invokeTemplates = getTemplate('invoke_static_methods.dart.tmpl');
-  final retrieveTemplates = getTemplate('retrieve_static_fields.dart.tmpl');
-
-  final outputDir = join("lib", "src");
-  final sInst = StringBuffer();
-  final sStatic = StringBuffer();
-  final sInvoke = StringBuffer();
-  final outPutPaths = {
-    sInst: join(outputDir, "jni_object_methods_generated.dart"),
-    sStatic: join(outputDir, "jni_class_methods_generated.dart"),
-    sInvoke: join(outputDir, "direct_methods_generated.dart")
-  };
-  for (final s in [sInst, sStatic, sInvoke]) {
-    s.write(_license);
-    s.write("// Autogenerated; DO NOT EDIT\n"
-        "// Generated by running the script in tool/gen_aux_methods.dart\n");
-    s.write("// coverage:ignore-file\n");
-  }
-
-  sInst.write("part of 'jni_object.dart';\n\n");
-  sStatic.write("part of 'jni_class.dart';\n\n");
-  sInvoke.write("part of 'jni.dart';\n\n");
-
-  sInst.write("extension JniObjectCallMethods on JniObject {");
-  sStatic.write("extension JniClassCallMethods on JniClass {");
-  sInvoke.write("extension JniInvokeMethods on Jni {");
-
-  for (final t in targetTypes.keys) {
-    void write(String template) {
-      final resultConverter =
-          resultConverters[t] ?? (resultVar) => "return $resultVar";
-      final skel = template
-          .replaceAll("{TYPE}", t == "String" ? "Object" : t)
-          .replaceAll("{PTYPE}", t)
-          .replaceAll("{TARGET_TYPE}", targetTypes[t]!)
-          .replaceAll("{RESULT}", resultConverter("result"))
-          .replaceAll(
-              "{STR_REF_DEL}",
-              t == "String"
-                  ? "final strRes = _env.asDartString(result, "
-                      "deleteOriginal: true);"
-                  : "");
-      final inst_ =
-          skel.replaceAll("{STATIC}", "").replaceAll("{THIS}", "_obj");
-      final static_ =
-          skel.replaceAll("{STATIC}", "Static").replaceAll("{THIS}", "_cls");
-      sInst.write(inst_);
-      sStatic.write(static_);
-    }
-
-    write(methodTemplates);
-    if (t != "Void") {
-      write(fieldTemplates);
-    }
-    final invokeResultConverter =
-        (invokeResultConverters[t] ?? (String r) => "return $r");
-    void writeI(String template) {
-      final replaced = template
-          .replaceAll("{TYPE}", t == "String" ? "Object" : t)
-          .replaceAll("{PTYPE}", t)
-          .replaceAll("{TARGET_TYPE}", targetTypes[t]!)
-          .replaceAll("{CLS_REF_DEL}",
-              t == "Object" || t == "String" ? "" : "env.DeleteLocalRef(cls);")
-          .replaceAll(
-              "{STR_REF_DEL}",
-              t == "String"
-                  ? "final strRes = env.asDartString(result, "
-                      "deleteOriginal: true);"
-                  : "")
-          .replaceAll("{INVOKE_RESULT}", invokeResultConverter("result"));
-      sInvoke.write(replaced);
-    }
-
-    writeI(invokeTemplates);
-    if (t != "Void") {
-      writeI(retrieveTemplates);
-    }
-  }
-  sInst.write("}");
-  sStatic.write("}");
-  sInvoke.write("}");
-  for (final s in [sInst, sStatic, sInvoke]) {
-    final outputFile = io.File(outPutPaths[s]!);
-    outputFile.writeAsStringSync(s.toString(), flush: true);
-  }
-  io.stderr.write("Running dart format..\n");
-  io.Process.run("dart", ["format", ...outPutPaths.values]);
-}
diff --git a/pkgs/jni/tool/templates/invoke_static_methods.dart.tmpl b/pkgs/jni/tool/templates/invoke_static_methods.dart.tmpl
deleted file mode 100644
index 7372d4c..0000000
--- a/pkgs/jni/tool/templates/invoke_static_methods.dart.tmpl
+++ /dev/null
@@ -1,29 +0,0 @@
-  {TARGET_TYPE} invoke{PTYPE}Method(String className, String methodName, String signature, List<dynamic> args) {
-	return using((Arena arena) {
-		final env = getEnv();
-		final classNameChars = className.toNativeChars(arena);
-		final methodNameChars = methodName.toNativeChars(arena);
-		final signatureChars = signature.toNativeChars(arena);
-		final cls = _bindings.LoadClass(classNameChars);
-		if (cls == nullptr) {
-			env.checkException();
-		}
-		final methodID = env.GetStaticMethodID(cls, methodNameChars, signatureChars);
-		if (methodID == nullptr) {
-			try {
-				env.checkException();
-			} catch (e) {
-				env.DeleteLocalRef(cls);
-				rethrow;
-			}
-		}
-		final jvArgs = JValueArgs(args, env, arena);
-		final result = env.CallStatic{TYPE}MethodA(cls, methodID, jvArgs.values);
-		jvArgs.disposeIn(env);
-		{CLS_REF_DEL}
-		{STR_REF_DEL}
-		env.checkException();
-		{INVOKE_RESULT};
-	});
-  }
-
diff --git a/pkgs/jni/tool/templates/jni_object_fields.dart.tmpl b/pkgs/jni/tool/templates/jni_object_fields.dart.tmpl
deleted file mode 100644
index e7ea50b..0000000
--- a/pkgs/jni/tool/templates/jni_object_fields.dart.tmpl
+++ /dev/null
@@ -1,16 +0,0 @@
-  /// Retrieves the value of the field denoted by [fieldID]
-  {TARGET_TYPE} get{STATIC}{PTYPE}Field(JFieldID fieldID) {
-    _checkDeleted();
-	final result = _env.Get{STATIC}{TYPE}Field({THIS}, fieldID);
-	{STR_REF_DEL}
-	_env.checkException();
-	{RESULT};
-  }
-
-  /// Retrieve field of given [name] and [signature]
-  {TARGET_TYPE} get{STATIC}{PTYPE}FieldByName(String name, String signature) {
-	final fID = get{STATIC}FieldID(name, signature);
-	final result = get{STATIC}{PTYPE}Field(fID);
-	return result;
-  }
-
diff --git a/pkgs/jni/tool/templates/jni_object_methods.dart.tmpl b/pkgs/jni/tool/templates/jni_object_methods.dart.tmpl
deleted file mode 100644
index 462a0d4..0000000
--- a/pkgs/jni/tool/templates/jni_object_methods.dart.tmpl
+++ /dev/null
@@ -1,23 +0,0 @@
-  /// Calls method pointed to by [methodID] with [args] as arguments
-  {TARGET_TYPE} call{STATIC}{PTYPE}Method(JMethodID methodID, List<dynamic> args) {
-    _checkDeleted();
-    final jvArgs = JValueArgs(args, _env);
-    final result = _env.Call{STATIC}{TYPE}MethodA({THIS}, methodID, jvArgs.values);
-	jvArgs.disposeIn(_env);
-    calloc.free(jvArgs.values);
-	{STR_REF_DEL}
-    _env.checkException();
-    {RESULT};
-  }
-
-  /// Looks up method with [name] and [signature], calls it with [args] as arguments.
-  /// If calling the same method multiple times, consider using [get{STATIC}MethodID]
-  /// and [call{STATIC}{PTYPE}Method].
-  {TARGET_TYPE} call{STATIC}{PTYPE}MethodByName(
-      String name, String signature, List<dynamic> args) {
-    final mID = get{STATIC}MethodID(name, signature);
-    final result = call{STATIC}{PTYPE}Method(mID, args);
-    return result;
-  }
-
-
diff --git a/pkgs/jni/tool/templates/retrieve_static_fields.dart.tmpl b/pkgs/jni/tool/templates/retrieve_static_fields.dart.tmpl
deleted file mode 100644
index b83e94c..0000000
--- a/pkgs/jni/tool/templates/retrieve_static_fields.dart.tmpl
+++ /dev/null
@@ -1,28 +0,0 @@
-  {TARGET_TYPE} retrieve{PTYPE}Field(String className, String fieldName, String signature) {
-	return using((Arena arena) {
-		final arena = Arena();
-		final env = getEnv();
-		final classNameChars = className.toNativeChars(arena);
-		final fieldNameChars = fieldName.toNativeChars(arena);
-		final signatueChars = signature.toNativeChars(arena);
-		final cls = _bindings.LoadClass(classNameChars);
-		if (cls == nullptr) {
-			env.checkException();
-		}
-		final fieldID = env.GetStaticFieldID(cls, fieldNameChars, signatueChars);
-		if (fieldID == nullptr) {
-			try {
-				env.checkException();
-			} catch (e) {
-				env.DeleteLocalRef(cls);
-				rethrow;
-			}
-		}
-		final result = env.GetStatic{TYPE}Field(cls, fieldID);
-		{CLS_REF_DEL}
-		{STR_REF_DEL}
-		env.checkException();
-		{INVOKE_RESULT};
-	});
-  }
-
diff --git a/pkgs/jnigen/CHANGELOG.md b/pkgs/jnigen/CHANGELOG.md
new file mode 100644
index 0000000..22eaa56
--- /dev/null
+++ b/pkgs/jnigen/CHANGELOG.md
@@ -0,0 +1,2 @@
+## 0.1.0
+* Initial version: Basic bindings generation, maven and android utilities
diff --git a/pkgs/jnigen/analysis_options.yaml b/pkgs/jnigen/analysis_options.yaml
index e714a82..543efa0 100644
--- a/pkgs/jnigen/analysis_options.yaml
+++ b/pkgs/jnigen/analysis_options.yaml
@@ -5,7 +5,7 @@
 include: package:lints/recommended.yaml
 
 analyzer:
-  exclude: [build/**, examples/**]
+  exclude: [build/**, example/**]
   language:
     strict-raw-types: true
     strict-inference: true
diff --git a/pkgs/jnigen/example/README.md b/pkgs/jnigen/example/README.md
new file mode 100644
index 0000000..821e883
--- /dev/null
+++ b/pkgs/jnigen/example/README.md
@@ -0,0 +1,42 @@
+## jnigen examples
+
+This directory contains examples on how to use jnigen.
+
+| Directory | Description |
+| ------- | --------- |
+| [in_app_java](in_app_java/) | Demonstrates how to include custom Java code in Flutter application and call that using jnigen |
+| [pdfbox_plugin](pdfbox_plugin/) | Example of a flutter plugin which provides bindings to Apache PDFBox library. Currently works on Flutter desktop and Dart standalone on linux. |
+| [notification_plugin](notification_plugin/) | Example of a reusable Flutter plugin with custom Java code which uses Android libraries. |
+
+We intend to cover few more use cases in future.
+
+Currently supported platforms are Linux (Standalone, Flutter), and Android (Flutter).
+
+## Creating a jnigen-based plugin from scratch
+
+### Dart package (Standalone only)
+* Create dart package, add `jni` as dependency and `jnigen` as dev dependency.
+* Write the jnigen config similar to [the one in pdfbox_plugin](pdfbox_plugin/jnigen.yaml).
+* Generate JNI bindings by running `dart run jnigen --config jnigen.yaml`.
+
+* In the CLI project which uses this package, add this package, and `jni` as a dependency.
+* Run `dart run jni:setup && dart run jni:setup -p <generated_package_name>` to build native libraries for JNI base library and your package respectively.
+* Import the package. See [pdf_info.dart](pdfbox_plugin/dart_example/bin/pdf_info.dart) for how to use the JNI from dart standalone.
+
+### Flutter FFI plugin
+Flutter FFI plugin has the advantage of bundling the required native libraries along with Android / Linux Desktop app.
+
+To create an FFI plugin with JNI bindings:
+
+* Create a plugin using `plugin_ffi` template.
+* Remove ffigen-specific files.
+* Follow the above steps to generate JNI bindings. The plugin can be used from a flutter project.
+
+* To use the plugin from Dart projects as well, comment-out or remove flutter SDK requirements from the pubspec.
+
+### Android plugin with custom Java code
+* Create an FFI plugin with Android as the only platform.
+* Build the example/ Android project using command `flutter build apk`. After a release build is done, jnigen can use a gradle stub to collect compile classpaths.
+* Write your custom Java code in `android/src/main/java` hierarchy of the plugin.
+* Generate JNI bindings as described above. See [notification_plugin/jnigen.yaml](notification_plugin/jnigen.yaml) for example configuration.
+
diff --git a/pkgs/jnigen/examples/in_app_java/.gitignore b/pkgs/jnigen/example/in_app_java/.gitignore
similarity index 100%
rename from pkgs/jnigen/examples/in_app_java/.gitignore
rename to pkgs/jnigen/example/in_app_java/.gitignore
diff --git a/pkgs/jnigen/examples/in_app_java/.metadata b/pkgs/jnigen/example/in_app_java/.metadata
similarity index 100%
rename from pkgs/jnigen/examples/in_app_java/.metadata
rename to pkgs/jnigen/example/in_app_java/.metadata
diff --git a/pkgs/jnigen/examples/in_app_java/README.md b/pkgs/jnigen/example/in_app_java/README.md
similarity index 100%
rename from pkgs/jnigen/examples/in_app_java/README.md
rename to pkgs/jnigen/example/in_app_java/README.md
diff --git a/pkgs/jnigen/examples/in_app_java/analysis_options.yaml b/pkgs/jnigen/example/in_app_java/analysis_options.yaml
similarity index 100%
rename from pkgs/jnigen/examples/in_app_java/analysis_options.yaml
rename to pkgs/jnigen/example/in_app_java/analysis_options.yaml
diff --git a/pkgs/jnigen/examples/in_app_java/android/.gitignore b/pkgs/jnigen/example/in_app_java/android/.gitignore
similarity index 100%
rename from pkgs/jnigen/examples/in_app_java/android/.gitignore
rename to pkgs/jnigen/example/in_app_java/android/.gitignore
diff --git a/pkgs/jnigen/examples/in_app_java/android/app/build.gradle b/pkgs/jnigen/example/in_app_java/android/app/build.gradle
similarity index 100%
rename from pkgs/jnigen/examples/in_app_java/android/app/build.gradle
rename to pkgs/jnigen/example/in_app_java/android/app/build.gradle
diff --git a/pkgs/jnigen/examples/in_app_java/android/app/src/debug/AndroidManifest.xml b/pkgs/jnigen/example/in_app_java/android/app/src/debug/AndroidManifest.xml
similarity index 100%
rename from pkgs/jnigen/examples/in_app_java/android/app/src/debug/AndroidManifest.xml
rename to pkgs/jnigen/example/in_app_java/android/app/src/debug/AndroidManifest.xml
diff --git a/pkgs/jnigen/examples/in_app_java/android/app/src/main/AndroidManifest.xml b/pkgs/jnigen/example/in_app_java/android/app/src/main/AndroidManifest.xml
similarity index 100%
rename from pkgs/jnigen/examples/in_app_java/android/app/src/main/AndroidManifest.xml
rename to pkgs/jnigen/example/in_app_java/android/app/src/main/AndroidManifest.xml
diff --git a/pkgs/jnigen/examples/in_app_java/android/app/src/main/java/com/example/in_app_java/AndroidUtils.java b/pkgs/jnigen/example/in_app_java/android/app/src/main/java/com/example/in_app_java/AndroidUtils.java
similarity index 100%
rename from pkgs/jnigen/examples/in_app_java/android/app/src/main/java/com/example/in_app_java/AndroidUtils.java
rename to pkgs/jnigen/example/in_app_java/android/app/src/main/java/com/example/in_app_java/AndroidUtils.java
diff --git a/pkgs/jnigen/examples/in_app_java/android/app/src/main/kotlin/com/example/in_app_java/MainActivity.kt b/pkgs/jnigen/example/in_app_java/android/app/src/main/kotlin/com/example/in_app_java/MainActivity.kt
similarity index 100%
rename from pkgs/jnigen/examples/in_app_java/android/app/src/main/kotlin/com/example/in_app_java/MainActivity.kt
rename to pkgs/jnigen/example/in_app_java/android/app/src/main/kotlin/com/example/in_app_java/MainActivity.kt
diff --git a/pkgs/jnigen/examples/in_app_java/android/app/src/main/res/drawable-v21/launch_background.xml b/pkgs/jnigen/example/in_app_java/android/app/src/main/res/drawable-v21/launch_background.xml
similarity index 100%
rename from pkgs/jnigen/examples/in_app_java/android/app/src/main/res/drawable-v21/launch_background.xml
rename to pkgs/jnigen/example/in_app_java/android/app/src/main/res/drawable-v21/launch_background.xml
diff --git a/pkgs/jnigen/examples/in_app_java/android/app/src/main/res/drawable/launch_background.xml b/pkgs/jnigen/example/in_app_java/android/app/src/main/res/drawable/launch_background.xml
similarity index 100%
rename from pkgs/jnigen/examples/in_app_java/android/app/src/main/res/drawable/launch_background.xml
rename to pkgs/jnigen/example/in_app_java/android/app/src/main/res/drawable/launch_background.xml
diff --git a/pkgs/jnigen/examples/in_app_java/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/pkgs/jnigen/example/in_app_java/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
similarity index 100%
rename from pkgs/jnigen/examples/in_app_java/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
rename to pkgs/jnigen/example/in_app_java/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jnigen/examples/in_app_java/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/pkgs/jnigen/example/in_app_java/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
similarity index 100%
rename from pkgs/jnigen/examples/in_app_java/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
rename to pkgs/jnigen/example/in_app_java/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jnigen/examples/in_app_java/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/pkgs/jnigen/example/in_app_java/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
similarity index 100%
rename from pkgs/jnigen/examples/in_app_java/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
rename to pkgs/jnigen/example/in_app_java/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jnigen/examples/in_app_java/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/pkgs/jnigen/example/in_app_java/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
similarity index 100%
rename from pkgs/jnigen/examples/in_app_java/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
rename to pkgs/jnigen/example/in_app_java/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jnigen/examples/in_app_java/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/pkgs/jnigen/example/in_app_java/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
similarity index 100%
rename from pkgs/jnigen/examples/in_app_java/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
rename to pkgs/jnigen/example/in_app_java/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jnigen/examples/in_app_java/android/app/src/main/res/values-night/styles.xml b/pkgs/jnigen/example/in_app_java/android/app/src/main/res/values-night/styles.xml
similarity index 100%
rename from pkgs/jnigen/examples/in_app_java/android/app/src/main/res/values-night/styles.xml
rename to pkgs/jnigen/example/in_app_java/android/app/src/main/res/values-night/styles.xml
diff --git a/pkgs/jnigen/examples/in_app_java/android/app/src/main/res/values/styles.xml b/pkgs/jnigen/example/in_app_java/android/app/src/main/res/values/styles.xml
similarity index 100%
rename from pkgs/jnigen/examples/in_app_java/android/app/src/main/res/values/styles.xml
rename to pkgs/jnigen/example/in_app_java/android/app/src/main/res/values/styles.xml
diff --git a/pkgs/jnigen/examples/in_app_java/android/app/src/profile/AndroidManifest.xml b/pkgs/jnigen/example/in_app_java/android/app/src/profile/AndroidManifest.xml
similarity index 100%
rename from pkgs/jnigen/examples/in_app_java/android/app/src/profile/AndroidManifest.xml
rename to pkgs/jnigen/example/in_app_java/android/app/src/profile/AndroidManifest.xml
diff --git a/pkgs/jnigen/examples/in_app_java/android/build.gradle b/pkgs/jnigen/example/in_app_java/android/build.gradle
similarity index 100%
rename from pkgs/jnigen/examples/in_app_java/android/build.gradle
rename to pkgs/jnigen/example/in_app_java/android/build.gradle
diff --git a/pkgs/jnigen/examples/in_app_java/android/gradle.properties b/pkgs/jnigen/example/in_app_java/android/gradle.properties
similarity index 100%
rename from pkgs/jnigen/examples/in_app_java/android/gradle.properties
rename to pkgs/jnigen/example/in_app_java/android/gradle.properties
diff --git a/pkgs/jnigen/examples/in_app_java/android/gradle/wrapper/gradle-wrapper.properties b/pkgs/jnigen/example/in_app_java/android/gradle/wrapper/gradle-wrapper.properties
similarity index 100%
rename from pkgs/jnigen/examples/in_app_java/android/gradle/wrapper/gradle-wrapper.properties
rename to pkgs/jnigen/example/in_app_java/android/gradle/wrapper/gradle-wrapper.properties
diff --git a/pkgs/jnigen/examples/in_app_java/android/settings.gradle b/pkgs/jnigen/example/in_app_java/android/settings.gradle
similarity index 100%
rename from pkgs/jnigen/examples/in_app_java/android/settings.gradle
rename to pkgs/jnigen/example/in_app_java/android/settings.gradle
diff --git a/pkgs/jnigen/examples/in_app_java/jnigen.yaml b/pkgs/jnigen/example/in_app_java/jnigen.yaml
similarity index 100%
rename from pkgs/jnigen/examples/in_app_java/jnigen.yaml
rename to pkgs/jnigen/example/in_app_java/jnigen.yaml
diff --git a/pkgs/jnigen/example/in_app_java/lib/android_utils/_init.dart b/pkgs/jnigen/example/in_app_java/lib/android_utils/_init.dart
new file mode 100644
index 0000000..656ca5a
--- /dev/null
+++ b/pkgs/jnigen/example/in_app_java/lib/android_utils/_init.dart
@@ -0,0 +1,5 @@
+import "dart:ffi";
+import "package:jni/internal_helpers_for_jnigen.dart";
+
+final Pointer<T> Function<T extends NativeType>(String sym) jniLookup =
+    ProtectedJniExtensions.initGeneratedLibrary("android_utils");
diff --git a/pkgs/jnigen/examples/in_app_java/lib/android_utils/com/example/in_app_java.dart b/pkgs/jnigen/example/in_app_java/lib/android_utils/com/example/in_app_java.dart
similarity index 69%
rename from pkgs/jnigen/examples/in_app_java/lib/android_utils/com/example/in_app_java.dart
rename to pkgs/jnigen/example/in_app_java/lib/android_utils/com/example/in_app_java.dart
index 3412fc1..f638a75 100644
--- a/pkgs/jnigen/examples/in_app_java/lib/android_utils/com/example/in_app_java.dart
+++ b/pkgs/jnigen/example/in_app_java/lib/android_utils/com/example/in_app_java.dart
@@ -8,24 +8,25 @@
 // ignore_for_file: unused_element
 
 import "dart:ffi" as ffi;
-
 import "package:jni/jni.dart" as jni;
 
-import "../../init.dart" show jlookup;
+import "../../_init.dart" show jniLookup;
 
 /// from: com.example.in_app_java.AndroidUtils
-class AndroidUtils extends jni.JlObject {
+class AndroidUtils extends jni.JniObject {
   AndroidUtils.fromRef(ffi.Pointer<ffi.Void> ref) : super.fromRef(ref);
 
   static final _ctor =
-      jlookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function()>>(
+      jniLookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function()>>(
               "com_example_in_app_java_AndroidUtils_ctor")
           .asFunction<ffi.Pointer<ffi.Void> Function()>();
 
   /// from: public void <init>()
-  AndroidUtils() : super.fromRef(_ctor());
+  AndroidUtils() : super.fromRef(_ctor()) {
+    jni.Jni.env.checkException();
+  }
 
-  static final _showToast = jlookup<
+  static final _showToast = jniLookup<
           ffi.NativeFunction<
               ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
                   ffi.Int32)>>("com_example_in_app_java_AndroidUtils_showToast")
@@ -34,6 +35,10 @@
 
   /// from: static void showToast(android.app.Activity mainActivity, java.lang.CharSequence text, int duration)
   static void showToast(
-          jni.JlObject mainActivity, jni.JlObject text, int duration) =>
-      _showToast(mainActivity.reference, text.reference, duration);
+      jni.JniObject mainActivity, jni.JniObject text, int duration) {
+    final result__ =
+        _showToast(mainActivity.reference, text.reference, duration);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 }
diff --git a/pkgs/jnigen/examples/in_app_java/lib/main.dart b/pkgs/jnigen/example/in_app_java/lib/main.dart
similarity index 89%
rename from pkgs/jnigen/examples/in_app_java/lib/main.dart
rename to pkgs/jnigen/example/in_app_java/lib/main.dart
index 10081f5..4ca151f 100644
--- a/pkgs/jnigen/examples/in_app_java/lib/main.dart
+++ b/pkgs/jnigen/example/in_app_java/lib/main.dart
@@ -10,12 +10,10 @@
 // more customization in future.
 import 'android_utils/com/example/in_app_java.dart';
 
-JlObject activity = JlObject.fromRef(Jni.getInstance().getCurrentActivity());
+JniObject activity = JniObject.fromRef(Jni.getCurrentActivity());
 
 void showToast(String text) {
-  final jstr = JlString.fromString(text);
-  AndroidUtils.showToast(activity, jstr, 0);
-  jstr.delete();
+  AndroidUtils.showToast(activity, text.jniString(), 0);
 }
 
 void main() {
diff --git a/pkgs/jnigen/examples/in_app_java/pubspec.yaml b/pkgs/jnigen/example/in_app_java/pubspec.yaml
similarity index 100%
rename from pkgs/jnigen/examples/in_app_java/pubspec.yaml
rename to pkgs/jnigen/example/in_app_java/pubspec.yaml
diff --git a/pkgs/jnigen/examples/in_app_java/src/android_utils/CMakeLists.txt b/pkgs/jnigen/example/in_app_java/src/android_utils/CMakeLists.txt
similarity index 100%
rename from pkgs/jnigen/examples/in_app_java/src/android_utils/CMakeLists.txt
rename to pkgs/jnigen/example/in_app_java/src/android_utils/CMakeLists.txt
diff --git a/pkgs/jnigen/examples/in_app_java/src/android_utils/android_utils.c b/pkgs/jnigen/example/in_app_java/src/android_utils/android_utils.c
similarity index 79%
rename from pkgs/jnigen/examples/in_app_java/src/android_utils/android_utils.c
rename to pkgs/jnigen/example/in_app_java/src/android_utils/android_utils.c
index f41c216..041a9d7 100644
--- a/pkgs/jnigen/examples/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 "dartjni.h"
 
 thread_local JNIEnv *jniEnv;
-struct jni_context jni;
+JniContext jni;
 
-struct jni_context (*context_getter)(void);
+JniContext (*context_getter)(void);
 JNIEnv *(*env_getter)(void);
 
-void setJniGetters(struct jni_context (*cg)(void),
+void setJniGetters(JniContext (*cg)(void),
         JNIEnv *(*eg)(void)) {
     context_getter = cg;
     env_getter = eg;
@@ -24,7 +24,9 @@
 jobject com_example_in_app_java_AndroidUtils_ctor() {
     load_env();
     load_class_gr(&_c_com_example_in_app_java_AndroidUtils, "com/example/in_app_java/AndroidUtils");
+    if (_c_com_example_in_app_java_AndroidUtils == NULL) return (jobject)0;
     load_method(_c_com_example_in_app_java_AndroidUtils, &_m_com_example_in_app_java_AndroidUtils_ctor, "<init>", "()V");
+    if (_m_com_example_in_app_java_AndroidUtils_ctor == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->NewObject(jniEnv, _c_com_example_in_app_java_AndroidUtils, _m_com_example_in_app_java_AndroidUtils_ctor);
     return to_global_ref(_result);
 }
@@ -34,7 +36,9 @@
 void com_example_in_app_java_AndroidUtils_showToast(jobject mainActivity, jobject text, int32_t duration) {
     load_env();
     load_class_gr(&_c_com_example_in_app_java_AndroidUtils, "com/example/in_app_java/AndroidUtils");
+    if (_c_com_example_in_app_java_AndroidUtils == NULL) return (void)0;
     load_static_method(_c_com_example_in_app_java_AndroidUtils, &_m_com_example_in_app_java_AndroidUtils_showToast, "showToast", "(Landroid/app/Activity;Ljava/lang/CharSequence;I)V");
+    if (_m_com_example_in_app_java_AndroidUtils_showToast == NULL) return (void)0;
     (*jniEnv)->CallStaticVoidMethod(jniEnv, _c_com_example_in_app_java_AndroidUtils, _m_com_example_in_app_java_AndroidUtils_showToast, mainActivity, text, duration);
 }
 
diff --git a/pkgs/jnigen/examples/in_app_java/src/android_utils/dartjni.h b/pkgs/jnigen/example/in_app_java/src/android_utils/dartjni.h
similarity index 81%
rename from pkgs/jnigen/examples/in_app_java/src/android_utils/dartjni.h
rename to pkgs/jnigen/example/in_app_java/src/android_utils/dartjni.h
index cd94b15..0ce5069 100644
--- a/pkgs/jnigen/examples/in_app_java/src/android_utils/dartjni.h
+++ b/pkgs/jnigen/example/in_app_java/src/android_utils/dartjni.h
@@ -2,6 +2,8 @@
 // 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.
 
+#pragma once
+
 #include <jni.h>
 #include <stdint.h>
 #include <stdio.h>
@@ -38,17 +40,17 @@
 #define __ENVP_CAST (void **)
 #endif
 
-struct jni_context {
+typedef struct JniContext {
 	JavaVM *jvm;
 	jobject classLoader;
 	jmethodID loadClassMethod;
 	jobject currentActivity;
 	jobject appContext;
-};
+} JniContext;
 
 extern thread_local JNIEnv *jniEnv;
 
-extern struct jni_context jni;
+extern JniContext jni;
 
 enum DartJniLogLevel {
 	JNI_VERBOSE = 2,
@@ -58,10 +60,25 @@
 	JNI_ERROR
 };
 
-FFI_PLUGIN_EXPORT struct jni_context GetJniContext();
+enum JniType {
+	boolType = 0,
+	byteType = 1,
+	shortType = 2,
+	charType = 3,
+	intType = 4,
+	longType = 5,
+	floatType = 6,
+	doubleType = 7,
+	objectType = 8,
+	voidType = 9,
+};
+
+FFI_PLUGIN_EXPORT JniContext GetJniContext();
 
 FFI_PLUGIN_EXPORT JavaVM *GetJavaVM(void);
 
+FFI_PLUGIN_EXPORT int DestroyJavaVM();
+
 FFI_PLUGIN_EXPORT JNIEnv *GetJniEnv(void);
 
 FFI_PLUGIN_EXPORT JNIEnv *SpawnJvm(JavaVMInitArgs *args);
@@ -74,26 +91,16 @@
 
 FFI_PLUGIN_EXPORT jobject GetCurrentActivity(void);
 
-FFI_PLUGIN_EXPORT void SetJNILogging(int level);
+/// For use by jni_gen's generated code
+/// don't use these.
 
-FFI_PLUGIN_EXPORT jstring ToJavaString(char *str);
-
-FFI_PLUGIN_EXPORT const char *GetJavaStringChars(jstring jstr);
-
-FFI_PLUGIN_EXPORT void ReleaseJavaStringChars(jstring jstr, const char *buf);
-
-// These 2 are the function pointer variables defined and exported by
-// the generated C files.
-//
-// initGeneratedLibrary function in Jni class will set these to
-// corresponding functions to the implementations from `dartjni` base library
-// which initializes and manages the JNI.
-extern struct jni_context (*context_getter)(void);
+// these 2 fn ptr vars will be defined by generated code library
+extern JniContext (*context_getter)(void);
 extern JNIEnv *(*env_getter)(void);
 
-// This function will be exported by generated code library and will set the
-// above 2 variables.
-FFI_PLUGIN_EXPORT void setJniGetters(struct jni_context (*cg)(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),
 		JNIEnv *(*eg)(void));
 
 // `static inline` because `inline` doesn't work, it may still not
@@ -101,6 +108,7 @@
 //
 // 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) {
 #ifdef __ANDROID__
 	jstring className = (*jniEnv)->NewStringUTF(jniEnv, name);
diff --git a/pkgs/jnigen/examples/in_app_java/tool/generate_bindings.dart b/pkgs/jnigen/example/in_app_java/tool/generate_bindings.dart
similarity index 100%
rename from pkgs/jnigen/examples/in_app_java/tool/generate_bindings.dart
rename to pkgs/jnigen/example/in_app_java/tool/generate_bindings.dart
diff --git a/pkgs/jnigen/examples/notification_plugin/.gitignore b/pkgs/jnigen/example/notification_plugin/.gitignore
similarity index 100%
rename from pkgs/jnigen/examples/notification_plugin/.gitignore
rename to pkgs/jnigen/example/notification_plugin/.gitignore
diff --git a/pkgs/jnigen/examples/notification_plugin/.metadata b/pkgs/jnigen/example/notification_plugin/.metadata
similarity index 100%
rename from pkgs/jnigen/examples/notification_plugin/.metadata
rename to pkgs/jnigen/example/notification_plugin/.metadata
diff --git a/pkgs/jnigen/examples/notification_plugin/README.md b/pkgs/jnigen/example/notification_plugin/README.md
similarity index 100%
rename from pkgs/jnigen/examples/notification_plugin/README.md
rename to pkgs/jnigen/example/notification_plugin/README.md
diff --git a/pkgs/jnigen/examples/notification_plugin/analysis_options.yaml b/pkgs/jnigen/example/notification_plugin/analysis_options.yaml
similarity index 100%
rename from pkgs/jnigen/examples/notification_plugin/analysis_options.yaml
rename to pkgs/jnigen/example/notification_plugin/analysis_options.yaml
diff --git a/pkgs/jnigen/examples/notification_plugin/android/.gitignore b/pkgs/jnigen/example/notification_plugin/android/.gitignore
similarity index 100%
rename from pkgs/jnigen/examples/notification_plugin/android/.gitignore
rename to pkgs/jnigen/example/notification_plugin/android/.gitignore
diff --git a/pkgs/jnigen/examples/notification_plugin/android/build.gradle b/pkgs/jnigen/example/notification_plugin/android/build.gradle
similarity index 100%
rename from pkgs/jnigen/examples/notification_plugin/android/build.gradle
rename to pkgs/jnigen/example/notification_plugin/android/build.gradle
diff --git a/pkgs/jnigen/examples/notification_plugin/android/settings.gradle b/pkgs/jnigen/example/notification_plugin/android/settings.gradle
similarity index 100%
rename from pkgs/jnigen/examples/notification_plugin/android/settings.gradle
rename to pkgs/jnigen/example/notification_plugin/android/settings.gradle
diff --git a/pkgs/jnigen/examples/notification_plugin/android/src/main/AndroidManifest.xml b/pkgs/jnigen/example/notification_plugin/android/src/main/AndroidManifest.xml
similarity index 100%
rename from pkgs/jnigen/examples/notification_plugin/android/src/main/AndroidManifest.xml
rename to pkgs/jnigen/example/notification_plugin/android/src/main/AndroidManifest.xml
diff --git a/pkgs/jnigen/examples/notification_plugin/android/src/main/java/com/example/notification_plugin/Notifications.java b/pkgs/jnigen/example/notification_plugin/android/src/main/java/com/example/notification_plugin/Notifications.java
similarity index 100%
rename from pkgs/jnigen/examples/notification_plugin/android/src/main/java/com/example/notification_plugin/Notifications.java
rename to pkgs/jnigen/example/notification_plugin/android/src/main/java/com/example/notification_plugin/Notifications.java
diff --git a/pkgs/jnigen/examples/notification_plugin/example/.gitignore b/pkgs/jnigen/example/notification_plugin/example/.gitignore
similarity index 100%
rename from pkgs/jnigen/examples/notification_plugin/example/.gitignore
rename to pkgs/jnigen/example/notification_plugin/example/.gitignore
diff --git a/pkgs/jnigen/examples/notification_plugin/example/README.md b/pkgs/jnigen/example/notification_plugin/example/README.md
similarity index 100%
rename from pkgs/jnigen/examples/notification_plugin/example/README.md
rename to pkgs/jnigen/example/notification_plugin/example/README.md
diff --git a/pkgs/jnigen/examples/notification_plugin/example/analysis_options.yaml b/pkgs/jnigen/example/notification_plugin/example/analysis_options.yaml
similarity index 100%
rename from pkgs/jnigen/examples/notification_plugin/example/analysis_options.yaml
rename to pkgs/jnigen/example/notification_plugin/example/analysis_options.yaml
diff --git a/pkgs/jnigen/examples/notification_plugin/example/android/.gitignore b/pkgs/jnigen/example/notification_plugin/example/android/.gitignore
similarity index 100%
rename from pkgs/jnigen/examples/notification_plugin/example/android/.gitignore
rename to pkgs/jnigen/example/notification_plugin/example/android/.gitignore
diff --git a/pkgs/jnigen/examples/notification_plugin/example/android/app/build.gradle b/pkgs/jnigen/example/notification_plugin/example/android/app/build.gradle
similarity index 100%
rename from pkgs/jnigen/examples/notification_plugin/example/android/app/build.gradle
rename to pkgs/jnigen/example/notification_plugin/example/android/app/build.gradle
diff --git a/pkgs/jnigen/examples/notification_plugin/example/android/app/src/debug/AndroidManifest.xml b/pkgs/jnigen/example/notification_plugin/example/android/app/src/debug/AndroidManifest.xml
similarity index 100%
rename from pkgs/jnigen/examples/notification_plugin/example/android/app/src/debug/AndroidManifest.xml
rename to pkgs/jnigen/example/notification_plugin/example/android/app/src/debug/AndroidManifest.xml
diff --git a/pkgs/jnigen/examples/notification_plugin/example/android/app/src/main/AndroidManifest.xml b/pkgs/jnigen/example/notification_plugin/example/android/app/src/main/AndroidManifest.xml
similarity index 100%
rename from pkgs/jnigen/examples/notification_plugin/example/android/app/src/main/AndroidManifest.xml
rename to pkgs/jnigen/example/notification_plugin/example/android/app/src/main/AndroidManifest.xml
diff --git a/pkgs/jnigen/examples/notification_plugin/example/android/app/src/main/kotlin/com/example/notification_plugin_example/MainActivity.kt b/pkgs/jnigen/example/notification_plugin/example/android/app/src/main/kotlin/com/example/notification_plugin_example/MainActivity.kt
similarity index 100%
rename from pkgs/jnigen/examples/notification_plugin/example/android/app/src/main/kotlin/com/example/notification_plugin_example/MainActivity.kt
rename to pkgs/jnigen/example/notification_plugin/example/android/app/src/main/kotlin/com/example/notification_plugin_example/MainActivity.kt
diff --git a/pkgs/jnigen/examples/notification_plugin/example/android/app/src/main/res/drawable-v21/launch_background.xml b/pkgs/jnigen/example/notification_plugin/example/android/app/src/main/res/drawable-v21/launch_background.xml
similarity index 100%
rename from pkgs/jnigen/examples/notification_plugin/example/android/app/src/main/res/drawable-v21/launch_background.xml
rename to pkgs/jnigen/example/notification_plugin/example/android/app/src/main/res/drawable-v21/launch_background.xml
diff --git a/pkgs/jnigen/examples/notification_plugin/example/android/app/src/main/res/drawable/launch_background.xml b/pkgs/jnigen/example/notification_plugin/example/android/app/src/main/res/drawable/launch_background.xml
similarity index 100%
rename from pkgs/jnigen/examples/notification_plugin/example/android/app/src/main/res/drawable/launch_background.xml
rename to pkgs/jnigen/example/notification_plugin/example/android/app/src/main/res/drawable/launch_background.xml
diff --git a/pkgs/jnigen/examples/notification_plugin/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/pkgs/jnigen/example/notification_plugin/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
similarity index 100%
rename from pkgs/jnigen/examples/notification_plugin/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
rename to pkgs/jnigen/example/notification_plugin/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jnigen/examples/notification_plugin/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/pkgs/jnigen/example/notification_plugin/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
similarity index 100%
rename from pkgs/jnigen/examples/notification_plugin/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
rename to pkgs/jnigen/example/notification_plugin/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jnigen/examples/notification_plugin/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/pkgs/jnigen/example/notification_plugin/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
similarity index 100%
rename from pkgs/jnigen/examples/notification_plugin/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
rename to pkgs/jnigen/example/notification_plugin/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jnigen/examples/notification_plugin/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/pkgs/jnigen/example/notification_plugin/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
similarity index 100%
rename from pkgs/jnigen/examples/notification_plugin/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
rename to pkgs/jnigen/example/notification_plugin/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jnigen/examples/notification_plugin/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/pkgs/jnigen/example/notification_plugin/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
similarity index 100%
rename from pkgs/jnigen/examples/notification_plugin/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
rename to pkgs/jnigen/example/notification_plugin/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jnigen/examples/notification_plugin/example/android/app/src/main/res/values-night/styles.xml b/pkgs/jnigen/example/notification_plugin/example/android/app/src/main/res/values-night/styles.xml
similarity index 100%
rename from pkgs/jnigen/examples/notification_plugin/example/android/app/src/main/res/values-night/styles.xml
rename to pkgs/jnigen/example/notification_plugin/example/android/app/src/main/res/values-night/styles.xml
diff --git a/pkgs/jnigen/examples/notification_plugin/example/android/app/src/main/res/values/styles.xml b/pkgs/jnigen/example/notification_plugin/example/android/app/src/main/res/values/styles.xml
similarity index 100%
rename from pkgs/jnigen/examples/notification_plugin/example/android/app/src/main/res/values/styles.xml
rename to pkgs/jnigen/example/notification_plugin/example/android/app/src/main/res/values/styles.xml
diff --git a/pkgs/jnigen/examples/notification_plugin/example/android/app/src/profile/AndroidManifest.xml b/pkgs/jnigen/example/notification_plugin/example/android/app/src/profile/AndroidManifest.xml
similarity index 100%
rename from pkgs/jnigen/examples/notification_plugin/example/android/app/src/profile/AndroidManifest.xml
rename to pkgs/jnigen/example/notification_plugin/example/android/app/src/profile/AndroidManifest.xml
diff --git a/pkgs/jnigen/examples/notification_plugin/example/android/build.gradle b/pkgs/jnigen/example/notification_plugin/example/android/build.gradle
similarity index 100%
rename from pkgs/jnigen/examples/notification_plugin/example/android/build.gradle
rename to pkgs/jnigen/example/notification_plugin/example/android/build.gradle
diff --git a/pkgs/jnigen/examples/notification_plugin/example/android/gradle.properties b/pkgs/jnigen/example/notification_plugin/example/android/gradle.properties
similarity index 100%
rename from pkgs/jnigen/examples/notification_plugin/example/android/gradle.properties
rename to pkgs/jnigen/example/notification_plugin/example/android/gradle.properties
diff --git a/pkgs/jnigen/examples/notification_plugin/example/android/gradle/wrapper/gradle-wrapper.properties b/pkgs/jnigen/example/notification_plugin/example/android/gradle/wrapper/gradle-wrapper.properties
similarity index 100%
rename from pkgs/jnigen/examples/notification_plugin/example/android/gradle/wrapper/gradle-wrapper.properties
rename to pkgs/jnigen/example/notification_plugin/example/android/gradle/wrapper/gradle-wrapper.properties
diff --git a/pkgs/jnigen/examples/notification_plugin/example/android/settings.gradle b/pkgs/jnigen/example/notification_plugin/example/android/settings.gradle
similarity index 100%
rename from pkgs/jnigen/examples/notification_plugin/example/android/settings.gradle
rename to pkgs/jnigen/example/notification_plugin/example/android/settings.gradle
diff --git a/pkgs/jnigen/examples/notification_plugin/example/lib/main.dart b/pkgs/jnigen/example/notification_plugin/example/lib/main.dart
similarity index 93%
rename from pkgs/jnigen/examples/notification_plugin/example/lib/main.dart
rename to pkgs/jnigen/example/notification_plugin/example/lib/main.dart
index 4bc30d4..277ba34 100644
--- a/pkgs/jnigen/examples/notification_plugin/example/lib/main.dart
+++ b/pkgs/jnigen/example/notification_plugin/example/lib/main.dart
@@ -10,14 +10,14 @@
 // more customization in future.
 import 'package:notification_plugin/com/example/notification_plugin.dart';
 
-JlObject activity = JlObject.fromRef(Jni.getInstance().getCurrentActivity());
+JniObject activity = JniObject.fromRef(Jni.getCurrentActivity());
 
 int i = 0;
 
 void showNotification(String title, String text) {
   i = i + 1;
-  var jTitle = JlString.fromString(title);
-  var jText = JlString.fromString(text);
+  var jTitle = JniString.fromString(title);
+  var jText = JniString.fromString(text);
   Notifications.showNotification(activity, i, jTitle, jText);
   jTitle.delete();
   jText.delete();
diff --git a/pkgs/jnigen/examples/notification_plugin/example/pubspec.yaml b/pkgs/jnigen/example/notification_plugin/example/pubspec.yaml
similarity index 97%
rename from pkgs/jnigen/examples/notification_plugin/example/pubspec.yaml
rename to pkgs/jnigen/example/notification_plugin/example/pubspec.yaml
index b1f6a97..fad3bdb 100644
--- a/pkgs/jnigen/examples/notification_plugin/example/pubspec.yaml
+++ b/pkgs/jnigen/example/notification_plugin/example/pubspec.yaml
@@ -1,5 +1,5 @@
 name: notification_plugin_example
-description: Demonstrates how to use the notification_plugin plugin.
+description: Demonstrates how to use notification_plugin.
 
 # The following line prevents the package from being accidentally published to
 # pub.dev using `flutter pub publish`. This is preferred for private packages.
diff --git a/pkgs/jnigen/examples/notification_plugin/jnigen.yaml b/pkgs/jnigen/example/notification_plugin/jnigen.yaml
similarity index 100%
rename from pkgs/jnigen/examples/notification_plugin/jnigen.yaml
rename to pkgs/jnigen/example/notification_plugin/jnigen.yaml
diff --git a/pkgs/jnigen/example/notification_plugin/lib/_init.dart b/pkgs/jnigen/example/notification_plugin/lib/_init.dart
new file mode 100644
index 0000000..b45c5c3
--- /dev/null
+++ b/pkgs/jnigen/example/notification_plugin/lib/_init.dart
@@ -0,0 +1,9 @@
+// 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:jni/internal_helpers_for_jnigen.dart";
+
+final Pointer<T> Function<T extends NativeType>(String sym) jniLookup =
+    ProtectedJniExtensions.initGeneratedLibrary("notification_plugin");
diff --git a/pkgs/jnigen/examples/notification_plugin/lib/com/example/notification_plugin.dart b/pkgs/jnigen/example/notification_plugin/lib/com/example/notification_plugin.dart
similarity index 71%
rename from pkgs/jnigen/examples/notification_plugin/lib/com/example/notification_plugin.dart
rename to pkgs/jnigen/example/notification_plugin/lib/com/example/notification_plugin.dart
index f7bd86c..d0b08fb 100644
--- a/pkgs/jnigen/examples/notification_plugin/lib/com/example/notification_plugin.dart
+++ b/pkgs/jnigen/example/notification_plugin/lib/com/example/notification_plugin.dart
@@ -12,24 +12,25 @@
 // ignore_for_file: unused_element
 
 import "dart:ffi" as ffi;
-
 import "package:jni/jni.dart" as jni;
 
-import "../../init.dart" show jlookup;
+import "../../_init.dart" show jniLookup;
 
 /// from: com.example.notification_plugin.Notifications
-class Notifications extends jni.JlObject {
+class Notifications extends jni.JniObject {
   Notifications.fromRef(ffi.Pointer<ffi.Void> ref) : super.fromRef(ref);
 
   static final _ctor =
-      jlookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function()>>(
+      jniLookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function()>>(
               "com_example_notification_plugin_Notifications_ctor")
           .asFunction<ffi.Pointer<ffi.Void> Function()>();
 
   /// from: public void <init>()
-  Notifications() : super.fromRef(_ctor());
+  Notifications() : super.fromRef(_ctor()) {
+    jni.Jni.env.checkException();
+  }
 
-  static final _showNotification = jlookup<
+  static final _showNotification = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Int32,
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -39,8 +40,11 @@
               ffi.Pointer<ffi.Void>)>();
 
   /// from: static public void showNotification(android.content.Context context, int notificationID, java.lang.String title, java.lang.String text)
-  static void showNotification(jni.JlObject context, int notificationID,
-          jni.JlString title, jni.JlString text) =>
-      _showNotification(
-          context.reference, notificationID, title.reference, text.reference);
+  static void showNotification(jni.JniObject context, int notificationID,
+      jni.JniString title, jni.JniString text) {
+    final result__ = _showNotification(
+        context.reference, notificationID, title.reference, text.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 }
diff --git a/pkgs/jnigen/examples/notification_plugin/pubspec.yaml b/pkgs/jnigen/example/notification_plugin/pubspec.yaml
similarity index 96%
rename from pkgs/jnigen/examples/notification_plugin/pubspec.yaml
rename to pkgs/jnigen/example/notification_plugin/pubspec.yaml
index a680e74..77cc904 100644
--- a/pkgs/jnigen/examples/notification_plugin/pubspec.yaml
+++ b/pkgs/jnigen/example/notification_plugin/pubspec.yaml
@@ -1,5 +1,5 @@
 name: notification_plugin
-description: A new Flutter FFI plugin project.
+description: Example for Android plugin with custom Java code using jnigen.
 version: 0.0.1
 publish_to: none
 homepage: https://github.com/dart-lang/jnigen
diff --git a/pkgs/jnigen/examples/notification_plugin/src/CMakeLists.txt b/pkgs/jnigen/example/notification_plugin/src/CMakeLists.txt
similarity index 100%
rename from pkgs/jnigen/examples/notification_plugin/src/CMakeLists.txt
rename to pkgs/jnigen/example/notification_plugin/src/CMakeLists.txt
diff --git a/pkgs/jnigen/examples/in_app_java/src/android_utils/dartjni.h b/pkgs/jnigen/example/notification_plugin/src/dartjni.h
similarity index 81%
copy from pkgs/jnigen/examples/in_app_java/src/android_utils/dartjni.h
copy to pkgs/jnigen/example/notification_plugin/src/dartjni.h
index cd94b15..0ce5069 100644
--- a/pkgs/jnigen/examples/in_app_java/src/android_utils/dartjni.h
+++ b/pkgs/jnigen/example/notification_plugin/src/dartjni.h
@@ -2,6 +2,8 @@
 // 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.
 
+#pragma once
+
 #include <jni.h>
 #include <stdint.h>
 #include <stdio.h>
@@ -38,17 +40,17 @@
 #define __ENVP_CAST (void **)
 #endif
 
-struct jni_context {
+typedef struct JniContext {
 	JavaVM *jvm;
 	jobject classLoader;
 	jmethodID loadClassMethod;
 	jobject currentActivity;
 	jobject appContext;
-};
+} JniContext;
 
 extern thread_local JNIEnv *jniEnv;
 
-extern struct jni_context jni;
+extern JniContext jni;
 
 enum DartJniLogLevel {
 	JNI_VERBOSE = 2,
@@ -58,10 +60,25 @@
 	JNI_ERROR
 };
 
-FFI_PLUGIN_EXPORT struct jni_context GetJniContext();
+enum JniType {
+	boolType = 0,
+	byteType = 1,
+	shortType = 2,
+	charType = 3,
+	intType = 4,
+	longType = 5,
+	floatType = 6,
+	doubleType = 7,
+	objectType = 8,
+	voidType = 9,
+};
+
+FFI_PLUGIN_EXPORT JniContext GetJniContext();
 
 FFI_PLUGIN_EXPORT JavaVM *GetJavaVM(void);
 
+FFI_PLUGIN_EXPORT int DestroyJavaVM();
+
 FFI_PLUGIN_EXPORT JNIEnv *GetJniEnv(void);
 
 FFI_PLUGIN_EXPORT JNIEnv *SpawnJvm(JavaVMInitArgs *args);
@@ -74,26 +91,16 @@
 
 FFI_PLUGIN_EXPORT jobject GetCurrentActivity(void);
 
-FFI_PLUGIN_EXPORT void SetJNILogging(int level);
+/// For use by jni_gen's generated code
+/// don't use these.
 
-FFI_PLUGIN_EXPORT jstring ToJavaString(char *str);
-
-FFI_PLUGIN_EXPORT const char *GetJavaStringChars(jstring jstr);
-
-FFI_PLUGIN_EXPORT void ReleaseJavaStringChars(jstring jstr, const char *buf);
-
-// These 2 are the function pointer variables defined and exported by
-// the generated C files.
-//
-// initGeneratedLibrary function in Jni class will set these to
-// corresponding functions to the implementations from `dartjni` base library
-// which initializes and manages the JNI.
-extern struct jni_context (*context_getter)(void);
+// these 2 fn ptr vars will be defined by generated code library
+extern JniContext (*context_getter)(void);
 extern JNIEnv *(*env_getter)(void);
 
-// This function will be exported by generated code library and will set the
-// above 2 variables.
-FFI_PLUGIN_EXPORT void setJniGetters(struct jni_context (*cg)(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),
 		JNIEnv *(*eg)(void));
 
 // `static inline` because `inline` doesn't work, it may still not
@@ -101,6 +108,7 @@
 //
 // 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) {
 #ifdef __ANDROID__
 	jstring className = (*jniEnv)->NewStringUTF(jniEnv, name);
diff --git a/pkgs/jnigen/examples/notification_plugin/src/notification_plugin.c b/pkgs/jnigen/example/notification_plugin/src/notification_plugin.c
similarity index 81%
rename from pkgs/jnigen/examples/notification_plugin/src/notification_plugin.c
rename to pkgs/jnigen/example/notification_plugin/src/notification_plugin.c
index 0408aa1..021b839 100644
--- a/pkgs/jnigen/examples/notification_plugin/src/notification_plugin.c
+++ b/pkgs/jnigen/example/notification_plugin/src/notification_plugin.c
@@ -9,12 +9,12 @@
 #include "dartjni.h"
 
 thread_local JNIEnv *jniEnv;
-struct jni_context jni;
+JniContext jni;
 
-struct jni_context (*context_getter)(void);
+JniContext (*context_getter)(void);
 JNIEnv *(*env_getter)(void);
 
-void setJniGetters(struct jni_context (*cg)(void),
+void setJniGetters(JniContext (*cg)(void),
         JNIEnv *(*eg)(void)) {
     context_getter = cg;
     env_getter = eg;
@@ -28,7 +28,9 @@
 jobject com_example_notification_plugin_Notifications_ctor() {
     load_env();
     load_class_gr(&_c_com_example_notification_plugin_Notifications, "com/example/notification_plugin/Notifications");
+    if (_c_com_example_notification_plugin_Notifications == NULL) return (jobject)0;
     load_method(_c_com_example_notification_plugin_Notifications, &_m_com_example_notification_plugin_Notifications_ctor, "<init>", "()V");
+    if (_m_com_example_notification_plugin_Notifications_ctor == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->NewObject(jniEnv, _c_com_example_notification_plugin_Notifications, _m_com_example_notification_plugin_Notifications_ctor);
     return to_global_ref(_result);
 }
@@ -38,7 +40,9 @@
 void com_example_notification_plugin_Notifications_showNotification(jobject context, int32_t notificationID, jobject title, jobject text) {
     load_env();
     load_class_gr(&_c_com_example_notification_plugin_Notifications, "com/example/notification_plugin/Notifications");
+    if (_c_com_example_notification_plugin_Notifications == NULL) return (void)0;
     load_static_method(_c_com_example_notification_plugin_Notifications, &_m_com_example_notification_plugin_Notifications_showNotification, "showNotification", "(Landroid/content/Context;ILjava/lang/String;Ljava/lang/String;)V");
+    if (_m_com_example_notification_plugin_Notifications_showNotification == NULL) return (void)0;
     (*jniEnv)->CallStaticVoidMethod(jniEnv, _c_com_example_notification_plugin_Notifications, _m_com_example_notification_plugin_Notifications_showNotification, context, notificationID, title, text);
 }
 
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/.gitignore b/pkgs/jnigen/example/pdfbox_plugin/.gitignore
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/.gitignore
rename to pkgs/jnigen/example/pdfbox_plugin/.gitignore
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/.metadata b/pkgs/jnigen/example/pdfbox_plugin/.metadata
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/.metadata
rename to pkgs/jnigen/example/pdfbox_plugin/.metadata
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/README.md b/pkgs/jnigen/example/pdfbox_plugin/README.md
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/README.md
rename to pkgs/jnigen/example/pdfbox_plugin/README.md
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/analysis_options.yaml b/pkgs/jnigen/example/pdfbox_plugin/analysis_options.yaml
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/analysis_options.yaml
rename to pkgs/jnigen/example/pdfbox_plugin/analysis_options.yaml
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/android/.gitignore b/pkgs/jnigen/example/pdfbox_plugin/android/.gitignore
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/android/.gitignore
rename to pkgs/jnigen/example/pdfbox_plugin/android/.gitignore
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/android/build.gradle b/pkgs/jnigen/example/pdfbox_plugin/android/build.gradle
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/android/build.gradle
rename to pkgs/jnigen/example/pdfbox_plugin/android/build.gradle
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/android/settings.gradle b/pkgs/jnigen/example/pdfbox_plugin/android/settings.gradle
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/android/settings.gradle
rename to pkgs/jnigen/example/pdfbox_plugin/android/settings.gradle
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/android/src/main/AndroidManifest.xml b/pkgs/jnigen/example/pdfbox_plugin/android/src/main/AndroidManifest.xml
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/android/src/main/AndroidManifest.xml
rename to pkgs/jnigen/example/pdfbox_plugin/android/src/main/AndroidManifest.xml
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/dart_example/.gitignore b/pkgs/jnigen/example/pdfbox_plugin/dart_example/.gitignore
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/dart_example/.gitignore
rename to pkgs/jnigen/example/pdfbox_plugin/dart_example/.gitignore
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/dart_example/CHANGELOG.md b/pkgs/jnigen/example/pdfbox_plugin/dart_example/CHANGELOG.md
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/dart_example/CHANGELOG.md
rename to pkgs/jnigen/example/pdfbox_plugin/dart_example/CHANGELOG.md
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/dart_example/README.md b/pkgs/jnigen/example/pdfbox_plugin/dart_example/README.md
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/dart_example/README.md
rename to pkgs/jnigen/example/pdfbox_plugin/dart_example/README.md
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/dart_example/analysis_options.yaml b/pkgs/jnigen/example/pdfbox_plugin/dart_example/analysis_options.yaml
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/dart_example/analysis_options.yaml
rename to pkgs/jnigen/example/pdfbox_plugin/dart_example/analysis_options.yaml
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/dart_example/bin/pdf_info.dart b/pkgs/jnigen/example/pdfbox_plugin/dart_example/bin/pdf_info.dart
similarity index 74%
rename from pkgs/jnigen/examples/pdfbox_plugin/dart_example/bin/pdf_info.dart
rename to pkgs/jnigen/example/pdfbox_plugin/dart_example/bin/pdf_info.dart
index 92f9c30..c16ac20 100644
--- a/pkgs/jnigen/examples/pdfbox_plugin/dart_example/bin/pdf_info.dart
+++ b/pkgs/jnigen/example/pdfbox_plugin/dart_example/bin/pdf_info.dart
@@ -6,39 +6,34 @@
 
 import 'package:path/path.dart';
 import 'package:jni/jni.dart';
-import 'dart:ffi';
 
 import 'package:pdfbox_plugin/third_party/org/apache/pdfbox/pdmodel.dart';
 
 void writeInfo(String file) {
-  var jni = Jni.getInstance();
+  final inputFile = Jni.newInstance(
+      "java/io/FileInputStream", "(Ljava/lang/String;)V", [file]);
 
-  var inputFile = jni
-      .newInstance("java/io/FileInputStream", "(Ljava/lang/String;)V", [file]);
-  var inputJl = JlObject.fromRef(inputFile.jobject);
-
-  var pdDoc = PDDocument.load7(inputJl);
+  final pdDoc = PDDocument.load7(inputFile);
   int pages = pdDoc.getNumberOfPages();
   final info = pdDoc.getDocumentInformation();
   final title = info.getTitle();
   final subject = info.getSubject();
   final author = info.getAuthor();
   stderr.writeln('Number of pages: $pages');
-  if (title.reference != nullptr) {
+
+  if (!title.isNull) {
     stderr.writeln('Title: ${title.toDartString()}');
   }
-  if (subject.reference != nullptr) {
+
+  if (!subject.isNull) {
     stderr.writeln('Subject: ${subject.toDartString()}');
   }
-  if (author.reference != nullptr) {
+
+  if (!author.isNull) {
     stderr.writeln('Author: ${author.toDartString()}');
   }
-  stderr.writeln('PDF Version: ${pdDoc.getVersion()}');
 
-  for (JlObject jr in [pdDoc, info, title, author, subject]) {
-    jr.delete();
-  }
-  inputFile.delete();
+  stderr.writeln('PDF Version: ${pdDoc.getVersion().toStringAsPrecision(2)}');
 }
 
 final jniLibsDir = join('build', 'jni_libs');
@@ -66,7 +61,7 @@
     stderr.writeln(jarError);
     return;
   }
-  Jni.spawn(helperDir: jniLibsDir, classPath: jars);
+  Jni.spawn(dylibDir: jniLibsDir, classPath: jars);
   if (arguments.length != 1) {
     stderr.writeln('usage: dart run pdf_info:pdf_info <Path_to_PDF>');
     exitCode = 1;
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/dart_example/pubspec.yaml b/pkgs/jnigen/example/pdfbox_plugin/dart_example/pubspec.yaml
similarity index 98%
rename from pkgs/jnigen/examples/pdfbox_plugin/dart_example/pubspec.yaml
rename to pkgs/jnigen/example/pdfbox_plugin/dart_example/pubspec.yaml
index c1e2660..235ccbd 100644
--- a/pkgs/jnigen/examples/pdfbox_plugin/dart_example/pubspec.yaml
+++ b/pkgs/jnigen/example/pdfbox_plugin/dart_example/pubspec.yaml
@@ -1,5 +1,5 @@
 name: pdf_info
-description: Dart standalone example using jnigen PDFBox bindings
+description: Dart standalone example using jnigen PDFBox bindings.
 version: 1.0.0
 publish_to: none
 # homepage: https://www.example.com
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/example/.gitignore b/pkgs/jnigen/example/pdfbox_plugin/example/.gitignore
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/example/.gitignore
rename to pkgs/jnigen/example/pdfbox_plugin/example/.gitignore
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/example/README.md b/pkgs/jnigen/example/pdfbox_plugin/example/README.md
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/example/README.md
rename to pkgs/jnigen/example/pdfbox_plugin/example/README.md
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/example/analysis_options.yaml b/pkgs/jnigen/example/pdfbox_plugin/example/analysis_options.yaml
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/example/analysis_options.yaml
rename to pkgs/jnigen/example/pdfbox_plugin/example/analysis_options.yaml
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/example/android/.gitignore b/pkgs/jnigen/example/pdfbox_plugin/example/android/.gitignore
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/example/android/.gitignore
rename to pkgs/jnigen/example/pdfbox_plugin/example/android/.gitignore
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/example/android/app/build.gradle b/pkgs/jnigen/example/pdfbox_plugin/example/android/app/build.gradle
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/example/android/app/build.gradle
rename to pkgs/jnigen/example/pdfbox_plugin/example/android/app/build.gradle
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/example/android/app/src/debug/AndroidManifest.xml b/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/debug/AndroidManifest.xml
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/example/android/app/src/debug/AndroidManifest.xml
rename to pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/debug/AndroidManifest.xml
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/example/android/app/src/main/AndroidManifest.xml b/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/AndroidManifest.xml
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/example/android/app/src/main/AndroidManifest.xml
rename to pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/AndroidManifest.xml
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/example/android/app/src/main/kotlin/com/example/pdfbox_plugin_example/MainActivity.kt b/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/kotlin/com/example/pdfbox_plugin_example/MainActivity.kt
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/example/android/app/src/main/kotlin/com/example/pdfbox_plugin_example/MainActivity.kt
rename to pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/kotlin/com/example/pdfbox_plugin_example/MainActivity.kt
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/example/android/app/src/main/res/drawable-v21/launch_background.xml b/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/res/drawable-v21/launch_background.xml
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/example/android/app/src/main/res/drawable-v21/launch_background.xml
rename to pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/res/drawable-v21/launch_background.xml
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/example/android/app/src/main/res/drawable/launch_background.xml b/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/res/drawable/launch_background.xml
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/example/android/app/src/main/res/drawable/launch_background.xml
rename to pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/res/drawable/launch_background.xml
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
rename to pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
rename to pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
rename to pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
rename to pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
rename to pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/example/android/app/src/main/res/values-night/styles.xml b/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/res/values-night/styles.xml
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/example/android/app/src/main/res/values-night/styles.xml
rename to pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/res/values-night/styles.xml
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/example/android/app/src/main/res/values/styles.xml b/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/res/values/styles.xml
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/example/android/app/src/main/res/values/styles.xml
rename to pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/res/values/styles.xml
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/example/android/app/src/profile/AndroidManifest.xml b/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/profile/AndroidManifest.xml
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/example/android/app/src/profile/AndroidManifest.xml
rename to pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/profile/AndroidManifest.xml
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/example/android/build.gradle b/pkgs/jnigen/example/pdfbox_plugin/example/android/build.gradle
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/example/android/build.gradle
rename to pkgs/jnigen/example/pdfbox_plugin/example/android/build.gradle
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/example/android/gradle.properties b/pkgs/jnigen/example/pdfbox_plugin/example/android/gradle.properties
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/example/android/gradle.properties
rename to pkgs/jnigen/example/pdfbox_plugin/example/android/gradle.properties
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/example/android/gradle/wrapper/gradle-wrapper.properties b/pkgs/jnigen/example/pdfbox_plugin/example/android/gradle/wrapper/gradle-wrapper.properties
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/example/android/gradle/wrapper/gradle-wrapper.properties
rename to pkgs/jnigen/example/pdfbox_plugin/example/android/gradle/wrapper/gradle-wrapper.properties
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/example/android/settings.gradle b/pkgs/jnigen/example/pdfbox_plugin/example/android/settings.gradle
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/example/android/settings.gradle
rename to pkgs/jnigen/example/pdfbox_plugin/example/android/settings.gradle
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/example/lib/main.dart b/pkgs/jnigen/example/pdfbox_plugin/example/lib/main.dart
similarity index 92%
rename from pkgs/jnigen/examples/pdfbox_plugin/example/lib/main.dart
rename to pkgs/jnigen/example/pdfbox_plugin/example/lib/main.dart
index 82d8657..6842ba0 100644
--- a/pkgs/jnigen/examples/pdfbox_plugin/example/lib/main.dart
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/lib/main.dart
@@ -6,7 +6,6 @@
 import 'dart:io';
 import 'dart:async';
 
-import 'dart:ffi'; // for nullptr :=
 import 'package:jni/jni.dart';
 import 'package:path/path.dart';
 
@@ -18,7 +17,6 @@
 
 Stream<String> files(String dir) => Directory(dir).list().map((e) => e.path);
 
-late Jni jni;
 const jarError = 'No JAR files were found.\n'
     'Run `dart run jnigen:download_maven_jars --config jnigen.yaml` '
     'in plugin directory.\n'
@@ -48,7 +46,6 @@
     }
     Jni.spawn(classPath: jars);
   }
-  jni = Jni.getInstance();
   runApp(const PDFInfoApp());
 }
 
@@ -162,25 +159,22 @@
   late String author, subject, title;
   late int numPages;
 
-  /// Converts JlString to dart string and deletes the original.
-  String _fromJavaStr(JlString jstr) {
+  /// Converts JniString to dart string and deletes the original.
+  /// Also handles the case where the underlying string is Null.
+  String _fromJavaStr(JniString jstr) {
     if (jstr.reference == nullptr) {
       return '(null)';
     }
-    final result = jstr.toDartString();
-    jstr.delete();
-    return result;
+    return jstr.toDartString(deleteOriginal: true);
   }
 
   PDFFileInfo.usingPDFBox(this.filename) {
     // Since java.io is not directly available, use package:jni API to
     // create a java.io.File object.
     final inputFile =
-        jni.newInstance("java/io/File", "(Ljava/lang/String;)V", [filename]);
-    final inputJl = JlObject.fromRef(inputFile.jobject);
-
+        Jni.newInstance("java/io/File", "(Ljava/lang/String;)V", [filename]);
     // Static method call PDDocument.load -> PDDocument
-    final pdf = PDDocument.load(inputJl);
+    final pdf = PDDocument.load(inputFile);
     // Instance method call getNumberOfPages() -> int
     numPages = pdf.getNumberOfPages();
     // Instance method that returns an object
@@ -192,11 +186,7 @@
     title = _fromJavaStr(info.getTitle());
     subject = _fromJavaStr(info.getSubject());
 
-    /// Delete objects after done.
-    info.delete();
     pdf.close();
-    pdf.delete();
-    inputFile.delete();
   }
 }
 
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/example/linux/.gitignore b/pkgs/jnigen/example/pdfbox_plugin/example/linux/.gitignore
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/example/linux/.gitignore
rename to pkgs/jnigen/example/pdfbox_plugin/example/linux/.gitignore
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/example/linux/CMakeLists.txt b/pkgs/jnigen/example/pdfbox_plugin/example/linux/CMakeLists.txt
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/example/linux/CMakeLists.txt
rename to pkgs/jnigen/example/pdfbox_plugin/example/linux/CMakeLists.txt
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/example/linux/flutter/CMakeLists.txt b/pkgs/jnigen/example/pdfbox_plugin/example/linux/flutter/CMakeLists.txt
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/example/linux/flutter/CMakeLists.txt
rename to pkgs/jnigen/example/pdfbox_plugin/example/linux/flutter/CMakeLists.txt
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/example/linux/flutter/generated_plugin_registrant.cc b/pkgs/jnigen/example/pdfbox_plugin/example/linux/flutter/generated_plugin_registrant.cc
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/example/linux/flutter/generated_plugin_registrant.cc
rename to pkgs/jnigen/example/pdfbox_plugin/example/linux/flutter/generated_plugin_registrant.cc
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/example/linux/flutter/generated_plugin_registrant.h b/pkgs/jnigen/example/pdfbox_plugin/example/linux/flutter/generated_plugin_registrant.h
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/example/linux/flutter/generated_plugin_registrant.h
rename to pkgs/jnigen/example/pdfbox_plugin/example/linux/flutter/generated_plugin_registrant.h
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/example/linux/flutter/generated_plugins.cmake b/pkgs/jnigen/example/pdfbox_plugin/example/linux/flutter/generated_plugins.cmake
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/example/linux/flutter/generated_plugins.cmake
rename to pkgs/jnigen/example/pdfbox_plugin/example/linux/flutter/generated_plugins.cmake
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/example/linux/main.cc b/pkgs/jnigen/example/pdfbox_plugin/example/linux/main.cc
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/example/linux/main.cc
rename to pkgs/jnigen/example/pdfbox_plugin/example/linux/main.cc
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/example/linux/my_application.cc b/pkgs/jnigen/example/pdfbox_plugin/example/linux/my_application.cc
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/example/linux/my_application.cc
rename to pkgs/jnigen/example/pdfbox_plugin/example/linux/my_application.cc
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/example/linux/my_application.h b/pkgs/jnigen/example/pdfbox_plugin/example/linux/my_application.h
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/example/linux/my_application.h
rename to pkgs/jnigen/example/pdfbox_plugin/example/linux/my_application.h
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/example/pubspec.yaml b/pkgs/jnigen/example/pdfbox_plugin/example/pubspec.yaml
similarity index 98%
rename from pkgs/jnigen/examples/pdfbox_plugin/example/pubspec.yaml
rename to pkgs/jnigen/example/pdfbox_plugin/example/pubspec.yaml
index ce5dd42..67c80b7 100644
--- a/pkgs/jnigen/examples/pdfbox_plugin/example/pubspec.yaml
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/pubspec.yaml
@@ -1,5 +1,5 @@
 name: pdfbox_example
-description: Demonstrates how to use the pdfbox_plugin plugin.
+description: Demonstrates how to use pdfbox_plugin.
 
 # The following line prevents the package from being accidentally published to
 # pub.dev using `flutter pub publish`. This is preferred for private packages.
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/example/windows/.gitignore b/pkgs/jnigen/example/pdfbox_plugin/example/windows/.gitignore
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/example/windows/.gitignore
rename to pkgs/jnigen/example/pdfbox_plugin/example/windows/.gitignore
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/example/windows/CMakeLists.txt b/pkgs/jnigen/example/pdfbox_plugin/example/windows/CMakeLists.txt
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/example/windows/CMakeLists.txt
rename to pkgs/jnigen/example/pdfbox_plugin/example/windows/CMakeLists.txt
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/example/windows/flutter/CMakeLists.txt b/pkgs/jnigen/example/pdfbox_plugin/example/windows/flutter/CMakeLists.txt
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/example/windows/flutter/CMakeLists.txt
rename to pkgs/jnigen/example/pdfbox_plugin/example/windows/flutter/CMakeLists.txt
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/example/windows/flutter/generated_plugin_registrant.cc b/pkgs/jnigen/example/pdfbox_plugin/example/windows/flutter/generated_plugin_registrant.cc
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/example/windows/flutter/generated_plugin_registrant.cc
rename to pkgs/jnigen/example/pdfbox_plugin/example/windows/flutter/generated_plugin_registrant.cc
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/example/windows/flutter/generated_plugin_registrant.h b/pkgs/jnigen/example/pdfbox_plugin/example/windows/flutter/generated_plugin_registrant.h
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/example/windows/flutter/generated_plugin_registrant.h
rename to pkgs/jnigen/example/pdfbox_plugin/example/windows/flutter/generated_plugin_registrant.h
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/example/windows/flutter/generated_plugins.cmake b/pkgs/jnigen/example/pdfbox_plugin/example/windows/flutter/generated_plugins.cmake
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/example/windows/flutter/generated_plugins.cmake
rename to pkgs/jnigen/example/pdfbox_plugin/example/windows/flutter/generated_plugins.cmake
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/example/windows/runner/CMakeLists.txt b/pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/CMakeLists.txt
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/example/windows/runner/CMakeLists.txt
rename to pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/CMakeLists.txt
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/example/windows/runner/Runner.rc b/pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/Runner.rc
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/example/windows/runner/Runner.rc
rename to pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/Runner.rc
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/example/windows/runner/flutter_window.cpp b/pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/flutter_window.cpp
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/example/windows/runner/flutter_window.cpp
rename to pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/flutter_window.cpp
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/example/windows/runner/flutter_window.h b/pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/flutter_window.h
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/example/windows/runner/flutter_window.h
rename to pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/flutter_window.h
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/example/windows/runner/main.cpp b/pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/main.cpp
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/example/windows/runner/main.cpp
rename to pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/main.cpp
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/example/windows/runner/resource.h b/pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/resource.h
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/example/windows/runner/resource.h
rename to pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/resource.h
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/example/windows/runner/resources/app_icon.ico b/pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/resources/app_icon.ico
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/example/windows/runner/resources/app_icon.ico
rename to pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/resources/app_icon.ico
Binary files differ
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/example/windows/runner/runner.exe.manifest b/pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/runner.exe.manifest
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/example/windows/runner/runner.exe.manifest
rename to pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/runner.exe.manifest
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/example/windows/runner/utils.cpp b/pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/utils.cpp
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/example/windows/runner/utils.cpp
rename to pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/utils.cpp
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/example/windows/runner/utils.h b/pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/utils.h
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/example/windows/runner/utils.h
rename to pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/utils.h
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/example/windows/runner/win32_window.cpp b/pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/win32_window.cpp
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/example/windows/runner/win32_window.cpp
rename to pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/win32_window.cpp
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/example/windows/runner/win32_window.h b/pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/win32_window.h
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/example/windows/runner/win32_window.h
rename to pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/win32_window.h
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/jnigen.yaml b/pkgs/jnigen/example/pdfbox_plugin/jnigen.yaml
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/jnigen.yaml
rename to pkgs/jnigen/example/pdfbox_plugin/jnigen.yaml
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/jnigen_full.yaml b/pkgs/jnigen/example/pdfbox_plugin/jnigen_full.yaml
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/jnigen_full.yaml
rename to pkgs/jnigen/example/pdfbox_plugin/jnigen_full.yaml
diff --git a/pkgs/jnigen/example/pdfbox_plugin/lib/third_party/_init.dart b/pkgs/jnigen/example/pdfbox_plugin/lib/third_party/_init.dart
new file mode 100644
index 0000000..86170ee
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/lib/third_party/_init.dart
@@ -0,0 +1,23 @@
+// Generated from Apache PDFBox library which is licensed under the Apache License 2.0.
+// The following copyright from the original authors applies.
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You 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.
+
+import "dart:ffi";
+import "package:jni/internal_helpers_for_jnigen.dart";
+
+final Pointer<T> Function<T extends NativeType>(String sym) jniLookup =
+    ProtectedJniExtensions.initGeneratedLibrary("pdfbox_plugin");
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/lib/third_party/org/apache/pdfbox/pdmodel.dart b/pkgs/jnigen/example/pdfbox_plugin/lib/third_party/org/apache/pdfbox/pdmodel.dart
similarity index 77%
rename from pkgs/jnigen/examples/pdfbox_plugin/lib/third_party/org/apache/pdfbox/pdmodel.dart
rename to pkgs/jnigen/example/pdfbox_plugin/lib/third_party/org/apache/pdfbox/pdmodel.dart
index f3be916..5ac4a5d 100644
--- a/pkgs/jnigen/examples/pdfbox_plugin/lib/third_party/org/apache/pdfbox/pdmodel.dart
+++ b/pkgs/jnigen/example/pdfbox_plugin/lib/third_party/org/apache/pdfbox/pdmodel.dart
@@ -26,21 +26,20 @@
 // ignore_for_file: unused_element
 
 import "dart:ffi" as ffi;
-
 import "package:jni/jni.dart" as jni;
 
-import "../../../init.dart" show jlookup;
+import "../../../_init.dart" show jniLookup;
 
 /// from: org.apache.pdfbox.pdmodel.PDDocument
 ///
 /// This is the in-memory representation of the PDF document.
 /// The \#close() method must be called once the document is no longer needed.
 ///@author Ben Litchfield
-class PDDocument extends jni.JlObject {
+class PDDocument extends jni.JniObject {
   PDDocument.fromRef(ffi.Pointer<ffi.Void> ref) : super.fromRef(ref);
 
   static final _get_RESERVE_BYTE_RANGE =
-      jlookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function()>>(
+      jniLookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function()>>(
               "get_org_apache_pdfbox_pdmodel_PDDocument_RESERVE_BYTE_RANGE")
           .asFunction<ffi.Pointer<ffi.Void> Function()>();
 
@@ -53,19 +52,19 @@
   /// PDSignature\#setByteRange(int[]) ) only if you call
   /// \#saveIncrementalForExternalSigning(java.io.OutputStream) saveIncrementalForExternalSigning()
   /// twice.
-  static jni.JlObject get RESERVE_BYTE_RANGE =>
-      jni.JlObject.fromRef(_get_RESERVE_BYTE_RANGE());
+  static jni.JniObject get RESERVE_BYTE_RANGE =>
+      jni.JniObject.fromRef(_get_RESERVE_BYTE_RANGE());
 
   static final _get_LOG =
-      jlookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function()>>(
+      jniLookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function()>>(
               "get_org_apache_pdfbox_pdmodel_PDDocument_LOG")
           .asFunction<ffi.Pointer<ffi.Void> Function()>();
 
   /// from: private static final org.apache.commons.logging.Log LOG
   /// The returned object must be deleted after use, by calling the `delete` method.
-  static jni.JlObject get LOG => jni.JlObject.fromRef(_get_LOG());
+  static jni.JniObject get LOG => jni.JniObject.fromRef(_get_LOG());
 
-  static final _get_document = jlookup<
+  static final _get_document = jniLookup<
           ffi.NativeFunction<
               ffi.Pointer<ffi.Void> Function(
     ffi.Pointer<ffi.Void>,
@@ -77,9 +76,9 @@
 
   /// from: private final org.apache.pdfbox.cos.COSDocument document
   /// The returned object must be deleted after use, by calling the `delete` method.
-  jni.JlObject get document => jni.JlObject.fromRef(_get_document(reference));
+  jni.JniObject get document => jni.JniObject.fromRef(_get_document(reference));
 
-  static final _get_documentInformation = jlookup<
+  static final _get_documentInformation = jniLookup<
           ffi.NativeFunction<
               ffi.Pointer<ffi.Void> Function(
     ffi.Pointer<ffi.Void>,
@@ -93,7 +92,7 @@
   /// The returned object must be deleted after use, by calling the `delete` method.
   PDDocumentInformation get documentInformation =>
       PDDocumentInformation.fromRef(_get_documentInformation(reference));
-  static final _set_documentInformation = jlookup<
+  static final _set_documentInformation = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -106,7 +105,7 @@
   set documentInformation(PDDocumentInformation value) =>
       _set_documentInformation(reference, value.reference);
 
-  static final _get_documentCatalog = jlookup<
+  static final _get_documentCatalog = jniLookup<
           ffi.NativeFunction<
               ffi.Pointer<ffi.Void> Function(
     ffi.Pointer<ffi.Void>,
@@ -118,9 +117,9 @@
 
   /// from: private org.apache.pdfbox.pdmodel.PDDocumentCatalog documentCatalog
   /// The returned object must be deleted after use, by calling the `delete` method.
-  jni.JlObject get documentCatalog =>
-      jni.JlObject.fromRef(_get_documentCatalog(reference));
-  static final _set_documentCatalog = jlookup<
+  jni.JniObject get documentCatalog =>
+      jni.JniObject.fromRef(_get_documentCatalog(reference));
+  static final _set_documentCatalog = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -130,10 +129,10 @@
 
   /// from: private org.apache.pdfbox.pdmodel.PDDocumentCatalog documentCatalog
   /// The returned object must be deleted after use, by calling the `delete` method.
-  set documentCatalog(jni.JlObject value) =>
+  set documentCatalog(jni.JniObject value) =>
       _set_documentCatalog(reference, value.reference);
 
-  static final _get_encryption = jlookup<
+  static final _get_encryption = jniLookup<
           ffi.NativeFunction<
               ffi.Pointer<ffi.Void> Function(
     ffi.Pointer<ffi.Void>,
@@ -145,9 +144,9 @@
 
   /// from: private org.apache.pdfbox.pdmodel.encryption.PDEncryption encryption
   /// The returned object must be deleted after use, by calling the `delete` method.
-  jni.JlObject get encryption =>
-      jni.JlObject.fromRef(_get_encryption(reference));
-  static final _set_encryption = jlookup<
+  jni.JniObject get encryption =>
+      jni.JniObject.fromRef(_get_encryption(reference));
+  static final _set_encryption = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -157,10 +156,10 @@
 
   /// from: private org.apache.pdfbox.pdmodel.encryption.PDEncryption encryption
   /// The returned object must be deleted after use, by calling the `delete` method.
-  set encryption(jni.JlObject value) =>
+  set encryption(jni.JniObject value) =>
       _set_encryption(reference, value.reference);
 
-  static final _get_allSecurityToBeRemoved = jlookup<
+  static final _get_allSecurityToBeRemoved = jniLookup<
           ffi.NativeFunction<
               ffi.Uint8 Function(
     ffi.Pointer<ffi.Void>,
@@ -173,7 +172,7 @@
   /// from: private boolean allSecurityToBeRemoved
   bool get allSecurityToBeRemoved =>
       _get_allSecurityToBeRemoved(reference) != 0;
-  static final _set_allSecurityToBeRemoved = jlookup<
+  static final _set_allSecurityToBeRemoved = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Uint8)>>(
           "set_org_apache_pdfbox_pdmodel_PDDocument_allSecurityToBeRemoved")
@@ -183,7 +182,7 @@
   set allSecurityToBeRemoved(bool value) =>
       _set_allSecurityToBeRemoved(reference, value ? 1 : 0);
 
-  static final _get_documentId = jlookup<
+  static final _get_documentId = jniLookup<
           ffi.NativeFunction<
               ffi.Pointer<ffi.Void> Function(
     ffi.Pointer<ffi.Void>,
@@ -195,9 +194,9 @@
 
   /// from: private java.lang.Long documentId
   /// The returned object must be deleted after use, by calling the `delete` method.
-  jni.JlObject get documentId =>
-      jni.JlObject.fromRef(_get_documentId(reference));
-  static final _set_documentId = jlookup<
+  jni.JniObject get documentId =>
+      jni.JniObject.fromRef(_get_documentId(reference));
+  static final _set_documentId = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -207,10 +206,10 @@
 
   /// from: private java.lang.Long documentId
   /// The returned object must be deleted after use, by calling the `delete` method.
-  set documentId(jni.JlObject value) =>
+  set documentId(jni.JniObject value) =>
       _set_documentId(reference, value.reference);
 
-  static final _get_pdfSource = jlookup<
+  static final _get_pdfSource = jniLookup<
           ffi.NativeFunction<
               ffi.Pointer<ffi.Void> Function(
     ffi.Pointer<ffi.Void>,
@@ -222,9 +221,10 @@
 
   /// from: private final org.apache.pdfbox.io.RandomAccessRead pdfSource
   /// The returned object must be deleted after use, by calling the `delete` method.
-  jni.JlObject get pdfSource => jni.JlObject.fromRef(_get_pdfSource(reference));
+  jni.JniObject get pdfSource =>
+      jni.JniObject.fromRef(_get_pdfSource(reference));
 
-  static final _get_accessPermission = jlookup<
+  static final _get_accessPermission = jniLookup<
           ffi.NativeFunction<
               ffi.Pointer<ffi.Void> Function(
     ffi.Pointer<ffi.Void>,
@@ -236,9 +236,9 @@
 
   /// from: private org.apache.pdfbox.pdmodel.encryption.AccessPermission accessPermission
   /// The returned object must be deleted after use, by calling the `delete` method.
-  jni.JlObject get accessPermission =>
-      jni.JlObject.fromRef(_get_accessPermission(reference));
-  static final _set_accessPermission = jlookup<
+  jni.JniObject get accessPermission =>
+      jni.JniObject.fromRef(_get_accessPermission(reference));
+  static final _set_accessPermission = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -248,10 +248,10 @@
 
   /// from: private org.apache.pdfbox.pdmodel.encryption.AccessPermission accessPermission
   /// The returned object must be deleted after use, by calling the `delete` method.
-  set accessPermission(jni.JlObject value) =>
+  set accessPermission(jni.JniObject value) =>
       _set_accessPermission(reference, value.reference);
 
-  static final _get_fontsToSubset = jlookup<
+  static final _get_fontsToSubset = jniLookup<
           ffi.NativeFunction<
               ffi.Pointer<ffi.Void> Function(
     ffi.Pointer<ffi.Void>,
@@ -263,10 +263,10 @@
 
   /// from: private final java.util.Set<org.apache.pdfbox.pdmodel.font.PDFont> fontsToSubset
   /// The returned object must be deleted after use, by calling the `delete` method.
-  jni.JlObject get fontsToSubset =>
-      jni.JlObject.fromRef(_get_fontsToSubset(reference));
+  jni.JniObject get fontsToSubset =>
+      jni.JniObject.fromRef(_get_fontsToSubset(reference));
 
-  static final _get_fontsToClose = jlookup<
+  static final _get_fontsToClose = jniLookup<
           ffi.NativeFunction<
               ffi.Pointer<ffi.Void> Function(
     ffi.Pointer<ffi.Void>,
@@ -278,10 +278,10 @@
 
   /// from: private final java.util.Set<org.apache.fontbox.ttf.TrueTypeFont> fontsToClose
   /// The returned object must be deleted after use, by calling the `delete` method.
-  jni.JlObject get fontsToClose =>
-      jni.JlObject.fromRef(_get_fontsToClose(reference));
+  jni.JniObject get fontsToClose =>
+      jni.JniObject.fromRef(_get_fontsToClose(reference));
 
-  static final _get_signInterface = jlookup<
+  static final _get_signInterface = jniLookup<
           ffi.NativeFunction<
               ffi.Pointer<ffi.Void> Function(
     ffi.Pointer<ffi.Void>,
@@ -293,9 +293,9 @@
 
   /// from: private org.apache.pdfbox.pdmodel.interactive.digitalsignature.SignatureInterface signInterface
   /// The returned object must be deleted after use, by calling the `delete` method.
-  jni.JlObject get signInterface =>
-      jni.JlObject.fromRef(_get_signInterface(reference));
-  static final _set_signInterface = jlookup<
+  jni.JniObject get signInterface =>
+      jni.JniObject.fromRef(_get_signInterface(reference));
+  static final _set_signInterface = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -305,10 +305,10 @@
 
   /// from: private org.apache.pdfbox.pdmodel.interactive.digitalsignature.SignatureInterface signInterface
   /// The returned object must be deleted after use, by calling the `delete` method.
-  set signInterface(jni.JlObject value) =>
+  set signInterface(jni.JniObject value) =>
       _set_signInterface(reference, value.reference);
 
-  static final _get_signingSupport = jlookup<
+  static final _get_signingSupport = jniLookup<
           ffi.NativeFunction<
               ffi.Pointer<ffi.Void> Function(
     ffi.Pointer<ffi.Void>,
@@ -320,9 +320,9 @@
 
   /// from: private org.apache.pdfbox.pdmodel.interactive.digitalsignature.SigningSupport signingSupport
   /// The returned object must be deleted after use, by calling the `delete` method.
-  jni.JlObject get signingSupport =>
-      jni.JlObject.fromRef(_get_signingSupport(reference));
-  static final _set_signingSupport = jlookup<
+  jni.JniObject get signingSupport =>
+      jni.JniObject.fromRef(_get_signingSupport(reference));
+  static final _set_signingSupport = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -332,10 +332,10 @@
 
   /// from: private org.apache.pdfbox.pdmodel.interactive.digitalsignature.SigningSupport signingSupport
   /// The returned object must be deleted after use, by calling the `delete` method.
-  set signingSupport(jni.JlObject value) =>
+  set signingSupport(jni.JniObject value) =>
       _set_signingSupport(reference, value.reference);
 
-  static final _get_resourceCache = jlookup<
+  static final _get_resourceCache = jniLookup<
           ffi.NativeFunction<
               ffi.Pointer<ffi.Void> Function(
     ffi.Pointer<ffi.Void>,
@@ -347,9 +347,9 @@
 
   /// from: private org.apache.pdfbox.pdmodel.ResourceCache resourceCache
   /// The returned object must be deleted after use, by calling the `delete` method.
-  jni.JlObject get resourceCache =>
-      jni.JlObject.fromRef(_get_resourceCache(reference));
-  static final _set_resourceCache = jlookup<
+  jni.JniObject get resourceCache =>
+      jni.JniObject.fromRef(_get_resourceCache(reference));
+  static final _set_resourceCache = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -359,10 +359,10 @@
 
   /// from: private org.apache.pdfbox.pdmodel.ResourceCache resourceCache
   /// The returned object must be deleted after use, by calling the `delete` method.
-  set resourceCache(jni.JlObject value) =>
+  set resourceCache(jni.JniObject value) =>
       _set_resourceCache(reference, value.reference);
 
-  static final _get_signatureAdded = jlookup<
+  static final _get_signatureAdded = jniLookup<
           ffi.NativeFunction<
               ffi.Uint8 Function(
     ffi.Pointer<ffi.Void>,
@@ -374,7 +374,7 @@
 
   /// from: private boolean signatureAdded
   bool get signatureAdded => _get_signatureAdded(reference) != 0;
-  static final _set_signatureAdded = jlookup<
+  static final _set_signatureAdded = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Uint8)>>(
           "set_org_apache_pdfbox_pdmodel_PDDocument_signatureAdded")
@@ -385,7 +385,7 @@
       _set_signatureAdded(reference, value ? 1 : 0);
 
   static final _ctor =
-      jlookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function()>>(
+      jniLookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function()>>(
               "org_apache_pdfbox_pdmodel_PDDocument_ctor")
           .asFunction<ffi.Pointer<ffi.Void> Function()>();
 
@@ -393,9 +393,11 @@
   ///
   /// Creates an empty PDF document.
   /// You need to add at least one page for the document to be valid.
-  PDDocument() : super.fromRef(_ctor());
+  PDDocument() : super.fromRef(_ctor()) {
+    jni.Jni.env.checkException();
+  }
 
-  static final _ctor1 = jlookup<
+  static final _ctor1 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "org_apache_pdfbox_pdmodel_PDDocument_ctor1")
@@ -406,10 +408,12 @@
   /// Creates an empty PDF document.
   /// You need to add at least one page for the document to be valid.
   ///@param memUsageSetting defines how memory is used for buffering PDF streams
-  PDDocument.ctor1(jni.JlObject memUsageSetting)
-      : super.fromRef(_ctor1(memUsageSetting.reference));
+  PDDocument.ctor1(jni.JniObject memUsageSetting)
+      : super.fromRef(_ctor1(memUsageSetting.reference)) {
+    jni.Jni.env.checkException();
+  }
 
-  static final _ctor2 = jlookup<
+  static final _ctor2 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "org_apache_pdfbox_pdmodel_PDDocument_ctor2")
@@ -419,9 +423,11 @@
   ///
   /// Constructor that uses an existing document. The COSDocument that is passed in must be valid.
   ///@param doc The COSDocument that this document wraps.
-  PDDocument.ctor2(jni.JlObject doc) : super.fromRef(_ctor2(doc.reference));
+  PDDocument.ctor2(jni.JniObject doc) : super.fromRef(_ctor2(doc.reference)) {
+    jni.Jni.env.checkException();
+  }
 
-  static final _ctor3 = jlookup<
+  static final _ctor3 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -435,10 +441,12 @@
   /// Constructor that uses an existing document. The COSDocument that is passed in must be valid.
   ///@param doc The COSDocument that this document wraps.
   ///@param source the parser which is used to read the pdf
-  PDDocument.ctor3(jni.JlObject doc, jni.JlObject source)
-      : super.fromRef(_ctor3(doc.reference, source.reference));
+  PDDocument.ctor3(jni.JniObject doc, jni.JniObject source)
+      : super.fromRef(_ctor3(doc.reference, source.reference)) {
+    jni.Jni.env.checkException();
+  }
 
-  static final _ctor4 = jlookup<
+  static final _ctor4 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>,
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -454,11 +462,13 @@
   ///@param source the parser which is used to read the pdf
   ///@param permission he access permissions of the pdf
   PDDocument.ctor4(
-      jni.JlObject doc, jni.JlObject source, jni.JlObject permission)
+      jni.JniObject doc, jni.JniObject source, jni.JniObject permission)
       : super.fromRef(
-            _ctor4(doc.reference, source.reference, permission.reference));
+            _ctor4(doc.reference, source.reference, permission.reference)) {
+    jni.Jni.env.checkException();
+  }
 
-  static final _addPage = jlookup<
+  static final _addPage = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -471,9 +481,13 @@
   /// This will add a page to the document. This is a convenience method, that will add the page to the root of the
   /// hierarchy and set the parent of the page to the root.
   ///@param page The page to add to the document.
-  void addPage(jni.JlObject page) => _addPage(reference, page.reference);
+  void addPage(jni.JniObject page) {
+    final result__ = _addPage(reference, page.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _addSignature = jlookup<
+  static final _addSignature = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -493,10 +507,13 @@
   ///@throws IOException if there is an error creating required fields
   ///@throws IllegalStateException if one attempts to add several signature
   /// fields.
-  void addSignature(jni.JlObject sigObject) =>
-      _addSignature(reference, sigObject.reference);
+  void addSignature(jni.JniObject sigObject) {
+    final result__ = _addSignature(reference, sigObject.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _addSignature1 = jlookup<
+  static final _addSignature1 = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(ffi.Pointer<ffi.Void>,
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -518,10 +535,14 @@
   ///@throws IOException if there is an error creating required fields
   ///@throws IllegalStateException if one attempts to add several signature
   /// fields.
-  void addSignature1(jni.JlObject sigObject, jni.JlObject options) =>
-      _addSignature1(reference, sigObject.reference, options.reference);
+  void addSignature1(jni.JniObject sigObject, jni.JniObject options) {
+    final result__ =
+        _addSignature1(reference, sigObject.reference, options.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _addSignature2 = jlookup<
+  static final _addSignature2 = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(ffi.Pointer<ffi.Void>,
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -542,11 +563,15 @@
   ///@throws IOException if there is an error creating required fields
   ///@throws IllegalStateException if one attempts to add several signature
   /// fields.
-  void addSignature2(jni.JlObject sigObject, jni.JlObject signatureInterface) =>
-      _addSignature2(
-          reference, sigObject.reference, signatureInterface.reference);
+  void addSignature2(
+      jni.JniObject sigObject, jni.JniObject signatureInterface) {
+    final result__ = _addSignature2(
+        reference, sigObject.reference, signatureInterface.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _addSignature3 = jlookup<
+  static final _addSignature3 = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>,
@@ -573,12 +598,15 @@
   ///@throws IOException if there is an error creating required fields
   ///@throws IllegalStateException if one attempts to add several signature
   /// fields.
-  void addSignature3(jni.JlObject sigObject, jni.JlObject signatureInterface,
-          jni.JlObject options) =>
-      _addSignature3(reference, sigObject.reference,
-          signatureInterface.reference, options.reference);
+  void addSignature3(jni.JniObject sigObject, jni.JniObject signatureInterface,
+      jni.JniObject options) {
+    final result__ = _addSignature3(reference, sigObject.reference,
+        signatureInterface.reference, options.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _findSignatureField = jlookup<
+  static final _findSignatureField = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>,
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -594,12 +622,15 @@
   ///@param fieldIterator iterator on all fields.
   ///@param sigObject signature object (the /V part).
   ///@return a signature field if found, or null if none was found.
-  jni.JlObject findSignatureField(
-          jni.JlObject fieldIterator, jni.JlObject sigObject) =>
-      jni.JlObject.fromRef(_findSignatureField(
-          reference, fieldIterator.reference, sigObject.reference));
+  jni.JniObject findSignatureField(
+      jni.JniObject fieldIterator, jni.JniObject sigObject) {
+    final result__ = jni.JniObject.fromRef(_findSignatureField(
+        reference, fieldIterator.reference, sigObject.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _checkSignatureField = jlookup<
+  static final _checkSignatureField = jniLookup<
               ffi.NativeFunction<
                   ffi.Uint8 Function(ffi.Pointer<ffi.Void>,
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -615,12 +646,15 @@
   ///@param signatureField the signature field.
   ///@return true if the field already existed in the field list, false if not.
   bool checkSignatureField(
-          jni.JlObject fieldIterator, jni.JlObject signatureField) =>
-      _checkSignatureField(
-          reference, fieldIterator.reference, signatureField.reference) !=
-      0;
+      jni.JniObject fieldIterator, jni.JniObject signatureField) {
+    final result__ = _checkSignatureField(
+            reference, fieldIterator.reference, signatureField.reference) !=
+        0;
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _checkSignatureAnnotation = jlookup<
+  static final _checkSignatureAnnotation = jniLookup<
               ffi.NativeFunction<
                   ffi.Uint8 Function(ffi.Pointer<ffi.Void>,
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -636,12 +670,15 @@
   ///@param widget the annotation widget.
   ///@return true if the widget already existed in the annotation list, false if not.
   bool checkSignatureAnnotation(
-          jni.JlObject annotations, jni.JlObject widget) =>
-      _checkSignatureAnnotation(
-          reference, annotations.reference, widget.reference) !=
-      0;
+      jni.JniObject annotations, jni.JniObject widget) {
+    final result__ = _checkSignatureAnnotation(
+            reference, annotations.reference, widget.reference) !=
+        0;
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _prepareVisibleSignature = jlookup<
+  static final _prepareVisibleSignature = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>,
@@ -654,12 +691,18 @@
               ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
 
   /// from: private void prepareVisibleSignature(org.apache.pdfbox.pdmodel.interactive.form.PDSignatureField signatureField, org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm acroForm, org.apache.pdfbox.cos.COSDocument visualSignature)
-  void prepareVisibleSignature(jni.JlObject signatureField,
-          jni.JlObject acroForm, jni.JlObject visualSignature) =>
-      _prepareVisibleSignature(reference, signatureField.reference,
-          acroForm.reference, visualSignature.reference);
+  void prepareVisibleSignature(jni.JniObject signatureField,
+      jni.JniObject acroForm, jni.JniObject visualSignature) {
+    final result__ = _prepareVisibleSignature(
+        reference,
+        signatureField.reference,
+        acroForm.reference,
+        visualSignature.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _assignSignatureRectangle = jlookup<
+  static final _assignSignatureRectangle = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(ffi.Pointer<ffi.Void>,
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -670,11 +713,14 @@
 
   /// from: private void assignSignatureRectangle(org.apache.pdfbox.pdmodel.interactive.form.PDSignatureField signatureField, org.apache.pdfbox.cos.COSDictionary annotDict)
   void assignSignatureRectangle(
-          jni.JlObject signatureField, jni.JlObject annotDict) =>
-      _assignSignatureRectangle(
-          reference, signatureField.reference, annotDict.reference);
+      jni.JniObject signatureField, jni.JniObject annotDict) {
+    final result__ = _assignSignatureRectangle(
+        reference, signatureField.reference, annotDict.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _assignAppearanceDictionary = jlookup<
+  static final _assignAppearanceDictionary = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(ffi.Pointer<ffi.Void>,
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -685,11 +731,14 @@
 
   /// from: private void assignAppearanceDictionary(org.apache.pdfbox.pdmodel.interactive.form.PDSignatureField signatureField, org.apache.pdfbox.cos.COSDictionary apDict)
   void assignAppearanceDictionary(
-          jni.JlObject signatureField, jni.JlObject apDict) =>
-      _assignAppearanceDictionary(
-          reference, signatureField.reference, apDict.reference);
+      jni.JniObject signatureField, jni.JniObject apDict) {
+    final result__ = _assignAppearanceDictionary(
+        reference, signatureField.reference, apDict.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _assignAcroFormDefaultResource = jlookup<
+  static final _assignAcroFormDefaultResource = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(ffi.Pointer<ffi.Void>,
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -700,11 +749,14 @@
 
   /// from: private void assignAcroFormDefaultResource(org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm acroForm, org.apache.pdfbox.cos.COSDictionary newDict)
   void assignAcroFormDefaultResource(
-          jni.JlObject acroForm, jni.JlObject newDict) =>
-      _assignAcroFormDefaultResource(
-          reference, acroForm.reference, newDict.reference);
+      jni.JniObject acroForm, jni.JniObject newDict) {
+    final result__ = _assignAcroFormDefaultResource(
+        reference, acroForm.reference, newDict.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _prepareNonVisibleSignature = jlookup<
+  static final _prepareNonVisibleSignature = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -713,10 +765,14 @@
           void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
 
   /// from: private void prepareNonVisibleSignature(org.apache.pdfbox.pdmodel.interactive.form.PDSignatureField signatureField)
-  void prepareNonVisibleSignature(jni.JlObject signatureField) =>
-      _prepareNonVisibleSignature(reference, signatureField.reference);
+  void prepareNonVisibleSignature(jni.JniObject signatureField) {
+    final result__ =
+        _prepareNonVisibleSignature(reference, signatureField.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _addSignatureField = jlookup<
+  static final _addSignatureField = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>,
@@ -738,12 +794,15 @@
   ///@throws IOException if there is an error creating required fields
   ///@deprecated The method is misleading, because only one signature may be
   /// added in a document. The method will be removed in the future.
-  void addSignatureField(jni.JlObject sigFields,
-          jni.JlObject signatureInterface, jni.JlObject options) =>
-      _addSignatureField(reference, sigFields.reference,
-          signatureInterface.reference, options.reference);
+  void addSignatureField(jni.JniObject sigFields,
+      jni.JniObject signatureInterface, jni.JniObject options) {
+    final result__ = _addSignatureField(reference, sigFields.reference,
+        signatureInterface.reference, options.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _removePage = jlookup<
+  static final _removePage = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -755,9 +814,13 @@
   ///
   /// Remove the page from the document.
   ///@param page The page to remove from the document.
-  void removePage(jni.JlObject page) => _removePage(reference, page.reference);
+  void removePage(jni.JniObject page) {
+    final result__ = _removePage(reference, page.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _removePage1 = jlookup<
+  static final _removePage1 = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Int32)>>(
           "org_apache_pdfbox_pdmodel_PDDocument_removePage1")
@@ -767,9 +830,13 @@
   ///
   /// Remove the page from the document.
   ///@param pageNumber 0 based index to page number.
-  void removePage1(int pageNumber) => _removePage1(reference, pageNumber);
+  void removePage1(int pageNumber) {
+    final result__ = _removePage1(reference, pageNumber);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _importPage = jlookup<
+  static final _importPage = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -802,10 +869,14 @@
   ///@param page The page to import.
   ///@return The page that was imported.
   ///@throws IOException If there is an error copying the page.
-  jni.JlObject importPage(jni.JlObject page) =>
-      jni.JlObject.fromRef(_importPage(reference, page.reference));
+  jni.JniObject importPage(jni.JniObject page) {
+    final result__ =
+        jni.JniObject.fromRef(_importPage(reference, page.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getDocument = jlookup<
+  static final _getDocument = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "org_apache_pdfbox_pdmodel_PDDocument_getDocument")
@@ -816,9 +887,13 @@
   ///
   /// This will get the low level document.
   ///@return The document that this layer sits on top of.
-  jni.JlObject getDocument() => jni.JlObject.fromRef(_getDocument(reference));
+  jni.JniObject getDocument() {
+    final result__ = jni.JniObject.fromRef(_getDocument(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getDocumentInformation = jlookup<
+  static final _getDocumentInformation = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "org_apache_pdfbox_pdmodel_PDDocument_getDocumentInformation")
@@ -834,10 +909,14 @@
   /// document level metadata, a metadata stream should be used instead, see
   /// PDDocumentCatalog\#getMetadata().
   ///@return The documents /Info dictionary, never null.
-  PDDocumentInformation getDocumentInformation() =>
-      PDDocumentInformation.fromRef(_getDocumentInformation(reference));
+  PDDocumentInformation getDocumentInformation() {
+    final result__ =
+        PDDocumentInformation.fromRef(_getDocumentInformation(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _setDocumentInformation = jlookup<
+  static final _setDocumentInformation = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -853,10 +932,13 @@
   /// document level metadata, a metadata stream should be used instead, see
   /// PDDocumentCatalog\#setMetadata(org.apache.pdfbox.pdmodel.common.PDMetadata) PDDocumentCatalog\#setMetadata(PDMetadata).
   ///@param info The updated document information.
-  void setDocumentInformation(PDDocumentInformation info) =>
-      _setDocumentInformation(reference, info.reference);
+  void setDocumentInformation(PDDocumentInformation info) {
+    final result__ = _setDocumentInformation(reference, info.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getDocumentCatalog = jlookup<
+  static final _getDocumentCatalog = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "org_apache_pdfbox_pdmodel_PDDocument_getDocumentCatalog")
@@ -867,11 +949,14 @@
   ///
   /// This will get the document CATALOG. This is guaranteed to not return null.
   ///@return The documents /Root dictionary
-  jni.JlObject getDocumentCatalog() =>
-      jni.JlObject.fromRef(_getDocumentCatalog(reference));
+  jni.JniObject getDocumentCatalog() {
+    final result__ = jni.JniObject.fromRef(_getDocumentCatalog(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _isEncrypted =
-      jlookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
               "org_apache_pdfbox_pdmodel_PDDocument_isEncrypted")
           .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
@@ -879,9 +964,13 @@
   ///
   /// This will tell if this document is encrypted or not.
   ///@return true If this document is encrypted.
-  bool isEncrypted() => _isEncrypted(reference) != 0;
+  bool isEncrypted() {
+    final result__ = _isEncrypted(reference) != 0;
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getEncryption = jlookup<
+  static final _getEncryption = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "org_apache_pdfbox_pdmodel_PDDocument_getEncryption")
@@ -895,10 +984,13 @@
   /// but the only supported subclass at this time is a
   /// PDStandardEncryption object.
   ///@return The encryption dictionary(most likely a PDStandardEncryption object)
-  jni.JlObject getEncryption() =>
-      jni.JlObject.fromRef(_getEncryption(reference));
+  jni.JniObject getEncryption() {
+    final result__ = jni.JniObject.fromRef(_getEncryption(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _setEncryptionDictionary = jlookup<
+  static final _setEncryptionDictionary = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -911,10 +1003,13 @@
   /// This will set the encryption dictionary for this document.
   ///@param encryption The encryption dictionary(most likely a PDStandardEncryption object)
   ///@throws IOException If there is an error determining which security handler to use.
-  void setEncryptionDictionary(jni.JlObject encryption) =>
-      _setEncryptionDictionary(reference, encryption.reference);
+  void setEncryptionDictionary(jni.JniObject encryption) {
+    final result__ = _setEncryptionDictionary(reference, encryption.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getLastSignatureDictionary = jlookup<
+  static final _getLastSignatureDictionary = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "org_apache_pdfbox_pdmodel_PDDocument_getLastSignatureDictionary")
@@ -927,10 +1022,14 @@
   /// last in time when empty signature fields are created first but signed after other fields.
   ///@return the last signature as <code>PDSignatureField</code>.
   ///@throws IOException if no document catalog can be found.
-  jni.JlObject getLastSignatureDictionary() =>
-      jni.JlObject.fromRef(_getLastSignatureDictionary(reference));
+  jni.JniObject getLastSignatureDictionary() {
+    final result__ =
+        jni.JniObject.fromRef(_getLastSignatureDictionary(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getSignatureFields = jlookup<
+  static final _getSignatureFields = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "org_apache_pdfbox_pdmodel_PDDocument_getSignatureFields")
@@ -942,10 +1041,13 @@
   /// Retrieve all signature fields from the document.
   ///@return a <code>List</code> of <code>PDSignatureField</code>s
   ///@throws IOException if no document catalog can be found.
-  jni.JlObject getSignatureFields() =>
-      jni.JlObject.fromRef(_getSignatureFields(reference));
+  jni.JniObject getSignatureFields() {
+    final result__ = jni.JniObject.fromRef(_getSignatureFields(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getSignatureDictionaries = jlookup<
+  static final _getSignatureDictionaries = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "org_apache_pdfbox_pdmodel_PDDocument_getSignatureDictionaries")
@@ -957,10 +1059,14 @@
   /// Retrieve all signature dictionaries from the document.
   ///@return a <code>List</code> of <code>PDSignatureField</code>s
   ///@throws IOException if no document catalog can be found.
-  jni.JlObject getSignatureDictionaries() =>
-      jni.JlObject.fromRef(_getSignatureDictionaries(reference));
+  jni.JniObject getSignatureDictionaries() {
+    final result__ =
+        jni.JniObject.fromRef(_getSignatureDictionaries(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _registerTrueTypeFontForClosing = jlookup<
+  static final _registerTrueTypeFontForClosing = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -974,10 +1080,13 @@
   /// is closed when the PDDocument is closed to avoid memory leaks. Users don't have to call this
   /// method, it is done by the appropriate PDFont classes.
   ///@param ttf
-  void registerTrueTypeFontForClosing(jni.JlObject ttf) =>
-      _registerTrueTypeFontForClosing(reference, ttf.reference);
+  void registerTrueTypeFontForClosing(jni.JniObject ttf) {
+    final result__ = _registerTrueTypeFontForClosing(reference, ttf.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getFontsToSubset = jlookup<
+  static final _getFontsToSubset = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "org_apache_pdfbox_pdmodel_PDDocument_getFontsToSubset")
@@ -987,10 +1096,13 @@
   /// The returned object must be deleted after use, by calling the `delete` method.
   ///
   /// Returns the list of fonts which will be subset before the document is saved.
-  jni.JlObject getFontsToSubset() =>
-      jni.JlObject.fromRef(_getFontsToSubset(reference));
+  jni.JniObject getFontsToSubset() {
+    final result__ = jni.JniObject.fromRef(_getFontsToSubset(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _load = jlookup<
+  static final _load = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "org_apache_pdfbox_pdmodel_PDDocument_load")
@@ -1004,10 +1116,13 @@
   ///@return loaded document
   ///@throws InvalidPasswordException If the file required a non-empty password.
   ///@throws IOException in case of a file reading or parsing error
-  static PDDocument load(jni.JlObject file) =>
-      PDDocument.fromRef(_load(file.reference));
+  static PDDocument load(jni.JniObject file) {
+    final result__ = PDDocument.fromRef(_load(file.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _load1 = jlookup<
+  static final _load1 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1025,10 +1140,14 @@
   ///@return loaded document
   ///@throws InvalidPasswordException If the file required a non-empty password.
   ///@throws IOException in case of a file reading or parsing error
-  static PDDocument load1(jni.JlObject file, jni.JlObject memUsageSetting) =>
-      PDDocument.fromRef(_load1(file.reference, memUsageSetting.reference));
+  static PDDocument load1(jni.JniObject file, jni.JniObject memUsageSetting) {
+    final result__ =
+        PDDocument.fromRef(_load1(file.reference, memUsageSetting.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _load2 = jlookup<
+  static final _load2 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1046,10 +1165,14 @@
   ///@return loaded document
   ///@throws InvalidPasswordException If the password is incorrect.
   ///@throws IOException in case of a file reading or parsing error
-  static PDDocument load2(jni.JlObject file, jni.JlString password) =>
-      PDDocument.fromRef(_load2(file.reference, password.reference));
+  static PDDocument load2(jni.JniObject file, jni.JniString password) {
+    final result__ =
+        PDDocument.fromRef(_load2(file.reference, password.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _load3 = jlookup<
+  static final _load3 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>,
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1068,12 +1191,15 @@
   ///@return loaded document
   ///@throws InvalidPasswordException If the password is incorrect.
   ///@throws IOException in case of a file reading or parsing error
-  static PDDocument load3(jni.JlObject file, jni.JlString password,
-          jni.JlObject memUsageSetting) =>
-      PDDocument.fromRef(_load3(
-          file.reference, password.reference, memUsageSetting.reference));
+  static PDDocument load3(jni.JniObject file, jni.JniString password,
+      jni.JniObject memUsageSetting) {
+    final result__ = PDDocument.fromRef(
+        _load3(file.reference, password.reference, memUsageSetting.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _load4 = jlookup<
+  static final _load4 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>,
@@ -1098,12 +1224,15 @@
   ///@param alias alias to be used for decryption when using public key security
   ///@return loaded document
   ///@throws IOException in case of a file reading or parsing error
-  static PDDocument load4(jni.JlObject file, jni.JlString password,
-          jni.JlObject keyStore, jni.JlString alias) =>
-      PDDocument.fromRef(_load4(file.reference, password.reference,
-          keyStore.reference, alias.reference));
+  static PDDocument load4(jni.JniObject file, jni.JniString password,
+      jni.JniObject keyStore, jni.JniString alias) {
+    final result__ = PDDocument.fromRef(_load4(file.reference,
+        password.reference, keyStore.reference, alias.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _load5 = jlookup<
+  static final _load5 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>,
@@ -1132,15 +1261,22 @@
   ///@return loaded document
   ///@throws IOException in case of a file reading or parsing error
   static PDDocument load5(
-          jni.JlObject file,
-          jni.JlString password,
-          jni.JlObject keyStore,
-          jni.JlString alias,
-          jni.JlObject memUsageSetting) =>
-      PDDocument.fromRef(_load5(file.reference, password.reference,
-          keyStore.reference, alias.reference, memUsageSetting.reference));
+      jni.JniObject file,
+      jni.JniString password,
+      jni.JniObject keyStore,
+      jni.JniString alias,
+      jni.JniObject memUsageSetting) {
+    final result__ = PDDocument.fromRef(_load5(
+        file.reference,
+        password.reference,
+        keyStore.reference,
+        alias.reference,
+        memUsageSetting.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _load6 = jlookup<
+  static final _load6 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>,
@@ -1160,15 +1296,22 @@
   /// from: private static org.apache.pdfbox.pdmodel.PDDocument load(org.apache.pdfbox.io.RandomAccessBufferedFileInputStream raFile, java.lang.String password, java.io.InputStream keyStore, java.lang.String alias, org.apache.pdfbox.io.MemoryUsageSetting memUsageSetting)
   /// The returned object must be deleted after use, by calling the `delete` method.
   static PDDocument load6(
-          jni.JlObject raFile,
-          jni.JlString password,
-          jni.JlObject keyStore,
-          jni.JlString alias,
-          jni.JlObject memUsageSetting) =>
-      PDDocument.fromRef(_load6(raFile.reference, password.reference,
-          keyStore.reference, alias.reference, memUsageSetting.reference));
+      jni.JniObject raFile,
+      jni.JniString password,
+      jni.JniObject keyStore,
+      jni.JniString alias,
+      jni.JniObject memUsageSetting) {
+    final result__ = PDDocument.fromRef(_load6(
+        raFile.reference,
+        password.reference,
+        keyStore.reference,
+        alias.reference,
+        memUsageSetting.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _load7 = jlookup<
+  static final _load7 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "org_apache_pdfbox_pdmodel_PDDocument_load7")
@@ -1183,10 +1326,13 @@
   ///@return loaded document
   ///@throws InvalidPasswordException If the PDF required a non-empty password.
   ///@throws IOException In case of a reading or parsing error.
-  static PDDocument load7(jni.JlObject input) =>
-      PDDocument.fromRef(_load7(input.reference));
+  static PDDocument load7(jni.JniObject input) {
+    final result__ = PDDocument.fromRef(_load7(input.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _load8 = jlookup<
+  static final _load8 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1205,10 +1351,14 @@
   ///@return loaded document
   ///@throws InvalidPasswordException If the PDF required a non-empty password.
   ///@throws IOException In case of a reading or parsing error.
-  static PDDocument load8(jni.JlObject input, jni.JlObject memUsageSetting) =>
-      PDDocument.fromRef(_load8(input.reference, memUsageSetting.reference));
+  static PDDocument load8(jni.JniObject input, jni.JniObject memUsageSetting) {
+    final result__ =
+        PDDocument.fromRef(_load8(input.reference, memUsageSetting.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _load9 = jlookup<
+  static final _load9 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1227,10 +1377,14 @@
   ///@return loaded document
   ///@throws InvalidPasswordException If the password is incorrect.
   ///@throws IOException In case of a reading or parsing error.
-  static PDDocument load9(jni.JlObject input, jni.JlString password) =>
-      PDDocument.fromRef(_load9(input.reference, password.reference));
+  static PDDocument load9(jni.JniObject input, jni.JniString password) {
+    final result__ =
+        PDDocument.fromRef(_load9(input.reference, password.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _load10 = jlookup<
+  static final _load10 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>,
@@ -1256,12 +1410,15 @@
   ///@param alias alias to be used for decryption when using public key security
   ///@return loaded document
   ///@throws IOException In case of a reading or parsing error.
-  static PDDocument load10(jni.JlObject input, jni.JlString password,
-          jni.JlObject keyStore, jni.JlString alias) =>
-      PDDocument.fromRef(_load10(input.reference, password.reference,
-          keyStore.reference, alias.reference));
+  static PDDocument load10(jni.JniObject input, jni.JniString password,
+      jni.JniObject keyStore, jni.JniString alias) {
+    final result__ = PDDocument.fromRef(_load10(input.reference,
+        password.reference, keyStore.reference, alias.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _load11 = jlookup<
+  static final _load11 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>,
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1281,12 +1438,15 @@
   ///@return loaded document
   ///@throws InvalidPasswordException If the password is incorrect.
   ///@throws IOException In case of a reading or parsing error.
-  static PDDocument load11(jni.JlObject input, jni.JlString password,
-          jni.JlObject memUsageSetting) =>
-      PDDocument.fromRef(_load11(
-          input.reference, password.reference, memUsageSetting.reference));
+  static PDDocument load11(jni.JniObject input, jni.JniString password,
+      jni.JniObject memUsageSetting) {
+    final result__ = PDDocument.fromRef(_load11(
+        input.reference, password.reference, memUsageSetting.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _load12 = jlookup<
+  static final _load12 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>,
@@ -1317,15 +1477,22 @@
   ///@throws InvalidPasswordException If the password is incorrect.
   ///@throws IOException In case of a reading or parsing error.
   static PDDocument load12(
-          jni.JlObject input,
-          jni.JlString password,
-          jni.JlObject keyStore,
-          jni.JlString alias,
-          jni.JlObject memUsageSetting) =>
-      PDDocument.fromRef(_load12(input.reference, password.reference,
-          keyStore.reference, alias.reference, memUsageSetting.reference));
+      jni.JniObject input,
+      jni.JniString password,
+      jni.JniObject keyStore,
+      jni.JniString alias,
+      jni.JniObject memUsageSetting) {
+    final result__ = PDDocument.fromRef(_load12(
+        input.reference,
+        password.reference,
+        keyStore.reference,
+        alias.reference,
+        memUsageSetting.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _load13 = jlookup<
+  static final _load13 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "org_apache_pdfbox_pdmodel_PDDocument_load13")
@@ -1339,10 +1506,13 @@
   ///@return loaded document
   ///@throws InvalidPasswordException If the PDF required a non-empty password.
   ///@throws IOException In case of a reading or parsing error.
-  static PDDocument load13(jni.JlObject input) =>
-      PDDocument.fromRef(_load13(input.reference));
+  static PDDocument load13(jni.JniObject input) {
+    final result__ = PDDocument.fromRef(_load13(input.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _load14 = jlookup<
+  static final _load14 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1360,10 +1530,14 @@
   ///@return loaded document
   ///@throws InvalidPasswordException If the password is incorrect.
   ///@throws IOException In case of a reading or parsing error.
-  static PDDocument load14(jni.JlObject input, jni.JlString password) =>
-      PDDocument.fromRef(_load14(input.reference, password.reference));
+  static PDDocument load14(jni.JniObject input, jni.JniString password) {
+    final result__ =
+        PDDocument.fromRef(_load14(input.reference, password.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _load15 = jlookup<
+  static final _load15 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>,
@@ -1389,12 +1563,15 @@
   ///@return loaded document
   ///@throws InvalidPasswordException If the password is incorrect.
   ///@throws IOException In case of a reading or parsing error.
-  static PDDocument load15(jni.JlObject input, jni.JlString password,
-          jni.JlObject keyStore, jni.JlString alias) =>
-      PDDocument.fromRef(_load15(input.reference, password.reference,
-          keyStore.reference, alias.reference));
+  static PDDocument load15(jni.JniObject input, jni.JniString password,
+      jni.JniObject keyStore, jni.JniString alias) {
+    final result__ = PDDocument.fromRef(_load15(input.reference,
+        password.reference, keyStore.reference, alias.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _load16 = jlookup<
+  static final _load16 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>,
@@ -1424,15 +1601,22 @@
   ///@throws InvalidPasswordException If the password is incorrect.
   ///@throws IOException In case of a reading or parsing error.
   static PDDocument load16(
-          jni.JlObject input,
-          jni.JlString password,
-          jni.JlObject keyStore,
-          jni.JlString alias,
-          jni.JlObject memUsageSetting) =>
-      PDDocument.fromRef(_load16(input.reference, password.reference,
-          keyStore.reference, alias.reference, memUsageSetting.reference));
+      jni.JniObject input,
+      jni.JniString password,
+      jni.JniObject keyStore,
+      jni.JniString alias,
+      jni.JniObject memUsageSetting) {
+    final result__ = PDDocument.fromRef(_load16(
+        input.reference,
+        password.reference,
+        keyStore.reference,
+        alias.reference,
+        memUsageSetting.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _save = jlookup<
+  static final _save = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1449,9 +1633,13 @@
   /// do not use the document after saving because the contents are now encrypted.
   ///@param fileName The file to save as.
   ///@throws IOException if the output could not be written
-  void save(jni.JlString fileName) => _save(reference, fileName.reference);
+  void save(jni.JniString fileName) {
+    final result__ = _save(reference, fileName.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _save1 = jlookup<
+  static final _save1 = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1468,9 +1656,13 @@
   /// do not use the document after saving because the contents are now encrypted.
   ///@param file The file to save as.
   ///@throws IOException if the output could not be written
-  void save1(jni.JlObject file) => _save1(reference, file.reference);
+  void save1(jni.JniObject file) {
+    final result__ = _save1(reference, file.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _save2 = jlookup<
+  static final _save2 = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1488,9 +1680,13 @@
   ///@param output The stream to write to. It will be closed when done. It is recommended to wrap
   /// it in a java.io.BufferedOutputStream, unless it is already buffered.
   ///@throws IOException if the output could not be written
-  void save2(jni.JlObject output) => _save2(reference, output.reference);
+  void save2(jni.JniObject output) {
+    final result__ = _save2(reference, output.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _saveIncremental = jlookup<
+  static final _saveIncremental = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1513,10 +1709,13 @@
   /// harmed!
   ///@throws IOException if the output could not be written
   ///@throws IllegalStateException if the document was not loaded from a file or a stream.
-  void saveIncremental(jni.JlObject output) =>
-      _saveIncremental(reference, output.reference);
+  void saveIncremental(jni.JniObject output) {
+    final result__ = _saveIncremental(reference, output.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _saveIncremental1 = jlookup<
+  static final _saveIncremental1 = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(ffi.Pointer<ffi.Void>,
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1545,10 +1744,14 @@
   ///@param objectsToWrite objects that __must__ be part of the incremental saving.
   ///@throws IOException if the output could not be written
   ///@throws IllegalStateException if the document was not loaded from a file or a stream.
-  void saveIncremental1(jni.JlObject output, jni.JlObject objectsToWrite) =>
-      _saveIncremental1(reference, output.reference, objectsToWrite.reference);
+  void saveIncremental1(jni.JniObject output, jni.JniObject objectsToWrite) {
+    final result__ = _saveIncremental1(
+        reference, output.reference, objectsToWrite.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _saveIncrementalForExternalSigning = jlookup<
+  static final _saveIncrementalForExternalSigning = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1597,11 +1800,14 @@
   ///@throws IOException if the output could not be written
   ///@throws IllegalStateException if the document was not loaded from a file or a stream or
   /// signature options were not set.
-  jni.JlObject saveIncrementalForExternalSigning(jni.JlObject output) =>
-      jni.JlObject.fromRef(
-          _saveIncrementalForExternalSigning(reference, output.reference));
+  jni.JniObject saveIncrementalForExternalSigning(jni.JniObject output) {
+    final result__ = jni.JniObject.fromRef(
+        _saveIncrementalForExternalSigning(reference, output.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getPage = jlookup<
+  static final _getPage = jniLookup<
           ffi.NativeFunction<
               ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>,
                   ffi.Int32)>>("org_apache_pdfbox_pdmodel_PDDocument_getPage")
@@ -1617,10 +1823,13 @@
   /// PDDocument\#getPages() instead.
   ///@param pageIndex the 0-based page index
   ///@return the page at the given index.
-  jni.JlObject getPage(int pageIndex) =>
-      jni.JlObject.fromRef(_getPage(reference, pageIndex));
+  jni.JniObject getPage(int pageIndex) {
+    final result__ = jni.JniObject.fromRef(_getPage(reference, pageIndex));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getPages = jlookup<
+  static final _getPages = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "org_apache_pdfbox_pdmodel_PDDocument_getPages")
@@ -1631,10 +1840,14 @@
   ///
   /// Returns the page tree.
   ///@return the page tree
-  jni.JlObject getPages() => jni.JlObject.fromRef(_getPages(reference));
+  jni.JniObject getPages() {
+    final result__ = jni.JniObject.fromRef(_getPages(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _getNumberOfPages =
-      jlookup<ffi.NativeFunction<ffi.Int32 Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Int32 Function(ffi.Pointer<ffi.Void>)>>(
               "org_apache_pdfbox_pdmodel_PDDocument_getNumberOfPages")
           .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
@@ -1642,10 +1855,14 @@
   ///
   /// This will return the total page count of the PDF document.
   ///@return The total number of pages in the PDF document.
-  int getNumberOfPages() => _getNumberOfPages(reference);
+  int getNumberOfPages() {
+    final result__ = _getNumberOfPages(reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _close =
-      jlookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
               "org_apache_pdfbox_pdmodel_PDDocument_close")
           .asFunction<void Function(ffi.Pointer<ffi.Void>)>();
 
@@ -1653,9 +1870,13 @@
   ///
   /// This will close the underlying COSDocument object.
   ///@throws IOException If there is an error releasing resources.
-  void close() => _close(reference);
+  void close() {
+    final result__ = _close(reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _protect = jlookup<
+  static final _protect = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1675,9 +1896,13 @@
   ///@see org.apache.pdfbox.pdmodel.encryption.PublicKeyProtectionPolicy
   ///@param policy The protection policy.
   ///@throws IOException if there isn't any suitable security handler.
-  void protect(jni.JlObject policy) => _protect(reference, policy.reference);
+  void protect(jni.JniObject policy) {
+    final result__ = _protect(reference, policy.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getCurrentAccessPermission = jlookup<
+  static final _getCurrentAccessPermission = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "org_apache_pdfbox_pdmodel_PDDocument_getCurrentAccessPermission")
@@ -1691,11 +1916,15 @@
   /// only mode so that permissions cannot be changed. Methods providing access to content should rely on this object
   /// to verify if the current user is allowed to proceed.
   ///@return the access permissions for the current user on the document.
-  jni.JlObject getCurrentAccessPermission() =>
-      jni.JlObject.fromRef(_getCurrentAccessPermission(reference));
+  jni.JniObject getCurrentAccessPermission() {
+    final result__ =
+        jni.JniObject.fromRef(_getCurrentAccessPermission(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _isAllSecurityToBeRemoved =
-      jlookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
               "org_apache_pdfbox_pdmodel_PDDocument_isAllSecurityToBeRemoved")
           .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
@@ -1703,9 +1932,13 @@
   ///
   /// Indicates if all security is removed or not when writing the pdf.
   ///@return returns true if all security shall be removed otherwise false
-  bool isAllSecurityToBeRemoved() => _isAllSecurityToBeRemoved(reference) != 0;
+  bool isAllSecurityToBeRemoved() {
+    final result__ = _isAllSecurityToBeRemoved(reference) != 0;
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _setAllSecurityToBeRemoved = jlookup<
+  static final _setAllSecurityToBeRemoved = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Uint8)>>(
           "org_apache_pdfbox_pdmodel_PDDocument_setAllSecurityToBeRemoved")
@@ -1715,10 +1948,14 @@
   ///
   /// Activates/Deactivates the removal of all security when writing the pdf.
   ///@param removeAllSecurity remove all security if set to true
-  void setAllSecurityToBeRemoved(bool removeAllSecurity) =>
-      _setAllSecurityToBeRemoved(reference, removeAllSecurity ? 1 : 0);
+  void setAllSecurityToBeRemoved(bool removeAllSecurity) {
+    final result__ =
+        _setAllSecurityToBeRemoved(reference, removeAllSecurity ? 1 : 0);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getDocumentId = jlookup<
+  static final _getDocumentId = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "org_apache_pdfbox_pdmodel_PDDocument_getDocumentId")
@@ -1729,10 +1966,13 @@
   ///
   /// Provides the document ID.
   ///@return the document ID
-  jni.JlObject getDocumentId() =>
-      jni.JlObject.fromRef(_getDocumentId(reference));
+  jni.JniObject getDocumentId() {
+    final result__ = jni.JniObject.fromRef(_getDocumentId(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _setDocumentId = jlookup<
+  static final _setDocumentId = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1744,11 +1984,14 @@
   ///
   /// Sets the document ID to the given value.
   ///@param docId the new document ID
-  void setDocumentId(jni.JlObject docId) =>
-      _setDocumentId(reference, docId.reference);
+  void setDocumentId(jni.JniObject docId) {
+    final result__ = _setDocumentId(reference, docId.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _getVersion =
-      jlookup<ffi.NativeFunction<ffi.Float Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Float Function(ffi.Pointer<ffi.Void>)>>(
               "org_apache_pdfbox_pdmodel_PDDocument_getVersion")
           .asFunction<double Function(ffi.Pointer<ffi.Void>)>();
 
@@ -1756,9 +1999,13 @@
   ///
   /// Returns the PDF specification version this document conforms to.
   ///@return the PDF version (e.g. 1.4f)
-  double getVersion() => _getVersion(reference);
+  double getVersion() {
+    final result__ = _getVersion(reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _setVersion = jlookup<
+  static final _setVersion = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Float)>>(
           "org_apache_pdfbox_pdmodel_PDDocument_setVersion")
@@ -1768,9 +2015,13 @@
   ///
   /// Sets the PDF specification version for this document.
   ///@param newVersion the new PDF version (e.g. 1.4f)
-  void setVersion(double newVersion) => _setVersion(reference, newVersion);
+  void setVersion(double newVersion) {
+    final result__ = _setVersion(reference, newVersion);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getResourceCache = jlookup<
+  static final _getResourceCache = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "org_apache_pdfbox_pdmodel_PDDocument_getResourceCache")
@@ -1781,10 +2032,13 @@
   ///
   /// Returns the resource cache associated with this document, or null if there is none.
   ///@return the resource cache or null.
-  jni.JlObject getResourceCache() =>
-      jni.JlObject.fromRef(_getResourceCache(reference));
+  jni.JniObject getResourceCache() {
+    final result__ = jni.JniObject.fromRef(_getResourceCache(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _setResourceCache = jlookup<
+  static final _setResourceCache = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1796,8 +2050,11 @@
   ///
   /// Sets the resource cache associated with this document.
   ///@param resourceCache A resource cache, or null.
-  void setResourceCache(jni.JlObject resourceCache) =>
-      _setResourceCache(reference, resourceCache.reference);
+  void setResourceCache(jni.JniObject resourceCache) {
+    final result__ = _setResourceCache(reference, resourceCache.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 }
 
 /// from: org.apache.pdfbox.pdmodel.PDDocumentInformation
@@ -1807,10 +2064,10 @@
 /// method then it will clear the value.
 ///@author Ben Litchfield
 ///@author Gerardo Ortiz
-class PDDocumentInformation extends jni.JlObject {
+class PDDocumentInformation extends jni.JniObject {
   PDDocumentInformation.fromRef(ffi.Pointer<ffi.Void> ref) : super.fromRef(ref);
 
-  static final _get_info = jlookup<
+  static final _get_info = jniLookup<
           ffi.NativeFunction<
               ffi.Pointer<ffi.Void> Function(
     ffi.Pointer<ffi.Void>,
@@ -1822,19 +2079,21 @@
 
   /// from: private final org.apache.pdfbox.cos.COSDictionary info
   /// The returned object must be deleted after use, by calling the `delete` method.
-  jni.JlObject get info => jni.JlObject.fromRef(_get_info(reference));
+  jni.JniObject get info => jni.JniObject.fromRef(_get_info(reference));
 
   static final _ctor =
-      jlookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function()>>(
+      jniLookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function()>>(
               "org_apache_pdfbox_pdmodel_PDDocumentInformation_ctor")
           .asFunction<ffi.Pointer<ffi.Void> Function()>();
 
   /// from: public void <init>()
   ///
   /// Default Constructor.
-  PDDocumentInformation() : super.fromRef(_ctor());
+  PDDocumentInformation() : super.fromRef(_ctor()) {
+    jni.Jni.env.checkException();
+  }
 
-  static final _ctor1 = jlookup<
+  static final _ctor1 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "org_apache_pdfbox_pdmodel_PDDocumentInformation_ctor1")
@@ -1844,10 +2103,12 @@
   ///
   /// Constructor that is used for a preexisting dictionary.
   ///@param dic The underlying dictionary.
-  PDDocumentInformation.ctor1(jni.JlObject dic)
-      : super.fromRef(_ctor1(dic.reference));
+  PDDocumentInformation.ctor1(jni.JniObject dic)
+      : super.fromRef(_ctor1(dic.reference)) {
+    jni.Jni.env.checkException();
+  }
 
-  static final _getCOSObject = jlookup<
+  static final _getCOSObject = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "org_apache_pdfbox_pdmodel_PDDocumentInformation_getCOSObject")
@@ -1858,9 +2119,13 @@
   ///
   /// This will get the underlying dictionary that this object wraps.
   ///@return The underlying info dictionary.
-  jni.JlObject getCOSObject() => jni.JlObject.fromRef(_getCOSObject(reference));
+  jni.JniObject getCOSObject() {
+    final result__ = jni.JniObject.fromRef(_getCOSObject(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getPropertyStringValue = jlookup<
+  static final _getPropertyStringValue = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1880,11 +2145,14 @@
   ///
   ///@param propertyKey the dictionaries key
   ///@return the properties value
-  jni.JlObject getPropertyStringValue(jni.JlString propertyKey) =>
-      jni.JlObject.fromRef(
-          _getPropertyStringValue(reference, propertyKey.reference));
+  jni.JniObject getPropertyStringValue(jni.JniString propertyKey) {
+    final result__ = jni.JniObject.fromRef(
+        _getPropertyStringValue(reference, propertyKey.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getTitle = jlookup<
+  static final _getTitle = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "org_apache_pdfbox_pdmodel_PDDocumentInformation_getTitle")
@@ -1895,9 +2163,13 @@
   ///
   /// This will get the title of the document.  This will return null if no title exists.
   ///@return The title of the document.
-  jni.JlString getTitle() => jni.JlString.fromRef(_getTitle(reference));
+  jni.JniString getTitle() {
+    final result__ = jni.JniString.fromRef(_getTitle(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _setTitle = jlookup<
+  static final _setTitle = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1909,9 +2181,13 @@
   ///
   /// This will set the title of the document.
   ///@param title The new title for the document.
-  void setTitle(jni.JlString title) => _setTitle(reference, title.reference);
+  void setTitle(jni.JniString title) {
+    final result__ = _setTitle(reference, title.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getAuthor = jlookup<
+  static final _getAuthor = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "org_apache_pdfbox_pdmodel_PDDocumentInformation_getAuthor")
@@ -1922,9 +2198,13 @@
   ///
   /// This will get the author of the document.  This will return null if no author exists.
   ///@return The author of the document.
-  jni.JlString getAuthor() => jni.JlString.fromRef(_getAuthor(reference));
+  jni.JniString getAuthor() {
+    final result__ = jni.JniString.fromRef(_getAuthor(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _setAuthor = jlookup<
+  static final _setAuthor = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1936,10 +2216,13 @@
   ///
   /// This will set the author of the document.
   ///@param author The new author for the document.
-  void setAuthor(jni.JlString author) =>
-      _setAuthor(reference, author.reference);
+  void setAuthor(jni.JniString author) {
+    final result__ = _setAuthor(reference, author.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getSubject = jlookup<
+  static final _getSubject = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "org_apache_pdfbox_pdmodel_PDDocumentInformation_getSubject")
@@ -1950,9 +2233,13 @@
   ///
   /// This will get the subject of the document.  This will return null if no subject exists.
   ///@return The subject of the document.
-  jni.JlString getSubject() => jni.JlString.fromRef(_getSubject(reference));
+  jni.JniString getSubject() {
+    final result__ = jni.JniString.fromRef(_getSubject(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _setSubject = jlookup<
+  static final _setSubject = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1964,10 +2251,13 @@
   ///
   /// This will set the subject of the document.
   ///@param subject The new subject for the document.
-  void setSubject(jni.JlString subject) =>
-      _setSubject(reference, subject.reference);
+  void setSubject(jni.JniString subject) {
+    final result__ = _setSubject(reference, subject.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getKeywords = jlookup<
+  static final _getKeywords = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "org_apache_pdfbox_pdmodel_PDDocumentInformation_getKeywords")
@@ -1978,9 +2268,13 @@
   ///
   /// This will get the keywords of the document.  This will return null if no keywords exists.
   ///@return The keywords of the document.
-  jni.JlString getKeywords() => jni.JlString.fromRef(_getKeywords(reference));
+  jni.JniString getKeywords() {
+    final result__ = jni.JniString.fromRef(_getKeywords(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _setKeywords = jlookup<
+  static final _setKeywords = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1992,10 +2286,13 @@
   ///
   /// This will set the keywords of the document.
   ///@param keywords The new keywords for the document.
-  void setKeywords(jni.JlString keywords) =>
-      _setKeywords(reference, keywords.reference);
+  void setKeywords(jni.JniString keywords) {
+    final result__ = _setKeywords(reference, keywords.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getCreator = jlookup<
+  static final _getCreator = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "org_apache_pdfbox_pdmodel_PDDocumentInformation_getCreator")
@@ -2006,9 +2303,13 @@
   ///
   /// This will get the creator of the document.  This will return null if no creator exists.
   ///@return The creator of the document.
-  jni.JlString getCreator() => jni.JlString.fromRef(_getCreator(reference));
+  jni.JniString getCreator() {
+    final result__ = jni.JniString.fromRef(_getCreator(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _setCreator = jlookup<
+  static final _setCreator = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -2020,10 +2321,13 @@
   ///
   /// This will set the creator of the document.
   ///@param creator The new creator for the document.
-  void setCreator(jni.JlString creator) =>
-      _setCreator(reference, creator.reference);
+  void setCreator(jni.JniString creator) {
+    final result__ = _setCreator(reference, creator.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getProducer = jlookup<
+  static final _getProducer = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "org_apache_pdfbox_pdmodel_PDDocumentInformation_getProducer")
@@ -2034,9 +2338,13 @@
   ///
   /// This will get the producer of the document.  This will return null if no producer exists.
   ///@return The producer of the document.
-  jni.JlString getProducer() => jni.JlString.fromRef(_getProducer(reference));
+  jni.JniString getProducer() {
+    final result__ = jni.JniString.fromRef(_getProducer(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _setProducer = jlookup<
+  static final _setProducer = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -2048,10 +2356,13 @@
   ///
   /// This will set the producer of the document.
   ///@param producer The new producer for the document.
-  void setProducer(jni.JlString producer) =>
-      _setProducer(reference, producer.reference);
+  void setProducer(jni.JniString producer) {
+    final result__ = _setProducer(reference, producer.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getCreationDate = jlookup<
+  static final _getCreationDate = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "org_apache_pdfbox_pdmodel_PDDocumentInformation_getCreationDate")
@@ -2062,10 +2373,13 @@
   ///
   /// This will get the creation date of the document.  This will return null if no creation date exists.
   ///@return The creation date of the document.
-  jni.JlObject getCreationDate() =>
-      jni.JlObject.fromRef(_getCreationDate(reference));
+  jni.JniObject getCreationDate() {
+    final result__ = jni.JniObject.fromRef(_getCreationDate(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _setCreationDate = jlookup<
+  static final _setCreationDate = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -2077,10 +2391,13 @@
   ///
   /// This will set the creation date of the document.
   ///@param date The new creation date for the document.
-  void setCreationDate(jni.JlObject date) =>
-      _setCreationDate(reference, date.reference);
+  void setCreationDate(jni.JniObject date) {
+    final result__ = _setCreationDate(reference, date.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getModificationDate = jlookup<
+  static final _getModificationDate = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "org_apache_pdfbox_pdmodel_PDDocumentInformation_getModificationDate")
@@ -2091,10 +2408,13 @@
   ///
   /// This will get the modification date of the document.  This will return null if no modification date exists.
   ///@return The modification date of the document.
-  jni.JlObject getModificationDate() =>
-      jni.JlObject.fromRef(_getModificationDate(reference));
+  jni.JniObject getModificationDate() {
+    final result__ = jni.JniObject.fromRef(_getModificationDate(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _setModificationDate = jlookup<
+  static final _setModificationDate = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -2106,10 +2426,13 @@
   ///
   /// This will set the modification date of the document.
   ///@param date The new modification date for the document.
-  void setModificationDate(jni.JlObject date) =>
-      _setModificationDate(reference, date.reference);
+  void setModificationDate(jni.JniObject date) {
+    final result__ = _setModificationDate(reference, date.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getTrapped = jlookup<
+  static final _getTrapped = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "org_apache_pdfbox_pdmodel_PDDocumentInformation_getTrapped")
@@ -2121,9 +2444,13 @@
   /// This will get the trapped value for the document.
   /// This will return null if one is not found.
   ///@return The trapped value for the document.
-  jni.JlString getTrapped() => jni.JlString.fromRef(_getTrapped(reference));
+  jni.JniString getTrapped() {
+    final result__ = jni.JniString.fromRef(_getTrapped(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getMetadataKeys = jlookup<
+  static final _getMetadataKeys = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "org_apache_pdfbox_pdmodel_PDDocumentInformation_getMetadataKeys")
@@ -2135,10 +2462,13 @@
   /// This will get the keys of all metadata information fields for the document.
   ///@return all metadata key strings.
   ///@since Apache PDFBox 1.3.0
-  jni.JlObject getMetadataKeys() =>
-      jni.JlObject.fromRef(_getMetadataKeys(reference));
+  jni.JniObject getMetadataKeys() {
+    final result__ = jni.JniObject.fromRef(_getMetadataKeys(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getCustomMetadataValue = jlookup<
+  static final _getCustomMetadataValue = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -2154,11 +2484,14 @@
   ///  This will return null if one is not found.
   ///@param fieldName Name of custom metadata field from pdf document.
   ///@return String Value of metadata field
-  jni.JlString getCustomMetadataValue(jni.JlString fieldName) =>
-      jni.JlString.fromRef(
-          _getCustomMetadataValue(reference, fieldName.reference));
+  jni.JniString getCustomMetadataValue(jni.JniString fieldName) {
+    final result__ = jni.JniString.fromRef(
+        _getCustomMetadataValue(reference, fieldName.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _setCustomMetadataValue = jlookup<
+  static final _setCustomMetadataValue = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(ffi.Pointer<ffi.Void>,
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -2173,11 +2506,14 @@
   ///@param fieldName The name of the custom metadata field.
   ///@param fieldValue The value to the custom metadata field.
   void setCustomMetadataValue(
-          jni.JlString fieldName, jni.JlString fieldValue) =>
-      _setCustomMetadataValue(
-          reference, fieldName.reference, fieldValue.reference);
+      jni.JniString fieldName, jni.JniString fieldValue) {
+    final result__ = _setCustomMetadataValue(
+        reference, fieldName.reference, fieldValue.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _setTrapped = jlookup<
+  static final _setTrapped = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -2191,6 +2527,9 @@
   /// 'True', 'False', or 'Unknown'.
   ///@param value The new trapped value for the document.
   ///@throws IllegalArgumentException if the parameter is invalid.
-  void setTrapped(jni.JlString value) =>
-      _setTrapped(reference, value.reference);
+  void setTrapped(jni.JniString value) {
+    final result__ = _setTrapped(reference, value.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 }
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/lib/third_party/org/apache/pdfbox/text.dart b/pkgs/jnigen/example/pdfbox_plugin/lib/third_party/org/apache/pdfbox/text.dart
similarity index 76%
rename from pkgs/jnigen/examples/pdfbox_plugin/lib/third_party/org/apache/pdfbox/text.dart
rename to pkgs/jnigen/example/pdfbox_plugin/lib/third_party/org/apache/pdfbox/text.dart
index 6a7d7cc..ca4f36c 100644
--- a/pkgs/jnigen/examples/pdfbox_plugin/lib/third_party/org/apache/pdfbox/text.dart
+++ b/pkgs/jnigen/example/pdfbox_plugin/lib/third_party/org/apache/pdfbox/text.dart
@@ -26,11 +26,10 @@
 // ignore_for_file: unused_element
 
 import "dart:ffi" as ffi;
-
 import "package:jni/jni.dart" as jni;
 
 import "../pdfbox/pdmodel.dart" as pdmodel_;
-import "../../../init.dart" show jlookup;
+import "../../../_init.dart" show jniLookup;
 
 /// from: org.apache.pdfbox.text.PDFTextStripper
 ///
@@ -41,17 +40,17 @@
 /// The basic flow of this process is that we get a document and use a series of processXXX() functions that work on
 /// smaller and smaller chunks of the page. Eventually, we fully process each page and then print it.
 ///@author Ben Litchfield
-class PDFTextStripper extends jni.JlObject {
+class PDFTextStripper extends jni.JniObject {
   PDFTextStripper.fromRef(ffi.Pointer<ffi.Void> ref) : super.fromRef(ref);
 
-  static final _get_defaultIndentThreshold = jlookup<
+  static final _get_defaultIndentThreshold = jniLookup<
               ffi.NativeFunction<ffi.Float Function()>>(
           "get_org_apache_pdfbox_text_PDFTextStripper_defaultIndentThreshold")
       .asFunction<double Function()>();
 
   /// from: private static float defaultIndentThreshold
   static double get defaultIndentThreshold => _get_defaultIndentThreshold();
-  static final _set_defaultIndentThreshold = jlookup<
+  static final _set_defaultIndentThreshold = jniLookup<
               ffi.NativeFunction<ffi.Void Function(ffi.Float)>>(
           "set_org_apache_pdfbox_text_PDFTextStripper_defaultIndentThreshold")
       .asFunction<void Function(double)>();
@@ -61,14 +60,14 @@
       _set_defaultIndentThreshold(value);
 
   static final _get_defaultDropThreshold =
-      jlookup<ffi.NativeFunction<ffi.Float Function()>>(
+      jniLookup<ffi.NativeFunction<ffi.Float Function()>>(
               "get_org_apache_pdfbox_text_PDFTextStripper_defaultDropThreshold")
           .asFunction<double Function()>();
 
   /// from: private static float defaultDropThreshold
   static double get defaultDropThreshold => _get_defaultDropThreshold();
   static final _set_defaultDropThreshold =
-      jlookup<ffi.NativeFunction<ffi.Void Function(ffi.Float)>>(
+      jniLookup<ffi.NativeFunction<ffi.Void Function(ffi.Float)>>(
               "set_org_apache_pdfbox_text_PDFTextStripper_defaultDropThreshold")
           .asFunction<void Function(double)>();
 
@@ -77,15 +76,15 @@
       _set_defaultDropThreshold(value);
 
   static final _get_LOG =
-      jlookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function()>>(
+      jniLookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function()>>(
               "get_org_apache_pdfbox_text_PDFTextStripper_LOG")
           .asFunction<ffi.Pointer<ffi.Void> Function()>();
 
   /// from: private static final org.apache.commons.logging.Log LOG
   /// The returned object must be deleted after use, by calling the `delete` method.
-  static jni.JlObject get LOG => jni.JlObject.fromRef(_get_LOG());
+  static jni.JniObject get LOG => jni.JniObject.fromRef(_get_LOG());
 
-  static final _get_LINE_SEPARATOR = jlookup<
+  static final _get_LINE_SEPARATOR = jniLookup<
           ffi.NativeFunction<
               ffi.Pointer<ffi.Void> Function(
     ffi.Pointer<ffi.Void>,
@@ -99,10 +98,10 @@
   /// The returned object must be deleted after use, by calling the `delete` method.
   ///
   /// The platform's line separator.
-  jni.JlString get LINE_SEPARATOR =>
-      jni.JlString.fromRef(_get_LINE_SEPARATOR(reference));
+  jni.JniString get LINE_SEPARATOR =>
+      jni.JniString.fromRef(_get_LINE_SEPARATOR(reference));
 
-  static final _get_lineSeparator = jlookup<
+  static final _get_lineSeparator = jniLookup<
           ffi.NativeFunction<
               ffi.Pointer<ffi.Void> Function(
     ffi.Pointer<ffi.Void>,
@@ -114,9 +113,9 @@
 
   /// from: private java.lang.String lineSeparator
   /// The returned object must be deleted after use, by calling the `delete` method.
-  jni.JlString get lineSeparator =>
-      jni.JlString.fromRef(_get_lineSeparator(reference));
-  static final _set_lineSeparator = jlookup<
+  jni.JniString get lineSeparator =>
+      jni.JniString.fromRef(_get_lineSeparator(reference));
+  static final _set_lineSeparator = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -126,10 +125,10 @@
 
   /// from: private java.lang.String lineSeparator
   /// The returned object must be deleted after use, by calling the `delete` method.
-  set lineSeparator(jni.JlString value) =>
+  set lineSeparator(jni.JniString value) =>
       _set_lineSeparator(reference, value.reference);
 
-  static final _get_wordSeparator = jlookup<
+  static final _get_wordSeparator = jniLookup<
           ffi.NativeFunction<
               ffi.Pointer<ffi.Void> Function(
     ffi.Pointer<ffi.Void>,
@@ -141,9 +140,9 @@
 
   /// from: private java.lang.String wordSeparator
   /// The returned object must be deleted after use, by calling the `delete` method.
-  jni.JlString get wordSeparator =>
-      jni.JlString.fromRef(_get_wordSeparator(reference));
-  static final _set_wordSeparator = jlookup<
+  jni.JniString get wordSeparator =>
+      jni.JniString.fromRef(_get_wordSeparator(reference));
+  static final _set_wordSeparator = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -153,10 +152,10 @@
 
   /// from: private java.lang.String wordSeparator
   /// The returned object must be deleted after use, by calling the `delete` method.
-  set wordSeparator(jni.JlString value) =>
+  set wordSeparator(jni.JniString value) =>
       _set_wordSeparator(reference, value.reference);
 
-  static final _get_paragraphStart = jlookup<
+  static final _get_paragraphStart = jniLookup<
           ffi.NativeFunction<
               ffi.Pointer<ffi.Void> Function(
     ffi.Pointer<ffi.Void>,
@@ -168,9 +167,9 @@
 
   /// from: private java.lang.String paragraphStart
   /// The returned object must be deleted after use, by calling the `delete` method.
-  jni.JlString get paragraphStart =>
-      jni.JlString.fromRef(_get_paragraphStart(reference));
-  static final _set_paragraphStart = jlookup<
+  jni.JniString get paragraphStart =>
+      jni.JniString.fromRef(_get_paragraphStart(reference));
+  static final _set_paragraphStart = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -180,10 +179,10 @@
 
   /// from: private java.lang.String paragraphStart
   /// The returned object must be deleted after use, by calling the `delete` method.
-  set paragraphStart(jni.JlString value) =>
+  set paragraphStart(jni.JniString value) =>
       _set_paragraphStart(reference, value.reference);
 
-  static final _get_paragraphEnd = jlookup<
+  static final _get_paragraphEnd = jniLookup<
           ffi.NativeFunction<
               ffi.Pointer<ffi.Void> Function(
     ffi.Pointer<ffi.Void>,
@@ -195,9 +194,9 @@
 
   /// from: private java.lang.String paragraphEnd
   /// The returned object must be deleted after use, by calling the `delete` method.
-  jni.JlString get paragraphEnd =>
-      jni.JlString.fromRef(_get_paragraphEnd(reference));
-  static final _set_paragraphEnd = jlookup<
+  jni.JniString get paragraphEnd =>
+      jni.JniString.fromRef(_get_paragraphEnd(reference));
+  static final _set_paragraphEnd = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -207,10 +206,10 @@
 
   /// from: private java.lang.String paragraphEnd
   /// The returned object must be deleted after use, by calling the `delete` method.
-  set paragraphEnd(jni.JlString value) =>
+  set paragraphEnd(jni.JniString value) =>
       _set_paragraphEnd(reference, value.reference);
 
-  static final _get_pageStart = jlookup<
+  static final _get_pageStart = jniLookup<
           ffi.NativeFunction<
               ffi.Pointer<ffi.Void> Function(
     ffi.Pointer<ffi.Void>,
@@ -222,8 +221,9 @@
 
   /// from: private java.lang.String pageStart
   /// The returned object must be deleted after use, by calling the `delete` method.
-  jni.JlString get pageStart => jni.JlString.fromRef(_get_pageStart(reference));
-  static final _set_pageStart = jlookup<
+  jni.JniString get pageStart =>
+      jni.JniString.fromRef(_get_pageStart(reference));
+  static final _set_pageStart = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -233,10 +233,10 @@
 
   /// from: private java.lang.String pageStart
   /// The returned object must be deleted after use, by calling the `delete` method.
-  set pageStart(jni.JlString value) =>
+  set pageStart(jni.JniString value) =>
       _set_pageStart(reference, value.reference);
 
-  static final _get_pageEnd = jlookup<
+  static final _get_pageEnd = jniLookup<
           ffi.NativeFunction<
               ffi.Pointer<ffi.Void> Function(
     ffi.Pointer<ffi.Void>,
@@ -248,8 +248,8 @@
 
   /// from: private java.lang.String pageEnd
   /// The returned object must be deleted after use, by calling the `delete` method.
-  jni.JlString get pageEnd => jni.JlString.fromRef(_get_pageEnd(reference));
-  static final _set_pageEnd = jlookup<
+  jni.JniString get pageEnd => jni.JniString.fromRef(_get_pageEnd(reference));
+  static final _set_pageEnd = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -259,9 +259,9 @@
 
   /// from: private java.lang.String pageEnd
   /// The returned object must be deleted after use, by calling the `delete` method.
-  set pageEnd(jni.JlString value) => _set_pageEnd(reference, value.reference);
+  set pageEnd(jni.JniString value) => _set_pageEnd(reference, value.reference);
 
-  static final _get_articleStart = jlookup<
+  static final _get_articleStart = jniLookup<
           ffi.NativeFunction<
               ffi.Pointer<ffi.Void> Function(
     ffi.Pointer<ffi.Void>,
@@ -273,9 +273,9 @@
 
   /// from: private java.lang.String articleStart
   /// The returned object must be deleted after use, by calling the `delete` method.
-  jni.JlString get articleStart =>
-      jni.JlString.fromRef(_get_articleStart(reference));
-  static final _set_articleStart = jlookup<
+  jni.JniString get articleStart =>
+      jni.JniString.fromRef(_get_articleStart(reference));
+  static final _set_articleStart = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -285,10 +285,10 @@
 
   /// from: private java.lang.String articleStart
   /// The returned object must be deleted after use, by calling the `delete` method.
-  set articleStart(jni.JlString value) =>
+  set articleStart(jni.JniString value) =>
       _set_articleStart(reference, value.reference);
 
-  static final _get_articleEnd = jlookup<
+  static final _get_articleEnd = jniLookup<
           ffi.NativeFunction<
               ffi.Pointer<ffi.Void> Function(
     ffi.Pointer<ffi.Void>,
@@ -300,9 +300,9 @@
 
   /// from: private java.lang.String articleEnd
   /// The returned object must be deleted after use, by calling the `delete` method.
-  jni.JlString get articleEnd =>
-      jni.JlString.fromRef(_get_articleEnd(reference));
-  static final _set_articleEnd = jlookup<
+  jni.JniString get articleEnd =>
+      jni.JniString.fromRef(_get_articleEnd(reference));
+  static final _set_articleEnd = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -312,10 +312,10 @@
 
   /// from: private java.lang.String articleEnd
   /// The returned object must be deleted after use, by calling the `delete` method.
-  set articleEnd(jni.JlString value) =>
+  set articleEnd(jni.JniString value) =>
       _set_articleEnd(reference, value.reference);
 
-  static final _get_currentPageNo = jlookup<
+  static final _get_currentPageNo = jniLookup<
           ffi.NativeFunction<
               ffi.Int32 Function(
     ffi.Pointer<ffi.Void>,
@@ -327,7 +327,7 @@
 
   /// from: private int currentPageNo
   int get currentPageNo => _get_currentPageNo(reference);
-  static final _set_currentPageNo = jlookup<
+  static final _set_currentPageNo = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Int32)>>(
           "set_org_apache_pdfbox_text_PDFTextStripper_currentPageNo")
@@ -336,7 +336,7 @@
   /// from: private int currentPageNo
   set currentPageNo(int value) => _set_currentPageNo(reference, value);
 
-  static final _get_startPage = jlookup<
+  static final _get_startPage = jniLookup<
           ffi.NativeFunction<
               ffi.Int32 Function(
     ffi.Pointer<ffi.Void>,
@@ -348,7 +348,7 @@
 
   /// from: private int startPage
   int get startPage => _get_startPage(reference);
-  static final _set_startPage = jlookup<
+  static final _set_startPage = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Int32)>>(
           "set_org_apache_pdfbox_text_PDFTextStripper_startPage")
@@ -357,7 +357,7 @@
   /// from: private int startPage
   set startPage(int value) => _set_startPage(reference, value);
 
-  static final _get_endPage = jlookup<
+  static final _get_endPage = jniLookup<
           ffi.NativeFunction<
               ffi.Int32 Function(
     ffi.Pointer<ffi.Void>,
@@ -369,7 +369,7 @@
 
   /// from: private int endPage
   int get endPage => _get_endPage(reference);
-  static final _set_endPage = jlookup<
+  static final _set_endPage = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Int32)>>(
           "set_org_apache_pdfbox_text_PDFTextStripper_endPage")
@@ -378,7 +378,7 @@
   /// from: private int endPage
   set endPage(int value) => _set_endPage(reference, value);
 
-  static final _get_startBookmark = jlookup<
+  static final _get_startBookmark = jniLookup<
           ffi.NativeFunction<
               ffi.Pointer<ffi.Void> Function(
     ffi.Pointer<ffi.Void>,
@@ -390,9 +390,9 @@
 
   /// from: private org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline.PDOutlineItem startBookmark
   /// The returned object must be deleted after use, by calling the `delete` method.
-  jni.JlObject get startBookmark =>
-      jni.JlObject.fromRef(_get_startBookmark(reference));
-  static final _set_startBookmark = jlookup<
+  jni.JniObject get startBookmark =>
+      jni.JniObject.fromRef(_get_startBookmark(reference));
+  static final _set_startBookmark = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -402,10 +402,10 @@
 
   /// from: private org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline.PDOutlineItem startBookmark
   /// The returned object must be deleted after use, by calling the `delete` method.
-  set startBookmark(jni.JlObject value) =>
+  set startBookmark(jni.JniObject value) =>
       _set_startBookmark(reference, value.reference);
 
-  static final _get_startBookmarkPageNumber = jlookup<
+  static final _get_startBookmarkPageNumber = jniLookup<
           ffi.NativeFunction<
               ffi.Int32 Function(
     ffi.Pointer<ffi.Void>,
@@ -417,7 +417,7 @@
 
   /// from: private int startBookmarkPageNumber
   int get startBookmarkPageNumber => _get_startBookmarkPageNumber(reference);
-  static final _set_startBookmarkPageNumber = jlookup<
+  static final _set_startBookmarkPageNumber = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Int32)>>(
           "set_org_apache_pdfbox_text_PDFTextStripper_startBookmarkPageNumber")
@@ -427,7 +427,7 @@
   set startBookmarkPageNumber(int value) =>
       _set_startBookmarkPageNumber(reference, value);
 
-  static final _get_endBookmarkPageNumber = jlookup<
+  static final _get_endBookmarkPageNumber = jniLookup<
           ffi.NativeFunction<
               ffi.Int32 Function(
     ffi.Pointer<ffi.Void>,
@@ -439,7 +439,7 @@
 
   /// from: private int endBookmarkPageNumber
   int get endBookmarkPageNumber => _get_endBookmarkPageNumber(reference);
-  static final _set_endBookmarkPageNumber = jlookup<
+  static final _set_endBookmarkPageNumber = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Int32)>>(
           "set_org_apache_pdfbox_text_PDFTextStripper_endBookmarkPageNumber")
@@ -449,7 +449,7 @@
   set endBookmarkPageNumber(int value) =>
       _set_endBookmarkPageNumber(reference, value);
 
-  static final _get_endBookmark = jlookup<
+  static final _get_endBookmark = jniLookup<
           ffi.NativeFunction<
               ffi.Pointer<ffi.Void> Function(
     ffi.Pointer<ffi.Void>,
@@ -461,9 +461,9 @@
 
   /// from: private org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline.PDOutlineItem endBookmark
   /// The returned object must be deleted after use, by calling the `delete` method.
-  jni.JlObject get endBookmark =>
-      jni.JlObject.fromRef(_get_endBookmark(reference));
-  static final _set_endBookmark = jlookup<
+  jni.JniObject get endBookmark =>
+      jni.JniObject.fromRef(_get_endBookmark(reference));
+  static final _set_endBookmark = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -473,10 +473,10 @@
 
   /// from: private org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline.PDOutlineItem endBookmark
   /// The returned object must be deleted after use, by calling the `delete` method.
-  set endBookmark(jni.JlObject value) =>
+  set endBookmark(jni.JniObject value) =>
       _set_endBookmark(reference, value.reference);
 
-  static final _get_suppressDuplicateOverlappingText = jlookup<
+  static final _get_suppressDuplicateOverlappingText = jniLookup<
           ffi.NativeFunction<
               ffi.Uint8 Function(
     ffi.Pointer<ffi.Void>,
@@ -489,7 +489,7 @@
   /// from: private boolean suppressDuplicateOverlappingText
   bool get suppressDuplicateOverlappingText =>
       _get_suppressDuplicateOverlappingText(reference) != 0;
-  static final _set_suppressDuplicateOverlappingText = jlookup<
+  static final _set_suppressDuplicateOverlappingText = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Uint8)>>(
           "set_org_apache_pdfbox_text_PDFTextStripper_suppressDuplicateOverlappingText")
@@ -499,7 +499,7 @@
   set suppressDuplicateOverlappingText(bool value) =>
       _set_suppressDuplicateOverlappingText(reference, value ? 1 : 0);
 
-  static final _get_shouldSeparateByBeads = jlookup<
+  static final _get_shouldSeparateByBeads = jniLookup<
           ffi.NativeFunction<
               ffi.Uint8 Function(
     ffi.Pointer<ffi.Void>,
@@ -511,7 +511,7 @@
 
   /// from: private boolean shouldSeparateByBeads
   bool get shouldSeparateByBeads => _get_shouldSeparateByBeads(reference) != 0;
-  static final _set_shouldSeparateByBeads = jlookup<
+  static final _set_shouldSeparateByBeads = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Uint8)>>(
           "set_org_apache_pdfbox_text_PDFTextStripper_shouldSeparateByBeads")
@@ -521,7 +521,7 @@
   set shouldSeparateByBeads(bool value) =>
       _set_shouldSeparateByBeads(reference, value ? 1 : 0);
 
-  static final _get_sortByPosition = jlookup<
+  static final _get_sortByPosition = jniLookup<
           ffi.NativeFunction<
               ffi.Uint8 Function(
     ffi.Pointer<ffi.Void>,
@@ -533,7 +533,7 @@
 
   /// from: private boolean sortByPosition
   bool get sortByPosition => _get_sortByPosition(reference) != 0;
-  static final _set_sortByPosition = jlookup<
+  static final _set_sortByPosition = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Uint8)>>(
           "set_org_apache_pdfbox_text_PDFTextStripper_sortByPosition")
@@ -543,7 +543,7 @@
   set sortByPosition(bool value) =>
       _set_sortByPosition(reference, value ? 1 : 0);
 
-  static final _get_addMoreFormatting = jlookup<
+  static final _get_addMoreFormatting = jniLookup<
           ffi.NativeFunction<
               ffi.Uint8 Function(
     ffi.Pointer<ffi.Void>,
@@ -555,7 +555,7 @@
 
   /// from: private boolean addMoreFormatting
   bool get addMoreFormatting => _get_addMoreFormatting(reference) != 0;
-  static final _set_addMoreFormatting = jlookup<
+  static final _set_addMoreFormatting = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Uint8)>>(
           "set_org_apache_pdfbox_text_PDFTextStripper_addMoreFormatting")
@@ -565,7 +565,7 @@
   set addMoreFormatting(bool value) =>
       _set_addMoreFormatting(reference, value ? 1 : 0);
 
-  static final _get_indentThreshold = jlookup<
+  static final _get_indentThreshold = jniLookup<
           ffi.NativeFunction<
               ffi.Float Function(
     ffi.Pointer<ffi.Void>,
@@ -577,7 +577,7 @@
 
   /// from: private float indentThreshold
   double get indentThreshold => _get_indentThreshold(reference);
-  static final _set_indentThreshold = jlookup<
+  static final _set_indentThreshold = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Float)>>(
           "set_org_apache_pdfbox_text_PDFTextStripper_indentThreshold")
@@ -586,7 +586,7 @@
   /// from: private float indentThreshold
   set indentThreshold(double value) => _set_indentThreshold(reference, value);
 
-  static final _get_dropThreshold = jlookup<
+  static final _get_dropThreshold = jniLookup<
           ffi.NativeFunction<
               ffi.Float Function(
     ffi.Pointer<ffi.Void>,
@@ -598,7 +598,7 @@
 
   /// from: private float dropThreshold
   double get dropThreshold => _get_dropThreshold(reference);
-  static final _set_dropThreshold = jlookup<
+  static final _set_dropThreshold = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Float)>>(
           "set_org_apache_pdfbox_text_PDFTextStripper_dropThreshold")
@@ -607,7 +607,7 @@
   /// from: private float dropThreshold
   set dropThreshold(double value) => _set_dropThreshold(reference, value);
 
-  static final _get_spacingTolerance = jlookup<
+  static final _get_spacingTolerance = jniLookup<
           ffi.NativeFunction<
               ffi.Float Function(
     ffi.Pointer<ffi.Void>,
@@ -619,7 +619,7 @@
 
   /// from: private float spacingTolerance
   double get spacingTolerance => _get_spacingTolerance(reference);
-  static final _set_spacingTolerance = jlookup<
+  static final _set_spacingTolerance = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Float)>>(
           "set_org_apache_pdfbox_text_PDFTextStripper_spacingTolerance")
@@ -628,7 +628,7 @@
   /// from: private float spacingTolerance
   set spacingTolerance(double value) => _set_spacingTolerance(reference, value);
 
-  static final _get_averageCharTolerance = jlookup<
+  static final _get_averageCharTolerance = jniLookup<
           ffi.NativeFunction<
               ffi.Float Function(
     ffi.Pointer<ffi.Void>,
@@ -640,7 +640,7 @@
 
   /// from: private float averageCharTolerance
   double get averageCharTolerance => _get_averageCharTolerance(reference);
-  static final _set_averageCharTolerance = jlookup<
+  static final _set_averageCharTolerance = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Float)>>(
           "set_org_apache_pdfbox_text_PDFTextStripper_averageCharTolerance")
@@ -650,7 +650,7 @@
   set averageCharTolerance(double value) =>
       _set_averageCharTolerance(reference, value);
 
-  static final _get_beadRectangles = jlookup<
+  static final _get_beadRectangles = jniLookup<
           ffi.NativeFunction<
               ffi.Pointer<ffi.Void> Function(
     ffi.Pointer<ffi.Void>,
@@ -662,9 +662,9 @@
 
   /// from: private java.util.List<org.apache.pdfbox.pdmodel.common.PDRectangle> beadRectangles
   /// The returned object must be deleted after use, by calling the `delete` method.
-  jni.JlObject get beadRectangles =>
-      jni.JlObject.fromRef(_get_beadRectangles(reference));
-  static final _set_beadRectangles = jlookup<
+  jni.JniObject get beadRectangles =>
+      jni.JniObject.fromRef(_get_beadRectangles(reference));
+  static final _set_beadRectangles = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -674,10 +674,10 @@
 
   /// from: private java.util.List<org.apache.pdfbox.pdmodel.common.PDRectangle> beadRectangles
   /// The returned object must be deleted after use, by calling the `delete` method.
-  set beadRectangles(jni.JlObject value) =>
+  set beadRectangles(jni.JniObject value) =>
       _set_beadRectangles(reference, value.reference);
 
-  static final _get_charactersByArticle = jlookup<
+  static final _get_charactersByArticle = jniLookup<
           ffi.NativeFunction<
               ffi.Pointer<ffi.Void> Function(
     ffi.Pointer<ffi.Void>,
@@ -702,9 +702,9 @@
   /// text after second article
   ///
   /// Most PDFs won't have any beads, so charactersByArticle will contain a single entry.
-  jni.JlObject get charactersByArticle =>
-      jni.JlObject.fromRef(_get_charactersByArticle(reference));
-  static final _set_charactersByArticle = jlookup<
+  jni.JniObject get charactersByArticle =>
+      jni.JniObject.fromRef(_get_charactersByArticle(reference));
+  static final _set_charactersByArticle = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -727,10 +727,10 @@
   /// text after second article
   ///
   /// Most PDFs won't have any beads, so charactersByArticle will contain a single entry.
-  set charactersByArticle(jni.JlObject value) =>
+  set charactersByArticle(jni.JniObject value) =>
       _set_charactersByArticle(reference, value.reference);
 
-  static final _get_characterListMapping = jlookup<
+  static final _get_characterListMapping = jniLookup<
           ffi.NativeFunction<
               ffi.Pointer<ffi.Void> Function(
     ffi.Pointer<ffi.Void>,
@@ -742,9 +742,9 @@
 
   /// from: private java.util.Map<java.lang.String,java.util.TreeMap<java.lang.Float,java.util.TreeSet<java.lang.Float>>> characterListMapping
   /// The returned object must be deleted after use, by calling the `delete` method.
-  jni.JlObject get characterListMapping =>
-      jni.JlObject.fromRef(_get_characterListMapping(reference));
-  static final _set_characterListMapping = jlookup<
+  jni.JniObject get characterListMapping =>
+      jni.JniObject.fromRef(_get_characterListMapping(reference));
+  static final _set_characterListMapping = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -754,10 +754,10 @@
 
   /// from: private java.util.Map<java.lang.String,java.util.TreeMap<java.lang.Float,java.util.TreeSet<java.lang.Float>>> characterListMapping
   /// The returned object must be deleted after use, by calling the `delete` method.
-  set characterListMapping(jni.JlObject value) =>
+  set characterListMapping(jni.JniObject value) =>
       _set_characterListMapping(reference, value.reference);
 
-  static final _get_document = jlookup<
+  static final _get_document = jniLookup<
           ffi.NativeFunction<
               ffi.Pointer<ffi.Void> Function(
     ffi.Pointer<ffi.Void>,
@@ -771,7 +771,7 @@
   /// The returned object must be deleted after use, by calling the `delete` method.
   pdmodel_.PDDocument get document =>
       pdmodel_.PDDocument.fromRef(_get_document(reference));
-  static final _set_document = jlookup<
+  static final _set_document = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -784,7 +784,7 @@
   set document(pdmodel_.PDDocument value) =>
       _set_document(reference, value.reference);
 
-  static final _get_output = jlookup<
+  static final _get_output = jniLookup<
           ffi.NativeFunction<
               ffi.Pointer<ffi.Void> Function(
     ffi.Pointer<ffi.Void>,
@@ -796,8 +796,8 @@
 
   /// from: protected java.io.Writer output
   /// The returned object must be deleted after use, by calling the `delete` method.
-  jni.JlObject get output => jni.JlObject.fromRef(_get_output(reference));
-  static final _set_output = jlookup<
+  jni.JniObject get output => jni.JniObject.fromRef(_get_output(reference));
+  static final _set_output = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -807,9 +807,9 @@
 
   /// from: protected java.io.Writer output
   /// The returned object must be deleted after use, by calling the `delete` method.
-  set output(jni.JlObject value) => _set_output(reference, value.reference);
+  set output(jni.JniObject value) => _set_output(reference, value.reference);
 
-  static final _get_inParagraph = jlookup<
+  static final _get_inParagraph = jniLookup<
           ffi.NativeFunction<
               ffi.Uint8 Function(
     ffi.Pointer<ffi.Void>,
@@ -823,7 +823,7 @@
   ///
   /// True if we started a paragraph but haven't ended it yet.
   bool get inParagraph => _get_inParagraph(reference) != 0;
-  static final _set_inParagraph = jlookup<
+  static final _set_inParagraph = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Uint8)>>(
           "set_org_apache_pdfbox_text_PDFTextStripper_inParagraph")
@@ -852,7 +852,7 @@
   /// from: private static final float LAST_WORD_SPACING_RESET_VALUE
   static const LAST_WORD_SPACING_RESET_VALUE = -1.0;
 
-  static final _get_LIST_ITEM_EXPRESSIONS = jlookup<
+  static final _get_LIST_ITEM_EXPRESSIONS = jniLookup<
               ffi.NativeFunction<ffi.Pointer<ffi.Void> Function()>>(
           "get_org_apache_pdfbox_text_PDFTextStripper_LIST_ITEM_EXPRESSIONS")
       .asFunction<ffi.Pointer<ffi.Void> Function()>();
@@ -862,10 +862,10 @@
   ///
   /// a list of regular expressions that match commonly used list item formats, i.e. bullets, numbers, letters, Roman
   /// numerals, etc. Not meant to be comprehensive.
-  static jni.JlObject get LIST_ITEM_EXPRESSIONS =>
-      jni.JlObject.fromRef(_get_LIST_ITEM_EXPRESSIONS());
+  static jni.JniObject get LIST_ITEM_EXPRESSIONS =>
+      jni.JniObject.fromRef(_get_LIST_ITEM_EXPRESSIONS());
 
-  static final _get_listOfPatterns = jlookup<
+  static final _get_listOfPatterns = jniLookup<
           ffi.NativeFunction<
               ffi.Pointer<ffi.Void> Function(
     ffi.Pointer<ffi.Void>,
@@ -877,9 +877,9 @@
 
   /// from: private java.util.List<java.util.regex.Pattern> listOfPatterns
   /// The returned object must be deleted after use, by calling the `delete` method.
-  jni.JlObject get listOfPatterns =>
-      jni.JlObject.fromRef(_get_listOfPatterns(reference));
-  static final _set_listOfPatterns = jlookup<
+  jni.JniObject get listOfPatterns =>
+      jni.JniObject.fromRef(_get_listOfPatterns(reference));
+  static final _set_listOfPatterns = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -889,30 +889,30 @@
 
   /// from: private java.util.List<java.util.regex.Pattern> listOfPatterns
   /// The returned object must be deleted after use, by calling the `delete` method.
-  set listOfPatterns(jni.JlObject value) =>
+  set listOfPatterns(jni.JniObject value) =>
       _set_listOfPatterns(reference, value.reference);
 
   static final _get_MIRRORING_CHAR_MAP =
-      jlookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function()>>(
+      jniLookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function()>>(
               "get_org_apache_pdfbox_text_PDFTextStripper_MIRRORING_CHAR_MAP")
           .asFunction<ffi.Pointer<ffi.Void> Function()>();
 
   /// from: private static java.util.Map<java.lang.Character,java.lang.Character> MIRRORING_CHAR_MAP
   /// The returned object must be deleted after use, by calling the `delete` method.
-  static jni.JlObject get MIRRORING_CHAR_MAP =>
-      jni.JlObject.fromRef(_get_MIRRORING_CHAR_MAP());
+  static jni.JniObject get MIRRORING_CHAR_MAP =>
+      jni.JniObject.fromRef(_get_MIRRORING_CHAR_MAP());
   static final _set_MIRRORING_CHAR_MAP =
-      jlookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
               "set_org_apache_pdfbox_text_PDFTextStripper_MIRRORING_CHAR_MAP")
           .asFunction<void Function(ffi.Pointer<ffi.Void>)>();
 
   /// from: private static java.util.Map<java.lang.Character,java.lang.Character> MIRRORING_CHAR_MAP
   /// The returned object must be deleted after use, by calling the `delete` method.
-  static set MIRRORING_CHAR_MAP(jni.JlObject value) =>
+  static set MIRRORING_CHAR_MAP(jni.JniObject value) =>
       _set_MIRRORING_CHAR_MAP(value.reference);
 
   static final _ctor =
-      jlookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function()>>(
+      jniLookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function()>>(
               "org_apache_pdfbox_text_PDFTextStripper_ctor")
           .asFunction<ffi.Pointer<ffi.Void> Function()>();
 
@@ -920,9 +920,11 @@
   ///
   /// Instantiate a new PDFTextStripper object.
   ///@throws IOException If there is an error loading the properties.
-  PDFTextStripper() : super.fromRef(_ctor());
+  PDFTextStripper() : super.fromRef(_ctor()) {
+    jni.Jni.env.checkException();
+  }
 
-  static final _getText = jlookup<
+  static final _getText = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -944,18 +946,25 @@
   ///@param doc The document to get the text from.
   ///@return The text of the PDF document.
   ///@throws IOException if the doc state is invalid or it is encrypted.
-  jni.JlString getText(pdmodel_.PDDocument doc) =>
-      jni.JlString.fromRef(_getText(reference, doc.reference));
+  jni.JniString getText(pdmodel_.PDDocument doc) {
+    final result__ = jni.JniString.fromRef(_getText(reference, doc.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _resetEngine =
-      jlookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
               "org_apache_pdfbox_text_PDFTextStripper_resetEngine")
           .asFunction<void Function(ffi.Pointer<ffi.Void>)>();
 
   /// from: private void resetEngine()
-  void resetEngine() => _resetEngine(reference);
+  void resetEngine() {
+    final result__ = _resetEngine(reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _writeText = jlookup<
+  static final _writeText = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(ffi.Pointer<ffi.Void>,
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -970,10 +979,14 @@
   ///@param doc The document to get the data from.
   ///@param outputStream The location to put the text.
   ///@throws IOException If the doc is in an invalid state.
-  void writeText(pdmodel_.PDDocument doc, jni.JlObject outputStream) =>
-      _writeText(reference, doc.reference, outputStream.reference);
+  void writeText(pdmodel_.PDDocument doc, jni.JniObject outputStream) {
+    final result__ =
+        _writeText(reference, doc.reference, outputStream.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _processPages = jlookup<
+  static final _processPages = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -986,10 +999,13 @@
   /// This will process all of the pages and the text that is in them.
   ///@param pages The pages object in the document.
   ///@throws IOException If there is an error parsing the text.
-  void processPages(jni.JlObject pages) =>
-      _processPages(reference, pages.reference);
+  void processPages(jni.JniObject pages) {
+    final result__ = _processPages(reference, pages.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _startDocument = jlookup<
+  static final _startDocument = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1002,10 +1018,13 @@
   /// This method is available for subclasses of this class. It will be called before processing of the document start.
   ///@param document The PDF document that is being processed.
   ///@throws IOException If an IO error occurs.
-  void startDocument(pdmodel_.PDDocument document) =>
-      _startDocument(reference, document.reference);
+  void startDocument(pdmodel_.PDDocument document) {
+    final result__ = _startDocument(reference, document.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _endDocument = jlookup<
+  static final _endDocument = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1019,10 +1038,13 @@
   /// finishes.
   ///@param document The PDF document that is being processed.
   ///@throws IOException If an IO error occurs.
-  void endDocument(pdmodel_.PDDocument document) =>
-      _endDocument(reference, document.reference);
+  void endDocument(pdmodel_.PDDocument document) {
+    final result__ = _endDocument(reference, document.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _processPage = jlookup<
+  static final _processPage = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1035,10 +1057,13 @@
   /// This will process the contents of a page.
   ///@param page The page to process.
   ///@throws IOException If there is an error processing the page.
-  void processPage(jni.JlObject page) =>
-      _processPage(reference, page.reference);
+  void processPage(jni.JniObject page) {
+    final result__ = _processPage(reference, page.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _fillBeadRectangles = jlookup<
+  static final _fillBeadRectangles = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1047,11 +1072,14 @@
           void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
 
   /// from: private void fillBeadRectangles(org.apache.pdfbox.pdmodel.PDPage page)
-  void fillBeadRectangles(jni.JlObject page) =>
-      _fillBeadRectangles(reference, page.reference);
+  void fillBeadRectangles(jni.JniObject page) {
+    final result__ = _fillBeadRectangles(reference, page.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _startArticle =
-      jlookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
               "org_apache_pdfbox_text_PDFTextStripper_startArticle")
           .asFunction<void Function(ffi.Pointer<ffi.Void>)>();
 
@@ -1061,9 +1089,13 @@
   /// assumes that the primary direction of text is left to right. Default implementation is to do nothing. Subclasses
   /// may provide additional information.
   ///@throws IOException If there is any error writing to the stream.
-  void startArticle() => _startArticle(reference);
+  void startArticle() {
+    final result__ = _startArticle(reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _startArticle1 = jlookup<
+  static final _startArticle1 = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Uint8)>>(
           "org_apache_pdfbox_text_PDFTextStripper_startArticle1")
@@ -1075,10 +1107,14 @@
   /// Default implementation is to do nothing. Subclasses may provide additional information.
   ///@param isLTR true if primary direction of text is left to right.
   ///@throws IOException If there is any error writing to the stream.
-  void startArticle1(bool isLTR) => _startArticle1(reference, isLTR ? 1 : 0);
+  void startArticle1(bool isLTR) {
+    final result__ = _startArticle1(reference, isLTR ? 1 : 0);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _endArticle =
-      jlookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
               "org_apache_pdfbox_text_PDFTextStripper_endArticle")
           .asFunction<void Function(ffi.Pointer<ffi.Void>)>();
 
@@ -1086,9 +1122,13 @@
   ///
   /// End an article. Default implementation is to do nothing. Subclasses may provide additional information.
   ///@throws IOException If there is any error writing to the stream.
-  void endArticle() => _endArticle(reference);
+  void endArticle() {
+    final result__ = _endArticle(reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _startPage1 = jlookup<
+  static final _startPage1 = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1101,9 +1141,13 @@
   /// Start a new page. Default implementation is to do nothing. Subclasses may provide additional information.
   ///@param page The page we are about to process.
   ///@throws IOException If there is any error writing to the stream.
-  void startPage1(jni.JlObject page) => _startPage1(reference, page.reference);
+  void startPage1(jni.JniObject page) {
+    final result__ = _startPage1(reference, page.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _endPage1 = jlookup<
+  static final _endPage1 = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1116,10 +1160,14 @@
   /// End a page. Default implementation is to do nothing. Subclasses may provide additional information.
   ///@param page The page we are about to process.
   ///@throws IOException If there is any error writing to the stream.
-  void endPage1(jni.JlObject page) => _endPage1(reference, page.reference);
+  void endPage1(jni.JniObject page) {
+    final result__ = _endPage1(reference, page.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _writePage =
-      jlookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
               "org_apache_pdfbox_text_PDFTextStripper_writePage")
           .asFunction<void Function(ffi.Pointer<ffi.Void>)>();
 
@@ -1129,9 +1177,13 @@
   /// text, where newlines and word spacings should be placed. The text will be sorted only if that feature was
   /// enabled.
   ///@throws IOException If there is an error writing the text.
-  void writePage() => _writePage(reference);
+  void writePage() {
+    final result__ = _writePage(reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _overlap = jlookup<
+  static final _overlap = jniLookup<
           ffi.NativeFunction<
               ffi.Uint8 Function(
                   ffi.Pointer<ffi.Void>,
@@ -1144,11 +1196,14 @@
               ffi.Pointer<ffi.Void>, double, double, double, double)>();
 
   /// from: private boolean overlap(float y1, float height1, float y2, float height2)
-  bool overlap(double y1, double height1, double y2, double height2) =>
-      _overlap(reference, y1, height1, y2, height2) != 0;
+  bool overlap(double y1, double height1, double y2, double height2) {
+    final result__ = _overlap(reference, y1, height1, y2, height2) != 0;
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _writeLineSeparator =
-      jlookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
               "org_apache_pdfbox_text_PDFTextStripper_writeLineSeparator")
           .asFunction<void Function(ffi.Pointer<ffi.Void>)>();
 
@@ -1156,10 +1211,14 @@
   ///
   /// Write the line separator value to the output stream.
   ///@throws IOException If there is a problem writing out the line separator to the document.
-  void writeLineSeparator() => _writeLineSeparator(reference);
+  void writeLineSeparator() {
+    final result__ = _writeLineSeparator(reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _writeWordSeparator =
-      jlookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
               "org_apache_pdfbox_text_PDFTextStripper_writeWordSeparator")
           .asFunction<void Function(ffi.Pointer<ffi.Void>)>();
 
@@ -1167,9 +1226,13 @@
   ///
   /// Write the word separator value to the output stream.
   ///@throws IOException If there is a problem writing out the word separator to the document.
-  void writeWordSeparator() => _writeWordSeparator(reference);
+  void writeWordSeparator() {
+    final result__ = _writeWordSeparator(reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _writeCharacters = jlookup<
+  static final _writeCharacters = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1182,10 +1245,13 @@
   /// Write the string in TextPosition to the output stream.
   ///@param text The text to write to the stream.
   ///@throws IOException If there is an error when writing the text.
-  void writeCharacters(jni.JlObject text) =>
-      _writeCharacters(reference, text.reference);
+  void writeCharacters(jni.JniObject text) {
+    final result__ = _writeCharacters(reference, text.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _writeString = jlookup<
+  static final _writeString = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(ffi.Pointer<ffi.Void>,
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1201,10 +1267,14 @@
   ///@param text The text to write to the stream.
   ///@param textPositions The TextPositions belonging to the text.
   ///@throws IOException If there is an error when writing the text.
-  void writeString(jni.JlString text, jni.JlObject textPositions) =>
-      _writeString(reference, text.reference, textPositions.reference);
+  void writeString(jni.JniString text, jni.JniObject textPositions) {
+    final result__ =
+        _writeString(reference, text.reference, textPositions.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _writeString1 = jlookup<
+  static final _writeString1 = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1217,10 +1287,13 @@
   /// Write a Java string to the output stream.
   ///@param text The text to write to the stream.
   ///@throws IOException If there is an error when writing the text.
-  void writeString1(jni.JlString text) =>
-      _writeString1(reference, text.reference);
+  void writeString1(jni.JniString text) {
+    final result__ = _writeString1(reference, text.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _within = jlookup<
+  static final _within = jniLookup<
           ffi.NativeFunction<
               ffi.Uint8 Function(ffi.Pointer<ffi.Void>, ffi.Float, ffi.Float,
                   ffi.Float)>>("org_apache_pdfbox_text_PDFTextStripper_within")
@@ -1233,10 +1306,13 @@
   ///@param first The first number to compare to.
   ///@param second The second number to compare to.
   ///@param variance The allowed variance.
-  bool within(double first, double second, double variance) =>
-      _within(reference, first, second, variance) != 0;
+  bool within(double first, double second, double variance) {
+    final result__ = _within(reference, first, second, variance) != 0;
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _processTextPosition = jlookup<
+  static final _processTextPosition = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1249,11 +1325,14 @@
   /// This will process a TextPosition object and add the text to the list of characters on a page. It takes care of
   /// overlapping text.
   ///@param text The text to process.
-  void processTextPosition(jni.JlObject text) =>
-      _processTextPosition(reference, text.reference);
+  void processTextPosition(jni.JniObject text) {
+    final result__ = _processTextPosition(reference, text.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _getStartPage =
-      jlookup<ffi.NativeFunction<ffi.Int32 Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Int32 Function(ffi.Pointer<ffi.Void>)>>(
               "org_apache_pdfbox_text_PDFTextStripper_getStartPage")
           .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
@@ -1263,9 +1342,13 @@
   /// document, if the start page is 1 then all pages will be extracted. If the start page is 4 then pages 4 and 5 will
   /// be extracted. The default value is 1.
   ///@return Value of property startPage.
-  int getStartPage() => _getStartPage(reference);
+  int getStartPage() {
+    final result__ = _getStartPage(reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _setStartPage = jlookup<
+  static final _setStartPage = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Int32)>>(
           "org_apache_pdfbox_text_PDFTextStripper_setStartPage")
@@ -1275,11 +1358,14 @@
   ///
   /// This will set the first page to be extracted by this class.
   ///@param startPageValue New value of 1-based startPage property.
-  void setStartPage(int startPageValue) =>
-      _setStartPage(reference, startPageValue);
+  void setStartPage(int startPageValue) {
+    final result__ = _setStartPage(reference, startPageValue);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _getEndPage =
-      jlookup<ffi.NativeFunction<ffi.Int32 Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Int32 Function(ffi.Pointer<ffi.Void>)>>(
               "org_apache_pdfbox_text_PDFTextStripper_getEndPage")
           .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
@@ -1289,9 +1375,13 @@
   /// value of 5 would extract the entire document, an end page of 2 would extract pages 1 and 2. This defaults to
   /// Integer.MAX_VALUE such that all pages of the pdf will be extracted.
   ///@return Value of property endPage.
-  int getEndPage() => _getEndPage(reference);
+  int getEndPage() {
+    final result__ = _getEndPage(reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _setEndPage = jlookup<
+  static final _setEndPage = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Int32)>>(
           "org_apache_pdfbox_text_PDFTextStripper_setEndPage")
@@ -1301,9 +1391,13 @@
   ///
   /// This will set the last page to be extracted by this class.
   ///@param endPageValue New value of 1-based endPage property.
-  void setEndPage(int endPageValue) => _setEndPage(reference, endPageValue);
+  void setEndPage(int endPageValue) {
+    final result__ = _setEndPage(reference, endPageValue);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _setLineSeparator = jlookup<
+  static final _setLineSeparator = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1316,10 +1410,13 @@
   /// Set the desired line separator for output text. The line.separator system property is used if the line separator
   /// preference is not set explicitly using this method.
   ///@param separator The desired line separator string.
-  void setLineSeparator(jni.JlString separator) =>
-      _setLineSeparator(reference, separator.reference);
+  void setLineSeparator(jni.JniString separator) {
+    final result__ = _setLineSeparator(reference, separator.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getLineSeparator = jlookup<
+  static final _getLineSeparator = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "org_apache_pdfbox_text_PDFTextStripper_getLineSeparator")
@@ -1330,10 +1427,13 @@
   ///
   /// This will get the line separator.
   ///@return The desired line separator string.
-  jni.JlString getLineSeparator() =>
-      jni.JlString.fromRef(_getLineSeparator(reference));
+  jni.JniString getLineSeparator() {
+    final result__ = jni.JniString.fromRef(_getLineSeparator(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getWordSeparator = jlookup<
+  static final _getWordSeparator = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "org_apache_pdfbox_text_PDFTextStripper_getWordSeparator")
@@ -1344,10 +1444,13 @@
   ///
   /// This will get the word separator.
   ///@return The desired word separator string.
-  jni.JlString getWordSeparator() =>
-      jni.JlString.fromRef(_getWordSeparator(reference));
+  jni.JniString getWordSeparator() {
+    final result__ = jni.JniString.fromRef(_getWordSeparator(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _setWordSeparator = jlookup<
+  static final _setWordSeparator = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1362,10 +1465,13 @@
   /// accurate count of characters that are found in a PDF document then you might want to set the word separator to
   /// the empty string.
   ///@param separator The desired page separator string.
-  void setWordSeparator(jni.JlString separator) =>
-      _setWordSeparator(reference, separator.reference);
+  void setWordSeparator(jni.JniString separator) {
+    final result__ = _setWordSeparator(reference, separator.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getSuppressDuplicateOverlappingText = jlookup<
+  static final _getSuppressDuplicateOverlappingText = jniLookup<
               ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
           "org_apache_pdfbox_text_PDFTextStripper_getSuppressDuplicateOverlappingText")
       .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
@@ -1373,11 +1479,14 @@
   /// from: public boolean getSuppressDuplicateOverlappingText()
   ///
   /// @return Returns the suppressDuplicateOverlappingText.
-  bool getSuppressDuplicateOverlappingText() =>
-      _getSuppressDuplicateOverlappingText(reference) != 0;
+  bool getSuppressDuplicateOverlappingText() {
+    final result__ = _getSuppressDuplicateOverlappingText(reference) != 0;
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _getCurrentPageNo =
-      jlookup<ffi.NativeFunction<ffi.Int32 Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Int32 Function(ffi.Pointer<ffi.Void>)>>(
               "org_apache_pdfbox_text_PDFTextStripper_getCurrentPageNo")
           .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
@@ -1385,9 +1494,13 @@
   ///
   /// Get the current page number that is being processed.
   ///@return A 1 based number representing the current page.
-  int getCurrentPageNo() => _getCurrentPageNo(reference);
+  int getCurrentPageNo() {
+    final result__ = _getCurrentPageNo(reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getOutput = jlookup<
+  static final _getOutput = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "org_apache_pdfbox_text_PDFTextStripper_getOutput")
@@ -1398,9 +1511,13 @@
   ///
   /// The output stream that is being written to.
   ///@return The stream that output is being written to.
-  jni.JlObject getOutput() => jni.JlObject.fromRef(_getOutput(reference));
+  jni.JniObject getOutput() {
+    final result__ = jni.JniObject.fromRef(_getOutput(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getCharactersByArticle = jlookup<
+  static final _getCharactersByArticle = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "org_apache_pdfbox_text_PDFTextStripper_getCharactersByArticle")
@@ -1412,10 +1529,13 @@
   /// Character strings are grouped by articles. It is quite common that there will only be a single article. This
   /// returns a List that contains List objects, the inner lists will contain TextPosition objects.
   ///@return A double List of TextPositions for all text strings on the page.
-  jni.JlObject getCharactersByArticle() =>
-      jni.JlObject.fromRef(_getCharactersByArticle(reference));
+  jni.JniObject getCharactersByArticle() {
+    final result__ = jni.JniObject.fromRef(_getCharactersByArticle(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _setSuppressDuplicateOverlappingText = jlookup<
+  static final _setSuppressDuplicateOverlappingText = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Uint8)>>(
           "org_apache_pdfbox_text_PDFTextStripper_setSuppressDuplicateOverlappingText")
@@ -1428,12 +1548,15 @@
   /// means that certain sections will be duplicated, but better performance will be noticed.
   ///@param suppressDuplicateOverlappingTextValue The suppressDuplicateOverlappingText to set.
   void setSuppressDuplicateOverlappingText(
-          bool suppressDuplicateOverlappingTextValue) =>
-      _setSuppressDuplicateOverlappingText(
-          reference, suppressDuplicateOverlappingTextValue ? 1 : 0);
+      bool suppressDuplicateOverlappingTextValue) {
+    final result__ = _setSuppressDuplicateOverlappingText(
+        reference, suppressDuplicateOverlappingTextValue ? 1 : 0);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _getSeparateByBeads =
-      jlookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
               "org_apache_pdfbox_text_PDFTextStripper_getSeparateByBeads")
           .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
@@ -1441,9 +1564,13 @@
   ///
   /// This will tell if the text stripper should separate by beads.
   ///@return If the text will be grouped by beads.
-  bool getSeparateByBeads() => _getSeparateByBeads(reference) != 0;
+  bool getSeparateByBeads() {
+    final result__ = _getSeparateByBeads(reference) != 0;
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _setShouldSeparateByBeads = jlookup<
+  static final _setShouldSeparateByBeads = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Uint8)>>(
           "org_apache_pdfbox_text_PDFTextStripper_setShouldSeparateByBeads")
@@ -1453,10 +1580,14 @@
   ///
   /// Set if the text stripper should group the text output by a list of beads. The default value is true!
   ///@param aShouldSeparateByBeads The new grouping of beads.
-  void setShouldSeparateByBeads(bool aShouldSeparateByBeads) =>
-      _setShouldSeparateByBeads(reference, aShouldSeparateByBeads ? 1 : 0);
+  void setShouldSeparateByBeads(bool aShouldSeparateByBeads) {
+    final result__ =
+        _setShouldSeparateByBeads(reference, aShouldSeparateByBeads ? 1 : 0);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getEndBookmark = jlookup<
+  static final _getEndBookmark = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "org_apache_pdfbox_text_PDFTextStripper_getEndBookmark")
@@ -1467,10 +1598,13 @@
   ///
   /// Get the bookmark where text extraction should end, inclusive. Default is null.
   ///@return The ending bookmark.
-  jni.JlObject getEndBookmark() =>
-      jni.JlObject.fromRef(_getEndBookmark(reference));
+  jni.JniObject getEndBookmark() {
+    final result__ = jni.JniObject.fromRef(_getEndBookmark(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _setEndBookmark = jlookup<
+  static final _setEndBookmark = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1482,10 +1616,13 @@
   ///
   /// Set the bookmark where the text extraction should stop.
   ///@param aEndBookmark The ending bookmark.
-  void setEndBookmark(jni.JlObject aEndBookmark) =>
-      _setEndBookmark(reference, aEndBookmark.reference);
+  void setEndBookmark(jni.JniObject aEndBookmark) {
+    final result__ = _setEndBookmark(reference, aEndBookmark.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getStartBookmark = jlookup<
+  static final _getStartBookmark = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "org_apache_pdfbox_text_PDFTextStripper_getStartBookmark")
@@ -1496,10 +1633,13 @@
   ///
   /// Get the bookmark where text extraction should start, inclusive. Default is null.
   ///@return The starting bookmark.
-  jni.JlObject getStartBookmark() =>
-      jni.JlObject.fromRef(_getStartBookmark(reference));
+  jni.JniObject getStartBookmark() {
+    final result__ = jni.JniObject.fromRef(_getStartBookmark(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _setStartBookmark = jlookup<
+  static final _setStartBookmark = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1511,11 +1651,14 @@
   ///
   /// Set the bookmark where text extraction should start, inclusive.
   ///@param aStartBookmark The starting bookmark.
-  void setStartBookmark(jni.JlObject aStartBookmark) =>
-      _setStartBookmark(reference, aStartBookmark.reference);
+  void setStartBookmark(jni.JniObject aStartBookmark) {
+    final result__ = _setStartBookmark(reference, aStartBookmark.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _getAddMoreFormatting =
-      jlookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
               "org_apache_pdfbox_text_PDFTextStripper_getAddMoreFormatting")
           .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
@@ -1523,9 +1666,13 @@
   ///
   /// This will tell if the text stripper should add some more text formatting.
   ///@return true if some more text formatting will be added
-  bool getAddMoreFormatting() => _getAddMoreFormatting(reference) != 0;
+  bool getAddMoreFormatting() {
+    final result__ = _getAddMoreFormatting(reference) != 0;
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _setAddMoreFormatting = jlookup<
+  static final _setAddMoreFormatting = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Uint8)>>(
           "org_apache_pdfbox_text_PDFTextStripper_setAddMoreFormatting")
@@ -1535,11 +1682,15 @@
   ///
   /// There will some additional text formatting be added if addMoreFormatting is set to true. Default is false.
   ///@param newAddMoreFormatting Tell PDFBox to add some more text formatting
-  void setAddMoreFormatting(bool newAddMoreFormatting) =>
-      _setAddMoreFormatting(reference, newAddMoreFormatting ? 1 : 0);
+  void setAddMoreFormatting(bool newAddMoreFormatting) {
+    final result__ =
+        _setAddMoreFormatting(reference, newAddMoreFormatting ? 1 : 0);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _getSortByPosition =
-      jlookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
               "org_apache_pdfbox_text_PDFTextStripper_getSortByPosition")
           .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
@@ -1547,9 +1698,13 @@
   ///
   /// This will tell if the text stripper should sort the text tokens before writing to the stream.
   ///@return true If the text tokens will be sorted before being written.
-  bool getSortByPosition() => _getSortByPosition(reference) != 0;
+  bool getSortByPosition() {
+    final result__ = _getSortByPosition(reference) != 0;
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _setSortByPosition = jlookup<
+  static final _setSortByPosition = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Uint8)>>(
           "org_apache_pdfbox_text_PDFTextStripper_setSortByPosition")
@@ -1565,11 +1720,14 @@
   /// A PDF writer could choose to write each character in a different order. By default PDFBox does __not__ sort
   /// the text tokens before processing them due to performance reasons.
   ///@param newSortByPosition Tell PDFBox to sort the text positions.
-  void setSortByPosition(bool newSortByPosition) =>
-      _setSortByPosition(reference, newSortByPosition ? 1 : 0);
+  void setSortByPosition(bool newSortByPosition) {
+    final result__ = _setSortByPosition(reference, newSortByPosition ? 1 : 0);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _getSpacingTolerance =
-      jlookup<ffi.NativeFunction<ffi.Float Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Float Function(ffi.Pointer<ffi.Void>)>>(
               "org_apache_pdfbox_text_PDFTextStripper_getSpacingTolerance")
           .asFunction<double Function(ffi.Pointer<ffi.Void>)>();
 
@@ -1578,9 +1736,13 @@
   /// Get the current space width-based tolerance value that is being used to estimate where spaces in text should be
   /// added. Note that the default value for this has been determined from trial and error.
   ///@return The current tolerance / scaling factor
-  double getSpacingTolerance() => _getSpacingTolerance(reference);
+  double getSpacingTolerance() {
+    final result__ = _getSpacingTolerance(reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _setSpacingTolerance = jlookup<
+  static final _setSpacingTolerance = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Float)>>(
           "org_apache_pdfbox_text_PDFTextStripper_setSpacingTolerance")
@@ -1592,11 +1754,14 @@
   /// that the default value for this has been determined from trial and error. Setting this value larger will reduce
   /// the number of spaces added.
   ///@param spacingToleranceValue tolerance / scaling factor to use
-  void setSpacingTolerance(double spacingToleranceValue) =>
-      _setSpacingTolerance(reference, spacingToleranceValue);
+  void setSpacingTolerance(double spacingToleranceValue) {
+    final result__ = _setSpacingTolerance(reference, spacingToleranceValue);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _getAverageCharTolerance =
-      jlookup<ffi.NativeFunction<ffi.Float Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Float Function(ffi.Pointer<ffi.Void>)>>(
               "org_apache_pdfbox_text_PDFTextStripper_getAverageCharTolerance")
           .asFunction<double Function(ffi.Pointer<ffi.Void>)>();
 
@@ -1605,9 +1770,13 @@
   /// Get the current character width-based tolerance value that is being used to estimate where spaces in text should
   /// be added. Note that the default value for this has been determined from trial and error.
   ///@return The current tolerance / scaling factor
-  double getAverageCharTolerance() => _getAverageCharTolerance(reference);
+  double getAverageCharTolerance() {
+    final result__ = _getAverageCharTolerance(reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _setAverageCharTolerance = jlookup<
+  static final _setAverageCharTolerance = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Float)>>(
           "org_apache_pdfbox_text_PDFTextStripper_setAverageCharTolerance")
@@ -1619,11 +1788,15 @@
   /// that the default value for this has been determined from trial and error. Setting this value larger will reduce
   /// the number of spaces added.
   ///@param averageCharToleranceValue average tolerance / scaling factor to use
-  void setAverageCharTolerance(double averageCharToleranceValue) =>
-      _setAverageCharTolerance(reference, averageCharToleranceValue);
+  void setAverageCharTolerance(double averageCharToleranceValue) {
+    final result__ =
+        _setAverageCharTolerance(reference, averageCharToleranceValue);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _getIndentThreshold =
-      jlookup<ffi.NativeFunction<ffi.Float Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Float Function(ffi.Pointer<ffi.Void>)>>(
               "org_apache_pdfbox_text_PDFTextStripper_getIndentThreshold")
           .asFunction<double Function(ffi.Pointer<ffi.Void>)>();
 
@@ -1632,9 +1805,13 @@
   /// returns the multiple of whitespace character widths for the current text which the current line start can be
   /// indented from the previous line start beyond which the current line start is considered to be a paragraph start.
   ///@return the number of whitespace character widths to use when detecting paragraph indents.
-  double getIndentThreshold() => _getIndentThreshold(reference);
+  double getIndentThreshold() {
+    final result__ = _getIndentThreshold(reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _setIndentThreshold = jlookup<
+  static final _setIndentThreshold = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Float)>>(
           "org_apache_pdfbox_text_PDFTextStripper_setIndentThreshold")
@@ -1646,11 +1823,14 @@
   /// indented from the previous line start beyond which the current line start is considered to be a paragraph start.
   /// The default value is 2.0.
   ///@param indentThresholdValue the number of whitespace character widths to use when detecting paragraph indents.
-  void setIndentThreshold(double indentThresholdValue) =>
-      _setIndentThreshold(reference, indentThresholdValue);
+  void setIndentThreshold(double indentThresholdValue) {
+    final result__ = _setIndentThreshold(reference, indentThresholdValue);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _getDropThreshold =
-      jlookup<ffi.NativeFunction<ffi.Float Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Float Function(ffi.Pointer<ffi.Void>)>>(
               "org_apache_pdfbox_text_PDFTextStripper_getDropThreshold")
           .asFunction<double Function(ffi.Pointer<ffi.Void>)>();
 
@@ -1659,9 +1839,13 @@
   /// the minimum whitespace, as a multiple of the max height of the current characters beyond which the current line
   /// start is considered to be a paragraph start.
   ///@return the character height multiple for max allowed whitespace between lines in the same paragraph.
-  double getDropThreshold() => _getDropThreshold(reference);
+  double getDropThreshold() {
+    final result__ = _getDropThreshold(reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _setDropThreshold = jlookup<
+  static final _setDropThreshold = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Float)>>(
           "org_apache_pdfbox_text_PDFTextStripper_setDropThreshold")
@@ -1673,10 +1857,13 @@
   /// line start is considered to be a paragraph start. The default value is 2.5.
   ///@param dropThresholdValue the character height multiple for max allowed whitespace between lines in the same
   /// paragraph.
-  void setDropThreshold(double dropThresholdValue) =>
-      _setDropThreshold(reference, dropThresholdValue);
+  void setDropThreshold(double dropThresholdValue) {
+    final result__ = _setDropThreshold(reference, dropThresholdValue);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getParagraphStart = jlookup<
+  static final _getParagraphStart = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "org_apache_pdfbox_text_PDFTextStripper_getParagraphStart")
@@ -1687,10 +1874,13 @@
   ///
   /// Returns the string which will be used at the beginning of a paragraph.
   ///@return the paragraph start string
-  jni.JlString getParagraphStart() =>
-      jni.JlString.fromRef(_getParagraphStart(reference));
+  jni.JniString getParagraphStart() {
+    final result__ = jni.JniString.fromRef(_getParagraphStart(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _setParagraphStart = jlookup<
+  static final _setParagraphStart = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1702,10 +1892,13 @@
   ///
   /// Sets the string which will be used at the beginning of a paragraph.
   ///@param s the paragraph start string
-  void setParagraphStart(jni.JlString s) =>
-      _setParagraphStart(reference, s.reference);
+  void setParagraphStart(jni.JniString s) {
+    final result__ = _setParagraphStart(reference, s.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getParagraphEnd = jlookup<
+  static final _getParagraphEnd = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "org_apache_pdfbox_text_PDFTextStripper_getParagraphEnd")
@@ -1716,10 +1909,13 @@
   ///
   /// Returns the string which will be used at the end of a paragraph.
   ///@return the paragraph end string
-  jni.JlString getParagraphEnd() =>
-      jni.JlString.fromRef(_getParagraphEnd(reference));
+  jni.JniString getParagraphEnd() {
+    final result__ = jni.JniString.fromRef(_getParagraphEnd(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _setParagraphEnd = jlookup<
+  static final _setParagraphEnd = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1731,10 +1927,13 @@
   ///
   /// Sets the string which will be used at the end of a paragraph.
   ///@param s the paragraph end string
-  void setParagraphEnd(jni.JlString s) =>
-      _setParagraphEnd(reference, s.reference);
+  void setParagraphEnd(jni.JniString s) {
+    final result__ = _setParagraphEnd(reference, s.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getPageStart = jlookup<
+  static final _getPageStart = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "org_apache_pdfbox_text_PDFTextStripper_getPageStart")
@@ -1745,9 +1944,13 @@
   ///
   /// Returns the string which will be used at the beginning of a page.
   ///@return the page start string
-  jni.JlString getPageStart() => jni.JlString.fromRef(_getPageStart(reference));
+  jni.JniString getPageStart() {
+    final result__ = jni.JniString.fromRef(_getPageStart(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _setPageStart = jlookup<
+  static final _setPageStart = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1759,10 +1962,13 @@
   ///
   /// Sets the string which will be used at the beginning of a page.
   ///@param pageStartValue the page start string
-  void setPageStart(jni.JlString pageStartValue) =>
-      _setPageStart(reference, pageStartValue.reference);
+  void setPageStart(jni.JniString pageStartValue) {
+    final result__ = _setPageStart(reference, pageStartValue.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getPageEnd = jlookup<
+  static final _getPageEnd = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "org_apache_pdfbox_text_PDFTextStripper_getPageEnd")
@@ -1773,9 +1979,13 @@
   ///
   /// Returns the string which will be used at the end of a page.
   ///@return the page end string
-  jni.JlString getPageEnd() => jni.JlString.fromRef(_getPageEnd(reference));
+  jni.JniString getPageEnd() {
+    final result__ = jni.JniString.fromRef(_getPageEnd(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _setPageEnd = jlookup<
+  static final _setPageEnd = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1787,10 +1997,13 @@
   ///
   /// Sets the string which will be used at the end of a page.
   ///@param pageEndValue the page end string
-  void setPageEnd(jni.JlString pageEndValue) =>
-      _setPageEnd(reference, pageEndValue.reference);
+  void setPageEnd(jni.JniString pageEndValue) {
+    final result__ = _setPageEnd(reference, pageEndValue.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getArticleStart = jlookup<
+  static final _getArticleStart = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "org_apache_pdfbox_text_PDFTextStripper_getArticleStart")
@@ -1801,10 +2014,13 @@
   ///
   /// Returns the string which will be used at the beginning of an article.
   ///@return the article start string
-  jni.JlString getArticleStart() =>
-      jni.JlString.fromRef(_getArticleStart(reference));
+  jni.JniString getArticleStart() {
+    final result__ = jni.JniString.fromRef(_getArticleStart(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _setArticleStart = jlookup<
+  static final _setArticleStart = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1816,10 +2032,13 @@
   ///
   /// Sets the string which will be used at the beginning of an article.
   ///@param articleStartValue the article start string
-  void setArticleStart(jni.JlString articleStartValue) =>
-      _setArticleStart(reference, articleStartValue.reference);
+  void setArticleStart(jni.JniString articleStartValue) {
+    final result__ = _setArticleStart(reference, articleStartValue.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getArticleEnd = jlookup<
+  static final _getArticleEnd = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "org_apache_pdfbox_text_PDFTextStripper_getArticleEnd")
@@ -1830,10 +2049,13 @@
   ///
   /// Returns the string which will be used at the end of an article.
   ///@return the article end string
-  jni.JlString getArticleEnd() =>
-      jni.JlString.fromRef(_getArticleEnd(reference));
+  jni.JniString getArticleEnd() {
+    final result__ = jni.JniString.fromRef(_getArticleEnd(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _setArticleEnd = jlookup<
+  static final _setArticleEnd = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1845,10 +2067,13 @@
   ///
   /// Sets the string which will be used at the end of an article.
   ///@param articleEndValue the article end string
-  void setArticleEnd(jni.JlString articleEndValue) =>
-      _setArticleEnd(reference, articleEndValue.reference);
+  void setArticleEnd(jni.JniString articleEndValue) {
+    final result__ = _setArticleEnd(reference, articleEndValue.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _handleLineSeparation = jlookup<
+  static final _handleLineSeparation = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>,
@@ -1875,19 +2100,22 @@
   ///@param maxHeightForLine max height for positions since lastLineStartPosition
   ///@return start position of the last line
   ///@throws IOException if something went wrong
-  jni.JlObject handleLineSeparation(
-          jni.JlObject current,
-          jni.JlObject lastPosition,
-          jni.JlObject lastLineStartPosition,
-          double maxHeightForLine) =>
-      jni.JlObject.fromRef(_handleLineSeparation(
-          reference,
-          current.reference,
-          lastPosition.reference,
-          lastLineStartPosition.reference,
-          maxHeightForLine));
+  jni.JniObject handleLineSeparation(
+      jni.JniObject current,
+      jni.JniObject lastPosition,
+      jni.JniObject lastLineStartPosition,
+      double maxHeightForLine) {
+    final result__ = jni.JniObject.fromRef(_handleLineSeparation(
+        reference,
+        current.reference,
+        lastPosition.reference,
+        lastLineStartPosition.reference,
+        maxHeightForLine));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _isParagraphSeparation = jlookup<
+  static final _isParagraphSeparation = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>,
@@ -1924,16 +2152,19 @@
   ///@param lastPosition the previous text position (should not be null).
   ///@param lastLineStartPosition the last text position that followed a line separator, or null.
   ///@param maxHeightForLine max height for text positions since lasLineStartPosition.
-  void isParagraphSeparation(jni.JlObject position, jni.JlObject lastPosition,
-          jni.JlObject lastLineStartPosition, double maxHeightForLine) =>
-      _isParagraphSeparation(
-          reference,
-          position.reference,
-          lastPosition.reference,
-          lastLineStartPosition.reference,
-          maxHeightForLine);
+  void isParagraphSeparation(jni.JniObject position, jni.JniObject lastPosition,
+      jni.JniObject lastLineStartPosition, double maxHeightForLine) {
+    final result__ = _isParagraphSeparation(
+        reference,
+        position.reference,
+        lastPosition.reference,
+        lastLineStartPosition.reference,
+        maxHeightForLine);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _multiplyFloat = jlookup<
+  static final _multiplyFloat = jniLookup<
               ffi.NativeFunction<
                   ffi.Float Function(
                       ffi.Pointer<ffi.Void>, ffi.Float, ffi.Float)>>(
@@ -1941,11 +2172,14 @@
       .asFunction<double Function(ffi.Pointer<ffi.Void>, double, double)>();
 
   /// from: private float multiplyFloat(float value1, float value2)
-  double multiplyFloat(double value1, double value2) =>
-      _multiplyFloat(reference, value1, value2);
+  double multiplyFloat(double value1, double value2) {
+    final result__ = _multiplyFloat(reference, value1, value2);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _writeParagraphSeparator =
-      jlookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
               "org_apache_pdfbox_text_PDFTextStripper_writeParagraphSeparator")
           .asFunction<void Function(ffi.Pointer<ffi.Void>)>();
 
@@ -1953,10 +2187,14 @@
   ///
   /// writes the paragraph separator string to the output.
   ///@throws IOException if something went wrong
-  void writeParagraphSeparator() => _writeParagraphSeparator(reference);
+  void writeParagraphSeparator() {
+    final result__ = _writeParagraphSeparator(reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _writeParagraphStart =
-      jlookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
               "org_apache_pdfbox_text_PDFTextStripper_writeParagraphStart")
           .asFunction<void Function(ffi.Pointer<ffi.Void>)>();
 
@@ -1964,10 +2202,14 @@
   ///
   /// Write something (if defined) at the start of a paragraph.
   ///@throws IOException if something went wrong
-  void writeParagraphStart() => _writeParagraphStart(reference);
+  void writeParagraphStart() {
+    final result__ = _writeParagraphStart(reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _writeParagraphEnd =
-      jlookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
               "org_apache_pdfbox_text_PDFTextStripper_writeParagraphEnd")
           .asFunction<void Function(ffi.Pointer<ffi.Void>)>();
 
@@ -1975,10 +2217,14 @@
   ///
   /// Write something (if defined) at the end of a paragraph.
   ///@throws IOException if something went wrong
-  void writeParagraphEnd() => _writeParagraphEnd(reference);
+  void writeParagraphEnd() {
+    final result__ = _writeParagraphEnd(reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _writePageStart =
-      jlookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
               "org_apache_pdfbox_text_PDFTextStripper_writePageStart")
           .asFunction<void Function(ffi.Pointer<ffi.Void>)>();
 
@@ -1986,10 +2232,14 @@
   ///
   /// Write something (if defined) at the start of a page.
   ///@throws IOException if something went wrong
-  void writePageStart() => _writePageStart(reference);
+  void writePageStart() {
+    final result__ = _writePageStart(reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _writePageEnd =
-      jlookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
               "org_apache_pdfbox_text_PDFTextStripper_writePageEnd")
           .asFunction<void Function(ffi.Pointer<ffi.Void>)>();
 
@@ -1997,9 +2247,13 @@
   ///
   /// Write something (if defined) at the end of a page.
   ///@throws IOException if something went wrong
-  void writePageEnd() => _writePageEnd(reference);
+  void writePageEnd() {
+    final result__ = _writePageEnd(reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _matchListItemPattern = jlookup<
+  static final _matchListItemPattern = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -2017,10 +2271,14 @@
   /// using \#setListItemPatterns(List).
   ///@param pw position
   ///@return the matching pattern
-  jni.JlObject matchListItemPattern(jni.JlObject pw) =>
-      jni.JlObject.fromRef(_matchListItemPattern(reference, pw.reference));
+  jni.JniObject matchListItemPattern(jni.JniObject pw) {
+    final result__ =
+        jni.JniObject.fromRef(_matchListItemPattern(reference, pw.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _setListItemPatterns = jlookup<
+  static final _setListItemPatterns = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -2032,10 +2290,13 @@
   ///
   /// use to supply a different set of regular expression patterns for matching list item starts.
   ///@param patterns list of patterns
-  void setListItemPatterns(jni.JlObject patterns) =>
-      _setListItemPatterns(reference, patterns.reference);
+  void setListItemPatterns(jni.JniObject patterns) {
+    final result__ = _setListItemPatterns(reference, patterns.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getListItemPatterns = jlookup<
+  static final _getListItemPatterns = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "org_apache_pdfbox_text_PDFTextStripper_getListItemPatterns")
@@ -2060,10 +2321,13 @@
   ///
   /// This method returns a list of such regular expression Patterns.
   ///@return a list of Pattern objects.
-  jni.JlObject getListItemPatterns() =>
-      jni.JlObject.fromRef(_getListItemPatterns(reference));
+  jni.JniObject getListItemPatterns() {
+    final result__ = jni.JniObject.fromRef(_getListItemPatterns(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _matchPattern = jlookup<
+  static final _matchPattern = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -2085,11 +2349,15 @@
   ///@param string the string to be searched
   ///@param patterns list of patterns
   ///@return matching pattern
-  static jni.JlObject matchPattern(
-          jni.JlString string, jni.JlObject patterns) =>
-      jni.JlObject.fromRef(_matchPattern(string.reference, patterns.reference));
+  static jni.JniObject matchPattern(
+      jni.JniString string, jni.JniObject patterns) {
+    final result__ = jni.JniObject.fromRef(
+        _matchPattern(string.reference, patterns.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _writeLine = jlookup<
+  static final _writeLine = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -2102,9 +2370,13 @@
   /// Write a list of string containing a whole line of a document.
   ///@param line a list with the words of the given line
   ///@throws IOException if something went wrong
-  void writeLine(jni.JlObject line) => _writeLine(reference, line.reference);
+  void writeLine(jni.JniObject line) {
+    final result__ = _writeLine(reference, line.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _normalize = jlookup<
+  static final _normalize = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -2119,10 +2391,14 @@
   /// Normalize the given list of TextPositions.
   ///@param line list of TextPositions
   ///@return a list of strings, one string for every word
-  jni.JlObject normalize(jni.JlObject line) =>
-      jni.JlObject.fromRef(_normalize(reference, line.reference));
+  jni.JniObject normalize(jni.JniObject line) {
+    final result__ =
+        jni.JniObject.fromRef(_normalize(reference, line.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _handleDirection = jlookup<
+  static final _handleDirection = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -2142,11 +2418,15 @@
   /// Based on http://www.nesterovsky-bros.com/weblog/2013/07/28/VisualToLogicalConversionInJava.aspx
   ///@param word The word that shall be processed
   ///@return new word with the correct direction of the containing characters
-  jni.JlString handleDirection(jni.JlString word) =>
-      jni.JlString.fromRef(_handleDirection(reference, word.reference));
+  jni.JniString handleDirection(jni.JniString word) {
+    final result__ =
+        jni.JniString.fromRef(_handleDirection(reference, word.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _parseBidiFile =
-      jlookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
               "org_apache_pdfbox_text_PDFTextStripper_parseBidiFile")
           .asFunction<void Function(ffi.Pointer<ffi.Void>)>();
 
@@ -2155,10 +2435,13 @@
   /// This method parses the bidi file provided as inputstream.
   ///@param inputStream - The bidi file as inputstream
   ///@throws IOException if any line could not be read by the LineNumberReader
-  static void parseBidiFile(jni.JlObject inputStream) =>
-      _parseBidiFile(inputStream.reference);
+  static void parseBidiFile(jni.JniObject inputStream) {
+    final result__ = _parseBidiFile(inputStream.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _createWord = jlookup<
+  static final _createWord = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>,
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -2171,11 +2454,14 @@
   /// The returned object must be deleted after use, by calling the `delete` method.
   ///
   /// Used within \#normalize(List) to create a single WordWithTextPositions entry.
-  jni.JlObject createWord(jni.JlString word, jni.JlObject wordPositions) =>
-      jni.JlObject.fromRef(
-          _createWord(reference, word.reference, wordPositions.reference));
+  jni.JniObject createWord(jni.JniString word, jni.JniObject wordPositions) {
+    final result__ = jni.JniObject.fromRef(
+        _createWord(reference, word.reference, wordPositions.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _normalizeWord = jlookup<
+  static final _normalizeWord = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -2191,10 +2477,14 @@
   /// normalises Arabic and Hebrew presentation forms.
   ///@param word Word to normalize
   ///@return Normalized word
-  jni.JlString normalizeWord(jni.JlString word) =>
-      jni.JlString.fromRef(_normalizeWord(reference, word.reference));
+  jni.JniString normalizeWord(jni.JniString word) {
+    final result__ =
+        jni.JniString.fromRef(_normalizeWord(reference, word.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _normalizeAdd = jlookup<
+  static final _normalizeAdd = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>,
@@ -2216,8 +2506,18 @@
   ///
   /// Used within \#normalize(List) to handle a TextPosition.
   ///@return The StringBuilder that must be used when calling this method.
-  jni.JlObject normalizeAdd(jni.JlObject normalized, jni.JlObject lineBuilder,
-          jni.JlObject wordPositions, jni.JlObject item) =>
-      jni.JlObject.fromRef(_normalizeAdd(reference, normalized.reference,
-          lineBuilder.reference, wordPositions.reference, item.reference));
+  jni.JniObject normalizeAdd(
+      jni.JniObject normalized,
+      jni.JniObject lineBuilder,
+      jni.JniObject wordPositions,
+      jni.JniObject item) {
+    final result__ = jni.JniObject.fromRef(_normalizeAdd(
+        reference,
+        normalized.reference,
+        lineBuilder.reference,
+        wordPositions.reference,
+        item.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 }
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/linux/CMakeLists.txt b/pkgs/jnigen/example/pdfbox_plugin/linux/CMakeLists.txt
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/linux/CMakeLists.txt
rename to pkgs/jnigen/example/pdfbox_plugin/linux/CMakeLists.txt
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/pubspec.yaml b/pkgs/jnigen/example/pdfbox_plugin/pubspec.yaml
similarity index 97%
rename from pkgs/jnigen/examples/pdfbox_plugin/pubspec.yaml
rename to pkgs/jnigen/example/pdfbox_plugin/pubspec.yaml
index 78aee9d..82c8715 100644
--- a/pkgs/jnigen/examples/pdfbox_plugin/pubspec.yaml
+++ b/pkgs/jnigen/example/pdfbox_plugin/pubspec.yaml
@@ -1,6 +1,6 @@
 name: pdfbox_plugin
 description: |
-  Example of using jnigen to generate bindings for a non-trivial library
+  Example of using jnigen to generate bindings for a non-trivial Java library.
 version: 0.0.1
 publish_to: none
 homepage: https://github.com/dart-lang/jnigen
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/src/CMakeLists.txt b/pkgs/jnigen/example/pdfbox_plugin/src/CMakeLists.txt
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/src/CMakeLists.txt
rename to pkgs/jnigen/example/pdfbox_plugin/src/CMakeLists.txt
diff --git a/pkgs/jnigen/examples/in_app_java/src/android_utils/dartjni.h b/pkgs/jnigen/example/pdfbox_plugin/src/third_party/dartjni.h
similarity index 81%
copy from pkgs/jnigen/examples/in_app_java/src/android_utils/dartjni.h
copy to pkgs/jnigen/example/pdfbox_plugin/src/third_party/dartjni.h
index cd94b15..0ce5069 100644
--- a/pkgs/jnigen/examples/in_app_java/src/android_utils/dartjni.h
+++ b/pkgs/jnigen/example/pdfbox_plugin/src/third_party/dartjni.h
@@ -2,6 +2,8 @@
 // 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.
 
+#pragma once
+
 #include <jni.h>
 #include <stdint.h>
 #include <stdio.h>
@@ -38,17 +40,17 @@
 #define __ENVP_CAST (void **)
 #endif
 
-struct jni_context {
+typedef struct JniContext {
 	JavaVM *jvm;
 	jobject classLoader;
 	jmethodID loadClassMethod;
 	jobject currentActivity;
 	jobject appContext;
-};
+} JniContext;
 
 extern thread_local JNIEnv *jniEnv;
 
-extern struct jni_context jni;
+extern JniContext jni;
 
 enum DartJniLogLevel {
 	JNI_VERBOSE = 2,
@@ -58,10 +60,25 @@
 	JNI_ERROR
 };
 
-FFI_PLUGIN_EXPORT struct jni_context GetJniContext();
+enum JniType {
+	boolType = 0,
+	byteType = 1,
+	shortType = 2,
+	charType = 3,
+	intType = 4,
+	longType = 5,
+	floatType = 6,
+	doubleType = 7,
+	objectType = 8,
+	voidType = 9,
+};
+
+FFI_PLUGIN_EXPORT JniContext GetJniContext();
 
 FFI_PLUGIN_EXPORT JavaVM *GetJavaVM(void);
 
+FFI_PLUGIN_EXPORT int DestroyJavaVM();
+
 FFI_PLUGIN_EXPORT JNIEnv *GetJniEnv(void);
 
 FFI_PLUGIN_EXPORT JNIEnv *SpawnJvm(JavaVMInitArgs *args);
@@ -74,26 +91,16 @@
 
 FFI_PLUGIN_EXPORT jobject GetCurrentActivity(void);
 
-FFI_PLUGIN_EXPORT void SetJNILogging(int level);
+/// For use by jni_gen's generated code
+/// don't use these.
 
-FFI_PLUGIN_EXPORT jstring ToJavaString(char *str);
-
-FFI_PLUGIN_EXPORT const char *GetJavaStringChars(jstring jstr);
-
-FFI_PLUGIN_EXPORT void ReleaseJavaStringChars(jstring jstr, const char *buf);
-
-// These 2 are the function pointer variables defined and exported by
-// the generated C files.
-//
-// initGeneratedLibrary function in Jni class will set these to
-// corresponding functions to the implementations from `dartjni` base library
-// which initializes and manages the JNI.
-extern struct jni_context (*context_getter)(void);
+// these 2 fn ptr vars will be defined by generated code library
+extern JniContext (*context_getter)(void);
 extern JNIEnv *(*env_getter)(void);
 
-// This function will be exported by generated code library and will set the
-// above 2 variables.
-FFI_PLUGIN_EXPORT void setJniGetters(struct jni_context (*cg)(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),
 		JNIEnv *(*eg)(void));
 
 // `static inline` because `inline` doesn't work, it may still not
@@ -101,6 +108,7 @@
 //
 // 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) {
 #ifdef __ANDROID__
 	jstring className = (*jniEnv)->NewStringUTF(jniEnv, name);
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/src/third_party/pdfbox_plugin.c b/pkgs/jnigen/example/pdfbox_plugin/src/third_party/pdfbox_plugin.c
similarity index 81%
rename from pkgs/jnigen/examples/pdfbox_plugin/src/third_party/pdfbox_plugin.c
rename to pkgs/jnigen/example/pdfbox_plugin/src/third_party/pdfbox_plugin.c
index 0de63de..656a985 100644
--- a/pkgs/jnigen/examples/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 "dartjni.h"
 
 thread_local JNIEnv *jniEnv;
-struct jni_context jni;
+JniContext jni;
 
-struct jni_context (*context_getter)(void);
+JniContext (*context_getter)(void);
 JNIEnv *(*env_getter)(void);
 
-void setJniGetters(struct jni_context (*cg)(void),
+void setJniGetters(JniContext (*cg)(void),
         JNIEnv *(*eg)(void)) {
     context_getter = cg;
     env_getter = eg;
@@ -42,7 +42,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocument_ctor() {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_ctor, "<init>", "()V");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_ctor == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->NewObject(jniEnv, _c_org_apache_pdfbox_pdmodel_PDDocument, _m_org_apache_pdfbox_pdmodel_PDDocument_ctor);
     return to_global_ref(_result);
 }
@@ -52,7 +54,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocument_ctor1(jobject memUsageSetting) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_ctor1, "<init>", "(Lorg/apache/pdfbox/io/MemoryUsageSetting;)V");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_ctor1 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->NewObject(jniEnv, _c_org_apache_pdfbox_pdmodel_PDDocument, _m_org_apache_pdfbox_pdmodel_PDDocument_ctor1, memUsageSetting);
     return to_global_ref(_result);
 }
@@ -62,7 +66,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocument_ctor2(jobject doc) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_ctor2, "<init>", "(Lorg/apache/pdfbox/cos/COSDocument;)V");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_ctor2 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->NewObject(jniEnv, _c_org_apache_pdfbox_pdmodel_PDDocument, _m_org_apache_pdfbox_pdmodel_PDDocument_ctor2, doc);
     return to_global_ref(_result);
 }
@@ -72,7 +78,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocument_ctor3(jobject doc, jobject source) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_ctor3, "<init>", "(Lorg/apache/pdfbox/cos/COSDocument;Lorg/apache/pdfbox/io/RandomAccessRead;)V");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_ctor3 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->NewObject(jniEnv, _c_org_apache_pdfbox_pdmodel_PDDocument, _m_org_apache_pdfbox_pdmodel_PDDocument_ctor3, doc, source);
     return to_global_ref(_result);
 }
@@ -82,7 +90,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocument_ctor4(jobject doc, jobject source, jobject permission) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_ctor4, "<init>", "(Lorg/apache/pdfbox/cos/COSDocument;Lorg/apache/pdfbox/io/RandomAccessRead;Lorg/apache/pdfbox/pdmodel/encryption/AccessPermission;)V");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_ctor4 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->NewObject(jniEnv, _c_org_apache_pdfbox_pdmodel_PDDocument, _m_org_apache_pdfbox_pdmodel_PDDocument_ctor4, doc, source, permission);
     return to_global_ref(_result);
 }
@@ -92,7 +102,9 @@
 void org_apache_pdfbox_pdmodel_PDDocument_addPage(jobject self_, jobject page) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_addPage, "addPage", "(Lorg/apache/pdfbox/pdmodel/PDPage;)V");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_addPage == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_addPage, page);
 }
 
@@ -101,7 +113,9 @@
 void org_apache_pdfbox_pdmodel_PDDocument_addSignature(jobject self_, jobject sigObject) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_addSignature, "addSignature", "(Lorg/apache/pdfbox/pdmodel/interactive/digitalsignature/PDSignature;)V");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_addSignature == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_addSignature, sigObject);
 }
 
@@ -110,7 +124,9 @@
 void org_apache_pdfbox_pdmodel_PDDocument_addSignature1(jobject self_, jobject sigObject, jobject options) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_addSignature1, "addSignature", "(Lorg/apache/pdfbox/pdmodel/interactive/digitalsignature/PDSignature;Lorg/apache/pdfbox/pdmodel/interactive/digitalsignature/SignatureOptions;)V");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_addSignature1 == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_addSignature1, sigObject, options);
 }
 
@@ -119,7 +135,9 @@
 void org_apache_pdfbox_pdmodel_PDDocument_addSignature2(jobject self_, jobject sigObject, jobject signatureInterface) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_addSignature2, "addSignature", "(Lorg/apache/pdfbox/pdmodel/interactive/digitalsignature/PDSignature;Lorg/apache/pdfbox/pdmodel/interactive/digitalsignature/SignatureInterface;)V");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_addSignature2 == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_addSignature2, sigObject, signatureInterface);
 }
 
@@ -128,7 +146,9 @@
 void org_apache_pdfbox_pdmodel_PDDocument_addSignature3(jobject self_, jobject sigObject, jobject signatureInterface, jobject options) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_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_org_apache_pdfbox_pdmodel_PDDocument_addSignature3 == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_addSignature3, sigObject, signatureInterface, options);
 }
 
@@ -137,7 +157,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocument_findSignatureField(jobject self_, jobject fieldIterator, jobject sigObject) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_findSignatureField, "findSignatureField", "(Ljava/util/Iterator;Lorg/apache/pdfbox/pdmodel/interactive/digitalsignature/PDSignature;)Lorg/apache/pdfbox/pdmodel/interactive/form/PDSignatureField;");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_findSignatureField == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_findSignatureField, fieldIterator, sigObject);
     return to_global_ref(_result);
 }
@@ -147,7 +169,9 @@
 uint8_t org_apache_pdfbox_pdmodel_PDDocument_checkSignatureField(jobject self_, jobject fieldIterator, jobject signatureField) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (uint8_t)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_checkSignatureField, "checkSignatureField", "(Ljava/util/Iterator;Lorg/apache/pdfbox/pdmodel/interactive/form/PDSignatureField;)Z");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_checkSignatureField == NULL) return (uint8_t)0;
     uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_checkSignatureField, fieldIterator, signatureField);
     return _result;
 }
@@ -157,7 +181,9 @@
 uint8_t org_apache_pdfbox_pdmodel_PDDocument_checkSignatureAnnotation(jobject self_, jobject annotations, jobject widget) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (uint8_t)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_checkSignatureAnnotation, "checkSignatureAnnotation", "(Ljava/util/List;Lorg/apache/pdfbox/pdmodel/interactive/annotation/PDAnnotationWidget;)Z");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_checkSignatureAnnotation == NULL) return (uint8_t)0;
     uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_checkSignatureAnnotation, annotations, widget);
     return _result;
 }
@@ -167,7 +193,9 @@
 void org_apache_pdfbox_pdmodel_PDDocument_prepareVisibleSignature(jobject self_, jobject signatureField, jobject acroForm, jobject visualSignature) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_prepareVisibleSignature, "prepareVisibleSignature", "(Lorg/apache/pdfbox/pdmodel/interactive/form/PDSignatureField;Lorg/apache/pdfbox/pdmodel/interactive/form/PDAcroForm;Lorg/apache/pdfbox/cos/COSDocument;)V");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_prepareVisibleSignature == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_prepareVisibleSignature, signatureField, acroForm, visualSignature);
 }
 
@@ -176,7 +204,9 @@
 void org_apache_pdfbox_pdmodel_PDDocument_assignSignatureRectangle(jobject self_, jobject signatureField, jobject annotDict) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_assignSignatureRectangle, "assignSignatureRectangle", "(Lorg/apache/pdfbox/pdmodel/interactive/form/PDSignatureField;Lorg/apache/pdfbox/cos/COSDictionary;)V");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_assignSignatureRectangle == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_assignSignatureRectangle, signatureField, annotDict);
 }
 
@@ -185,7 +215,9 @@
 void org_apache_pdfbox_pdmodel_PDDocument_assignAppearanceDictionary(jobject self_, jobject signatureField, jobject apDict) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_assignAppearanceDictionary, "assignAppearanceDictionary", "(Lorg/apache/pdfbox/pdmodel/interactive/form/PDSignatureField;Lorg/apache/pdfbox/cos/COSDictionary;)V");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_assignAppearanceDictionary == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_assignAppearanceDictionary, signatureField, apDict);
 }
 
@@ -194,7 +226,9 @@
 void org_apache_pdfbox_pdmodel_PDDocument_assignAcroFormDefaultResource(jobject self_, jobject acroForm, jobject newDict) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_assignAcroFormDefaultResource, "assignAcroFormDefaultResource", "(Lorg/apache/pdfbox/pdmodel/interactive/form/PDAcroForm;Lorg/apache/pdfbox/cos/COSDictionary;)V");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_assignAcroFormDefaultResource == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_assignAcroFormDefaultResource, acroForm, newDict);
 }
 
@@ -203,7 +237,9 @@
 void org_apache_pdfbox_pdmodel_PDDocument_prepareNonVisibleSignature(jobject self_, jobject signatureField) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_prepareNonVisibleSignature, "prepareNonVisibleSignature", "(Lorg/apache/pdfbox/pdmodel/interactive/form/PDSignatureField;)V");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_prepareNonVisibleSignature == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_prepareNonVisibleSignature, signatureField);
 }
 
@@ -212,7 +248,9 @@
 void org_apache_pdfbox_pdmodel_PDDocument_addSignatureField(jobject self_, jobject sigFields, jobject signatureInterface, jobject options) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_addSignatureField, "addSignatureField", "(Ljava/util/List;Lorg/apache/pdfbox/pdmodel/interactive/digitalsignature/SignatureInterface;Lorg/apache/pdfbox/pdmodel/interactive/digitalsignature/SignatureOptions;)V");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_addSignatureField == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_addSignatureField, sigFields, signatureInterface, options);
 }
 
@@ -221,7 +259,9 @@
 void org_apache_pdfbox_pdmodel_PDDocument_removePage(jobject self_, jobject page) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_removePage, "removePage", "(Lorg/apache/pdfbox/pdmodel/PDPage;)V");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_removePage == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_removePage, page);
 }
 
@@ -230,7 +270,9 @@
 void org_apache_pdfbox_pdmodel_PDDocument_removePage1(jobject self_, int32_t pageNumber) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_removePage1, "removePage", "(I)V");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_removePage1 == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_removePage1, pageNumber);
 }
 
@@ -239,7 +281,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocument_importPage(jobject self_, jobject page) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_importPage, "importPage", "(Lorg/apache/pdfbox/pdmodel/PDPage;)Lorg/apache/pdfbox/pdmodel/PDPage;");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_importPage == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_importPage, page);
     return to_global_ref(_result);
 }
@@ -249,7 +293,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocument_getDocument(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_getDocument, "getDocument", "()Lorg/apache/pdfbox/cos/COSDocument;");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_getDocument == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_getDocument);
     return to_global_ref(_result);
 }
@@ -259,7 +305,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocument_getDocumentInformation(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_getDocumentInformation, "getDocumentInformation", "()Lorg/apache/pdfbox/pdmodel/PDDocumentInformation;");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_getDocumentInformation == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_getDocumentInformation);
     return to_global_ref(_result);
 }
@@ -269,7 +317,9 @@
 void org_apache_pdfbox_pdmodel_PDDocument_setDocumentInformation(jobject self_, jobject info) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_setDocumentInformation, "setDocumentInformation", "(Lorg/apache/pdfbox/pdmodel/PDDocumentInformation;)V");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_setDocumentInformation == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_setDocumentInformation, info);
 }
 
@@ -278,7 +328,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocument_getDocumentCatalog(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_getDocumentCatalog, "getDocumentCatalog", "()Lorg/apache/pdfbox/pdmodel/PDDocumentCatalog;");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_getDocumentCatalog == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_getDocumentCatalog);
     return to_global_ref(_result);
 }
@@ -288,7 +340,9 @@
 uint8_t org_apache_pdfbox_pdmodel_PDDocument_isEncrypted(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (uint8_t)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_isEncrypted, "isEncrypted", "()Z");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_isEncrypted == NULL) return (uint8_t)0;
     uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_isEncrypted);
     return _result;
 }
@@ -298,7 +352,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocument_getEncryption(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_getEncryption, "getEncryption", "()Lorg/apache/pdfbox/pdmodel/encryption/PDEncryption;");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_getEncryption == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_getEncryption);
     return to_global_ref(_result);
 }
@@ -308,7 +364,9 @@
 void org_apache_pdfbox_pdmodel_PDDocument_setEncryptionDictionary(jobject self_, jobject encryption) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_setEncryptionDictionary, "setEncryptionDictionary", "(Lorg/apache/pdfbox/pdmodel/encryption/PDEncryption;)V");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_setEncryptionDictionary == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_setEncryptionDictionary, encryption);
 }
 
@@ -317,7 +375,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocument_getLastSignatureDictionary(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_getLastSignatureDictionary, "getLastSignatureDictionary", "()Lorg/apache/pdfbox/pdmodel/interactive/digitalsignature/PDSignature;");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_getLastSignatureDictionary == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_getLastSignatureDictionary);
     return to_global_ref(_result);
 }
@@ -327,7 +387,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocument_getSignatureFields(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_getSignatureFields, "getSignatureFields", "()Ljava/util/List;");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_getSignatureFields == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_getSignatureFields);
     return to_global_ref(_result);
 }
@@ -337,7 +399,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocument_getSignatureDictionaries(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_getSignatureDictionaries, "getSignatureDictionaries", "()Ljava/util/List;");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_getSignatureDictionaries == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_getSignatureDictionaries);
     return to_global_ref(_result);
 }
@@ -347,7 +411,9 @@
 void org_apache_pdfbox_pdmodel_PDDocument_registerTrueTypeFontForClosing(jobject self_, jobject ttf) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_registerTrueTypeFontForClosing, "registerTrueTypeFontForClosing", "(Lorg/apache/fontbox/ttf/TrueTypeFont;)V");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_registerTrueTypeFontForClosing == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_registerTrueTypeFontForClosing, ttf);
 }
 
@@ -356,7 +422,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocument_getFontsToSubset(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_getFontsToSubset, "getFontsToSubset", "()Ljava/util/Set;");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_getFontsToSubset == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_getFontsToSubset);
     return to_global_ref(_result);
 }
@@ -366,7 +434,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocument_load(jobject file) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_static_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_load, "load", "(Ljava/io/File;)Lorg/apache/pdfbox/pdmodel/PDDocument;");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_load == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallStaticObjectMethod(jniEnv, _c_org_apache_pdfbox_pdmodel_PDDocument, _m_org_apache_pdfbox_pdmodel_PDDocument_load, file);
     return to_global_ref(_result);
 }
@@ -376,7 +446,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocument_load1(jobject file, jobject memUsageSetting) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_static_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_load1, "load", "(Ljava/io/File;Lorg/apache/pdfbox/io/MemoryUsageSetting;)Lorg/apache/pdfbox/pdmodel/PDDocument;");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_load1 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallStaticObjectMethod(jniEnv, _c_org_apache_pdfbox_pdmodel_PDDocument, _m_org_apache_pdfbox_pdmodel_PDDocument_load1, file, memUsageSetting);
     return to_global_ref(_result);
 }
@@ -386,7 +458,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocument_load2(jobject file, jobject password) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_static_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_load2, "load", "(Ljava/io/File;Ljava/lang/String;)Lorg/apache/pdfbox/pdmodel/PDDocument;");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_load2 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallStaticObjectMethod(jniEnv, _c_org_apache_pdfbox_pdmodel_PDDocument, _m_org_apache_pdfbox_pdmodel_PDDocument_load2, file, password);
     return to_global_ref(_result);
 }
@@ -396,7 +470,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocument_load3(jobject file, jobject password, jobject memUsageSetting) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_static_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_load3, "load", "(Ljava/io/File;Ljava/lang/String;Lorg/apache/pdfbox/io/MemoryUsageSetting;)Lorg/apache/pdfbox/pdmodel/PDDocument;");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_load3 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallStaticObjectMethod(jniEnv, _c_org_apache_pdfbox_pdmodel_PDDocument, _m_org_apache_pdfbox_pdmodel_PDDocument_load3, file, password, memUsageSetting);
     return to_global_ref(_result);
 }
@@ -406,7 +482,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocument_load4(jobject file, jobject password, jobject keyStore, jobject alias) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_static_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_load4, "load", "(Ljava/io/File;Ljava/lang/String;Ljava/io/InputStream;Ljava/lang/String;)Lorg/apache/pdfbox/pdmodel/PDDocument;");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_load4 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallStaticObjectMethod(jniEnv, _c_org_apache_pdfbox_pdmodel_PDDocument, _m_org_apache_pdfbox_pdmodel_PDDocument_load4, file, password, keyStore, alias);
     return to_global_ref(_result);
 }
@@ -416,7 +494,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocument_load5(jobject file, jobject password, jobject keyStore, jobject alias, jobject memUsageSetting) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_static_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_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_org_apache_pdfbox_pdmodel_PDDocument_load5 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallStaticObjectMethod(jniEnv, _c_org_apache_pdfbox_pdmodel_PDDocument, _m_org_apache_pdfbox_pdmodel_PDDocument_load5, file, password, keyStore, alias, memUsageSetting);
     return to_global_ref(_result);
 }
@@ -426,7 +506,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocument_load6(jobject raFile, jobject password, jobject keyStore, jobject alias, jobject memUsageSetting) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_static_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_load6, "load", "(Lorg/apache/pdfbox/io/RandomAccessBufferedFileInputStream;Ljava/lang/String;Ljava/io/InputStream;Ljava/lang/String;Lorg/apache/pdfbox/io/MemoryUsageSetting;)Lorg/apache/pdfbox/pdmodel/PDDocument;");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_load6 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallStaticObjectMethod(jniEnv, _c_org_apache_pdfbox_pdmodel_PDDocument, _m_org_apache_pdfbox_pdmodel_PDDocument_load6, raFile, password, keyStore, alias, memUsageSetting);
     return to_global_ref(_result);
 }
@@ -436,7 +518,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocument_load7(jobject input) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_static_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_load7, "load", "(Ljava/io/InputStream;)Lorg/apache/pdfbox/pdmodel/PDDocument;");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_load7 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallStaticObjectMethod(jniEnv, _c_org_apache_pdfbox_pdmodel_PDDocument, _m_org_apache_pdfbox_pdmodel_PDDocument_load7, input);
     return to_global_ref(_result);
 }
@@ -446,7 +530,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocument_load8(jobject input, jobject memUsageSetting) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_static_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_load8, "load", "(Ljava/io/InputStream;Lorg/apache/pdfbox/io/MemoryUsageSetting;)Lorg/apache/pdfbox/pdmodel/PDDocument;");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_load8 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallStaticObjectMethod(jniEnv, _c_org_apache_pdfbox_pdmodel_PDDocument, _m_org_apache_pdfbox_pdmodel_PDDocument_load8, input, memUsageSetting);
     return to_global_ref(_result);
 }
@@ -456,7 +542,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocument_load9(jobject input, jobject password) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_static_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_load9, "load", "(Ljava/io/InputStream;Ljava/lang/String;)Lorg/apache/pdfbox/pdmodel/PDDocument;");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_load9 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallStaticObjectMethod(jniEnv, _c_org_apache_pdfbox_pdmodel_PDDocument, _m_org_apache_pdfbox_pdmodel_PDDocument_load9, input, password);
     return to_global_ref(_result);
 }
@@ -466,7 +554,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocument_load10(jobject input, jobject password, jobject keyStore, jobject alias) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_static_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_load10, "load", "(Ljava/io/InputStream;Ljava/lang/String;Ljava/io/InputStream;Ljava/lang/String;)Lorg/apache/pdfbox/pdmodel/PDDocument;");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_load10 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallStaticObjectMethod(jniEnv, _c_org_apache_pdfbox_pdmodel_PDDocument, _m_org_apache_pdfbox_pdmodel_PDDocument_load10, input, password, keyStore, alias);
     return to_global_ref(_result);
 }
@@ -476,7 +566,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocument_load11(jobject input, jobject password, jobject memUsageSetting) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_static_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_load11, "load", "(Ljava/io/InputStream;Ljava/lang/String;Lorg/apache/pdfbox/io/MemoryUsageSetting;)Lorg/apache/pdfbox/pdmodel/PDDocument;");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_load11 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallStaticObjectMethod(jniEnv, _c_org_apache_pdfbox_pdmodel_PDDocument, _m_org_apache_pdfbox_pdmodel_PDDocument_load11, input, password, memUsageSetting);
     return to_global_ref(_result);
 }
@@ -486,7 +578,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocument_load12(jobject input, jobject password, jobject keyStore, jobject alias, jobject memUsageSetting) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_static_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_load12, "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_org_apache_pdfbox_pdmodel_PDDocument_load12 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallStaticObjectMethod(jniEnv, _c_org_apache_pdfbox_pdmodel_PDDocument, _m_org_apache_pdfbox_pdmodel_PDDocument_load12, input, password, keyStore, alias, memUsageSetting);
     return to_global_ref(_result);
 }
@@ -496,7 +590,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocument_load13(jobject input) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_static_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_load13, "load", "(L[B;)Lorg/apache/pdfbox/pdmodel/PDDocument;");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_load13 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallStaticObjectMethod(jniEnv, _c_org_apache_pdfbox_pdmodel_PDDocument, _m_org_apache_pdfbox_pdmodel_PDDocument_load13, input);
     return to_global_ref(_result);
 }
@@ -506,7 +602,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocument_load14(jobject input, jobject password) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_static_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_load14, "load", "(L[B;Ljava/lang/String;)Lorg/apache/pdfbox/pdmodel/PDDocument;");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_load14 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallStaticObjectMethod(jniEnv, _c_org_apache_pdfbox_pdmodel_PDDocument, _m_org_apache_pdfbox_pdmodel_PDDocument_load14, input, password);
     return to_global_ref(_result);
 }
@@ -516,7 +614,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocument_load15(jobject input, jobject password, jobject keyStore, jobject alias) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_static_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_load15, "load", "(L[B;Ljava/lang/String;Ljava/io/InputStream;Ljava/lang/String;)Lorg/apache/pdfbox/pdmodel/PDDocument;");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_load15 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallStaticObjectMethod(jniEnv, _c_org_apache_pdfbox_pdmodel_PDDocument, _m_org_apache_pdfbox_pdmodel_PDDocument_load15, input, password, keyStore, alias);
     return to_global_ref(_result);
 }
@@ -526,7 +626,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocument_load16(jobject input, jobject password, jobject keyStore, jobject alias, jobject memUsageSetting) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_static_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_load16, "load", "(L[B;Ljava/lang/String;Ljava/io/InputStream;Ljava/lang/String;Lorg/apache/pdfbox/io/MemoryUsageSetting;)Lorg/apache/pdfbox/pdmodel/PDDocument;");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_load16 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallStaticObjectMethod(jniEnv, _c_org_apache_pdfbox_pdmodel_PDDocument, _m_org_apache_pdfbox_pdmodel_PDDocument_load16, input, password, keyStore, alias, memUsageSetting);
     return to_global_ref(_result);
 }
@@ -536,7 +638,9 @@
 void org_apache_pdfbox_pdmodel_PDDocument_save(jobject self_, jobject fileName) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_save, "save", "(Ljava/lang/String;)V");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_save == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_save, fileName);
 }
 
@@ -545,7 +649,9 @@
 void org_apache_pdfbox_pdmodel_PDDocument_save1(jobject self_, jobject file) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_save1, "save", "(Ljava/io/File;)V");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_save1 == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_save1, file);
 }
 
@@ -554,7 +660,9 @@
 void org_apache_pdfbox_pdmodel_PDDocument_save2(jobject self_, jobject output) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_save2, "save", "(Ljava/io/OutputStream;)V");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_save2 == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_save2, output);
 }
 
@@ -563,7 +671,9 @@
 void org_apache_pdfbox_pdmodel_PDDocument_saveIncremental(jobject self_, jobject output) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_saveIncremental, "saveIncremental", "(Ljava/io/OutputStream;)V");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_saveIncremental == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_saveIncremental, output);
 }
 
@@ -572,7 +682,9 @@
 void org_apache_pdfbox_pdmodel_PDDocument_saveIncremental1(jobject self_, jobject output, jobject objectsToWrite) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_saveIncremental1, "saveIncremental", "(Ljava/io/OutputStream;Ljava/util/Set;)V");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_saveIncremental1 == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_saveIncremental1, output, objectsToWrite);
 }
 
@@ -581,7 +693,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocument_saveIncrementalForExternalSigning(jobject self_, jobject output) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_saveIncrementalForExternalSigning, "saveIncrementalForExternalSigning", "(Ljava/io/OutputStream;)Lorg/apache/pdfbox/pdmodel/interactive/digitalsignature/ExternalSigningSupport;");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_saveIncrementalForExternalSigning == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_saveIncrementalForExternalSigning, output);
     return to_global_ref(_result);
 }
@@ -591,7 +705,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocument_getPage(jobject self_, int32_t pageIndex) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_getPage, "getPage", "(I)Lorg/apache/pdfbox/pdmodel/PDPage;");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_getPage == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_getPage, pageIndex);
     return to_global_ref(_result);
 }
@@ -601,7 +717,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocument_getPages(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_getPages, "getPages", "()Lorg/apache/pdfbox/pdmodel/PDPageTree;");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_getPages == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_getPages);
     return to_global_ref(_result);
 }
@@ -611,7 +729,9 @@
 int32_t org_apache_pdfbox_pdmodel_PDDocument_getNumberOfPages(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (int32_t)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_getNumberOfPages, "getNumberOfPages", "()I");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_getNumberOfPages == NULL) return (int32_t)0;
     int32_t _result = (*jniEnv)->CallIntMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_getNumberOfPages);
     return _result;
 }
@@ -621,7 +741,9 @@
 void org_apache_pdfbox_pdmodel_PDDocument_close(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_close, "close", "()V");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_close == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_close);
 }
 
@@ -630,7 +752,9 @@
 void org_apache_pdfbox_pdmodel_PDDocument_protect(jobject self_, jobject policy) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_protect, "protect", "(Lorg/apache/pdfbox/pdmodel/encryption/ProtectionPolicy;)V");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_protect == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_protect, policy);
 }
 
@@ -639,7 +763,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocument_getCurrentAccessPermission(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_getCurrentAccessPermission, "getCurrentAccessPermission", "()Lorg/apache/pdfbox/pdmodel/encryption/AccessPermission;");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_getCurrentAccessPermission == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_getCurrentAccessPermission);
     return to_global_ref(_result);
 }
@@ -649,7 +775,9 @@
 uint8_t org_apache_pdfbox_pdmodel_PDDocument_isAllSecurityToBeRemoved(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (uint8_t)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_isAllSecurityToBeRemoved, "isAllSecurityToBeRemoved", "()Z");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_isAllSecurityToBeRemoved == NULL) return (uint8_t)0;
     uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_isAllSecurityToBeRemoved);
     return _result;
 }
@@ -659,7 +787,9 @@
 void org_apache_pdfbox_pdmodel_PDDocument_setAllSecurityToBeRemoved(jobject self_, uint8_t removeAllSecurity) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_setAllSecurityToBeRemoved, "setAllSecurityToBeRemoved", "(Z)V");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_setAllSecurityToBeRemoved == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_setAllSecurityToBeRemoved, removeAllSecurity);
 }
 
@@ -668,7 +798,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocument_getDocumentId(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_getDocumentId, "getDocumentId", "()Ljava/lang/Long;");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_getDocumentId == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_getDocumentId);
     return to_global_ref(_result);
 }
@@ -678,7 +810,9 @@
 void org_apache_pdfbox_pdmodel_PDDocument_setDocumentId(jobject self_, jobject docId) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_setDocumentId, "setDocumentId", "(Ljava/lang/Long;)V");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_setDocumentId == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_setDocumentId, docId);
 }
 
@@ -687,7 +821,9 @@
 float org_apache_pdfbox_pdmodel_PDDocument_getVersion(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (float)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_getVersion, "getVersion", "()F");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_getVersion == NULL) return (float)0;
     float _result = (*jniEnv)->CallFloatMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_getVersion);
     return _result;
 }
@@ -697,7 +833,9 @@
 void org_apache_pdfbox_pdmodel_PDDocument_setVersion(jobject self_, float newVersion) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_setVersion, "setVersion", "(F)V");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_setVersion == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_setVersion, newVersion);
 }
 
@@ -706,7 +844,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocument_getResourceCache(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_getResourceCache, "getResourceCache", "()Lorg/apache/pdfbox/pdmodel/ResourceCache;");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_getResourceCache == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_getResourceCache);
     return to_global_ref(_result);
 }
@@ -716,7 +856,9 @@
 void org_apache_pdfbox_pdmodel_PDDocument_setResourceCache(jobject self_, jobject resourceCache) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_setResourceCache, "setResourceCache", "(Lorg/apache/pdfbox/pdmodel/ResourceCache;)V");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocument_setResourceCache == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_setResourceCache, resourceCache);
 }
 
@@ -724,6 +866,7 @@
 jobject get_org_apache_pdfbox_pdmodel_PDDocument_RESERVE_BYTE_RANGE() {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_static_field(_c_org_apache_pdfbox_pdmodel_PDDocument, &_f_org_apache_pdfbox_pdmodel_PDDocument_RESERVE_BYTE_RANGE, "RESERVE_BYTE_RANGE","L[I;");
     return to_global_ref((*jniEnv)->GetStaticObjectField(jniEnv, _c_org_apache_pdfbox_pdmodel_PDDocument, _f_org_apache_pdfbox_pdmodel_PDDocument_RESERVE_BYTE_RANGE));
 }
@@ -733,6 +876,7 @@
 jobject get_org_apache_pdfbox_pdmodel_PDDocument_LOG() {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_static_field(_c_org_apache_pdfbox_pdmodel_PDDocument, &_f_org_apache_pdfbox_pdmodel_PDDocument_LOG, "LOG","Lorg/apache/commons/logging/Log;");
     return to_global_ref((*jniEnv)->GetStaticObjectField(jniEnv, _c_org_apache_pdfbox_pdmodel_PDDocument, _f_org_apache_pdfbox_pdmodel_PDDocument_LOG));
 }
@@ -742,6 +886,7 @@
 jobject get_org_apache_pdfbox_pdmodel_PDDocument_document(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_field(_c_org_apache_pdfbox_pdmodel_PDDocument, &_f_org_apache_pdfbox_pdmodel_PDDocument_document, "document","Lorg/apache/pdfbox/cos/COSDocument;");
     return to_global_ref((*jniEnv)->GetObjectField(jniEnv, self_, _f_org_apache_pdfbox_pdmodel_PDDocument_document));
 }
@@ -751,6 +896,7 @@
 jobject get_org_apache_pdfbox_pdmodel_PDDocument_documentInformation(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_field(_c_org_apache_pdfbox_pdmodel_PDDocument, &_f_org_apache_pdfbox_pdmodel_PDDocument_documentInformation, "documentInformation","Lorg/apache/pdfbox/pdmodel/PDDocumentInformation;");
     return to_global_ref((*jniEnv)->GetObjectField(jniEnv, self_, _f_org_apache_pdfbox_pdmodel_PDDocument_documentInformation));
 }
@@ -758,6 +904,7 @@
 void set_org_apache_pdfbox_pdmodel_PDDocument_documentInformation(jobject self_, jobject value) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (void)0;
     load_field(_c_org_apache_pdfbox_pdmodel_PDDocument, &_f_org_apache_pdfbox_pdmodel_PDDocument_documentInformation, "documentInformation","Lorg/apache/pdfbox/pdmodel/PDDocumentInformation;");
     ((*jniEnv)->SetObjectField(jniEnv, self_, _f_org_apache_pdfbox_pdmodel_PDDocument_documentInformation, value));
 }
@@ -767,6 +914,7 @@
 jobject get_org_apache_pdfbox_pdmodel_PDDocument_documentCatalog(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_field(_c_org_apache_pdfbox_pdmodel_PDDocument, &_f_org_apache_pdfbox_pdmodel_PDDocument_documentCatalog, "documentCatalog","Lorg/apache/pdfbox/pdmodel/PDDocumentCatalog;");
     return to_global_ref((*jniEnv)->GetObjectField(jniEnv, self_, _f_org_apache_pdfbox_pdmodel_PDDocument_documentCatalog));
 }
@@ -774,6 +922,7 @@
 void set_org_apache_pdfbox_pdmodel_PDDocument_documentCatalog(jobject self_, jobject value) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (void)0;
     load_field(_c_org_apache_pdfbox_pdmodel_PDDocument, &_f_org_apache_pdfbox_pdmodel_PDDocument_documentCatalog, "documentCatalog","Lorg/apache/pdfbox/pdmodel/PDDocumentCatalog;");
     ((*jniEnv)->SetObjectField(jniEnv, self_, _f_org_apache_pdfbox_pdmodel_PDDocument_documentCatalog, value));
 }
@@ -783,6 +932,7 @@
 jobject get_org_apache_pdfbox_pdmodel_PDDocument_encryption(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_field(_c_org_apache_pdfbox_pdmodel_PDDocument, &_f_org_apache_pdfbox_pdmodel_PDDocument_encryption, "encryption","Lorg/apache/pdfbox/pdmodel/encryption/PDEncryption;");
     return to_global_ref((*jniEnv)->GetObjectField(jniEnv, self_, _f_org_apache_pdfbox_pdmodel_PDDocument_encryption));
 }
@@ -790,6 +940,7 @@
 void set_org_apache_pdfbox_pdmodel_PDDocument_encryption(jobject self_, jobject value) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (void)0;
     load_field(_c_org_apache_pdfbox_pdmodel_PDDocument, &_f_org_apache_pdfbox_pdmodel_PDDocument_encryption, "encryption","Lorg/apache/pdfbox/pdmodel/encryption/PDEncryption;");
     ((*jniEnv)->SetObjectField(jniEnv, self_, _f_org_apache_pdfbox_pdmodel_PDDocument_encryption, value));
 }
@@ -799,6 +950,7 @@
 uint8_t get_org_apache_pdfbox_pdmodel_PDDocument_allSecurityToBeRemoved(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (uint8_t)0;
     load_field(_c_org_apache_pdfbox_pdmodel_PDDocument, &_f_org_apache_pdfbox_pdmodel_PDDocument_allSecurityToBeRemoved, "allSecurityToBeRemoved","Z");
     return ((*jniEnv)->GetBooleanField(jniEnv, self_, _f_org_apache_pdfbox_pdmodel_PDDocument_allSecurityToBeRemoved));
 }
@@ -806,6 +958,7 @@
 void set_org_apache_pdfbox_pdmodel_PDDocument_allSecurityToBeRemoved(jobject self_, uint8_t value) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (void)0;
     load_field(_c_org_apache_pdfbox_pdmodel_PDDocument, &_f_org_apache_pdfbox_pdmodel_PDDocument_allSecurityToBeRemoved, "allSecurityToBeRemoved","Z");
     ((*jniEnv)->SetBooleanField(jniEnv, self_, _f_org_apache_pdfbox_pdmodel_PDDocument_allSecurityToBeRemoved, value));
 }
@@ -815,6 +968,7 @@
 jobject get_org_apache_pdfbox_pdmodel_PDDocument_documentId(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_field(_c_org_apache_pdfbox_pdmodel_PDDocument, &_f_org_apache_pdfbox_pdmodel_PDDocument_documentId, "documentId","Ljava/lang/Long;");
     return to_global_ref((*jniEnv)->GetObjectField(jniEnv, self_, _f_org_apache_pdfbox_pdmodel_PDDocument_documentId));
 }
@@ -822,6 +976,7 @@
 void set_org_apache_pdfbox_pdmodel_PDDocument_documentId(jobject self_, jobject value) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (void)0;
     load_field(_c_org_apache_pdfbox_pdmodel_PDDocument, &_f_org_apache_pdfbox_pdmodel_PDDocument_documentId, "documentId","Ljava/lang/Long;");
     ((*jniEnv)->SetObjectField(jniEnv, self_, _f_org_apache_pdfbox_pdmodel_PDDocument_documentId, value));
 }
@@ -831,6 +986,7 @@
 jobject get_org_apache_pdfbox_pdmodel_PDDocument_pdfSource(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_field(_c_org_apache_pdfbox_pdmodel_PDDocument, &_f_org_apache_pdfbox_pdmodel_PDDocument_pdfSource, "pdfSource","Lorg/apache/pdfbox/io/RandomAccessRead;");
     return to_global_ref((*jniEnv)->GetObjectField(jniEnv, self_, _f_org_apache_pdfbox_pdmodel_PDDocument_pdfSource));
 }
@@ -840,6 +996,7 @@
 jobject get_org_apache_pdfbox_pdmodel_PDDocument_accessPermission(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_field(_c_org_apache_pdfbox_pdmodel_PDDocument, &_f_org_apache_pdfbox_pdmodel_PDDocument_accessPermission, "accessPermission","Lorg/apache/pdfbox/pdmodel/encryption/AccessPermission;");
     return to_global_ref((*jniEnv)->GetObjectField(jniEnv, self_, _f_org_apache_pdfbox_pdmodel_PDDocument_accessPermission));
 }
@@ -847,6 +1004,7 @@
 void set_org_apache_pdfbox_pdmodel_PDDocument_accessPermission(jobject self_, jobject value) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (void)0;
     load_field(_c_org_apache_pdfbox_pdmodel_PDDocument, &_f_org_apache_pdfbox_pdmodel_PDDocument_accessPermission, "accessPermission","Lorg/apache/pdfbox/pdmodel/encryption/AccessPermission;");
     ((*jniEnv)->SetObjectField(jniEnv, self_, _f_org_apache_pdfbox_pdmodel_PDDocument_accessPermission, value));
 }
@@ -856,6 +1014,7 @@
 jobject get_org_apache_pdfbox_pdmodel_PDDocument_fontsToSubset(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_field(_c_org_apache_pdfbox_pdmodel_PDDocument, &_f_org_apache_pdfbox_pdmodel_PDDocument_fontsToSubset, "fontsToSubset","Ljava/util/Set;");
     return to_global_ref((*jniEnv)->GetObjectField(jniEnv, self_, _f_org_apache_pdfbox_pdmodel_PDDocument_fontsToSubset));
 }
@@ -865,6 +1024,7 @@
 jobject get_org_apache_pdfbox_pdmodel_PDDocument_fontsToClose(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_field(_c_org_apache_pdfbox_pdmodel_PDDocument, &_f_org_apache_pdfbox_pdmodel_PDDocument_fontsToClose, "fontsToClose","Ljava/util/Set;");
     return to_global_ref((*jniEnv)->GetObjectField(jniEnv, self_, _f_org_apache_pdfbox_pdmodel_PDDocument_fontsToClose));
 }
@@ -874,6 +1034,7 @@
 jobject get_org_apache_pdfbox_pdmodel_PDDocument_signInterface(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_field(_c_org_apache_pdfbox_pdmodel_PDDocument, &_f_org_apache_pdfbox_pdmodel_PDDocument_signInterface, "signInterface","Lorg/apache/pdfbox/pdmodel/interactive/digitalsignature/SignatureInterface;");
     return to_global_ref((*jniEnv)->GetObjectField(jniEnv, self_, _f_org_apache_pdfbox_pdmodel_PDDocument_signInterface));
 }
@@ -881,6 +1042,7 @@
 void set_org_apache_pdfbox_pdmodel_PDDocument_signInterface(jobject self_, jobject value) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (void)0;
     load_field(_c_org_apache_pdfbox_pdmodel_PDDocument, &_f_org_apache_pdfbox_pdmodel_PDDocument_signInterface, "signInterface","Lorg/apache/pdfbox/pdmodel/interactive/digitalsignature/SignatureInterface;");
     ((*jniEnv)->SetObjectField(jniEnv, self_, _f_org_apache_pdfbox_pdmodel_PDDocument_signInterface, value));
 }
@@ -890,6 +1052,7 @@
 jobject get_org_apache_pdfbox_pdmodel_PDDocument_signingSupport(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_field(_c_org_apache_pdfbox_pdmodel_PDDocument, &_f_org_apache_pdfbox_pdmodel_PDDocument_signingSupport, "signingSupport","Lorg/apache/pdfbox/pdmodel/interactive/digitalsignature/SigningSupport;");
     return to_global_ref((*jniEnv)->GetObjectField(jniEnv, self_, _f_org_apache_pdfbox_pdmodel_PDDocument_signingSupport));
 }
@@ -897,6 +1060,7 @@
 void set_org_apache_pdfbox_pdmodel_PDDocument_signingSupport(jobject self_, jobject value) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (void)0;
     load_field(_c_org_apache_pdfbox_pdmodel_PDDocument, &_f_org_apache_pdfbox_pdmodel_PDDocument_signingSupport, "signingSupport","Lorg/apache/pdfbox/pdmodel/interactive/digitalsignature/SigningSupport;");
     ((*jniEnv)->SetObjectField(jniEnv, self_, _f_org_apache_pdfbox_pdmodel_PDDocument_signingSupport, value));
 }
@@ -906,6 +1070,7 @@
 jobject get_org_apache_pdfbox_pdmodel_PDDocument_resourceCache(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (jobject)0;
     load_field(_c_org_apache_pdfbox_pdmodel_PDDocument, &_f_org_apache_pdfbox_pdmodel_PDDocument_resourceCache, "resourceCache","Lorg/apache/pdfbox/pdmodel/ResourceCache;");
     return to_global_ref((*jniEnv)->GetObjectField(jniEnv, self_, _f_org_apache_pdfbox_pdmodel_PDDocument_resourceCache));
 }
@@ -913,6 +1078,7 @@
 void set_org_apache_pdfbox_pdmodel_PDDocument_resourceCache(jobject self_, jobject value) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (void)0;
     load_field(_c_org_apache_pdfbox_pdmodel_PDDocument, &_f_org_apache_pdfbox_pdmodel_PDDocument_resourceCache, "resourceCache","Lorg/apache/pdfbox/pdmodel/ResourceCache;");
     ((*jniEnv)->SetObjectField(jniEnv, self_, _f_org_apache_pdfbox_pdmodel_PDDocument_resourceCache, value));
 }
@@ -922,6 +1088,7 @@
 uint8_t get_org_apache_pdfbox_pdmodel_PDDocument_signatureAdded(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (uint8_t)0;
     load_field(_c_org_apache_pdfbox_pdmodel_PDDocument, &_f_org_apache_pdfbox_pdmodel_PDDocument_signatureAdded, "signatureAdded","Z");
     return ((*jniEnv)->GetBooleanField(jniEnv, self_, _f_org_apache_pdfbox_pdmodel_PDDocument_signatureAdded));
 }
@@ -929,6 +1096,7 @@
 void set_org_apache_pdfbox_pdmodel_PDDocument_signatureAdded(jobject self_, uint8_t value) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocument == NULL) return (void)0;
     load_field(_c_org_apache_pdfbox_pdmodel_PDDocument, &_f_org_apache_pdfbox_pdmodel_PDDocument_signatureAdded, "signatureAdded","Z");
     ((*jniEnv)->SetBooleanField(jniEnv, self_, _f_org_apache_pdfbox_pdmodel_PDDocument_signatureAdded, value));
 }
@@ -942,7 +1110,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocumentInformation_ctor() {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocumentInformation == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, &_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_ctor, "<init>", "()V");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_ctor == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->NewObject(jniEnv, _c_org_apache_pdfbox_pdmodel_PDDocumentInformation, _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_ctor);
     return to_global_ref(_result);
 }
@@ -952,7 +1122,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocumentInformation_ctor1(jobject dic) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocumentInformation == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, &_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_ctor1, "<init>", "(Lorg/apache/pdfbox/cos/COSDictionary;)V");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_ctor1 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->NewObject(jniEnv, _c_org_apache_pdfbox_pdmodel_PDDocumentInformation, _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_ctor1, dic);
     return to_global_ref(_result);
 }
@@ -962,7 +1134,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocumentInformation_getCOSObject(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocumentInformation == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, &_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getCOSObject, "getCOSObject", "()Lorg/apache/pdfbox/cos/COSDictionary;");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getCOSObject == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getCOSObject);
     return to_global_ref(_result);
 }
@@ -972,7 +1146,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocumentInformation_getPropertyStringValue(jobject self_, jobject propertyKey) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocumentInformation == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, &_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getPropertyStringValue, "getPropertyStringValue", "(Ljava/lang/String;)Ljava/lang/Object;");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getPropertyStringValue == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getPropertyStringValue, propertyKey);
     return to_global_ref(_result);
 }
@@ -982,7 +1158,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocumentInformation_getTitle(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocumentInformation == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, &_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getTitle, "getTitle", "()Ljava/lang/String;");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getTitle == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getTitle);
     return to_global_ref(_result);
 }
@@ -992,7 +1170,9 @@
 void org_apache_pdfbox_pdmodel_PDDocumentInformation_setTitle(jobject self_, jobject title) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocumentInformation == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, &_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setTitle, "setTitle", "(Ljava/lang/String;)V");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setTitle == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setTitle, title);
 }
 
@@ -1001,7 +1181,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocumentInformation_getAuthor(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocumentInformation == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, &_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getAuthor, "getAuthor", "()Ljava/lang/String;");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getAuthor == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getAuthor);
     return to_global_ref(_result);
 }
@@ -1011,7 +1193,9 @@
 void org_apache_pdfbox_pdmodel_PDDocumentInformation_setAuthor(jobject self_, jobject author) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocumentInformation == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, &_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setAuthor, "setAuthor", "(Ljava/lang/String;)V");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setAuthor == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setAuthor, author);
 }
 
@@ -1020,7 +1204,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocumentInformation_getSubject(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocumentInformation == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, &_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getSubject, "getSubject", "()Ljava/lang/String;");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getSubject == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getSubject);
     return to_global_ref(_result);
 }
@@ -1030,7 +1216,9 @@
 void org_apache_pdfbox_pdmodel_PDDocumentInformation_setSubject(jobject self_, jobject subject) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocumentInformation == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, &_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setSubject, "setSubject", "(Ljava/lang/String;)V");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setSubject == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setSubject, subject);
 }
 
@@ -1039,7 +1227,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocumentInformation_getKeywords(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocumentInformation == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, &_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getKeywords, "getKeywords", "()Ljava/lang/String;");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getKeywords == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getKeywords);
     return to_global_ref(_result);
 }
@@ -1049,7 +1239,9 @@
 void org_apache_pdfbox_pdmodel_PDDocumentInformation_setKeywords(jobject self_, jobject keywords) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocumentInformation == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, &_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setKeywords, "setKeywords", "(Ljava/lang/String;)V");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setKeywords == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setKeywords, keywords);
 }
 
@@ -1058,7 +1250,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocumentInformation_getCreator(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocumentInformation == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, &_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getCreator, "getCreator", "()Ljava/lang/String;");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getCreator == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getCreator);
     return to_global_ref(_result);
 }
@@ -1068,7 +1262,9 @@
 void org_apache_pdfbox_pdmodel_PDDocumentInformation_setCreator(jobject self_, jobject creator) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocumentInformation == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, &_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setCreator, "setCreator", "(Ljava/lang/String;)V");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setCreator == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setCreator, creator);
 }
 
@@ -1077,7 +1273,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocumentInformation_getProducer(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocumentInformation == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, &_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getProducer, "getProducer", "()Ljava/lang/String;");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getProducer == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getProducer);
     return to_global_ref(_result);
 }
@@ -1087,7 +1285,9 @@
 void org_apache_pdfbox_pdmodel_PDDocumentInformation_setProducer(jobject self_, jobject producer) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocumentInformation == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, &_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setProducer, "setProducer", "(Ljava/lang/String;)V");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setProducer == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setProducer, producer);
 }
 
@@ -1096,7 +1296,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocumentInformation_getCreationDate(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocumentInformation == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, &_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getCreationDate, "getCreationDate", "()Ljava/util/Calendar;");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getCreationDate == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getCreationDate);
     return to_global_ref(_result);
 }
@@ -1106,7 +1308,9 @@
 void org_apache_pdfbox_pdmodel_PDDocumentInformation_setCreationDate(jobject self_, jobject date) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocumentInformation == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, &_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setCreationDate, "setCreationDate", "(Ljava/util/Calendar;)V");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setCreationDate == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setCreationDate, date);
 }
 
@@ -1115,7 +1319,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocumentInformation_getModificationDate(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocumentInformation == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, &_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getModificationDate, "getModificationDate", "()Ljava/util/Calendar;");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getModificationDate == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getModificationDate);
     return to_global_ref(_result);
 }
@@ -1125,7 +1331,9 @@
 void org_apache_pdfbox_pdmodel_PDDocumentInformation_setModificationDate(jobject self_, jobject date) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocumentInformation == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, &_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setModificationDate, "setModificationDate", "(Ljava/util/Calendar;)V");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setModificationDate == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setModificationDate, date);
 }
 
@@ -1134,7 +1342,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocumentInformation_getTrapped(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocumentInformation == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, &_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getTrapped, "getTrapped", "()Ljava/lang/String;");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getTrapped == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getTrapped);
     return to_global_ref(_result);
 }
@@ -1144,7 +1354,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocumentInformation_getMetadataKeys(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocumentInformation == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, &_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getMetadataKeys, "getMetadataKeys", "()Ljava/util/Set;");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getMetadataKeys == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getMetadataKeys);
     return to_global_ref(_result);
 }
@@ -1154,7 +1366,9 @@
 jobject org_apache_pdfbox_pdmodel_PDDocumentInformation_getCustomMetadataValue(jobject self_, jobject fieldName) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocumentInformation == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, &_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getCustomMetadataValue, "getCustomMetadataValue", "(Ljava/lang/String;)Ljava/lang/String;");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getCustomMetadataValue == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getCustomMetadataValue, fieldName);
     return to_global_ref(_result);
 }
@@ -1164,7 +1378,9 @@
 void org_apache_pdfbox_pdmodel_PDDocumentInformation_setCustomMetadataValue(jobject self_, jobject fieldName, jobject fieldValue) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocumentInformation == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, &_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setCustomMetadataValue, "setCustomMetadataValue", "(Ljava/lang/String;Ljava/lang/String;)V");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setCustomMetadataValue == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setCustomMetadataValue, fieldName, fieldValue);
 }
 
@@ -1173,7 +1389,9 @@
 void org_apache_pdfbox_pdmodel_PDDocumentInformation_setTrapped(jobject self_, jobject value) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocumentInformation == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, &_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setTrapped, "setTrapped", "(Ljava/lang/String;)V");
+    if (_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setTrapped == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setTrapped, value);
 }
 
@@ -1181,6 +1399,7 @@
 jobject get_org_apache_pdfbox_pdmodel_PDDocumentInformation_info(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+    if (_c_org_apache_pdfbox_pdmodel_PDDocumentInformation == NULL) return (jobject)0;
     load_field(_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, &_f_org_apache_pdfbox_pdmodel_PDDocumentInformation_info, "info","Lorg/apache/pdfbox/cos/COSDictionary;");
     return to_global_ref((*jniEnv)->GetObjectField(jniEnv, self_, _f_org_apache_pdfbox_pdmodel_PDDocumentInformation_info));
 }
@@ -1194,7 +1413,9 @@
 jobject org_apache_pdfbox_text_PDFTextStripper_ctor() {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_ctor, "<init>", "()V");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_ctor == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->NewObject(jniEnv, _c_org_apache_pdfbox_text_PDFTextStripper, _m_org_apache_pdfbox_text_PDFTextStripper_ctor);
     return to_global_ref(_result);
 }
@@ -1204,7 +1425,9 @@
 jobject org_apache_pdfbox_text_PDFTextStripper_getText(jobject self_, jobject doc) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_getText, "getText", "(Lorg/apache/pdfbox/pdmodel/PDDocument;)Ljava/lang/String;");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_getText == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_getText, doc);
     return to_global_ref(_result);
 }
@@ -1214,7 +1437,9 @@
 void org_apache_pdfbox_text_PDFTextStripper_resetEngine(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_resetEngine, "resetEngine", "()V");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_resetEngine == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_resetEngine);
 }
 
@@ -1223,7 +1448,9 @@
 void org_apache_pdfbox_text_PDFTextStripper_writeText(jobject self_, jobject doc, jobject outputStream) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_writeText, "writeText", "(Lorg/apache/pdfbox/pdmodel/PDDocument;Ljava/io/Writer;)V");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_writeText == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_writeText, doc, outputStream);
 }
 
@@ -1232,7 +1459,9 @@
 void org_apache_pdfbox_text_PDFTextStripper_processPages(jobject self_, jobject pages) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_processPages, "processPages", "(Lorg/apache/pdfbox/pdmodel/PDPageTree;)V");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_processPages == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_processPages, pages);
 }
 
@@ -1241,7 +1470,9 @@
 void org_apache_pdfbox_text_PDFTextStripper_startDocument(jobject self_, jobject document) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_startDocument, "startDocument", "(Lorg/apache/pdfbox/pdmodel/PDDocument;)V");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_startDocument == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_startDocument, document);
 }
 
@@ -1250,7 +1481,9 @@
 void org_apache_pdfbox_text_PDFTextStripper_endDocument(jobject self_, jobject document) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_endDocument, "endDocument", "(Lorg/apache/pdfbox/pdmodel/PDDocument;)V");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_endDocument == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_endDocument, document);
 }
 
@@ -1259,7 +1492,9 @@
 void org_apache_pdfbox_text_PDFTextStripper_processPage(jobject self_, jobject page) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_processPage, "processPage", "(Lorg/apache/pdfbox/pdmodel/PDPage;)V");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_processPage == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_processPage, page);
 }
 
@@ -1268,7 +1503,9 @@
 void org_apache_pdfbox_text_PDFTextStripper_fillBeadRectangles(jobject self_, jobject page) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_fillBeadRectangles, "fillBeadRectangles", "(Lorg/apache/pdfbox/pdmodel/PDPage;)V");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_fillBeadRectangles == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_fillBeadRectangles, page);
 }
 
@@ -1277,7 +1514,9 @@
 void org_apache_pdfbox_text_PDFTextStripper_startArticle(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_startArticle, "startArticle", "()V");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_startArticle == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_startArticle);
 }
 
@@ -1286,7 +1525,9 @@
 void org_apache_pdfbox_text_PDFTextStripper_startArticle1(jobject self_, uint8_t isLTR) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_startArticle1, "startArticle", "(Z)V");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_startArticle1 == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_startArticle1, isLTR);
 }
 
@@ -1295,7 +1536,9 @@
 void org_apache_pdfbox_text_PDFTextStripper_endArticle(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_endArticle, "endArticle", "()V");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_endArticle == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_endArticle);
 }
 
@@ -1304,7 +1547,9 @@
 void org_apache_pdfbox_text_PDFTextStripper_startPage1(jobject self_, jobject page) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_startPage1, "startPage", "(Lorg/apache/pdfbox/pdmodel/PDPage;)V");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_startPage1 == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_startPage1, page);
 }
 
@@ -1313,7 +1558,9 @@
 void org_apache_pdfbox_text_PDFTextStripper_endPage1(jobject self_, jobject page) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_endPage1, "endPage", "(Lorg/apache/pdfbox/pdmodel/PDPage;)V");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_endPage1 == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_endPage1, page);
 }
 
@@ -1322,7 +1569,9 @@
 void org_apache_pdfbox_text_PDFTextStripper_writePage(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_writePage, "writePage", "()V");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_writePage == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_writePage);
 }
 
@@ -1331,7 +1580,9 @@
 uint8_t org_apache_pdfbox_text_PDFTextStripper_overlap(jobject self_, float y1, float height1, float y2, float height2) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (uint8_t)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_overlap, "overlap", "(FFFF)Z");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_overlap == NULL) return (uint8_t)0;
     uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_overlap, y1, height1, y2, height2);
     return _result;
 }
@@ -1341,7 +1592,9 @@
 void org_apache_pdfbox_text_PDFTextStripper_writeLineSeparator(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_writeLineSeparator, "writeLineSeparator", "()V");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_writeLineSeparator == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_writeLineSeparator);
 }
 
@@ -1350,7 +1603,9 @@
 void org_apache_pdfbox_text_PDFTextStripper_writeWordSeparator(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_writeWordSeparator, "writeWordSeparator", "()V");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_writeWordSeparator == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_writeWordSeparator);
 }
 
@@ -1359,7 +1614,9 @@
 void org_apache_pdfbox_text_PDFTextStripper_writeCharacters(jobject self_, jobject text) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_writeCharacters, "writeCharacters", "(Lorg/apache/pdfbox/text/TextPosition;)V");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_writeCharacters == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_writeCharacters, text);
 }
 
@@ -1368,7 +1625,9 @@
 void org_apache_pdfbox_text_PDFTextStripper_writeString(jobject self_, jobject text, jobject textPositions) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_writeString, "writeString", "(Ljava/lang/String;Ljava/util/List;)V");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_writeString == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_writeString, text, textPositions);
 }
 
@@ -1377,7 +1636,9 @@
 void org_apache_pdfbox_text_PDFTextStripper_writeString1(jobject self_, jobject text) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_writeString1, "writeString", "(Ljava/lang/String;)V");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_writeString1 == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_writeString1, text);
 }
 
@@ -1386,7 +1647,9 @@
 uint8_t org_apache_pdfbox_text_PDFTextStripper_within(jobject self_, float first, float second, float variance) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (uint8_t)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_within, "within", "(FFF)Z");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_within == NULL) return (uint8_t)0;
     uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_within, first, second, variance);
     return _result;
 }
@@ -1396,7 +1659,9 @@
 void org_apache_pdfbox_text_PDFTextStripper_processTextPosition(jobject self_, jobject text) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_processTextPosition, "processTextPosition", "(Lorg/apache/pdfbox/text/TextPosition;)V");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_processTextPosition == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_processTextPosition, text);
 }
 
@@ -1405,7 +1670,9 @@
 int32_t org_apache_pdfbox_text_PDFTextStripper_getStartPage(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (int32_t)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_getStartPage, "getStartPage", "()I");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_getStartPage == NULL) return (int32_t)0;
     int32_t _result = (*jniEnv)->CallIntMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_getStartPage);
     return _result;
 }
@@ -1415,7 +1682,9 @@
 void org_apache_pdfbox_text_PDFTextStripper_setStartPage(jobject self_, int32_t startPageValue) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_setStartPage, "setStartPage", "(I)V");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_setStartPage == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_setStartPage, startPageValue);
 }
 
@@ -1424,7 +1693,9 @@
 int32_t org_apache_pdfbox_text_PDFTextStripper_getEndPage(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (int32_t)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_getEndPage, "getEndPage", "()I");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_getEndPage == NULL) return (int32_t)0;
     int32_t _result = (*jniEnv)->CallIntMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_getEndPage);
     return _result;
 }
@@ -1434,7 +1705,9 @@
 void org_apache_pdfbox_text_PDFTextStripper_setEndPage(jobject self_, int32_t endPageValue) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_setEndPage, "setEndPage", "(I)V");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_setEndPage == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_setEndPage, endPageValue);
 }
 
@@ -1443,7 +1716,9 @@
 void org_apache_pdfbox_text_PDFTextStripper_setLineSeparator(jobject self_, jobject separator) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_setLineSeparator, "setLineSeparator", "(Ljava/lang/String;)V");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_setLineSeparator == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_setLineSeparator, separator);
 }
 
@@ -1452,7 +1727,9 @@
 jobject org_apache_pdfbox_text_PDFTextStripper_getLineSeparator(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_getLineSeparator, "getLineSeparator", "()Ljava/lang/String;");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_getLineSeparator == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_getLineSeparator);
     return to_global_ref(_result);
 }
@@ -1462,7 +1739,9 @@
 jobject org_apache_pdfbox_text_PDFTextStripper_getWordSeparator(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_getWordSeparator, "getWordSeparator", "()Ljava/lang/String;");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_getWordSeparator == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_getWordSeparator);
     return to_global_ref(_result);
 }
@@ -1472,7 +1751,9 @@
 void org_apache_pdfbox_text_PDFTextStripper_setWordSeparator(jobject self_, jobject separator) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_setWordSeparator, "setWordSeparator", "(Ljava/lang/String;)V");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_setWordSeparator == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_setWordSeparator, separator);
 }
 
@@ -1481,7 +1762,9 @@
 uint8_t org_apache_pdfbox_text_PDFTextStripper_getSuppressDuplicateOverlappingText(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (uint8_t)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_getSuppressDuplicateOverlappingText, "getSuppressDuplicateOverlappingText", "()Z");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_getSuppressDuplicateOverlappingText == NULL) return (uint8_t)0;
     uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_getSuppressDuplicateOverlappingText);
     return _result;
 }
@@ -1491,7 +1774,9 @@
 int32_t org_apache_pdfbox_text_PDFTextStripper_getCurrentPageNo(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (int32_t)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_getCurrentPageNo, "getCurrentPageNo", "()I");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_getCurrentPageNo == NULL) return (int32_t)0;
     int32_t _result = (*jniEnv)->CallIntMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_getCurrentPageNo);
     return _result;
 }
@@ -1501,7 +1786,9 @@
 jobject org_apache_pdfbox_text_PDFTextStripper_getOutput(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_getOutput, "getOutput", "()Ljava/io/Writer;");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_getOutput == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_getOutput);
     return to_global_ref(_result);
 }
@@ -1511,7 +1798,9 @@
 jobject org_apache_pdfbox_text_PDFTextStripper_getCharactersByArticle(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_getCharactersByArticle, "getCharactersByArticle", "()Ljava/util/List;");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_getCharactersByArticle == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_getCharactersByArticle);
     return to_global_ref(_result);
 }
@@ -1521,7 +1810,9 @@
 void org_apache_pdfbox_text_PDFTextStripper_setSuppressDuplicateOverlappingText(jobject self_, uint8_t suppressDuplicateOverlappingTextValue) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_setSuppressDuplicateOverlappingText, "setSuppressDuplicateOverlappingText", "(Z)V");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_setSuppressDuplicateOverlappingText == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_setSuppressDuplicateOverlappingText, suppressDuplicateOverlappingTextValue);
 }
 
@@ -1530,7 +1821,9 @@
 uint8_t org_apache_pdfbox_text_PDFTextStripper_getSeparateByBeads(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (uint8_t)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_getSeparateByBeads, "getSeparateByBeads", "()Z");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_getSeparateByBeads == NULL) return (uint8_t)0;
     uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_getSeparateByBeads);
     return _result;
 }
@@ -1540,7 +1833,9 @@
 void org_apache_pdfbox_text_PDFTextStripper_setShouldSeparateByBeads(jobject self_, uint8_t aShouldSeparateByBeads) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_setShouldSeparateByBeads, "setShouldSeparateByBeads", "(Z)V");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_setShouldSeparateByBeads == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_setShouldSeparateByBeads, aShouldSeparateByBeads);
 }
 
@@ -1549,7 +1844,9 @@
 jobject org_apache_pdfbox_text_PDFTextStripper_getEndBookmark(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_getEndBookmark, "getEndBookmark", "()Lorg/apache/pdfbox/pdmodel/interactive/documentnavigation/outline/PDOutlineItem;");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_getEndBookmark == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_getEndBookmark);
     return to_global_ref(_result);
 }
@@ -1559,7 +1856,9 @@
 void org_apache_pdfbox_text_PDFTextStripper_setEndBookmark(jobject self_, jobject aEndBookmark) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_setEndBookmark, "setEndBookmark", "(Lorg/apache/pdfbox/pdmodel/interactive/documentnavigation/outline/PDOutlineItem;)V");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_setEndBookmark == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_setEndBookmark, aEndBookmark);
 }
 
@@ -1568,7 +1867,9 @@
 jobject org_apache_pdfbox_text_PDFTextStripper_getStartBookmark(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_getStartBookmark, "getStartBookmark", "()Lorg/apache/pdfbox/pdmodel/interactive/documentnavigation/outline/PDOutlineItem;");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_getStartBookmark == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_getStartBookmark);
     return to_global_ref(_result);
 }
@@ -1578,7 +1879,9 @@
 void org_apache_pdfbox_text_PDFTextStripper_setStartBookmark(jobject self_, jobject aStartBookmark) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_setStartBookmark, "setStartBookmark", "(Lorg/apache/pdfbox/pdmodel/interactive/documentnavigation/outline/PDOutlineItem;)V");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_setStartBookmark == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_setStartBookmark, aStartBookmark);
 }
 
@@ -1587,7 +1890,9 @@
 uint8_t org_apache_pdfbox_text_PDFTextStripper_getAddMoreFormatting(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (uint8_t)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_getAddMoreFormatting, "getAddMoreFormatting", "()Z");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_getAddMoreFormatting == NULL) return (uint8_t)0;
     uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_getAddMoreFormatting);
     return _result;
 }
@@ -1597,7 +1902,9 @@
 void org_apache_pdfbox_text_PDFTextStripper_setAddMoreFormatting(jobject self_, uint8_t newAddMoreFormatting) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_setAddMoreFormatting, "setAddMoreFormatting", "(Z)V");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_setAddMoreFormatting == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_setAddMoreFormatting, newAddMoreFormatting);
 }
 
@@ -1606,7 +1913,9 @@
 uint8_t org_apache_pdfbox_text_PDFTextStripper_getSortByPosition(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (uint8_t)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_getSortByPosition, "getSortByPosition", "()Z");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_getSortByPosition == NULL) return (uint8_t)0;
     uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_getSortByPosition);
     return _result;
 }
@@ -1616,7 +1925,9 @@
 void org_apache_pdfbox_text_PDFTextStripper_setSortByPosition(jobject self_, uint8_t newSortByPosition) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_setSortByPosition, "setSortByPosition", "(Z)V");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_setSortByPosition == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_setSortByPosition, newSortByPosition);
 }
 
@@ -1625,7 +1936,9 @@
 float org_apache_pdfbox_text_PDFTextStripper_getSpacingTolerance(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (float)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_getSpacingTolerance, "getSpacingTolerance", "()F");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_getSpacingTolerance == NULL) return (float)0;
     float _result = (*jniEnv)->CallFloatMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_getSpacingTolerance);
     return _result;
 }
@@ -1635,7 +1948,9 @@
 void org_apache_pdfbox_text_PDFTextStripper_setSpacingTolerance(jobject self_, float spacingToleranceValue) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_setSpacingTolerance, "setSpacingTolerance", "(F)V");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_setSpacingTolerance == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_setSpacingTolerance, spacingToleranceValue);
 }
 
@@ -1644,7 +1959,9 @@
 float org_apache_pdfbox_text_PDFTextStripper_getAverageCharTolerance(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (float)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_getAverageCharTolerance, "getAverageCharTolerance", "()F");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_getAverageCharTolerance == NULL) return (float)0;
     float _result = (*jniEnv)->CallFloatMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_getAverageCharTolerance);
     return _result;
 }
@@ -1654,7 +1971,9 @@
 void org_apache_pdfbox_text_PDFTextStripper_setAverageCharTolerance(jobject self_, float averageCharToleranceValue) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_setAverageCharTolerance, "setAverageCharTolerance", "(F)V");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_setAverageCharTolerance == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_setAverageCharTolerance, averageCharToleranceValue);
 }
 
@@ -1663,7 +1982,9 @@
 float org_apache_pdfbox_text_PDFTextStripper_getIndentThreshold(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (float)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_getIndentThreshold, "getIndentThreshold", "()F");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_getIndentThreshold == NULL) return (float)0;
     float _result = (*jniEnv)->CallFloatMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_getIndentThreshold);
     return _result;
 }
@@ -1673,7 +1994,9 @@
 void org_apache_pdfbox_text_PDFTextStripper_setIndentThreshold(jobject self_, float indentThresholdValue) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_setIndentThreshold, "setIndentThreshold", "(F)V");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_setIndentThreshold == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_setIndentThreshold, indentThresholdValue);
 }
 
@@ -1682,7 +2005,9 @@
 float org_apache_pdfbox_text_PDFTextStripper_getDropThreshold(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (float)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_getDropThreshold, "getDropThreshold", "()F");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_getDropThreshold == NULL) return (float)0;
     float _result = (*jniEnv)->CallFloatMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_getDropThreshold);
     return _result;
 }
@@ -1692,7 +2017,9 @@
 void org_apache_pdfbox_text_PDFTextStripper_setDropThreshold(jobject self_, float dropThresholdValue) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_setDropThreshold, "setDropThreshold", "(F)V");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_setDropThreshold == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_setDropThreshold, dropThresholdValue);
 }
 
@@ -1701,7 +2028,9 @@
 jobject org_apache_pdfbox_text_PDFTextStripper_getParagraphStart(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_getParagraphStart, "getParagraphStart", "()Ljava/lang/String;");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_getParagraphStart == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_getParagraphStart);
     return to_global_ref(_result);
 }
@@ -1711,7 +2040,9 @@
 void org_apache_pdfbox_text_PDFTextStripper_setParagraphStart(jobject self_, jobject s) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_setParagraphStart, "setParagraphStart", "(Ljava/lang/String;)V");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_setParagraphStart == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_setParagraphStart, s);
 }
 
@@ -1720,7 +2051,9 @@
 jobject org_apache_pdfbox_text_PDFTextStripper_getParagraphEnd(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_getParagraphEnd, "getParagraphEnd", "()Ljava/lang/String;");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_getParagraphEnd == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_getParagraphEnd);
     return to_global_ref(_result);
 }
@@ -1730,7 +2063,9 @@
 void org_apache_pdfbox_text_PDFTextStripper_setParagraphEnd(jobject self_, jobject s) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_setParagraphEnd, "setParagraphEnd", "(Ljava/lang/String;)V");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_setParagraphEnd == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_setParagraphEnd, s);
 }
 
@@ -1739,7 +2074,9 @@
 jobject org_apache_pdfbox_text_PDFTextStripper_getPageStart(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_getPageStart, "getPageStart", "()Ljava/lang/String;");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_getPageStart == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_getPageStart);
     return to_global_ref(_result);
 }
@@ -1749,7 +2086,9 @@
 void org_apache_pdfbox_text_PDFTextStripper_setPageStart(jobject self_, jobject pageStartValue) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_setPageStart, "setPageStart", "(Ljava/lang/String;)V");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_setPageStart == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_setPageStart, pageStartValue);
 }
 
@@ -1758,7 +2097,9 @@
 jobject org_apache_pdfbox_text_PDFTextStripper_getPageEnd(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_getPageEnd, "getPageEnd", "()Ljava/lang/String;");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_getPageEnd == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_getPageEnd);
     return to_global_ref(_result);
 }
@@ -1768,7 +2109,9 @@
 void org_apache_pdfbox_text_PDFTextStripper_setPageEnd(jobject self_, jobject pageEndValue) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_setPageEnd, "setPageEnd", "(Ljava/lang/String;)V");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_setPageEnd == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_setPageEnd, pageEndValue);
 }
 
@@ -1777,7 +2120,9 @@
 jobject org_apache_pdfbox_text_PDFTextStripper_getArticleStart(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_getArticleStart, "getArticleStart", "()Ljava/lang/String;");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_getArticleStart == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_getArticleStart);
     return to_global_ref(_result);
 }
@@ -1787,7 +2132,9 @@
 void org_apache_pdfbox_text_PDFTextStripper_setArticleStart(jobject self_, jobject articleStartValue) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_setArticleStart, "setArticleStart", "(Ljava/lang/String;)V");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_setArticleStart == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_setArticleStart, articleStartValue);
 }
 
@@ -1796,7 +2143,9 @@
 jobject org_apache_pdfbox_text_PDFTextStripper_getArticleEnd(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_getArticleEnd, "getArticleEnd", "()Ljava/lang/String;");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_getArticleEnd == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_getArticleEnd);
     return to_global_ref(_result);
 }
@@ -1806,7 +2155,9 @@
 void org_apache_pdfbox_text_PDFTextStripper_setArticleEnd(jobject self_, jobject articleEndValue) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_setArticleEnd, "setArticleEnd", "(Ljava/lang/String;)V");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_setArticleEnd == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_setArticleEnd, articleEndValue);
 }
 
@@ -1815,7 +2166,9 @@
 jobject org_apache_pdfbox_text_PDFTextStripper_handleLineSeparation(jobject self_, jobject current, jobject lastPosition, jobject lastLineStartPosition, float maxHeightForLine) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_handleLineSeparation, "handleLineSeparation", "(Lorg/apache/pdfbox/text/PDFTextStripper$PositionWrapper;Lorg/apache/pdfbox/text/PDFTextStripper$PositionWrapper;Lorg/apache/pdfbox/text/PDFTextStripper$PositionWrapper;F)Lorg/apache/pdfbox/text/PDFTextStripper$PositionWrapper;");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_handleLineSeparation == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_handleLineSeparation, current, lastPosition, lastLineStartPosition, maxHeightForLine);
     return to_global_ref(_result);
 }
@@ -1825,7 +2178,9 @@
 void org_apache_pdfbox_text_PDFTextStripper_isParagraphSeparation(jobject self_, jobject position, jobject lastPosition, jobject lastLineStartPosition, float maxHeightForLine) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_isParagraphSeparation, "isParagraphSeparation", "(Lorg/apache/pdfbox/text/PDFTextStripper$PositionWrapper;Lorg/apache/pdfbox/text/PDFTextStripper$PositionWrapper;Lorg/apache/pdfbox/text/PDFTextStripper$PositionWrapper;F)V");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_isParagraphSeparation == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_isParagraphSeparation, position, lastPosition, lastLineStartPosition, maxHeightForLine);
 }
 
@@ -1834,7 +2189,9 @@
 float org_apache_pdfbox_text_PDFTextStripper_multiplyFloat(jobject self_, float value1, float value2) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (float)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_multiplyFloat, "multiplyFloat", "(FF)F");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_multiplyFloat == NULL) return (float)0;
     float _result = (*jniEnv)->CallFloatMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_multiplyFloat, value1, value2);
     return _result;
 }
@@ -1844,7 +2201,9 @@
 void org_apache_pdfbox_text_PDFTextStripper_writeParagraphSeparator(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_writeParagraphSeparator, "writeParagraphSeparator", "()V");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_writeParagraphSeparator == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_writeParagraphSeparator);
 }
 
@@ -1853,7 +2212,9 @@
 void org_apache_pdfbox_text_PDFTextStripper_writeParagraphStart(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_writeParagraphStart, "writeParagraphStart", "()V");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_writeParagraphStart == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_writeParagraphStart);
 }
 
@@ -1862,7 +2223,9 @@
 void org_apache_pdfbox_text_PDFTextStripper_writeParagraphEnd(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_writeParagraphEnd, "writeParagraphEnd", "()V");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_writeParagraphEnd == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_writeParagraphEnd);
 }
 
@@ -1871,7 +2234,9 @@
 void org_apache_pdfbox_text_PDFTextStripper_writePageStart(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_writePageStart, "writePageStart", "()V");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_writePageStart == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_writePageStart);
 }
 
@@ -1880,7 +2245,9 @@
 void org_apache_pdfbox_text_PDFTextStripper_writePageEnd(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_writePageEnd, "writePageEnd", "()V");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_writePageEnd == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_writePageEnd);
 }
 
@@ -1889,7 +2256,9 @@
 jobject org_apache_pdfbox_text_PDFTextStripper_matchListItemPattern(jobject self_, jobject pw) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_matchListItemPattern, "matchListItemPattern", "(Lorg/apache/pdfbox/text/PDFTextStripper$PositionWrapper;)Ljava/util/regex/Pattern;");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_matchListItemPattern == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_matchListItemPattern, pw);
     return to_global_ref(_result);
 }
@@ -1899,7 +2268,9 @@
 void org_apache_pdfbox_text_PDFTextStripper_setListItemPatterns(jobject self_, jobject patterns) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_setListItemPatterns, "setListItemPatterns", "(Ljava/util/List;)V");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_setListItemPatterns == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_setListItemPatterns, patterns);
 }
 
@@ -1908,7 +2279,9 @@
 jobject org_apache_pdfbox_text_PDFTextStripper_getListItemPatterns(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_getListItemPatterns, "getListItemPatterns", "()Ljava/util/List;");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_getListItemPatterns == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_getListItemPatterns);
     return to_global_ref(_result);
 }
@@ -1918,7 +2291,9 @@
 jobject org_apache_pdfbox_text_PDFTextStripper_matchPattern(jobject string, jobject patterns) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (jobject)0;
     load_static_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_matchPattern, "matchPattern", "(Ljava/lang/String;Ljava/util/List;)Ljava/util/regex/Pattern;");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_matchPattern == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallStaticObjectMethod(jniEnv, _c_org_apache_pdfbox_text_PDFTextStripper, _m_org_apache_pdfbox_text_PDFTextStripper_matchPattern, string, patterns);
     return to_global_ref(_result);
 }
@@ -1928,7 +2303,9 @@
 void org_apache_pdfbox_text_PDFTextStripper_writeLine(jobject self_, jobject line) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_writeLine, "writeLine", "(Ljava/util/List;)V");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_writeLine == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_writeLine, line);
 }
 
@@ -1937,7 +2314,9 @@
 jobject org_apache_pdfbox_text_PDFTextStripper_normalize(jobject self_, jobject line) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_normalize, "normalize", "(Ljava/util/List;)Ljava/util/List;");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_normalize == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_normalize, line);
     return to_global_ref(_result);
 }
@@ -1947,7 +2326,9 @@
 jobject org_apache_pdfbox_text_PDFTextStripper_handleDirection(jobject self_, jobject word) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_handleDirection, "handleDirection", "(Ljava/lang/String;)Ljava/lang/String;");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_handleDirection == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_handleDirection, word);
     return to_global_ref(_result);
 }
@@ -1957,7 +2338,9 @@
 void org_apache_pdfbox_text_PDFTextStripper_parseBidiFile(jobject inputStream) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_static_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_parseBidiFile, "parseBidiFile", "(Ljava/io/InputStream;)V");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_parseBidiFile == NULL) return (void)0;
     (*jniEnv)->CallStaticVoidMethod(jniEnv, _c_org_apache_pdfbox_text_PDFTextStripper, _m_org_apache_pdfbox_text_PDFTextStripper_parseBidiFile, inputStream);
 }
 
@@ -1966,7 +2349,9 @@
 jobject org_apache_pdfbox_text_PDFTextStripper_createWord(jobject self_, jobject word, jobject wordPositions) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_createWord, "createWord", "(Ljava/lang/String;Ljava/util/List;)Lorg/apache/pdfbox/text/PDFTextStripper$WordWithTextPositions;");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_createWord == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_createWord, word, wordPositions);
     return to_global_ref(_result);
 }
@@ -1976,7 +2361,9 @@
 jobject org_apache_pdfbox_text_PDFTextStripper_normalizeWord(jobject self_, jobject word) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_normalizeWord, "normalizeWord", "(Ljava/lang/String;)Ljava/lang/String;");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_normalizeWord == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_normalizeWord, word);
     return to_global_ref(_result);
 }
@@ -1986,7 +2373,9 @@
 jobject org_apache_pdfbox_text_PDFTextStripper_normalizeAdd(jobject self_, jobject normalized, jobject lineBuilder, jobject wordPositions, jobject item) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (jobject)0;
     load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_normalizeAdd, "normalizeAdd", "(Ljava/util/List;Ljava/lang/StringBuilder;Ljava/util/List;Lorg/apache/pdfbox/text/PDFTextStripper$LineItem;)Ljava/lang/StringBuilder;");
+    if (_m_org_apache_pdfbox_text_PDFTextStripper_normalizeAdd == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_normalizeAdd, normalized, lineBuilder, wordPositions, item);
     return to_global_ref(_result);
 }
@@ -1995,6 +2384,7 @@
 float get_org_apache_pdfbox_text_PDFTextStripper_defaultIndentThreshold() {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (float)0;
     load_static_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_defaultIndentThreshold, "defaultIndentThreshold","F");
     return ((*jniEnv)->GetStaticFloatField(jniEnv, _c_org_apache_pdfbox_text_PDFTextStripper, _f_org_apache_pdfbox_text_PDFTextStripper_defaultIndentThreshold));
 }
@@ -2002,6 +2392,7 @@
 void set_org_apache_pdfbox_text_PDFTextStripper_defaultIndentThreshold(float value) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_static_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_defaultIndentThreshold, "defaultIndentThreshold","F");
     ((*jniEnv)->SetStaticFloatField(jniEnv, _c_org_apache_pdfbox_text_PDFTextStripper, _f_org_apache_pdfbox_text_PDFTextStripper_defaultIndentThreshold, value));
 }
@@ -2011,6 +2402,7 @@
 float get_org_apache_pdfbox_text_PDFTextStripper_defaultDropThreshold() {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (float)0;
     load_static_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_defaultDropThreshold, "defaultDropThreshold","F");
     return ((*jniEnv)->GetStaticFloatField(jniEnv, _c_org_apache_pdfbox_text_PDFTextStripper, _f_org_apache_pdfbox_text_PDFTextStripper_defaultDropThreshold));
 }
@@ -2018,6 +2410,7 @@
 void set_org_apache_pdfbox_text_PDFTextStripper_defaultDropThreshold(float value) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_static_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_defaultDropThreshold, "defaultDropThreshold","F");
     ((*jniEnv)->SetStaticFloatField(jniEnv, _c_org_apache_pdfbox_text_PDFTextStripper, _f_org_apache_pdfbox_text_PDFTextStripper_defaultDropThreshold, value));
 }
@@ -2027,6 +2420,7 @@
 jobject get_org_apache_pdfbox_text_PDFTextStripper_LOG() {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (jobject)0;
     load_static_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_LOG, "LOG","Lorg/apache/commons/logging/Log;");
     return to_global_ref((*jniEnv)->GetStaticObjectField(jniEnv, _c_org_apache_pdfbox_text_PDFTextStripper, _f_org_apache_pdfbox_text_PDFTextStripper_LOG));
 }
@@ -2036,6 +2430,7 @@
 jobject get_org_apache_pdfbox_text_PDFTextStripper_LINE_SEPARATOR(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (jobject)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_LINE_SEPARATOR, "LINE_SEPARATOR","Ljava/lang/String;");
     return to_global_ref((*jniEnv)->GetObjectField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_LINE_SEPARATOR));
 }
@@ -2045,6 +2440,7 @@
 jobject get_org_apache_pdfbox_text_PDFTextStripper_lineSeparator(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (jobject)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_lineSeparator, "lineSeparator","Ljava/lang/String;");
     return to_global_ref((*jniEnv)->GetObjectField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_lineSeparator));
 }
@@ -2052,6 +2448,7 @@
 void set_org_apache_pdfbox_text_PDFTextStripper_lineSeparator(jobject self_, jobject value) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_lineSeparator, "lineSeparator","Ljava/lang/String;");
     ((*jniEnv)->SetObjectField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_lineSeparator, value));
 }
@@ -2061,6 +2458,7 @@
 jobject get_org_apache_pdfbox_text_PDFTextStripper_wordSeparator(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (jobject)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_wordSeparator, "wordSeparator","Ljava/lang/String;");
     return to_global_ref((*jniEnv)->GetObjectField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_wordSeparator));
 }
@@ -2068,6 +2466,7 @@
 void set_org_apache_pdfbox_text_PDFTextStripper_wordSeparator(jobject self_, jobject value) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_wordSeparator, "wordSeparator","Ljava/lang/String;");
     ((*jniEnv)->SetObjectField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_wordSeparator, value));
 }
@@ -2077,6 +2476,7 @@
 jobject get_org_apache_pdfbox_text_PDFTextStripper_paragraphStart(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (jobject)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_paragraphStart, "paragraphStart","Ljava/lang/String;");
     return to_global_ref((*jniEnv)->GetObjectField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_paragraphStart));
 }
@@ -2084,6 +2484,7 @@
 void set_org_apache_pdfbox_text_PDFTextStripper_paragraphStart(jobject self_, jobject value) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_paragraphStart, "paragraphStart","Ljava/lang/String;");
     ((*jniEnv)->SetObjectField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_paragraphStart, value));
 }
@@ -2093,6 +2494,7 @@
 jobject get_org_apache_pdfbox_text_PDFTextStripper_paragraphEnd(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (jobject)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_paragraphEnd, "paragraphEnd","Ljava/lang/String;");
     return to_global_ref((*jniEnv)->GetObjectField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_paragraphEnd));
 }
@@ -2100,6 +2502,7 @@
 void set_org_apache_pdfbox_text_PDFTextStripper_paragraphEnd(jobject self_, jobject value) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_paragraphEnd, "paragraphEnd","Ljava/lang/String;");
     ((*jniEnv)->SetObjectField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_paragraphEnd, value));
 }
@@ -2109,6 +2512,7 @@
 jobject get_org_apache_pdfbox_text_PDFTextStripper_pageStart(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (jobject)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_pageStart, "pageStart","Ljava/lang/String;");
     return to_global_ref((*jniEnv)->GetObjectField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_pageStart));
 }
@@ -2116,6 +2520,7 @@
 void set_org_apache_pdfbox_text_PDFTextStripper_pageStart(jobject self_, jobject value) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_pageStart, "pageStart","Ljava/lang/String;");
     ((*jniEnv)->SetObjectField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_pageStart, value));
 }
@@ -2125,6 +2530,7 @@
 jobject get_org_apache_pdfbox_text_PDFTextStripper_pageEnd(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (jobject)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_pageEnd, "pageEnd","Ljava/lang/String;");
     return to_global_ref((*jniEnv)->GetObjectField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_pageEnd));
 }
@@ -2132,6 +2538,7 @@
 void set_org_apache_pdfbox_text_PDFTextStripper_pageEnd(jobject self_, jobject value) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_pageEnd, "pageEnd","Ljava/lang/String;");
     ((*jniEnv)->SetObjectField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_pageEnd, value));
 }
@@ -2141,6 +2548,7 @@
 jobject get_org_apache_pdfbox_text_PDFTextStripper_articleStart(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (jobject)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_articleStart, "articleStart","Ljava/lang/String;");
     return to_global_ref((*jniEnv)->GetObjectField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_articleStart));
 }
@@ -2148,6 +2556,7 @@
 void set_org_apache_pdfbox_text_PDFTextStripper_articleStart(jobject self_, jobject value) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_articleStart, "articleStart","Ljava/lang/String;");
     ((*jniEnv)->SetObjectField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_articleStart, value));
 }
@@ -2157,6 +2566,7 @@
 jobject get_org_apache_pdfbox_text_PDFTextStripper_articleEnd(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (jobject)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_articleEnd, "articleEnd","Ljava/lang/String;");
     return to_global_ref((*jniEnv)->GetObjectField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_articleEnd));
 }
@@ -2164,6 +2574,7 @@
 void set_org_apache_pdfbox_text_PDFTextStripper_articleEnd(jobject self_, jobject value) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_articleEnd, "articleEnd","Ljava/lang/String;");
     ((*jniEnv)->SetObjectField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_articleEnd, value));
 }
@@ -2173,6 +2584,7 @@
 int32_t get_org_apache_pdfbox_text_PDFTextStripper_currentPageNo(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (int32_t)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_currentPageNo, "currentPageNo","I");
     return ((*jniEnv)->GetIntField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_currentPageNo));
 }
@@ -2180,6 +2592,7 @@
 void set_org_apache_pdfbox_text_PDFTextStripper_currentPageNo(jobject self_, int32_t value) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_currentPageNo, "currentPageNo","I");
     ((*jniEnv)->SetIntField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_currentPageNo, value));
 }
@@ -2189,6 +2602,7 @@
 int32_t get_org_apache_pdfbox_text_PDFTextStripper_startPage(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (int32_t)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_startPage, "startPage","I");
     return ((*jniEnv)->GetIntField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_startPage));
 }
@@ -2196,6 +2610,7 @@
 void set_org_apache_pdfbox_text_PDFTextStripper_startPage(jobject self_, int32_t value) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_startPage, "startPage","I");
     ((*jniEnv)->SetIntField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_startPage, value));
 }
@@ -2205,6 +2620,7 @@
 int32_t get_org_apache_pdfbox_text_PDFTextStripper_endPage(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (int32_t)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_endPage, "endPage","I");
     return ((*jniEnv)->GetIntField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_endPage));
 }
@@ -2212,6 +2628,7 @@
 void set_org_apache_pdfbox_text_PDFTextStripper_endPage(jobject self_, int32_t value) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_endPage, "endPage","I");
     ((*jniEnv)->SetIntField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_endPage, value));
 }
@@ -2221,6 +2638,7 @@
 jobject get_org_apache_pdfbox_text_PDFTextStripper_startBookmark(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (jobject)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_startBookmark, "startBookmark","Lorg/apache/pdfbox/pdmodel/interactive/documentnavigation/outline/PDOutlineItem;");
     return to_global_ref((*jniEnv)->GetObjectField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_startBookmark));
 }
@@ -2228,6 +2646,7 @@
 void set_org_apache_pdfbox_text_PDFTextStripper_startBookmark(jobject self_, jobject value) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_startBookmark, "startBookmark","Lorg/apache/pdfbox/pdmodel/interactive/documentnavigation/outline/PDOutlineItem;");
     ((*jniEnv)->SetObjectField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_startBookmark, value));
 }
@@ -2237,6 +2656,7 @@
 int32_t get_org_apache_pdfbox_text_PDFTextStripper_startBookmarkPageNumber(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (int32_t)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_startBookmarkPageNumber, "startBookmarkPageNumber","I");
     return ((*jniEnv)->GetIntField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_startBookmarkPageNumber));
 }
@@ -2244,6 +2664,7 @@
 void set_org_apache_pdfbox_text_PDFTextStripper_startBookmarkPageNumber(jobject self_, int32_t value) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_startBookmarkPageNumber, "startBookmarkPageNumber","I");
     ((*jniEnv)->SetIntField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_startBookmarkPageNumber, value));
 }
@@ -2253,6 +2674,7 @@
 int32_t get_org_apache_pdfbox_text_PDFTextStripper_endBookmarkPageNumber(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (int32_t)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_endBookmarkPageNumber, "endBookmarkPageNumber","I");
     return ((*jniEnv)->GetIntField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_endBookmarkPageNumber));
 }
@@ -2260,6 +2682,7 @@
 void set_org_apache_pdfbox_text_PDFTextStripper_endBookmarkPageNumber(jobject self_, int32_t value) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_endBookmarkPageNumber, "endBookmarkPageNumber","I");
     ((*jniEnv)->SetIntField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_endBookmarkPageNumber, value));
 }
@@ -2269,6 +2692,7 @@
 jobject get_org_apache_pdfbox_text_PDFTextStripper_endBookmark(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (jobject)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_endBookmark, "endBookmark","Lorg/apache/pdfbox/pdmodel/interactive/documentnavigation/outline/PDOutlineItem;");
     return to_global_ref((*jniEnv)->GetObjectField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_endBookmark));
 }
@@ -2276,6 +2700,7 @@
 void set_org_apache_pdfbox_text_PDFTextStripper_endBookmark(jobject self_, jobject value) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_endBookmark, "endBookmark","Lorg/apache/pdfbox/pdmodel/interactive/documentnavigation/outline/PDOutlineItem;");
     ((*jniEnv)->SetObjectField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_endBookmark, value));
 }
@@ -2285,6 +2710,7 @@
 uint8_t get_org_apache_pdfbox_text_PDFTextStripper_suppressDuplicateOverlappingText(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (uint8_t)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_suppressDuplicateOverlappingText, "suppressDuplicateOverlappingText","Z");
     return ((*jniEnv)->GetBooleanField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_suppressDuplicateOverlappingText));
 }
@@ -2292,6 +2718,7 @@
 void set_org_apache_pdfbox_text_PDFTextStripper_suppressDuplicateOverlappingText(jobject self_, uint8_t value) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_suppressDuplicateOverlappingText, "suppressDuplicateOverlappingText","Z");
     ((*jniEnv)->SetBooleanField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_suppressDuplicateOverlappingText, value));
 }
@@ -2301,6 +2728,7 @@
 uint8_t get_org_apache_pdfbox_text_PDFTextStripper_shouldSeparateByBeads(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (uint8_t)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_shouldSeparateByBeads, "shouldSeparateByBeads","Z");
     return ((*jniEnv)->GetBooleanField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_shouldSeparateByBeads));
 }
@@ -2308,6 +2736,7 @@
 void set_org_apache_pdfbox_text_PDFTextStripper_shouldSeparateByBeads(jobject self_, uint8_t value) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_shouldSeparateByBeads, "shouldSeparateByBeads","Z");
     ((*jniEnv)->SetBooleanField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_shouldSeparateByBeads, value));
 }
@@ -2317,6 +2746,7 @@
 uint8_t get_org_apache_pdfbox_text_PDFTextStripper_sortByPosition(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (uint8_t)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_sortByPosition, "sortByPosition","Z");
     return ((*jniEnv)->GetBooleanField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_sortByPosition));
 }
@@ -2324,6 +2754,7 @@
 void set_org_apache_pdfbox_text_PDFTextStripper_sortByPosition(jobject self_, uint8_t value) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_sortByPosition, "sortByPosition","Z");
     ((*jniEnv)->SetBooleanField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_sortByPosition, value));
 }
@@ -2333,6 +2764,7 @@
 uint8_t get_org_apache_pdfbox_text_PDFTextStripper_addMoreFormatting(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (uint8_t)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_addMoreFormatting, "addMoreFormatting","Z");
     return ((*jniEnv)->GetBooleanField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_addMoreFormatting));
 }
@@ -2340,6 +2772,7 @@
 void set_org_apache_pdfbox_text_PDFTextStripper_addMoreFormatting(jobject self_, uint8_t value) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_addMoreFormatting, "addMoreFormatting","Z");
     ((*jniEnv)->SetBooleanField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_addMoreFormatting, value));
 }
@@ -2349,6 +2782,7 @@
 float get_org_apache_pdfbox_text_PDFTextStripper_indentThreshold(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (float)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_indentThreshold, "indentThreshold","F");
     return ((*jniEnv)->GetFloatField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_indentThreshold));
 }
@@ -2356,6 +2790,7 @@
 void set_org_apache_pdfbox_text_PDFTextStripper_indentThreshold(jobject self_, float value) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_indentThreshold, "indentThreshold","F");
     ((*jniEnv)->SetFloatField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_indentThreshold, value));
 }
@@ -2365,6 +2800,7 @@
 float get_org_apache_pdfbox_text_PDFTextStripper_dropThreshold(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (float)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_dropThreshold, "dropThreshold","F");
     return ((*jniEnv)->GetFloatField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_dropThreshold));
 }
@@ -2372,6 +2808,7 @@
 void set_org_apache_pdfbox_text_PDFTextStripper_dropThreshold(jobject self_, float value) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_dropThreshold, "dropThreshold","F");
     ((*jniEnv)->SetFloatField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_dropThreshold, value));
 }
@@ -2381,6 +2818,7 @@
 float get_org_apache_pdfbox_text_PDFTextStripper_spacingTolerance(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (float)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_spacingTolerance, "spacingTolerance","F");
     return ((*jniEnv)->GetFloatField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_spacingTolerance));
 }
@@ -2388,6 +2826,7 @@
 void set_org_apache_pdfbox_text_PDFTextStripper_spacingTolerance(jobject self_, float value) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_spacingTolerance, "spacingTolerance","F");
     ((*jniEnv)->SetFloatField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_spacingTolerance, value));
 }
@@ -2397,6 +2836,7 @@
 float get_org_apache_pdfbox_text_PDFTextStripper_averageCharTolerance(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (float)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_averageCharTolerance, "averageCharTolerance","F");
     return ((*jniEnv)->GetFloatField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_averageCharTolerance));
 }
@@ -2404,6 +2844,7 @@
 void set_org_apache_pdfbox_text_PDFTextStripper_averageCharTolerance(jobject self_, float value) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_averageCharTolerance, "averageCharTolerance","F");
     ((*jniEnv)->SetFloatField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_averageCharTolerance, value));
 }
@@ -2413,6 +2854,7 @@
 jobject get_org_apache_pdfbox_text_PDFTextStripper_beadRectangles(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (jobject)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_beadRectangles, "beadRectangles","Ljava/util/List;");
     return to_global_ref((*jniEnv)->GetObjectField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_beadRectangles));
 }
@@ -2420,6 +2862,7 @@
 void set_org_apache_pdfbox_text_PDFTextStripper_beadRectangles(jobject self_, jobject value) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_beadRectangles, "beadRectangles","Ljava/util/List;");
     ((*jniEnv)->SetObjectField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_beadRectangles, value));
 }
@@ -2429,6 +2872,7 @@
 jobject get_org_apache_pdfbox_text_PDFTextStripper_charactersByArticle(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (jobject)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_charactersByArticle, "charactersByArticle","Ljava/util/ArrayList;");
     return to_global_ref((*jniEnv)->GetObjectField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_charactersByArticle));
 }
@@ -2436,6 +2880,7 @@
 void set_org_apache_pdfbox_text_PDFTextStripper_charactersByArticle(jobject self_, jobject value) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_charactersByArticle, "charactersByArticle","Ljava/util/ArrayList;");
     ((*jniEnv)->SetObjectField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_charactersByArticle, value));
 }
@@ -2445,6 +2890,7 @@
 jobject get_org_apache_pdfbox_text_PDFTextStripper_characterListMapping(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (jobject)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_characterListMapping, "characterListMapping","Ljava/util/Map;");
     return to_global_ref((*jniEnv)->GetObjectField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_characterListMapping));
 }
@@ -2452,6 +2898,7 @@
 void set_org_apache_pdfbox_text_PDFTextStripper_characterListMapping(jobject self_, jobject value) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_characterListMapping, "characterListMapping","Ljava/util/Map;");
     ((*jniEnv)->SetObjectField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_characterListMapping, value));
 }
@@ -2461,6 +2908,7 @@
 jobject get_org_apache_pdfbox_text_PDFTextStripper_document(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (jobject)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_document, "document","Lorg/apache/pdfbox/pdmodel/PDDocument;");
     return to_global_ref((*jniEnv)->GetObjectField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_document));
 }
@@ -2468,6 +2916,7 @@
 void set_org_apache_pdfbox_text_PDFTextStripper_document(jobject self_, jobject value) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_document, "document","Lorg/apache/pdfbox/pdmodel/PDDocument;");
     ((*jniEnv)->SetObjectField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_document, value));
 }
@@ -2477,6 +2926,7 @@
 jobject get_org_apache_pdfbox_text_PDFTextStripper_output(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (jobject)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_output, "output","Ljava/io/Writer;");
     return to_global_ref((*jniEnv)->GetObjectField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_output));
 }
@@ -2484,6 +2934,7 @@
 void set_org_apache_pdfbox_text_PDFTextStripper_output(jobject self_, jobject value) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_output, "output","Ljava/io/Writer;");
     ((*jniEnv)->SetObjectField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_output, value));
 }
@@ -2493,6 +2944,7 @@
 uint8_t get_org_apache_pdfbox_text_PDFTextStripper_inParagraph(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (uint8_t)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_inParagraph, "inParagraph","Z");
     return ((*jniEnv)->GetBooleanField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_inParagraph));
 }
@@ -2500,6 +2952,7 @@
 void set_org_apache_pdfbox_text_PDFTextStripper_inParagraph(jobject self_, uint8_t value) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_inParagraph, "inParagraph","Z");
     ((*jniEnv)->SetBooleanField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_inParagraph, value));
 }
@@ -2509,6 +2962,7 @@
 jobject get_org_apache_pdfbox_text_PDFTextStripper_LIST_ITEM_EXPRESSIONS() {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (jobject)0;
     load_static_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_LIST_ITEM_EXPRESSIONS, "LIST_ITEM_EXPRESSIONS","L[java/lang/String;");
     return to_global_ref((*jniEnv)->GetStaticObjectField(jniEnv, _c_org_apache_pdfbox_text_PDFTextStripper, _f_org_apache_pdfbox_text_PDFTextStripper_LIST_ITEM_EXPRESSIONS));
 }
@@ -2518,6 +2972,7 @@
 jobject get_org_apache_pdfbox_text_PDFTextStripper_listOfPatterns(jobject self_) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (jobject)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_listOfPatterns, "listOfPatterns","Ljava/util/List;");
     return to_global_ref((*jniEnv)->GetObjectField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_listOfPatterns));
 }
@@ -2525,6 +2980,7 @@
 void set_org_apache_pdfbox_text_PDFTextStripper_listOfPatterns(jobject self_, jobject value) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_listOfPatterns, "listOfPatterns","Ljava/util/List;");
     ((*jniEnv)->SetObjectField(jniEnv, self_, _f_org_apache_pdfbox_text_PDFTextStripper_listOfPatterns, value));
 }
@@ -2534,6 +2990,7 @@
 jobject get_org_apache_pdfbox_text_PDFTextStripper_MIRRORING_CHAR_MAP() {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (jobject)0;
     load_static_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_MIRRORING_CHAR_MAP, "MIRRORING_CHAR_MAP","Ljava/util/Map;");
     return to_global_ref((*jniEnv)->GetStaticObjectField(jniEnv, _c_org_apache_pdfbox_text_PDFTextStripper, _f_org_apache_pdfbox_text_PDFTextStripper_MIRRORING_CHAR_MAP));
 }
@@ -2541,6 +2998,7 @@
 void set_org_apache_pdfbox_text_PDFTextStripper_MIRRORING_CHAR_MAP(jobject value) {
     load_env();
     load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    if (_c_org_apache_pdfbox_text_PDFTextStripper == NULL) return (void)0;
     load_static_field(_c_org_apache_pdfbox_text_PDFTextStripper, &_f_org_apache_pdfbox_text_PDFTextStripper_MIRRORING_CHAR_MAP, "MIRRORING_CHAR_MAP","Ljava/util/Map;");
     ((*jniEnv)->SetStaticObjectField(jniEnv, _c_org_apache_pdfbox_text_PDFTextStripper, _f_org_apache_pdfbox_text_PDFTextStripper_MIRRORING_CHAR_MAP, value));
 }
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/tool/generate_bindings.dart b/pkgs/jnigen/example/pdfbox_plugin/tool/generate_bindings.dart
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/tool/generate_bindings.dart
rename to pkgs/jnigen/example/pdfbox_plugin/tool/generate_bindings.dart
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/windows/.gitignore b/pkgs/jnigen/example/pdfbox_plugin/windows/.gitignore
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/windows/.gitignore
rename to pkgs/jnigen/example/pdfbox_plugin/windows/.gitignore
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/windows/CMakeLists.txt b/pkgs/jnigen/example/pdfbox_plugin/windows/CMakeLists.txt
similarity index 100%
rename from pkgs/jnigen/examples/pdfbox_plugin/windows/CMakeLists.txt
rename to pkgs/jnigen/example/pdfbox_plugin/windows/CMakeLists.txt
diff --git a/pkgs/jnigen/examples/README.md b/pkgs/jnigen/examples/README.md
deleted file mode 100644
index 9b19c3a..0000000
--- a/pkgs/jnigen/examples/README.md
+++ /dev/null
@@ -1,11 +0,0 @@
-## jnigen examples
-
-This directory contains examples on how to use jnigen.
-
-| Directory | Description |
-| ------- | --------- |
-| [in_app_java](in_app_java/) | Demonstrates how to include custom Java code in Flutter application and call that using jnigen |
-| [pdfbox_plugin](pdfbox_plugin/) | Example of a flutter plugin which provides bindings to Apache PDFBox library. Currently works on Flutter desktop and Dart standalone on linux. |
-
-We intend to cover few more use cases in future.
-
diff --git a/pkgs/jnigen/examples/in_app_java/lib/android_utils/init.dart b/pkgs/jnigen/examples/in_app_java/lib/android_utils/init.dart
deleted file mode 100644
index 5642f98..0000000
--- a/pkgs/jnigen/examples/in_app_java/lib/android_utils/init.dart
+++ /dev/null
@@ -1,5 +0,0 @@
-import "dart:ffi";
-import "package:jni/jni.dart";
-
-final Pointer<T> Function<T extends NativeType>(String sym) jlookup =
-    Jni.getInstance().initGeneratedLibrary("android_utils");
diff --git a/pkgs/jnigen/examples/notification_plugin/lib/init.dart b/pkgs/jnigen/examples/notification_plugin/lib/init.dart
deleted file mode 100644
index 9a4243f..0000000
--- a/pkgs/jnigen/examples/notification_plugin/lib/init.dart
+++ /dev/null
@@ -1,5 +0,0 @@
-import "dart:ffi";
-import "package:jni/jni.dart";
-
-final Pointer<T> Function<T extends NativeType>(String sym) jlookup =
-    Jni.getInstance().initGeneratedLibrary("notification_plugin");
diff --git a/pkgs/jnigen/examples/notification_plugin/src/dartjni.h b/pkgs/jnigen/examples/notification_plugin/src/dartjni.h
deleted file mode 100644
index cd94b15..0000000
--- a/pkgs/jnigen/examples/notification_plugin/src/dartjni.h
+++ /dev/null
@@ -1,177 +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.
-
-#include <jni.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#if _WIN32
-#include <windows.h>
-#else
-#include <pthread.h>
-#include <unistd.h>
-#endif
-
-#if _WIN32
-#define FFI_PLUGIN_EXPORT __declspec(dllexport)
-#else
-#define FFI_PLUGIN_EXPORT
-#endif
-
-#if defined _WIN32
-#define thread_local __declspec(thread)
-#else
-#define thread_local __thread
-#endif
-
-#ifdef __ANDROID__
-#include <android/log.h>
-#endif
-
-#define JNI_LOG_TAG "Dart-JNI"
-
-#ifdef __ANDROID__
-#define __ENVP_CAST (JNIEnv **)
-#else
-#define __ENVP_CAST (void **)
-#endif
-
-struct jni_context {
-	JavaVM *jvm;
-	jobject classLoader;
-	jmethodID loadClassMethod;
-	jobject currentActivity;
-	jobject appContext;
-};
-
-extern thread_local JNIEnv *jniEnv;
-
-extern struct jni_context jni;
-
-enum DartJniLogLevel {
-	JNI_VERBOSE = 2,
-	JNI_DEBUG,
-	JNI_INFO,
-	JNI_WARN,
-	JNI_ERROR
-};
-
-FFI_PLUGIN_EXPORT struct jni_context GetJniContext();
-
-FFI_PLUGIN_EXPORT JavaVM *GetJavaVM(void);
-
-FFI_PLUGIN_EXPORT JNIEnv *GetJniEnv(void);
-
-FFI_PLUGIN_EXPORT JNIEnv *SpawnJvm(JavaVMInitArgs *args);
-
-FFI_PLUGIN_EXPORT jclass LoadClass(const char *name);
-
-FFI_PLUGIN_EXPORT jobject GetClassLoader(void);
-
-FFI_PLUGIN_EXPORT jobject GetApplicationContext(void);
-
-FFI_PLUGIN_EXPORT jobject GetCurrentActivity(void);
-
-FFI_PLUGIN_EXPORT void SetJNILogging(int level);
-
-FFI_PLUGIN_EXPORT jstring ToJavaString(char *str);
-
-FFI_PLUGIN_EXPORT const char *GetJavaStringChars(jstring jstr);
-
-FFI_PLUGIN_EXPORT void ReleaseJavaStringChars(jstring jstr, const char *buf);
-
-// These 2 are the function pointer variables defined and exported by
-// the generated C files.
-//
-// initGeneratedLibrary function in Jni class will set these to
-// corresponding functions to the implementations from `dartjni` base library
-// which initializes and manages the JNI.
-extern struct jni_context (*context_getter)(void);
-extern JNIEnv *(*env_getter)(void);
-
-// This function will be exported by generated code library and will set the
-// above 2 variables.
-FFI_PLUGIN_EXPORT void setJniGetters(struct jni_context (*cg)(void),
-		JNIEnv *(*eg)(void));
-
-// `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) {
-#ifdef __ANDROID__
-	jstring className = (*jniEnv)->NewStringUTF(jniEnv, name);
-	*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) {
-	if (*cls == NULL) {
-		__load_class_into(cls, name);
-	}
-}
-
-static inline void load_class_gr(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);
-	}
-}
-
-static inline void load_env() {
-	if (jniEnv == NULL) {
-		jni = context_getter();
-		jniEnv = env_getter();
-	}
-}
-
-static inline void load_method(jclass cls, jmethodID *res, const char *name,
-                               const char *sig) {
-	if (*res == NULL) {
-		*res = (*jniEnv)->GetMethodID(jniEnv, cls, name, sig);
-	}
-}
-
-static inline void load_static_method(jclass cls, jmethodID *res,
-                                      const char *name, const char *sig) {
-	if (*res == NULL) {
-		*res = (*jniEnv)->GetStaticMethodID(jniEnv, cls, name, sig);
-	}
-}
-
-static inline void load_field(jclass cls, jfieldID *res, const char *name,
-                              const char *sig) {
-	if (*res == NULL) {
-		*res = (*jniEnv)->GetFieldID(jniEnv, cls, name, sig);
-	}
-}
-
-static inline void load_static_field(jclass cls, jfieldID *res,
-                                     const char *name, const char *sig) {
-	if (*res == NULL) {
-		*res = (*jniEnv)->GetStaticFieldID(jniEnv, cls, name, sig);
-	}
-}
-
-static inline jobject to_global_ref(jobject ref) {
-	jobject g = (*jniEnv)->NewGlobalRef(jniEnv, ref);
-	(*jniEnv)->DeleteLocalRef(jniEnv, ref);
-	return g;
-}
-
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/lib/third_party/init.dart b/pkgs/jnigen/examples/pdfbox_plugin/lib/third_party/init.dart
deleted file mode 100644
index 4e88081..0000000
--- a/pkgs/jnigen/examples/pdfbox_plugin/lib/third_party/init.dart
+++ /dev/null
@@ -1,5 +0,0 @@
-import "dart:ffi";
-import "package:jni/jni.dart";
-
-final Pointer<T> Function<T extends NativeType>(String sym) jlookup =
-    Jni.getInstance().initGeneratedLibrary("pdfbox_plugin");
diff --git a/pkgs/jnigen/examples/pdfbox_plugin/src/third_party/dartjni.h b/pkgs/jnigen/examples/pdfbox_plugin/src/third_party/dartjni.h
deleted file mode 100644
index cd94b15..0000000
--- a/pkgs/jnigen/examples/pdfbox_plugin/src/third_party/dartjni.h
+++ /dev/null
@@ -1,177 +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.
-
-#include <jni.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#if _WIN32
-#include <windows.h>
-#else
-#include <pthread.h>
-#include <unistd.h>
-#endif
-
-#if _WIN32
-#define FFI_PLUGIN_EXPORT __declspec(dllexport)
-#else
-#define FFI_PLUGIN_EXPORT
-#endif
-
-#if defined _WIN32
-#define thread_local __declspec(thread)
-#else
-#define thread_local __thread
-#endif
-
-#ifdef __ANDROID__
-#include <android/log.h>
-#endif
-
-#define JNI_LOG_TAG "Dart-JNI"
-
-#ifdef __ANDROID__
-#define __ENVP_CAST (JNIEnv **)
-#else
-#define __ENVP_CAST (void **)
-#endif
-
-struct jni_context {
-	JavaVM *jvm;
-	jobject classLoader;
-	jmethodID loadClassMethod;
-	jobject currentActivity;
-	jobject appContext;
-};
-
-extern thread_local JNIEnv *jniEnv;
-
-extern struct jni_context jni;
-
-enum DartJniLogLevel {
-	JNI_VERBOSE = 2,
-	JNI_DEBUG,
-	JNI_INFO,
-	JNI_WARN,
-	JNI_ERROR
-};
-
-FFI_PLUGIN_EXPORT struct jni_context GetJniContext();
-
-FFI_PLUGIN_EXPORT JavaVM *GetJavaVM(void);
-
-FFI_PLUGIN_EXPORT JNIEnv *GetJniEnv(void);
-
-FFI_PLUGIN_EXPORT JNIEnv *SpawnJvm(JavaVMInitArgs *args);
-
-FFI_PLUGIN_EXPORT jclass LoadClass(const char *name);
-
-FFI_PLUGIN_EXPORT jobject GetClassLoader(void);
-
-FFI_PLUGIN_EXPORT jobject GetApplicationContext(void);
-
-FFI_PLUGIN_EXPORT jobject GetCurrentActivity(void);
-
-FFI_PLUGIN_EXPORT void SetJNILogging(int level);
-
-FFI_PLUGIN_EXPORT jstring ToJavaString(char *str);
-
-FFI_PLUGIN_EXPORT const char *GetJavaStringChars(jstring jstr);
-
-FFI_PLUGIN_EXPORT void ReleaseJavaStringChars(jstring jstr, const char *buf);
-
-// These 2 are the function pointer variables defined and exported by
-// the generated C files.
-//
-// initGeneratedLibrary function in Jni class will set these to
-// corresponding functions to the implementations from `dartjni` base library
-// which initializes and manages the JNI.
-extern struct jni_context (*context_getter)(void);
-extern JNIEnv *(*env_getter)(void);
-
-// This function will be exported by generated code library and will set the
-// above 2 variables.
-FFI_PLUGIN_EXPORT void setJniGetters(struct jni_context (*cg)(void),
-		JNIEnv *(*eg)(void));
-
-// `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) {
-#ifdef __ANDROID__
-	jstring className = (*jniEnv)->NewStringUTF(jniEnv, name);
-	*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) {
-	if (*cls == NULL) {
-		__load_class_into(cls, name);
-	}
-}
-
-static inline void load_class_gr(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);
-	}
-}
-
-static inline void load_env() {
-	if (jniEnv == NULL) {
-		jni = context_getter();
-		jniEnv = env_getter();
-	}
-}
-
-static inline void load_method(jclass cls, jmethodID *res, const char *name,
-                               const char *sig) {
-	if (*res == NULL) {
-		*res = (*jniEnv)->GetMethodID(jniEnv, cls, name, sig);
-	}
-}
-
-static inline void load_static_method(jclass cls, jmethodID *res,
-                                      const char *name, const char *sig) {
-	if (*res == NULL) {
-		*res = (*jniEnv)->GetStaticMethodID(jniEnv, cls, name, sig);
-	}
-}
-
-static inline void load_field(jclass cls, jfieldID *res, const char *name,
-                              const char *sig) {
-	if (*res == NULL) {
-		*res = (*jniEnv)->GetFieldID(jniEnv, cls, name, sig);
-	}
-}
-
-static inline void load_static_field(jclass cls, jfieldID *res,
-                                     const char *name, const char *sig) {
-	if (*res == NULL) {
-		*res = (*jniEnv)->GetStaticFieldID(jniEnv, cls, name, sig);
-	}
-}
-
-static inline jobject to_global_ref(jobject ref) {
-	jobject g = (*jniEnv)->NewGlobalRef(jniEnv, ref);
-	(*jniEnv)->DeleteLocalRef(jniEnv, ref);
-	return g;
-}
-
diff --git a/pkgs/jnigen/lib/src/bindings/c_bindings.dart b/pkgs/jnigen/lib/src/bindings/c_bindings.dart
index 14a2d2e..faadae3 100644
--- a/pkgs/jnigen/lib/src/bindings/c_bindings.dart
+++ b/pkgs/jnigen/lib/src/bindings/c_bindings.dart
@@ -87,12 +87,15 @@
     final classVar = '${_classVarPrefix}_$cClassName';
     final signature = _signature(m);
 
+    final ifError = '($cReturnType)0';
+
     s.write(_loadEnvCall);
-    s.write(_loadClassCall(classVar, _internalName(c.binaryName)));
+    s.write(_loadClassCall(classVar, _internalName(c.binaryName), ifError));
 
     final ifStatic = isStatic ? 'static_' : '';
     s.write('${_indent}load_${ifStatic}method($classVar, '
         '&$methodVar, "${m.name}", "$signature");\n');
+    s.write('${_indent}if ($methodVar == NULL) return $ifError;\n');
 
     s.write(_initParams(m));
 
@@ -152,7 +155,7 @@
       s.write(formalArgs.join(', '));
       s.write(') {\n');
       s.write(_loadEnvCall);
-      s.write(_loadClassCall(classVar, _internalName(c.binaryName)));
+      s.write(_loadClassCall(classVar, _internalName(c.binaryName), '($ct)0'));
 
       var ifStatic = isStatic ? 'static_' : '';
       s.write(
@@ -185,9 +188,10 @@
 
   final String _loadEnvCall = '${_indent}load_env();\n';
 
-  String _loadClassCall(String classVar, String internalName) {
+  String _loadClassCall(String classVar, String internalName, String ifError) {
     return '${_indent}load_class_gr(&$classVar, '
-        '"$internalName");\n';
+        '"$internalName");\n'
+        '${_indent}if ($classVar == NULL) return $ifError;\n';
   }
 
   String _formalArgs(Method m) {
@@ -345,12 +349,11 @@
       '#include "dartjni.h"\n'
       '\n';
   static const defines = 'thread_local JNIEnv *jniEnv;\n'
-      'struct jni_context jni;\n\n'
-      'struct jni_context (*context_getter)(void);\n'
+      'JniContext jni;\n\n'
+      'JniContext (*context_getter)(void);\n'
       'JNIEnv *(*env_getter)(void);\n'
       '\n';
-  static const initializers =
-      'void setJniGetters(struct jni_context (*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/common.dart b/pkgs/jnigen/lib/src/bindings/common.dart
index 5c93f54..69e19b1 100644
--- a/pkgs/jnigen/lib/src/bindings/common.dart
+++ b/pkgs/jnigen/lib/src/bindings/common.dart
@@ -36,6 +36,7 @@
 }
 
 bool isPrimitive(TypeUsage t) => t.kind == Kind.primitive;
+bool isVoid(TypeUsage t) => isPrimitive(t) && t.name == 'void';
 
 bool isStaticField(Field f) => f.modifiers.contains('static');
 bool isStaticMethod(Method m) => m.modifiers.contains('static');
diff --git a/pkgs/jnigen/lib/src/bindings/dart_bindings.dart b/pkgs/jnigen/lib/src/bindings/dart_bindings.dart
index 8367161..8495b17 100644
--- a/pkgs/jnigen/lib/src/bindings/dart_bindings.dart
+++ b/pkgs/jnigen/lib/src/bindings/dart_bindings.dart
@@ -16,7 +16,7 @@
   // Name for reference in base class.
   static const _self = 'reference';
   // symbol lookup function for generated code.
-  static const _jlookup = 'jlookup';
+  static const _jniLookup = 'jniLookup';
 
   // import prefixes
   static const ffi = 'ffi.';
@@ -26,7 +26,7 @@
 
   static const String _void = '${ffi}Void';
 
-  static const String _jlObject = '${jni}JlObject';
+  static const String _jniObject = '${jni}JniObject';
 
   DartBindingsGenerator(this.config, this.resolver);
   Config config;
@@ -52,11 +52,11 @@
     s.write(_breakDocComment(decl.javadoc, depth: ''));
     final name = _getSimpleName(decl.binaryName);
 
-    var superName = _jlObject;
+    var superName = _jniObject;
     if (decl.superclass != null) {
       superName = resolver
               .resolve((decl.superclass!.type as DeclaredType).binaryName) ??
-          _jlObject;
+          _jniObject;
     }
 
     s.write('class $name extends $superName {\n');
@@ -105,7 +105,7 @@
     final sym = '_$name';
     final ffiSig = dartSigForMethod(m, isFfiSig: true);
     final dartSig = dartSigForMethod(m, isFfiSig: false);
-    s.write('${_indent}static final $sym = $_jlookup'
+    s.write('${_indent}static final $sym = $_jniLookup'
         '<${ffi}NativeFunction<$ffiSig>>("$cName")\n'
         '.asFunction<$dartSig>();\n');
     // Different logic for constructor and method;
@@ -127,15 +127,17 @@
       final className = _getSimpleName(c.binaryName);
       final ctorFnName = name == 'ctor' ? className : '$className.$name';
       s.write('$ctorFnName(${_formalArgs(m)}) : '
-          'super.fromRef($wrapperExpr);\n');
+          'super.fromRef($wrapperExpr) { jni.Jni.env.checkException(); }\n');
       return s.toString();
     }
 
     var wrapperExpr = '$sym(${_actualArgs(m)})';
     wrapperExpr = _toDartResult(wrapperExpr, m.returnType, returnType);
-    s.write('$returnType $name(${_formalArgs(m)}) '
-        '=> $wrapperExpr;\n');
-
+    final depth = '$_indent$_indent';
+    s.write('$returnType $name(${_formalArgs(m)}) {');
+    s.write('${depth}final result__ = $wrapperExpr;');
+    s.write('${depth}jni.Jni.env.checkException();');
+    s.write('${depth}return result__;\n$_indent}');
     return s.toString();
   }
 
@@ -180,7 +182,7 @@
       final sym = '_${symPrefix}_$name';
       final ffiSig = dartSigForField(f, isSetter: isSetter, isFfiSig: true);
       final dartSig = dartSigForField(f, isSetter: isSetter, isFfiSig: false);
-      s.write('${_indent}static final $sym = $_jlookup'
+      s.write('${_indent}static final $sym = $_jniLookup'
           '<${ffi}NativeFunction<$ffiSig>>("${symPrefix}_$cName")\n'
           '.asFunction<$dartSig>();\n');
       // write original type
@@ -284,13 +286,13 @@
         throw SkipException('Not supported: generics');
       case Kind.array:
         if (resolver != null) {
-          return _jlObject;
+          return _jniObject;
         }
         return _voidPtr;
       case Kind.declared:
         if (resolver != null) {
           return resolver.resolve((t.type as DeclaredType).binaryName) ??
-              _jlObject;
+              _jniObject;
         }
         return _voidPtr;
     }
@@ -359,14 +361,14 @@
 
 class DartPreludes {
   static String initFile(String libraryName) => 'import "dart:ffi";\n'
-      'import "package:jni/jni.dart";\n'
+      'import "package:jni/internal_helpers_for_jnigen.dart";\n'
       '\n'
       'final Pointer<T> Function<T extends NativeType>(String sym) '
-      'jlookup = Jni.getInstance().initGeneratedLibrary("$libraryName");\n'
+      'jniLookup = ProtectedJniExtensions.initGeneratedLibrary("$libraryName");\n'
       '\n';
   static const autoGeneratedNotice = '// Autogenerated by jnigen. '
       'DO NOT EDIT!\n\n';
-  static const defaultImports = 'import "dart:ffi" as ffi;\n\n'
+  static const defaultImports = 'import "dart:ffi" as ffi;\n'
       'import "package:jni/jni.dart" as jni;\n\n';
   static const defaultLintSuppressions =
       '// ignore_for_file: camel_case_types\n'
diff --git a/pkgs/jnigen/lib/src/elements/elements.dart b/pkgs/jnigen/lib/src/elements/elements.dart
index 2673a4b..f7773fa 100644
--- a/pkgs/jnigen/lib/src/elements/elements.dart
+++ b/pkgs/jnigen/lib/src/elements/elements.dart
@@ -26,7 +26,7 @@
 
 @JsonSerializable(explicitToJson: true)
 class ClassDecl {
-  /// Methods & properties already defined by dart JlObject base class.
+  /// Methods & properties already defined by dart JniObject base class.
   static const Map<String, int> _definedSyms = {
     'equals': 1,
     'toString': 1,
@@ -34,7 +34,22 @@
     'runtimeType': 1,
     'noSuchMethod': 1,
     'reference': 1,
+    'isDeleted': 1,
+    'isNull': 1,
+    'use': 1,
     'delete': 1,
+    'getFieldID': 1,
+    'getStaticFieldID': 1,
+    'getMethodID': 1,
+    'getStaticMethodID': 1,
+    'getField': 1,
+    'getFieldByName': 1,
+    'getStaticField': 1,
+    'getStaticFieldByName': 1,
+    'callMethod': 1,
+    'callMethodByName': 1,
+    'callStaticMethod': 1,
+    'callStaticMethodByName': 1,
   };
 
   ClassDecl({
diff --git a/pkgs/jnigen/lib/src/writers/writers.dart b/pkgs/jnigen/lib/src/writers/writers.dart
index c4f3843..e762fee 100644
--- a/pkgs/jnigen/lib/src/writers/writers.dart
+++ b/pkgs/jnigen/lib/src/writers/writers.dart
@@ -36,7 +36,7 @@
 /// Example:
 /// `android.os` -> `$dartWrappersRoot`/`android/os.dart`
 class FilesWriter extends BindingsWriter {
-  static const _initFileName = 'init.dart';
+  static const _initFileName = '_init.dart';
 
   FilesWriter(this.config);
   Config config;
@@ -62,8 +62,11 @@
     log.info('Creating dart init file ...');
     final initFileUri = dartRoot.resolve(_initFileName);
     final initFile = await File.fromUri(initFileUri).create(recursive: true);
-    await initFile.writeAsString(DartPreludes.initFile(config.libraryName),
-        flush: true);
+    var initCode = DartPreludes.initFile(config.libraryName);
+    if (preamble != null) {
+      initCode = '$preamble\n$initCode';
+    }
+    await initFile.writeAsString(initCode, flush: true);
     final subdir = config.cSubdir ?? '.';
     final cFileRelativePath = '$subdir/$libraryName.c';
     final cFile = await File.fromUri(cRoot.resolve(cFileRelativePath))
@@ -81,7 +84,7 @@
       final dartFile = await File.fromUri(dartFileUri).create(recursive: true);
       final resolver = PackagePathResolver(
           config.importMap ?? const {}, packageName, classNames,
-          predefined: {'java.lang.String': 'jni.JlString'});
+          predefined: {'java.lang.String': 'jni.JniString'});
       final cgen = CBindingGenerator(config);
       final dgen = DartBindingsGenerator(config, resolver);
 
@@ -101,7 +104,7 @@
       dartFileStream
         ..write(DartPreludes.bindingFileHeaders)
         ..write(resolver.getImportStrings().join('\n'))
-        ..write('import "$initImportPath" show jlookup;\n\n');
+        ..write('import "$initImportPath" show jniLookup;\n\n');
       // write dart bindings only after all imports are figured out
       dartBindings.forEach(dartFileStream.write);
       cBindings.forEach(cFileStream.write);
diff --git a/pkgs/jnigen/pubspec.yaml b/pkgs/jnigen/pubspec.yaml
index fe8defa..3feb9e3 100644
--- a/pkgs/jnigen/pubspec.yaml
+++ b/pkgs/jnigen/pubspec.yaml
@@ -3,7 +3,7 @@
 # BSD-style license that can be found in the LICENSE file.
 
 name: jnigen
-version: 0.0.1
+version: 0.1.0
 homepage: https://github.com/dart-lang/jnigen
 description: Experimental generator for FFI+JNI bindings.
 
diff --git a/pkgs/jnigen/test/bindings_test.dart b/pkgs/jnigen/test/bindings_test.dart
index f8bab76..d2b5283 100644
--- a/pkgs/jnigen/test/bindings_test.dart
+++ b/pkgs/jnigen/test/bindings_test.dart
@@ -32,8 +32,13 @@
       'dart', ['run', 'jni:setup', '-S', join(simplePackagePath, 'src')]);
   await runCmd('dart',
       ['run', 'jni:setup', '-S', join(jacksonCorePath, 'third_party', 'src')]);
-  await runCmd('javac',
-      ['dev/dart/simple_package/Example.java', 'dev/dart/pkg2/C2.java'],
+  final group = join('com', 'github', 'dart_lang', 'jnigen');
+  await runCmd(
+      'javac',
+      [
+        join(group, 'simple_package', 'Example.java'),
+        join(group, 'pkg2', 'C2.java')
+      ],
       workingDirectory: simplePackageJavaPath);
   await runCmd('dart', [
     'run',
@@ -46,7 +51,7 @@
 
   if (!Platform.isAndroid) {
     Jni.spawn(
-        helperDir: 'build/jni_libs',
+        dylibDir: 'build/jni_libs',
         classPath: [simplePackageJavaPath, ...jacksonJars]);
   }
 }
@@ -81,20 +86,30 @@
     aux.delete();
     ex.delete();
   });
+  test('exceptions', () {
+    expect(() => Example.throwException(), throwsA(isA<JniException>()));
+  });
   test('simple json parsing test', () {
-    final json = JlString.fromString('[1, true, false, 2, 4]');
+    final json = JniString.fromString('[1, true, false, 2, 4]');
     final factory = JsonFactory();
     final parser = factory.createParser6(json);
     final values = <bool>[];
     while (!parser.isClosed()) {
       final next = parser.nextToken();
+      if (next.isNull) continue;
       values.add(next.isNumeric());
       next.delete();
     }
-    expect(
-        values, equals([false, true, false, false, true, true, false, false]));
-    parser.delete();
-    factory.delete();
-    json.delete();
+    expect(values, equals([false, true, false, false, true, true, false]));
+    Jni.deleteAll([factory, parser, json]);
+  });
+  test("parsing invalid JSON throws JniException", () {
+    using((arena) {
+      final factory = JsonFactory()..deletedIn(arena);
+      final erroneous = factory
+          .createParser6("<html>".jniString()..deletedIn(arena))
+        ..deletedIn(arena);
+      expect(() => erroneous.nextToken(), throwsA(isA<JniException>()));
+    });
   });
 }
diff --git a/pkgs/jnigen/test/jackson_core_test/third_party/lib/_init.dart b/pkgs/jnigen/test/jackson_core_test/third_party/lib/_init.dart
new file mode 100644
index 0000000..5c602fd
--- /dev/null
+++ b/pkgs/jnigen/test/jackson_core_test/third_party/lib/_init.dart
@@ -0,0 +1,22 @@
+// Generated from jackson-core which is licensed under the Apache License 2.0.
+// The following copyright from the original authors applies.
+// See https://github.com/FasterXML/jackson-core/blob/2.14/LICENSE
+//
+// Copyright (c) 2007 - The Jackson Project Authors
+// 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.
+
+import "dart:ffi";
+import "package:jni/internal_helpers_for_jnigen.dart";
+
+final Pointer<T> Function<T extends NativeType>(String sym) jniLookup =
+    ProtectedJniExtensions.initGeneratedLibrary("jackson_core_test");
diff --git a/pkgs/jnigen/test/jackson_core_test/third_party/lib/com/fasterxml/jackson/core.dart b/pkgs/jnigen/test/jackson_core_test/third_party/lib/com/fasterxml/jackson/core.dart
index 1f4a1aa..d106959 100644
--- a/pkgs/jnigen/test/jackson_core_test/third_party/lib/com/fasterxml/jackson/core.dart
+++ b/pkgs/jnigen/test/jackson_core_test/third_party/lib/com/fasterxml/jackson/core.dart
@@ -25,10 +25,9 @@
 // ignore_for_file: unused_element
 
 import "dart:ffi" as ffi;
-
 import "package:jni/jni.dart" as jni;
 
-import "../../../init.dart" show jlookup;
+import "../../../_init.dart" show jniLookup;
 
 /// from: com.fasterxml.jackson.core.JsonFactory
 ///
@@ -49,7 +48,7 @@
 /// the default constructor is used for constructing factory
 /// instances.
 ///@author Tatu Saloranta
-class JsonFactory extends jni.JlObject {
+class JsonFactory extends jni.JniObject {
   JsonFactory.fromRef(ffi.Pointer<ffi.Void> ref) : super.fromRef(ref);
 
   /// from: private static final long serialVersionUID
@@ -61,7 +60,7 @@
   /// (and returned by \#getFormatName()
   static const FORMAT_NAME_JSON = "JSON";
 
-  static final _get_DEFAULT_FACTORY_FEATURE_FLAGS = jlookup<
+  static final _get_DEFAULT_FACTORY_FEATURE_FLAGS = jniLookup<
               ffi.NativeFunction<ffi.Int32 Function()>>(
           "get_com_fasterxml_jackson_core_JsonFactory_DEFAULT_FACTORY_FEATURE_FLAGS")
       .asFunction<int Function()>();
@@ -72,7 +71,7 @@
   static int get DEFAULT_FACTORY_FEATURE_FLAGS =>
       _get_DEFAULT_FACTORY_FEATURE_FLAGS();
 
-  static final _get_DEFAULT_PARSER_FEATURE_FLAGS = jlookup<
+  static final _get_DEFAULT_PARSER_FEATURE_FLAGS = jniLookup<
               ffi.NativeFunction<ffi.Int32 Function()>>(
           "get_com_fasterxml_jackson_core_JsonFactory_DEFAULT_PARSER_FEATURE_FLAGS")
       .asFunction<int Function()>();
@@ -84,7 +83,7 @@
   static int get DEFAULT_PARSER_FEATURE_FLAGS =>
       _get_DEFAULT_PARSER_FEATURE_FLAGS();
 
-  static final _get_DEFAULT_GENERATOR_FEATURE_FLAGS = jlookup<
+  static final _get_DEFAULT_GENERATOR_FEATURE_FLAGS = jniLookup<
               ffi.NativeFunction<ffi.Int32 Function()>>(
           "get_com_fasterxml_jackson_core_JsonFactory_DEFAULT_GENERATOR_FEATURE_FLAGS")
       .asFunction<int Function()>();
@@ -96,18 +95,18 @@
   static int get DEFAULT_GENERATOR_FEATURE_FLAGS =>
       _get_DEFAULT_GENERATOR_FEATURE_FLAGS();
 
-  static final _get_DEFAULT_ROOT_VALUE_SEPARATOR = jlookup<
+  static final _get_DEFAULT_ROOT_VALUE_SEPARATOR = jniLookup<
               ffi.NativeFunction<ffi.Pointer<ffi.Void> Function()>>(
           "get_com_fasterxml_jackson_core_JsonFactory_DEFAULT_ROOT_VALUE_SEPARATOR")
       .asFunction<ffi.Pointer<ffi.Void> Function()>();
 
   /// from: static public final com.fasterxml.jackson.core.SerializableString DEFAULT_ROOT_VALUE_SEPARATOR
   /// The returned object must be deleted after use, by calling the `delete` method.
-  static jni.JlObject get DEFAULT_ROOT_VALUE_SEPARATOR =>
-      jni.JlObject.fromRef(_get_DEFAULT_ROOT_VALUE_SEPARATOR());
+  static jni.JniObject get DEFAULT_ROOT_VALUE_SEPARATOR =>
+      jni.JniObject.fromRef(_get_DEFAULT_ROOT_VALUE_SEPARATOR());
 
   static final _ctor =
-      jlookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function()>>(
+      jniLookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function()>>(
               "com_fasterxml_jackson_core_JsonFactory_ctor")
           .asFunction<ffi.Pointer<ffi.Void> Function()>();
 
@@ -121,18 +120,22 @@
   /// processing objects (such as symbol tables parsers use)
   /// and this reuse only works within context of a single
   /// factory instance.
-  JsonFactory() : super.fromRef(_ctor());
+  JsonFactory() : super.fromRef(_ctor()) {
+    jni.Jni.env.checkException();
+  }
 
-  static final _ctor1 = jlookup<
+  static final _ctor1 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonFactory_ctor1")
       .asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>();
 
   /// from: public void <init>(com.fasterxml.jackson.core.ObjectCodec oc)
-  JsonFactory.ctor1(jni.JlObject oc) : super.fromRef(_ctor1(oc.reference));
+  JsonFactory.ctor1(jni.JniObject oc) : super.fromRef(_ctor1(oc.reference)) {
+    jni.Jni.env.checkException();
+  }
 
-  static final _ctor2 = jlookup<
+  static final _ctor2 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -147,10 +150,12 @@
   ///@param src Original factory to copy settings from
   ///@param codec Databinding-level codec to use, if any
   ///@since 2.2.1
-  JsonFactory.ctor2(JsonFactory src, jni.JlObject codec)
-      : super.fromRef(_ctor2(src.reference, codec.reference));
+  JsonFactory.ctor2(JsonFactory src, jni.JniObject codec)
+      : super.fromRef(_ctor2(src.reference, codec.reference)) {
+    jni.Jni.env.checkException();
+  }
 
-  static final _ctor3 = jlookup<
+  static final _ctor3 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonFactory_ctor3")
@@ -161,9 +166,11 @@
   /// Constructor used by JsonFactoryBuilder for instantiation.
   ///@param b Builder that contains settings to use
   ///@since 2.10
-  JsonFactory.ctor3(jni.JlObject b) : super.fromRef(_ctor3(b.reference));
+  JsonFactory.ctor3(jni.JniObject b) : super.fromRef(_ctor3(b.reference)) {
+    jni.Jni.env.checkException();
+  }
 
-  static final _ctor4 = jlookup<
+  static final _ctor4 = jniLookup<
           ffi.NativeFunction<
               ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>,
                   ffi.Uint8)>>("com_fasterxml_jackson_core_JsonFactory_ctor4")
@@ -176,10 +183,12 @@
   /// implementation for json.
   ///@param b Builder that contains settings to use
   ///@param bogus Argument only needed to separate constructor signature; ignored
-  JsonFactory.ctor4(jni.JlObject b, bool bogus)
-      : super.fromRef(_ctor4(b.reference, bogus ? 1 : 0));
+  JsonFactory.ctor4(jni.JniObject b, bool bogus)
+      : super.fromRef(_ctor4(b.reference, bogus ? 1 : 0)) {
+    jni.Jni.env.checkException();
+  }
 
-  static final _rebuild = jlookup<
+  static final _rebuild = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonFactory_rebuild")
@@ -192,10 +201,14 @@
   /// with settings of this factory.
   ///@return Builder instance to use
   ///@since 2.10
-  jni.JlObject rebuild() => jni.JlObject.fromRef(_rebuild(reference));
+  jni.JniObject rebuild() {
+    final result__ = jni.JniObject.fromRef(_rebuild(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _builder =
-      jlookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function()>>(
+      jniLookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function()>>(
               "com_fasterxml_jackson_core_JsonFactory_builder")
           .asFunction<ffi.Pointer<ffi.Void> Function()>();
 
@@ -210,9 +223,13 @@
   /// NOTE: signature unfortunately does not expose true implementation type; this
   /// will be fixed in 3.0.
   ///@return Builder instance to use
-  static jni.JlObject builder() => jni.JlObject.fromRef(_builder());
+  static jni.JniObject builder() {
+    final result__ = jni.JniObject.fromRef(_builder());
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _copy = jlookup<
+  static final _copy = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonFactory_copy")
@@ -233,9 +250,13 @@
   /// set codec after making the copy.
   ///@return Copy of this factory instance
   ///@since 2.1
-  JsonFactory copy() => JsonFactory.fromRef(_copy(reference));
+  JsonFactory copy() {
+    final result__ = JsonFactory.fromRef(_copy(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _readResolve = jlookup<
+  static final _readResolve = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonFactory_readResolve")
@@ -250,10 +271,14 @@
   ///
   /// Note: must be overridden by sub-classes as well.
   ///@return Newly constructed instance
-  jni.JlObject readResolve() => jni.JlObject.fromRef(_readResolve(reference));
+  jni.JniObject readResolve() {
+    final result__ = jni.JniObject.fromRef(_readResolve(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _requiresPropertyOrdering =
-      jlookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
               "com_fasterxml_jackson_core_JsonFactory_requiresPropertyOrdering")
           .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
@@ -273,10 +298,14 @@
   ///@return Whether format supported by this factory
   ///   requires Object properties to be ordered.
   ///@since 2.3
-  bool requiresPropertyOrdering() => _requiresPropertyOrdering(reference) != 0;
+  bool requiresPropertyOrdering() {
+    final result__ = _requiresPropertyOrdering(reference) != 0;
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _canHandleBinaryNatively =
-      jlookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
               "com_fasterxml_jackson_core_JsonFactory_canHandleBinaryNatively")
           .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
@@ -293,10 +322,14 @@
   ///@return Whether format supported by this factory
   ///    supports native binary content
   ///@since 2.3
-  bool canHandleBinaryNatively() => _canHandleBinaryNatively(reference) != 0;
+  bool canHandleBinaryNatively() {
+    final result__ = _canHandleBinaryNatively(reference) != 0;
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _canUseCharArrays =
-      jlookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
               "com_fasterxml_jackson_core_JsonFactory_canUseCharArrays")
           .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
@@ -313,10 +346,14 @@
   ///@return Whether access to decoded textual content can be efficiently
   ///   accessed using parser method {@code getTextCharacters()}.
   ///@since 2.4
-  bool canUseCharArrays() => _canUseCharArrays(reference) != 0;
+  bool canUseCharArrays() {
+    final result__ = _canUseCharArrays(reference) != 0;
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _canParseAsync =
-      jlookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
               "com_fasterxml_jackson_core_JsonFactory_canParseAsync")
           .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
@@ -329,9 +366,13 @@
   ///@return Whether this factory supports non-blocking ("async") parsing or
   ///    not (and consequently whether {@code createNonBlockingXxx()} method(s) work)
   ///@since 2.9
-  bool canParseAsync() => _canParseAsync(reference) != 0;
+  bool canParseAsync() {
+    final result__ = _canParseAsync(reference) != 0;
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getFormatReadFeatureType = jlookup<
+  static final _getFormatReadFeatureType = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonFactory_getFormatReadFeatureType")
@@ -339,10 +380,14 @@
 
   /// from: public java.lang.Class<? extends com.fasterxml.jackson.core.FormatFeature> getFormatReadFeatureType()
   /// The returned object must be deleted after use, by calling the `delete` method.
-  jni.JlObject getFormatReadFeatureType() =>
-      jni.JlObject.fromRef(_getFormatReadFeatureType(reference));
+  jni.JniObject getFormatReadFeatureType() {
+    final result__ =
+        jni.JniObject.fromRef(_getFormatReadFeatureType(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getFormatWriteFeatureType = jlookup<
+  static final _getFormatWriteFeatureType = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonFactory_getFormatWriteFeatureType")
@@ -350,10 +395,14 @@
 
   /// from: public java.lang.Class<? extends com.fasterxml.jackson.core.FormatFeature> getFormatWriteFeatureType()
   /// The returned object must be deleted after use, by calling the `delete` method.
-  jni.JlObject getFormatWriteFeatureType() =>
-      jni.JlObject.fromRef(_getFormatWriteFeatureType(reference));
+  jni.JniObject getFormatWriteFeatureType() {
+    final result__ =
+        jni.JniObject.fromRef(_getFormatWriteFeatureType(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _canUseSchema = jlookup<
+  static final _canUseSchema = jniLookup<
               ffi.NativeFunction<
                   ffi.Uint8 Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -371,10 +420,13 @@
   ///@param schema Schema instance to check
   ///@return Whether parsers and generators constructed by this factory
   ///   can use specified format schema instance
-  bool canUseSchema(jni.JlObject schema) =>
-      _canUseSchema(reference, schema.reference) != 0;
+  bool canUseSchema(jni.JniObject schema) {
+    final result__ = _canUseSchema(reference, schema.reference) != 0;
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getFormatName = jlookup<
+  static final _getFormatName = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonFactory_getFormatName")
@@ -389,10 +441,13 @@
   /// Note: sub-classes should override this method; default
   /// implementation will return null for all sub-classes
   ///@return Name of the format handled by parsers, generators this factory creates
-  jni.JlString getFormatName() =>
-      jni.JlString.fromRef(_getFormatName(reference));
+  jni.JniString getFormatName() {
+    final result__ = jni.JniString.fromRef(_getFormatName(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _hasFormat = jlookup<
+  static final _hasFormat = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -403,11 +458,15 @@
 
   /// from: public com.fasterxml.jackson.core.format.MatchStrength hasFormat(com.fasterxml.jackson.core.format.InputAccessor acc)
   /// The returned object must be deleted after use, by calling the `delete` method.
-  jni.JlObject hasFormat(jni.JlObject acc) =>
-      jni.JlObject.fromRef(_hasFormat(reference, acc.reference));
+  jni.JniObject hasFormat(jni.JniObject acc) {
+    final result__ =
+        jni.JniObject.fromRef(_hasFormat(reference, acc.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _requiresCustomCodec =
-      jlookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
               "com_fasterxml_jackson_core_JsonFactory_requiresCustomCodec")
           .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
@@ -422,9 +481,13 @@
   ///   generators created by this factory; false if a general
   ///   ObjectCodec is enough
   ///@since 2.1
-  bool requiresCustomCodec() => _requiresCustomCodec(reference) != 0;
+  bool requiresCustomCodec() {
+    final result__ = _requiresCustomCodec(reference) != 0;
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _hasJSONFormat = jlookup<
+  static final _hasJSONFormat = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -435,10 +498,14 @@
 
   /// from: protected com.fasterxml.jackson.core.format.MatchStrength hasJSONFormat(com.fasterxml.jackson.core.format.InputAccessor acc)
   /// The returned object must be deleted after use, by calling the `delete` method.
-  jni.JlObject hasJSONFormat(jni.JlObject acc) =>
-      jni.JlObject.fromRef(_hasJSONFormat(reference, acc.reference));
+  jni.JniObject hasJSONFormat(jni.JniObject acc) {
+    final result__ =
+        jni.JniObject.fromRef(_hasJSONFormat(reference, acc.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _version = jlookup<
+  static final _version = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonFactory_version")
@@ -446,9 +513,13 @@
 
   /// from: public com.fasterxml.jackson.core.Version version()
   /// The returned object must be deleted after use, by calling the `delete` method.
-  jni.JlObject version() => jni.JlObject.fromRef(_version(reference));
+  jni.JniObject version() {
+    final result__ = jni.JniObject.fromRef(_version(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _configure = jlookup<
+  static final _configure = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>,
                       ffi.Pointer<ffi.Void>, ffi.Uint8)>>(
@@ -466,10 +537,14 @@
   ///@param state Whether to enable or disable the feature
   ///@return This factory instance (to allow call chaining)
   ///@deprecated since 2.10 use JsonFactoryBuilder\#configure(JsonFactory.Feature, boolean) instead
-  JsonFactory configure(JsonFactory_Feature f, bool state) =>
-      JsonFactory.fromRef(_configure(reference, f.reference, state ? 1 : 0));
+  JsonFactory configure(JsonFactory_Feature f, bool state) {
+    final result__ =
+        JsonFactory.fromRef(_configure(reference, f.reference, state ? 1 : 0));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _enable = jlookup<
+  static final _enable = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -486,10 +561,13 @@
   ///@param f Feature to enable
   ///@return This factory instance (to allow call chaining)
   ///@deprecated since 2.10 use JsonFactoryBuilder\#configure(JsonFactory.Feature, boolean) instead
-  JsonFactory enable(JsonFactory_Feature f) =>
-      JsonFactory.fromRef(_enable(reference, f.reference));
+  JsonFactory enable(JsonFactory_Feature f) {
+    final result__ = JsonFactory.fromRef(_enable(reference, f.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _disable = jlookup<
+  static final _disable = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -506,10 +584,13 @@
   ///@param f Feature to disable
   ///@return This factory instance (to allow call chaining)
   ///@deprecated since 2.10 use JsonFactoryBuilder\#configure(JsonFactory.Feature, boolean) instead
-  JsonFactory disable(JsonFactory_Feature f) =>
-      JsonFactory.fromRef(_disable(reference, f.reference));
+  JsonFactory disable(JsonFactory_Feature f) {
+    final result__ = JsonFactory.fromRef(_disable(reference, f.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _isEnabled = jlookup<
+  static final _isEnabled = jniLookup<
               ffi.NativeFunction<
                   ffi.Uint8 Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -521,42 +602,61 @@
   /// Checked whether specified parser feature is enabled.
   ///@param f Feature to check
   ///@return True if the specified feature is enabled
-  bool isEnabled(JsonFactory_Feature f) =>
-      _isEnabled(reference, f.reference) != 0;
+  bool isEnabled(JsonFactory_Feature f) {
+    final result__ = _isEnabled(reference, f.reference) != 0;
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _getParserFeatures =
-      jlookup<ffi.NativeFunction<ffi.Int32 Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Int32 Function(ffi.Pointer<ffi.Void>)>>(
               "com_fasterxml_jackson_core_JsonFactory_getParserFeatures")
           .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
   /// from: public final int getParserFeatures()
-  int getParserFeatures() => _getParserFeatures(reference);
+  int getParserFeatures() {
+    final result__ = _getParserFeatures(reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _getGeneratorFeatures =
-      jlookup<ffi.NativeFunction<ffi.Int32 Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Int32 Function(ffi.Pointer<ffi.Void>)>>(
               "com_fasterxml_jackson_core_JsonFactory_getGeneratorFeatures")
           .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
   /// from: public final int getGeneratorFeatures()
-  int getGeneratorFeatures() => _getGeneratorFeatures(reference);
+  int getGeneratorFeatures() {
+    final result__ = _getGeneratorFeatures(reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _getFormatParserFeatures =
-      jlookup<ffi.NativeFunction<ffi.Int32 Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Int32 Function(ffi.Pointer<ffi.Void>)>>(
               "com_fasterxml_jackson_core_JsonFactory_getFormatParserFeatures")
           .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
   /// from: public int getFormatParserFeatures()
-  int getFormatParserFeatures() => _getFormatParserFeatures(reference);
+  int getFormatParserFeatures() {
+    final result__ = _getFormatParserFeatures(reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getFormatGeneratorFeatures = jlookup<
+  static final _getFormatGeneratorFeatures = jniLookup<
               ffi.NativeFunction<ffi.Int32 Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonFactory_getFormatGeneratorFeatures")
       .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
   /// from: public int getFormatGeneratorFeatures()
-  int getFormatGeneratorFeatures() => _getFormatGeneratorFeatures(reference);
+  int getFormatGeneratorFeatures() {
+    final result__ = _getFormatGeneratorFeatures(reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _configure1 = jlookup<
+  static final _configure1 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>,
                       ffi.Pointer<ffi.Void>, ffi.Uint8)>>(
@@ -573,10 +673,14 @@
   ///@param f Feature to enable/disable
   ///@param state Whether to enable or disable the feature
   ///@return This factory instance (to allow call chaining)
-  JsonFactory configure1(JsonParser_Feature f, bool state) =>
-      JsonFactory.fromRef(_configure1(reference, f.reference, state ? 1 : 0));
+  JsonFactory configure1(JsonParser_Feature f, bool state) {
+    final result__ =
+        JsonFactory.fromRef(_configure1(reference, f.reference, state ? 1 : 0));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _enable1 = jlookup<
+  static final _enable1 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -592,10 +696,13 @@
   /// (check JsonParser.Feature for list of features)
   ///@param f Feature to enable
   ///@return This factory instance (to allow call chaining)
-  JsonFactory enable1(JsonParser_Feature f) =>
-      JsonFactory.fromRef(_enable1(reference, f.reference));
+  JsonFactory enable1(JsonParser_Feature f) {
+    final result__ = JsonFactory.fromRef(_enable1(reference, f.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _disable1 = jlookup<
+  static final _disable1 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -611,10 +718,13 @@
   /// (check JsonParser.Feature for list of features)
   ///@param f Feature to disable
   ///@return This factory instance (to allow call chaining)
-  JsonFactory disable1(JsonParser_Feature f) =>
-      JsonFactory.fromRef(_disable1(reference, f.reference));
+  JsonFactory disable1(JsonParser_Feature f) {
+    final result__ = JsonFactory.fromRef(_disable1(reference, f.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _isEnabled1 = jlookup<
+  static final _isEnabled1 = jniLookup<
               ffi.NativeFunction<
                   ffi.Uint8 Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -626,10 +736,13 @@
   /// Method for checking if the specified parser feature is enabled.
   ///@param f Feature to check
   ///@return True if specified feature is enabled
-  bool isEnabled1(JsonParser_Feature f) =>
-      _isEnabled1(reference, f.reference) != 0;
+  bool isEnabled1(JsonParser_Feature f) {
+    final result__ = _isEnabled1(reference, f.reference) != 0;
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _isEnabled2 = jlookup<
+  static final _isEnabled2 = jniLookup<
               ffi.NativeFunction<
                   ffi.Uint8 Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -642,9 +755,13 @@
   ///@param f Feature to check
   ///@return True if specified feature is enabled
   ///@since 2.10
-  bool isEnabled2(jni.JlObject f) => _isEnabled2(reference, f.reference) != 0;
+  bool isEnabled2(jni.JniObject f) {
+    final result__ = _isEnabled2(reference, f.reference) != 0;
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getInputDecorator = jlookup<
+  static final _getInputDecorator = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonFactory_getInputDecorator")
@@ -656,10 +773,13 @@
   /// Method for getting currently configured input decorator (if any;
   /// there is no default decorator).
   ///@return InputDecorator configured, if any
-  jni.JlObject getInputDecorator() =>
-      jni.JlObject.fromRef(_getInputDecorator(reference));
+  jni.JniObject getInputDecorator() {
+    final result__ = jni.JniObject.fromRef(_getInputDecorator(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _setInputDecorator = jlookup<
+  static final _setInputDecorator = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -675,10 +795,14 @@
   ///@param d Decorator to configure for this factory, if any ({@code null} if none)
   ///@return This factory instance (to allow call chaining)
   ///@deprecated Since 2.10 use JsonFactoryBuilder\#inputDecorator(InputDecorator) instead
-  JsonFactory setInputDecorator(jni.JlObject d) =>
-      JsonFactory.fromRef(_setInputDecorator(reference, d.reference));
+  JsonFactory setInputDecorator(jni.JniObject d) {
+    final result__ =
+        JsonFactory.fromRef(_setInputDecorator(reference, d.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _configure2 = jlookup<
+  static final _configure2 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>,
                       ffi.Pointer<ffi.Void>, ffi.Uint8)>>(
@@ -695,10 +819,14 @@
   ///@param f Feature to enable/disable
   ///@param state Whether to enable or disable the feature
   ///@return This factory instance (to allow call chaining)
-  JsonFactory configure2(jni.JlObject f, bool state) =>
-      JsonFactory.fromRef(_configure2(reference, f.reference, state ? 1 : 0));
+  JsonFactory configure2(jni.JniObject f, bool state) {
+    final result__ =
+        JsonFactory.fromRef(_configure2(reference, f.reference, state ? 1 : 0));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _enable2 = jlookup<
+  static final _enable2 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -714,10 +842,13 @@
   /// (check JsonGenerator.Feature for list of features)
   ///@param f Feature to enable
   ///@return This factory instance (to allow call chaining)
-  JsonFactory enable2(jni.JlObject f) =>
-      JsonFactory.fromRef(_enable2(reference, f.reference));
+  JsonFactory enable2(jni.JniObject f) {
+    final result__ = JsonFactory.fromRef(_enable2(reference, f.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _disable2 = jlookup<
+  static final _disable2 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -733,10 +864,13 @@
   /// (check JsonGenerator.Feature for list of features)
   ///@param f Feature to disable
   ///@return This factory instance (to allow call chaining)
-  JsonFactory disable2(jni.JlObject f) =>
-      JsonFactory.fromRef(_disable2(reference, f.reference));
+  JsonFactory disable2(jni.JniObject f) {
+    final result__ = JsonFactory.fromRef(_disable2(reference, f.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _isEnabled3 = jlookup<
+  static final _isEnabled3 = jniLookup<
               ffi.NativeFunction<
                   ffi.Uint8 Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -748,9 +882,13 @@
   /// Check whether specified generator feature is enabled.
   ///@param f Feature to check
   ///@return Whether specified feature is enabled
-  bool isEnabled3(jni.JlObject f) => _isEnabled3(reference, f.reference) != 0;
+  bool isEnabled3(jni.JniObject f) {
+    final result__ = _isEnabled3(reference, f.reference) != 0;
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _isEnabled4 = jlookup<
+  static final _isEnabled4 = jniLookup<
               ffi.NativeFunction<
                   ffi.Uint8 Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -763,9 +901,13 @@
   ///@param f Feature to check
   ///@return Whether specified feature is enabled
   ///@since 2.10
-  bool isEnabled4(jni.JlObject f) => _isEnabled4(reference, f.reference) != 0;
+  bool isEnabled4(jni.JniObject f) {
+    final result__ = _isEnabled4(reference, f.reference) != 0;
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getCharacterEscapes = jlookup<
+  static final _getCharacterEscapes = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonFactory_getCharacterEscapes")
@@ -777,10 +919,13 @@
   /// Method for accessing custom escapes factory uses for JsonGenerators
   /// it creates.
   ///@return Configured {@code CharacterEscapes}, if any; {@code null} if none
-  jni.JlObject getCharacterEscapes() =>
-      jni.JlObject.fromRef(_getCharacterEscapes(reference));
+  jni.JniObject getCharacterEscapes() {
+    final result__ = jni.JniObject.fromRef(_getCharacterEscapes(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _setCharacterEscapes = jlookup<
+  static final _setCharacterEscapes = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -796,10 +941,14 @@
   /// it creates.
   ///@param esc CharaterEscapes to set (or {@code null} for "none")
   ///@return This factory instance (to allow call chaining)
-  JsonFactory setCharacterEscapes(jni.JlObject esc) =>
-      JsonFactory.fromRef(_setCharacterEscapes(reference, esc.reference));
+  JsonFactory setCharacterEscapes(jni.JniObject esc) {
+    final result__ =
+        JsonFactory.fromRef(_setCharacterEscapes(reference, esc.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getOutputDecorator = jlookup<
+  static final _getOutputDecorator = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonFactory_getOutputDecorator")
@@ -812,10 +961,13 @@
   /// there is no default decorator).
   ///@return OutputDecorator configured for generators factory creates, if any;
   ///    {@code null} if none.
-  jni.JlObject getOutputDecorator() =>
-      jni.JlObject.fromRef(_getOutputDecorator(reference));
+  jni.JniObject getOutputDecorator() {
+    final result__ = jni.JniObject.fromRef(_getOutputDecorator(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _setOutputDecorator = jlookup<
+  static final _setOutputDecorator = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -831,10 +983,14 @@
   ///@return This factory instance (to allow call chaining)
   ///@param d Output decorator to use, if any
   ///@deprecated Since 2.10 use JsonFactoryBuilder\#outputDecorator(OutputDecorator) instead
-  JsonFactory setOutputDecorator(jni.JlObject d) =>
-      JsonFactory.fromRef(_setOutputDecorator(reference, d.reference));
+  JsonFactory setOutputDecorator(jni.JniObject d) {
+    final result__ =
+        JsonFactory.fromRef(_setOutputDecorator(reference, d.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _setRootValueSeparator = jlookup<
+  static final _setRootValueSeparator = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -851,10 +1007,14 @@
   ///@param sep Separator to use, if any; null means that no separator is
   ///   automatically added
   ///@return This factory instance (to allow call chaining)
-  JsonFactory setRootValueSeparator(jni.JlString sep) =>
-      JsonFactory.fromRef(_setRootValueSeparator(reference, sep.reference));
+  JsonFactory setRootValueSeparator(jni.JniString sep) {
+    final result__ =
+        JsonFactory.fromRef(_setRootValueSeparator(reference, sep.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getRootValueSeparator = jlookup<
+  static final _getRootValueSeparator = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonFactory_getRootValueSeparator")
@@ -864,10 +1024,13 @@
   /// The returned object must be deleted after use, by calling the `delete` method.
   ///
   /// @return Root value separator configured, if any
-  jni.JlString getRootValueSeparator() =>
-      jni.JlString.fromRef(_getRootValueSeparator(reference));
+  jni.JniString getRootValueSeparator() {
+    final result__ = jni.JniString.fromRef(_getRootValueSeparator(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _setCodec = jlookup<
+  static final _setCodec = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -886,10 +1049,13 @@
   /// of JsonParser and JsonGenerator instances.
   ///@param oc Codec to use
   ///@return This factory instance (to allow call chaining)
-  JsonFactory setCodec(jni.JlObject oc) =>
-      JsonFactory.fromRef(_setCodec(reference, oc.reference));
+  JsonFactory setCodec(jni.JniObject oc) {
+    final result__ = JsonFactory.fromRef(_setCodec(reference, oc.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getCodec = jlookup<
+  static final _getCodec = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonFactory_getCodec")
@@ -897,9 +1063,13 @@
 
   /// from: public com.fasterxml.jackson.core.ObjectCodec getCodec()
   /// The returned object must be deleted after use, by calling the `delete` method.
-  jni.JlObject getCodec() => jni.JlObject.fromRef(_getCodec(reference));
+  jni.JniObject getCodec() {
+    final result__ = jni.JniObject.fromRef(_getCodec(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _createParser = jlookup<
+  static final _createParser = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -927,10 +1097,13 @@
   /// the parser, since caller has no access to it.
   ///@param f File that contains JSON content to parse
   ///@since 2.1
-  JsonParser createParser(jni.JlObject f) =>
-      JsonParser.fromRef(_createParser(reference, f.reference));
+  JsonParser createParser(jni.JniObject f) {
+    final result__ = JsonParser.fromRef(_createParser(reference, f.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _createParser1 = jlookup<
+  static final _createParser1 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -956,10 +1129,14 @@
   /// the parser, since caller has no access to it.
   ///@param url URL pointing to resource that contains JSON content to parse
   ///@since 2.1
-  JsonParser createParser1(jni.JlObject url) =>
-      JsonParser.fromRef(_createParser1(reference, url.reference));
+  JsonParser createParser1(jni.JniObject url) {
+    final result__ =
+        JsonParser.fromRef(_createParser1(reference, url.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _createParser2 = jlookup<
+  static final _createParser2 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -988,10 +1165,14 @@
   /// For other charsets use \#createParser(java.io.Reader).
   ///@param in InputStream to use for reading JSON content to parse
   ///@since 2.1
-  JsonParser createParser2(jni.JlObject in0) =>
-      JsonParser.fromRef(_createParser2(reference, in0.reference));
+  JsonParser createParser2(jni.JniObject in0) {
+    final result__ =
+        JsonParser.fromRef(_createParser2(reference, in0.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _createParser3 = jlookup<
+  static final _createParser3 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1013,10 +1194,13 @@
   /// is enabled.
   ///@param r Reader to use for reading JSON content to parse
   ///@since 2.1
-  JsonParser createParser3(jni.JlObject r) =>
-      JsonParser.fromRef(_createParser3(reference, r.reference));
+  JsonParser createParser3(jni.JniObject r) {
+    final result__ = JsonParser.fromRef(_createParser3(reference, r.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _createParser4 = jlookup<
+  static final _createParser4 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1031,10 +1215,14 @@
   /// Method for constructing parser for parsing
   /// the contents of given byte array.
   ///@since 2.1
-  JsonParser createParser4(jni.JlObject data) =>
-      JsonParser.fromRef(_createParser4(reference, data.reference));
+  JsonParser createParser4(jni.JniObject data) {
+    final result__ =
+        JsonParser.fromRef(_createParser4(reference, data.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _createParser5 = jlookup<
+  static final _createParser5 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>,
                       ffi.Pointer<ffi.Void>, ffi.Int32, ffi.Int32)>>(
@@ -1052,11 +1240,14 @@
   ///@param offset Offset of the first data byte within buffer
   ///@param len Length of contents to parse within buffer
   ///@since 2.1
-  JsonParser createParser5(jni.JlObject data, int offset, int len) =>
-      JsonParser.fromRef(
-          _createParser5(reference, data.reference, offset, len));
+  JsonParser createParser5(jni.JniObject data, int offset, int len) {
+    final result__ = JsonParser.fromRef(
+        _createParser5(reference, data.reference, offset, len));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _createParser6 = jlookup<
+  static final _createParser6 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1071,10 +1262,14 @@
   /// Method for constructing parser for parsing
   /// contents of given String.
   ///@since 2.1
-  JsonParser createParser6(jni.JlString content) =>
-      JsonParser.fromRef(_createParser6(reference, content.reference));
+  JsonParser createParser6(jni.JniString content) {
+    final result__ =
+        JsonParser.fromRef(_createParser6(reference, content.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _createParser7 = jlookup<
+  static final _createParser7 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1089,10 +1284,14 @@
   /// Method for constructing parser for parsing
   /// contents of given char array.
   ///@since 2.4
-  JsonParser createParser7(jni.JlObject content) =>
-      JsonParser.fromRef(_createParser7(reference, content.reference));
+  JsonParser createParser7(jni.JniObject content) {
+    final result__ =
+        JsonParser.fromRef(_createParser7(reference, content.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _createParser8 = jlookup<
+  static final _createParser8 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>,
                       ffi.Pointer<ffi.Void>, ffi.Int32, ffi.Int32)>>(
@@ -1106,11 +1305,14 @@
   ///
   /// Method for constructing parser for parsing contents of given char array.
   ///@since 2.4
-  JsonParser createParser8(jni.JlObject content, int offset, int len) =>
-      JsonParser.fromRef(
-          _createParser8(reference, content.reference, offset, len));
+  JsonParser createParser8(jni.JniObject content, int offset, int len) {
+    final result__ = JsonParser.fromRef(
+        _createParser8(reference, content.reference, offset, len));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _createParser9 = jlookup<
+  static final _createParser9 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1128,10 +1330,14 @@
   /// If this factory does not support DataInput as source,
   /// will throw UnsupportedOperationException
   ///@since 2.8
-  JsonParser createParser9(jni.JlObject in0) =>
-      JsonParser.fromRef(_createParser9(reference, in0.reference));
+  JsonParser createParser9(jni.JniObject in0) {
+    final result__ =
+        JsonParser.fromRef(_createParser9(reference, in0.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _createNonBlockingByteArrayParser = jlookup<
+  static final _createNonBlockingByteArrayParser = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonFactory_createNonBlockingByteArrayParser")
@@ -1153,10 +1359,14 @@
   /// (and US-ASCII since it is proper subset); other encodings are not supported
   /// at this point.
   ///@since 2.9
-  JsonParser createNonBlockingByteArrayParser() =>
-      JsonParser.fromRef(_createNonBlockingByteArrayParser(reference));
+  JsonParser createNonBlockingByteArrayParser() {
+    final result__ =
+        JsonParser.fromRef(_createNonBlockingByteArrayParser(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _createGenerator = jlookup<
+  static final _createGenerator = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>,
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1186,11 +1396,14 @@
   ///@param out OutputStream to use for writing JSON content
   ///@param enc Character encoding to use
   ///@since 2.1
-  jni.JlObject createGenerator(jni.JlObject out, jni.JlObject enc) =>
-      jni.JlObject.fromRef(
-          _createGenerator(reference, out.reference, enc.reference));
+  jni.JniObject createGenerator(jni.JniObject out, jni.JniObject enc) {
+    final result__ = jni.JniObject.fromRef(
+        _createGenerator(reference, out.reference, enc.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _createGenerator1 = jlookup<
+  static final _createGenerator1 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1207,10 +1420,14 @@
   ///
   /// Note: there are formats that use fixed encoding (like most binary data formats).
   ///@since 2.1
-  jni.JlObject createGenerator1(jni.JlObject out) =>
-      jni.JlObject.fromRef(_createGenerator1(reference, out.reference));
+  jni.JniObject createGenerator1(jni.JniObject out) {
+    final result__ =
+        jni.JniObject.fromRef(_createGenerator1(reference, out.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _createGenerator2 = jlookup<
+  static final _createGenerator2 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1233,10 +1450,14 @@
   /// Using application needs to close it explicitly.
   ///@since 2.1
   ///@param w Writer to use for writing JSON content
-  jni.JlObject createGenerator2(jni.JlObject w) =>
-      jni.JlObject.fromRef(_createGenerator2(reference, w.reference));
+  jni.JniObject createGenerator2(jni.JniObject w) {
+    final result__ =
+        jni.JniObject.fromRef(_createGenerator2(reference, w.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _createGenerator3 = jlookup<
+  static final _createGenerator3 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>,
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1260,11 +1481,14 @@
   ///@param f File to write contents to
   ///@param enc Character encoding to use
   ///@since 2.1
-  jni.JlObject createGenerator3(jni.JlObject f, jni.JlObject enc) =>
-      jni.JlObject.fromRef(
-          _createGenerator3(reference, f.reference, enc.reference));
+  jni.JniObject createGenerator3(jni.JniObject f, jni.JniObject enc) {
+    final result__ = jni.JniObject.fromRef(
+        _createGenerator3(reference, f.reference, enc.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _createGenerator4 = jlookup<
+  static final _createGenerator4 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>,
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1279,11 +1503,14 @@
   /// Method for constructing generator for writing content using specified
   /// DataOutput instance.
   ///@since 2.8
-  jni.JlObject createGenerator4(jni.JlObject out, jni.JlObject enc) =>
-      jni.JlObject.fromRef(
-          _createGenerator4(reference, out.reference, enc.reference));
+  jni.JniObject createGenerator4(jni.JniObject out, jni.JniObject enc) {
+    final result__ = jni.JniObject.fromRef(
+        _createGenerator4(reference, out.reference, enc.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _createGenerator5 = jlookup<
+  static final _createGenerator5 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1300,10 +1527,14 @@
   ///
   /// Note: there are formats that use fixed encoding (like most binary data formats).
   ///@since 2.8
-  jni.JlObject createGenerator5(jni.JlObject out) =>
-      jni.JlObject.fromRef(_createGenerator5(reference, out.reference));
+  jni.JniObject createGenerator5(jni.JniObject out) {
+    final result__ =
+        jni.JniObject.fromRef(_createGenerator5(reference, out.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _createJsonParser = jlookup<
+  static final _createJsonParser = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1333,10 +1564,14 @@
   ///@throws IOException if parser initialization fails due to I/O (read) problem
   ///@throws JsonParseException if parser initialization fails due to content decoding problem
   ///@deprecated Since 2.2, use \#createParser(File) instead.
-  JsonParser createJsonParser(jni.JlObject f) =>
-      JsonParser.fromRef(_createJsonParser(reference, f.reference));
+  JsonParser createJsonParser(jni.JniObject f) {
+    final result__ =
+        JsonParser.fromRef(_createJsonParser(reference, f.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _createJsonParser1 = jlookup<
+  static final _createJsonParser1 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1365,10 +1600,14 @@
   ///@throws IOException if parser initialization fails due to I/O (read) problem
   ///@throws JsonParseException if parser initialization fails due to content decoding problem
   ///@deprecated Since 2.2, use \#createParser(URL) instead.
-  JsonParser createJsonParser1(jni.JlObject url) =>
-      JsonParser.fromRef(_createJsonParser1(reference, url.reference));
+  JsonParser createJsonParser1(jni.JniObject url) {
+    final result__ =
+        JsonParser.fromRef(_createJsonParser1(reference, url.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _createJsonParser2 = jlookup<
+  static final _createJsonParser2 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1400,10 +1639,14 @@
   ///@throws IOException if parser initialization fails due to I/O (read) problem
   ///@throws JsonParseException if parser initialization fails due to content decoding problem
   ///@deprecated Since 2.2, use \#createParser(InputStream) instead.
-  JsonParser createJsonParser2(jni.JlObject in0) =>
-      JsonParser.fromRef(_createJsonParser2(reference, in0.reference));
+  JsonParser createJsonParser2(jni.JniObject in0) {
+    final result__ =
+        JsonParser.fromRef(_createJsonParser2(reference, in0.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _createJsonParser3 = jlookup<
+  static final _createJsonParser3 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1428,10 +1671,14 @@
   ///@throws IOException if parser initialization fails due to I/O (read) problem
   ///@throws JsonParseException if parser initialization fails due to content decoding problem
   ///@deprecated Since 2.2, use \#createParser(Reader) instead.
-  JsonParser createJsonParser3(jni.JlObject r) =>
-      JsonParser.fromRef(_createJsonParser3(reference, r.reference));
+  JsonParser createJsonParser3(jni.JniObject r) {
+    final result__ =
+        JsonParser.fromRef(_createJsonParser3(reference, r.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _createJsonParser4 = jlookup<
+  static final _createJsonParser4 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1449,10 +1696,14 @@
   ///@throws IOException if parser initialization fails due to I/O (read) problem
   ///@throws JsonParseException if parser initialization fails due to content decoding problem
   ///@deprecated Since 2.2, use \#createParser(byte[]) instead.
-  JsonParser createJsonParser4(jni.JlObject data) =>
-      JsonParser.fromRef(_createJsonParser4(reference, data.reference));
+  JsonParser createJsonParser4(jni.JniObject data) {
+    final result__ =
+        JsonParser.fromRef(_createJsonParser4(reference, data.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _createJsonParser5 = jlookup<
+  static final _createJsonParser5 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>,
                       ffi.Pointer<ffi.Void>, ffi.Int32, ffi.Int32)>>(
@@ -1473,11 +1724,14 @@
   ///@throws IOException if parser initialization fails due to I/O (read) problem
   ///@throws JsonParseException if parser initialization fails due to content decoding problem
   ///@deprecated Since 2.2, use \#createParser(byte[],int,int) instead.
-  JsonParser createJsonParser5(jni.JlObject data, int offset, int len) =>
-      JsonParser.fromRef(
-          _createJsonParser5(reference, data.reference, offset, len));
+  JsonParser createJsonParser5(jni.JniObject data, int offset, int len) {
+    final result__ = JsonParser.fromRef(
+        _createJsonParser5(reference, data.reference, offset, len));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _createJsonParser6 = jlookup<
+  static final _createJsonParser6 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1496,10 +1750,14 @@
   ///@throws IOException if parser initialization fails due to I/O (read) problem
   ///@throws JsonParseException if parser initialization fails due to content decoding problem
   ///@deprecated Since 2.2, use \#createParser(String) instead.
-  JsonParser createJsonParser6(jni.JlString content) =>
-      JsonParser.fromRef(_createJsonParser6(reference, content.reference));
+  JsonParser createJsonParser6(jni.JniString content) {
+    final result__ =
+        JsonParser.fromRef(_createJsonParser6(reference, content.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _createJsonGenerator = jlookup<
+  static final _createJsonGenerator = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>,
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1531,11 +1789,14 @@
   ///@return Generator constructed
   ///@throws IOException if parser initialization fails due to I/O (write) problem
   ///@deprecated Since 2.2, use \#createGenerator(OutputStream, JsonEncoding) instead.
-  jni.JlObject createJsonGenerator(jni.JlObject out, jni.JlObject enc) =>
-      jni.JlObject.fromRef(
-          _createJsonGenerator(reference, out.reference, enc.reference));
+  jni.JniObject createJsonGenerator(jni.JniObject out, jni.JniObject enc) {
+    final result__ = jni.JniObject.fromRef(
+        _createJsonGenerator(reference, out.reference, enc.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _createJsonGenerator1 = jlookup<
+  static final _createJsonGenerator1 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1560,10 +1821,14 @@
   ///@return Generator constructed
   ///@throws IOException if parser initialization fails due to I/O (write) problem
   ///@deprecated Since 2.2, use \#createGenerator(Writer) instead.
-  jni.JlObject createJsonGenerator1(jni.JlObject out) =>
-      jni.JlObject.fromRef(_createJsonGenerator1(reference, out.reference));
+  jni.JniObject createJsonGenerator1(jni.JniObject out) {
+    final result__ =
+        jni.JniObject.fromRef(_createJsonGenerator1(reference, out.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _createJsonGenerator2 = jlookup<
+  static final _createJsonGenerator2 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1583,27 +1848,35 @@
   ///@return Generator constructed
   ///@throws IOException if parser initialization fails due to I/O (write) problem
   ///@deprecated Since 2.2, use \#createGenerator(OutputStream) instead.
-  jni.JlObject createJsonGenerator2(jni.JlObject out) =>
-      jni.JlObject.fromRef(_createJsonGenerator2(reference, out.reference));
+  jni.JniObject createJsonGenerator2(jni.JniObject out) {
+    final result__ =
+        jni.JniObject.fromRef(_createJsonGenerator2(reference, out.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 }
 
 /// from: com.fasterxml.jackson.core.JsonFactory$Feature
 ///
 /// Enumeration that defines all on/off features that can only be
 /// changed for JsonFactory.
-class JsonFactory_Feature extends jni.JlObject {
+class JsonFactory_Feature extends jni.JniObject {
   JsonFactory_Feature.fromRef(ffi.Pointer<ffi.Void> ref) : super.fromRef(ref);
 
   static final _values =
-      jlookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function()>>(
+      jniLookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function()>>(
               "com_fasterxml_jackson_core_JsonFactory__Feature_values")
           .asFunction<ffi.Pointer<ffi.Void> Function()>();
 
   /// from: static public com.fasterxml.jackson.core.JsonFactory.Feature[] values()
   /// The returned object must be deleted after use, by calling the `delete` method.
-  static jni.JlObject values() => jni.JlObject.fromRef(_values());
+  static jni.JniObject values() {
+    final result__ = jni.JniObject.fromRef(_values());
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _valueOf = jlookup<
+  static final _valueOf = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonFactory__Feature_valueOf")
@@ -1611,11 +1884,14 @@
 
   /// from: static public com.fasterxml.jackson.core.JsonFactory.Feature valueOf(java.lang.String name)
   /// The returned object must be deleted after use, by calling the `delete` method.
-  static JsonFactory_Feature valueOf(jni.JlString name) =>
-      JsonFactory_Feature.fromRef(_valueOf(name.reference));
+  static JsonFactory_Feature valueOf(jni.JniString name) {
+    final result__ = JsonFactory_Feature.fromRef(_valueOf(name.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _collectDefaults =
-      jlookup<ffi.NativeFunction<ffi.Int32 Function()>>(
+      jniLookup<ffi.NativeFunction<ffi.Int32 Function()>>(
               "com_fasterxml_jackson_core_JsonFactory__Feature_collectDefaults")
           .asFunction<int Function()>();
 
@@ -1624,41 +1900,59 @@
   /// Method that calculates bit set (flags) of all features that
   /// are enabled by default.
   ///@return Bit field of features enabled by default
-  static int collectDefaults() => _collectDefaults();
+  static int collectDefaults() {
+    final result__ = _collectDefaults();
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _ctor =
-      jlookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function(ffi.Uint8)>>(
+      jniLookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function(ffi.Uint8)>>(
               "com_fasterxml_jackson_core_JsonFactory__Feature_ctor")
           .asFunction<ffi.Pointer<ffi.Void> Function(int)>();
 
   /// from: private void <init>(boolean defaultState)
   JsonFactory_Feature(bool defaultState)
-      : super.fromRef(_ctor(defaultState ? 1 : 0));
+      : super.fromRef(_ctor(defaultState ? 1 : 0)) {
+    jni.Jni.env.checkException();
+  }
 
-  static final _enabledByDefault = jlookup<
+  static final _enabledByDefault = jniLookup<
               ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonFactory__Feature_enabledByDefault")
       .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
   /// from: public boolean enabledByDefault()
-  bool enabledByDefault() => _enabledByDefault(reference) != 0;
+  bool enabledByDefault() {
+    final result__ = _enabledByDefault(reference) != 0;
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _enabledIn = jlookup<
+  static final _enabledIn = jniLookup<
               ffi.NativeFunction<
                   ffi.Uint8 Function(ffi.Pointer<ffi.Void>, ffi.Int32)>>(
           "com_fasterxml_jackson_core_JsonFactory__Feature_enabledIn")
       .asFunction<int Function(ffi.Pointer<ffi.Void>, int)>();
 
   /// from: public boolean enabledIn(int flags)
-  bool enabledIn(int flags) => _enabledIn(reference, flags) != 0;
+  bool enabledIn(int flags) {
+    final result__ = _enabledIn(reference, flags) != 0;
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _getMask =
-      jlookup<ffi.NativeFunction<ffi.Int32 Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Int32 Function(ffi.Pointer<ffi.Void>)>>(
               "com_fasterxml_jackson_core_JsonFactory__Feature_getMask")
           .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
   /// from: public int getMask()
-  int getMask() => _getMask(reference);
+  int getMask() {
+    final result__ = _getMask(reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 }
 
 /// from: com.fasterxml.jackson.core.JsonParser
@@ -1667,7 +1961,7 @@
 /// Instances are created using factory methods of
 /// a JsonFactory instance.
 ///@author Tatu Saloranta
-class JsonParser extends jni.JlObject {
+class JsonParser extends jni.JniObject {
   JsonParser.fromRef(ffi.Pointer<ffi.Void> ref) : super.fromRef(ref);
 
   /// from: private static final int MIN_BYTE_I
@@ -1682,7 +1976,7 @@
   /// from: private static final int MAX_SHORT_I
   static const MAX_SHORT_I = 32767;
 
-  static final _get_DEFAULT_READ_CAPABILITIES = jlookup<
+  static final _get_DEFAULT_READ_CAPABILITIES = jniLookup<
               ffi.NativeFunction<ffi.Pointer<ffi.Void> Function()>>(
           "get_com_fasterxml_jackson_core_JsonParser_DEFAULT_READ_CAPABILITIES")
       .asFunction<ffi.Pointer<ffi.Void> Function()>();
@@ -1694,26 +1988,30 @@
   /// basis for format-specific readers (or as bogus instance if non-null
   /// set needs to be passed).
   ///@since 2.12
-  static jni.JlObject get DEFAULT_READ_CAPABILITIES =>
-      jni.JlObject.fromRef(_get_DEFAULT_READ_CAPABILITIES());
+  static jni.JniObject get DEFAULT_READ_CAPABILITIES =>
+      jni.JniObject.fromRef(_get_DEFAULT_READ_CAPABILITIES());
 
   static final _ctor =
-      jlookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function()>>(
+      jniLookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function()>>(
               "com_fasterxml_jackson_core_JsonParser_ctor")
           .asFunction<ffi.Pointer<ffi.Void> Function()>();
 
   /// from: protected void <init>()
-  JsonParser() : super.fromRef(_ctor());
+  JsonParser() : super.fromRef(_ctor()) {
+    jni.Jni.env.checkException();
+  }
 
   static final _ctor1 =
-      jlookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function(ffi.Int32)>>(
+      jniLookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function(ffi.Int32)>>(
               "com_fasterxml_jackson_core_JsonParser_ctor1")
           .asFunction<ffi.Pointer<ffi.Void> Function(int)>();
 
   /// from: protected void <init>(int features)
-  JsonParser.ctor1(int features) : super.fromRef(_ctor1(features));
+  JsonParser.ctor1(int features) : super.fromRef(_ctor1(features)) {
+    jni.Jni.env.checkException();
+  }
 
-  static final _getCodec = jlookup<
+  static final _getCodec = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonParser_getCodec")
@@ -1726,9 +2024,13 @@
   /// parser, if any. Codec is used by \#readValueAs(Class)
   /// method (and its variants).
   ///@return Codec assigned to this parser, if any; {@code null} if none
-  jni.JlObject getCodec() => jni.JlObject.fromRef(_getCodec(reference));
+  jni.JniObject getCodec() {
+    final result__ = jni.JniObject.fromRef(_getCodec(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _setCodec = jlookup<
+  static final _setCodec = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1742,9 +2044,13 @@
   /// parser, if any. Codec is used by \#readValueAs(Class)
   /// method (and its variants).
   ///@param oc Codec to assign, if any; {@code null} if none
-  void setCodec(jni.JlObject oc) => _setCodec(reference, oc.reference);
+  void setCodec(jni.JniObject oc) {
+    final result__ = _setCodec(reference, oc.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getInputSource = jlookup<
+  static final _getInputSource = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonParser_getInputSource")
@@ -1767,10 +2073,13 @@
   /// In general use of this accessor should be considered as
   /// "last effort", i.e. only used if no other mechanism is applicable.
   ///@return Input source this parser was configured with
-  jni.JlObject getInputSource() =>
-      jni.JlObject.fromRef(_getInputSource(reference));
+  jni.JniObject getInputSource() {
+    final result__ = jni.JniObject.fromRef(_getInputSource(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _setRequestPayloadOnError = jlookup<
+  static final _setRequestPayloadOnError = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1783,10 +2092,13 @@
   /// Sets the payload to be passed if JsonParseException is thrown.
   ///@param payload Payload to pass
   ///@since 2.8
-  void setRequestPayloadOnError(jni.JlObject payload) =>
-      _setRequestPayloadOnError(reference, payload.reference);
+  void setRequestPayloadOnError(jni.JniObject payload) {
+    final result__ = _setRequestPayloadOnError(reference, payload.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _setRequestPayloadOnError1 = jlookup<
+  static final _setRequestPayloadOnError1 = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(ffi.Pointer<ffi.Void>,
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1801,11 +2113,14 @@
   ///@param payload Payload to pass
   ///@param charset Character encoding for (lazily) decoding payload
   ///@since 2.8
-  void setRequestPayloadOnError1(jni.JlObject payload, jni.JlString charset) =>
-      _setRequestPayloadOnError1(
-          reference, payload.reference, charset.reference);
+  void setRequestPayloadOnError1(jni.JniObject payload, jni.JniString charset) {
+    final result__ = _setRequestPayloadOnError1(
+        reference, payload.reference, charset.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _setRequestPayloadOnError2 = jlookup<
+  static final _setRequestPayloadOnError2 = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1818,10 +2133,13 @@
   /// Sets the String request payload
   ///@param payload Payload to pass
   ///@since 2.8
-  void setRequestPayloadOnError2(jni.JlString payload) =>
-      _setRequestPayloadOnError2(reference, payload.reference);
+  void setRequestPayloadOnError2(jni.JniString payload) {
+    final result__ = _setRequestPayloadOnError2(reference, payload.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _setSchema = jlookup<
+  static final _setSchema = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1841,10 +2159,13 @@
   /// is thrown.
   ///@param schema Schema to use
   ///@throws UnsupportedOperationException if parser does not support schema
-  void setSchema(jni.JlObject schema) =>
-      _setSchema(reference, schema.reference);
+  void setSchema(jni.JniObject schema) {
+    final result__ = _setSchema(reference, schema.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getSchema = jlookup<
+  static final _getSchema = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonParser_getSchema")
@@ -1857,9 +2178,13 @@
   /// Default implementation returns null.
   ///@return Schema in use by this parser, if any; {@code null} if none
   ///@since 2.1
-  jni.JlObject getSchema() => jni.JlObject.fromRef(_getSchema(reference));
+  jni.JniObject getSchema() {
+    final result__ = jni.JniObject.fromRef(_getSchema(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _canUseSchema = jlookup<
+  static final _canUseSchema = jniLookup<
               ffi.NativeFunction<
                   ffi.Uint8 Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -1872,11 +2197,14 @@
   /// this parser (using \#setSchema).
   ///@param schema Schema to check
   ///@return True if this parser can use given schema; false if not
-  bool canUseSchema(jni.JlObject schema) =>
-      _canUseSchema(reference, schema.reference) != 0;
+  bool canUseSchema(jni.JniObject schema) {
+    final result__ = _canUseSchema(reference, schema.reference) != 0;
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _requiresCustomCodec =
-      jlookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
               "com_fasterxml_jackson_core_JsonParser_requiresCustomCodec")
           .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
@@ -1890,10 +2218,14 @@
   ///@return True if format-specific codec is needed with this parser; false if a general
   ///   ObjectCodec is enough
   ///@since 2.1
-  bool requiresCustomCodec() => _requiresCustomCodec(reference) != 0;
+  bool requiresCustomCodec() {
+    final result__ = _requiresCustomCodec(reference) != 0;
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _canParseAsync =
-      jlookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
               "com_fasterxml_jackson_core_JsonParser_canParseAsync")
           .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
@@ -1910,9 +2242,13 @@
   /// input is read by blocking
   ///@return True if this is a non-blocking ("asynchronous") parser
   ///@since 2.9
-  bool canParseAsync() => _canParseAsync(reference) != 0;
+  bool canParseAsync() {
+    final result__ = _canParseAsync(reference) != 0;
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getNonBlockingInputFeeder = jlookup<
+  static final _getNonBlockingInputFeeder = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonParser_getNonBlockingInputFeeder")
@@ -1926,10 +2262,14 @@
   /// parsers that use blocking I/O.
   ///@return Input feeder to use with non-blocking (async) parsing
   ///@since 2.9
-  jni.JlObject getNonBlockingInputFeeder() =>
-      jni.JlObject.fromRef(_getNonBlockingInputFeeder(reference));
+  jni.JniObject getNonBlockingInputFeeder() {
+    final result__ =
+        jni.JniObject.fromRef(_getNonBlockingInputFeeder(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getReadCapabilities = jlookup<
+  static final _getReadCapabilities = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonParser_getReadCapabilities")
@@ -1942,10 +2282,13 @@
   /// underlying data format being read (directly or indirectly).
   ///@return Set of read capabilities for content to read via this parser
   ///@since 2.12
-  jni.JlObject getReadCapabilities() =>
-      jni.JlObject.fromRef(_getReadCapabilities(reference));
+  jni.JniObject getReadCapabilities() {
+    final result__ = jni.JniObject.fromRef(_getReadCapabilities(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _version = jlookup<
+  static final _version = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonParser_version")
@@ -1958,10 +2301,14 @@
   /// Left for sub-classes to implement.
   ///@return Version of this generator (derived from version declared for
   ///   {@code jackson-core} jar that contains the class
-  jni.JlObject version() => jni.JlObject.fromRef(_version(reference));
+  jni.JniObject version() {
+    final result__ = jni.JniObject.fromRef(_version(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _close =
-      jlookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
               "com_fasterxml_jackson_core_JsonParser_close")
           .asFunction<void Function(ffi.Pointer<ffi.Void>)>();
 
@@ -1981,10 +2328,14 @@
   /// java.io.File or java.net.URL and creates
   /// stream or reader it does own them.
   ///@throws IOException if there is either an underlying I/O problem
-  void close() => _close(reference);
+  void close() {
+    final result__ = _close(reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _isClosed =
-      jlookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
               "com_fasterxml_jackson_core_JsonParser_isClosed")
           .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
@@ -1997,9 +2348,13 @@
   /// call to \#close or because parser has encountered
   /// end of input.
   ///@return {@code True} if this parser instance has been closed
-  bool isClosed() => _isClosed(reference) != 0;
+  bool isClosed() {
+    final result__ = _isClosed(reference) != 0;
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getParsingContext = jlookup<
+  static final _getParsingContext = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonParser_getParsingContext")
@@ -2017,10 +2372,13 @@
   /// Contexts can also be used for simple xpath-like matching of
   /// input, if so desired.
   ///@return Stream input context (JsonStreamContext) associated with this parser
-  jni.JlObject getParsingContext() =>
-      jni.JlObject.fromRef(_getParsingContext(reference));
+  jni.JniObject getParsingContext() {
+    final result__ = jni.JniObject.fromRef(_getParsingContext(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _currentLocation = jlookup<
+  static final _currentLocation = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonParser_currentLocation")
@@ -2041,10 +2399,13 @@
   /// to other library)
   ///@return Location of the last processed input unit (byte or character)
   ///@since 2.13
-  jni.JlObject currentLocation() =>
-      jni.JlObject.fromRef(_currentLocation(reference));
+  jni.JniObject currentLocation() {
+    final result__ = jni.JniObject.fromRef(_currentLocation(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _currentTokenLocation = jlookup<
+  static final _currentTokenLocation = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonParser_currentTokenLocation")
@@ -2065,10 +2426,13 @@
   /// to other library)
   ///@return Starting location of the token parser currently points to
   ///@since 2.13 (will eventually replace \#getTokenLocation)
-  jni.JlObject currentTokenLocation() =>
-      jni.JlObject.fromRef(_currentTokenLocation(reference));
+  jni.JniObject currentTokenLocation() {
+    final result__ = jni.JniObject.fromRef(_currentTokenLocation(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getCurrentLocation = jlookup<
+  static final _getCurrentLocation = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonParser_getCurrentLocation")
@@ -2080,10 +2444,13 @@
   /// Alias for \#currentLocation(), to be deprecated in later
   /// Jackson 2.x versions (and removed from Jackson 3.0).
   ///@return Location of the last processed input unit (byte or character)
-  jni.JlObject getCurrentLocation() =>
-      jni.JlObject.fromRef(_getCurrentLocation(reference));
+  jni.JniObject getCurrentLocation() {
+    final result__ = jni.JniObject.fromRef(_getCurrentLocation(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getTokenLocation = jlookup<
+  static final _getTokenLocation = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonParser_getTokenLocation")
@@ -2095,10 +2462,13 @@
   /// Alias for \#currentTokenLocation(), to be deprecated in later
   /// Jackson 2.x versions (and removed from Jackson 3.0).
   ///@return Starting location of the token parser currently points to
-  jni.JlObject getTokenLocation() =>
-      jni.JlObject.fromRef(_getTokenLocation(reference));
+  jni.JniObject getTokenLocation() {
+    final result__ = jni.JniObject.fromRef(_getTokenLocation(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _currentValue = jlookup<
+  static final _currentValue = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonParser_currentValue")
@@ -2118,9 +2488,13 @@
   /// and gets passed through data-binding.
   ///@return "Current value" associated with the current input context (state) of this parser
   ///@since 2.13 (added as replacement for older \#getCurrentValue()
-  jni.JlObject currentValue() => jni.JlObject.fromRef(_currentValue(reference));
+  jni.JniObject currentValue() {
+    final result__ = jni.JniObject.fromRef(_currentValue(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _assignCurrentValue = jlookup<
+  static final _assignCurrentValue = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -2136,10 +2510,13 @@
   ///</code>
   ///@param v Current value to assign for the current input context of this parser
   ///@since 2.13 (added as replacement for older \#setCurrentValue
-  void assignCurrentValue(jni.JlObject v) =>
-      _assignCurrentValue(reference, v.reference);
+  void assignCurrentValue(jni.JniObject v) {
+    final result__ = _assignCurrentValue(reference, v.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getCurrentValue = jlookup<
+  static final _getCurrentValue = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonParser_getCurrentValue")
@@ -2151,10 +2528,13 @@
   /// Alias for \#currentValue(), to be deprecated in later
   /// Jackson 2.x versions (and removed from Jackson 3.0).
   ///@return Location of the last processed input unit (byte or character)
-  jni.JlObject getCurrentValue() =>
-      jni.JlObject.fromRef(_getCurrentValue(reference));
+  jni.JniObject getCurrentValue() {
+    final result__ = jni.JniObject.fromRef(_getCurrentValue(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _setCurrentValue = jlookup<
+  static final _setCurrentValue = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -2167,10 +2547,13 @@
   /// Alias for \#assignCurrentValue, to be deprecated in later
   /// Jackson 2.x versions (and removed from Jackson 3.0).
   ///@param v Current value to assign for the current input context of this parser
-  void setCurrentValue(jni.JlObject v) =>
-      _setCurrentValue(reference, v.reference);
+  void setCurrentValue(jni.JniObject v) {
+    final result__ = _setCurrentValue(reference, v.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _releaseBuffered = jlookup<
+  static final _releaseBuffered = jniLookup<
               ffi.NativeFunction<
                   ffi.Int32 Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -2190,10 +2573,13 @@
   ///    (that is, input can not be sent to OutputStream;
   ///    otherwise number of bytes released (0 if there was nothing to release)
   ///@throws IOException if write to stream threw exception
-  int releaseBuffered(jni.JlObject out) =>
-      _releaseBuffered(reference, out.reference);
+  int releaseBuffered(jni.JniObject out) {
+    final result__ = _releaseBuffered(reference, out.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _releaseBuffered1 = jlookup<
+  static final _releaseBuffered1 = jniLookup<
               ffi.NativeFunction<
                   ffi.Int32 Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -2214,10 +2600,13 @@
   ///    (that is, input can not be sent to Writer;
   ///    otherwise number of chars released (0 if there was nothing to release)
   ///@throws IOException if write using Writer threw exception
-  int releaseBuffered1(jni.JlObject w) =>
-      _releaseBuffered1(reference, w.reference);
+  int releaseBuffered1(jni.JniObject w) {
+    final result__ = _releaseBuffered1(reference, w.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _enable = jlookup<
+  static final _enable = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -2233,10 +2622,13 @@
   /// (check Feature for list of features)
   ///@param f Feature to enable
   ///@return This parser, to allow call chaining
-  JsonParser enable(JsonParser_Feature f) =>
-      JsonParser.fromRef(_enable(reference, f.reference));
+  JsonParser enable(JsonParser_Feature f) {
+    final result__ = JsonParser.fromRef(_enable(reference, f.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _disable = jlookup<
+  static final _disable = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -2252,10 +2644,13 @@
   /// (check Feature for list of features)
   ///@param f Feature to disable
   ///@return This parser, to allow call chaining
-  JsonParser disable(JsonParser_Feature f) =>
-      JsonParser.fromRef(_disable(reference, f.reference));
+  JsonParser disable(JsonParser_Feature f) {
+    final result__ = JsonParser.fromRef(_disable(reference, f.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _configure = jlookup<
+  static final _configure = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>,
                       ffi.Pointer<ffi.Void>, ffi.Uint8)>>(
@@ -2272,10 +2667,14 @@
   ///@param f Feature to enable or disable
   ///@param state Whether to enable feature ({@code true}) or disable ({@code false})
   ///@return This parser, to allow call chaining
-  JsonParser configure(JsonParser_Feature f, bool state) =>
-      JsonParser.fromRef(_configure(reference, f.reference, state ? 1 : 0));
+  JsonParser configure(JsonParser_Feature f, bool state) {
+    final result__ =
+        JsonParser.fromRef(_configure(reference, f.reference, state ? 1 : 0));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _isEnabled = jlookup<
+  static final _isEnabled = jniLookup<
               ffi.NativeFunction<
                   ffi.Uint8 Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -2287,10 +2686,13 @@
   /// Method for checking whether specified Feature is enabled.
   ///@param f Feature to check
   ///@return {@code True} if feature is enabled; {@code false} otherwise
-  bool isEnabled(JsonParser_Feature f) =>
-      _isEnabled(reference, f.reference) != 0;
+  bool isEnabled(JsonParser_Feature f) {
+    final result__ = _isEnabled(reference, f.reference) != 0;
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _isEnabled1 = jlookup<
+  static final _isEnabled1 = jniLookup<
               ffi.NativeFunction<
                   ffi.Uint8 Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -2303,10 +2705,14 @@
   ///@param f Feature to check
   ///@return {@code True} if feature is enabled; {@code false} otherwise
   ///@since 2.10
-  bool isEnabled1(jni.JlObject f) => _isEnabled1(reference, f.reference) != 0;
+  bool isEnabled1(jni.JniObject f) {
+    final result__ = _isEnabled1(reference, f.reference) != 0;
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _getFeatureMask =
-      jlookup<ffi.NativeFunction<ffi.Int32 Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Int32 Function(ffi.Pointer<ffi.Void>)>>(
               "com_fasterxml_jackson_core_JsonParser_getFeatureMask")
           .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
@@ -2315,9 +2721,13 @@
   /// Bulk access method for getting state of all standard Features.
   ///@return Bit mask that defines current states of all standard Features.
   ///@since 2.3
-  int getFeatureMask() => _getFeatureMask(reference);
+  int getFeatureMask() {
+    final result__ = _getFeatureMask(reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _setFeatureMask = jlookup<
+  static final _setFeatureMask = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Int32)>>(
@@ -2332,10 +2742,13 @@
   ///@return This parser, to allow call chaining
   ///@since 2.3
   ///@deprecated Since 2.7, use \#overrideStdFeatures(int, int) instead
-  JsonParser setFeatureMask(int mask) =>
-      JsonParser.fromRef(_setFeatureMask(reference, mask));
+  JsonParser setFeatureMask(int mask) {
+    final result__ = JsonParser.fromRef(_setFeatureMask(reference, mask));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _overrideStdFeatures = jlookup<
+  static final _overrideStdFeatures = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Int32, ffi.Int32)>>(
@@ -2358,11 +2771,15 @@
   ///@param mask Bit mask of features to change
   ///@return This parser, to allow call chaining
   ///@since 2.6
-  JsonParser overrideStdFeatures(int values, int mask) =>
-      JsonParser.fromRef(_overrideStdFeatures(reference, values, mask));
+  JsonParser overrideStdFeatures(int values, int mask) {
+    final result__ =
+        JsonParser.fromRef(_overrideStdFeatures(reference, values, mask));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _getFormatFeatures =
-      jlookup<ffi.NativeFunction<ffi.Int32 Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Int32 Function(ffi.Pointer<ffi.Void>)>>(
               "com_fasterxml_jackson_core_JsonParser_getFormatFeatures")
           .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
@@ -2372,9 +2789,13 @@
   /// on/off configuration settings.
   ///@return Bit mask that defines current states of all standard FormatFeatures.
   ///@since 2.6
-  int getFormatFeatures() => _getFormatFeatures(reference);
+  int getFormatFeatures() {
+    final result__ = _getFormatFeatures(reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _overrideFormatFeatures = jlookup<
+  static final _overrideFormatFeatures = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Int32, ffi.Int32)>>(
@@ -2395,10 +2816,14 @@
   ///@param mask Bit mask of features to change
   ///@return This parser, to allow call chaining
   ///@since 2.6
-  JsonParser overrideFormatFeatures(int values, int mask) =>
-      JsonParser.fromRef(_overrideFormatFeatures(reference, values, mask));
+  JsonParser overrideFormatFeatures(int values, int mask) {
+    final result__ =
+        JsonParser.fromRef(_overrideFormatFeatures(reference, values, mask));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _nextToken = jlookup<
+  static final _nextToken = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonParser_nextToken")
@@ -2415,9 +2840,13 @@
   ///   to indicate end-of-input
   ///@throws IOException for low-level read issues, or
   ///   JsonParseException for decoding problems
-  JsonToken nextToken() => JsonToken.fromRef(_nextToken(reference));
+  JsonToken nextToken() {
+    final result__ = JsonToken.fromRef(_nextToken(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _nextValue = jlookup<
+  static final _nextValue = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonParser_nextValue")
@@ -2442,9 +2871,13 @@
   ///   available yet)
   ///@throws IOException for low-level read issues, or
   ///   JsonParseException for decoding problems
-  JsonToken nextValue() => JsonToken.fromRef(_nextValue(reference));
+  JsonToken nextValue() {
+    final result__ = JsonToken.fromRef(_nextValue(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _nextFieldName = jlookup<
+  static final _nextFieldName = jniLookup<
               ffi.NativeFunction<
                   ffi.Uint8 Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -2468,10 +2901,13 @@
   ///    specified name; {@code false} otherwise (different token or non-matching name)
   ///@throws IOException for low-level read issues, or
   ///   JsonParseException for decoding problems
-  bool nextFieldName(jni.JlObject str) =>
-      _nextFieldName(reference, str.reference) != 0;
+  bool nextFieldName(jni.JniObject str) {
+    final result__ = _nextFieldName(reference, str.reference) != 0;
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _nextFieldName1 = jlookup<
+  static final _nextFieldName1 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonParser_nextFieldName1")
@@ -2488,10 +2924,13 @@
   ///@throws IOException for low-level read issues, or
   ///   JsonParseException for decoding problems
   ///@since 2.5
-  jni.JlString nextFieldName1() =>
-      jni.JlString.fromRef(_nextFieldName1(reference));
+  jni.JniString nextFieldName1() {
+    final result__ = jni.JniString.fromRef(_nextFieldName1(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _nextTextValue = jlookup<
+  static final _nextTextValue = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonParser_nextTextValue")
@@ -2513,10 +2952,13 @@
   ///   to; or {@code null} if next token is of some other type
   ///@throws IOException for low-level read issues, or
   ///   JsonParseException for decoding problems
-  jni.JlString nextTextValue() =>
-      jni.JlString.fromRef(_nextTextValue(reference));
+  jni.JniString nextTextValue() {
+    final result__ = jni.JniString.fromRef(_nextTextValue(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _nextIntValue = jlookup<
+  static final _nextIntValue = jniLookup<
               ffi.NativeFunction<
                   ffi.Int32 Function(ffi.Pointer<ffi.Void>, ffi.Int32)>>(
           "com_fasterxml_jackson_core_JsonParser_nextIntValue")
@@ -2541,9 +2983,13 @@
   ///@throws IOException for low-level read issues, or
   ///   JsonParseException for decoding problems
   ///@throws InputCoercionException if integer number does not fit in Java {@code int}
-  int nextIntValue(int defaultValue) => _nextIntValue(reference, defaultValue);
+  int nextIntValue(int defaultValue) {
+    final result__ = _nextIntValue(reference, defaultValue);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _nextLongValue = jlookup<
+  static final _nextLongValue = jniLookup<
               ffi.NativeFunction<
                   ffi.Int64 Function(ffi.Pointer<ffi.Void>, ffi.Int64)>>(
           "com_fasterxml_jackson_core_JsonParser_nextLongValue")
@@ -2568,10 +3014,13 @@
   ///@throws IOException for low-level read issues, or
   ///   JsonParseException for decoding problems
   ///@throws InputCoercionException if integer number does not fit in Java {@code long}
-  int nextLongValue(int defaultValue) =>
-      _nextLongValue(reference, defaultValue);
+  int nextLongValue(int defaultValue) {
+    final result__ = _nextLongValue(reference, defaultValue);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _nextBooleanValue = jlookup<
+  static final _nextBooleanValue = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonParser_nextBooleanValue")
@@ -2596,10 +3045,13 @@
   ///   token parser advanced to; or {@code null} if next token is of some other type
   ///@throws IOException for low-level read issues, or
   ///   JsonParseException for decoding problems
-  jni.JlObject nextBooleanValue() =>
-      jni.JlObject.fromRef(_nextBooleanValue(reference));
+  jni.JniObject nextBooleanValue() {
+    final result__ = jni.JniObject.fromRef(_nextBooleanValue(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _skipChildren = jlookup<
+  static final _skipChildren = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonParser_skipChildren")
@@ -2623,10 +3075,14 @@
   ///@return This parser, to allow call chaining
   ///@throws IOException for low-level read issues, or
   ///   JsonParseException for decoding problems
-  JsonParser skipChildren() => JsonParser.fromRef(_skipChildren(reference));
+  JsonParser skipChildren() {
+    final result__ = JsonParser.fromRef(_skipChildren(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _finishToken =
-      jlookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
               "com_fasterxml_jackson_core_JsonParser_finishToken")
           .asFunction<void Function(ffi.Pointer<ffi.Void>)>();
 
@@ -2645,9 +3101,13 @@
   ///@throws IOException for low-level read issues, or
   ///   JsonParseException for decoding problems
   ///@since 2.8
-  void finishToken() => _finishToken(reference);
+  void finishToken() {
+    final result__ = _finishToken(reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _currentToken = jlookup<
+  static final _currentToken = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonParser_currentToken")
@@ -2665,10 +3125,14 @@
   ///   after end-of-input has been encountered, as well as
   ///   if the current token has been explicitly cleared.
   ///@since 2.8
-  JsonToken currentToken() => JsonToken.fromRef(_currentToken(reference));
+  JsonToken currentToken() {
+    final result__ = JsonToken.fromRef(_currentToken(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _currentTokenId =
-      jlookup<ffi.NativeFunction<ffi.Int32 Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Int32 Function(ffi.Pointer<ffi.Void>)>>(
               "com_fasterxml_jackson_core_JsonParser_currentTokenId")
           .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
@@ -2683,9 +3147,13 @@
   /// to profile performance before deciding to use this method.
   ///@since 2.8
   ///@return {@code int} matching one of constants from JsonTokenId.
-  int currentTokenId() => _currentTokenId(reference);
+  int currentTokenId() {
+    final result__ = _currentTokenId(reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getCurrentToken = jlookup<
+  static final _getCurrentToken = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonParser_getCurrentToken")
@@ -2698,10 +3166,14 @@
   /// Jackson 2.13 (will be removed from 3.0).
   ///@return Type of the token this parser currently points to,
   ///   if any: null before any tokens have been read, and
-  JsonToken getCurrentToken() => JsonToken.fromRef(_getCurrentToken(reference));
+  JsonToken getCurrentToken() {
+    final result__ = JsonToken.fromRef(_getCurrentToken(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _getCurrentTokenId =
-      jlookup<ffi.NativeFunction<ffi.Int32 Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Int32 Function(ffi.Pointer<ffi.Void>)>>(
               "com_fasterxml_jackson_core_JsonParser_getCurrentTokenId")
           .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
@@ -2710,10 +3182,14 @@
   /// Deprecated alias for \#currentTokenId().
   ///@return {@code int} matching one of constants from JsonTokenId.
   ///@deprecated Since 2.12 use \#currentTokenId instead
-  int getCurrentTokenId() => _getCurrentTokenId(reference);
+  int getCurrentTokenId() {
+    final result__ = _getCurrentTokenId(reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _hasCurrentToken =
-      jlookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
               "com_fasterxml_jackson_core_JsonParser_hasCurrentToken")
           .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
@@ -2727,9 +3203,13 @@
   ///   was just constructed, encountered end-of-input
   ///   and returned null from \#nextToken, or the token
   ///   has been consumed)
-  bool hasCurrentToken() => _hasCurrentToken(reference) != 0;
+  bool hasCurrentToken() {
+    final result__ = _hasCurrentToken(reference) != 0;
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _hasTokenId = jlookup<
+  static final _hasTokenId = jniLookup<
               ffi.NativeFunction<
                   ffi.Uint8 Function(ffi.Pointer<ffi.Void>, ffi.Int32)>>(
           "com_fasterxml_jackson_core_JsonParser_hasTokenId")
@@ -2749,9 +3229,13 @@
   ///@param id Token id to match (from (@link JsonTokenId})
   ///@return {@code True} if the parser current points to specified token
   ///@since 2.5
-  bool hasTokenId(int id) => _hasTokenId(reference, id) != 0;
+  bool hasTokenId(int id) {
+    final result__ = _hasTokenId(reference, id) != 0;
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _hasToken = jlookup<
+  static final _hasToken = jniLookup<
               ffi.NativeFunction<
                   ffi.Uint8 Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -2772,10 +3256,14 @@
   ///@param t Token to match
   ///@return {@code True} if the parser current points to specified token
   ///@since 2.6
-  bool hasToken(JsonToken t) => _hasToken(reference, t.reference) != 0;
+  bool hasToken(JsonToken t) {
+    final result__ = _hasToken(reference, t.reference) != 0;
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _isExpectedStartArrayToken =
-      jlookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
               "com_fasterxml_jackson_core_JsonParser_isExpectedStartArrayToken")
           .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
@@ -2797,10 +3285,13 @@
   ///@return True if the current token can be considered as a
   ///   start-array marker (such JsonToken\#START_ARRAY);
   ///   {@code false} if not
-  bool isExpectedStartArrayToken() =>
-      _isExpectedStartArrayToken(reference) != 0;
+  bool isExpectedStartArrayToken() {
+    final result__ = _isExpectedStartArrayToken(reference) != 0;
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _isExpectedStartObjectToken = jlookup<
+  static final _isExpectedStartObjectToken = jniLookup<
               ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonParser_isExpectedStartObjectToken")
       .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
@@ -2813,11 +3304,14 @@
   ///   start-array marker (such JsonToken\#START_OBJECT);
   ///   {@code false} if not
   ///@since 2.5
-  bool isExpectedStartObjectToken() =>
-      _isExpectedStartObjectToken(reference) != 0;
+  bool isExpectedStartObjectToken() {
+    final result__ = _isExpectedStartObjectToken(reference) != 0;
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _isExpectedNumberIntToken =
-      jlookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
               "com_fasterxml_jackson_core_JsonParser_isExpectedNumberIntToken")
           .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
@@ -2832,10 +3326,14 @@
   ///   start-array marker (such JsonToken\#VALUE_NUMBER_INT);
   ///   {@code false} if not
   ///@since 2.12
-  bool isExpectedNumberIntToken() => _isExpectedNumberIntToken(reference) != 0;
+  bool isExpectedNumberIntToken() {
+    final result__ = _isExpectedNumberIntToken(reference) != 0;
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _isNaN =
-      jlookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
               "com_fasterxml_jackson_core_JsonParser_isNaN")
           .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
@@ -2853,10 +3351,14 @@
   ///@throws IOException for low-level read issues, or
   ///   JsonParseException for decoding problems
   ///@since 2.9
-  bool isNaN() => _isNaN(reference) != 0;
+  bool isNaN() {
+    final result__ = _isNaN(reference) != 0;
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _clearCurrentToken =
-      jlookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
               "com_fasterxml_jackson_core_JsonParser_clearCurrentToken")
           .asFunction<void Function(ffi.Pointer<ffi.Void>)>();
 
@@ -2872,9 +3374,13 @@
   /// Method was added to be used by the optional data binder, since
   /// it has to be able to consume last token used for binding (so that
   /// it will not be used again).
-  void clearCurrentToken() => _clearCurrentToken(reference);
+  void clearCurrentToken() {
+    final result__ = _clearCurrentToken(reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getLastClearedToken = jlookup<
+  static final _getLastClearedToken = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonParser_getLastClearedToken")
@@ -2889,10 +3395,13 @@
   /// Will return null if no tokens have been cleared,
   /// or if parser has been closed.
   ///@return Last cleared token, if any; {@code null} otherwise
-  JsonToken getLastClearedToken() =>
-      JsonToken.fromRef(_getLastClearedToken(reference));
+  JsonToken getLastClearedToken() {
+    final result__ = JsonToken.fromRef(_getLastClearedToken(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _overrideCurrentName = jlookup<
+  static final _overrideCurrentName = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -2910,10 +3419,13 @@
   /// Note that use of this method should only be done as sort of last
   /// resort, as it is a work-around for regular operation.
   ///@param name Name to use as the current name; may be null.
-  void overrideCurrentName(jni.JlString name) =>
-      _overrideCurrentName(reference, name.reference);
+  void overrideCurrentName(jni.JniString name) {
+    final result__ = _overrideCurrentName(reference, name.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getCurrentName = jlookup<
+  static final _getCurrentName = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonParser_getCurrentName")
@@ -2926,10 +3438,13 @@
   ///@return Name of the current field in the parsing context
   ///@throws IOException for low-level read issues, or
   ///   JsonParseException for decoding problems
-  jni.JlString getCurrentName() =>
-      jni.JlString.fromRef(_getCurrentName(reference));
+  jni.JniString getCurrentName() {
+    final result__ = jni.JniString.fromRef(_getCurrentName(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _currentName = jlookup<
+  static final _currentName = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonParser_currentName")
@@ -2947,9 +3462,13 @@
   ///@throws IOException for low-level read issues, or
   ///   JsonParseException for decoding problems
   ///@since 2.10
-  jni.JlString currentName() => jni.JlString.fromRef(_currentName(reference));
+  jni.JniString currentName() {
+    final result__ = jni.JniString.fromRef(_currentName(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getText = jlookup<
+  static final _getText = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonParser_getText")
@@ -2966,9 +3485,13 @@
   ///   by \#nextToken() or other iteration methods)
   ///@throws IOException for low-level read issues, or
   ///   JsonParseException for decoding problems
-  jni.JlString getText() => jni.JlString.fromRef(_getText(reference));
+  jni.JniString getText() {
+    final result__ = jni.JniString.fromRef(_getText(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getText1 = jlookup<
+  static final _getText1 = jniLookup<
               ffi.NativeFunction<
                   ffi.Int32 Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -2992,9 +3515,13 @@
   ///   {@code writer}, or
   ///   JsonParseException for decoding problems
   ///@since 2.8
-  int getText1(jni.JlObject writer) => _getText1(reference, writer.reference);
+  int getText1(jni.JniObject writer) {
+    final result__ = _getText1(reference, writer.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getTextCharacters = jlookup<
+  static final _getTextCharacters = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonParser_getTextCharacters")
@@ -3030,11 +3557,14 @@
   ///    at offset 0, and not necessarily until the end of buffer)
   ///@throws IOException for low-level read issues, or
   ///   JsonParseException for decoding problems
-  jni.JlObject getTextCharacters() =>
-      jni.JlObject.fromRef(_getTextCharacters(reference));
+  jni.JniObject getTextCharacters() {
+    final result__ = jni.JniObject.fromRef(_getTextCharacters(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _getTextLength =
-      jlookup<ffi.NativeFunction<ffi.Int32 Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Int32 Function(ffi.Pointer<ffi.Void>)>>(
               "com_fasterxml_jackson_core_JsonParser_getTextLength")
           .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
@@ -3047,10 +3577,14 @@
   ///   textual content of the current token.
   ///@throws IOException for low-level read issues, or
   ///   JsonParseException for decoding problems
-  int getTextLength() => _getTextLength(reference);
+  int getTextLength() {
+    final result__ = _getTextLength(reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _getTextOffset =
-      jlookup<ffi.NativeFunction<ffi.Int32 Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Int32 Function(ffi.Pointer<ffi.Void>)>>(
               "com_fasterxml_jackson_core_JsonParser_getTextOffset")
           .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
@@ -3063,10 +3597,14 @@
   ///   textual content of the current token.
   ///@throws IOException for low-level read issues, or
   ///   JsonParseException for decoding problems
-  int getTextOffset() => _getTextOffset(reference);
+  int getTextOffset() {
+    final result__ = _getTextOffset(reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _hasTextCharacters =
-      jlookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
               "com_fasterxml_jackson_core_JsonParser_hasTextCharacters")
           .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
@@ -3086,9 +3624,13 @@
   ///@return True if parser currently has character array that can
   ///   be efficiently returned via \#getTextCharacters; false
   ///   means that it may or may not exist
-  bool hasTextCharacters() => _hasTextCharacters(reference) != 0;
+  bool hasTextCharacters() {
+    final result__ = _hasTextCharacters(reference) != 0;
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getNumberValue = jlookup<
+  static final _getNumberValue = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonParser_getNumberValue")
@@ -3107,10 +3649,13 @@
   ///    the current token is not numeric, or if decoding of the value fails
   ///    (invalid format for numbers); plain IOException if underlying
   ///    content read fails (possible if values are extracted lazily)
-  jni.JlObject getNumberValue() =>
-      jni.JlObject.fromRef(_getNumberValue(reference));
+  jni.JniObject getNumberValue() {
+    final result__ = jni.JniObject.fromRef(_getNumberValue(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getNumberValueExact = jlookup<
+  static final _getNumberValueExact = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonParser_getNumberValueExact")
@@ -3133,10 +3678,13 @@
   ///    (invalid format for numbers); plain IOException if underlying
   ///    content read fails (possible if values are extracted lazily)
   ///@since 2.12
-  jni.JlObject getNumberValueExact() =>
-      jni.JlObject.fromRef(_getNumberValueExact(reference));
+  jni.JniObject getNumberValueExact() {
+    final result__ = jni.JniObject.fromRef(_getNumberValueExact(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getNumberType = jlookup<
+  static final _getNumberType = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonParser_getNumberType")
@@ -3152,11 +3700,14 @@
   ///@return Type of current number, if parser points to numeric token; {@code null} otherwise
   ///@throws IOException for low-level read issues, or
   ///   JsonParseException for decoding problems
-  JsonParser_NumberType getNumberType() =>
-      JsonParser_NumberType.fromRef(_getNumberType(reference));
+  JsonParser_NumberType getNumberType() {
+    final result__ = JsonParser_NumberType.fromRef(_getNumberType(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _getByteValue =
-      jlookup<ffi.NativeFunction<ffi.Int8 Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Int8 Function(ffi.Pointer<ffi.Void>)>>(
               "com_fasterxml_jackson_core_JsonParser_getByteValue")
           .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
@@ -3183,10 +3734,14 @@
   ///   range of {@code [-128, 255]}); otherwise exception thrown
   ///@throws IOException for low-level read issues, or
   ///   JsonParseException for decoding problems
-  int getByteValue() => _getByteValue(reference);
+  int getByteValue() {
+    final result__ = _getByteValue(reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _getShortValue =
-      jlookup<ffi.NativeFunction<ffi.Int16 Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Int16 Function(ffi.Pointer<ffi.Void>)>>(
               "com_fasterxml_jackson_core_JsonParser_getShortValue")
           .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
@@ -3207,10 +3762,14 @@
   ///   Java 16-bit signed {@code short} range); otherwise exception thrown
   ///@throws IOException for low-level read issues, or
   ///   JsonParseException for decoding problems
-  int getShortValue() => _getShortValue(reference);
+  int getShortValue() {
+    final result__ = _getShortValue(reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _getIntValue =
-      jlookup<ffi.NativeFunction<ffi.Int32 Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Int32 Function(ffi.Pointer<ffi.Void>)>>(
               "com_fasterxml_jackson_core_JsonParser_getIntValue")
           .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
@@ -3231,10 +3790,14 @@
   ///   Java 32-bit signed {@code int} range); otherwise exception thrown
   ///@throws IOException for low-level read issues, or
   ///   JsonParseException for decoding problems
-  int getIntValue() => _getIntValue(reference);
+  int getIntValue() {
+    final result__ = _getIntValue(reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _getLongValue =
-      jlookup<ffi.NativeFunction<ffi.Int64 Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Int64 Function(ffi.Pointer<ffi.Void>)>>(
               "com_fasterxml_jackson_core_JsonParser_getLongValue")
           .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
@@ -3255,9 +3818,13 @@
   ///   Java 32-bit signed {@code long} range); otherwise exception thrown
   ///@throws IOException for low-level read issues, or
   ///   JsonParseException for decoding problems
-  int getLongValue() => _getLongValue(reference);
+  int getLongValue() {
+    final result__ = _getLongValue(reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getBigIntegerValue = jlookup<
+  static final _getBigIntegerValue = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonParser_getBigIntegerValue")
@@ -3277,11 +3844,14 @@
   ///     otherwise exception thrown
   ///@throws IOException for low-level read issues, or
   ///   JsonParseException for decoding problems
-  jni.JlObject getBigIntegerValue() =>
-      jni.JlObject.fromRef(_getBigIntegerValue(reference));
+  jni.JniObject getBigIntegerValue() {
+    final result__ = jni.JniObject.fromRef(_getBigIntegerValue(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _getFloatValue =
-      jlookup<ffi.NativeFunction<ffi.Float Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Float Function(ffi.Pointer<ffi.Void>)>>(
               "com_fasterxml_jackson_core_JsonParser_getFloatValue")
           .asFunction<double Function(ffi.Pointer<ffi.Void>)>();
 
@@ -3302,10 +3872,14 @@
   ///   Java {@code float} range); otherwise exception thrown
   ///@throws IOException for low-level read issues, or
   ///   JsonParseException for decoding problems
-  double getFloatValue() => _getFloatValue(reference);
+  double getFloatValue() {
+    final result__ = _getFloatValue(reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _getDoubleValue =
-      jlookup<ffi.NativeFunction<ffi.Double Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Double Function(ffi.Pointer<ffi.Void>)>>(
               "com_fasterxml_jackson_core_JsonParser_getDoubleValue")
           .asFunction<double Function(ffi.Pointer<ffi.Void>)>();
 
@@ -3326,9 +3900,13 @@
   ///   Java {@code double} range); otherwise exception thrown
   ///@throws IOException for low-level read issues, or
   ///   JsonParseException for decoding problems
-  double getDoubleValue() => _getDoubleValue(reference);
+  double getDoubleValue() {
+    final result__ = _getDoubleValue(reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getDecimalValue = jlookup<
+  static final _getDecimalValue = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonParser_getDecimalValue")
@@ -3345,11 +3923,14 @@
   ///   otherwise exception thrown
   ///@throws IOException for low-level read issues, or
   ///   JsonParseException for decoding problems
-  jni.JlObject getDecimalValue() =>
-      jni.JlObject.fromRef(_getDecimalValue(reference));
+  jni.JniObject getDecimalValue() {
+    final result__ = jni.JniObject.fromRef(_getDecimalValue(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _getBooleanValue =
-      jlookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
               "com_fasterxml_jackson_core_JsonParser_getBooleanValue")
           .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
@@ -3366,9 +3947,13 @@
   ///   otherwise throws JsonParseException
   ///@throws IOException for low-level read issues, or
   ///   JsonParseException for decoding problems
-  bool getBooleanValue() => _getBooleanValue(reference) != 0;
+  bool getBooleanValue() {
+    final result__ = _getBooleanValue(reference) != 0;
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getEmbeddedObject = jlookup<
+  static final _getEmbeddedObject = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonParser_getEmbeddedObject")
@@ -3391,10 +3976,13 @@
   ///   for the current token, if any; {@code null otherwise}
   ///@throws IOException for low-level read issues, or
   ///   JsonParseException for decoding problems
-  jni.JlObject getEmbeddedObject() =>
-      jni.JlObject.fromRef(_getEmbeddedObject(reference));
+  jni.JniObject getEmbeddedObject() {
+    final result__ = jni.JniObject.fromRef(_getEmbeddedObject(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getBinaryValue = jlookup<
+  static final _getBinaryValue = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -3426,10 +4014,14 @@
   ///@return Decoded binary data
   ///@throws IOException for low-level read issues, or
   ///   JsonParseException for decoding problems
-  jni.JlObject getBinaryValue(jni.JlObject bv) =>
-      jni.JlObject.fromRef(_getBinaryValue(reference, bv.reference));
+  jni.JniObject getBinaryValue(jni.JniObject bv) {
+    final result__ =
+        jni.JniObject.fromRef(_getBinaryValue(reference, bv.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getBinaryValue1 = jlookup<
+  static final _getBinaryValue1 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonParser_getBinaryValue1")
@@ -3444,10 +4036,13 @@
   ///@return Decoded binary data
   ///@throws IOException for low-level read issues, or
   ///   JsonParseException for decoding problems
-  jni.JlObject getBinaryValue1() =>
-      jni.JlObject.fromRef(_getBinaryValue1(reference));
+  jni.JniObject getBinaryValue1() {
+    final result__ = jni.JniObject.fromRef(_getBinaryValue1(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _readBinaryValue = jlookup<
+  static final _readBinaryValue = jniLookup<
               ffi.NativeFunction<
                   ffi.Int32 Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -3467,10 +4062,13 @@
   ///@throws IOException for low-level read issues, or
   ///   JsonParseException for decoding problems
   ///@since 2.1
-  int readBinaryValue(jni.JlObject out) =>
-      _readBinaryValue(reference, out.reference);
+  int readBinaryValue(jni.JniObject out) {
+    final result__ = _readBinaryValue(reference, out.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _readBinaryValue1 = jlookup<
+  static final _readBinaryValue1 = jniLookup<
               ffi.NativeFunction<
                   ffi.Int32 Function(ffi.Pointer<ffi.Void>,
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -3489,11 +4087,14 @@
   ///@throws IOException for low-level read issues, or
   ///   JsonParseException for decoding problems
   ///@since 2.1
-  int readBinaryValue1(jni.JlObject bv, jni.JlObject out) =>
-      _readBinaryValue1(reference, bv.reference, out.reference);
+  int readBinaryValue1(jni.JniObject bv, jni.JniObject out) {
+    final result__ = _readBinaryValue1(reference, bv.reference, out.reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _getValueAsInt =
-      jlookup<ffi.NativeFunction<ffi.Int32 Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Int32 Function(ffi.Pointer<ffi.Void>)>>(
               "com_fasterxml_jackson_core_JsonParser_getValueAsInt")
           .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
@@ -3512,9 +4113,13 @@
   ///    otherwise
   ///@throws IOException for low-level read issues, or
   ///   JsonParseException for decoding problems
-  int getValueAsInt() => _getValueAsInt(reference);
+  int getValueAsInt() {
+    final result__ = _getValueAsInt(reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getValueAsInt1 = jlookup<
+  static final _getValueAsInt1 = jniLookup<
               ffi.NativeFunction<
                   ffi.Int32 Function(ffi.Pointer<ffi.Void>, ffi.Int32)>>(
           "com_fasterxml_jackson_core_JsonParser_getValueAsInt1")
@@ -3535,10 +4140,14 @@
   ///@return {@code int} value current token is converted to, if possible; {@code def} otherwise
   ///@throws IOException for low-level read issues, or
   ///   JsonParseException for decoding problems
-  int getValueAsInt1(int def) => _getValueAsInt1(reference, def);
+  int getValueAsInt1(int def) {
+    final result__ = _getValueAsInt1(reference, def);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _getValueAsLong =
-      jlookup<ffi.NativeFunction<ffi.Int64 Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Int64 Function(ffi.Pointer<ffi.Void>)>>(
               "com_fasterxml_jackson_core_JsonParser_getValueAsLong")
           .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
@@ -3557,9 +4166,13 @@
   ///    otherwise
   ///@throws IOException for low-level read issues, or
   ///   JsonParseException for decoding problems
-  int getValueAsLong() => _getValueAsLong(reference);
+  int getValueAsLong() {
+    final result__ = _getValueAsLong(reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getValueAsLong1 = jlookup<
+  static final _getValueAsLong1 = jniLookup<
               ffi.NativeFunction<
                   ffi.Int64 Function(ffi.Pointer<ffi.Void>, ffi.Int64)>>(
           "com_fasterxml_jackson_core_JsonParser_getValueAsLong1")
@@ -3580,10 +4193,14 @@
   ///@return {@code long} value current token is converted to, if possible; {@code def} otherwise
   ///@throws IOException for low-level read issues, or
   ///   JsonParseException for decoding problems
-  int getValueAsLong1(int def) => _getValueAsLong1(reference, def);
+  int getValueAsLong1(int def) {
+    final result__ = _getValueAsLong1(reference, def);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _getValueAsDouble =
-      jlookup<ffi.NativeFunction<ffi.Double Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Double Function(ffi.Pointer<ffi.Void>)>>(
               "com_fasterxml_jackson_core_JsonParser_getValueAsDouble")
           .asFunction<double Function(ffi.Pointer<ffi.Void>)>();
 
@@ -3602,9 +4219,13 @@
   ///    otherwise
   ///@throws IOException for low-level read issues, or
   ///   JsonParseException for decoding problems
-  double getValueAsDouble() => _getValueAsDouble(reference);
+  double getValueAsDouble() {
+    final result__ = _getValueAsDouble(reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getValueAsDouble1 = jlookup<
+  static final _getValueAsDouble1 = jniLookup<
               ffi.NativeFunction<
                   ffi.Double Function(ffi.Pointer<ffi.Void>, ffi.Double)>>(
           "com_fasterxml_jackson_core_JsonParser_getValueAsDouble1")
@@ -3625,10 +4246,14 @@
   ///@return {@code double} value current token is converted to, if possible; {@code def} otherwise
   ///@throws IOException for low-level read issues, or
   ///   JsonParseException for decoding problems
-  double getValueAsDouble1(double def) => _getValueAsDouble1(reference, def);
+  double getValueAsDouble1(double def) {
+    final result__ = _getValueAsDouble1(reference, def);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _getValueAsBoolean =
-      jlookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
               "com_fasterxml_jackson_core_JsonParser_getValueAsBoolean")
           .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
@@ -3647,9 +4272,13 @@
   ///    otherwise
   ///@throws IOException for low-level read issues, or
   ///   JsonParseException for decoding problems
-  bool getValueAsBoolean() => _getValueAsBoolean(reference) != 0;
+  bool getValueAsBoolean() {
+    final result__ = _getValueAsBoolean(reference) != 0;
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getValueAsBoolean1 = jlookup<
+  static final _getValueAsBoolean1 = jniLookup<
               ffi.NativeFunction<
                   ffi.Uint8 Function(ffi.Pointer<ffi.Void>, ffi.Uint8)>>(
           "com_fasterxml_jackson_core_JsonParser_getValueAsBoolean1")
@@ -3670,10 +4299,13 @@
   ///@return {@code boolean} value current token is converted to, if possible; {@code def} otherwise
   ///@throws IOException for low-level read issues, or
   ///   JsonParseException for decoding problems
-  bool getValueAsBoolean1(bool def) =>
-      _getValueAsBoolean1(reference, def ? 1 : 0) != 0;
+  bool getValueAsBoolean1(bool def) {
+    final result__ = _getValueAsBoolean1(reference, def ? 1 : 0) != 0;
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getValueAsString = jlookup<
+  static final _getValueAsString = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonParser_getValueAsString")
@@ -3693,10 +4325,13 @@
   ///@throws IOException for low-level read issues, or
   ///   JsonParseException for decoding problems
   ///@since 2.1
-  jni.JlString getValueAsString() =>
-      jni.JlString.fromRef(_getValueAsString(reference));
+  jni.JniString getValueAsString() {
+    final result__ = jni.JniString.fromRef(_getValueAsString(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getValueAsString1 = jlookup<
+  static final _getValueAsString1 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -3720,11 +4355,15 @@
   ///@throws IOException for low-level read issues, or
   ///   JsonParseException for decoding problems
   ///@since 2.1
-  jni.JlString getValueAsString1(jni.JlString def) =>
-      jni.JlString.fromRef(_getValueAsString1(reference, def.reference));
+  jni.JniString getValueAsString1(jni.JniString def) {
+    final result__ =
+        jni.JniString.fromRef(_getValueAsString1(reference, def.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _canReadObjectId =
-      jlookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
               "com_fasterxml_jackson_core_JsonParser_canReadObjectId")
           .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
@@ -3741,10 +4380,14 @@
   ///@return {@code True} if the format being read supports native Object Ids;
   ///    {@code false} if not
   ///@since 2.3
-  bool canReadObjectId() => _canReadObjectId(reference) != 0;
+  bool canReadObjectId() {
+    final result__ = _canReadObjectId(reference) != 0;
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _canReadTypeId =
-      jlookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
               "com_fasterxml_jackson_core_JsonParser_canReadTypeId")
           .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
@@ -3761,9 +4404,13 @@
   ///@return {@code True} if the format being read supports native Type Ids;
   ///    {@code false} if not
   ///@since 2.3
-  bool canReadTypeId() => _canReadTypeId(reference) != 0;
+  bool canReadTypeId() {
+    final result__ = _canReadTypeId(reference) != 0;
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getObjectId = jlookup<
+  static final _getObjectId = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonParser_getObjectId")
@@ -3785,9 +4432,13 @@
   ///@throws IOException for low-level read issues, or
   ///   JsonParseException for decoding problems
   ///@since 2.3
-  jni.JlObject getObjectId() => jni.JlObject.fromRef(_getObjectId(reference));
+  jni.JniObject getObjectId() {
+    final result__ = jni.JniObject.fromRef(_getObjectId(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getTypeId = jlookup<
+  static final _getTypeId = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonParser_getTypeId")
@@ -3809,9 +4460,13 @@
   ///@throws IOException for low-level read issues, or
   ///   JsonParseException for decoding problems
   ///@since 2.3
-  jni.JlObject getTypeId() => jni.JlObject.fromRef(_getTypeId(reference));
+  jni.JniObject getTypeId() {
+    final result__ = jni.JniObject.fromRef(_getTypeId(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _readValuesAs = jlookup<
+  static final _readValuesAs = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -3831,10 +4486,14 @@
   ///@return Iterator for reading multiple Java values from content
   ///@throws IOException if there is either an underlying I/O problem or decoding
   ///    issue at format layer
-  jni.JlObject readValuesAs(jni.JlObject valueType) =>
-      jni.JlObject.fromRef(_readValuesAs(reference, valueType.reference));
+  jni.JniObject readValuesAs(jni.JniObject valueType) {
+    final result__ =
+        jni.JniObject.fromRef(_readValuesAs(reference, valueType.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _readValuesAs1 = jlookup<
+  static final _readValuesAs1 = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(
                       ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
@@ -3854,26 +4513,34 @@
   ///@return Iterator for reading multiple Java values from content
   ///@throws IOException if there is either an underlying I/O problem or decoding
   ///    issue at format layer
-  jni.JlObject readValuesAs1(jni.JlObject valueTypeRef) =>
-      jni.JlObject.fromRef(_readValuesAs1(reference, valueTypeRef.reference));
+  jni.JniObject readValuesAs1(jni.JniObject valueTypeRef) {
+    final result__ = jni.JniObject.fromRef(
+        _readValuesAs1(reference, valueTypeRef.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 }
 
 /// from: com.fasterxml.jackson.core.JsonParser$Feature
 ///
 /// Enumeration that defines all on/off features for parsers.
-class JsonParser_Feature extends jni.JlObject {
+class JsonParser_Feature extends jni.JniObject {
   JsonParser_Feature.fromRef(ffi.Pointer<ffi.Void> ref) : super.fromRef(ref);
 
   static final _values =
-      jlookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function()>>(
+      jniLookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function()>>(
               "com_fasterxml_jackson_core_JsonParser__Feature_values")
           .asFunction<ffi.Pointer<ffi.Void> Function()>();
 
   /// from: static public com.fasterxml.jackson.core.JsonParser.Feature[] values()
   /// The returned object must be deleted after use, by calling the `delete` method.
-  static jni.JlObject values() => jni.JlObject.fromRef(_values());
+  static jni.JniObject values() {
+    final result__ = jni.JniObject.fromRef(_values());
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _valueOf = jlookup<
+  static final _valueOf = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonParser__Feature_valueOf")
@@ -3881,11 +4548,14 @@
 
   /// from: static public com.fasterxml.jackson.core.JsonParser.Feature valueOf(java.lang.String name)
   /// The returned object must be deleted after use, by calling the `delete` method.
-  static JsonParser_Feature valueOf(jni.JlString name) =>
-      JsonParser_Feature.fromRef(_valueOf(name.reference));
+  static JsonParser_Feature valueOf(jni.JniString name) {
+    final result__ = JsonParser_Feature.fromRef(_valueOf(name.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _collectDefaults =
-      jlookup<ffi.NativeFunction<ffi.Int32 Function()>>(
+      jniLookup<ffi.NativeFunction<ffi.Int32 Function()>>(
               "com_fasterxml_jackson_core_JsonParser__Feature_collectDefaults")
           .asFunction<int Function()>();
 
@@ -3894,60 +4564,82 @@
   /// Method that calculates bit set (flags) of all features that
   /// are enabled by default.
   ///@return Bit mask of all features that are enabled by default
-  static int collectDefaults() => _collectDefaults();
+  static int collectDefaults() {
+    final result__ = _collectDefaults();
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _ctor =
-      jlookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function(ffi.Uint8)>>(
+      jniLookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function(ffi.Uint8)>>(
               "com_fasterxml_jackson_core_JsonParser__Feature_ctor")
           .asFunction<ffi.Pointer<ffi.Void> Function(int)>();
 
   /// from: private void <init>(boolean defaultState)
   JsonParser_Feature(bool defaultState)
-      : super.fromRef(_ctor(defaultState ? 1 : 0));
+      : super.fromRef(_ctor(defaultState ? 1 : 0)) {
+    jni.Jni.env.checkException();
+  }
 
   static final _enabledByDefault =
-      jlookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
               "com_fasterxml_jackson_core_JsonParser__Feature_enabledByDefault")
           .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
   /// from: public boolean enabledByDefault()
-  bool enabledByDefault() => _enabledByDefault(reference) != 0;
+  bool enabledByDefault() {
+    final result__ = _enabledByDefault(reference) != 0;
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _enabledIn = jlookup<
+  static final _enabledIn = jniLookup<
               ffi.NativeFunction<
                   ffi.Uint8 Function(ffi.Pointer<ffi.Void>, ffi.Int32)>>(
           "com_fasterxml_jackson_core_JsonParser__Feature_enabledIn")
       .asFunction<int Function(ffi.Pointer<ffi.Void>, int)>();
 
   /// from: public boolean enabledIn(int flags)
-  bool enabledIn(int flags) => _enabledIn(reference, flags) != 0;
+  bool enabledIn(int flags) {
+    final result__ = _enabledIn(reference, flags) != 0;
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _getMask =
-      jlookup<ffi.NativeFunction<ffi.Int32 Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Int32 Function(ffi.Pointer<ffi.Void>)>>(
               "com_fasterxml_jackson_core_JsonParser__Feature_getMask")
           .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
   /// from: public int getMask()
-  int getMask() => _getMask(reference);
+  int getMask() {
+    final result__ = _getMask(reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 }
 
 /// from: com.fasterxml.jackson.core.JsonParser$NumberType
 ///
 /// Enumeration of possible "native" (optimal) types that can be
 /// used for numbers.
-class JsonParser_NumberType extends jni.JlObject {
+class JsonParser_NumberType extends jni.JniObject {
   JsonParser_NumberType.fromRef(ffi.Pointer<ffi.Void> ref) : super.fromRef(ref);
 
   static final _values =
-      jlookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function()>>(
+      jniLookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function()>>(
               "com_fasterxml_jackson_core_JsonParser__NumberType_values")
           .asFunction<ffi.Pointer<ffi.Void> Function()>();
 
   /// from: static public com.fasterxml.jackson.core.JsonParser.NumberType[] values()
   /// The returned object must be deleted after use, by calling the `delete` method.
-  static jni.JlObject values() => jni.JlObject.fromRef(_values());
+  static jni.JniObject values() {
+    final result__ = jni.JniObject.fromRef(_values());
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _valueOf = jlookup<
+  static final _valueOf = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonParser__NumberType_valueOf")
@@ -3955,35 +4647,44 @@
 
   /// from: static public com.fasterxml.jackson.core.JsonParser.NumberType valueOf(java.lang.String name)
   /// The returned object must be deleted after use, by calling the `delete` method.
-  static JsonParser_NumberType valueOf(jni.JlString name) =>
-      JsonParser_NumberType.fromRef(_valueOf(name.reference));
+  static JsonParser_NumberType valueOf(jni.JniString name) {
+    final result__ = JsonParser_NumberType.fromRef(_valueOf(name.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _ctor =
-      jlookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function()>>(
+      jniLookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function()>>(
               "com_fasterxml_jackson_core_JsonParser__NumberType_ctor")
           .asFunction<ffi.Pointer<ffi.Void> Function()>();
 
   /// from: private void <init>()
-  JsonParser_NumberType() : super.fromRef(_ctor());
+  JsonParser_NumberType() : super.fromRef(_ctor()) {
+    jni.Jni.env.checkException();
+  }
 }
 
 /// from: com.fasterxml.jackson.core.JsonToken
 ///
 /// Enumeration for basic token types used for returning results
 /// of parsing JSON content.
-class JsonToken extends jni.JlObject {
+class JsonToken extends jni.JniObject {
   JsonToken.fromRef(ffi.Pointer<ffi.Void> ref) : super.fromRef(ref);
 
   static final _values =
-      jlookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function()>>(
+      jniLookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function()>>(
               "com_fasterxml_jackson_core_JsonToken_values")
           .asFunction<ffi.Pointer<ffi.Void> Function()>();
 
   /// from: static public com.fasterxml.jackson.core.JsonToken[] values()
   /// The returned object must be deleted after use, by calling the `delete` method.
-  static jni.JlObject values() => jni.JlObject.fromRef(_values());
+  static jni.JniObject values() {
+    final result__ = jni.JniObject.fromRef(_values());
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _valueOf = jlookup<
+  static final _valueOf = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonToken_valueOf")
@@ -3991,10 +4692,13 @@
 
   /// from: static public com.fasterxml.jackson.core.JsonToken valueOf(java.lang.String name)
   /// The returned object must be deleted after use, by calling the `delete` method.
-  static JsonToken valueOf(jni.JlString name) =>
-      JsonToken.fromRef(_valueOf(name.reference));
+  static JsonToken valueOf(jni.JniString name) {
+    final result__ = JsonToken.fromRef(_valueOf(name.reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _ctor = jlookup<
+  static final _ctor = jniLookup<
           ffi.NativeFunction<
               ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>,
                   ffi.Int32)>>("com_fasterxml_jackson_core_JsonToken_ctor")
@@ -4005,18 +4709,24 @@
   /// @param token representation for this token, if there is a
   ///   single static representation; null otherwise
   ///@param id Numeric id from JsonTokenId
-  JsonToken(jni.JlString token, int id)
-      : super.fromRef(_ctor(token.reference, id));
+  JsonToken(jni.JniString token, int id)
+      : super.fromRef(_ctor(token.reference, id)) {
+    jni.Jni.env.checkException();
+  }
 
   static final _id =
-      jlookup<ffi.NativeFunction<ffi.Int32 Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Int32 Function(ffi.Pointer<ffi.Void>)>>(
               "com_fasterxml_jackson_core_JsonToken_id")
           .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
   /// from: public final int id()
-  int id() => _id(reference);
+  int id() {
+    final result__ = _id(reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _asString = jlookup<
+  static final _asString = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonToken_asString")
@@ -4024,9 +4734,13 @@
 
   /// from: public final java.lang.String asString()
   /// The returned object must be deleted after use, by calling the `delete` method.
-  jni.JlString asString() => jni.JlString.fromRef(_asString(reference));
+  jni.JniString asString() {
+    final result__ = jni.JniString.fromRef(_asString(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _asCharArray = jlookup<
+  static final _asCharArray = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonToken_asCharArray")
@@ -4034,9 +4748,13 @@
 
   /// from: public final char[] asCharArray()
   /// The returned object must be deleted after use, by calling the `delete` method.
-  jni.JlObject asCharArray() => jni.JlObject.fromRef(_asCharArray(reference));
+  jni.JniObject asCharArray() {
+    final result__ = jni.JniObject.fromRef(_asCharArray(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _asByteArray = jlookup<
+  static final _asByteArray = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_fasterxml_jackson_core_JsonToken_asByteArray")
@@ -4044,10 +4762,14 @@
 
   /// from: public final byte[] asByteArray()
   /// The returned object must be deleted after use, by calling the `delete` method.
-  jni.JlObject asByteArray() => jni.JlObject.fromRef(_asByteArray(reference));
+  jni.JniObject asByteArray() {
+    final result__ = jni.JniObject.fromRef(_asByteArray(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _isNumeric =
-      jlookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
               "com_fasterxml_jackson_core_JsonToken_isNumeric")
           .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
@@ -4055,10 +4777,14 @@
   ///
   /// @return {@code True} if this token is {@code VALUE_NUMBER_INT} or {@code VALUE_NUMBER_FLOAT},
   ///   {@code false} otherwise
-  bool isNumeric() => _isNumeric(reference) != 0;
+  bool isNumeric() {
+    final result__ = _isNumeric(reference) != 0;
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _isStructStart =
-      jlookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
               "com_fasterxml_jackson_core_JsonToken_isStructStart")
           .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
@@ -4071,10 +4797,14 @@
   ///@return {@code True} if this token is {@code START_OBJECT} or {@code START_ARRAY},
   ///   {@code false} otherwise
   ///@since 2.3
-  bool isStructStart() => _isStructStart(reference) != 0;
+  bool isStructStart() {
+    final result__ = _isStructStart(reference) != 0;
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _isStructEnd =
-      jlookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
               "com_fasterxml_jackson_core_JsonToken_isStructEnd")
           .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
@@ -4087,10 +4817,14 @@
   ///@return {@code True} if this token is {@code END_OBJECT} or {@code END_ARRAY},
   ///   {@code false} otherwise
   ///@since 2.3
-  bool isStructEnd() => _isStructEnd(reference) != 0;
+  bool isStructEnd() {
+    final result__ = _isStructEnd(reference) != 0;
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _isScalarValue =
-      jlookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
               "com_fasterxml_jackson_core_JsonToken_isScalarValue")
           .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
@@ -4102,10 +4836,14 @@
   /// {@code FIELD_NAME}.
   ///@return {@code True} if this token is a scalar value token (one of
   ///   {@code VALUE_xxx} tokens), {@code false} otherwise
-  bool isScalarValue() => _isScalarValue(reference) != 0;
+  bool isScalarValue() {
+    final result__ = _isScalarValue(reference) != 0;
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _isBoolean =
-      jlookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
               "com_fasterxml_jackson_core_JsonToken_isBoolean")
           .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
@@ -4113,5 +4851,9 @@
   ///
   /// @return {@code True} if this token is {@code VALUE_TRUE} or {@code VALUE_FALSE},
   ///   {@code false} otherwise
-  bool isBoolean() => _isBoolean(reference) != 0;
+  bool isBoolean() {
+    final result__ = _isBoolean(reference) != 0;
+    jni.Jni.env.checkException();
+    return result__;
+  }
 }
diff --git a/pkgs/jnigen/test/jackson_core_test/third_party/lib/init.dart b/pkgs/jnigen/test/jackson_core_test/third_party/lib/init.dart
deleted file mode 100644
index 062c5a8..0000000
--- a/pkgs/jnigen/test/jackson_core_test/third_party/lib/init.dart
+++ /dev/null
@@ -1,5 +0,0 @@
-import "dart:ffi";
-import "package:jni/jni.dart";
-
-final Pointer<T> Function<T extends NativeType>(String sym) jlookup =
-    Jni.getInstance().initGeneratedLibrary("jackson_core_test");
diff --git a/pkgs/jnigen/test/jackson_core_test/third_party/src/dartjni.h b/pkgs/jnigen/test/jackson_core_test/third_party/src/dartjni.h
index cd94b15..0ce5069 100644
--- a/pkgs/jnigen/test/jackson_core_test/third_party/src/dartjni.h
+++ b/pkgs/jnigen/test/jackson_core_test/third_party/src/dartjni.h
@@ -2,6 +2,8 @@
 // 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.
 
+#pragma once
+
 #include <jni.h>
 #include <stdint.h>
 #include <stdio.h>
@@ -38,17 +40,17 @@
 #define __ENVP_CAST (void **)
 #endif
 
-struct jni_context {
+typedef struct JniContext {
 	JavaVM *jvm;
 	jobject classLoader;
 	jmethodID loadClassMethod;
 	jobject currentActivity;
 	jobject appContext;
-};
+} JniContext;
 
 extern thread_local JNIEnv *jniEnv;
 
-extern struct jni_context jni;
+extern JniContext jni;
 
 enum DartJniLogLevel {
 	JNI_VERBOSE = 2,
@@ -58,10 +60,25 @@
 	JNI_ERROR
 };
 
-FFI_PLUGIN_EXPORT struct jni_context GetJniContext();
+enum JniType {
+	boolType = 0,
+	byteType = 1,
+	shortType = 2,
+	charType = 3,
+	intType = 4,
+	longType = 5,
+	floatType = 6,
+	doubleType = 7,
+	objectType = 8,
+	voidType = 9,
+};
+
+FFI_PLUGIN_EXPORT JniContext GetJniContext();
 
 FFI_PLUGIN_EXPORT JavaVM *GetJavaVM(void);
 
+FFI_PLUGIN_EXPORT int DestroyJavaVM();
+
 FFI_PLUGIN_EXPORT JNIEnv *GetJniEnv(void);
 
 FFI_PLUGIN_EXPORT JNIEnv *SpawnJvm(JavaVMInitArgs *args);
@@ -74,26 +91,16 @@
 
 FFI_PLUGIN_EXPORT jobject GetCurrentActivity(void);
 
-FFI_PLUGIN_EXPORT void SetJNILogging(int level);
+/// For use by jni_gen's generated code
+/// don't use these.
 
-FFI_PLUGIN_EXPORT jstring ToJavaString(char *str);
-
-FFI_PLUGIN_EXPORT const char *GetJavaStringChars(jstring jstr);
-
-FFI_PLUGIN_EXPORT void ReleaseJavaStringChars(jstring jstr, const char *buf);
-
-// These 2 are the function pointer variables defined and exported by
-// the generated C files.
-//
-// initGeneratedLibrary function in Jni class will set these to
-// corresponding functions to the implementations from `dartjni` base library
-// which initializes and manages the JNI.
-extern struct jni_context (*context_getter)(void);
+// these 2 fn ptr vars will be defined by generated code library
+extern JniContext (*context_getter)(void);
 extern JNIEnv *(*env_getter)(void);
 
-// This function will be exported by generated code library and will set the
-// above 2 variables.
-FFI_PLUGIN_EXPORT void setJniGetters(struct jni_context (*cg)(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),
 		JNIEnv *(*eg)(void));
 
 // `static inline` because `inline` doesn't work, it may still not
@@ -101,6 +108,7 @@
 //
 // 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) {
 #ifdef __ANDROID__
 	jstring className = (*jniEnv)->NewStringUTF(jniEnv, name);
diff --git a/pkgs/jnigen/test/jackson_core_test/third_party/src/jackson_core_test.c b/pkgs/jnigen/test/jackson_core_test/third_party/src/jackson_core_test.c
index a690b7c..6bbe92a 100644
--- a/pkgs/jnigen/test/jackson_core_test/third_party/src/jackson_core_test.c
+++ b/pkgs/jnigen/test/jackson_core_test/third_party/src/jackson_core_test.c
@@ -22,12 +22,12 @@
 #include "dartjni.h"
 
 thread_local JNIEnv *jniEnv;
-struct jni_context jni;
+JniContext jni;
 
-struct jni_context (*context_getter)(void);
+JniContext (*context_getter)(void);
 JNIEnv *(*env_getter)(void);
 
-void setJniGetters(struct jni_context (*cg)(void),
+void setJniGetters(JniContext (*cg)(void),
         JNIEnv *(*eg)(void)) {
     context_getter = cg;
     env_getter = eg;
@@ -41,7 +41,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_ctor() {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_ctor, "<init>", "()V");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_ctor == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->NewObject(jniEnv, _c_com_fasterxml_jackson_core_JsonFactory, _m_com_fasterxml_jackson_core_JsonFactory_ctor);
     return to_global_ref(_result);
 }
@@ -51,7 +53,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_ctor1(jobject oc) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_ctor1, "<init>", "(Lcom/fasterxml/jackson/core/ObjectCodec;)V");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_ctor1 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->NewObject(jniEnv, _c_com_fasterxml_jackson_core_JsonFactory, _m_com_fasterxml_jackson_core_JsonFactory_ctor1, oc);
     return to_global_ref(_result);
 }
@@ -61,7 +65,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_ctor2(jobject src, jobject codec) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_ctor2, "<init>", "(Lcom/fasterxml/jackson/core/JsonFactory;Lcom/fasterxml/jackson/core/ObjectCodec;)V");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_ctor2 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->NewObject(jniEnv, _c_com_fasterxml_jackson_core_JsonFactory, _m_com_fasterxml_jackson_core_JsonFactory_ctor2, src, codec);
     return to_global_ref(_result);
 }
@@ -71,7 +77,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_ctor3(jobject b) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_ctor3, "<init>", "(Lcom/fasterxml/jackson/core/JsonFactoryBuilder;)V");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_ctor3 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->NewObject(jniEnv, _c_com_fasterxml_jackson_core_JsonFactory, _m_com_fasterxml_jackson_core_JsonFactory_ctor3, b);
     return to_global_ref(_result);
 }
@@ -81,7 +89,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_ctor4(jobject b, uint8_t bogus) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_ctor4, "<init>", "(Lcom/fasterxml/jackson/core/TSFBuilder;Z)V");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_ctor4 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->NewObject(jniEnv, _c_com_fasterxml_jackson_core_JsonFactory, _m_com_fasterxml_jackson_core_JsonFactory_ctor4, b, bogus);
     return to_global_ref(_result);
 }
@@ -91,7 +101,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_rebuild(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_rebuild, "rebuild", "()Lcom/fasterxml/jackson/core/TSFBuilder;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_rebuild == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_rebuild);
     return to_global_ref(_result);
 }
@@ -101,7 +113,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_builder() {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_static_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_builder, "builder", "()Lcom/fasterxml/jackson/core/TSFBuilder;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_builder == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallStaticObjectMethod(jniEnv, _c_com_fasterxml_jackson_core_JsonFactory, _m_com_fasterxml_jackson_core_JsonFactory_builder);
     return to_global_ref(_result);
 }
@@ -111,7 +125,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_copy(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_copy, "copy", "()Lcom/fasterxml/jackson/core/JsonFactory;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_copy == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_copy);
     return to_global_ref(_result);
 }
@@ -121,7 +137,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_readResolve(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_readResolve, "readResolve", "()Ljava/lang/Object;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_readResolve == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_readResolve);
     return to_global_ref(_result);
 }
@@ -131,7 +149,9 @@
 uint8_t com_fasterxml_jackson_core_JsonFactory_requiresPropertyOrdering(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (uint8_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_requiresPropertyOrdering, "requiresPropertyOrdering", "()Z");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_requiresPropertyOrdering == NULL) return (uint8_t)0;
     uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_requiresPropertyOrdering);
     return _result;
 }
@@ -141,7 +161,9 @@
 uint8_t com_fasterxml_jackson_core_JsonFactory_canHandleBinaryNatively(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (uint8_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_canHandleBinaryNatively, "canHandleBinaryNatively", "()Z");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_canHandleBinaryNatively == NULL) return (uint8_t)0;
     uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_canHandleBinaryNatively);
     return _result;
 }
@@ -151,7 +173,9 @@
 uint8_t com_fasterxml_jackson_core_JsonFactory_canUseCharArrays(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (uint8_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_canUseCharArrays, "canUseCharArrays", "()Z");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_canUseCharArrays == NULL) return (uint8_t)0;
     uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_canUseCharArrays);
     return _result;
 }
@@ -161,7 +185,9 @@
 uint8_t com_fasterxml_jackson_core_JsonFactory_canParseAsync(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (uint8_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_canParseAsync, "canParseAsync", "()Z");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_canParseAsync == NULL) return (uint8_t)0;
     uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_canParseAsync);
     return _result;
 }
@@ -171,7 +197,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_getFormatReadFeatureType(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_getFormatReadFeatureType, "getFormatReadFeatureType", "()Ljava/lang/Class;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_getFormatReadFeatureType == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_getFormatReadFeatureType);
     return to_global_ref(_result);
 }
@@ -181,7 +209,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_getFormatWriteFeatureType(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_getFormatWriteFeatureType, "getFormatWriteFeatureType", "()Ljava/lang/Class;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_getFormatWriteFeatureType == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_getFormatWriteFeatureType);
     return to_global_ref(_result);
 }
@@ -191,7 +221,9 @@
 uint8_t com_fasterxml_jackson_core_JsonFactory_canUseSchema(jobject self_, jobject schema) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (uint8_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_canUseSchema, "canUseSchema", "(Lcom/fasterxml/jackson/core/FormatSchema;)Z");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_canUseSchema == NULL) return (uint8_t)0;
     uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_canUseSchema, schema);
     return _result;
 }
@@ -201,7 +233,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_getFormatName(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_getFormatName, "getFormatName", "()Ljava/lang/String;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_getFormatName == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_getFormatName);
     return to_global_ref(_result);
 }
@@ -211,7 +245,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_hasFormat(jobject self_, jobject acc) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_hasFormat, "hasFormat", "(Lcom/fasterxml/jackson/core/format/InputAccessor;)Lcom/fasterxml/jackson/core/format/MatchStrength;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_hasFormat == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_hasFormat, acc);
     return to_global_ref(_result);
 }
@@ -221,7 +257,9 @@
 uint8_t com_fasterxml_jackson_core_JsonFactory_requiresCustomCodec(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (uint8_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_requiresCustomCodec, "requiresCustomCodec", "()Z");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_requiresCustomCodec == NULL) return (uint8_t)0;
     uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_requiresCustomCodec);
     return _result;
 }
@@ -231,7 +269,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_hasJSONFormat(jobject self_, jobject acc) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_hasJSONFormat, "hasJSONFormat", "(Lcom/fasterxml/jackson/core/format/InputAccessor;)Lcom/fasterxml/jackson/core/format/MatchStrength;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_hasJSONFormat == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_hasJSONFormat, acc);
     return to_global_ref(_result);
 }
@@ -241,7 +281,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_version(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_version, "version", "()Lcom/fasterxml/jackson/core/Version;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_version == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_version);
     return to_global_ref(_result);
 }
@@ -251,7 +293,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_configure(jobject self_, jobject f, uint8_t state) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_configure, "configure", "(Lcom/fasterxml/jackson/core/JsonFactory$Feature;Z)Lcom/fasterxml/jackson/core/JsonFactory;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_configure == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_configure, f, state);
     return to_global_ref(_result);
 }
@@ -261,7 +305,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_enable(jobject self_, jobject f) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_enable, "enable", "(Lcom/fasterxml/jackson/core/JsonFactory$Feature;)Lcom/fasterxml/jackson/core/JsonFactory;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_enable == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_enable, f);
     return to_global_ref(_result);
 }
@@ -271,7 +317,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_disable(jobject self_, jobject f) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_disable, "disable", "(Lcom/fasterxml/jackson/core/JsonFactory$Feature;)Lcom/fasterxml/jackson/core/JsonFactory;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_disable == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_disable, f);
     return to_global_ref(_result);
 }
@@ -281,7 +329,9 @@
 uint8_t com_fasterxml_jackson_core_JsonFactory_isEnabled(jobject self_, jobject f) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (uint8_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_isEnabled, "isEnabled", "(Lcom/fasterxml/jackson/core/JsonFactory$Feature;)Z");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_isEnabled == NULL) return (uint8_t)0;
     uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_isEnabled, f);
     return _result;
 }
@@ -291,7 +341,9 @@
 int32_t com_fasterxml_jackson_core_JsonFactory_getParserFeatures(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (int32_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_getParserFeatures, "getParserFeatures", "()I");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_getParserFeatures == NULL) return (int32_t)0;
     int32_t _result = (*jniEnv)->CallIntMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_getParserFeatures);
     return _result;
 }
@@ -301,7 +353,9 @@
 int32_t com_fasterxml_jackson_core_JsonFactory_getGeneratorFeatures(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (int32_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_getGeneratorFeatures, "getGeneratorFeatures", "()I");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_getGeneratorFeatures == NULL) return (int32_t)0;
     int32_t _result = (*jniEnv)->CallIntMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_getGeneratorFeatures);
     return _result;
 }
@@ -311,7 +365,9 @@
 int32_t com_fasterxml_jackson_core_JsonFactory_getFormatParserFeatures(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (int32_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_getFormatParserFeatures, "getFormatParserFeatures", "()I");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_getFormatParserFeatures == NULL) return (int32_t)0;
     int32_t _result = (*jniEnv)->CallIntMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_getFormatParserFeatures);
     return _result;
 }
@@ -321,7 +377,9 @@
 int32_t com_fasterxml_jackson_core_JsonFactory_getFormatGeneratorFeatures(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (int32_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_getFormatGeneratorFeatures, "getFormatGeneratorFeatures", "()I");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_getFormatGeneratorFeatures == NULL) return (int32_t)0;
     int32_t _result = (*jniEnv)->CallIntMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_getFormatGeneratorFeatures);
     return _result;
 }
@@ -331,7 +389,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_configure1(jobject self_, jobject f, uint8_t state) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_configure1, "configure", "(Lcom/fasterxml/jackson/core/JsonParser$Feature;Z)Lcom/fasterxml/jackson/core/JsonFactory;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_configure1 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_configure1, f, state);
     return to_global_ref(_result);
 }
@@ -341,7 +401,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_enable1(jobject self_, jobject f) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_enable1, "enable", "(Lcom/fasterxml/jackson/core/JsonParser$Feature;)Lcom/fasterxml/jackson/core/JsonFactory;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_enable1 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_enable1, f);
     return to_global_ref(_result);
 }
@@ -351,7 +413,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_disable1(jobject self_, jobject f) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_disable1, "disable", "(Lcom/fasterxml/jackson/core/JsonParser$Feature;)Lcom/fasterxml/jackson/core/JsonFactory;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_disable1 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_disable1, f);
     return to_global_ref(_result);
 }
@@ -361,7 +425,9 @@
 uint8_t com_fasterxml_jackson_core_JsonFactory_isEnabled1(jobject self_, jobject f) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (uint8_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_isEnabled1, "isEnabled", "(Lcom/fasterxml/jackson/core/JsonParser$Feature;)Z");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_isEnabled1 == NULL) return (uint8_t)0;
     uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_isEnabled1, f);
     return _result;
 }
@@ -371,7 +437,9 @@
 uint8_t com_fasterxml_jackson_core_JsonFactory_isEnabled2(jobject self_, jobject f) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (uint8_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_isEnabled2, "isEnabled", "(Lcom/fasterxml/jackson/core/StreamReadFeature;)Z");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_isEnabled2 == NULL) return (uint8_t)0;
     uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_isEnabled2, f);
     return _result;
 }
@@ -381,7 +449,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_getInputDecorator(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_getInputDecorator, "getInputDecorator", "()Lcom/fasterxml/jackson/core/io/InputDecorator;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_getInputDecorator == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_getInputDecorator);
     return to_global_ref(_result);
 }
@@ -391,7 +461,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_setInputDecorator(jobject self_, jobject d) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_setInputDecorator, "setInputDecorator", "(Lcom/fasterxml/jackson/core/io/InputDecorator;)Lcom/fasterxml/jackson/core/JsonFactory;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_setInputDecorator == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_setInputDecorator, d);
     return to_global_ref(_result);
 }
@@ -401,7 +473,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_configure2(jobject self_, jobject f, uint8_t state) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_configure2, "configure", "(Lcom/fasterxml/jackson/core/JsonGenerator$Feature;Z)Lcom/fasterxml/jackson/core/JsonFactory;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_configure2 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_configure2, f, state);
     return to_global_ref(_result);
 }
@@ -411,7 +485,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_enable2(jobject self_, jobject f) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_enable2, "enable", "(Lcom/fasterxml/jackson/core/JsonGenerator$Feature;)Lcom/fasterxml/jackson/core/JsonFactory;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_enable2 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_enable2, f);
     return to_global_ref(_result);
 }
@@ -421,7 +497,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_disable2(jobject self_, jobject f) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_disable2, "disable", "(Lcom/fasterxml/jackson/core/JsonGenerator$Feature;)Lcom/fasterxml/jackson/core/JsonFactory;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_disable2 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_disable2, f);
     return to_global_ref(_result);
 }
@@ -431,7 +509,9 @@
 uint8_t com_fasterxml_jackson_core_JsonFactory_isEnabled3(jobject self_, jobject f) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (uint8_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_isEnabled3, "isEnabled", "(Lcom/fasterxml/jackson/core/JsonGenerator$Feature;)Z");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_isEnabled3 == NULL) return (uint8_t)0;
     uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_isEnabled3, f);
     return _result;
 }
@@ -441,7 +521,9 @@
 uint8_t com_fasterxml_jackson_core_JsonFactory_isEnabled4(jobject self_, jobject f) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (uint8_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_isEnabled4, "isEnabled", "(Lcom/fasterxml/jackson/core/StreamWriteFeature;)Z");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_isEnabled4 == NULL) return (uint8_t)0;
     uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_isEnabled4, f);
     return _result;
 }
@@ -451,7 +533,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_getCharacterEscapes(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_getCharacterEscapes, "getCharacterEscapes", "()Lcom/fasterxml/jackson/core/io/CharacterEscapes;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_getCharacterEscapes == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_getCharacterEscapes);
     return to_global_ref(_result);
 }
@@ -461,7 +545,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_setCharacterEscapes(jobject self_, jobject esc) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_setCharacterEscapes, "setCharacterEscapes", "(Lcom/fasterxml/jackson/core/io/CharacterEscapes;)Lcom/fasterxml/jackson/core/JsonFactory;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_setCharacterEscapes == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_setCharacterEscapes, esc);
     return to_global_ref(_result);
 }
@@ -471,7 +557,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_getOutputDecorator(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_getOutputDecorator, "getOutputDecorator", "()Lcom/fasterxml/jackson/core/io/OutputDecorator;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_getOutputDecorator == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_getOutputDecorator);
     return to_global_ref(_result);
 }
@@ -481,7 +569,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_setOutputDecorator(jobject self_, jobject d) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_setOutputDecorator, "setOutputDecorator", "(Lcom/fasterxml/jackson/core/io/OutputDecorator;)Lcom/fasterxml/jackson/core/JsonFactory;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_setOutputDecorator == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_setOutputDecorator, d);
     return to_global_ref(_result);
 }
@@ -491,7 +581,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_setRootValueSeparator(jobject self_, jobject sep) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_setRootValueSeparator, "setRootValueSeparator", "(Ljava/lang/String;)Lcom/fasterxml/jackson/core/JsonFactory;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_setRootValueSeparator == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_setRootValueSeparator, sep);
     return to_global_ref(_result);
 }
@@ -501,7 +593,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_getRootValueSeparator(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_getRootValueSeparator, "getRootValueSeparator", "()Ljava/lang/String;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_getRootValueSeparator == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_getRootValueSeparator);
     return to_global_ref(_result);
 }
@@ -511,7 +605,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_setCodec(jobject self_, jobject oc) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_setCodec, "setCodec", "(Lcom/fasterxml/jackson/core/ObjectCodec;)Lcom/fasterxml/jackson/core/JsonFactory;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_setCodec == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_setCodec, oc);
     return to_global_ref(_result);
 }
@@ -521,7 +617,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_getCodec(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_getCodec, "getCodec", "()Lcom/fasterxml/jackson/core/ObjectCodec;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_getCodec == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_getCodec);
     return to_global_ref(_result);
 }
@@ -531,7 +629,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_createParser(jobject self_, jobject f) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_createParser, "createParser", "(Ljava/io/File;)Lcom/fasterxml/jackson/core/JsonParser;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_createParser == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_createParser, f);
     return to_global_ref(_result);
 }
@@ -541,7 +641,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_createParser1(jobject self_, jobject url) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_createParser1, "createParser", "(Ljava/net/URL;)Lcom/fasterxml/jackson/core/JsonParser;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_createParser1 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_createParser1, url);
     return to_global_ref(_result);
 }
@@ -551,7 +653,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_createParser2(jobject self_, jobject in) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_createParser2, "createParser", "(Ljava/io/InputStream;)Lcom/fasterxml/jackson/core/JsonParser;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_createParser2 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_createParser2, in);
     return to_global_ref(_result);
 }
@@ -561,7 +665,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_createParser3(jobject self_, jobject r) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_createParser3, "createParser", "(Ljava/io/Reader;)Lcom/fasterxml/jackson/core/JsonParser;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_createParser3 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_createParser3, r);
     return to_global_ref(_result);
 }
@@ -571,7 +677,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_createParser4(jobject self_, jobject data) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_createParser4, "createParser", "(L[B;)Lcom/fasterxml/jackson/core/JsonParser;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_createParser4 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_createParser4, data);
     return to_global_ref(_result);
 }
@@ -581,7 +689,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_createParser5(jobject self_, jobject data, int32_t offset, int32_t len) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_createParser5, "createParser", "(L[B;II)Lcom/fasterxml/jackson/core/JsonParser;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_createParser5 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_createParser5, data, offset, len);
     return to_global_ref(_result);
 }
@@ -591,7 +701,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_createParser6(jobject self_, jobject content) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_createParser6, "createParser", "(Ljava/lang/String;)Lcom/fasterxml/jackson/core/JsonParser;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_createParser6 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_createParser6, content);
     return to_global_ref(_result);
 }
@@ -601,7 +713,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_createParser7(jobject self_, jobject content) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_createParser7, "createParser", "(L[C;)Lcom/fasterxml/jackson/core/JsonParser;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_createParser7 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_createParser7, content);
     return to_global_ref(_result);
 }
@@ -611,7 +725,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_createParser8(jobject self_, jobject content, int32_t offset, int32_t len) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_createParser8, "createParser", "(L[C;II)Lcom/fasterxml/jackson/core/JsonParser;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_createParser8 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_createParser8, content, offset, len);
     return to_global_ref(_result);
 }
@@ -621,7 +737,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_createParser9(jobject self_, jobject in) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_createParser9, "createParser", "(Ljava/io/DataInput;)Lcom/fasterxml/jackson/core/JsonParser;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_createParser9 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_createParser9, in);
     return to_global_ref(_result);
 }
@@ -631,7 +749,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_createNonBlockingByteArrayParser(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_createNonBlockingByteArrayParser, "createNonBlockingByteArrayParser", "()Lcom/fasterxml/jackson/core/JsonParser;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_createNonBlockingByteArrayParser == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_createNonBlockingByteArrayParser);
     return to_global_ref(_result);
 }
@@ -641,7 +761,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_createGenerator(jobject self_, jobject out, jobject enc) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_createGenerator, "createGenerator", "(Ljava/io/OutputStream;Lcom/fasterxml/jackson/core/JsonEncoding;)Lcom/fasterxml/jackson/core/JsonGenerator;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_createGenerator == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_createGenerator, out, enc);
     return to_global_ref(_result);
 }
@@ -651,7 +773,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_createGenerator1(jobject self_, jobject out) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_createGenerator1, "createGenerator", "(Ljava/io/OutputStream;)Lcom/fasterxml/jackson/core/JsonGenerator;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_createGenerator1 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_createGenerator1, out);
     return to_global_ref(_result);
 }
@@ -661,7 +785,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_createGenerator2(jobject self_, jobject w) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_createGenerator2, "createGenerator", "(Ljava/io/Writer;)Lcom/fasterxml/jackson/core/JsonGenerator;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_createGenerator2 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_createGenerator2, w);
     return to_global_ref(_result);
 }
@@ -671,7 +797,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_createGenerator3(jobject self_, jobject f, jobject enc) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_createGenerator3, "createGenerator", "(Ljava/io/File;Lcom/fasterxml/jackson/core/JsonEncoding;)Lcom/fasterxml/jackson/core/JsonGenerator;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_createGenerator3 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_createGenerator3, f, enc);
     return to_global_ref(_result);
 }
@@ -681,7 +809,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_createGenerator4(jobject self_, jobject out, jobject enc) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_createGenerator4, "createGenerator", "(Ljava/io/DataOutput;Lcom/fasterxml/jackson/core/JsonEncoding;)Lcom/fasterxml/jackson/core/JsonGenerator;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_createGenerator4 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_createGenerator4, out, enc);
     return to_global_ref(_result);
 }
@@ -691,7 +821,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_createGenerator5(jobject self_, jobject out) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_createGenerator5, "createGenerator", "(Ljava/io/DataOutput;)Lcom/fasterxml/jackson/core/JsonGenerator;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_createGenerator5 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_createGenerator5, out);
     return to_global_ref(_result);
 }
@@ -701,7 +833,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_createJsonParser(jobject self_, jobject f) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_createJsonParser, "createJsonParser", "(Ljava/io/File;)Lcom/fasterxml/jackson/core/JsonParser;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_createJsonParser == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_createJsonParser, f);
     return to_global_ref(_result);
 }
@@ -711,7 +845,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_createJsonParser1(jobject self_, jobject url) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_createJsonParser1, "createJsonParser", "(Ljava/net/URL;)Lcom/fasterxml/jackson/core/JsonParser;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_createJsonParser1 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_createJsonParser1, url);
     return to_global_ref(_result);
 }
@@ -721,7 +857,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_createJsonParser2(jobject self_, jobject in) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_createJsonParser2, "createJsonParser", "(Ljava/io/InputStream;)Lcom/fasterxml/jackson/core/JsonParser;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_createJsonParser2 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_createJsonParser2, in);
     return to_global_ref(_result);
 }
@@ -731,7 +869,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_createJsonParser3(jobject self_, jobject r) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_createJsonParser3, "createJsonParser", "(Ljava/io/Reader;)Lcom/fasterxml/jackson/core/JsonParser;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_createJsonParser3 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_createJsonParser3, r);
     return to_global_ref(_result);
 }
@@ -741,7 +881,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_createJsonParser4(jobject self_, jobject data) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_createJsonParser4, "createJsonParser", "(L[B;)Lcom/fasterxml/jackson/core/JsonParser;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_createJsonParser4 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_createJsonParser4, data);
     return to_global_ref(_result);
 }
@@ -751,7 +893,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_createJsonParser5(jobject self_, jobject data, int32_t offset, int32_t len) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_createJsonParser5, "createJsonParser", "(L[B;II)Lcom/fasterxml/jackson/core/JsonParser;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_createJsonParser5 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_createJsonParser5, data, offset, len);
     return to_global_ref(_result);
 }
@@ -761,7 +905,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_createJsonParser6(jobject self_, jobject content) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_createJsonParser6, "createJsonParser", "(Ljava/lang/String;)Lcom/fasterxml/jackson/core/JsonParser;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_createJsonParser6 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_createJsonParser6, content);
     return to_global_ref(_result);
 }
@@ -771,7 +917,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_createJsonGenerator(jobject self_, jobject out, jobject enc) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_createJsonGenerator, "createJsonGenerator", "(Ljava/io/OutputStream;Lcom/fasterxml/jackson/core/JsonEncoding;)Lcom/fasterxml/jackson/core/JsonGenerator;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_createJsonGenerator == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_createJsonGenerator, out, enc);
     return to_global_ref(_result);
 }
@@ -781,7 +929,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_createJsonGenerator1(jobject self_, jobject out) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_createJsonGenerator1, "createJsonGenerator", "(Ljava/io/Writer;)Lcom/fasterxml/jackson/core/JsonGenerator;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_createJsonGenerator1 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_createJsonGenerator1, out);
     return to_global_ref(_result);
 }
@@ -791,7 +941,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory_createJsonGenerator2(jobject self_, jobject out) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory, &_m_com_fasterxml_jackson_core_JsonFactory_createJsonGenerator2, "createJsonGenerator", "(Ljava/io/OutputStream;)Lcom/fasterxml/jackson/core/JsonGenerator;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory_createJsonGenerator2 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory_createJsonGenerator2, out);
     return to_global_ref(_result);
 }
@@ -800,6 +952,7 @@
 int32_t get_com_fasterxml_jackson_core_JsonFactory_DEFAULT_FACTORY_FEATURE_FLAGS() {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (int32_t)0;
     load_static_field(_c_com_fasterxml_jackson_core_JsonFactory, &_f_com_fasterxml_jackson_core_JsonFactory_DEFAULT_FACTORY_FEATURE_FLAGS, "DEFAULT_FACTORY_FEATURE_FLAGS","I");
     return ((*jniEnv)->GetStaticIntField(jniEnv, _c_com_fasterxml_jackson_core_JsonFactory, _f_com_fasterxml_jackson_core_JsonFactory_DEFAULT_FACTORY_FEATURE_FLAGS));
 }
@@ -809,6 +962,7 @@
 int32_t get_com_fasterxml_jackson_core_JsonFactory_DEFAULT_PARSER_FEATURE_FLAGS() {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (int32_t)0;
     load_static_field(_c_com_fasterxml_jackson_core_JsonFactory, &_f_com_fasterxml_jackson_core_JsonFactory_DEFAULT_PARSER_FEATURE_FLAGS, "DEFAULT_PARSER_FEATURE_FLAGS","I");
     return ((*jniEnv)->GetStaticIntField(jniEnv, _c_com_fasterxml_jackson_core_JsonFactory, _f_com_fasterxml_jackson_core_JsonFactory_DEFAULT_PARSER_FEATURE_FLAGS));
 }
@@ -818,6 +972,7 @@
 int32_t get_com_fasterxml_jackson_core_JsonFactory_DEFAULT_GENERATOR_FEATURE_FLAGS() {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (int32_t)0;
     load_static_field(_c_com_fasterxml_jackson_core_JsonFactory, &_f_com_fasterxml_jackson_core_JsonFactory_DEFAULT_GENERATOR_FEATURE_FLAGS, "DEFAULT_GENERATOR_FEATURE_FLAGS","I");
     return ((*jniEnv)->GetStaticIntField(jniEnv, _c_com_fasterxml_jackson_core_JsonFactory, _f_com_fasterxml_jackson_core_JsonFactory_DEFAULT_GENERATOR_FEATURE_FLAGS));
 }
@@ -827,6 +982,7 @@
 jobject get_com_fasterxml_jackson_core_JsonFactory_DEFAULT_ROOT_VALUE_SEPARATOR() {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory, "com/fasterxml/jackson/core/JsonFactory");
+    if (_c_com_fasterxml_jackson_core_JsonFactory == NULL) return (jobject)0;
     load_static_field(_c_com_fasterxml_jackson_core_JsonFactory, &_f_com_fasterxml_jackson_core_JsonFactory_DEFAULT_ROOT_VALUE_SEPARATOR, "DEFAULT_ROOT_VALUE_SEPARATOR","Lcom/fasterxml/jackson/core/SerializableString;");
     return to_global_ref((*jniEnv)->GetStaticObjectField(jniEnv, _c_com_fasterxml_jackson_core_JsonFactory, _f_com_fasterxml_jackson_core_JsonFactory_DEFAULT_ROOT_VALUE_SEPARATOR));
 }
@@ -840,7 +996,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory__Feature_values() {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory__Feature, "com/fasterxml/jackson/core/JsonFactory$Feature");
+    if (_c_com_fasterxml_jackson_core_JsonFactory__Feature == NULL) return (jobject)0;
     load_static_method(_c_com_fasterxml_jackson_core_JsonFactory__Feature, &_m_com_fasterxml_jackson_core_JsonFactory__Feature_values, "values", "()L[com/fasterxml/jackson/core/JsonFactory$Feature;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory__Feature_values == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallStaticObjectMethod(jniEnv, _c_com_fasterxml_jackson_core_JsonFactory__Feature, _m_com_fasterxml_jackson_core_JsonFactory__Feature_values);
     return to_global_ref(_result);
 }
@@ -850,7 +1008,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory__Feature_valueOf(jobject name) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory__Feature, "com/fasterxml/jackson/core/JsonFactory$Feature");
+    if (_c_com_fasterxml_jackson_core_JsonFactory__Feature == NULL) return (jobject)0;
     load_static_method(_c_com_fasterxml_jackson_core_JsonFactory__Feature, &_m_com_fasterxml_jackson_core_JsonFactory__Feature_valueOf, "valueOf", "(Ljava/lang/String;)Lcom/fasterxml/jackson/core/JsonFactory$Feature;");
+    if (_m_com_fasterxml_jackson_core_JsonFactory__Feature_valueOf == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallStaticObjectMethod(jniEnv, _c_com_fasterxml_jackson_core_JsonFactory__Feature, _m_com_fasterxml_jackson_core_JsonFactory__Feature_valueOf, name);
     return to_global_ref(_result);
 }
@@ -860,7 +1020,9 @@
 int32_t com_fasterxml_jackson_core_JsonFactory__Feature_collectDefaults() {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory__Feature, "com/fasterxml/jackson/core/JsonFactory$Feature");
+    if (_c_com_fasterxml_jackson_core_JsonFactory__Feature == NULL) return (int32_t)0;
     load_static_method(_c_com_fasterxml_jackson_core_JsonFactory__Feature, &_m_com_fasterxml_jackson_core_JsonFactory__Feature_collectDefaults, "collectDefaults", "()I");
+    if (_m_com_fasterxml_jackson_core_JsonFactory__Feature_collectDefaults == NULL) return (int32_t)0;
     int32_t _result = (*jniEnv)->CallStaticIntMethod(jniEnv, _c_com_fasterxml_jackson_core_JsonFactory__Feature, _m_com_fasterxml_jackson_core_JsonFactory__Feature_collectDefaults);
     return _result;
 }
@@ -870,7 +1032,9 @@
 jobject com_fasterxml_jackson_core_JsonFactory__Feature_ctor(uint8_t defaultState) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory__Feature, "com/fasterxml/jackson/core/JsonFactory$Feature");
+    if (_c_com_fasterxml_jackson_core_JsonFactory__Feature == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory__Feature, &_m_com_fasterxml_jackson_core_JsonFactory__Feature_ctor, "<init>", "(Z)V");
+    if (_m_com_fasterxml_jackson_core_JsonFactory__Feature_ctor == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->NewObject(jniEnv, _c_com_fasterxml_jackson_core_JsonFactory__Feature, _m_com_fasterxml_jackson_core_JsonFactory__Feature_ctor, defaultState);
     return to_global_ref(_result);
 }
@@ -880,7 +1044,9 @@
 uint8_t com_fasterxml_jackson_core_JsonFactory__Feature_enabledByDefault(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory__Feature, "com/fasterxml/jackson/core/JsonFactory$Feature");
+    if (_c_com_fasterxml_jackson_core_JsonFactory__Feature == NULL) return (uint8_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory__Feature, &_m_com_fasterxml_jackson_core_JsonFactory__Feature_enabledByDefault, "enabledByDefault", "()Z");
+    if (_m_com_fasterxml_jackson_core_JsonFactory__Feature_enabledByDefault == NULL) return (uint8_t)0;
     uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory__Feature_enabledByDefault);
     return _result;
 }
@@ -890,7 +1056,9 @@
 uint8_t com_fasterxml_jackson_core_JsonFactory__Feature_enabledIn(jobject self_, int32_t flags) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory__Feature, "com/fasterxml/jackson/core/JsonFactory$Feature");
+    if (_c_com_fasterxml_jackson_core_JsonFactory__Feature == NULL) return (uint8_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory__Feature, &_m_com_fasterxml_jackson_core_JsonFactory__Feature_enabledIn, "enabledIn", "(I)Z");
+    if (_m_com_fasterxml_jackson_core_JsonFactory__Feature_enabledIn == NULL) return (uint8_t)0;
     uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory__Feature_enabledIn, flags);
     return _result;
 }
@@ -900,7 +1068,9 @@
 int32_t com_fasterxml_jackson_core_JsonFactory__Feature_getMask(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonFactory__Feature, "com/fasterxml/jackson/core/JsonFactory$Feature");
+    if (_c_com_fasterxml_jackson_core_JsonFactory__Feature == NULL) return (int32_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonFactory__Feature, &_m_com_fasterxml_jackson_core_JsonFactory__Feature_getMask, "getMask", "()I");
+    if (_m_com_fasterxml_jackson_core_JsonFactory__Feature_getMask == NULL) return (int32_t)0;
     int32_t _result = (*jniEnv)->CallIntMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonFactory__Feature_getMask);
     return _result;
 }
@@ -913,7 +1083,9 @@
 jobject com_fasterxml_jackson_core_JsonParser_ctor() {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_ctor, "<init>", "()V");
+    if (_m_com_fasterxml_jackson_core_JsonParser_ctor == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->NewObject(jniEnv, _c_com_fasterxml_jackson_core_JsonParser, _m_com_fasterxml_jackson_core_JsonParser_ctor);
     return to_global_ref(_result);
 }
@@ -923,7 +1095,9 @@
 jobject com_fasterxml_jackson_core_JsonParser_ctor1(int32_t features) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_ctor1, "<init>", "(I)V");
+    if (_m_com_fasterxml_jackson_core_JsonParser_ctor1 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->NewObject(jniEnv, _c_com_fasterxml_jackson_core_JsonParser, _m_com_fasterxml_jackson_core_JsonParser_ctor1, features);
     return to_global_ref(_result);
 }
@@ -933,7 +1107,9 @@
 jobject com_fasterxml_jackson_core_JsonParser_getCodec(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_getCodec, "getCodec", "()Lcom/fasterxml/jackson/core/ObjectCodec;");
+    if (_m_com_fasterxml_jackson_core_JsonParser_getCodec == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_getCodec);
     return to_global_ref(_result);
 }
@@ -943,7 +1119,9 @@
 void com_fasterxml_jackson_core_JsonParser_setCodec(jobject self_, jobject oc) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (void)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_setCodec, "setCodec", "(Lcom/fasterxml/jackson/core/ObjectCodec;)V");
+    if (_m_com_fasterxml_jackson_core_JsonParser_setCodec == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_setCodec, oc);
 }
 
@@ -952,7 +1130,9 @@
 jobject com_fasterxml_jackson_core_JsonParser_getInputSource(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_getInputSource, "getInputSource", "()Ljava/lang/Object;");
+    if (_m_com_fasterxml_jackson_core_JsonParser_getInputSource == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_getInputSource);
     return to_global_ref(_result);
 }
@@ -962,7 +1142,9 @@
 void com_fasterxml_jackson_core_JsonParser_setRequestPayloadOnError(jobject self_, jobject payload) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (void)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_setRequestPayloadOnError, "setRequestPayloadOnError", "(Lcom/fasterxml/jackson/core/util/RequestPayload;)V");
+    if (_m_com_fasterxml_jackson_core_JsonParser_setRequestPayloadOnError == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_setRequestPayloadOnError, payload);
 }
 
@@ -971,7 +1153,9 @@
 void com_fasterxml_jackson_core_JsonParser_setRequestPayloadOnError1(jobject self_, jobject payload, jobject charset) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (void)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_setRequestPayloadOnError1, "setRequestPayloadOnError", "(L[B;Ljava/lang/String;)V");
+    if (_m_com_fasterxml_jackson_core_JsonParser_setRequestPayloadOnError1 == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_setRequestPayloadOnError1, payload, charset);
 }
 
@@ -980,7 +1164,9 @@
 void com_fasterxml_jackson_core_JsonParser_setRequestPayloadOnError2(jobject self_, jobject payload) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (void)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_setRequestPayloadOnError2, "setRequestPayloadOnError", "(Ljava/lang/String;)V");
+    if (_m_com_fasterxml_jackson_core_JsonParser_setRequestPayloadOnError2 == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_setRequestPayloadOnError2, payload);
 }
 
@@ -989,7 +1175,9 @@
 void com_fasterxml_jackson_core_JsonParser_setSchema(jobject self_, jobject schema) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (void)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_setSchema, "setSchema", "(Lcom/fasterxml/jackson/core/FormatSchema;)V");
+    if (_m_com_fasterxml_jackson_core_JsonParser_setSchema == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_setSchema, schema);
 }
 
@@ -998,7 +1186,9 @@
 jobject com_fasterxml_jackson_core_JsonParser_getSchema(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_getSchema, "getSchema", "()Lcom/fasterxml/jackson/core/FormatSchema;");
+    if (_m_com_fasterxml_jackson_core_JsonParser_getSchema == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_getSchema);
     return to_global_ref(_result);
 }
@@ -1008,7 +1198,9 @@
 uint8_t com_fasterxml_jackson_core_JsonParser_canUseSchema(jobject self_, jobject schema) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (uint8_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_canUseSchema, "canUseSchema", "(Lcom/fasterxml/jackson/core/FormatSchema;)Z");
+    if (_m_com_fasterxml_jackson_core_JsonParser_canUseSchema == NULL) return (uint8_t)0;
     uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_canUseSchema, schema);
     return _result;
 }
@@ -1018,7 +1210,9 @@
 uint8_t com_fasterxml_jackson_core_JsonParser_requiresCustomCodec(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (uint8_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_requiresCustomCodec, "requiresCustomCodec", "()Z");
+    if (_m_com_fasterxml_jackson_core_JsonParser_requiresCustomCodec == NULL) return (uint8_t)0;
     uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_requiresCustomCodec);
     return _result;
 }
@@ -1028,7 +1222,9 @@
 uint8_t com_fasterxml_jackson_core_JsonParser_canParseAsync(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (uint8_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_canParseAsync, "canParseAsync", "()Z");
+    if (_m_com_fasterxml_jackson_core_JsonParser_canParseAsync == NULL) return (uint8_t)0;
     uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_canParseAsync);
     return _result;
 }
@@ -1038,7 +1234,9 @@
 jobject com_fasterxml_jackson_core_JsonParser_getNonBlockingInputFeeder(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_getNonBlockingInputFeeder, "getNonBlockingInputFeeder", "()Lcom/fasterxml/jackson/core/async/NonBlockingInputFeeder;");
+    if (_m_com_fasterxml_jackson_core_JsonParser_getNonBlockingInputFeeder == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_getNonBlockingInputFeeder);
     return to_global_ref(_result);
 }
@@ -1048,7 +1246,9 @@
 jobject com_fasterxml_jackson_core_JsonParser_getReadCapabilities(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_getReadCapabilities, "getReadCapabilities", "()Lcom/fasterxml/jackson/core/util/JacksonFeatureSet;");
+    if (_m_com_fasterxml_jackson_core_JsonParser_getReadCapabilities == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_getReadCapabilities);
     return to_global_ref(_result);
 }
@@ -1058,7 +1258,9 @@
 jobject com_fasterxml_jackson_core_JsonParser_version(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_version, "version", "()Lcom/fasterxml/jackson/core/Version;");
+    if (_m_com_fasterxml_jackson_core_JsonParser_version == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_version);
     return to_global_ref(_result);
 }
@@ -1068,7 +1270,9 @@
 void com_fasterxml_jackson_core_JsonParser_close(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (void)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_close, "close", "()V");
+    if (_m_com_fasterxml_jackson_core_JsonParser_close == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_close);
 }
 
@@ -1077,7 +1281,9 @@
 uint8_t com_fasterxml_jackson_core_JsonParser_isClosed(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (uint8_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_isClosed, "isClosed", "()Z");
+    if (_m_com_fasterxml_jackson_core_JsonParser_isClosed == NULL) return (uint8_t)0;
     uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_isClosed);
     return _result;
 }
@@ -1087,7 +1293,9 @@
 jobject com_fasterxml_jackson_core_JsonParser_getParsingContext(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_getParsingContext, "getParsingContext", "()Lcom/fasterxml/jackson/core/JsonStreamContext;");
+    if (_m_com_fasterxml_jackson_core_JsonParser_getParsingContext == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_getParsingContext);
     return to_global_ref(_result);
 }
@@ -1097,7 +1305,9 @@
 jobject com_fasterxml_jackson_core_JsonParser_currentLocation(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_currentLocation, "currentLocation", "()Lcom/fasterxml/jackson/core/JsonLocation;");
+    if (_m_com_fasterxml_jackson_core_JsonParser_currentLocation == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_currentLocation);
     return to_global_ref(_result);
 }
@@ -1107,7 +1317,9 @@
 jobject com_fasterxml_jackson_core_JsonParser_currentTokenLocation(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_currentTokenLocation, "currentTokenLocation", "()Lcom/fasterxml/jackson/core/JsonLocation;");
+    if (_m_com_fasterxml_jackson_core_JsonParser_currentTokenLocation == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_currentTokenLocation);
     return to_global_ref(_result);
 }
@@ -1117,7 +1329,9 @@
 jobject com_fasterxml_jackson_core_JsonParser_getCurrentLocation(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_getCurrentLocation, "getCurrentLocation", "()Lcom/fasterxml/jackson/core/JsonLocation;");
+    if (_m_com_fasterxml_jackson_core_JsonParser_getCurrentLocation == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_getCurrentLocation);
     return to_global_ref(_result);
 }
@@ -1127,7 +1341,9 @@
 jobject com_fasterxml_jackson_core_JsonParser_getTokenLocation(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_getTokenLocation, "getTokenLocation", "()Lcom/fasterxml/jackson/core/JsonLocation;");
+    if (_m_com_fasterxml_jackson_core_JsonParser_getTokenLocation == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_getTokenLocation);
     return to_global_ref(_result);
 }
@@ -1137,7 +1353,9 @@
 jobject com_fasterxml_jackson_core_JsonParser_currentValue(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_currentValue, "currentValue", "()Ljava/lang/Object;");
+    if (_m_com_fasterxml_jackson_core_JsonParser_currentValue == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_currentValue);
     return to_global_ref(_result);
 }
@@ -1147,7 +1365,9 @@
 void com_fasterxml_jackson_core_JsonParser_assignCurrentValue(jobject self_, jobject v) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (void)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_assignCurrentValue, "assignCurrentValue", "(Ljava/lang/Object;)V");
+    if (_m_com_fasterxml_jackson_core_JsonParser_assignCurrentValue == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_assignCurrentValue, v);
 }
 
@@ -1156,7 +1376,9 @@
 jobject com_fasterxml_jackson_core_JsonParser_getCurrentValue(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_getCurrentValue, "getCurrentValue", "()Ljava/lang/Object;");
+    if (_m_com_fasterxml_jackson_core_JsonParser_getCurrentValue == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_getCurrentValue);
     return to_global_ref(_result);
 }
@@ -1166,7 +1388,9 @@
 void com_fasterxml_jackson_core_JsonParser_setCurrentValue(jobject self_, jobject v) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (void)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_setCurrentValue, "setCurrentValue", "(Ljava/lang/Object;)V");
+    if (_m_com_fasterxml_jackson_core_JsonParser_setCurrentValue == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_setCurrentValue, v);
 }
 
@@ -1175,7 +1399,9 @@
 int32_t com_fasterxml_jackson_core_JsonParser_releaseBuffered(jobject self_, jobject out) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (int32_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_releaseBuffered, "releaseBuffered", "(Ljava/io/OutputStream;)I");
+    if (_m_com_fasterxml_jackson_core_JsonParser_releaseBuffered == NULL) return (int32_t)0;
     int32_t _result = (*jniEnv)->CallIntMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_releaseBuffered, out);
     return _result;
 }
@@ -1185,7 +1411,9 @@
 int32_t com_fasterxml_jackson_core_JsonParser_releaseBuffered1(jobject self_, jobject w) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (int32_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_releaseBuffered1, "releaseBuffered", "(Ljava/io/Writer;)I");
+    if (_m_com_fasterxml_jackson_core_JsonParser_releaseBuffered1 == NULL) return (int32_t)0;
     int32_t _result = (*jniEnv)->CallIntMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_releaseBuffered1, w);
     return _result;
 }
@@ -1195,7 +1423,9 @@
 jobject com_fasterxml_jackson_core_JsonParser_enable(jobject self_, jobject f) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_enable, "enable", "(Lcom/fasterxml/jackson/core/JsonParser$Feature;)Lcom/fasterxml/jackson/core/JsonParser;");
+    if (_m_com_fasterxml_jackson_core_JsonParser_enable == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_enable, f);
     return to_global_ref(_result);
 }
@@ -1205,7 +1435,9 @@
 jobject com_fasterxml_jackson_core_JsonParser_disable(jobject self_, jobject f) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_disable, "disable", "(Lcom/fasterxml/jackson/core/JsonParser$Feature;)Lcom/fasterxml/jackson/core/JsonParser;");
+    if (_m_com_fasterxml_jackson_core_JsonParser_disable == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_disable, f);
     return to_global_ref(_result);
 }
@@ -1215,7 +1447,9 @@
 jobject com_fasterxml_jackson_core_JsonParser_configure(jobject self_, jobject f, uint8_t state) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_configure, "configure", "(Lcom/fasterxml/jackson/core/JsonParser$Feature;Z)Lcom/fasterxml/jackson/core/JsonParser;");
+    if (_m_com_fasterxml_jackson_core_JsonParser_configure == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_configure, f, state);
     return to_global_ref(_result);
 }
@@ -1225,7 +1459,9 @@
 uint8_t com_fasterxml_jackson_core_JsonParser_isEnabled(jobject self_, jobject f) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (uint8_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_isEnabled, "isEnabled", "(Lcom/fasterxml/jackson/core/JsonParser$Feature;)Z");
+    if (_m_com_fasterxml_jackson_core_JsonParser_isEnabled == NULL) return (uint8_t)0;
     uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_isEnabled, f);
     return _result;
 }
@@ -1235,7 +1471,9 @@
 uint8_t com_fasterxml_jackson_core_JsonParser_isEnabled1(jobject self_, jobject f) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (uint8_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_isEnabled1, "isEnabled", "(Lcom/fasterxml/jackson/core/StreamReadFeature;)Z");
+    if (_m_com_fasterxml_jackson_core_JsonParser_isEnabled1 == NULL) return (uint8_t)0;
     uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_isEnabled1, f);
     return _result;
 }
@@ -1245,7 +1483,9 @@
 int32_t com_fasterxml_jackson_core_JsonParser_getFeatureMask(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (int32_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_getFeatureMask, "getFeatureMask", "()I");
+    if (_m_com_fasterxml_jackson_core_JsonParser_getFeatureMask == NULL) return (int32_t)0;
     int32_t _result = (*jniEnv)->CallIntMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_getFeatureMask);
     return _result;
 }
@@ -1255,7 +1495,9 @@
 jobject com_fasterxml_jackson_core_JsonParser_setFeatureMask(jobject self_, int32_t mask) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_setFeatureMask, "setFeatureMask", "(I)Lcom/fasterxml/jackson/core/JsonParser;");
+    if (_m_com_fasterxml_jackson_core_JsonParser_setFeatureMask == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_setFeatureMask, mask);
     return to_global_ref(_result);
 }
@@ -1265,7 +1507,9 @@
 jobject com_fasterxml_jackson_core_JsonParser_overrideStdFeatures(jobject self_, int32_t values, int32_t mask) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_overrideStdFeatures, "overrideStdFeatures", "(II)Lcom/fasterxml/jackson/core/JsonParser;");
+    if (_m_com_fasterxml_jackson_core_JsonParser_overrideStdFeatures == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_overrideStdFeatures, values, mask);
     return to_global_ref(_result);
 }
@@ -1275,7 +1519,9 @@
 int32_t com_fasterxml_jackson_core_JsonParser_getFormatFeatures(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (int32_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_getFormatFeatures, "getFormatFeatures", "()I");
+    if (_m_com_fasterxml_jackson_core_JsonParser_getFormatFeatures == NULL) return (int32_t)0;
     int32_t _result = (*jniEnv)->CallIntMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_getFormatFeatures);
     return _result;
 }
@@ -1285,7 +1531,9 @@
 jobject com_fasterxml_jackson_core_JsonParser_overrideFormatFeatures(jobject self_, int32_t values, int32_t mask) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_overrideFormatFeatures, "overrideFormatFeatures", "(II)Lcom/fasterxml/jackson/core/JsonParser;");
+    if (_m_com_fasterxml_jackson_core_JsonParser_overrideFormatFeatures == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_overrideFormatFeatures, values, mask);
     return to_global_ref(_result);
 }
@@ -1295,7 +1543,9 @@
 jobject com_fasterxml_jackson_core_JsonParser_nextToken(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_nextToken, "nextToken", "()Lcom/fasterxml/jackson/core/JsonToken;");
+    if (_m_com_fasterxml_jackson_core_JsonParser_nextToken == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_nextToken);
     return to_global_ref(_result);
 }
@@ -1305,7 +1555,9 @@
 jobject com_fasterxml_jackson_core_JsonParser_nextValue(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_nextValue, "nextValue", "()Lcom/fasterxml/jackson/core/JsonToken;");
+    if (_m_com_fasterxml_jackson_core_JsonParser_nextValue == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_nextValue);
     return to_global_ref(_result);
 }
@@ -1315,7 +1567,9 @@
 uint8_t com_fasterxml_jackson_core_JsonParser_nextFieldName(jobject self_, jobject str) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (uint8_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_nextFieldName, "nextFieldName", "(Lcom/fasterxml/jackson/core/SerializableString;)Z");
+    if (_m_com_fasterxml_jackson_core_JsonParser_nextFieldName == NULL) return (uint8_t)0;
     uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_nextFieldName, str);
     return _result;
 }
@@ -1325,7 +1579,9 @@
 jobject com_fasterxml_jackson_core_JsonParser_nextFieldName1(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_nextFieldName1, "nextFieldName", "()Ljava/lang/String;");
+    if (_m_com_fasterxml_jackson_core_JsonParser_nextFieldName1 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_nextFieldName1);
     return to_global_ref(_result);
 }
@@ -1335,7 +1591,9 @@
 jobject com_fasterxml_jackson_core_JsonParser_nextTextValue(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_nextTextValue, "nextTextValue", "()Ljava/lang/String;");
+    if (_m_com_fasterxml_jackson_core_JsonParser_nextTextValue == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_nextTextValue);
     return to_global_ref(_result);
 }
@@ -1345,7 +1603,9 @@
 int32_t com_fasterxml_jackson_core_JsonParser_nextIntValue(jobject self_, int32_t defaultValue) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (int32_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_nextIntValue, "nextIntValue", "(I)I");
+    if (_m_com_fasterxml_jackson_core_JsonParser_nextIntValue == NULL) return (int32_t)0;
     int32_t _result = (*jniEnv)->CallIntMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_nextIntValue, defaultValue);
     return _result;
 }
@@ -1355,7 +1615,9 @@
 int64_t com_fasterxml_jackson_core_JsonParser_nextLongValue(jobject self_, int64_t defaultValue) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (int64_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_nextLongValue, "nextLongValue", "(J)J");
+    if (_m_com_fasterxml_jackson_core_JsonParser_nextLongValue == NULL) return (int64_t)0;
     int64_t _result = (*jniEnv)->CallLongMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_nextLongValue, defaultValue);
     return _result;
 }
@@ -1365,7 +1627,9 @@
 jobject com_fasterxml_jackson_core_JsonParser_nextBooleanValue(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_nextBooleanValue, "nextBooleanValue", "()Ljava/lang/Boolean;");
+    if (_m_com_fasterxml_jackson_core_JsonParser_nextBooleanValue == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_nextBooleanValue);
     return to_global_ref(_result);
 }
@@ -1375,7 +1639,9 @@
 jobject com_fasterxml_jackson_core_JsonParser_skipChildren(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_skipChildren, "skipChildren", "()Lcom/fasterxml/jackson/core/JsonParser;");
+    if (_m_com_fasterxml_jackson_core_JsonParser_skipChildren == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_skipChildren);
     return to_global_ref(_result);
 }
@@ -1385,7 +1651,9 @@
 void com_fasterxml_jackson_core_JsonParser_finishToken(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (void)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_finishToken, "finishToken", "()V");
+    if (_m_com_fasterxml_jackson_core_JsonParser_finishToken == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_finishToken);
 }
 
@@ -1394,7 +1662,9 @@
 jobject com_fasterxml_jackson_core_JsonParser_currentToken(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_currentToken, "currentToken", "()Lcom/fasterxml/jackson/core/JsonToken;");
+    if (_m_com_fasterxml_jackson_core_JsonParser_currentToken == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_currentToken);
     return to_global_ref(_result);
 }
@@ -1404,7 +1674,9 @@
 int32_t com_fasterxml_jackson_core_JsonParser_currentTokenId(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (int32_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_currentTokenId, "currentTokenId", "()I");
+    if (_m_com_fasterxml_jackson_core_JsonParser_currentTokenId == NULL) return (int32_t)0;
     int32_t _result = (*jniEnv)->CallIntMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_currentTokenId);
     return _result;
 }
@@ -1414,7 +1686,9 @@
 jobject com_fasterxml_jackson_core_JsonParser_getCurrentToken(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_getCurrentToken, "getCurrentToken", "()Lcom/fasterxml/jackson/core/JsonToken;");
+    if (_m_com_fasterxml_jackson_core_JsonParser_getCurrentToken == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_getCurrentToken);
     return to_global_ref(_result);
 }
@@ -1424,7 +1698,9 @@
 int32_t com_fasterxml_jackson_core_JsonParser_getCurrentTokenId(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (int32_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_getCurrentTokenId, "getCurrentTokenId", "()I");
+    if (_m_com_fasterxml_jackson_core_JsonParser_getCurrentTokenId == NULL) return (int32_t)0;
     int32_t _result = (*jniEnv)->CallIntMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_getCurrentTokenId);
     return _result;
 }
@@ -1434,7 +1710,9 @@
 uint8_t com_fasterxml_jackson_core_JsonParser_hasCurrentToken(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (uint8_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_hasCurrentToken, "hasCurrentToken", "()Z");
+    if (_m_com_fasterxml_jackson_core_JsonParser_hasCurrentToken == NULL) return (uint8_t)0;
     uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_hasCurrentToken);
     return _result;
 }
@@ -1444,7 +1722,9 @@
 uint8_t com_fasterxml_jackson_core_JsonParser_hasTokenId(jobject self_, int32_t id) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (uint8_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_hasTokenId, "hasTokenId", "(I)Z");
+    if (_m_com_fasterxml_jackson_core_JsonParser_hasTokenId == NULL) return (uint8_t)0;
     uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_hasTokenId, id);
     return _result;
 }
@@ -1454,7 +1734,9 @@
 uint8_t com_fasterxml_jackson_core_JsonParser_hasToken(jobject self_, jobject t) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (uint8_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_hasToken, "hasToken", "(Lcom/fasterxml/jackson/core/JsonToken;)Z");
+    if (_m_com_fasterxml_jackson_core_JsonParser_hasToken == NULL) return (uint8_t)0;
     uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_hasToken, t);
     return _result;
 }
@@ -1464,7 +1746,9 @@
 uint8_t com_fasterxml_jackson_core_JsonParser_isExpectedStartArrayToken(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (uint8_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_isExpectedStartArrayToken, "isExpectedStartArrayToken", "()Z");
+    if (_m_com_fasterxml_jackson_core_JsonParser_isExpectedStartArrayToken == NULL) return (uint8_t)0;
     uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_isExpectedStartArrayToken);
     return _result;
 }
@@ -1474,7 +1758,9 @@
 uint8_t com_fasterxml_jackson_core_JsonParser_isExpectedStartObjectToken(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (uint8_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_isExpectedStartObjectToken, "isExpectedStartObjectToken", "()Z");
+    if (_m_com_fasterxml_jackson_core_JsonParser_isExpectedStartObjectToken == NULL) return (uint8_t)0;
     uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_isExpectedStartObjectToken);
     return _result;
 }
@@ -1484,7 +1770,9 @@
 uint8_t com_fasterxml_jackson_core_JsonParser_isExpectedNumberIntToken(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (uint8_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_isExpectedNumberIntToken, "isExpectedNumberIntToken", "()Z");
+    if (_m_com_fasterxml_jackson_core_JsonParser_isExpectedNumberIntToken == NULL) return (uint8_t)0;
     uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_isExpectedNumberIntToken);
     return _result;
 }
@@ -1494,7 +1782,9 @@
 uint8_t com_fasterxml_jackson_core_JsonParser_isNaN(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (uint8_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_isNaN, "isNaN", "()Z");
+    if (_m_com_fasterxml_jackson_core_JsonParser_isNaN == NULL) return (uint8_t)0;
     uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_isNaN);
     return _result;
 }
@@ -1504,7 +1794,9 @@
 void com_fasterxml_jackson_core_JsonParser_clearCurrentToken(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (void)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_clearCurrentToken, "clearCurrentToken", "()V");
+    if (_m_com_fasterxml_jackson_core_JsonParser_clearCurrentToken == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_clearCurrentToken);
 }
 
@@ -1513,7 +1805,9 @@
 jobject com_fasterxml_jackson_core_JsonParser_getLastClearedToken(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_getLastClearedToken, "getLastClearedToken", "()Lcom/fasterxml/jackson/core/JsonToken;");
+    if (_m_com_fasterxml_jackson_core_JsonParser_getLastClearedToken == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_getLastClearedToken);
     return to_global_ref(_result);
 }
@@ -1523,7 +1817,9 @@
 void com_fasterxml_jackson_core_JsonParser_overrideCurrentName(jobject self_, jobject name) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (void)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_overrideCurrentName, "overrideCurrentName", "(Ljava/lang/String;)V");
+    if (_m_com_fasterxml_jackson_core_JsonParser_overrideCurrentName == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_overrideCurrentName, name);
 }
 
@@ -1532,7 +1828,9 @@
 jobject com_fasterxml_jackson_core_JsonParser_getCurrentName(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_getCurrentName, "getCurrentName", "()Ljava/lang/String;");
+    if (_m_com_fasterxml_jackson_core_JsonParser_getCurrentName == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_getCurrentName);
     return to_global_ref(_result);
 }
@@ -1542,7 +1840,9 @@
 jobject com_fasterxml_jackson_core_JsonParser_currentName(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_currentName, "currentName", "()Ljava/lang/String;");
+    if (_m_com_fasterxml_jackson_core_JsonParser_currentName == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_currentName);
     return to_global_ref(_result);
 }
@@ -1552,7 +1852,9 @@
 jobject com_fasterxml_jackson_core_JsonParser_getText(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_getText, "getText", "()Ljava/lang/String;");
+    if (_m_com_fasterxml_jackson_core_JsonParser_getText == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_getText);
     return to_global_ref(_result);
 }
@@ -1562,7 +1864,9 @@
 int32_t com_fasterxml_jackson_core_JsonParser_getText1(jobject self_, jobject writer) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (int32_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_getText1, "getText", "(Ljava/io/Writer;)I");
+    if (_m_com_fasterxml_jackson_core_JsonParser_getText1 == NULL) return (int32_t)0;
     int32_t _result = (*jniEnv)->CallIntMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_getText1, writer);
     return _result;
 }
@@ -1572,7 +1876,9 @@
 jobject com_fasterxml_jackson_core_JsonParser_getTextCharacters(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_getTextCharacters, "getTextCharacters", "()L[C;");
+    if (_m_com_fasterxml_jackson_core_JsonParser_getTextCharacters == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_getTextCharacters);
     return to_global_ref(_result);
 }
@@ -1582,7 +1888,9 @@
 int32_t com_fasterxml_jackson_core_JsonParser_getTextLength(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (int32_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_getTextLength, "getTextLength", "()I");
+    if (_m_com_fasterxml_jackson_core_JsonParser_getTextLength == NULL) return (int32_t)0;
     int32_t _result = (*jniEnv)->CallIntMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_getTextLength);
     return _result;
 }
@@ -1592,7 +1900,9 @@
 int32_t com_fasterxml_jackson_core_JsonParser_getTextOffset(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (int32_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_getTextOffset, "getTextOffset", "()I");
+    if (_m_com_fasterxml_jackson_core_JsonParser_getTextOffset == NULL) return (int32_t)0;
     int32_t _result = (*jniEnv)->CallIntMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_getTextOffset);
     return _result;
 }
@@ -1602,7 +1912,9 @@
 uint8_t com_fasterxml_jackson_core_JsonParser_hasTextCharacters(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (uint8_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_hasTextCharacters, "hasTextCharacters", "()Z");
+    if (_m_com_fasterxml_jackson_core_JsonParser_hasTextCharacters == NULL) return (uint8_t)0;
     uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_hasTextCharacters);
     return _result;
 }
@@ -1612,7 +1924,9 @@
 jobject com_fasterxml_jackson_core_JsonParser_getNumberValue(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_getNumberValue, "getNumberValue", "()Ljava/lang/Number;");
+    if (_m_com_fasterxml_jackson_core_JsonParser_getNumberValue == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_getNumberValue);
     return to_global_ref(_result);
 }
@@ -1622,7 +1936,9 @@
 jobject com_fasterxml_jackson_core_JsonParser_getNumberValueExact(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_getNumberValueExact, "getNumberValueExact", "()Ljava/lang/Number;");
+    if (_m_com_fasterxml_jackson_core_JsonParser_getNumberValueExact == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_getNumberValueExact);
     return to_global_ref(_result);
 }
@@ -1632,7 +1948,9 @@
 jobject com_fasterxml_jackson_core_JsonParser_getNumberType(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_getNumberType, "getNumberType", "()Lcom/fasterxml/jackson/core/JsonParser$NumberType;");
+    if (_m_com_fasterxml_jackson_core_JsonParser_getNumberType == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_getNumberType);
     return to_global_ref(_result);
 }
@@ -1642,7 +1960,9 @@
 int8_t com_fasterxml_jackson_core_JsonParser_getByteValue(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (int8_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_getByteValue, "getByteValue", "()B");
+    if (_m_com_fasterxml_jackson_core_JsonParser_getByteValue == NULL) return (int8_t)0;
     int8_t _result = (*jniEnv)->CallByteMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_getByteValue);
     return _result;
 }
@@ -1652,7 +1972,9 @@
 int16_t com_fasterxml_jackson_core_JsonParser_getShortValue(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (int16_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_getShortValue, "getShortValue", "()S");
+    if (_m_com_fasterxml_jackson_core_JsonParser_getShortValue == NULL) return (int16_t)0;
     int16_t _result = (*jniEnv)->CallShortMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_getShortValue);
     return _result;
 }
@@ -1662,7 +1984,9 @@
 int32_t com_fasterxml_jackson_core_JsonParser_getIntValue(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (int32_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_getIntValue, "getIntValue", "()I");
+    if (_m_com_fasterxml_jackson_core_JsonParser_getIntValue == NULL) return (int32_t)0;
     int32_t _result = (*jniEnv)->CallIntMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_getIntValue);
     return _result;
 }
@@ -1672,7 +1996,9 @@
 int64_t com_fasterxml_jackson_core_JsonParser_getLongValue(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (int64_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_getLongValue, "getLongValue", "()J");
+    if (_m_com_fasterxml_jackson_core_JsonParser_getLongValue == NULL) return (int64_t)0;
     int64_t _result = (*jniEnv)->CallLongMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_getLongValue);
     return _result;
 }
@@ -1682,7 +2008,9 @@
 jobject com_fasterxml_jackson_core_JsonParser_getBigIntegerValue(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_getBigIntegerValue, "getBigIntegerValue", "()Ljava/math/BigInteger;");
+    if (_m_com_fasterxml_jackson_core_JsonParser_getBigIntegerValue == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_getBigIntegerValue);
     return to_global_ref(_result);
 }
@@ -1692,7 +2020,9 @@
 float com_fasterxml_jackson_core_JsonParser_getFloatValue(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (float)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_getFloatValue, "getFloatValue", "()F");
+    if (_m_com_fasterxml_jackson_core_JsonParser_getFloatValue == NULL) return (float)0;
     float _result = (*jniEnv)->CallFloatMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_getFloatValue);
     return _result;
 }
@@ -1702,7 +2032,9 @@
 double com_fasterxml_jackson_core_JsonParser_getDoubleValue(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (double)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_getDoubleValue, "getDoubleValue", "()D");
+    if (_m_com_fasterxml_jackson_core_JsonParser_getDoubleValue == NULL) return (double)0;
     double _result = (*jniEnv)->CallDoubleMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_getDoubleValue);
     return _result;
 }
@@ -1712,7 +2044,9 @@
 jobject com_fasterxml_jackson_core_JsonParser_getDecimalValue(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_getDecimalValue, "getDecimalValue", "()Ljava/math/BigDecimal;");
+    if (_m_com_fasterxml_jackson_core_JsonParser_getDecimalValue == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_getDecimalValue);
     return to_global_ref(_result);
 }
@@ -1722,7 +2056,9 @@
 uint8_t com_fasterxml_jackson_core_JsonParser_getBooleanValue(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (uint8_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_getBooleanValue, "getBooleanValue", "()Z");
+    if (_m_com_fasterxml_jackson_core_JsonParser_getBooleanValue == NULL) return (uint8_t)0;
     uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_getBooleanValue);
     return _result;
 }
@@ -1732,7 +2068,9 @@
 jobject com_fasterxml_jackson_core_JsonParser_getEmbeddedObject(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_getEmbeddedObject, "getEmbeddedObject", "()Ljava/lang/Object;");
+    if (_m_com_fasterxml_jackson_core_JsonParser_getEmbeddedObject == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_getEmbeddedObject);
     return to_global_ref(_result);
 }
@@ -1742,7 +2080,9 @@
 jobject com_fasterxml_jackson_core_JsonParser_getBinaryValue(jobject self_, jobject bv) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_getBinaryValue, "getBinaryValue", "(Lcom/fasterxml/jackson/core/Base64Variant;)L[B;");
+    if (_m_com_fasterxml_jackson_core_JsonParser_getBinaryValue == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_getBinaryValue, bv);
     return to_global_ref(_result);
 }
@@ -1752,7 +2092,9 @@
 jobject com_fasterxml_jackson_core_JsonParser_getBinaryValue1(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_getBinaryValue1, "getBinaryValue", "()L[B;");
+    if (_m_com_fasterxml_jackson_core_JsonParser_getBinaryValue1 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_getBinaryValue1);
     return to_global_ref(_result);
 }
@@ -1762,7 +2104,9 @@
 int32_t com_fasterxml_jackson_core_JsonParser_readBinaryValue(jobject self_, jobject out) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (int32_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_readBinaryValue, "readBinaryValue", "(Ljava/io/OutputStream;)I");
+    if (_m_com_fasterxml_jackson_core_JsonParser_readBinaryValue == NULL) return (int32_t)0;
     int32_t _result = (*jniEnv)->CallIntMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_readBinaryValue, out);
     return _result;
 }
@@ -1772,7 +2116,9 @@
 int32_t com_fasterxml_jackson_core_JsonParser_readBinaryValue1(jobject self_, jobject bv, jobject out) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (int32_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_readBinaryValue1, "readBinaryValue", "(Lcom/fasterxml/jackson/core/Base64Variant;Ljava/io/OutputStream;)I");
+    if (_m_com_fasterxml_jackson_core_JsonParser_readBinaryValue1 == NULL) return (int32_t)0;
     int32_t _result = (*jniEnv)->CallIntMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_readBinaryValue1, bv, out);
     return _result;
 }
@@ -1782,7 +2128,9 @@
 int32_t com_fasterxml_jackson_core_JsonParser_getValueAsInt(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (int32_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_getValueAsInt, "getValueAsInt", "()I");
+    if (_m_com_fasterxml_jackson_core_JsonParser_getValueAsInt == NULL) return (int32_t)0;
     int32_t _result = (*jniEnv)->CallIntMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_getValueAsInt);
     return _result;
 }
@@ -1792,7 +2140,9 @@
 int32_t com_fasterxml_jackson_core_JsonParser_getValueAsInt1(jobject self_, int32_t def) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (int32_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_getValueAsInt1, "getValueAsInt", "(I)I");
+    if (_m_com_fasterxml_jackson_core_JsonParser_getValueAsInt1 == NULL) return (int32_t)0;
     int32_t _result = (*jniEnv)->CallIntMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_getValueAsInt1, def);
     return _result;
 }
@@ -1802,7 +2152,9 @@
 int64_t com_fasterxml_jackson_core_JsonParser_getValueAsLong(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (int64_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_getValueAsLong, "getValueAsLong", "()J");
+    if (_m_com_fasterxml_jackson_core_JsonParser_getValueAsLong == NULL) return (int64_t)0;
     int64_t _result = (*jniEnv)->CallLongMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_getValueAsLong);
     return _result;
 }
@@ -1812,7 +2164,9 @@
 int64_t com_fasterxml_jackson_core_JsonParser_getValueAsLong1(jobject self_, int64_t def) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (int64_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_getValueAsLong1, "getValueAsLong", "(J)J");
+    if (_m_com_fasterxml_jackson_core_JsonParser_getValueAsLong1 == NULL) return (int64_t)0;
     int64_t _result = (*jniEnv)->CallLongMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_getValueAsLong1, def);
     return _result;
 }
@@ -1822,7 +2176,9 @@
 double com_fasterxml_jackson_core_JsonParser_getValueAsDouble(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (double)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_getValueAsDouble, "getValueAsDouble", "()D");
+    if (_m_com_fasterxml_jackson_core_JsonParser_getValueAsDouble == NULL) return (double)0;
     double _result = (*jniEnv)->CallDoubleMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_getValueAsDouble);
     return _result;
 }
@@ -1832,7 +2188,9 @@
 double com_fasterxml_jackson_core_JsonParser_getValueAsDouble1(jobject self_, double def) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (double)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_getValueAsDouble1, "getValueAsDouble", "(D)D");
+    if (_m_com_fasterxml_jackson_core_JsonParser_getValueAsDouble1 == NULL) return (double)0;
     double _result = (*jniEnv)->CallDoubleMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_getValueAsDouble1, def);
     return _result;
 }
@@ -1842,7 +2200,9 @@
 uint8_t com_fasterxml_jackson_core_JsonParser_getValueAsBoolean(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (uint8_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_getValueAsBoolean, "getValueAsBoolean", "()Z");
+    if (_m_com_fasterxml_jackson_core_JsonParser_getValueAsBoolean == NULL) return (uint8_t)0;
     uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_getValueAsBoolean);
     return _result;
 }
@@ -1852,7 +2212,9 @@
 uint8_t com_fasterxml_jackson_core_JsonParser_getValueAsBoolean1(jobject self_, uint8_t def) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (uint8_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_getValueAsBoolean1, "getValueAsBoolean", "(Z)Z");
+    if (_m_com_fasterxml_jackson_core_JsonParser_getValueAsBoolean1 == NULL) return (uint8_t)0;
     uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_getValueAsBoolean1, def);
     return _result;
 }
@@ -1862,7 +2224,9 @@
 jobject com_fasterxml_jackson_core_JsonParser_getValueAsString(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_getValueAsString, "getValueAsString", "()Ljava/lang/String;");
+    if (_m_com_fasterxml_jackson_core_JsonParser_getValueAsString == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_getValueAsString);
     return to_global_ref(_result);
 }
@@ -1872,7 +2236,9 @@
 jobject com_fasterxml_jackson_core_JsonParser_getValueAsString1(jobject self_, jobject def) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_getValueAsString1, "getValueAsString", "(Ljava/lang/String;)Ljava/lang/String;");
+    if (_m_com_fasterxml_jackson_core_JsonParser_getValueAsString1 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_getValueAsString1, def);
     return to_global_ref(_result);
 }
@@ -1882,7 +2248,9 @@
 uint8_t com_fasterxml_jackson_core_JsonParser_canReadObjectId(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (uint8_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_canReadObjectId, "canReadObjectId", "()Z");
+    if (_m_com_fasterxml_jackson_core_JsonParser_canReadObjectId == NULL) return (uint8_t)0;
     uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_canReadObjectId);
     return _result;
 }
@@ -1892,7 +2260,9 @@
 uint8_t com_fasterxml_jackson_core_JsonParser_canReadTypeId(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (uint8_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_canReadTypeId, "canReadTypeId", "()Z");
+    if (_m_com_fasterxml_jackson_core_JsonParser_canReadTypeId == NULL) return (uint8_t)0;
     uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_canReadTypeId);
     return _result;
 }
@@ -1902,7 +2272,9 @@
 jobject com_fasterxml_jackson_core_JsonParser_getObjectId(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_getObjectId, "getObjectId", "()Ljava/lang/Object;");
+    if (_m_com_fasterxml_jackson_core_JsonParser_getObjectId == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_getObjectId);
     return to_global_ref(_result);
 }
@@ -1912,7 +2284,9 @@
 jobject com_fasterxml_jackson_core_JsonParser_getTypeId(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_getTypeId, "getTypeId", "()Ljava/lang/Object;");
+    if (_m_com_fasterxml_jackson_core_JsonParser_getTypeId == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_getTypeId);
     return to_global_ref(_result);
 }
@@ -1922,7 +2296,9 @@
 jobject com_fasterxml_jackson_core_JsonParser_readValueAs(jobject self_, jobject valueType) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_readValueAs, "readValueAs", "(Ljava/lang/Class;)Ljava/lang/Object;");
+    if (_m_com_fasterxml_jackson_core_JsonParser_readValueAs == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_readValueAs, valueType);
     return to_global_ref(_result);
 }
@@ -1932,7 +2308,9 @@
 jobject com_fasterxml_jackson_core_JsonParser_readValueAs1(jobject self_, jobject valueTypeRef) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_readValueAs1, "readValueAs", "(Lcom/fasterxml/jackson/core/type/TypeReference;)Ljava/lang/Object;");
+    if (_m_com_fasterxml_jackson_core_JsonParser_readValueAs1 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_readValueAs1, valueTypeRef);
     return to_global_ref(_result);
 }
@@ -1942,7 +2320,9 @@
 jobject com_fasterxml_jackson_core_JsonParser_readValuesAs(jobject self_, jobject valueType) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_readValuesAs, "readValuesAs", "(Ljava/lang/Class;)Ljava/util/Iterator;");
+    if (_m_com_fasterxml_jackson_core_JsonParser_readValuesAs == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_readValuesAs, valueType);
     return to_global_ref(_result);
 }
@@ -1952,7 +2332,9 @@
 jobject com_fasterxml_jackson_core_JsonParser_readValuesAs1(jobject self_, jobject valueTypeRef) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_readValuesAs1, "readValuesAs", "(Lcom/fasterxml/jackson/core/type/TypeReference;)Ljava/util/Iterator;");
+    if (_m_com_fasterxml_jackson_core_JsonParser_readValuesAs1 == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_readValuesAs1, valueTypeRef);
     return to_global_ref(_result);
 }
@@ -1962,7 +2344,9 @@
 jobject com_fasterxml_jackson_core_JsonParser_readValueAsTree(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser, &_m_com_fasterxml_jackson_core_JsonParser_readValueAsTree, "readValueAsTree", "()Ljava/lang/Object;");
+    if (_m_com_fasterxml_jackson_core_JsonParser_readValueAsTree == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser_readValueAsTree);
     return to_global_ref(_result);
 }
@@ -1971,6 +2355,7 @@
 jobject get_com_fasterxml_jackson_core_JsonParser_DEFAULT_READ_CAPABILITIES() {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser, "com/fasterxml/jackson/core/JsonParser");
+    if (_c_com_fasterxml_jackson_core_JsonParser == NULL) return (jobject)0;
     load_static_field(_c_com_fasterxml_jackson_core_JsonParser, &_f_com_fasterxml_jackson_core_JsonParser_DEFAULT_READ_CAPABILITIES, "DEFAULT_READ_CAPABILITIES","Lcom/fasterxml/jackson/core/util/JacksonFeatureSet;");
     return to_global_ref((*jniEnv)->GetStaticObjectField(jniEnv, _c_com_fasterxml_jackson_core_JsonParser, _f_com_fasterxml_jackson_core_JsonParser_DEFAULT_READ_CAPABILITIES));
 }
@@ -1984,7 +2369,9 @@
 jobject com_fasterxml_jackson_core_JsonParser__Feature_values() {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser__Feature, "com/fasterxml/jackson/core/JsonParser$Feature");
+    if (_c_com_fasterxml_jackson_core_JsonParser__Feature == NULL) return (jobject)0;
     load_static_method(_c_com_fasterxml_jackson_core_JsonParser__Feature, &_m_com_fasterxml_jackson_core_JsonParser__Feature_values, "values", "()L[com/fasterxml/jackson/core/JsonParser$Feature;");
+    if (_m_com_fasterxml_jackson_core_JsonParser__Feature_values == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallStaticObjectMethod(jniEnv, _c_com_fasterxml_jackson_core_JsonParser__Feature, _m_com_fasterxml_jackson_core_JsonParser__Feature_values);
     return to_global_ref(_result);
 }
@@ -1994,7 +2381,9 @@
 jobject com_fasterxml_jackson_core_JsonParser__Feature_valueOf(jobject name) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser__Feature, "com/fasterxml/jackson/core/JsonParser$Feature");
+    if (_c_com_fasterxml_jackson_core_JsonParser__Feature == NULL) return (jobject)0;
     load_static_method(_c_com_fasterxml_jackson_core_JsonParser__Feature, &_m_com_fasterxml_jackson_core_JsonParser__Feature_valueOf, "valueOf", "(Ljava/lang/String;)Lcom/fasterxml/jackson/core/JsonParser$Feature;");
+    if (_m_com_fasterxml_jackson_core_JsonParser__Feature_valueOf == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallStaticObjectMethod(jniEnv, _c_com_fasterxml_jackson_core_JsonParser__Feature, _m_com_fasterxml_jackson_core_JsonParser__Feature_valueOf, name);
     return to_global_ref(_result);
 }
@@ -2004,7 +2393,9 @@
 int32_t com_fasterxml_jackson_core_JsonParser__Feature_collectDefaults() {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser__Feature, "com/fasterxml/jackson/core/JsonParser$Feature");
+    if (_c_com_fasterxml_jackson_core_JsonParser__Feature == NULL) return (int32_t)0;
     load_static_method(_c_com_fasterxml_jackson_core_JsonParser__Feature, &_m_com_fasterxml_jackson_core_JsonParser__Feature_collectDefaults, "collectDefaults", "()I");
+    if (_m_com_fasterxml_jackson_core_JsonParser__Feature_collectDefaults == NULL) return (int32_t)0;
     int32_t _result = (*jniEnv)->CallStaticIntMethod(jniEnv, _c_com_fasterxml_jackson_core_JsonParser__Feature, _m_com_fasterxml_jackson_core_JsonParser__Feature_collectDefaults);
     return _result;
 }
@@ -2014,7 +2405,9 @@
 jobject com_fasterxml_jackson_core_JsonParser__Feature_ctor(uint8_t defaultState) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser__Feature, "com/fasterxml/jackson/core/JsonParser$Feature");
+    if (_c_com_fasterxml_jackson_core_JsonParser__Feature == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser__Feature, &_m_com_fasterxml_jackson_core_JsonParser__Feature_ctor, "<init>", "(Z)V");
+    if (_m_com_fasterxml_jackson_core_JsonParser__Feature_ctor == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->NewObject(jniEnv, _c_com_fasterxml_jackson_core_JsonParser__Feature, _m_com_fasterxml_jackson_core_JsonParser__Feature_ctor, defaultState);
     return to_global_ref(_result);
 }
@@ -2024,7 +2417,9 @@
 uint8_t com_fasterxml_jackson_core_JsonParser__Feature_enabledByDefault(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser__Feature, "com/fasterxml/jackson/core/JsonParser$Feature");
+    if (_c_com_fasterxml_jackson_core_JsonParser__Feature == NULL) return (uint8_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser__Feature, &_m_com_fasterxml_jackson_core_JsonParser__Feature_enabledByDefault, "enabledByDefault", "()Z");
+    if (_m_com_fasterxml_jackson_core_JsonParser__Feature_enabledByDefault == NULL) return (uint8_t)0;
     uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser__Feature_enabledByDefault);
     return _result;
 }
@@ -2034,7 +2429,9 @@
 uint8_t com_fasterxml_jackson_core_JsonParser__Feature_enabledIn(jobject self_, int32_t flags) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser__Feature, "com/fasterxml/jackson/core/JsonParser$Feature");
+    if (_c_com_fasterxml_jackson_core_JsonParser__Feature == NULL) return (uint8_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser__Feature, &_m_com_fasterxml_jackson_core_JsonParser__Feature_enabledIn, "enabledIn", "(I)Z");
+    if (_m_com_fasterxml_jackson_core_JsonParser__Feature_enabledIn == NULL) return (uint8_t)0;
     uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser__Feature_enabledIn, flags);
     return _result;
 }
@@ -2044,7 +2441,9 @@
 int32_t com_fasterxml_jackson_core_JsonParser__Feature_getMask(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser__Feature, "com/fasterxml/jackson/core/JsonParser$Feature");
+    if (_c_com_fasterxml_jackson_core_JsonParser__Feature == NULL) return (int32_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser__Feature, &_m_com_fasterxml_jackson_core_JsonParser__Feature_getMask, "getMask", "()I");
+    if (_m_com_fasterxml_jackson_core_JsonParser__Feature_getMask == NULL) return (int32_t)0;
     int32_t _result = (*jniEnv)->CallIntMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonParser__Feature_getMask);
     return _result;
 }
@@ -2057,7 +2456,9 @@
 jobject com_fasterxml_jackson_core_JsonParser__NumberType_values() {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser__NumberType, "com/fasterxml/jackson/core/JsonParser$NumberType");
+    if (_c_com_fasterxml_jackson_core_JsonParser__NumberType == NULL) return (jobject)0;
     load_static_method(_c_com_fasterxml_jackson_core_JsonParser__NumberType, &_m_com_fasterxml_jackson_core_JsonParser__NumberType_values, "values", "()L[com/fasterxml/jackson/core/JsonParser$NumberType;");
+    if (_m_com_fasterxml_jackson_core_JsonParser__NumberType_values == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallStaticObjectMethod(jniEnv, _c_com_fasterxml_jackson_core_JsonParser__NumberType, _m_com_fasterxml_jackson_core_JsonParser__NumberType_values);
     return to_global_ref(_result);
 }
@@ -2067,7 +2468,9 @@
 jobject com_fasterxml_jackson_core_JsonParser__NumberType_valueOf(jobject name) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser__NumberType, "com/fasterxml/jackson/core/JsonParser$NumberType");
+    if (_c_com_fasterxml_jackson_core_JsonParser__NumberType == NULL) return (jobject)0;
     load_static_method(_c_com_fasterxml_jackson_core_JsonParser__NumberType, &_m_com_fasterxml_jackson_core_JsonParser__NumberType_valueOf, "valueOf", "(Ljava/lang/String;)Lcom/fasterxml/jackson/core/JsonParser$NumberType;");
+    if (_m_com_fasterxml_jackson_core_JsonParser__NumberType_valueOf == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallStaticObjectMethod(jniEnv, _c_com_fasterxml_jackson_core_JsonParser__NumberType, _m_com_fasterxml_jackson_core_JsonParser__NumberType_valueOf, name);
     return to_global_ref(_result);
 }
@@ -2077,7 +2480,9 @@
 jobject com_fasterxml_jackson_core_JsonParser__NumberType_ctor() {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonParser__NumberType, "com/fasterxml/jackson/core/JsonParser$NumberType");
+    if (_c_com_fasterxml_jackson_core_JsonParser__NumberType == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonParser__NumberType, &_m_com_fasterxml_jackson_core_JsonParser__NumberType_ctor, "<init>", "()V");
+    if (_m_com_fasterxml_jackson_core_JsonParser__NumberType_ctor == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->NewObject(jniEnv, _c_com_fasterxml_jackson_core_JsonParser__NumberType, _m_com_fasterxml_jackson_core_JsonParser__NumberType_ctor);
     return to_global_ref(_result);
 }
@@ -2090,7 +2495,9 @@
 jobject com_fasterxml_jackson_core_JsonToken_values() {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonToken, "com/fasterxml/jackson/core/JsonToken");
+    if (_c_com_fasterxml_jackson_core_JsonToken == NULL) return (jobject)0;
     load_static_method(_c_com_fasterxml_jackson_core_JsonToken, &_m_com_fasterxml_jackson_core_JsonToken_values, "values", "()L[com/fasterxml/jackson/core/JsonToken;");
+    if (_m_com_fasterxml_jackson_core_JsonToken_values == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallStaticObjectMethod(jniEnv, _c_com_fasterxml_jackson_core_JsonToken, _m_com_fasterxml_jackson_core_JsonToken_values);
     return to_global_ref(_result);
 }
@@ -2100,7 +2507,9 @@
 jobject com_fasterxml_jackson_core_JsonToken_valueOf(jobject name) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonToken, "com/fasterxml/jackson/core/JsonToken");
+    if (_c_com_fasterxml_jackson_core_JsonToken == NULL) return (jobject)0;
     load_static_method(_c_com_fasterxml_jackson_core_JsonToken, &_m_com_fasterxml_jackson_core_JsonToken_valueOf, "valueOf", "(Ljava/lang/String;)Lcom/fasterxml/jackson/core/JsonToken;");
+    if (_m_com_fasterxml_jackson_core_JsonToken_valueOf == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallStaticObjectMethod(jniEnv, _c_com_fasterxml_jackson_core_JsonToken, _m_com_fasterxml_jackson_core_JsonToken_valueOf, name);
     return to_global_ref(_result);
 }
@@ -2110,7 +2519,9 @@
 jobject com_fasterxml_jackson_core_JsonToken_ctor(jobject token, int32_t id) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonToken, "com/fasterxml/jackson/core/JsonToken");
+    if (_c_com_fasterxml_jackson_core_JsonToken == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonToken, &_m_com_fasterxml_jackson_core_JsonToken_ctor, "<init>", "(Ljava/lang/String;I)V");
+    if (_m_com_fasterxml_jackson_core_JsonToken_ctor == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->NewObject(jniEnv, _c_com_fasterxml_jackson_core_JsonToken, _m_com_fasterxml_jackson_core_JsonToken_ctor, token, id);
     return to_global_ref(_result);
 }
@@ -2120,7 +2531,9 @@
 int32_t com_fasterxml_jackson_core_JsonToken_id(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonToken, "com/fasterxml/jackson/core/JsonToken");
+    if (_c_com_fasterxml_jackson_core_JsonToken == NULL) return (int32_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonToken, &_m_com_fasterxml_jackson_core_JsonToken_id, "id", "()I");
+    if (_m_com_fasterxml_jackson_core_JsonToken_id == NULL) return (int32_t)0;
     int32_t _result = (*jniEnv)->CallIntMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonToken_id);
     return _result;
 }
@@ -2130,7 +2543,9 @@
 jobject com_fasterxml_jackson_core_JsonToken_asString(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonToken, "com/fasterxml/jackson/core/JsonToken");
+    if (_c_com_fasterxml_jackson_core_JsonToken == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonToken, &_m_com_fasterxml_jackson_core_JsonToken_asString, "asString", "()Ljava/lang/String;");
+    if (_m_com_fasterxml_jackson_core_JsonToken_asString == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonToken_asString);
     return to_global_ref(_result);
 }
@@ -2140,7 +2555,9 @@
 jobject com_fasterxml_jackson_core_JsonToken_asCharArray(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonToken, "com/fasterxml/jackson/core/JsonToken");
+    if (_c_com_fasterxml_jackson_core_JsonToken == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonToken, &_m_com_fasterxml_jackson_core_JsonToken_asCharArray, "asCharArray", "()L[C;");
+    if (_m_com_fasterxml_jackson_core_JsonToken_asCharArray == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonToken_asCharArray);
     return to_global_ref(_result);
 }
@@ -2150,7 +2567,9 @@
 jobject com_fasterxml_jackson_core_JsonToken_asByteArray(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonToken, "com/fasterxml/jackson/core/JsonToken");
+    if (_c_com_fasterxml_jackson_core_JsonToken == NULL) return (jobject)0;
     load_method(_c_com_fasterxml_jackson_core_JsonToken, &_m_com_fasterxml_jackson_core_JsonToken_asByteArray, "asByteArray", "()L[B;");
+    if (_m_com_fasterxml_jackson_core_JsonToken_asByteArray == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonToken_asByteArray);
     return to_global_ref(_result);
 }
@@ -2160,7 +2579,9 @@
 uint8_t com_fasterxml_jackson_core_JsonToken_isNumeric(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonToken, "com/fasterxml/jackson/core/JsonToken");
+    if (_c_com_fasterxml_jackson_core_JsonToken == NULL) return (uint8_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonToken, &_m_com_fasterxml_jackson_core_JsonToken_isNumeric, "isNumeric", "()Z");
+    if (_m_com_fasterxml_jackson_core_JsonToken_isNumeric == NULL) return (uint8_t)0;
     uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonToken_isNumeric);
     return _result;
 }
@@ -2170,7 +2591,9 @@
 uint8_t com_fasterxml_jackson_core_JsonToken_isStructStart(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonToken, "com/fasterxml/jackson/core/JsonToken");
+    if (_c_com_fasterxml_jackson_core_JsonToken == NULL) return (uint8_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonToken, &_m_com_fasterxml_jackson_core_JsonToken_isStructStart, "isStructStart", "()Z");
+    if (_m_com_fasterxml_jackson_core_JsonToken_isStructStart == NULL) return (uint8_t)0;
     uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonToken_isStructStart);
     return _result;
 }
@@ -2180,7 +2603,9 @@
 uint8_t com_fasterxml_jackson_core_JsonToken_isStructEnd(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonToken, "com/fasterxml/jackson/core/JsonToken");
+    if (_c_com_fasterxml_jackson_core_JsonToken == NULL) return (uint8_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonToken, &_m_com_fasterxml_jackson_core_JsonToken_isStructEnd, "isStructEnd", "()Z");
+    if (_m_com_fasterxml_jackson_core_JsonToken_isStructEnd == NULL) return (uint8_t)0;
     uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonToken_isStructEnd);
     return _result;
 }
@@ -2190,7 +2615,9 @@
 uint8_t com_fasterxml_jackson_core_JsonToken_isScalarValue(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonToken, "com/fasterxml/jackson/core/JsonToken");
+    if (_c_com_fasterxml_jackson_core_JsonToken == NULL) return (uint8_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonToken, &_m_com_fasterxml_jackson_core_JsonToken_isScalarValue, "isScalarValue", "()Z");
+    if (_m_com_fasterxml_jackson_core_JsonToken_isScalarValue == NULL) return (uint8_t)0;
     uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonToken_isScalarValue);
     return _result;
 }
@@ -2200,7 +2627,9 @@
 uint8_t com_fasterxml_jackson_core_JsonToken_isBoolean(jobject self_) {
     load_env();
     load_class_gr(&_c_com_fasterxml_jackson_core_JsonToken, "com/fasterxml/jackson/core/JsonToken");
+    if (_c_com_fasterxml_jackson_core_JsonToken == NULL) return (uint8_t)0;
     load_method(_c_com_fasterxml_jackson_core_JsonToken, &_m_com_fasterxml_jackson_core_JsonToken_isBoolean, "isBoolean", "()Z");
+    if (_m_com_fasterxml_jackson_core_JsonToken_isBoolean == NULL) return (uint8_t)0;
     uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_com_fasterxml_jackson_core_JsonToken_isBoolean);
     return _result;
 }
diff --git a/pkgs/jnigen/test/simple_package_test/generate.dart b/pkgs/jnigen/test/simple_package_test/generate.dart
index 471a648..87906b8 100644
--- a/pkgs/jnigen/test/simple_package_test/generate.dart
+++ b/pkgs/jnigen/test/simple_package_test/generate.dart
@@ -13,6 +13,13 @@
 final testRoot = join('test', testName);
 final javaPath = join(testRoot, 'java');
 
+const preamble = '''
+// 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.
+
+''';
+
 var javaPrefix = join('com', 'github', 'dart_lang', 'jnigen');
 
 var javaFiles = [
@@ -42,6 +49,7 @@
       'com.github.dart_lang.jnigen.simple_package',
       'com.github.dart_lang.jnigen.pkg2',
     ],
+    preamble: preamble,
     cRoot: cWrapperDir,
     dartRoot: dartWrappersRoot,
     libraryName: 'simple_package',
diff --git a/pkgs/jnigen/test/simple_package_test/generated_files_test.dart b/pkgs/jnigen/test/simple_package_test/generated_files_test.dart
index 1efa35c..ae1b4ba 100644
--- a/pkgs/jnigen/test/simple_package_test/generated_files_test.dart
+++ b/pkgs/jnigen/test/simple_package_test/generated_files_test.dart
@@ -17,10 +17,12 @@
     compareDirs(join(testRoot, 'lib'), join(testRoot, 'test_lib'));
     compareDirs(join(testRoot, 'src'), join(testRoot, 'test_src'));
   });
-  for (var path in ['test_lib', 'test_src']) {
-    final folder = Directory(path);
-    if (await folder.exists()) {
-      await folder.delete(recursive: true);
+  tearDownAll(() async {
+    for (var path in ['test_lib', 'test_src']) {
+      final folder = Directory(join(testRoot, path));
+      if (await folder.exists()) {
+        await folder.delete(recursive: true);
+      }
     }
-  }
+  });
 }
diff --git a/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/pkg2/C2.java b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/pkg2/C2.java
index a3c8204..fde1e6d 100644
--- a/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/pkg2/C2.java
+++ b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/pkg2/C2.java
@@ -1,3 +1,7 @@
+// 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.
+
 package com.github.dart_lang.jnigen.pkg2;
 
 public class C2 {
diff --git a/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/simple_package/Example.java b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/simple_package/Example.java
index 81c2dd7..ec0c55d 100644
--- a/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/simple_package/Example.java
+++ b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/simple_package/Example.java
@@ -1,3 +1,7 @@
+// 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.
+
 package com.github.dart_lang.jnigen.simple_package;
 
 public class Example {
@@ -32,6 +36,10 @@
     this.num = num;
   }
 
+  public static void throwException() {
+    throw new RuntimeException("Hello");
+  }
+
   public static class Aux {
     public boolean value;
 
diff --git a/pkgs/jnigen/test/simple_package_test/lib/_init.dart b/pkgs/jnigen/test/simple_package_test/lib/_init.dart
new file mode 100644
index 0000000..f0e14e4
--- /dev/null
+++ b/pkgs/jnigen/test/simple_package_test/lib/_init.dart
@@ -0,0 +1,9 @@
+// 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:jni/internal_helpers_for_jnigen.dart";
+
+final Pointer<T> Function<T extends NativeType>(String sym) jniLookup =
+    ProtectedJniExtensions.initGeneratedLibrary("simple_package");
diff --git a/pkgs/jnigen/test/simple_package_test/lib/com/github/dart_lang/jnigen/pkg2.dart b/pkgs/jnigen/test/simple_package_test/lib/com/github/dart_lang/jnigen/pkg2.dart
index 1d9f5ee..4f81578 100644
--- a/pkgs/jnigen/test/simple_package_test/lib/com/github/dart_lang/jnigen/pkg2.dart
+++ b/pkgs/jnigen/test/simple_package_test/lib/com/github/dart_lang/jnigen/pkg2.dart
@@ -1,3 +1,7 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
 // Autogenerated by jnigen. DO NOT EDIT!
 
 // ignore_for_file: camel_case_types
@@ -8,24 +12,23 @@
 // ignore_for_file: unused_element
 
 import "dart:ffi" as ffi;
-
 import "package:jni/jni.dart" as jni;
 
-import "../../../../init.dart" show jlookup;
+import "../../../../_init.dart" show jniLookup;
 
 /// from: com.github.dart_lang.jnigen.pkg2.C2
-class C2 extends jni.JlObject {
+class C2 extends jni.JniObject {
   C2.fromRef(ffi.Pointer<ffi.Void> ref) : super.fromRef(ref);
 
   static final _get_CONSTANT =
-      jlookup<ffi.NativeFunction<ffi.Int32 Function()>>(
+      jniLookup<ffi.NativeFunction<ffi.Int32 Function()>>(
               "get_com_github_dart_lang_jnigen_pkg2_C2_CONSTANT")
           .asFunction<int Function()>();
 
   /// from: static public int CONSTANT
   static int get CONSTANT => _get_CONSTANT();
   static final _set_CONSTANT =
-      jlookup<ffi.NativeFunction<ffi.Void Function(ffi.Int32)>>(
+      jniLookup<ffi.NativeFunction<ffi.Void Function(ffi.Int32)>>(
               "set_com_github_dart_lang_jnigen_pkg2_C2_CONSTANT")
           .asFunction<void Function(int)>();
 
@@ -33,10 +36,12 @@
   static set CONSTANT(int value) => _set_CONSTANT(value);
 
   static final _ctor =
-      jlookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function()>>(
+      jniLookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function()>>(
               "com_github_dart_lang_jnigen_pkg2_C2_ctor")
           .asFunction<ffi.Pointer<ffi.Void> Function()>();
 
   /// from: public void <init>()
-  C2() : super.fromRef(_ctor());
+  C2() : super.fromRef(_ctor()) {
+    jni.Jni.env.checkException();
+  }
 }
diff --git a/pkgs/jnigen/test/simple_package_test/lib/com/github/dart_lang/jnigen/simple_package.dart b/pkgs/jnigen/test/simple_package_test/lib/com/github/dart_lang/jnigen/simple_package.dart
index 41655b8..3d05204 100644
--- a/pkgs/jnigen/test/simple_package_test/lib/com/github/dart_lang/jnigen/simple_package.dart
+++ b/pkgs/jnigen/test/simple_package_test/lib/com/github/dart_lang/jnigen/simple_package.dart
@@ -1,3 +1,7 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
 // Autogenerated by jnigen. DO NOT EDIT!
 
 // ignore_for_file: camel_case_types
@@ -8,13 +12,12 @@
 // ignore_for_file: unused_element
 
 import "dart:ffi" as ffi;
-
 import "package:jni/jni.dart" as jni;
 
-import "../../../../init.dart" show jlookup;
+import "../../../../_init.dart" show jniLookup;
 
 /// from: com.github.dart_lang.jnigen.simple_package.Example
-class Example extends jni.JlObject {
+class Example extends jni.JniObject {
   Example.fromRef(ffi.Pointer<ffi.Void> ref) : super.fromRef(ref);
 
   /// from: static public final int ON
@@ -24,7 +27,7 @@
   static const OFF = 0;
 
   static final _get_aux =
-      jlookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function()>>(
+      jniLookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function()>>(
               "get_com_github_dart_lang_jnigen_simple_package_Example_aux")
           .asFunction<ffi.Pointer<ffi.Void> Function()>();
 
@@ -32,7 +35,7 @@
   /// The returned object must be deleted after use, by calling the `delete` method.
   static Example_Aux get aux => Example_Aux.fromRef(_get_aux());
   static final _set_aux =
-      jlookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
               "set_com_github_dart_lang_jnigen_simple_package_Example_aux")
           .asFunction<void Function(ffi.Pointer<ffi.Void>)>();
 
@@ -40,14 +43,14 @@
   /// The returned object must be deleted after use, by calling the `delete` method.
   static set aux(Example_Aux value) => _set_aux(value.reference);
 
-  static final _get_num = jlookup<ffi.NativeFunction<ffi.Int32 Function()>>(
+  static final _get_num = jniLookup<ffi.NativeFunction<ffi.Int32 Function()>>(
           "get_com_github_dart_lang_jnigen_simple_package_Example_num")
       .asFunction<int Function()>();
 
   /// from: static public int num
   static int get num => _get_num();
   static final _set_num =
-      jlookup<ffi.NativeFunction<ffi.Void Function(ffi.Int32)>>(
+      jniLookup<ffi.NativeFunction<ffi.Void Function(ffi.Int32)>>(
               "set_com_github_dart_lang_jnigen_simple_package_Example_num")
           .asFunction<void Function(int)>();
 
@@ -55,31 +58,41 @@
   static set num(int value) => _set_num(value);
 
   static final _ctor =
-      jlookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function()>>(
+      jniLookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function()>>(
               "com_github_dart_lang_jnigen_simple_package_Example_ctor")
           .asFunction<ffi.Pointer<ffi.Void> Function()>();
 
   /// from: public void <init>()
-  Example() : super.fromRef(_ctor());
+  Example() : super.fromRef(_ctor()) {
+    jni.Jni.env.checkException();
+  }
 
   static final _getAux =
-      jlookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function()>>(
+      jniLookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function()>>(
               "com_github_dart_lang_jnigen_simple_package_Example_getAux")
           .asFunction<ffi.Pointer<ffi.Void> Function()>();
 
   /// from: static public com.github.dart_lang.jnigen.simple_package.Example.Aux getAux()
   /// The returned object must be deleted after use, by calling the `delete` method.
-  static Example_Aux getAux() => Example_Aux.fromRef(_getAux());
+  static Example_Aux getAux() {
+    final result__ = Example_Aux.fromRef(_getAux());
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _addInts =
-      jlookup<ffi.NativeFunction<ffi.Int32 Function(ffi.Int32, ffi.Int32)>>(
+      jniLookup<ffi.NativeFunction<ffi.Int32 Function(ffi.Int32, ffi.Int32)>>(
               "com_github_dart_lang_jnigen_simple_package_Example_addInts")
           .asFunction<int Function(int, int)>();
 
   /// from: static public int addInts(int a, int b)
-  static int addInts(int a, int b) => _addInts(a, b);
+  static int addInts(int a, int b) {
+    final result__ = _addInts(a, b);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _getSelf = jlookup<
+  static final _getSelf = jniLookup<
               ffi.NativeFunction<
                   ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
           "com_github_dart_lang_jnigen_simple_package_Example_getSelf")
@@ -87,31 +100,55 @@
 
   /// from: public com.github.dart_lang.jnigen.simple_package.Example getSelf()
   /// The returned object must be deleted after use, by calling the `delete` method.
-  Example getSelf() => Example.fromRef(_getSelf(reference));
+  Example getSelf() {
+    final result__ = Example.fromRef(_getSelf(reference));
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
   static final _getNum =
-      jlookup<ffi.NativeFunction<ffi.Int32 Function(ffi.Pointer<ffi.Void>)>>(
+      jniLookup<ffi.NativeFunction<ffi.Int32 Function(ffi.Pointer<ffi.Void>)>>(
               "com_github_dart_lang_jnigen_simple_package_Example_getNum")
           .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
   /// from: public int getNum()
-  int getNum() => _getNum(reference);
+  int getNum() {
+    final result__ = _getNum(reference);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _setNum = jlookup<
+  static final _setNum = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Int32)>>(
           "com_github_dart_lang_jnigen_simple_package_Example_setNum")
       .asFunction<void Function(ffi.Pointer<ffi.Void>, int)>();
 
   /// from: public void setNum(int num)
-  void setNum(int num) => _setNum(reference, num);
+  void setNum(int num) {
+    final result__ = _setNum(reference, num);
+    jni.Jni.env.checkException();
+    return result__;
+  }
+
+  static final _throwException = jniLookup<
+              ffi.NativeFunction<ffi.Void Function()>>(
+          "com_github_dart_lang_jnigen_simple_package_Example_throwException")
+      .asFunction<void Function()>();
+
+  /// from: static public void throwException()
+  static void throwException() {
+    final result__ = _throwException();
+    jni.Jni.env.checkException();
+    return result__;
+  }
 }
 
 /// from: com.github.dart_lang.jnigen.simple_package.Example$Aux
-class Example_Aux extends jni.JlObject {
+class Example_Aux extends jni.JniObject {
   Example_Aux.fromRef(ffi.Pointer<ffi.Void> ref) : super.fromRef(ref);
 
-  static final _get_value = jlookup<
+  static final _get_value = jniLookup<
           ffi.NativeFunction<
               ffi.Uint8 Function(
     ffi.Pointer<ffi.Void>,
@@ -123,7 +160,7 @@
 
   /// from: public boolean value
   bool get value => _get_value(reference) != 0;
-  static final _set_value = jlookup<
+  static final _set_value = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Uint8)>>(
           "set_com_github_dart_lang_jnigen_simple_package_Example__Aux_value")
@@ -133,27 +170,37 @@
   set value(bool value) => _set_value(reference, value ? 1 : 0);
 
   static final _ctor =
-      jlookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function(ffi.Uint8)>>(
+      jniLookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function(ffi.Uint8)>>(
               "com_github_dart_lang_jnigen_simple_package_Example__Aux_ctor")
           .asFunction<ffi.Pointer<ffi.Void> Function(int)>();
 
   /// from: public void <init>(boolean value)
-  Example_Aux(bool value) : super.fromRef(_ctor(value ? 1 : 0));
+  Example_Aux(bool value) : super.fromRef(_ctor(value ? 1 : 0)) {
+    jni.Jni.env.checkException();
+  }
 
-  static final _getValue = jlookup<
+  static final _getValue = jniLookup<
               ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
           "com_github_dart_lang_jnigen_simple_package_Example__Aux_getValue")
       .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
 
   /// from: public boolean getValue()
-  bool getValue() => _getValue(reference) != 0;
+  bool getValue() {
+    final result__ = _getValue(reference) != 0;
+    jni.Jni.env.checkException();
+    return result__;
+  }
 
-  static final _setValue = jlookup<
+  static final _setValue = jniLookup<
               ffi.NativeFunction<
                   ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Uint8)>>(
           "com_github_dart_lang_jnigen_simple_package_Example__Aux_setValue")
       .asFunction<void Function(ffi.Pointer<ffi.Void>, int)>();
 
   /// from: public void setValue(boolean value)
-  void setValue(bool value) => _setValue(reference, value ? 1 : 0);
+  void setValue(bool value) {
+    final result__ = _setValue(reference, value ? 1 : 0);
+    jni.Jni.env.checkException();
+    return result__;
+  }
 }
diff --git a/pkgs/jnigen/test/simple_package_test/lib/init.dart b/pkgs/jnigen/test/simple_package_test/lib/init.dart
deleted file mode 100644
index 4b5537c..0000000
--- a/pkgs/jnigen/test/simple_package_test/lib/init.dart
+++ /dev/null
@@ -1,5 +0,0 @@
-import "dart:ffi";
-import "package:jni/jni.dart";
-
-final Pointer<T> Function<T extends NativeType>(String sym) jlookup =
-    Jni.getInstance().initGeneratedLibrary("simple_package");
diff --git a/pkgs/jnigen/test/simple_package_test/src/dartjni.h b/pkgs/jnigen/test/simple_package_test/src/dartjni.h
index cd94b15..0ce5069 100644
--- a/pkgs/jnigen/test/simple_package_test/src/dartjni.h
+++ b/pkgs/jnigen/test/simple_package_test/src/dartjni.h
@@ -2,6 +2,8 @@
 // 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.
 
+#pragma once
+
 #include <jni.h>
 #include <stdint.h>
 #include <stdio.h>
@@ -38,17 +40,17 @@
 #define __ENVP_CAST (void **)
 #endif
 
-struct jni_context {
+typedef struct JniContext {
 	JavaVM *jvm;
 	jobject classLoader;
 	jmethodID loadClassMethod;
 	jobject currentActivity;
 	jobject appContext;
-};
+} JniContext;
 
 extern thread_local JNIEnv *jniEnv;
 
-extern struct jni_context jni;
+extern JniContext jni;
 
 enum DartJniLogLevel {
 	JNI_VERBOSE = 2,
@@ -58,10 +60,25 @@
 	JNI_ERROR
 };
 
-FFI_PLUGIN_EXPORT struct jni_context GetJniContext();
+enum JniType {
+	boolType = 0,
+	byteType = 1,
+	shortType = 2,
+	charType = 3,
+	intType = 4,
+	longType = 5,
+	floatType = 6,
+	doubleType = 7,
+	objectType = 8,
+	voidType = 9,
+};
+
+FFI_PLUGIN_EXPORT JniContext GetJniContext();
 
 FFI_PLUGIN_EXPORT JavaVM *GetJavaVM(void);
 
+FFI_PLUGIN_EXPORT int DestroyJavaVM();
+
 FFI_PLUGIN_EXPORT JNIEnv *GetJniEnv(void);
 
 FFI_PLUGIN_EXPORT JNIEnv *SpawnJvm(JavaVMInitArgs *args);
@@ -74,26 +91,16 @@
 
 FFI_PLUGIN_EXPORT jobject GetCurrentActivity(void);
 
-FFI_PLUGIN_EXPORT void SetJNILogging(int level);
+/// For use by jni_gen's generated code
+/// don't use these.
 
-FFI_PLUGIN_EXPORT jstring ToJavaString(char *str);
-
-FFI_PLUGIN_EXPORT const char *GetJavaStringChars(jstring jstr);
-
-FFI_PLUGIN_EXPORT void ReleaseJavaStringChars(jstring jstr, const char *buf);
-
-// These 2 are the function pointer variables defined and exported by
-// the generated C files.
-//
-// initGeneratedLibrary function in Jni class will set these to
-// corresponding functions to the implementations from `dartjni` base library
-// which initializes and manages the JNI.
-extern struct jni_context (*context_getter)(void);
+// these 2 fn ptr vars will be defined by generated code library
+extern JniContext (*context_getter)(void);
 extern JNIEnv *(*env_getter)(void);
 
-// This function will be exported by generated code library and will set the
-// above 2 variables.
-FFI_PLUGIN_EXPORT void setJniGetters(struct jni_context (*cg)(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),
 		JNIEnv *(*eg)(void));
 
 // `static inline` because `inline` doesn't work, it may still not
@@ -101,6 +108,7 @@
 //
 // 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) {
 #ifdef __ANDROID__
 	jstring className = (*jniEnv)->NewStringUTF(jniEnv, name);
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 3ab0c54..dc38b43 100644
--- a/pkgs/jnigen/test/simple_package_test/src/simple_package.c
+++ b/pkgs/jnigen/test/simple_package_test/src/simple_package.c
@@ -1,3 +1,8 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+
 // Autogenerated by jnigen. DO NOT EDIT!
 
 #include <stdint.h>
@@ -5,12 +10,12 @@
 #include "dartjni.h"
 
 thread_local JNIEnv *jniEnv;
-struct jni_context jni;
+JniContext jni;
 
-struct jni_context (*context_getter)(void);
+JniContext (*context_getter)(void);
 JNIEnv *(*env_getter)(void);
 
-void setJniGetters(struct jni_context (*cg)(void),
+void setJniGetters(JniContext (*cg)(void),
         JNIEnv *(*eg)(void)) {
     context_getter = cg;
     env_getter = eg;
@@ -24,7 +29,9 @@
 jobject com_github_dart_lang_jnigen_simple_package_Example_ctor() {
     load_env();
     load_class_gr(&_c_com_github_dart_lang_jnigen_simple_package_Example, "com/github/dart_lang/jnigen/simple_package/Example");
+    if (_c_com_github_dart_lang_jnigen_simple_package_Example == NULL) return (jobject)0;
     load_method(_c_com_github_dart_lang_jnigen_simple_package_Example, &_m_com_github_dart_lang_jnigen_simple_package_Example_ctor, "<init>", "()V");
+    if (_m_com_github_dart_lang_jnigen_simple_package_Example_ctor == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->NewObject(jniEnv, _c_com_github_dart_lang_jnigen_simple_package_Example, _m_com_github_dart_lang_jnigen_simple_package_Example_ctor);
     return to_global_ref(_result);
 }
@@ -34,7 +41,9 @@
 jobject com_github_dart_lang_jnigen_simple_package_Example_getAux() {
     load_env();
     load_class_gr(&_c_com_github_dart_lang_jnigen_simple_package_Example, "com/github/dart_lang/jnigen/simple_package/Example");
+    if (_c_com_github_dart_lang_jnigen_simple_package_Example == NULL) return (jobject)0;
     load_static_method(_c_com_github_dart_lang_jnigen_simple_package_Example, &_m_com_github_dart_lang_jnigen_simple_package_Example_getAux, "getAux", "()Lcom/github/dart_lang/jnigen/simple_package/Example$Aux;");
+    if (_m_com_github_dart_lang_jnigen_simple_package_Example_getAux == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallStaticObjectMethod(jniEnv, _c_com_github_dart_lang_jnigen_simple_package_Example, _m_com_github_dart_lang_jnigen_simple_package_Example_getAux);
     return to_global_ref(_result);
 }
@@ -44,7 +53,9 @@
 int32_t com_github_dart_lang_jnigen_simple_package_Example_addInts(int32_t a, int32_t b) {
     load_env();
     load_class_gr(&_c_com_github_dart_lang_jnigen_simple_package_Example, "com/github/dart_lang/jnigen/simple_package/Example");
+    if (_c_com_github_dart_lang_jnigen_simple_package_Example == NULL) return (int32_t)0;
     load_static_method(_c_com_github_dart_lang_jnigen_simple_package_Example, &_m_com_github_dart_lang_jnigen_simple_package_Example_addInts, "addInts", "(II)I");
+    if (_m_com_github_dart_lang_jnigen_simple_package_Example_addInts == NULL) return (int32_t)0;
     int32_t _result = (*jniEnv)->CallStaticIntMethod(jniEnv, _c_com_github_dart_lang_jnigen_simple_package_Example, _m_com_github_dart_lang_jnigen_simple_package_Example_addInts, a, b);
     return _result;
 }
@@ -54,7 +65,9 @@
 jobject com_github_dart_lang_jnigen_simple_package_Example_getSelf(jobject self_) {
     load_env();
     load_class_gr(&_c_com_github_dart_lang_jnigen_simple_package_Example, "com/github/dart_lang/jnigen/simple_package/Example");
+    if (_c_com_github_dart_lang_jnigen_simple_package_Example == NULL) return (jobject)0;
     load_method(_c_com_github_dart_lang_jnigen_simple_package_Example, &_m_com_github_dart_lang_jnigen_simple_package_Example_getSelf, "getSelf", "()Lcom/github/dart_lang/jnigen/simple_package/Example;");
+    if (_m_com_github_dart_lang_jnigen_simple_package_Example_getSelf == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_com_github_dart_lang_jnigen_simple_package_Example_getSelf);
     return to_global_ref(_result);
 }
@@ -64,7 +77,9 @@
 int32_t com_github_dart_lang_jnigen_simple_package_Example_getNum(jobject self_) {
     load_env();
     load_class_gr(&_c_com_github_dart_lang_jnigen_simple_package_Example, "com/github/dart_lang/jnigen/simple_package/Example");
+    if (_c_com_github_dart_lang_jnigen_simple_package_Example == NULL) return (int32_t)0;
     load_method(_c_com_github_dart_lang_jnigen_simple_package_Example, &_m_com_github_dart_lang_jnigen_simple_package_Example_getNum, "getNum", "()I");
+    if (_m_com_github_dart_lang_jnigen_simple_package_Example_getNum == NULL) return (int32_t)0;
     int32_t _result = (*jniEnv)->CallIntMethod(jniEnv, self_, _m_com_github_dart_lang_jnigen_simple_package_Example_getNum);
     return _result;
 }
@@ -74,14 +89,28 @@
 void com_github_dart_lang_jnigen_simple_package_Example_setNum(jobject self_, int32_t num) {
     load_env();
     load_class_gr(&_c_com_github_dart_lang_jnigen_simple_package_Example, "com/github/dart_lang/jnigen/simple_package/Example");
+    if (_c_com_github_dart_lang_jnigen_simple_package_Example == NULL) return (void)0;
     load_method(_c_com_github_dart_lang_jnigen_simple_package_Example, &_m_com_github_dart_lang_jnigen_simple_package_Example_setNum, "setNum", "(I)V");
+    if (_m_com_github_dart_lang_jnigen_simple_package_Example_setNum == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_com_github_dart_lang_jnigen_simple_package_Example_setNum, num);
 }
 
+jmethodID _m_com_github_dart_lang_jnigen_simple_package_Example_throwException = NULL;
+FFI_PLUGIN_EXPORT
+void com_github_dart_lang_jnigen_simple_package_Example_throwException() {
+    load_env();
+    load_class_gr(&_c_com_github_dart_lang_jnigen_simple_package_Example, "com/github/dart_lang/jnigen/simple_package/Example");
+    if (_c_com_github_dart_lang_jnigen_simple_package_Example == NULL) return (void)0;
+    load_static_method(_c_com_github_dart_lang_jnigen_simple_package_Example, &_m_com_github_dart_lang_jnigen_simple_package_Example_throwException, "throwException", "()V");
+    if (_m_com_github_dart_lang_jnigen_simple_package_Example_throwException == NULL) return (void)0;
+    (*jniEnv)->CallStaticVoidMethod(jniEnv, _c_com_github_dart_lang_jnigen_simple_package_Example, _m_com_github_dart_lang_jnigen_simple_package_Example_throwException);
+}
+
 jfieldID _f_com_github_dart_lang_jnigen_simple_package_Example_aux = NULL;
 jobject get_com_github_dart_lang_jnigen_simple_package_Example_aux() {
     load_env();
     load_class_gr(&_c_com_github_dart_lang_jnigen_simple_package_Example, "com/github/dart_lang/jnigen/simple_package/Example");
+    if (_c_com_github_dart_lang_jnigen_simple_package_Example == NULL) return (jobject)0;
     load_static_field(_c_com_github_dart_lang_jnigen_simple_package_Example, &_f_com_github_dart_lang_jnigen_simple_package_Example_aux, "aux","Lcom/github/dart_lang/jnigen/simple_package/Example$Aux;");
     return to_global_ref((*jniEnv)->GetStaticObjectField(jniEnv, _c_com_github_dart_lang_jnigen_simple_package_Example, _f_com_github_dart_lang_jnigen_simple_package_Example_aux));
 }
@@ -89,6 +118,7 @@
 void set_com_github_dart_lang_jnigen_simple_package_Example_aux(jobject value) {
     load_env();
     load_class_gr(&_c_com_github_dart_lang_jnigen_simple_package_Example, "com/github/dart_lang/jnigen/simple_package/Example");
+    if (_c_com_github_dart_lang_jnigen_simple_package_Example == NULL) return (void)0;
     load_static_field(_c_com_github_dart_lang_jnigen_simple_package_Example, &_f_com_github_dart_lang_jnigen_simple_package_Example_aux, "aux","Lcom/github/dart_lang/jnigen/simple_package/Example$Aux;");
     ((*jniEnv)->SetStaticObjectField(jniEnv, _c_com_github_dart_lang_jnigen_simple_package_Example, _f_com_github_dart_lang_jnigen_simple_package_Example_aux, value));
 }
@@ -98,6 +128,7 @@
 int32_t get_com_github_dart_lang_jnigen_simple_package_Example_num() {
     load_env();
     load_class_gr(&_c_com_github_dart_lang_jnigen_simple_package_Example, "com/github/dart_lang/jnigen/simple_package/Example");
+    if (_c_com_github_dart_lang_jnigen_simple_package_Example == NULL) return (int32_t)0;
     load_static_field(_c_com_github_dart_lang_jnigen_simple_package_Example, &_f_com_github_dart_lang_jnigen_simple_package_Example_num, "num","I");
     return ((*jniEnv)->GetStaticIntField(jniEnv, _c_com_github_dart_lang_jnigen_simple_package_Example, _f_com_github_dart_lang_jnigen_simple_package_Example_num));
 }
@@ -105,6 +136,7 @@
 void set_com_github_dart_lang_jnigen_simple_package_Example_num(int32_t value) {
     load_env();
     load_class_gr(&_c_com_github_dart_lang_jnigen_simple_package_Example, "com/github/dart_lang/jnigen/simple_package/Example");
+    if (_c_com_github_dart_lang_jnigen_simple_package_Example == NULL) return (void)0;
     load_static_field(_c_com_github_dart_lang_jnigen_simple_package_Example, &_f_com_github_dart_lang_jnigen_simple_package_Example_num, "num","I");
     ((*jniEnv)->SetStaticIntField(jniEnv, _c_com_github_dart_lang_jnigen_simple_package_Example, _f_com_github_dart_lang_jnigen_simple_package_Example_num, value));
 }
@@ -118,7 +150,9 @@
 jobject com_github_dart_lang_jnigen_simple_package_Example__Aux_ctor(uint8_t value) {
     load_env();
     load_class_gr(&_c_com_github_dart_lang_jnigen_simple_package_Example__Aux, "com/github/dart_lang/jnigen/simple_package/Example$Aux");
+    if (_c_com_github_dart_lang_jnigen_simple_package_Example__Aux == NULL) return (jobject)0;
     load_method(_c_com_github_dart_lang_jnigen_simple_package_Example__Aux, &_m_com_github_dart_lang_jnigen_simple_package_Example__Aux_ctor, "<init>", "(Z)V");
+    if (_m_com_github_dart_lang_jnigen_simple_package_Example__Aux_ctor == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->NewObject(jniEnv, _c_com_github_dart_lang_jnigen_simple_package_Example__Aux, _m_com_github_dart_lang_jnigen_simple_package_Example__Aux_ctor, value);
     return to_global_ref(_result);
 }
@@ -128,7 +162,9 @@
 uint8_t com_github_dart_lang_jnigen_simple_package_Example__Aux_getValue(jobject self_) {
     load_env();
     load_class_gr(&_c_com_github_dart_lang_jnigen_simple_package_Example__Aux, "com/github/dart_lang/jnigen/simple_package/Example$Aux");
+    if (_c_com_github_dart_lang_jnigen_simple_package_Example__Aux == NULL) return (uint8_t)0;
     load_method(_c_com_github_dart_lang_jnigen_simple_package_Example__Aux, &_m_com_github_dart_lang_jnigen_simple_package_Example__Aux_getValue, "getValue", "()Z");
+    if (_m_com_github_dart_lang_jnigen_simple_package_Example__Aux_getValue == NULL) return (uint8_t)0;
     uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_com_github_dart_lang_jnigen_simple_package_Example__Aux_getValue);
     return _result;
 }
@@ -138,7 +174,9 @@
 void com_github_dart_lang_jnigen_simple_package_Example__Aux_setValue(jobject self_, uint8_t value) {
     load_env();
     load_class_gr(&_c_com_github_dart_lang_jnigen_simple_package_Example__Aux, "com/github/dart_lang/jnigen/simple_package/Example$Aux");
+    if (_c_com_github_dart_lang_jnigen_simple_package_Example__Aux == NULL) return (void)0;
     load_method(_c_com_github_dart_lang_jnigen_simple_package_Example__Aux, &_m_com_github_dart_lang_jnigen_simple_package_Example__Aux_setValue, "setValue", "(Z)V");
+    if (_m_com_github_dart_lang_jnigen_simple_package_Example__Aux_setValue == NULL) return (void)0;
     (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_com_github_dart_lang_jnigen_simple_package_Example__Aux_setValue, value);
 }
 
@@ -146,6 +184,7 @@
 uint8_t get_com_github_dart_lang_jnigen_simple_package_Example__Aux_value(jobject self_) {
     load_env();
     load_class_gr(&_c_com_github_dart_lang_jnigen_simple_package_Example__Aux, "com/github/dart_lang/jnigen/simple_package/Example$Aux");
+    if (_c_com_github_dart_lang_jnigen_simple_package_Example__Aux == NULL) return (uint8_t)0;
     load_field(_c_com_github_dart_lang_jnigen_simple_package_Example__Aux, &_f_com_github_dart_lang_jnigen_simple_package_Example__Aux_value, "value","Z");
     return ((*jniEnv)->GetBooleanField(jniEnv, self_, _f_com_github_dart_lang_jnigen_simple_package_Example__Aux_value));
 }
@@ -153,6 +192,7 @@
 void set_com_github_dart_lang_jnigen_simple_package_Example__Aux_value(jobject self_, uint8_t value) {
     load_env();
     load_class_gr(&_c_com_github_dart_lang_jnigen_simple_package_Example__Aux, "com/github/dart_lang/jnigen/simple_package/Example$Aux");
+    if (_c_com_github_dart_lang_jnigen_simple_package_Example__Aux == NULL) return (void)0;
     load_field(_c_com_github_dart_lang_jnigen_simple_package_Example__Aux, &_f_com_github_dart_lang_jnigen_simple_package_Example__Aux_value, "value","Z");
     ((*jniEnv)->SetBooleanField(jniEnv, self_, _f_com_github_dart_lang_jnigen_simple_package_Example__Aux_value, value));
 }
@@ -166,7 +206,9 @@
 jobject com_github_dart_lang_jnigen_pkg2_C2_ctor() {
     load_env();
     load_class_gr(&_c_com_github_dart_lang_jnigen_pkg2_C2, "com/github/dart_lang/jnigen/pkg2/C2");
+    if (_c_com_github_dart_lang_jnigen_pkg2_C2 == NULL) return (jobject)0;
     load_method(_c_com_github_dart_lang_jnigen_pkg2_C2, &_m_com_github_dart_lang_jnigen_pkg2_C2_ctor, "<init>", "()V");
+    if (_m_com_github_dart_lang_jnigen_pkg2_C2_ctor == NULL) return (jobject)0;
     jobject _result = (*jniEnv)->NewObject(jniEnv, _c_com_github_dart_lang_jnigen_pkg2_C2, _m_com_github_dart_lang_jnigen_pkg2_C2_ctor);
     return to_global_ref(_result);
 }
@@ -175,6 +217,7 @@
 int32_t get_com_github_dart_lang_jnigen_pkg2_C2_CONSTANT() {
     load_env();
     load_class_gr(&_c_com_github_dart_lang_jnigen_pkg2_C2, "com/github/dart_lang/jnigen/pkg2/C2");
+    if (_c_com_github_dart_lang_jnigen_pkg2_C2 == NULL) return (int32_t)0;
     load_static_field(_c_com_github_dart_lang_jnigen_pkg2_C2, &_f_com_github_dart_lang_jnigen_pkg2_C2_CONSTANT, "CONSTANT","I");
     return ((*jniEnv)->GetStaticIntField(jniEnv, _c_com_github_dart_lang_jnigen_pkg2_C2, _f_com_github_dart_lang_jnigen_pkg2_C2_CONSTANT));
 }
@@ -182,6 +225,7 @@
 void set_com_github_dart_lang_jnigen_pkg2_C2_CONSTANT(int32_t value) {
     load_env();
     load_class_gr(&_c_com_github_dart_lang_jnigen_pkg2_C2, "com/github/dart_lang/jnigen/pkg2/C2");
+    if (_c_com_github_dart_lang_jnigen_pkg2_C2 == NULL) return (void)0;
     load_static_field(_c_com_github_dart_lang_jnigen_pkg2_C2, &_f_com_github_dart_lang_jnigen_pkg2_C2_CONSTANT, "CONSTANT","I");
     ((*jniEnv)->SetStaticIntField(jniEnv, _c_com_github_dart_lang_jnigen_pkg2_C2, _f_com_github_dart_lang_jnigen_pkg2_C2_CONSTANT, value));
 }
diff --git a/pkgs/jnigen/test/test_util/test_util.dart b/pkgs/jnigen/test/test_util/test_util.dart
index 49bc5ff..7162034 100644
--- a/pkgs/jnigen/test/test_util/test_util.dart
+++ b/pkgs/jnigen/test/test_util/test_util.dart
@@ -1,3 +1,7 @@
+// 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:path/path.dart' hide equals;