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

Call to JNI_CreateJavaVM crashes with Error ID 5448524541440E4350500630 FF

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Not an Issue
    • Icon: P4 P4
    • None
    • 1.3.1
    • hotspot
    • sparc
    • solaris_2.6



      Name: ddT132432 Date: 08/24/2001


      java version "1.3.1"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.1-b24)
      Java HotSpot(TM) Client VM (build 1.3.1-b24, mixed mode)

      0) First Note
      --------------
      Java Code is not involved in this problem. Program crashes when calling
      JNI_CreateJavaVM invocation API function.
      Native Code is provided below with Makefile. Java Code is provided as well.

      1) Description of Native Program.
      ---------------------------------
      I wrote a program in C++, based on a recursive function which has two
      parameters. Let's call it ContructOrCall, its prototype is void ContructOrCall(int construct, int level). This function calls itself
      ContructOrCall(construct, level - 1) until level is 0. If level is 0, then ContructOrCall constructs a Java Object (by calling a function named
      TJSI_RunJavaApp, see description below) if construct equals 1, else ContructOrCall calls a method of the constrcuted Java Object (done by
      a call to TJSI_CallMethod). Before testing the value of level, ContructOrCall fills in a local array whose role is to fill in the CPU stack.

      2) Bug rises
      ------------

      Depending on the recursive depth, loading the Java VM may fail as the call to JNI_CreateJavaVM displays the following error message, followed by a core
      dump due to a segmentation fault :

      #
      # HotSpot Virtual Machine Error, Internal Error
      # Please report this error at
      # http://java.sun.com/cgi-bin/bugreport.cgi
      #
      # Error ID: 5448524541440E4350500630 FF
      #
      # Problematic Thread:
      Segmentation Fault (core dumped)

      3) Native Source Code and MakeFile
      -----------------------------------

      3.1 Main2.cpp
      -------------

      #include <iostream.h>
      #include <stdio.h>

      #define GARBAGE_SIZE 5000
      #define GARBAGE_VAL 10

      TJSI_Handle h;
      int *dummy;

      void ContructOrCall(int construct, int level)
      {
       int i;
       int garbage[GARBAGE_SIZE];
       
       for(i = 0;i < GARBAGE_SIZE;i++)
       {
        garbage[i] = (int)dummy;
       }
       

       cout << "ContructOrCall[" << construct << "] : level = " << level <<
            " " << (unsigned int) &i << "," << (unsigned int) &dummy << endl;
       if(level > 0)
       {
        
        ContructOrCall(construct, level - 1);
       }
       else
       {
        if(construct)
        {
         cout << "Construct!!" << endl;
         h = TJSI_RunJavaApp("ProgressBarDemo", "<init>");
         cout << "ContructOrCall : construct : h = " << h << endl;
        }
        else
        {
         cout << "Call!!" << endl;
         int k = TJSI_CallMethod(h, "SetProgressBarVal", 50);
        }
       }
      }

      int main(void)
      {
       int k,level;
       dummy = (int*)malloc(sizeof(int)); // (int*)10; //
       level=25;
       cout << "ContructOrCall(1, " << level << ")" << endl;
       ContructOrCall(1, level);
       level=15;
       cout << "ContructOrCall(0, " << level << ")" << endl;
       ContructOrCall(0, level);
       
       return 0;
      }

      3.2) tjsi.cpp
      -------------

      #include "tjsi.h"
      #include <stdarg.h>
      #include <jni.h>

      #include <iostream.h>
      #include <string.h>

      #define USER_CLASSPATH "."

      typedef struct TJSI_VMRecord_struct
      {
       JNIEnv *env;
       JavaVM *jvm;
       char *ClassName;
       JDK1_1InitArgs vm_args;
       jclass cls;
       jobject object;
      } TJSI_VMRecord;

      static TJSI_VMRecord VMRecordArray[TJSI_MAXVMINSTANCES];

      static int VMRecordArrayIndex = 0;

      void PrintRecordFields(TJSI_VMRecord aRecord)
      {
       cout << "PrintRecordFields : env = " << aRecord.env << endl;
       cout << "PrintRecordFields : jvm = " << aRecord.jvm << endl;
       cout << "PrintRecordFields : ClassName = " << aRecord.ClassName << endl;
       cout << "PrintRecordFields : cls = " << aRecord.cls << endl;
       cout << "PrintRecordFields : object = " << aRecord.object << endl;
       return;
      }

      TJSI_Handle TJSI_RunJavaApp(char *ClassName,
                                  char *ConstrutorName)
      {
       static char classpath[1024];
       char *tmp;
       static void *venv;

       if(VMRecordArrayIndex < TJSI_MAXVMINSTANCES)
       // OK. Room available. So we go further in creation of VM
       {
        VMRecordArray[VMRecordArrayIndex].vm_args.version = JNI_VERSION_1_2;
        cout << "Before JNI_GetDefaultJavaVMInitArgs(" << VMRecordArrayIndex << ")"<<endl;
        JNI_GetDefaultJavaVMInitArgs(&(VMRecordArray[VMRecordArrayIndex].vm_args));
        cout << "TJSI_RunJavaApp : vm_args.classpath = " << endl;
        cout <<(VMRecordArray[VMRecordArrayIndex].vm_args).classpath << endl;
        if(((VMRecordArray[VMRecordArrayIndex].vm_args).classpath) != NULL)
        {
         sprintf(classpath, "%s%c%s",
                 ((VMRecordArray[VMRecordArrayIndex].vm_args).classpath), PATH_SEPARATOR, USER_CLASSPATH);
        }
        else
        {
         sprintf(classpath, "%c%s", PATH_SEPARATOR, USER_CLASSPATH);
        }
        cout << "TJSI_RunJavaApp : classpath = <" << classpath << ">" << endl;
        tmp=strdup(classpath);
        cout << "tmp" << endl;
        VMRecordArray[VMRecordArrayIndex].vm_args.classpath = tmp;
        jint res;
        VMRecordArray[VMRecordArrayIndex].vm_args.nativeStackSize = 1000000;
        cout << "Before JNI_CreateJavaVM(" << VMRecordArrayIndex << ")"<< endl;
        res = JNI_CreateJavaVM(&(VMRecordArray[VMRecordArrayIndex].jvm),&venv,&(VMRecordArray[VMRecordArrayIndex].vm_args));
        cout << "OK" << endl;
        if(res < 0)
        {
         // Sorry Folk : Creation of Java VM has failed.
         return TJSI_CANNOTCREATEVM;
        }
        // Creation of Java VM has successed.
        VMRecordArray[VMRecordArrayIndex].env = (JNIEnv *)venv;
        cout << "TJSI_RunJavaApp : env = " << VMRecordArray[VMRecordArrayIndex].env <<endl;
        
        VMRecordArray[VMRecordArrayIndex].ClassName = strdup(ClassName);
        
        VMRecordArray[VMRecordArrayIndex].cls = VMRecordArray[VMRecordArrayIndex].env->FindClass(ClassName);
        cout << "TJSI_RunJavaApp : cls = " << VMRecordArray[VMRecordArrayIndex].cls <<endl;
        if(VMRecordArray[VMRecordArrayIndex].cls == 0)
        {
         // Sorry Folk : the class name was not found.
         return TJSI_CANNOTFINDCLASS;
        }
        
        jmethodID mid = VMRecordArray[VMRecordArrayIndex].env->GetMethodID(VMRecordArray[VMRecordArrayIndex].cls, "<init>", "()V");
        if(mid == 0)
        {
         // Sorry Folk : Could not find a constructor with Signature ()V
         return TJSI_CANNOTFINDCONTR;
        }
        
        VMRecordArray[VMRecordArrayIndex].object = VMRecordArray[VMRecordArrayIndex].env->NewObject(VMRecordArray[VMRecordArrayIndex].cls, mid);
        if(VMRecordArray[VMRecordArrayIndex].object == 0)
        {
         // Sorry Folk : the class instance could not be created.
         return TJSI_CANNOTCREATEOBJECT;
        }
        //////
        jmethodID mid2 = VMRecordArray[VMRecordArrayIndex].env->GetMethodID(
                     VMRecordArray[VMRecordArrayIndex].cls, "SetProgressBarVal","(I)V");
        cout << "TJSI_RunJavaApp : mid2 = " << mid2 << endl;
        VMRecordArray[VMRecordArrayIndex].env->CallVoidMethod(VMRecordArray[VMRecordArrayIndex].object, mid2, 200);
        
        
        /////
        // PrintRecordFields(VMRecordArray[VMRecordArrayIndex]);
        // Reaching this point means erveything is alright : Java VM is now created
        // and class instance has successfully been created.
        return VMRecordArrayIndex++;
       }
       else
       // No more room in VMRecordArray.
       {
        return TJSI_NOMOREVMHANDLE;
       }
      }

      int TJSI_CallMethod(TJSI_Handle handle, char *MethodName, int i)
      {
       
       if(handle < VMRecordArrayIndex)
       {
        TJSI_VMRecord Record = VMRecordArray[handle];
        // cout << "TJSI_CallMethod : Record =" << endl;
        // PrintRecordFields(Record);
        // cout << "TJSI_CallMethod : VMRecordArray[handle] =" << endl;
        // PrintRecordFields(VMRecordArray[handle]);
        
        jmethodID mid = Record.env->GetMethodID(Record.cls, MethodName, "(I)V");
        if(mid == 0)
        {
         // Sorry Folk : invalid method.
         return TJSI_INVALIDMETHODNAME;
        }
        
        Record.env->CallVoidMethod(Record.object, mid, i);
       }
       else
       {
        // Sorry Folk : got an invalid index.
        return TJSI_INVALIDHANDLE;
       }
      }

      3.3) tjsi.h
      -----------

      #ifndef __TJSI_H__
      #define __TJSI_H__

      // This is an interface to create a VM and instanciate objects

      typedef int TJSI_Handle;

      #define TJSI_CANNOTCREATEVM -1
      #define TJSI_CANNOTFINDCLASS -2
      #define TJSI_CANNOTFINDMETHOD -3
      #define TJSI_CANNOTCREATEOBJECT -4
      #define TJSI_INVALIDMETHODSIG -5
      #define TJSI_INVALIDMETHODNAME -6
      #define TJSI_NOMOREVMHANDLE -7
      #define TJSI_CANNOTFINDCONTR -8
      #define TJSI_INVALIDHANDLE -9

      #define TJSI_MAXVMINSTANCES 1024

      #ifdef _WIN32
      #define PATH_SEPARATOR ';'
      #else /* UNIX */
      #define PATH_SEPARATOR ':'
      #endif

      // Instanciate an object of class ClassName by calling Constructor of
      // name ConstrutorName. It is assumed the signature of constructor is
      // ()V which is not limitative.
      // If an error occurs, returns value < 0. Meaning is defined Above.
      TJSI_Handle TJSI_RunJavaApp(char *, char *);

      int TJSI_CallMethod(TJSI_Handle , char *, int);

      #endif

      JAVA CODE
      -------------
      import java.awt.*;
      import java.awt.event.*;
      import javax.swing.*;

      public class ProgressBarDemo extends JFrame {
       
       static private JProgressBar progressBar;
       private JLabel label;
       private JLabel overflow;
       private String newline = "\n";

       static void main(String[] args) {
          int i , j,k;
                            ProgressBarDemo P = new ProgressBarDemo();
      for(j = 0; j< 4;j++) {
      for(i = 0; i < 1024; i++) {
      ProgressBarDemo.SetProgressBarVal(i );
      for(k=0;k<10000;k++){
      }
      }
      }
                        }

       
       public ProgressBarDemo() {
        super("ProgressBarDemo");
       
        progressBar = new JProgressBar(JProgressBar.HORIZONTAL, 0, 1024);
        progressBar.setValue(0);
        progressBar.setStringPainted(true);
        
        label = new JLabel("FIFO Filling");
          
        JPanel panel = new JPanel();
        panel.add(progressBar);
        panel.add(label);
        
        overflow = new JLabel("No Overflow");
        
        JPanel contentPane = new JPanel();
        contentPane.setLayout(new BorderLayout());
        contentPane.add(panel, BorderLayout.NORTH);
        contentPane.add(overflow, BorderLayout.CENTER);
        setContentPane(contentPane); //Create a timer.
        
        addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent e) {
          System.exit(0);
        }});
        pack();
        setVisible(true);
        
       } /** * The actionPerformed method in this class * is called when the user presses the start button. */
        
       static public void SetProgressBarVal(int i)
       {
        progressBar.setValue(i);
       }
        
      }

      3.4) Makefile !! Set JAVAHOME var accordingly to your environment.
      --------------

      JAVAHOME =
      JAVALIB = $(JAVAHOME)/jre/lib/sparc
      IFLAGS = -I$(JAVAHOME)/include -I$(JAVAHOME)/include/solaris -I.
      LFLAGS = -L$(JAVAHOME)/jre/lib/sparc -L$(JAVAHOME)/lib/sparc

      # CC = gcc
      CC = g++

      OBJECTS = main2.o tjsi.o

      .cpp.o:
      $(CC) -c -g $(IFLAGS) $<

      all: myjavamake


      myjavamake: main2.o tjsi.o
      $(CC) -o $@ $(LFLAGS) $(OBJECTS) -ljava

      4) Further Notes.
      ------------------

      TJSI_RunJavaApp : its goal is to hide details of loading a JVM and details
      of contructing an objet to the user. User gives java class name and contructor
      name (it is assumed the constructor signature is "()V"), the function returns
      a handle to the user. If this handle is > 0, TJSI_RunJavaApp successed.
      Otherwise it failed. TJSI_RunJavaApp manages handles so we can create more
      than one VM and identify them.
      TJSI_RunJavaApp manages an array of records of type TJSI_VMRecord. On of
      TJSI_VMRecord fields is the contructed object ID of which user may later
      call methods.

      TJSI_CallMethod : its goal is to hide details of calling a java object method
      to the user. Prototype of TJSI_CallMethod is

      int TJSI_CallMethod(TJSI_Handle handle, char *MethodName, int i)

      The user gives the name of the method he wants to call, with parameter i (it
      is assumed that method signature is "(I)V"), and gives the handle returned
      by TJSI_RunJavaApp.
      (Review ID: 130145)
      ======================================================================

            xjiangsunw Xuyang Jiang (Inactive)
            ddressersunw Daniel Dresser (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: