问题
I wrote a small pieces of java program as following:
package com.ny.utils.pub;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
public class NetWriter {
private static String link = "http://xxx.yyyyyy.com:4444";
public String getLink() {
return link;
}
public static void setLink(String link) {
NetWriter.link = link;
}
private static HttpURLConnection conn = null;
private static BufferedReader bufReader = null;
private static InputStreamReader isReader = null;
private static OutputStreamWriter osw = null;
private static URL url = null;
static {
try {
url = new URL(link);
} catch(MalformedURLException e) {
}
}
public static void write(String msg) {
long threadId = Thread.currentThread().getId();
System.out.println("--Insert>{" + threadId + "}:" + msg);
try {
conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded");
conn.setRequestProperty("Content-Language", "en-US");
conn.setUseCaches(false);
conn.setDoOutput(true);
conn.setReadTimeout(5000);
conn.setConnectTimeout(5000);
osw = new OutputStreamWriter(conn.getOutputStream());
osw.write(msg);
osw.flush();
osw.close();
if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
System.err.println("Server not return HTTP_OK status");
} else {
System.out.println(" request: " + msg);
isReader = new InputStreamReader(conn.getInputStream());
bufReader = new BufferedReader(isReader);
String rep = bufReader.readLine();
if (conn.getResponseCode() == 200) {
System.out.println("Post data OK to " + link);
}
System.out.println(" response: " + rep);
}
} catch(IOException e) {
System.err.println("Post data error: " + link + " "
+ e.getMessage());
e.printStackTrace();
}
}
}
When I wrote another program to invoke method in this class, which will lead "Too many open files" and then the OS will refuse user to login. The called script is as following:
try{
NetWriter.write(new String(content, "utf-8"));
}catch(Exception e){
logger.error(e.getMessage());
e.printStackTrace();
}
}
When the problem reappeared, I found that the handle occupation was increasing. The following is piece of message that I execute the command "lsof -p PROGRAM_PID"
java 27439 root 66u unix 0xffff8103473fb6c0 10151765 socket
java 27439 root 67u unix 0xffff8103473fb6c0 10151765 socket
java 27439 root 68u unix 0xffff8103473fb6c0 10151765 socket
java 27439 root 69r FIFO 0,6 10151917 pipe
java 27439 root 70w FIFO 0,6 10151917 pipe
java 27439 root 71r 0000 0,11 0 10151918 eventpoll
java 27439 root 72r FIFO 0,6 10151919 pipe
java 27439 root 73w FIFO 0,6 10151919 pipe
java 27439 root 74r 0000 0,11 0 10151920 eventpoll
java 27439 root 75u unix 0xffff8103473fb6c0 10151765 socket
java 27439 root 76u unix 0xffff8103473fb6c0 10151765 socket
java 27439 root 77r FIFO 0,6 10152042 pipe
java 27439 root 78w FIFO 0,6 10152042 pipe
java 27439 root 79r 0000 0,11 0 10152043 eventpoll
java 27439 root 80r FIFO 0,6 10152044 pipe
java 27439 root 81w FIFO 0,6 10152044 pipe
java 27439 root 82r 0000 0,11 0 10152045 eventpoll
java 27439 root 83u unix 0xffff8103473fb6c0 10151765 socket
java 27439 root 84r FIFO 0,6 10154168 pipe
java 27439 root 85w FIFO 0,6 10154168 pipe
java 27439 root 86r 0000 0,11 0 10154169 eventpoll
java 27439 root 87r FIFO 0,6 10154170 pipe
Number of handles (pipe socket eventpool) will up to thousands.
I tried many methods to avoid this, but failed. Anybody can tell me the defect in the above program?
回答1:
You do not close the input reader. It should be closed.
As a general rule, you should close resources in a finally
block.
In this case, you should close the input and output readers in a finally
block.
回答2:
If you haven't found a solution, worth checking this thread out:
Android - HttpUrlConnection is not closing. Eventually results to SocketException
This is something to do with "Keep-Alive" connections in Jellybean. Hope that helps
回答3:
Try using OkHttp Instead.
I struggled with this for hours/days/weeks, doing everything you should like setting small read/connect timeouts and using a finally
block to close out connections, input streams, output streams, etc. But we never found a working solution. It seemed like HttpsUrlConnection
was flawed in some way.
So we tried OkHttp
as a drop-in replacement for HttpsUrlConnection
and voila! It worked out of the box.
So, if you're struggling with this and are having a really hard time fixing it, I suggest you try using OkHttp as well.
Here are the basics:
Once you get the Maven dependency added, you can do something like the following to download a file:
OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
OutputStream output = null;
try {
Request request = new Request.Builder().url( download_url ).build();
Response response = okHttpClient.newCall( request ).execute();
if ( !response.isSuccessful() ) {
throw new FileNotFoundException();
}
output = new FileOutputStream( output_path );
output.write( response.body().bytes() );
}
finally {
// Ensure streams are closed, even if there's an exception.
if ( output != null ) output.flush();
if ( output != null ) output.close();
}
Switching to OkHttp instantly fixed our leaked file descriptor issue so it's worth trying if you're stuck, even at the expense of adding another library dependency.
来源:https://stackoverflow.com/questions/8091984/java-app-with-urlconnection-leads-too-many-open-files