From 2b3d3db68da14b782f8d69ccebc18af04c61ce15 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Tue, 2 Oct 2001 14:31:47 +0000 Subject: javaprims.h: Rebuilt class list. * gcj/javaprims.h: Rebuilt class list. * boehm.cc (_Jv_GCRegisterDisappearingLink): New function. (_Jv_GCCanReclaimSoftReference): New function. * include/jvm.h (_Jv_GCRegisterDisappearingLink): Declare. (_Jv_GCCanReclaimSoftReference): Declare. * java/lang/ref/Reference.java (referent): Now a RawData. (create): Renamed from `created'. Added object argument. (Reference): Don't initialize `referent' here. * Makefile.in: Rebuilt. * Makefile.am (nat_source_files): Added new file. * java/lang/ref/natReference.cc: New file. From-SVN: r45958 --- libjava/ChangeLog | 12 ++ libjava/Makefile.am | 1 + libjava/Makefile.in | 72 ++++---- libjava/boehm.cc | 13 ++ libjava/gcj/javaprims.h | 1 + libjava/include/jvm.h | 7 + libjava/java/lang/ref/Reference.java | 25 ++- libjava/java/lang/ref/natReference.cc | 304 ++++++++++++++++++++++++++++++++++ 8 files changed, 401 insertions(+), 34 deletions(-) create mode 100644 libjava/java/lang/ref/natReference.cc (limited to 'libjava') diff --git a/libjava/ChangeLog b/libjava/ChangeLog index ee54950..e98a208 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -1,5 +1,17 @@ 2001-10-01 Tom Tromey + * gcj/javaprims.h: Rebuilt class list. + * boehm.cc (_Jv_GCRegisterDisappearingLink): New function. + (_Jv_GCCanReclaimSoftReference): New function. + * include/jvm.h (_Jv_GCRegisterDisappearingLink): Declare. + (_Jv_GCCanReclaimSoftReference): Declare. + * java/lang/ref/Reference.java (referent): Now a RawData. + (create): Renamed from `created'. Added object argument. + (Reference): Don't initialize `referent' here. + * Makefile.in: Rebuilt. + * Makefile.am (nat_source_files): Added new file. + * java/lang/ref/natReference.cc: New file. + * prims.cc (_Jv_NewMultiArrayUnchecked): New method. (_Jv_NewMultiArray): Use it. Check each array dimension. (_Jv_NewMultiArray): Likewise. diff --git a/libjava/Makefile.am b/libjava/Makefile.am index d86f120..d99334b 100644 --- a/libjava/Makefile.am +++ b/libjava/Makefile.am @@ -1511,6 +1511,7 @@ java/lang/natStringBuffer.cc \ java/lang/natSystem.cc \ java/lang/natThread.cc \ java/lang/natThrowable.cc \ +java/lang/ref/natReference.cc \ java/lang/reflect/natArray.cc \ java/lang/reflect/natConstructor.cc \ java/lang/reflect/natField.cc \ diff --git a/libjava/Makefile.in b/libjava/Makefile.in index 543be31..5359902 100644 --- a/libjava/Makefile.in +++ b/libjava/Makefile.in @@ -63,16 +63,13 @@ host_alias = @host_alias@ host_triplet = @host@ target_alias = @target_alias@ target_triplet = @target@ -AMTAR = @AMTAR@ AM_RUNTESTFLAGS = @AM_RUNTESTFLAGS@ AR = @AR@ AS = @AS@ -AWK = @AWK@ CC = @CC@ COMPPATH = @COMPPATH@ CXX = @CXX@ CXXCPP = @CXXCPP@ -DEPDIR = @DEPDIR@ DIRLTDL = @DIRLTDL@ DIVIDESPEC = @DIVIDESPEC@ DLLTOOL = @DLLTOOL@ @@ -89,7 +86,6 @@ GCSPEC = @GCSPEC@ GCTESTSPEC = @GCTESTSPEC@ HASH_SYNC_SPEC = @HASH_SYNC_SPEC@ INCLTDL = @INCLTDL@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JC1GCSPEC = @JC1GCSPEC@ LIBFFI = @LIBFFI@ LIBGCJDEBUG = @LIBGCJDEBUG@ @@ -122,34 +118,43 @@ ZINCS = @ZINCS@ ZLIBS = @ZLIBS@ ZLIBSPEC = @ZLIBSPEC@ ZLIBTESTSPEC = @ZLIBTESTSPEC@ -am__include = @am__include@ -am__quote = @am__quote@ here = @here@ -install_sh = @install_sh@ libgcj_basedir = @libgcj_basedir@ 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 @@ -169,8 +174,10 @@ AM_CXXFLAGS = -fno-rtti -fnon-call-exceptions \ @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) @@ -239,7 +246,8 @@ extra_headers = java/lang/Object.h java/lang/Class.h 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 @@ -1243,6 +1251,7 @@ java/lang/natStringBuffer.cc \ java/lang/natSystem.cc \ java/lang/natThread.cc \ java/lang/natThrowable.cc \ +java/lang/ref/natReference.cc \ java/lang/reflect/natArray.cc \ java/lang/reflect/natConstructor.cc \ java/lang/reflect/natField.cc \ @@ -1396,12 +1405,12 @@ 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/reflect/natArray.lo java/lang/reflect/natConstructor.lo \ -java/lang/reflect/natField.lo java/lang/reflect/natMethod.lo \ -java/net/natInetAddress.lo java/net/natPlainDatagramSocketImpl.lo \ -java/net/natPlainSocketImpl.lo java/text/natCollator.lo \ -java/util/natResourceBundle.lo java/util/zip/natDeflater.lo \ -java/util/zip/natInflater.lo +java/lang/ref/natReference.lo java/lang/reflect/natArray.lo \ +java/lang/reflect/natConstructor.lo java/lang/reflect/natField.lo \ +java/lang/reflect/natMethod.lo java/net/natInetAddress.lo \ +java/net/natPlainDatagramSocketImpl.lo java/net/natPlainSocketImpl.lo \ +java/text/natCollator.lo java/util/natResourceBundle.lo \ +java/util/zip/natDeflater.lo java/util/zip/natInflater.lo libgcjx_la_OBJECTS = gnu/gcj/xlib/natClip.lo \ gnu/gcj/xlib/natColormap.lo gnu/gcj/xlib/natDisplay.lo \ gnu/gcj/xlib/natDrawable.lo gnu/gcj/xlib/natFont.lo \ @@ -1445,7 +1454,7 @@ libgcj-test.spec.in libgcj.spec.in DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) -TAR = gtar +TAR = tar GZIP_ENV = --best DIST_SUBDIRS = @DIRLTDL@ testsuite gcj include @DIRLTDL@ gcj include DEP_FILES = .deps/$(srcdir)/$(CONVERT_DIR)/gen-from-JIS.P \ @@ -1841,6 +1850,7 @@ DEP_FILES = .deps/$(srcdir)/$(CONVERT_DIR)/gen-from-JIS.P \ .deps/java/lang/ref/PhantomReference.P .deps/java/lang/ref/Reference.P \ .deps/java/lang/ref/ReferenceQueue.P \ .deps/java/lang/ref/SoftReference.P .deps/java/lang/ref/WeakReference.P \ +.deps/java/lang/ref/natReference.P \ .deps/java/lang/reflect/AccessibleObject.P \ .deps/java/lang/reflect/Array.P .deps/java/lang/reflect/Constructor.P \ .deps/java/lang/reflect/Field.P \ @@ -2483,7 +2493,7 @@ distdir: $(DISTFILES) @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 \ diff --git a/libjava/boehm.cc b/libjava/boehm.cc index 27e332b..19b58ba 100644 --- a/libjava/boehm.cc +++ b/libjava/boehm.cc @@ -543,6 +543,19 @@ _Jv_AllocTraceOne (jsize size /* includes vtable slot */) #endif /* JV_HASH_SYNCHRONIZATION */ +void +_Jv_GCRegisterDisappearingLink (jobject *objp) +{ + GC_general_register_disappearing_link ((GC_PTR *) objp, (GC_PTR) *objp); +} + +jboolean +_Jv_GCCanReclaimSoftReference (jobject obj) +{ + // For now, always reclaim soft references. FIXME. + return true; +} + #if 0 void _Jv_InitGC (void) diff --git a/libjava/gcj/javaprims.h b/libjava/gcj/javaprims.h index e075bc1..d327315 100644 --- a/libjava/gcj/javaprims.h +++ b/libjava/gcj/javaprims.h @@ -192,6 +192,7 @@ extern "Java" class Short; class StackOverflowError; class String; + class String$CaseInsensitiveComparator; class StringBuffer; class StringIndexOutOfBoundsException; class System; diff --git a/libjava/include/jvm.h b/libjava/include/jvm.h index 957869e..259d669 100644 --- a/libjava/include/jvm.h +++ b/libjava/include/jvm.h @@ -166,6 +166,13 @@ void _Jv_RunGC (void); /* Disable and enable GC. */ void _Jv_DisableGC (void); void _Jv_EnableGC (void); +/* Register a disappearing link. This is a field F which should be + cleared when *F is found to be inaccessible. This is used in the + implementation of java.lang.ref.Reference. */ +void _Jv_GCRegisterDisappearingLink (jobject *objp); +/* Return true if OBJECT should be reclaimed. This is used to + implement soft references. */ +jboolean _Jv_GCCanReclaimSoftReference (jobject obj); /* Return approximation of total size of heap. */ long _Jv_GCTotalMemory (void); diff --git a/libjava/java/lang/ref/Reference.java b/libjava/java/lang/ref/Reference.java index 2349033..5a6c663 100644 --- a/libjava/java/lang/ref/Reference.java +++ b/libjava/java/lang/ref/Reference.java @@ -64,8 +64,21 @@ public abstract class Reference /** * The underlying object. This field is handled in a special way by * the garbage collection. + * GCJ LOCAL: + * This is a RawData because it must be disguised from the GC. + * END GCJ LOCAL */ - Object referent; + gnu.gcj.RawData referent; + + /** + * This is like REFERENT but is not scanned by the GC. We keep a + * copy around so that we can see when clear() has been called. + * GCJ LOCAL: + * This field doesn't exist in Classpath; we use it to detect + * clearing. + * END GCJ LOCAL + */ + gnu.gcj.RawData copy; /** * The queue this reference is registered on. This is null, if this @@ -97,7 +110,7 @@ public abstract class Reference */ Reference(Object ref) { - referent = ref; + create (ref); } /** @@ -112,11 +125,16 @@ public abstract class Reference { if (q == null) throw new NullPointerException(); - referent = ref; queue = q; + create (ref); } /** + * Notifies the VM that a new Reference has been created. + */ + private native void create (Object o); + + /** * Returns the object, this reference refers to. * @return the object, this reference refers to, or null if the * reference was cleared. @@ -138,6 +156,7 @@ public abstract class Reference public void clear() { referent = null; + copy = null; } /** diff --git a/libjava/java/lang/ref/natReference.cc b/libjava/java/lang/ref/natReference.cc new file mode 100644 index 0000000..8e316ee --- /dev/null +++ b/libjava/java/lang/ref/natReference.cc @@ -0,0 +1,304 @@ +// natReference.cc - Native code for References + +/* 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. */ + +// Written by Tom Tromey + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +static void finalize_reference (jobject ref); +static void finalize_referred_to_object (jobject obj); + + + +enum weight +{ + SOFT = 0, + WEAK = 1, + FINALIZE = 2, + PHANTOM = 3, + + // This is used to mark the head of a list. + HEAD = 4, + + // This is used to mark a deleted item. + DELETED = 5 +}; + +// Objects of this type are used in the hash table to keep track of +// the mapping between a finalizable object and the various References +// which refer to it. +struct object_list +{ + // The reference object. This is NULL for FINALIZE weight. + jobject reference; + + // The weight of this object. + enum weight weight; + + // Next in list. + object_list *next; +}; + +// Hash table used to hold mapping from object to References. The +// object_list item in the hash holds the object itself in the +// reference field; chained to it are all the references sorted in +// order of weight (lowest first). +static object_list *hash = NULL; + +// Number of slots used in HASH. +static int hash_count = 0; + +// Number of slots total in HASH. Must be power of 2. +static int hash_size = 0; + +static object_list * +find_slot (jobject key) +{ + jint hcode = _Jv_HashCode (key); + /* step must be non-zero, and relatively prime with hash_size. */ + jint step = (hcode ^ (hcode >> 16)) | 1; + int start_index = hcode & (hash_size - 1); + int index = start_index; + int deleted_index = -1; + for (;;) + { + object_list *ptr = &hash[index]; + if (ptr->reference == key) + return ptr; + else if (ptr->reference == NULL) + { + if (deleted_index == -1) + return ptr; + else + return &hash[deleted_index]; + } + else if (ptr->weight == DELETED) + deleted_index = index; + index = (index + step) & (hash_size - 1); + JvAssert (index != start_index); + } +} + +static void +rehash () +{ + if (hash == NULL) + { + hash_size = 1024; + hash = (object_list *) _Jv_Malloc (hash_size * sizeof (object_list)); + memset (hash, 0, hash_size * sizeof (object_list)); + } + else + { + object_list *old = hash; + int i = hash_size; + + hash_size *= 2; + hash = (object_list *) _Jv_Malloc (hash_size * sizeof (object_list)); + memset (hash, 0, hash_size * sizeof (object_list)); + + while (--i >= 0) + { + if (old[i].reference == NULL || old[i].weight == DELETED) + continue; + object_list *newslot = find_slot (old[i].reference); + *newslot = old[i]; + } + + _Jv_Free (old); + } +} + +// Remove a Reference. +static void +remove_from_hash (jobject obj) +{ + java::lang::ref::Reference *ref + = reinterpret_cast (obj); + object_list *head = find_slot (ref->copy); + object_list **link = &head->next; + head = head->next; + + while (head && head->reference != ref) + { + link = &head->next; + head = head->next; + } + + // Remove the slot. + if (head) + { + *link = head->next; + _Jv_Free (head); + } +} + +// FIXME what happens if an object's finalizer creates a Reference to +// the object, and the object has never before been added to the hash? +// Madness! + +// Add an item to the hash table. If the item is new, we also add a +// finalizer item. We keep items in the hash table until they are +// completely collected; this lets us know when an item is new, even +// if it has been resurrected after its finalizer has been run. +static void +add_to_hash (java::lang::ref::Reference *the_reference) +{ + JvSynchronize sync (java::lang::ref::Reference::lock); + + if (3 * hash_count >= 2 * hash_size) + rehash (); + + jobject referent = the_reference->referent; + object_list *item = find_slot (referent); + if (item->reference == NULL) + { + // New item, so make an entry for the finalizer. + item->reference = referent; + item->weight = HEAD; + + item->next = (object_list *) _Jv_Malloc (sizeof (object_list)); + item->next->reference = NULL; + item->next->weight = FINALIZE; + item->next->next = NULL; + ++hash_count; + } + + object_list *n = (object_list *) _Jv_Malloc (sizeof (object_list)); + n->reference = the_reference; + + enum weight w = PHANTOM; + if (java::lang::ref::SoftReference::class$.isInstance (the_reference)) + w = SOFT; + else if (java::lang::ref::WeakReference::class$.isInstance (the_reference)) + w = WEAK; + n->weight = w; + + object_list **link = &item->next; + object_list *iter = *link; + while (iter && iter->weight < n->weight) + { + link = &iter->next; + iter = *link; + } + *link = n; + n->next = (*link) ? (*link)->next : NULL; +} + +// This is called when an object is ready to be finalized. This +// actually implements the appropriate Reference semantics. +static void +finalize_referred_to_object (jobject obj) +{ + JvSynchronize sync (java::lang::ref::Reference::lock); + + object_list *list = find_slot (obj); + object_list *head = list->next; + if (head == NULL) + { + // We have a truly dead object: the object's finalizer has been + // run, all the object's references have been processed, and the + // object is unreachable. There is, at long last, no way to + // resurrect it. + list->weight = DELETED; + --hash_count; + return; + } + + enum weight w = head->weight; + if (w == FINALIZE) + { + // If we have a Reference A to a Reference B, and B is + // finalized, then we have to take special care to make sure + // that B is properly deregistered. This is super gross. FIXME + // will it fail if B's finalizer resurrects B? + if (java::lang::ref::Reference::class$.isInstance (obj)) + finalize_reference (obj); + else + _Jv_FinalizeObject (obj); + list->next = head->next; + _Jv_Free (head); + } + else if (w != SOFT || _Jv_GCCanReclaimSoftReference (obj)) + { + // If we just decided to reclaim a soft reference, we might as + // well do all the weak references at the same time. + if (w == SOFT) + w = WEAK; + + while (head && head->weight <= w) + { + java::lang::ref::Reference *ref + = reinterpret_cast (head->reference); + // If the copy is already NULL then the user must have + // called Reference.clear(). + if (ref->copy != NULL) + { + if (w == PHANTOM) + ref->referent = ref->copy; + else + ref->copy = NULL; + ref->enqueue (); + } + + object_list *next = head->next; + _Jv_Free (head); + head = next; + } + list->next = head; + } + + // Re-register this finalizer. We always re-register because we + // can't know until the next collection cycle whether or not the + // object is truly unreachable. + _Jv_RegisterFinalizer (obj, finalize_referred_to_object); +} + +// This is called when a Reference object is finalized. If there is a +// Reference pointing to this Reference then that case is handled by +// finalize_referred_to_object. +static void +finalize_reference (jobject ref) +{ + JvSynchronize sync (java::lang::ref::Reference::lock); + remove_from_hash (ref); + // The user might have a subclass of Reference with a finalizer. + _Jv_FinalizeObject (ref); +} + +void +::java::lang::ref::Reference::create (jobject ref) +{ + // Nothing says you can't make a Reference with a NULL referent. + // But there's nothing to do in such a case. + referent = reinterpret_cast (ref); + copy = referent; + if (referent != NULL) + { + JvSynchronize sync (java::lang::ref::Reference::lock); + // `this' is a new Reference object. We register a new + // finalizer for pointed-to object and we arrange a special + // finalizer for ourselves as well. + _Jv_RegisterFinalizer (this, finalize_reference); + _Jv_RegisterFinalizer (referent, finalize_referred_to_object); + jobject *objp = reinterpret_cast (&referent); + _Jv_GCRegisterDisappearingLink (objp); + add_to_hash (this); + } +} -- cgit v1.1