Javaのプログラムを呼び出す

Javaのプログラムを呼び出す方法としては、コンソールからjava.exeを使って実行する方法が殆どで、例えばネットワークインターフェースの情報を取得するプログラムで利用したIfInfoTest.javaだと

java -cp c:\java\net\classes net.test.IfInfoTest

として起動するとか、コマンドライン実行が面倒な場合には、上記コマンドをfoo.batのようにバッチファイル化して起動する方法などが考えられます。


ただ個人的には、コマンドラインで呼び出したりバッチファイルにするのはスマートでなかったり、アイコンを定義できなかったりと不便なのと、それにJavaアプリケーションをWindowsサービスとして登録したかったこともあったので、C++のプログラムから呼び出すクラスを作ってみました。


JvmEnvクラスでは、JNIを起動する時に必要な環境の構築と情報の保持を行います。
JvmEnv.h

#ifndef _JVM_ENV_CLASS
#define _JVM_ENV_CLASS

#include <windows.h>
#include <tchar.h>
#include <comdef.h>

#include <string>
#include <vector>
#include <map>

typedef std::basic_string<_TCHAR>   String;
typedef std::vector<String>         string_array;
typedef std::map<String, String>    string_map;
typedef std::pair<String, String>   string_pair;
typedef string_map::iterator        psmap;
typedef std::map<String, void *>    pointer_map;
typedef std::pair<String, void *>   pointer_pair;
typedef pointer_map::iterator       ppmap;

#include <jni.h>

typedef jint (WINAPI *lpJNI_GetDefaultJavaVMInitArgs)(void *args);
typedef jint (WINAPI *lpJNI_CreateJavaVM)(JavaVM **pvm, void **penv, void *args);
typedef jint (WINAPI *lpJNI_GetCreatedJavaVMs)(JavaVM **, jsize, jsize *);
typedef void (WINAPI *lpPrintRoutine)(FILE *file, const char *format, va_list args);
typedef void (WINAPI *lpAbortRoutine)();
typedef void (WINAPI *lpExitRoutine)(int code);

//  Java environment access type

extern const int JDKJavaHome;
extern const int JDKRuntimeLib;
extern const int JREJavaHome;
extern const int JRERuntimeLib;
extern const int CurrentVersion;
extern const int TargetVersion;
extern const int LatestVersion;

class JvmEnv {
private:
    void    copy(const JvmEnv& from);

    static String   getRegValue(HKEY hkey, String valueKey, DWORD type);

    static void JNICALL jni_vfprintf(FILE *file, const char *format, va_list args);
    static void JNICALL jni_exit(jint code);
    static void JNICALL jni_abort();

public:
    JvmEnv();
    JvmEnv(const JvmEnv& from);
    ~JvmEnv();

    JvmEnv&         operator=(const JvmEnv& original);

    void            loadArgs(int argc, _TCHAR* argv[], bool first_program = true);
    void            addProgParam(String argv);
    void            addJavaParam(String argv);

    void            setJLibName(String libpath);
    int             loadJLib(String libpath = String());
    int             unloadJLib();

    int             createJvm();
    JavaVM          *getJvm();
    jobjectArray    jvmArgs(JNIEnv* jEnv);
    int             destroyJvm();

    String          getCallerName();

    void            addClassPath(String path, String file = String());
    String          getClassPath();

    static void     setPrintRoutine(lpPrintRoutine routine);
    static void     setAbortRoutine(lpAbortRoutine routine);
    static void     setExitRoutine(lpExitRoutine routine);

    static string_map   installedJvm(int type);
    static String       findJvm(int type, bool version = true, String basic = String());

private:
    string_array    prog_params;
    string_array    java_params;
    string_array    class_path;

    String          vm_lib;
    String          caller_name;

    JavaVM          *jvm;
    JNIEnv          *jni_env;

    HINSTANCE                       hjvm;
    lpJNI_GetDefaultJavaVMInitArgs  fnJNI_GetDefaultJavaVMInitArgs;
    lpJNI_CreateJavaVM              fnJNI_CreateJavaVM;
    lpJNI_GetCreatedJavaVMs         fnJNI_GetCreatedJavaVMs;
};  //  class JvmEnv

#endif  //  _JVM_ENV_CLASS

JvmEnv.cpp

#include "jvmenv.h"
#include "jvmservice.h"

const int JavaHome          = 0x01;
const int RuntimeLib        = 0x02;

const int JDK_BASE          = 0x04;
const int JDK               = JDK_BASE;
const int JDKJavaHome       = (JDK_BASE+JavaHome);
const int JDKRuntimeLib     = (JDK_BASE+RuntimeLib);

const int JRE_BASE          = 0x08;
const int JRE               = JRE_BASE;
const int JREJavaHome       = (JRE_BASE+JavaHome);
const int JRERuntimeLib     = (JRE_BASE+RuntimeLib);

const int CurrentVersion    = 0x80;
const int TargetVersion     = CurrentVersion+0x10;
const int LatestVersion     = CurrentVersion+0x20;

const String JAVA_ROOT              = String(_T("SOFTWARE\\JavaSoft"));
const String JDK_PATH               = String(_T("\\Java Development Kit"));
const String JRE_PATH               = String(_T("\\Java Runtime Environment"));
const String CURRENT_VERSION        = String(_T("CurrentVersion"));

const char *szJNI_GetDefaultJavaVMInitArgs  = "JNI_GetDefaultJavaVMInitArgs";
const char *szJNI_CreateJavaVM              = "JNI_CreateJavaVM";
const char *szJNI_GetCreatedJavaVMs         = "JNI_GetCreatedJavaVMs";

#define BUFF_SIZE           256

static lpPrintRoutine print_routine = NULL;
static lpAbortRoutine abort_routine = NULL;
static lpExitRoutine exit_routine = NULL;

/*
 *  JvmEnvの値をコピーする
 *  param   : コピー元のデータ(JvmEnvクラス)
 *
 *  return  : 無し
 */
void JvmEnv::copy(const JvmEnv& from) {
    for (size_t i = 0; i < from.prog_params.size(); i++)
        prog_params.push_back(from.prog_params.at(i));
    for (size_t i = 0; i < from.java_params.size(); i++)
        java_params.push_back(from.java_params.at(i));
    for (size_t i = 0; i < from.class_path.size(); i++)
        class_path.push_back(from.class_path.at(i));

    vm_lib = from.vm_lib;
    caller_name = from.caller_name;
    jvm = from.jvm;
    jni_env = from.jni_env;
    hjvm = from.hjvm;
    fnJNI_GetDefaultJavaVMInitArgs = from.fnJNI_GetDefaultJavaVMInitArgs;
    fnJNI_CreateJavaVM = from.fnJNI_CreateJavaVM;
    fnJNI_GetCreatedJavaVMs = from.fnJNI_GetCreatedJavaVMs;
}

/*
 *  Registoryからデータを取得する
 *  param   : Registoryキー(HKEY)
 *            データキー(String)
 *            データタイプ(DWORD)
 *
 *  return  : String
 */
String JvmEnv::getRegValue(HKEY hkey, String valueKey, DWORD type) {
    DWORD buffSize = 0;
    DWORD valueType = type;

    int rc;
    rc = RegQueryValueEx(hkey, valueKey.c_str(), 0, &valueType, NULL, &buffSize);
    String result;
    if (rc == ERROR_SUCCESS) {
        buffSize++;
        char *buff = (char *)calloc(buffSize, sizeof(char));
        if (buff != NULL) {
            if (RegQueryValueEx(hkey, valueKey.c_str(), 0, &valueType, (LPBYTE)buff, &buffSize) == ERROR_SUCCESS) {
                result = String((_TCHAR*)buff);
            }
            free(buff);
        }
    }
    return result;
}

