-
Bug
-
Resolution: Fixed
-
P3
-
1.1, 1.1.3, 1.1.4
-
1.2fcs
-
generic, sparc
-
solaris_2.5, solaris_2.5.1
-
Not verified
The following is from 20.1.11, the description of the finalize() method of
java.lang.Object:
"It is guaranteed, however, that the thread that invokes finalize will not
be holding any user-visible synchronization locks when finalize is invoked."
When our GC implementation synchronously runs finalizers while managing an
allocation failure, they are run in the same thread that requested the memory,
which could be holding any arbitrary user-visible synchronization locks. Thus,
the finalize method could successfully acquire the lock when the state that it
is supposed to enforce mutual exclusion for is inconsistent, because the initial
owner of the lock up on the execution stack cannot expect access to that state
on any arbitrary memory allocation.
The following program demonstrates the violation. The finalize method for the
LockTest object is able to synchronize on the static object "lock" while the
lock is clearly already owned by the main thread of execution.
public class LockTest {
int[] data;
LockTest()
{
data = new int[10000];
}
static Object lock = new Object();
protected void finalize() throws Throwable
{
super.finalize();
synchronized (lock) {
System.out.print(" <<RUNNING FINALIZER>> ");
}
}
public static void main(String[] args)
{
LockTest obj;
int count = 0;
while (true) {
synchronized (lock) {
System.out.print("enter {");
System.out.print(++ count);
obj = new LockTest();
System.out.println("} exit");
}
}
}
}
java.lang.Object:
"It is guaranteed, however, that the thread that invokes finalize will not
be holding any user-visible synchronization locks when finalize is invoked."
When our GC implementation synchronously runs finalizers while managing an
allocation failure, they are run in the same thread that requested the memory,
which could be holding any arbitrary user-visible synchronization locks. Thus,
the finalize method could successfully acquire the lock when the state that it
is supposed to enforce mutual exclusion for is inconsistent, because the initial
owner of the lock up on the execution stack cannot expect access to that state
on any arbitrary memory allocation.
The following program demonstrates the violation. The finalize method for the
LockTest object is able to synchronize on the static object "lock" while the
lock is clearly already owned by the main thread of execution.
public class LockTest {
int[] data;
LockTest()
{
data = new int[10000];
}
static Object lock = new Object();
protected void finalize() throws Throwable
{
super.finalize();
synchronized (lock) {
System.out.print(" <<RUNNING FINALIZER>> ");
}
}
public static void main(String[] args)
{
LockTest obj;
int count = 0;
while (true) {
synchronized (lock) {
System.out.print("enter {");
System.out.print(++ count);
obj = new LockTest();
System.out.println("} exit");
}
}
}
}
- relates to
-
JDK-4041759 possible deadlock between class loading lock and asynchronous finalization
-
- Closed
-