* 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_ThreadStart): Throw InternalError.
(_Jv_ThreadInitData): Don't throw error if this is not the first
thread.
* 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.
From-SVN: r46163
+2001-10-10 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_ThreadStart): Throw InternalError.
+ (_Jv_ThreadInitData): Don't throw error if this is not the first
+ thread.
+ * 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.
+
2001-10-09 Per Bothner <per@bothner.com>
* strtod.c (_strtod_r): Logic to check for missing digits
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 \
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 \
mkinstalldirs = @mkinstalldirs@
AUTOMAKE_OPTIONS = foreign
-@TESTSUBDIR_TRUE@SUBDIRS = @TESTSUBDIR_TRUE@$(DIRLTDL) testsuite gcj include
-@TESTSUBDIR_FALSE@SUBDIRS = @TESTSUBDIR_FALSE@$(DIRLTDL) gcj include
-@USE_LIBDIR_TRUE@toolexeclibdir = @USE_LIBDIR_TRUE@$(libdir)$(MULTISUBDIR)
-@USE_LIBDIR_FALSE@toolexeclibdir = @USE_LIBDIR_FALSE@$(toolexecdir)/lib$(MULTISUBDIR)
-@USE_LIBDIR_FALSE@toolexecdir = @USE_LIBDIR_FALSE@$(exec_prefix)/$(target_alias)
-@XLIB_AWT_TRUE@cond_x_ltlibrary = @XLIB_AWT_TRUE@libgcjx.la
-@XLIB_AWT_FALSE@cond_x_ltlibrary =
+@TESTSUBDIR_TRUE@SUBDIRS = \
+@TESTSUBDIR_TRUE@$(DIRLTDL) testsuite gcj include
+@TESTSUBDIR_FALSE@SUBDIRS = \
+@TESTSUBDIR_FALSE@$(DIRLTDL) gcj include
+@USE_LIBDIR_TRUE@toolexeclibdir = \
+@USE_LIBDIR_TRUE@$(libdir)$(MULTISUBDIR)
+@USE_LIBDIR_FALSE@toolexeclibdir = \
+@USE_LIBDIR_FALSE@$(toolexecdir)/lib$(MULTISUBDIR)
+@USE_LIBDIR_FALSE@toolexecdir = \
+@USE_LIBDIR_FALSE@$(exec_prefix)/$(target_alias)
+@XLIB_AWT_TRUE@cond_x_ltlibrary = \
+@XLIB_AWT_TRUE@libgcjx.la
+@XLIB_AWT_FALSE@cond_x_ltlibrary = \
toolexeclib_LTLIBRARIES = libgcj.la $(cond_x_ltlibrary)
toolexeclib_DATA = libgcj.spec
data_DATA = libgcj.jar
-@NATIVE_TRUE@bin_PROGRAMS = @NATIVE_TRUE@jv-convert gij rmic rmiregistry
+@NATIVE_TRUE@bin_PROGRAMS = \
+@NATIVE_TRUE@jv-convert gij rmic rmiregistry
bin_SCRIPTS = addr2name.awk
-@CANADIAN_TRUE@@NULL_TARGET_TRUE@ZIP = @CANADIAN_TRUE@@NULL_TARGET_TRUE@$(MULTIBUILDTOP)../$(COMPPATH)/fastjar/jar$(EXEEXT)
-@CANADIAN_TRUE@@NULL_TARGET_FALSE@ZIP = @CANADIAN_TRUE@@NULL_TARGET_FALSE@jar
-@CANADIAN_FALSE@ZIP = @CANADIAN_FALSE@$(MULTIBUILDTOP)../$(COMPPATH)/fastjar/jar$(EXEEXT)
-@CANADIAN_TRUE@GCJH = @CANADIAN_TRUE@gcjh
-@CANADIAN_FALSE@GCJH = @CANADIAN_FALSE@$(MULTIBUILDTOP)../$(COMPPATH)/gcc/gcjh$(EXEEXT)
+@CANADIAN_TRUE@@NULL_TARGET_TRUE@ZIP = \
+@CANADIAN_TRUE@@NULL_TARGET_TRUE@$(MULTIBUILDTOP)../$(COMPPATH)/fastjar/jar$(EXEEXT)
+@CANADIAN_TRUE@@NULL_TARGET_FALSE@ZIP = \
+@CANADIAN_TRUE@@NULL_TARGET_FALSE@jar
+@CANADIAN_FALSE@ZIP = \
+@CANADIAN_FALSE@$(MULTIBUILDTOP)../$(COMPPATH)/fastjar/jar$(EXEEXT)
+@CANADIAN_TRUE@GCJH = \
+@CANADIAN_TRUE@gcjh
+@CANADIAN_FALSE@GCJH = \
+@CANADIAN_FALSE@$(MULTIBUILDTOP)../$(COMPPATH)/gcc/gcjh$(EXEEXT)
GCJ_WITH_FLAGS = $(GCJ) --encoding=UTF-8
@LIBGCJ_CXXFLAGS@ @X_CFLAGS@ $(WARNINGS) -D_GNU_SOURCE \
-DPREFIX="\"$(prefix)\""
-@USING_GCC_TRUE@AM_CFLAGS = @USING_GCC_TRUE@@LIBGCJ_CFLAGS@ $(WARNINGS)
-@USING_GCC_FALSE@AM_CFLAGS = @USING_GCC_FALSE@@LIBGCJ_CFLAGS@
+@USING_GCC_TRUE@AM_CFLAGS = \
+@USING_GCC_TRUE@@LIBGCJ_CFLAGS@ $(WARNINGS)
+@USING_GCC_FALSE@AM_CFLAGS = \
+@USING_GCC_FALSE@@LIBGCJ_CFLAGS@
JCFLAGS = -g
JC1FLAGS = @LIBGCJ_JAVAFLAGS@ $(GCJFLAGS)
NM = nm
-@NATIVE_TRUE@@MAINTAINER_MODE_TRUE@noinst_PROGRAMS = @NATIVE_TRUE@@MAINTAINER_MODE_TRUE@gen-from-JIS
+@NATIVE_TRUE@@MAINTAINER_MODE_TRUE@noinst_PROGRAMS = \
+@NATIVE_TRUE@@MAINTAINER_MODE_TRUE@gen-from-JIS
CONVERT_DIR = gnu/gcj/convert
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 \
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 \
gnu/gcj/convert/natInput_SJIS.lo gnu/gcj/convert/natOutput_EUCJIS.lo \
gnu/gcj/convert/natOutput_SJIS.lo gnu/gcj/io/natSimpleSHSStream.lo \
gnu/gcj/io/shs.lo gnu/gcj/protocol/core/natCoreInputStream.lo \
-gnu/gcj/runtime/natFirstThread.lo gnu/gcj/runtime/natSharedLibLoader.lo \
-java/io/natFile.lo java/io/natFileDescriptor.lo \
-java/io/natObjectInputStream.lo java/io/natObjectOutputStream.lo \
-java/lang/natCharacter.lo java/lang/natClass.lo \
-java/lang/natClassLoader.lo java/lang/natConcreteProcess.lo \
-java/lang/natDouble.lo java/lang/natFloat.lo java/lang/natMath.lo \
-java/lang/natObject.lo java/lang/natRuntime.lo java/lang/natString.lo \
+gnu/gcj/runtime/natFinalizerThread.lo gnu/gcj/runtime/natFirstThread.lo \
+gnu/gcj/runtime/natSharedLibLoader.lo java/io/natFile.lo \
+java/io/natFileDescriptor.lo java/io/natObjectInputStream.lo \
+java/io/natObjectOutputStream.lo java/lang/natCharacter.lo \
+java/lang/natClass.lo java/lang/natClassLoader.lo \
+java/lang/natConcreteProcess.lo java/lang/natDouble.lo \
+java/lang/natFloat.lo java/lang/natMath.lo java/lang/natObject.lo \
+java/lang/natRuntime.lo java/lang/natString.lo \
java/lang/natStringBuffer.lo java/lang/natSystem.lo \
java/lang/natThread.lo java/lang/natThrowable.lo \
java/lang/ref/natReference.lo java/lang/reflect/natArray.lo \
.deps/gnu/gcj/protocol/http/Handler.P \
.deps/gnu/gcj/protocol/jar/Connection.P \
.deps/gnu/gcj/protocol/jar/Handler.P \
-.deps/gnu/gcj/runtime/FileDeleter.P .deps/gnu/gcj/runtime/FirstThread.P \
+.deps/gnu/gcj/runtime/FileDeleter.P \
+.deps/gnu/gcj/runtime/FinalizerThread.P \
+.deps/gnu/gcj/runtime/FirstThread.P \
.deps/gnu/gcj/runtime/SharedLibLoader.P \
.deps/gnu/gcj/runtime/VMClassLoader.P \
+.deps/gnu/gcj/runtime/natFinalizerThread.P \
.deps/gnu/gcj/runtime/natFirstThread.P \
.deps/gnu/gcj/runtime/natSharedLibLoader.P .deps/gnu/gcj/xlib/Clip.P \
.deps/gnu/gcj/xlib/Colormap.P .deps/gnu/gcj/xlib/Display.P \
@for file in $(DISTFILES); do \
d=$(srcdir); \
if test -d $$d/$$file; then \
- cp -pr $$d/$$file $(distdir)/$$file; \
+ cp -pr $$/$$file $(distdir)/$$file; \
else \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
#endif /* JV_HASH_SYNCHRONIZATION */
+void
+_Jv_GCInitializeFinalizers (void (*notifier) (void))
+{
+ GC_finalize_on_demand = 1;
+ GC_finalizer_notifier = notifier;
+}
+
void
_Jv_GCRegisterDisappearingLink (jobject *objp)
{
--- /dev/null
+// 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 ();
+ }
+ }
+ }
+}
// 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.
this.args = args;
this.is_jar = is_jar;
}
-
+
public void run()
{
if (is_jar)
klass_name = getMain(klass_name);
-
+
if (klass == null)
{
try
throw new NoClassDefFoundError(klass_name);
}
}
-
+
call_main();
}
--- /dev/null
+// 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 ();
+}
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. */
#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>
void
java::lang::Runtime::runFinalization (void)
{
- _Jv_RunFinalizers ();
+ gnu::gcj::runtime::FinalizerThread::finalizerReady ();
}
jlong
// 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.
#include <gcj/cni.h>
#include <jvm.h>
#include <java/lang/Thread.h>
+#include <java/lang/InternalError.h>
java::lang::Thread *_Jv_OnlyThread = NULL;
_Jv_Thread_t *
-_Jv_ThreadInitData (java::lang::Thread * thread)
+_Jv_ThreadInitData (java::lang::Thread *thread)
{
- // Don't use JvAssert, since we want this to fail even when compiled
- // without assertions.
- if (_Jv_OnlyThread)
- JvFail ("only thread already running");
- _Jv_OnlyThread = thread;
+ // It is ok to create a new Thread object, as long as it isn't started.
+ if (_Jv_OnlyThread == NULL)
+ _Jv_OnlyThread = thread;
return NULL;
}
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"));
}
// FIXME: should still run all finalizers.
}
+void
+_Jv_GCInitializeFinalizers (void (*) (void))
+{
+}
+
void
_Jv_RunGC (void)
{
#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>
#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>
_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;
}