powered by Jive Software

Memory leak in Smack, or have I misunderstood PacketExtensions/Providers?

I have some code that process my own custom extension. I have created a PacketExtension and a PacketExtensionProvider. The problem is that every time I get a packet, the PacketExtension gets allocated but never destroyed, meaning that after a while my program crashes with java.lang.OutOfMemoryError.

Here’'s the relevant code:

Main.java:

import org.jivesoftware.smack.*;

import org.jivesoftware.smack.packet.*;

import org.jivesoftware.smack.PacketCollector.*;

import org.jivesoftware.smack.PacketListener.*;

import org.jivesoftware.smack.filter.*;

import org.jivesoftware.smack.provider.*;

public static TestResponseProvider respProv=new TestResponseProvider();

public static XMPPConnection connection;

public static void main(String[] args)

{

ProviderManager.addExtensionProvider(“TestResponse”,“TEST”, respProv);

connection = new XMPPConnection(“some.server.net”);

connection.login(“login”, “passw”);

PacketFilter filter = new PacketExtensionFilter(“TestResponse”,“TEST”);

PacketCollector myCollector = connection.createPacketCollector(filter);

PacketListener myListener = new PacketListener()

{

public void processPacket(Packet packet)

{

TestResponse theResp=(TestResponse)packet.getExtension(“TestResponse”,“TEST”);

(Processing of the response)

}

};

connection.addPacketListener(myListener,filter);

}

TestResponse.java:

import org.jivesoftware.smack.packet.*;

public class TestResponse implements PacketExtension

{

private static int count=0;

int data[] = new int[65536];

public TestResponse()

{

count++;

System.out.println("[“count”] TestResponse objects allocated");

}

public void finalize()

{

count–;

System.out.println("[“count”] TestResponse objects allocated");

}

public String getNamespace()

{

return “TEST”;

}

public String getElementName()

{

return “TestResponse”;

}

public String toXML()

{

String xmlQuery;

xmlQuery="<“getElementName()” xmlns="“getNamespace()”">";

xmlQuery*="</"*getElementName()+">";

return xmlQuery;

}

}

TestResponseProvider.java:

import org.jivesoftware.smack.packet.*;

import org.jivesoftware.smack.provider.*;

import org.xmlpull.v1.*;

public class TestResponseProvider implements PacketExtensionProvider

{

public TestResponseProvider()

{

}

public PacketExtension parseExtension(XmlPullParser parser)

{

TestResponse tempResp = new TestResponse();

int eventType = parser.getEventType();

while (eventType != XmlPullParser.END_DOCUMENT)

{

/*

Code to parse the extension and put stuff in the tempResp object

*/

eventType = parser.next();

}

return tempResp;

}

}

/code

As you can see I have put some debug code in my PacketExtension (TestResponse) which displays the number of objects in the constructor and finalizer. When I run this program, the count just goes up and up until I run out of memory!

I think I managed to stop the memory leak by changing my ProcessPacket function to:

public void processPacket(Packet packet)

{

TestResponse theResp=(TestResponse)packet.getExtension(“TestResponse”,“TEST”);

(Processing of the response)

packet.removeExtension(theResp);

}[/code]

That is, I added “packet.removeExtension(theResp)” to the end of my function, but is this really the way it is supposed to work, shouldn’'t the Packet class be able to clean up the extensions itself?

Hey Andreas,

Seems to me that the root of the problem is that you defined a collector but you are never consuming it. Therefore, the collector is preventing the packets from being garbage collected. Try removing the collector since you are using a packet listener and also remove the packet.removeExtension(theResp).

Regards,

– Gato

You are absolutley correct, thanks.