1

SystemC 内で JNI を使用する場合、自分では説明できない非常に奇妙な問題に直面します。

私の使用環境に関するいくつかの情報: 私は現在、openjdk-6 と openjdk-7 がインストールされた 12.04 ubuntu で開発しています。この問題は両方の jdk で再現されます。

この主な方法を持つ:

#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が同じままであることがわかるように)。

助言がありますか?さらに情報が必要な場合はお知らせください。

4

1 に答える 1