Skip to content
This repository has been archived by the owner on Apr 29, 2024. It is now read-only.

Make several exceptions into errors #396

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions jni/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
## 0.8.0-wip

- **Breaking Change** ([#394](https://github.com/dart-lang/jnigen/issues/394)):
Converted various `Exception`s into `Error`s:
- `UseAfterReleaseException` -> `UseAfterReleaseError`
- `DoubleReleaseException` -> `DoubleReleaseError`
- `SpawnException` -> `JniError` (It's now a `sealed class`)
- `JNullException` -> `JNullError`
- `InvalidCallTypeException` -> `InvalidCallTypeError`
- `HelperNotFoundException` -> `HelperNotFoundError`
- `JvmExistsException` -> `JniVmExistsError`
- `NoJvmInstanceException` -> `NoJvmInstanceError`
- **Breaking Change**: Removed `InvalidJStringException`.

[TODO(#393): Add the fact that `JException` is now a `JObject`.]: #

## 0.7.0

- **Breaking Change** ([#387](https://github.com/dart-lang/jnigen/issues/387)):
Expand Down
8 changes: 5 additions & 3 deletions jni/lib/jni.dart
Original file line number Diff line number Diff line change
Expand Up @@ -60,19 +60,21 @@
/// This library provides classes and functions for JNI interop from Dart.
library jni;

export 'src/third_party/generated_bindings.dart'
hide JniBindings, JniEnv, JniEnv1, JniExceptionDetails;
export 'src/errors.dart';
export 'src/jni.dart' hide ProtectedJniExtensions;
export 'src/jvalues.dart' hide JValueArgs, toJValues;
export 'src/types.dart';
export 'src/jarray.dart';
export 'src/jexceptions.dart';
export 'src/jobject.dart';
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 'src/third_party/generated_bindings.dart'
hide JniBindings, JniEnv, JniEnv1, JniExceptionDetails;

export 'package:ffi/ffi.dart' show using, Arena;
export 'dart:ffi' show nullptr;
2 changes: 1 addition & 1 deletion jni/lib/src/accessors.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import 'package:ffi/ffi.dart' show using;

import 'package:jni/src/jvalues.dart';

import 'jexceptions.dart';
import 'errors.dart';
import 'third_party/generated_bindings.dart';
import 'jni.dart';

Expand Down
141 changes: 141 additions & 0 deletions jni/lib/src/errors.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'package:jni/src/third_party/generated_bindings.dart';

final class UseAfterReleaseError extends Error {
@override
String toString() {
return 'Use after release error';
}
}

// TODO(#393): Use NullPointerError once it's available.
final class JNullError extends Error {
@override
String toString() => 'The reference was null';
}

final class DoubleReleaseError extends Error {
@override
String toString() {
return 'Double release error';
}
}

/// Represents JNI errors that might be returned by methods like
/// `JNI_CreateJavaVM`.
sealed class JniError extends Error {
static const _errors = {
JniErrorCode.JNI_ERR: JniGenericError.new,
JniErrorCode.JNI_EDETACHED: JniThreadDetachedError.new,
JniErrorCode.JNI_EVERSION: JniVersionError.new,
JniErrorCode.JNI_ENOMEM: JniOutOfMemoryError.new,
JniErrorCode.JNI_EEXIST: JniVmExistsError.new,
JniErrorCode.JNI_EINVAL: JniArgumentError.new,
};

final String message;

JniError(this.message);

factory JniError.of(int status) {
if (!_errors.containsKey(status)) {
status = JniErrorCode.JNI_ERR;
}
return _errors[status]!();
}

@override
String toString() {
return 'JniError: $message';
}
}

final class JniGenericError extends JniError {
JniGenericError() : super('Generic JNI error');
}

final class JniThreadDetachedError extends JniError {
JniThreadDetachedError() : super('Thread detached from VM');
}

final class JniVersionError extends JniError {
JniVersionError() : super('JNI version error');
}

final class JniOutOfMemoryError extends JniError {
JniOutOfMemoryError() : super('Out of memory');
}

final class JniVmExistsError extends JniError {
JniVmExistsError() : super('VM Already created');
}

final class JniArgumentError extends JniError {
JniArgumentError() : super('Invalid arguments');
}

final class NoJvmInstanceError extends Error {
@override
String toString() => 'No JNI instance is available';
}

// TODO(#395): Remove this when calltypes are removed.
extension on int {
static const _names = {
JniCallType.booleanType: 'bool',
JniCallType.byteType: 'byte',
JniCallType.shortType: 'short',
JniCallType.charType: 'char',
JniCallType.intType: 'int',
JniCallType.longType: 'long',
JniCallType.floatType: 'float',
JniCallType.doubleType: 'double',
JniCallType.objectType: 'object',
JniCallType.voidType: 'void',
};
String str() => _names[this]!;
}

// TODO(#395): Remove this when calltypes are removed.
final class InvalidCallTypeError extends Error {
final int type;
final Set<int> allowed;

InvalidCallTypeError(this.type, this.allowed);

@override
String toString() => 'Invalid type for call ${type.str()}. '
'Allowed types are ${allowed.map((t) => t.str()).toSet()}';
}

// TODO(#393): Remove this class in favor of `JThrowable`.
class JniException implements Exception {
/// Error message from Java exception.
final String message;

/// Stack trace from Java.
final String stackTrace;

JniException(this.message, this.stackTrace);

@override
String toString() => 'Exception in Java code called through JNI: '
'$message\n\n$stackTrace\n';
}

final class HelperNotFoundError extends Error {
final String path;

HelperNotFoundError(this.path);

@override
String toString() => '''
Lookup for helper library $path failed.
Please ensure that `dartjni` shared library is built.
Provided jni:setup script can be used to build the shared library.
If the library is already built, ensure that the JVM libraries can be
loaded from Dart.''';
}
123 changes: 0 additions & 123 deletions jni/lib/src/jexceptions.dart

This file was deleted.

20 changes: 10 additions & 10 deletions jni/lib/src/jni.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import 'dart:isolate';
import 'package:ffi/ffi.dart';
import 'package:path/path.dart';

import 'jexceptions.dart';
import 'errors.dart';
import 'jobject.dart';
import 'third_party/generated_bindings.dart';
import 'jvalues.dart';
Expand Down Expand Up @@ -38,7 +38,7 @@ DynamicLibrary _loadDartJniLibrary({String? dir, String baseName = "dartjni"}) {
final dylib = DynamicLibrary.open(libPath);
return dylib;
} on Error {
throw HelperNotFoundException(libPath);
throw HelperNotFoundError(libPath);
}
}

Expand Down Expand Up @@ -97,12 +97,12 @@ abstract class Jni {
jniVersion: jniVersion,
);
if (status == false) {
throw JvmExistsException();
throw JniVmExistsError();
}
}

/// Same as [spawn] but if a JVM exists, returns silently instead of
/// throwing [JvmExistsException].
/// throwing [JvmExistsError].
///
/// If the options are different than that of existing VM, the existing VM's
/// options will remain in effect.
Expand All @@ -129,7 +129,7 @@ abstract class Jni {
} else if (status == DART_JNI_SINGLETON_EXISTS) {
return false;
} else {
throw SpawnException.of(status);
throw JniError.of(status);
}
});

Expand Down Expand Up @@ -176,12 +176,12 @@ abstract class Jni {
return _bindings.GetJavaVM();
}

/// Returns the instance of [GlobalJniEnvStruct], which is an abstraction over JNIEnv
/// without the same-thread restriction.
/// Returns the instance of [GlobalJniEnvStruct], which is an abstraction over
/// JNIEnv without the same-thread restriction.
static Pointer<GlobalJniEnvStruct> _fetchGlobalEnv() {
final env = _bindings.GetGlobalEnv();
if (env == nullptr) {
throw NoJvmInstanceException();
throw NoJvmInstanceError();
}
return env;
}
Expand Down Expand Up @@ -336,11 +336,11 @@ extension AdditionalEnvMethods on GlobalJniEnv {
/// DeleteGlobalRef.
String toDartString(JStringPtr jstringPtr, {bool releaseOriginal = false}) {
if (jstringPtr == nullptr) {
throw const JNullException();
throw JNullError();
}
final chars = GetStringChars(jstringPtr, nullptr);
if (chars == nullptr) {
throw InvalidJStringException(jstringPtr);
throw ArgumentError('Not a valid jstring pointer.');
}
final result = chars.cast<Utf16>().toDartString();
ReleaseStringChars(jstringPtr, chars);
Expand Down
Loading
Loading