Java tutorial
/* * ========================================================================= * This file is part of NITRO * ========================================================================= * * (C) Copyright 2004 - 2010, General Dynamics - Advanced Information Systems * * NITRO is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, If not, * see <http://www.gnu.org/licenses/>. */ package nitf; import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * This class provides the functionality to manage the underlying memory */ public final class NITFResourceManager { // this makes sure that the jni library gets loaded by NITFObject static { NITFObject.class.getName(); } private static final Log log = LogFactory.getLog(NITFResourceManager.class); // the Singleton instance private static final NITFResourceManager singleton = new NITFResourceManager(); /** * @return the singleton instance of the NITFResourceManager */ public static NITFResourceManager getInstance() { return singleton; } private static class TrackedObject { private Long address = NITFObject.INVALID_ADDRESS; private Integer javaRefCount = 0; private Integer nativeRefCount = 0; private MemoryDestructor destructor = null; private String className = null; public TrackedObject(DestructibleObject object) { address = object.getAddress(); className = object.getClass().getCanonicalName(); destructor = object.getDestructor(); javaRefCount = 1; } public void reference(boolean nativeRef) { if (nativeRef) nativeRefCount += 1; else javaRefCount += 1; } public void unReference(boolean nativeRef) { if (nativeRef) nativeRefCount -= 1; else javaRefCount -= 1; } boolean canDestroy() { return javaRefCount <= 0 && nativeRefCount <= 0; } boolean destroy() { if (canDestroy() && destructor != null) { return destructor.destructMemory(address); } return false; } @Override public String toString() { return "[" + className + ", address=" + address + ", javaRefs=" + javaRefCount + ", nativeRefs=" + nativeRefCount + "]"; } } private Map<Long, TrackedObject> trackedObjects; /** * Increments the java reference count of an object * * @param object */ protected void incrementRefCount(DestructibleObject object) { if (object != null && object.isValid()) { long address = object.getAddress(); if (trackedObjects.containsKey(address)) { TrackedObject trackedObject = trackedObjects.get(address); trackedObject.reference(false); log.debug("Incremented ref count: " + trackedObject.toString()); } else { TrackedObject trackedObject = new TrackedObject(object); trackedObjects.put(address, trackedObject); log.debug("Tracking new object: " + trackedObject.toString()); } } else { log.error("Cannot reference invalid object"); } } /** * Increments either the java or native reference count * * @param address * @param nativeRef */ protected void incrementRefCount(long address, boolean nativeRef) { if (address != NITFObject.INVALID_ADDRESS) { if (trackedObjects.containsKey(address)) { TrackedObject trackedObject = trackedObjects.get(address); trackedObject.reference(nativeRef); log.debug("Incremented ref count: " + trackedObject.toString()); } else { log.error("Unable to track unkown object: " + address); } } else { log.error("Cannot reference invalid address"); } } /** * Decrements the reference count of an object, and destructs the object if * the count is now < 1 * * @param object */ protected void decrementRefCount(long address, boolean nativeRef) { if (address != NITFObject.INVALID_ADDRESS) { // if its in here, update its count, if not, forget about it if (trackedObjects.containsKey(address)) { TrackedObject trackedObject = trackedObjects.get(address); trackedObject.unReference(nativeRef); log.debug("Decremented ref count: " + trackedObject.toString()); if (trackedObject.canDestroy()) { if (trackedObject.destroy()) { trackedObjects.remove(address); log.debug("Destroyed object: " + trackedObject.toString()); } else { log.error("Unable to destroy object: " + trackedObject.toString()); } } } else { log.warn("Unable to decrement reference count for untracked address: " + address); } } else { log.error("Cannot reference invalid address"); } } protected String getObjectInfo(long address) { TrackedObject trackedObject = trackedObjects.get(address); return trackedObject != null ? trackedObject.toString() : null; } /** * This attempts to load plugins from the directory given * * @param dirName * plugin directory to load * @throws NITFException */ public static void loadPluginDir(String dirName) throws NITFException { PluginRegistry.loadPluginDir(dirName); } // private constructor private NITFResourceManager() { trackedObjects = Collections.synchronizedMap(new LinkedHashMap<Long, TrackedObject>()); } }