diff --git a/jni.go b/jni.go index c900a30..325ae1c 100644 --- a/jni.go +++ b/jni.go @@ -93,7 +93,7 @@ func varArgs(args []Value) *C.jvalue { // Java object. func IsSameObject(e Env, ref1, ref2 Object) bool { same := C._jni_IsSameObject(e.env, C.jobject(ref1), C.jobject(ref2)) - return same == C.JNI_TRUE + return same == TRUE } // CallStaticIntMethod calls a static method on a Java class, returning an int. @@ -270,11 +270,8 @@ func GetObjectClass(e Env, obj Object) Class { if obj == 0 { panic("null object") } + // GetObjectClass does not throw any exceptions cls := C._jni_GetObjectClass(e.env, C.jobject(obj)) - if err := exception(e); err != nil { - // GetObjectClass should never fail. - panic(err) - } return Class(cls) } @@ -287,11 +284,9 @@ func IsInstanceOf(e Env, obj Object, cls Class) bool { if cls == 0 { panic("null class") } + // Note: does not throw any exceptions res := C._jni_IsInstanceOf(e.env, C.jobject(obj), C.jclass(cls)) - if err := exception(e); err != nil { - panic(err) - } - return res == C.JNI_TRUE + return res == TRUE } // GetStaticMethodID returns the id for a static method. It panics if the method @@ -396,181 +391,127 @@ func GoString(e Env, str String) string { } // GetStaticObjectField looks up the value of a static field of type Object. -// It panics if it is unable to find the field. +// This should never throw an exception. func GetStaticObjectField(env Env, clazz Class, fieldID FieldID) Object { value := C._jni_GetStaticObjectField(env.env, C.jclass(clazz), C.jfieldID(fieldID)) - if err := exception(env); err != nil { - panic(err) - } return Object(value) } // GetStaticBooleanField looks up the value of a static field of type boolean. -// It panics if it is unable to find the field. +// This should never throw an exception. func GetStaticBooleanField(env Env, clazz Class, fieldID FieldID) bool { value := C._jni_GetStaticBooleanField(env.env, C.jclass(clazz), C.jfieldID(fieldID)) - if err := exception(env); err != nil { - panic(err) - } return value != 0 } // GetStaticByteField looks up the value of a static field of type byte. -// It panics if it is unable to find the field. +// This should never throw an exception. func GetStaticByteField(env Env, clazz Class, fieldID FieldID) byte { value := C._jni_GetStaticByteField(env.env, C.jclass(clazz), C.jfieldID(fieldID)) - if err := exception(env); err != nil { - panic(err) - } return byte(value) } // GetStaticCharField looks up the value of a static field of type char. -// It panics if it is unable to find the field. +// This should never throw an exception. func GetStaticCharField(env Env, clazz Class, fieldID FieldID) byte { value := C._jni_GetStaticCharField(env.env, C.jclass(clazz), C.jfieldID(fieldID)) - if err := exception(env); err != nil { - panic(err) - } return byte(value) } // GetStaticShortField looks up the value of a static field of type short. -// It panics if it is unable to find the field. +// This should never throw an exception. func GetStaticShortField(env Env, clazz Class, fieldID FieldID) int16 { value := C._jni_GetStaticShortField(env.env, C.jclass(clazz), C.jfieldID(fieldID)) - if err := exception(env); err != nil { - panic(err) - } return int16(value) } // GetStaticIntField looks up the value of a static field of type int. -// It panics if it is unable to find the field. +// This should never throw an exception. func GetStaticIntField(env Env, clazz Class, fieldID FieldID) int32 { value := C._jni_GetStaticIntField(env.env, C.jclass(clazz), C.jfieldID(fieldID)) - if err := exception(env); err != nil { - panic(err) - } return int32(value) } // GetStaticLongField looks up the value of a static field of type long. -// It panics if it is unable to find the field. +// This should never throw an exception. func GetStaticLongField(env Env, clazz Class, fieldID FieldID) int64 { value := C._jni_GetStaticLongField(env.env, C.jclass(clazz), C.jfieldID(fieldID)) - if err := exception(env); err != nil { - panic(err) - } return int64(value) } // GetStaticFloatField looks up the value of a static field of type float. -// It panics if it is unable to find the field. +// This should never throw an exception. func GetStaticFloatField(env Env, clazz Class, fieldID FieldID) float32 { value := C._jni_GetStaticFloatField(env.env, C.jclass(clazz), C.jfieldID(fieldID)) - if err := exception(env); err != nil { - panic(err) - } return float32(value) } // GetStaticDoubleField looks up the value of a static field of type double. -// It panics if it is unable to find the field. +// This should never throw an exception. func GetStaticDoubleField(env Env, clazz Class, fieldID FieldID) float64 { value := C._jni_GetStaticDoubleField(env.env, C.jclass(clazz), C.jfieldID(fieldID)) - if err := exception(env); err != nil { - panic(err) - } return float64(value) } // GetObjectField looks up the value of a static field of type Object. -// It panics if it is unable to find the field. +// This should never throw an exception. func GetObjectField(env Env, obj Object, fieldID FieldID) Object { value := C._jni_GetObjectField(env.env, C.jobject(obj), C.jfieldID(fieldID)) - if err := exception(env); err != nil { - panic(err) - } return Object(value) } // GetBooleanField looks up the value of a static field of type boolean. -// It panics if it is unable to find the field. +// This should never throw an exception. func GetBooleanField(env Env, obj Object, fieldID FieldID) bool { value := C._jni_GetBooleanField(env.env, C.jobject(obj), C.jfieldID(fieldID)) - if err := exception(env); err != nil { - panic(err) - } return value != 0 } // GetByteField looks up the value of a static field of type byte. -// It panics if it is unable to find the field. +// This should never throw an exception. func GetByteField(env Env, obj Object, fieldID FieldID) byte { value := C._jni_GetByteField(env.env, C.jobject(obj), C.jfieldID(fieldID)) - if err := exception(env); err != nil { - panic(err) - } return byte(value) } // GetCharField looks up the value of a static field of type char. -// It panics if it is unable to find the field. +// This should never throw an exception. func GetCharField(env Env, obj Object, fieldID FieldID) byte { value := C._jni_GetCharField(env.env, C.jobject(obj), C.jfieldID(fieldID)) - if err := exception(env); err != nil { - panic(err) - } return byte(value) } // GetShortField looks up the value of a static field of type short. -// It panics if it is unable to find the field. +// This should never throw an exception. func GetShortField(env Env, obj Object, fieldID FieldID) int16 { value := C._jni_GetShortField(env.env, C.jobject(obj), C.jfieldID(fieldID)) - if err := exception(env); err != nil { - panic(err) - } return int16(value) } // GetIntField looks up the value of a static field of type int. -// It panics if it is unable to find the field. +// This should never throw an exception. func GetIntField(env Env, obj Object, fieldID FieldID) int32 { value := C._jni_GetIntField(env.env, C.jobject(obj), C.jfieldID(fieldID)) - if err := exception(env); err != nil { - panic(err) - } return int32(value) } // GetLongField looks up the value of a static field of type long. -// It panics if it is unable to find the field. +// This should never throw an exception. func GetLongField(env Env, obj Object, fieldID FieldID) int64 { value := C._jni_GetLongField(env.env, C.jobject(obj), C.jfieldID(fieldID)) - if err := exception(env); err != nil { - panic(err) - } return int64(value) } // GetFloatField looks up the value of a static field of type float. -// It panics if it is unable to find the field. +// This should never throw an exception. func GetFloatField(env Env, obj Object, fieldID FieldID) float32 { value := C._jni_GetFloatField(env.env, C.jobject(obj), C.jfieldID(fieldID)) - if err := exception(env); err != nil { - panic(err) - } return float32(value) } // GetDoubleField looks up the value of a static field of type double. -// It panics if it is unable to find the field. +// This should never throw an exception. func GetDoubleField(env Env, obj Object, fieldID FieldID) float64 { value := C._jni_GetDoubleField(env.env, C.jobject(obj), C.jfieldID(fieldID)) - if err := exception(env); err != nil { - panic(err) - } return float64(value) } diff --git a/jni_notandroid.go b/jni_notandroid.go index 508a77a..65d5a7e 100644 --- a/jni_notandroid.go +++ b/jni_notandroid.go @@ -9,29 +9,13 @@ package jni */ import "C" -import ( - "unsafe" -) - // CreateJavaVM creates a new Java VM with the options specified (if any). // This should not be called more than once as it can result in an error if // a JVM already exists for a given process. // // This is not implemented on Android and is therefore excluded on that // platform by build flags and C. -func CreateJavaVM(opts ...string) JVM { - nOptions := len(opts) - optstrings := make([]*C.char, nOptions) - for i, _ := range optstrings { - optstrings[i] = C.CString(opts[i]) - defer C.free(unsafe.Pointer(optstrings[i])) - } - var jvm *C.JavaVM - if nOptions > 0 { - jvm = C._jni_CreateJavaVM(&optstrings[0], C.int(nOptions)) - } else { - jvm = C._jni_CreateJavaVM((**C.char)(nil), 0) - } +func CreateJavaVM() JVM { + jvm := C._jni_CreateJavaVM((**C.char)(nil), 0) return JVM{ jvm: jvm } } - diff --git a/jni_test.go b/jni_test.go index 8301719..d9d2eb6 100644 --- a/jni_test.go +++ b/jni_test.go @@ -1,11 +1,12 @@ // +build !android -//go:generate javac test/AClass.java +//go:generate javac test/AClass.java test/AClass2.java package jni import ( "sync" "testing" + "unsafe" ) var ( @@ -25,6 +26,17 @@ func TestCreateJVM(t *testing.T) { }) } +func TestDo(t *testing.T) { + // create an invalid JVM + vm2 := JVMFor(uintptr(unsafe.Pointer(vm.jvm))) + err := Do(vm2, func(env Env) error { + return nil + }) + if err != nil { + t.Errorf("Do() returned an error") + } +} + func TestFindClass(t *testing.T) { err := Do(vm, func(env Env) error { cls := FindClass(env, "test/AClass") @@ -36,6 +48,34 @@ func TestFindClass(t *testing.T) { if err != nil { t.Errorf("Error: %s", err) } + defer func() { + if r := recover(); r == nil { + t.Errorf("No exception for class not found") + } else { + t.Logf("Panic: %s", r) + } + }() + err = Do(vm, func(env Env) error { + cls := FindClass(env, "test/NoSuchClass") + if cls == 0 { + t.Errorf("Class is nil") + } + return nil + }) +} + +func TestEnvFor(t *testing.T) { + err := Do(vm, func(env Env) error { + env2 := EnvFor(uintptr(unsafe.Pointer(env.env))) + cls := FindClass(env2, "test/AClass") + if cls == 0 { + t.Errorf("Class is nil") + } + return nil + }) + if err != nil { + t.Errorf("Error: %s", err) + } } func TestGetMethodID(t *testing.T) { @@ -67,6 +107,7 @@ func TestNewObject(t *testing.T) { if inst == 0 { t.Errorf("NewGlobalRef returned nil") } + DeleteGlobalRef(env, inst) return nil }) if err != nil { @@ -93,6 +134,7 @@ func TestIsSameObject(t *testing.T) { if !IsSameObject(env, inst, inst2) { t.Errorf("New local ref is not the same as original object") } + DeleteLocalRef(env, inst) return nil }) if err != nil { @@ -100,6 +142,21 @@ func TestIsSameObject(t *testing.T) { } } +func TestStaticMethod(t *testing.T) { + defer func() { + if r := recover(); r == nil { + t.Errorf("GetStaticMethodID() did not panic") + } else { + t.Logf("Panic: %s", r) + } + }() + Do(vm, func(env Env) error { + cls := FindClass(env, "test/AClass") + GetStaticMethodID(env, cls, "noSuchMethod","()V") + return nil + }) +} + func TestStaticIntMethod(t *testing.T) { err := Do(vm, func(env Env) error { cls := FindClass(env, "test/AClass") @@ -122,6 +179,40 @@ func TestStaticIntMethod(t *testing.T) { } } +func TestStaticObjectMethod(t *testing.T) { + err := Do(vm, func(env Env) error { + cls := FindClass(env, "test/AClass") + mid := GetMethodID(env, cls, "", "()V") + mid = GetStaticMethodID(env, cls, "GetStaticObject", "()Ljava/lang/Object;") + if mid == nil { + t.Errorf("MethodID is nil") + } + _, err := CallStaticObjectMethod(env, cls, mid) + if err != nil { + t.Errorf("Method invocation failed") + } + return err + }) + if err != nil { + t.Errorf("Error: %s", err) + } +} + +func TestMethod(t *testing.T) { + defer func() { + if r := recover(); r == nil { + t.Errorf("GetMethodID() did not panic") + } else { + t.Logf("Panic: %s", r) + } + }() + Do(vm, func(env Env) error { + cls := FindClass(env, "test/AClass") + GetMethodID(env, cls, "noSuchMethod","()V") + return nil + }) +} + func TestIntMethod(t *testing.T) { err := Do(vm, func(env Env) error { cls := FindClass(env, "test/AClass") @@ -135,7 +226,7 @@ func TestIntMethod(t *testing.T) { if err != nil { t.Errorf("Method invocation failed") } - if res != 0 { + if res != 101 { t.Errorf("Method returned %d, not expected value of %d.", res, 0) } return nil @@ -319,14 +410,6 @@ func TestVoidMethod(t *testing.T) { if err != nil { t.Errorf("Method invocation failed") } - mid = GetMethodID(env, cls, "GetInt", "()I") - res, err := CallIntMethod(env, inst, mid) - if err != nil { - t.Errorf("Method invocation falied") - } - if res != 1 { - t.Errorf("Method returned %d, not expected value of %d.", res, 1) - } return nil }) if err != nil { @@ -422,6 +505,23 @@ func TestStaticVoidMethod(t *testing.T) { } func TestGetObjectClass(t *testing.T) { + defer func() { + if r := recover(); r == nil { + t.Errorf("GetObjectClass() did not panic") + } else { + t.Logf("Panic: %s", r) + } + }() + err := Do(vm, func(env Env) error { + GetObjectClass(env, Object(unsafe.Pointer(uintptr(0)))) + return nil + }) + if err != nil { + t.Errorf("Error: %s", err) + } +} + +func TestGetObjectClass2(t *testing.T) { err := Do(vm, func(env Env) error { cls := FindClass(env, "test/AClass") mid := GetMethodID(env, cls, "", "()V") @@ -440,18 +540,51 @@ func TestGetObjectClass(t *testing.T) { } } -func TestField(t *testing.T) { +func TestIsInstanceOf(t *testing.T) { + defer func() { + if r := recover(); r == nil { + t.Errorf("IsInstanceOf() did not panic") + } else { + t.Logf("Panic: %s", r) + } + }() + err := Do(vm, func(env Env) error { + IsInstanceOf(env, Object(0), Class(0)) + return nil + }) + if err != nil { + t.Errorf("Error: %s", err) + } +} + +func TestIsInstanceOf2(t *testing.T) { + defer func() { + if r := recover(); r == nil { + t.Errorf("IsInstanceOf() did not panic") + } else { + t.Logf("Panic: %s", r) + } + }() err := Do(vm, func(env Env) error { cls := FindClass(env, "test/AClass") mid := GetMethodID(env, cls, "", "()V") inst, _ := NewObject(env, cls, mid) - fid := GetFieldID(env, cls, "intval", "I") - if fid == nil { - t.Errorf("FieldID is nil") - } - res := GetIntField(env, inst, fid) - if res != 0 { - t.Errorf("Method returned %d, not expected value of %d.", res, 0) + IsInstanceOf(env, inst, Class(0)) + return nil + }) + if err != nil { + t.Errorf("Error: %s", err) + } +} + +func TestIsInstanceOf3(t *testing.T) { + err := Do(vm, func(env Env) error { + cls := FindClass(env, "test/AClass") + mid := GetMethodID(env, cls, "", "()V") + inst, _ := NewObject(env, cls, mid) + cls = FindClass(env, "java/lang/String") + if IsInstanceOf(env, inst, cls) { + t.Errorf("IsInstanceOf() returned wrong value") } return nil }) @@ -460,16 +593,82 @@ func TestField(t *testing.T) { } } -func TestStaticField(t *testing.T) { +func TestField(t *testing.T) { err := Do(vm, func(env Env) error { cls := FindClass(env, "test/AClass") - fid := GetStaticFieldID(env, cls, "staticintval", "I") + mid := GetMethodID(env, cls, "", "()V") + inst, _ := NewObject(env, cls, mid) + fid := GetFieldID(env, cls, "in", "I") if fid == nil { t.Errorf("FieldID is nil") } - res := GetStaticIntField(env, cls, fid) - if res != 100 { - t.Errorf("Method returned %d, not expected value of %d.", res, 100) + r1 := GetIntField(env, inst, fid) + if r1 != 101 { + t.Errorf("Method returned %d, not expected value of %d.", r1, 0) + } + fid = GetFieldID(env, cls, "bl", "Z") + if fid == nil { + t.Errorf("FieldID is nil") + } + r2 := GetBooleanField(env, inst, fid) + if r2 != false { + t.Errorf("Boolean field value is incorrect") + } + fid = GetFieldID(env, cls, "bt", "B") + if fid == nil { + t.Errorf("FieldID is nil") + } + r3 := GetByteField(env, inst, fid) + if r3 != 'c' { + t.Errorf("Byte field value is incorrect") + } + fid = GetFieldID(env, cls, "ch", "C") + if fid == nil { + t.Errorf("FieldID is nil") + } + r4 := GetCharField(env, inst, fid) + if r4 != 'd' { + t.Errorf("Char field value is incorrect") + } + fid = GetFieldID(env, cls, "obj", "Ljava/lang/Object;") + if fid == nil { + t.Errorf("FieldID is nil") + } + r5 := GetObjectField(env, inst, fid) + if r5 == 0 { + t.Errorf("Object field value is incorrect") + } + fid = GetFieldID(env, cls, "sh", "S") + if fid == nil { + t.Errorf("FieldID is nil") + } + r6 := GetShortField(env, inst, fid) + if r6 != 11 { + t.Errorf("Short field value is incorrect") + } + fid = GetFieldID(env, cls, "lo", "J") + if fid == nil { + t.Errorf("FieldID is nil") + } + r7 := GetLongField(env, inst, fid) + if r7 != 1001 { + t.Errorf("Long field value is incorrect") + } + fid = GetFieldID(env, cls, "fl", "F") + if fid == nil { + t.Errorf("FieldID is nil") + } + r8 := GetFloatField(env, inst, fid) + if r8 != 2.2 { + t.Errorf("Float field value is incorrect") + } + fid = GetFieldID(env, cls, "db", "D") + if fid == nil { + t.Errorf("FieldID is nil") + } + r9 := GetDoubleField(env, inst, fid) + if r9 != 1001.1001 { + t.Errorf("Double field value is incorrect") } return nil }) @@ -477,3 +676,268 @@ func TestStaticField(t *testing.T) { t.Errorf("Error: %s", err) } } + +func TestField2(t *testing.T) { + defer func() { + if r := recover(); r == nil { + t.Errorf("GetFieldID() did not panic") + } else { + t.Logf("Panic: %s", r) + } + }() + Do(vm, func(env Env) error { + cls := FindClass(env, "test/AClass") + GetFieldID(env, cls, "noSuchField", "I") + return nil + }) +} + +func TestStaticField(t *testing.T) { + err := Do(vm, func(env Env) error { + cls := FindClass(env, "test/AClass") + fid := GetStaticFieldID(env, cls, "staticint", "I") + if fid == nil { + t.Errorf("FieldID is nil") + } + r1 := GetStaticIntField(env, cls, fid) + if r1 != 100 { + t.Errorf("Method returned %d, not expected value of %d.", r1, 100) + } + fid = GetStaticFieldID(env, cls, "staticbl", "Z") + if fid == nil { + t.Errorf("FieldID is nil") + } + r2 := GetStaticBooleanField(env, cls, fid) + if r2 != true { + t.Errorf("Boolean field value is incorrect") + } + fid = GetStaticFieldID(env, cls, "staticbt", "B") + if fid == nil { + t.Errorf("FieldID is nil") + } + r3 := GetStaticByteField(env, cls, fid) + if r3 != 'a' { + t.Errorf("Byte field value is incorrect") + } + fid = GetStaticFieldID(env, cls, "staticch", "C") + if fid == nil { + t.Errorf("FieldID is nil") + } + r4 := GetStaticCharField(env, cls, fid) + if r4 != 'b' { + t.Errorf("Char field value is incorrect") + } + fid = GetStaticFieldID(env, cls, "staticobj", "Ljava/lang/Object;") + if fid == nil { + t.Errorf("FieldID is nil") + } + r5 := GetStaticObjectField(env, cls, fid) + if r5 == 0 { + t.Errorf("Object field value is incorrect") + } + fid = GetStaticFieldID(env, cls, "staticsh", "S") + if fid == nil { + t.Errorf("FieldID is nil") + } + r6 := GetStaticShortField(env, cls, fid) + if r6 != 10 { + t.Errorf("Short field value is incorrect") + } + fid = GetStaticFieldID(env, cls, "staticlo", "J") + if fid == nil { + t.Errorf("FieldID is nil") + } + r7 := GetStaticLongField(env, cls, fid) + if r7 != 1000 { + t.Errorf("Long field value is incorrect") + } + fid = GetStaticFieldID(env, cls, "staticfl", "F") + if fid == nil { + t.Errorf("FieldID is nil") + } + r8 := GetStaticFloatField(env, cls, fid) + if r8 != 1.1 { + t.Errorf("Float field value is incorrect") + } + fid = GetStaticFieldID(env, cls, "staticdb", "D") + if fid == nil { + t.Errorf("FieldID is nil") + } + r9 := GetStaticDoubleField(env, cls, fid) + if r9 != 1000.0001 { + t.Errorf("Double field value is incorrect") + } + return nil + }) + if err != nil { + t.Errorf("Error: %s", err) + } +} + +func TestStaticField2(t *testing.T) { + defer func() { + if r := recover(); r == nil { + t.Errorf("GetStaticField() did not panic") + } else { + t.Logf("Panic: %s", r) + } + }() + Do(vm, func(env Env) error { + cls := FindClass(env, "test/AClass") + fid := GetStaticFieldID(env, cls, "FieldNotFound", "I") + GetStaticIntField(env, cls, fid) + return nil + }) +} + +func TestByteArray(t *testing.T) { + arr := []byte{'a','b','c'} + Do(vm, func(env Env) error { + jarr := NewByteArray(env, arr) + arr2 := GetByteArrayElements(env, jarr) + if arr2[0] != 'a' || + arr2[1] != 'b' || + arr2[2] != 'c' || + len(arr2) != 3 { + t.Errorf("GetByteArrayElements() failed") + } + return nil + }) +} + +func TestClassLoaderFor(t *testing.T) { + defer func() { + if r := recover(); r == nil { + t.Errorf("ClassLoaderFor() did not panic") + } else { + t.Logf("Panic: %s", r) + } + }() + Do(vm, func(env Env) error { + cls := FindClass(env, "java/lang/Object") + if cls == 0 { + t.Errorf("Class is nil") + } + mid := GetMethodID(env, cls, "", "()V") + if mid == nil { + t.Errorf("Method ID is nil") + } + inst, err := NewObject(env, cls, mid) + if err != nil { + t.Errorf("NewObject raised exception") + } + if inst == 0 { + t.Errorf("NewObject returned nil") + } + ClassLoaderFor(env, inst) + return nil + }) +} + +func TestClassLoaderFor2(t *testing.T) { + Do(vm, func(env Env) error { + cls := FindClass(env, "test/AClass") + mid := GetMethodID(env, cls, "", "()V") + inst, _ := NewObject(env, cls, mid) + cl := ClassLoaderFor(env, inst) + if cl == 0 { + t.Errorf("ClassLoaderFor() returned nil") + } + return nil + }) +} + +func TestClassLoaderFor3(t *testing.T) { + defer func() { + if r := recover(); r == nil { + t.Errorf("ClassLoaderFor() did not panic") + } else { + t.Logf("Panic: %s", r) + } + }() + Do(vm, func(env Env) error { + cls := FindClass(env, "java/lang/Object") + mid := GetMethodID(env, cls, "", "()V") + inst, _ := NewObject(env, cls, mid) + cl := ClassLoaderFor(env, inst) + if cl == 0 { + t.Errorf("ClassLoaderFor() returned nil") + } + return nil + }) +} + +func TestClassLoaderFor4(t *testing.T) { + defer func() { + if r := recover(); r == nil { + t.Errorf("ClassLoaderFor() did not panic") + } else { + t.Logf("Panic: %s", r) + } + }() + Do(vm, func(env Env) error { + cls := FindClass(env, "test/AClass2") + mid := GetMethodID(env, cls, "", "()V") + inst, _ := NewObject(env, cls, mid) + cl := ClassLoaderFor(env, inst) + if cl == 0 { + t.Errorf("ClassLoaderFor() returned nil") + } + return nil + }) +} + +func TestLoadClass(t *testing.T) { + Do(vm, func(env Env) error { + cls := FindClass(env, "test/AClass") + mid := GetMethodID(env, cls, "", "()V") + inst, _ := NewObject(env, cls, mid) + cl := ClassLoaderFor(env, inst) + if cl == 0 { + t.Errorf("ClassLoaderFor() returned nil") + } + cls, err := LoadClass(env, cl, "java.lang.String") + if err != nil { + t.Errorf("LoadClass() returned error: %s", err) + } + if cls == 0 { + t.Errorf("LoadClass() failed") + } + return nil + }) +} + +func TestLoadClass2(t *testing.T) { + Do(vm, func(env Env) error { + cls := FindClass(env, "test/AClass") + mid := GetMethodID(env, cls, "", "()V") + inst, _ := NewObject(env, cls, mid) + _, err := LoadClass(env, inst, "java.lang.String") + if err == nil { + t.Errorf("LoadClass() did not return an error") + } else { + t.Logf("Error: %s", err) + } + return nil + }) +} + +func TestJavaString(t *testing.T) { + Do(vm, func(env Env) error { + jstr := JavaString(env, "") + if jstr != 0 { + t.Errorf("String is not nil") + } + gstr := GoString(env, jstr) + if gstr != "" { + t.Errorf("String is not empty") + } + + jstr = JavaString(env, "test string") + gstr = GoString(env, jstr) + if gstr != "test string" { + t.Errorf("Strings do not match") + } + return nil + }) +} diff --git a/test/AClass.class b/test/AClass.class index 608a39e..45d3b33 100644 Binary files a/test/AClass.class and b/test/AClass.class differ diff --git a/test/AClass.java b/test/AClass.java index f5a8fd9..fd8002d 100644 --- a/test/AClass.java +++ b/test/AClass.java @@ -1,24 +1,86 @@ package test; -public class AClass { - public static int staticintval = 100; +import java.lang.Class; +import java.lang.ClassLoader; +import java.lang.Exception; +import java.lang.Object; +import java.lang.String; - public int intval = 0; +public class AClass { + public static Object staticobj = new Object(); + public static boolean staticbl = true; + public static byte staticbt = 'a'; + public static char staticch = 'b'; + public static short staticsh = 10; + public static int staticint = 100; + public static long staticlo = 1000; + public static float staticfl = (float)1.1; + public static double staticdb = 1000.0001; + + private static Object pstaticobj = new Object(); + private static boolean pstaticbl = true; + private static byte pstaticbt = 'a'; + private static char pstaticch = 'b'; + private static short pstaticsh = 10; + private static int pstaticint = 100; + private static long pstaticlo = 1000; + private static float pstaticfl = (float)1.1; + private static double pstaticdb = 1000.0001; + + public Object obj = new Object(); + public boolean bl = false; + public byte bt = 'c'; + public char ch = 'd'; + public short sh = 11; + public int in = 101; + public long lo = 1001; + public float fl = (float)2.2; + public double db = 1001.1001; + + private Object pobj = new Object(); + private boolean pbl = false; + private byte pbt = 'c'; + private char pch = 'd'; + private short psh = 11; + private int pin = 101; + private long plo = 1001; + private float pfl = (float)2.2; + private double pdb = 1001.1001; + + public static Boolean GetStaticBoolean() { + return staticbl; + } + + public static byte GetStaticByte() { + return staticbt; + } + + public static char GetStaticChar() { + return staticch; + } + + public static short GetStaticShort() { + return staticsh; + } public static int GetStaticInt() { - return staticintval; + return staticint; } public static void SetStaticInt(int val) { - staticintval = val; + staticint = val; + } + + public static Object GetStaticObject() { + return staticobj; } public void IncInt() { - intval = intval + 1; + in = in + 1; } public int GetInt() { - return intval; + return in; } public boolean GetBoolean() { @@ -50,10 +112,18 @@ public class AClass { } public void SetInt(int val) { - intval = val; + in = val; } public void AddInts(int val1, int val2) { - intval = val1 + val2; + in = val1 + val2; + } + + public Class loadClass(String s) throws Exception { + throw new Exception("AClass: loadClass exception"); + } + + public ClassLoader getClassLoader() { + return this.getClass().getClassLoader(); } } diff --git a/test/AClass2.class b/test/AClass2.class new file mode 100644 index 0000000..b064474 Binary files /dev/null and b/test/AClass2.class differ diff --git a/test/AClass2.java b/test/AClass2.java new file mode 100644 index 0000000..c94fe5e --- /dev/null +++ b/test/AClass2.java @@ -0,0 +1,10 @@ +package test; + +import java.lang.ClassLoader; +import java.lang.Exception; + +public class AClass2 { + public ClassLoader getClassLoader() throws Exception { + throw new Exception("Exception"); + } +}