/*
* Project Info: http://jcae.sourceforge.net
*
* This program 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 2.1 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, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*
* (C) Copyright 2012, by EADS France
*/
package org.jcae.vtk;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import vtk.vtkJavaGarbageCollector;
import vtk.vtkObject;
import vtk.vtkObjectBase;
/**
*
* @author Jerome Robert
*/
final class VTKMemoryManager {
private final static Logger LOGGER =
Logger.getLogger(VTKMemoryManager.class.getName());
/**
* vtk.vtkGlobalJavaHash.GarbageCollector if vtk ≶ 5.8,
* vtkObject.JAVA_OBJECT_MANAGER.getAutoGarbageCollector() else
*/
public final static vtkJavaGarbageCollector GC;
private final static Method DELETE_ALL_METHOD;
private final static Object OBJECT_MANAGER;
private final static Method UNREGISTER_METHOD;
private final static ConcurrentHashMap<Long, WeakReference<?>> OBJECT_MAP;
static
{
vtkJavaGarbageCollector lGC = null;
Method lDeleteAll = null, lUnregisterMethod = null;
Object lObjectManager = null;
ConcurrentHashMap<Long, WeakReference<?>> lObjectMap = null;
try
{
try {
Class<?> javaHash = vtkObject.class.forName("vtk.vtkGlobalJavaHash");
Field f = javaHash.getDeclaredField("GarbageCollector");
lGC = (vtkJavaGarbageCollector) f.get(null);
lDeleteAll = javaHash.getDeclaredMethod("GC");
lObjectMap = (ConcurrentHashMap)
javaHash.getDeclaredField("PointerToReference").get(null);
} catch (ClassNotFoundException ex) {
Field f = vtkObjectBase.class.getDeclaredField("JAVA_OBJECT_MANAGER");
lObjectManager = f.get(null);
Method m = lObjectManager.getClass().getDeclaredMethod("getAutoGarbageCollector");
lGC = (vtkJavaGarbageCollector) m.invoke(lObjectManager);
lDeleteAll = lObjectManager.getClass().getDeclaredMethod("deleteAll");
lUnregisterMethod = lObjectManager.getClass().getDeclaredMethod("unRegisterJavaObject", Long.class);
}
}
catch(Exception ex)
{
LOGGER.log(Level.SEVERE, null, ex);
}
GC = lGC;
DELETE_ALL_METHOD = lDeleteAll;
OBJECT_MANAGER = lObjectManager;
UNREGISTER_METHOD = lUnregisterMethod;
OBJECT_MAP = lObjectMap;
}
private VTKMemoryManager(){}
/**
* vtkGlobalJavaHash.GC() if vtk ≶ 5.8, else
* vtkObject.JAVA_OBJECT_MANAGER.deleteAll();
*/
public static void deleteAll()
{
try {
DELETE_ALL_METHOD.invoke(OBJECT_MANAGER);
} catch (IllegalAccessException ex) {
LOGGER.log(Level.SEVERE, null, ex);
} catch (IllegalArgumentException ex) {
LOGGER.log(Level.SEVERE, null, ex);
} catch (InvocationTargetException ex) {
LOGGER.log(Level.SEVERE, null, ex);
}
}
/**
* Tag a vtkObjectBase so it will be deleted at the native level at the
* next vtkGlobalJavaHash.GC() call. Such call is normally triggered by
* vtkJavaGarbageCollector.
* As JVM doesn't monitor the native memory usage, VTK object may never be
* deleted if the Java garbage collector is not triggered by other java
* object creation. This methods allows to manually tag a vtkObject as
* removable without actually removing it.
*/
public static void delete(vtkObjectBase o)
{
if(OBJECT_MAP != null)
{
WeakReference<?> ref = (WeakReference) OBJECT_MAP.get(o.GetVTKId());
ref.clear();
}
else //OBJECT_MANAGER != null
{
try {
UNREGISTER_METHOD.invoke(OBJECT_MANAGER, o.GetVTKId());
} catch (IllegalAccessException ex) {
LOGGER.log(Level.SEVERE, null, ex);
} catch (IllegalArgumentException ex) {
LOGGER.log(Level.SEVERE, null, ex);
} catch (InvocationTargetException ex) {
LOGGER.log(Level.SEVERE, null, ex);
}
}
}
}