6921472: RFE: java launcher code needs clean up
authorksrini
Fri, 09 Jul 2010 11:04:34 -0700
changeset 6005 f9e6c98d4ee3
parent 6004 f88fd15b64b9
child 6007 fd42c86c4d29
6921472: RFE: java launcher code needs clean up Summary: This changeset also contains fixes for 6405284, 6753938 and 6922500 Reviewed-by: darcy
jdk/src/share/bin/emessages.h
jdk/src/share/bin/java.c
jdk/src/share/bin/java.h
jdk/src/share/bin/jli_util.c
jdk/src/share/bin/jli_util.h
jdk/src/solaris/bin/java_md.c
jdk/src/windows/bin/java_md.c
jdk/test/tools/launcher/Arrrghs.java
--- a/jdk/src/share/bin/emessages.h	Mon Jul 12 18:18:13 2010 +0100
+++ b/jdk/src/share/bin/emessages.h	Fri Jul 09 11:04:34 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -44,7 +44,7 @@
 
 #define JVM_ERROR1      "Error: Could not create the Java Virtual Machine.\n" GEN_ERROR
 #define JVM_ERROR2      "Error: Could not detach main thread.\n" JNI_ERROR
-#define JVM_ERROR3      "Error: SPARC V8 processor detected; Server compiler requires V9 or better.\nUse Client compiler on V8 processors.\nCould not create the Java virtual machine."
+#define JVM_ERROR3      "Error: SPARC V8 processor detected;  Required V9 processors or better.\nUse JDK5 client compiler for V8 processors.\n" JVM_ERROR1
 
 #define JAR_ERROR1      "Error: Failed to load Main-Class manifest attribute from\n%s\n%s"
 #define JAR_ERROR2      "Error: Unable to access jarfile %s"
@@ -69,7 +69,8 @@
 #define CFG_ERROR5      "Error: Could not determine application home."
 #define CFG_ERROR6      "Error: could not open `%s'"
 #define CFG_ERROR7      "Error: no known VMs. (check for corrupt jvm.cfg file)"
-#define CFG_ERROR8      "Error: no `%s' JVM at `%s'."
+#define CFG_ERROR8      "Error: missing `%s' JVM at `%s'.\nPlease install or use the JRE or JDK that contains these missing components."
+#define CFG_ERROR9      "Error: could not determine JVM type."
 
 
 #define SPC_ERROR1      "Error: Syntax error in version specification \"%s\""
--- a/jdk/src/share/bin/java.c	Mon Jul 12 18:18:13 2010 +0100
+++ b/jdk/src/share/bin/java.c	Fri Jul 09 11:04:34 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -192,8 +192,8 @@
     int ret;
     InvocationFunctions ifn;
     jlong start, end;
-    char jrepath[MAXPATHLEN], jvmpath[MAXPATHLEN];
-    char ** original_argv = argv;
+    char jvmpath[MAXPATHLEN];
+    char jrepath[MAXPATHLEN];
 
     _fVersion = fullversion;
     _dVersion = dotversion;
@@ -225,14 +225,17 @@
      */
     SelectVersion(argc, argv, &main_class);
 
-    /* copy original argv */
-    JLI_TraceLauncher("Command line Args:\n");
-    original_argv = (JLI_CopyArgs(argc, (const char**)argv));
+    if (JLI_IsTraceLauncher()) {
+        int i;
+        printf("Command line args:\n");
+        for (i = 0; i < argc ; i++) {
+            printf("argv[%d] = %s\n", i, argv[i]);
+        }
+    }
 
     CreateExecutionEnvironment(&argc, &argv,
                                jrepath, sizeof(jrepath),
-                               jvmpath, sizeof(jvmpath),
-                               original_argv);
+                               jvmpath, sizeof(jvmpath));
 
     ifn.CreateJavaVM = 0;
     ifn.GetDefaultJavaVMInitArgs = 0;
@@ -301,22 +304,43 @@
     return ContinueInNewThread(&ifn, argc, argv, jarfile, classname, ret);
 
 }
