6914123: (str) Missing synchronization in java.lang.String#contentEquals(CharSequence)
authorjgish
Fri, 27 Jul 2012 16:17:11 -0400
changeset 13404 8e63aa2e956c
parent 13403 bec625fee309
child 13405 69267890f7d9
6914123: (str) Missing synchronization in java.lang.String#contentEquals(CharSequence) Summary: Change contentEquals( CharSequence cs ) to do synchronization if cs is a StringBuffer Reviewed-by: mduigou Contributed-by: Jim Gish <jim.gish@oracle.com>
jdk/src/share/classes/java/lang/String.java
--- a/jdk/src/share/classes/java/lang/String.java	Wed Aug 01 11:08:11 2012 -0400
+++ b/jdk/src/share/classes/java/lang/String.java	Fri Jul 27 16:17:11 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -987,7 +987,8 @@
     /**
      * Compares this string to the specified {@code StringBuffer}.  The result
      * is {@code true} if and only if this {@code String} represents the same
-     * sequence of characters as the specified {@code StringBuffer}.
+     * sequence of characters as the specified {@code StringBuffer}. This method
+     * synchronizes on the {@code StringBuffer}.
      *
      * @param  sb
      *         The {@code StringBuffer} to compare this {@code String} against
@@ -999,15 +1000,29 @@
      * @since  1.4
      */
     public boolean contentEquals(StringBuffer sb) {
-        synchronized (sb) {
-            return contentEquals((CharSequence) sb);
+        return contentEquals((CharSequence) sb);
+    }
+
+    private boolean nonSyncContentEquals(AbstractStringBuilder sb) {
+        char v1[] = value;
+        char v2[] = sb.getValue();
+        int i = 0;
+        int n = value.length;
+        while (n-- != 0) {
+            if (v1[i] != v2[i]) {
+                return false;
+            }
+            i++;
         }
+        return true;
     }
 
     /**
-     * Compares this string to the specified {@code CharSequence}.  The result
-     * is {@code true} if and only if this {@code String} represents the same
-     * sequence of char values as the specified sequence.
+     * Compares this string to the specified {@code CharSequence}.  The
+     * result is {@code true} if and only if this {@code String} represents the
+     * same sequence of char values as the specified sequence. Note that if the
+     * {@code CharSequence} is a {@code StringBuffer} then the method
+     * synchronizes on it.
      *
      * @param  cs
      *         The sequence to compare this {@code String} against
@@ -1023,16 +1038,13 @@
             return false;
         // Argument is a StringBuffer, StringBuilder
         if (cs instanceof AbstractStringBuilder) {
-            char v1[] = value;
-            char v2[] = ((AbstractStringBuilder) cs).getValue();
-            int i = 0;
-            int n = value.length;
-            while (n-- != 0) {
-                if (v1[i] != v2[i])
-                    return false;
-                i++;
+            if (cs instanceof StringBuffer) {
+                synchronized(cs) {
+                   return nonSyncContentEquals((AbstractStringBuilder)cs);
+                }
+            } else {
+                return nonSyncContentEquals((AbstractStringBuilder)cs);
             }
-            return true;
         }
         // Argument is a String
         if (cs.equals(this))