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

FileOutputStream.write() throws IOException when redirecting stdout in native code (1.4.2, win)

XMLWordPrintable

    • x86
    • windows_2000

      There is a Windows C problem, using JNI when creating a JVM to run a simple
      Java problem (System.out.println("Hello World")).

      If redirection of stdout to a file is done on the C side before creating the
      JVM, the output does not appear in the file and an IOException is thrown

      Detail Analysis:

      Customer has written a simple java class which simulates the
      this problem. It will print out the IOException whenever write() fails.
      The following exception is seen:

      java.io.IOException: The handle is invalid
           at java.io.FileOutputStream.writeBytes(Native Method)
           at java.io.FileOutputStream.write(FileOutputStream.java:260)
           at java.io.BufferedOutputStream.flushBuffer
      BufferedOutputStream.java:66)
           at
      java.io.BufferedOutputStream.flush(BufferedOutputStream.java:124)
           at IntClient_jni.Los(PrintStream_Sim.java:12)




      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      1) Write a simple "Hello World" Java program which uses
      System.out.println("Hello World");

      2) Write a C program that does the following:
           a)redirect stdout to a log file (freopen)
           b)using JNI to create JVM
           c)run the main() method of the Java program by using JNI.

      You will not see the "Hello World" in the file. But if you take out
      the stdout redirection from the C program, you will see the Hello World from
      console and no exception on Java side.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      You should see the System.out redirect output to the log file if we
      redirect the stdout from C side before creating JVM.

      ACTUAL BEHAVIOR - There is printout in the redirected log file and
       an exception is seen: java.io.IOException: The handle is invalid
           at java.io.FileOutputStream.writeBytes(Native Method)
           at java.io.FileOutputStream.write(FileOutputStream.java:260)
           at
      java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:66)
           at
      java.io.BufferedOutputStream.flush(BufferedOutputStream.java:124)
           at IntClient_jni.Los(PrintStream_Sim.java:12)

      exception on Java side.

      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      java.io.IOException: The handle is invalid
           at java.io.FileOutputStream.writeBytes(Native Method)
           at java.io.FileOutputStream.write(FileOutputStream.java:260)
           at
      java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:66)
           at
      java.io.BufferedOutputStream.flush(BufferedOutputStream.java:124)
           at IntClient_jni.Los(PrintStream_Sim.java:12)


      REPRODUCIBILITY :
      This bug is easily reproduced.

      ---------- BEGIN SOURCE ----------
      1) Java Side "Hello World" Program:
          ===========================

      import java.io.*;

      public class PrintStream_Sim{

         public static void main(String [] argv) {
            try {
               FileOutputStream fdOut = new
      FileOutputStream(FileDescriptor.out);
               BufferedOutputStream bout = new BufferedOutputStream(fdOut,
      128);

               bout.write(45);
               bout.flush();
                 } catch (Throwable t) {
               try {
               PrintStream o = new PrintStream(new
      FileOutputStream("mythrowable.txt"));
               t.printStackTrace(o);
               o.close();
                       } catch (Exception e) {}
            }
         }
      }

      2) The C program that creates the JVM and run the Hello World:
          ================================================

      int main(int argc, char* argv[])
      {
              FILE * t = freopen("D:\\temp\\stdout.log", "w", stdout);
                           t = freopen("D:\\temp\\stderr.log", "w", stderr);

              JavaVM *jvm;

              JNIEnv *env;

              JavaVMInitArgs vm_args;

              jclass cls;

              jmethodID mid;

              printf("beginning execution...\n");
              JavaVMOption options[2];
          options[0].optionString =
               "-Djava.class.path=.";
           
              options[1].optionString = "vfprintf";
              options[1].extraInfo = (void*)jio_vfprintf;
           
              vm_args.version = JNI_VERSION_1_2;
              vm_args.options = options;
              vm_args.nOptions = 2;
              vm_args.ignoreUnrecognized = JNI_TRUE;

              jint res = JNI_CreateJavaVM(&jvm, (void **)&env,&vm_args);
              if (res < 0) {
                      printf("Can't create Java VM\n");
                      fflush(stdout);
                      return 1;
              }

              
              /* Find the class */

              cls = env->FindClass("PrintStream_Sim");
              if (cls == 0) {

              fprintf(stderr,
              "Could not locate class your CLASSPATH.\n");
               return 1 ;
              }

              /* Find the method */
              mid = env->GetStaticMethodID(cls, "main",
      "(Ljava/lang/String;)V");
              if (mid == 0) {
              fprintf(stderr, "Could not locate method main with signature
      \n");
              return 1;
              }

              /* Invoke the method */

              env->CallStaticVoidMethod(cls, mid, NULL);

              /* we are done */
              jvm->DestroyJavaVM();
              
              return 0;
      }

      ---------- END SOURCE ----------
      workaround: None

            iris Iris Clark
            atongschsunw Albert Tong-schmidt (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: