modules/jdk.packager/src/main/native/library/common/JavaVirtualMachine.cpp

Print this page

        

@@ -44,53 +44,38 @@
 
 #include "jni.h"
 
 #include <map>
 #include <list>
+#include <sstream>
 
 
-bool RunVM() {
+bool RunVM(JvmLaunchType type) {
     bool result = false;
     JavaVirtualMachine javavm;
 
-    if (javavm.StartJVM() == true) {
-        result = true;
+    switch (type){ 
+        case USER_APP_LAUNCH:
+            result = javavm.StartJVM();
+            break; 
+        case SINGLE_INSTANCE_NOTIFICATION_LAUNCH:
+            result = javavm.NotifySingleInstance();
+            break; 
     }
-    else {
+
+    if (!result) {
         Platform& platform = Platform::GetInstance();
         platform.ShowMessage(_T("Failed to launch JVM\n"));
     }
 
     return result;
 }
 
+JavaLibrary::JavaLibrary() : Library(), FCreateProc(NULL)  {
+}
 
-// Private typedef for function pointer casting
-#define LAUNCH_FUNC "JLI_Launch"
-typedef int (JNICALL *JVM_CREATE)(int argc, char ** argv,
-                                    int jargc, const char** jargv,
-                                    int appclassc, const char** appclassv,
-                                    const char* fullversion,
-                                    const char* dotversion,
-                                    const char* pname,
-                                    const char* lname,
-                                    jboolean javaargs,
-                                    jboolean cpwildcard,
-                                    jboolean javaw,
-                                    jint ergo);
-
-class JavaLibrary : public Library {
-    JVM_CREATE FCreateProc;
-
-    JavaLibrary(const TString &FileName);
-
-public:
-    JavaLibrary() : Library() {
-        FCreateProc = NULL;
-    }
-
-    bool JavaVMCreate(size_t argc, char *argv[]) {
+bool JavaLibrary::JavaVMCreate(size_t argc, char *argv[]) {
         if (FCreateProc == NULL) {
             FCreateProc = (JVM_CREATE)GetProcAddress(LAUNCH_FUNC);
         }
 
         if (FCreateProc == NULL) {

@@ -109,72 +94,58 @@
             "java",
             false,
             false,
             false,
             0) == 0;
-    }
-};
+}
 
 //--------------------------------------------------------------------------------------------------
 
-struct JavaOptionItem {
-    TString name;
-    TString value;
-    void* extraInfo;
-};
-
-
-class JavaOptions {
-private:
-    std::list<JavaOptionItem> FItems;
-    JavaVMOption* FOptions;
-
-public:
-    JavaOptions() {
-        FOptions = NULL;
-    }
+JavaOptions::JavaOptions(): FOptions(NULL) {
+}
 
-    ~JavaOptions() {
+JavaOptions::~JavaOptions() {
         if (FOptions != NULL) {
             for (unsigned int index = 0; index < GetCount(); index++) {
                 delete[] FOptions[index].optionString;
             }
 
             delete[] FOptions;
         }
-    }
+}
 
-    void AppendValue(const TString Key, TString Value, void* Extra) {
+void JavaOptions::AppendValue(const TString Key, TString Value, void* Extra) {
         JavaOptionItem item;
         item.name = Key;
         item.value = Value;
         item.extraInfo = Extra;
         FItems.push_back(item);
-    }
+}
 
-    void AppendValue(const TString Key, TString Value) {
+void JavaOptions::AppendValue(const TString Key, TString Value) {
         AppendValue(Key, Value, NULL);
-    }
+}
 
-    void AppendValue(const TString Key) {
+void JavaOptions::AppendValue(const TString Key) {
         AppendValue(Key, _T(""), NULL);
-    }
+}
 
-    void AppendValues(OrderedMap<TString, TString> Values) {
+void JavaOptions::AppendValues(OrderedMap<TString, TString> Values) {
         std::vector<TString> orderedKeys = Values.GetKeys();
 
-        for (std::vector<TString>::const_iterator iterator = orderedKeys.begin(); iterator != orderedKeys.end(); iterator++) {
+    for (std::vector<TString>::const_iterator iterator = orderedKeys.begin();
+        iterator != orderedKeys.end(); iterator++) {
             TString name = *iterator;
             TString value;
 
             if (Values.GetValue(name, value) == true) {
                 AppendValue(name, value);
             }
         }
-    }
+}
 
-    void ReplaceValue(const TString Key, TString Value) {
+void JavaOptions::ReplaceValue(const TString Key, TString Value) {
         for (std::list<JavaOptionItem>::iterator iterator = FItems.begin();
              iterator != FItems.end(); iterator++) {
 
             TString lkey = iterator->name;
 

@@ -184,13 +155,13 @@
                 iterator = FItems.erase(iterator);
                 FItems.insert(iterator, item);
                 break;
             }
         }
-    }
+}
 
-    std::list<TString> ToList() {
+std::list<TString> JavaOptions::ToList() {
         std::list<TString> result;
         Macros& macros = Macros::GetInstance();
 
         for (std::list<JavaOptionItem>::const_iterator iterator = FItems.begin();
              iterator != FItems.end(); iterator++) {

@@ -200,16 +171,15 @@
             option = macros.ExpandMacros(option);
             result.push_back(option);
         }
 
         return result;
-    }
+}
 
-    size_t GetCount() {
+size_t JavaOptions::GetCount() {
         return FItems.size();
-    }
-};
+}
 
 // jvmuserargs can have a trailing equals in the key. This needs to be removed to use
 // other parts of the launcher.
 OrderedMap<TString, TString> RemoveTrailingEquals(OrderedMap<TString, TString> Map) {
     OrderedMap<TString, TString> result;

@@ -307,23 +277,11 @@
         Messages& messages = Messages::GetInstance();
         platform.ShowMessage(messages.GetMessage(NO_MAIN_CLASS_SPECIFIED));
         return false;
     }
 
-    JavaLibrary javaLibrary;
-
-    // TODO: Clean this up. Because of bug JDK-8131321 the opening of the PE file fails in WindowsPlatform.cpp on the check to
-    // if (pNTHeader->Signature == IMAGE_NT_SIGNATURE)
-#ifdef _WIN64
-    if (FilePath::FileExists(_T("msvcr100.dll")) == true) {
-        javaLibrary.AddDependency(_T("msvcr100.dll"));
-    }
-#else
-    javaLibrary.AddDependencies(platform.FilterOutRuntimeDependenciesForPlatform(platform.GetLibraryImports(package.GetJVMLibraryFileName())));
-#endif
-
-    javaLibrary.Load(package.GetJVMLibraryFileName());
+    configureLibrary();
 
     // Initialize the arguments to JLI_Launch()
     //
     // On Mac OS X JLI_Launch spawns a new thread that actually starts the JVM. This
     // new thread simply re-runs main(argc, argv). Therefore we do not want

@@ -347,10 +305,54 @@
     else {
         options.AppendValue(_T("-m"));
         options.AppendValue(mainModule);
     }
 
+    return launchVM(options, vmargs, false);
+}
+
+bool JavaVirtualMachine::NotifySingleInstance() {
+    Package& package = Package::GetInstance();
+
+    std::list<TString> vmargs;
+    vmargs.push_back(package.GetCommandName());
+
+    JavaOptions options;
+    options.AppendValue(_T("-Djava.library.path"), package.GetPackageAppDirectory()
+                      + FilePath::PathSeparator() + package.GetPackageLauncherDirectory());
+    options.AppendValue(_T("-Djava.launcher.path"), package.GetPackageLauncherDirectory());
+    // launch SingleInstanceNewActivation.main() to pass arguments to another instance
+    options.AppendValue(_T("-m"));
+    options.AppendValue(_T("jdk.packager.services/jdk.packager.services.singleton.SingleInstanceNewActivation"));
+
+    configureLibrary();
+
+    return launchVM(options, vmargs, true);
+}
+
+void JavaVirtualMachine::configureLibrary() {
+    Platform& platform = Platform::GetInstance();
+    Package& package = Package::GetInstance();
+    // TODO: Clean this up. Because of bug JDK-8131321 the opening of the PE file
+    // fails in WindowsPlatform.cpp on the check to
+    // if (pNTHeader->Signature == IMAGE_NT_SIGNATURE)
+    TString libName = package.GetJVMLibraryFileName();
+#ifdef _WIN64
+    if (FilePath::FileExists(_T("msvcr100.dll")) == true) {
+        javaLibrary.AddDependency(_T("msvcr100.dll"));
+    }
+#else
+    javaLibrary.AddDependencies(
+        platform.FilterOutRuntimeDependenciesForPlatform(platform.GetLibraryImports(libName)));
+#endif
+    javaLibrary.Load(libName);
+}
+
+bool JavaVirtualMachine::launchVM(JavaOptions& options, std::list<TString>& vmargs, bool addSiProcessId) {
+    Platform& platform = Platform::GetInstance();
+    Package& package = Package::GetInstance();
+
 #ifdef MAC
     // Mac adds a ProcessSerialNumber to args when launched from .app
     // filter out the psn since they it's not expected in the app
     if (platform.IsMainThread() == false) {
         std::list<TString> loptions = options.ToList();

@@ -359,16 +361,25 @@
 #else
     std::list<TString> loptions = options.ToList();
     vmargs.splice(vmargs.end(), loptions, loptions.begin(), loptions.end());
 #endif
 
+    if (addSiProcessId) {
+        // add single instance process ID as a first argument
+        TProcessID pid = platform.GetSingleInstanceProcessId();
+        std::ostringstream s;
+        s << pid;
+        std::string procIdStr(s.str());
+        vmargs.push_back(TString(procIdStr.begin(), procIdStr.end()));
+    }
+
     std::list<TString> largs = package.GetArgs();
     vmargs.splice(vmargs.end(), largs, largs.begin(), largs.end());
+
     size_t argc = vmargs.size();
     DynamicBuffer<char*> argv(argc + 1);
     unsigned int index = 0;
-
     for (std::list<TString>::const_iterator iterator = vmargs.begin();
          iterator != vmargs.end(); iterator++) {
         TString item = *iterator;
         std::string arg = PlatformString(item).toStdString();
 #ifdef DEBUG

@@ -378,18 +389,18 @@
         index++;
     }
 
     argv[argc] = NULL;
 
-    // On Mac we can only free the boot fields if the calling thread is not the main thread.
-    #ifdef MAC
+// On Mac we can only free the boot fields if the calling thread is not the main thread.
+#ifdef MAC
     if (platform.IsMainThread() == false) {
         package.FreeBootFields();
     }
-    #else
+#else
     package.FreeBootFields();
-    #endif //MAC
+#endif //MAC
 
     if (javaLibrary.JavaVMCreate(argc, argv.GetData()) == true) {
         return true;
     }