【发布时间】:2014-06-25 16:20:26
【问题描述】:
在 SystemC 中使用 JNI 时,我遇到了一个非常奇怪的问题,我自己无法解释。
关于我使用的环境的一些信息:我目前正在安装 openjdk-6 和 openjdk-7 的 12.04 ubuntu 上进行开发。两个 jdks 都会重现该问题!
有这个主要方法:
#include "tlm.h"
#include "SystemCWrapper.h"
int sc_main(int argc, char *argv[]) {
SystemCWrapper wrapper("test");
std::cout << "############ Before ############" << std::endl;
wrapper.run();
std::cout << "############ SC-START ############" << std::endl;
sc_core::sc_start();
std::cout << "############ After ############" << std::endl;
wrapper.run();
return 0;
}
以及 SystemCWrapper 的以下实现:
#include "SystemCWrapper.h"
#include <jni.h>
#include <iostream>
#include <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h>
SC_HAS_PROCESS( SystemCWrapper );
using std::cout;
using std::cerr;
using std::endl;
static JavaVM * createJavaVM () {
JavaVM *jvm;
JNIEnv *env;
JavaVMInitArgs vm_args; /* JDK/JRE 6 VM initialization arguments */
JavaVMOption* options = new JavaVMOption[2];
options[0].optionString = const_cast<char*>("-Djava.class.path=HelloWorld.jar");
options[1].optionString = const_cast<char*>("-verbose:jni");
vm_args.version = JNI_VERSION_1_6;
vm_args.nOptions = 1; // NOTE: set to 2 for more verbose jni information
vm_args.options = options;
vm_args.ignoreUnrecognized = false;
/* load and initialize a Java VM, return a JNI interface pointer in env */
JNI_CreateJavaVM(&jvm, (void**) &env, &vm_args);
return jvm;
}
SystemCWrapper::SystemCWrapper(sc_core::sc_module_name nam) : sc_module(nam), jvm(NULL){
SC_THREAD(run); // Thread to run the ISS
// setup the JNI
jvm = createJavaVM();
}
SystemCWrapper::~SystemCWrapper() {
}
void SystemCWrapper::run() {
// Print general information
cout << "Hello SystemC (PID: " << getpid() << ", PTID: " << pthread_self() << ", LTID: " << syscall(SYS_gettid) << ")" << endl;
JNIEnv* env;
int ret = jvm->GetEnv((void**)&env, JNI_VERSION_1_6);
if(ret == JNI_OK) {
cout << "Retrieve successful." << endl;
} else if(ret == JNI_EDETACHED){
cerr << "Environment is detached." << endl;
} else {
cerr << "Retrieving environment failed! (" << ret << ")" << endl;
}
jclass clazz = env->FindClass("JavaProgram");
if(clazz == NULL) {
cerr << "Class not found" << endl;
return;
}
jmethodID mConstr = env->GetMethodID(clazz, "<init>", "()V");
if(mConstr == NULL) {
cerr << "Constructor not found" << endl;
return;
}
jmethodID mRun = env->GetMethodID(clazz, "run", "()I");
if(mRun == NULL) {
cerr << "Run method not found" << endl;
return;
}
jobject obj = env->NewObject(clazz, mConstr);
if(obj == NULL) {
cerr << "Object was not created!" << endl;
return;
}
int result = env->CallIntMethod(obj, mRun);
if(result == 0) {
cerr << "Run should never return 0!" << endl;
return;
}
}
结果进入以下控制台输出(Java 程序仅输出“Hello Java!”,如果被调用):
$ ./build/bin/jnitest
SystemC 2.3.1-Accellera --- Jun 6 2014 13:36:39
Copyright (c) 1996-2014 by all Contributors,
ALL RIGHTS RESERVED
############ Before ############
Hello SystemC (PID: 5660, PTID: 140661929555776, LTID: 5660)
Retrieve successful.
Hello Java!
############ SC-START ############
Hello SystemC (PID: 5660, PTID: 140661929555776, LTID: 5660)
Retrieve successful.
Object was not created!
############ After ############
Hello SystemC (PID: 5660, PTID: 140661929555776, LTID: 5660)
Retrieve successful.
Hello Java!
似乎 SystemC 方法 sc_core::sc_start(); 所做的事情是每个 JNI 调用都没有“传递”到 Java。
我尝试了一些调整,但即使我将当前线程附加到 jvm,也没有任何变化(因为可以看到线程 ID 甚至保持不变)。
有什么建议吗?如果需要更多信息,请告诉我。
【问题讨论】:
-
你到底想做什么?将 SystemC 和 java 虚拟机连接起来是一件相当奇怪的事情。
-
我同意乍一看这看起来很奇怪,但在我们目前的情况下,我们的指令集模拟器是用 Java 实现的。现在我们想把它集成到一个基于 SystemC/TLM 的平台仿真框架中。基本上,我们想要实现的目标与embecosm.com/appnotes/ean1/ean1-tlm2-or1ksim-2.0.html 中的相同,但是我们不想为基于 C 的模拟器构建 SystemC/TLM 包装器,而是希望使用 JNI 包装我们的 java 模拟器。
-
SC_THREAD 上下文中的堆栈大小?你跑的东西比标准的要重得多。
-
我尝试使用
set_stack_size(size_t size)增加堆栈大小,但没有帮助。我还调整了代码以仅调用静态方法(而不是创建对象并在其上调用方法),但这也无济于事。但是我注意到java代码中抛出了一个异常,所以我将代码更改为`public class JavaProgram { public static int run() { return -1; } } ` 但仍然抛出异常。在 sc start() 之后使用 env->ExceptionDescribe() 打印异常我在返回 -1 时得到一个 StackOverflow 异常。可能和sc_thread模型有关?
标签: java-native-interface systemc