Skip to content

Commit 7efefec

Browse files
Make Some JNI functions leaf and remove Jni.accessors (#1355)
* Make some functions leaf, refactor array construction * Remove Jni.accessors
1 parent 4423654 commit 7efefec

21 files changed

+1009
-1078
lines changed

pkgs/jni/CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## 0.11.0-wip
2+
3+
- **Breaking Change** Removed `Jni.accessors`.
4+
- Made most `Jni.env` methods into leaf functions to speed up their execution.
5+
16
## 0.10.1
27

38
- Fixed an issue with `JObject.castTo` where the type checking could fail in

pkgs/jni/lib/jni.dart

-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ export 'dart:ffi' show nullptr;
6565
export 'package:ffi/ffi.dart' show Arena, using;
6666

6767
export 'src/errors.dart';
68-
export 'src/jarray.dart';
6968
export 'src/jni.dart' hide ProtectedJniExtensions;
7069
export 'src/jobject.dart';
7170
export 'src/jreference.dart';

pkgs/jni/lib/src/accessors.dart

+1-18
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import '../jni.dart';
88

99
void _check(JThrowablePtr exception) {
1010
if (exception != nullptr) {
11-
Jni.accessors.throwException(exception);
11+
Jni.throwException(exception);
1212
}
1313
}
1414

@@ -102,20 +102,3 @@ extension JThrowableCheckMethod on JThrowablePtr {
102102
_check(this);
103103
}
104104
}
105-
106-
extension JniAccessorWrappers on JniAccessors {
107-
/// Rethrows Java exception in Dart as [JniException].
108-
///
109-
/// The original exception object is deleted by this method. The message
110-
/// and Java stack trace are included in the exception.
111-
void throwException(JThrowablePtr exception) {
112-
final details = getExceptionDetails(exception);
113-
final env = Jni.env;
114-
final message = env.toDartString(details.message);
115-
final stacktrace = env.toDartString(details.stacktrace);
116-
env.DeleteGlobalRef(exception);
117-
env.DeleteGlobalRef(details.message);
118-
env.DeleteGlobalRef(details.stacktrace);
119-
throw JniException(message, stacktrace);
120-
}
121-
}

pkgs/jni/lib/src/jarray.dart

+33-83
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,10 @@
44

55
// ignore_for_file: unnecessary_cast, overridden_fields
66

7-
import 'dart:ffi';
8-
import 'dart:typed_data';
9-
10-
import 'package:collection/collection.dart';
11-
import 'package:ffi/ffi.dart';
12-
13-
import '../internal_helpers_for_jnigen.dart';
14-
import 'jni.dart';
15-
import 'jobject.dart';
16-
import 'third_party/generated_bindings.dart';
17-
import 'types.dart';
7+
part of 'types.dart';
188