/*
 *  print_routineの呼出
 *  param   : 出力ファイル(FILEポインター)
 *            フォーマット(const charポインター)
 *            パラメータリスト(va_list)
 *
 *  return  : 無し
 */
void (JNICALL JvmEnv::jni_vfprintf)(FILE *file, const char *format, va_list args) {
    if (print_routine != NULL)
        print_routine(file, format, args);
}

/*
 *  abort_routineの呼出
 *  param   : 無し
 *
 *  return  : 無し
 */
void (JNICALL JvmEnv::jni_abort)() {
    if (abort_routine != NULL)
        abort_routine();
}

/*
 *  exit_routineの呼出
 *  param   : exitコード(int)
 *
 *  return  : 無し
 */
void (JNICALL JvmEnv::jni_exit)(jint code) {
    if (exit_routine != NULL)
        exit_routine(code);
}

//  Constructer
JvmEnv::JvmEnv() {
    jvm = NULL;
    jni_env = NULL;
    hjvm = NULL;
    fnJNI_GetDefaultJavaVMInitArgs = NULL;
    fnJNI_CreateJavaVM = NULL;
    fnJNI_GetCreatedJavaVMs = NULL;
}

//  Copy Constructer
JvmEnv::JvmEnv(const JvmEnv& from) {
    copy(from);
}

//  Destructer
JvmEnv::~JvmEnv() {
}

/*
 *  "=(代入)"オペレータの処理
 */
JvmEnv& JvmEnv::operator=(const JvmEnv& original) {
    copy(original);
    return *this;
}

/*
 *  プログラム起動時のパラメータを保存する
 *  param   : パラメータの数(int)
 *            パラメータ(_TCHARポインター)
 *
 *  return  : 無し
 */
void JvmEnv::loadArgs(int argc, _TCHAR* argv[], bool first_program) {
    for (int i = 0; i < argc; i++) {
        if (first_program && (i == 0))
            caller_name = String(argv[i]);
        else {
            if ((argv[i][0] == _T('-')) && (argv[i][1] != _T('-'))) {
                java_params.push_back(String(argv[i]));
            }
            else {
                prog_params.push_back(String(argv[i]));
            }
        }
    }
}

/*
 *  プログラム実行用パラメータを追加する
 *  param   : パラメータ(String)
 *
 *  return  : 無し
 */
void JvmEnv::addProgParam(String argv) {
    prog_params.push_back(argv);
}

/*
 *  Javaの起動用パラメータを追加する
 *  param   : パラメータ(String)
 *
 *  return  : 無し
 */
void JvmEnv::addJavaParam(String argv) {
    java_params.push_back(argv);
}

/*
 *  JavaVM Libraryの名前を指定する
 *  param   : JavaVM Libraryの名前(String)
 *
 *  return  : 無し
 */
void JvmEnv::setJLibName(String libpath) {
    vm_lib = libpath;
}

/*
 *  JavaVM Libraryをロードし、ファンクションのアドレスを取得する
 *  param   : JavaVM Libraryの名前(String)
 *
 *  return  : int
 */
int JvmEnv::loadJLib(String libpath) {
    if (!libpath.empty()) {
        vm_lib = libpath;
    }
    else {
        if (vm_lib.empty()) {
            vm_lib = findJvm(JRERuntimeLib+LatestVersion, false);
        }
    }
    if (!vm_lib.empty()) {
        hjvm = LoadLibrary(vm_lib.c_str());
        if (hjvm != NULL) {
            fnJNI_GetDefaultJavaVMInitArgs = (lpJNI_GetDefaultJavaVMInitArgs)GetProcAddress(hjvm, szJNI_GetDefaultJavaVMInitArgs);
            if (fnJNI_GetDefaultJavaVMInitArgs == NULL) {
                return -1;
            }
            fnJNI_CreateJavaVM = (lpJNI_CreateJavaVM)GetProcAddress(hjvm, szJNI_CreateJavaVM);
            if (fnJNI_CreateJavaVM == NULL) {
                return -2;
            }
            fnJNI_GetCreatedJavaVMs = (lpJNI_GetCreatedJavaVMs)GetProcAddress(hjvm, szJNI_GetCreatedJavaVMs);
            if (fnJNI_GetCreatedJavaVMs == NULL) {
                return -4;
            }
        }
        else {
            return -64;
        }
    }
    else {
        return -128;
    }
    return 0;
}

/*
 *  JavaVM Libraryをアンロードする
 *  param   : 無し
 *
 *  return  : int
 */
int JvmEnv::unloadJLib() {
    if (hjvm != NULL) {
        if (FreeLibrary(hjvm)) {
            return -128;
        }
        fnJNI_GetDefaultJavaVMInitArgs = NULL;
        fnJNI_CreateJavaVM = NULL;
        fnJNI_GetCreatedJavaVMs = NULL;
    }
    hjvm = NULL;
    return 0;
}

/*
 *  JavaVMを初期化する
 *  param   : 無し
 *
 *  return  : int
 */
int JvmEnv::createJvm() {
    JavaVMInitArgs  vm_args;

    vm_args.version = JNI_VERSION_1_6;
    fnJNI_GetDefaultJavaVMInitArgs(&vm_args);

    size_t array_len = (java_params.size() + 4) * sizeof(JavaVMOption);
    JavaVMOption *option_array = (JavaVMOption *)malloc(array_len);
    memset(option_array, 0, array_len);
    size_t pos = 0;
    for (pos = 0; pos < java_params.size(); pos++) {
        option_array[pos].optionString = _strdup((char *)_bstr_t(java_params.at(pos).c_str()));
    }
    option_array[pos++].optionString = _strdup((char *)_bstr_t(getClassPath().c_str()));
    option_array[pos].optionString = "vfprintf";
    option_array[pos++].extraInfo = (void *)jni_vfprintf;
    option_array[pos].optionString = "abort";
    option_array[pos++].extraInfo = (void *)jni_abort;
    option_array[pos].optionString = "exit";
    option_array[pos++].extraInfo = (void *)jni_exit;

    vm_args.version = JNI_VERSION_1_6;
    vm_args.options = option_array;
    vm_args.nOptions = (jint)(java_params.size() + 4);
    vm_args.ignoreUnrecognized = JNI_TRUE;

    int rc = fnJNI_CreateJavaVM(&jvm, (void**)&jni_env, &vm_args);
    for (size_t i = 0; i < java_params.size()+1; i++) {
        free(option_array[i].optionString);
    }
    free(option_array);
    if (rc != JNI_OK)
        return -128;
    return 0;
}

/*
 *  JavaVMを終了する
 *  param   : 無し
 *
 *  return  : int
 */
int JvmEnv::destroyJvm() {
    if (jvm != NULL) {
        if (jvm->DestroyJavaVM() != JNI_OK) {
            return -128;
        }
    }
    jvm = NULL;
    return 0;
}

/*
 *  JavaVMを取得する
 *  param   : 無し
 *
 *  return  : JavaVMポインター
 */
JavaVM *JvmEnv::getJvm() {
    return jvm;
}

/*
 *  JavaVM用パラメータを取得する
 *  param   : 無し
 *
 *  return  : jobjectArray
 */
jobjectArray JvmEnv::jvmArgs(JNIEnv* jni_env) {
    jclass clazz = jni_env->FindClass("java/lang/String");
    if (clazz == NULL) {
        return NULL;
    }

    size_t num = prog_params.size();
    jobjectArray ja = jni_env->NewObjectArray((jsize)num, clazz, NULL);
    
    for(size_t i = 0; i < num; i++) {
        String c_string = prog_params.at(i);
        _bstr_t value = _bstr_t((_TCHAR *)c_string.c_str());
        jstring j_string = jni_env->NewString((const jchar *)((wchar_t *)value), (jsize)value.length());
        jni_env->SetObjectArrayElement(ja, (jsize)i, j_string);
    }
    return ja;
}

