RFR: 6206780 (str) Forwarding append methods in String{Buffer, Builder} are inconsistent

Peter Levart peter.levart at gmail.com
Sun Oct 7 22:17:12 UTC 2012


On 10/07/2012 08:42 PM, Alan Bateman wrote:
> On 06/10/2012 01:52, Jim Gish wrote:
>> I've revamped the previous proposed change.  Please review the update 
>> at http://cr.openjdk.java.net/~jgish/Bug6206780-sb-append-forward/ 
>> <http://cr.openjdk.java.net/%7Ejgish/Bug6206780-sb-append-forward/>
>>
>> This revision contains the following additions/changes:
>> 1. consistent usage of @Overrides
>> 2. comments on unsynchronized methods depending on other synchronized 
>> methods
>> 3. overall more code coverage of insert, append, indexOf, 
>> lastIndexOf, etc. for both StringBuffer and StringBuilder
>> 4. testing of StringBuffer to ensure that all public un-synchronized 
>> methods are actually synchronized along their call chain.  the 
>> StringBuffer/TestSynchronization class uses reflection to decide 
>> which methods to test and could be (with a bit of work on method 
>> parameter setup), be used to test any class for these synchronization 
>> properties.  The motivation for this test is to provide some degree 
>> of assurance that modifications to StringBuffer, particularly 
>> addition of new methods, do not break the synchronization contract. 
>> The code also includes a self-test to guard against breaking the test 
>> program itself.
>>
> I'm skimmed over this and StringBuffer looks a lot better, thanks for 
> reverting back and adding the comments.
>
> I don't have time to review the tests just now but it looks like 
> you've added a test of useful tests. I did look at 
> TestSynchronization.testSynchronized and the approach looks right. The 
> timeout is short so there will periodically be false positives but 
> that's okay as increasing the timeout will slow down the test (the 
> main thing I was looking for was the potential for false negatives).
>
> -Alan

Hi Jim,

Here's a way to test for synchronization deterministically. And it takes 
as much time as the testing methods runs (no timeouts):


public class SyncTest
{
     public static class MyClass
     {
         public synchronized void synchronized_method() throws 
InterruptedException
         {
             Thread.sleep(1000);
         }

         public void not_synchronized_method() throws InterruptedException
         {
             Thread.sleep(1000);
         }

         public void indirectly_synchronized_method() throws 
InterruptedException
         {
             Thread.sleep(100);
             synchronized_method();
         }
     }

     private static boolean isSynchronized(Method m, Object target)
     {
         Thread t = new Thread(new InvokeTask(m, target));

         Boolean isSynchronized = null;

         synchronized (target)
         {
             t.start();

             while (isSynchronized == null)
             {
                 switch (t.getState())
                 {
                     case NEW:
                     case RUNNABLE:
                     case WAITING:
                     case TIMED_WAITING:
                         Thread.yield();
                         break;
                     case BLOCKED:
                         isSynchronized = true;
                         break;
                     case TERMINATED:
                         isSynchronized = false;
                         break;
                 }
             }
         }

         try
         {
             t.join();
         }
         catch (InterruptedException ex)
         {
             ex.printStackTrace();
         }

         return isSynchronized;
     }

     public static void main(String[] args)
     {
         Method[] methods = MyClass.class.getDeclaredMethods();
         Object target = new MyClass();

         for (Method m : methods)
         {
             System.out.println(m + " - isSynchronized: " + 
isSynchronized(m, target));;
         }
     }

     static class InvokeTask implements Runnable
     {
         private final Method m;
         private final Object target;
         private final Object[] args;

         InvokeTask(Method m, Object target, Object...args)
         {
             this.m = m;
             this.target = target;
             this.args = args;
         }

         @Override
         public void run()
         {
             try
             {
                 m.invoke(target, args);
             }
             catch (Exception e)
             {
                 e.printStackTrace();
             }
         }
     }
}



Regards, Peter




More information about the core-libs-dev mailing list