如果我使用CGO运行代码,我目前收到此错误消息。在纯C中使用几乎相同的代码,我没有收到错误消息。
Go(CGO)案例:下面的代码编译时没有错误,但在执行时会发出错误。
package main
/*
#cgo CFLAGS: -Id:/jdk/include -Id:/jdk/include/win32
#cgo LDFLAGS: -Ld:/jdk/jre/bin/server -ljvm
#include <jni.h>
JNIEnv* create_vm(JavaVM **jvm)
{
JNIEnv* env;
printf("*env\n");
JavaVMInitArgs args;
printf("args\n");
JavaVMOption options;
printf("options\n");
args.version = JNI_VERSION_1_8;
args.nOptions = 0;
printf("set values\n");
int rv;
rv = JNI_CreateJavaVM(jvm, (void**)&env, &args);
printf("jni create java vm\n");
if (rv != JNI_OK) {
printf("Failed to create Java VMn");
} else {
printf("Launched JVM! :)\n");
}
return env;
}
void invoke_class(JNIEnv* env)
{
jclass hello_world_class;
jmethodID main_method;
jmethodID square_method;
jmethodID power_method;
jint number=20;
jint exponent=3;
hello_world_class = (*env)->FindClass(env, "helloWorld");
main_method = (*env)->GetStaticMethodID(env, hello_world_class, "main", "([Ljava/lang/String;)V");
square_method = (*env)->GetStaticMethodID(env, hello_world_class, "square", "(I)I");
power_method = (*env)->GetStaticMethodID(env, hello_world_class, "power", "(II)I");
(*env)->CallStaticVoidMethod(env, hello_world_class, main_method, NULL);
printf("%d squared is %d\n", number,
(*env)->CallStaticIntMethod(env, hello_world_class, square_method, number));
printf("%d raised to the %d power is %d\n", number, exponent,
(*env)->CallStaticIntMethod(env, hello_world_class, power_method, number, exponent));
}
void test()
{
printf("START TEST\n");
JavaVM *jvm;
printf("*jvm\n");
JNIEnv *env;
printf("*env\n");
env = create_vm(&jvm);
printf("create_vm\n");
invoke_class(env);
printf("invoke class\n");
}
*/
import "C"
func main() {
C.test()
}
上面的CGO代码输出
START TEST
*jvm
*env
*env
args
options
set values
Exception 0xc0000005 0x0 0x0 0x50003b6
PC=0x50003b6
signal arrived during external code execution
main._Cfunc_test()
command-line-arguments/_obj/_cgo_gotypes.go:43 +0x48
main.main()
D:/Projects/Go/src/loable.tech/go-jasper/main.go:66 +0x27
goroutine 17 [syscall, locked to thread]:
runtime.goexit()
D:/Go/src/runtime/asm_amd64.s:2197 +0x1
rax 0x6
rbx 0x3100800
rcx 0xcafebabe
rdi 0x1
rsi 0x0
rbp 0x51e052a0
rsp 0x72f678
r8 0x500047b
r9 0x72f840
r10 0x2
r11 0x72f9b0
r12 0x3d8
r13 0x6
r14 0x0
r15 0xf1
rip 0x50003b6
rflags 0x210246
cs 0x33
fs 0x53
gs 0x2b
现在这里是令人困惑的部分。当我使用C代替go并使用与上面几乎相同的代码时,一切都按预期工作。
纯C代码
#include <jni.h>
JNIEnv* create_vm(JavaVM **jvm)
{
JNIEnv* env;
printf("*env\n");
JavaVMInitArgs args;
printf("args\n");
JavaVMOption options;
printf("options\n");
args.version = JNI_VERSION_1_8;
args.nOptions = 0;
printf("set values\n");
int rv;
rv = JNI_CreateJavaVM(jvm, (void**)&env, &args);
printf("jni create java vm\n");
if (rv != JNI_OK) {
printf("Failed to create Java VMn");
} else {
printf("Launched JVM! :)\n");
}
return env;
}
void invoke_class(JNIEnv* env)
{
jclass hello_world_class;
jmethodID main_method;
jmethodID square_method;
jmethodID power_method;
jint number=20;
jint exponent=3;
hello_world_class = (*env)->FindClass(env, "helloWorld");
main_method = (*env)->GetStaticMethodID(env, hello_world_class, "main", "([Ljava/lang/String;)V");
square_method = (*env)->GetStaticMethodID(env, hello_world_class, "square", "(I)I");
power_method = (*env)->GetStaticMethodID(env, hello_world_class, "power", "(II)I");
(*env)->CallStaticVoidMethod(env, hello_world_class, main_method, NULL);
printf("%d squared is %d\n", number,
(*env)->CallStaticIntMethod(env, hello_world_class, square_method, number));
printf("%d raised to the %d power is %d\n", number, exponent,
(*env)->CallStaticIntMethod(env, hello_world_class, power_method, number, exponent));
}
void main()
{
printf("START TEST\n");
JavaVM *jvm;
printf("*jvm\n");
JNIEnv *env;
printf("*env\n");
env = create_vm(&jvm);
printf("create_vm\n");
invoke_class(env);
printf("invoke class\n");
}
这是上面C代码的输出,这是我期待的输出。
START TEST
*jvm
*env
*env
args
options
set values
jni create java vm
Launched JVM! :)
create_vm
Hello, World
20 squared is 400
20 raised to the 3 power is 8000
invoke class
答案 0 :(得分:0)
不是我常用的机器所以无法验证,但我认为这与JVM启动的工作原理有关。 This answer提供了一些相关信息。我的猜测是golang有一些处理信号/异常的机制,这会干扰JVM信号/异常处理。也许可以通过在golang中显式处理信号来做某事。 signals in golang here有一个入门指南。然而,这只是猜想,因为我现在无法验证它。