/*
 *  実行プログラム名を取得する
 *  param   : 無し
 *
 *  return  : String
 */
String JvmEnv::getCallerName() {
    return caller_name;
}

/*
 *  クラスパスを追加する
 *  param   : クラスパス(String)
 *
 *  return  : void
 */
void JvmEnv::addClassPath(String path, String file) {
    if (file.empty())
        class_path.push_back(path);
    else {
        String full_path = path;
        full_path.append(_T("\\"));
        full_path.append(file);
        class_path.push_back(full_path);
    }
}

/*
 *  クラスパスを取得する
 *  param   : 無し
 *
 *  return  : String
 */
String JvmEnv::getClassPath() {
    String path;
    if (!class_path.empty()) {
        path = String(_T("-Djava.class.path="));
        for (size_t i = 0; i < class_path.size(); i++) {
            if (i > 0)
                path.append(_T(";"));
            path.append(class_path.at(i));
        }
    }
    return path;
}

/*
 *  導入済みのJava情報を取得する
 *  param   : 確認するJavaのタイプ(int)
 *
 *  return  : string_map
 */
string_map JvmEnv::installedJvm(int type) {
    string_map      result;
    string_array    vers;

    unsigned long buffSize = BUFF_SIZE;
    HKEY hkey = NULL;
    HKEY hVKey = NULL;
    FILETIME ft;
    String subkey = JAVA_ROOT;

    int rc;
    if ((rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, subkey.c_str(), 0, KEY_READ, &hkey)) == ERROR_SUCCESS) {
        RegCloseKey(hkey);
        switch ((int)(type&0x0c)) {
            case JDK:
                subkey.append(JDK_PATH);
                break;
            case JRE:
                subkey.append(JRE_PATH);
                break;
        }
        if ((rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, subkey.c_str(), 0, KEY_READ, &hkey)) == ERROR_SUCCESS) {
            String key = CURRENT_VERSION;
            String value = getRegValue(hkey, key, 0);
            result.insert(string_pair(key, value));
            _TCHAR version[BUFF_SIZE];
            for (int i = 0; ; i++) {
                buffSize = BUFF_SIZE;
                memset(version, BUFF_SIZE, sizeof(_TCHAR));
                rc = RegEnumKeyEx(hkey, i, version, &buffSize, NULL, NULL, NULL, &ft);
                if (rc != ERROR_SUCCESS) {
                   break;
                }
                vers.push_back(String((_TCHAR *)version));
            }
            if (!vers.empty()) {
                switch (type&0x03) {
                    case JavaHome:
                        for (size_t i = 0; i < vers.size(); i++) {
                            key = vers.at(i);
                            if ((rc = RegOpenKeyEx(hkey, key.c_str(), 0, KEY_READ, &hVKey)) == ERROR_SUCCESS) {
                                value = getRegValue(hVKey, String(_T("JavaHome")), 0);
                                result.insert(string_pair(key, value));
                                RegCloseKey(hVKey);
                            }
                        }
                        break;
                    case RuntimeLib:
                        for (size_t i = 0; i < vers.size(); i++) {
                            key = vers.at(i);
                            if ((rc = RegOpenKeyEx(hkey, key.c_str(), 0, KEY_READ, &hVKey)) == ERROR_SUCCESS) {
                                value = getRegValue(hVKey, String(_T("RuntimeLib")), 0);
                                result.insert(string_pair(key, value));
                                RegCloseKey(hVKey);
                            }
                        }
                        break;
                }
            }
            RegCloseKey(hkey);
        }
    }
    return result;
}

