3

I'm using HttpURLConnection for querying back-end server. Requests are POST. My code looks like:

InputStream is = null;
HttpURLConnection connection = null;
try {
    connection = (HttpURLConnection)new URL(uri).openConnection();
    connection.setRequestMethod("POST");
    connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=" + ENCODING);
    connection.setDoOutput(true);
    byte[] content = buildFormUrlEncoded(params);
    connection.setRequestProperty("Content-Length", String.valueOf(content.length));

    connection.connect();

    OutputStream os = null;
    try {
        os = connection.getOutputStream();
        os.write(content);
    } finally {
        if (os != null) { os.close(); }
    }

    is = connection.getInputStream();
    handle(is);
} finally {
    if (is != null) { is.close(); }
    if (connection != null) { connection.disconnect(); }
}

However I'm getting this StrictMode error:

A resource was acquired at attached stack trace but never released. See java.io.Closeable for information on avoiding resource leaks.
java.lang.Throwable: Explicit termination method 'close' not called
    at dalvik.system.CloseGuard.open(CloseGuard.java:184)
    at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:300)
    at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:257)
    at libcore.net.http.HttpConnection.setupSecureSocket(HttpConnection.java:210)
    at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.makeSslConnection(HttpsURLConnectionImpl.java:477)
    at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:432)
    at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:282)
    at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:232)
    at libcore.net.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:80)
    at libcore.net.http.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:164)

When I am debugging code, os.close(), is.close() and connection.disconnect() is called.

Could StrictMode happen because of connection is keep alive in pool?

EDIT

  • If connection.setRequestProperty("connection", "close"); is added the StrictMode error disappear.
  • If http URL instead of https URL is used the StrictMode error disappear.
  • If BufferedReader is used the StrictMode error happens less often.

I would like to keep https for security and keep alive to reduce handshake overhead.

EDIT 2

Looks like this occurs only in case of android 3.X and 4.0.X.

Salw
  • 1,880
  • 17
  • 22

2 Answers2

2

My code looks like this:

@Override
    protected Boolean doInBackground(Void... params) {
        JSONObject holder = new JSONObject();
        try {
            Resources res = getResources();

            holder.put(res.getString(R.string.str),"");


            URL url = new URL(res.getString(R.string.url));
            String charset = res.getString(R.string.utf);
            HttpURLConnection http = null;

                HttpsURLConnection https = (HttpsURLConnection) url.openConnection();

                http = https;
                http.setRequestMethod(res.getString(R.string.post));
                http.setDoInput(true);
                http.setDoOutput(true);
                http.setRequestProperty(res.getString(R.string.charset), charset);
                http.setRequestProperty(res.getString(R.string.content_type), "application/x-www-form-urlencoded;charset=" + charset);

                String query = String.format("query1=%s&query2=%s&query3=%s&query4=%s", 
                     URLEncoder.encode(res.getString(R.string.qu1), charset), 
                     URLEncoder.encode(res.getString(R.string.qu2), charset),
                     URLEncoder.encode(res.getString(R.string.qu3), charset),
                     URLEncoder.encode(holder.toString(), charset));

                OutputStream output = null;
                try {
                     output = http.getOutputStream();
                     output.write(query.getBytes(charset));
                } finally {
                     if (output != null) try { output.close(); } catch (IOException logOrIgnore) {}
                }
                //InputStream response = http.getInputStream();

                BufferedReader in = new BufferedReader(new InputStreamReader(http.getInputStream()),4800); 
                StringBuffer responseBuffer = new StringBuffer();
                String line;

                while ((line = in.readLine()) != null) { 
                    responseBuffer.append(line);
                }

                in.close();
                answer = new Gson().fromJson(responseBuffer.toString(), Answer.class);
                //s = responseBuffer.toString();
        } catch (Exception e) {
            e.printStackTrace();
            getData();
        }
        return true;
    }

I believe you'll find the answer there.

Michal
  • 15,429
  • 10
  • 73
  • 104
  • 1
    Did you add the IOException? You need to surround the .close() with try-catch – Michal Aug 02 '12 at 10:57
  • I turned off keep alive and there is no more resource leak. Now I'm trying to find where is located code in Android that is responsible for connection pool. I suspect connections in pool are weak references and GC finalizes it. Because it is still open, there is StrictMode error from CloseGuard. – Salw Aug 02 '12 at 11:53
  • Why are you making simple things complicated? I strongly recommend to seek error in the code, not in Android. – Michal Aug 02 '12 at 11:58
  • I have searched for error in the code and I'm unable to find it. It looks like StrictMode error happens only in case of combination https and keep alive. I have no code for ssl certificates handling nor code for pooling connections. If I want to look what is different I must to look into platform sources. – Salw Aug 02 '12 at 14:02
  • And did you add exception handling for closing InputStream? I will edit my code for https, as I am using it for https as well. – Michal Aug 02 '12 at 15:13
  • I have created simple testing application and used your code with few modifications in it. I have tested it on android API 9 and greater. StrictMode error occured in all API versions excluding 9, 10 and 16. Here is code: [java](http://pastebin.com/edMkN86b) (I had to erase true URL and params) [layout](http://pastebin.com/Q6t7p2T3) . The problem occurs after I click button, wait few sec and click on button it again. – Salw Aug 03 '12 at 12:29
  • Wow, I am sorry for belittling your question, this could be some serious issue...:( – Michal Aug 03 '12 at 12:31
  • Please explain your code. You just pasted your code. Maybe some people do not understand what you've been doing there. :) – thehayro Jul 12 '13 at 15:21
  • 1
    **1)** The code is already obsolete. **2)** Is it really necessary after 1 year? **3)** I can't event remember... – Michal Jul 15 '13 at 10:37
1

Try the following ,


After closing streams and connections make then null.

is=null;os=null;connection=null;
SIVAKUMAR.J
  • 4,258
  • 9
  • 45
  • 80