[jnigen] Jni_gen Examples (https://github.com/dart-lang/jnigen/issues/36)

diff --git a/.github/workflows/test-package.yml b/.github/workflows/test-package.yml
index f35e0bb..0b4123f 100644
--- a/.github/workflows/test-package.yml
+++ b/.github/workflows/test-package.yml
@@ -117,6 +117,8 @@
       - uses: subosito/flutter-action@v2
         with:
           channel: 'stable'
+          cache: true
+          cache-key: 'flutter-:os:-:channel:-:version:-:arch:-:hash:'
       - uses: actions/setup-java@v2
         with:
           distribution: 'zulu'
@@ -157,6 +159,8 @@
       - uses: subosito/flutter-action@v2
         with:
           channel: 'stable'
+          cache: true
+          cache-key: 'flutter-:os:-:channel:-:version:-:arch:-:hash:'
       - uses: actions/setup-java@v2
         with:
           distribution: 'zulu'
@@ -167,7 +171,6 @@
       - run: flutter config --enable-linux-desktop
       - run: flutter pub get
       - run: dart run jni:setup
-      - run: flutter test
       - run: flutter build linux
 
   build_jni_example_windows:
@@ -180,6 +183,8 @@
       - uses: subosito/flutter-action@v2
         with:
           channel: 'stable'
+          cache: true
+          cache-key: 'flutter-:os:-:channel:-:version:-:arch:-:hash:'
       - uses: actions/setup-java@v2
         with:
           distribution: 'zulu'
@@ -202,9 +207,36 @@
       - uses: subosito/flutter-action@v2
         with:
           channel: 'stable'
+          cache: true
+          cache-key: 'flutter-:os:-:channel:-:version:-:arch:-:hash:'
       - run: flutter pub get
       - run: flutter build apk
-      - run: flutter build appbundle
+
+  build_in_app_java_example:
+    runs-on: ubuntu-latest
+    defaults:
+      run:
+        working-directory: ./pkgs/jni_gen/examples/in_app_java
+    steps:
+      - uses: actions/checkout@v3
+      - uses: actions/setup-java@v2
+        with:
+          distribution: 'zulu'
+          java-version: '11'
+      - uses: subosito/flutter-action@v2
+        with:
+          channel: 'stable'
+          cache: true
+          cache-key: 'flutter-:os:-:channel:-:version:-:arch:-:hash:'
+      - run: flutter pub get
+      - run: flutter analyze
+      - run: flutter build apk
+      - name: re-generate bindings
+        run: flutter pub run jni_gen -Ddart_root=_dart -Dc_root=_c --config jnigen.yaml
+      - name: compare generated dart bindings
+        run: diff -qr lib/android_utils _dart
+      - name: compare generated C bindings
+        run: diff -qr src/android_utils _c
 
   coveralls_finish:
     needs: [test_jni_gen, test_jni]
@@ -216,3 +248,50 @@
           github-token: ${{ secrets.github_token }}
           parallel-finished: true
 
+  run_pdfbox_example_linux:
+    runs-on: ubuntu-latest
+    defaults:
+      run:
+        working-directory: ./pkgs/jni_gen/examples/pdfbox_plugin
+    steps:
+      - uses: actions/checkout@v3
+      - uses: subosito/flutter-action@v2
+        with:
+          channel: 'stable'
+          cache: true
+          cache-key: 'flutter-:os:-:channel:-:version:-:arch:-:hash:'
+      - uses: actions/setup-java@v2
+        with:
+          distribution: 'zulu'
+          java-version: '11'
+      - run: |
+          sudo apt-get update -y
+          sudo apt-get install -y ninja-build libgtk-3-dev
+      - run: flutter config --enable-linux-desktop
+      - run: dart pub get
+      - name: Generate bindings
+        run: |
+          dart run jni_gen -Dc_root=_c -Ddart_root=_dart --config jnigen.yaml
+      - name: Compare generated bindings
+        run: |
+          diff -qr _c src/
+          diff -qr _dart lib/third_party
+      - name: Generate full bindings
+        run: dart run jni_gen --config jnigen_full.yaml
+      - name: Analyze generated bindings
+        run: |
+          flutter pub get # dart-analyze errors on flutter example
+          flutter analyze
+      - name: Run standalone example
+        run: |
+          dart pub get
+          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/jni_gen/examples/pdfbox_plugin/dart_example
+      - name: Build flutter example for pdfbox_plugin
+        run: |
+          flutter pub get
+          flutter build linux
+        working-directory: ./pkgs/jni_gen/examples/pdfbox_plugin/example
+
diff --git a/pkgs/jni/example/pubspec.lock b/pkgs/jni/example/pubspec.lock
index 2f0d348..43745f0 100644
--- a/pkgs/jni/example/pubspec.lock
+++ b/pkgs/jni/example/pubspec.lock
@@ -7,7 +7,7 @@
       name: archive
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "3.1.11"
+    version: "3.3.0"
   args:
     dependency: transitive
     description:
@@ -21,7 +21,7 @@
       name: async
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "2.8.2"
+    version: "2.9.0"
   boolean_selector:
     dependency: transitive
     description:
@@ -35,21 +35,14 @@
       name: characters
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.2.0"
-  charcode:
-    dependency: transitive
-    description:
-      name: charcode
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "1.3.1"
+    version: "1.2.1"
   clock:
     dependency: transitive
     description:
       name: clock
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.1.0"
+    version: "1.1.1"
   collection:
     dependency: transitive
     description:
@@ -63,7 +56,7 @@
       name: crypto
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "3.0.1"
+    version: "3.0.2"
   cupertino_icons:
     dependency: "direct main"
     description:
@@ -77,7 +70,7 @@
       name: fake_async
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.3.0"
+    version: "1.3.1"
   ffi:
     dependency: "direct main"
     description:
@@ -144,21 +137,21 @@
       name: matcher
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "0.12.11"
+    version: "0.12.12"
   material_color_utilities:
     dependency: transitive
     description:
       name: material_color_utilities
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "0.1.4"
+    version: "0.1.5"
   meta:
     dependency: transitive
     description:
       name: meta
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.7.0"
+    version: "1.8.0"
   package_config:
     dependency: transitive
     description:
@@ -172,7 +165,7 @@
       name: path
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.8.1"
+    version: "1.8.2"
   platform:
     dependency: transitive
     description:
@@ -205,7 +198,7 @@
       name: source_span
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.8.2"
+    version: "1.9.0"
   stack_trace:
     dependency: transitive
     description:
@@ -226,35 +219,35 @@
       name: string_scanner
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.1.0"
+    version: "1.1.1"
   sync_http:
     dependency: transitive
     description:
       name: sync_http
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "0.3.0"
+    version: "0.3.1"
   term_glyph:
     dependency: transitive
     description:
       name: term_glyph
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.2.0"
+    version: "1.2.1"
   test_api:
     dependency: transitive
     description:
       name: test_api
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "0.4.9"
+    version: "0.4.12"
   typed_data:
     dependency: transitive
     description:
       name: typed_data
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.3.0"
+    version: "1.3.1"
   vector_math:
     dependency: transitive
     description:
@@ -268,7 +261,7 @@
       name: vm_service
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "8.2.2"
+    version: "9.0.0"
   webdriver:
     dependency: transitive
     description:
diff --git a/pkgs/jni/example/test/widget_test.dart b/pkgs/jni/example/test/widget_test.dart
index ec585ec..def4482 100644
--- a/pkgs/jni/example/test/widget_test.dart
+++ b/pkgs/jni/example/test/widget_test.dart
@@ -11,6 +11,9 @@
 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
diff --git a/pkgs/jni_gen/README.md b/pkgs/jni_gen/README.md
index 1ae735d..1ba0193 100644
--- a/pkgs/jni_gen/README.md
+++ b/pkgs/jni_gen/README.md
@@ -28,4 +28,5 @@
 The generated C file has to be linked to JNI libraries. Therefore a CMake configuration is always generated which builds the generated code as shared library. The `init.dart` in generated dart code loads the library on first time a method is accessed. On dart standalone, it will be loaded from the same directory specified in `Jni.spawn` call.
 
 ## Examples
-See [jackson_core_test](test/jackson_core_test) folder for an example how bindings are generated. Runnable examples will be added soon.
+Few runnable examples are provided in [examples/](examples/) directory. These directories do not include generated code. Generate the bindings by running `dart run jni_gen --config jnigen.yaml` in the example project root. See the respective READMEs for more details.
+
diff --git a/pkgs/jni_gen/analysis_options.yaml b/pkgs/jni_gen/analysis_options.yaml
index 3fa121a..e714a82 100644
--- a/pkgs/jni_gen/analysis_options.yaml
+++ b/pkgs/jni_gen/analysis_options.yaml
@@ -5,7 +5,7 @@
 include: package:lints/recommended.yaml
 
 analyzer:
-  exclude: [build/**]
+  exclude: [build/**, examples/**]
   language:
     strict-raw-types: true
     strict-inference: true
diff --git a/pkgs/jni_gen/bin/download_maven_jars.dart b/pkgs/jni_gen/bin/download_maven_jars.dart
new file mode 100644
index 0000000..a4ada5b
--- /dev/null
+++ b/pkgs/jni_gen/bin/download_maven_jars.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:jni_gen/jni_gen.dart';
+import 'package:jni_gen/tools.dart';
+
+/// Downloads maven dependencies downloaded by equivalent jni_gen invocation.
+///
+/// Useful for running standalone examples on already generated sources.
+void main(List<String> args) async {
+  final config = Config.parseArgs(args);
+  final mavenDownloads = config.mavenDownloads;
+  if (mavenDownloads != null) {
+    await MavenTools.downloadMavenJars(
+        MavenTools.deps(mavenDownloads.jarOnlyDeps + mavenDownloads.sourceDeps),
+        mavenDownloads.jarDir);
+    await Directory(mavenDownloads.jarDir)
+        .list()
+        .map((entry) => entry.path)
+        .where((path) => path.endsWith('.jar'))
+        .forEach(stdout.writeln);
+  } else {
+    stderr.writeln('No maven dependencies found in config.');
+    exitCode = 2;
+  }
+}
diff --git a/pkgs/jni_gen/cmake/CMakeLists.txt.tmpl b/pkgs/jni_gen/cmake/CMakeLists.txt.tmpl
index 21d0d80..cf7b53d 100644
--- a/pkgs/jni_gen/cmake/CMakeLists.txt.tmpl
+++ b/pkgs/jni_gen/cmake/CMakeLists.txt.tmpl
@@ -6,7 +6,7 @@
 project({{LIBRARY_NAME}} VERSION 0.0.1 LANGUAGES C)
 
 add_library({{LIBRARY_NAME}} SHARED
-  "{{LIBRARY_NAME}}.c"
+  "{{SUBDIR}}/{{LIBRARY_NAME}}.c"
 )
 
 set_target_properties({{LIBRARY_NAME}} PROPERTIES
diff --git a/pkgs/jni_gen/examples/README.md b/pkgs/jni_gen/examples/README.md
new file mode 100644
index 0000000..11e3fc0
--- /dev/null
+++ b/pkgs/jni_gen/examples/README.md
@@ -0,0 +1,11 @@
+## jni_gen examples
+
+This directory contains examples on how to use jni_gen.
+
+| Directory | Description |
+| ------- | --------- |
+| [in_app_java](in_app_java/) | Demonstrates how to include custom Java code in Flutter application and call that using jni_gen |
+| [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/jni_gen/examples/in_app_java/.gitignore b/pkgs/jni_gen/examples/in_app_java/.gitignore
new file mode 100644
index 0000000..8c64048
--- /dev/null
+++ b/pkgs/jni_gen/examples/in_app_java/.gitignore
@@ -0,0 +1,50 @@
+# Miscellaneous
+*.class
+*.log
+*.pyc
+*.swp
+.DS_Store
+.atom/
+.buildlog/
+.history
+.svn/
+migrate_working_dir/
+
+# IntelliJ related
+*.iml
+*.ipr
+*.iws
+.idea/
+
+# The .vscode folder contains launch configuration and tasks you configure in
+# VS Code which you may wish to be included in version control, so this line
+# is commented out by default.
+#.vscode/
+
+# Flutter/Dart/Pub related
+**/doc/api/
+**/ios/Flutter/.last_build_id
+.dart_tool/
+.flutter-plugins
+.flutter-plugins-dependencies
+.packages
+.pub-cache/
+.pub/
+/build/
+
+# Web related
+lib/generated_plugin_registrant.dart
+
+# Symbolication related
+app.*.symbols
+
+# Obfuscation related
+app.*.map.json
+
+# Android Studio will place build artifacts here
+/android/app/debug
+/android/app/profile
+/android/app/release
+
+## Generated by build process
+android/app/.cxx
diff --git a/pkgs/jni_gen/examples/in_app_java/.metadata b/pkgs/jni_gen/examples/in_app_java/.metadata
new file mode 100644
index 0000000..2544bab
--- /dev/null
+++ b/pkgs/jni_gen/examples/in_app_java/.metadata
@@ -0,0 +1,30 @@
+# This file tracks properties of this Flutter project.
+# Used by Flutter tool to assess capabilities and perform upgrades etc.
+#
+# This file should be version controlled.
+
+version:
+  revision: f1875d570e39de09040c8f79aa13cc56baab8db1
+  channel: stable
+
+project_type: app
+
+# Tracks metadata for the flutter migrate command
+migration:
+  platforms:
+    - platform: root
+      create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
+      base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
+    - platform: android
+      create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
+      base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
+
+  # User provided section
+
+  # List of Local paths (relative to this file) that should be
+  # ignored by the migrate tool.
+  #
+  # Files that are not part of the templates will be ignored by default.
+  unmanaged_files:
+    - 'lib/main.dart'
+    - 'ios/Runner.xcodeproj/project.pbxproj'
diff --git a/pkgs/jni_gen/examples/in_app_java/README.md b/pkgs/jni_gen/examples/in_app_java/README.md
new file mode 100644
index 0000000..f910deb
--- /dev/null
+++ b/pkgs/jni_gen/examples/in_app_java/README.md
@@ -0,0 +1,24 @@
+# In-App Java Example
+
+This example shows how to write custom java code in `android/app/src` and call it using `jni_gen` generated bindings.
+
+#### How to run this example:
+* Run `flutter run` to run the app.
+
+* To regenerate bindings after changing Java code, run `flutter pub run jni_gen --config jnigen.yaml`. This requires at least one APK build to have been run before, so that it's possible for `jni_gen` to obtain classpaths of Android Gradle libraries. Therefore, once run `flutter build apk` before generating bindings for the first time, or after a `flutter clean`.
+
+#### General steps
+These are general steps to integrate Java code into a flutter project using `jni_gen`.
+
+* Write Java code in suitable package folder, under `android/` subproject of the flutter app.
+
+* Create A jnigen config like `jnigen.yaml` in this example.
+
+* Generate bindings using jnigen config.
+
+* Add an `externalNativeBuild` to gradle script (see `android/app/build.gradle` in this example).
+
+* Add proguard rules to exclude your custom classes from tree shaking, since they are always accessed reflectively in JNI.
+
+* Build and run the app.
+
diff --git a/pkgs/jni_gen/examples/in_app_java/analysis_options.yaml b/pkgs/jni_gen/examples/in_app_java/analysis_options.yaml
new file mode 100644
index 0000000..61b6c4d
--- /dev/null
+++ b/pkgs/jni_gen/examples/in_app_java/analysis_options.yaml
@@ -0,0 +1,29 @@
+# This file configures the analyzer, which statically analyzes Dart code to
+# check for errors, warnings, and lints.
+#
+# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
+# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
+# invoked from the command line by running `flutter analyze`.
+
+# The following line activates a set of recommended lints for Flutter apps,
+# packages, and plugins designed to encourage good coding practices.
+include: package:flutter_lints/flutter.yaml
+
+linter:
+  # The lint rules applied to this project can be customized in the
+  # section below to disable rules from the `package:flutter_lints/flutter.yaml`
+  # included above or to enable additional rules. A list of all available lints
+  # and their documentation is published at
+  # https://dart-lang.github.io/linter/lints/index.html.
+  #
+  # Instead of disabling a lint rule for the entire project in the
+  # section below, it can also be suppressed for a single line of code
+  # or a specific dart file by using the `// ignore: name_of_lint` and
+  # `// ignore_for_file: name_of_lint` syntax on the line or in the file
+  # producing the lint.
+  rules:
+    # avoid_print: false  # Uncomment to disable the `avoid_print` rule
+    # prefer_single_quotes: true  # Uncomment to enable the `prefer_single_quotes` rule
+
+# Additional information about this file can be found at
+# https://dart.dev/guides/language/analysis-options
diff --git a/pkgs/jni_gen/examples/in_app_java/android/.gitignore b/pkgs/jni_gen/examples/in_app_java/android/.gitignore
new file mode 100644
index 0000000..6f56801
--- /dev/null
+++ b/pkgs/jni_gen/examples/in_app_java/android/.gitignore
@@ -0,0 +1,13 @@
+gradle-wrapper.jar
+/.gradle
+/captures/
+/gradlew
+/gradlew.bat
+/local.properties
+GeneratedPluginRegistrant.java
+
+# Remember to never publicly share your keystore.
+# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
+key.properties
+**/*.keystore
+**/*.jks
diff --git a/pkgs/jni_gen/examples/in_app_java/android/app/build.gradle b/pkgs/jni_gen/examples/in_app_java/android/app/build.gradle
new file mode 100644
index 0000000..784c659
--- /dev/null
+++ b/pkgs/jni_gen/examples/in_app_java/android/app/build.gradle
@@ -0,0 +1,77 @@
+def localProperties = new Properties()
+def localPropertiesFile = rootProject.file('local.properties')
+if (localPropertiesFile.exists()) {
+    localPropertiesFile.withReader('UTF-8') { reader ->
+        localProperties.load(reader)
+    }
+}
+
+def flutterRoot = localProperties.getProperty('flutter.sdk')
+if (flutterRoot == null) {
+    throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
+}
+
+def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
+if (flutterVersionCode == null) {
+    flutterVersionCode = '1'
+}
+
+def flutterVersionName = localProperties.getProperty('flutter.versionName')
+if (flutterVersionName == null) {
+    flutterVersionName = '1.0'
+}
+
+apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android'
+apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
+
+android {
+    compileSdkVersion flutter.compileSdkVersion
+    ndkVersion flutter.ndkVersion
+
+    compileOptions {
+        sourceCompatibility JavaVersion.VERSION_1_8
+        targetCompatibility JavaVersion.VERSION_1_8
+    }
+
+    kotlinOptions {
+        jvmTarget = '1.8'
+    }
+
+    sourceSets {
+        main.java.srcDirs += 'src/main/kotlin'
+    }
+
+    defaultConfig {
+        // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
+        applicationId "com.example.in_app_java"
+        // 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
+        targetSdkVersion flutter.targetSdkVersion
+        versionCode flutterVersionCode.toInteger()
+        versionName flutterVersionName
+    }
+
+    buildTypes {
+        release {
+            // TODO: Add your own signing config for the release build.
+            // Signing with the debug keys for now, so `flutter run --release` works.
+            signingConfig signingConfigs.debug
+        }
+    }
+
+externalNativeBuild {
+		cmake {
+			path "../../src/android_utils/CMakeLists.txt"
+		}
+	}
+}
+
+flutter {
+    source '../..'
+}
+
+dependencies {
+    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+}
diff --git a/pkgs/jni_gen/examples/in_app_java/android/app/src/debug/AndroidManifest.xml b/pkgs/jni_gen/examples/in_app_java/android/app/src/debug/AndroidManifest.xml
new file mode 100644
index 0000000..a096030
--- /dev/null
+++ b/pkgs/jni_gen/examples/in_app_java/android/app/src/debug/AndroidManifest.xml
@@ -0,0 +1,8 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.in_app_java">
+    <!-- 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.
+    -->
+    <uses-permission android:name="android.permission.INTERNET"/>
+</manifest>
diff --git a/pkgs/jni_gen/examples/in_app_java/android/app/src/main/AndroidManifest.xml b/pkgs/jni_gen/examples/in_app_java/android/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..e674e57
--- /dev/null
+++ b/pkgs/jni_gen/examples/in_app_java/android/app/src/main/AndroidManifest.xml
@@ -0,0 +1,34 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.in_app_java">
+   <application
+        android:label="in_app_java"
+        android:name="${applicationName}"
+        android:icon="@mipmap/ic_launcher">
+        <activity
+            android:name=".MainActivity"
+            android:exported="true"
+            android:launchMode="singleTop"
+            android:theme="@style/LaunchTheme"
+            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
+            android:hardwareAccelerated="true"
+            android:windowSoftInputMode="adjustResize">
+            <!-- Specifies an Android theme to apply to this Activity as soon as
+                 the Android process has started. This theme is visible to the user
+                 while the Flutter UI initializes. After that, this theme continues
+                 to determine the Window background behind the Flutter UI. -->
+            <meta-data
+              android:name="io.flutter.embedding.android.NormalTheme"
+              android:resource="@style/NormalTheme"
+              />
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
+        <!-- Don't delete the meta-data below.
+             This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
+        <meta-data
+            android:name="flutterEmbedding"
+            android:value="2" />
+    </application>
+</manifest>
diff --git a/pkgs/jni_gen/examples/in_app_java/android/app/src/main/java/com/example/in_app_java/AndroidUtils.java b/pkgs/jni_gen/examples/in_app_java/android/app/src/main/java/com/example/in_app_java/AndroidUtils.java
new file mode 100644
index 0000000..4c297bf
--- /dev/null
+++ b/pkgs/jni_gen/examples/in_app_java/android/app/src/main/java/com/example/in_app_java/AndroidUtils.java
@@ -0,0 +1,12 @@
+package com.example.in_app_java;
+
+import android.app.Activity;
+import android.widget.Toast;
+import androidx.annotation.Keep;
+
+@Keep
+public class AndroidUtils {
+  static void showToast(Activity mainActivity, CharSequence text, int duration) {
+    mainActivity.runOnUiThread(() -> Toast.makeText(mainActivity, text, duration).show());
+  }
+}
diff --git a/pkgs/jni_gen/examples/in_app_java/android/app/src/main/kotlin/com/example/in_app_java/MainActivity.kt b/pkgs/jni_gen/examples/in_app_java/android/app/src/main/kotlin/com/example/in_app_java/MainActivity.kt
new file mode 100644
index 0000000..c8fde0c
--- /dev/null
+++ b/pkgs/jni_gen/examples/in_app_java/android/app/src/main/kotlin/com/example/in_app_java/MainActivity.kt
@@ -0,0 +1,6 @@
+package com.example.in_app_java
+
+import io.flutter.embedding.android.FlutterActivity
+
+class MainActivity: FlutterActivity() {
+}
diff --git a/pkgs/jni_gen/examples/in_app_java/android/app/src/main/res/drawable-v21/launch_background.xml b/pkgs/jni_gen/examples/in_app_java/android/app/src/main/res/drawable-v21/launch_background.xml
new file mode 100644
index 0000000..f74085f
--- /dev/null
+++ b/pkgs/jni_gen/examples/in_app_java/android/app/src/main/res/drawable-v21/launch_background.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Modify this file to customize your launch splash screen -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="?android:colorBackground" />
+
+    <!-- You can insert your own image assets here -->
+    <!-- <item>
+        <bitmap
+            android:gravity="center"
+            android:src="@mipmap/launch_image" />
+    </item> -->
+</layer-list>
diff --git a/pkgs/jni_gen/examples/in_app_java/android/app/src/main/res/drawable/launch_background.xml b/pkgs/jni_gen/examples/in_app_java/android/app/src/main/res/drawable/launch_background.xml
new file mode 100644
index 0000000..304732f
--- /dev/null
+++ b/pkgs/jni_gen/examples/in_app_java/android/app/src/main/res/drawable/launch_background.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Modify this file to customize your launch splash screen -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@android:color/white" />
+
+    <!-- You can insert your own image assets here -->
+    <!-- <item>
+        <bitmap
+            android:gravity="center"
+            android:src="@mipmap/launch_image" />
+    </item> -->
+</layer-list>
diff --git a/pkgs/jni_gen/examples/in_app_java/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/pkgs/jni_gen/examples/in_app_java/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..db77bb4
--- /dev/null
+++ b/pkgs/jni_gen/examples/in_app_java/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jni_gen/examples/in_app_java/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/pkgs/jni_gen/examples/in_app_java/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..17987b7
--- /dev/null
+++ b/pkgs/jni_gen/examples/in_app_java/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jni_gen/examples/in_app_java/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/pkgs/jni_gen/examples/in_app_java/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..09d4391
--- /dev/null
+++ b/pkgs/jni_gen/examples/in_app_java/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jni_gen/examples/in_app_java/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/pkgs/jni_gen/examples/in_app_java/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..d5f1c8d
--- /dev/null
+++ b/pkgs/jni_gen/examples/in_app_java/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jni_gen/examples/in_app_java/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/pkgs/jni_gen/examples/in_app_java/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..4d6372e
--- /dev/null
+++ b/pkgs/jni_gen/examples/in_app_java/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jni_gen/examples/in_app_java/android/app/src/main/res/values-night/styles.xml b/pkgs/jni_gen/examples/in_app_java/android/app/src/main/res/values-night/styles.xml
new file mode 100644
index 0000000..06952be
--- /dev/null
+++ b/pkgs/jni_gen/examples/in_app_java/android/app/src/main/res/values-night/styles.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
+    <style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
+        <!-- Show a splash screen on the activity. Automatically removed when
+             the Flutter engine draws its first frame -->
+        <item name="android:windowBackground">@drawable/launch_background</item>
+    </style>
+    <!-- Theme applied to the Android Window as soon as the process has started.
+         This theme determines the color of the Android Window while your
+         Flutter UI initializes, as well as behind your Flutter UI while its
+         running.
+
+         This Theme is only used starting with V2 of Flutter's Android embedding. -->
+    <style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
+        <item name="android:windowBackground">?android:colorBackground</item>
+    </style>
+</resources>
diff --git a/pkgs/jni_gen/examples/in_app_java/android/app/src/main/res/values/styles.xml b/pkgs/jni_gen/examples/in_app_java/android/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..cb1ef88
--- /dev/null
+++ b/pkgs/jni_gen/examples/in_app_java/android/app/src/main/res/values/styles.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
+    <style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
+        <!-- Show a splash screen on the activity. Automatically removed when
+             the Flutter engine draws its first frame -->
+        <item name="android:windowBackground">@drawable/launch_background</item>
+    </style>
+    <!-- Theme applied to the Android Window as soon as the process has started.
+         This theme determines the color of the Android Window while your
+         Flutter UI initializes, as well as behind your Flutter UI while its
+         running.
+
+         This Theme is only used starting with V2 of Flutter's Android embedding. -->
+    <style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
+        <item name="android:windowBackground">?android:colorBackground</item>
+    </style>
+</resources>
diff --git a/pkgs/jni_gen/examples/in_app_java/android/app/src/profile/AndroidManifest.xml b/pkgs/jni_gen/examples/in_app_java/android/app/src/profile/AndroidManifest.xml
new file mode 100644
index 0000000..a096030
--- /dev/null
+++ b/pkgs/jni_gen/examples/in_app_java/android/app/src/profile/AndroidManifest.xml
@@ -0,0 +1,8 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.in_app_java">
+    <!-- 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.
+    -->
+    <uses-permission android:name="android.permission.INTERNET"/>
+</manifest>
diff --git a/pkgs/jni_gen/examples/in_app_java/android/build.gradle b/pkgs/jni_gen/examples/in_app_java/android/build.gradle
new file mode 100644
index 0000000..e42825f
--- /dev/null
+++ b/pkgs/jni_gen/examples/in_app_java/android/build.gradle
@@ -0,0 +1,33 @@
+buildscript {
+    ext.kotlin_version = '1.6.10'
+    repositories {
+        google()
+        mavenCentral()
+    }
+
+    dependencies {
+        classpath 'com.android.tools.build:gradle:7.1.2'
+        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+    }
+}
+
+allprojects {
+    repositories {
+        google()
+        mavenCentral()
+    }
+}
+
+rootProject.buildDir = '../build'
+subprojects {
+    project.buildDir = "${rootProject.buildDir}/${project.name}"
+}
+
+subprojects {
+    project.evaluationDependsOn(':app')
+}
+
+task clean(type: Delete) {
+    delete rootProject.buildDir
+}
+
diff --git a/pkgs/jni_gen/examples/in_app_java/android/gradle.properties b/pkgs/jni_gen/examples/in_app_java/android/gradle.properties
new file mode 100644
index 0000000..94adc3a
--- /dev/null
+++ b/pkgs/jni_gen/examples/in_app_java/android/gradle.properties
@@ -0,0 +1,3 @@
+org.gradle.jvmargs=-Xmx1536M
+android.useAndroidX=true
+android.enableJetifier=true
diff --git a/pkgs/jni_gen/examples/in_app_java/android/gradle/wrapper/gradle-wrapper.properties b/pkgs/jni_gen/examples/in_app_java/android/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..cc5527d
--- /dev/null
+++ b/pkgs/jni_gen/examples/in_app_java/android/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Fri Jun 23 08:50:38 CEST 2017
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip
diff --git a/pkgs/jni_gen/examples/in_app_java/android/settings.gradle b/pkgs/jni_gen/examples/in_app_java/android/settings.gradle
new file mode 100644
index 0000000..44e62bc
--- /dev/null
+++ b/pkgs/jni_gen/examples/in_app_java/android/settings.gradle
@@ -0,0 +1,11 @@
+include ':app'
+
+def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
+def properties = new Properties()
+
+assert localPropertiesFile.exists()
+localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
+
+def flutterSdkPath = properties.getProperty("flutter.sdk")
+assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
+apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
diff --git a/pkgs/jni_gen/examples/in_app_java/jnigen.yaml b/pkgs/jni_gen/examples/in_app_java/jnigen.yaml
new file mode 100644
index 0000000..52b63cd
--- /dev/null
+++ b/pkgs/jni_gen/examples/in_app_java/jnigen.yaml
@@ -0,0 +1,11 @@
+android_sdk_config:
+  add_gradle_deps: true
+
+library_name: android_utils
+source_path:
+  - 'android/app/src/main/java'
+classes:
+  - 'com.example.in_app_java.AndroidUtils'
+c_root: src/android_utils
+dart_root: lib/android_utils
+
diff --git a/pkgs/jni_gen/examples/in_app_java/lib/android_utils/com/example/in_app_java.dart b/pkgs/jni_gen/examples/in_app_java/lib/android_utils/com/example/in_app_java.dart
new file mode 100644
index 0000000..6f6a010
--- /dev/null
+++ b/pkgs/jni_gen/examples/in_app_java/lib/android_utils/com/example/in_app_java.dart
@@ -0,0 +1,39 @@
+// Autogenerated by jni_gen. DO NOT EDIT!
+
+// ignore_for_file: camel_case_types
+// ignore_for_file: non_constant_identifier_names
+// ignore_for_file: constant_identifier_names
+// ignore_for_file: annotate_overrides
+// ignore_for_file: no_leading_underscores_for_local_identifiers
+// ignore_for_file: unused_element
+
+import "dart:ffi" as ffi;
+
+import "package:jni/jni.dart" as jni;
+
+import "../../init.dart" show jlookup;
+
+/// from: com.example.in_app_java.AndroidUtils
+class AndroidUtils extends jni.JlObject {
+  AndroidUtils.fromRef(ffi.Pointer<ffi.Void> ref) : super.fromRef(ref);
+
+  static final _ctor =
+      jlookup<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());
+
+  static final _showToast = jlookup<
+          ffi.NativeFunction<
+              ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+                  ffi.Int32)>>("com_example_in_app_java_AndroidUtils_showToast")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>, int)>();
+
+  /// 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);
+}
diff --git a/pkgs/jni_gen/examples/in_app_java/lib/android_utils/init.dart b/pkgs/jni_gen/examples/in_app_java/lib/android_utils/init.dart
new file mode 100644
index 0000000..5642f98
--- /dev/null
+++ b/pkgs/jni_gen/examples/in_app_java/lib/android_utils/init.dart
@@ -0,0 +1,5 @@
+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/jni_gen/examples/in_app_java/lib/main.dart b/pkgs/jni_gen/examples/in_app_java/lib/main.dart
new file mode 100644
index 0000000..b47cb31
--- /dev/null
+++ b/pkgs/jni_gen/examples/in_app_java/lib/main.dart
@@ -0,0 +1,60 @@
+import 'package:flutter/material.dart';
+import 'package:jni/jni.dart';
+
+// The hierarchy created in generated code will mirror the java package
+// structure. This is an implementation convenience and we may allow
+// more customization in future.
+import 'android_utils/com/example/in_app_java.dart';
+
+JlObject activity = JlObject.fromRef(Jni.getInstance().getCurrentActivity());
+
+void showToast(String text) {
+  final jstr = JlString.fromString(text);
+  AndroidUtils.showToast(activity, jstr, 0);
+  jstr.delete();
+}
+
+void main() {
+  runApp(const MyApp());
+}
+
+class MyApp extends StatelessWidget {
+  const MyApp({Key? key}) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    return MaterialApp(
+      title: 'Flutter Demo',
+      theme: ThemeData(
+        primarySwatch: Colors.teal,
+      ),
+      home: const MyHomePage(title: 'Flutter Demo Home Page'),
+    );
+  }
+}
+
+class MyHomePage extends StatelessWidget {
+  const MyHomePage({Key? key, required this.title}) : super(key: key);
+
+  final String title;
+
+  @override
+  Widget build(BuildContext context) {
+    return Scaffold(
+      appBar: AppBar(
+        title: Text(title),
+      ),
+      body: Center(
+        child: Column(
+          mainAxisAlignment: MainAxisAlignment.center,
+          children: [
+            ElevatedButton(
+              child: const Text('Show toast'),
+              onPressed: () => showToast('😀'),
+            ),
+          ],
+        ),
+      ),
+    );
+  }
+}
diff --git a/pkgs/jni_gen/examples/in_app_java/pubspec.yaml b/pkgs/jni_gen/examples/in_app_java/pubspec.yaml
new file mode 100644
index 0000000..aef5291
--- /dev/null
+++ b/pkgs/jni_gen/examples/in_app_java/pubspec.yaml
@@ -0,0 +1,67 @@
+name: in_app_java
+description: |
+  Example on how to use jnigen to bridge between java and dart in a flutter
+  project.
+
+publish_to: 'none' # Remove this line if you wish to publish to pub.dev
+
+version: 1.0.0+1
+
+environment:
+  sdk: ">=2.17.6 <3.0.0"
+
+dependencies:
+  flutter:
+    sdk: flutter
+  jni:
+    path: ../../../jni/
+
+  # The following adds the Cupertino Icons font to your application.
+  # Use with the CupertinoIcons class for iOS style icons.
+  cupertino_icons: ^1.0.2
+
+dev_dependencies:
+  flutter_test:
+    sdk: flutter
+  jni_gen:
+    path: ../../
+
+  flutter_lints: ^2.0.0
+
+flutter:
+
+  # The following line ensures that the Material Icons font is
+  # included with your application, so that you can use the icons in
+  # the material Icons class.
+  uses-material-design: true
+
+  # To add assets to your application, add an assets section, like this:
+  # assets:
+  #   - images/a_dot_burr.jpeg
+  #   - images/a_dot_ham.jpeg
+
+  # An image asset can refer to one or more resolution-specific "variants", see
+  # https://flutter.dev/assets-and-images/#resolution-aware
+
+  # For details regarding adding assets from package dependencies, see
+  # https://flutter.dev/assets-and-images/#from-packages
+
+  # To add custom fonts to your application, add a fonts section here,
+  # in this "flutter" section. Each entry in this list should have a
+  # "family" key with the font family name, and a "fonts" key with a
+  # list giving the asset and other descriptors for the font. For
+  # example:
+  # fonts:
+  #   - family: Schyler
+  #     fonts:
+  #       - asset: fonts/Schyler-Regular.ttf
+  #       - asset: fonts/Schyler-Italic.ttf
+  #         style: italic
+  #   - family: Trajan Pro
+  #     fonts:
+  #       - asset: fonts/TrajanPro.ttf
+  #       - asset: fonts/TrajanPro_Bold.ttf
+  #         weight: 700
+  #
+  # For details regarding fonts from package dependencies,
+  # see https://flutter.dev/custom-fonts/#from-packages
diff --git a/pkgs/jni_gen/examples/in_app_java/src/android_utils/CMakeLists.txt b/pkgs/jni_gen/examples/in_app_java/src/android_utils/CMakeLists.txt
new file mode 100644
index 0000000..fe6f925
--- /dev/null
+++ b/pkgs/jni_gen/examples/in_app_java/src/android_utils/CMakeLists.txt
@@ -0,0 +1,30 @@
+# The Flutter tooling requires that developers have CMake 3.10 or later
+# installed. You should not increase this version, as doing so will cause
+# the plugin to fail to compile for some customers of the plugin.
+cmake_minimum_required(VERSION 3.10)
+
+project(android_utils VERSION 0.0.1 LANGUAGES C)
+
+add_library(android_utils SHARED
+  "./android_utils.c"
+)
+
+set_target_properties(android_utils PROPERTIES
+  OUTPUT_NAME "android_utils"
+)
+
+target_compile_definitions(android_utils PUBLIC DART_SHARED_LIB)
+
+if(WIN32)
+	set_target_properties(${TARGET_NAME} PROPERTIES
+		LINK_FLAGS "/DELAYLOAD:jvm.dll")
+endif()
+
+if (ANDROID)
+	target_link_libraries(android_utils log)
+else()
+	find_package(Java REQUIRED)
+	find_package(JNI REQUIRED)
+	include_directories(${JNI_INCLUDE_DIRS})
+	target_link_libraries(android_utils ${JNI_LIBRARIES})
+endif()
diff --git a/pkgs/jni_gen/examples/in_app_java/src/android_utils/android_utils.c b/pkgs/jni_gen/examples/in_app_java/src/android_utils/android_utils.c
new file mode 100644
index 0000000..d9c365c
--- /dev/null
+++ b/pkgs/jni_gen/examples/in_app_java/src/android_utils/android_utils.c
@@ -0,0 +1,40 @@
+// Autogenerated by jni_gen. DO NOT EDIT!
+
+#include <stdint.h>
+#include "jni.h"
+#include "dartjni.h"
+
+thread_local JNIEnv *jniEnv;
+struct jni_context jni;
+
+struct jni_context (*context_getter)(void);
+JNIEnv *(*env_getter)(void);
+
+void setJniGetters(struct jni_context (*cg)(void),
+        JNIEnv *(*eg)(void)) {
+    context_getter = cg;
+    env_getter = eg;
+}
+
+// com.example.in_app_java.AndroidUtils
+jclass _c_com_example_in_app_java_AndroidUtils = NULL;
+
+jmethodID _m_com_example_in_app_java_AndroidUtils_ctor = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_com_example_in_app_java_AndroidUtils, &_m_com_example_in_app_java_AndroidUtils_ctor, "<init>", "()V");
+    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);
+}
+
+jmethodID _m_com_example_in_app_java_AndroidUtils_showToast = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    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");
+    (*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/jni_gen/examples/in_app_java/src/android_utils/dartjni.h b/pkgs/jni_gen/examples/in_app_java/src/android_utils/dartjni.h
new file mode 100644
index 0000000..cd94b15
--- /dev/null
+++ b/pkgs/jni_gen/examples/in_app_java/src/android_utils/dartjni.h
@@ -0,0 +1,177 @@
+// 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/jni_gen/examples/in_app_java/test/widget_test.dart b/pkgs/jni_gen/examples/in_app_java/test/widget_test.dart
new file mode 100644
index 0000000..0c153cc
--- /dev/null
+++ b/pkgs/jni_gen/examples/in_app_java/test/widget_test.dart
@@ -0,0 +1,30 @@
+// This is a basic Flutter widget test.
+//
+// To perform an interaction with a widget in your test, use the WidgetTester
+// utility in the flutter_test package. For example, you can send tap and scroll
+// gestures. You can also use WidgetTester to find child widgets in the widget
+// tree, read text, and verify that the values of widget properties are correct.
+
+import 'package:flutter/material.dart';
+import 'package:flutter_test/flutter_test.dart';
+
+import 'package:in_app_java/main.dart';
+
+void main() {
+  testWidgets('Counter increments smoke test', (WidgetTester tester) async {
+    // Build our app and trigger a frame.
+    await tester.pumpWidget(const MyApp());
+
+    // Verify that our counter starts at 0.
+    expect(find.text('0'), findsOneWidget);
+    expect(find.text('1'), findsNothing);
+
+    // Tap the '+' icon and trigger a frame.
+    await tester.tap(find.byIcon(Icons.add));
+    await tester.pump();
+
+    // Verify that our counter has incremented.
+    expect(find.text('0'), findsNothing);
+    expect(find.text('1'), findsOneWidget);
+  });
+}
diff --git a/pkgs/jni_gen/examples/in_app_java/tool/generate_bindings.dart b/pkgs/jni_gen/examples/in_app_java/tool/generate_bindings.dart
new file mode 100644
index 0000000..2628d99
--- /dev/null
+++ b/pkgs/jni_gen/examples/in_app_java/tool/generate_bindings.dart
@@ -0,0 +1,15 @@
+import 'package:jni_gen/jni_gen.dart';
+
+void main(List<String> args) async {
+  final config = Config(
+    sourcePath: [Uri.directory('android/app/src/main/java')],
+    classes: ['com.example.in_app_java.AndroidUtils'],
+    cRoot: Uri.directory('src/android_utils'),
+    dartRoot: Uri.directory('lib/android_utils'),
+    libraryName: 'android_utils',
+    androidSdkConfig: AndroidSdkConfig(
+      versions: [31],
+    ),
+  );
+  await generateJniBindings(config);
+}
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/.gitignore b/pkgs/jni_gen/examples/pdfbox_plugin/.gitignore
new file mode 100644
index 0000000..4080544
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/.gitignore
@@ -0,0 +1,37 @@
+# Miscellaneous
+*.class
+*.log
+*.pyc
+*.swp
+.DS_Store
+.atom/
+.buildlog/
+.history
+.svn/
+migrate_working_dir/
+
+# IntelliJ related
+*.iml
+*.ipr
+*.iws
+.idea/
+
+# The .vscode folder contains launch configuration and tasks you configure in
+# VS Code which you may wish to be included in version control, so this line
+# is commented out by default.
+#.vscode/
+
+# Flutter/Dart/Pub related
+# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
+/pubspec.lock
+**/doc/api/
+.dart_tool/
+.packages
+build/
+
+## Downloaded by jni_gen
+/mvn_java/
+/mvn_jar/
+## Sometimes generated by maven.
+## TODO(#34) This is unwanted.
+/target/
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/.metadata b/pkgs/jni_gen/examples/pdfbox_plugin/.metadata
new file mode 100644
index 0000000..9d23aa9
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/.metadata
@@ -0,0 +1,36 @@
+# This file tracks properties of this Flutter project.
+# Used by Flutter tool to assess capabilities and perform upgrades etc.
+#
+# This file should be version controlled.
+
+version:
+  revision: f1875d570e39de09040c8f79aa13cc56baab8db1
+  channel: stable
+
+project_type: plugin_ffi
+
+# Tracks metadata for the flutter migrate command
+migration:
+  platforms:
+    - platform: root
+      create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
+      base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
+    - platform: android
+      create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
+      base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
+    - platform: linux
+      create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
+      base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
+    - platform: windows
+      create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
+      base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
+
+  # User provided section
+
+  # List of Local paths (relative to this file) that should be
+  # ignored by the migrate tool.
+  #
+  # Files that are not part of the templates will be ignored by default.
+  unmanaged_files:
+    - 'lib/main.dart'
+    - 'ios/Runner.xcodeproj/project.pbxproj'
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/README.md b/pkgs/jni_gen/examples/pdfbox_plugin/README.md
new file mode 100644
index 0000000..5fa64ea
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/README.md
@@ -0,0 +1,8 @@
+# pdfbox_plugin
+
+Example of a JNI plugin using `jni_gen` to auto-generate bindings for PDFBox java library.
+
+Bindings can be generated by running `dart run jni_gen --config jnigen.yaml`. Required source code and JARs will be downloaded using maven (requires `mvn` command).
+
+`jni_gen` is also available as an API which tooling scripts can use. See `tool/generate_bindings.dart` for the script equivalent of the YAML file.
+
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/analysis_options.yaml b/pkgs/jni_gen/examples/pdfbox_plugin/analysis_options.yaml
new file mode 100644
index 0000000..198e7e0
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/analysis_options.yaml
@@ -0,0 +1,4 @@
+#include: package:flutter_lints/flutter.yaml
+
+# Additional information about this file can be found at
+# https://dart.dev/guides/language/analysis-options
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/android/.gitignore b/pkgs/jni_gen/examples/pdfbox_plugin/android/.gitignore
new file mode 100644
index 0000000..161bdcd
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/android/.gitignore
@@ -0,0 +1,9 @@
+*.iml
+.gradle
+/local.properties
+/.idea/workspace.xml
+/.idea/libraries
+.DS_Store
+/build
+/captures
+.cxx
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/android/build.gradle b/pkgs/jni_gen/examples/pdfbox_plugin/android/build.gradle
new file mode 100644
index 0000000..9c3bca8
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/android/build.gradle
@@ -0,0 +1,59 @@
+// The Android Gradle Plugin builds the native code with the Android NDK.
+
+group 'com.example.pdfbox_plugin'
+version '1.0'
+
+buildscript {
+    repositories {
+        google()
+        mavenCentral()
+    }
+
+    dependencies {
+        // The Android Gradle Plugin knows how to build native code with the NDK.
+        classpath 'com.android.tools.build:gradle:7.1.2'
+    }
+}
+
+rootProject.allprojects {
+    repositories {
+        google()
+        mavenCentral()
+    }
+}
+
+apply plugin: 'com.android.library'
+
+android {
+    // Bumping the plugin compileSdkVersion requires all clients of this plugin
+    // to bump the version in their app.
+    compileSdkVersion 31
+
+    // Bumping the plugin ndkVersion requires all clients of this plugin to bump
+    // the version in their app and to download a newer version of the NDK.
+    ndkVersion "21.1.6352462"
+
+    // Invoke the shared CMake build with the Android Gradle Plugin.
+    externalNativeBuild {
+        cmake {
+            path "../src/CMakeLists.txt"
+
+            // The default CMake version for the Android Gradle Plugin is 3.10.2.
+            // https://developer.android.com/studio/projects/install-ndk#vanilla_cmake
+            //
+            // The Flutter tooling requires that developers have CMake 3.10 or later
+            // installed. You should not increase this version, as doing so will cause
+            // the plugin to fail to compile for some customers of the plugin.
+            // version "3.10.2"
+        }
+    }
+
+    compileOptions {
+        sourceCompatibility JavaVersion.VERSION_1_8
+        targetCompatibility JavaVersion.VERSION_1_8
+    }
+
+    defaultConfig {
+        minSdkVersion 16
+    }
+}
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/android/settings.gradle b/pkgs/jni_gen/examples/pdfbox_plugin/android/settings.gradle
new file mode 100644
index 0000000..84ca2f9
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/android/settings.gradle
@@ -0,0 +1 @@
+rootProject.name = 'pdfbox_plugin'
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/android/src/main/AndroidManifest.xml b/pkgs/jni_gen/examples/pdfbox_plugin/android/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..ae0f6a3
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/android/src/main/AndroidManifest.xml
@@ -0,0 +1,3 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+  package="com.example.pdfbox_plugin">
+</manifest>
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/dart_example/.gitignore b/pkgs/jni_gen/examples/pdfbox_plugin/dart_example/.gitignore
new file mode 100644
index 0000000..9644944
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/dart_example/.gitignore
@@ -0,0 +1,12 @@
+# Files and directories created by pub.
+.dart_tool/
+.packages
+
+# Conventional directory for build output.
+build/
+
+# PDF files
+*.pdf
+
+# AOT compiled
+*.exe
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/dart_example/CHANGELOG.md b/pkgs/jni_gen/examples/pdfbox_plugin/dart_example/CHANGELOG.md
new file mode 100644
index 0000000..effe43c
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/dart_example/CHANGELOG.md
@@ -0,0 +1,3 @@
+## 1.0.0
+
+- Initial version.
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/dart_example/README.md b/pkgs/jni_gen/examples/pdfbox_plugin/dart_example/README.md
new file mode 100644
index 0000000..f111493
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/dart_example/README.md
@@ -0,0 +1,10 @@
+## Running
+After generating `pdfbox_plugin` bindings in the parent directory
+
+* setup native libraries: `dart run jni:setup && dart run jni:setup -p pdfbox_plugin`
+
+* `dart run bin/pdf_info.dart <Path_to_PDF_File>`
+
+Alternatively, it's possible to compile `bin/pdf_info.dart` and then run it.
+
+To run it from other directories, the `helperDir` and `classpath` parameters in `Jni.spawn` call should be adjusted appropriately.
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/dart_example/analysis_options.yaml b/pkgs/jni_gen/examples/pdfbox_plugin/dart_example/analysis_options.yaml
new file mode 100644
index 0000000..dee8927
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/dart_example/analysis_options.yaml
@@ -0,0 +1,30 @@
+# This file configures the static analysis results for your project (errors,
+# warnings, and lints).
+#
+# This enables the 'recommended' set of lints from `package:lints`.
+# This set helps identify many issues that may lead to problems when running
+# or consuming Dart code, and enforces writing Dart using a single, idiomatic
+# style and format.
+#
+# If you want a smaller set of lints you can change this to specify
+# 'package:lints/core.yaml'. These are just the most critical lints
+# (the recommended set includes the core lints).
+# The core lints are also what is used by pub.dev for scoring packages.
+
+include: package:lints/recommended.yaml
+
+# Uncomment the following section to specify additional rules.
+
+# linter:
+#   rules:
+#     - camel_case_types
+
+# analyzer:
+#   exclude:
+#     - path/to/excluded/files/**
+
+# For more information about the core and recommended set of lints, see
+# https://dart.dev/go/core-lints
+
+# For additional information about configuring this file, see
+# https://dart.dev/guides/language/analysis-options
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/dart_example/bin/pdf_info.dart b/pkgs/jni_gen/examples/pdfbox_plugin/dart_example/bin/pdf_info.dart
new file mode 100644
index 0000000..f8756ff
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/dart_example/bin/pdf_info.dart
@@ -0,0 +1,72 @@
+import 'dart:io';
+
+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();
+
+  var inputFile = jni
+      .newInstance("java/io/FileInputStream", "(Ljava/lang/String;)V", [file]);
+  var inputJl = JlObject.fromRef(inputFile.jobject);
+
+  var pdDoc = PDDocument.load7(inputJl);
+  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) {
+    stderr.writeln('Title: ${title.toDartString()}');
+  }
+  if (subject.reference != nullptr) {
+    stderr.writeln('Subject: ${subject.toDartString()}');
+  }
+  if (author.reference != nullptr) {
+    stderr.writeln('Author: ${author.toDartString()}');
+  }
+  stderr.writeln('PDF Version: ${pdDoc.getVersion()}');
+
+  for (JlObject jr in [pdDoc, info, title, author, subject]) {
+    jr.delete();
+  }
+  inputFile.delete();
+}
+
+final jniLibsDir = join('build', 'jni_libs');
+
+const jarError = 'No JAR files were found.\n'
+    'Run `dart run jni_gen:download_maven_jars --config jnigen.yaml` '
+    'in plugin directory.\n'
+    'Alternatively, regenerate JNI bindings in plugin directory, which will '
+    'automatically download the JAR files.';
+
+void main(List<String> arguments) {
+  final jarDir = join('..', 'mvn_jar');
+  List<String> jars;
+  try {
+    jars = Directory(jarDir)
+        .listSync()
+        .map((e) => e.path)
+        .where((path) => path.endsWith('.jar'))
+        .toList();
+  } on OSError catch (_) {
+    stderr.writeln(jarError);
+    return;
+  }
+  if (jars.isEmpty) {
+    stderr.writeln(jarError);
+    return;
+  }
+  Jni.spawn(helperDir: jniLibsDir, classPath: jars);
+  if (arguments.length != 1) {
+    stderr.writeln('usage: dart run pdf_info:pdf_info <Path_to_PDF>');
+    exitCode = 1;
+    return;
+  }
+  writeInfo(arguments[0]);
+}
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/dart_example/pubspec.yaml b/pkgs/jni_gen/examples/pdfbox_plugin/dart_example/pubspec.yaml
new file mode 100644
index 0000000..b694b73
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/dart_example/pubspec.yaml
@@ -0,0 +1,19 @@
+name: pdf_info
+description: Dart standalone example using jni_gen PDFBox bindings
+version: 1.0.0
+publish_to: none
+# homepage: https://www.example.com
+
+environment:
+  sdk: '>=2.17.6 <3.0.0'
+
+dependencies:
+  path: ^1.8.0
+  jni:
+    path: ../../../../jni/
+  pdfbox_plugin:
+    path: ../
+
+dev_dependencies:
+  lints: ^2.0.0
+  test: ^1.16.0
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/example/.gitignore b/pkgs/jni_gen/examples/pdfbox_plugin/example/.gitignore
new file mode 100644
index 0000000..a8e938c
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/example/.gitignore
@@ -0,0 +1,47 @@
+# Miscellaneous
+*.class
+*.log
+*.pyc
+*.swp
+.DS_Store
+.atom/
+.buildlog/
+.history
+.svn/
+migrate_working_dir/
+
+# IntelliJ related
+*.iml
+*.ipr
+*.iws
+.idea/
+
+# The .vscode folder contains launch configuration and tasks you configure in
+# VS Code which you may wish to be included in version control, so this line
+# is commented out by default.
+#.vscode/
+
+# Flutter/Dart/Pub related
+**/doc/api/
+**/ios/Flutter/.last_build_id
+.dart_tool/
+.flutter-plugins
+.flutter-plugins-dependencies
+.packages
+.pub-cache/
+.pub/
+/build/
+
+# Web related
+lib/generated_plugin_registrant.dart
+
+# Symbolication related
+app.*.symbols
+
+# Obfuscation related
+app.*.map.json
+
+# Android Studio will place build artifacts here
+/android/app/debug
+/android/app/profile
+/android/app/release
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/example/README.md b/pkgs/jni_gen/examples/pdfbox_plugin/example/README.md
new file mode 100644
index 0000000..697559c
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/example/README.md
@@ -0,0 +1,18 @@
+# pdfbox_plugin_example
+
+Demonstrates how to use the PDFBox bindings generated using `jni_gen`. This is a Linux Flutter application. The sample application lists the PDF files in a directory with number of pages and title, also allowing to navigate between directories.
+
+First, it's required to have generated the dart and C bindings in the plugin directory, which also downloads the required JARs using maven. The bindings are not committed because generated code is several thousands of lines.
+
+On a Linux machine, following commands can be used to run the example application.
+
+```
+cd .. ## From this folder
+dart run jni_gen --config jnigen.yaml ## Downloads PDFBox JARs and generates bindings.
+cd example/
+flutter run --release ## Opens the files list from home directory
+```
+
+It may take some time for PDFBox to process all PDFs in a directory. In the interest of simplicity, this example application displays the list after all PDFs are processed.
+
+Follow along the code in `lib/main.dart` to see how generated bindings are used.
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/example/analysis_options.yaml b/pkgs/jni_gen/examples/pdfbox_plugin/example/analysis_options.yaml
new file mode 100644
index 0000000..61b6c4d
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/example/analysis_options.yaml
@@ -0,0 +1,29 @@
+# This file configures the analyzer, which statically analyzes Dart code to
+# check for errors, warnings, and lints.
+#
+# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
+# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
+# invoked from the command line by running `flutter analyze`.
+
+# The following line activates a set of recommended lints for Flutter apps,
+# packages, and plugins designed to encourage good coding practices.
+include: package:flutter_lints/flutter.yaml
+
+linter:
+  # The lint rules applied to this project can be customized in the
+  # section below to disable rules from the `package:flutter_lints/flutter.yaml`
+  # included above or to enable additional rules. A list of all available lints
+  # and their documentation is published at
+  # https://dart-lang.github.io/linter/lints/index.html.
+  #
+  # Instead of disabling a lint rule for the entire project in the
+  # section below, it can also be suppressed for a single line of code
+  # or a specific dart file by using the `// ignore: name_of_lint` and
+  # `// ignore_for_file: name_of_lint` syntax on the line or in the file
+  # producing the lint.
+  rules:
+    # avoid_print: false  # Uncomment to disable the `avoid_print` rule
+    # prefer_single_quotes: true  # Uncomment to enable the `prefer_single_quotes` rule
+
+# Additional information about this file can be found at
+# https://dart.dev/guides/language/analysis-options
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/example/android/.gitignore b/pkgs/jni_gen/examples/pdfbox_plugin/example/android/.gitignore
new file mode 100644
index 0000000..6f56801
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/example/android/.gitignore
@@ -0,0 +1,13 @@
+gradle-wrapper.jar
+/.gradle
+/captures/
+/gradlew
+/gradlew.bat
+/local.properties
+GeneratedPluginRegistrant.java
+
+# Remember to never publicly share your keystore.
+# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
+key.properties
+**/*.keystore
+**/*.jks
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/example/android/app/build.gradle b/pkgs/jni_gen/examples/pdfbox_plugin/example/android/app/build.gradle
new file mode 100644
index 0000000..162ad5b
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/example/android/app/build.gradle
@@ -0,0 +1,71 @@
+def localProperties = new Properties()
+def localPropertiesFile = rootProject.file('local.properties')
+if (localPropertiesFile.exists()) {
+    localPropertiesFile.withReader('UTF-8') { reader ->
+        localProperties.load(reader)
+    }
+}
+
+def flutterRoot = localProperties.getProperty('flutter.sdk')
+if (flutterRoot == null) {
+    throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
+}
+
+def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
+if (flutterVersionCode == null) {
+    flutterVersionCode = '1'
+}
+
+def flutterVersionName = localProperties.getProperty('flutter.versionName')
+if (flutterVersionName == null) {
+    flutterVersionName = '1.0'
+}
+
+apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android'
+apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
+
+android {
+    compileSdkVersion flutter.compileSdkVersion
+    ndkVersion flutter.ndkVersion
+
+    compileOptions {
+        sourceCompatibility JavaVersion.VERSION_1_8
+        targetCompatibility JavaVersion.VERSION_1_8
+    }
+
+    kotlinOptions {
+        jvmTarget = '1.8'
+    }
+
+    sourceSets {
+        main.java.srcDirs += 'src/main/kotlin'
+    }
+
+    defaultConfig {
+        // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
+        applicationId "com.example.pdfbox_plugin_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
+        targetSdkVersion flutter.targetSdkVersion
+        versionCode flutterVersionCode.toInteger()
+        versionName flutterVersionName
+    }
+
+    buildTypes {
+        release {
+            // TODO: Add your own signing config for the release build.
+            // Signing with the debug keys for now, so `flutter run --release` works.
+            signingConfig signingConfigs.debug
+        }
+    }
+}
+
+flutter {
+    source '../..'
+}
+
+dependencies {
+    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+}
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/example/android/app/src/debug/AndroidManifest.xml b/pkgs/jni_gen/examples/pdfbox_plugin/example/android/app/src/debug/AndroidManifest.xml
new file mode 100644
index 0000000..3789e50
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/example/android/app/src/debug/AndroidManifest.xml
@@ -0,0 +1,8 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.pdfbox_plugin_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.
+    -->
+    <uses-permission android:name="android.permission.INTERNET"/>
+</manifest>
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/example/android/app/src/main/AndroidManifest.xml b/pkgs/jni_gen/examples/pdfbox_plugin/example/android/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..a46900a
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/example/android/app/src/main/AndroidManifest.xml
@@ -0,0 +1,34 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.pdfbox_plugin_example">
+   <application
+        android:label="pdfbox_plugin_example"
+        android:name="${applicationName}"
+        android:icon="@mipmap/ic_launcher">
+        <activity
+            android:name=".MainActivity"
+            android:exported="true"
+            android:launchMode="singleTop"
+            android:theme="@style/LaunchTheme"
+            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
+            android:hardwareAccelerated="true"
+            android:windowSoftInputMode="adjustResize">
+            <!-- Specifies an Android theme to apply to this Activity as soon as
+                 the Android process has started. This theme is visible to the user
+                 while the Flutter UI initializes. After that, this theme continues
+                 to determine the Window background behind the Flutter UI. -->
+            <meta-data
+              android:name="io.flutter.embedding.android.NormalTheme"
+              android:resource="@style/NormalTheme"
+              />
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
+        <!-- Don't delete the meta-data below.
+             This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
+        <meta-data
+            android:name="flutterEmbedding"
+            android:value="2" />
+    </application>
+</manifest>
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/example/android/app/src/main/kotlin/com/example/pdfbox_plugin_example/MainActivity.kt b/pkgs/jni_gen/examples/pdfbox_plugin/example/android/app/src/main/kotlin/com/example/pdfbox_plugin_example/MainActivity.kt
new file mode 100644
index 0000000..68d076c
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/example/android/app/src/main/kotlin/com/example/pdfbox_plugin_example/MainActivity.kt
@@ -0,0 +1,6 @@
+package com.example.pdfbox_plugin_example
+
+import io.flutter.embedding.android.FlutterActivity
+
+class MainActivity: FlutterActivity() {
+}
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/example/android/app/src/main/res/drawable-v21/launch_background.xml b/pkgs/jni_gen/examples/pdfbox_plugin/example/android/app/src/main/res/drawable-v21/launch_background.xml
new file mode 100644
index 0000000..f74085f
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/example/android/app/src/main/res/drawable-v21/launch_background.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Modify this file to customize your launch splash screen -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="?android:colorBackground" />
+
+    <!-- You can insert your own image assets here -->
+    <!-- <item>
+        <bitmap
+            android:gravity="center"
+            android:src="@mipmap/launch_image" />
+    </item> -->
+</layer-list>
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/example/android/app/src/main/res/drawable/launch_background.xml b/pkgs/jni_gen/examples/pdfbox_plugin/example/android/app/src/main/res/drawable/launch_background.xml
new file mode 100644
index 0000000..304732f
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/example/android/app/src/main/res/drawable/launch_background.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Modify this file to customize your launch splash screen -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@android:color/white" />
+
+    <!-- You can insert your own image assets here -->
+    <!-- <item>
+        <bitmap
+            android:gravity="center"
+            android:src="@mipmap/launch_image" />
+    </item> -->
+</layer-list>
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/pkgs/jni_gen/examples/pdfbox_plugin/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..db77bb4
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/pkgs/jni_gen/examples/pdfbox_plugin/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..17987b7
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/pkgs/jni_gen/examples/pdfbox_plugin/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..09d4391
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/pkgs/jni_gen/examples/pdfbox_plugin/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..d5f1c8d
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/pkgs/jni_gen/examples/pdfbox_plugin/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..4d6372e
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/example/android/app/src/main/res/values-night/styles.xml b/pkgs/jni_gen/examples/pdfbox_plugin/example/android/app/src/main/res/values-night/styles.xml
new file mode 100644
index 0000000..06952be
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/example/android/app/src/main/res/values-night/styles.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
+    <style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
+        <!-- Show a splash screen on the activity. Automatically removed when
+             the Flutter engine draws its first frame -->
+        <item name="android:windowBackground">@drawable/launch_background</item>
+    </style>
+    <!-- Theme applied to the Android Window as soon as the process has started.
+         This theme determines the color of the Android Window while your
+         Flutter UI initializes, as well as behind your Flutter UI while its
+         running.
+
+         This Theme is only used starting with V2 of Flutter's Android embedding. -->
+    <style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
+        <item name="android:windowBackground">?android:colorBackground</item>
+    </style>
+</resources>
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/example/android/app/src/main/res/values/styles.xml b/pkgs/jni_gen/examples/pdfbox_plugin/example/android/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..cb1ef88
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/example/android/app/src/main/res/values/styles.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
+    <style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
+        <!-- Show a splash screen on the activity. Automatically removed when
+             the Flutter engine draws its first frame -->
+        <item name="android:windowBackground">@drawable/launch_background</item>
+    </style>
+    <!-- Theme applied to the Android Window as soon as the process has started.
+         This theme determines the color of the Android Window while your
+         Flutter UI initializes, as well as behind your Flutter UI while its
+         running.
+
+         This Theme is only used starting with V2 of Flutter's Android embedding. -->
+    <style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
+        <item name="android:windowBackground">?android:colorBackground</item>
+    </style>
+</resources>
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/example/android/app/src/profile/AndroidManifest.xml b/pkgs/jni_gen/examples/pdfbox_plugin/example/android/app/src/profile/AndroidManifest.xml
new file mode 100644
index 0000000..3789e50
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/example/android/app/src/profile/AndroidManifest.xml
@@ -0,0 +1,8 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.pdfbox_plugin_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.
+    -->
+    <uses-permission android:name="android.permission.INTERNET"/>
+</manifest>
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/example/android/build.gradle b/pkgs/jni_gen/examples/pdfbox_plugin/example/android/build.gradle
new file mode 100644
index 0000000..83ae220
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/example/android/build.gradle
@@ -0,0 +1,31 @@
+buildscript {
+    ext.kotlin_version = '1.6.10'
+    repositories {
+        google()
+        mavenCentral()
+    }
+
+    dependencies {
+        classpath 'com.android.tools.build:gradle:7.1.2'
+        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+    }
+}
+
+allprojects {
+    repositories {
+        google()
+        mavenCentral()
+    }
+}
+
+rootProject.buildDir = '../build'
+subprojects {
+    project.buildDir = "${rootProject.buildDir}/${project.name}"
+}
+subprojects {
+    project.evaluationDependsOn(':app')
+}
+
+task clean(type: Delete) {
+    delete rootProject.buildDir
+}
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/example/android/gradle.properties b/pkgs/jni_gen/examples/pdfbox_plugin/example/android/gradle.properties
new file mode 100644
index 0000000..94adc3a
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/example/android/gradle.properties
@@ -0,0 +1,3 @@
+org.gradle.jvmargs=-Xmx1536M
+android.useAndroidX=true
+android.enableJetifier=true
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/example/android/gradle/wrapper/gradle-wrapper.properties b/pkgs/jni_gen/examples/pdfbox_plugin/example/android/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..cc5527d
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/example/android/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Fri Jun 23 08:50:38 CEST 2017
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/example/android/settings.gradle b/pkgs/jni_gen/examples/pdfbox_plugin/example/android/settings.gradle
new file mode 100644
index 0000000..44e62bc
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/example/android/settings.gradle
@@ -0,0 +1,11 @@
+include ':app'
+
+def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
+def properties = new Properties()
+
+assert localPropertiesFile.exists()
+localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
+
+def flutterSdkPath = properties.getProperty("flutter.sdk")
+assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
+apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/example/lib/main.dart b/pkgs/jni_gen/examples/pdfbox_plugin/example/lib/main.dart
new file mode 100644
index 0000000..1557b84
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/example/lib/main.dart
@@ -0,0 +1,212 @@
+import 'package:flutter/material.dart';
+import 'dart:io';
+import 'dart:async';
+
+import 'dart:ffi'; // for nullptr :=
+import 'package:jni/jni.dart';
+import 'package:path/path.dart';
+
+// Import the generated bindings.
+// Note: the structure generated bindings corresponds to Java package's
+// structure. Therefore, `org.apache.pdfbox.pdmodel` package becomes
+// `org/apache/pdfbox/pdmodel.dart`
+import 'package:pdfbox_plugin/third_party/org/apache/pdfbox/pdmodel.dart';
+
+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 jni_gen:download_maven_jars --config jnigen.yaml` '
+    'in plugin directory.\n'
+    'Alternatively, regenerate JNI bindings in plugin directory, which will '
+    'automatically download the JAR files.';
+
+void main() {
+  if (!Platform.isAndroid) {
+    // Assuming application is run from example/ folder
+    // It's required to manually provide the JAR files as classpath when
+    // spawning the JVM.
+    const jarDir = '../mvn_jar/';
+    List<String> jars;
+    try {
+      jars = Directory(jarDir)
+          .listSync()
+          .map((e) => e.path)
+          .where((path) => path.endsWith('.jar'))
+          .toList();
+    } on OSError catch (_) {
+      stderr.writeln(jarError);
+      return;
+    }
+    if (jars.isEmpty) {
+      stderr.writeln(jarError);
+      return;
+    }
+    Jni.spawn(classPath: jars);
+  }
+  jni = Jni.getInstance();
+  runApp(const PDFInfoApp());
+}
+
+class PDFInfoApp extends StatefulWidget {
+  const PDFInfoApp({super.key});
+
+  @override
+  PDFInfoAppState createState() => PDFInfoAppState();
+}
+
+class PDFInfoAppState extends State<PDFInfoApp> {
+  bool _isLoading = true;
+  String _dir = '.';
+  List<String> _pdfs = [];
+  List<String> _dirs = [];
+
+  void setDir(String dir) async {
+    final pdfs = <String>[];
+    final dirs = <String>[];
+
+    setState(() => _isLoading = true);
+
+    await for (var item in Directory(dir).list()) {
+      final isDir = (await item.stat()).type == FileSystemEntityType.directory;
+      if (item.path.endsWith('.pdf') && !isDir) {
+        pdfs.add(item.path);
+      } else if (isDir) {
+        dirs.add(item.path);
+      }
+    }
+    setState(() {
+      _isLoading = false;
+      _dir = dir;
+      _pdfs = pdfs;
+      _dirs = dirs;
+    });
+  }
+
+  @override
+  void initState() {
+    super.initState();
+    final dir = Platform.environment['HOME'] ?? '.';
+    setDir(dir);
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    final dirBaseName = basename(_dir);
+    return MaterialApp(
+      home: Scaffold(
+        appBar: AppBar(
+          title: Text('PDF Info: $dirBaseName'),
+        ),
+        body: SingleChildScrollView(
+          child: Container(
+              padding: const EdgeInsets.all(10),
+              child: _isLoading
+                  ? const Text('loading...')
+                  : Table(border: TableBorder.all(), children: [
+                      TableRow(children: [
+                        for (var heading in ['File', 'Title', 'Pages'])
+                          TableCell(
+                              child: _pad(Text(heading,
+                                  style: const TextStyle(
+                                      fontSize: 16,
+                                      decoration: TextDecoration.underline)))),
+                      ]),
+                      TableRow(children: [
+                        TableCell(
+                          child: _pad(
+                            InkWell(
+                              child: const Text('..'),
+                              onTap: () => setDir(dirname(_dir)),
+                            ),
+                          ),
+                        ),
+                        const TableCell(child: Text('')),
+                        const TableCell(child: Text('')),
+                      ]),
+                      for (var dir in _dirs) _dirTile(basename(dir)),
+                      for (var pdfname in _pdfs)
+                        _pdfInfo(PDFFileInfo.usingPDFBox(pdfname)),
+                    ])),
+        ),
+      ),
+    );
+  }
+
+  TableRow _dirTile(String target) {
+    return TableRow(children: [
+      TableCell(
+        child: _pad(
+          InkWell(
+            onTap: () => setDir(join(_dir, target)),
+            child: Text(
+              target,
+              style: const TextStyle(fontWeight: FontWeight.bold),
+            ),
+          ),
+        ),
+      ),
+      const TableCell(child: Text('-')),
+      const TableCell(child: Text('-')),
+    ]);
+  }
+}
+
+// It's generally a good practice to separate JNI calls from UI / model code.
+class PDFFileInfo {
+  String filename;
+  late String author, subject, title;
+  late int numPages;
+
+  /// Converts JlString to dart string and deletes the original.
+  String _fromJavaStr(JlString jstr) {
+    if (jstr.reference == nullptr) {
+      return '(null)';
+    }
+    final result = jstr.toDartString();
+    jstr.delete();
+    return result;
+  }
+
+  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);
+
+    // Static method call PDDocument.load -> PDDocument
+    final pdf = PDDocument.load(inputJl);
+    // Instance method call getNumberOfPages() -> int
+    numPages = pdf.getNumberOfPages();
+    // Instance method that returns an object
+    final info = pdf.getDocumentInformation();
+
+    /// java.lang.String is a special case and is mapped to JlString which is
+    /// a subclass of JlObject.
+    author = _fromJavaStr(info.getAuthor());
+    title = _fromJavaStr(info.getTitle());
+    subject = _fromJavaStr(info.getSubject());
+
+    /// Delete objects after done.
+    info.delete();
+    pdf.close();
+    pdf.delete();
+    inputFile.delete();
+  }
+}
+
+Padding _pad(Widget w) => Padding(
+    padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), child: w);
+
+TableRow _pdfInfo(PDFFileInfo info) {
+  return TableRow(children: [
+    TableCell(
+        child: _pad(Text(basename(info.filename),
+            style: const TextStyle(fontWeight: FontWeight.bold)))),
+    TableCell(child: _pad(Text(info.title))),
+    TableCell(
+        child: _pad(Text(info.numPages.toString(),
+            style: const TextStyle(color: Colors.grey)))),
+  ]);
+}
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/example/linux/.gitignore b/pkgs/jni_gen/examples/pdfbox_plugin/example/linux/.gitignore
new file mode 100644
index 0000000..d3896c9
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/example/linux/.gitignore
@@ -0,0 +1 @@
+flutter/ephemeral
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/example/linux/CMakeLists.txt b/pkgs/jni_gen/examples/pdfbox_plugin/example/linux/CMakeLists.txt
new file mode 100644
index 0000000..f36768d
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/example/linux/CMakeLists.txt
@@ -0,0 +1,138 @@
+# Project-level configuration.
+cmake_minimum_required(VERSION 3.10)
+project(runner LANGUAGES CXX)
+
+# The name of the executable created for the application. Change this to change
+# the on-disk name of your application.
+set(BINARY_NAME "pdfbox_plugin_example")
+# The unique GTK application identifier for this application. See:
+# https://wiki.gnome.org/HowDoI/ChooseApplicationID
+set(APPLICATION_ID "com.example.pdfbox_plugin")
+
+# Explicitly opt in to modern CMake behaviors to avoid warnings with recent
+# versions of CMake.
+cmake_policy(SET CMP0063 NEW)
+
+# Load bundled libraries from the lib/ directory relative to the binary.
+set(CMAKE_INSTALL_RPATH "$ORIGIN/lib")
+
+# Root filesystem for cross-building.
+if(FLUTTER_TARGET_PLATFORM_SYSROOT)
+  set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT})
+  set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT})
+  set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+  set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
+  set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+  set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+endif()
+
+# Define build configuration options.
+if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
+  set(CMAKE_BUILD_TYPE "Debug" CACHE
+    STRING "Flutter build mode" FORCE)
+  set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
+    "Debug" "Profile" "Release")
+endif()
+
+# Compilation settings that should be applied to most targets.
+#
+# Be cautious about adding new options here, as plugins use this function by
+# default. In most cases, you should add new options to specific targets instead
+# of modifying this function.
+function(APPLY_STANDARD_SETTINGS TARGET)
+  target_compile_features(${TARGET} PUBLIC cxx_std_14)
+  target_compile_options(${TARGET} PRIVATE -Wall -Werror)
+  target_compile_options(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:-O3>")
+  target_compile_definitions(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:NDEBUG>")
+endfunction()
+
+# Flutter library and tool build rules.
+set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
+add_subdirectory(${FLUTTER_MANAGED_DIR})
+
+# System-level dependencies.
+find_package(PkgConfig REQUIRED)
+pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
+
+add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}")
+
+# Define the application target. To change its name, change BINARY_NAME above,
+# not the value here, or `flutter run` will no longer work.
+#
+# Any new source files that you add to the application should be added here.
+add_executable(${BINARY_NAME}
+  "main.cc"
+  "my_application.cc"
+  "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
+)
+
+# Apply the standard set of build settings. This can be removed for applications
+# that need different build settings.
+apply_standard_settings(${BINARY_NAME})
+
+# Add dependency libraries. Add any application-specific dependencies here.
+target_link_libraries(${BINARY_NAME} PRIVATE flutter)
+target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK)
+
+# Run the Flutter tool portions of the build. This must not be removed.
+add_dependencies(${BINARY_NAME} flutter_assemble)
+
+# Only the install-generated bundle's copy of the executable will launch
+# correctly, since the resources must in the right relative locations. To avoid
+# people trying to run the unbundled copy, put it in a subdirectory instead of
+# the default top-level location.
+set_target_properties(${BINARY_NAME}
+  PROPERTIES
+  RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run"
+)
+
+# Generated plugin build rules, which manage building the plugins and adding
+# them to the application.
+include(flutter/generated_plugins.cmake)
+
+
+# === Installation ===
+# By default, "installing" just makes a relocatable bundle in the build
+# directory.
+set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle")
+if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
+  set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
+endif()
+
+# Start with a clean build bundle directory every time.
+install(CODE "
+  file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\")
+  " COMPONENT Runtime)
+
+set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
+set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib")
+
+install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
+  COMPONENT Runtime)
+
+install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
+  COMPONENT Runtime)
+
+install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
+  COMPONENT Runtime)
+
+foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES})
+  install(FILES "${bundled_library}"
+    DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
+    COMPONENT Runtime)
+endforeach(bundled_library)
+
+# Fully re-copy the assets directory on each build to avoid having stale files
+# from a previous install.
+set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
+install(CODE "
+  file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
+  " COMPONENT Runtime)
+install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
+  DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
+
+# Install the AOT library on non-Debug builds only.
+if(NOT CMAKE_BUILD_TYPE MATCHES "Debug")
+  install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
+    COMPONENT Runtime)
+endif()
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/example/linux/flutter/CMakeLists.txt b/pkgs/jni_gen/examples/pdfbox_plugin/example/linux/flutter/CMakeLists.txt
new file mode 100644
index 0000000..d5bd016
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/example/linux/flutter/CMakeLists.txt
@@ -0,0 +1,88 @@
+# This file controls Flutter-level build steps. It should not be edited.
+cmake_minimum_required(VERSION 3.10)
+
+set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")
+
+# Configuration provided via flutter tool.
+include(${EPHEMERAL_DIR}/generated_config.cmake)
+
+# TODO: Move the rest of this into files in ephemeral. See
+# https://github.com/flutter/flutter/issues/57146.
+
+# Serves the same purpose as list(TRANSFORM ... PREPEND ...),
+# which isn't available in 3.10.
+function(list_prepend LIST_NAME PREFIX)
+    set(NEW_LIST "")
+    foreach(element ${${LIST_NAME}})
+        list(APPEND NEW_LIST "${PREFIX}${element}")
+    endforeach(element)
+    set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE)
+endfunction()
+
+# === Flutter Library ===
+# System-level dependencies.
+find_package(PkgConfig REQUIRED)
+pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
+pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0)
+pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0)
+
+set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so")
+
+# Published to parent scope for install step.
+set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)
+set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE)
+set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE)
+set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE)
+
+list(APPEND FLUTTER_LIBRARY_HEADERS
+  "fl_basic_message_channel.h"
+  "fl_binary_codec.h"
+  "fl_binary_messenger.h"
+  "fl_dart_project.h"
+  "fl_engine.h"
+  "fl_json_message_codec.h"
+  "fl_json_method_codec.h"
+  "fl_message_codec.h"
+  "fl_method_call.h"
+  "fl_method_channel.h"
+  "fl_method_codec.h"
+  "fl_method_response.h"
+  "fl_plugin_registrar.h"
+  "fl_plugin_registry.h"
+  "fl_standard_message_codec.h"
+  "fl_standard_method_codec.h"
+  "fl_string_codec.h"
+  "fl_value.h"
+  "fl_view.h"
+  "flutter_linux.h"
+)
+list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/")
+add_library(flutter INTERFACE)
+target_include_directories(flutter INTERFACE
+  "${EPHEMERAL_DIR}"
+)
+target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}")
+target_link_libraries(flutter INTERFACE
+  PkgConfig::GTK
+  PkgConfig::GLIB
+  PkgConfig::GIO
+)
+add_dependencies(flutter flutter_assemble)
+
+# === Flutter tool backend ===
+# _phony_ is a non-existent file to force this command to run every time,
+# since currently there's no way to get a full input/output list from the
+# flutter tool.
+add_custom_command(
+  OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
+    ${CMAKE_CURRENT_BINARY_DIR}/_phony_
+  COMMAND ${CMAKE_COMMAND} -E env
+    ${FLUTTER_TOOL_ENVIRONMENT}
+    "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh"
+      ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE}
+  VERBATIM
+)
+add_custom_target(flutter_assemble DEPENDS
+  "${FLUTTER_LIBRARY}"
+  ${FLUTTER_LIBRARY_HEADERS}
+)
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/example/linux/flutter/generated_plugin_registrant.cc b/pkgs/jni_gen/examples/pdfbox_plugin/example/linux/flutter/generated_plugin_registrant.cc
new file mode 100644
index 0000000..e71a16d
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/example/linux/flutter/generated_plugin_registrant.cc
@@ -0,0 +1,11 @@
+//
+//  Generated file. Do not edit.
+//
+
+// clang-format off
+
+#include "generated_plugin_registrant.h"
+
+
+void fl_register_plugins(FlPluginRegistry* registry) {
+}
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/example/linux/flutter/generated_plugin_registrant.h b/pkgs/jni_gen/examples/pdfbox_plugin/example/linux/flutter/generated_plugin_registrant.h
new file mode 100644
index 0000000..e0f0a47
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/example/linux/flutter/generated_plugin_registrant.h
@@ -0,0 +1,15 @@
+//
+//  Generated file. Do not edit.
+//
+
+// clang-format off
+
+#ifndef GENERATED_PLUGIN_REGISTRANT_
+#define GENERATED_PLUGIN_REGISTRANT_
+
+#include <flutter_linux/flutter_linux.h>
+
+// Registers Flutter plugins.
+void fl_register_plugins(FlPluginRegistry* registry);
+
+#endif  // GENERATED_PLUGIN_REGISTRANT_
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/example/linux/flutter/generated_plugins.cmake b/pkgs/jni_gen/examples/pdfbox_plugin/example/linux/flutter/generated_plugins.cmake
new file mode 100644
index 0000000..d2cbe73
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/example/linux/flutter/generated_plugins.cmake
@@ -0,0 +1,25 @@
+#
+# Generated file, do not edit.
+#
+
+list(APPEND FLUTTER_PLUGIN_LIST
+)
+
+list(APPEND FLUTTER_FFI_PLUGIN_LIST
+  jni
+  pdfbox_plugin
+)
+
+set(PLUGIN_BUNDLED_LIBRARIES)
+
+foreach(plugin ${FLUTTER_PLUGIN_LIST})
+  add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin})
+  target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
+  list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
+  list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
+endforeach(plugin)
+
+foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
+  add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin})
+  list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
+endforeach(ffi_plugin)
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/example/linux/main.cc b/pkgs/jni_gen/examples/pdfbox_plugin/example/linux/main.cc
new file mode 100644
index 0000000..e7c5c54
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/example/linux/main.cc
@@ -0,0 +1,6 @@
+#include "my_application.h"
+
+int main(int argc, char** argv) {
+  g_autoptr(MyApplication) app = my_application_new();
+  return g_application_run(G_APPLICATION(app), argc, argv);
+}
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/example/linux/my_application.cc b/pkgs/jni_gen/examples/pdfbox_plugin/example/linux/my_application.cc
new file mode 100644
index 0000000..b13351b
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/example/linux/my_application.cc
@@ -0,0 +1,104 @@
+#include "my_application.h"
+
+#include <flutter_linux/flutter_linux.h>
+#ifdef GDK_WINDOWING_X11
+#include <gdk/gdkx.h>
+#endif
+
+#include "flutter/generated_plugin_registrant.h"
+
+struct _MyApplication {
+  GtkApplication parent_instance;
+  char** dart_entrypoint_arguments;
+};
+
+G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION)
+
+// Implements GApplication::activate.
+static void my_application_activate(GApplication* application) {
+  MyApplication* self = MY_APPLICATION(application);
+  GtkWindow* window =
+      GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application)));
+
+  // Use a header bar when running in GNOME as this is the common style used
+  // by applications and is the setup most users will be using (e.g. Ubuntu
+  // desktop).
+  // If running on X and not using GNOME then just use a traditional title bar
+  // in case the window manager does more exotic layout, e.g. tiling.
+  // If running on Wayland assume the header bar will work (may need changing
+  // if future cases occur).
+  gboolean use_header_bar = TRUE;
+#ifdef GDK_WINDOWING_X11
+  GdkScreen* screen = gtk_window_get_screen(window);
+  if (GDK_IS_X11_SCREEN(screen)) {
+    const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen);
+    if (g_strcmp0(wm_name, "GNOME Shell") != 0) {
+      use_header_bar = FALSE;
+    }
+  }
+#endif
+  if (use_header_bar) {
+    GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new());
+    gtk_widget_show(GTK_WIDGET(header_bar));
+    gtk_header_bar_set_title(header_bar, "pdfbox_plugin_example");
+    gtk_header_bar_set_show_close_button(header_bar, TRUE);
+    gtk_window_set_titlebar(window, GTK_WIDGET(header_bar));
+  } else {
+    gtk_window_set_title(window, "pdfbox_plugin_example");
+  }
+
+  gtk_window_set_default_size(window, 1280, 720);
+  gtk_widget_show(GTK_WIDGET(window));
+
+  g_autoptr(FlDartProject) project = fl_dart_project_new();
+  fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments);
+
+  FlView* view = fl_view_new(project);
+  gtk_widget_show(GTK_WIDGET(view));
+  gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view));
+
+  fl_register_plugins(FL_PLUGIN_REGISTRY(view));
+
+  gtk_widget_grab_focus(GTK_WIDGET(view));
+}
+
+// Implements GApplication::local_command_line.
+static gboolean my_application_local_command_line(GApplication* application, gchar*** arguments, int* exit_status) {
+  MyApplication* self = MY_APPLICATION(application);
+  // Strip out the first argument as it is the binary name.
+  self->dart_entrypoint_arguments = g_strdupv(*arguments + 1);
+
+  g_autoptr(GError) error = nullptr;
+  if (!g_application_register(application, nullptr, &error)) {
+     g_warning("Failed to register: %s", error->message);
+     *exit_status = 1;
+     return TRUE;
+  }
+
+  g_application_activate(application);
+  *exit_status = 0;
+
+  return TRUE;
+}
+
+// Implements GObject::dispose.
+static void my_application_dispose(GObject* object) {
+  MyApplication* self = MY_APPLICATION(object);
+  g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev);
+  G_OBJECT_CLASS(my_application_parent_class)->dispose(object);
+}
+
+static void my_application_class_init(MyApplicationClass* klass) {
+  G_APPLICATION_CLASS(klass)->activate = my_application_activate;
+  G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line;
+  G_OBJECT_CLASS(klass)->dispose = my_application_dispose;
+}
+
+static void my_application_init(MyApplication* self) {}
+
+MyApplication* my_application_new() {
+  return MY_APPLICATION(g_object_new(my_application_get_type(),
+                                     "application-id", APPLICATION_ID,
+                                     "flags", G_APPLICATION_NON_UNIQUE,
+                                     nullptr));
+}
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/example/linux/my_application.h b/pkgs/jni_gen/examples/pdfbox_plugin/example/linux/my_application.h
new file mode 100644
index 0000000..72271d5
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/example/linux/my_application.h
@@ -0,0 +1,18 @@
+#ifndef FLUTTER_MY_APPLICATION_H_
+#define FLUTTER_MY_APPLICATION_H_
+
+#include <gtk/gtk.h>
+
+G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION,
+                     GtkApplication)
+
+/**
+ * my_application_new:
+ *
+ * Creates a new Flutter-based application.
+ *
+ * Returns: a new #MyApplication.
+ */
+MyApplication* my_application_new();
+
+#endif  // FLUTTER_MY_APPLICATION_H_
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/example/pubspec.yaml b/pkgs/jni_gen/examples/pdfbox_plugin/example/pubspec.yaml
new file mode 100644
index 0000000..ce5dd42
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/example/pubspec.yaml
@@ -0,0 +1,99 @@
+name: pdfbox_example
+description: Demonstrates how to use the pdfbox_plugin plugin.
+
+# The following line prevents the package from being accidentally published to
+# pub.dev using `flutter pub publish`. This is preferred for private packages.
+publish_to: 'none' # Remove this line if you wish to publish to pub.dev
+
+# The following defines the version and build number for your application.
+# A version number is three numbers separated by dots, like 1.2.43
+# followed by an optional build number separated by a +.
+# Both the version and the builder number may be overridden in flutter
+# build by specifying --build-name and --build-number, respectively.
+# In Android, build-name is used as versionName while build-number used as versionCode.
+# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
+# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
+# Read more about iOS versioning at
+# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
+version: 1.0.0+1
+
+environment:
+  sdk: ">=2.17.6 <3.0.0"
+
+# Dependencies specify other packages that your package needs in order to work.
+# To automatically upgrade your package dependencies to the latest versions
+# consider running `flutter pub upgrade --major-versions`. Alternatively,
+# dependencies can be manually updated by changing the version numbers below to
+# the latest version available on pub.dev. To see which dependencies have newer
+# versions available, run `flutter pub outdated`.
+dependencies:
+  flutter:
+    sdk: flutter
+
+  jni:
+    path: ../../../../jni/
+  path: ^1.8.0
+  pdfbox_plugin:
+    # When depending on this package from a real application you should use:
+    #   pdfbox_plugin: ^x.y.z
+    # See https://dart.dev/tools/pub/dependencies#version-constraints
+    # The example app is bundled with the plugin so we use a path dependency on
+    # the parent directory to use the current plugin's version.
+    path: ../
+
+  # The following adds the Cupertino Icons font to your application.
+  # Use with the CupertinoIcons class for iOS style icons.
+  cupertino_icons: ^1.0.2
+
+dev_dependencies:
+  flutter_test:
+    sdk: flutter
+
+  # The "flutter_lints" package below contains a set of recommended lints to
+  # encourage good coding practices. The lint set provided by the package is
+  # activated in the `analysis_options.yaml` file located at the root of your
+  # package. See that file for information about deactivating specific lint
+  # rules and activating additional ones.
+  flutter_lints: ^2.0.0
+
+# For information on the generic Dart part of this file, see the
+# following page: https://dart.dev/tools/pub/pubspec
+
+# The following section is specific to Flutter packages.
+flutter:
+
+  # The following line ensures that the Material Icons font is
+  # included with your application, so that you can use the icons in
+  # the material Icons class.
+  uses-material-design: true
+
+  # To add assets to your application, add an assets section, like this:
+  # assets:
+  #   - images/a_dot_burr.jpeg
+  #   - images/a_dot_ham.jpeg
+
+  # An image asset can refer to one or more resolution-specific "variants", see
+  # https://flutter.dev/assets-and-images/#resolution-aware
+
+  # For details regarding adding assets from package dependencies, see
+  # https://flutter.dev/assets-and-images/#from-packages
+
+  # To add custom fonts to your application, add a fonts section here,
+  # in this "flutter" section. Each entry in this list should have a
+  # "family" key with the font family name, and a "fonts" key with a
+  # list giving the asset and other descriptors for the font. For
+  # example:
+  # fonts:
+  #   - family: Schyler
+  #     fonts:
+  #       - asset: fonts/Schyler-Regular.ttf
+  #       - asset: fonts/Schyler-Italic.ttf
+  #         style: italic
+  #   - family: Trajan Pro
+  #     fonts:
+  #       - asset: fonts/TrajanPro.ttf
+  #       - asset: fonts/TrajanPro_Bold.ttf
+  #         weight: 700
+  #
+  # For details regarding fonts from package dependencies,
+  # see https://flutter.dev/custom-fonts/#from-packages
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/.gitignore b/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/.gitignore
new file mode 100644
index 0000000..d492d0d
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/.gitignore
@@ -0,0 +1,17 @@
+flutter/ephemeral/
+
+# Visual Studio user-specific files.
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# Visual Studio build-related files.
+x64/
+x86/
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!*.[Cc]ache/
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/CMakeLists.txt b/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/CMakeLists.txt
new file mode 100644
index 0000000..c233397
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/CMakeLists.txt
@@ -0,0 +1,101 @@
+# Project-level configuration.
+cmake_minimum_required(VERSION 3.14)
+project(pdfbox_plugin_example LANGUAGES CXX)
+
+# The name of the executable created for the application. Change this to change
+# the on-disk name of your application.
+set(BINARY_NAME "pdfbox_plugin_example")
+
+# Explicitly opt in to modern CMake behaviors to avoid warnings with recent
+# versions of CMake.
+cmake_policy(SET CMP0063 NEW)
+
+# Define build configuration option.
+get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
+if(IS_MULTICONFIG)
+  set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release"
+    CACHE STRING "" FORCE)
+else()
+  if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
+    set(CMAKE_BUILD_TYPE "Debug" CACHE
+      STRING "Flutter build mode" FORCE)
+    set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
+      "Debug" "Profile" "Release")
+  endif()
+endif()
+# Define settings for the Profile build mode.
+set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}")
+set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}")
+set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}")
+set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}")
+
+# Use Unicode for all projects.
+add_definitions(-DUNICODE -D_UNICODE)
+
+# Compilation settings that should be applied to most targets.
+#
+# Be cautious about adding new options here, as plugins use this function by
+# default. In most cases, you should add new options to specific targets instead
+# of modifying this function.
+function(APPLY_STANDARD_SETTINGS TARGET)
+  target_compile_features(${TARGET} PUBLIC cxx_std_17)
+  target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100")
+  target_compile_options(${TARGET} PRIVATE /EHsc)
+  target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0")
+  target_compile_definitions(${TARGET} PRIVATE "$<$<CONFIG:Debug>:_DEBUG>")
+endfunction()
+
+# Flutter library and tool build rules.
+set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
+add_subdirectory(${FLUTTER_MANAGED_DIR})
+
+# Application build; see runner/CMakeLists.txt.
+add_subdirectory("runner")
+
+# Generated plugin build rules, which manage building the plugins and adding
+# them to the application.
+include(flutter/generated_plugins.cmake)
+
+
+# === Installation ===
+# Support files are copied into place next to the executable, so that it can
+# run in place. This is done instead of making a separate bundle (as on Linux)
+# so that building and running from within Visual Studio will work.
+set(BUILD_BUNDLE_DIR "$<TARGET_FILE_DIR:${BINARY_NAME}>")
+# Make the "install" step default, as it's required to run.
+set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1)
+if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
+  set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
+endif()
+
+set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
+set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}")
+
+install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
+  COMPONENT Runtime)
+
+install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
+  COMPONENT Runtime)
+
+install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
+  COMPONENT Runtime)
+
+if(PLUGIN_BUNDLED_LIBRARIES)
+  install(FILES "${PLUGIN_BUNDLED_LIBRARIES}"
+    DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
+    COMPONENT Runtime)
+endif()
+
+# Fully re-copy the assets directory on each build to avoid having stale files
+# from a previous install.
+set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
+install(CODE "
+  file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
+  " COMPONENT Runtime)
+install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
+  DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
+
+# Install the AOT library on non-Debug builds only.
+install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
+  CONFIGURATIONS Profile;Release
+  COMPONENT Runtime)
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/flutter/CMakeLists.txt b/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/flutter/CMakeLists.txt
new file mode 100644
index 0000000..930d207
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/flutter/CMakeLists.txt
@@ -0,0 +1,104 @@
+# This file controls Flutter-level build steps. It should not be edited.
+cmake_minimum_required(VERSION 3.14)
+
+set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")
+
+# Configuration provided via flutter tool.
+include(${EPHEMERAL_DIR}/generated_config.cmake)
+
+# TODO: Move the rest of this into files in ephemeral. See
+# https://github.com/flutter/flutter/issues/57146.
+set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper")
+
+# === Flutter Library ===
+set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll")
+
+# Published to parent scope for install step.
+set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)
+set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE)
+set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE)
+set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE)
+
+list(APPEND FLUTTER_LIBRARY_HEADERS
+  "flutter_export.h"
+  "flutter_windows.h"
+  "flutter_messenger.h"
+  "flutter_plugin_registrar.h"
+  "flutter_texture_registrar.h"
+)
+list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/")
+add_library(flutter INTERFACE)
+target_include_directories(flutter INTERFACE
+  "${EPHEMERAL_DIR}"
+)
+target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib")
+add_dependencies(flutter flutter_assemble)
+
+# === Wrapper ===
+list(APPEND CPP_WRAPPER_SOURCES_CORE
+  "core_implementations.cc"
+  "standard_codec.cc"
+)
+list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/")
+list(APPEND CPP_WRAPPER_SOURCES_PLUGIN
+  "plugin_registrar.cc"
+)
+list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/")
+list(APPEND CPP_WRAPPER_SOURCES_APP
+  "flutter_engine.cc"
+  "flutter_view_controller.cc"
+)
+list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/")
+
+# Wrapper sources needed for a plugin.
+add_library(flutter_wrapper_plugin STATIC
+  ${CPP_WRAPPER_SOURCES_CORE}
+  ${CPP_WRAPPER_SOURCES_PLUGIN}
+)
+apply_standard_settings(flutter_wrapper_plugin)
+set_target_properties(flutter_wrapper_plugin PROPERTIES
+  POSITION_INDEPENDENT_CODE ON)
+set_target_properties(flutter_wrapper_plugin PROPERTIES
+  CXX_VISIBILITY_PRESET hidden)
+target_link_libraries(flutter_wrapper_plugin PUBLIC flutter)
+target_include_directories(flutter_wrapper_plugin PUBLIC
+  "${WRAPPER_ROOT}/include"
+)
+add_dependencies(flutter_wrapper_plugin flutter_assemble)
+
+# Wrapper sources needed for the runner.
+add_library(flutter_wrapper_app STATIC
+  ${CPP_WRAPPER_SOURCES_CORE}
+  ${CPP_WRAPPER_SOURCES_APP}
+)
+apply_standard_settings(flutter_wrapper_app)
+target_link_libraries(flutter_wrapper_app PUBLIC flutter)
+target_include_directories(flutter_wrapper_app PUBLIC
+  "${WRAPPER_ROOT}/include"
+)
+add_dependencies(flutter_wrapper_app flutter_assemble)
+
+# === Flutter tool backend ===
+# _phony_ is a non-existent file to force this command to run every time,
+# since currently there's no way to get a full input/output list from the
+# flutter tool.
+set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_")
+set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE)
+add_custom_command(
+  OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
+    ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN}
+    ${CPP_WRAPPER_SOURCES_APP}
+    ${PHONY_OUTPUT}
+  COMMAND ${CMAKE_COMMAND} -E env
+    ${FLUTTER_TOOL_ENVIRONMENT}
+    "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat"
+      windows-x64 $<CONFIG>
+  VERBATIM
+)
+add_custom_target(flutter_assemble DEPENDS
+  "${FLUTTER_LIBRARY}"
+  ${FLUTTER_LIBRARY_HEADERS}
+  ${CPP_WRAPPER_SOURCES_CORE}
+  ${CPP_WRAPPER_SOURCES_PLUGIN}
+  ${CPP_WRAPPER_SOURCES_APP}
+)
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/flutter/generated_plugin_registrant.cc b/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/flutter/generated_plugin_registrant.cc
new file mode 100644
index 0000000..8b6d468
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/flutter/generated_plugin_registrant.cc
@@ -0,0 +1,11 @@
+//
+//  Generated file. Do not edit.
+//
+
+// clang-format off
+
+#include "generated_plugin_registrant.h"
+
+
+void RegisterPlugins(flutter::PluginRegistry* registry) {
+}
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/flutter/generated_plugin_registrant.h b/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/flutter/generated_plugin_registrant.h
new file mode 100644
index 0000000..dc139d8
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/flutter/generated_plugin_registrant.h
@@ -0,0 +1,15 @@
+//
+//  Generated file. Do not edit.
+//
+
+// clang-format off
+
+#ifndef GENERATED_PLUGIN_REGISTRANT_
+#define GENERATED_PLUGIN_REGISTRANT_
+
+#include <flutter/plugin_registry.h>
+
+// Registers Flutter plugins.
+void RegisterPlugins(flutter::PluginRegistry* registry);
+
+#endif  // GENERATED_PLUGIN_REGISTRANT_
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/flutter/generated_plugins.cmake b/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/flutter/generated_plugins.cmake
new file mode 100644
index 0000000..facaded
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/flutter/generated_plugins.cmake
@@ -0,0 +1,25 @@
+#
+# Generated file, do not edit.
+#
+
+list(APPEND FLUTTER_PLUGIN_LIST
+)
+
+list(APPEND FLUTTER_FFI_PLUGIN_LIST
+  jni
+  pdfbox_plugin
+)
+
+set(PLUGIN_BUNDLED_LIBRARIES)
+
+foreach(plugin ${FLUTTER_PLUGIN_LIST})
+  add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin})
+  target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
+  list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
+  list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
+endforeach(plugin)
+
+foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
+  add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin})
+  list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
+endforeach(ffi_plugin)
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/runner/CMakeLists.txt b/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/runner/CMakeLists.txt
new file mode 100644
index 0000000..b9e550f
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/runner/CMakeLists.txt
@@ -0,0 +1,32 @@
+cmake_minimum_required(VERSION 3.14)
+project(runner LANGUAGES CXX)
+
+# Define the application target. To change its name, change BINARY_NAME in the
+# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer
+# work.
+#
+# Any new source files that you add to the application should be added here.
+add_executable(${BINARY_NAME} WIN32
+  "flutter_window.cpp"
+  "main.cpp"
+  "utils.cpp"
+  "win32_window.cpp"
+  "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
+  "Runner.rc"
+  "runner.exe.manifest"
+)
+
+# Apply the standard set of build settings. This can be removed for applications
+# that need different build settings.
+apply_standard_settings(${BINARY_NAME})
+
+# Disable Windows macros that collide with C++ standard library functions.
+target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX")
+
+# Add dependency libraries and include directories. Add any application-specific
+# dependencies here.
+target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app)
+target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}")
+
+# Run the Flutter tool portions of the build. This must not be removed.
+add_dependencies(${BINARY_NAME} flutter_assemble)
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/runner/Runner.rc b/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/runner/Runner.rc
new file mode 100644
index 0000000..05d079f
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/runner/Runner.rc
@@ -0,0 +1,121 @@
+// Microsoft Visual C++ generated resource script.
+//
+#pragma code_page(65001)
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "winres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (United States) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+    "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+    "#include ""winres.h""\r\n"
+    "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+    "\r\n"
+    "\0"
+END
+
+#endif    // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_APP_ICON            ICON                    "resources\\app_icon.ico"
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+#ifdef FLUTTER_BUILD_NUMBER
+#define VERSION_AS_NUMBER FLUTTER_BUILD_NUMBER
+#else
+#define VERSION_AS_NUMBER 1,0,0
+#endif
+
+#ifdef FLUTTER_BUILD_NAME
+#define VERSION_AS_STRING #FLUTTER_BUILD_NAME
+#else
+#define VERSION_AS_STRING "1.0.0"
+#endif
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION VERSION_AS_NUMBER
+ PRODUCTVERSION VERSION_AS_NUMBER
+ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+#ifdef _DEBUG
+ FILEFLAGS VS_FF_DEBUG
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS VOS__WINDOWS32
+ FILETYPE VFT_APP
+ FILESUBTYPE 0x0L
+BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK "040904e4"
+        BEGIN
+            VALUE "CompanyName", "com.example" "\0"
+            VALUE "FileDescription", "pdfbox_plugin_example" "\0"
+            VALUE "FileVersion", VERSION_AS_STRING "\0"
+            VALUE "InternalName", "pdfbox_plugin_example" "\0"
+            VALUE "LegalCopyright", "Copyright (C) 2022 com.example. All rights reserved." "\0"
+            VALUE "OriginalFilename", "pdfbox_plugin_example.exe" "\0"
+            VALUE "ProductName", "pdfbox_plugin_example" "\0"
+            VALUE "ProductVersion", VERSION_AS_STRING "\0"
+        END
+    END
+    BLOCK "VarFileInfo"
+    BEGIN
+        VALUE "Translation", 0x409, 1252
+    END
+END
+
+#endif    // English (United States) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif    // not APSTUDIO_INVOKED
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/runner/flutter_window.cpp b/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/runner/flutter_window.cpp
new file mode 100644
index 0000000..b43b909
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/runner/flutter_window.cpp
@@ -0,0 +1,61 @@
+#include "flutter_window.h"
+
+#include <optional>
+
+#include "flutter/generated_plugin_registrant.h"
+
+FlutterWindow::FlutterWindow(const flutter::DartProject& project)
+    : project_(project) {}
+
+FlutterWindow::~FlutterWindow() {}
+
+bool FlutterWindow::OnCreate() {
+  if (!Win32Window::OnCreate()) {
+    return false;
+  }
+
+  RECT frame = GetClientArea();
+
+  // The size here must match the window dimensions to avoid unnecessary surface
+  // creation / destruction in the startup path.
+  flutter_controller_ = std::make_unique<flutter::FlutterViewController>(
+      frame.right - frame.left, frame.bottom - frame.top, project_);
+  // Ensure that basic setup of the controller was successful.
+  if (!flutter_controller_->engine() || !flutter_controller_->view()) {
+    return false;
+  }
+  RegisterPlugins(flutter_controller_->engine());
+  SetChildContent(flutter_controller_->view()->GetNativeWindow());
+  return true;
+}
+
+void FlutterWindow::OnDestroy() {
+  if (flutter_controller_) {
+    flutter_controller_ = nullptr;
+  }
+
+  Win32Window::OnDestroy();
+}
+
+LRESULT
+FlutterWindow::MessageHandler(HWND hwnd, UINT const message,
+                              WPARAM const wparam,
+                              LPARAM const lparam) noexcept {
+  // Give Flutter, including plugins, an opportunity to handle window messages.
+  if (flutter_controller_) {
+    std::optional<LRESULT> result =
+        flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam,
+                                                      lparam);
+    if (result) {
+      return *result;
+    }
+  }
+
+  switch (message) {
+    case WM_FONTCHANGE:
+      flutter_controller_->engine()->ReloadSystemFonts();
+      break;
+  }
+
+  return Win32Window::MessageHandler(hwnd, message, wparam, lparam);
+}
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/runner/flutter_window.h b/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/runner/flutter_window.h
new file mode 100644
index 0000000..6da0652
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/runner/flutter_window.h
@@ -0,0 +1,33 @@
+#ifndef RUNNER_FLUTTER_WINDOW_H_
+#define RUNNER_FLUTTER_WINDOW_H_
+
+#include <flutter/dart_project.h>
+#include <flutter/flutter_view_controller.h>
+
+#include <memory>
+
+#include "win32_window.h"
+
+// A window that does nothing but host a Flutter view.
+class FlutterWindow : public Win32Window {
+ public:
+  // Creates a new FlutterWindow hosting a Flutter view running |project|.
+  explicit FlutterWindow(const flutter::DartProject& project);
+  virtual ~FlutterWindow();
+
+ protected:
+  // Win32Window:
+  bool OnCreate() override;
+  void OnDestroy() override;
+  LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam,
+                         LPARAM const lparam) noexcept override;
+
+ private:
+  // The project to run.
+  flutter::DartProject project_;
+
+  // The Flutter instance hosted by this window.
+  std::unique_ptr<flutter::FlutterViewController> flutter_controller_;
+};
+
+#endif  // RUNNER_FLUTTER_WINDOW_H_
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/runner/main.cpp b/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/runner/main.cpp
new file mode 100644
index 0000000..44bdbc6
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/runner/main.cpp
@@ -0,0 +1,43 @@
+#include <flutter/dart_project.h>
+#include <flutter/flutter_view_controller.h>
+#include <windows.h>
+
+#include "flutter_window.h"
+#include "utils.h"
+
+int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
+                      _In_ wchar_t *command_line, _In_ int show_command) {
+  // Attach to console when present (e.g., 'flutter run') or create a
+  // new console when running with a debugger.
+  if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) {
+    CreateAndAttachConsole();
+  }
+
+  // Initialize COM, so that it is available for use in the library and/or
+  // plugins.
+  ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
+
+  flutter::DartProject project(L"data");
+
+  std::vector<std::string> command_line_arguments =
+      GetCommandLineArguments();
+
+  project.set_dart_entrypoint_arguments(std::move(command_line_arguments));
+
+  FlutterWindow window(project);
+  Win32Window::Point origin(10, 10);
+  Win32Window::Size size(1280, 720);
+  if (!window.CreateAndShow(L"pdfbox_plugin_example", origin, size)) {
+    return EXIT_FAILURE;
+  }
+  window.SetQuitOnClose(true);
+
+  ::MSG msg;
+  while (::GetMessage(&msg, nullptr, 0, 0)) {
+    ::TranslateMessage(&msg);
+    ::DispatchMessage(&msg);
+  }
+
+  ::CoUninitialize();
+  return EXIT_SUCCESS;
+}
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/runner/resource.h b/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/runner/resource.h
new file mode 100644
index 0000000..66a65d1
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/runner/resource.h
@@ -0,0 +1,16 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by Runner.rc
+//
+#define IDI_APP_ICON                    101
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        102
+#define _APS_NEXT_COMMAND_VALUE         40001
+#define _APS_NEXT_CONTROL_VALUE         1001
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/runner/resources/app_icon.ico b/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/runner/resources/app_icon.ico
new file mode 100644
index 0000000..c04e20c
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/runner/resources/app_icon.ico
Binary files differ
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/runner/runner.exe.manifest b/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/runner/runner.exe.manifest
new file mode 100644
index 0000000..c977c4a
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/runner/runner.exe.manifest
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+  <application xmlns="urn:schemas-microsoft-com:asm.v3">
+    <windowsSettings>
+      <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
+    </windowsSettings>
+  </application>
+  <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
+    <application>
+      <!-- Windows 10 -->
+      <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
+      <!-- Windows 8.1 -->
+      <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
+      <!-- Windows 8 -->
+      <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
+      <!-- Windows 7 -->
+      <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
+    </application>
+  </compatibility>
+</assembly>
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/runner/utils.cpp b/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/runner/utils.cpp
new file mode 100644
index 0000000..f5bf9fa
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/runner/utils.cpp
@@ -0,0 +1,64 @@
+#include "utils.h"
+
+#include <flutter_windows.h>
+#include <io.h>
+#include <stdio.h>
+#include <windows.h>
+
+#include <iostream>
+
+void CreateAndAttachConsole() {
+  if (::AllocConsole()) {
+    FILE *unused;
+    if (freopen_s(&unused, "CONOUT$", "w", stdout)) {
+      _dup2(_fileno(stdout), 1);
+    }
+    if (freopen_s(&unused, "CONOUT$", "w", stderr)) {
+      _dup2(_fileno(stdout), 2);
+    }
+    std::ios::sync_with_stdio();
+    FlutterDesktopResyncOutputStreams();
+  }
+}
+
+std::vector<std::string> GetCommandLineArguments() {
+  // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use.
+  int argc;
+  wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc);
+  if (argv == nullptr) {
+    return std::vector<std::string>();
+  }
+
+  std::vector<std::string> command_line_arguments;
+
+  // Skip the first argument as it's the binary name.
+  for (int i = 1; i < argc; i++) {
+    command_line_arguments.push_back(Utf8FromUtf16(argv[i]));
+  }
+
+  ::LocalFree(argv);
+
+  return command_line_arguments;
+}
+
+std::string Utf8FromUtf16(const wchar_t* utf16_string) {
+  if (utf16_string == nullptr) {
+    return std::string();
+  }
+  int target_length = ::WideCharToMultiByte(
+      CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string,
+      -1, nullptr, 0, nullptr, nullptr);
+  std::string utf8_string;
+  if (target_length == 0 || target_length > utf8_string.max_size()) {
+    return utf8_string;
+  }
+  utf8_string.resize(target_length);
+  int converted_length = ::WideCharToMultiByte(
+      CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string,
+      -1, utf8_string.data(),
+      target_length, nullptr, nullptr);
+  if (converted_length == 0) {
+    return std::string();
+  }
+  return utf8_string;
+}
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/runner/utils.h b/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/runner/utils.h
new file mode 100644
index 0000000..3879d54
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/runner/utils.h
@@ -0,0 +1,19 @@
+#ifndef RUNNER_UTILS_H_
+#define RUNNER_UTILS_H_
+
+#include <string>
+#include <vector>
+
+// Creates a console for the process, and redirects stdout and stderr to
+// it for both the runner and the Flutter library.
+void CreateAndAttachConsole();
+
+// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string
+// encoded in UTF-8. Returns an empty std::string on failure.
+std::string Utf8FromUtf16(const wchar_t* utf16_string);
+
+// Gets the command line arguments passed in as a std::vector<std::string>,
+// encoded in UTF-8. Returns an empty std::vector<std::string> on failure.
+std::vector<std::string> GetCommandLineArguments();
+
+#endif  // RUNNER_UTILS_H_
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/runner/win32_window.cpp b/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/runner/win32_window.cpp
new file mode 100644
index 0000000..c10f08d
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/runner/win32_window.cpp
@@ -0,0 +1,245 @@
+#include "win32_window.h"
+
+#include <flutter_windows.h>
+
+#include "resource.h"
+
+namespace {
+
+constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW";
+
+// The number of Win32Window objects that currently exist.
+static int g_active_window_count = 0;
+
+using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd);
+
+// Scale helper to convert logical scaler values to physical using passed in
+// scale factor
+int Scale(int source, double scale_factor) {
+  return static_cast<int>(source * scale_factor);
+}
+
+// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module.
+// This API is only needed for PerMonitor V1 awareness mode.
+void EnableFullDpiSupportIfAvailable(HWND hwnd) {
+  HMODULE user32_module = LoadLibraryA("User32.dll");
+  if (!user32_module) {
+    return;
+  }
+  auto enable_non_client_dpi_scaling =
+      reinterpret_cast<EnableNonClientDpiScaling*>(
+          GetProcAddress(user32_module, "EnableNonClientDpiScaling"));
+  if (enable_non_client_dpi_scaling != nullptr) {
+    enable_non_client_dpi_scaling(hwnd);
+    FreeLibrary(user32_module);
+  }
+}
+
+}  // namespace
+
+// Manages the Win32Window's window class registration.
+class WindowClassRegistrar {
+ public:
+  ~WindowClassRegistrar() = default;
+
+  // Returns the singleton registar instance.
+  static WindowClassRegistrar* GetInstance() {
+    if (!instance_) {
+      instance_ = new WindowClassRegistrar();
+    }
+    return instance_;
+  }
+
+  // Returns the name of the window class, registering the class if it hasn't
+  // previously been registered.
+  const wchar_t* GetWindowClass();
+
+  // Unregisters the window class. Should only be called if there are no
+  // instances of the window.
+  void UnregisterWindowClass();
+
+ private:
+  WindowClassRegistrar() = default;
+
+  static WindowClassRegistrar* instance_;
+
+  bool class_registered_ = false;
+};
+
+WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr;
+
+const wchar_t* WindowClassRegistrar::GetWindowClass() {
+  if (!class_registered_) {
+    WNDCLASS window_class{};
+    window_class.hCursor = LoadCursor(nullptr, IDC_ARROW);
+    window_class.lpszClassName = kWindowClassName;
+    window_class.style = CS_HREDRAW | CS_VREDRAW;
+    window_class.cbClsExtra = 0;
+    window_class.cbWndExtra = 0;
+    window_class.hInstance = GetModuleHandle(nullptr);
+    window_class.hIcon =
+        LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON));
+    window_class.hbrBackground = 0;
+    window_class.lpszMenuName = nullptr;
+    window_class.lpfnWndProc = Win32Window::WndProc;
+    RegisterClass(&window_class);
+    class_registered_ = true;
+  }
+  return kWindowClassName;
+}
+
+void WindowClassRegistrar::UnregisterWindowClass() {
+  UnregisterClass(kWindowClassName, nullptr);
+  class_registered_ = false;
+}
+
+Win32Window::Win32Window() {
+  ++g_active_window_count;
+}
+
+Win32Window::~Win32Window() {
+  --g_active_window_count;
+  Destroy();
+}
+
+bool Win32Window::CreateAndShow(const std::wstring& title,
+                                const Point& origin,
+                                const Size& size) {
+  Destroy();
+
+  const wchar_t* window_class =
+      WindowClassRegistrar::GetInstance()->GetWindowClass();
+
+  const POINT target_point = {static_cast<LONG>(origin.x),
+                              static_cast<LONG>(origin.y)};
+  HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST);
+  UINT dpi = FlutterDesktopGetDpiForMonitor(monitor);
+  double scale_factor = dpi / 96.0;
+
+  HWND window = CreateWindow(
+      window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE,
+      Scale(origin.x, scale_factor), Scale(origin.y, scale_factor),
+      Scale(size.width, scale_factor), Scale(size.height, scale_factor),
+      nullptr, nullptr, GetModuleHandle(nullptr), this);
+
+  if (!window) {
+    return false;
+  }
+
+  return OnCreate();
+}
+
+// static
+LRESULT CALLBACK Win32Window::WndProc(HWND const window,
+                                      UINT const message,
+                                      WPARAM const wparam,
+                                      LPARAM const lparam) noexcept {
+  if (message == WM_NCCREATE) {
+    auto window_struct = reinterpret_cast<CREATESTRUCT*>(lparam);
+    SetWindowLongPtr(window, GWLP_USERDATA,
+                     reinterpret_cast<LONG_PTR>(window_struct->lpCreateParams));
+
+    auto that = static_cast<Win32Window*>(window_struct->lpCreateParams);
+    EnableFullDpiSupportIfAvailable(window);
+    that->window_handle_ = window;
+  } else if (Win32Window* that = GetThisFromHandle(window)) {
+    return that->MessageHandler(window, message, wparam, lparam);
+  }
+
+  return DefWindowProc(window, message, wparam, lparam);
+}
+
+LRESULT
+Win32Window::MessageHandler(HWND hwnd,
+                            UINT const message,
+                            WPARAM const wparam,
+                            LPARAM const lparam) noexcept {
+  switch (message) {
+    case WM_DESTROY:
+      window_handle_ = nullptr;
+      Destroy();
+      if (quit_on_close_) {
+        PostQuitMessage(0);
+      }
+      return 0;
+
+    case WM_DPICHANGED: {
+      auto newRectSize = reinterpret_cast<RECT*>(lparam);
+      LONG newWidth = newRectSize->right - newRectSize->left;
+      LONG newHeight = newRectSize->bottom - newRectSize->top;
+
+      SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth,
+                   newHeight, SWP_NOZORDER | SWP_NOACTIVATE);
+
+      return 0;
+    }
+    case WM_SIZE: {
+      RECT rect = GetClientArea();
+      if (child_content_ != nullptr) {
+        // Size and position the child window.
+        MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left,
+                   rect.bottom - rect.top, TRUE);
+      }
+      return 0;
+    }
+
+    case WM_ACTIVATE:
+      if (child_content_ != nullptr) {
+        SetFocus(child_content_);
+      }
+      return 0;
+  }
+
+  return DefWindowProc(window_handle_, message, wparam, lparam);
+}
+
+void Win32Window::Destroy() {
+  OnDestroy();
+
+  if (window_handle_) {
+    DestroyWindow(window_handle_);
+    window_handle_ = nullptr;
+  }
+  if (g_active_window_count == 0) {
+    WindowClassRegistrar::GetInstance()->UnregisterWindowClass();
+  }
+}
+
+Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept {
+  return reinterpret_cast<Win32Window*>(
+      GetWindowLongPtr(window, GWLP_USERDATA));
+}
+
+void Win32Window::SetChildContent(HWND content) {
+  child_content_ = content;
+  SetParent(content, window_handle_);
+  RECT frame = GetClientArea();
+
+  MoveWindow(content, frame.left, frame.top, frame.right - frame.left,
+             frame.bottom - frame.top, true);
+
+  SetFocus(child_content_);
+}
+
+RECT Win32Window::GetClientArea() {
+  RECT frame;
+  GetClientRect(window_handle_, &frame);
+  return frame;
+}
+
+HWND Win32Window::GetHandle() {
+  return window_handle_;
+}
+
+void Win32Window::SetQuitOnClose(bool quit_on_close) {
+  quit_on_close_ = quit_on_close;
+}
+
+bool Win32Window::OnCreate() {
+  // No-op; provided for subclasses.
+  return true;
+}
+
+void Win32Window::OnDestroy() {
+  // No-op; provided for subclasses.
+}
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/runner/win32_window.h b/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/runner/win32_window.h
new file mode 100644
index 0000000..17ba431
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/example/windows/runner/win32_window.h
@@ -0,0 +1,98 @@
+#ifndef RUNNER_WIN32_WINDOW_H_
+#define RUNNER_WIN32_WINDOW_H_
+
+#include <windows.h>
+
+#include <functional>
+#include <memory>
+#include <string>
+
+// A class abstraction for a high DPI-aware Win32 Window. Intended to be
+// inherited from by classes that wish to specialize with custom
+// rendering and input handling
+class Win32Window {
+ public:
+  struct Point {
+    unsigned int x;
+    unsigned int y;
+    Point(unsigned int x, unsigned int y) : x(x), y(y) {}
+  };
+
+  struct Size {
+    unsigned int width;
+    unsigned int height;
+    Size(unsigned int width, unsigned int height)
+        : width(width), height(height) {}
+  };
+
+  Win32Window();
+  virtual ~Win32Window();
+
+  // Creates and shows a win32 window with |title| and position and size using
+  // |origin| and |size|. New windows are created on the default monitor. Window
+  // sizes are specified to the OS in physical pixels, hence to ensure a
+  // consistent size to will treat the width height passed in to this function
+  // as logical pixels and scale to appropriate for the default monitor. Returns
+  // true if the window was created successfully.
+  bool CreateAndShow(const std::wstring& title,
+                     const Point& origin,
+                     const Size& size);
+
+  // Release OS resources associated with window.
+  void Destroy();
+
+  // Inserts |content| into the window tree.
+  void SetChildContent(HWND content);
+
+  // Returns the backing Window handle to enable clients to set icon and other
+  // window properties. Returns nullptr if the window has been destroyed.
+  HWND GetHandle();
+
+  // If true, closing this window will quit the application.
+  void SetQuitOnClose(bool quit_on_close);
+
+  // Return a RECT representing the bounds of the current client area.
+  RECT GetClientArea();
+
+ protected:
+  // Processes and route salient window messages for mouse handling,
+  // size change and DPI. Delegates handling of these to member overloads that
+  // inheriting classes can handle.
+  virtual LRESULT MessageHandler(HWND window,
+                                 UINT const message,
+                                 WPARAM const wparam,
+                                 LPARAM const lparam) noexcept;
+
+  // Called when CreateAndShow is called, allowing subclass window-related
+  // setup. Subclasses should return false if setup fails.
+  virtual bool OnCreate();
+
+  // Called when Destroy is called.
+  virtual void OnDestroy();
+
+ private:
+  friend class WindowClassRegistrar;
+
+  // OS callback called by message pump. Handles the WM_NCCREATE message which
+  // is passed when the non-client area is being created and enables automatic
+  // non-client DPI scaling so that the non-client area automatically
+  // responsponds to changes in DPI. All other messages are handled by
+  // MessageHandler.
+  static LRESULT CALLBACK WndProc(HWND const window,
+                                  UINT const message,
+                                  WPARAM const wparam,
+                                  LPARAM const lparam) noexcept;
+
+  // Retrieves a class instance pointer for |window|
+  static Win32Window* GetThisFromHandle(HWND const window) noexcept;
+
+  bool quit_on_close_ = false;
+
+  // window handle for top level window.
+  HWND window_handle_ = nullptr;
+
+  // window handle for hosted content.
+  HWND child_content_ = nullptr;
+};
+
+#endif  // RUNNER_WIN32_WINDOW_H_
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/jnigen.yaml b/pkgs/jni_gen/examples/pdfbox_plugin/jnigen.yaml
new file mode 100644
index 0000000..1e98f4c
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/jnigen.yaml
@@ -0,0 +1,64 @@
+## Name of the generated library, this is required and used as the name of
+## shared library which contains C bindings
+library_name: pdfbox_plugin
+
+## String to be pasted verbatim into generated bindings
+preamble: |
+  // 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.
+
+## Root for generated C bindings.
+c_root: 'src/'
+
+## C files can be stored in a different sub-directory inside c_root.
+##
+## We have a guideline to keep all generated code in third_party/ since original
+## project's license applies to generated code. So we specify third_party/ as
+## c_subdir while keeping generated CMakeLists.txt in src/.
+c_subdir: 'third_party/'
+
+## Root for generated Dart bindings.
+dart_root: 'lib/third_party/'
+
+## Classes / packages for which bindings need to be generated.
+classes:
+  - 'org.apache.pdfbox.pdmodel.PDDocument'
+  - 'org.apache.pdfbox.pdmodel.PDDocumentInformation'
+  - 'org.apache.pdfbox.text.PDFTextStripper'
+
+## Dependencies to be downloaded using Maven (Invokes `mvn` command). These
+## dependencies are always downloaded along with their transitive dependencies.
+##
+## Dependencies should be specified using groupID:artifactID:version format
+## The downloaded dependencies are automatically added to classpath of the
+## Java API scanning process. There's no need to specify these again in
+## sourcepath and classpath.
+##
+## Note that when maven based tooling is used, the first run often has to fetch
+## all the dependencies and might take some time. However, maven caches most
+## artifacts in local repository, thus subsequent runs will be faster.
+maven_downloads:
+  ## For these dependencies, both source and JARs are downloaded.
+  source_deps:
+    - 'org.apache.pdfbox:pdfbox:2.0.26'
+  ## Runtime dependencies for which bindings aren't generated directly.
+  ## Only JARs are downloaded.
+  jar_only_deps:
+    - 'org.bouncycastle:bcmail-jdk15on:1.70'
+    - 'org.bouncycastle:bcprov-jdk15on:1.70'
+
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/jnigen_full.yaml b/pkgs/jni_gen/examples/pdfbox_plugin/jnigen_full.yaml
new file mode 100644
index 0000000..2652756
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/jnigen_full.yaml
@@ -0,0 +1,63 @@
+## Name of the generated library, this is required and used as the name of
+## shared library which contains C bindings
+library_name: pdfbox_plugin
+
+## String to be pasted verbatim into generated bindings
+preamble: |
+  // 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.
+
+## Root for generated C bindings.
+c_root: 'src/'
+
+## C files can be stored in a different sub-directory inside c_root.
+##
+## We have a guideline to keep all generated code in third_party/ since original
+## project's license applies to generated code. So we specify third_party/ as
+## c_subdir while keeping generated CMakeLists.txt in src/.
+c_subdir: 'third_party/'
+
+## Root for generated Dart bindings.
+dart_root: 'lib/third_party/'
+
+## Classes / packages for which bindings need to be generated.
+classes:
+  - 'org.apache.pdfbox.pdmodel'
+  - 'org.apache.pdfbox.text'
+
+## Dependencies to be downloaded using Maven (Invokes `mvn` command). These
+## dependencies are always downloaded along with their transitive dependencies.
+##
+## Dependencies should be specified using groupID:artifactID:version format
+## The downloaded dependencies are automatically added to classpath of the
+## Java API scanning process. There's no need to specify these again in
+## sourcepath and classpath.
+##
+## Note that when maven based tooling is used, the first run often has to fetch
+## all the dependencies and might take some time. However, maven caches most
+## artifacts in local repository, thus subsequent runs will be faster.
+maven_downloads:
+  ## For these dependencies, both source and JARs are downloaded.
+  source_deps:
+    - 'org.apache.pdfbox:pdfbox:2.0.26'
+  ## Runtime dependencies for which bindings aren't generated directly.
+  ## Only JARs are downloaded.
+  jar_only_deps:
+    - 'org.bouncycastle:bcmail-jdk15on:1.70'
+    - 'org.bouncycastle:bcprov-jdk15on:1.70'
+
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/lib/third_party/init.dart b/pkgs/jni_gen/examples/pdfbox_plugin/lib/third_party/init.dart
new file mode 100644
index 0000000..4e88081
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/lib/third_party/init.dart
@@ -0,0 +1,5 @@
+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/jni_gen/examples/pdfbox_plugin/lib/third_party/org/apache/pdfbox/pdmodel.dart b/pkgs/jni_gen/examples/pdfbox_plugin/lib/third_party/org/apache/pdfbox/pdmodel.dart
new file mode 100644
index 0000000..2eeee30
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/lib/third_party/org/apache/pdfbox/pdmodel.dart
@@ -0,0 +1,2196 @@
+// 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.
+
+// Autogenerated by jni_gen. DO NOT EDIT!
+
+// ignore_for_file: camel_case_types
+// ignore_for_file: non_constant_identifier_names
+// ignore_for_file: constant_identifier_names
+// ignore_for_file: annotate_overrides
+// ignore_for_file: no_leading_underscores_for_local_identifiers
+// ignore_for_file: unused_element
+
+import "dart:ffi" as ffi;
+
+import "package:jni/jni.dart" as jni;
+
+import "../../../init.dart" show jlookup;
+
+/// 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 {
+  PDDocument.fromRef(ffi.Pointer<ffi.Void> ref) : super.fromRef(ref);
+
+  static final _get_RESERVE_BYTE_RANGE =
+      jlookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function()>>(
+              "get_org_apache_pdfbox_pdmodel_PDDocument_RESERVE_BYTE_RANGE")
+          .asFunction<ffi.Pointer<ffi.Void> Function()>();
+
+  /// from: private static final int[] RESERVE_BYTE_RANGE
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// For signing: large reserve byte range used as placeholder in the saved PDF until the actual
+  /// length of the PDF is known. You'll need to fetch (with
+  /// PDSignature\#getByteRange() ) and reassign this yourself (with
+  /// 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 final _get_LOG =
+      jlookup<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 final _get_document = jlookup<
+          ffi.NativeFunction<
+              ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>>("get_org_apache_pdfbox_pdmodel_PDDocument_document")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>();
+
+  /// 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));
+
+  static final _get_documentInformation = jlookup<
+          ffi.NativeFunction<
+              ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>>("get_org_apache_pdfbox_pdmodel_PDDocument_documentInformation")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>();
+
+  /// from: private org.apache.pdfbox.pdmodel.PDDocumentInformation documentInformation
+  /// 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<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "set_org_apache_pdfbox_pdmodel_PDDocument_documentInformation")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: private org.apache.pdfbox.pdmodel.PDDocumentInformation documentInformation
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  set documentInformation(PDDocumentInformation value) =>
+      _set_documentInformation(reference, value.reference);
+
+  static final _get_documentCatalog = jlookup<
+          ffi.NativeFunction<
+              ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>>("get_org_apache_pdfbox_pdmodel_PDDocument_documentCatalog")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>();
+
+  /// 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<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "set_org_apache_pdfbox_pdmodel_PDDocument_documentCatalog")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// 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(reference, value.reference);
+
+  static final _get_encryption = jlookup<
+          ffi.NativeFunction<
+              ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>>("get_org_apache_pdfbox_pdmodel_PDDocument_encryption")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>();
+
+  /// 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<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "set_org_apache_pdfbox_pdmodel_PDDocument_encryption")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// 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(reference, value.reference);
+
+  static final _get_allSecurityToBeRemoved = jlookup<
+          ffi.NativeFunction<
+              ffi.Uint8 Function(
+    ffi.Pointer<ffi.Void>,
+  )>>("get_org_apache_pdfbox_pdmodel_PDDocument_allSecurityToBeRemoved")
+      .asFunction<
+          int Function(
+    ffi.Pointer<ffi.Void>,
+  )>();
+
+  /// from: private boolean allSecurityToBeRemoved
+  bool get allSecurityToBeRemoved =>
+      _get_allSecurityToBeRemoved(reference) != 0;
+  static final _set_allSecurityToBeRemoved = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Uint8)>>(
+          "set_org_apache_pdfbox_pdmodel_PDDocument_allSecurityToBeRemoved")
+      .asFunction<void Function(ffi.Pointer<ffi.Void>, int)>();
+
+  /// from: private boolean allSecurityToBeRemoved
+  set allSecurityToBeRemoved(bool value) =>
+      _set_allSecurityToBeRemoved(reference, value ? 1 : 0);
+
+  static final _get_documentId = jlookup<
+          ffi.NativeFunction<
+              ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>>("get_org_apache_pdfbox_pdmodel_PDDocument_documentId")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>();
+
+  /// 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<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "set_org_apache_pdfbox_pdmodel_PDDocument_documentId")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// 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(reference, value.reference);
+
+  static final _get_pdfSource = jlookup<
+          ffi.NativeFunction<
+              ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>>("get_org_apache_pdfbox_pdmodel_PDDocument_pdfSource")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>();
+
+  /// 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));
+
+  static final _get_accessPermission = jlookup<
+          ffi.NativeFunction<
+              ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>>("get_org_apache_pdfbox_pdmodel_PDDocument_accessPermission")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>();
+
+  /// 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<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "set_org_apache_pdfbox_pdmodel_PDDocument_accessPermission")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// 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(reference, value.reference);
+
+  static final _get_fontsToSubset = jlookup<
+          ffi.NativeFunction<
+              ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>>("get_org_apache_pdfbox_pdmodel_PDDocument_fontsToSubset")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>();
+
+  /// 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));
+
+  static final _get_fontsToClose = jlookup<
+          ffi.NativeFunction<
+              ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>>("get_org_apache_pdfbox_pdmodel_PDDocument_fontsToClose")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>();
+
+  /// 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));
+
+  static final _get_signInterface = jlookup<
+          ffi.NativeFunction<
+              ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>>("get_org_apache_pdfbox_pdmodel_PDDocument_signInterface")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>();
+
+  /// 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<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "set_org_apache_pdfbox_pdmodel_PDDocument_signInterface")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// 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(reference, value.reference);
+
+  static final _get_signingSupport = jlookup<
+          ffi.NativeFunction<
+              ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>>("get_org_apache_pdfbox_pdmodel_PDDocument_signingSupport")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>();
+
+  /// 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<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "set_org_apache_pdfbox_pdmodel_PDDocument_signingSupport")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// 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(reference, value.reference);
+
+  static final _get_resourceCache = jlookup<
+          ffi.NativeFunction<
+              ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>>("get_org_apache_pdfbox_pdmodel_PDDocument_resourceCache")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>();
+
+  /// 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<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "set_org_apache_pdfbox_pdmodel_PDDocument_resourceCache")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// 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(reference, value.reference);
+
+  static final _get_signatureAdded = jlookup<
+          ffi.NativeFunction<
+              ffi.Uint8 Function(
+    ffi.Pointer<ffi.Void>,
+  )>>("get_org_apache_pdfbox_pdmodel_PDDocument_signatureAdded")
+      .asFunction<
+          int Function(
+    ffi.Pointer<ffi.Void>,
+  )>();
+
+  /// from: private boolean signatureAdded
+  bool get signatureAdded => _get_signatureAdded(reference) != 0;
+  static final _set_signatureAdded = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Uint8)>>(
+          "set_org_apache_pdfbox_pdmodel_PDDocument_signatureAdded")
+      .asFunction<void Function(ffi.Pointer<ffi.Void>, int)>();
+
+  /// from: private boolean signatureAdded
+  set signatureAdded(bool value) =>
+      _set_signatureAdded(reference, value ? 1 : 0);
+
+  static final _ctor =
+      jlookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function()>>(
+              "org_apache_pdfbox_pdmodel_PDDocument_ctor")
+          .asFunction<ffi.Pointer<ffi.Void> Function()>();
+
+  /// from: public void <init>()
+  ///
+  /// Creates an empty PDF document.
+  /// You need to add at least one page for the document to be valid.
+  PDDocument() : super.fromRef(_ctor());
+
+  static final _ctor1 = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_ctor1")
+      .asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: public void <init>(org.apache.pdfbox.io.MemoryUsageSetting memUsageSetting)
+  ///
+  /// 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));
+
+  static final _ctor2 = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_ctor2")
+      .asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: public void <init>(org.apache.pdfbox.cos.COSDocument doc)
+  ///
+  /// 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));
+
+  static final _ctor3 = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_ctor3")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: public void <init>(org.apache.pdfbox.cos.COSDocument doc, org.apache.pdfbox.io.RandomAccessRead source)
+  ///
+  /// 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));
+
+  static final _ctor4 = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_ctor4")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>,
+              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: public void <init>(org.apache.pdfbox.cos.COSDocument doc, org.apache.pdfbox.io.RandomAccessRead source, org.apache.pdfbox.pdmodel.encryption.AccessPermission permission)
+  ///
+  /// 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
+  ///@param permission he access permissions of the pdf
+  PDDocument.ctor4(
+      jni.JlObject doc, jni.JlObject source, jni.JlObject permission)
+      : super.fromRef(
+            _ctor4(doc.reference, source.reference, permission.reference));
+
+  static final _addPage = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_addPage")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: public void addPage(org.apache.pdfbox.pdmodel.PDPage page)
+  ///
+  /// 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);
+
+  static final _addSignature = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_addSignature")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: public void addSignature(org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature sigObject)
+  ///
+  /// Add parameters of signature to be created externally using default signature options. See
+  /// \#saveIncrementalForExternalSigning(OutputStream) method description on external
+  /// signature creation scenario details.
+  ///
+  /// Only one signature may be added in a document. To sign several times,
+  /// load document, add signature, save incremental and close again.
+  ///@param sigObject is the PDSignatureField model
+  ///@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);
+
+  static final _addSignature1 = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_addSignature1")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+              ffi.Pointer<ffi.Void>)>();
+
+  /// from: public void addSignature(org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature sigObject, org.apache.pdfbox.pdmodel.interactive.digitalsignature.SignatureOptions options)
+  ///
+  /// Add parameters of signature to be created externally. See
+  /// \#saveIncrementalForExternalSigning(OutputStream) method description on external
+  /// signature creation scenario details.
+  ///
+  /// Only one signature may be added in a document. To sign several times,
+  /// load document, add signature, save incremental and close again.
+  ///@param sigObject is the PDSignatureField model
+  ///@param options signature options
+  ///@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);
+
+  static final _addSignature2 = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_addSignature2")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+              ffi.Pointer<ffi.Void>)>();
+
+  /// from: public void addSignature(org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature sigObject, org.apache.pdfbox.pdmodel.interactive.digitalsignature.SignatureInterface signatureInterface)
+  ///
+  /// Add a signature to be created using the instance of given interface.
+  ///
+  /// Only one signature may be added in a document. To sign several times,
+  /// load document, add signature, save incremental and close again.
+  ///@param sigObject is the PDSignatureField model
+  ///@param signatureInterface is an interface whose implementation provides
+  /// signing capabilities. Can be null if external signing if used.
+  ///@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);
+
+  static final _addSignature3 = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_addSignature3")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: public void addSignature(org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature sigObject, org.apache.pdfbox.pdmodel.interactive.digitalsignature.SignatureInterface signatureInterface, org.apache.pdfbox.pdmodel.interactive.digitalsignature.SignatureOptions options)
+  ///
+  /// This will add a signature to the document. If the 0-based page number in the options
+  /// parameter is smaller than 0 or larger than max, the nearest valid page number will be used
+  /// (i.e. 0 or max) and no exception will be thrown.
+  ///
+  /// Only one signature may be added in a document. To sign several times,
+  /// load document, add signature, save incremental and close again.
+  ///@param sigObject is the PDSignatureField model
+  ///@param signatureInterface is an interface whose implementation provides
+  /// signing capabilities. Can be null if external signing if used.
+  ///@param options signature options
+  ///@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);
+
+  static final _findSignatureField = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_findSignatureField")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>,
+              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: private org.apache.pdfbox.pdmodel.interactive.form.PDSignatureField findSignatureField(java.util.Iterator<org.apache.pdfbox.pdmodel.interactive.form.PDField> fieldIterator, org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature sigObject)
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// Search acroform fields for signature field with specific signature dictionary.
+  ///@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));
+
+  static final _checkSignatureField = jlookup<
+              ffi.NativeFunction<
+                  ffi.Uint8 Function(ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_checkSignatureField")
+      .asFunction<
+          int Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+              ffi.Pointer<ffi.Void>)>();
+
+  /// from: private boolean checkSignatureField(java.util.Iterator<org.apache.pdfbox.pdmodel.interactive.form.PDField> fieldIterator, org.apache.pdfbox.pdmodel.interactive.form.PDSignatureField signatureField)
+  ///
+  /// Check if the field already exists in the field list.
+  ///@param fieldIterator iterator on all fields.
+  ///@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;
+
+  static final _checkSignatureAnnotation = jlookup<
+              ffi.NativeFunction<
+                  ffi.Uint8 Function(ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_checkSignatureAnnotation")
+      .asFunction<
+          int Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+              ffi.Pointer<ffi.Void>)>();
+
+  /// from: private boolean checkSignatureAnnotation(java.util.List<org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotation> annotations, org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationWidget widget)
+  ///
+  /// Check if the widget already exists in the annotation list
+  ///@param annotations the list of PDAnnotation fields.
+  ///@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;
+
+  static final _prepareVisibleSignature = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_prepareVisibleSignature")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+              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);
+
+  static final _assignSignatureRectangle = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_assignSignatureRectangle")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+              ffi.Pointer<ffi.Void>)>();
+
+  /// 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);
+
+  static final _assignAppearanceDictionary = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_assignAppearanceDictionary")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+              ffi.Pointer<ffi.Void>)>();
+
+  /// 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);
+
+  static final _assignAcroFormDefaultResource = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_assignAcroFormDefaultResource")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+              ffi.Pointer<ffi.Void>)>();
+
+  /// 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);
+
+  static final _prepareNonVisibleSignature = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_prepareNonVisibleSignature")
+      .asFunction<
+          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);
+
+  static final _addSignatureField = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_addSignatureField")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: public void addSignatureField(java.util.List<org.apache.pdfbox.pdmodel.interactive.form.PDSignatureField> sigFields, org.apache.pdfbox.pdmodel.interactive.digitalsignature.SignatureInterface signatureInterface, org.apache.pdfbox.pdmodel.interactive.digitalsignature.SignatureOptions options)
+  ///
+  /// This will add a list of signature fields to the document.
+  ///@param sigFields are the PDSignatureFields that should be added to the document
+  ///@param signatureInterface is an interface whose implementation provides
+  /// signing capabilities. Can be null if external signing if used.
+  ///@param options signature options
+  ///@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);
+
+  static final _removePage = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_removePage")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: public void removePage(org.apache.pdfbox.pdmodel.PDPage page)
+  ///
+  /// Remove the page from the document.
+  ///@param page The page to remove from the document.
+  void removePage(jni.JlObject page) => _removePage(reference, page.reference);
+
+  static final _removePage1 = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Int32)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_removePage1")
+      .asFunction<void Function(ffi.Pointer<ffi.Void>, int)>();
+
+  /// from: public void removePage(int pageNumber)
+  ///
+  /// Remove the page from the document.
+  ///@param pageNumber 0 based index to page number.
+  void removePage1(int pageNumber) => _removePage1(reference, pageNumber);
+
+  static final _importPage = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_importPage")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: public org.apache.pdfbox.pdmodel.PDPage importPage(org.apache.pdfbox.pdmodel.PDPage page)
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// This will import and copy the contents from another location. Currently the content stream is
+  /// stored in a scratch file. The scratch file is associated with the document. If you are adding
+  /// a page to this document from another document and want to copy the contents to this
+  /// document's scratch file then use this method otherwise just use the \#addPage addPage()
+  /// method.
+  ///
+  /// Unlike \#addPage addPage(), this method creates a new PDPage object. If your page has
+  /// annotations, and if these link to pages not in the target document, then the target document
+  /// might become huge. What you need to do is to delete page references of such annotations. See
+  /// <a href="http://stackoverflow.com/a/35477351/535646">here</a> for how to do this.
+  ///
+  /// Inherited (global) resources are ignored because these can contain resources not needed for
+  /// this page which could bloat your document, see
+  /// <a href="https://issues.apache.org/jira/browse/PDFBOX-28">PDFBOX-28</a> and related issues.
+  /// If you need them, call <code>importedPage.setResources(page.getResources());</code>
+  ///
+  /// This method should only be used to import a page from a loaded document, not from a generated
+  /// document because these can contain unfinished parts, e.g. font subsetting information.
+  ///@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));
+
+  static final _getDocument = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_getDocument")
+      .asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: public org.apache.pdfbox.cos.COSDocument getDocument()
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// 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));
+
+  static final _getDocumentInformation = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_getDocumentInformation")
+      .asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: public org.apache.pdfbox.pdmodel.PDDocumentInformation getDocumentInformation()
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// This will get the document info dictionary. If it doesn't exist, an empty document info
+  /// dictionary is created in the document trailer.
+  ///
+  /// In PDF 2.0 this is deprecated except for two entries, /CreationDate and /ModDate. For any other
+  /// 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));
+
+  static final _setDocumentInformation = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_setDocumentInformation")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: public void setDocumentInformation(org.apache.pdfbox.pdmodel.PDDocumentInformation info)
+  ///
+  /// This will set the document information for this document.
+  ///
+  /// In PDF 2.0 this is deprecated except for two entries, /CreationDate and /ModDate. For any other
+  /// 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);
+
+  static final _getDocumentCatalog = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_getDocumentCatalog")
+      .asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: public org.apache.pdfbox.pdmodel.PDDocumentCatalog getDocumentCatalog()
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// 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));
+
+  static final _isEncrypted =
+      jlookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
+              "org_apache_pdfbox_pdmodel_PDDocument_isEncrypted")
+          .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: public boolean isEncrypted()
+  ///
+  /// This will tell if this document is encrypted or not.
+  ///@return true If this document is encrypted.
+  bool isEncrypted() => _isEncrypted(reference) != 0;
+
+  static final _getEncryption = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_getEncryption")
+      .asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: public org.apache.pdfbox.pdmodel.encryption.PDEncryption getEncryption()
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// This will get the encryption dictionary for this document. This will still return the parameters if the document
+  /// was decrypted. As the encryption architecture in PDF documents is pluggable this returns an abstract class,
+  /// 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));
+
+  static final _setEncryptionDictionary = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_setEncryptionDictionary")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: public void setEncryptionDictionary(org.apache.pdfbox.pdmodel.encryption.PDEncryption encryption)
+  ///
+  /// 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);
+
+  static final _getLastSignatureDictionary = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_getLastSignatureDictionary")
+      .asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: public org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature getLastSignatureDictionary()
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// This will return the last signature from the field tree. Note that this may not be the
+  /// 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));
+
+  static final _getSignatureFields = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_getSignatureFields")
+      .asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: public java.util.List<org.apache.pdfbox.pdmodel.interactive.form.PDSignatureField> getSignatureFields()
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// 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));
+
+  static final _getSignatureDictionaries = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_getSignatureDictionaries")
+      .asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: public java.util.List<org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature> getSignatureDictionaries()
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// 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));
+
+  static final _registerTrueTypeFontForClosing = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_registerTrueTypeFontForClosing")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: public void registerTrueTypeFontForClosing(org.apache.fontbox.ttf.TrueTypeFont ttf)
+  ///
+  /// For internal PDFBox use when creating PDF documents: register a TrueTypeFont to make sure it
+  /// 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);
+
+  static final _getFontsToSubset = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_getFontsToSubset")
+      .asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: java.util.Set<org.apache.pdfbox.pdmodel.font.PDFont> getFontsToSubset()
+  /// 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));
+
+  static final _load = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_load")
+      .asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: static public org.apache.pdfbox.pdmodel.PDDocument load(java.io.File file)
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// Parses a PDF. Unrestricted main memory will be used for buffering PDF streams.
+  ///@param file file to be loaded
+  ///@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 final _load1 = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_load1")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: static public org.apache.pdfbox.pdmodel.PDDocument load(java.io.File file, org.apache.pdfbox.io.MemoryUsageSetting memUsageSetting)
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// Parses a PDF.
+  ///@param file file to be loaded
+  ///@param memUsageSetting defines how memory is used for buffering PDF streams
+  ///@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 final _load2 = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_load2")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: static public org.apache.pdfbox.pdmodel.PDDocument load(java.io.File file, java.lang.String password)
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// Parses a PDF. Unrestricted main memory will be used for buffering PDF streams.
+  ///@param file file to be loaded
+  ///@param password password to be used for decryption
+  ///@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 final _load3 = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_load3")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>,
+              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: static public org.apache.pdfbox.pdmodel.PDDocument load(java.io.File file, java.lang.String password, org.apache.pdfbox.io.MemoryUsageSetting memUsageSetting)
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// Parses a PDF.
+  ///@param file file to be loaded
+  ///@param password password to be used for decryption
+  ///@param memUsageSetting defines how memory is used for buffering PDF streams
+  ///@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 final _load4 = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(
+                      ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_load4")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+              ffi.Pointer<ffi.Void>,
+              ffi.Pointer<ffi.Void>,
+              ffi.Pointer<ffi.Void>,
+              ffi.Pointer<ffi.Void>)>();
+
+  /// from: static public org.apache.pdfbox.pdmodel.PDDocument load(java.io.File file, java.lang.String password, java.io.InputStream keyStore, java.lang.String alias)
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// Parses a PDF. Unrestricted main memory will be used for buffering PDF streams.
+  ///@param file file to be loaded
+  ///@param password password to be used for decryption
+  ///@param keyStore key store to be used for decryption when using public key security
+  ///@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 final _load5 = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(
+                      ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_load5")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+              ffi.Pointer<ffi.Void>,
+              ffi.Pointer<ffi.Void>,
+              ffi.Pointer<ffi.Void>,
+              ffi.Pointer<ffi.Void>,
+              ffi.Pointer<ffi.Void>)>();
+
+  /// from: static public org.apache.pdfbox.pdmodel.PDDocument load(java.io.File file, 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.
+  ///
+  /// Parses a PDF.
+  ///@param file file to be loaded
+  ///@param password password to be used for decryption
+  ///@param keyStore key store to be used for decryption when using public key security
+  ///@param alias alias to be used for decryption when using public key security
+  ///@param memUsageSetting defines how memory is used for buffering PDF streams
+  ///@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));
+
+  static final _load6 = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(
+                      ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_load6")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+              ffi.Pointer<ffi.Void>,
+              ffi.Pointer<ffi.Void>,
+              ffi.Pointer<ffi.Void>,
+              ffi.Pointer<ffi.Void>,
+              ffi.Pointer<ffi.Void>)>();
+
+  /// 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));
+
+  static final _load7 = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_load7")
+      .asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: static public org.apache.pdfbox.pdmodel.PDDocument load(java.io.InputStream input)
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// Parses a PDF. The given input stream is copied to the memory to enable random access to the
+  /// pdf. Unrestricted main memory will be used for buffering PDF streams.
+  ///@param input stream that contains the document. Don't forget to close it after loading.
+  ///@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 final _load8 = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_load8")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: static public org.apache.pdfbox.pdmodel.PDDocument load(java.io.InputStream input, org.apache.pdfbox.io.MemoryUsageSetting memUsageSetting)
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// Parses a PDF. Depending on the memory settings parameter the given input stream is either
+  /// copied to main memory or to a temporary file to enable random access to the pdf.
+  ///@param input stream that contains the document. Don't forget to close it after loading.
+  ///@param memUsageSetting defines how memory is used for buffering input stream and PDF streams
+  ///@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 final _load9 = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_load9")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: static public org.apache.pdfbox.pdmodel.PDDocument load(java.io.InputStream input, java.lang.String password)
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// Parses a PDF. The given input stream is copied to the memory to enable random access to the
+  /// pdf. Unrestricted main memory will be used for buffering PDF streams.
+  ///@param input stream that contains the document. Don't forget to close it after loading.
+  ///@param password password to be used for decryption
+  ///@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 final _load10 = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(
+                      ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_load10")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+              ffi.Pointer<ffi.Void>,
+              ffi.Pointer<ffi.Void>,
+              ffi.Pointer<ffi.Void>,
+              ffi.Pointer<ffi.Void>)>();
+
+  /// from: static public org.apache.pdfbox.pdmodel.PDDocument load(java.io.InputStream input, java.lang.String password, java.io.InputStream keyStore, java.lang.String alias)
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// Parses a PDF. The given input stream is copied to the memory to enable random access to the
+  /// pdf. Unrestricted main memory will be used for buffering PDF streams.
+  ///@param input stream that contains the document. Don't forget to close it after loading.
+  ///@param password password to be used for decryption
+  ///@param keyStore key store to be used for decryption when using public key security
+  ///@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 final _load11 = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_load11")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>,
+              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: static public org.apache.pdfbox.pdmodel.PDDocument load(java.io.InputStream input, java.lang.String password, org.apache.pdfbox.io.MemoryUsageSetting memUsageSetting)
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// Parses a PDF. Depending on the memory settings parameter the given input stream is either
+  /// copied to main memory or to a temporary file to enable random access to the pdf.
+  ///@param input stream that contains the document. Don't forget to close it after loading.
+  ///@param password password to be used for decryption
+  ///@param memUsageSetting defines how memory is used for buffering input stream and PDF streams
+  ///@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 final _load12 = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(
+                      ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_load12")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+              ffi.Pointer<ffi.Void>,
+              ffi.Pointer<ffi.Void>,
+              ffi.Pointer<ffi.Void>,
+              ffi.Pointer<ffi.Void>,
+              ffi.Pointer<ffi.Void>)>();
+
+  /// from: static public org.apache.pdfbox.pdmodel.PDDocument load(java.io.InputStream input, 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.
+  ///
+  /// Parses a PDF. Depending on the memory settings parameter the given input stream is either
+  /// copied to memory or to a temporary file to enable random access to the pdf.
+  ///@param input stream that contains the document. Don't forget to close it after loading.
+  ///@param password password to be used for decryption
+  ///@param keyStore key store to be used for decryption when using public key security
+  ///@param alias alias to be used for decryption when using public key security
+  ///@param memUsageSetting defines how memory is used for buffering input stream and PDF streams
+  ///@return loaded document
+  ///@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));
+
+  static final _load13 = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_load13")
+      .asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: static public org.apache.pdfbox.pdmodel.PDDocument load(byte[] input)
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// Parses a PDF. Unrestricted main memory will be used for buffering PDF streams.
+  ///@param input byte array that contains the document.
+  ///@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 final _load14 = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_load14")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: static public org.apache.pdfbox.pdmodel.PDDocument load(byte[] input, java.lang.String password)
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// Parses a PDF. Unrestricted main memory will be used for buffering PDF streams.
+  ///@param input byte array that contains the document.
+  ///@param password password to be used for decryption
+  ///@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 final _load15 = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(
+                      ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_load15")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+              ffi.Pointer<ffi.Void>,
+              ffi.Pointer<ffi.Void>,
+              ffi.Pointer<ffi.Void>,
+              ffi.Pointer<ffi.Void>)>();
+
+  /// from: static public org.apache.pdfbox.pdmodel.PDDocument load(byte[] input, java.lang.String password, java.io.InputStream keyStore, java.lang.String alias)
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// Parses a PDF. Unrestricted main memory will be used for buffering PDF streams.
+  ///@param input byte array that contains the document.
+  ///@param password password to be used for decryption
+  ///@param keyStore key store to be used for decryption when using public key security
+  ///@param alias alias to be used for decryption when using public key security
+  ///@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 final _load16 = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(
+                      ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_load16")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+              ffi.Pointer<ffi.Void>,
+              ffi.Pointer<ffi.Void>,
+              ffi.Pointer<ffi.Void>,
+              ffi.Pointer<ffi.Void>,
+              ffi.Pointer<ffi.Void>)>();
+
+  /// from: static public org.apache.pdfbox.pdmodel.PDDocument load(byte[] input, 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.
+  ///
+  /// Parses a PDF.
+  ///@param input byte array that contains the document.
+  ///@param password password to be used for decryption
+  ///@param keyStore key store to be used for decryption when using public key security
+  ///@param alias alias to be used for decryption when using public key security
+  ///@param memUsageSetting defines how memory is used for buffering input stream and PDF streams
+  ///@return loaded document
+  ///@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));
+
+  static final _save = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_save")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: public void save(java.lang.String fileName)
+  ///
+  /// Save the document to a file.
+  ///
+  /// If encryption has been activated (with
+  /// \#protect(org.apache.pdfbox.pdmodel.encryption.ProtectionPolicy) protect(ProtectionPolicy)),
+  /// 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);
+
+  static final _save1 = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_save1")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: public void save(java.io.File file)
+  ///
+  /// Save the document to a file.
+  ///
+  /// If encryption has been activated (with
+  /// \#protect(org.apache.pdfbox.pdmodel.encryption.ProtectionPolicy) protect(ProtectionPolicy)),
+  /// 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);
+
+  static final _save2 = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_save2")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: public void save(java.io.OutputStream output)
+  ///
+  /// This will save the document to an output stream.
+  ///
+  /// If encryption has been activated (with
+  /// \#protect(org.apache.pdfbox.pdmodel.encryption.ProtectionPolicy) protect(ProtectionPolicy)),
+  /// do not use the document after saving because the contents are now encrypted.
+  ///@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);
+
+  static final _saveIncremental = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_saveIncremental")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: public void saveIncremental(java.io.OutputStream output)
+  ///
+  /// Save the PDF as an incremental update. This is only possible if the PDF was loaded from a
+  /// file or a stream, not if the document was created in PDFBox itself. There must be a path of
+  /// objects that have COSUpdateInfo\#isNeedToBeUpdated() set, starting from the document
+  /// catalog. For signatures this is taken care by PDFBox itself.
+  ///
+  /// Other usages of this method are for experienced users only. You will usually never need it.
+  /// It is useful only if you are required to keep the current revision and append the changes. A
+  /// typical use case is changing a signed file without invalidating the signature.
+  ///@param output stream to write to. It will be closed when done. It
+  /// <i>__must never__</i> point to the source file or that one will be
+  /// 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);
+
+  static final _saveIncremental1 = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_saveIncremental1")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+              ffi.Pointer<ffi.Void>)>();
+
+  /// from: public void saveIncremental(java.io.OutputStream output, java.util.Set<org.apache.pdfbox.cos.COSDictionary> objectsToWrite)
+  ///
+  /// Save the PDF as an incremental update. This is only possible if the PDF was loaded from a
+  /// file or a stream, not if the document was created in PDFBox itself. This allows to include
+  /// objects even if there is no path of objects that have
+  /// COSUpdateInfo\#isNeedToBeUpdated() set so the incremental update gets smaller. Only
+  /// dictionaries are supported; if you need to update other objects classes, then add their
+  /// parent dictionary.
+  ///
+  /// This method is for experienced users only. You will usually never need it. It is useful only
+  /// if you are required to keep the current revision and append the changes. A typical use case
+  /// is changing a signed file without invalidating the signature. To know which objects are
+  /// getting changed, you need to have some understanding of the PDF specification, and look at
+  /// the saved file with an editor to verify that you are updating the correct objects. You should
+  /// also inspect the page and document structures of the file with PDFDebugger.
+  ///@param output stream to write to. It will be closed when done. It
+  /// <i>__must never__</i> point to the source file or that one will be harmed!
+  ///@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);
+
+  static final _saveIncrementalForExternalSigning = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_saveIncrementalForExternalSigning")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: public org.apache.pdfbox.pdmodel.interactive.digitalsignature.ExternalSigningSupport saveIncrementalForExternalSigning(java.io.OutputStream output)
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  ///
+  /// __(This is a new feature for 2.0.3. The API for external signing might change based on feedback after release!)__
+  ///
+  /// Save PDF incrementally without closing for external signature creation scenario. The general
+  /// sequence is:
+  /// <pre>
+  ///    PDDocument pdDocument = ...;
+  ///    OutputStream outputStream = ...;
+  ///    SignatureOptions signatureOptions = ...; // options to specify fine tuned signature options or null for defaults
+  ///    PDSignature pdSignature = ...;
+  ///
+  ///    // add signature parameters to be used when creating signature dictionary
+  ///    pdDocument.addSignature(pdSignature, signatureOptions);
+  ///    // prepare PDF for signing and obtain helper class to be used
+  ///    ExternalSigningSupport externalSigningSupport = pdDocument.saveIncrementalForExternalSigning(outputStream);
+  ///    // get data to be signed
+  ///    InputStream dataToBeSigned = externalSigningSupport.getContent();
+  ///    // invoke signature service
+  ///    byte[] signature = sign(dataToBeSigned);
+  ///    // set resulted CMS signature
+  ///    externalSigningSupport.setSignature(signature);
+  ///
+  ///    // last step is to close the document
+  ///    pdDocument.close();
+  /// </pre>
+  ///
+  /// Note that after calling this method, only {@code close()} method may invoked for
+  /// {@code PDDocument} instance and only AFTER ExternalSigningSupport instance is used.
+  ///
+  ///
+  ///@param output stream to write the final PDF. It will be closed when the
+  /// document is closed. It <i>__must never__</i> point to the source file
+  /// or that one will be harmed!
+  ///@return instance to be used for external signing and setting CMS signature
+  ///@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));
+
+  static final _getPage = jlookup<
+          ffi.NativeFunction<
+              ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>,
+                  ffi.Int32)>>("org_apache_pdfbox_pdmodel_PDDocument_getPage")
+      .asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>, int)>();
+
+  /// from: public org.apache.pdfbox.pdmodel.PDPage getPage(int pageIndex)
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// Returns the page at the given 0-based index.
+  ///
+  /// This method is too slow to get all the pages from a large PDF document
+  /// (1000 pages or more). For such documents, use the iterator of
+  /// 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));
+
+  static final _getPages = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_getPages")
+      .asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: public org.apache.pdfbox.pdmodel.PDPageTree getPages()
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// Returns the page tree.
+  ///@return the page tree
+  jni.JlObject getPages() => jni.JlObject.fromRef(_getPages(reference));
+
+  static final _getNumberOfPages =
+      jlookup<ffi.NativeFunction<ffi.Int32 Function(ffi.Pointer<ffi.Void>)>>(
+              "org_apache_pdfbox_pdmodel_PDDocument_getNumberOfPages")
+          .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: public int getNumberOfPages()
+  ///
+  /// 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);
+
+  static final _close =
+      jlookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
+              "org_apache_pdfbox_pdmodel_PDDocument_close")
+          .asFunction<void Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: public void close()
+  ///
+  /// This will close the underlying COSDocument object.
+  ///@throws IOException If there is an error releasing resources.
+  void close() => _close(reference);
+
+  static final _protect = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_protect")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: public void protect(org.apache.pdfbox.pdmodel.encryption.ProtectionPolicy policy)
+  ///
+  /// Protects the document with a protection policy. The document content will be really
+  /// encrypted when it will be saved. This method only marks the document for encryption. It also
+  /// calls \#setAllSecurityToBeRemoved(boolean) with a false argument if it was set to true
+  /// previously and logs a warning.
+  ///
+  /// Do not use the document after saving, because the structures are encrypted.
+  ///@see org.apache.pdfbox.pdmodel.encryption.StandardProtectionPolicy
+  ///@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);
+
+  static final _getCurrentAccessPermission = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_getCurrentAccessPermission")
+      .asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: public org.apache.pdfbox.pdmodel.encryption.AccessPermission getCurrentAccessPermission()
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// Returns the access permissions granted when the document was decrypted. If the document was not decrypted this
+  /// method returns the access permission for a document owner (ie can do everything). The returned object is in read
+  /// 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));
+
+  static final _isAllSecurityToBeRemoved =
+      jlookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
+              "org_apache_pdfbox_pdmodel_PDDocument_isAllSecurityToBeRemoved")
+          .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: public boolean isAllSecurityToBeRemoved()
+  ///
+  /// 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;
+
+  static final _setAllSecurityToBeRemoved = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Uint8)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_setAllSecurityToBeRemoved")
+      .asFunction<void Function(ffi.Pointer<ffi.Void>, int)>();
+
+  /// from: public void setAllSecurityToBeRemoved(boolean removeAllSecurity)
+  ///
+  /// 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);
+
+  static final _getDocumentId = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_getDocumentId")
+      .asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: public java.lang.Long getDocumentId()
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// Provides the document ID.
+  ///@return the document ID
+  jni.JlObject getDocumentId() =>
+      jni.JlObject.fromRef(_getDocumentId(reference));
+
+  static final _setDocumentId = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_setDocumentId")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: public void setDocumentId(java.lang.Long docId)
+  ///
+  /// Sets the document ID to the given value.
+  ///@param docId the new document ID
+  void setDocumentId(jni.JlObject docId) =>
+      _setDocumentId(reference, docId.reference);
+
+  static final _getVersion =
+      jlookup<ffi.NativeFunction<ffi.Float Function(ffi.Pointer<ffi.Void>)>>(
+              "org_apache_pdfbox_pdmodel_PDDocument_getVersion")
+          .asFunction<double Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: public float getVersion()
+  ///
+  /// Returns the PDF specification version this document conforms to.
+  ///@return the PDF version (e.g. 1.4f)
+  double getVersion() => _getVersion(reference);
+
+  static final _setVersion = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Float)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_setVersion")
+      .asFunction<void Function(ffi.Pointer<ffi.Void>, double)>();
+
+  /// from: public void setVersion(float newVersion)
+  ///
+  /// 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);
+
+  static final _getResourceCache = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_getResourceCache")
+      .asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: public org.apache.pdfbox.pdmodel.ResourceCache getResourceCache()
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// 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));
+
+  static final _setResourceCache = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocument_setResourceCache")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: public void setResourceCache(org.apache.pdfbox.pdmodel.ResourceCache resourceCache)
+  ///
+  /// Sets the resource cache associated with this document.
+  ///@param resourceCache A resource cache, or null.
+  void setResourceCache(jni.JlObject resourceCache) =>
+      _setResourceCache(reference, resourceCache.reference);
+}
+
+/// from: org.apache.pdfbox.pdmodel.PDDocumentInformation
+///
+/// This is the document metadata.  Each getXXX method will return the entry if
+/// it exists or null if it does not exist.  If you pass in null for the setXXX
+/// method then it will clear the value.
+///@author Ben Litchfield
+///@author Gerardo Ortiz
+class PDDocumentInformation extends jni.JlObject {
+  PDDocumentInformation.fromRef(ffi.Pointer<ffi.Void> ref) : super.fromRef(ref);
+
+  static final _get_info = jlookup<
+          ffi.NativeFunction<
+              ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>>("get_org_apache_pdfbox_pdmodel_PDDocumentInformation_info")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>();
+
+  /// 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));
+
+  static final _ctor =
+      jlookup<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());
+
+  static final _ctor1 = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocumentInformation_ctor1")
+      .asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: public void <init>(org.apache.pdfbox.cos.COSDictionary dic)
+  ///
+  /// Constructor that is used for a preexisting dictionary.
+  ///@param dic The underlying dictionary.
+  PDDocumentInformation.ctor1(jni.JlObject dic)
+      : super.fromRef(_ctor1(dic.reference));
+
+  static final _getCOSObject = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocumentInformation_getCOSObject")
+      .asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: public org.apache.pdfbox.cos.COSDictionary getCOSObject()
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// This will get the underlying dictionary that this object wraps.
+  ///@return The underlying info dictionary.
+  jni.JlObject getCOSObject() => jni.JlObject.fromRef(_getCOSObject(reference));
+
+  static final _getPropertyStringValue = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocumentInformation_getPropertyStringValue")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: public java.lang.Object getPropertyStringValue(java.lang.String propertyKey)
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// Return the properties String value.
+  ///
+  /// Allows to retrieve the
+  /// low level date for validation purposes.
+  ///
+  ///
+  ///@param propertyKey the dictionaries key
+  ///@return the properties value
+  jni.JlObject getPropertyStringValue(jni.JlString propertyKey) =>
+      jni.JlObject.fromRef(
+          _getPropertyStringValue(reference, propertyKey.reference));
+
+  static final _getTitle = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocumentInformation_getTitle")
+      .asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: public java.lang.String getTitle()
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// 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));
+
+  static final _setTitle = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocumentInformation_setTitle")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: public void setTitle(java.lang.String title)
+  ///
+  /// 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);
+
+  static final _getAuthor = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocumentInformation_getAuthor")
+      .asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: public java.lang.String getAuthor()
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// 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));
+
+  static final _setAuthor = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocumentInformation_setAuthor")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: public void setAuthor(java.lang.String author)
+  ///
+  /// 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);
+
+  static final _getSubject = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocumentInformation_getSubject")
+      .asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: public java.lang.String getSubject()
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// 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));
+
+  static final _setSubject = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocumentInformation_setSubject")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: public void setSubject(java.lang.String subject)
+  ///
+  /// 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);
+
+  static final _getKeywords = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocumentInformation_getKeywords")
+      .asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: public java.lang.String getKeywords()
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// 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));
+
+  static final _setKeywords = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocumentInformation_setKeywords")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: public void setKeywords(java.lang.String keywords)
+  ///
+  /// 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);
+
+  static final _getCreator = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocumentInformation_getCreator")
+      .asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: public java.lang.String getCreator()
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// 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));
+
+  static final _setCreator = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocumentInformation_setCreator")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: public void setCreator(java.lang.String creator)
+  ///
+  /// 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);
+
+  static final _getProducer = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocumentInformation_getProducer")
+      .asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: public java.lang.String getProducer()
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// 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));
+
+  static final _setProducer = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocumentInformation_setProducer")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: public void setProducer(java.lang.String producer)
+  ///
+  /// 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);
+
+  static final _getCreationDate = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocumentInformation_getCreationDate")
+      .asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: public java.util.Calendar getCreationDate()
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// 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));
+
+  static final _setCreationDate = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocumentInformation_setCreationDate")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: public void setCreationDate(java.util.Calendar date)
+  ///
+  /// 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);
+
+  static final _getModificationDate = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocumentInformation_getModificationDate")
+      .asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: public java.util.Calendar getModificationDate()
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// 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));
+
+  static final _setModificationDate = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocumentInformation_setModificationDate")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: public void setModificationDate(java.util.Calendar date)
+  ///
+  /// 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);
+
+  static final _getTrapped = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocumentInformation_getTrapped")
+      .asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: public java.lang.String getTrapped()
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// 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));
+
+  static final _getMetadataKeys = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocumentInformation_getMetadataKeys")
+      .asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: public java.util.Set<java.lang.String> getMetadataKeys()
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// 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));
+
+  static final _getCustomMetadataValue = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocumentInformation_getCustomMetadataValue")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: public java.lang.String getCustomMetadataValue(java.lang.String fieldName)
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// This will get the value of a custom metadata information field for the document.
+  ///  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));
+
+  static final _setCustomMetadataValue = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocumentInformation_setCustomMetadataValue")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+              ffi.Pointer<ffi.Void>)>();
+
+  /// from: public void setCustomMetadataValue(java.lang.String fieldName, java.lang.String fieldValue)
+  ///
+  /// Set the custom metadata value.
+  ///@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);
+
+  static final _setTrapped = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_pdmodel_PDDocumentInformation_setTrapped")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: public void setTrapped(java.lang.String value)
+  ///
+  /// This will set the trapped of the document.  This will be
+  /// '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);
+}
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/lib/third_party/org/apache/pdfbox/text.dart b/pkgs/jni_gen/examples/pdfbox_plugin/lib/third_party/org/apache/pdfbox/text.dart
new file mode 100644
index 0000000..0b8fe1e
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/lib/third_party/org/apache/pdfbox/text.dart
@@ -0,0 +1,2223 @@
+// 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.
+
+// Autogenerated by jni_gen. DO NOT EDIT!
+
+// ignore_for_file: camel_case_types
+// ignore_for_file: non_constant_identifier_names
+// ignore_for_file: constant_identifier_names
+// ignore_for_file: annotate_overrides
+// ignore_for_file: no_leading_underscores_for_local_identifiers
+// 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;
+
+/// from: org.apache.pdfbox.text.PDFTextStripper
+///
+/// This class will take a pdf document and strip out all of the text and ignore the formatting and such. Please note; it
+/// is up to clients of this class to verify that a specific user has the correct permissions to extract text from the
+/// PDF document.
+///
+/// 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 {
+  PDFTextStripper.fromRef(ffi.Pointer<ffi.Void> ref) : super.fromRef(ref);
+
+  static final _get_defaultIndentThreshold = jlookup<
+              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<
+              ffi.NativeFunction<ffi.Void Function(ffi.Float)>>(
+          "set_org_apache_pdfbox_text_PDFTextStripper_defaultIndentThreshold")
+      .asFunction<void Function(double)>();
+
+  /// from: private static float defaultIndentThreshold
+  static set defaultIndentThreshold(double value) =>
+      _set_defaultIndentThreshold(value);
+
+  static final _get_defaultDropThreshold =
+      jlookup<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)>>(
+              "set_org_apache_pdfbox_text_PDFTextStripper_defaultDropThreshold")
+          .asFunction<void Function(double)>();
+
+  /// from: private static float defaultDropThreshold
+  static set defaultDropThreshold(double value) =>
+      _set_defaultDropThreshold(value);
+
+  static final _get_LOG =
+      jlookup<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 final _get_LINE_SEPARATOR = jlookup<
+          ffi.NativeFunction<
+              ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>>("get_org_apache_pdfbox_text_PDFTextStripper_LINE_SEPARATOR")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>();
+
+  /// from: protected final java.lang.String LINE_SEPARATOR
+  /// 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));
+
+  static final _get_lineSeparator = jlookup<
+          ffi.NativeFunction<
+              ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>>("get_org_apache_pdfbox_text_PDFTextStripper_lineSeparator")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>();
+
+  /// 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<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "set_org_apache_pdfbox_text_PDFTextStripper_lineSeparator")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// 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(reference, value.reference);
+
+  static final _get_wordSeparator = jlookup<
+          ffi.NativeFunction<
+              ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>>("get_org_apache_pdfbox_text_PDFTextStripper_wordSeparator")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>();
+
+  /// 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<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "set_org_apache_pdfbox_text_PDFTextStripper_wordSeparator")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// 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(reference, value.reference);
+
+  static final _get_paragraphStart = jlookup<
+          ffi.NativeFunction<
+              ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>>("get_org_apache_pdfbox_text_PDFTextStripper_paragraphStart")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>();
+
+  /// 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<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "set_org_apache_pdfbox_text_PDFTextStripper_paragraphStart")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// 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(reference, value.reference);
+
+  static final _get_paragraphEnd = jlookup<
+          ffi.NativeFunction<
+              ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>>("get_org_apache_pdfbox_text_PDFTextStripper_paragraphEnd")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>();
+
+  /// 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<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "set_org_apache_pdfbox_text_PDFTextStripper_paragraphEnd")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// 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(reference, value.reference);
+
+  static final _get_pageStart = jlookup<
+          ffi.NativeFunction<
+              ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>>("get_org_apache_pdfbox_text_PDFTextStripper_pageStart")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>();
+
+  /// 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<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "set_org_apache_pdfbox_text_PDFTextStripper_pageStart")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// 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(reference, value.reference);
+
+  static final _get_pageEnd = jlookup<
+          ffi.NativeFunction<
+              ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>>("get_org_apache_pdfbox_text_PDFTextStripper_pageEnd")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>();
+
+  /// 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<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "set_org_apache_pdfbox_text_PDFTextStripper_pageEnd")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// 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);
+
+  static final _get_articleStart = jlookup<
+          ffi.NativeFunction<
+              ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>>("get_org_apache_pdfbox_text_PDFTextStripper_articleStart")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>();
+
+  /// 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<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "set_org_apache_pdfbox_text_PDFTextStripper_articleStart")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// 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(reference, value.reference);
+
+  static final _get_articleEnd = jlookup<
+          ffi.NativeFunction<
+              ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>>("get_org_apache_pdfbox_text_PDFTextStripper_articleEnd")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>();
+
+  /// 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<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "set_org_apache_pdfbox_text_PDFTextStripper_articleEnd")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// 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(reference, value.reference);
+
+  static final _get_currentPageNo = jlookup<
+          ffi.NativeFunction<
+              ffi.Int32 Function(
+    ffi.Pointer<ffi.Void>,
+  )>>("get_org_apache_pdfbox_text_PDFTextStripper_currentPageNo")
+      .asFunction<
+          int Function(
+    ffi.Pointer<ffi.Void>,
+  )>();
+
+  /// from: private int currentPageNo
+  int get currentPageNo => _get_currentPageNo(reference);
+  static final _set_currentPageNo = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Int32)>>(
+          "set_org_apache_pdfbox_text_PDFTextStripper_currentPageNo")
+      .asFunction<void Function(ffi.Pointer<ffi.Void>, int)>();
+
+  /// from: private int currentPageNo
+  set currentPageNo(int value) => _set_currentPageNo(reference, value);
+
+  static final _get_startPage = jlookup<
+          ffi.NativeFunction<
+              ffi.Int32 Function(
+    ffi.Pointer<ffi.Void>,
+  )>>("get_org_apache_pdfbox_text_PDFTextStripper_startPage")
+      .asFunction<
+          int Function(
+    ffi.Pointer<ffi.Void>,
+  )>();
+
+  /// from: private int startPage
+  int get startPage => _get_startPage(reference);
+  static final _set_startPage = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Int32)>>(
+          "set_org_apache_pdfbox_text_PDFTextStripper_startPage")
+      .asFunction<void Function(ffi.Pointer<ffi.Void>, int)>();
+
+  /// from: private int startPage
+  set startPage(int value) => _set_startPage(reference, value);
+
+  static final _get_endPage = jlookup<
+          ffi.NativeFunction<
+              ffi.Int32 Function(
+    ffi.Pointer<ffi.Void>,
+  )>>("get_org_apache_pdfbox_text_PDFTextStripper_endPage")
+      .asFunction<
+          int Function(
+    ffi.Pointer<ffi.Void>,
+  )>();
+
+  /// from: private int endPage
+  int get endPage => _get_endPage(reference);
+  static final _set_endPage = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Int32)>>(
+          "set_org_apache_pdfbox_text_PDFTextStripper_endPage")
+      .asFunction<void Function(ffi.Pointer<ffi.Void>, int)>();
+
+  /// from: private int endPage
+  set endPage(int value) => _set_endPage(reference, value);
+
+  static final _get_startBookmark = jlookup<
+          ffi.NativeFunction<
+              ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>>("get_org_apache_pdfbox_text_PDFTextStripper_startBookmark")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>();
+
+  /// 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<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "set_org_apache_pdfbox_text_PDFTextStripper_startBookmark")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// 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(reference, value.reference);
+
+  static final _get_startBookmarkPageNumber = jlookup<
+          ffi.NativeFunction<
+              ffi.Int32 Function(
+    ffi.Pointer<ffi.Void>,
+  )>>("get_org_apache_pdfbox_text_PDFTextStripper_startBookmarkPageNumber")
+      .asFunction<
+          int Function(
+    ffi.Pointer<ffi.Void>,
+  )>();
+
+  /// from: private int startBookmarkPageNumber
+  int get startBookmarkPageNumber => _get_startBookmarkPageNumber(reference);
+  static final _set_startBookmarkPageNumber = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Int32)>>(
+          "set_org_apache_pdfbox_text_PDFTextStripper_startBookmarkPageNumber")
+      .asFunction<void Function(ffi.Pointer<ffi.Void>, int)>();
+
+  /// from: private int startBookmarkPageNumber
+  set startBookmarkPageNumber(int value) =>
+      _set_startBookmarkPageNumber(reference, value);
+
+  static final _get_endBookmarkPageNumber = jlookup<
+          ffi.NativeFunction<
+              ffi.Int32 Function(
+    ffi.Pointer<ffi.Void>,
+  )>>("get_org_apache_pdfbox_text_PDFTextStripper_endBookmarkPageNumber")
+      .asFunction<
+          int Function(
+    ffi.Pointer<ffi.Void>,
+  )>();
+
+  /// from: private int endBookmarkPageNumber
+  int get endBookmarkPageNumber => _get_endBookmarkPageNumber(reference);
+  static final _set_endBookmarkPageNumber = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Int32)>>(
+          "set_org_apache_pdfbox_text_PDFTextStripper_endBookmarkPageNumber")
+      .asFunction<void Function(ffi.Pointer<ffi.Void>, int)>();
+
+  /// from: private int endBookmarkPageNumber
+  set endBookmarkPageNumber(int value) =>
+      _set_endBookmarkPageNumber(reference, value);
+
+  static final _get_endBookmark = jlookup<
+          ffi.NativeFunction<
+              ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>>("get_org_apache_pdfbox_text_PDFTextStripper_endBookmark")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>();
+
+  /// 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<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "set_org_apache_pdfbox_text_PDFTextStripper_endBookmark")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// 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(reference, value.reference);
+
+  static final _get_suppressDuplicateOverlappingText = jlookup<
+          ffi.NativeFunction<
+              ffi.Uint8 Function(
+    ffi.Pointer<ffi.Void>,
+  )>>("get_org_apache_pdfbox_text_PDFTextStripper_suppressDuplicateOverlappingText")
+      .asFunction<
+          int Function(
+    ffi.Pointer<ffi.Void>,
+  )>();
+
+  /// from: private boolean suppressDuplicateOverlappingText
+  bool get suppressDuplicateOverlappingText =>
+      _get_suppressDuplicateOverlappingText(reference) != 0;
+  static final _set_suppressDuplicateOverlappingText = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Uint8)>>(
+          "set_org_apache_pdfbox_text_PDFTextStripper_suppressDuplicateOverlappingText")
+      .asFunction<void Function(ffi.Pointer<ffi.Void>, int)>();
+
+  /// from: private boolean suppressDuplicateOverlappingText
+  set suppressDuplicateOverlappingText(bool value) =>
+      _set_suppressDuplicateOverlappingText(reference, value ? 1 : 0);
+
+  static final _get_shouldSeparateByBeads = jlookup<
+          ffi.NativeFunction<
+              ffi.Uint8 Function(
+    ffi.Pointer<ffi.Void>,
+  )>>("get_org_apache_pdfbox_text_PDFTextStripper_shouldSeparateByBeads")
+      .asFunction<
+          int Function(
+    ffi.Pointer<ffi.Void>,
+  )>();
+
+  /// from: private boolean shouldSeparateByBeads
+  bool get shouldSeparateByBeads => _get_shouldSeparateByBeads(reference) != 0;
+  static final _set_shouldSeparateByBeads = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Uint8)>>(
+          "set_org_apache_pdfbox_text_PDFTextStripper_shouldSeparateByBeads")
+      .asFunction<void Function(ffi.Pointer<ffi.Void>, int)>();
+
+  /// from: private boolean shouldSeparateByBeads
+  set shouldSeparateByBeads(bool value) =>
+      _set_shouldSeparateByBeads(reference, value ? 1 : 0);
+
+  static final _get_sortByPosition = jlookup<
+          ffi.NativeFunction<
+              ffi.Uint8 Function(
+    ffi.Pointer<ffi.Void>,
+  )>>("get_org_apache_pdfbox_text_PDFTextStripper_sortByPosition")
+      .asFunction<
+          int Function(
+    ffi.Pointer<ffi.Void>,
+  )>();
+
+  /// from: private boolean sortByPosition
+  bool get sortByPosition => _get_sortByPosition(reference) != 0;
+  static final _set_sortByPosition = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Uint8)>>(
+          "set_org_apache_pdfbox_text_PDFTextStripper_sortByPosition")
+      .asFunction<void Function(ffi.Pointer<ffi.Void>, int)>();
+
+  /// from: private boolean sortByPosition
+  set sortByPosition(bool value) =>
+      _set_sortByPosition(reference, value ? 1 : 0);
+
+  static final _get_addMoreFormatting = jlookup<
+          ffi.NativeFunction<
+              ffi.Uint8 Function(
+    ffi.Pointer<ffi.Void>,
+  )>>("get_org_apache_pdfbox_text_PDFTextStripper_addMoreFormatting")
+      .asFunction<
+          int Function(
+    ffi.Pointer<ffi.Void>,
+  )>();
+
+  /// from: private boolean addMoreFormatting
+  bool get addMoreFormatting => _get_addMoreFormatting(reference) != 0;
+  static final _set_addMoreFormatting = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Uint8)>>(
+          "set_org_apache_pdfbox_text_PDFTextStripper_addMoreFormatting")
+      .asFunction<void Function(ffi.Pointer<ffi.Void>, int)>();
+
+  /// from: private boolean addMoreFormatting
+  set addMoreFormatting(bool value) =>
+      _set_addMoreFormatting(reference, value ? 1 : 0);
+
+  static final _get_indentThreshold = jlookup<
+          ffi.NativeFunction<
+              ffi.Float Function(
+    ffi.Pointer<ffi.Void>,
+  )>>("get_org_apache_pdfbox_text_PDFTextStripper_indentThreshold")
+      .asFunction<
+          double Function(
+    ffi.Pointer<ffi.Void>,
+  )>();
+
+  /// from: private float indentThreshold
+  double get indentThreshold => _get_indentThreshold(reference);
+  static final _set_indentThreshold = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Float)>>(
+          "set_org_apache_pdfbox_text_PDFTextStripper_indentThreshold")
+      .asFunction<void Function(ffi.Pointer<ffi.Void>, double)>();
+
+  /// from: private float indentThreshold
+  set indentThreshold(double value) => _set_indentThreshold(reference, value);
+
+  static final _get_dropThreshold = jlookup<
+          ffi.NativeFunction<
+              ffi.Float Function(
+    ffi.Pointer<ffi.Void>,
+  )>>("get_org_apache_pdfbox_text_PDFTextStripper_dropThreshold")
+      .asFunction<
+          double Function(
+    ffi.Pointer<ffi.Void>,
+  )>();
+
+  /// from: private float dropThreshold
+  double get dropThreshold => _get_dropThreshold(reference);
+  static final _set_dropThreshold = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Float)>>(
+          "set_org_apache_pdfbox_text_PDFTextStripper_dropThreshold")
+      .asFunction<void Function(ffi.Pointer<ffi.Void>, double)>();
+
+  /// from: private float dropThreshold
+  set dropThreshold(double value) => _set_dropThreshold(reference, value);
+
+  static final _get_spacingTolerance = jlookup<
+          ffi.NativeFunction<
+              ffi.Float Function(
+    ffi.Pointer<ffi.Void>,
+  )>>("get_org_apache_pdfbox_text_PDFTextStripper_spacingTolerance")
+      .asFunction<
+          double Function(
+    ffi.Pointer<ffi.Void>,
+  )>();
+
+  /// from: private float spacingTolerance
+  double get spacingTolerance => _get_spacingTolerance(reference);
+  static final _set_spacingTolerance = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Float)>>(
+          "set_org_apache_pdfbox_text_PDFTextStripper_spacingTolerance")
+      .asFunction<void Function(ffi.Pointer<ffi.Void>, double)>();
+
+  /// from: private float spacingTolerance
+  set spacingTolerance(double value) => _set_spacingTolerance(reference, value);
+
+  static final _get_averageCharTolerance = jlookup<
+          ffi.NativeFunction<
+              ffi.Float Function(
+    ffi.Pointer<ffi.Void>,
+  )>>("get_org_apache_pdfbox_text_PDFTextStripper_averageCharTolerance")
+      .asFunction<
+          double Function(
+    ffi.Pointer<ffi.Void>,
+  )>();
+
+  /// from: private float averageCharTolerance
+  double get averageCharTolerance => _get_averageCharTolerance(reference);
+  static final _set_averageCharTolerance = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Float)>>(
+          "set_org_apache_pdfbox_text_PDFTextStripper_averageCharTolerance")
+      .asFunction<void Function(ffi.Pointer<ffi.Void>, double)>();
+
+  /// from: private float averageCharTolerance
+  set averageCharTolerance(double value) =>
+      _set_averageCharTolerance(reference, value);
+
+  static final _get_beadRectangles = jlookup<
+          ffi.NativeFunction<
+              ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>>("get_org_apache_pdfbox_text_PDFTextStripper_beadRectangles")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>();
+
+  /// 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<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "set_org_apache_pdfbox_text_PDFTextStripper_beadRectangles")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// 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(reference, value.reference);
+
+  static final _get_charactersByArticle = jlookup<
+          ffi.NativeFunction<
+              ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>>("get_org_apache_pdfbox_text_PDFTextStripper_charactersByArticle")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>();
+
+  /// from: protected java.util.ArrayList<java.util.List<org.apache.pdfbox.text.TextPosition>> charactersByArticle
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// The charactersByArticle is used to extract text by article divisions. For example a PDF that has two columns like
+  /// a newspaper, we want to extract the first column and then the second column. In this example the PDF would have 2
+  /// beads(or articles), one for each column. The size of the charactersByArticle would be 5, because not all text on
+  /// the screen will fall into one of the articles. The five divisions are shown below
+  ///
+  /// Text before first article
+  /// first article text
+  /// text between first article and second article
+  /// second article text
+  /// 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<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "set_org_apache_pdfbox_text_PDFTextStripper_charactersByArticle")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: protected java.util.ArrayList<java.util.List<org.apache.pdfbox.text.TextPosition>> charactersByArticle
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// The charactersByArticle is used to extract text by article divisions. For example a PDF that has two columns like
+  /// a newspaper, we want to extract the first column and then the second column. In this example the PDF would have 2
+  /// beads(or articles), one for each column. The size of the charactersByArticle would be 5, because not all text on
+  /// the screen will fall into one of the articles. The five divisions are shown below
+  ///
+  /// Text before first article
+  /// first article text
+  /// text between first article and second article
+  /// second article text
+  /// 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(reference, value.reference);
+
+  static final _get_characterListMapping = jlookup<
+          ffi.NativeFunction<
+              ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>>("get_org_apache_pdfbox_text_PDFTextStripper_characterListMapping")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>();
+
+  /// 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<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "set_org_apache_pdfbox_text_PDFTextStripper_characterListMapping")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// 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(reference, value.reference);
+
+  static final _get_document = jlookup<
+          ffi.NativeFunction<
+              ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>>("get_org_apache_pdfbox_text_PDFTextStripper_document")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>();
+
+  /// from: protected org.apache.pdfbox.pdmodel.PDDocument document
+  /// 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<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "set_org_apache_pdfbox_text_PDFTextStripper_document")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: protected org.apache.pdfbox.pdmodel.PDDocument document
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  set document(pdmodel_.PDDocument value) =>
+      _set_document(reference, value.reference);
+
+  static final _get_output = jlookup<
+          ffi.NativeFunction<
+              ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>>("get_org_apache_pdfbox_text_PDFTextStripper_output")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>();
+
+  /// 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<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "set_org_apache_pdfbox_text_PDFTextStripper_output")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// 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);
+
+  static final _get_inParagraph = jlookup<
+          ffi.NativeFunction<
+              ffi.Uint8 Function(
+    ffi.Pointer<ffi.Void>,
+  )>>("get_org_apache_pdfbox_text_PDFTextStripper_inParagraph")
+      .asFunction<
+          int Function(
+    ffi.Pointer<ffi.Void>,
+  )>();
+
+  /// from: private boolean inParagraph
+  ///
+  /// True if we started a paragraph but haven't ended it yet.
+  bool get inParagraph => _get_inParagraph(reference) != 0;
+  static final _set_inParagraph = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Uint8)>>(
+          "set_org_apache_pdfbox_text_PDFTextStripper_inParagraph")
+      .asFunction<void Function(ffi.Pointer<ffi.Void>, int)>();
+
+  /// from: private boolean inParagraph
+  ///
+  /// True if we started a paragraph but haven't ended it yet.
+  set inParagraph(bool value) => _set_inParagraph(reference, value ? 1 : 0);
+
+  /// from: private static final float END_OF_LAST_TEXT_X_RESET_VALUE
+  static const END_OF_LAST_TEXT_X_RESET_VALUE = -1.0;
+
+  /// from: private static final float MAX_Y_FOR_LINE_RESET_VALUE
+  static const MAX_Y_FOR_LINE_RESET_VALUE = -3.4028235e+38;
+
+  /// from: private static final float EXPECTED_START_OF_NEXT_WORD_X_RESET_VALUE
+  static const EXPECTED_START_OF_NEXT_WORD_X_RESET_VALUE = -3.4028235e+38;
+
+  /// from: private static final float MAX_HEIGHT_FOR_LINE_RESET_VALUE
+  static const MAX_HEIGHT_FOR_LINE_RESET_VALUE = -1.0;
+
+  /// from: private static final float MIN_Y_TOP_FOR_LINE_RESET_VALUE
+  static const MIN_Y_TOP_FOR_LINE_RESET_VALUE = 3.4028235e+38;
+
+  /// 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<
+              ffi.NativeFunction<ffi.Pointer<ffi.Void> Function()>>(
+          "get_org_apache_pdfbox_text_PDFTextStripper_LIST_ITEM_EXPRESSIONS")
+      .asFunction<ffi.Pointer<ffi.Void> Function()>();
+
+  /// from: private static final java.lang.String[] LIST_ITEM_EXPRESSIONS
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// 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 final _get_listOfPatterns = jlookup<
+          ffi.NativeFunction<
+              ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>>("get_org_apache_pdfbox_text_PDFTextStripper_listOfPatterns")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+    ffi.Pointer<ffi.Void>,
+  )>();
+
+  /// 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<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "set_org_apache_pdfbox_text_PDFTextStripper_listOfPatterns")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// 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(reference, value.reference);
+
+  static final _get_MIRRORING_CHAR_MAP =
+      jlookup<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 final _set_MIRRORING_CHAR_MAP =
+      jlookup<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) =>
+      _set_MIRRORING_CHAR_MAP(value.reference);
+
+  static final _ctor =
+      jlookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function()>>(
+              "org_apache_pdfbox_text_PDFTextStripper_ctor")
+          .asFunction<ffi.Pointer<ffi.Void> Function()>();
+
+  /// from: public void <init>()
+  ///
+  /// Instantiate a new PDFTextStripper object.
+  ///@throws IOException If there is an error loading the properties.
+  PDFTextStripper() : super.fromRef(_ctor());
+
+  static final _getText = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_getText")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: public java.lang.String getText(org.apache.pdfbox.pdmodel.PDDocument doc)
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// This will return the text of a document. See writeText. <br>
+  /// NOTE: The document must not be encrypted when coming into this method.
+  ///
+  /// IMPORTANT: By default, text extraction is done in the same sequence as the text in the PDF page content stream.
+  /// PDF is a graphic format, not a text format, and unlike HTML, it has no requirements that text one on page
+  /// be rendered in a certain order. The order is the one that was determined by the software that created the
+  /// PDF. To get text sorted from left to right and top to botton, use \#setSortByPosition(boolean).
+  ///@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));
+
+  static final _resetEngine =
+      jlookup<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);
+
+  static final _writeText = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_writeText")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+              ffi.Pointer<ffi.Void>)>();
+
+  /// from: public void writeText(org.apache.pdfbox.pdmodel.PDDocument doc, java.io.Writer outputStream)
+  ///
+  /// This will take a PDDocument and write the text of that document to the print writer.
+  ///@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);
+
+  static final _processPages = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_processPages")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: protected void processPages(org.apache.pdfbox.pdmodel.PDPageTree pages)
+  ///
+  /// 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);
+
+  static final _startDocument = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_startDocument")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: protected void startDocument(org.apache.pdfbox.pdmodel.PDDocument document)
+  ///
+  /// 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);
+
+  static final _endDocument = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_endDocument")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: protected void endDocument(org.apache.pdfbox.pdmodel.PDDocument document)
+  ///
+  /// This method is available for subclasses of this class. It will be called after processing of the document
+  /// 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);
+
+  static final _processPage = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_processPage")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: public void processPage(org.apache.pdfbox.pdmodel.PDPage page)
+  ///
+  /// 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);
+
+  static final _fillBeadRectangles = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_fillBeadRectangles")
+      .asFunction<
+          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);
+
+  static final _startArticle =
+      jlookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
+              "org_apache_pdfbox_text_PDFTextStripper_startArticle")
+          .asFunction<void Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: protected void startArticle()
+  ///
+  /// Start a new article, which is typically defined as a column on a single page (also referred to as a bead). This
+  /// 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);
+
+  static final _startArticle1 = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Uint8)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_startArticle1")
+      .asFunction<void Function(ffi.Pointer<ffi.Void>, int)>();
+
+  /// from: protected void startArticle(boolean isLTR)
+  ///
+  /// Start a new article, which is typically defined as a column on a single page (also referred to as a bead).
+  /// 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);
+
+  static final _endArticle =
+      jlookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
+              "org_apache_pdfbox_text_PDFTextStripper_endArticle")
+          .asFunction<void Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: protected void endArticle()
+  ///
+  /// 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);
+
+  static final _startPage1 = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_startPage1")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: protected void startPage(org.apache.pdfbox.pdmodel.PDPage page)
+  ///
+  /// 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);
+
+  static final _endPage1 = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_endPage1")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: protected void endPage(org.apache.pdfbox.pdmodel.PDPage page)
+  ///
+  /// 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);
+
+  static final _writePage =
+      jlookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
+              "org_apache_pdfbox_text_PDFTextStripper_writePage")
+          .asFunction<void Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: protected void writePage()
+  ///
+  /// This will print the text of the processed page to "output". It will estimate, based on the coordinates of the
+  /// 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);
+
+  static final _overlap = jlookup<
+          ffi.NativeFunction<
+              ffi.Uint8 Function(
+                  ffi.Pointer<ffi.Void>,
+                  ffi.Float,
+                  ffi.Float,
+                  ffi.Float,
+                  ffi.Float)>>("org_apache_pdfbox_text_PDFTextStripper_overlap")
+      .asFunction<
+          int Function(
+              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;
+
+  static final _writeLineSeparator =
+      jlookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
+              "org_apache_pdfbox_text_PDFTextStripper_writeLineSeparator")
+          .asFunction<void Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: protected void writeLineSeparator()
+  ///
+  /// 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);
+
+  static final _writeWordSeparator =
+      jlookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
+              "org_apache_pdfbox_text_PDFTextStripper_writeWordSeparator")
+          .asFunction<void Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: protected void writeWordSeparator()
+  ///
+  /// 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);
+
+  static final _writeCharacters = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_writeCharacters")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: protected void writeCharacters(org.apache.pdfbox.text.TextPosition text)
+  ///
+  /// 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);
+
+  static final _writeString = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_writeString")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+              ffi.Pointer<ffi.Void>)>();
+
+  /// from: protected void writeString(java.lang.String text, java.util.List<org.apache.pdfbox.text.TextPosition> textPositions)
+  ///
+  /// Write a Java string to the output stream. The default implementation will ignore the <code>textPositions</code>
+  /// and just calls \#writeString(String).
+  ///@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);
+
+  static final _writeString1 = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_writeString1")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: protected void writeString(java.lang.String text)
+  ///
+  /// 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);
+
+  static final _within = jlookup<
+          ffi.NativeFunction<
+              ffi.Uint8 Function(ffi.Pointer<ffi.Void>, ffi.Float, ffi.Float,
+                  ffi.Float)>>("org_apache_pdfbox_text_PDFTextStripper_within")
+      .asFunction<
+          int Function(ffi.Pointer<ffi.Void>, double, double, double)>();
+
+  /// from: private boolean within(float first, float second, float variance)
+  ///
+  /// This will determine of two floating point numbers are within a specified variance.
+  ///@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;
+
+  static final _processTextPosition = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_processTextPosition")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: protected void processTextPosition(org.apache.pdfbox.text.TextPosition text)
+  ///
+  /// 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);
+
+  static final _getStartPage =
+      jlookup<ffi.NativeFunction<ffi.Int32 Function(ffi.Pointer<ffi.Void>)>>(
+              "org_apache_pdfbox_text_PDFTextStripper_getStartPage")
+          .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: public int getStartPage()
+  ///
+  /// This is the page that the text extraction will start on. The pages start at page 1. For example in a 5 page PDF
+  /// 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);
+
+  static final _setStartPage = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Int32)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_setStartPage")
+      .asFunction<void Function(ffi.Pointer<ffi.Void>, int)>();
+
+  /// from: public void setStartPage(int startPageValue)
+  ///
+  /// 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);
+
+  static final _getEndPage =
+      jlookup<ffi.NativeFunction<ffi.Int32 Function(ffi.Pointer<ffi.Void>)>>(
+              "org_apache_pdfbox_text_PDFTextStripper_getEndPage")
+          .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: public int getEndPage()
+  ///
+  /// This will get the last page that will be extracted. This is inclusive, for example if a 5 page PDF an endPage
+  /// 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);
+
+  static final _setEndPage = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Int32)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_setEndPage")
+      .asFunction<void Function(ffi.Pointer<ffi.Void>, int)>();
+
+  /// from: public void setEndPage(int endPageValue)
+  ///
+  /// 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);
+
+  static final _setLineSeparator = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_setLineSeparator")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: public void setLineSeparator(java.lang.String separator)
+  ///
+  /// 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);
+
+  static final _getLineSeparator = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_getLineSeparator")
+      .asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: public java.lang.String getLineSeparator()
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// This will get the line separator.
+  ///@return The desired line separator string.
+  jni.JlString getLineSeparator() =>
+      jni.JlString.fromRef(_getLineSeparator(reference));
+
+  static final _getWordSeparator = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_getWordSeparator")
+      .asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: public java.lang.String getWordSeparator()
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// This will get the word separator.
+  ///@return The desired word separator string.
+  jni.JlString getWordSeparator() =>
+      jni.JlString.fromRef(_getWordSeparator(reference));
+
+  static final _setWordSeparator = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_setWordSeparator")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: public void setWordSeparator(java.lang.String separator)
+  ///
+  /// Set the desired word separator for output text. The PDFBox text extraction algorithm will output a space
+  /// character if there is enough space between two words. By default a space character is used. If you need and
+  /// 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);
+
+  static final _getSuppressDuplicateOverlappingText = jlookup<
+              ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_getSuppressDuplicateOverlappingText")
+      .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: public boolean getSuppressDuplicateOverlappingText()
+  ///
+  /// @return Returns the suppressDuplicateOverlappingText.
+  bool getSuppressDuplicateOverlappingText() =>
+      _getSuppressDuplicateOverlappingText(reference) != 0;
+
+  static final _getCurrentPageNo =
+      jlookup<ffi.NativeFunction<ffi.Int32 Function(ffi.Pointer<ffi.Void>)>>(
+              "org_apache_pdfbox_text_PDFTextStripper_getCurrentPageNo")
+          .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: protected int getCurrentPageNo()
+  ///
+  /// Get the current page number that is being processed.
+  ///@return A 1 based number representing the current page.
+  int getCurrentPageNo() => _getCurrentPageNo(reference);
+
+  static final _getOutput = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_getOutput")
+      .asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: protected java.io.Writer getOutput()
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// 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));
+
+  static final _getCharactersByArticle = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_getCharactersByArticle")
+      .asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: protected java.util.List<java.util.List<org.apache.pdfbox.text.TextPosition>> getCharactersByArticle()
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// 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));
+
+  static final _setSuppressDuplicateOverlappingText = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Uint8)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_setSuppressDuplicateOverlappingText")
+      .asFunction<void Function(ffi.Pointer<ffi.Void>, int)>();
+
+  /// from: public void setSuppressDuplicateOverlappingText(boolean suppressDuplicateOverlappingTextValue)
+  ///
+  /// By default the text stripper will attempt to remove text that overlapps each other. Word paints the same
+  /// character several times in order to make it look bold. By setting this to false all text will be extracted, which
+  /// 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);
+
+  static final _getSeparateByBeads =
+      jlookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
+              "org_apache_pdfbox_text_PDFTextStripper_getSeparateByBeads")
+          .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: public boolean getSeparateByBeads()
+  ///
+  /// 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;
+
+  static final _setShouldSeparateByBeads = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Uint8)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_setShouldSeparateByBeads")
+      .asFunction<void Function(ffi.Pointer<ffi.Void>, int)>();
+
+  /// from: public void setShouldSeparateByBeads(boolean aShouldSeparateByBeads)
+  ///
+  /// 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);
+
+  static final _getEndBookmark = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_getEndBookmark")
+      .asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: public org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline.PDOutlineItem getEndBookmark()
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// Get the bookmark where text extraction should end, inclusive. Default is null.
+  ///@return The ending bookmark.
+  jni.JlObject getEndBookmark() =>
+      jni.JlObject.fromRef(_getEndBookmark(reference));
+
+  static final _setEndBookmark = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_setEndBookmark")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: public void setEndBookmark(org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline.PDOutlineItem aEndBookmark)
+  ///
+  /// Set the bookmark where the text extraction should stop.
+  ///@param aEndBookmark The ending bookmark.
+  void setEndBookmark(jni.JlObject aEndBookmark) =>
+      _setEndBookmark(reference, aEndBookmark.reference);
+
+  static final _getStartBookmark = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_getStartBookmark")
+      .asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: public org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline.PDOutlineItem getStartBookmark()
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// Get the bookmark where text extraction should start, inclusive. Default is null.
+  ///@return The starting bookmark.
+  jni.JlObject getStartBookmark() =>
+      jni.JlObject.fromRef(_getStartBookmark(reference));
+
+  static final _setStartBookmark = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_setStartBookmark")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: public void setStartBookmark(org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline.PDOutlineItem aStartBookmark)
+  ///
+  /// Set the bookmark where text extraction should start, inclusive.
+  ///@param aStartBookmark The starting bookmark.
+  void setStartBookmark(jni.JlObject aStartBookmark) =>
+      _setStartBookmark(reference, aStartBookmark.reference);
+
+  static final _getAddMoreFormatting =
+      jlookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
+              "org_apache_pdfbox_text_PDFTextStripper_getAddMoreFormatting")
+          .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: public boolean getAddMoreFormatting()
+  ///
+  /// 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;
+
+  static final _setAddMoreFormatting = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Uint8)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_setAddMoreFormatting")
+      .asFunction<void Function(ffi.Pointer<ffi.Void>, int)>();
+
+  /// from: public void setAddMoreFormatting(boolean newAddMoreFormatting)
+  ///
+  /// 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);
+
+  static final _getSortByPosition =
+      jlookup<ffi.NativeFunction<ffi.Uint8 Function(ffi.Pointer<ffi.Void>)>>(
+              "org_apache_pdfbox_text_PDFTextStripper_getSortByPosition")
+          .asFunction<int Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: public boolean getSortByPosition()
+  ///
+  /// 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;
+
+  static final _setSortByPosition = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Uint8)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_setSortByPosition")
+      .asFunction<void Function(ffi.Pointer<ffi.Void>, int)>();
+
+  /// from: public void setSortByPosition(boolean newSortByPosition)
+  ///
+  /// The order of the text tokens in a PDF file may not be in the same as they appear visually on the screen. For
+  /// example, a PDF writer may write out all text by font, so all bold or larger text, then make a second pass and
+  /// write out the normal text.<br>
+  /// The default is to __not__ sort by position.<br>
+  /// <br>
+  /// 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);
+
+  static final _getSpacingTolerance =
+      jlookup<ffi.NativeFunction<ffi.Float Function(ffi.Pointer<ffi.Void>)>>(
+              "org_apache_pdfbox_text_PDFTextStripper_getSpacingTolerance")
+          .asFunction<double Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: public float getSpacingTolerance()
+  ///
+  /// 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);
+
+  static final _setSpacingTolerance = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Float)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_setSpacingTolerance")
+      .asFunction<void Function(ffi.Pointer<ffi.Void>, double)>();
+
+  /// from: public void setSpacingTolerance(float spacingToleranceValue)
+  ///
+  /// Set the space width-based tolerance value that is used to estimate where spaces in text should be added. Note
+  /// 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);
+
+  static final _getAverageCharTolerance =
+      jlookup<ffi.NativeFunction<ffi.Float Function(ffi.Pointer<ffi.Void>)>>(
+              "org_apache_pdfbox_text_PDFTextStripper_getAverageCharTolerance")
+          .asFunction<double Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: public float getAverageCharTolerance()
+  ///
+  /// 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);
+
+  static final _setAverageCharTolerance = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Float)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_setAverageCharTolerance")
+      .asFunction<void Function(ffi.Pointer<ffi.Void>, double)>();
+
+  /// from: public void setAverageCharTolerance(float averageCharToleranceValue)
+  ///
+  /// Set the character width-based tolerance value that is used to estimate where spaces in text should be added. Note
+  /// 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);
+
+  static final _getIndentThreshold =
+      jlookup<ffi.NativeFunction<ffi.Float Function(ffi.Pointer<ffi.Void>)>>(
+              "org_apache_pdfbox_text_PDFTextStripper_getIndentThreshold")
+          .asFunction<double Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: public float getIndentThreshold()
+  ///
+  /// 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);
+
+  static final _setIndentThreshold = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Float)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_setIndentThreshold")
+      .asFunction<void Function(ffi.Pointer<ffi.Void>, double)>();
+
+  /// from: public void setIndentThreshold(float indentThresholdValue)
+  ///
+  /// sets 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.
+  /// 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);
+
+  static final _getDropThreshold =
+      jlookup<ffi.NativeFunction<ffi.Float Function(ffi.Pointer<ffi.Void>)>>(
+              "org_apache_pdfbox_text_PDFTextStripper_getDropThreshold")
+          .asFunction<double Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: public float getDropThreshold()
+  ///
+  /// 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);
+
+  static final _setDropThreshold = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Float)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_setDropThreshold")
+      .asFunction<void Function(ffi.Pointer<ffi.Void>, double)>();
+
+  /// from: public void setDropThreshold(float dropThresholdValue)
+  ///
+  /// sets 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. 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);
+
+  static final _getParagraphStart = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_getParagraphStart")
+      .asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: public java.lang.String getParagraphStart()
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// 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));
+
+  static final _setParagraphStart = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_setParagraphStart")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: public void setParagraphStart(java.lang.String s)
+  ///
+  /// 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);
+
+  static final _getParagraphEnd = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_getParagraphEnd")
+      .asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: public java.lang.String getParagraphEnd()
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// 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));
+
+  static final _setParagraphEnd = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_setParagraphEnd")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: public void setParagraphEnd(java.lang.String s)
+  ///
+  /// 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);
+
+  static final _getPageStart = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_getPageStart")
+      .asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: public java.lang.String getPageStart()
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// 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));
+
+  static final _setPageStart = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_setPageStart")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: public void setPageStart(java.lang.String pageStartValue)
+  ///
+  /// 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);
+
+  static final _getPageEnd = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_getPageEnd")
+      .asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: public java.lang.String getPageEnd()
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// 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));
+
+  static final _setPageEnd = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_setPageEnd")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: public void setPageEnd(java.lang.String pageEndValue)
+  ///
+  /// 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);
+
+  static final _getArticleStart = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_getArticleStart")
+      .asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: public java.lang.String getArticleStart()
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// 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));
+
+  static final _setArticleStart = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_setArticleStart")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: public void setArticleStart(java.lang.String articleStartValue)
+  ///
+  /// 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);
+
+  static final _getArticleEnd = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_getArticleEnd")
+      .asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: public java.lang.String getArticleEnd()
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// 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));
+
+  static final _setArticleEnd = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_setArticleEnd")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: public void setArticleEnd(java.lang.String articleEndValue)
+  ///
+  /// 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);
+
+  static final _handleLineSeparation = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(
+                      ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>,
+                      ffi.Float)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_handleLineSeparation")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+              ffi.Pointer<ffi.Void>,
+              ffi.Pointer<ffi.Void>,
+              ffi.Pointer<ffi.Void>,
+              ffi.Pointer<ffi.Void>,
+              double)>();
+
+  /// from: private org.apache.pdfbox.text.PDFTextStripper.PositionWrapper handleLineSeparation(org.apache.pdfbox.text.PDFTextStripper.PositionWrapper current, org.apache.pdfbox.text.PDFTextStripper.PositionWrapper lastPosition, org.apache.pdfbox.text.PDFTextStripper.PositionWrapper lastLineStartPosition, float maxHeightForLine)
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// handles the line separator for a new line given the specified current and previous TextPositions.
+  ///@param current the current text position
+  ///@param lastPosition the previous text position
+  ///@param lastLineStartPosition the last text position that followed a line separator.
+  ///@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));
+
+  static final _isParagraphSeparation = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>,
+                      ffi.Float)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_isParagraphSeparation")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>, double)>();
+
+  /// from: private void isParagraphSeparation(org.apache.pdfbox.text.PDFTextStripper.PositionWrapper position, org.apache.pdfbox.text.PDFTextStripper.PositionWrapper lastPosition, org.apache.pdfbox.text.PDFTextStripper.PositionWrapper lastLineStartPosition, float maxHeightForLine)
+  ///
+  /// tests the relationship between the last text position, the current text position and the last text position that
+  /// followed a line separator to decide if the gap represents a paragraph separation. This should <i>only</i> be
+  /// called for consecutive text positions that first pass the line separation test.
+  ///
+  /// This base implementation tests to see if the lastLineStartPosition is null OR if the current vertical position
+  /// has dropped below the last text vertical position by at least 2.5 times the current text height OR if the current
+  /// horizontal position is indented by at least 2 times the current width of a space character.
+  ///
+  ///
+  ///
+  /// This also attempts to identify text that is indented under a hanging indent.
+  ///
+  ///
+  ///
+  /// This method sets the isParagraphStart and isHangingIndent flags on the current position object.
+  ///
+  ///
+  ///@param position the current text position. This may have its isParagraphStart or isHangingIndent flags set upon
+  /// return.
+  ///@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);
+
+  static final _multiplyFloat = jlookup<
+              ffi.NativeFunction<
+                  ffi.Float Function(
+                      ffi.Pointer<ffi.Void>, ffi.Float, ffi.Float)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_multiplyFloat")
+      .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);
+
+  static final _writeParagraphSeparator =
+      jlookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
+              "org_apache_pdfbox_text_PDFTextStripper_writeParagraphSeparator")
+          .asFunction<void Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: protected void writeParagraphSeparator()
+  ///
+  /// writes the paragraph separator string to the output.
+  ///@throws IOException if something went wrong
+  void writeParagraphSeparator() => _writeParagraphSeparator(reference);
+
+  static final _writeParagraphStart =
+      jlookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
+              "org_apache_pdfbox_text_PDFTextStripper_writeParagraphStart")
+          .asFunction<void Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: protected void writeParagraphStart()
+  ///
+  /// Write something (if defined) at the start of a paragraph.
+  ///@throws IOException if something went wrong
+  void writeParagraphStart() => _writeParagraphStart(reference);
+
+  static final _writeParagraphEnd =
+      jlookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
+              "org_apache_pdfbox_text_PDFTextStripper_writeParagraphEnd")
+          .asFunction<void Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: protected void writeParagraphEnd()
+  ///
+  /// Write something (if defined) at the end of a paragraph.
+  ///@throws IOException if something went wrong
+  void writeParagraphEnd() => _writeParagraphEnd(reference);
+
+  static final _writePageStart =
+      jlookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
+              "org_apache_pdfbox_text_PDFTextStripper_writePageStart")
+          .asFunction<void Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: protected void writePageStart()
+  ///
+  /// Write something (if defined) at the start of a page.
+  ///@throws IOException if something went wrong
+  void writePageStart() => _writePageStart(reference);
+
+  static final _writePageEnd =
+      jlookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
+              "org_apache_pdfbox_text_PDFTextStripper_writePageEnd")
+          .asFunction<void Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: protected void writePageEnd()
+  ///
+  /// Write something (if defined) at the end of a page.
+  ///@throws IOException if something went wrong
+  void writePageEnd() => _writePageEnd(reference);
+
+  static final _matchListItemPattern = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_matchListItemPattern")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: private java.util.regex.Pattern matchListItemPattern(org.apache.pdfbox.text.PDFTextStripper.PositionWrapper pw)
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// returns the list item Pattern object that matches the text at the specified PositionWrapper or null if the text
+  /// does not match such a pattern. The list of Patterns tested against is given by the \#getListItemPatterns()
+  /// method. To add to the list, simply override that method (if sub-classing) or explicitly supply your own list
+  /// using \#setListItemPatterns(List).
+  ///@param pw position
+  ///@return the matching pattern
+  jni.JlObject matchListItemPattern(jni.JlObject pw) =>
+      jni.JlObject.fromRef(_matchListItemPattern(reference, pw.reference));
+
+  static final _setListItemPatterns = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_setListItemPatterns")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: protected void setListItemPatterns(java.util.List<java.util.regex.Pattern> patterns)
+  ///
+  /// 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);
+
+  static final _getListItemPatterns = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_getListItemPatterns")
+      .asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: protected java.util.List<java.util.regex.Pattern> getListItemPatterns()
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// returns a list of regular expression Patterns representing different common list item formats. For example
+  /// numbered items of form:
+  /// <ol>
+  /// <li>some text</li>
+  /// <li>more text</li>
+  /// </ol>
+  /// or
+  /// <ul>
+  /// <li>some text</li>
+  /// <li>more text</li>
+  /// </ul>
+  /// etc., all begin with some character pattern. The pattern "\\d+\." (matches "1.", "2.", ...) or "\[\\d+\]"
+  /// (matches "[1]", "[2]", ...).
+  ///
+  /// This method returns a list of such regular expression Patterns.
+  ///@return a list of Pattern objects.
+  jni.JlObject getListItemPatterns() =>
+      jni.JlObject.fromRef(_getListItemPatterns(reference));
+
+  static final _matchPattern = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_matchPattern")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: static protected java.util.regex.Pattern matchPattern(java.lang.String string, java.util.List<java.util.regex.Pattern> patterns)
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// iterates over the specified list of Patterns until it finds one that matches the specified string. Then returns
+  /// the Pattern.
+  ///
+  /// Order of the supplied list of patterns is important as most common patterns should come first. Patterns should be
+  /// strict in general, and all will be used with case sensitivity on.
+  ///
+  ///
+  ///@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 final _writeLine = jlookup<
+              ffi.NativeFunction<
+                  ffi.Void Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_writeLine")
+      .asFunction<
+          void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: private void writeLine(java.util.List<org.apache.pdfbox.text.PDFTextStripper.WordWithTextPositions> line)
+  ///
+  /// 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);
+
+  static final _normalize = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_normalize")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: private java.util.List<org.apache.pdfbox.text.PDFTextStripper.WordWithTextPositions> normalize(java.util.List<org.apache.pdfbox.text.PDFTextStripper.LineItem> line)
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// 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));
+
+  static final _handleDirection = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_handleDirection")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: private java.lang.String handleDirection(java.lang.String word)
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// Handles the LTR and RTL direction of the given words. The whole implementation stands and falls with the given
+  /// word. If the word is a full line, the results will be the best. If the word contains of single words or
+  /// characters, the order of the characters in a word or words in a line may wrong, due to RTL and LTR marks and
+  /// characters!
+  ///
+  /// 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));
+
+  static final _parseBidiFile =
+      jlookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
+              "org_apache_pdfbox_text_PDFTextStripper_parseBidiFile")
+          .asFunction<void Function(ffi.Pointer<ffi.Void>)>();
+
+  /// from: private static void parseBidiFile(java.io.InputStream inputStream)
+  ///
+  /// 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 final _createWord = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_createWord")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>,
+              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: private org.apache.pdfbox.text.PDFTextStripper.WordWithTextPositions createWord(java.lang.String word, java.util.List<org.apache.pdfbox.text.TextPosition> wordPositions)
+  /// 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));
+
+  static final _normalizeWord = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(
+                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_normalizeWord")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+  /// from: private java.lang.String normalizeWord(java.lang.String word)
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// Normalize certain Unicode characters. For example, convert the single "fi" ligature to "f" and "i". Also
+  /// 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));
+
+  static final _normalizeAdd = jlookup<
+              ffi.NativeFunction<
+                  ffi.Pointer<ffi.Void> Function(
+                      ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>,
+                      ffi.Pointer<ffi.Void>)>>(
+          "org_apache_pdfbox_text_PDFTextStripper_normalizeAdd")
+      .asFunction<
+          ffi.Pointer<ffi.Void> Function(
+              ffi.Pointer<ffi.Void>,
+              ffi.Pointer<ffi.Void>,
+              ffi.Pointer<ffi.Void>,
+              ffi.Pointer<ffi.Void>,
+              ffi.Pointer<ffi.Void>)>();
+
+  /// from: private java.lang.StringBuilder normalizeAdd(java.util.List<org.apache.pdfbox.text.PDFTextStripper.WordWithTextPositions> normalized, java.lang.StringBuilder lineBuilder, java.util.List<org.apache.pdfbox.text.TextPosition> wordPositions, org.apache.pdfbox.text.PDFTextStripper.LineItem item)
+  /// The returned object must be deleted after use, by calling the `delete` method.
+  ///
+  /// 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));
+}
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/linux/CMakeLists.txt b/pkgs/jni_gen/examples/pdfbox_plugin/linux/CMakeLists.txt
new file mode 100644
index 0000000..986e388
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/linux/CMakeLists.txt
@@ -0,0 +1,22 @@
+# The Flutter tooling requires that developers have CMake 3.10 or later
+# installed. You should not increase this version, as doing so will cause
+# the plugin to fail to compile for some customers of the plugin.
+cmake_minimum_required(VERSION 3.10)
+
+# Project-level configuration.
+set(PROJECT_NAME "pdfbox_plugin")
+project(${PROJECT_NAME} LANGUAGES CXX)
+
+# Invoke the build for native code shared with the other target platforms.
+# This can be changed to accomodate different builds.
+add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/../src" "${CMAKE_CURRENT_BINARY_DIR}/shared")
+
+# List of absolute paths to libraries that should be bundled with the plugin.
+# This list could contain prebuilt libraries, or libraries created by an
+# external build triggered from this build file.
+set(pdfbox_plugin_bundled_libraries
+  # Defined in ../src/CMakeLists.txt.
+  # This can be changed to accomodate different builds.
+  $<TARGET_FILE:pdfbox_plugin>
+  PARENT_SCOPE
+)
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/pubspec.yaml b/pkgs/jni_gen/examples/pdfbox_plugin/pubspec.yaml
new file mode 100644
index 0000000..7ec1e1f
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/pubspec.yaml
@@ -0,0 +1,38 @@
+name: pdfbox_plugin
+description: |
+  Example of using jni_gen to generate bindings for a non-trivial library
+version: 0.0.1
+publish_to: none
+homepage: https://github.com/dart-lang/jni_gen
+
+environment:
+  sdk: ">=2.17.6 <3.0.0"
+  #flutter: ">=2.11.0"
+
+dependencies:
+  jni:
+    path: ../../../jni/
+  #flutter:
+    #sdk: flutter
+  plugin_platform_interface: ^2.0.2
+
+dev_dependencies:
+  ## Path dependency for sake of the example
+  jni_gen:
+    path: ../../
+  test: any
+  lints: ^2.0.0
+
+flutter:
+  # A JNI plugin uses FFI for calling into C code. Thus the relevant shared
+  # library artifacts must be bundled with final application.
+  # Please refer to README.md for a detailed explanation.
+  plugin:
+    platforms:
+      android:
+        ffiPlugin: true
+      linux:
+        ffiPlugin: true
+      windows:
+        ffiPlugin: true
+
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/src/CMakeLists.txt b/pkgs/jni_gen/examples/pdfbox_plugin/src/CMakeLists.txt
new file mode 100644
index 0000000..4ed5b3d
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/src/CMakeLists.txt
@@ -0,0 +1,30 @@
+# The Flutter tooling requires that developers have CMake 3.10 or later
+# installed. You should not increase this version, as doing so will cause
+# the plugin to fail to compile for some customers of the plugin.
+cmake_minimum_required(VERSION 3.10)
+
+project(pdfbox_plugin VERSION 0.0.1 LANGUAGES C)
+
+add_library(pdfbox_plugin SHARED
+  "third_party//pdfbox_plugin.c"
+)
+
+set_target_properties(pdfbox_plugin PROPERTIES
+  OUTPUT_NAME "pdfbox_plugin"
+)
+
+target_compile_definitions(pdfbox_plugin PUBLIC DART_SHARED_LIB)
+
+if(WIN32)
+	set_target_properties(${TARGET_NAME} PROPERTIES
+		LINK_FLAGS "/DELAYLOAD:jvm.dll")
+endif()
+
+if (ANDROID)
+	target_link_libraries(pdfbox_plugin log)
+else()
+	find_package(Java REQUIRED)
+	find_package(JNI REQUIRED)
+	include_directories(${JNI_INCLUDE_DIRS})
+	target_link_libraries(pdfbox_plugin ${JNI_LIBRARIES})
+endif()
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/src/third_party/dartjni.h b/pkgs/jni_gen/examples/pdfbox_plugin/src/third_party/dartjni.h
new file mode 100644
index 0000000..cd94b15
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/src/third_party/dartjni.h
@@ -0,0 +1,177 @@
+// 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/jni_gen/examples/pdfbox_plugin/src/third_party/pdfbox_plugin.c b/pkgs/jni_gen/examples/pdfbox_plugin/src/third_party/pdfbox_plugin.c
new file mode 100644
index 0000000..a4f00da
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/src/third_party/pdfbox_plugin.c
@@ -0,0 +1,2548 @@
+// 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.
+
+// Autogenerated by jni_gen. DO NOT EDIT!
+
+#include <stdint.h>
+#include "jni.h"
+#include "dartjni.h"
+
+thread_local JNIEnv *jniEnv;
+struct jni_context jni;
+
+struct jni_context (*context_getter)(void);
+JNIEnv *(*env_getter)(void);
+
+void setJniGetters(struct jni_context (*cg)(void),
+        JNIEnv *(*eg)(void)) {
+    context_getter = cg;
+    env_getter = eg;
+}
+
+// org.apache.pdfbox.pdmodel.PDDocument
+jclass _c_org_apache_pdfbox_pdmodel_PDDocument = NULL;
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_ctor = NULL;
+FFI_PLUGIN_EXPORT
+jobject org_apache_pdfbox_pdmodel_PDDocument_ctor() {
+    load_env();
+    load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_ctor, "<init>", "()V");
+    jobject _result = (*jniEnv)->NewObject(jniEnv, _c_org_apache_pdfbox_pdmodel_PDDocument, _m_org_apache_pdfbox_pdmodel_PDDocument_ctor);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_ctor1 = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_ctor1, "<init>", "(Lorg/apache/pdfbox/io/MemoryUsageSetting;)V");
+    jobject _result = (*jniEnv)->NewObject(jniEnv, _c_org_apache_pdfbox_pdmodel_PDDocument, _m_org_apache_pdfbox_pdmodel_PDDocument_ctor1, memUsageSetting);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_ctor2 = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_ctor2, "<init>", "(Lorg/apache/pdfbox/cos/COSDocument;)V");
+    jobject _result = (*jniEnv)->NewObject(jniEnv, _c_org_apache_pdfbox_pdmodel_PDDocument, _m_org_apache_pdfbox_pdmodel_PDDocument_ctor2, doc);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_ctor3 = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    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");
+    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);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_ctor4 = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    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");
+    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);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_addPage = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_addPage, "addPage", "(Lorg/apache/pdfbox/pdmodel/PDPage;)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_addPage, page);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_addSignature = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_addSignature, "addSignature", "(Lorg/apache/pdfbox/pdmodel/interactive/digitalsignature/PDSignature;)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_addSignature, sigObject);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_addSignature1 = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    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");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_addSignature1, sigObject, options);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_addSignature2 = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    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");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_addSignature2, sigObject, signatureInterface);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_addSignature3 = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    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");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_addSignature3, sigObject, signatureInterface, options);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_findSignatureField = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    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;");
+    jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_findSignatureField, fieldIterator, sigObject);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_checkSignatureField = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    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");
+    uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_checkSignatureField, fieldIterator, signatureField);
+    return _result;
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_checkSignatureAnnotation = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    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");
+    uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_checkSignatureAnnotation, annotations, widget);
+    return _result;
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_prepareVisibleSignature = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    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");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_prepareVisibleSignature, signatureField, acroForm, visualSignature);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_assignSignatureRectangle = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    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");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_assignSignatureRectangle, signatureField, annotDict);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_assignAppearanceDictionary = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    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");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_assignAppearanceDictionary, signatureField, apDict);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_assignAcroFormDefaultResource = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    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");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_assignAcroFormDefaultResource, acroForm, newDict);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_prepareNonVisibleSignature = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_prepareNonVisibleSignature, "prepareNonVisibleSignature", "(Lorg/apache/pdfbox/pdmodel/interactive/form/PDSignatureField;)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_prepareNonVisibleSignature, signatureField);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_addSignatureField = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    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");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_addSignatureField, sigFields, signatureInterface, options);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_removePage = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_removePage, "removePage", "(Lorg/apache/pdfbox/pdmodel/PDPage;)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_removePage, page);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_removePage1 = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_removePage1, "removePage", "(I)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_removePage1, pageNumber);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_importPage = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    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;");
+    jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_importPage, page);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_getDocument = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_getDocument, "getDocument", "()Lorg/apache/pdfbox/cos/COSDocument;");
+    jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_getDocument);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_getDocumentInformation = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_getDocumentInformation, "getDocumentInformation", "()Lorg/apache/pdfbox/pdmodel/PDDocumentInformation;");
+    jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_getDocumentInformation);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_setDocumentInformation = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_setDocumentInformation, "setDocumentInformation", "(Lorg/apache/pdfbox/pdmodel/PDDocumentInformation;)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_setDocumentInformation, info);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_getDocumentCatalog = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_getDocumentCatalog, "getDocumentCatalog", "()Lorg/apache/pdfbox/pdmodel/PDDocumentCatalog;");
+    jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_getDocumentCatalog);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_isEncrypted = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_isEncrypted, "isEncrypted", "()Z");
+    uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_isEncrypted);
+    return _result;
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_getEncryption = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_getEncryption, "getEncryption", "()Lorg/apache/pdfbox/pdmodel/encryption/PDEncryption;");
+    jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_getEncryption);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_setEncryptionDictionary = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_setEncryptionDictionary, "setEncryptionDictionary", "(Lorg/apache/pdfbox/pdmodel/encryption/PDEncryption;)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_setEncryptionDictionary, encryption);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_getLastSignatureDictionary = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_getLastSignatureDictionary, "getLastSignatureDictionary", "()Lorg/apache/pdfbox/pdmodel/interactive/digitalsignature/PDSignature;");
+    jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_getLastSignatureDictionary);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_getSignatureFields = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_getSignatureFields, "getSignatureFields", "()Ljava/util/List;");
+    jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_getSignatureFields);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_getSignatureDictionaries = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_getSignatureDictionaries, "getSignatureDictionaries", "()Ljava/util/List;");
+    jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_getSignatureDictionaries);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_registerTrueTypeFontForClosing = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_registerTrueTypeFontForClosing, "registerTrueTypeFontForClosing", "(Lorg/apache/fontbox/ttf/TrueTypeFont;)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_registerTrueTypeFontForClosing, ttf);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_getFontsToSubset = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_getFontsToSubset, "getFontsToSubset", "()Ljava/util/Set;");
+    jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_getFontsToSubset);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_load = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    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;");
+    jobject _result = (*jniEnv)->CallStaticObjectMethod(jniEnv, _c_org_apache_pdfbox_pdmodel_PDDocument, _m_org_apache_pdfbox_pdmodel_PDDocument_load, file);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_load1 = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    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;");
+    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);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_load2 = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    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;");
+    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);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_load3 = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    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;");
+    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);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_load4 = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    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;");
+    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);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_load5 = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    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;");
+    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);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_load6 = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    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;");
+    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);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_load7 = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    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;");
+    jobject _result = (*jniEnv)->CallStaticObjectMethod(jniEnv, _c_org_apache_pdfbox_pdmodel_PDDocument, _m_org_apache_pdfbox_pdmodel_PDDocument_load7, input);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_load8 = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    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;");
+    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);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_load9 = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    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;");
+    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);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_load10 = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    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;");
+    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);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_load11 = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    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;");
+    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);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_load12 = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    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;");
+    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);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_load13 = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_static_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_load13, "load", "(L[B;)Lorg/apache/pdfbox/pdmodel/PDDocument;");
+    jobject _result = (*jniEnv)->CallStaticObjectMethod(jniEnv, _c_org_apache_pdfbox_pdmodel_PDDocument, _m_org_apache_pdfbox_pdmodel_PDDocument_load13, input);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_load14 = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    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;");
+    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);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_load15 = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    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;");
+    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);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_load16 = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    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;");
+    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);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_save = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_save, "save", "(Ljava/lang/String;)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_save, fileName);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_save1 = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_save1, "save", "(Ljava/io/File;)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_save1, file);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_save2 = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_save2, "save", "(Ljava/io/OutputStream;)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_save2, output);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_saveIncremental = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_saveIncremental, "saveIncremental", "(Ljava/io/OutputStream;)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_saveIncremental, output);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_saveIncremental1 = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_saveIncremental1, "saveIncremental", "(Ljava/io/OutputStream;Ljava/util/Set;)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_saveIncremental1, output, objectsToWrite);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_saveIncrementalForExternalSigning = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    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;");
+    jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_saveIncrementalForExternalSigning, output);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_getPage = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_getPage, "getPage", "(I)Lorg/apache/pdfbox/pdmodel/PDPage;");
+    jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_getPage, pageIndex);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_getPages = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_getPages, "getPages", "()Lorg/apache/pdfbox/pdmodel/PDPageTree;");
+    jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_getPages);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_getNumberOfPages = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_getNumberOfPages, "getNumberOfPages", "()I");
+    int32_t _result = (*jniEnv)->CallIntMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_getNumberOfPages);
+    return _result;
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_close = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_close, "close", "()V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_close);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_protect = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_protect, "protect", "(Lorg/apache/pdfbox/pdmodel/encryption/ProtectionPolicy;)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_protect, policy);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_getCurrentAccessPermission = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_getCurrentAccessPermission, "getCurrentAccessPermission", "()Lorg/apache/pdfbox/pdmodel/encryption/AccessPermission;");
+    jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_getCurrentAccessPermission);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_isAllSecurityToBeRemoved = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_isAllSecurityToBeRemoved, "isAllSecurityToBeRemoved", "()Z");
+    uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_isAllSecurityToBeRemoved);
+    return _result;
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_setAllSecurityToBeRemoved = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_setAllSecurityToBeRemoved, "setAllSecurityToBeRemoved", "(Z)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_setAllSecurityToBeRemoved, removeAllSecurity);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_getDocumentId = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_getDocumentId, "getDocumentId", "()Ljava/lang/Long;");
+    jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_getDocumentId);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_setDocumentId = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_setDocumentId, "setDocumentId", "(Ljava/lang/Long;)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_setDocumentId, docId);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_getVersion = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_getVersion, "getVersion", "()F");
+    float _result = (*jniEnv)->CallFloatMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_getVersion);
+    return _result;
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_setVersion = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_setVersion, "setVersion", "(F)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_setVersion, newVersion);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_getResourceCache = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_getResourceCache, "getResourceCache", "()Lorg/apache/pdfbox/pdmodel/ResourceCache;");
+    jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_getResourceCache);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocument_setResourceCache = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocument, &_m_org_apache_pdfbox_pdmodel_PDDocument_setResourceCache, "setResourceCache", "(Lorg/apache/pdfbox/pdmodel/ResourceCache;)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocument_setResourceCache, resourceCache);
+}
+
+jfieldID _f_org_apache_pdfbox_pdmodel_PDDocument_RESERVE_BYTE_RANGE = NULL;
+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");
+    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));
+}
+
+
+jfieldID _f_org_apache_pdfbox_pdmodel_PDDocument_LOG = NULL;
+jobject get_org_apache_pdfbox_pdmodel_PDDocument_LOG() {
+    load_env();
+    load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+    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));
+}
+
+
+jfieldID _f_org_apache_pdfbox_pdmodel_PDDocument_document = NULL;
+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");
+    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));
+}
+
+
+jfieldID _f_org_apache_pdfbox_pdmodel_PDDocument_documentInformation = NULL;
+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");
+    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));
+}
+
+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");
+    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));
+}
+
+
+jfieldID _f_org_apache_pdfbox_pdmodel_PDDocument_documentCatalog = NULL;
+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");
+    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));
+}
+
+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");
+    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));
+}
+
+
+jfieldID _f_org_apache_pdfbox_pdmodel_PDDocument_encryption = NULL;
+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");
+    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));
+}
+
+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");
+    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));
+}
+
+
+jfieldID _f_org_apache_pdfbox_pdmodel_PDDocument_allSecurityToBeRemoved = NULL;
+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");
+    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));
+}
+
+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");
+    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));
+}
+
+
+jfieldID _f_org_apache_pdfbox_pdmodel_PDDocument_documentId = NULL;
+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");
+    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));
+}
+
+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");
+    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));
+}
+
+
+jfieldID _f_org_apache_pdfbox_pdmodel_PDDocument_pdfSource = NULL;
+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");
+    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));
+}
+
+
+jfieldID _f_org_apache_pdfbox_pdmodel_PDDocument_accessPermission = NULL;
+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");
+    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));
+}
+
+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");
+    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));
+}
+
+
+jfieldID _f_org_apache_pdfbox_pdmodel_PDDocument_fontsToSubset = NULL;
+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");
+    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));
+}
+
+
+jfieldID _f_org_apache_pdfbox_pdmodel_PDDocument_fontsToClose = NULL;
+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");
+    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));
+}
+
+
+jfieldID _f_org_apache_pdfbox_pdmodel_PDDocument_signInterface = NULL;
+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");
+    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));
+}
+
+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");
+    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));
+}
+
+
+jfieldID _f_org_apache_pdfbox_pdmodel_PDDocument_signingSupport = NULL;
+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");
+    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));
+}
+
+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");
+    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));
+}
+
+
+jfieldID _f_org_apache_pdfbox_pdmodel_PDDocument_resourceCache = NULL;
+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");
+    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));
+}
+
+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");
+    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));
+}
+
+
+jfieldID _f_org_apache_pdfbox_pdmodel_PDDocument_signatureAdded = NULL;
+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");
+    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));
+}
+
+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");
+    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));
+}
+
+
+// org.apache.pdfbox.pdmodel.PDDocumentInformation
+jclass _c_org_apache_pdfbox_pdmodel_PDDocumentInformation = NULL;
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_ctor = NULL;
+FFI_PLUGIN_EXPORT
+jobject org_apache_pdfbox_pdmodel_PDDocumentInformation_ctor() {
+    load_env();
+    load_class_gr(&_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, &_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_ctor, "<init>", "()V");
+    jobject _result = (*jniEnv)->NewObject(jniEnv, _c_org_apache_pdfbox_pdmodel_PDDocumentInformation, _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_ctor);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_ctor1 = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, &_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_ctor1, "<init>", "(Lorg/apache/pdfbox/cos/COSDictionary;)V");
+    jobject _result = (*jniEnv)->NewObject(jniEnv, _c_org_apache_pdfbox_pdmodel_PDDocumentInformation, _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_ctor1, dic);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getCOSObject = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, &_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getCOSObject, "getCOSObject", "()Lorg/apache/pdfbox/cos/COSDictionary;");
+    jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getCOSObject);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getPropertyStringValue = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, &_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getPropertyStringValue, "getPropertyStringValue", "(Ljava/lang/String;)Ljava/lang/Object;");
+    jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getPropertyStringValue, propertyKey);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getTitle = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, &_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getTitle, "getTitle", "()Ljava/lang/String;");
+    jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getTitle);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setTitle = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, &_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setTitle, "setTitle", "(Ljava/lang/String;)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setTitle, title);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getAuthor = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, &_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getAuthor, "getAuthor", "()Ljava/lang/String;");
+    jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getAuthor);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setAuthor = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, &_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setAuthor, "setAuthor", "(Ljava/lang/String;)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setAuthor, author);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getSubject = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, &_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getSubject, "getSubject", "()Ljava/lang/String;");
+    jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getSubject);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setSubject = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, &_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setSubject, "setSubject", "(Ljava/lang/String;)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setSubject, subject);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getKeywords = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, &_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getKeywords, "getKeywords", "()Ljava/lang/String;");
+    jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getKeywords);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setKeywords = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, &_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setKeywords, "setKeywords", "(Ljava/lang/String;)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setKeywords, keywords);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getCreator = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, &_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getCreator, "getCreator", "()Ljava/lang/String;");
+    jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getCreator);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setCreator = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, &_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setCreator, "setCreator", "(Ljava/lang/String;)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setCreator, creator);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getProducer = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, &_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getProducer, "getProducer", "()Ljava/lang/String;");
+    jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getProducer);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setProducer = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, &_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setProducer, "setProducer", "(Ljava/lang/String;)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setProducer, producer);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getCreationDate = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, &_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getCreationDate, "getCreationDate", "()Ljava/util/Calendar;");
+    jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getCreationDate);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setCreationDate = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, &_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setCreationDate, "setCreationDate", "(Ljava/util/Calendar;)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setCreationDate, date);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getModificationDate = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, &_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getModificationDate, "getModificationDate", "()Ljava/util/Calendar;");
+    jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getModificationDate);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setModificationDate = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, &_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setModificationDate, "setModificationDate", "(Ljava/util/Calendar;)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setModificationDate, date);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getTrapped = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, &_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getTrapped, "getTrapped", "()Ljava/lang/String;");
+    jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getTrapped);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getMetadataKeys = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, &_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getMetadataKeys, "getMetadataKeys", "()Ljava/util/Set;");
+    jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getMetadataKeys);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getCustomMetadataValue = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, &_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getCustomMetadataValue, "getCustomMetadataValue", "(Ljava/lang/String;)Ljava/lang/String;");
+    jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_getCustomMetadataValue, fieldName);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setCustomMetadataValue = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, &_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setCustomMetadataValue, "setCustomMetadataValue", "(Ljava/lang/String;Ljava/lang/String;)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setCustomMetadataValue, fieldName, fieldValue);
+}
+
+jmethodID _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setTrapped = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_pdmodel_PDDocumentInformation, &_m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setTrapped, "setTrapped", "(Ljava/lang/String;)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_pdmodel_PDDocumentInformation_setTrapped, value);
+}
+
+jfieldID _f_org_apache_pdfbox_pdmodel_PDDocumentInformation_info = NULL;
+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");
+    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));
+}
+
+
+// org.apache.pdfbox.text.PDFTextStripper
+jclass _c_org_apache_pdfbox_text_PDFTextStripper = NULL;
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_ctor = NULL;
+FFI_PLUGIN_EXPORT
+jobject org_apache_pdfbox_text_PDFTextStripper_ctor() {
+    load_env();
+    load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_ctor, "<init>", "()V");
+    jobject _result = (*jniEnv)->NewObject(jniEnv, _c_org_apache_pdfbox_text_PDFTextStripper, _m_org_apache_pdfbox_text_PDFTextStripper_ctor);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_getText = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_getText, "getText", "(Lorg/apache/pdfbox/pdmodel/PDDocument;)Ljava/lang/String;");
+    jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_getText, doc);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_resetEngine = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_resetEngine, "resetEngine", "()V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_resetEngine);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_writeText = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    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");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_writeText, doc, outputStream);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_processPages = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_processPages, "processPages", "(Lorg/apache/pdfbox/pdmodel/PDPageTree;)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_processPages, pages);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_startDocument = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_startDocument, "startDocument", "(Lorg/apache/pdfbox/pdmodel/PDDocument;)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_startDocument, document);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_endDocument = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_endDocument, "endDocument", "(Lorg/apache/pdfbox/pdmodel/PDDocument;)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_endDocument, document);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_processPage = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_processPage, "processPage", "(Lorg/apache/pdfbox/pdmodel/PDPage;)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_processPage, page);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_fillBeadRectangles = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_fillBeadRectangles, "fillBeadRectangles", "(Lorg/apache/pdfbox/pdmodel/PDPage;)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_fillBeadRectangles, page);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_startArticle = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_startArticle, "startArticle", "()V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_startArticle);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_startArticle1 = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_startArticle1, "startArticle", "(Z)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_startArticle1, isLTR);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_endArticle = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_endArticle, "endArticle", "()V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_endArticle);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_startPage1 = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_startPage1, "startPage", "(Lorg/apache/pdfbox/pdmodel/PDPage;)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_startPage1, page);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_endPage1 = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_endPage1, "endPage", "(Lorg/apache/pdfbox/pdmodel/PDPage;)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_endPage1, page);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_writePage = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_writePage, "writePage", "()V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_writePage);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_overlap = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_overlap, "overlap", "(FFFF)Z");
+    uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_overlap, y1, height1, y2, height2);
+    return _result;
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_writeLineSeparator = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_writeLineSeparator, "writeLineSeparator", "()V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_writeLineSeparator);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_writeWordSeparator = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_writeWordSeparator, "writeWordSeparator", "()V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_writeWordSeparator);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_writeCharacters = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_writeCharacters, "writeCharacters", "(Lorg/apache/pdfbox/text/TextPosition;)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_writeCharacters, text);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_writeString = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_writeString, "writeString", "(Ljava/lang/String;Ljava/util/List;)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_writeString, text, textPositions);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_writeString1 = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_writeString1, "writeString", "(Ljava/lang/String;)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_writeString1, text);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_within = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_within, "within", "(FFF)Z");
+    uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_within, first, second, variance);
+    return _result;
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_processTextPosition = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_processTextPosition, "processTextPosition", "(Lorg/apache/pdfbox/text/TextPosition;)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_processTextPosition, text);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_getStartPage = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_getStartPage, "getStartPage", "()I");
+    int32_t _result = (*jniEnv)->CallIntMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_getStartPage);
+    return _result;
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_setStartPage = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_setStartPage, "setStartPage", "(I)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_setStartPage, startPageValue);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_getEndPage = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_getEndPage, "getEndPage", "()I");
+    int32_t _result = (*jniEnv)->CallIntMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_getEndPage);
+    return _result;
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_setEndPage = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_setEndPage, "setEndPage", "(I)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_setEndPage, endPageValue);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_setLineSeparator = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_setLineSeparator, "setLineSeparator", "(Ljava/lang/String;)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_setLineSeparator, separator);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_getLineSeparator = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_getLineSeparator, "getLineSeparator", "()Ljava/lang/String;");
+    jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_getLineSeparator);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_getWordSeparator = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_getWordSeparator, "getWordSeparator", "()Ljava/lang/String;");
+    jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_getWordSeparator);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_setWordSeparator = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_setWordSeparator, "setWordSeparator", "(Ljava/lang/String;)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_setWordSeparator, separator);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_getSuppressDuplicateOverlappingText = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_getSuppressDuplicateOverlappingText, "getSuppressDuplicateOverlappingText", "()Z");
+    uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_getSuppressDuplicateOverlappingText);
+    return _result;
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_getCurrentPageNo = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_getCurrentPageNo, "getCurrentPageNo", "()I");
+    int32_t _result = (*jniEnv)->CallIntMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_getCurrentPageNo);
+    return _result;
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_getOutput = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_getOutput, "getOutput", "()Ljava/io/Writer;");
+    jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_getOutput);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_getCharactersByArticle = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_getCharactersByArticle, "getCharactersByArticle", "()Ljava/util/List;");
+    jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_getCharactersByArticle);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_setSuppressDuplicateOverlappingText = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_setSuppressDuplicateOverlappingText, "setSuppressDuplicateOverlappingText", "(Z)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_setSuppressDuplicateOverlappingText, suppressDuplicateOverlappingTextValue);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_getSeparateByBeads = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_getSeparateByBeads, "getSeparateByBeads", "()Z");
+    uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_getSeparateByBeads);
+    return _result;
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_setShouldSeparateByBeads = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_setShouldSeparateByBeads, "setShouldSeparateByBeads", "(Z)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_setShouldSeparateByBeads, aShouldSeparateByBeads);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_getEndBookmark = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_getEndBookmark, "getEndBookmark", "()Lorg/apache/pdfbox/pdmodel/interactive/documentnavigation/outline/PDOutlineItem;");
+    jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_getEndBookmark);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_setEndBookmark = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    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");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_setEndBookmark, aEndBookmark);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_getStartBookmark = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_getStartBookmark, "getStartBookmark", "()Lorg/apache/pdfbox/pdmodel/interactive/documentnavigation/outline/PDOutlineItem;");
+    jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_getStartBookmark);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_setStartBookmark = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    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");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_setStartBookmark, aStartBookmark);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_getAddMoreFormatting = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_getAddMoreFormatting, "getAddMoreFormatting", "()Z");
+    uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_getAddMoreFormatting);
+    return _result;
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_setAddMoreFormatting = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_setAddMoreFormatting, "setAddMoreFormatting", "(Z)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_setAddMoreFormatting, newAddMoreFormatting);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_getSortByPosition = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_getSortByPosition, "getSortByPosition", "()Z");
+    uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_getSortByPosition);
+    return _result;
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_setSortByPosition = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_setSortByPosition, "setSortByPosition", "(Z)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_setSortByPosition, newSortByPosition);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_getSpacingTolerance = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_getSpacingTolerance, "getSpacingTolerance", "()F");
+    float _result = (*jniEnv)->CallFloatMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_getSpacingTolerance);
+    return _result;
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_setSpacingTolerance = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_setSpacingTolerance, "setSpacingTolerance", "(F)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_setSpacingTolerance, spacingToleranceValue);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_getAverageCharTolerance = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_getAverageCharTolerance, "getAverageCharTolerance", "()F");
+    float _result = (*jniEnv)->CallFloatMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_getAverageCharTolerance);
+    return _result;
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_setAverageCharTolerance = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_setAverageCharTolerance, "setAverageCharTolerance", "(F)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_setAverageCharTolerance, averageCharToleranceValue);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_getIndentThreshold = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_getIndentThreshold, "getIndentThreshold", "()F");
+    float _result = (*jniEnv)->CallFloatMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_getIndentThreshold);
+    return _result;
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_setIndentThreshold = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_setIndentThreshold, "setIndentThreshold", "(F)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_setIndentThreshold, indentThresholdValue);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_getDropThreshold = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_getDropThreshold, "getDropThreshold", "()F");
+    float _result = (*jniEnv)->CallFloatMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_getDropThreshold);
+    return _result;
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_setDropThreshold = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_setDropThreshold, "setDropThreshold", "(F)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_setDropThreshold, dropThresholdValue);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_getParagraphStart = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_getParagraphStart, "getParagraphStart", "()Ljava/lang/String;");
+    jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_getParagraphStart);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_setParagraphStart = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_setParagraphStart, "setParagraphStart", "(Ljava/lang/String;)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_setParagraphStart, s);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_getParagraphEnd = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_getParagraphEnd, "getParagraphEnd", "()Ljava/lang/String;");
+    jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_getParagraphEnd);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_setParagraphEnd = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_setParagraphEnd, "setParagraphEnd", "(Ljava/lang/String;)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_setParagraphEnd, s);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_getPageStart = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_getPageStart, "getPageStart", "()Ljava/lang/String;");
+    jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_getPageStart);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_setPageStart = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_setPageStart, "setPageStart", "(Ljava/lang/String;)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_setPageStart, pageStartValue);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_getPageEnd = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_getPageEnd, "getPageEnd", "()Ljava/lang/String;");
+    jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_getPageEnd);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_setPageEnd = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_setPageEnd, "setPageEnd", "(Ljava/lang/String;)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_setPageEnd, pageEndValue);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_getArticleStart = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_getArticleStart, "getArticleStart", "()Ljava/lang/String;");
+    jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_getArticleStart);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_setArticleStart = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_setArticleStart, "setArticleStart", "(Ljava/lang/String;)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_setArticleStart, articleStartValue);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_getArticleEnd = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_getArticleEnd, "getArticleEnd", "()Ljava/lang/String;");
+    jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_getArticleEnd);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_setArticleEnd = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_setArticleEnd, "setArticleEnd", "(Ljava/lang/String;)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_setArticleEnd, articleEndValue);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_handleLineSeparation = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    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;");
+    jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_handleLineSeparation, current, lastPosition, lastLineStartPosition, maxHeightForLine);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_isParagraphSeparation = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    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");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_isParagraphSeparation, position, lastPosition, lastLineStartPosition, maxHeightForLine);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_multiplyFloat = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_multiplyFloat, "multiplyFloat", "(FF)F");
+    float _result = (*jniEnv)->CallFloatMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_multiplyFloat, value1, value2);
+    return _result;
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_writeParagraphSeparator = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_writeParagraphSeparator, "writeParagraphSeparator", "()V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_writeParagraphSeparator);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_writeParagraphStart = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_writeParagraphStart, "writeParagraphStart", "()V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_writeParagraphStart);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_writeParagraphEnd = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_writeParagraphEnd, "writeParagraphEnd", "()V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_writeParagraphEnd);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_writePageStart = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_writePageStart, "writePageStart", "()V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_writePageStart);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_writePageEnd = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_writePageEnd, "writePageEnd", "()V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_writePageEnd);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_matchListItemPattern = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    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;");
+    jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_matchListItemPattern, pw);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_setListItemPatterns = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_setListItemPatterns, "setListItemPatterns", "(Ljava/util/List;)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_setListItemPatterns, patterns);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_getListItemPatterns = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_getListItemPatterns, "getListItemPatterns", "()Ljava/util/List;");
+    jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_getListItemPatterns);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_matchPattern = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    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;");
+    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);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_writeLine = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_writeLine, "writeLine", "(Ljava/util/List;)V");
+    (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_writeLine, line);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_normalize = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_normalize, "normalize", "(Ljava/util/List;)Ljava/util/List;");
+    jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_normalize, line);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_handleDirection = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_handleDirection, "handleDirection", "(Ljava/lang/String;)Ljava/lang/String;");
+    jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_handleDirection, word);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_parseBidiFile = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_static_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_parseBidiFile, "parseBidiFile", "(Ljava/io/InputStream;)V");
+    (*jniEnv)->CallStaticVoidMethod(jniEnv, _c_org_apache_pdfbox_text_PDFTextStripper, _m_org_apache_pdfbox_text_PDFTextStripper_parseBidiFile, inputStream);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_createWord = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    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;");
+    jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_createWord, word, wordPositions);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_normalizeWord = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    load_method(_c_org_apache_pdfbox_text_PDFTextStripper, &_m_org_apache_pdfbox_text_PDFTextStripper_normalizeWord, "normalizeWord", "(Ljava/lang/String;)Ljava/lang/String;");
+    jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_normalizeWord, word);
+    return to_global_ref(_result);
+}
+
+jmethodID _m_org_apache_pdfbox_text_PDFTextStripper_normalizeAdd = NULL;
+FFI_PLUGIN_EXPORT
+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");
+    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;");
+    jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_org_apache_pdfbox_text_PDFTextStripper_normalizeAdd, normalized, lineBuilder, wordPositions, item);
+    return to_global_ref(_result);
+}
+
+jfieldID _f_org_apache_pdfbox_text_PDFTextStripper_defaultIndentThreshold = NULL;
+float get_org_apache_pdfbox_text_PDFTextStripper_defaultIndentThreshold() {
+    load_env();
+    load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    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));
+}
+
+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");
+    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));
+}
+
+
+jfieldID _f_org_apache_pdfbox_text_PDFTextStripper_defaultDropThreshold = NULL;
+float get_org_apache_pdfbox_text_PDFTextStripper_defaultDropThreshold() {
+    load_env();
+    load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    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));
+}
+
+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");
+    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));
+}
+
+
+jfieldID _f_org_apache_pdfbox_text_PDFTextStripper_LOG = NULL;
+jobject get_org_apache_pdfbox_text_PDFTextStripper_LOG() {
+    load_env();
+    load_class_gr(&_c_org_apache_pdfbox_text_PDFTextStripper, "org/apache/pdfbox/text/PDFTextStripper");
+    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));
+}
+
+
+jfieldID _f_org_apache_pdfbox_text_PDFTextStripper_LINE_SEPARATOR = NULL;
+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");
+    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));
+}
+
+
+jfieldID _f_org_apache_pdfbox_text_PDFTextStripper_lineSeparator = NULL;
+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");
+    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));
+}
+
+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");
+    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));
+}
+
+
+jfieldID _f_org_apache_pdfbox_text_PDFTextStripper_wordSeparator = NULL;
+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");
+    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));
+}
+
+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");
+    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));
+}
+
+
+jfieldID _f_org_apache_pdfbox_text_PDFTextStripper_paragraphStart = NULL;
+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");
+    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));
+}
+
+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");
+    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));
+}
+
+
+jfieldID _f_org_apache_pdfbox_text_PDFTextStripper_paragraphEnd = NULL;
+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");
+    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));
+}
+
+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");
+    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));
+}
+
+
+jfieldID _f_org_apache_pdfbox_text_PDFTextStripper_pageStart = NULL;
+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");
+    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));
+}
+
+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");
+    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));
+}
+
+
+jfieldID _f_org_apache_pdfbox_text_PDFTextStripper_pageEnd = NULL;
+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");
+    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));
+}
+
+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");
+    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));
+}
+
+
+jfieldID _f_org_apache_pdfbox_text_PDFTextStripper_articleStart = NULL;
+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");
+    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));
+}
+
+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");
+    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));
+}
+
+
+jfieldID _f_org_apache_pdfbox_text_PDFTextStripper_articleEnd = NULL;
+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");
+    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));
+}
+
+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");
+    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));
+}
+
+
+jfieldID _f_org_apache_pdfbox_text_PDFTextStripper_currentPageNo = NULL;
+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");
+    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));
+}
+
+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");
+    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));
+}
+
+
+jfieldID _f_org_apache_pdfbox_text_PDFTextStripper_startPage = NULL;
+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");
+    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));
+}
+
+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");
+    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));
+}
+
+
+jfieldID _f_org_apache_pdfbox_text_PDFTextStripper_endPage = NULL;
+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");
+    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));
+}
+
+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");
+    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));
+}
+
+
+jfieldID _f_org_apache_pdfbox_text_PDFTextStripper_startBookmark = NULL;
+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");
+    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));
+}
+
+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");
+    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));
+}
+
+
+jfieldID _f_org_apache_pdfbox_text_PDFTextStripper_startBookmarkPageNumber = NULL;
+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");
+    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));
+}
+
+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");
+    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));
+}
+
+
+jfieldID _f_org_apache_pdfbox_text_PDFTextStripper_endBookmarkPageNumber = NULL;
+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");
+    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));
+}
+
+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");
+    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));
+}
+
+
+jfieldID _f_org_apache_pdfbox_text_PDFTextStripper_endBookmark = NULL;
+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");
+    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));
+}
+
+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");
+    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));
+}
+
+
+jfieldID _f_org_apache_pdfbox_text_PDFTextStripper_suppressDuplicateOverlappingText = NULL;
+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");
+    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));
+}
+
+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");
+    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));
+}
+
+
+jfieldID _f_org_apache_pdfbox_text_PDFTextStripper_shouldSeparateByBeads = NULL;
+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");
+    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));
+}
+
+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");
+    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));
+}
+
+
+jfieldID _f_org_apache_pdfbox_text_PDFTextStripper_sortByPosition = NULL;
+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");
+    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));
+}
+
+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");
+    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));
+}
+
+
+jfieldID _f_org_apache_pdfbox_text_PDFTextStripper_addMoreFormatting = NULL;
+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");
+    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));
+}
+
+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");
+    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));
+}
+
+
+jfieldID _f_org_apache_pdfbox_text_PDFTextStripper_indentThreshold = NULL;
+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");
+    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));
+}
+
+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");
+    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));
+}
+
+
+jfieldID _f_org_apache_pdfbox_text_PDFTextStripper_dropThreshold = NULL;
+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");
+    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));
+}
+
+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");
+    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));
+}
+
+
+jfieldID _f_org_apache_pdfbox_text_PDFTextStripper_spacingTolerance = NULL;
+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");
+    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));
+}
+
+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");
+    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));
+}
+
+
+jfieldID _f_org_apache_pdfbox_text_PDFTextStripper_averageCharTolerance = NULL;
+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");
+    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));
+}
+
+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");
+    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));
+}
+
+
+jfieldID _f_org_apache_pdfbox_text_PDFTextStripper_beadRectangles = NULL;
+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");
+    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));
+}
+
+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");
+    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));
+}
+
+
+jfieldID _f_org_apache_pdfbox_text_PDFTextStripper_charactersByArticle = NULL;
+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");
+    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));
+}
+
+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");
+    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));
+}
+
+
+jfieldID _f_org_apache_pdfbox_text_PDFTextStripper_characterListMapping = NULL;
+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");
+    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));
+}
+
+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");
+    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));
+}
+
+
+jfieldID _f_org_apache_pdfbox_text_PDFTextStripper_document = NULL;
+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");
+    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));
+}
+
+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");
+    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));
+}
+
+
+jfieldID _f_org_apache_pdfbox_text_PDFTextStripper_output = NULL;
+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");
+    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));
+}
+
+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");
+    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));
+}
+
+
+jfieldID _f_org_apache_pdfbox_text_PDFTextStripper_inParagraph = NULL;
+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");
+    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));
+}
+
+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");
+    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));
+}
+
+
+jfieldID _f_org_apache_pdfbox_text_PDFTextStripper_LIST_ITEM_EXPRESSIONS = NULL;
+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");
+    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));
+}
+
+
+jfieldID _f_org_apache_pdfbox_text_PDFTextStripper_listOfPatterns = NULL;
+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");
+    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));
+}
+
+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");
+    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));
+}
+
+
+jfieldID _f_org_apache_pdfbox_text_PDFTextStripper_MIRRORING_CHAR_MAP = NULL;
+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");
+    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));
+}
+
+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");
+    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/jni_gen/examples/pdfbox_plugin/tool/generate_bindings.dart b/pkgs/jni_gen/examples/pdfbox_plugin/tool/generate_bindings.dart
new file mode 100644
index 0000000..b7ea48e
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/tool/generate_bindings.dart
@@ -0,0 +1,38 @@
+import 'package:jni_gen/jni_gen.dart';
+
+const preamble = '''
+// 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.
+''';
+
+void main(List<String> arguments) async {
+  final config = Config(
+    mavenDownloads: MavenDownloads(
+      sourceDeps: ['org.apache.pdfbox:pdfbox:2.0.26'],
+      jarOnlyDeps: [
+        'org.bouncycastle:bcmail-jdk15on:1.70',
+        'org.bouncycastle:bcprov-jdk15on:1.70',
+      ],
+    ),
+    classes: ['org.apache.pdfbox.pdmodel', 'org.apache.pdfbox.text'],
+    cRoot: Uri.directory('src/'),
+    dartRoot: Uri.directory('lib/'),
+    libraryName: 'pdfbox_plugin',
+  );
+  await generateJniBindings(config);
+}
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/windows/.gitignore b/pkgs/jni_gen/examples/pdfbox_plugin/windows/.gitignore
new file mode 100644
index 0000000..b3eb2be
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/windows/.gitignore
@@ -0,0 +1,17 @@
+flutter/
+
+# Visual Studio user-specific files.
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# Visual Studio build-related files.
+x64/
+x86/
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!*.[Cc]ache/
diff --git a/pkgs/jni_gen/examples/pdfbox_plugin/windows/CMakeLists.txt b/pkgs/jni_gen/examples/pdfbox_plugin/windows/CMakeLists.txt
new file mode 100644
index 0000000..3d9bd5c
--- /dev/null
+++ b/pkgs/jni_gen/examples/pdfbox_plugin/windows/CMakeLists.txt
@@ -0,0 +1,23 @@
+# The Flutter tooling requires that developers have a version of Visual Studio
+# installed that includes CMake 3.14 or later. You should not increase this
+# version, as doing so will cause the plugin to fail to compile for some
+# customers of the plugin.
+cmake_minimum_required(VERSION 3.14)
+
+# Project-level configuration.
+set(PROJECT_NAME "pdfbox_plugin")
+project(${PROJECT_NAME} LANGUAGES CXX)
+
+# Invoke the build for native code shared with the other target platforms.
+# This can be changed to accomodate different builds.
+add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/../src" "${CMAKE_CURRENT_BINARY_DIR}/shared")
+
+# List of absolute paths to libraries that should be bundled with the plugin.
+# This list could contain prebuilt libraries, or libraries created by an
+# external build triggered from this build file.
+set(pdfbox_plugin_bundled_libraries
+  # Defined in ../src/CMakeLists.txt.
+  # This can be changed to accomodate different builds.
+  $<TARGET_FILE:pdfbox_plugin>
+  PARENT_SCOPE
+)
diff --git a/pkgs/jni_gen/lib/src/bindings/dart_bindings.dart b/pkgs/jni_gen/lib/src/bindings/dart_bindings.dart
index 7a27303..3ca7353 100644
--- a/pkgs/jni_gen/lib/src/bindings/dart_bindings.dart
+++ b/pkgs/jni_gen/lib/src/bindings/dart_bindings.dart
@@ -159,7 +159,7 @@
     final name = f.finalName;
     final s = StringBuffer();
 
-    void _writeDocs({bool writeDeleteInstruction = true}) {
+    void writeDocs({bool writeDeleteInstruction = true}) {
       s.write('$_indent/// from: ${_originalFieldDecl(f)}\n');
       if (!isPrimitive(f.type) && writeDeleteInstruction) {
         s.write(_deleteInstruction);
@@ -168,7 +168,7 @@
     }
 
     if (isStaticField(f) && isFinalField(f) && f.defaultValue != null) {
-      _writeDocs(writeDeleteInstruction: false);
+      writeDocs(writeDeleteInstruction: false);
       s.write('${_indent}static const $name = ${_literal(f.defaultValue)};\n');
       return s.toString();
     }
@@ -183,7 +183,7 @@
           '<${ffi}NativeFunction<$ffiSig>>("${symPrefix}_$cName")\n'
           '.asFunction<$dartSig>();\n');
       // write original type
-      _writeDocs();
+      writeDocs();
       s.write(_indent);
       if (isStaticField(f)) s.write('static ');
       if (isSetter) {
diff --git a/pkgs/jni_gen/lib/src/bindings/symbol_resolver.dart b/pkgs/jni_gen/lib/src/bindings/symbol_resolver.dart
index 43b928f..0ccdc86 100644
--- a/pkgs/jni_gen/lib/src/bindings/symbol_resolver.dart
+++ b/pkgs/jni_gen/lib/src/bindings/symbol_resolver.dart
@@ -15,19 +15,20 @@
 }
 
 class PackagePathResolver implements SymbolResolver {
-  PackagePathResolver(this.packages, this.currentPackage, this.inputClassNames,
+  PackagePathResolver(this.importMap, this.currentPackage, this.inputClassNames,
       {this.predefined = const {}});
 
   final String currentPackage;
-  final Map<String, String> packages;
+  final Map<String, String> importMap;
   final Map<String, String> predefined;
   final Set<String> inputClassNames;
 
   final List<String> importStrings = [];
 
+  final Set<String> relativeImportedPackages = {};
+
   final Map<String, String> _importedNameToPackage = {};
   final Map<String, String> _packageToImportedName = {};
-
   // return null if type's package cannot be resolved
   // else return the fully qualified name of type
   @override
@@ -46,8 +47,13 @@
 
     if (_packageToImportedName.containsKey(package)) {
       // This package was already resolved
-      final importedName = _packageToImportedName[package];
-      return '$importedName.$simpleTypeName';
+      // but we still need to check if it was a relative import, in which case
+      // the class not in inputClassNames cannot be mapped here.
+      if (!relativeImportedPackages.contains(package) ||
+          inputClassNames.contains(binaryName)) {
+        final importedName = _packageToImportedName[package];
+        return '$importedName.$simpleTypeName';
+      }
     }
 
     final packageImport = getImport(package, binaryName);
@@ -102,6 +108,7 @@
         pathToCommon = '../' * (src.length - common);
       }
       final pathToPackage = dest.skip(max(common - 1, 0)).join('/');
+      relativeImportedPackages.add(packageToResolve);
       return '$pathToCommon$pathToPackage.dart';
     }
 
@@ -110,9 +117,9 @@
       final left = split[0];
       right.add(split[1]);
       // eg: packages[org.apache.pdfbox]/org/apache/pdfbox.dart
-      if (packages.containsKey(prefix)) {
+      if (importMap.containsKey(prefix)) {
         final sub = packageToResolve.replaceAll('.', '/');
-        final pkg = _suffix(packages[prefix]!, '/');
+        final pkg = _suffix(importMap[prefix]!, '/');
         return '$pkg$sub.dart';
       }
       prefix = left;
diff --git a/pkgs/jni_gen/lib/src/config/config.dart b/pkgs/jni_gen/lib/src/config/config.dart
index a0272f3..278e1bd 100644
--- a/pkgs/jni_gen/lib/src/config/config.dart
+++ b/pkgs/jni_gen/lib/src/config/config.dart
@@ -41,18 +41,35 @@
 /// The SDK directories for platform stub JARs and sources are searched in the
 /// same order in which [versions] are specified.
 ///
-/// If [sdkRoot] is not provided, an attempt is made to discover it
-/// using the environment variable `ANDROID_SDK_ROOT`, which will fail if the
-/// environment variable is not set.
-///
 /// If [includeSources] is true, `jni_gen` searches for Android SDK sources
 /// as well in the SDK directory and adds them to the source path.
+///
+/// If [addGradleDeps] is true, a gradle stub is run in order to collect the
+/// actual compile classpath of the `android/` subproject.
+/// This will fail if there was no previous build of the project, or if a
+/// `clean` task was run either through flutter or gradle wrapper. In such case,
+/// it's required to run `flutter build apk` & retry running `jni_gen`.
+///
+/// A configuration is invalid if [versions] is unspecified or empty, and
+/// [addGradleDeps] is also false. If [sdkRoot] is not specified but versions is
+/// specified, an attempt is made to find out SDK installation directory using
+/// environment variable `ANDROID_SDK_ROOT` if it's defined, else an error
+/// will be thrown.
 class AndroidSdkConfig {
   AndroidSdkConfig(
-      {required this.versions, this.sdkRoot, this.includeSources = false});
-  List<int> versions;
+      {this.versions,
+      this.sdkRoot,
+      this.includeSources = false,
+      this.addGradleDeps = false}) {
+    if (versions == null && !addGradleDeps) {
+      throw ArgumentError('Neither any SDK versions nor `addGradleDeps` '
+          'is specified. Unable to find Android libraries.');
+    }
+  }
+  List<int>? versions;
   String? sdkRoot;
   bool includeSources;
+  bool addGradleDeps;
 }
 
 /// Additional options to pass to the summary generator component.
@@ -87,6 +104,7 @@
     required this.libraryName,
     required this.cRoot,
     required this.dartRoot,
+    this.cSubdir,
     this.exclude,
     this.sourcePath,
     this.classPath,
@@ -113,11 +131,19 @@
   String libraryName;
 
   /// Directory to write JNI C Bindings.
+  ///
+  /// Strictly speaking, this is the root to place the `CMakeLists.txt` file
+  /// for the generated C bindings. It may be desirable to use the [cSubdir]
+  /// options to write C files to a subdirectory of [cRoot]. For instance,
+  /// when generated code is required to be in `third_party` directory.
   Uri cRoot;
 
   /// Directory to write Dart bindings.
   Uri dartRoot;
 
+  /// Subdirectory relative to [cRoot] to write generated C code.
+  String? cSubdir;
+
   /// Methods and fields to be excluded from generated bindings.
   BindingExclusions? exclude;
 
@@ -159,7 +185,6 @@
 
   static Config parseArgs(List<String> args) {
     final prov = YamlReader.parseArgs(args);
-
     final List<String> missingValues = [];
     T must<T>(T? Function(String) f, T ifNull, String property) {
       final res = f(property);
@@ -214,6 +239,7 @@
       ),
       cRoot: Uri.directory(must(prov.getString, '', _Props.cRoot)),
       dartRoot: Uri.directory(must(prov.getString, '', _Props.dartRoot)),
+      cSubdir: prov.getString(_Props.cSubdir),
       preamble: prov.getString(_Props.preamble),
       libraryName: must(prov.getString, '', _Props.libraryName),
       importMap: prov.getStringMap(_Props.importMap),
@@ -229,13 +255,14 @@
           : null,
       androidSdkConfig: prov.hasValue(_Props.androidSdkConfig)
           ? AndroidSdkConfig(
-              versions: must<List<String>>(
-                      prov.getStringList, [], _Props.androidSdkVersions)
-                  .map(int.parse)
+              versions: prov
+                  .getStringList(_Props.androidSdkVersions)
+                  ?.map(int.parse)
                   .toList(),
               sdkRoot: getSdkRoot(),
               includeSources:
                   prov.getBool(_Props.includeAndroidSources) ?? false,
+              addGradleDeps: prov.getBool(_Props.addGradleDeps) ?? false,
             )
           : null,
     );
@@ -272,6 +299,7 @@
 
   static const importMap = 'import_map';
   static const cRoot = 'c_root';
+  static const cSubdir = 'c_subdir';
   static const dartRoot = 'dart_root';
   static const preamble = 'preamble';
   static const libraryName = 'library_name';
@@ -286,4 +314,5 @@
   static const androidSdkRoot = '$androidSdkConfig.sdk_root';
   static const androidSdkVersions = '$androidSdkConfig.versions';
   static const includeAndroidSources = '$androidSdkConfig.include_sources';
+  static const addGradleDeps = '$androidSdkConfig.add_gradle_deps';
 }
diff --git a/pkgs/jni_gen/lib/src/config/yaml_reader.dart b/pkgs/jni_gen/lib/src/config/yaml_reader.dart
index 3d12dae..6765d9d 100644
--- a/pkgs/jni_gen/lib/src/config/yaml_reader.dart
+++ b/pkgs/jni_gen/lib/src/config/yaml_reader.dart
@@ -89,7 +89,7 @@
       }
       throw ConfigError('expected boolean value for $property, got $v');
     }
-    return null;
+    return getYamlValue<bool>(property);
   }
 
   String? getString(String property) {
diff --git a/pkgs/jni_gen/lib/src/generate_bindings.dart b/pkgs/jni_gen/lib/src/generate_bindings.dart
index b939f9c..09f948f 100644
--- a/pkgs/jni_gen/lib/src/generate_bindings.dart
+++ b/pkgs/jni_gen/lib/src/generate_bindings.dart
@@ -44,15 +44,20 @@
   }
 
   final androidConfig = config.androidSdkConfig;
-  if (androidConfig != null) {
+  if (androidConfig != null && androidConfig.addGradleDeps) {
+    final deps = AndroidSdkTools.getGradleClasspaths();
+    extraJars.addAll(deps.map(Uri.file));
+  }
+  if (androidConfig != null && androidConfig.versions != null) {
+    final versions = androidConfig.versions!;
     final androidJar = await AndroidSdkTools.getAndroidJarPath(
-        sdkRoot: androidConfig.sdkRoot, versionOrder: androidConfig.versions);
+        sdkRoot: androidConfig.sdkRoot, versionOrder: versions);
     if (androidJar != null) {
       extraJars.add(Uri.directory(androidJar));
     }
     if (androidConfig.includeSources) {
       final androidSources = await AndroidSdkTools.getAndroidSourcesPath(
-          sdkRoot: androidConfig.sdkRoot, versionOrder: androidConfig.versions);
+          sdkRoot: androidConfig.sdkRoot, versionOrder: versions);
       if (androidSources != null) {
         extraSources.add(Uri.directory(androidSources));
       }
diff --git a/pkgs/jni_gen/lib/src/tools/android_sdk_tools.dart b/pkgs/jni_gen/lib/src/tools/android_sdk_tools.dart
index e1092b2..029555a 100644
--- a/pkgs/jni_gen/lib/src/tools/android_sdk_tools.dart
+++ b/pkgs/jni_gen/lib/src/tools/android_sdk_tools.dart
@@ -42,4 +42,51 @@
   static Future<String?> getAndroidJarPath(
           {String? sdkRoot, required List<int> versionOrder}) async =>
       await _getFile('platforms', 'android.jar', sdkRoot, versionOrder);
+
+  static const _gradleListDepsFunction = '''
+task listDependencies(type: Copy) {
+  project.afterEvaluate {
+  	def app = project(':app')
+	def android = app.android
+	def cp = [android.getBootClasspath()[0]]
+	android.applicationVariants.each { variant ->
+		if (variant.name.equals('release')) {
+			cp += variant.javaCompile.classpath.getFiles()
+		}
+	}
+ 	cp.each { println it }
+  }
+}
+''';
+
+  /// Get release compile classpath used by Gradle for android build.
+  ///
+  /// This function temporarily overwrites the build.gradle file by a stub with
+  /// function to list all dependency paths for release variant.
+  /// This function fails if no gradle build is attempted
+  static List<String> getGradleClasspaths() {
+    stderr.writeln('trying to obtain gradle classpaths');
+    const android = 'android';
+    final buildGradle = join(android, 'build.gradle');
+    final buildGradleOld = join(android, 'build.gradle.old');
+    final origBuild = File(buildGradle);
+    final script = origBuild.readAsStringSync();
+    origBuild.renameSync(buildGradleOld);
+    origBuild.createSync();
+    origBuild.writeAsStringSync('$script\n$_gradleListDepsFunction\n');
+    final procRes = Process.runSync('./gradlew', ['-q', 'listDependencies'],
+        workingDirectory: android);
+    origBuild.writeAsStringSync(script);
+    File(buildGradleOld).deleteSync();
+    if (procRes.exitCode != 0) {
+      throw Exception('\n\ngradle exited with exit code ${procRes.exitCode}\n'
+          'This can be related to a known issue with gradle. '
+          'Please run `flutter build apk` and try again\n');
+    }
+    final gradleClassPaths = (procRes.stdout as String).split('\n');
+    if (gradleClassPaths.last.isEmpty) {
+      gradleClassPaths.removeLast();
+    }
+    return gradleClassPaths;
+  }
 }
diff --git a/pkgs/jni_gen/lib/src/writers/writers.dart b/pkgs/jni_gen/lib/src/writers/writers.dart
index 38b202e..6febf91 100644
--- a/pkgs/jni_gen/lib/src/writers/writers.dart
+++ b/pkgs/jni_gen/lib/src/writers/writers.dart
@@ -63,8 +63,9 @@
     final initFile = await File.fromUri(initFileUri).create(recursive: true);
     await initFile.writeAsString(DartPreludes.initFile(config.libraryName),
         flush: true);
-
-    final cFile = await File.fromUri(cRoot.resolve('$libraryName.c'))
+    final subdir = config.cSubdir ?? '.';
+    final cFileRelativePath = '$subdir/$libraryName.c';
+    final cFile = await File.fromUri(cRoot.resolve(cFileRelativePath))
         .create(recursive: true);
     final cFileStream = cFile.openWrite();
     if (preamble != null) {
@@ -116,10 +117,14 @@
 
     stderr.writeln('Copying auxiliary files...');
     await _copyFileFromPackage(
-        'jni', 'src/dartjni.h', cRoot.resolve('dartjni.h'));
+        'jni', 'src/dartjni.h', cRoot.resolve('$subdir/dartjni.h'));
     await _copyFileFromPackage(
         'jni_gen', 'cmake/CMakeLists.txt.tmpl', cRoot.resolve('CMakeLists.txt'),
-        transform: (s) => s.replaceAll('{{LIBRARY_NAME}}', libraryName));
+        transform: (s) {
+      return s
+          .replaceAll('{{LIBRARY_NAME}}', libraryName)
+          .replaceAll('{{SUBDIR}}', subdir);
+    });
     stderr.writeln('Completed.');
   }
 
diff --git a/pkgs/jni_gen/test/bindings_test.dart b/pkgs/jni_gen/test/bindings_test.dart
index fd8a196..51b92eb 100644
--- a/pkgs/jni_gen/test/bindings_test.dart
+++ b/pkgs/jni_gen/test/bindings_test.dart
@@ -35,6 +35,12 @@
   await runCmd('javac',
       ['dev/dart/simple_package/Example.java', 'dev/dart/pkg2/C2.java'],
       workingDirectory: simplePackageJavaPath);
+  await runCmd('dart', [
+    'run',
+    'jni_gen:download_maven_jars',
+    '--config',
+    join(jacksonCorePath, 'jnigen.yaml')
+  ]);
 
   final jacksonJars = await getJarPaths(join(jacksonCorePath, 'third_party'));
 
diff --git a/pkgs/jni_gen/test/jackson_core_test/third_party/src/CMakeLists.txt b/pkgs/jni_gen/test/jackson_core_test/third_party/src/CMakeLists.txt
index 657e001..475daed 100644
--- a/pkgs/jni_gen/test/jackson_core_test/third_party/src/CMakeLists.txt
+++ b/pkgs/jni_gen/test/jackson_core_test/third_party/src/CMakeLists.txt
@@ -6,7 +6,7 @@
 project(jackson_core_test VERSION 0.0.1 LANGUAGES C)
 
 add_library(jackson_core_test SHARED
-  "jackson_core_test.c"
+  "./jackson_core_test.c"
 )
 
 set_target_properties(jackson_core_test PROPERTIES
diff --git a/pkgs/jni_gen/test/simple_package_test/src/CMakeLists.txt b/pkgs/jni_gen/test/simple_package_test/src/CMakeLists.txt
index ef0660b..a029be9 100644
--- a/pkgs/jni_gen/test/simple_package_test/src/CMakeLists.txt
+++ b/pkgs/jni_gen/test/simple_package_test/src/CMakeLists.txt
@@ -6,7 +6,7 @@
 project(simple_package VERSION 0.0.1 LANGUAGES C)
 
 add_library(simple_package SHARED
-  "simple_package.c"
+  "./simple_package.c"
 )
 
 set_target_properties(simple_package PROPERTIES