Name: moC74494 Date: 02/27/98
Garbage collection deadlocks with class constructor
(usually String.<init>), if any synchronization is
encountered in a finalize() method.
Initially encountered in a finalize() method for an
I/O class, which tidied up files (requiring
synchronization) but reproduced with the simple
'FinalizeLock' test program supplied.
(problem found under JDK.1.1.3, and reproduced under JDK.1.1.5)
------------------- VM THREAD DUMP ----------------
Full thread dump:
"Allocator" (TID:0xf73c48, sys_thread_t:0x87f350, Win32ID:0x88, state:CW) prio=5
java.lang.String.<init>(String.java:118)
FinalizeLock.allocate(FinalizeLock.java:86)
FinalizeLock$Allocator.run(FinalizeLock.java:18)
"Finalizer thread" (TID:0xf70088, sys_thread_t:0x874d70, Win32ID:0xbb, state:MW) prio=2
FinalizeLock.close(FinalizeLock.java:66)
FinalizeLock$ToDie.finalize(FinalizeLock.java:36)
"main" (TID:0xf700b0, sys_thread_t:0x87d720, Win32ID:0xd3, state:S) prio=5
java.lang.Thread.suspend(Thread.java:657)
FinalizeLock.main(FinalizeLock.java:48)
Monitor Cache Dump:
FinalizeLock@F73C58/FBC6F0: owner "Allocator" (0x87f350, 1 entry)
Registered Monitor Dump:
Thread queue lock: <unowned>
Name and type hash table lock: <unowned>
String intern lock: <unowned>
JNI pinning lock: <unowned>
JNI global reference lock: <unowned>
BinClass lock: <unowned>
Class loading lock: <unowned>
Java stack lock: <unowned>
Code rewrite lock: <unowned>
Heap lock: <unowned>
Has finalization queue lock: <unowned>
Finalize me queue lock: <unowned>
Waiters: 1
Monitor registry: <unowned>
-------------------- TEST PROGRAM -------------------------
// Class to test the behavior of implicit GC operation
// when there is a locked finalizer thread
public class FinalizeLock
{
boolean oFinalizing = false;
// Thread to run the allocation method
class Allocator extends Thread
{
Allocator()
{
setName("Allocator");
}
public void run()
{
allocate();
}
}
// Class used for the sole purpose of having finalize called
class ToDie
{
int id = 0;
ToDie(int i)
{
id = i;
System.out.println(" New ToDie no. " + id);
}
public void finalize()
{
System.out.println(" Finalizing ToDie no. " + id);
oFinalizing = true;
close(id);
}
}
// Start a new instance, and call the GC in order to lock the finalizer thread
public static void main(String[] argv)
{
FinalizeLock xFL = new FinalizeLock();
System.gc();
System.out.println("GC called");
Thread.currentThread().suspend();
}
// Start up the thread that does the allocation, and create a few objects that will
// be garbage collected when GC runs.
FinalizeLock()
{
Allocator xA = new Allocator();
xA.start();
for (int i=0; i < 10; i++)
{
ToDie td = new ToDie(i);
}
}
// Synchronized close - the Finalizer thread will wait here.
synchronized public void close(int i)
{
System.out.println("Done close for: " + i);
}
// Create loads of strings and stuff them into a vector so as not to lose them.
synchronized public void allocate()
{
java.util.Vector v = new java.util.Vector();
System.out.println("Allocate called, waiting for finalizer");
// Wait for the finalizer to run
while (!oFinalizing);
System.out.println("Now allocating strings");
for (int i=0;;i++)
{
//System.out.println("Allocating: " + i);
v.addElement( new String("asdhfdsuk"));
}
}
}
(Review ID: 25767)
======================================================================
- duplicates
-
JDK-4091873 (refs) Calling a synchronized method from finalize() can lock VM
-
- Closed
-