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]
# 1

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 > top of Java-index,Java Essentials,New To Java...
# 2
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?
Conquerana at 2007-7-12 19:17:22 > top of Java-index,Java Essentials,New To Java...
# 3

> 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 > top of Java-index,Java Essentials,New To Java...
# 4
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 > top of Java-index,Java Essentials,New To Java...
# 5

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 > top of Java-index,Java Essentials,New To Java...
# 6

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

Conquerana at 2007-7-12 19:17:22 > top of Java-index,Java Essentials,New To Java...
# 7
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 > top of Java-index,Java Essentials,New To Java...
# 8

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

Conquerana at 2007-7-12 19:17:22 > top of Java-index,Java Essentials,New To Java...
# 9

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 > top of Java-index,Java Essentials,New To Java...
# 10

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.

marcelschoena at 2007-7-12 19:17:22 > top of Java-index,Java Essentials,New To Java...
# 11
A profiling tool?
Conquerana at 2007-7-12 19:17:22 > top of Java-index,Java Essentials,New To Java...
# 12
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 > top of Java-index,Java Essentials,New To Java...