So in our Java Server implementation, when you authenticate with the Server, we create a Session object, put it into our Session Catalog, and pass back either a String that is the session ID or the actual Session object, depending on what environment you're operating in. The Session implements HttpSessionBindingListener so that it will get a callback when the bound Session is being destroyed. When we get the callback, we take the Session out of the Session Catalog, which should, in theory at least, be the last strong reference to the Session object.
We may have opened a number of objects of different types on behalf of the Session. Each type of object has its own Catalog, which -- in this case -- is stored in a static WeakHashMap where the Session is the key and the Catalog of objects opened on behalf of that Session is the stored value. So when the Session is headed off to the Garbage Collector, we'll also garbage collect the Catalog of objects that was associated with it in the WeakHashMap.
The advantage of this approach is that when I add a new type of object to the system that I want to open on behalf of the Session, I don't have to change the Session object. I just have to create a static WeakHashMap that holds all of the Catalogs for the new object type. This also puts all of the Catalog information in the place where I'd like it to be, given the general architecture of the Java Server. In this case, the Catalog classes are all inner classes inside of the object class that they hold.
As I said, I think it's clever... :)