001/* 002 * This file is part of the Jikes RVM project (http://jikesrvm.org). 003 * 004 * This file is licensed to You under the Eclipse Public License (EPL); 005 * You may not use this file except in compliance with the License. You 006 * may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/eclipse-1.0.php 009 * 010 * See the COPYRIGHT.txt file distributed with this work for information 011 * regarding copyright ownership. 012 */ 013package org.jikesrvm.scheduler; 014 015import org.jikesrvm.VM; 016import org.jikesrvm.mm.mminterface.MemoryManager; 017import org.jikesrvm.runtime.Magic; 018import org.vmmagic.pragma.Uninterruptible; 019import org.vmmagic.pragma.NonMoving; 020 021/** 022 * Finalizer thread. 023 * <p> 024 * This thread is created by RVMThread.boot() at runtime startup. 025 * Its "run" method does the following: 026 * <ul> 027 * <li>1. yield to the gcwaitqueue, until scheduled by GC. 028 * <li> 2. For all objects on finalize queue, run the finalize() method 029 * <li> 3. Go to 1 030 * </ul> 031 * <p> 032 * This thread comes out of wait state via notify from the garbage collector 033 */ 034@NonMoving 035public class FinalizerThread extends SystemThread { 036 037 private static final int verbose = 0; // currently goes up to 2 038 039 private final Object[] none = new Object[0]; 040 private static boolean shouldRun; 041 private static Monitor schedLock; 042 043 public static void boot() { 044 schedLock = new Monitor(); 045 FinalizerThread ft = new FinalizerThread(); 046 ft.start(); 047 } 048 049 @Uninterruptible 050 public static void schedule() { 051 schedLock.lockNoHandshake(); 052 shouldRun = true; 053 schedLock.broadcast(); 054 schedLock.unlock(); 055 } 056 057 public FinalizerThread() { 058 super("FinalizerThread"); 059 } 060 061 /** Run the finalizer thread (one per RVM) */ 062 @Override 063 public void run() { 064 if (verbose >= 1) { 065 RVMThread.trace("FinalizerThread ", "run routine entered"); 066 } 067 068 try { 069 while (true) { 070 071 // suspend this thread: it will resume when the garbage collector 072 // places objects on the finalizer queue and notifies. 073 schedLock.lockNoHandshake(); 074 if (!shouldRun) { 075 if (verbose >= 1) { 076 VM.sysWriteln("finalizer thread sleeping."); 077 } 078 schedLock.waitWithHandshake(); 079 } 080 shouldRun = false; 081 schedLock.unlock(); 082 083 if (verbose >= 1) { 084 VM.sysWriteln("FinalizerThread starting finalization"); 085 } 086 087 while (true) { 088 Object o = MemoryManager.getFinalizedObject(); 089 if (o == null) break; 090 if (verbose >= 2) { 091 VM.sysWrite("FinalizerThread finalizing object at ", Magic.objectAsAddress(o)); 092 VM.sysWrite(" of type "); 093 VM.sysWrite(Magic.getObjectType(o).getDescriptor()); 094 VM.sysWriteln(); 095 } 096 try { 097 java.lang.JikesRVMSupport.invokeFinalize(o); 098 } catch (Throwable e) { 099 if (verbose >= 1) VM.sysWriteln("Throwable exception caught for finalize call"); 100 } 101 if (verbose >= 2) { 102 VM.sysWriteln("FinalizerThread done with object at ", Magic.objectAsAddress(o)); 103 } 104 } 105 if (verbose >= 1) VM.sysWriteln("FinalizerThread finished finalization"); 106 107 } // while (true) 108 } catch (Throwable e) { 109 VM.sysWriteln("Unexpected exception thrown in finalizer thread: ", e.toString()); 110 e.printStackTrace(); 111 } 112 113 } // run 114 115}