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

creating JVM via C program "steals" space from main thread stack rendering JNI useless

    Details

    • Type: Bug
    • Status: Closed
    • Priority: P2
    • Resolution: Fixed
    • Affects Version/s: 5.0u2
    • Fix Version/s: 6
    • Component/s: hotspot
    • Labels:
    • Subcomponent:
    • Introduced In Version:
    • Resolved In Build:
      b43
    • CPU:
      generic
    • OS:
      solaris_8

      Backports

        Description

        Problem: Initializing a Java VM "steals" stack space from other
        threads. It basically renders JNI unusable in any non-trivial way. The
        problem occurs on Solaris 8/10 on either sparc/x86. A test program is
        included to demonstrate the problem.

        Java Version:

        >> java -version java version "1.5.0_02" Java(TM) 2 Runtime Environment,

        Standard Edition (build 1.5.0_02-b09) Java HotSpot(TM) Server VM (build
        1.5.0_02-b09, mixed mode)

        This program demonstrates that initializing a Java VM "steals"
          * stack space from other threads.
          * For instance, in the sample output below, before initializing the
          * JVM, the application has used up 1.8M of stack space. But after
          * initializing the JVM, the main thread's allocated stack space has
          * shrunk to just the single 488K block at 0xFFB76000! That means
          * that the main thread can never again exceed 488K of stack, or else
          * the program will crash.

          Stack starts near 0xffbeef10

          Initial stack:
          FF3A0000 176K read/exec /usr/lib/ld.so.1
          FF3DC000 8K read/write/exec /usr/lib/ld.so.1
          FF3DE000 8K read/write/exec /usr/lib/ld.so.1
          FFBEC000 16K read/write/exec [ stack ]
           total 7352K

          recurse() stack near 0xffa1a2ec

          Stack after recurse(20000):
          FF3A0000 176K read/exec /usr/lib/ld.so.1
          FF3DC000 8K read/write/exec /usr/lib/ld.so.1
          FF3DE000 8K read/write/exec /usr/lib/ld.so.1
          FFA18000 1888K read/write/exec [ stack ]
           total 9224K

           Stack after jvm:
           FF3A0000 176K read/exec /usr/lib/ld.so.1
           FF3DC000 8K read/write/exec /usr/lib/ld.so.1
           FF3DE000 8K read/write/exec /usr/lib/ld.so.1
           FFA18000 1376K read/write/exec [ stack ]
           FFB70000 24K - [ stack ]
           FFB76000 488K read/write/exec [ stack ]
            total 82304K

        To compile:

        solaris sparc:
           cc -g -I/usr/local/java/jdk/include
        -I/usr/local/java/jdk/include/solaris
        -L/usr/local/java/jdk/jre/lib/sparc -R/usr/local/java/jdk/jre/lib/sparc
        -ljvm -lpthread stack.c

        solaris x86:
           cc -g -I/usr/local/java/jdk/include
        -I/usr/local/java/jdk/include/solaris -L/usr/local/java/jdk/jre/lib/i386
        -R/usr/local/java/jdk/jre/lib/i386 -ljvm -lpthread stack.c

        linux:
           gcc -g -I/usr/local/java/jdk/include
        -I/usr/local/java/jdk/include/linux
        -L/usr/local/java/jdk/jre/lib/i386/server
        -Wl,-rpath,/usr/local/java/jdk/jre/lib/i386/server -ljvm -lpthread stack.c
          */

        #include <stdio.h>
        #include <stdlib.h>
        #include <unistd.h>
        #include <jni.h>

        void recurse(int n)
        {
             if (n > 0) {
          recurse(n-1);
             } else {
          printf("recurse() stack near 0x%x\n", &n);
             }
        }

        void pmap()
        {
             /* check if we have gnu grep installed */
             int ret = system("echo hi | gnu grep -1 hi > /dev/null 2>&1");
             char buf[BUFSIZ];
             if (ret == 0) {
          snprintf(buf, sizeof(buf), "pmap %d | gnu grep -3 stack", getpid());
             } else {
          snprintf(buf, sizeof(buf), "pmap %d | grep stack", getpid());
             }
             system(buf);
        }

        void jvm()
        {
             JavaVMInitArgs vm_args;
             vm_args.version = JNI_VERSION_1_4;
             vm_args.nOptions = 0;
             JNI_GetDefaultJavaVMInitArgs(&vm_args);
             JavaVM *jvm;
             JNIEnv *env;
             long result = JNI_CreateJavaVM(&jvm, (void **)&env, &vm_args);
             if (result == JNI_ERR) {
          fprintf(stderr, "ERROR initializing the JVM\n");
          exit(1);
             }
        }

        int main(int argc, char **argv)
        {
             int x;
             printf("Stack starts near 0x%x\n", &x);
             printf("\nInitial stack:\n");
             pmap();
             printf("\n");

             int n = 20000;
        #ifdef __linux
             /* linux appears to give you a larger initial stack */
             n = 100000;
        #endif
             if (argc >= 2) {
          n = atoi(argv[1]);
             }
             recurse(n);

             printf("\nStack after recurse(%d):\n", n);
             pmap();

             jvm();

             printf("\nStack after jvm:\n");
             pmap();

             printf("\nPrepare to crash:\n");
             recurse(n*2);

             printf("\nWOOHOO! No crash!\n");
        }
        ###@###.### 2005-05-12 19:57:37 GMT

          Attachments

            Issue Links

              Activity

                People

                • Assignee:
                  sbohne Steve Bohne (Inactive)
                  Reporter:
                  msusko Mark Susko (Inactive)
                • Votes:
                  0 Vote for this issue
                  Watchers:
                  4 Start watching this issue

                  Dates

                  • Created:
                    Updated:
                    Resolved:
                    Imported:
                    Indexed: