Synchronisation in Java is a relatively expensive operation, typically requiring about 75 CPU cycles in srcjava. In many cases, Sun's implementations of the standard Java classes e.g. StringBuffer and Vector, are very conservative in their use of synchronisation, thus imposing overhead on single-threaded programs where the synchronisation is not needed.
We designed and implemented a static analyser which would perform a data-flow analysis on allocated objects to determine whether those objects ever became exposed outside their creating threads. If not, accesses to that object by method invocations would not need to be synchronised.
Our initial simple and conservative implementation was able to detect that allocated objects were unexposed only when these objects were accessed exclusively via local variables. Unfortunately, most objects (StringBuffers being the notable exception) tend not to be used in this manner, except by hardened C programmers such as myself. Rather, they are accessed in a more object-oriented way via fields of other, containing objects.
This observation prompted us to design and begin implementation of a second analyser which performs a global analysis of allocated objects, building an exposure dependency graph between objects e.g. the operation x.a=y stores y into x, so that an edge is added from x to y. We believe this analyser will be able to detect a higher proportion of unexposed objects than our first implementation.