/*
 *  JNIのvfprintf処理にユーザ処理を加えるルーチンを登録します
 *  param   : ユーザ処理ルーチン(PrintRoutineアドレス)
 *
 *  return  : 無し
 */
void JvmEnv::setPrintRoutine(lpPrintRoutine routine) {
    print_routine = routine;
}

/*
 *  JNIのabort処理にユーザ処理を加えるルーチンを登録します
 *  param   : ユーザ処理ルーチン(PrintRoutineアドレス)
 *
 *  return  : 無し
 */
void JvmEnv::setAbortRoutine(lpAbortRoutine routine) {
    abort_routine = routine;
}

/*
 *  JNIのexit処理にユーザ処理を加えるルーチンを登録します
 *  param   : ユーザ処理ルーチン(ExitRoutineアドレス)
 *
 *  return  : 無し
 */
void JvmEnv::setExitRoutine(lpExitRoutine routine) {
    exit_routine = routine;
}

/*
 *  導入済みのJava情報から指定のパス情報を取得する
 *  param   : 確認するJavaのタイプ(int)
 *            取得したい情報(String)
 *
 *  return  : String
 */
String JvmEnv::findJvm(int type, bool version, String basic) {
    String      result;

    string_map  installed = installedJvm(type&0x0f);
    psmap       item = installed.end();
    switch (type&0xf0) {
        case CurrentVersion:
            item = installed.find(CURRENT_VERSION);
            if (item != installed.end()) {
                if (version) {
                    result = item->second;
                }
                else {
                    item = installed.find(item->second);
                    if (item != installed.end())
                        result = item->second;
                }
            }
            break;
        case TargetVersion:
            for (psmap ent = installed.begin(); ent != installed.end(); ent++) {
                if (ent->first == basic) {
                    if (version) {
                        result = item->first;
                    }
                    else {
                        result = item->second;
                    }
                }
            }
            break;
        case LatestVersion:
            for (psmap ent = installed.begin(); ent != installed.end(); ent++) {
                String subkey = ent->first;
                if (subkey.compare(CURRENT_VERSION) == 0) {
                    continue;
                }
                if (!basic.empty()) {
                    if (subkey.compare(0, basic.length(), basic) != 0) {
                        continue;
                    }
                }
                if (item == installed.end()) {
                    item = ent;
                }
                else {
                    if (subkey.compare(item->first) > 0) {
                        item = ent;
                    }
                }
            }
            if (version) {
                result = item->first;
            }
            else {
                result = item->second;
            }
            break;
    }
    return result;
}

JvmServiceクラスで実際にJavaのプログラムを呼び出します。
単にプログラムを呼び出して実行するだけじゃなくって、実行結果として数値(int)と文字列を取得できるように構築しました。
JvmService.h

#ifndef _JVM_SERVICE_CLASS
#define _JVM_SERVICE_CLASS

class JvmService {
private:
    String  jniClassPath(String original);

public:
    JvmService(JvmEnv jvm_env);
    JvmService(const JvmService& from);
    ~JvmService();

    void    setCallClass(String main_class, String package = String());
    String  getCallClass();
    int     execute();
    int     end_wait(int wait_time = INFINITE);
    void    result();

    void    setReturnCodeName(String name);
    int     getReturnCode();
    void    setReturnMessageName(String name);
    String  getReturnMessage();

    static void WINAPI startApp(JvmService *svc);

private:
    JvmEnv  jvm_env;

    String  main_class;
    HANDLE  java_thread;

    String  rc_field;
    int     rc;
    String  rm_field;
    String  rm;
};  //  class JvmService

#endif  //  _JVM_SERVICE_CLASS

JvmService.cpp

#include "jvmenv.h"
#include "jvmservice.h"

/*
 * パス分離記号の"."を"/"に変換する
 *  param   : パス(String)
 *
 *  return  : String
 */
