java - C++ 到 JNI SIGSEGV 崩溃
问题描述
我正在慢慢失去理智,因为尽管进行了多次尝试和搜索,但我找不到可行的解决方案。
当我使用字符串从 C++ 调用 java / JNI 时发生崩溃。
任何帮助将非常感激。我是 JNI 的新手,所以我可能会做错事,也就是我应该预先分配内存缓冲区并传递它吗?
下面的代码
爪哇位
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;i<exponent;i++){
output *= input;
}
return output;
}
public static void hello(String val) {
}
}
C++ 位
#include <stdio.h>
#include <string>
#include <jni.h>
#include <iostream>
JNIEXPORT jstring JNICALL Java_com_baeldung_jni_HelloWorldJNI_sayHello (JNIEnv* env) {
std::string hello = "Hello from C++ !!";
std::cout << hello << std::endl;
return env->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 = &options;
args.ignoreUnrecognized = 0;
int rv = JNI_CreateJavaVM(jvm, (void**)&env, &args);
if (rv < 0 || !env)
printf("Unable to Launch JVM %d\n",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->FindClass("helloWorld");
main_method = env->GetStaticMethodID(hello_world_class, "main", "([Ljava/lang/String;)V");
square_method = env->GetStaticMethodID(hello_world_class, "square", "(I)I");
power_method = env->GetStaticMethodID(hello_world_class, "power", "(II)I");
env->CallStaticVoidMethod(hello_world_class, main_method, NULL);
printf("%d squared is %d\n", number,
env->CallStaticIntMethod(hello_world_class, square_method, number));
printf("%d raised to the %d power is %d\n", number, exponent,
env->CallStaticIntMethod(hello_world_class, power_method, number, exponent));
printf("lalalalala\n");
std::string message = "This comes from jni.";
const char *result = message.c_str();
jstring argString = env->NewStringUTF(result);
jmethodID hello_method = env->GetStaticMethodID(hello_world_class, "hello", "([Ljava/lang/String;)V");
env->CallStaticVoidMethod(hello_world_class, hello_method, argString);
}
int main(int argc, char **argv)
{
JavaVM *jvm;
JNIEnv *env;
env = create_vm(&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
解决方案
我回答我自己的问题。问题在于传递给 JNI 的方法签名带有额外的 [
jmethodID hello_method = env->GetStaticMethodID(hello_world_class, "hello", "([Ljava/lang/String;)V");
jmethodID hello_method = env->GetStaticMethodID(hello_world_class, "hello", "(Ljava/lang/String;)V");
推荐阅读
- c# - Mononame 不生成 Debug.xnb
- javascript - 指针在链表中是如何工作的?
- delphi - Delphi IDE 冻结代码完成并跳转到声明
- nestjs - NestJs/TypeORM:如何保存多对多
- swift - Typescript 联合类型的 Swift 等价物是什么?
- java - Java 构造问题 findmissing 元素
- arrays - Javascript将一个数组中的元素推入另一个数组
- css - tablerow 背景颜色不适用于 tabledata #css
- swift - 如何从自定义上滑菜单中显示控制器
- python - 将 csv 数据转换为逗号的单独列表