Skip to content

Commit

Permalink
dev complete
Browse files Browse the repository at this point in the history
  • Loading branch information
vintagewang committed Jun 10, 2012
1 parent 700515a commit b05912e
Show file tree
Hide file tree
Showing 6 changed files with 244 additions and 10 deletions.
41 changes: 36 additions & 5 deletions src/JWUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,6 @@
#include <unistd.h>
#endif

#ifdef WIN32
#define FILE_SEPARATOR "\\"
#else
#define FILE_SEPARATOR "/"
#endif

namespace JWUtil
{
Expand Down Expand Up @@ -117,4 +112,40 @@ namespace JWUtil
}
}
}

void addLibPath(const char* path)
{
assert(NULL != path);

#if defined(WIN32)
const char* libPath = "PATH";
#elif defined(AIX)
const char* libPath = "LIBPATH";
#elif defined(HPUX)
const char* libPath = "SHLIB_PATH";
#else
const char* libPath = "LD_LIBRARY_PATH";
#endif
const char* envLibPath = getenv(libPath);
std::string pathValue = path;
pathValue += PATH_SEPARATOR;
pathValue += (envLibPath != NULL) ? envLibPath : "";
setEnv(libPath, pathValue.c_str());
}

std::string getLibPath()
{
#if defined(WIN32)
const char* libPath = "PATH";
#elif defined(AIX)
const char* libPath = "LIBPATH";
#elif defined(HPUX)
const char* libPath = "SHLIB_PATH";
#else
const char* libPath = "LD_LIBRARY_PATH";
#endif
const char* envLibPath = getenv(libPath);

return (envLibPath != NULL) ? envLibPath : "";
}
}
12 changes: 12 additions & 0 deletions src/JWUtil.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@
#define _JW_JWUTIL_H__
#include <string>

#ifdef WIN32
#define FILE_SEPARATOR "\\"
#define PATH_SEPARATOR ";"
#else
#define FILE_SEPARATOR "/"
#define PATH_SEPARATOR ":"
#endif

namespace JWUtil
{
/**
Expand All @@ -43,6 +51,10 @@ namespace JWUtil
* 字符串替换
*/
void replaceAll(std::string& source, const char* oldString, const char* newString);

void addLibPath(const char* path);

std::string getLibPath();
};

#endif // end of _JW_JWUTIL_H__
87 changes: 87 additions & 0 deletions src/JavaConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
#include "JavaConfig.h"
#include "JWUtil.h"
#include "JavaLauncher.h"
#include <string>
#include <stdio.h>
#include <stdlib.h>
Expand Down Expand Up @@ -122,6 +123,13 @@ bool JavaConfig::load()
return false;
}

// 加载LIBPATH
JWUtil::addLibPath(".");
JWUtil::addLibPath(JWUtil::getCurrentExeFileDir().c_str());
JWUtil::addLibPath((this->javaHome + "/jre/bin").c_str());



return true;
}

Expand Down Expand Up @@ -276,3 +284,82 @@ std::string JavaConfig::getJVMDllPath()

return result;
}

std::string JavaConfig::getMainClass()
{
std::string retString = this->mainClass;
std::replace(retString.begin(), retString.end(), '.', '/');
return retString;
}

void JavaConfig::buildJavaVMInitArgs(JavaVMInitArgs& args)
{
int index = 0;

OptionTable table;
this->buildNewOptionTable(table);

// 为JavaVMInitArgs分配内存
args.nOptions = static_cast<jint>(table.size() + 2);
args.options = new JavaVMOption[args.nOptions];

// 设置JavaVMInitArgs
args.version = JNI_VERSION_1_2;
args.ignoreUnrecognized = JNI_FALSE;

printLog("JavaVMInitArgs:");
printLog(" version 0x%08x", args.version);
printLog(" ignoreUnrecognized is %s", args.ignoreUnrecognized ? "JNI_TRUE" : "JNI_FALSE");
printLog(" nOptions is %d", args.nOptions);

OptionTable::const_iterator it = table.begin();
for(index = 0; it != table.end(); it++, index++) {
std::string optString = it->first + (it->second.length() > 0 ? "=" + it->second : "");

char *key = new char[optString.length() + 1];
memset(key, 0, optString.length() + 1);
sprintf(key, "%s", optString.c_str());
args.options[index].optionString = key;
args.options[index].extraInfo = NULL;
printLog("\toption[%2d] = '%s'", index, args.options[index].optionString);
}

{
char *key = new char[32];
memset(key, 0, 32);
strcpy(key, "exit");
args.options[index].optionString = key;
args.options[index].extraInfo = (void*) JavaLauncher::exitHandler;
printLog("\toption[%2d] = '%s'(JNI Invocation API JVM exit hook)", index, args.options[index].optionString);
}

{
index++;
char *key = new char[32];
memset(key, 0, 32);
strcpy(key, "abort");
args.options[index].optionString = key;
args.options[index].extraInfo = (void*) JavaLauncher::abortHandler;
printLog("\toption[%2d] = '%s'(JNI Invocation API JVM abort hook)", index, args.options[index].optionString);
}

}

void JavaConfig::buildNewOptionTable(OptionTable& table)
{
table = this->optionTable;

OptionTable::iterator it = this->propertyTable.begin();
for(; it != this->propertyTable.end(); it++) {
this->optionTable["-D" + it->first] = it->second;
}

// -Djava.class.path
std::string javaClassPath = table["-Djava.class.path"];
for(std::size_t i = 0; i < this->classPathList.size(); i++) {
javaClassPath += this->classPathList[i];
javaClassPath += PATH_SEPARATOR;
}

table["-Djava.class.path"] = javaClassPath;
}
6 changes: 6 additions & 0 deletions src/JavaConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <string>
#include <map>
#include <vector>
#include <jni.h>

typedef std::vector<std::string> ClassPathList;
typedef std::vector<std::string> OptionList;
Expand Down Expand Up @@ -54,7 +55,12 @@ class JavaConfig

std::string getJVMDllPath();

std::string getMainClass();

void buildJavaVMInitArgs(JavaVMInitArgs& args);

private:
void buildNewOptionTable(OptionTable& table);
static std::string getConfigFile();
static bool expandMacro(std::string& value);
};
Expand Down
99 changes: 94 additions & 5 deletions src/JavaLauncher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@
#define NULL_CHECK0(e) if ((e) == 0) return 0
#define NULL_CHECK(e) if ((e) == 0) return

JavaLauncher::JavaLauncher()
JavaLauncher::JavaLauncher() : exitCode(0)
, abortCode(0)
, exited(false)
, aborted(false)
{
}

Expand All @@ -43,28 +46,85 @@ int JavaLauncher::launchJavaApp(int argc, char** argv)
DLL jvmDll(jvmPath.c_str());

