我将从我的代码开始:
#include <jni.h>
int main(int argc, char const *argv[]) {
JavaVMInitArgs args;
JNIEnv *env;
JavaVM *vm;
args.version = JNI_VERSION_1_8;
args.ignoreUnrecognized = JNI_FALSE;
JNI_CreateJavaVM(&vm, (void **)&env, &args);
jclass System;
jclass PrintStream;
jobject out;
jfieldID outID;
jstring someText;
jmethodID println;
someText = (*env)->NewStringUTF(env, "Hello World");
System = (*env)->FindClass(env, "java/lang/System");
PrintStream = (*env)->FindClass(env, "java/io/PrintStream");
outID = (*env)->GetStaticFieldID(env, System, "out", "Ljava/io/PrintStream;");
out = (*env)->GetStaticObjectField(env, System, outID);
println = (*env)->GetMethodID(env, PrintStream, "println", "(Ljava/lang/String;)V");
(*env)->CallVoidMethod(env, out, println, someText);
return 0;
}
我希望它打印“Hello World”,但它没有,相反,我得到了段错误(核心转储)
烦人的错误。我无法弄清楚这段代码有什么问题,我尝试注释掉 someText = (*env)->NewStringUTF(env, "Hello World");
之后的所有内容,但程序没有崩溃时,我还尝试仅注释 someText = (*env)->NewStringUTF(env, "Hello World");
并且我也工作了。我什至将 println
签名更改为 "boolean"
并将 0 传递给它,程序按照我的预期打印了“false”,所以我猜这是 的问题NewStringUTF
方法。
openjdk 版本“1.8.0_131”
OpenJDK 运行时环境(内部版本 1.8.0_131-b11)
OpenJDK 64 位服务器虚拟机(版本 25.131-b11,混合模式)
(gdb) bt
#0 0x00007ffff713b2ff in ?? () from /usr/lib/jvm/java-8-openjdk/jre/lib/amd64/server/libjvm.so
#1 0x00007ffff78955c4 in ?? () from /usr/lib/jvm/java-8-openjdk/jre/lib/amd64/server/libjvm.so
#2 0x00007ffff7507e71 in JNI_CreateJavaVM () from /usr/lib/jvm/java-8-openjdk/jre/lib/amd64/server/libjvm.so
#3 0x0000000000400558 in main (argc=1, argv=0x7fffffffe678) at main.c:11
(gdb) info f
Stack level 0, frame at 0x7fffffffe310:
rip = 0x7ffff713b2ff; saved rip = 0x7ffff78955c4
called by frame at 0x7fffffffe490
Arglist at 0x7fffffffe2c8, args:
Locals at 0x7fffffffe2c8, Previous frame's sp is 0x7fffffffe310
Saved registers:
rbx at 0x7fffffffe2d8, rbp at 0x7fffffffe300, r12 at 0x7fffffffe2e0, r13 at 0x7fffffffe2e8, r14 at 0x7fffffffe2f0,
r15 at 0x7fffffffe2f8, rip at 0x7fffffffe308
注释掉NewStringUTF
后
(gdb) bt
#0 0x00007fffe61082b4 in ?? ()
#1 0x0000000000000246 in ?? ()
#2 0x00007fffe6108160 in ?? ()
#3 0x00007fffffffe0f0 in ?? ()
#4 0x00007fffffffe090 in ?? ()
#5 0x00007ffff78f6748 in ?? () from /usr/lib/jvm/java-8-openjdk/jre/lib/amd64/server/libjvm.so
Backtrace stopped: previous frame inner to this frame (corrupt stack?)
(gdb) info f
Stack level 0, frame at 0x7fffffffde80:
rip = 0x7fffe61082b4; saved rip = 0x246
called by frame at 0x7fffffffde88
Arglist at 0x7fffffffde70, args:
Locals at 0x7fffffffde70, Previous frame's sp is 0x7fffffffde80
Saved registers:
rip at 0x7fffffffde78
经过一些观察,看起来函数 JNI_CreateJavaVM
在添加 NewStringUTF
后崩溃,但在删除后它“正常工作”。这有多奇怪?
这是我正在使用的 JDK 和 JRE:https://www.archlinux.org/packages/extra/x86_64/jdk8-openjdk/
我正在使用此命令进行编译:
gcc \
-I /usr/lib/jvm/java-8-openjdk/include/ \
-I /usr/lib/jvm/java-8-openjdk/include/linux/ \
-L /usr/lib/jvm/java-8-openjdk/jre/lib/amd64/server/ \
-l jvm \
main.c
并使用
运行文件export LD_LIBRARY_PATH=/usr/lib/jvm/java-8-openjdk/jre/lib/amd64/server/
./a.out
第二天
不同的代码,相同的问题:
#include <jni.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char const *argv[]) {
JavaVMInitArgs args;
JavaVM *jvm;
JNIEnv *env;
args.version = JNI_VERSION_1_8;
args.ignoreUnrecognized = JNI_FALSE;
printf("%s\n", "Creating VM");
JNI_CreateJavaVM(&jvm, (void **)&env, &args);
printf("%s\n", "VM Was Created");
jclass String = (*env)->FindClass(env, "java/lang/String");
if (String == NULL) {
printf("%s\n", "String was NULL");
exit(1);
}
jmethodID method = (*env)->GetMethodID(env, String, "codePointAt", "(I)I");
if (method == NULL) {
printf("%s\n", "method was NULL");
exit(1);
}
printf("%s\n", "I am finishing here");
(*jvm)->DestroyJavaVM(jvm);
return 0;
}
编译并运行:
$ gcc \
> -I /usr/lib/jvm/java-8-openjdk/include/ \
> -I /usr/lib/jvm/java-8-openjdk/include/linux/ \
> -L /usr/lib/jvm/java-8-openjdk/jre/lib/amd64/server/ \
> -l jvm \
> main.c && ./a.out
Creating VM
Segmentation fault (core dumped)
但是如果我评论代码部分:
#include <jni.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char const *argv[]) {
JavaVMInitArgs args;
JavaVM *jvm;
JNIEnv *env;
args.version = JNI_VERSION_1_8;
args.ignoreUnrecognized = JNI_FALSE;
printf("%s\n", "Creating VM");
JNI_CreateJavaVM(&jvm, (void **)&env, &args);
printf("%s\n", "VM Was Created");
jclass String = (*env)->FindClass(env, "java/lang/String");
if (String == NULL) {
printf("%s\n", "String was NULL");
exit(1);
}
/*jmethodID method = (*env)->GetMethodID(env, String, "codePointAt", "(I)I");
if (method == NULL) {
printf("%s\n", "method was NULL");
exit(1);
}*/
printf("%s\n", "I am finishing here");
(*jvm)->DestroyJavaVM(jvm);
return 0;
}
编译并运行:
$ gcc \
> -I /usr/lib/jvm/java-8-openjdk/include/ \
> -I /usr/lib/jvm/java-8-openjdk/include/linux/ \
> -L /usr/lib/jvm/java-8-openjdk/jre/lib/amd64/server/ \
> -l jvm \
> main.c && ./a.out
Creating VM
VM Was Created
I am finishing here
最佳答案
所以,对我来说,它按预期工作:
> gdb ./main
...
(gdb) run
Starting program: ..../issue/main
[New Thread 0x1403 of process 2600]
[New Thread 0x1503 of process 2600]
warning: unhandled dyld version (15)
Hello World
[Inferior 1 (process 2600) exited normally]
(gdb)
但是,我的环境略有不同。 macOS 和我使用 Oracle 的 JDK。
也许你可以尝试安装调试信息并检查 JDK 内部到底发生了什么?
关于java - C + JNI 无法执行一个非常简单的程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44991293/