Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4237806

HotSpot JVM doesn't support required JNI options (e.g., vfprintf hook)

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: P1 P1
    • 1.1
    • 1.0
    • hotspot
    • alpha
    • x86
    • windows_nt



      Name: mm8553 Date: 05/12/99


      I wrote a C program which creates a JVM using the JNI invocation
      interfaces. This program fails with the HotSpot jvm because the
      HotSpot jvm doesn't support jvm creation options (specified to
      JNI_CreateJavaVM() in the array of JavaVMOption structs) which
      are documented as being supported by all JVMs. Specifically,
      the HotSpot jvm doesn't support "vfprintf", "exit", or "abort".
      The document docs/guide/jni/jni-12.html says these must be
      supported. My program depends on it. As an aside, the HotSpot
      jvm returns JNI_EINVAL from JNI_CreateJavaVM() for this
      situation, but the doc says that JNI_ERR will be returned
      (though JNI_EINVAL seems more sensible to me).

      Although you probably don't need it to diagnose the problem,
      the following C program demonstrates the failure. The JVM
      outputs this message to standard error when you run it.

      Unrecognized option: vfprintf

      -------------------------
      #include <stdio.h>
      #include <string.h>
      #include <stdlib.h>
      #include <stdarg.h>

      #include <sys/types.h>
      #include <sys/stat.h>

      #include <jni.h>

      #define WIN32_LEAN_AND_MEAN
      #define STRICT
      #include <windows.h>

      void describeError(const char *fcn, long errcode);
      #define describeLastError(x) describeError(x, GetLastError())

      struct JavaRuntimeInfo {
         jint (JNICALL *CreateJavaVM)(JavaVM **pvm, void **penv, void *args);
      };

      static int LoadJavaRuntime(struct JavaRuntimeInfo *info);
      static jint JNICALL jvm_output(FILE *stream, const char *format, va_list arg);

      static JavaVM *jvm; // Describes a Java virtual machine

      int main(int argc, char **argv) {
         struct JavaRuntimeInfo javaRuntimeInfo;
         JavaVMInitArgs vm_args; // For initializing the Java VM
         JavaVMOption *options = (JavaVMOption *) malloc(2 * sizeof(JavaVMOption));
         int optcnt = 0;

         char *cp, *tcp;
         size_t classlen;
         JNIEnv *env;
         jint cr;

         /* Pick and load a Java runtime DLL */
         LoadJavaRuntime(&javaRuntimeInfo);

         if (!options) {
            fprintf(stderr, "Unable to acquire storage for JVM initialization options\n");
            return 1;
         }

         /* Build class path to use */
         cp = getenv("CLASSPATH");
         classlen = sizeof "-Djava.class.path=" + (cp ? strlen(cp) : 1);
         tcp = (char *) malloc(classlen);
         if (!tcp) {
            fprintf(stderr, "Unable to acquire storage for CLASSPATH\n");
            return 1;
         }

         sprintf(tcp, "-Djava.class.path=%s", cp ? cp : ".");
         options[optcnt++].optionString = tcp;
         printf("Setting %s\n", tcp);

      #ifndef SUPPRESS_HOTSPOT_BUG
         /* Trap line-mode output from JVM */
         options[optcnt].optionString = "vfprintf";
         options[optcnt++].extraInfo = jvm_output;
         printf("Redirecting JVM output.\n");
      #endif

         /* Initialize fields in startup struct */
         vm_args.version = JNI_VERSION_1_2; /* Initialize version field */
         vm_args.options = options;
         vm_args.nOptions = optcnt;
         vm_args.ignoreUnrecognized = JNI_FALSE;

         printf("Creating Java VM\n");
         cr = javaRuntimeInfo.CreateJavaVM(&jvm, (void **) &env, &vm_args);
         if (cr) {
            printf("Call to JNI_CreateJavaVM() failed with result value %ld.\n", (long) cr);
            return 1;
         }
         printf("Created Java VM successfully\n");

         /* Exit without doing anything useful */
         return 0;
      }


      static char *readStringRegValue(HKEY keyhandle, const char *valueName) {
         unsigned char *retvalue;
         DWORD valuelen;
         DWORD valueType;
         long result = RegQueryValueEx(keyhandle, valueName, NULL, &valueType,
                                       NULL, &valuelen);
         if (result != ERROR_SUCCESS) describeError("RegQueryValueEx", result);
         if (valueType != REG_SZ && valueType != REG_EXPAND_SZ) {
            fprintf(stderr, "Unexpected response from RegQueryValueEx(): "
                   "Value's type is %ld\n", (long) valueType);
            exit(201);
         }
         retvalue = (unsigned char *) malloc(valuelen);
         if (!retvalue) {
            fprintf(stderr, "Unable to acquire storage to read registry\n");
            exit(201);
         }
         result = RegQueryValueEx(keyhandle, valueName, NULL, &valueType,
                                  retvalue, &valuelen);
         if (result != ERROR_SUCCESS) describeError("RegQueryValueEx", result);

         return (char *) retvalue;
      }


      /* Locate the jvm dll to use. Look for hotspot, then classic. */
      #define JRE_KEY "Software\\JavaSoft\\Java Runtime Environment"
      #define HOTSPOT_PATH "\\bin\\hotspot\\jvm.dll"
      #define CLASSIC_PATH "\\bin\\classic\\jvm.dll"
      static int LoadJavaRuntime(struct JavaRuntimeInfo *info) {
         HKEY key, subkey;
         char *version, *homedir, *runtimedll;
         char workarea[FILENAME_MAX];
         long result;
         HINSTANCE dllHandle;
         struct stat st;

         /* Find the name of the DLL for the current version of the JRE */
         result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, JRE_KEY, 0, KEY_QUERY_VALUE,
                               &key);
         if (result != ERROR_SUCCESS) describeError("RegOpenKeyEx", result);

         version = readStringRegValue(key, "CurrentVersion");

         result = RegOpenKeyEx(key, version, 0, KEY_QUERY_VALUE, &subkey);
         if (result != ERROR_SUCCESS) describeError("RegOpenKeyEx", result);
         RegCloseKey(key);
         free(version);

         /* Initialize our dll path to the one named in the registry. We fall */
         /* back on this value if our later checks fail. */
         runtimedll = readStringRegValue(subkey, "RuntimeLib");

         homedir = readStringRegValue(subkey, "JavaHome");
         RegCloseKey(subkey);

         /* Look for the hotspot jvm first. If not found, try the classic jvm. */
         if (strlen(homedir) + sizeof HOTSPOT_PATH <= sizeof workarea) {
            sprintf(workarea, "%s" HOTSPOT_PATH, homedir);
            if (!stat(workarea, &st)) {
               runtimedll = workarea; /* This is the dll to use */
            } else {
               /* Check for classic jvm */
               if (strlen(homedir) + sizeof CLASSIC_PATH <= sizeof workarea) {
                  sprintf(workarea, "%s" CLASSIC_PATH, homedir);
                  if (!stat(workarea, &st)) {
                     runtimedll = workarea; /* This is the dll to use */
                  }
               }
            }
         }

      printf("Using JVM dll: %s\n", runtimedll);
         dllHandle = LoadLibrary(runtimedll);
         if (!dllHandle) describeLastError("LoadLibrary");

         info->CreateJavaVM =
                           (jint (JNICALL *)(JavaVM **, void **, void *))
                              GetProcAddress(dllHandle, "JNI_CreateJavaVM");
         if (!info->CreateJavaVM) describeLastError("GetProcAddress");

         return 0;
      }

      static FILE *errors = NULL;

      static jint JNICALL jvm_output(FILE *stream, const char *format,
                                                               va_list arg) {
         if (!errors) {
            errors = fopen("ErrorsFromJvm", "w");
            if (!errors) {perror("Error opening jvm output file"); exit(10);}
         }
         return vfprintf(errors, format, arg);
      }

      static void describeError(const char *fcn, long errcode) {
         char *msgbuffer;
         DWORD rc = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
                                  | FORMAT_MESSAGE_ALLOCATE_BUFFER,
                                  NULL, errcode, 0, (char *) &msgbuffer, 0, NULL);
         if (!rc) {
            fprintf(stderr, "Received error code %ld from FormatMessage() while"
                   " trying\nto format message for error code %ld, from"
                   " function %s()\n", GetLastError(), errcode, fcn);
            return;
         }
         fprintf(stderr, "Received error code %ld from function %s(): %s",
                errcode, fcn, msgbuffer);
         LocalFree(msgbuffer);
         exit(101);
      }
      (Review ID: 57737)
      ======================================================================

            rschmidtsunw Rene Schmidt (Inactive)
            mmuellersunw Marianne Mueller (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: