Memory Leak in Smack? (2.1.0 and 2.2.0)

We are using the smack libraries to send a large volume of message. At any given time we send 10-20 messages per second. The messages range from 200-800 bytes in length.

At the default JVM memory heap size of 64 megs our process runs out of memory in 30-45 minutes. Sooner if we lower the heap size, takes longer if we raise heap size. After several days of debugging we believe we have isolated the leak to the smack libraries.

I have included a test class to demonstrate the behavior. Set your JVM heap memory to 8 megs (-Xmx8m) and you should get ~10400 messages before you run out of memory. Just provide values for userName, serverPassword, serverName, serverPort, roomName, and roomPassword.

Have tested this with 2.1.0 and 2.2.0 and experienced the same behavior.

Has anyone else tried to use smack to send a large volume of messages?

public class LeakTest {

public static void main(String[] args) {

MultiUserChat chatRoom = null;

XMPPConnection chatConnection = null;

String userName = “”;

String serverPassword = “”;

String serverName = “”;

int serverPort = 5223;

String roomName = “”;

String roomPassword = “”;

try {

chatConnection = new SSLXMPPConnection(serverName, serverPort);

chatConnection.login(userName, serverPassword);

chatRoom = new MultiUserChat(chatConnection, roomName + “@conference.” + serverName);

DiscussionHistory discussionHistory = new DiscussionHistory();

discussionHistory.setMaxStanzas(0);

chatRoom.join(userName, roomPassword, discussionHistory, SmackConfiguration.getPacketReplyTimeout());

} catch (XMPPException e) {

e.printStackTrace();

}

NumberFormat memoryFormatter = NumberFormat.getNumberInstance();

int count = 0;

for ( ; ; ) {

try {

chatRoom.sendMessage("");

} catch (XMPPException e) {

e.printStackTrace();

}

if (count++ % 100 == 0) {

System.out.println("Count = " + count);

System.out.println("Free Memory: " + memoryFormatter.format(Runtime.getRuntime().freeMemory()));

System.out.println("Max Memory: " + memoryFormatter.format(Runtime.getRuntime().maxMemory()));

System.out.println("Total Memory: " + memoryFormatter.format(Runtime.getRuntime().totalMemory()));

try {

Thread.sleep(500);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

}

We fixed some memory leaks recently that were appearing in the debugger… as a result of a large volume of message, it was even occuring when debugging was turned off. I look into your test code and see if I can’'t ascertain what is occuring.

Alex

I may have narrowed down the issue but can’'t be sure until I know exactly how your “actual” implementation works. Are you reading any messages locally in the MUC from where you are sending the messages? Also, are you using wildfire?

Thanks,

Alex

Not totally sure I understand your question. However, we do not intercept the messages or have a PacketListener on our class that sends the messages.

We are using this the way you would use a JMS topic (publish/subscribe).

I am not sure which version you started to call it “wildfire” but our server is Jive Messenger 2.2.0.

I have located the origin of the “memory leak”. It originates as the MultiUserChat implementation collects packets from the MultiUserChat irregardless of whether or not you are using it, IE reading from the MUC. I have created an issue for this you can track it and vote on it accordingly to raise its priority

SMACK-129

In the mean time, a work around would be to read the packets building up in the MUC.

Cheers,

Alex

Thanks for the info we will give that a try!

Sorry about the quadruple post earlier. My computer and I were engaged in battle, I eventually won.

I have tried your suggestion and I still run out of memory with my test code at 10401 messages (with heap set at 8 megs).

I added a messageListener to the multiUserChat room. Did I misunderstand your workaround?

So, just to understand the problem, when a message is sent to the server a copy of that message is stored locally in the MultiUserChat object? This copy of the message is never removed unless you listen for it? Which listener do I need to add and implement to listen for it?

Just out of curiousity why would someone listen for a message they just sent to the server?

And to clarify I am running out of memory on the client side not server side.

Message was edited by: mjparme

Hey mjparme:

I should have been more through in my explanation. The workaround I had meant to say looked something more along these lines:

MultiUserChat chat;

while(chat.pollMessage()) {

chat.nextMessage();

}

/code

Its a hack but it will get the job done… your milage may vary.

The class was originally designed without your use case in mind. It is setup with a listener attached to it meaning it will acumulate all messages returned from the chat. The fact that the messages that one own user sends are accumulated there to was a design desicion on the part of the authors of XMPP. This frees up a lot of confusion in my mind, so that your own messages aren’'t an exemption from the messages sent out from the server.

Hope that helps,

Alex

Ok, we have the workaround in place. Another person on my team figured out you had to call the nextMessage() method on the MUC in the processPacket implementation to actually get the message to be removed from the MUC.

Thanks for the help!