Yes, the HttpSession object is basically a Map pairing session object names with session objects. However, that doesn't mean the session objects don't occupy RAM. They're still objects, whether you have them "directly" or not. And the amount of RAM (JVM heap space) that is tied up while a session is active is approximately equal to the average amount of RAM for one user's session times the number of active user sessions. Which means that if you have 1600 bytes worth of session data per user (and don't forget that there's maybe 20-30 bytes of system overhead per object), and 1000 users, you're chewing up 1.6 million bytes of RAM. The more users, and/or the more session storage, the harder it is to scale up.
Yes, accessing a session object directly can be much, much faster than pulling data from a file or database, but sometimes it's worth the performance hit just to be able to support more users. And when you are talking industrial-scale applications, it's not uncommon for the data persistency mechanism to maintain a cache of frequently-used (and possibly shared) objects, which can greatly reduce that overhead. The
EJB mechanism, for example, allows you to collapse EJBs to "handles", which are very small, which your application code then requests the EJB manager to resolve back to the original EJBs, so that the only time you need to use the extra memory is while you are actually processing an HTTP request.