I have a Java program that will freeze during the rush hour currently. I am looking for the reason. Right now, my idea is that it is because some of the codes are not AJAX, so it will hangs in there when requesting JSON object from server during rush hour (Internet speed is slow during rush hour). But I am not very sure that it is not AJAX though. I cannot paste all the codes here because it is related to company's property, so I am going to write some piece of codes/pseudocode. The program uses the following to do the request.
URL url = new URL("http://www.xxxxxxxx.com/");
URLConnection conection = url.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(conection .getInputStream()));
String inputLine;
String content = "";
while ((inputLine = in.readLine()) != null) {
content += inputLine;
}
in.close();
json = new JSONObject(content);
The above codes are some snippet of the program where I think it causes the freezing. My question is that, This piece of code does not seem to use any AJAX and it is not multithreading, right? So it hangs in there (freezing) when the Internet connection is very slow? I am not very experienced about this. Please help.
If you do not think this is the main reason that causes the freezing, what could be the most possible reason for this kind of problem in general speaking.
Thank you in advance.
Edits/Update:
My program is a swing program that runs in client side. There is no
real server side codes for this application. The URL address is a
3rd party server that provides some kind of data that the program
needs. I did not see the program uses any threads. It is basically core Java without using any threads as I see, and I am not very familiar with multi-threading, so I am not sure. (The program is not written by me, it is written by some former programmers) That is why I am considering that maybe it did not use other threads to run this server request when it should be.
What I mean by freezing is that the UI will freeze for a few seconds during the rush hour when it try to run some specific functions. The above code I wrote is some snippet from those functions. After the UI freezes for awhile, it then works as expected in the rest. However, in non-rush hour, it works like a charm.
Specifically, BufferedReader in = new BufferedReader(new
InputStreamReader(conection .getInputStream())); is what I think
that causes the problem. Could anyone confirm that?
All asynchronous methods like HTTP POST/GET, implement in separate Thread. User don't interest to see what your application does in background.
In addition, its not good practice to use String for appends, like jlordo says, use StringBuilder or StringBuffer.
StringBuilder buff= new StringBuilder();
while ((inputLine = in.readLine()) != null) {
if(!"".equals(line).trim){
buff.append(line).append("\n");
}
}
in.close();
You can add timeout to your session to be sure that application doesn't stuck at all.
[EDIT]
Regard to question changes, I don't think that
BufferedReader in = new BufferedReader(new InputStreamReader(conection .getInputStream()));
it's your problem.
You can try to do followed flow but I still thinks about separate Thread with GUI Thread
InputStream is = conection .getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line = null;
while ( (line = br.readLine()) != null) {
You probably want to use a SwingWorker thread to do the call to the server. That way, when it is busy, the UI won't freeze.
However, remember, you won't see the resulting changes on the screen that the new data would provide until the new data arrives.
See Oracle SwingWorker JavaDocs
Tutorial with example similar to yours
Related
Following security vulnerability has been reported on our application -
The call to readLine() at xyz.java line 119 might allow an attacker to
crash the program or otherwise make it unavailable to legitimate
users.
Code with vulnerability
Commented line reported -
BufferedReader reader = new BufferedReader(new InputStreamReader(
httpConnection.getInputStream()));
String inputLine;
StringBuffer okResponse = new StringBuffer();
while ((inputLine = reader.readLine()) != null) { //readLine() on this line has been reported
okResponse.append(inputLine);
}
reader.close();
return okResponse.toString();
The remediation for the same says -
Validate user input to ensure that it will not cause inappropriate
resource utilization.
But, it is not clear what exactly can be validated. Any pointers?
In theory an attacker could send you an unlimited amount of data via the httpConnection. Since you try to consume all of it, it might crash your application (OutOfMemory).
I´d assume you have a certain format and length for the okResponse in mind,
so you would be better off checking that.
Make sure you read to read the answer from Subhas linked by Luis Muñoz (Most Robust way of reading a file or stream using Java (to prevent DoS attacks)),
that has some more implementation details for reading content from a stream.
Another issue might be that the attack just keeps the connection open without sending any data. I`d assume there should be a timeout in place to cut the connection at some point, else the thread might be blocked forever.
Edit:
Since you code does not have it explicitly, you also should add a try ... finally ... block to make sure that the resources are properly closed.
I have written a simple program in Java on my Raspberry Pi 3. What it does is basically plays animations and sounds on a TV, and the input it receives to know what to play are sent by an android tablet using bluetooth.
On the tablet side, I have a few sliders (ex:volume) that send data through bluetooth whenever they are changed. The tablet acts as a server and the code looks like this:
final BluetoothSocket clientSocket = bluetoothServerSocket.accept();
InputStream is = clientSocket.getInputStream();
OutputStream os = clientSocket.getOutputStream();
bufIn = new BufferedReader( new InputStreamReader( is ) );
bufOut = new BufferedWriter( new OutputStreamWriter( os ) );
And whenever I want to send data, I do the following in another thread:
bufOut.write("<message>blabla</message>");
bufOut.flush();
However, if I move the sliders frenetically, the program stops at some point at bufOut.flush();. My thought on this is that the other end of the socket on the RPi is full and prevents the tablet from sending any more data.
So, on the RPi, I am using bluecove library and the code I have looks like this:
connection = (StreamConnection) Connector.open(serviceInDevice);
is = connection.openInputStream();
os = connection.openOutputStream();
bufIn = new BufferedReader(new InputStreamReader(is));
bufOut = new BufferedWriter(new OutputStreamWriter(os));
And for receiving data, I do the following on another thread:
while(true) {
String readLine = bufIn.readLine();
//Process data...
}
Here, after a slider frenzy, just when the tablet hangs on its flush() function, the program hangs on the readLine().
I have tried to test the state of bufIn once it seems stuck, using another thread and doing System.out.println(bufIn.ready()), but the thread also hangs on this line.
I have also tried to test the state of the inputStream is asynchronously by calling is.available(), but the return value is always 0.
I have tried changing the BufferedReaders and BufferedWriters to manipulating directly the OutputStream and InputStream, but the problem remains.
Adding a sleep on the sending part to avoid the oversending is not an option, because I also have to send audio data to the RPi and basically a lot of stuff.
Is there a known problem about bluetooth on the RPi, or am I missing something?
Thank you
Ok I have found the reason why the Bluetooth of my RPi freezes. The answer might not be very helpful to others, but I was using VNC to see the output of my raspberry on my computer, and as soon as I stopped using VNC the problem disappeared. So if anyone is wondering, VNC and Bluetooth simultaneously on the RPi is not recommended :p
I'm making a core server-management system for my company, and both the server manager and server itself are Java jar files. What I need to do is boot up the server from the server manager, and the server needs to be able to read console input. However, the way I currently have it coded, it ignores console input. I believe the while loop is freezing the thread, but IDK what to do about it. Any ideas?
Process process = Runtime.getRuntime().exec("sh start.sh");
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while((line = reader.readLine()) != null){
System.out.println(line);
}
Technically, your while loop isn't freezing the thread - the call to reader.readLine() is. I'd recommend you listen to both your InputStream and ErrorStream, and to do both at the same time you either need to use Threads or java NIO. For a Threaded solution, I built and used DataFetcher for specifically this kind of purpose. All you need to do is create a DataFetcher around an InputStream, add a FetcherListener, and start the DataFetcher with a new Thread
I have a really strange issue while working with Java sockets. This problem is only happening for a VERY small subset of the urls that I am processing. Let's call an example url abc.com.
Edit: url is lists.wikimedia.org/robots.txt that gives me problems.
I can curl/netcat/telnet lists.wikimedia.org with path /robots.txt perfectly fine. Telnet even tells me the IP address for lists.wikimedia.org (see below). However, when I try to do the same using Java socket like the following:
Socket s = new Socket("208.80.154.4", 80); // IP is same as the IP printed by telnet
BufferedWriter writer = new BufferedWriter(s.getOutputStream());
writer.println("HEAD /robots.txt HTTP/1.1");
writer.println("Host: lists.wikimedia.org");
writer.println("Connection: Keep-Alive");
writer.flush();
InputStreamReader r = new InputStreamReader(s.getInputStream());
BufferedReader reader = new BufferedReader(r);
String line;
while ((line = reader.readLine()) != null) {
...
}
The readLine blocks infinitely until the socket times out...
Does anyone have ANY idea why this might be happening? The same code works fine with most of the other URLs, and interestingly enough this bug only happens for some of the ROBOTS.TXT requests... I'm so confused why this might be happening.
Edit:
Interestingly enough, using apache HttpClient library gives me the correct result for lists.wikimedia.org/robots.txt. Is there something else I need to do if I want to manually do it via Socket?
Probably you are missing the additional CRLF to end the HTTP request header. I also would write them explicitly, to avoid platform confusions, like so (untested):
writer.print("HEAD /robots.txt HTTP/1.1\r\n");
writer.print("Host: lists.wikimedia.org\r\n");
writer.print("Connection: Keep-Alive\r\n");
writer.print("\r\n");
writer.flush();
also consider using a HTTPURLConnection instead of plain sockets, takes away all this burdons:
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
connection.setRequestMethod("HEAD");
...
I have used TaskExecutor from spring and futures to get the future from the task,but now when some task doesnt respond in some time I have to stop those tasks.I have tried using Future.cancel() method but its of no use the thread stills seems to be running .Can you suggest me some method to stop it?
My thread is waiting on reading the Html content from a link..so how do i stop the task
Edit: the relevant code:
URL link = new URL(Content);
URLConnection yc = link.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(yc.getInputStream()));
String inputLine;
StringBuffer Sbuff = new StringBuffer();
while (((inputLine = in.readLine()) != null) &&
((Calendar.getInstance().getTimeInMillis() - TimeatStart) / 1000) < 4) {
Sbuff.append(inputLine);
}
Generally speaking, you don't do that. If you want the HTTP request to stop after hanging for a while, then set a timeout on it. It's always best to let the thread finish whatever work it's been given to do.
Edit: Based on your source code, the first thing you need to do is make sure to call connect() on the URLConnection. Otherwise, nothing will happen. Take a look at Working with URLs in the Java Tutorial. After that, if you still want to set timeouts, use setConnectTimeout() to set the amount of time it should try to connect before timing out and setReadTimeout() to set the amount of time it should wait to receive data after a request is sent.