harmony-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Vladimir Ivanov (JIRA)" <j...@apache.org>
Subject [jira] Created: (HARMONY-51) java.io.Writer : write(String) should write String as atomic operation.
Date Fri, 27 Jan 2006 08:42:34 GMT
java.io.Writer : write(String) should write String as atomic operation.
-----------------------------------------------------------------------

         Key: HARMONY-51
         URL: http://issues.apache.org/jira/browse/HARMONY-51
     Project: Harmony
        Type: Bug
  Components: Classlib  
    Reporter: Vladimir Ivanov


java.io.Writer : write(String) should write String as atomic operation.

Code to reproduce (Note, the increment of fields due to call of write(String ...) methods
is occurred only after the assertion is checked):
import java.io.*; 
  
public class test29 { 

    public static void main(String args[]) { 
            Object lock = new Object(); 
            final MockWriter w = new MockWriter(lock); 
  
            class Thr extends Thread { 
                int seed; 
  
                Thr(int seed) { 
                    this.seed = seed; 
                } 
  
                public void run() { 
                    try { 
                        switch (seed) { 
                        case 0: 
                            w.write(new char[] { 'a' }); 
                            break; 
                        case 1: 
                            w.write("abcd".toCharArray(), 1, 1); 
                            break; 
                        case 2: 
                                       w.write("c"); 
                            break; 
                        case 3: 
                            w.write("abcd", 3, 1); 
                            break; 
			default:
			    break;
                        } 
                    } catch (Throwable e) { 
                        e.printStackTrace(); 
                    } 
                } 
            } 
  
            try {
	    Thr[] thrs = new Thr[4]; 
            synchronized (lock) { 
                for (int i = 0; i < 4; ++i) { 
                    thrs[i] = new Thr(i); 
                    thrs[i].start(); 
	            Thread.yield(); 
                } 
  
                Thread.sleep(3000); 
  
                System.out.println("" + w.written['a'] + w.written['b'] + w.written['c'] +
w.written['d']) ; 
                System.out.println(("" + w.written['a'] + w.written['b'] + w.written['c']
+ w.written['d']).equals("1100") ? "PASSED" : "FAILED") ; 
  
            } 
  
            for (int i = 0; i < thrs.length; ++i) { 
               thrs[i].join(); 
            } 
            w.close(); 
	    } catch (Exception e) {
		System.out.println("unex: " + e);
	    }
    }
} 
  
class MockWriter extends Writer { 
    public int[] written = new int['z']; 
  
    MockWriter(Object lock) { 
       super(lock); 
    } 
   
  
    public synchronized void close() throws IOException { 
    } 
  
    public synchronized void flush() throws IOException { 
    } 
  
    public void write(char[] arg0, int arg1, int arg2) throws IOException { 
        if (arg1 < 0 || arg2 < 0) { 
            throw new ArrayIndexOutOfBoundsException(); 
        } 
        for (int i = arg1; i < arg1 + arg2; ++i) { 
            ++written[arg0[i]];
	    System.out.println("written.length=" + written.length + ", increment field: " + arg0[i]);
        } 
    } 
} 

Steps to Reproduce: 
1. Build Harmony (check-out on 2006-01-25) j2se subset as described in README.txt. 
2. Compile test29.java using BEA 1.4 javac 
> javac -d . test29.java 
3. Run java using compatible VM (J9) 
> java -showversion test29


Output:
C:\tmp\tmp17>C:\harmony\trunk\deploy\jre\bin\java -showversion test29
java version 1.4.2 (subset)

(c) Copyright 1991, 2005 The Apache Software Foundation or its licensors, as app
licable.
written.length=122, increment field: a
written.length=122, increment field: b
written.length=122, increment field: c
1110
FAILED
written.length=122, increment field: d

C:\tmp\tmp17>C:\jrockit-j2sdk1.4.2_04\bin\java.exe -showversion test29
java version "1.4.2_04"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_04-b05)
BEA WebLogic JRockit(TM) 1.4.2_04 JVM  (build ari-31788-20040616-1132-win-ia32, Native Threads,
GC strategy: parallel)

written.length=122, increment field: a
written.length=122, increment field: b
1100
PASSED
written.length=122, increment field: d
written.length=122, increment field: c

C:\tmp\tmp17>

Suggested fix: add one synchronized section to Writer.java: write(String) method
-------------------------------------------
old code:
	public void write(String str) throws IOException {
		char buf[] = new char[str.length()];
		str.getChars(0, buf.length, buf, 0);
		write(buf);
	}
------------------------------------------
new code:
	public void write(String str) throws IOException {
		char buf[] = new char[str.length()];
		str.getChars(0, buf.length, buf, 0);
		synchronized (lock) {
			write(buf);
		}
	}
-------------------------------------------

junit test:
------------------------ WriterTest.java -------------------------------------------------

import java.io.*; 

import junit.framework.*; 
  
public class WriterTest extends TestCase { 
    public static void main(String[] args) { 
        junit.textui.TestRunner.run(WriterTest.class); 
    } 

    public void testWrite_String() { 
            Object lock = new Object(); 
            final MockWriter w = new MockWriter(lock); 
  
            class Thr extends Thread { 
                int seed; 
  
                Thr(int seed) { 
                    this.seed = seed; 
                } 
  
                public void run() { 
                    try { 
                        switch (seed) { 
                        case 0: 
                            w.write(new char[] { 'a' }); 
                            break; 
                        case 1: 
                            w.write("abcd".toCharArray(), 1, 1); 
                            break; 
                        case 2: 
                                       w.write("c"); 
                            break; 
                        case 3: 
                            w.write("abcd", 3, 1); 
                            break; 
			default:
			    break;
                        } 
                    } catch (Throwable e) { 
                        e.printStackTrace(); 
                    } 
                } 
            } 
  
            try {
                Thr[] thrs = new Thr[4]; 
                synchronized (lock) { 
                    for (int i = 0; i < 4; ++i) { 
                        thrs[i] = new Thr(i); 
                        thrs[i].start(); 
	                Thread.yield(); 
                    } 
  
                    Thread.sleep(3000); 
  
                    assertTrue(("" + w.written['a'] + w.written['b'] + w.written['c'] + w.written['d']).equals("1100"))
; 
  
                } 
  
                for (int i = 0; i < thrs.length; ++i) { 
                   thrs[i].join(); 
                } 
                w.close(); 
	    } catch (Exception e) {
		System.out.println("unex: " + e);
	    }
    }
} 
  
class MockWriter extends Writer { 
    public int[] written = new int['z']; 
  
    MockWriter(Object lock) { 
       super(lock); 
    } 
   
  
    public synchronized void close() throws IOException { 
    } 
  
    public synchronized void flush() throws IOException { 
    } 
  
    public void write(char[] arg0, int arg1, int arg2) throws IOException { 
        if (arg1 < 0 || arg2 < 0) { 
            throw new ArrayIndexOutOfBoundsException(); 
        } 
        for (int i = arg1; i < arg1 + arg2; ++i) { 
            ++written[arg0[i]];
        } 
    } 
} 
 

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
   http://issues.apache.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see:
   http://www.atlassian.com/software/jira


Mime
View raw message