JDK-8014814 : (str) StringBuffer "null" is not appended
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.lang
  • Affected Version: 8
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • Submitted: 2013-05-17
  • Updated: 2013-06-14
  • Resolved: 2013-05-23
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 8
8 b93Fixed
Related Reports
Relates :  
Relates :  
Description
sb1.append("TEST").append((CharSequence)null) , this works as expected. 
But if the second append is called after toString(), "null" is then not appended.

public class TestAppendNull {
    
    public static void main(String[] args) {
        
        StringBuffer sb1 = new StringBuffer();
        sb1.append("TEST");
        System.out.println(sb1.toString());

        sb1.append((CharSequence)null);
        System.out.println("Expected: TESTnull");
        System.out.println("Result: " + sb1.toString());
    }

}

bash-3.2$ $JAVA_HOME/bin/java TestAppendNull
TEST
Expected: TESTnull
Result: TEST


SQE test 
java_lang/Bug4812591
failed due to this issue
Comments
Note that this is not really a regression but exposes a bug introduced by 8010849.
21-05-2013

Thanks for the analysis and suggested fix Alan. Indeed this exposes an existing bug that could break StringBuffer. The StringBuffer append(CharSequence cs) method claimed to achieve synchronization (and then correct toStringCache behaviour) by the super.append method calling other StringBuffer methods after narrowing of cs to a specific type. But that is incorrect if cs==null as in that case the AbstractStringBuilder.appendNull method is called directly, with no calls to an overridden StringBuffer method. (I have verified that none of the other methods claiming to not need sync suffer from a similar flaw - this is an isolated case.) I would propose a simpler fix is to just model append(CharSequence) on append(String) and append(StringBuffer) - make it synchronized and clear the cache. In both cases you will end up with redundant nested synchronization for some usages, but at least this form of the change only impacts StringBuffer. I will also augment to ToStringCacheTest to check for the appendNull case.
20-05-2013

Regression caused by JDK-8013395. Also a possible bug in JDK-8010849 too as appendNull doesn't synchronize. This gets it working append, need to add a test too. diff --git a/src/share/classes/java/lang/AbstractStringBuilder.java b/src/share/classes/java/lang/AbstractStringBuilder.java --- a/src/share/classes/java/lang/AbstractStringBuilder.java +++ b/src/share/classes/java/lang/AbstractStringBuilder.java @@ -461,7 +461,7 @@ return this.append(s, 0, s.length()); } - private AbstractStringBuilder appendNull() { + AbstractStringBuilder appendNull() { int c = count; ensureCapacityInternal(c + 4); final char[] value = this.value; diff --git a/src/share/classes/java/lang/StringBuffer.java b/src/share/classes/java/lang/StringBuffer.java --- a/src/share/classes/java/lang/StringBuffer.java +++ b/src/share/classes/java/lang/StringBuffer.java @@ -343,6 +343,12 @@ return this; } + @Override + synchronized AbstractStringBuilder appendNull() { + toStringCache = null; + return super.appendNull(); + } + /** * @throws IndexOutOfBoundsException {@inheritDoc} * @since 1.5
17-05-2013