String JvmService::jniClassPath(String original) {
    String path = original;
    size_t pos = path.find(_T('.'));
    do {
        if (pos != String::npos) {
            path.replace(pos++, 1, _T("/"));
            pos = path.find(_T('.'), pos);
        }
    } while (pos != String::npos);
    return path;
}

//  Constructer
JvmService::JvmService(JvmEnv jvm_env) {
    this->jvm_env = jvm_env;
    this->java_thread = NULL;
    this->rc = 0;
}

//  Copy Constructer
JvmService::JvmService(const JvmService& from) {
    jvm_env = from.jvm_env;
    main_class = from.main_class;
    java_thread = from.java_thread;
    rc_field = from.rc_field;
    rc = from.rc;
    rm_field = from.rm_field;
    rm = from.rm;
}

//  Destructer
JvmService::~JvmService() {
}

/*
 *  起動するJavaのクラスを設定する
 *  param   : クラス名(String)
 *            パッケージ名(String)
 *
 *  return  : 無し
 */
void JvmService::setCallClass(String class_name, String package) {
    if (package.empty()) {
        main_class = class_name;
    }
    else {
        main_class = package;
        main_class.append(_T("."));
        main_class.append(class_name);
    }
}

/*
 *  起動するJavaのクラスを取得する
 *  param   : クラス名(String)
 *            パッケージ名(String)
 *
 *  return  : 無し
 */
String JvmService::getCallClass() {
    return jniClassPath(main_class);
}

/*
 *  設定したJavaのプログラムを起動する
 *  param   : 無し
 *
 *  return  : int
 */
int JvmService::execute() {
    java_thread = CreateThread(NULL, 4096, (LPTHREAD_START_ROUTINE)JvmService::startApp, (void *)this, 0, NULL);
    if (java_thread != NULL) {
        WaitForSingleObject(java_thread, 0);
        return 0;
    }
    return -1;
}

/*
 *  Javaプログラムの終了を待つ
 *  param   : 待ち時間-秒(int)
 *
 *  return  : int
 */
int JvmService::end_wait(int wait_time) {
    unsigned long rc = 0;
    if (wait_time >= 0)
        rc = WaitForSingleObject(java_thread, wait_time*1000);
    else
        rc = WaitForSingleObject(java_thread, INFINITE);
    if (rc != WAIT_TIMEOUT) {
        CloseHandle(java_thread);
        return 0;
    }
    return -1;
}

/*
 *  Javaの処理結果を取得する
 *  param   : 無し
 *
 *  return  : なし
 */
void JvmService::result() {
    JNIEnv              *t_env;
    JavaVM              *vm = jvm_env.getJvm();

    if (vm->AttachCurrentThread((void**)&t_env, NULL) == JNI_OK) {
        jclass clazz = t_env->FindClass((const char *)_bstr_t((_TCHAR *)getCallClass().c_str()));
        if (clazz != NULL) {
            _bstr_t rc_str = _bstr_t((_TCHAR *)rc_field.c_str());
            const char *rc_name = (const char *)rc_str;
            jfieldID rc_area = t_env->GetStaticFieldID(clazz, rc_name, "I");
            if (t_env->ExceptionCheck() == JNI_TRUE) {
                if (t_env->ExceptionOccurred() != NULL) {
                    t_env->ExceptionClear();
                }
            }
            else {
                if (rc_area != NULL) {
                    rc = (int)t_env->GetStaticIntField(clazz, rc_area);
                }
            }
           _bstr_t rm_str = _bstr_t((_TCHAR *)rm_field.c_str());
           const char *rm_name = (const char *)rm_str;
            jfieldID rm_area = t_env->GetStaticFieldID(clazz, rm_name, "Ljava/lang/String;");
            if (t_env->ExceptionCheck() == JNI_TRUE) {
                if (t_env->ExceptionOccurred() != NULL) {
                    t_env->ExceptionClear();
                }
            }
            else {
                if (rm_area != NULL) {
                    jstring msg = (jstring)t_env->GetStaticObjectField(clazz, rm_area);
                    const jchar *words = t_env->GetStringChars(msg, NULL);
                    _bstr_t orginal = _bstr_t((wchar_t *)words);
                    t_env->ReleaseStringChars(msg, words);
                    rm = String((_TCHAR *)orginal);
                }
            }
        }
        vm->DetachCurrentThread();
    }
}

