By: Tzvetan Mikov (tmikov.delete@this.gmail.com), October 21, 2006 9:24 am
Room: Moderated Discussions
David Wragg (david@wragg.org) on 10/20/06 wrote:
---------------------------
>Java specifies default values for unitialized fields: 0 for ints, null for pointers,
>etc. An implementation can obey this by allocating new objects from zeroed blocks
>(with appropriate barriers around the zeroing process). The problem is the object
>header, particularly the vtable pointer. On an architecture with a suitably relaxed
>memory ordering, a thread might get the address of an object, read a zero vtable
>address, and then try to access the vtable (e.g. for a method call), leading to
>a SIGSEGV. But as part of its many duties, the SIGSEGV handler can detect this
>rare case and fix it up (probably by resuming execution at an appropriate safepoint).
Very interesting! It certainly is a very creative solution, although it seems a bit hairy. Are you aware of any implementation, not necessarily Java, that uses this kind of trick to fix threading problems ?
>Your basic point stands, and your example Java code should be considered buggy:
>The caller might find that it gets a valid object back, but all the fields are null,
>0, etc. It does need to synchronize, though not necessarily during expensive initialization activity. E.g.
>[...]
>The advantage is that you don't hold the lock for a long time, in order to avoid
>contending with other uses of the same lock. Of course, at that point you might
>well decide to use a dedicated lock and synchronize over the whole method, to ensure
>that you don't create redundant objects.
I think that in this case using volatile is much better. It is cheaper than synchronization, and the basic premise of the code is that it is OK to create redundant objects at first.
I just checked Sun's JDK - they use use this pattern with a volatile declaration in the implementation of java.lang.Class. So I was probably wrong of accusing Sun of shipping a buggy.
---------------------------
>Java specifies default values for unitialized fields: 0 for ints, null for pointers,
>etc. An implementation can obey this by allocating new objects from zeroed blocks
>(with appropriate barriers around the zeroing process). The problem is the object
>header, particularly the vtable pointer. On an architecture with a suitably relaxed
>memory ordering, a thread might get the address of an object, read a zero vtable
>address, and then try to access the vtable (e.g. for a method call), leading to
>a SIGSEGV. But as part of its many duties, the SIGSEGV handler can detect this
>rare case and fix it up (probably by resuming execution at an appropriate safepoint).
Very interesting! It certainly is a very creative solution, although it seems a bit hairy. Are you aware of any implementation, not necessarily Java, that uses this kind of trick to fix threading problems ?
>Your basic point stands, and your example Java code should be considered buggy:
>The caller might find that it gets a valid object back, but all the fields are null,
>0, etc. It does need to synchronize, though not necessarily during expensive initialization activity. E.g.
>[...]
>The advantage is that you don't hold the lock for a long time, in order to avoid
>contending with other uses of the same lock. Of course, at that point you might
>well decide to use a dedicated lock and synchronize over the whole method, to ensure
>that you don't create redundant objects.
I think that in this case using volatile is much better. It is cheaper than synchronization, and the basic premise of the code is that it is OK to create redundant objects at first.
I just checked Sun's JDK - they use use this pattern with a volatile declaration in the implementation of java.lang.Class. So I was probably wrong of accusing Sun of shipping a buggy.