Skip to content

1.2.0

Choose a tag to compare

@gmpassos gmpassos released this 10 Aug 09:33
· 4 commits to main since this release

Signatures written as Java, so a JNI descriptor never has to be typed by hand.

A descriptor fails in the least helpful way there is: J is long and I is int, Z is boolean, a class needs L, a trailing ; and slashes instead of dots — and any of it wrong surfaces as a NoSuchMethodError from inside the VM, pointing at nothing.

Declarations

Name and types written once, as Java:

instance.callJava('String greet()');
fixtures.callJavaStatic('int add(int, int)', [2, 40]);
clazz.newJava('(String, int)', ['demo', 7]);
object.getJavaField('int intField');
object.setJavaField('String stringField', 'text');

Also callJavaAs<T> / callJavaStaticAs<T>, and getJavaStaticField / setJavaStaticField.

The declaration is what javap prints, so it pastes in unedited — modifiers, annotations, parameter names, generic arguments and a throws clause are ignored, java.lang is implicit, varargs count as an array:

Written Descriptor
jsig('public static int add(int a, int b)') (II)I
jsig('java.util.List<String> subList(int, int)') (II)Ljava/util/List;
jsig('void write(byte[]) throws java.io.IOException') ([B)V
jsig('String format(String, Object...)') (Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;
jsig('(String, int)') (Ljava/lang/String;I)V (constructor)
jtype('int[][]') [[I

Typed builder

Impossible to malform, and const-constructible for a signature on a hot path:

const add = JSig.of([JType.int_, JType.int_], returns: JType.int_);
JType.of('java.util.List').array;   // [Ljava/util/List;
JType.int_.array.array;             // [[I

JavaMethod.parse and JavaField.parse expose the parsed form when the name and the signature are wanted separately.

Notes

  • Nothing is deprecated. jsig and jtype return plain descriptor strings, so they drop into the existing call / callStatic / getField, and every 1.1.1 call site keeps working.
  • Declarations are parsed once and cached by string, the same reasoning as the member-id cache: a call in a loop re-parses nothing.
  • A malformed declaration raises a JniError at the call site naming the token that failed, rather than a NoSuchMethodError from the VM later. That is still a runtime check — the typed builder is the compile-time one.
  • 366 tests (56 new), on Linux and macOS, and on the declared 3.10 SDK floor.

Full changelog: https://github.com/gmpassos/java_interop/blob/main/CHANGELOG.md