+/*
+ * Always detach the main thread so that it appears to have ended when
+ * the application's main method exits.  This will invoke the
+ * uncaught exception handler machinery if main threw an
+ * exception.  An uncaught exception handler cannot change the
+ * launcher's return code except by calling System.exit.
+ *
+ * Wait for all non-daemon threads to end, then destroy the VM.
+ * This will actually create a trivial new Java waiter thread
+ * named "DestroyJavaVM", but this will be seen as a different
+ * thread from the one that executed main, even though they are
+ * the same C thread.  This allows mainThread.join() and
+ * mainThread.isAlive() to work as expected.
+ */
+#define LEAVE() \
+    if ((*vm)->DetachCurrentThread(vm) != 0) { \
+        JLI_ReportErrorMessage(JVM_ERROR2); \
+        ret = 1; \
+    } \
+    (*vm)->DestroyJavaVM(vm); \
+    return ret \
 
 #define CHECK_EXCEPTION_NULL_LEAVE(e) \
     if ((*env)->ExceptionOccurred(env)) { \
         JLI_ReportExceptionDescription(env); \
-        goto leave; \
+        LEAVE(); \
     } \
     if ((e) == NULL) { \
         JLI_ReportErrorMessage(JNI_ERROR); \
-        goto leave; \
+        LEAVE(); \
     }
 
 #define CHECK_EXCEPTION_LEAVE(rv) \
     if ((*env)->ExceptionOccurred(env)) { \
         JLI_ReportExceptionDescription(env); \
         ret = (rv); \
-        goto leave; \
+        LEAVE(); \
     }
 
 int JNICALL
@@ -349,8 +373,7 @@
         PrintJavaVersion(env, showVersion);
         CHECK_EXCEPTION_LEAVE(0);
         if (printVersion) {
-            ret = 0;
-            goto leave;
+            LEAVE();
         }
     }
 
@@ -358,7 +381,7 @@
     if (printXUsage || printUsage || (jarfile == 0 && classname == 0)) {
         PrintUsage(env, printXUsage);
         CHECK_EXCEPTION_LEAVE(1);
-        goto leave;
+        LEAVE();
     }
 
     FreeKnownVMs();  /* after last possible PrintUsage() */
@@ -430,30 +453,7 @@
      * System.exit) will be non-zero if main threw an exception.
      */
     ret = (*env)->ExceptionOccurred(env) == NULL ? 0 : 1;
-
-leave:
-    /*
-     * Always detach the main thread so that it appears to have ended when
-     * the application's main method exits.  This will invoke the
-     * uncaught exception handler machinery if main threw an
-     * exception.  An uncaught exception handler cannot change the
-     * launcher's return code except by calling System.exit.
-     */
-    if ((*vm)->DetachCurrentThread(vm) != 0) {
-        JLI_ReportErrorMessage(JVM_ERROR2);
-        ret = 1;
-    }
-    /*
-     * Wait for all non-daemon threads to end, then destroy the VM.
-     * This will actually create a trivial new Java waiter thread
-     * named "DestroyJavaVM", but this will be seen as a different
-     * thread from the one that executed main, even though they are
-     * the same C thread.  This allows mainThread.join() and
-     * mainThread.isAlive() to work as expected.
-     */
-    (*vm)->DestroyJavaVM(vm);
-
-    return ret;
+    LEAVE();
 }
 
 /*
@@ -1076,15 +1076,17 @@
     if (--argc >= 0) {
         if (jarflag) {
             *pjarfile = *argv++;
-            *pclassname = 0;
+            *pclassname = NULL;
         } else {
-            *pjarfile = 0;
+            *pjarfile = NULL;
             *pclassname = *argv++;
         }
         *pargc = argc;
         *pargv = argv;
     }
-
+    if (*pjarfile == NULL && *pclassname == NULL) {
+        *pret = 1;
+    }
     return JNI_TRUE;
 }
 
--- a/jdk/src/share/bin/java.h	Mon Jul 12 18:18:13 2010 +0100
+++ b/jdk/src/share/bin/java.h	Fri Jul 09 11:04:34 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -114,13 +114,19 @@
 
 #define GetArch() GetArchPath(CURRENT_DATA_MODEL)
 
-void CreateExecutionEnvironment(int *_argc,
-                                       char ***_argv,
-                                       char jrepath[],
-                                       jint so_jrepath,
-                                       char jvmpath[],
-                                       jint so_jvmpath,
-                                       char **original_argv);
+/*
+ * Different platforms will implement this, here
+ * pargc is a pointer to the original argc,
+ * pargv is a pointer to the original argv,
+ * jrepath is an accessible path to the jre as determined by the call
+ * so_jrepath is the length of the buffer jrepath
+ * jvmpath is an accessible path to the jvm as determined by the call
+ * so_jvmpath is the length of the buffer jvmpath
+ */
+void CreateExecutionEnvironment(int *argc, char ***argv,
+                                char *jrepath, jint so_jrepath,
+                                char *jvmpath, jint so_jvmpath);
+
 /* Reports an error message to stderr or a window as appropriate. */
 void JLI_ReportErrorMessage(const char * message, ...);
 
