This is the mail archive of the java-patches@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: Patch: finalizer thread - please comment


>>>>> "Bryce" == Bryce McKinlay <bryce@waitaki.otago.ac.nz> writes:

Bryce> It looks like user code that calls Runtime.runFinalization() is
Bryce> still going to do the wrong thing, because finalization will
Bryce> then be run in the current thread. I think its sufficient to
Bryce> have runFinalization just notify the finalization thread so
Bryce> that it wakes up and does some work, this seems to be what
Bryce> other JVMs do.

I agree.

Bryce> And calling _Jv_GCInitializeFinalizers from posix-threads.cc
Bryce> doesn't seem right, that should be in _Jv_CreateJavaVM too?

Yes.

New patch appended.  What do you think?
I still haven't built a no-threads version, but I will before I check
anything in.

Tom

Index: ChangeLog
from  Tom Tromey  <tromey@redhat.com>

	* gnu/gcj/runtime/natFinalizerThread.cc: New file.
	* java/lang/natRuntime.cc: Include FinalizerThread.h.
	(runFinalization): Call finalizerReady.
	* nogc.cc (_Jv_GCInitializeFinalizers): New function.
	* prims.cc: Include VirtualMachineError.h, FinalizerThread.h.
	(_Jv_CreateJavaVM): Start the finalizer thread.
	* no-threads.cc: Include InternalError.h.
	(_Jv_ThreadInitData): Throw InternalError if thread already
	running.
	(_Jv_ThreadStart): Throw InternalError.
	* Makefile.in: Rebuilt.
	* Makefile.am (ordinary_java_source_files): Added
	FinalizerThread.java.
	(nat_source_files): Added natFinalizerThread.cc.
	* include/jvm.h (_Jv_GCInitializeFinalizers): Declare.
	* boehm.cc (_Jv_GCInitializeFinalizers): New function.
	* gnu/gcj/runtime/FirstThread.java (run): Start finalizer thread.
	* gnu/gcj/runtime/FinalizerThread.java: New file.

Index: Makefile.am
===================================================================
RCS file: /cvs/gcc/gcc/libjava/Makefile.am,v
retrieving revision 1.174
diff -u -r1.174 Makefile.am
--- Makefile.am 2001/10/02 22:49:53 1.174
+++ Makefile.am 2001/10/09 20:09:14
@@ -1137,6 +1137,7 @@
 gnu/gcj/protocol/jar/Connection.java \
 gnu/gcj/protocol/jar/Handler.java \
 gnu/gcj/runtime/FileDeleter.java \
+gnu/gcj/runtime/FinalizerThread.java \
 gnu/gcj/runtime/FirstThread.java \
 gnu/gcj/runtime/SharedLibLoader.java \
 gnu/gcj/runtime/VMClassLoader.java \
@@ -1495,6 +1496,7 @@
 gnu/gcj/io/natSimpleSHSStream.cc \
 gnu/gcj/io/shs.cc \
 gnu/gcj/protocol/core/natCoreInputStream.cc \
+gnu/gcj/runtime/natFinalizerThread.cc \
 gnu/gcj/runtime/natFirstThread.cc \
 gnu/gcj/runtime/natSharedLibLoader.cc \
 java/io/natFile.cc \
Index: boehm.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/boehm.cc,v
retrieving revision 1.28
diff -u -r1.28 boehm.cc
--- boehm.cc 2001/10/02 14:31:42 1.28
+++ boehm.cc 2001/10/09 20:09:17
@@ -544,6 +544,13 @@
 #endif /* JV_HASH_SYNCHRONIZATION */
 
 void
+_Jv_GCInitializeFinalizers (void (*notifier) (void))
+{
+  GC_finalize_on_demand = 1;
+  GC_finalizer_notifier = notifier;
+}
+
+void
 _Jv_GCRegisterDisappearingLink (jobject *objp)
 {
   GC_general_register_disappearing_link ((GC_PTR *) objp, (GC_PTR) *objp);
Index: no-threads.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/no-threads.cc,v
retrieving revision 1.7
diff -u -r1.7 no-threads.cc
--- no-threads.cc 2001/09/21 07:46:32 1.7
+++ no-threads.cc 2001/10/09 20:09:17
@@ -1,6 +1,6 @@
 // no-thread.cc - Implementation of `no threads' threads.
 
-/* Copyright (C) 1998, 1999  Free Software Foundation
+/* Copyright (C) 1998, 1999, 2001  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -13,6 +13,7 @@
 #include <gcj/cni.h>
 #include <jvm.h>
 #include <java/lang/Thread.h>
+#include <java/lang/InternalError.h>
 
 java::lang::Thread *_Jv_OnlyThread = NULL;
 
@@ -22,7 +23,7 @@
   // Don't use JvAssert, since we want this to fail even when compiled
   // without assertions.
   if (_Jv_OnlyThread)
-    JvFail ("only thread already running");
+    throw new java::lang::InternalError (JvNewStringLatin1 ("only thread already running"));
   _Jv_OnlyThread = thread;
   return NULL;
 }
@@ -30,5 +31,5 @@
 void
 _Jv_ThreadStart (java::lang::Thread *, _Jv_Thread_t *, _Jv_ThreadStartFunc *)
 {
-  JvFail ("Thread.start called but threads not available");
+  throw new java::lang::InternalError (JvNewStringLatin1 ("Thread.start called but threads not available"));
 }
Index: nogc.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/nogc.cc,v
retrieving revision 1.10
diff -u -r1.10 nogc.cc
--- nogc.cc 2001/09/10 01:21:08 1.10
+++ nogc.cc 2001/10/09 20:09:17
@@ -92,6 +92,11 @@
 }
 
 void
+_Jv_GCInitializeFinalizers (void (*) (void))
+{
+}
+
+void
 _Jv_RunGC (void)
 {
 }
Index: prims.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/prims.cc,v
retrieving revision 1.59
diff -u -r1.59 prims.cc
--- prims.cc 2001/10/02 13:44:31 1.59
+++ prims.cc 2001/10/09 20:09:18
@@ -53,7 +53,6 @@
 #include <java/lang/String.h>
 #include <java/lang/Thread.h>
 #include <java/lang/ThreadGroup.h>
-#include <gnu/gcj/runtime/FirstThread.h>
 #include <java/lang/ArrayIndexOutOfBoundsException.h>
 #include <java/lang/ArithmeticException.h>
 #include <java/lang/ClassFormatError.h>
@@ -64,7 +63,10 @@
 #include <java/lang/reflect/Modifier.h>
 #include <java/io/PrintStream.h>
 #include <java/lang/UnsatisfiedLinkError.h>
+#include <java/lang/VirtualMachineError.h>
 #include <gnu/gcj/runtime/VMClassLoader.h>
+#include <gnu/gcj/runtime/FinalizerThread.h>
+#include <gnu/gcj/runtime/FirstThread.h>
 
 #ifdef USE_LTDL
 #include <ltdl.h>
@@ -893,6 +895,21 @@
 #endif
 
   _Jv_JNI_Init ();
+
+  _Jv_GCInitializeFinalizers (&::gnu::gcj::runtime::FinalizerThread::finalizerReady);
+
+  // Start the GC finalizer thread.  A VirtualMachineError can be
+  // thrown by the runtime if, say, threads aren't available.  In this
+  // case finalizers simply won't run.
+  try
+    {
+      using namespace gnu::gcj::runtime;
+      FinalizerThread *ft = new FinalizerThread ();
+      ft->start ();
+    }
+  catch (java::lang::VirtualMachineError *ignore)
+    {
+    }
 
   return 0;
 }
Index: gnu/gcj/runtime/FinalizerThread.java
===================================================================
RCS file: FinalizerThread.java
diff -N FinalizerThread.java
--- /dev/null	Tue May  5 13:32:27 1998
+++ gnu/gcj/runtime/FinalizerThread.java Tue Oct 9 13:09:18 2001
@@ -0,0 +1,73 @@
+// FinalizerThread.java -- Thread in which finalizers are run.
+
+/* Copyright (C) 2001  Free Software Foundation
+
+   This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
+details.  */
+
+package gnu.gcj.runtime;
+
+/**
+ * @author Tom Tromey <tromey@redhat.com>
+ * @date October 3, 2001
+ */
+public final class FinalizerThread extends Thread
+{
+  // Finalizers must be run in a thread with no Java-visible locks
+  // held.  This qualifies because we don't make the lock visible.
+  private static final Object lock = new Object ();
+
+  // This is true if the finalizer thread started successfully.  It
+  // might be false if, for instance, there are no threads on the
+  // current platform.  In this situation we run finalizers in the
+  // caller's thread.
+  private static boolean thread_started = false;
+
+  public FinalizerThread ()
+  {
+    super ("LibgcjInternalFinalizerThread");
+    setDaemon (true);
+  }
+
+  // This is called by the runtime when a finalizer is ready to be
+  // run.  It simply wakes up the finalizer thread.
+  public static void finalizerReady ()
+  {
+    synchronized (lock)
+      {
+	if (! thread_started)
+	  runFinalizers ();
+	else
+	  lock.notify ();
+      }
+  }
+
+  // Actually run the finalizers.
+  private static native void runFinalizers ();
+
+  public void run ()
+  {
+    // Wait on a lock.  Whenever we wake up, try to invoke the
+    // finalizers.
+    synchronized (lock)
+      {
+	thread_started = true;
+	while (true)
+	  {
+	    try
+	      {
+		lock.wait ();
+	      }
+	    catch (InterruptedException _)
+	      {
+		// Just ignore it.  It doesn't hurt to run finalizers
+		// when none are pending.
+	      }
+	    runFinalizers ();
+	  }
+      }
+  }
+}
Index: gnu/gcj/runtime/FirstThread.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/gcj/runtime/FirstThread.java,v
retrieving revision 1.9
diff -u -r1.9 FirstThread.java
--- gnu/gcj/runtime/FirstThread.java 2001/08/26 11:30:08 1.9
+++ gnu/gcj/runtime/FirstThread.java 2001/10/09 20:09:18
@@ -1,6 +1,6 @@
 // FirstThread.java - Implementation of very first thread.
 
-/* Copyright (C) 1998, 1999, 2000  Free Software Foundation
+/* Copyright (C) 1998, 1999, 2000, 2001  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -33,12 +33,12 @@
     this.args = args;
     this.is_jar = is_jar;
   }
-  
+
   public void run()
   {
     if (is_jar)
       klass_name = getMain(klass_name);
-    
+
     if (klass == null)
       {
         try
@@ -50,7 +50,7 @@
 	    throw new NoClassDefFoundError(klass_name);
 	  }
       }
-    
+
     call_main();
   }
 
Index: gnu/gcj/runtime/natFinalizerThread.cc
===================================================================
RCS file: natFinalizerThread.cc
diff -N natFinalizerThread.cc
--- /dev/null	Tue May  5 13:32:27 1998
+++ gnu/gcj/runtime/natFinalizerThread.cc Tue Oct 9 13:09:18 2001
@@ -0,0 +1,22 @@
+// natFinalizerThread.cc - Implementation of FinalizerThread native methods.
+
+/* Copyright (C) 2001  Free Software Foundation
+
+   This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
+details.  */
+
+#include <config.h>
+
+#include <gcj/cni.h>
+#include <jvm.h>
+
+#include <gnu/gcj/runtime/FinalizerThread.h>
+
+void
+gnu::gcj::runtime::FinalizerThread::runFinalizers ()
+{
+  _Jv_RunFinalizers ();
+}
Index: include/jvm.h
===================================================================
RCS file: /cvs/gcc/gcc/libjava/include/jvm.h,v
retrieving revision 1.41
diff -u -r1.41 jvm.h
--- include/jvm.h 2001/10/02 14:31:45 1.41
+++ include/jvm.h 2001/10/09 20:09:19
@@ -157,6 +157,9 @@
    memory.  */
 void *_Jv_MallocUnchecked (jsize size) __attribute__((__malloc__));
 
+/* Initialize finalizers.  The argument is a function to be called
+   when a finalizer is ready to be run.  */
+void _Jv_GCInitializeFinalizers (void (*notifier) (void));
 /* Run finalizers for objects ready to be finalized..  */
 void _Jv_RunFinalizers (void);
 /* Run all finalizers.  Should be called only before exit.  */
Index: java/lang/natRuntime.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/lang/natRuntime.cc,v
retrieving revision 1.18
diff -u -r1.18 natRuntime.cc
--- java/lang/natRuntime.cc 2001/06/15 23:22:02 1.18
+++ java/lang/natRuntime.cc 2001/10/09 20:09:19
@@ -18,6 +18,7 @@
 #include <java/lang/UnknownError.h>
 #include <java/lang/UnsatisfiedLinkError.h>
 #include <gnu/gcj/runtime/FileDeleter.h>
+#include <gnu/gcj/runtime/FinalizerThread.h>
 
 #include <jni.h>
 
@@ -208,7 +209,7 @@
 void
 java::lang::Runtime::runFinalization (void)
 {
-  _Jv_RunFinalizers ();
+  gnu::gcj::runtime::FinalizerThread::finalizerReady ();
 }
 
 jlong


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]