C + JNI无法执行一个非常简单的程序

时间:2017-07-08 22:29:01

标签: java c java-native-interface jnienv

我将从我的代码开始:

#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;
}

我希望它可以打印&#34; Hello World&#34;但它没有,而是我得到Segmentation fault (core dumped)恼人的错误。我无法弄清楚这段代码有什么问题,我试图在someText = (*env)->NewStringUTF(env, "Hello World");之后注释掉所有内容并且程序没有崩溃,我也尝试只评论someText = (*env)->NewStringUTF(env, "Hello World");而且我也做过工作。我甚至将println签名更改为"boolean"并将0传递给它,程序打印&#34; false&#34;正如我所料,所以我猜这是NewStringUTF方法的错误。

openjdk version "1.8.0_131" OpenJDK Runtime Environment (build 1.8.0_131-b11) OpenJDK 64-Bit Server VM (build 25.131-b11, mixed mode)

(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后崩溃了,但它已经&#34;工作&#34;在它被删除后。这有多奇怪?

这是我正在使用的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

1 个答案:

答案 0 :(得分:1)

所以,对我来说,它按预期工作:

str

然而,我的环境略有不同。 macOS和我使用Oracle的JDK。

也许您可以尝试安装调试信息并检查JDK中究竟发生了什么?