Edit: I’ve figured out the constructor for the singleton is getting called multiple times so it appears the classes are getting loaded more than once by separate class loaders. How can I make a global singleton in Tomcat? I’ve been googling, but no luck so far.
I have a singleton object that I construct like thus:
private static volatile KeyMapper mapper = null;
public static KeyMapper getMapper()
{
if(mapper == null)
{
synchronized(Utils.class)
{
if(mapper == null)
{
mapper = new LocalMemoryMapper();
}
}
}
return mapper;
}
The class KeyMapper is basically a synchronized wrapper to HashMap with only two functions, one to add a mapping and one to remove a mapping. When running in Tomcat 6.24 on my 32bit Windows machine everything works fine. However when running on a 64 bit Linux machine (CentOS 5.4 with OpenJDK 1.6.0-b09) I add one mapping and print out the size of the HashMap used by KeyMapper to verify the mapping got added (i.e. verify size = 1). Then I try to retrieve the mapping with another request and I keep getting null and when I checked the size of the HashMap it was 0. I’m confident the mapping isn’t accidentally being removed since I’ve commented out all calls to remove (and I don’t use clear or any other mutators, just get and put).
The requests are going through Tomcat 6.24 (configured to use 200 threads with a minimum of 4 threads) and I passed -Xnoclassgc to the jvm to ensure the class isn’t inadvertently getting garbage collected (jvm is also running in -server mode). I also added a finalize method to KeyMapper to print to stderr if it ever gets garbage collected to verify that it wasn’t being garbage collected.
I’m at my wits end and I can’t figure out why one minute the entry in HashMap is there and the next it isn’t 🙁
I found a rather poor fix. I exported my code as a JAR and put it in $TOMCAT/lib and that worked. This is clearly a class loader issue.
Edit: Figured out the solution
Ok, I finally figured out the problem.
I had made my application the default application for the server by adding a to server.xml and setting the path to “”. However, when I was accessing it through the URL http://localhost/somepage.jsp for somethings, but also the URL http://localhost/appname/anotherpage.jsp for other things.
Once I changed all the URLs to use http://localhost/ instead of http://localhost/appname the problem was fixed.