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

JNI_CreateJavaVM on Mac OSX 10.9 Mavericks corrupts the callers stack size

    Details

    • Subcomponent:
    • Resolved In Build:
      b57
    • OS:
      os_x

      Backports

        Description

        FULL PRODUCT VERSION :
        java version " 1.7.0_25 "
        Java(TM) SE Runtime Environment (build 1.7.0_25-b15)
        Java HotSpot(TM) 64-Bit Server VM (build 23.25-b01, mixed mode)

        FULL OS VERSION :
        Darwin xxx.stata.com 13.0.0 Darwin Kernel Version 13.0.0: Tue Jul 2 15:57:48 PDT 2013; root:xnu-2422.1.35~2/RELEASE_X86_64 x86_64

        A DESCRIPTION OF THE PROBLEM :
        Our application is a large statistical program primarily written in C, C++, and Objective C. We have implemented some of our features using Java and have chosen to dynamically load the JRE for this purpose. Our application runs on Solaris, Linux, Mac OS, and Windows.

        We have obtained a beta copy of Mac OS 10.9 Mavericks and during our testing we discovered a severe problem where the act of calling JNI_CreateJavaVM or any subsequent JNI calls reduces the available program stack from 8 megabytes to approximately 512 kilobytes. Note that this problems does not occur on previous versions for Mac OS.


        THE PROBLEM WAS REPRODUCIBLE WITH -Xint FLAG: Did not try

        THE PROBLEM WAS REPRODUCIBLE WITH -server FLAG: Did not try

        STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
        The code dynamically loads the java runtime and the recursively calls a function which requires ~1k stack per call.

        The problem is only reproducible on MacOS 10.9 Mavericks.

        You will need to obtain the include directories from the java development kit for Mac OS and place it in the current directory.

        compile code:
          $ gcc -I include -I include/darwin test.c

        You will need to extract the jre-7u25 runtime to the same directory as the new binary (a.out). http://download.oracle.com/otn-pub/java/jdk/7u25-b15/jre-7u25-macosx-x64.tar.gz

        Call the test program:
          Note that the first argument determines if the java runtime is to be loaded (0 | 1) and the second argument determines how many times the test function is called recursively to verify stack availability.

          $ ./a.out 1 7000


        NOTE: I can provide a complete bundle (zip etc) for your convenience, but there does not seem to be a way to attach that here.


        EXPECTED VERSUS ACTUAL BEHAVIOR :
        Expected:

        $ ./a.out 1 7000
        Create JVM

        Actual (working on OSX 10.8 - ~ 7M stack test):
        $ ./a.out 1 7000
        Create JVM

        Actual (working on OSX 10.9 JAVA NOT LOADED - ~7M stack test):
        $ ./a.out 1 7000

        Actual (fails on OSX 10.9 - ~7M stack test)
        $ ./a.out 1 7000
        Create JVM
        Segmentation fault: 11

        Actual (fails on OSX 10.9 - ~1M stack test)
        $ ./a.out 1 1000
        Create JVM
        Segmentation fault: 11


        ERROR MESSAGES/STACK TRACES THAT OCCUR :
        Segmentation fault: 11

        REPRODUCIBILITY :
        This bug can be reproduced always.

        ---------- BEGIN SOURCE ----------
        /* test.c begins here */

        #include <stdlib.h>
        #include <stdio.h>
        #include <dlfcn.h>
        #include " jni.h "

        typedefjint (JNICALL CreateJavaVM_t)(JavaVM **pvm, void **env, void *args) ;

        int CreateVM(JavaVM ** jvm)
        {
        char jvmlib[] = " jre1.7.0_25.jre/Contents/Home/lib/jli/libjli.dylib " ;
        CreateJavaVM_t*pfnCreateJavaVM = NULL ;
        void*hinst = NULL ;

        intopcnt = 0 ;
        JNIEnv*env;
            JavaVMInitArgs vm_args;
            JavaVMOption options[1];


        options[opcnt++].optionString = (char*) " -Xcheck:jni " ;

            vm_args.version = JNI_VERSION_1_6;
            vm_args.nOptions = opcnt;
            vm_args.options = options;
            vm_args.ignoreUnrecognized = JNI_FALSE;

        hinst = dlopen(jvmlib, RTLD_NOW) ;
        if (hinst == NULL) {
        printf( " dlopen failed
         " ) ;
        return(-1) ;
        }

        pfnCreateJavaVM = (CreateJavaVM_t*) dlsym(hinst, " JNI_CreateJavaVM " ) ;
        if (pfnCreateJavaVM==NULL) {
        printf( " dlsym failed
         " ) ;
        return(-1) ;
        }

            int ret = pfnCreateJavaVM(jvm, (void**)&env, &vm_args);
            if(ret < 0) {
                printf( "
        Unable to Launch JVM
         " );
                return(-1) ;
            }

            if ((*env)->ExceptionCheck(env) == JNI_TRUE ) {
                printf( " exception
         " );
                exit(-1);
            }
        return(0) ;
        }

        void r(int n, int max) {
        char sz[984] ;
        if (n>=max) return ;
        n++ ;
        r(n, max) ;
        }

        int main(int argc, char *argv[])
        {
        int usevm, stacksize ;
        JavaVM *jvm ;
        int retcode ;

        if(argc != 3) {
        printf( " Usage: usejvm<0|1> stacksize<#>
         " ) ;
        return(-1) ;
        }

        usevm = (int)atoi(argv[1]) ;
        stacksize = (int)atoi(argv[2]) ;

        if(stacksize<=0) {
        printf( " Usage: stacksize in KB must be larger than 1
         " ) ;
        return(-1) ;
        }

        if(usevm != 0) {
        printf( " Create JVM
         " ) ;
        retcode = CreateVM(&jvm) ;
        if(retcode<0) return(-1) ;
        }

        r(0,stacksize) ;
        return(0) ;
        }

        /* end test.c */

        ---------- END SOURCE ----------

          Attachments

            Issue Links

              Activity

                People

                • Assignee:
                  gziemski Gerard Ziemski
                  Reporter:
                  webbuggrp Webbug Group
                • Votes:
                  0 Vote for this issue
                  Watchers:
                  8 Start watching this issue

                  Dates

                  • Due:
                    Created:
                    Updated:
                    Resolved: