Memory Leaks when using Threads!?
Hi, I wrote a chat client that sets up one on one chats..
This involves sockets and such.. I have a problem..
In task manager when checking the memory usage of
java.exe for my chat server.. Say I support a one on one chat
and the people leave it.. The memory usage goes from 8332kbs
to 8870kbs and back to 8840 kbs.. And it keeps increasing like this
as people come in chats and leave the chats...
THIS IS A PROBLEM BCAUSE BY THE END OF THE DAY IT WILL
take up a lot of memory! Yikes..
Now I close the sockets using socket.close(), etc.. However it still happens..
has anyone encountered this problem and know how to deal with it?
Thank you very much!!!!!!!!!!
[733 byte] By [
Conquerana] at [2007-11-27 7:36:48]

You have a memory leak in your code. There are plenty of Java servers in the world that handles hundreds of thousands of users and stay up for months without memory leaks so it isn't Java or threads or networking.
One well-known leak occurs because of String.substring(), which retains a reference to the original bigger String. If you're using that, make a new String(string.substring(x,y)) to lose the reference to 'string'.
ejpa at 2007-7-12 19:17:22 >

Thank you, I'm glad to know its not java..I guess I'll just have to figure it out then.. Is there anyreading material that is good for closing up threads withno leaks?
> One well-known leak occurs because of
> String.substring(), which retains a reference to the
> original bigger String. If you're using that, make a
> new String(string.substring(x,y)) to lose the
> reference to 'string'.
I believe this is no longer an issue, although I haven't confirmed it firsthand.
jverda at 2007-7-12 19:17:22 >

Still open: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4513622 'and it's entirely possible that the bug will not be fixed in future releases'.Rather controversial as to whether it should/should not be fixed.
ejpa at 2007-7-12 19:17:22 >

Sun's 1.5 JDK String.java has this:
public String substring(int beginIndex, int endIndex) {
if (beginIndex < 0) {
throw new StringIndexOutOfBoundsException(beginIndex);
}
if (endIndex > count) {
throw new StringIndexOutOfBoundsException(endIndex);
}
if (beginIndex > endIndex) {
throw new StringIndexOutOfBoundsException(endIndex - beginIndex);
}
return ((beginIndex == 0) && (endIndex == count)) ? this :
new String(offset + beginIndex, endIndex - beginIndex, value);
}
EDIT: I thought this showed that this "bug" (feature, actually) was no longer around, but I was confused. A new String object is created, but looking at that constructor, we see that it uses the same backing array. So the bu^H^Hfeature is still present (as of Sun's JDK 1.5).
Message was edited by:
jverd
jverda at 2007-7-12 19:17:22 >

I'm not using substring... Heres the general code
public class ServerThread extends Thread
{
// The Socket connected to our client
private ChatServer chatServer;
private Socket person;
private Socket otherPerson;
private DataOutputStream OA;
private DataOutputStream OB;
private boolean OneLessChat = false;
// Constructor.
public ServerThread( ChatServer s, Socket socket, DataOutputStream A, DataOutputStream B) {
chatServer = s;
person = socket;
OA = A;
OB = B;
// Start up the thread
start();
}
public void run() {
try {
String message;
DataInputStream input = new DataInputStream( person.getInputStream() );
//get username first
String username = input.readUTF();
//send it out
OB.writeUTF( username );
while( true )
{
try
{
message = input.readUTF();
//check if exit
} catch( IOException ie )
{
System.out.println("kick out");
message = "exitChat()";
}
if( message.equals("exitChat2()") )
{
OneLessChat = true;
break;
}
OB.writeUTF( message );
if( message.equals("exitChat()") )
break;
//send message out
OA.writeUTF( message );
}
} catch( EOFException ie ) {
System.out.println("the problem is in your server thread");
// This doesn't need an error message
} catch( IOException ie ) {
// This does tell the world! Closes the socket "person"
ie.printStackTrace();
} finally { chatServer.removeConnection( person, OneLessChat ); }
}
}
-
Now I have four constructor variables
chatServer
person
OA
OB
Do I need to somehow close those as well? I have the same memory leaks when I close OA and OB, do I need to close chatServer? Forgive me I'm a newbie when it comes to memory leaks..
Message was edited by:
Conqueran
I don't see where you are closing anything. If you get EOFException or indeed any IOException you must close the socket immediately and probably terminate the thread I would have thought. There's your leak.
ejpa at 2007-7-12 19:17:22 >

Thank you for telling me but how DO I close everything?
I know sockets close with socket.close() and I do that in removeConnection
function, but how do I close the rest of the stuff?
And how do I terminate the thread? I didn't know I needed to terminate the thread, I thought they terminated on their own when "finally" is hit (removeConnection).. Isn't "finally" hit even when I get an EOFException and IOException?
Message was edited by:
Conqueran
null
null
Closing the socket is enough, although you should actuallyclose the output stream instead to ensure it gets flushed.
The thread will exit when the run() method returns.
I can't figure out your exception handling in all that unformatted code, or why you need both exitChat() and exitChat2(), but in general this code looks to be all over the place. The first catch (IOException) should be a catch for EOFException, at which point you should close the socket, which you don't. Instead, depending on your logic and the input, you may try to write to the socket, which will throw another IOException, which you are catching, printing the stack trace, and continuing. So the run() method may never return.
Also your existing catch for EOFException occurs in a block of code that only does writes, so it will never happen.
You shouldn't rely on the well-formedness of the input for a clean exit: you should react appropriately to the exceptions you have caught. Any IOException should be taken as a reason to close the conversation and the socket and exit the thread.
ejpa at 2007-7-12 19:17:22 >

There are tons of ways how you can introduce a memory leak through lingering objects in your code. It's impossible knowing that it may be without seeing your code. It may be just some Hashtable where objects get registered but never removed (Listeners of any kind) etc.
I suggest you use a profiling tool if possible.
Google for java profilerJProbeOptimizeitJProfilerAppPerfectAll these should have free demo versions.The JDK also comes with a profiler. I've never used it, but I don't think it's as rich or intuitive as the above.
jverda at 2007-7-12 19:17:22 >