--- a/jdk/src/share/bin/jli_util.c	Mon Jul 12 18:18:13 2010 +0100
+++ b/jdk/src/share/bin/jli_util.c	Fri Jul 09 11:04:34 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -85,23 +85,6 @@
 }
 
 /*
- * Makes a copy of arguments
- */
-char**
-JLI_CopyArgs(int argc, const char **iargv)
-{
-    int i;
-    char** oargv = (char**)JLI_MemAlloc(sizeof(char*)*(argc+1));
-    for (i = 0 ; i < argc+1 ; i++) {
-        oargv[i] = (iargv[i] == NULL) ? NULL : JLI_StringDup(iargv[i]);
-        if (iargv[i] != NULL && JLI_IsTraceLauncher() == JNI_TRUE) {
-            printf("\targv[%d] = '%s'\n",i,iargv[i]);
-        }
-    }
-    return oargv;
-}
-
-/*
  * debug helpers we use
  */
 static jboolean _launcher_debug = JNI_FALSE;
--- a/jdk/src/share/bin/jli_util.h	Mon Jul 12 18:18:13 2010 +0100
+++ b/jdk/src/share/bin/jli_util.h	Fri Jul 09 11:04:34 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,7 +33,6 @@
 void *JLI_MemRealloc(void *ptr, size_t size);
 char *JLI_StringDup(const char *s1);
 void  JLI_MemFree(void *ptr);
-char **JLI_CopyArgs(int argc, const char **iargv);
 int   JLI_StrCCmp(const char *s1, const char* s2);
 
 
@@ -56,10 +55,12 @@
 #include <io.h>
 #define JLI_StrCaseCmp(p1, p2)          stricmp((p1), (p2))
 #define JLI_StrNCaseCmp(p1, p2, p3)     strnicmp((p1), (p2), (p3))
+#define JLI_Snprintf                    _snprintf
 #else
 #include <unistd.h>
 #define JLI_StrCaseCmp(p1, p2)          strcasecmp((p1), (p2))
 #define JLI_StrNCaseCmp(p1, p2, p3)     strncasecmp((p1), (p2), (p3))
+#define JLI_Snprintf                    snprintf
 #endif /* _WIN32 */
 
 /*
--- a/jdk/src/solaris/bin/java_md.c	Mon Jul 12 18:18:13 2010 +0100
+++ b/jdk/src/solaris/bin/java_md.c	Fri Jul 09 11:04:34 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -183,13 +183,9 @@
 }
 
 void
-CreateExecutionEnvironment(int *_argcp,
-                           char ***_argvp,
-                           char jrepath[],
-                           jint so_jrepath,
-                           char jvmpath[],
-                           jint so_jvmpath,
-                           char **original_argv) {
+CreateExecutionEnvironment(int *pargc, char ***pargv,
+                           char jrepath[], jint so_jrepath,
+                           char jvmpath[], jint so_jvmpath) {
   /*
    * First, determine if we are running the desired data model.  If we
    * are running the desired data model, all the error messages
@@ -200,18 +196,17 @@
    * os/processor combination has dual mode capabilities.
    */
 