/*
 *  Javaの結果コードを取得するエリアの名前を設定する
 *  param   : エリアの名前(String)
 *
 *  return  : 無し
 */
void JvmService::setReturnCodeName(String name) {
    rc_field = name;
}

/*
 *  Javaの結果コードを取得する
 *  param   : 無し
 *
 *  return  : int
 */
int JvmService::getReturnCode() {
    return rc;
}

/*
 *  Javaの結果メッセージを取得するエリアの名前を設定する
 *  param   : エリアの名前(String)
 *
 *  return  : 無し
 */
void JvmService::setReturnMessageName(String name) {
    rm_field = name;
}

/*
 *  Javaの結果メッセージを取得する
 *  param   : 無し
 *
 *  return  : String
 */
String JvmService::getReturnMessage() {
    return rm;
}

/*
 *  Javaを呼び出す
 *  param   : 起動時に利用する情報(JvmServiceクラス)
 *
 *  return  : unsigned long
 */
void WINAPI JvmService::startApp(JvmService *svc) {
    JNIEnv              *t_env;
    JavaVM              *vm = svc->jvm_env.getJvm();

    if (vm->AttachCurrentThread((void**)&t_env, NULL) == JNI_OK) {
        jclass clazz = t_env->FindClass((const char *)_bstr_t((_TCHAR *)svc->getCallClass().c_str()));
        if (clazz != NULL) {
            jmethodID mid = t_env->GetStaticMethodID(clazz, "main", "([Ljava/lang/String;)V");
            if (mid != NULL) {
                jobjectArray ja = svc->jvm_env.jvmArgs(t_env);
                jthrowable tobj;
                t_env->CallStaticVoidMethod(clazz, mid, ja);
                if (t_env->ExceptionCheck() == JNI_TRUE) {
                    if ((tobj = t_env->ExceptionOccurred()) != NULL) {
                        t_env->ExceptionDescribe();
                        t_env->ExceptionClear();
                    }
                }
            }
        }
        vm->DetachCurrentThread();
    }
}

サンプルとして、ネットワークインターフェースの情報を取得するプログラムをこのクラスを使って起動するアプリケーションを作りました。
jnicall.cpp

#include <windows.h>
#include <tchar.h>

#include <iostream>
#include <locale>

#include <jvmenv.h>
#include <jvmservice.h>

int _tmain(int argc, _TCHAR* argv[]) {
	std::wcout.imbue(std::locale("japanese"));

	JvmEnv env;
	env.loadArgs(argc, argv);
	env.addJavaParam(String(_T("-Xms8m")));
	env.addJavaParam(String(_T("-Xms16m")));
	env.addJavaParam(String(_T("-client")));
	env.addJavaParam(String(_T("-Djava.compiler=NONE")));

	String latest = env.findJvm(JRERuntimeLib+LatestVersion, false);
	if (env.loadJLib(latest) == 0) {
		env.addClassPath(_T("c:\\java\\net\\classes"));
		if (env.createJvm() == 0) {
			JvmService service = JvmService(env);
			service.setCallClass(_T("IfInfoTest"), _T("net.test"));
			service.execute();
			service.end_wait();
			service.result();
			std::wcout << _T("Execute result ") << service.getReturnCode() << _T(":") << service.getReturnMessage() << std::endl;
			env.destroyJvm();
		}
		env.unloadJLib();
	}

	return 0;
}

結局サンプルプログラムがコンソールアプリケーションなのでちょっと変な感じですが、この部分はWindowsアプリケーションとして作ることも可能です。