gpt4 book ai didi

java - 使用 jni 时出现 fatal error

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:21:34 28 4
gpt4 key购买 nike

我正在尝试使用 jni 从 C++ 调用 Java 方法。实际上更多的是回调(java -> c++ -> java)我通过在 .exe (c++ -> java) 中测试它来检查 c++ 程序是否有错误该程序在 Visual Studio 中完美运行。但是当我将它转换为 dll 并在 java 中使用它时失败并崩溃。我认为它与 jvm.dll 有关,因为我必须将它包含到我的 visual studio 项目中。

C++:

#include <stdio.h>
#include <jni.h>
#include <string.h>
#include "Inter.h"

JNIEnv* create_vm(JavaVM ** jvm) {

JNIEnv *env;
JavaVMInitArgs vm_args;
JavaVMOption options;
options.optionString = "-Djava.class.path=C:\\Users\\SolidSnake\\workspace\\Test\\bin"; //Path to the java source code
vm_args.version = JNI_VERSION_1_8;
vm_args.nOptions = 1;
vm_args.options = &options;
vm_args.ignoreUnrecognized = 0;

int ret = JNI_CreateJavaVM(jvm, (void**)&env, &vm_args);
if(ret < 0)
printf("\nUnable to Launch JVM\n");
return env;
}

void callMethod() {
JNIEnv *env;
JavaVM * jvm;
env = create_vm(&jvm);
jclass m;
jmethodID test;
m = env->FindClass("Main");
test = env->GetStaticMethodID(m,"callbackFromC","()V");
env->CallStaticVoidMethod(m,test);
}

Java:

public final class Main {

public native int callToC();

public static void callbackFromC() {
System.out.println("Hello from C!");
}

public static void main(String[] args) {
System.loadLibrary("Test");
new Main().callToC();
}

}

崩溃:

#
# A fatal error has been detected by the Java Runtime Environment:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x000007f9aed32ff8, pid=4016, tid=8228
#
# JRE version: Java(TM) SE Runtime Environment (8.0_11-b12) (build 1.8.0_11-b12)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.11-b03 mixed mode windows-amd64 compressed oops)
# Problematic frame:
# C [Test.dll+0x1a08] JNIEnv_::FindClass+0x28
#
# Failed to write core dump. Minidumps are not enabled by default on client versions of Windows

程序是这样的 (j:callToC) -> (c:callMethod) -> (j:callbackFromC)

最佳答案

几天前我遇到了同样的问题,我找到了问题的解决方案(也许不是最好的),现在我很自豪地分享它(这个可能对将来的人有用)。

这是我只有两个项目(C++->Java)时运行良好的代码,即调用 Java 方法的 C++ 项目:

void JVM:: Init( const std:: string& javaClassesPath )  {    
std:: string optionString = ( std:: string("-Djava.class.path=") + javaClassesPath );
JavaVMOption options_;
options_.optionString = const_cast<char*>( optionString.c_str() );

// initializing of JVM initial arguments:
JavaVMInitArgs arguments_;
memset( &arguments_, 0, sizeof( arguments_ ) );
arguments_.version = JNI_VERSION_1_6;
arguments_.nOptions = 1;
arguments_.options = &options_;
arguments_.ignoreUnrecognized = 0;

// creating JVM:
long status = JNI_CreateJavaVM( &jvm_, (void**)&env_, &arguments_ );
if ( status == JNI_ERR )
throw std:: exception("Error: unable to create Java Virtual Machine.\n");

FindClass("ChartBuilder");
}

这段代码是通过以下方式调用的:

JVM JChartBuilder( "D:\\Java Src\\Chart\\Chart.jar" ); // the path that will be used as classpath when creating VM (unless this path is specified it will be unable to find the class ChartBuilder)

然后 (Java->C++Java)当我得到必须使用 JNI 从那个 C++ 项目调用方法的第三个项目 (Java) 时,我遇到了一个问题,即当一个已经在当前进程中运行时我无法创建 VM。但是我们可以附加到现有的 VM!因此,可以更改上面列出的代码以满足此要求:

void JVM:: Init( const std:: string& javaClassesPath )
{
// initializing of JVM options:
std:: string optionString = ( std:: string("-Djava.class.path=") + javaClassesPath );
JavaVMOption options_;
options_.optionString = const_cast<char*>( optionString.c_str() );

// initializing of JVM initial arguments:
JavaVMInitArgs arguments_;
memset( &arguments_, 0, sizeof( arguments_ ) );
arguments_.version = JNI_VERSION_1_6;
arguments_.nOptions = 1;
arguments_.options = &options_;
arguments_.ignoreUnrecognized = 0;

// creating JVM or attaching to JVM:
long status;
/* is there any running VMs in the process? */
JavaVM* createdVMs[1] = { nullptr };
jsize numberOfVMs;
status = JNI_GetCreatedJavaVMs(createdVMs, 1, &numberOfVMs);
/* END OF is there any running VMs in the process? */
if( numberOfVMs != 0 )
{ // if VM already runs:
jvm_ = createdVMs[0]; // get the VM
jvm_->AttachCurrentThread((void**)&env_, NULL); // attach to the VM
}
else
{ // if VM does not run:
status = JNI_CreateJavaVM( &jvm_, (void**)&env_, &arguments_ );
}

if ( status == JNI_ERR )
throw std:: exception("Error: unable to create Java Virtual Machine.\n");

FindClass("ChartBuilder");
}

但这还不是全部。当运行主 Java 项目(Java->C++->Java 中的第一个)时,出现以下问题:无法找到指定的类 ChartBuilder。那就是我附加到现有的 VM,但是这个虚拟机不知道这个类的路径。请记住,当我在 C++ 中创建 VM 时,我明确指定了路径。为了解决这个问题,我现在必须在运行主 Java 项目时额外指定类路径。

就是这样。我唯一不喜欢的是在运行主 Java 项目时需要指定 ChartBuilder 的类路径,但这对我来说并不重要,尽管我想知道如何避免这种需要。也许有人知道?

关于java - 使用 jni 时出现 fatal error ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25497599/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com