-    int original_argc = *_argcp;
     jboolean jvmpathExists;
 
     /* Compute/set the name of the executable */
-    SetExecname(*_argvp);
+    SetExecname(*pargv);
 
     /* Check data model flags, and exec process, if needed */
     {
       char *arch        = (char *)GetArch(); /* like sparc or sparcv9 */
       char * jvmtype    = NULL;
-      int argc          = *_argcp;
-      char **argv       = original_argv;
+      int  argc         = *pargc;
+      char **argv       = *pargv;
 
       int running       = CURRENT_DATA_MODEL;
 
@@ -233,7 +228,7 @@
       { /* open new scope to declare local variables */
         int i;
 
-        newargv = (char **)JLI_MemAlloc((argc+1) * sizeof(*newargv));
+        newargv = (char **)JLI_MemAlloc((argc+1) * sizeof(char*));
         newargv[newargc++] = argv[0];
 
         /* scan for data model arguments and remove from argument list;
@@ -293,7 +288,11 @@
         }
 
         jvmpath[0] = '\0';
-        jvmtype = CheckJvmType(_argcp, _argvp, JNI_FALSE);
+        jvmtype = CheckJvmType(pargc, pargv, JNI_FALSE);
+        if (JLI_StrCmp(jvmtype, "ERROR") == 0) {
+            JLI_ReportErrorMessage(CFG_ERROR9);
+            exit(4);
+        }
 
         if (!GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath, arch )) {
           JLI_ReportErrorMessage(CFG_ERROR8, jvmtype, jvmpath);
@@ -309,7 +308,9 @@
         if (running != wanted) {
           /* Find out where the JRE is that we will be using. */
           if (!GetJREPath(jrepath, so_jrepath, GetArchPath(wanted), JNI_TRUE)) {
-            goto EndDataModelSpeculate;
+            /* give up and let other code report error message */
+            JLI_ReportErrorMessage(JRE_ERROR2, wanted);
+            exit(1);
           }
 
           /*
@@ -317,16 +318,21 @@
            * selection options.
            */
           if (ReadKnownVMs(jrepath, GetArchPath(wanted), JNI_TRUE) < 1) {
-            goto EndDataModelSpeculate;
+            /* give up and let other code report error message */
+            JLI_ReportErrorMessage(JRE_ERROR2, wanted);
+            exit(1);
           }
           jvmpath[0] = '\0';
-          jvmtype = CheckJvmType(_argcp, _argvp, JNI_TRUE);
+          jvmtype = CheckJvmType(pargc, pargv, JNI_TRUE);
+          if (JLI_StrCmp(jvmtype, "ERROR") == 0) {
+            JLI_ReportErrorMessage(CFG_ERROR9);
+            exit(4);
+          }
+
           /* exec child can do error checking on the existence of the path */
           jvmpathExists = GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath, GetArchPath(wanted));
 
         }
-      EndDataModelSpeculate: /* give up and let other code report error message */
-        ;
 #else
         JLI_ReportErrorMessage(JRE_ERROR2, wanted);
         exit(1);
@@ -398,9 +404,9 @@
     struct stat s;
 
     if (JLI_StrChr(jvmtype, '/')) {
-        sprintf(jvmpath, "%s/" JVM_DLL, jvmtype);
+        JLI_Snprintf(jvmpath, jvmpathsize, "%s/" JVM_DLL, jvmtype);
     } else {
-        sprintf(jvmpath, "%s/lib/%s/%s/" JVM_DLL, jrepath, arch, jvmtype);
+        JLI_Snprintf(jvmpath, jvmpathsize, "%s/lib/%s/%s/" JVM_DLL, jrepath, arch, jvmtype);
     }
 
     JLI_TraceLauncher("Does `%s' exist ... ", jvmpath);
