简体   繁体   中英

C + JNI Fails to execute a very simple program

I'll start with my code:

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

I would expect it to print "Hello World" but it does not, instead I get Segmentation fault (core dumped) annoying error. I could not figure out what is wrong with this code, I tried to comment out everything after someText = (*env)->NewStringUTF(env, "Hello World"); and the program didn't crash, I also tried to comment only the someText = (*env)->NewStringUTF(env, "Hello World"); and I worked too. I even changed the println signature to "boolean" and passed 0 to it, program printed "false" as I would expect so I guess this is something wrong with NewStringUTF method.

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

after commenting out the 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

After some observations, looks like the function JNI_CreateJavaVM is crashing after NewStringUTF was added, but it's "working" after it's removed. How weird is that?

This is JDK and JRE I am using: https://www.archlinux.org/packages/extra/x86_64/jdk8-openjdk/

I am compiling with this command:

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

And running the file with

export LD_LIBRARY_PATH=/usr/lib/jvm/java-8-openjdk/jre/lib/amd64/server/
./a.out

Next Day

Different code, same problem:

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

Compile and run:

$ 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)

But if I comment the part of the code:

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

Compile and run:

$ 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

So, for me, it works as expected:

> 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)

However, I have slightly different env. macOS and I use Oracle's JDK.

Maybe you can try installing debug info and check what exactly happens inside JDK?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM