[jnigen] Add `JBuffer`, `JByteBuffer` to enable fast copying to and from `Uint8List` (https://github.com/dart-lang/jnigen/issues/390)
`JBuffer` is now the default binding for `java.nio.Buffer` and `JByteBuffer` for `java.nio.ByteBuffer`.
diff --git a/pkgs/jni/CHANGELOG.md b/pkgs/jni/CHANGELOG.md
index f997531..64ddb4d 100644
--- a/pkgs/jni/CHANGELOG.md
+++ b/pkgs/jni/CHANGELOG.md
@@ -1,33 +1,57 @@
+## 0.7.0
+
+- **Breaking Change** ([#387](https://github.com/dart-lang/jnigen/issues/387)):
+ Added `JBuffer` and `JByteBuffer` classes as default classes for
+ `java.nio.Buffer` and `java.nio.ByteBuffer` respectively.
+- **Breaking Change**: Made the type classes `final`.
+- Fixed a bug where `addAll`, `removeAll` and `retainAll` in `JSet` would run
+ their respective operation twice.
+- Fixed a bug where `JList.insertAll` would not throw the potentially thrown
+ Java exception.
+
## 0.6.1
-* Depend on the stable version of Dart 3.1.
+
+- Depend on the stable version of Dart 3.1.
## 0.6.0
-* **Breaking Change** ([#131](https://github.com/dart-lang/jnigen/issues/131)): Renamed `delete*` to `release*`.
-* Added `PortProxy` and related methods used for interface implementation.
-* Added the missing binding for `java.lang.Character`.
+
+- **Breaking Change** ([#131](https://github.com/dart-lang/jnigen/issues/131)):
+ Renamed `delete*` to `release*`.
+- Added `PortProxy` and related methods used for interface implementation.
+- Added the missing binding for `java.lang.Character`.
## 0.5.0
-* **Breaking Change** ([#137](https://github.com/dart-lang/jnigen/issues/137)): Java primitive types are now all lowercase like `jint`, `jshort`, ...
-* The bindings for `java.util.Set`, `java.util.Map`, `java.util.List` and the numeric types like `java.lang.Integer`, `java.lang.Boolean`, ... are now included in `package:jni`.
+
+- **Breaking Change** ([#137](https://github.com/dart-lang/jnigen/issues/137)):
+ Java primitive types are now all lowercase like `jint`, `jshort`, ...
+- The bindings for `java.util.Set`, `java.util.Map`, `java.util.List` and the
+ numeric types like `java.lang.Integer`, `java.lang.Boolean`, ... are now
+ included in `package:jni`.
## 0.4.0
-* Type classes now have `superCount` and `superType` getters used for type inference.
+
+- Type classes now have `superCount` and `superType` getters used for type
+ inference.
## 0.3.0
-* Added `PortContinuation` used for `suspend fun` in Kotlin.
-* `dartjni` now depends on `dart_api_dl.h`.
+
+- Added `PortContinuation` used for `suspend fun` in Kotlin.
+- `dartjni` now depends on `dart_api_dl.h`.
## 0.2.1
-* Added `.clang-format` to pub.
+
+- Added `.clang-format` to pub.
## 0.2.0
-* Added array support
-* Added generic support
-* `JniX` turned into `JX` for a more terse code.
+
+- Added array support
+- Added generic support
+- `JniX` turned into `JX` for a more terse code.
## 0.1.1
-* Windows support for running tests and examples on development machines.
+
+- Windows support for running tests and examples on development machines.
## 0.1.0
-* Initial version: Android and Linux support, JObject API
+- Initial version: Android and Linux support, JObject API
diff --git a/pkgs/jni/lib/jni.dart b/pkgs/jni/lib/jni.dart
index d63fc73..85f99fa 100644
--- a/pkgs/jni/lib/jni.dart
+++ b/pkgs/jni/lib/jni.dart
@@ -71,6 +71,7 @@
export 'src/jprimitives.dart';
export 'src/jreference.dart' show JReferenceUseExtension;
export 'src/lang/lang.dart';
+export 'src/nio/nio.dart';
export 'src/util/util.dart';
export 'package:ffi/ffi.dart' show using, Arena;
diff --git a/pkgs/jni/lib/jni_symbols.yaml b/pkgs/jni/lib/jni_symbols.yaml
index 5159dc9..ac4a74c 100644
--- a/pkgs/jni/lib/jni_symbols.yaml
+++ b/pkgs/jni/lib/jni_symbols.yaml
@@ -75,3 +75,11 @@
'java.lang.Object': DECLARED
V:
'java.lang.Object': DECLARED
+ 'java.nio.Buffer':
+ name: JBuffer
+ type_class: JBufferType
+ super_count: 1
+ 'java.nio.ByteBuffer':
+ name: JByteBuffer
+ type_class: JByteBufferType
+ super_count: 2
diff --git a/pkgs/jni/lib/src/jarray.dart b/pkgs/jni/lib/src/jarray.dart
index 1b97039..fac1d85 100644
--- a/pkgs/jni/lib/src/jarray.dart
+++ b/pkgs/jni/lib/src/jarray.dart
@@ -16,7 +16,7 @@
import 'jprimitives.dart';
import 'types.dart';
-class JArrayType<T> extends JObjType<JArray<T>> {
+final class JArrayType<T> extends JObjType<JArray<T>> {
final JType<T> elementType;
const JArrayType(this.elementType);
diff --git a/pkgs/jni/lib/src/jobject.dart b/pkgs/jni/lib/src/jobject.dart
index 6a2cad2..a7e659c 100644
--- a/pkgs/jni/lib/src/jobject.dart
+++ b/pkgs/jni/lib/src/jobject.dart
@@ -19,7 +19,7 @@
// type switch like a regular type.
typedef _VoidType = void;
-class JObjectType extends JObjType<JObject> {
+final class JObjectType extends JObjType<JObject> {
const JObjectType();
@override
diff --git a/pkgs/jni/lib/src/lang/jboolean.dart b/pkgs/jni/lib/src/lang/jboolean.dart
index 3dd22b1..9ea92b4 100644
--- a/pkgs/jni/lib/src/lang/jboolean.dart
+++ b/pkgs/jni/lib/src/lang/jboolean.dart
@@ -9,7 +9,7 @@
import '../third_party/generated_bindings.dart';
import '../types.dart';
-class JBooleanType extends JObjType<JBoolean> {
+final class JBooleanType extends JObjType<JBoolean> {
const JBooleanType();
@override
diff --git a/pkgs/jni/lib/src/lang/jbyte.dart b/pkgs/jni/lib/src/lang/jbyte.dart
index 3cb9e96..6b5aa98 100644
--- a/pkgs/jni/lib/src/lang/jbyte.dart
+++ b/pkgs/jni/lib/src/lang/jbyte.dart
@@ -9,7 +9,7 @@
import '../types.dart';
import 'jnumber.dart';
-class JByteType extends JObjType<JByte> {
+final class JByteType extends JObjType<JByte> {
const JByteType();
@override
diff --git a/pkgs/jni/lib/src/lang/jcharacter.dart b/pkgs/jni/lib/src/lang/jcharacter.dart
index c43d2e0..b50f67f 100644
--- a/pkgs/jni/lib/src/lang/jcharacter.dart
+++ b/pkgs/jni/lib/src/lang/jcharacter.dart
@@ -6,7 +6,7 @@
import '../third_party/generated_bindings.dart';
import '../types.dart';
-class JCharacterType extends JObjType<JCharacter> {
+final class JCharacterType extends JObjType<JCharacter> {
const JCharacterType();
@override
diff --git a/pkgs/jni/lib/src/lang/jdouble.dart b/pkgs/jni/lib/src/lang/jdouble.dart
index c6852a1..6db163e 100644
--- a/pkgs/jni/lib/src/lang/jdouble.dart
+++ b/pkgs/jni/lib/src/lang/jdouble.dart
@@ -8,7 +8,7 @@
import '../types.dart';
import 'jnumber.dart';
-class JDoubleType extends JObjType<JDouble> {
+final class JDoubleType extends JObjType<JDouble> {
const JDoubleType();
@override
diff --git a/pkgs/jni/lib/src/lang/jfloat.dart b/pkgs/jni/lib/src/lang/jfloat.dart
index f23c237..a352659 100644
--- a/pkgs/jni/lib/src/lang/jfloat.dart
+++ b/pkgs/jni/lib/src/lang/jfloat.dart
@@ -9,7 +9,7 @@
import '../types.dart';
import 'jnumber.dart';
-class JFloatType extends JObjType<JFloat> {
+final class JFloatType extends JObjType<JFloat> {
const JFloatType();
@override
diff --git a/pkgs/jni/lib/src/lang/jinteger.dart b/pkgs/jni/lib/src/lang/jinteger.dart
index 907d7ba..8ece466 100644
--- a/pkgs/jni/lib/src/lang/jinteger.dart
+++ b/pkgs/jni/lib/src/lang/jinteger.dart
@@ -9,7 +9,7 @@
import '../types.dart';
import 'jnumber.dart';
-class JIntegerType extends JObjType<JInteger> {
+final class JIntegerType extends JObjType<JInteger> {
const JIntegerType();
@override
diff --git a/pkgs/jni/lib/src/lang/jlong.dart b/pkgs/jni/lib/src/lang/jlong.dart
index fb2ee80..66d054b 100644
--- a/pkgs/jni/lib/src/lang/jlong.dart
+++ b/pkgs/jni/lib/src/lang/jlong.dart
@@ -8,7 +8,7 @@
import '../types.dart';
import 'jnumber.dart';
-class JLongType extends JObjType<JLong> {
+final class JLongType extends JObjType<JLong> {
const JLongType();
@override
diff --git a/pkgs/jni/lib/src/lang/jnumber.dart b/pkgs/jni/lib/src/lang/jnumber.dart
index 43e1085..45d86dc 100644
--- a/pkgs/jni/lib/src/lang/jnumber.dart
+++ b/pkgs/jni/lib/src/lang/jnumber.dart
@@ -17,7 +17,7 @@
import 'jlong.dart';
import 'jshort.dart';
-class JNumberType extends JObjType<JNumber> {
+final class JNumberType extends JObjType<JNumber> {
const JNumberType();
@override
diff --git a/pkgs/jni/lib/src/lang/jshort.dart b/pkgs/jni/lib/src/lang/jshort.dart
index a07ea4e..39d3c1d 100644
--- a/pkgs/jni/lib/src/lang/jshort.dart
+++ b/pkgs/jni/lib/src/lang/jshort.dart
@@ -9,7 +9,7 @@
import '../types.dart';
import 'jnumber.dart';
-class JShortType extends JObjType<JShort> {
+final class JShortType extends JObjType<JShort> {
const JShortType();
@override
diff --git a/pkgs/jni/lib/src/lang/jstring.dart b/pkgs/jni/lib/src/lang/jstring.dart
index 43bda60..9e542ff 100644
--- a/pkgs/jni/lib/src/lang/jstring.dart
+++ b/pkgs/jni/lib/src/lang/jstring.dart
@@ -12,7 +12,7 @@
import '../third_party/generated_bindings.dart';
import '../types.dart';
-class JStringType extends JObjType<JString> {
+final class JStringType extends JObjType<JString> {
const JStringType();
@override
diff --git a/pkgs/jni/lib/src/nio/jbuffer.dart b/pkgs/jni/lib/src/nio/jbuffer.dart
new file mode 100644
index 0000000..cae6bc9
--- /dev/null
+++ b/pkgs/jni/lib/src/nio/jbuffer.dart
@@ -0,0 +1,255 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import '../accessors.dart';
+import '../jni.dart';
+import '../jobject.dart';
+import '../jvalues.dart';
+import '../third_party/generated_bindings.dart';
+import '../types.dart';
+
+final class JBufferType extends JObjType<JBuffer> {
+ const JBufferType();
+
+ @override
+ String get signature => r"Ljava/nio/Buffer;";
+
+ @override
+ JBuffer fromRef(JObjectPtr ref) => JBuffer.fromRef(ref);
+
+ @override
+ JObjType get superType => const JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => (JBufferType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == (JBufferType) && other is JBufferType;
+ }
+}
+
+/// A container for data of a specific primitive type.
+///
+/// The bindings for `java.nio.Buffer`.
+///
+/// A buffer is a linear, finite sequence of elements of a specific primitive
+/// type. Aside from its content, the essential properties of a buffer are its
+/// [capacity], [limit], and [position].
+///
+/// There is one subclass of this class for each non-boolean primitive type.
+/// We currently only have the bindings for `java.nio.ByteBuffer` in this
+/// package as [JByteBuffer].
+class JBuffer extends JObject {
+ @override
+ // ignore: overridden_fields
+ late final JObjType<JBuffer> $type = type;
+
+ JBuffer.fromRef(
+ JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ static final _class = Jni.findJClass(r"java/nio/Buffer");
+
+ /// The type which includes information such as the signature of this class.
+ static const type = JBufferType();
+
+ static final _capacityId =
+ Jni.accessors.getMethodIDOf(_class.reference, r"capacity", r"()I");
+
+ /// The number of elements this buffer contains.
+ ///
+ /// It is never negative and never changes.
+ int get capacity {
+ return Jni.accessors.callMethodWithArgs(
+ reference, _capacityId, JniCallType.intType, []).integer;
+ }
+
+ static final _positionId =
+ Jni.accessors.getMethodIDOf(_class.reference, r"position", r"()I");
+
+ /// The index of the next element to be read or written.
+ ///
+ /// It is never negative and is never greater than its [limit].
+ int get position {
+ return Jni.accessors.callMethodWithArgs(
+ reference, _positionId, JniCallType.intType, []).integer;
+ }
+
+ static final _setPositionId = Jni.accessors
+ .getMethodIDOf(_class.reference, r"position", r"(I)Ljava/nio/Buffer;");
+
+ /// Throws:
+ /// * [IllegalArgumentException] - If the preconditions on [newPosition] do
+ /// not hold.
+ set position(int position) {
+ Jni.env.DeleteGlobalRef(Jni.accessors.callMethodWithArgs(reference,
+ _setPositionId, JniCallType.objectType, [JValueInt(position)]).object);
+ }
+
+ static final _limitId =
+ Jni.accessors.getMethodIDOf(_class.reference, r"limit", r"()I");
+
+ /// The index of the first element that should not be read or written.
+ ///
+ /// It is never negative and is never greater than its [capacity].
+ int get limit {
+ return Jni.accessors.callMethodWithArgs(
+ reference, _limitId, JniCallType.intType, []).integer;
+ }
+
+ static final _setLimitId = Jni.accessors
+ .getMethodIDOf(_class.reference, r"limit", r"(I)Ljava/nio/Buffer;");
+
+ /// Throws:
+ /// * [IllegalArgumentException] - If the preconditions on [newLimit] do not
+ /// hold.
+ set limit(int newLimit) {
+ Jni.env.DeleteGlobalRef(Jni.accessors.callMethodWithArgs(reference,
+ _setLimitId, JniCallType.objectType, [JValueInt(newLimit)]).object);
+ }
+
+ static final _markId = Jni.accessors
+ .getMethodIDOf(_class.reference, r"mark", r"()Ljava/nio/Buffer;");
+
+ /// Sets this buffer's mark at its [position].
+ ///
+ /// Mark is the index to which its [position] will be reset when the [reset]
+ /// method is invoked.
+ void mark() {
+ Jni.env.DeleteGlobalRef(Jni.accessors.callMethodWithArgs(
+ reference, _markId, JniCallType.objectType, []).object);
+ }
+
+ static final _resetId = Jni.accessors
+ .getMethodIDOf(_class.reference, r"reset", r"()Ljava/nio/Buffer;");
+
+ /// Resets this buffer's [position] to the previously-marked position.
+ ///
+ /// Throws:
+ /// * [InvalidMarkException] - If the mark has not been set
+ void reset() {
+ Jni.env.DeleteGlobalRef(Jni.accessors.callMethodWithArgs(
+ reference, _resetId, JniCallType.objectType, []).object);
+ }
+
+ static final _clearId = Jni.accessors
+ .getMethodIDOf(_class.reference, r"clear", r"()Ljava/nio/Buffer;");
+
+ /// Clears this buffer.
+ ///
+ /// The [position] is set to zero, the [limit] is set to
+ /// the [capacity], and the mark is discarded.
+ void clear() {
+ Jni.env.DeleteGlobalRef(Jni.accessors.callMethodWithArgs(
+ reference, _clearId, JniCallType.objectType, []).object);
+ }
+
+ static final _flipId = Jni.accessors
+ .getMethodIDOf(_class.reference, r"flip", r"()Ljava/nio/Buffer;");
+
+ /// Flips this buffer.
+ ///
+ /// The limit is set to the current [position] and then the [position] is set
+ /// to zero. If the mark is defined then it is discarded.
+ void flip() {
+ Jni.env.DeleteGlobalRef(Jni.accessors.callMethodWithArgs(
+ reference, _flipId, JniCallType.objectType, []).object);
+ }
+
+ static final _rewindId = Jni.accessors
+ .getMethodIDOf(_class.reference, r"rewind", r"()Ljava/nio/Buffer;");
+
+ /// Rewinds this buffer.
+ ///
+ /// The [position] is set to zero and the mark is discarded.
+ void rewind() {
+ Jni.env.DeleteGlobalRef(Jni.accessors.callMethodWithArgs(
+ reference, _rewindId, JniCallType.objectType, []).object);
+ }
+
+ static final _remainingId =
+ Jni.accessors.getMethodIDOf(_class.reference, r"remaining", r"()I");
+
+ /// The number of elements between the current [position] and the
+ /// [limit].
+ int get remaining {
+ return Jni.accessors.callMethodWithArgs(
+ reference, _remainingId, JniCallType.intType, []).integer;
+ }
+
+ static final _hasRemainingId =
+ Jni.accessors.getMethodIDOf(_class.reference, r"hasRemaining", r"()Z");
+
+ /// Whether there are any elements between the current [position] and
+ /// the [limit].
+ bool get hasRemaining {
+ return Jni.accessors.callMethodWithArgs(
+ reference, _hasRemainingId, JniCallType.booleanType, []).boolean;
+ }
+
+ static final _isReadOnlyId =
+ Jni.accessors.getMethodIDOf(_class.reference, r"isReadOnly", r"()Z");
+
+ /// Whether or not this buffer is read-only.
+ bool get isReadOnly {
+ return Jni.accessors.callMethodWithArgs(
+ reference, _isReadOnlyId, JniCallType.booleanType, []).boolean;
+ }
+
+ static final _hasArrayId =
+ Jni.accessors.getMethodIDOf(_class.reference, r"hasArray", r"()Z");
+
+ /// Whether or not this buffer is backed by an accessible array.
+ bool get hasArray {
+ return Jni.accessors.callMethodWithArgs(
+ reference, _hasArrayId, JniCallType.booleanType, []).boolean;
+ }
+
+ static final _arrayId = Jni.accessors
+ .getMethodIDOf(_class.reference, r"array", r"()Ljava/lang/Object;");
+
+ /// The array that backs this buffer.
+ ///
+ /// Concrete subclasses like [JByteBuffer] provide more strongly-typed return
+ /// values for this method.
+ ///
+ /// Throws:
+ /// * [ReadOnlyBufferException] - If this buffer is backed by an array but is
+ /// read-only
+ /// * [UnsupportedOperationException] - If this buffer is not backed by an
+ /// accessible array
+ JObject get array {
+ return const JObjectType().fromRef(Jni.accessors.callMethodWithArgs(
+ reference, _arrayId, JniCallType.objectType, []).object);
+ }
+
+ static final _arrayOffsetId =
+ Jni.accessors.getMethodIDOf(_class.reference, r"arrayOffset", r"()I");
+
+ /// The offset within this buffer's backing array of the first element
+ /// of the buffer.
+ ///
+ /// Throws:
+ /// * [ReadOnlyBufferException] - If this buffer is backed by an array but is
+ /// read-only
+ /// * [UnsupportedOperationException] - If this buffer is not backed by an
+ /// accessible array
+ int get arrayOffset {
+ return Jni.accessors.callMethodWithArgs(
+ reference, _arrayOffsetId, JniCallType.intType, []).integer;
+ }
+
+ static final _isDirectId =
+ Jni.accessors.getMethodIDOf(_class.reference, r"isDirect", r"()Z");
+
+ /// Whether or not this buffer is direct.
+ bool get isDirect {
+ return Jni.accessors.callMethodWithArgs(
+ reference, _isDirectId, JniCallType.booleanType, []).boolean;
+ }
+}
diff --git a/pkgs/jni/lib/src/nio/jbyte_buffer.dart b/pkgs/jni/lib/src/nio/jbyte_buffer.dart
new file mode 100644
index 0000000..1b0acb2
--- /dev/null
+++ b/pkgs/jni/lib/src/nio/jbyte_buffer.dart
@@ -0,0 +1,316 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:ffi';
+import 'dart:typed_data';
+
+import '../accessors.dart';
+import '../jarray.dart';
+import '../jni.dart';
+import '../jprimitives.dart';
+import '../jreference.dart';
+import '../jvalues.dart';
+import '../third_party/generated_bindings.dart';
+import '../types.dart';
+import 'jbuffer.dart';
+
+final class JByteBufferType extends JObjType<JByteBuffer> {
+ const JByteBufferType();
+
+ @override
+ String get signature => r"Ljava/nio/ByteBuffer;";
+
+ @override
+ JByteBuffer fromRef(JObjectPtr ref) => JByteBuffer.fromRef(ref);
+
+ @override
+ JObjType get superType => const JBufferType();
+
+ @override
+ final superCount = 2;
+
+ @override
+ int get hashCode => (JByteBufferType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == (JByteBufferType) && other is JByteBufferType;
+ }
+}
+
+/// A byte [JBuffer].
+///
+/// The bindings for `java.nio.ByteBuffer`.
+///
+/// This enables fast memory copying between Java and Dart when directly
+/// allocated (See [JByteBuffer.allocateDirect]).
+///
+/// To create a [JByteBuffer] from the content of a [Uint8List],
+/// use [JByteBuffer.fromList]. This uses direct allocation to enable fast
+/// copying.
+///
+/// [asUint8List] provides a direct access to the underlying [Uint8List] that
+/// this buffer uses. This means any changes to it will change the content of
+/// the buffer and vice versa. This can be used to access to [Uint8List] methods
+/// such as [Uint8List.setRange].
+///
+/// Example:
+/// ```dart
+/// final directBuffer = JByteBuffer.allocateDirect(3);
+/// directBuffer.asUint8List().setAll(0, [1, 2, 3]);
+/// // The buffer is now 1, 2, 3.
+/// ```
+///
+/// Both the original buffer and the [Uint8List] keep the underlying Java buffer
+/// alive. Once all the instances of the original buffer and the lists produced
+/// from [asUint8List] are inaccessible both in Java and Dart, Java will
+/// correctly garbage collects the buffer and frees its underlying memory.
+///
+/// Example:
+/// ```dart
+/// final directBuffer = JByteBuffer.allocateDirect(3);
+/// final data = directBuffer.asUint8List();
+/// directBuffer.release(); // Releasing the original buffer.
+/// data.setAll(0, [1, 2, 3]); // Works! [data] is still accessible.
+/// ```
+///
+/// The original buffer can be [release]d when calling [asUint8List]
+/// by setting the `releaseOriginal` parameter to `true`.
+///
+/// Example:
+/// ```dart
+/// final directBuffer = JByteBuffer.allocateDirect(3);
+/// // [releaseOriginal] is `false` by default.
+/// final data1 = directBuffer.asUint8List();
+/// directBuffer.nextByte = 42; // No problem!
+/// print(data1[0]); // prints 42!
+/// final data2 = directBuffer.asUint8List(releaseOriginal: true);
+/// // directBuffer.nextByte = 42; // throws [UseAfterReleaseException]!
+/// ```
+class JByteBuffer extends JBuffer {
+ @override
+ // ignore: overridden_fields
+ late final JObjType<JByteBuffer> $type = type;
+
+ JByteBuffer.fromRef(
+ JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ static final _class = Jni.findJClass(r"java/nio/ByteBuffer");
+
+ /// The type which includes information such as the signature of this class.
+ static const type = JByteBufferType();
+
+ static final _allocateDirectId = Jni.accessors.getStaticMethodIDOf(
+ _class.reference, r"allocateDirect", r"(I)Ljava/nio/ByteBuffer;");
+
+ /// Allocates a new direct byte buffer.
+ ///
+ /// Throws:
+ /// * [IllegalArgumentException] - If the capacity is a negative integer
+ factory JByteBuffer.allocateDirect(int capacity) {
+ return JByteBuffer.fromRef(
+ Jni.accessors.callStaticMethodWithArgs(
+ _class.reference,
+ _allocateDirectId,
+ JniCallType.objectType,
+ [JValueInt(capacity)]).object,
+ );
+ }
+
+ static final _allocateId = Jni.accessors.getStaticMethodIDOf(
+ _class.reference, r"allocate", r"(I)Ljava/nio/ByteBuffer;");
+
+ /// Allocates a new byte buffer.
+ ///
+ /// Throws:
+ /// * [IllegalArgumentException] - If the capacity is a negative integer
+ factory JByteBuffer.allocate(int capacity) {
+ return const JByteBufferType().fromRef(Jni.accessors
+ .callStaticMethodWithArgs(_class.reference, _allocateId,
+ JniCallType.objectType, [JValueInt(capacity)]).object);
+ }
+
+ static final _wrapWholeId = Jni.accessors.getStaticMethodIDOf(
+ _class.reference, r"wrap", r"([B)Ljava/nio/ByteBuffer;");
+ static final _wrapId = Jni.accessors.getStaticMethodIDOf(
+ _class.reference, r"wrap", r"([BII)Ljava/nio/ByteBuffer;");
+
+ /// Wraps a byte array into a buffer.
+ ///
+ /// The new buffer will be backed by the given byte array; that is,
+ /// modifications to the buffer will cause the array to be modified
+ /// and vice versa.
+ static JByteBuffer wrap(
+ JArray<jbyte> array, [
+ int? offset,
+ int? length,
+ ]) {
+ if (offset == null && length == null) {
+ return const JByteBufferType().fromRef(
+ Jni.accessors.callStaticMethodWithArgs(
+ _class.reference,
+ _wrapWholeId,
+ JniCallType.objectType,
+ [array.reference],
+ ).object,
+ );
+ }
+ offset ??= 0;
+ length ??= array.length - offset;
+ return const JByteBufferType().fromRef(
+ Jni.accessors.callStaticMethodWithArgs(
+ _class.reference,
+ _wrapId,
+ JniCallType.objectType,
+ [array.reference, JValueInt(offset), JValueInt(length)],
+ ).object,
+ );
+ }
+
+ /// Creates a [JByteBuffer] from the content of [list].
+ ///
+ /// The [JByteBuffer] will be allocated using [JByteBuffer.allocateDirect].
+ factory JByteBuffer.fromList(Uint8List list) {
+ final buffer = JByteBuffer.allocateDirect(list.length);
+ buffer._asUint8ListUnsafe().setAll(0, list);
+ return buffer;
+ }
+
+ static final _sliceId = Jni.accessors
+ .getMethodIDOf(_class.reference, r"slice", r"()Ljava/nio/ByteBuffer;");
+
+ /// Creates a new byte buffer whose content is a shared subsequence of this
+ /// buffer's content.
+ JByteBuffer slice() {
+ return const JByteBufferType().fromRef(Jni.accessors.callMethodWithArgs(
+ reference, _sliceId, JniCallType.objectType, []).object);
+ }
+
+ static final _duplicateId = Jni.accessors.getMethodIDOf(
+ _class.reference, r"duplicate", r"()Ljava/nio/ByteBuffer;");
+
+ /// Creates a new byte buffer that shares this buffer's content.
+ JByteBuffer duplicate() {
+ return const JByteBufferType().fromRef(Jni.accessors.callMethodWithArgs(
+ reference, _duplicateId, JniCallType.objectType, []).object);
+ }
+
+ static final _asReadOnlyBufferId = Jni.accessors.getMethodIDOf(
+ _class.reference, r"asReadOnlyBuffer", r"()Ljava/nio/ByteBuffer;");
+
+ /// Creates a new, read-only byte buffer that shares this buffer's content.
+ JByteBuffer asReadOnlyBuffer() {
+ return const JByteBufferType().fromRef(Jni.accessors.callMethodWithArgs(
+ reference, _asReadOnlyBufferId, JniCallType.objectType, []).object);
+ }
+
+ static final _getId =
+ Jni.accessors.getMethodIDOf(_class.reference, r"get", r"()B");
+
+ /// Reads the byte at this buffer's current [position], and then increments the
+ /// [position].
+ ///
+ /// Throws:
+ /// * [BufferOverflowException] - If the buffer's current [position] is not
+ /// smaller than its [limit]
+ int get nextByte {
+ return Jni.accessors
+ .callMethodWithArgs(reference, _getId, JniCallType.byteType, []).byte;
+ }
+
+ static final _putId = Jni.accessors
+ .getMethodIDOf(_class.reference, r"put", r"(B)Ljava/nio/ByteBuffer;");
+
+ /// Writes the given byte into this buffer at the current [position], and then
+ /// increments the [position].
+ ///
+ /// Throws:
+ /// * [BufferOverflowException] - If this buffer's current [position] is not
+ /// smaller than its [limit]
+ /// * [ReadOnlyBufferException] - If this buffer is read-only
+ set nextByte(int b) {
+ Jni.env.DeleteGlobalRef(Jni.accessors.callMethodWithArgs(
+ reference, _putId, JniCallType.objectType, [JValueByte(b)]).object);
+ }
+
+ static final _arrayId =
+ Jni.accessors.getMethodIDOf(_class.reference, r"array", r"()[B");
+
+ @override
+ JArray<jbyte> get array {
+ return const JArrayType(jbyteType()).fromRef(Jni.accessors
+ .callMethodWithArgs(
+ reference, _arrayId, JniCallType.objectType, []).object);
+ }
+
+ void _ensureIsDirect() {
+ if (!isDirect) {
+ throw StateError(
+ 'The buffer must be created with `JByteBuffer.allocateDirect`.',
+ );
+ }
+ }
+
+ Pointer<Void> _directBufferAddress() {
+ final address = Jni.env.GetDirectBufferAddress(reference);
+ if (address == nullptr) {
+ throw StateError(
+ 'The memory region is undefined or '
+ 'direct buffer access is not supported by this JVM.',
+ );
+ }
+ return address;
+ }
+
+ int _directBufferCapacity() {
+ final capacity = Jni.env.GetDirectBufferCapacity(reference);
+ if (capacity == -1) {
+ throw StateError(
+ 'The object is an unaligned view buffer and the processor '
+ 'architecture does not support unaligned access.',
+ );
+ }
+ return capacity;
+ }
+
+ Uint8List _asUint8ListUnsafe() {
+ _ensureIsDirect();
+ final address = _directBufferAddress();
+ final capacity = _directBufferCapacity();
+ return address.cast<Uint8>().asTypedList(capacity);
+ }
+
+ /// Returns this byte buffer as a [Uint8List].
+ ///
+ /// If [releaseOriginal] is `true`, this byte buffer will be released.
+ ///
+ /// Throws [StateError] if the buffer is not direct
+ /// (see [JByteBuffer.allocateDirect]) or the JVM does not support the direct
+ /// buffer operations or the object is an unaligned view buffer and
+ /// the processor does not support unaligned access.
+ Uint8List asUint8List({bool releaseOriginal = false}) {
+ _ensureIsDirect();
+ final address = _directBufferAddress();
+ final capacity = _directBufferCapacity();
+ final token = releaseOriginal ? reference : Jni.env.NewGlobalRef(reference);
+ if (releaseOriginal) {
+ setAsReleased();
+ }
+ return address.cast<Uint8>().asTypedList(
+ capacity,
+ token: token,
+ finalizer: Jni.env.ptr.ref.DeleteGlobalRef.cast(),
+ );
+ }
+}
+
+extension Uint8ListToJava on Uint8List {
+ /// Creates a [JByteBuffer] from the content of this list.
+ ///
+ /// The [JByteBuffer] will be allocated using [JByteBuffer.allocateDirect].
+ JByteBuffer toJByteBuffer() {
+ return JByteBuffer.fromList(this);
+ }
+}
diff --git a/pkgs/jni/lib/src/nio/nio.dart b/pkgs/jni/lib/src/nio/nio.dart
new file mode 100644
index 0000000..3092870
--- /dev/null
+++ b/pkgs/jni/lib/src/nio/nio.dart
@@ -0,0 +1,6 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+export 'jbuffer.dart';
+export 'jbyte_buffer.dart';
diff --git a/pkgs/jni/lib/src/util/jiterator.dart b/pkgs/jni/lib/src/util/jiterator.dart
index eab305d..0d0122f 100644
--- a/pkgs/jni/lib/src/util/jiterator.dart
+++ b/pkgs/jni/lib/src/util/jiterator.dart
@@ -8,7 +8,7 @@
import '../third_party/generated_bindings.dart';
import '../types.dart';
-class JIteratorType<$E extends JObject> extends JObjType<JIterator<$E>> {
+final class JIteratorType<$E extends JObject> extends JObjType<JIterator<$E>> {
final JObjType<$E> E;
const JIteratorType(
diff --git a/pkgs/jni/lib/src/util/jlist.dart b/pkgs/jni/lib/src/util/jlist.dart
index 19cb1ed..9779032 100644
--- a/pkgs/jni/lib/src/util/jlist.dart
+++ b/pkgs/jni/lib/src/util/jlist.dart
@@ -15,7 +15,7 @@
import '../types.dart';
import 'jiterator.dart';
-class JListType<$E extends JObject> extends JObjType<JList<$E>> {
+final class JListType<$E extends JObject> extends JObjType<JList<$E>> {
final JObjType<$E> E;
const JListType(
@@ -193,10 +193,11 @@
Jni.env.IsInstanceOf(
(iterable as JObject).reference, _collectionClass.reference)) {
Jni.accessors.callMethodWithArgs(
- reference,
- _insertAllId,
- JniCallType.booleanType,
- [JValueInt(index), (iterable as JObject).reference]);
+ reference,
+ _insertAllId,
+ JniCallType.booleanType,
+ [JValueInt(index), (iterable as JObject).reference],
+ ).boolean;
return;
}
super.insertAll(index, iterable);
diff --git a/pkgs/jni/lib/src/util/jmap.dart b/pkgs/jni/lib/src/util/jmap.dart
index 015fea8..73a6d62 100644
--- a/pkgs/jni/lib/src/util/jmap.dart
+++ b/pkgs/jni/lib/src/util/jmap.dart
@@ -11,7 +11,7 @@
import '../types.dart';
import 'jset.dart';
-class JMapType<$K extends JObject, $V extends JObject>
+final class JMapType<$K extends JObject, $V extends JObject>
extends JObjType<JMap<$K, $V>> {
final JObjType<$K> K;
final JObjType<$V> V;
@@ -107,11 +107,9 @@
if (other is JMap<$K, $V>) {
Jni.accessors.callMethodWithArgs(reference, _addAllId,
JniCallType.voidType, [other.reference]).check();
- } else {
- for (final entry in other.entries) {
- this[entry.key] = entry.value;
- }
+ return;
}
+ super.addAll(other);
}
static final _clearId =
diff --git a/pkgs/jni/lib/src/util/jset.dart b/pkgs/jni/lib/src/util/jset.dart
index 367c121..df51003 100644
--- a/pkgs/jni/lib/src/util/jset.dart
+++ b/pkgs/jni/lib/src/util/jset.dart
@@ -12,7 +12,7 @@
import '../types.dart';
import 'jiterator.dart';
-class JSetType<$E extends JObject> extends JObjType<JSet<$E>> {
+final class JSetType<$E extends JObject> extends JObjType<JSet<$E>> {
final JObjType<$E> E;
const JSetType(
@@ -93,6 +93,7 @@
JniCallType.booleanType,
[(elements as JObject).reference],
).boolean;
+ return;
}
return super.addAll(elements);
}
@@ -173,6 +174,7 @@
(elements as JObject).reference, _collectionClass.reference)) {
Jni.accessors.callMethodWithArgs(reference, _removeAllId,
JniCallType.booleanType, [(elements as JObject).reference]).boolean;
+ return;
}
return super.removeAll(elements);
}
@@ -186,6 +188,7 @@
(elements as JObject).reference, _collectionClass.reference)) {
Jni.accessors.callMethodWithArgs(reference, _retainAllId,
JniCallType.booleanType, [(elements as JObject).reference]).boolean;
+ return;
}
return super.retainAll(elements);
}
diff --git a/pkgs/jni/pubspec.yaml b/pkgs/jni/pubspec.yaml
index 62ba94d..46bedce 100644
--- a/pkgs/jni/pubspec.yaml
+++ b/pkgs/jni/pubspec.yaml
@@ -4,7 +4,7 @@
name: jni
description: A library to access JNI from Dart and Flutter that acts as a support library for package:jnigen.
-version: 0.6.1
+version: 0.7.0
repository: https://github.com/dart-lang/jnigen/tree/main/jni
topics:
diff --git a/pkgs/jni/test/jarray_test.dart b/pkgs/jni/test/jarray_test.dart
index 3cc7c98..9a9f59c 100644
--- a/pkgs/jni/test/jarray_test.dart
+++ b/pkgs/jni/test/jarray_test.dart
@@ -319,6 +319,12 @@
expect((arr[0]..releasedBy(arena)).isNull, true);
});
});
+ testRunner('JArray of JCharacter', () {
+ using((arena) {
+ final arr = JArray(JCharacter.type, 1)..releasedBy(arena);
+ expect((arr[0]..releasedBy(arena)).isNull, true);
+ });
+ });
testRunner('JArray of JLong', () {
using((arena) {
final arr = JArray(JLong.type, 1)..releasedBy(arena);
diff --git a/pkgs/jni/test/jbyte_buffer_test.dart b/pkgs/jni/test/jbyte_buffer_test.dart
new file mode 100644
index 0000000..f68c47b
--- /dev/null
+++ b/pkgs/jni/test/jbyte_buffer_test.dart
@@ -0,0 +1,229 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+import 'dart:typed_data';
+
+import 'package:jni/jni.dart';
+import 'package:test/test.dart';
+
+import 'test_util/test_util.dart';
+
+void main() {
+ // Don't forget to initialize JNI.
+ if (!Platform.isAndroid) {
+ checkDylibIsUpToDate();
+ Jni.spawnIfNotExists(dylibDir: "build/jni_libs", jvmOptions: ["-Xmx128m"]);
+ }
+ run(testRunner: test);
+}
+
+void run({required TestRunnerCallback testRunner}) {
+ final throwsAJniException = throwsA(isA<JniException>());
+ JByteBuffer testDataBuffer(Arena arena) {
+ final buffer = JByteBuffer.allocate(3)..releasedBy(arena);
+ buffer.nextByte = 1;
+ buffer.nextByte = 2;
+ buffer.nextByte = 3;
+ buffer.position = 0;
+ return buffer;
+ }
+
+ testRunner('wrap whole array', () {
+ using((arena) {
+ final array = JArray(jbyte.type, 3)..releasedBy(arena);
+ array[0] = 1;
+ array[1] = 2;
+ array[2] = 3;
+ final buffer = JByteBuffer.wrap(array)..releasedBy(arena);
+ expect(buffer, testDataBuffer(arena));
+ });
+ });
+
+ testRunner('wrap partial array', () {
+ using((arena) {
+ final array = JArray(jbyte.type, 3)..releasedBy(arena);
+ array[0] = 1;
+ array[1] = 2;
+ array[2] = 3;
+ final buffer = JByteBuffer.wrap(array, 1, 1)..releasedBy(arena);
+ expect(buffer.nextByte, 2);
+ expect(() => buffer.nextByte, throwsAJniException);
+ });
+ });
+
+ testRunner('capacity', () {
+ using((arena) {
+ final buffer = testDataBuffer(arena);
+ expect(buffer.capacity, 3);
+ });
+ });
+
+ testRunner('position', () {
+ using((arena) {
+ final buffer = testDataBuffer(arena);
+ expect(buffer.position, 0);
+ buffer.position = 2;
+ expect(buffer.position, 2);
+ });
+ });
+
+ testRunner('limit', () {
+ using((arena) {
+ final buffer = testDataBuffer(arena);
+ expect(buffer.limit, 3);
+ buffer.limit = 2;
+ expect(buffer.limit, 2);
+ });
+ });
+
+ testRunner('mark and reset', () {
+ using((arena) {
+ final buffer = testDataBuffer(arena);
+ buffer.position = 1;
+ buffer.mark();
+ buffer.position = 2;
+ buffer.reset();
+ expect(buffer.position, 1);
+ });
+ });
+
+ testRunner('clear', () {
+ using((arena) {
+ final buffer = testDataBuffer(arena);
+ buffer.position = 2;
+ buffer.limit = 2;
+ buffer.clear();
+ expect(buffer.limit, 3);
+ expect(buffer.position, 0);
+ });
+ });
+
+ testRunner('flip', () {
+ using((arena) {
+ final buffer = testDataBuffer(arena);
+ buffer.position = 2;
+ buffer.flip();
+ expect(buffer.limit, 2);
+ expect(buffer.position, 0);
+ });
+ });
+
+ testRunner('rewind', () {
+ using((arena) {
+ final buffer = testDataBuffer(arena);
+ buffer.mark();
+ buffer.position = 2;
+ buffer.rewind();
+ expect(buffer.position, 0);
+ expect(buffer.reset, throwsAJniException);
+ });
+ });
+
+ testRunner('remaining and hasRemaining', () {
+ using((arena) {
+ final buffer = testDataBuffer(arena);
+ buffer.position = 2;
+ expect(buffer.remaining, 1);
+ expect(buffer.hasRemaining, true);
+ buffer.position = 3;
+ expect(buffer.remaining, 0);
+ expect(buffer.hasRemaining, false);
+ });
+ });
+
+ testRunner('isReadOnly and asReadOnlyBuffer', () {
+ using((arena) {
+ final buffer = testDataBuffer(arena);
+ expect(buffer.isReadOnly, false);
+ final readOnly = buffer.asReadOnlyBuffer()..releasedBy(arena);
+ expect(readOnly.isReadOnly, true);
+ });
+ });
+
+ testRunner('hasArray, array and arrayOffset', () {
+ using((arena) {
+ final buffer = testDataBuffer(arena);
+ expect(buffer.hasArray, true);
+ expect(buffer.arrayOffset, 0);
+ expect(buffer.array.length, 3);
+ final directBuffer = JByteBuffer.allocateDirect(3)..releasedBy(arena);
+ expect(directBuffer.hasArray, false);
+ });
+ });
+
+ testRunner('isDirect', () {
+ using((arena) {
+ final buffer = testDataBuffer(arena);
+ expect(buffer.isDirect, false);
+ final directBuffer = JByteBuffer.allocateDirect(3)..releasedBy(arena);
+ expect(directBuffer.isDirect, true);
+ });
+ });
+
+ testRunner('slice', () {
+ using((arena) {
+ final buffer = testDataBuffer(arena);
+ buffer.position = 1;
+ buffer.limit = 2;
+ final sliced = buffer.slice()..releasedBy(arena);
+ expect(sliced.capacity, 1);
+ expect(sliced.nextByte, 2);
+ });
+ });
+
+ testRunner('duplicate', () {
+ using((arena) {
+ final buffer = testDataBuffer(arena);
+ buffer.position = 1;
+ buffer.limit = 2;
+ final duplicate = buffer.duplicate()..releasedBy(arena);
+ expect(duplicate.capacity, 3);
+ expect(duplicate.position, 1);
+ expect(duplicate.limit, 2);
+ });
+ });
+
+ testRunner('asUint8List', () {
+ using((arena) {
+ final buffer = testDataBuffer(arena);
+ expect(buffer.asUint8List, throwsA(isA<StateError>()));
+ final list = Uint8List.fromList([1, 2, 3]);
+ final directBuffer = list.toJByteBuffer()..releasedBy(arena);
+ expect(directBuffer.asUint8List(), list);
+ });
+ });
+
+ testRunner('type hashCode, ==', () {
+ using((arena) {
+ final a = testDataBuffer(arena);
+ final b = testDataBuffer(arena);
+ expect(a.$type, b.$type);
+ expect(a.$type.hashCode, b.$type.hashCode);
+ final c = JBuffer.fromRef(nullptr);
+ final d = JBuffer.fromRef(nullptr);
+ expect(c.$type, d.$type);
+ expect(c.$type.hashCode, d.$type.hashCode);
+
+ expect(a.$type, isNot(c.$type));
+ expect(a.$type.hashCode, isNot(c.$type.hashCode));
+ });
+ });
+
+ testRunner('asUint8List releasing original', () {
+ using((arena) {
+ // Used as an example in [JByteBuffer].
+ final directBuffer = JByteBuffer.allocateDirect(3);
+ final data1 = directBuffer.asUint8List();
+ directBuffer.nextByte = 42; // No problem!
+ expect(data1[0], 42);
+ final data2 = directBuffer.asUint8List(releaseOriginal: true);
+ expect(
+ () => directBuffer.nextByte = 42,
+ throwsA(isA<UseAfterReleaseException>()),
+ );
+ expect(data2[0], 42);
+ });
+ });
+}
diff --git a/pkgs/jni/test/type_test.dart b/pkgs/jni/test/type_test.dart
index f0f3caa..0ad8490 100644
--- a/pkgs/jni/test/type_test.dart
+++ b/pkgs/jni/test/type_test.dart
@@ -25,7 +25,7 @@
JObjType<JObject> get $type => $AType();
}
-class $AType extends JObjType<A> {
+final class $AType extends JObjType<A> {
@override
A fromRef(Pointer<Void> ref) {
return A.fromRef(ref);
@@ -55,7 +55,7 @@
JObjType<JObject> get $type => $BType();
}
-class $BType extends JObjType<B> {
+final class $BType extends JObjType<B> {
@override
B fromRef(Pointer<Void> ref) {
return B.fromRef(ref);
@@ -86,7 +86,7 @@
JObjType<JObject> get $type => $CType();
}
-class $CType extends JObjType<C> {
+final class $CType extends JObjType<C> {
@override
C fromRef(Pointer<Void> ref) {
return C.fromRef(ref);
@@ -117,7 +117,7 @@
JObjType<JObject> get $type => $DType();
}
-class $DType extends JObjType<D> {
+final class $DType extends JObjType<D> {
@override
D fromRef(Pointer<Void> ref) {
return D.fromRef(ref);
@@ -148,7 +148,7 @@
JObjType<JObject> get $type => $EType();
}
-class $EType extends JObjType<E> {
+final class $EType extends JObjType<E> {
@override
E fromRef(Pointer<Void> ref) {
return E.fromRef(ref);
@@ -179,7 +179,7 @@
JObjType<JObject> get $type => $FType();
}
-class $FType extends JObjType<F> {
+final class $FType extends JObjType<F> {
@override
F fromRef(Pointer<Void> ref) {
return F.fromRef(ref);
@@ -292,6 +292,13 @@
]),
JObject.type,
);
+ expect(
+ lowestCommonSuperType([
+ JByteBuffer.type,
+ JBuffer.type,
+ ]),
+ JBuffer.type,
+ );
});
});
diff --git a/pkgs/jnigen/CHANGELOG.md b/pkgs/jnigen/CHANGELOG.md
index 7e18e40..00b2fc1 100644
--- a/pkgs/jnigen/CHANGELOG.md
+++ b/pkgs/jnigen/CHANGELOG.md
@@ -1,41 +1,74 @@
-## 0.6.1-wip
-* Add `ignore_for_file: lines_longer_than_80_chars` to the generated file preamble.
-* Added an explicit cast in generated `<Interface>.implement` code to allow `dart analyze` to pass when `strict-casts` is set.
+## 0.7.0
+
+- **Breaking Change** ([#387](https://github.com/dart-lang/jnigen/issues/387)):
+ Added `JBuffer` and `JByteBuffer` classes as default classes for
+ `java.nio.Buffer` and `java.nio.ByteBuffer` respectively.
+- **Breaking Change**: Made the type classes `final`.
+- Added `ignore_for_file: lines_longer_than_80_chars` to the generated file
+ preamble.
+- Added an explicit cast in generated `<Interface>.implement` code to allow
+ `dart analyze` to pass when `strict-casts` is set.
## 0.6.0
-* **Breaking Change** ([#131](https://github.com/dart-lang/jnigen/issues/131)): Renamed `delete*` to `release*`.
-* **Breaking Change** ([#354](https://github.com/dart-lang/jnigen/issues/354)): Renamed constructors from `ctor1`, `ctor2`, ... to `new1`, `new2`, ...
-* **Breaking Change**: Specifying a class always pulls in nested classes by default. If a nested class is specified in config, it will be an error.
-* **Breaking Change**: Removed `suspend_fun_to_async` flag from the config. It's now happening by default since we read the Kotlin's metadata and reliably identify the `suspend fun`s.
-* Fixed a bug where the nested classes would be generated incorrectly depending on the backend used for generation.
-* Fixed a bug where ASM backend would produce the incorrect parent for multi-level nested classes.
-* Fixed a bug where the backends would produce different descriptors for the same method.
-* Added `enable_experiment` option to config.
-* Created an experiment called `interface_implementation` which creates a `.implement` method for interfaces, so you can implement them using Dart.
-* Save all `jnigen` logs to a file in `.dart_tool/jnigen/logs/`. This is useful for debugging.
+
+- **Breaking Change** ([#131](https://github.com/dart-lang/jnigen/issues/131)):
+ Renamed `delete*` to `release*`.
+- **Breaking Change** ([#354](https://github.com/dart-lang/jnigen/issues/354)):
+ Renamed constructors from `ctor1`, `ctor2`, ... to `new1`, `new2`, ...
+- **Breaking Change**: Specifying a class always pulls in nested classes by
+ default. If a nested class is specified in config, it will be an error.
+- **Breaking Change**: Removed `suspend_fun_to_async` flag from the config. It's
+ now happening by default since we read the Kotlin's metadata and reliably
+ identify the `suspend fun`s.
+- Fixed a bug where the nested classes would be generated incorrectly depending
+ on the backend used for generation.
+- Fixed a bug where ASM backend would produce the incorrect parent for
+ multi-level nested classes.
+- Fixed a bug where the backends would produce different descriptors for the
+ same method.
+- Added `enable_experiment` option to config.
+- Created an experiment called `interface_implementation` which creates a
+ `.implement` method for interfaces, so you can implement them using Dart.
+- Save all `jnigen` logs to a file in `.dart_tool/jnigen/logs/`. This is useful
+ for debugging.
## 0.5.0
-* **Breaking Change** ([#72](https://github.com/dart-lang/jnigen/issues/72)): Removed support for `importMap` in favor of the newly added interop mechanism with importing yaml files.
-* **Breaking Change** ([#72](https://github.com/dart-lang/jnigen/issues/72)): `java.util.Set`, `java.util.Map`, `java.util.List`, `java.util.Iterator` and the boxed types like `java.lang.Integer`, `java.lang.Double`, ... will be generated as their corresponding classes in `package:jni`.
-* Strings now use UTF16.
+
+- **Breaking Change** ([#72](https://github.com/dart-lang/jnigen/issues/72)):
+ Removed support for `importMap` in favor of the newly added interop mechanism
+ with importing yaml files.
+- **Breaking Change** ([#72](https://github.com/dart-lang/jnigen/issues/72)):
+ `java.util.Set`, `java.util.Map`, `java.util.List`, `java.util.Iterator` and
+ the boxed types like `java.lang.Integer`, `java.lang.Double`, ... will be
+ generated as their corresponding classes in `package:jni`.
+- Strings now use UTF16.
## 0.4.0
-* **Breaking Change** ([#145](https://github.com/dart-lang/jnigen/issues/145)): Type arguments are now named instead of positional.
-* Type parameters can now be inferred when possible.
-* Fixed a bug where passing a `long` argument truncated it to `int` in pure dart bindings.
-* Removed array extensions from the generated code.
-* Added the ability to use source dependencies from Gradle.
-* Fixed an issue with the field setter.
-* Fixed an issue where exceptions were not properly thrown in pure Dart bindings.
+
+- **Breaking Change** ([#145](https://github.com/dart-lang/jnigen/issues/145)):
+ Type arguments are now named instead of positional.
+- Type parameters can now be inferred when possible.
+- Fixed a bug where passing a `long` argument truncated it to `int` in pure dart
+ bindings.
+- Removed array extensions from the generated code.
+- Added the ability to use source dependencies from Gradle.
+- Fixed an issue with the field setter.
+- Fixed an issue where exceptions were not properly thrown in pure Dart
+ bindings.
## 0.3.0
-* Added the option to convert Kotlin `suspend fun` to Dart async methods. Add `suspend_fun_to_async: true` to `jnigen.yaml`.
+
+- Added the option to convert Kotlin `suspend fun` to Dart async methods. Add
+ `suspend_fun_to_async: true` to `jnigen.yaml`.
## 0.2.0
-* Support generating bindings for generics.
+
+- Support generating bindings for generics.
## 0.1.1
-* Windows support for running tests and examples on development machines.
+
+- Windows support for running tests and examples on development machines.
## 0.1.0
-* Initial version: Basic bindings generation, maven and android utilities
+
+- Initial version: Basic bindings generation, maven and android utilities
diff --git a/pkgs/jnigen/example/in_app_java/lib/android_utils.dart b/pkgs/jnigen/example/in_app_java/lib/android_utils.dart
index ec72286..8a0e58a 100644
--- a/pkgs/jnigen/example/in_app_java/lib/android_utils.dart
+++ b/pkgs/jnigen/example/in_app_java/lib/android_utils.dart
@@ -55,7 +55,7 @@
}
}
-class $AndroidUtilsType extends jni.JObjType<AndroidUtils> {
+final class $AndroidUtilsType extends jni.JObjType<AndroidUtils> {
const $AndroidUtilsType();
@override
@@ -1027,7 +1027,7 @@
}
}
-class $EmojiCompatType extends jni.JObjType<EmojiCompat> {
+final class $EmojiCompatType extends jni.JObjType<EmojiCompat> {
const $EmojiCompatType();
@override
@@ -1361,7 +1361,7 @@
}
}
-class $EmojiCompat_ConfigType extends jni.JObjType<EmojiCompat_Config> {
+final class $EmojiCompat_ConfigType extends jni.JObjType<EmojiCompat_Config> {
const $EmojiCompat_ConfigType();
@override
@@ -1450,7 +1450,7 @@
}
}
-class $EmojiCompat_MetadataRepoLoaderCallbackType
+final class $EmojiCompat_MetadataRepoLoaderCallbackType
extends jni.JObjType<EmojiCompat_MetadataRepoLoaderCallback> {
const $EmojiCompat_MetadataRepoLoaderCallbackType();
@@ -1551,7 +1551,7 @@
}
}
-class $EmojiCompat_GlyphCheckerType
+final class $EmojiCompat_GlyphCheckerType
extends jni.JObjType<EmojiCompat_GlyphChecker> {
const $EmojiCompat_GlyphCheckerType();
@@ -1613,7 +1613,7 @@
}
}
-class $EmojiCompat_MetadataRepoLoaderType
+final class $EmojiCompat_MetadataRepoLoaderType
extends jni.JObjType<EmojiCompat_MetadataRepoLoader> {
const $EmojiCompat_MetadataRepoLoaderType();
@@ -1697,7 +1697,7 @@
}
}
-class $EmojiCompat_InitCallbackType
+final class $EmojiCompat_InitCallbackType
extends jni.JObjType<EmojiCompat_InitCallback> {
const $EmojiCompat_InitCallbackType();
@@ -1771,7 +1771,7 @@
}
}
-class $EmojiCompat_DefaultSpanFactoryType
+final class $EmojiCompat_DefaultSpanFactoryType
extends jni.JObjType<EmojiCompat_DefaultSpanFactory> {
const $EmojiCompat_DefaultSpanFactoryType();
@@ -1841,7 +1841,7 @@
}
}
-class $EmojiCompat_SpanFactoryType
+final class $EmojiCompat_SpanFactoryType
extends jni.JObjType<EmojiCompat_SpanFactory> {
const $EmojiCompat_SpanFactoryType();
@@ -1939,7 +1939,7 @@
}
}
-class $DefaultEmojiCompatConfigType
+final class $DefaultEmojiCompatConfigType
extends jni.JObjType<DefaultEmojiCompatConfig> {
const $DefaultEmojiCompatConfigType();
@@ -2017,7 +2017,7 @@
}
}
-class $DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28Type
+final class $DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28Type
extends jni
.JObjType<DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28> {
const $DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28Type();
@@ -2126,7 +2126,7 @@
}
}
-class $DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19Type
+final class $DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19Type
extends jni
.JObjType<DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19> {
const $DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19Type();
@@ -2264,7 +2264,8 @@
}
}
-class $DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelperType extends jni
+final class $DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelperType
+ extends jni
.JObjType<DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper> {
const $DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelperType();
@@ -2353,7 +2354,8 @@
}
}
-class $DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactoryType extends jni
+final class $DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactoryType
+ extends jni
.JObjType<DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory> {
const $DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactoryType();
@@ -2461,7 +2463,7 @@
}
}
-class $Build_PartitionType extends jni.JObjType<Build_Partition> {
+final class $Build_PartitionType extends jni.JObjType<Build_Partition> {
const $Build_PartitionType();
@override
@@ -2613,7 +2615,7 @@
}
}
-class $Build_VERSIONType extends jni.JObjType<Build_VERSION> {
+final class $Build_VERSIONType extends jni.JObjType<Build_VERSION> {
const $Build_VERSIONType();
@override
@@ -2763,7 +2765,7 @@
}
}
-class $Build_VERSION_CODESType extends jni.JObjType<Build_VERSION_CODES> {
+final class $Build_VERSION_CODESType extends jni.JObjType<Build_VERSION_CODES> {
const $Build_VERSION_CODESType();
@override
@@ -3112,7 +3114,7 @@
}
}
-class $BuildType extends jni.JObjType<Build> {
+final class $BuildType extends jni.JObjType<Build> {
const $BuildType();
@override
@@ -3624,7 +3626,7 @@
}
}
-class $HashMapType<$K extends jni.JObject, $V extends jni.JObject>
+final class $HashMapType<$K extends jni.JObject, $V extends jni.JObject>
extends jni.JObjType<HashMap<$K, $V>> {
final jni.JObjType<$K> K;
final jni.JObjType<$V> V;
diff --git a/pkgs/jnigen/example/kotlin_plugin/lib/kotlin_bindings.dart b/pkgs/jnigen/example/kotlin_plugin/lib/kotlin_bindings.dart
index ed2d034..efd0351 100644
--- a/pkgs/jnigen/example/kotlin_plugin/lib/kotlin_bindings.dart
+++ b/pkgs/jnigen/example/kotlin_plugin/lib/kotlin_bindings.dart
@@ -71,7 +71,7 @@
}
}
-class $ExampleType extends jni.JObjType<Example> {
+final class $ExampleType extends jni.JObjType<Example> {
const $ExampleType();
@override
diff --git a/pkgs/jnigen/example/notification_plugin/lib/notifications.dart b/pkgs/jnigen/example/notification_plugin/lib/notifications.dart
index ebb2f59..9855d16 100644
--- a/pkgs/jnigen/example/notification_plugin/lib/notifications.dart
+++ b/pkgs/jnigen/example/notification_plugin/lib/notifications.dart
@@ -75,7 +75,7 @@
}
}
-class $NotificationsType extends jni.JObjType<Notifications> {
+final class $NotificationsType extends jni.JObjType<Notifications> {
const $NotificationsType();
@override
diff --git a/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/pdmodel/PDDocument.dart b/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/pdmodel/PDDocument.dart
index 03a9da2..b2c40a2 100644
--- a/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/pdmodel/PDDocument.dart
+++ b/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/pdmodel/PDDocument.dart
@@ -1510,7 +1510,7 @@
}
}
-class $PDDocumentType extends jni.JObjType<PDDocument> {
+final class $PDDocumentType extends jni.JObjType<PDDocument> {
const $PDDocumentType();
@override
diff --git a/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/pdmodel/PDDocumentInformation.dart b/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/pdmodel/PDDocumentInformation.dart
index d928d21..3c959e7 100644
--- a/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/pdmodel/PDDocumentInformation.dart
+++ b/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/pdmodel/PDDocumentInformation.dart
@@ -496,7 +496,8 @@
}
}
-class $PDDocumentInformationType extends jni.JObjType<PDDocumentInformation> {
+final class $PDDocumentInformationType
+ extends jni.JObjType<PDDocumentInformation> {
const $PDDocumentInformationType();
@override
diff --git a/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/text/PDFTextStripper.dart b/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/text/PDFTextStripper.dart
index b42cd9a..930240b 100644
--- a/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/text/PDFTextStripper.dart
+++ b/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/text/PDFTextStripper.dart
@@ -1398,7 +1398,7 @@
}
}
-class $PDFTextStripperType extends jni.JObjType<PDFTextStripper> {
+final class $PDFTextStripperType extends jni.JObjType<PDFTextStripper> {
const $PDFTextStripperType();
@override
diff --git a/pkgs/jnigen/lib/src/bindings/dart_generator.dart b/pkgs/jnigen/lib/src/bindings/dart_generator.dart
index d8fb60d..ed52373 100644
--- a/pkgs/jnigen/lib/src/bindings/dart_generator.dart
+++ b/pkgs/jnigen/lib/src/bindings/dart_generator.dart
@@ -589,7 +589,7 @@
? '($typeClassName).hashCode'
: 'Object.hash($typeClassName, $hashCodeTypeClasses)';
s.write('''
-class $typeClassName$typeParamsDef extends $_jType<$name$typeParamsCall> {
+final class $typeClassName$typeParamsDef extends $_jType<$name$typeParamsCall> {
$typeClassesDef
const $typeClassName(
diff --git a/pkgs/jnigen/pubspec.yaml b/pkgs/jnigen/pubspec.yaml
index d8d08f7..3fbd456 100644
--- a/pkgs/jnigen/pubspec.yaml
+++ b/pkgs/jnigen/pubspec.yaml
@@ -4,7 +4,7 @@
name: jnigen
description: A Dart bindings generator for Java and Kotlin that uses JNI under the hood to interop with Java virtual machine.
-version: 0.6.1-wip
+version: 0.7.0
repository: https://github.com/dart-lang/jnigen/tree/main/jnigen
environment:
diff --git a/pkgs/jnigen/test/jackson_core_test/third_party/c_based/dart_bindings/com/fasterxml/jackson/core/JsonFactory.dart b/pkgs/jnigen/test/jackson_core_test/third_party/c_based/dart_bindings/com/fasterxml/jackson/core/JsonFactory.dart
index e1f19fe..95ddfd5 100644
--- a/pkgs/jnigen/test/jackson_core_test/third_party/c_based/dart_bindings/com/fasterxml/jackson/core/JsonFactory.dart
+++ b/pkgs/jnigen/test/jackson_core_test/third_party/c_based/dart_bindings/com/fasterxml/jackson/core/JsonFactory.dart
@@ -1854,7 +1854,7 @@
}
}
-class $JsonFactoryType extends jni.JObjType<JsonFactory> {
+final class $JsonFactoryType extends jni.JObjType<JsonFactory> {
const $JsonFactoryType();
@override
@@ -1969,7 +1969,7 @@
}
}
-class $JsonFactory_FeatureType extends jni.JObjType<JsonFactory_Feature> {
+final class $JsonFactory_FeatureType extends jni.JObjType<JsonFactory_Feature> {
const $JsonFactory_FeatureType();
@override
diff --git a/pkgs/jnigen/test/jackson_core_test/third_party/c_based/dart_bindings/com/fasterxml/jackson/core/JsonParser.dart b/pkgs/jnigen/test/jackson_core_test/third_party/c_based/dart_bindings/com/fasterxml/jackson/core/JsonParser.dart
index 1dac51c..5775da7 100644
--- a/pkgs/jnigen/test/jackson_core_test/third_party/c_based/dart_bindings/com/fasterxml/jackson/core/JsonParser.dart
+++ b/pkgs/jnigen/test/jackson_core_test/third_party/c_based/dart_bindings/com/fasterxml/jackson/core/JsonParser.dart
@@ -2636,7 +2636,7 @@
}
}
-class $JsonParserType extends jni.JObjType<JsonParser> {
+final class $JsonParserType extends jni.JObjType<JsonParser> {
const $JsonParserType();
@override
@@ -2750,7 +2750,7 @@
}
}
-class $JsonParser_FeatureType extends jni.JObjType<JsonParser_Feature> {
+final class $JsonParser_FeatureType extends jni.JObjType<JsonParser_Feature> {
const $JsonParser_FeatureType();
@override
@@ -2818,7 +2818,8 @@
}
}
-class $JsonParser_NumberTypeType extends jni.JObjType<JsonParser_NumberType> {
+final class $JsonParser_NumberTypeType
+ extends jni.JObjType<JsonParser_NumberType> {
const $JsonParser_NumberTypeType();
@override
diff --git a/pkgs/jnigen/test/jackson_core_test/third_party/c_based/dart_bindings/com/fasterxml/jackson/core/JsonToken.dart b/pkgs/jnigen/test/jackson_core_test/third_party/c_based/dart_bindings/com/fasterxml/jackson/core/JsonToken.dart
index fdbd542..bab355e 100644
--- a/pkgs/jnigen/test/jackson_core_test/third_party/c_based/dart_bindings/com/fasterxml/jackson/core/JsonToken.dart
+++ b/pkgs/jnigen/test/jackson_core_test/third_party/c_based/dart_bindings/com/fasterxml/jackson/core/JsonToken.dart
@@ -213,7 +213,7 @@
}
}
-class $JsonTokenType extends jni.JObjType<JsonToken> {
+final class $JsonTokenType extends jni.JObjType<JsonToken> {
const $JsonTokenType();
@override
diff --git a/pkgs/jnigen/test/jackson_core_test/third_party/dart_only/dart_bindings/com/fasterxml/jackson/core/JsonFactory.dart b/pkgs/jnigen/test/jackson_core_test/third_party/dart_only/dart_bindings/com/fasterxml/jackson/core/JsonFactory.dart
index f9f3631..3cdf2ff 100644
--- a/pkgs/jnigen/test/jackson_core_test/third_party/dart_only/dart_bindings/com/fasterxml/jackson/core/JsonFactory.dart
+++ b/pkgs/jnigen/test/jackson_core_test/third_party/dart_only/dart_bindings/com/fasterxml/jackson/core/JsonFactory.dart
@@ -1756,7 +1756,7 @@
}
}
-class $JsonFactoryType extends jni.JObjType<JsonFactory> {
+final class $JsonFactoryType extends jni.JObjType<JsonFactory> {
const $JsonFactoryType();
@override
@@ -1868,7 +1868,7 @@
}
}
-class $JsonFactory_FeatureType extends jni.JObjType<JsonFactory_Feature> {
+final class $JsonFactory_FeatureType extends jni.JObjType<JsonFactory_Feature> {
const $JsonFactory_FeatureType();
@override
diff --git a/pkgs/jnigen/test/jackson_core_test/third_party/dart_only/dart_bindings/com/fasterxml/jackson/core/JsonParser.dart b/pkgs/jnigen/test/jackson_core_test/third_party/dart_only/dart_bindings/com/fasterxml/jackson/core/JsonParser.dart
index ae607a9..d94c220 100644
--- a/pkgs/jnigen/test/jackson_core_test/third_party/dart_only/dart_bindings/com/fasterxml/jackson/core/JsonParser.dart
+++ b/pkgs/jnigen/test/jackson_core_test/third_party/dart_only/dart_bindings/com/fasterxml/jackson/core/JsonParser.dart
@@ -2489,7 +2489,7 @@
}
}
-class $JsonParserType extends jni.JObjType<JsonParser> {
+final class $JsonParserType extends jni.JObjType<JsonParser> {
const $JsonParserType();
@override
@@ -2600,7 +2600,7 @@
}
}
-class $JsonParser_FeatureType extends jni.JObjType<JsonParser_Feature> {
+final class $JsonParser_FeatureType extends jni.JObjType<JsonParser_Feature> {
const $JsonParser_FeatureType();
@override
@@ -2672,7 +2672,8 @@
}
}
-class $JsonParser_NumberTypeType extends jni.JObjType<JsonParser_NumberType> {
+final class $JsonParser_NumberTypeType
+ extends jni.JObjType<JsonParser_NumberType> {
const $JsonParser_NumberTypeType();
@override
diff --git a/pkgs/jnigen/test/jackson_core_test/third_party/dart_only/dart_bindings/com/fasterxml/jackson/core/JsonToken.dart b/pkgs/jnigen/test/jackson_core_test/third_party/dart_only/dart_bindings/com/fasterxml/jackson/core/JsonToken.dart
index da0a49e..573a815 100644
--- a/pkgs/jnigen/test/jackson_core_test/third_party/dart_only/dart_bindings/com/fasterxml/jackson/core/JsonToken.dart
+++ b/pkgs/jnigen/test/jackson_core_test/third_party/dart_only/dart_bindings/com/fasterxml/jackson/core/JsonToken.dart
@@ -199,7 +199,7 @@
}
}
-class $JsonTokenType extends jni.JObjType<JsonToken> {
+final class $JsonTokenType extends jni.JObjType<JsonToken> {
const $JsonTokenType();
@override
diff --git a/pkgs/jnigen/test/kotlin_test/c_based/dart_bindings/kotlin.dart b/pkgs/jnigen/test/kotlin_test/c_based/dart_bindings/kotlin.dart
index 5b80bb8..3e26427 100644
--- a/pkgs/jnigen/test/kotlin_test/c_based/dart_bindings/kotlin.dart
+++ b/pkgs/jnigen/test/kotlin_test/c_based/dart_bindings/kotlin.dart
@@ -102,7 +102,7 @@
}
}
-class $SuspendFunType extends jni.JObjType<SuspendFun> {
+final class $SuspendFunType extends jni.JObjType<SuspendFun> {
const $SuspendFunType();
@override
diff --git a/pkgs/jnigen/test/kotlin_test/dart_only/dart_bindings/kotlin.dart b/pkgs/jnigen/test/kotlin_test/dart_only/dart_bindings/kotlin.dart
index c352dfb..bd4441f 100644
--- a/pkgs/jnigen/test/kotlin_test/dart_only/dart_bindings/kotlin.dart
+++ b/pkgs/jnigen/test/kotlin_test/dart_only/dart_bindings/kotlin.dart
@@ -92,7 +92,7 @@
}
}
-class $SuspendFunType extends jni.JObjType<SuspendFun> {
+final class $SuspendFunType extends jni.JObjType<SuspendFun> {
const $SuspendFunType();
@override
diff --git a/pkgs/jnigen/test/simple_package_test/c_based/dart_bindings/simple_package.dart b/pkgs/jnigen/test/simple_package_test/c_based/dart_bindings/simple_package.dart
index 2879e35..1142fd6 100644
--- a/pkgs/jnigen/test/simple_package_test/c_based/dart_bindings/simple_package.dart
+++ b/pkgs/jnigen/test/simple_package_test/c_based/dart_bindings/simple_package.dart
@@ -66,7 +66,7 @@
}
}
-class $ColorType extends jni.JObjType<Color> {
+final class $ColorType extends jni.JObjType<Color> {
const $ColorType();
@override
@@ -779,7 +779,7 @@
}
}
-class $ExampleType extends jni.JObjType<Example> {
+final class $ExampleType extends jni.JObjType<Example> {
const $ExampleType();
@override
@@ -864,7 +864,7 @@
}
}
-class $Example_NestedType extends jni.JObjType<Example_Nested> {
+final class $Example_NestedType extends jni.JObjType<Example_Nested> {
const $Example_NestedType();
@override
@@ -928,7 +928,7 @@
}
}
-class $Example_Nested_NestedTwiceType
+final class $Example_Nested_NestedTwiceType
extends jni.JObjType<Example_Nested_NestedTwice> {
const $Example_Nested_NestedTwiceType();
@@ -1004,7 +1004,7 @@
}
}
-class $Example_NonStaticNestedType
+final class $Example_NonStaticNestedType
extends jni.JObjType<Example_NonStaticNested> {
const $Example_NonStaticNestedType();
@@ -1249,7 +1249,7 @@
}
}
-class $ExceptionsType extends jni.JObjType<Exceptions> {
+final class $ExceptionsType extends jni.JObjType<Exceptions> {
const $ExceptionsType();
@override
@@ -1504,7 +1504,7 @@
}
}
-class $FieldsType extends jni.JObjType<Fields> {
+final class $FieldsType extends jni.JObjType<Fields> {
const $FieldsType();
@override
@@ -1594,7 +1594,7 @@
}
}
-class $Fields_NestedType extends jni.JObjType<Fields_Nested> {
+final class $Fields_NestedType extends jni.JObjType<Fields_Nested> {
const $Fields_NestedType();
@override
@@ -1658,7 +1658,7 @@
}
}
-class $C2Type extends jni.JObjType<C2> {
+final class $C2Type extends jni.JObjType<C2> {
const $C2Type();
@override
@@ -1715,7 +1715,7 @@
}
}
-class $Example1Type extends jni.JObjType<Example1> {
+final class $Example1Type extends jni.JObjType<Example1> {
const $Example1Type();
@override
@@ -1780,8 +1780,8 @@
}
}
-class $GenericTypeParamsType<$S extends jni.JObject, $K extends jni.JObject>
- extends jni.JObjType<GenericTypeParams<$S, $K>> {
+final class $GenericTypeParamsType<$S extends jni.JObject,
+ $K extends jni.JObject> extends jni.JObjType<GenericTypeParams<$S, $K>> {
final jni.JObjType<$S> S;
final jni.JObjType<$K> K;
@@ -1959,7 +1959,7 @@
}
}
-class $GrandParentType<$T extends jni.JObject>
+final class $GrandParentType<$T extends jni.JObject>
extends jni.JObjType<GrandParent<$T>> {
final jni.JObjType<$T> T;
@@ -2096,8 +2096,8 @@
}
}
-class $GrandParent_ParentType<$T extends jni.JObject, $S extends jni.JObject>
- extends jni.JObjType<GrandParent_Parent<$T, $S>> {
+final class $GrandParent_ParentType<$T extends jni.JObject,
+ $S extends jni.JObject> extends jni.JObjType<GrandParent_Parent<$T, $S>> {
final jni.JObjType<$T> T;
final jni.JObjType<$S> S;
@@ -2275,7 +2275,7 @@
}
}
-class $GrandParent_Parent_ChildType<$T extends jni.JObject,
+final class $GrandParent_Parent_ChildType<$T extends jni.JObject,
$S extends jni.JObject, $U extends jni.JObject>
extends jni.JObjType<GrandParent_Parent_Child<$T, $S, $U>> {
final jni.JObjType<$T> T;
@@ -2381,7 +2381,7 @@
}
}
-class $GrandParent_StaticParentType<$S extends jni.JObject>
+final class $GrandParent_StaticParentType<$S extends jni.JObject>
extends jni.JObjType<GrandParent_StaticParent<$S>> {
final jni.JObjType<$S> S;
@@ -2528,7 +2528,7 @@
}
}
-class $GrandParent_StaticParent_ChildType<$S extends jni.JObject,
+final class $GrandParent_StaticParent_ChildType<$S extends jni.JObject,
$U extends jni.JObject>
extends jni.JObjType<GrandParent_StaticParent_Child<$S, $U>> {
final jni.JObjType<$S> S;
@@ -2653,7 +2653,7 @@
}
}
-class $MyMapType<$K extends jni.JObject, $V extends jni.JObject>
+final class $MyMapType<$K extends jni.JObject, $V extends jni.JObject>
extends jni.JObjType<MyMap<$K, $V>> {
final jni.JObjType<$K> K;
final jni.JObjType<$V> V;
@@ -2796,7 +2796,7 @@
}
}
-class $MyMap_MyEntryType<$K extends jni.JObject, $V extends jni.JObject>
+final class $MyMap_MyEntryType<$K extends jni.JObject, $V extends jni.JObject>
extends jni.JObjType<MyMap_MyEntry<$K, $V>> {
final jni.JObjType<$K> K;
final jni.JObjType<$V> V;
@@ -2996,7 +2996,8 @@
}
}
-class $MyStackType<$T extends jni.JObject> extends jni.JObjType<MyStack<$T>> {
+final class $MyStackType<$T extends jni.JObject>
+ extends jni.JObjType<MyStack<$T>> {
final jni.JObjType<$T> T;
const $MyStackType(
@@ -3060,7 +3061,7 @@
}
}
-class $StringKeyedMapType<$V extends jni.JObject>
+final class $StringKeyedMapType<$V extends jni.JObject>
extends jni.JObjType<StringKeyedMap<$V>> {
final jni.JObjType<$V> V;
@@ -3115,7 +3116,7 @@
}
}
-class $StringMapType extends jni.JObjType<StringMap> {
+final class $StringMapType extends jni.JObjType<StringMap> {
const $StringMapType();
@override
@@ -3161,7 +3162,7 @@
}
}
-class $StringStackType extends jni.JObjType<StringStack> {
+final class $StringStackType extends jni.JObjType<StringStack> {
const $StringStackType();
@override
@@ -3219,7 +3220,7 @@
}
}
-class $StringValuedMapType<$K extends jni.JObject>
+final class $StringValuedMapType<$K extends jni.JObject>
extends jni.JObjType<StringValuedMap<$K>> {
final jni.JObjType<$K> K;
@@ -3500,7 +3501,7 @@
}
}
-class $MyInterfaceType<$T extends jni.JObject>
+final class $MyInterfaceType<$T extends jni.JObject>
extends jni.JObjType<MyInterface<$T>> {
final jni.JObjType<$T> T;
@@ -3624,7 +3625,7 @@
}
}
-class $MyInterfaceConsumerType extends jni.JObjType<MyInterfaceConsumer> {
+final class $MyInterfaceConsumerType extends jni.JObjType<MyInterfaceConsumer> {
const $MyInterfaceConsumerType();
@override
@@ -3762,7 +3763,7 @@
}
}
-class $MyRunnableType extends jni.JObjType<MyRunnable> {
+final class $MyRunnableType extends jni.JObjType<MyRunnable> {
const $MyRunnableType();
@override
@@ -3862,7 +3863,7 @@
}
}
-class $MyRunnableRunnerType extends jni.JObjType<MyRunnableRunner> {
+final class $MyRunnableRunnerType extends jni.JObjType<MyRunnableRunner> {
const $MyRunnableRunnerType();
@override
@@ -3927,7 +3928,8 @@
}
}
-class $JsonSerializable_CaseType extends jni.JObjType<JsonSerializable_Case> {
+final class $JsonSerializable_CaseType
+ extends jni.JObjType<JsonSerializable_Case> {
const $JsonSerializable_CaseType();
@override
@@ -3976,7 +3978,7 @@
}
}
-class $MyDataClassType extends jni.JObjType<MyDataClass> {
+final class $MyDataClassType extends jni.JObjType<MyDataClass> {
const $MyDataClassType();
@override
diff --git a/pkgs/jnigen/test/simple_package_test/dart_only/dart_bindings/simple_package.dart b/pkgs/jnigen/test/simple_package_test/dart_only/dart_bindings/simple_package.dart
index b549cc8..7ac848d 100644
--- a/pkgs/jnigen/test/simple_package_test/dart_only/dart_bindings/simple_package.dart
+++ b/pkgs/jnigen/test/simple_package_test/dart_only/dart_bindings/simple_package.dart
@@ -68,7 +68,7 @@
}
}
-class $ColorType extends jni.JObjType<Color> {
+final class $ColorType extends jni.JObjType<Color> {
const $ColorType();
@override
@@ -718,7 +718,7 @@
}
}
-class $ExampleType extends jni.JObjType<Example> {
+final class $ExampleType extends jni.JObjType<Example> {
const $ExampleType();
@override
@@ -799,7 +799,7 @@
}
}
-class $Example_NestedType extends jni.JObjType<Example_Nested> {
+final class $Example_NestedType extends jni.JObjType<Example_Nested> {
const $Example_NestedType();
@override
@@ -865,7 +865,7 @@
}
}
-class $Example_Nested_NestedTwiceType
+final class $Example_Nested_NestedTwiceType
extends jni.JObjType<Example_Nested_NestedTwice> {
const $Example_Nested_NestedTwiceType();
@@ -935,7 +935,7 @@
}
}
-class $Example_NonStaticNestedType
+final class $Example_NonStaticNestedType
extends jni.JObjType<Example_NonStaticNested> {
const $Example_NonStaticNestedType();
@@ -1172,7 +1172,7 @@
}
}
-class $ExceptionsType extends jni.JObjType<Exceptions> {
+final class $ExceptionsType extends jni.JObjType<Exceptions> {
const $ExceptionsType();
@override
@@ -1383,7 +1383,7 @@
}
}
-class $FieldsType extends jni.JObjType<Fields> {
+final class $FieldsType extends jni.JObjType<Fields> {
const $FieldsType();
@override
@@ -1467,7 +1467,7 @@
}
}
-class $Fields_NestedType extends jni.JObjType<Fields_Nested> {
+final class $Fields_NestedType extends jni.JObjType<Fields_Nested> {
const $Fields_NestedType();
@override
@@ -1533,7 +1533,7 @@
}
}
-class $C2Type extends jni.JObjType<C2> {
+final class $C2Type extends jni.JObjType<C2> {
const $C2Type();
@override
@@ -1591,7 +1591,7 @@
}
}
-class $Example1Type extends jni.JObjType<Example1> {
+final class $Example1Type extends jni.JObjType<Example1> {
const $Example1Type();
@override
@@ -1662,8 +1662,8 @@
}
}
-class $GenericTypeParamsType<$S extends jni.JObject, $K extends jni.JObject>
- extends jni.JObjType<GenericTypeParams<$S, $K>> {
+final class $GenericTypeParamsType<$S extends jni.JObject,
+ $K extends jni.JObject> extends jni.JObjType<GenericTypeParams<$S, $K>> {
final jni.JObjType<$S> S;
final jni.JObjType<$K> K;
@@ -1835,7 +1835,7 @@
}
}
-class $GrandParentType<$T extends jni.JObject>
+final class $GrandParentType<$T extends jni.JObject>
extends jni.JObjType<GrandParent<$T>> {
final jni.JObjType<$T> T;
@@ -1957,8 +1957,8 @@
}
}
-class $GrandParent_ParentType<$T extends jni.JObject, $S extends jni.JObject>
- extends jni.JObjType<GrandParent_Parent<$T, $S>> {
+final class $GrandParent_ParentType<$T extends jni.JObject,
+ $S extends jni.JObject> extends jni.JObjType<GrandParent_Parent<$T, $S>> {
final jni.JObjType<$T> T;
final jni.JObjType<$S> S;
@@ -2111,7 +2111,7 @@
}
}
-class $GrandParent_Parent_ChildType<$T extends jni.JObject,
+final class $GrandParent_Parent_ChildType<$T extends jni.JObject,
$S extends jni.JObject, $U extends jni.JObject>
extends jni.JObjType<GrandParent_Parent_Child<$T, $S, $U>> {
final jni.JObjType<$T> T;
@@ -2211,7 +2211,7 @@
}
}
-class $GrandParent_StaticParentType<$S extends jni.JObject>
+final class $GrandParent_StaticParentType<$S extends jni.JObject>
extends jni.JObjType<GrandParent_StaticParent<$S>> {
final jni.JObjType<$S> S;
@@ -2341,7 +2341,7 @@
}
}
-class $GrandParent_StaticParent_ChildType<$S extends jni.JObject,
+final class $GrandParent_StaticParent_ChildType<$S extends jni.JObject,
$U extends jni.JObject>
extends jni.JObjType<GrandParent_StaticParent_Child<$S, $U>> {
final jni.JObjType<$S> S;
@@ -2464,7 +2464,7 @@
}
}
-class $MyMapType<$K extends jni.JObject, $V extends jni.JObject>
+final class $MyMapType<$K extends jni.JObject, $V extends jni.JObject>
extends jni.JObjType<MyMap<$K, $V>> {
final jni.JObjType<$K> K;
final jni.JObjType<$V> V;
@@ -2592,7 +2592,7 @@
}
}
-class $MyMap_MyEntryType<$K extends jni.JObject, $V extends jni.JObject>
+final class $MyMap_MyEntryType<$K extends jni.JObject, $V extends jni.JObject>
extends jni.JObjType<MyMap_MyEntry<$K, $V>> {
final jni.JObjType<$K> K;
final jni.JObjType<$V> V;
@@ -2797,7 +2797,8 @@
}
}
-class $MyStackType<$T extends jni.JObject> extends jni.JObjType<MyStack<$T>> {
+final class $MyStackType<$T extends jni.JObject>
+ extends jni.JObjType<MyStack<$T>> {
final jni.JObjType<$T> T;
const $MyStackType(
@@ -2866,7 +2867,7 @@
}
}
-class $StringKeyedMapType<$V extends jni.JObject>
+final class $StringKeyedMapType<$V extends jni.JObject>
extends jni.JObjType<StringKeyedMap<$V>> {
final jni.JObjType<$V> V;
@@ -2924,7 +2925,7 @@
}
}
-class $StringMapType extends jni.JObjType<StringMap> {
+final class $StringMapType extends jni.JObjType<StringMap> {
const $StringMapType();
@override
@@ -2973,7 +2974,7 @@
}
}
-class $StringStackType extends jni.JObjType<StringStack> {
+final class $StringStackType extends jni.JObjType<StringStack> {
const $StringStackType();
@override
@@ -3036,7 +3037,7 @@
}
}
-class $StringValuedMapType<$K extends jni.JObject>
+final class $StringValuedMapType<$K extends jni.JObject>
extends jni.JObjType<StringValuedMap<$K>> {
final jni.JObjType<$K> K;
@@ -3309,7 +3310,7 @@
}
}
-class $MyInterfaceType<$T extends jni.JObject>
+final class $MyInterfaceType<$T extends jni.JObject>
extends jni.JObjType<MyInterface<$T>> {
final jni.JObjType<$T> T;
@@ -3430,7 +3431,7 @@
}
}
-class $MyInterfaceConsumerType extends jni.JObjType<MyInterfaceConsumer> {
+final class $MyInterfaceConsumerType extends jni.JObjType<MyInterfaceConsumer> {
const $MyInterfaceConsumerType();
@override
@@ -3569,7 +3570,7 @@
}
}
-class $MyRunnableType extends jni.JObjType<MyRunnable> {
+final class $MyRunnableType extends jni.JObjType<MyRunnable> {
const $MyRunnableType();
@override
@@ -3656,7 +3657,7 @@
}
}
-class $MyRunnableRunnerType extends jni.JObjType<MyRunnableRunner> {
+final class $MyRunnableRunnerType extends jni.JObjType<MyRunnableRunner> {
const $MyRunnableRunnerType();
@override
@@ -3725,7 +3726,8 @@
}
}
-class $JsonSerializable_CaseType extends jni.JObjType<JsonSerializable_Case> {
+final class $JsonSerializable_CaseType
+ extends jni.JObjType<JsonSerializable_Case> {
const $JsonSerializable_CaseType();
@override
@@ -3777,7 +3779,7 @@
}
}
-class $MyDataClassType extends jni.JObjType<MyDataClass> {
+final class $MyDataClassType extends jni.JObjType<MyDataClass> {
const $MyDataClassType();
@override