Сбой C в JNI SIGSEGV

#java #c #java-native-interface

Вопрос:

Я медленно схожу с ума, так как, несмотря на множество попыток и поисков, я не могу найти жизнеспособного решения этой проблемы.

Я получаю сбой, когда вызываю java / JNI из C с помощью строки.

Любая помощь была бы очень признательна. Я новичок в JNI, поэтому я могу сделать что-то не так, например, должен ли я предварительно выделить буфер памяти и передать его?

Код ниже

Бит Java

 public class helloWorld{  public static void main(String[] args){  System.out.println("Hello, World");  }  public static int square(int input){  int output = input * input;  return output;  }  public static int power(int input, int exponent){  int output,i;  output=1;  for(i=0;ilt;exponent;i  ){  output *= input;  }  return output;  }   public static void hello(String val) {  } }  

Бит C

 #include lt;stdio.hgt; #include lt;stringgt; #include lt;jni.hgt; #include lt;iostreamgt;   JNIEXPORT jstring JNICALL Java_com_baeldung_jni_HelloWorldJNI_sayHello (JNIEnv* env) {  std::string hello = "Hello from C   !!";  std::cout lt;lt; hello lt;lt; std::endl;  return env-gt;NewStringUTF(hello.c_str()); }  JNIEnv* create_vm(JavaVM **jvm) {  JNIEnv* env;  JavaVMInitArgs args;  JavaVMOption options;  args.version = JNI_VERSION_1_6;  args.nOptions = 1;  options.optionString = (char *)"-Djava.class.path=./";  args.options = amp;options;  args.ignoreUnrecognized = 0;  int rv = JNI_CreateJavaVM(jvm, (void**)amp;env, amp;args);  if (rv lt; 0 || !env)  printf("Unable to Launch JVM %dn",rv);  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-gt;FindClass("helloWorld");  main_method = env-gt;GetStaticMethodID(hello_world_class, "main", "([Ljava/lang/String;)V");  square_method = env-gt;GetStaticMethodID(hello_world_class, "square", "(I)I");  power_method = env-gt;GetStaticMethodID(hello_world_class, "power", "(II)I");  env-gt;CallStaticVoidMethod(hello_world_class, main_method, NULL);  printf("%d squared is %dn", number,  env-gt;CallStaticIntMethod(hello_world_class, square_method, number));  printf("%d raised to the %d power is %dn", number, exponent,  env-gt;CallStaticIntMethod(hello_world_class, power_method, number, exponent));  printf("lalalalalan");     std::string message = "This comes from jni.";  const char *result = message.c_str();  jstring argString = env-gt;NewStringUTF(result);     jmethodID hello_method = env-gt;GetStaticMethodID(hello_world_class, "hello", "([Ljava/lang/String;)V");  env-gt;CallStaticVoidMethod(hello_world_class, hello_method, argString); }   int main(int argc, char **argv) {  JavaVM *jvm;  JNIEnv *env;  env = create_vm(amp;jvm);  if(env == NULL)  return 1;  invoke_class(env);   return 0; }  

