Reputation: 836
I'm writing a chat application. I use a while(true)
infinite loop to allow the application to constantly "listen" to both user input through the console and input from a Socket
. The infinite loop clearly isn't the optimal way to accomplish this - not surprisingly, I get an OutOfMemoryError: Java Heap space
after only about a minute of the program running (and my computer's fans screaming).
My question is: if not through an infinite loop, how can I modify my program to constantly (or at least at small intervals, like once every second) check the input sources, respond, and then go back to checking?
The code (with some notes) is below:
import java.io.*;
import java.net.*;
public class Main {
public static void main(String[] args) throws IOException, ConnectException {
ServerSocket receiveServerSocket = new ServerSocket(Integer.parseInt(args[0])); // args contains two port numbers
Socket sendSocket;
while(true) { // note - I use the exact same infinite loop strategy here, except in this case an OutOfMemoryError is not thrown
try {
sendSocket = new Socket(InetAddress.getLocalHost(), Integer.parseInt(args[1]));
break;
} catch (ConnectException e) {}
}
DataOutputStream os = new DataOutputStream(sendSocket.getOutputStream());
Socket receiveSocket = receiveServerSocket.accept();
DataInputStream is = new DataInputStream(receiveSocket.getInputStream());
BufferedReader input = new BufferedReader (new InputStreamReader(System.in));
String message;
while(true) { // Here's the infinite loop in question
if(input.ready()) { // "checks" to see if the user has entered text
message = input.readLine(); // responds
os.writeInt(message.getBytes().length);
os.writeBytes(message);
}
if(is.available() > 0) { // checks to see if Socket has received text
byte[] bytes = new byte[is.readInt()]; // responds (Incidentally, this is the specific line where the OutOfMemoryError occurs)
is.read(bytes,0,bytes.length);
System.out.println(new String(bytes,0,bytes.length,"UTF-8"));
}
}
}
}
Thanks
Upvotes: 0
Views: 1948
Reputation: 79847
There are two problems.
(1) You need to change
os.writeBytes(message);
to
os.write(message.getBytes(), 0, message.getBytes().length);
The reason is that writeBytes
discards one byte from every String
. From the Javadoc -
Writes out the string to the underlying output stream as a sequence of bytes. Each character in the string is written out, in sequence, by discarding its high eight bits. If no exception is thrown, the counter written is incremented by the length of s.
The effect of this of course is that the number of bytes you've written is actually half of the number of bytes you specified when you called writeInt
.
(2) You should write some kind of separator character such as a space after the call to writeInt
, in case the byte sequence begins with numeric characters. Otherwise, the call to readInt
might read the wrong number from the stream.
Upvotes: 1
Reputation: 1900
Try printing the value of is.readInt()
. It might be possible that you are reading a garbage value and trying to allocate that much memory resulting in the OutOfMemoryError.
Also put the while loop in a thread and call Thread.sleep(1000)
to make the checking periodic with a 1 sec interval.
Upvotes: 1
Reputation: 1074
Some of my observations :
Upvotes: 1
Reputation: 441
Your first while loop isn't really a loop as it breaks right after assigning a value to sendsocket.
Maybe have a flag for your application like
bool isRunning=true;
and you can do,
while(isRunning)
and when your application is closed it'll change isRunning=false, & kick out of the loop.
Upvotes: 0