My developers and I are having an issue with objects being garbage collected in our application when we don’t want them to be. We are using Java with Weblogic 10g3. We are programming a singleton pattern to handle all of our JMS connections.
There are two classes involved:
public class JMSObject {
...
private MessageProducer _producer;
private MessageConsumer _consumer;
...
// standard get/set procs... etc.
}
public class JMSFactory {
...
// Hashmap sessions with key == ConnectionFactory Name
Hashmap<String, List<Session>> _sessions;
// Hashmap of JMSObjects with key == ConnectionFactory Name + JMS Queue Name
Hashmap<String, List<JMSObject>> _jmsobjects;
...
// standard get/set & necessary sington functions
}
The init method of the Servlets calls the JMSFactory singlton method, any new Sessions are placed in the _sessions Hashmap and new MessageConsumer/MessageProducers are created as a JMSObject and placed in the _jmsobjects Hashmap, in the appropriate List.
The problem is that when the system is running the JMSObjects in the list get garbage collected after some time (sometimes in 5 minutes other times after a few hours.) We looked at this for a few days but could not find any reason for the JMSObjects to be garbarge collected. Since the JMSFactory has a reference to them why would the gc destroy them?
In the end we fixed it by changing the classes as follows(without changing method interfaces):
public class JMSObject {
...
private List<MessageProducer> _producers;
private List<MessageConsumer> _consumers;
...
// standard get/set procs... etc.
}
public class JMSFactory {
...
// Hashmap sessions with key == ConnectionFactory Name
Hashmap<String, List<Session>> _sessions;
// Hashmap of JMSObjects with key == ConnectionFactory Name + JMS Queue Name
private Hashmap<String JMSObject> _jmsobjects;
...
// standard get/set & necessary sington functions
}
So far in testing the JMSObjects are not being gc’ed. It has been running for 2 days.
Can someone explain why the indirect reference is causing the JMSObject to get gc’ed? And why the Sessions in the _sessions Hashmap was not getting gc’ed? Does it have anything to do with the fact the Sessions are built in Javax types and the JMSObject is something we wrote?
I think I know what your problem is, it’s something I ran into a while back (on WebLogic 6). I believe it has to do with WebLogic’s dynamic class reloading, which WebLogic seems to do from time to time, even when you’re not in a development environment (I’m guessing the web.xml is somehow getting touched by some service or something).
What happened in our case was that like you, we have a single instance of an object that’s defined as a static variable of some class, and just like you, it’s initialized by a servlet that has it’s load-on-startup parameter set. When WebLogic thinks there’s a change, it reloads the webapp by garbage collecting the classloader (which is fine) but it doesn’t re-initialize all the servlets that are marked “load-on-startup” (in our case, and I’m guessing yours, the servlet serves no purpose other than to initialize the static variable, there are no mappings to it, and so it cannot be invoke, the static variable gets GCed, but not-reinitialized, and the server needs to be restarted.
In our case, our solution was to initialize the static variable in a static initializer. The original developer used a servlet to initialize the variable because he wanted some servlet context information, which really wasn’t necessary. If you need context information, you could try doing your initialization in a ServletContextListener.