[ http://issues.apache.org/jira/browse/HARMONY-51?page=all ]
Tim Ellison reassigned HARMONY-51: ---------------------------------- Assign To: Tim Ellison > 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 > Assignee: Tim Ellison > > 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