@@ -424,26 +430,24 @@
 
     if (GetApplicationHome(path, pathsize)) {
         /* Is JRE co-located with the application? */
-        sprintf(libjava, "%s/lib/%s/" JAVA_DLL, path, arch);
+        JLI_Snprintf(libjava, sizeof(libjava), "%s/lib/%s/" JAVA_DLL, path, arch);
         if (access(libjava, F_OK) == 0) {
-            goto found;
+            JLI_TraceLauncher("JRE path is %s\n", path);
+            return JNI_TRUE;
         }
 
         /* Does the app ship a private JRE in <apphome>/jre directory? */
-        sprintf(libjava, "%s/jre/lib/%s/" JAVA_DLL, path, arch);
+        JLI_Snprintf(libjava, sizeof(libjava), "%s/jre/lib/%s/" JAVA_DLL, path, arch);
         if (access(libjava, F_OK) == 0) {
             JLI_StrCat(path, "/jre");
-            goto found;
+            JLI_TraceLauncher("JRE path is %s\n", path);
+            return JNI_TRUE;
         }
     }
 
     if (!speculative)
       JLI_ReportErrorMessage(JRE_ERROR8 JAVA_DLL);
     return JNI_FALSE;
-
- found:
-    JLI_TraceLauncher("JRE path is %s\n", path);
-    return JNI_TRUE;
 }
 
 jboolean
@@ -463,14 +467,18 @@
       int location;
 
       fp = fopen(jvmpath, "r");
-      if(fp == NULL)
-        goto error;
+      if (fp == NULL) {
+        JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror());
+        return JNI_FALSE;
+      }
 
       /* read in elf header */
       count = fread((void*)(&elf_head), sizeof(Elf32_Ehdr), 1, fp);
       fclose(fp);
-      if(count < 1)
-        goto error;
+      if (count < 1) {
+        JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror());
+        return JNI_FALSE;
+      }
 
       /*
        * Check for running a server vm (compiled with -xarch=v8plus)
@@ -481,41 +489,42 @@
        * does not have to be checked for in binaries with an LP64 data
        * model.
        */
-      if(elf_head.e_machine == EM_SPARC32PLUS) {
+      if (elf_head.e_machine == EM_SPARC32PLUS) {
         char buf[257];  /* recommended buffer size from sysinfo man
                            page */
         long length;
         char* location;
 
         length = sysinfo(SI_ISALIST, buf, 257);
-        if(length > 0) {
-          location = JLI_StrStr(buf, "sparcv8plus ");
-          if(location == NULL) {
+        if (length > 0) {
+            location = JLI_StrStr(buf, "sparcv8plus ");
+          if (location == NULL) {
             JLI_ReportErrorMessage(JVM_ERROR3);
             return JNI_FALSE;
           }
         }
       }
 #endif
-      JLI_ReportErrorMessage(DLL_ERROR1, __LINE__);
-      goto error;
+        JLI_ReportErrorMessage(DLL_ERROR1, __LINE__);
+        JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror());
+        return JNI_FALSE;
     }
 
     ifn->CreateJavaVM = (CreateJavaVM_t)
-      dlsym(libjvm, "JNI_CreateJavaVM");
-    if (ifn->CreateJavaVM == NULL)
-        goto error;
+        dlsym(libjvm, "JNI_CreateJavaVM");
+    if (ifn->CreateJavaVM == NULL) {
+        JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror());
+        return JNI_FALSE;
+    }
 
     ifn->GetDefaultJavaVMInitArgs = (GetDefaultJavaVMInitArgs_t)
         dlsym(libjvm, "JNI_GetDefaultJavaVMInitArgs");
-    if (ifn->GetDefaultJavaVMInitArgs == NULL)
-      goto error;
+    if (ifn->GetDefaultJavaVMInitArgs == NULL) {
+        JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror());
+        return JNI_FALSE;
+    }
 
     return JNI_TRUE;
-
-error:
-    JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror());
-    return JNI_FALSE;
 }
 
 /*
@@ -575,7 +584,7 @@
     char name[PATH_MAX + 2], *real;
 
     if ((JLI_StrLen(indir) + JLI_StrLen(cmd) + 1)  > PATH_MAX) return 0;
-    sprintf(name, "%s%c%s", indir, FILE_SEPARATOR, cmd);
+    JLI_Snprintf(name, sizeof(name), "%s%c%s", indir, FILE_SEPARATOR, cmd);
     if (!ProgramExists(name)) return 0;
     real = JLI_MemAlloc(PATH_MAX + 2);
     if (!realpath(name, real))
@@ -622,7 +631,7 @@
         else {
             /* relative path element */
             char dir[2*PATH_MAX];
