When an HttpSession is destroyed com.sun.faces.application.WebappLifecycleListener tries to remove it from its lists of activeSessions.
The call to activeSessions.remove never actually removes a Session because a new instance of io.undertow.servlet.spec.HttpSessionImpl is used for the call and HttpSessionImpl does not implement an equals method. Thus Object.equals is used and the comparison fails.
This problem occures only if a session is invalidated due to a session timeout. A manual call to session.invalidate() works without any problem.
After some time this leads to an OutOfMemoryError.
A fix that works for us was to add this equals method: