home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 November / Chip_1998-11_cd.bin / tema / Cafe / WDESAMPL.BIN / jre_main.c < prev    next >
C/C++ Source or Header  |  1997-11-24  |  12KB  |  446 lines

  1. /*
  2.  * @(#)jre_main.c    1.12 97/05/23 David Connelly
  3.  *
  4.  * Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
  5.  *
  6.  * Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
  7.  * modify and redistribute this software in source and binary code form,
  8.  * provided that i) this copyright notice and license appear on all copies of
  9.  * the software; and ii) Licensee does not utilize the software in a manner
  10.  * which is disparaging to Sun.
  11.  *
  12.  * This software is provided "AS IS," without a warranty of any kind. ALL
  13.  * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
  14.  * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
  15.  * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
  16.  * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
  17.  * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
  18.  * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
  19.  * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
  20.  * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
  21.  * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
  22.  * POSSIBILITY OF SUCH DAMAGES.
  23.  *
  24.  * This software is not designed or intended for use in on-line control of
  25.  * aircraft, air traffic, aircraft navigation or aircraft communications; or in
  26.  * the design, construction, operation or maintenance of any nuclear
  27.  * facility. Licensee represents and warrants that it will not use or
  28.  * redistribute the Software for such purposes.
  29.  */
  30.  
  31. /*
  32.  * Main program for invoking application with JRE (Java Runtime Environment)
  33.  */
  34.  
  35. #include <string.h>
  36. #include <stdlib.h>
  37. #include <stdio.h>
  38. #include <jni.h>
  39. #include "jre.h"
  40.  
  41. /* Name of this program */
  42. #define PROGRAM "jre"
  43.  
  44. /* Title of this program */
  45. #ifdef VERSION
  46. #define TITLE "Java(tm) Runtime Loader Version " VERSION
  47. #else
  48. #define TITLE "Java(tm) Runtime Loader"
  49. #endif
  50.  
  51. /* Check for null value and return */
  52. #define NULL_CHECK(e) if ((e) == 0) return 0
  53.  
  54. /* Enable debugging output */
  55. #ifdef JRE_DEBUG
  56. jboolean debug;
  57. #endif
  58.  
  59.  
  60. /* Forward declarations */
  61. jint ParseOptions(int *argcp, char ***argvp, JDK1_1InitArgs *vmargs);
  62. void AddProperty(char *def);
  63. void DeleteProperty(const char *name);
  64. void PrintUsage(void);
  65. jarray NewStringArray(JNIEnv *env, char **cpp, int count);
  66. long atoml(char *s);
  67.  
  68. /* Globals */
  69. static char **props;        /* User-defined properties */
  70. static int numProps, maxProps;    /* Current, max number of properties */
  71.  
  72. /*
  73.  * Main program to invoke Java runtime using JNI invocation API. Supports
  74.  * setting of VM arguments through standard command line options.
  75.  */
  76. void main(int argc, char *argv[])
  77. {
  78.     JRESettings set;
  79.     void *handle;
  80.     JDK1_1InitArgs vmargs;
  81.     JavaVM *jvm;
  82.     JNIEnv *env;
  83.     char *s, *name;
  84.     jclass cls;
  85.     jmethodID mid;
  86.     jarray args;
  87.     int i;
  88.  
  89.     /* First scan arguments for help and debug options */
  90.     for (i = 1; i < argc; i++) {
  91.     char *arg = argv[i];
  92.     if (*arg++ != '-') {
  93.         break;
  94.     }
  95.     if (strcmp(arg, "?") == 0 || strcmp(arg, "h") == 0 ||
  96.         strcmp(arg, "help") == 0) {
  97.         PrintUsage();
  98.         exit(1);
  99.     }
  100. #ifdef JRE_DEBUG
  101.     if (strcmp(arg, "d") == 0) {
  102.         debug = JNI_TRUE;
  103.     }
  104. #endif
  105.     }
  106.  
  107.     /* Get runtime settings */
  108. #ifdef VERSION
  109.     if (JRE_GetSettings(&set, VERSION) != 0) {
  110. #else
  111.     if (JRE_GetCurrentSettings(&set) != 0) {
  112. #endif
  113.     if (JRE_GetDefaultSettings(&set) != 0) {
  114.         fprintf(stderr, "Could not locate Java runtime\n");
  115.         exit(1);
  116.     }
  117.     }
  118.  
  119. #ifdef JRE_DEBUG
  120.     if (debug) {
  121.     char *ver = JRE_MakeVersion(set.majorVersion, set.minorVersion,
  122.                     set.microVersion);
  123.     fprintf(stderr, "Runtime Settings:\n");
  124.     fprintf(stderr, " javaHome   = %s\n",
  125.         set.javaHome != 0 ? set.javaHome : "<not set>");
  126.     fprintf(stderr, " runtimeLib = %s\n",
  127.         set.runtimeLib != 0 ? set.runtimeLib : "<not set>");
  128.     fprintf(stderr, " version    = %s\n", ver != 0 ? ver : "<not set>");
  129.     fprintf(stderr, " compiler   = %s\n\n",
  130.         set.compiler != 0 ? set.compiler : "<not set>");
  131.     }
  132. #endif
  133.  
  134.     /* Load runtime library */
  135.     handle = JRE_LoadLibrary(set.runtimeLib);
  136.     if (handle == 0) {
  137.     fprintf(stderr, "Could not load runtime library: %s\n",
  138.         set.runtimeLib);
  139.     exit(1);
  140.     }
  141.  
  142.     /* Add pre-defined system properties */
  143.     if (set.javaHome != 0) {
  144.     char *def = JRE_Malloc(strlen(set.javaHome) + 16);
  145.     sprintf(def, "java.home=%s", set.javaHome);
  146.     AddProperty(def);
  147.     }
  148.     if (set.compiler != 0) {
  149.     char *def = JRE_Malloc(strlen(set.compiler) + 16);
  150.     sprintf(def, "java.compiler=%s", set.compiler);
  151.     AddProperty(def);
  152.     }
  153.  
  154.     /*
  155.      * The following is used to specify that we require at least
  156.      * JNI version 1.1. Currently, this field is not checked but
  157.      * will be starting with JDK/JRE 1.2. The value returned after
  158.      * calling JNI_GetDefaultJavaVMInitArgs() is the actual JNI version
  159.      * supported, and is always higher that the requested version.
  160.      */
  161.     vmargs.version = 0x00010001;
  162.  
  163.     if (JRE_GetDefaultJavaVMInitArgs(handle, &vmargs) != 0) {
  164.     fprintf(stderr, "Could not initialize Java VM\n");
  165.     exit(1);
  166.     }
  167.     vmargs.classpath = set.classPath;
  168.  
  169.     /* Parse command line options */
  170.     --argc; argv++;
  171.     if (ParseOptions(&argc, &argv, &vmargs) != 0) {
  172.     PrintUsage();
  173.     exit(1);
  174.     }
  175.  
  176.     /* Get name of class */
  177.     if (*argv == 0) {
  178.     PrintUsage();
  179.     exit(1);
  180.     }
  181.     name = strdup(*argv++);
  182.     for (s = name; *s != '\0'; s++) {
  183.     if (*s == '.') *s = '/';
  184.     }
  185.     --argc;
  186.  
  187. #ifdef JRE_DEBUG
  188.     if (debug) {
  189.     fprintf(stderr, "CLASSPATH is %s\n\n", vmargs.classpath);
  190.     }
  191. #endif
  192.  
  193.     /* Set user-defined system properties for Java VM */
  194.     if (props != 0) {
  195.     if (numProps == maxProps) {
  196.         char **tmp = JRE_Malloc((numProps + 1) * sizeof(char **));
  197.         memcpy(tmp, props, numProps * sizeof(char **));
  198.         free(props);
  199.         props = tmp;
  200.     }
  201.     props[numProps] = 0;
  202.     vmargs.properties = props;
  203.     }
  204.  
  205.     /* Load and initialize Java VM */
  206.     if (JRE_CreateJavaVM(handle, &jvm, &env, &vmargs) != 0) {
  207.     fprintf(stderr, "Could not create Java VM\n");
  208.     exit(1);
  209.     }
  210.  
  211.     /* Free properties */
  212.     if (props != 0) {
  213.     free(props);
  214.     }
  215.  
  216.     /* Find class */
  217.     cls = (*env)->FindClass(env, name);
  218.     if (cls == 0) {
  219.     fprintf(stderr, "Class not found: %s\n", *--argv);
  220.     exit(1);
  221.     }
  222.  
  223.     /* Find main method of class */
  224.     mid = (*env)->GetStaticMethodID(env, cls, "main",
  225.                         "([Ljava/lang/String;)V");
  226.     if (mid == 0) {
  227.     fprintf(stderr, "In class %s: public static void main(String args[])"
  228.             " is not defined\n");
  229.     exit(1);
  230.     }
  231.  
  232.     /* Invoke main method */
  233.     args = NewStringArray(env, argv, argc);
  234.  
  235.     if (args == 0) {
  236.     JRE_FatalError(env, "Couldn't build argument list for main\n");
  237.     }
  238.     (*env)->CallStaticVoidMethod(env, cls, mid, args);
  239.     if ((*env)->ExceptionOccurred(env)) {
  240.     (*env)->ExceptionDescribe(env);
  241.     }
  242.  
  243.     /* Wait until we are the only user thread remaining then unload VM */
  244.     (*jvm)->DestroyJavaVM(jvm);
  245.  
  246.     /* Unload the runtime */
  247.     JRE_UnloadLibrary(handle);
  248. }
  249.  
  250. /*
  251.  * Parses command line VM options. Returns 0 if successful otherwise
  252.  * returns -1 if an invalid option was encountered.
  253.  */
  254. jint ParseOptions(int *argcp, char ***argvp, JDK1_1InitArgs *vmargs)
  255. {
  256.     char *arg, **argv = *argvp;
  257.  
  258.     while ((arg = *argv++) != 0 && *arg++ == '-') {
  259.     if (strcmp(arg, "classpath") == 0) {
  260.         if (*argv == 0) {
  261.         fprintf(stderr, "No class path given for %s option\n", arg);
  262.         return -1;
  263.         }
  264.         vmargs->classpath = *argv++;
  265.     } else if (strcmp(arg, "cp") == 0) {
  266.         char *cp = vmargs->classpath;
  267.         if (*argv == 0) {
  268.         fprintf(stderr, "No class path given for %s option\n", arg);
  269.         return -1;
  270.         }
  271.         vmargs->classpath = malloc(strlen(*argv) + strlen(cp) + 2);
  272.         if (vmargs->classpath == 0) {
  273.         perror("malloc");
  274.         exit(1);
  275.         }
  276.         sprintf(vmargs->classpath, "%s%c%s", *argv++, PATH_SEPARATOR, cp);
  277.     } else if (strncmp(arg, "D", 1) == 0) {
  278.         AddProperty(arg + 1);
  279.     } else if (strncmp(arg, "ss", 2) == 0) {
  280.         jint n = atoml(arg + 2);
  281.         if (n >= 1000) {
  282.         vmargs->nativeStackSize = n;
  283.         }
  284.     } else if (strncmp(arg, "oss", 3) == 0) {
  285.         jint n = atoml(arg + 3);
  286.         if (n >= 1000) {
  287.         vmargs->javaStackSize = n;
  288.         }
  289.     } else if (strncmp(arg, "ms", 2) == 0) {
  290.         jint n = atoml(arg + 2);
  291.         if (n >= 1000) {
  292.         vmargs->minHeapSize = n;
  293.         }
  294.     } else if (strncmp(arg, "mx", 2) == 0) {
  295.         jint n = atoml(arg + 2);
  296.         if (n >= 1000) {
  297.         vmargs->maxHeapSize = n;
  298.         }
  299.     } else if (strcmp(arg, "noasyncgc") == 0) {
  300.         vmargs->disableAsyncGC = JNI_TRUE;
  301.     } else if (strcmp(arg, "noclassgc") == 0) {
  302.         vmargs->enableClassGC = JNI_FALSE;
  303.     } else if (strcmp(arg, "verify") == 0) {
  304.         vmargs->verifyMode = 2;
  305.     } else if (strcmp(arg, "verifyremote") == 0) {
  306.         vmargs->verifyMode = 1;
  307.     } else if (strcmp(arg, "noverify") == 0) {
  308.         vmargs->verifyMode = 0;
  309.     } else if (strcmp(arg, "nojit") == 0) {
  310.         DeleteProperty("java.compiler");
  311.     } else if (strcmp(arg, "v") == 0 || strcmp(arg, "verbose") == 0) {
  312.         vmargs->verbose = JNI_TRUE;
  313. #ifdef JRE_DEBUG
  314.     } else if (strcmp(arg, "d") == 0) {
  315.         debug = JNI_TRUE;
  316. #endif
  317.     } else if (strcmp(arg, "verbosegc") == 0) {
  318.         vmargs->enableVerboseGC = JNI_TRUE;
  319.     } else if (strcmp(arg, "?") == 0 || strcmp(arg, "h") == 0 ||
  320.            strcmp(arg, "help") == 0) {
  321.         return -1;
  322.     } else {
  323.         fprintf(stderr, "Illegal option: -%s\n", arg);
  324.         return -1;
  325.     }
  326.     }
  327.     *argcp -= --argv - *argvp;
  328.     *argvp = argv;
  329.     return 0;
  330. }
  331.  
  332. /*
  333.  * Adds a user-defined system property definition.
  334.  */
  335. void AddProperty(char *def)
  336. {
  337.     if (numProps >= maxProps) {
  338.     if (props == 0) {
  339.         maxProps = 4;
  340.         props = JRE_Malloc(maxProps * sizeof(char **));
  341.     } else {
  342.         char **tmp;
  343.         maxProps *= 2;
  344.         tmp = JRE_Malloc(maxProps * sizeof(char **));
  345.         memcpy(tmp, props, numProps * sizeof(char **));
  346.         free(props);
  347.         props = tmp;
  348.     }
  349.     }
  350.     props[numProps++] = def;
  351. }
  352.  
  353. /*
  354.  * Deletes a property definition by name.
  355.  */
  356. void DeleteProperty(const char *name)
  357. {
  358.     int i;
  359.  
  360.     for (i = 0; i < numProps; ) {
  361.     char *def = props[i];
  362.     char *c = strchr(def, '=');
  363.     int n;
  364.     if (c != 0) {
  365.         n = c - def;
  366.     } else {
  367.         n = strlen(def);
  368.     }
  369.     if (strncmp(name, def, n) == 0) {
  370.         if (i < --numProps) {
  371.         memmove(&props[i], &props[i+1], (numProps-i) * sizeof(char **));
  372.         }
  373.     } else {
  374.         i++;
  375.     }
  376.     }
  377. }
  378.  
  379. /*
  380.  * Creates an array of Java string objects from the specified array of C
  381.  * strings. Returns 0 if the array could not be created.
  382.  */
  383. jarray NewStringArray(JNIEnv *env, char **cpp, int count)
  384. {
  385.     jclass cls;
  386.     jarray ary;
  387.     int i;
  388.  
  389.     NULL_CHECK(cls = (*env)->FindClass(env, "java/lang/String"));
  390.     NULL_CHECK(ary = (*env)->NewObjectArray(env, count, cls, 0));
  391.     for (i = 0; i < count; i++) {
  392.     jstring str = (*env)->NewStringUTF(env, *cpp++);
  393.     NULL_CHECK(str);
  394.     (*env)->SetObjectArrayElement(env, ary, i, str);
  395.     (*env)->DeleteLocalRef(env, str);
  396.     }
  397.     return ary;
  398. }
  399.  
  400. /*
  401.  * Parses a memory size specification from the specified C string.
  402.  */
  403. long atoml(char *s)
  404. {
  405.     long n = strtol(s, &s, 10);
  406.     switch (*s++) {
  407.     case 'M': case 'm':
  408.     n *= 1024 * 1024;
  409.     break;
  410.     case 'K': case 'k':
  411.     n *= 1024;
  412.     break;
  413.     case '\0':
  414.     return n;
  415.     default:
  416.     return -1;
  417.     }
  418.     return *s == '\0' ? n : -1;
  419. }
  420.  
  421. /*
  422.  * Prints help message.
  423.  */
  424. void PrintUsage()
  425. {
  426.     fprintf(stderr, TITLE "\n"
  427.     "Usage: " PROGRAM " [-options] classname [arguments]\n"
  428.     "Options:\n"
  429.     "    -?, -help         print out this message\n"
  430.     "    -v, -verbose      turn on verbose mode\n"
  431.     "    -verbosegc        print a message when garbage collection occurs\n"
  432.     "    -noasyncgc        disable asynchronous garbage collection\n"
  433.     "    -noclassgc        disable class garbage collection\n"
  434.     "    -ss<number>       set the maximum native stack size for any thread\n"
  435.     "    -oss<number>      set the maximum Java stack size for any thread\n"
  436.     "    -ms<number>       set the initial Java heap size\n"
  437.     "    -mx<number>       set the maximum Java heap size\n"
  438.     "    -D<name>=<value>  set a system property\n"
  439.     "    -classpath <path> set class path to <path>\n"
  440.     "    -cp <path>        prepend <path> to base class path\n"
  441.     "    -verify           verify all classes when loaded\n"
  442.     "    -verifyremote     verify classes loaded from the network (default)\n"
  443.     "    -noverify         do not verify any classes\n"
  444.     "    -nojit            disable JIT compiler\n");
  445. }
  446.