199
final class JArrayType<E> extends JObjType<JArray<E>> {
20-
final JType<E> elementType;
10+
final JArrayElementType<E> elementType;
2111

2212
const JArrayType(this.elementType);
2313

@@ -46,13 +36,13 @@ final class JArrayType<E> extends JObjType<JArray<E>> {
4636
}
4737

4838
class JArray<E> extends JObject {
49-
final JType<E> elementType;
39+
final JArrayElementType<E> elementType;
5040

5141
@override
5242
late final JArrayType<E> $type = type(elementType) as JArrayType<E>;
5343

5444
/// The type which includes information such as the signature of this class.
55-
static JObjType<JArray<T>> type<T>(JType<T> innerType) =>
45+
static JObjType<JArray<T>> type<T>(JArrayElementType<T> innerType) =>
5646
JArrayType(innerType);
5747

5848
/// Construct a new [JArray] with [reference] as its underlying reference.
@@ -62,40 +52,8 @@ class JArray<E> extends JObject {
6252
/// Creates a [JArray] of the given length from the given [elementType].
6353
///
6454
/// The [length] must be a non-negative integer.
65-
factory JArray(JType<E> elementType, int length) {
66-
const primitiveCallTypes = {
67-
'B': JniCallType.byteType,
68-
'Z': JniCallType.booleanType,
69-
'C': JniCallType.charType,
70-
'S': JniCallType.shortType,
71-
'I': JniCallType.intType,
72-
'J': JniCallType.longType,
73-
'F': JniCallType.floatType,
74-
'D': JniCallType.doubleType,
75-
};
76-
if (!primitiveCallTypes.containsKey(elementType.signature) &&
77-
elementType is JObjType) {
78-
final clazz = (elementType as JObjType).jClass;
79-
final array = JArray<E>.fromReference(
80-
elementType,
81-
JGlobalReference(
82-
Jni.accessors
83-
.newObjectArray(length, clazz.reference.pointer, nullptr)
84-
.objectPointer,
85-
),
86-
);
87-
clazz.release();
88-
return array;
89-
}
90-
return JArray.fromReference(
91-
elementType,
92-
JGlobalReference(
93-
Jni.accessors
94-
.newPrimitiveArray(
95-
length, primitiveCallTypes[elementType.signature]!)
96-
.objectPointer,
97-
),
98-
);
55+
factory JArray(JArrayElementType<E> elementType, int length) {
56+
return elementType._newArray(length);
9957
}
10058

10159
/// Creates a [JArray] of the given length with [fill] at each position.
@@ -105,25 +63,11 @@ class JArray<E> extends JObject {
10563
{JObjType<$E>? E}) {
10664
RangeError.checkNotNegative(length);
10765
E ??= fill.$type as JObjType<$E>;
108-
final clazz = E.jClass;
109-
final array = JArray<$E>.fromReference(
110-
E,
111-
JGlobalReference(Jni.accessors
112-
.newObjectArray(
113-
length, clazz.reference.pointer, fill.reference.pointer)
114-
.objectPointer),
115-
);
116-
clazz.release();
117-
return array;
66+
return E._newArray(length, fill);
11867
}
11968

12069
int? _length;
12170

122-
JniResult _elementAt(int index, int type) {
123-
RangeError.checkValidIndex(index, this);
124-
return Jni.accessors.getArrayElement(reference.pointer, index, type);
125-
}
126-
12771
/// The number of elements in this array.
12872
int get length {
12973
return _length ??= Jni.env.GetArrayLength(reference.pointer);
@@ -154,13 +98,13 @@ extension on Allocator {
15498

15599
extension BoolArray on JArray<jboolean> {
156100
bool operator [](int index) {
157-
return _elementAt(index, JniCallType.booleanType).boolean;
101+
RangeError.checkValidIndex(index, this);
102+
return Jni.env.GetBooleanArrayElement(reference.pointer, index);
158103
}
159104

160105
void operator []=(int index, bool value) {
161106
RangeError.checkValidIndex(index, this);
162-
Jni.accessors
163-
.setBooleanArrayElement(reference.pointer, index, value ? 1 : 0);
107+
Jni.env.SetBooleanArrayElement(reference.pointer, index, value);
164108
}
165109

166110
Uint8List getRange(int start, int end, {Allocator allocator = malloc}) {
@@ -187,12 +131,13 @@ extension BoolArray on JArray<jboolean> {
187131

188132
extension ByteArray on JArray<jbyte> {
189133
int operator [](int index) {
190-
return _elementAt(index, JniCallType.byteType).byte;
134+
RangeError.checkValidIndex(index, this);
135+
return Jni.env.GetByteArrayElement(reference.pointer, index);
191136
}
192137

193138
void operator []=(int index, int value) {
194139
RangeError.checkValidIndex(index, this);
195-
Jni.accessors.setByteArrayElement(reference.pointer, index, value).check();
140+
Jni.env.SetByteArrayElement(reference.pointer, index, value);
196141
}
197142

198143
Int8List getRange(int start, int end, {Allocator allocator = malloc}) {
@@ -222,12 +167,13 @@ extension ByteArray on JArray<jbyte> {
222167
/// the number of characters.
223168
extension CharArray on JArray<jchar> {
224169
int operator [](int index) {
225-
return _elementAt(index, JniCallType.charType).char;
170+
RangeError.checkValidIndex(index, this);
171+
return Jni.env.GetCharArrayElement(reference.pointer, index);
226172
}
227173

228174
void operator []=(int index, int value) {
229175
RangeError.checkValidIndex(index, this);
230-
Jni.accessors.setCharArrayElement(reference.pointer, index, value).check();
176+
Jni.env.SetCharArrayElement(reference.pointer, index, value);
231177
}
232178

233179
Uint16List getRange(int start, int end, {Allocator allocator = malloc}) {
@@ -253,12 +199,13 @@ extension CharArray on JArray<jchar> {
253199

254200
extension ShortArray on JArray<jshort> {
255201
int operator [](int index) {
256-
return _elementAt(index, JniCallType.shortType).short;
202+
RangeError.checkValidIndex(index, this);
203+
return Jni.env.GetShortArrayElement(reference.pointer, index);
257204
}
258205

259206
void operator []=(int index, int value) {
260207
RangeError.checkValidIndex(index, this);
261-
Jni.accessors.setShortArrayElement(reference.pointer, index, value).check();
208+
Jni.env.SetShortArrayElement(reference.pointer, index, value);
262209
}
263210

264211
Int16List getRange(int start, int end, {Allocator allocator = malloc}) {
@@ -284,12 +231,13 @@ extension ShortArray on JArray<jshort> {
284231

285232
extension IntArray on JArray<jint> {
286233
int operator [](int index) {
287-
return _elementAt(index, JniCallType.intType).integer;
234+
RangeError.checkValidIndex(index, this);
235+
return Jni.env.GetIntArrayElement(reference.pointer, index);
288236
}
289237

290238
void operator []=(int index, int value) {
291239
RangeError.checkValidIndex(index, this);
292-
Jni.accessors.setIntArrayElement(reference.pointer, index, value).check();
240+
Jni.env.SetIntArrayElement(reference.pointer, index, value);
293241
}
294242

295243
Int32List getRange(int start, int end, {Allocator allocator = malloc}) {
@@ -315,12 +263,13 @@ extension IntArray on JArray<jint> {
315263

316264
extension LongArray on JArray<jlong> {
317265
int operator [](int index) {
318-
return _elementAt(index, JniCallType.longType).long;
266+
RangeError.checkValidIndex(index, this);
267+
return Jni.env.GetLongArrayElement(reference.pointer, index);
319268
}
320269

321270
void operator []=(int index, int value) {
322271
RangeError.checkValidIndex(index, this);
323-
Jni.accessors.setLongArrayElement(reference.pointer, index, value).check();
272+
Jni.env.SetLongArrayElement(reference.pointer, index, value);
324273
}
325274

326275
Int64List getRange(int start, int end, {Allocator allocator = malloc}) {
@@ -346,12 +295,13 @@ extension LongArray on JArray<jlong> {
346295

347296
extension FloatArray on JArray<jfloat> {
348297
double operator [](int index) {
349-
return _elementAt(index, JniCallType.floatType).float;
298+
RangeError.checkValidIndex(index, this);
299+
return Jni.env.GetFloatArrayElement(reference.pointer, index);
350300
}
351301

352302
void operator []=(int index, double value) {
353303
RangeError.checkValidIndex(index, this);
354-
Jni.accessors.setFloatArrayElement(reference.pointer, index, value).check();
304+
Jni.env.SetFloatArrayElement(reference.pointer, index, value);
355305
}
356306

357307
Float32List getRange(int start, int end, {Allocator allocator = malloc}) {
@@ -377,14 +327,13 @@ extension FloatArray on JArray<jfloat> {
377327

378328
extension DoubleArray on JArray<jdouble> {
379329
double operator [](int index) {
380-
return _elementAt(index, JniCallType.doubleType).doubleFloat;
330+
RangeError.checkValidIndex(index, this);
331+
return Jni.env.GetDoubleArrayElement(reference.pointer, index);
381332
}
382333

383334
void operator []=(int index, double value) {
384335
RangeError.checkValidIndex(index, this);
385-
Jni.accessors
386-
.setDoubleArrayElement(reference.pointer, index, value)
387-
.check();
336+
Jni.env.SetDoubleArrayElement(reference.pointer, index, value);
388337
}
389338

390339
Float64List getRange(int start, int end, {Allocator allocator = malloc}) {
@@ -410,8 +359,9 @@ extension DoubleArray on JArray<jdouble> {
410359

411360
extension ObjectArray<T extends JObject> on JArray<T> {
412361
T operator [](int index) {
362+
RangeError.checkValidIndex(index, this);
413363
return (elementType as JObjType<T>).fromReference(JGlobalReference(
414-
_elementAt(index, JniCallType.objectType).objectPointer));
364+
Jni.env.GetObjectArrayElement(reference.pointer, index)));
415365
}
416366

417367
void operator []=(int index, T value) {

pkgs/jni/lib/src/jclass.dart

+11-24
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,7 @@ class JClass extends JObject {
1414
/// Constructs a [JClass] associated with the class or interface with
1515
/// the given string name.
1616
JClass.forName(String name)
17-
: super.fromReference(using((arena) {
18-
final cls = Jni.accessors.getClass(name.toNativeChars(arena));
19-
return JGlobalReference(cls.checkedClassRef);
20-
}));
17+
: super.fromReference(JGlobalReference(Jni.findClass(name)));
2118

2219
JConstructorId constructorId(String signature) {
2320
return JConstructorId._(this, signature);
@@ -43,13 +40,11 @@ class JClass extends JObject {
4340
/// A thin wrapper over a [JFieldIDPtr] of an instance field.
4441
extension type JInstanceFieldId._fromPointer(JFieldIDPtr pointer) {
4542
JInstanceFieldId._(JClass jClass, String name, String signature)
46-
: pointer = using((arena) => Jni.accessors
47-
.getFieldID(
43+
: pointer = using((arena) => Jni.env.GetFieldID(
4844
jClass.reference.pointer,
4945
name.toNativeChars(arena),
5046
signature.toNativeChars(arena),
51-
)
52-
.fieldID);
47+
));
5348

5449
DartT get<JavaT, DartT>(JObject object, JAccessible<JavaT, DartT> type) {
5550
return type._instanceGet(object.reference.pointer, this as JFieldIDPtr);
@@ -64,13 +59,11 @@ extension type JInstanceFieldId._fromPointer(JFieldIDPtr pointer) {
6459
/// A thin wrapper over a [JFieldIDPtr] of an static field.
6560
extension type JStaticFieldId._fromPointer(JFieldIDPtr pointer) {
6661
JStaticFieldId._(JClass jClass, String name, String signature)
67-
: pointer = using((arena) => Jni.accessors
68-
.getStaticFieldID(
62+
: pointer = using((arena) => Jni.env.GetStaticFieldID(
6963
jClass.reference.pointer,
7064
name.toNativeChars(arena),
7165
signature.toNativeChars(arena),
72-
)
73-
.fieldID);
66+
));
7467

7568
DartT get<JavaT, DartT>(JClass jClass, JAccessible<JavaT, DartT> type) {
7669
return type._staticGet(jClass.reference.pointer, this as JFieldIDPtr);
@@ -88,13 +81,11 @@ extension type JInstanceMethodId._fromPointer(JMethodIDPtr pointer) {
8881
JClass jClass,
8982
String name,
9083
String signature,
91-
) : pointer = using((arena) => Jni.accessors
92-
.getMethodID(
84+
) : pointer = using((arena) => Jni.env.GetMethodID(
9385
jClass.reference.pointer,
9486
name.toNativeChars(arena),
9587
signature.toNativeChars(arena),
96-
)
97-
.methodID);
88+
));
9889

9990
/// Calls the instance method on [object] with the given arguments.
10091
DartT call<JavaT, DartT>(
@@ -113,13 +104,11 @@ extension type JStaticMethodId._fromPointer(JMethodIDPtr pointer) {
113104
JClass jClass,
114105
String name,
115106
String signature,
116-
) : pointer = using((arena) => Jni.accessors
117-
.getStaticMethodID(
107+
) : pointer = using((arena) => Jni.env.GetStaticMethodID(
118108
jClass.reference.pointer,
119109
name.toNativeChars(arena),
120110
signature.toNativeChars(arena),
121-
)
122-
.methodID);
111+
));
123112

124113
/// Calls the static method on [jClass] with the given arguments.
125114
DartT call<JavaT, DartT>(
@@ -137,13 +126,11 @@ extension type JConstructorId._fromPointer(JMethodIDPtr pointer) {
137126
JConstructorId._(
138127
JClass jClass,
139128
String signature,
140-
) : pointer = using((arena) => Jni.accessors
141-
.getMethodID(
129+
) : pointer = using((arena) => Jni.env.GetMethodID(
142130
jClass.reference.pointer,
143131
'<init>'.toNativeChars(arena),
144132
signature.toNativeChars(arena),
145-
)
146-
.methodID);
133+
));
147134

148135
/// Constructs an instance of [jClass] with the given arguments.
149136
DartT call<JavaT, DartT>(JClass jClass,

0 commit comments

Comments
 (0)