и, наконец, журнал (усек его, так как он был слишком длинным)

 # # A fatal error has been detected by the Java Runtime Environment: # # SIGSEGV (0xb) at pc=0x0000000105b76b9c, pid=94283, tid=259 # # JRE version: OpenJDK Runtime Environment (16.0.1 9) (build 16.0.1 9-24) # Java VM: OpenJDK 64-Bit Server VM (16.0.1 9-24, mixed mode, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, bsd-amd64) # Problematic frame: # V [libjvm.dylib 0x571b9c] jni_CallStaticVoidMethodV 0xcc # # No core dump will be written. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again # # If you would like to submit a bug report, please visit: # https://bugreport.java.com/bugreport/crash.jsp #  --------------- S U M M A R Y ------------  Command Line:   Host: MacBookPro16,1 x86_64 2300 MHz, 16 cores, 16G, Darwin 20.4.0, macOS 11.3.1 (20E241) Time: Fri Oct 15 13:38:03 2021 BST elapsed time: 0.115419 seconds (0d 0h 0m 0s)  --------------- T H R E A D ---------------  Current thread (0x00007fc796008a00): JavaThread "main" [_thread_in_vm, id=259, stack(0x00007ffee9e0b000,0x00007ffeea60b000)]  Stack: [0x00007ffee9e0b000,0x00007ffeea60b000], sp=0x00007ffeea60a270, free space=8188k Native frames: (J=compiled Java code, A=aot compiled Java code, j=interpreted, Vv=VM code, C=native code) V [libjvm.dylib 0x571b9c] jni_CallStaticVoidMethodV 0xcc C [a.out 0x3701] JNIEnv_::CallStaticVoidMethod(_jclass*, _jmethodID*, ...) 0x171 C [a.out 0x39df] main 0xff C [libdyld.dylib 0x15f3d] start 0x1   siginfo: si_signo: 11 (SIGSEGV), si_code: 1 (SEGV_MAPERR), si_addr: 0x0000000000000000  Register to memory mapping:  RAX=0x9d0fb75d63f100d0 is an unknown value RBX=0x00007fc793f05418 points into unknown readable memory: 0x000000070fe19bc8 | c8 9b e1 0f 07 00 00 00 RCX=0x00007fc793f04ad8 points into unknown readable memory: 0x000000070fe1a1a8 | a8 a1 e1 0f 07 00 00 00 RDX=0x0 is NULL RSP=0x00007ffeea60a270 is pointing into the stack for thread: 0x00007fc796008a00 RBP=0x00007ffeea60a310 is pointing into the stack for thread: 0x00007fc796008a00 RSI=0x00007fc793f05418 points into unknown readable memory: 0x000000070fe19bc8 | c8 9b e1 0f 07 00 00 00 RDI=0x00007fc796008d10 points into unknown readable memory: 0x0000000106275e58 | 58 5e 27 06 01 00 00 00 R8 =0x0 is NULL R9 =0x0 is NULL R10=0x00007fff20269e10: __vfprintf.xdigs_lower 0 in /usr/lib/system/libsystem_c.dylib at 0x00007fff201e7000 R11=0xffffffc8ab1fff06 is an unknown value R12=0x00007fc796008a00 is a thread R13=0x00007fc796008d10 points into unknown readable memory: 0x0000000106275e58 | 58 5e 27 06 01 00 00 00 R14=0x0 is NULL R15=0x00007ffeea60a4a0 is pointing into the stack for thread: 0x00007fc796008a00   

Комментарии:

1. main_method = square_method = power_method = — Вам действительно следует проверить, действительны ли они, прежде чем вызывать вызов JNI.

2. хорошо, как мне их проверить? но проблема была не в этом, проблема заключалась в сигнатуре метода, переданной Getstaticmethod

3. Если возвращаемое значение равно nullptr , это означает, что метод / класс не был найден. Например, верните ошибку в свою программу и посмотрите на возвращаемое значение. Вы должны видеть, что hello_method это nullptr. Это означало бы, что предмет не был найден. При написании кода JNI очень важно проверять наличие любых ошибок и сообщать о них на уровне C . Обратите внимание, что ваша проблема была вызвана ошибкой в наборе текста (или ошибкой при вводе). Это те типы ошибок, которых можно избежать, выполнив проверку на вменяемость nullptr .

4. Кстати, это распространенная ошибка, когда подпись неверна из-за незнания правильной подписи, или просто толстые пальцы вводят неправильные символы в строке подписи, или какая-то ошибка копирования/вставки.

5. @PaulMcKenzie спасибо вам за весь ваш ценный вклад. 🙂 Очень признателен! Выученный урок проверьте наличие действительного удостоверения личности или проверьте наличие nullptr.

Ответ №1:

Я отвечаю на свой собственный вопрос. Проблема заключалась в сигнатуре метода, переданной JNI с дополнительным [

 jmethodID hello_method = env-gt;GetStaticMethodID(hello_world_class, "hello", "([Ljava/lang/String;)V");  
 jmethodID hello_method = env-gt;GetStaticMethodID(hello_world_class, "hello", "(Ljava/lang/String;)V");  

Комментарии:

1. Согласно моему комментарию, вам действительно следует проверить, что все эти функции возвращают действительные идентификаторы.