All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jlibs.core.lang.ref.Finalizer Maven / Gradle / Ivy

There is a newer version: 3.0.1
Show newest version
/**
 * Copyright 2015 Santhosh Kumar Tekuri
 *
 * The JLibs authors license this file to you under the Apache License,
 * version 2.0 (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at:
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */

package jlibs.core.lang.ref;

import jlibs.core.lang.ImpossibleException;

import java.lang.ref.*;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * This class provides guaranteed finalization for java objects.
 * 

* This is singleton class and its instance can be accessed as {@code Finalizer.}{@link #INSTANCE} *

* you can tell {@code Finalizer} to execute given {@code runnable} when a particular * object gets garbage collected: *

 * Object myObject = ...;
 * Finalizer.INSTANCE.{@link #track(Object, Runnable) track}(myObject, new Runnable(){
 *    public void run(){
 *        System.out.println("myObject is garbage collected");
 *    }
 * });
 * 
* * {@code Finalizer} creates a {@link java.lang.ref.WeakReference} for the object that needs to * be tracked. you can also tell which type of {@link java.lang.ref.Reference} to use as below: * *
 * Object myObject = ...;
 * Finalizer.INSTANCE.{@link #track(Object, Class, Runnable) track}(myObject, {@link java.lang.ref.SoftReference}.class, new Runnable(){
 *    public void run(){
 *        System.out.println("myObject is garbage collected");
 *    }
 * });
 * 
* * All the {@code track(...)} methods return the {@link java.lang.ref.Reference} object created. *

* You can also use {@code Finalizer} as a simple profiler. *

 * Object myObject = ...;
 * Finalizer.INSTANCE.{@link #trackGC(Object, String) trackGC}(myObject, "myObject is garbage collected");
 * 
* the above code says to print {@code "myObject is garbage collected"} to console, when {@code myObject} gets * garbage collected. *

* This class starts a {@link Thread} named {@code "JLibsFinalizer} with {@link Thread#MIN_PRIORITY} * * @author Santhosh Kumar T */ public class Finalizer extends ReferenceQueue implements Runnable{ public static final Finalizer INSTANCE = new Finalizer(); private Finalizer(){ Thread thread = new Thread(this, "JLibsFinalizer"); thread.setPriority(Thread.MIN_PRIORITY); thread.setDaemon(true); thread.start(); } @Override @SuppressWarnings({"InfiniteLoopStatement"}) public void run(){ while(true){ try{ Reference ref = super.remove(); Runnable runnable = tracked.remove(ref); try{ if(runnable!=null) runnable.run(); }catch(ThreadDeath td){ throw td; }catch(Throwable thr){ thr.printStackTrace(); } }catch(InterruptedException ie){ ie.printStackTrace(); } } } private Map tracked = new ConcurrentHashMap(); /** * tracks the given {@code obj} using {@link java.lang.ref.WeakReference}.
* Specified {@code runnable} is executed when {@code obj} gets garbage collected. * * @param obj object needs to be tracked * @param runnable runnable to be executed when {@code obj} gets garbage collected * * @return the {@link java.lang.ref.WeakReference} created for {@code obj} * * @see #track(Object, Class, Runnable) */ @SuppressWarnings("unchecked") public WeakReference track(T obj, Runnable runnable){ return (WeakReference)track(obj, WeakReference.class, runnable); } /** * tracks the given {@code obj} using specified reference {@code type}.
* Specified {@code runnable} is executed when {@code obj} gets garbage collected. * * @param obj object needs to be tracked * @param type type of reference to be used for tracking * @param runnable runnable to be executed when {@code obj} gets garbage collected * * @return the {@link java.lang.ref.Reference} created for {@code obj} * * @see #track(Object, Runnable) */ @SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"}) public > R track(T obj, Class type, Runnable runnable){ Class clazz = type; Reference ref; if(clazz==WeakReference.class) ref = new WeakReference(obj, this); else if(clazz==SoftReference.class) ref = new SoftReference(obj, this); else if(clazz==PhantomReference.class) ref = new PhantomReference(obj, this); else throw new ImpossibleException(); tracked.put(ref, runnable); return (R)ref; } /** * Prints message to {@code System.out} when {@code obj} gets garbage collected.

* The message will be {@code obj.getClass().getName()+'@'+System.identityHashCode(obj)} * * @param obj object needs to be tracked * * @see #trackGC(Object, String) */ public void trackGC(Object obj){ trackGC(obj, null); } /** * Prints {@code message} to {@code System.out} when {@code obj} gets garbage collected * * @param obj object needs to be tracked * @param message message to be printed when {@code obj} gets garbage collected. * if null, the message will be {@code obj.getClass().getName()+'@'+System.identityHashCode(obj)} */ public void trackGC(Object obj, String message){ if(message==null) message = obj.getClass().getName()+'@'+System.identityHashCode(obj); track(obj, new MessagePrinter(message)); } private static class MessagePrinter implements Runnable{ private String message; private MessagePrinter(String message){ this.message = message; } @Override public void run(){ System.out.println("JLibsFinalizer: '"+message+"' got garbage collected."); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy