The setTimeToLive() can be used to expire a JMS message. However, the messages would remain on the given destination beyond the time set to expire, if there are no message listeners. The messages sent to any destination with having setTimeToLive() attribute may not expire unless there's a message listener attached to given destination.
The messages marked to expire are validated and sent to the ExpiryQueue, at the time of processing by the attached message listener. IOW the messages which remain on the destination beyond the expiry limit, would expire (moved to the ExpiryQueue) by the time a listener is attached to the given destination.
Apart from what's given above, HornetQ has a reaper thread running, which scans the message store for expired messages and then remove them.