// 3, 获取创建JVM的函数指针
typedef jint(JNICALL *CreateJVMFun)(JavaVM**, void**, void*);
typedef jint(JNICALL * CreateJVMFun)(JavaVM**, void**, void*);
CreateJVMFun createJVMFun = (CreateJVMFun)jvmDll.getFunction("JNI_CreateJavaJVM");
if(NULL == createJVMFun){
if(NULL == createJVMFun) {
fprintf(stderr, "Load JVM error %s\n", jvmPath.c_str());
return -1;
}
JavaConfig::getInstance()->printLog("Get JVM function OK.");

// 4, 创建JVM
JavaVMInitArgs jvmArgs;
JavaVM* javaVM;
JNIEnv* jniEnv;
JavaConfig::getInstance()->buildJavaVMInitArgs(jvmArgs);
jint code = (*createJVMFun)(&javaVM, (void**)&jniEnv, &jvmArgs);
if(code < 0) {
fprintf(stderr, "Create java jvm Failed.\n");
return -1;
}

JavaConfig::getInstance()->printLog("Create java jvm OK.");

// 5, 获取包含Main方法的类
jclass mainClass = jniEnv->FindClass(JavaConfig::getInstance()->getMainClass().c_str());
if(0 == mainClass) {
reportErrorMessage(jniEnv, "Find main class Failed.");
javaVM->DestroyJavaVM();
return -1;
}

JavaConfig::getInstance()->printLog("Find Main class OK.");

// 6, 创建包含Main方法的类
jobject mainObject = jniEnv->AllocObject(mainClass);
if(0 == mainClass) {
reportErrorMessage(jniEnv, "Create main class Failed.");
javaVM->DestroyJavaVM();
return -1;
}

JavaConfig::getInstance()->printLog("Create Main class OK.");

// 7, 获取Main函数的方法ID
jmethodID mainId = jniEnv->GetStaticMethodID(mainClass, "main", "([Ljava/lang/String;)V");
if(0 == mainId) {
reportErrorMessage(jniEnv, "Get main method id Failed.");
javaVM->DestroyJavaVM();
return -1;
}

JavaConfig::getInstance()->printLog("Get main method id OK.");

// 8, 调用Main函数
jobjectArray mainArgs = newPlatformStringArray(jniEnv, argv, argc);
jniEnv->CallStaticVoidMethod(mainClass, mainId, mainArgs);
reportErrorMessage(jniEnv);

// 9, 资源清理
javaVM->DetachCurrentThread();
javaVM->DestroyJavaVM();

if(this->exited) {
return this->exitCode;
} else if(this->aborted) {
return this->abortCode;
}

return 0;
}

void JavaLauncher::exitHandler(int code)
{

JavaLauncher::getInstance()->setExitCode(code);
JavaConfig::getInstance()->printLog("exitHandler %d", code);
}

void JavaLauncher::abortHandler(int code)
{

JavaLauncher::getInstance()->setAbortCode(code);
JavaConfig::getInstance()->printLog("abortHandler %d", code);
}

jobject JavaLauncher::newPlatformString(JNIEnv *env, char *s)
Expand Down Expand Up @@ -148,3 +208,32 @@ void JavaLauncher::reportErrorMessage(JNIEnv* env, const char* errorMsg /*= NULL
fprintf(stderr, "%s\n", errorMsg);
}
}

jobjectArray JavaLauncher::newPlatformStringArray(JNIEnv *env, char **strv, int strc)
{
jclass cls;
jobjectArray ary;
int i;

NULL_CHECK0(cls = env->FindClass("java/lang/String"));
NULL_CHECK0(ary = env->NewObjectArray(strc, cls, 0));
for(i = 0; i < strc; i++) {
jobject str = newPlatformString(env, *strv++);
NULL_CHECK0(str);
env->SetObjectArrayElement(ary, i, str);
env->DeleteLocalRef(str);
}
return ary;
}

void JavaLauncher::setExitCode(int code)
{
this->exited = true;
this->exitCode = code;
}

void JavaLauncher::setAbortCode(int code)
{
this->aborted = true;
this->abortCode = code;
}
9 changes: 9 additions & 0 deletions src/JavaLauncher.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,28 @@

class JavaLauncher
{
int exitCode;
int abortCode;

bool exited;
bool aborted;

public:
JavaLauncher();
~JavaLauncher();
static JavaLauncher* getInstance();

int launchJavaApp(int argc, char** argv);
void setExitCode(int code);
void setAbortCode(int code);
static void exitHandler(int code);
static void abortHandler(int code);

private:
static jobject newPlatformString(JNIEnv *env, char *s);
static jobject getPlatformEncoding(JNIEnv *env);
static jboolean isEncodingSupported(JNIEnv *env, jobject enc);
static jobjectArray newPlatformStringArray(JNIEnv *env, char **strv, int strc);
static void reportErrorMessage(JNIEnv* env, const char* errorMsg = NULL);
};

Expand Down

0 comments on commit b05912e

Please sign in to comment.