The memory of a ConcurrentHashMap
of java-websocket WebSocketClients as values is growing unceasingly.
I've isolated it to the section of code that tries to reconnect to a whitelist of peers every second. I've tested to see if entries are being properly removed after a connection failure, and they are. I've also looked at everything I can find for "concurrenthashmap memory leak".
I have no idea how to implement this possible solution. Does that solution solve the problem? If so, please provide example code.
I tried to implement this suggestion
ConcurrentHashMap<String, MyClass> m =
new ConcurrentHashMap<String, MyClass>(8, 0.9f, 1);
and I think that slowed the growth rate somewhat, but I have no idea how to tweak it. Is that generally the correct approach? If so, please provide example code.
I also tried switching to a HashTable
as recommended here, but I get ConcurrentModificationExceptions
immediately, so I think that's out.
How can the memory of this ConcurrentHashMap
implementation be managed when there is rapid insertion and removal of thousands of entries per second? If it can't, is there an alternative?
Pass by reference instead of by copy
I added a HashMap
that stores a new
WebSocket
, and a connection can only be re-attempted if it's not present there as well as the ConcurrentHashMap
.
This GREATLY improved the memory management, but it still leaks a little, approximately by 0.1 MB per ~5 seconds for about 5 attempts per second.
Is this a problem with my code, WebSocket
's "destructor", or ConcurrentHashMap
's management of removed values?
Dead Object
s?
The growth rate has again been greatly reduced because I remove()
from the ConcurrentHashMap
before calling close()
on the WebSocketClient
and then finally remove()
ing from the HashMap
.
How & why could a WebSocketClient
still linger after being closed and removed from both Maps?
System.gc();
The leak rate has been greatly reduced again!
I call it after remove()
.
It is highly unlikely that the Map itself is leaking. What is probably happening, if it's related to the map at all, is that you are failing to remove data from the map when you're done with it. It can't get GC'd as long as the map is pointing to it.