Hi Bob, it is not the singletons that prevents a clean shutdown, the garbage collector is able to clean them up correctly if there is nothing else that keeps them alive. I guess that in your case there is something else that keeps the singletons alive. Please check that automatic eviction is disabled in your broker and/or connection pools, the threads started for the automaitc evition remain active and prevent a clean shutdown. And yes, this is also something that must be added to the 'central' shutdown routine, any running eviction threads must be stopped (Armin?).
>From my point of view, it is not a clean solution to add destroy methods to >the singletons to clean the static references this should be done by the >garbage collector, the problem must be solved at its roots! A good reason for this is: cleaning up static references will allow to free memory in the heap space, however if the class loaders are not released, all loaded classes, interned strings and any other static fields are not released and after each redeployment the perm. gen. space will increase in size until you get the deadly 'OutOfMemoryError: Perm Gen' where you will have several problems even shutting down your web-server. bye Danilo > Danilo, > > I implemented the wrapper you described here: > http://mail-archives.apache.org/mod_mbox/db-ojb-user/200506.mbox/[EMAIL > PROTECTED] > > This didn't clean up any of the objects I have left over after my application > shuts down. > > After the application is stopped in Tomcat, the wrapper class is pointed to > by PersistenceBrokerFactoryFactory.singleton which never gets null'd out (and > other static variables still hold references such as > MetadataManager.singleton). > > I guess I'd like to see a shutdown() or destroy() method at some level that > would clear out all of these static references. > > Bob > > > -----Original Message----- > From: Danilo Tommasina [mailto:[EMAIL PROTECTED] > Sent: Friday, July 15, 2005 3:33 AM > To: OJB Users List > Subject: Re: Cleaning up OJB when shutting down an application > > > Hi Armin, > > Below you can find a possible patch for the PersistenceBrokerThreadMapping, > this also contains a shutdown() method to guarantee that the > PersistenceBrokerThreadMapping is cleaned up correctly even if > PersistenceBrokers are not closed correctly. > > I would also suggest adding a central shutdown() method (where?) that should > call: > > - PersistenceBrokerFactory.releaseAllInstances() > - > ConnectionFactoryFactory.getInstance().createConnectionFactory().releaseAllResources() > - The new call to PersistenceBrokerThreadMapping.shutdown() > > We are also executing following calls, these don't seem to be necessary if > the 'evil ThreadLocal memory leak' is solved, include them at your choice. We > were using these to reduce the amount of leaked memory before applying the > workaround. Note that some more checks may be necessary if the shutdown is > called on an uninitialised OJB instance (errors in the config, connection > failure, ...) PersistenceBroker pb = null; try { > pb = PersistenceBrokerFactory.defaultPersistenceBroker(); > pb.clearCache(); // Clear complete OJB cache > } catch ( PersistenceBrokerException pbe ) { > // Silently ignore, this error should be handled somewhere else > (initialsiation of OJB failed } finally { > if ( pb != null ) { > pb.close(); > } > } > > And finally > MetadataManager.getInstance().removeAllProfiles() > > ---------------------- > patched PersistenceBrokerThreadMapping, I also allowed myself to add some > missing Javadoc ;) > ---------------------- > > public class PersistenceBrokerThreadMapping { > > /** A Collection of all HashMaps added to the <CODE>ThreadLocal > currentBrokerMap</CODE> that are still -alive-. > * If all the PersistenceBrokers are always correctly closed, the > Collection should remain empty. > * The Collection is iterated trough when calling the > <CODE>shutdown()</CODE> method and all the maps that are > * still alive will be cleared. > */ > private static Collection loadedHMs = new HashSet(); // NEW > > /** > * The hashmap that maps PBKeys to current brokers for the thread > */ > private static ThreadLocal currentBrokerMap = new ThreadLocal(); > > /** Mark a PersistenceBroker as preferred choice for current Thread > * @param key The PBKey the broker is associated to > * @param broker The PersistenceBroker to mark as current > */ > public static void setCurrentPersistenceBroker(PBKey key, > PersistenceBroker broker) > throws PBFactoryException > { > HashMap map = (HashMap) currentBrokerMap.get(); > WeakHashMap set = null; > if (map == null) > { > map = new HashMap(); > currentBrokerMap.set(map); > > loadedHMs.add( map ); // NEW > } > else > { > set = (WeakHashMap) map.get(key); > } > > if (set == null) > { > // We emulate weak HashSet using WeakHashMap > set = new WeakHashMap(); > map.put(key, set); > } > set.put(broker, null); > } > > /** Unmark a PersistenceBroker as preferred choice for current Thread > * @param key The PBKey the broker is associated to > * @param broker The PersistenceBroker to unmark > */ > public static void unsetCurrentPersistenceBroker(PBKey key, > PersistenceBroker broker) > throws PBFactoryException > { > HashMap map = (HashMap) currentBrokerMap.get(); > WeakHashMap set = null; > if (map != null) > { > set = (WeakHashMap) map.get(key); > if (set != null) > { > set.remove(broker); > if ( set.isEmpty() ) { // NEW > map.remove( key ); // NEW > } // NEW > } > if ( map.isEmpty() ) { // NEW > currentBrokerMap.set( null ); // NEW > loadedHMs.remove( map ); // NEW > } // NEW > } > } > > /** > * Return the current open [EMAIL PROTECTED] > org.apache.ojb.broker.PersistenceBroker} > * instance for the given [EMAIL PROTECTED] org.apache.ojb.broker.PBKey}, > if any. > * @param key > * @return null if no open [EMAIL PROTECTED] > org.apache.ojb.broker.PersistenceBroker} found. > */ > public static PersistenceBroker currentPersistenceBroker(PBKey key) > throws PBFactoryException, PersistenceBrokerException > { > HashMap map = (HashMap) currentBrokerMap.get(); > WeakHashMap set; > PersistenceBroker broker = null; > > if (map == null) > { > return null; > } > > set = (WeakHashMap) map.get(key); > if (set == null) > { > return null; > } > > // seek for an open broker, preferably in transaction > for (Iterator it = set.keySet().iterator(); it.hasNext(); ) > { > PersistenceBroker tmp = (PersistenceBroker) it.next(); > if (tmp == null || tmp.isClosed()) > { > it.remove(); > continue; > } > broker = tmp; > if (tmp.isInTransaction()) > { > break; // the best choice found > } > } > return broker; > } > > /** Clean up static fields and any registered ThreadLocal contents to > grant a clean > * shutdown/reload of OJB within hot-deployable applications. > */ > public static void shutdown() > { > for ( Iterator it = loadedHMs.iterator(); it.hasNext(); ) > { > ((HashMap) it.next()).clear(); > } > loadedHMs.clear(); > loadedHMs = null; > currentBrokerMap = null; > } > } > > >>Hi Danilo, Bob, >> >>AFAIK there was no patch checked in conjunction with PBThreadMapping. >>As you said the threads in tomcat will be recycled and it seems that >>ThreadLocal will cause a memory leak in this case: >>http://www.jroller.com/page/tackline/20050310 >>(sounds similar, but maybe I'm wrong) >> >>So we need some kind of shutdown method in PBF and in PBThreadMapping. >>Could you both summarize the needed changes I will check in a patch. I >>found the patch for PBThreadMapping (the new "shutdown"-method). >>What's needed too? >> >>regards, >>Armin >> >>Danilo Tommasina wrote: >> >> >>>Hello, >>> >>>please see my post 'ThreadLocal causing memory leak' of 9. Jun. 2005, >>>this is the same problem described there. I posted some code that can >>>be used as temporary solution or workaround and discussed a bit about >>>the issue with Martin Kalén, however I do not know the current >>>status... >>> >>>Both the workaround in the PersistenceBrokerFactoryDefaultImpl and my >>>proposed 'clean' solution in the PersistenceBrokerThreadMapping (I >>>sent the definitive code directly to Martin) seems to work correctly >>>in our application. To note is that we are using only the PB API and >>>are not using proxies. The workaround in the >>>PersistenceBrokerFactoryDefaultImpl 'may' cause problems or >>>performance issues with proxies, however I cannot test it, I did just >>>a short and not very deep analysis of the code searching for possible >>>side effects. >>> >>>As I cannot currently access the apache CVS (it seems to be flooded >>>and it is currently down), I cannot say if the issue has already been >>>patched in the latest CVS version or not. >>> >>>bye >>>Danilo >>> >>>Glugla, Robert T wrote: >>> >>> >>>>Environment: >>>> >>>>OJB: 1.0.3 >>>>JProfiler: 4.0.1 >>>>Tomcat: 5.0.19 >>>>JVM: Sun 1.4.2_06-b03 >>>> >>>>While profiling our OJB application, we noticed that after we shut >>>>it down in Tomcat, we had plenty of org.apache.ojb.broker.* and >>>>org.apache.ojb.metadata.* objects left behind in memory. Using >>>>JProfiler we tracked it down to several static variables not getting >>>>cleared out >>>>including: >>>> >>>>PersistenceBrokerFactoryFactory.singleton >>>>MetadataManager.singleton >>>>...several others... >>>> >>>>Does anyone have any suggestions as to how to clean these up >>>>properly? I looked for destroy methods and couldn't find any. As a >>>>test, I downloaded the OJB source and added destroy methods to >>>>PersistenceBrokerFactoryFactory & MetadataManager that I called from >>>>a context listener and it worked ok. Really, really don't want to >>>>do this myself. I'm guessing I'm just overlooking some easy way for >>>>cleaning these up already provided in OJB. >>>> >>>>Any suggestions? >>>> >>>>Thanks. >>>> >>>>Bob Glugla >>>>Boeing >>>> >>>>-------------------------------------------------------------------- >>>>- >>>>To unsubscribe, e-mail: [EMAIL PROTECTED] >>>>For additional commands, e-mail: [EMAIL PROTECTED] >>>> >>> >>>[EMAIL PROTECTED] >>>www.risksys.com >>> >>>--------------------------------------------------------------------- >>>To unsubscribe, e-mail: [EMAIL PROTECTED] >>>For additional commands, e-mail: [EMAIL PROTECTED] >>> >>> >>> >> >>--------------------------------------------------------------------- >>To unsubscribe, e-mail: [EMAIL PROTECTED] >>For additional commands, e-mail: [EMAIL PROTECTED] >> > > -- Danilo Tommasina, Dipl. Ing. FH Telecom Software Engineer, Chief Software Architect RCS Riskmanagement Concepts Systems AG Technoparkstrasse 1 CH-8005 Zuerich T: +41 1 445 29 08 [EMAIL PROTECTED] www.risksys.com --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
