diff -r 0fd27995241b -r 9ac0a0a7da70 javaruntimes/starterutils/src.linux/jvmstarterjni.cpp --- a/javaruntimes/starterutils/src.linux/jvmstarterjni.cpp Tue May 11 16:07:20 2010 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,447 +0,0 @@ -/* -* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -* All rights reserved. -* This component and the accompanying materials are made available -* under the terms of "Eclipse Public License v1.0" -* which accompanies this distribution, and is available -* at the URL "http://www.eclipse.org/legal/epl-v10.html". -* -* Initial Contributors: -* Nokia Corporation - initial contribution. -* -* Contributors: -* -* Description: This class is meant for starting the Linux JVM. -* -*/ - -#include -#include - -#include "jvmstarterjni.h" - -#include "jvmargsmodifier.h" - -#include "runtimeexception.h" -#include "logger.h" -#include "javaoslayer.h" -#include "dynamiclibloader.h" -#include "javacommonutils.h" - -using namespace java::runtime; -using namespace java::util; - -extern const wchar_t CLASS_PATH_SEPARATOR = L':'; -extern const char PATH_SEPARATOR_FROM = '\\'; -extern const char PATH_SEPARATOR_TO = '/'; - -JvmStarter* -JvmStarter::getJvmStarterInstance(const Configuration configuration, - const std::wstring& indetifier) -{ - JELOG2(EJavaRuntime); - return new JvmStarterJni(configuration, indetifier); -} - -JvmStarter* -JvmStarter::getJvmStarterInstance() -{ - JELOG2(EJavaRuntime); - return new JvmStarterJni(); -} - -JvmStarterJni::JvmStarterJni() -{ - JELOG2(EJavaRuntime); -} - -JvmStarterJni::JvmStarterJni(const Configuration configuration, - const std::wstring& indetifier) -{ - JELOG2(EJavaRuntime); - mConfiguration = configuration; - mIdentifier = indetifier; - - // In Linux the binary root varies depending on the user. - std::string rootStr; - JavaOsLayer::getResRoot(rootStr, false); - rootStr += "jsr/classes/common/"; - mExtensionPath.assign(rootStr.begin(), rootStr.end()); -} - - -JvmStarterJni::~JvmStarterJni() -{ - JELOG2(EJavaRuntime); -} - -void JvmStarterJni::overrideOldHeapSize(int /*heapSize*/) -{ - // Not supported by the JVM - JELOG2(EJavaRuntime); -} - -void JvmStarterJni::overrideNewHeapSize(int /*heapSize*/) -{ - // Not supported by the JVM - JELOG2(EJavaRuntime); -} - -void JvmStarterJni::overrideNativeStackSize(int /*stackSize*/) -{ - // Not supported by the JVM - JELOG2(EJavaRuntime); -} - -void JvmStarterJni::overrideJavaStackSize(int stackSize) -{ - JELOG2(EJavaRuntime); - std::wstring stackSizeStr = L"-Xss"; - stackSizeStr += JavaCommonUtils::intToWstring(stackSize); - stackSizeStr += L"K"; - mJvmArgs.push_back(stackSizeStr); -} - -int JvmStarterJni::startJvm() -{ - JELOG2(EJavaRuntime); - - // Set mJvmArgs container to contain all the JVM args and set mAppAndArgs - // to contain the main class and the arguments. - completeArgumentContainers(); - - // Give arguments to modifyJvmArguments for modification. Args - // are modified if the default empty implementation has been overridden - // by eclipsing the modifyJvmArguments dll. - modifyJvmArguments(mIdentifier, mJvmArgs, mAppAndArgs); - - // Allocate space for the raw JVM args. - int rawJvmArgumentCount = mJvmArgs.size(); - ScopedCharPointerArray rawJvmArgs(rawJvmArgumentCount); - - // Adding the JVM args. Main class and applcation arguments are handled - // later. - int ind = 0; - for (JvmArgs_t::iterator jvmArgsIter = mJvmArgs.begin(); - jvmArgsIter!= mJvmArgs.end(); - ++jvmArgsIter) - { - // Do character conversion while adding the arguments. - rawJvmArgs.get()[ind++] = JavaCommonUtils::wstringToUtf8(*jvmArgsIter); - } - return startJvmInSeparateThread(rawJvmArgumentCount, rawJvmArgs.get()); -} - -int JvmStarterJni::startJvm(int argc, char** argv) -{ - JELOG2(EJavaRuntime); - // Allocate space for the raw JVM args. This will contain only - // JVM arguments. Main class and application arguments are handled - // differently. - ScopedCharPointerArray rawJvmArgs(argc); - - // Assuming that in the beginning of the list there are JVM arguments and - // they start with '-'. - bool handlingArguments = true; - - int argCount = 0; - for (int i = 0; i < argc; i++) - { - if (argv[i][0] != '-') // codescanner::accessArrayElementWithoutCheck2 - { - // First non JVM argument was found. - handlingArguments = false; - } - if (handlingArguments) - { - if ((strcmp(argv[i], "-cp") == 0 || // codescanner::accessArrayElementWithoutCheck2 - strcmp(argv[i], "-classpath") == 0) && // codescanner::accessArrayElementWithoutCheck2 - (i + 1) < argc) - { - // There is class path available. - std::string cp("-Djava.class.path="); - cp += argv[i+1]; - i++; - rawJvmArgs.get()[argCount] = strdup(cp.c_str()); - } - else - { - // Normal JVM argument. - rawJvmArgs.get()[argCount] = strdup(argv[i]); // codescanner::accessArrayElementWithoutCheck2 - } - argCount++; - } - else - { - // The first non JVM argument can be considered as main class. - // The rest of the arguments are arguments for the Java app. - mAppAndArgs.push_back(JavaCommonUtils::utf8ToWstring(argv[i])); // codescanner::accessArrayElementWithoutCheck2 - } - } - return startJvmInSeparateThread(argCount, rawJvmArgs.get()); -} - - -void* JvmStarterJni::javaThreadMain(void* arg) -{ - JELOG2(EJavaRuntime); - int result = -1; - JvmStarterJni* jniStarter = (reinterpret_cast(arg)); - try - { - result = jniStarter->startJvmImpl(); - } - catch (RuntimeException& e) - { - ELOG1(EJavaRuntime, "JvmStarterJni::javaThreadMain() RuntimeException " - "catched in VM thread. %s", e.toString().c_str()); - } - catch (java::util::ExceptionBase& e) - { - ELOG1(EJavaRuntime, "JvmStarterJni::javaThreadMain() ExceptionBase " - "catched in VM thread. %s", e.toString().c_str()); - } - catch (std::exception& e) - { - ELOG1(EJavaRuntime, "JvmStarterJni::javaThreadMain() std::Exception " - "catched in VM thread. %s", e.what()); - } - return reinterpret_cast(result); -} - -int JvmStarterJni::startJvmInSeparateThread(int argc, char** argv) -{ - JELOG2(EJavaRuntime); - - // Store the argc and argv into member variables in order be avaliable - // for the JVM starter thread. - mArgCount = argc; - mArgs = argv; - // return startJvmImpl(); This could be used to start the JVM into same - // thread. - pthread_t threadId; - void* result; - - // Create the JVM thread. - pthread_create(&threadId, 0, javaThreadMain, this); - - // Wait until the thread has died. - pthread_join(threadId, &result); - return reinterpret_cast(result); -} - - -int JvmStarterJni::startJvmImpl() -{ - JELOG2(EJavaRuntime); - - JavaVM* jvm; // Denotes a Java VM. - JNIEnv* env; // Pointer to native method interface. - JavaVMInitArgs vmArgs; // VM initialization arguments. - JavaVMOption vmOption; - vmOption.extraInfo = 0; - - LOG(EJavaRuntime, EInfo, "VM args:"); - JvmOptionArgs_t jvmOptions; - for (int i = 0; i < mArgCount; i++) - { - vmOption.optionString = mArgs[i]; - jvmOptions.push_back(vmOption); - LOG1(EJavaRuntime, EInfo, " %s",mArgs[i]); // codescanner::accessArrayElementWithoutCheck2 - } - vmArgs.version = JNI_VERSION_1_4; - - // Initializing JavaVMInitArgs. - // Contiguity for std::vector is mandated by the standard as long - // as T is not bool. [See 23.2.4./1]. - vmArgs.options = &((jvmOptions)[0]); // codescanner::accessArrayElementWithoutCheck2 - vmArgs.nOptions = jvmOptions.size(); - vmArgs.ignoreUnrecognized = JNI_FALSE; - - JavaOsLayer::startUpTrace("Starting VM()", -1, -1); - - // Creating the JVM. - int res = JNI_CreateJavaVM(&jvm, reinterpret_cast(&env), &vmArgs); - LOG1(EJavaRuntime, EInfo, "JNI_CreateJavaVM() returned. st = %d", res); - if (res == 0) - { - // Converting the '.' to '/' in the main class - // (com.nokia.Foo -> com/nokia/Foo) - std::wstring& appMain = mAppAndArgs.front(); - std::replace(appMain.begin(), appMain.end(), '.', '/'); - - // Convert the main class to UTF-8. - ScopedCharPointer main(JavaCommonUtils::wstringToUtf8(appMain)); - - // Find the main class. - jclass mainClass = env->FindClass(main.get()); - LOG2(EJavaRuntime, EInfo, " mainClass (%s): %p", main.get(), mainClass); - if (mainClass != 0) - { - // Find method static void main(String[] args) from the main class. - jmethodID mainMethod = env->GetStaticMethodID(mainClass, "main", - "([Ljava/lang/String;)V"); - LOG1(EJavaRuntime, EInfo, " mainMethod: %p", mainMethod); - if (mainMethod != 0) - { - // Call the method static void main(). - env->CallStaticVoidMethod(mainClass, mainMethod, - getApplicationArguments(env)); - LOG(EJavaRuntime, EInfo, " CallStaticVoidMethod returned"); - } - else - { - std::string errorStr("Not able to find main() method."); - throw RuntimeException(errorStr, - __FILE__, __FUNCTION__, __LINE__); - } - } - else - { - std::string errorStr("Main class was not found."); - throw RuntimeException(errorStr, __FILE__, __FUNCTION__, __LINE__); - } - jvm->DestroyJavaVM(); - } - else - { - std::string errorStr("JNI_CreateJavaVM failed. Reason = ."); - errorStr += JavaCommonUtils::intToString(res); - throw RuntimeException(errorStr, __FILE__, __FUNCTION__, __LINE__); - } - return res; -} - - -void JvmStarterJni::completeArgumentContainers() -{ - JELOG2(EJavaRuntime); - - // Set the used porting layer. - mJvmArgs.push_back(L"-Dcom.nokia.jvm.port=sun.JvmPortJ2se"); - - // Disable JIT, if requested. - if (mJitDisabled) - { - mJvmArgs.push_back(L"-Xint"); - } - - // Add the classpath. - if (mClassPath.length() > 0) - { - mClassPath.insert(0, L"-Djava.class.path="); - mJvmArgs.push_front(mClassPath); - LOG1(EJavaRuntime, EInfo, " mClassPath = %S", mClassPath.c_str()); - } - - // Add the extension classpath. - if (mExtensionPath.length() > 0) - { - mExtensionPath.insert(0, L"-Djava.ext.dirs="); - mJvmArgs.push_front(mExtensionPath); - LOG1(EJavaRuntime, EInfo, " mExtensionPath = %S", - mExtensionPath.c_str()); - } - - // Add the prepending boot classpath if set. - if (mBootClassPathPrepend.length() > 0) - { - std::wstring bcpp(L"-Xbootclasspath/p:"); - bcpp += mBootClassPathPrepend; - mJvmArgs.push_front(bcpp); - LOG1(EJavaRuntime, EInfo, " bcpp = %S", bcpp.c_str()); - } - - // Add the appending boot classpath if set. - if (mBootClassPathAppend.length() > 0) - { - std::wstring bcpa(L"-Xbootclasspath/a:"); - bcpa += mBootClassPathAppend; - mJvmArgs.push_front(bcpa); - LOG1(EJavaRuntime, EInfo, " bcpa = %S", bcpa.c_str()); - } - - std::wstring javaBinRoot; - std::string binRoot; - JavaOsLayer::getBinRoot(binRoot, false); - javaBinRoot.assign(binRoot.begin(), binRoot.end()); - - // Setting the java.library.path. - std::wstring jlp(L"-Djava.library.path="); - jlp += javaBinRoot; - jlp += L"lib"; - mJvmArgs.push_front(jlp); - LOG1(EJavaRuntime, EInfo, " jlp = %S", jlp.c_str()); - - // Setting the java.home. - std::wstring jh = L"-Djava.home="; - const char* javaHome = getenv("JAVA_VM_HOME"); - if (javaHome == 0) - { - throw RuntimeException("JAVA_VM_HOME not defined", - __FILE__, __FUNCTION__, __LINE__); - } - std::string jhs(javaHome); - jh.append(jhs.begin(), jhs.end()); - mJvmArgs.push_front(jh); - LOG1(EJavaRuntime, EInfo, " jh = %S", jh.c_str()); - - // Define emma.properties to point to emma.properties file - // which is used when Java code coverage is measured. - std::wstring emma(L"-Demma.properties="); - emma += javaBinRoot; - emma += L"emma.properties"; - mJvmArgs.push_front(emma); - LOG1(EJavaRuntime, EInfo, " emma = %S", emma.c_str()); - - // Add the main class. - mAppAndArgs.push_front(mMainClass); - LOG1(EJavaRuntime, EInfo, " mMainClass = %S", mMainClass.c_str()); -} - -jobjectArray JvmStarterJni::getApplicationArguments(JNIEnv* env) -{ - JELOG2(EJavaRuntime); - // When using JNI_CreateJavaVM to start the JVM the arguments for the - // Java application must be handled so that a jobjectArray is created - // to contain Java Strings created using jni APIs. - - if (env == 0) - { - throw RuntimeException("JNIEnv was null", - __FILE__, __FUNCTION__, __LINE__); - } - - // Create the jobjectArray. mAppAndArgs container contains the main - // class which must be taken into account. - jobjectArray array = - (jobjectArray)env->NewObjectArray(mAppAndArgs.size() - 1, - env->FindClass("java/lang/String"), - env->NewStringUTF("")); - LOG(EJavaRuntime, EInfo, " Application arguments:"); - if (array != 0) - { - JvmArgs_t::iterator appAndArgsIter = mAppAndArgs.begin(); - // Skip the main class. - ++appAndArgsIter; - - int i = 0; - - // Fill the object array with application arguments. - for (; appAndArgsIter!= mAppAndArgs.end(); ++appAndArgsIter) - { - ScopedCharPointer appArg(JavaCommonUtils::wstringToUtf8(*appAndArgsIter)); - LOG1(EJavaRuntime, EInfo, " %s", appArg.get()); - env->SetObjectArrayElement(array, i++, - env->NewStringUTF(appArg.get())); - } - } - else - { - throw RuntimeException("jobjectArray was null", - __FILE__, __FUNCTION__, __LINE__); - } - return array; -} - -