-            sprintf(dir, "%s%c%s", getcwd(cwdbuf, sizeof(cwdbuf)),
+            JLI_Snprintf(dir, sizeof(dir), "%s%c%s", getcwd(cwdbuf, sizeof(cwdbuf)),
                     FILE_SEPARATOR, s);
             result = Resolve(dir, program);
         }
@@ -746,7 +755,7 @@
     if (JLI_StrLen(path) + JLI_StrLen(dir) + 11 > PATH_MAX)
         return (0);     /* Silently reject "impossibly" long paths */
 
-    sprintf(buffer, "%s/%s/bin/java", path, dir);
+    JLI_Snprintf(buffer, sizeof(buffer), "%s/%s/bin/java", path, dir);
     return ((access(buffer, X_OK) == 0) ? 1 : 0);
 }
 
--- a/jdk/src/windows/bin/java_md.c	Mon Jul 12 18:18:13 2010 +0100
+++ b/jdk/src/windows/bin/java_md.c	Fri Jul 09 11:04:34 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -80,26 +80,22 @@
  *
  */
 void
-CreateExecutionEnvironment(int *_argc,
-                           char ***_argv,
-                           char jrepath[],
-                           jint so_jrepath,
-                           char jvmpath[],
-                           jint so_jvmpath,
-                           char **original_argv) {
+CreateExecutionEnvironment(int *pargc, char ***pargv,
+                           char *jrepath, jint so_jrepath,
+                           char *jvmpath, jint so_jvmpath) {
     char * jvmtype;
     int i = 0;
-    char** pargv = *_argv;
     int running = CURRENT_DATA_MODEL;
 
     int wanted = running;
 
-    for (i = 0; i < *_argc ; i++) {
-        if (JLI_StrCmp(pargv[i], "-J-d64") == 0 || JLI_StrCmp(pargv[i], "-d64") == 0) {
+    char** argv = *pargv;
+    for (i = 0; i < *pargc ; i++) {
+        if (JLI_StrCmp(argv[i], "-J-d64") == 0 || JLI_StrCmp(argv[i], "-d64") == 0) {
             wanted = 64;
             continue;
         }
-        if (JLI_StrCmp(pargv[i], "-J-d32") == 0 || JLI_StrCmp(pargv[i], "-d32") == 0) {
+        if (JLI_StrCmp(argv[i], "-J-d32") == 0 || JLI_StrCmp(argv[i], "-d32") == 0) {
             wanted = 32;
             continue;
         }
@@ -123,7 +119,12 @@
         JLI_ReportErrorMessage(CFG_ERROR7);
         exit(1);
     }
-    jvmtype = CheckJvmType(_argc, _argv, JNI_FALSE);
+
+    jvmtype = CheckJvmType(pargc, pargv, JNI_FALSE);
+    if (JLI_StrCmp(jvmtype, "ERROR") == 0) {
+        JLI_ReportErrorMessage(CFG_ERROR9);
+        exit(4);
+    }
 
     jvmpath[0] = '\0';
     if (!GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath)) {
@@ -131,7 +132,6 @@
         exit(4);
     }
     /* If we got here, jvmpath has been correctly initialized. */
-
 }
 
 
@@ -203,19 +203,21 @@
     PREJVMSTART PreJVMStart;
     struct stat s;
 
+    /* Make sure the jrepath contains something */
+    if (jrepath[0] == NULL) {
+        return;
+    }
     /* 32 bit windows only please */
-    if (strcmp(GetArch(), "i386") != 0 ) {
+    if (JLI_StrCmp(GetArch(), "i386") != 0 ) {
         return;
     }
     /* Does our bundle directory exist ? */
-    strcpy(tmpbuf, jrepath);
-    strcat(tmpbuf, "\\lib\\bundles");
+    JLI_Snprintf(tmpbuf, sizeof(tmpbuf), "%s\\lib\\bundles", jrepath);
     if (stat(tmpbuf, &s) != 0) {
         return;
     }
     /* Does our jkernel dll exist ? */
-    strcpy(tmpbuf, jrepath);
-    strcat(tmpbuf, "\\bin\\jkernel.dll");
+    JLI_Snprintf(tmpbuf, sizeof(tmpbuf), "%s\\bin\\jkernel.dll", jrepath);
     if (stat(tmpbuf, &s) != 0) {
         return;
     }
@@ -249,30 +251,30 @@
 
     if (GetApplicationHome(path, pathsize)) {
         /* Is JRE co-located with the application? */
-        sprintf(javadll, "%s\\bin\\" JAVA_DLL, path);
+        JLI_Snprintf(javadll, sizeof(javadll), "%s\\bin\\" JAVA_DLL, path);
         if (stat(javadll, &s) == 0) {
-            goto found;
+            JLI_TraceLauncher("JRE path is %s\n", path);
+            return JNI_TRUE;
         }
 
         /* Does this app ship a private JRE in <apphome>\jre directory? */
-        sprintf(javadll, "%s\\jre\\bin\\" JAVA_DLL, path);
+        JLI_Snprintf(javadll, sizeof (javadll), "%s\\jre\\bin\\" JAVA_DLL, path);
         if (stat(javadll, &s) == 0) {
             JLI_StrCat(path, "\\jre");
-            goto found;
+            JLI_TraceLauncher("JRE path is %s\n", path);
+            return JNI_TRUE;
         }
     }
 
     /* Look for a public JRE on this machine. */
     if (GetPublicJREHome(path, pathsize)) {
-        goto found;
+        JLI_TraceLauncher("JRE path is %s\n", path);
+        return JNI_TRUE;
     }
 
     JLI_ReportErrorMessage(JRE_ERROR8 JAVA_DLL);
     return JNI_FALSE;
 
- found:
-    JLI_TraceLauncher("JRE path is %s\n", path);
-    return JNI_TRUE;
 }
 
 /*
@@ -286,9 +288,9 @@
 {
     struct stat s;
     if (JLI_StrChr(jvmtype, '/') || JLI_StrChr(jvmtype, '\\')) {
-        sprintf(jvmpath, "%s\\" JVM_DLL, jvmtype);
+        JLI_Snprintf(jvmpath, jvmpathsize, "%s\\" JVM_DLL, jvmtype);
     } else {
-        sprintf(jvmpath, "%s\\bin\\%s\\" JVM_DLL, jrepath, jvmtype);
+        JLI_Snprintf(jvmpath, jvmpathsize, "%s\\bin\\%s\\" JVM_DLL, jrepath, jvmtype);
     }
     if (stat(jvmpath, &s) == 0) {
         return JNI_TRUE;
--- a/jdk/test/tools/launcher/Arrrghs.java	Mon Jul 12 18:18:13 2010 +0100
+++ b/jdk/test/tools/launcher/Arrrghs.java	Fri Jul 09 11:04:34 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
 
 /**
  * @test
- * @bug 5030233 6214916 6356475 6571029 6684582 6742159 4459600 6758881
+ * @bug 5030233 6214916 6356475 6571029 6684582 6742159 4459600 6758881 6753938
  * @summary Argument parsing validation.
  * @compile -XDignore.symbol.file Arrrghs.java TestHelper.java
  * @run main Arrrghs
@@ -223,6 +223,20 @@
         tr.checkPositive();
         tr.isNotZeroOutput();
         System.out.println(tr);
+
+        // 6753938, test for non-negative exit value for an incorrectly formed
+        // command line,  '% java'
+        tr = TestHelper.doExec(TestHelper.javaCmd);
+        tr.checkNegative();
+        tr.isNotZeroOutput();
+        System.out.println(tr);
+
+        // 6753938, test for non-negative exit value for an incorrectly formed
+        // command line,  '% java -Xcomp'
+        tr = TestHelper.doExec(TestHelper.javaCmd, "-Xcomp");
+        tr.checkNegative();
+        tr.isNotZeroOutput();
+        System.out.println(tr);
     }
 
     /*