Tim,
Good catch! But I'm afraid it not only a test defect, but also a
possible Harmony implementation bug.
The JavaDoc for String says nothing about synchronization, but Charset's
does: " All of the methods defined in this class are safe for use by
multiple concurrent threads.". So it should be safe to invoke
Charset.encode() concurrently.
Looking inside the Charset.encode(CharBuffer), it has got lock on
itself, the cause is the system wide cached CharsetEncoder instance is
not synchronized[1], so if String.getBytes() always use
Charset.forName() to get the cached charset instance for some certain
encoding, the error won't happen. Probably String create a new Charset
every time. Even so, I think the Charset implementation should be safe
according to spec, so I suggest to also hold lock on the cached
CharsetEncoder during Charset.encode() so that this method is safe
enough to be used concurrently.
comments?
[1] code fragment from Charset.encode()
synchronized public final ByteBuffer encode(CharBuffer buffer) {
CharsetEncoder e = getCachedCharsetEncoder(canonicalName);
...
try {
// e is not safe for concurrent use
return e.encode(buffer);
} catch (CharacterCodingException ex) {
throw new Error(ex.getMessage(), ex);
}
}
Tim Ellison wrote:
The failing test does this (amongst other things):
final int THREAD_NUM = 20;
Thread[] thread = new Thread[THREAD_NUM];
for (int i = 0; i < THREAD_NUM; i++) {
thread[i] = new Thread() {
public void run() {
try {
sink
.write(ByteBuffer.wrap("bytes"
***** .getBytes(ISO8859_1)));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
};
}
for (int i = 0; i < THREAD_NUM; i++) {
thread[i].start();
}
If String#getBytes(String) is not thread safe then we are doomed ;-)
How about:
@@ -104,14 +104,13 @@
public void test_write_LByteBuffer_mutliThread() throws IOException,
InterruptedException {
final int THREAD_NUM = 20;
+ final byte[] strbytes = "bytes".getBytes(ISO8859_1);
Thread[] thread = new Thread[THREAD_NUM];
for (int i = 0; i < THREAD_NUM; i++) {
thread[i] = new Thread() {
public void run() {
try {
- sink
- .write(ByteBuffer.wrap("bytes"
- .getBytes(ISO8859_1)));
+ sink.write(ByteBuffer.wrap(strbytes));
} catch (IOException e) {
throw new RuntimeException(e);
}
Regards,
Tim
Apache Harmony Build wrote:
<snip>
[exec] [junit] java.lang.IllegalStateException
[exec] [junit] at
java.nio.charset.CharsetEncoder.encode(CharsetEncoder.java:480)
[exec] [junit] at
java.nio.charset.CharsetEncoder.encode(CharsetEncoder.java:347)
[exec] [junit] at
java.nio.charset.Charset.encode(Charset.java:639)
[exec] [junit] at java.lang.String.getBytes(String.java:838)
[exec] [junit] at
org.apache.harmony.tests.java.nio.channels.SinkChannelTest$1.run(SinkChannelTest.java:112)
[exec] [junit] Tests FAILED
--
Paulex Yang
China Software Development Lab
IBM
---------------------------------------------------------------------
Terms of use : http://incubator.apache.org/harmony/mailing.html
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]