1
0
forked from gmp/jni

Compare commits

...

4 Commits

Author SHA1 Message Date
511df960e4 jni: release string characters in conversion to Go string
This change should fix #13 by releasing the string buffer from the JVM after we
convert the string to a Go string. However, I've been having a lot of trouble
building the tests on Linux, and I've run out of time to keep messing with it.
I'm posting this patch in the hope that someone else is better positioned to
validate it. Please do not merge this unless you can verify that it works
properly.

Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
2025-12-30 09:43:33 -05:00
gmp
34026c7e22 Merge pull request 'master' (#8) from whereswaldon/jni:master into master
Reviewed-on: gmp/jni#8
2021-06-10 01:17:05 +00:00
f8a0df591f
fix: use proper return type for static booleans
Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
2021-05-31 16:11:30 -04:00
ff2a63c99a
feat: implement calling static boolean methods
Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
2021-04-18 14:41:05 -04:00
6 changed files with 63 additions and 1 deletions

View File

@ -15,6 +15,7 @@ __attribute__ ((visibility ("hidden"))) jfieldID _jni_GetFieldID(JNIEnv *env, jc
__attribute__ ((visibility ("hidden"))) jfieldID _jni_GetStaticFieldID(JNIEnv *env, jclass clazz, const char *name, const char *sig); __attribute__ ((visibility ("hidden"))) jfieldID _jni_GetStaticFieldID(JNIEnv *env, jclass clazz, const char *name, const char *sig);
__attribute__ ((visibility ("hidden"))) jsize _jni_GetStringLength(JNIEnv *env, jstring str); __attribute__ ((visibility ("hidden"))) jsize _jni_GetStringLength(JNIEnv *env, jstring str);
__attribute__ ((visibility ("hidden"))) const jchar *_jni_GetStringChars(JNIEnv *env, jstring str); __attribute__ ((visibility ("hidden"))) const jchar *_jni_GetStringChars(JNIEnv *env, jstring str);
__attribute__ ((visibility ("hidden"))) void _jni_ReleaseStringChars(JNIEnv *env, jstring str, const jchar *chars);
__attribute__ ((visibility ("hidden"))) jstring _jni_NewString(JNIEnv *env, const jchar *unicodeChars, jsize len); __attribute__ ((visibility ("hidden"))) jstring _jni_NewString(JNIEnv *env, const jchar *unicodeChars, jsize len);
__attribute__ ((visibility ("hidden"))) jboolean _jni_IsSameObject(JNIEnv *env, jobject ref1, jobject ref2); __attribute__ ((visibility ("hidden"))) jboolean _jni_IsSameObject(JNIEnv *env, jobject ref1, jobject ref2);
__attribute__ ((visibility ("hidden"))) jboolean _jni_IsInstanceOf(JNIEnv *env, jobject obj, jclass cls); __attribute__ ((visibility ("hidden"))) jboolean _jni_IsInstanceOf(JNIEnv *env, jobject obj, jclass cls);
@ -23,6 +24,7 @@ __attribute__ ((visibility ("hidden"))) void _jni_DeleteGlobalRef(JNIEnv *env, j
__attribute__ ((visibility ("hidden"))) jobject _jni_NewLocalRef(JNIEnv *env, jobject obj); __attribute__ ((visibility ("hidden"))) jobject _jni_NewLocalRef(JNIEnv *env, jobject obj);
__attribute__ ((visibility ("hidden"))) void _jni_DeleteLocalRef(JNIEnv *env, jobject obj); __attribute__ ((visibility ("hidden"))) void _jni_DeleteLocalRef(JNIEnv *env, jobject obj);
__attribute__ ((visibility ("hidden"))) jint _jni_CallStaticIntMethodA(JNIEnv *env, jclass cls, jmethodID method, jvalue *args); __attribute__ ((visibility ("hidden"))) jint _jni_CallStaticIntMethodA(JNIEnv *env, jclass cls, jmethodID method, jvalue *args);
__attribute__ ((visibility ("hidden"))) jboolean _jni_CallStaticBooleanMethodA(JNIEnv *env, jclass cls, jmethodID method, jvalue *args);
__attribute__ ((visibility ("hidden"))) jobject _jni_CallStaticObjectMethodA(JNIEnv *env, jclass cls, jmethodID method, jvalue *args); __attribute__ ((visibility ("hidden"))) jobject _jni_CallStaticObjectMethodA(JNIEnv *env, jclass cls, jmethodID method, jvalue *args);
__attribute__ ((visibility ("hidden"))) jobject _jni_NewObjectA(JNIEnv *env, jclass cls, jmethodID method, jvalue *args); __attribute__ ((visibility ("hidden"))) jobject _jni_NewObjectA(JNIEnv *env, jclass cls, jmethodID method, jvalue *args);
__attribute__ ((visibility ("hidden"))) void _jni_CallStaticVoidMethodA(JNIEnv *env, jclass cls, jmethodID method, jvalue *args); __attribute__ ((visibility ("hidden"))) void _jni_CallStaticVoidMethodA(JNIEnv *env, jclass cls, jmethodID method, jvalue *args);

8
jni.c
View File

@ -78,6 +78,10 @@ const jchar *_jni_GetStringChars(JNIEnv *env, jstring str) {
return (*env)->GetStringChars(env, str, NULL); return (*env)->GetStringChars(env, str, NULL);
} }
void _jni_ReleaseStringChars(JNIEnv *env, jstring str, const jchar *chars) {
(*env)->ReleaseStringChars(env, str, chars);
}
jstring _jni_NewString(JNIEnv *env, const jchar *unicodeChars, jsize len) { jstring _jni_NewString(JNIEnv *env, const jchar *unicodeChars, jsize len) {
return (*env)->NewString(env, unicodeChars, len); return (*env)->NewString(env, unicodeChars, len);
} }
@ -118,6 +122,10 @@ jint _jni_CallStaticIntMethodA(JNIEnv *env, jclass cls, jmethodID method, jvalue
return (*env)->CallStaticIntMethodA(env, cls, method, args); return (*env)->CallStaticIntMethodA(env, cls, method, args);
} }
jboolean _jni_CallStaticBooleanMethodA(JNIEnv *env, jclass cls, jmethodID method, jvalue *args) {
return (*env)->CallStaticBooleanMethodA(env, cls, method, args);
}
jobject _jni_CallStaticObjectMethodA(JNIEnv *env, jclass cls, jmethodID method, jvalue *args) { jobject _jni_CallStaticObjectMethodA(JNIEnv *env, jclass cls, jmethodID method, jvalue *args) {
return (*env)->CallStaticObjectMethodA(env, cls, method, args); return (*env)->CallStaticObjectMethodA(env, cls, method, args);
} }

10
jni.go
View File

@ -104,6 +104,12 @@ func CallStaticIntMethod(e Env, cls Class, method MethodID, args ...Value) (int,
return int(res), exception(e) return int(res), exception(e)
} }
// CallStaticBooleanMethod calls a static method on a Java class, returning an int.
func CallStaticBooleanMethod(e Env, cls Class, method MethodID, args ...Value) (bool, error) {
res := C._jni_CallStaticBooleanMethodA(e.env, C.jclass(cls), C.jmethodID(method), varArgs(args))
return res == TRUE, exception(e)
}
// FindClass returns a reference to a Java class with a given name, using the // FindClass returns a reference to a Java class with a given name, using the
// JVM's default class loader. Any exceptions caused by the underlying JNI call // JVM's default class loader. Any exceptions caused by the underlying JNI call
// (for example if the class is not found) will result in a panic. // (for example if the class is not found) will result in a panic.
@ -405,6 +411,10 @@ func GoString(e Env, str String) string {
} }
strlen := C._jni_GetStringLength(e.env, C.jstring(str)) strlen := C._jni_GetStringLength(e.env, C.jstring(str))
chars := C._jni_GetStringChars(e.env, C.jstring(str)) chars := C._jni_GetStringChars(e.env, C.jstring(str))
if chars == nil {
return ""
}
defer C._jni_ReleaseStringChars(e.env, C.jstring(str), chars)
var utf16Chars []uint16 var utf16Chars []uint16
hdr := (*reflect.SliceHeader)(unsafe.Pointer(&utf16Chars)) hdr := (*reflect.SliceHeader)(unsafe.Pointer(&utf16Chars))
hdr.Data = uintptr(unsafe.Pointer(chars)) hdr.Data = uintptr(unsafe.Pointer(chars))

View File

@ -198,6 +198,44 @@ func TestStaticObjectMethod(t *testing.T) {
} }
} }
func TestStaticBooleanMethod(t *testing.T) {
err := Do(vm, func(env Env) error {
cls := FindClass(env, "test/AClass")
mid := GetStaticMethodID(env, cls, "GetStaticBoolean", "()Z")
if mid == nil {
t.Errorf("MethodID is nil")
}
setterMid := GetStaticMethodID(env, cls, "SetStaticBoolean", "(Z)V")
if setterMid == nil {
t.Errorf("Setter MethodID is nil")
}
res, err := CallStaticBooleanMethod(env, cls, mid)
if err != nil {
t.Errorf("Method invocation failed")
}
if !res {
t.Errorf("Method returned %v, not expected value of %v.", res, true)
}
if err := CallStaticVoidMethod(env, cls, setterMid, FALSE); err != nil {
t.Errorf("Setter invocation failed")
}
res, err = CallStaticBooleanMethod(env, cls, mid)
if err != nil {
t.Errorf("Method invocation failed")
}
if res {
t.Errorf("Method returned %v, not expected value of %v.", res, false)
}
if err := CallStaticVoidMethod(env, cls, setterMid, TRUE); err != nil {
t.Errorf("Setter invocation failed")
}
return err
})
if err != nil {
t.Errorf("Error: %s", err)
}
}
func TestMethod(t *testing.T) { func TestMethod(t *testing.T) {
defer func() { defer func() {
if r := recover(); r == nil { if r := recover(); r == nil {

Binary file not shown.

View File

@ -47,7 +47,7 @@ public class AClass {
private float pfl = (float)2.2; private float pfl = (float)2.2;
private double pdb = 1001.1001; private double pdb = 1001.1001;
public static Boolean GetStaticBoolean() { public static boolean GetStaticBoolean() {
return staticbl; return staticbl;
} }
@ -75,6 +75,10 @@ public class AClass {
return staticobj; return staticobj;
} }
public static void SetStaticBoolean(boolean val) {
staticbl = val;
}
public void IncInt() { public void IncInt() {
in = in + 1; in = in + 1;
} }