¿Cómo lidiar con Java AssertionError (java.lang.SocketException)?

I have Android application, which pulls xml from server.

public class FeedParser {

    private final URL mURL;

    public FeedParser(String feedUrl) {
        try {
            mURL = new URL(feedUrl);
        } catch (MalformedURLException e) {
            throw new RuntimeException();
        }
    }

    private InputStream getInputStream() throws IOException {
        return mURL.openConnection().getInputStream();
    }

    public FeedItem parseFeed() {
        // SAX stuff here

        try {
            Xml.parse(getInputStream(), Xml.Encoding.UTF_8,
                    root.getContentHandler());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }
}

Sometimes, when XML.parse(...) executes, I get exception:

 AndroidRuntime: java.lang.RuntimeException: An error occured while executing doInBackground()
 AndroidRuntime:    at android.os.AsyncTask$3.done(AsyncTask.java:200)
 AndroidRuntime:    at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:274)
 AndroidRuntime:    at java.util.concurrent.FutureTask.setException(FutureTask.java:125)
 AndroidRuntime:    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:308)
 AndroidRuntime:    at java.util.concurrent.FutureTask.run(FutureTask.java:138)
 AndroidRuntime:    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
 AndroidRuntime:    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
 AndroidRuntime:    at java.lang.Thread.run(Thread.java:1019)
 AndroidRuntime: Caused by: java.lang.AssertionError: java.net.SocketException: Connection reset by peer
 AndroidRuntime:    at android.util.Xml.parse(Xml.java:89)
 AndroidRuntime:    at com.packagename.FeedParser.parseFeed(FeedParser.java:60)
 AndroidRuntime:    at com.packagename.UpdateService$FeedLookupTask.doInBackground(UpdateService.java:84)
 AndroidRuntime:    at com.packagename.UpdateService$FeedLookupTask.doInBackground(UpdateService.java:1)
 AndroidRuntime:    at android.os.AsyncTask$2.call(AsyncTask.java:185)
 AndroidRuntime:    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
 AndroidRuntime:    ... 4 more
 AndroidRuntime: Caused by: java.net.SocketException: Connection reset by peer
 AndroidRuntime:    at org.apache.harmony.luni.platform.OSNetworkSystem.read(Native Method)
 AndroidRuntime:    at dalvik.system.BlockGuard$WrappedNetworkSystem.read(BlockGuard.java:273)
 AndroidRuntime:    at org.apache.harmony.luni.net.PlainSocketImpl.read(PlainSocketImpl.java:458)
 AndroidRuntime:    at org.apache.harmony.luni.net.SocketInputStream.read(SocketInputStream.java:85)
 AndroidRuntime:    at org.apache.harmony.luni.net.SocketInputStream.read(SocketInputStream.java:65)
 AndroidRuntime:    at java.io.BufferedInputStream.fillbuf(BufferedInputStream.java:140)
 AndroidRuntime:    at java.io.BufferedInputStream.read(BufferedInputStream.java:225)
 AndroidRuntime:    at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.readLine(HttpURLConnectionImpl.java:660)
 AndroidRuntime:    at org.apache.harmony.luni.internal.net.www.protocol.http.ChunkedInputStream.readChunkSize(ChunkedInputStream.java:77)
 AndroidRuntime:    at org.apache.harmony.luni.internal.net.www.protocol.http.ChunkedInputStream.read(ChunkedInputStream.java:45)
 AndroidRuntime:    at java.io.InputStream.read(InputStream.java:157)
 AndroidRuntime:    at org.apache.harmony.xml.ExpatParser.parseFragment(ExpatParser.java:516)
 AndroidRuntime:    at org.apache.harmony.xml.ExpatParser.parseDocument(ExpatParser.java:479)
 AndroidRuntime:    at org.apache.harmony.xml.ExpatReader.parse(ExpatReader.java:318)
 AndroidRuntime:    at org.apache.harmony.xml.ExpatReader.parse(ExpatReader.java:275)

How do I handle such error?

EDITAR Knowing that catching errors is bad programming style, I seek for more elegant solution.

preguntado el 09 de marzo de 12 a las 14:03

retry the parsing/fetching? Basically an exception isn't bad, it just shows that something went wrong. So just think of a way to retry it and your done (don't retry forever! make a retry counter that limits it)... -

I heard that it's bad idea to catch Errors. To do so I'll need to write catch(Throwable)? -

No, you don't. catch(AssertionError e) is sufficient. -

You could further guard against the pitfalls of catching errors by only handling AssertionErrors whose cause is a SocketException, rethrowing any other errors. -

2 Respuestas

Connection reset by peer means the remote server you're reading from is closing the connection and then you're trying to read from it again. It's not necessarily a network error for the remote side to do this--it could do it for any number of reasons. Without knowing the protocol of your server, it's hard to know the exact reason.

You can set up your code to catch and retry a limited number of times, as suggested above. It's not a bad idea to catch errors.

Another possibility, depending on the size of your xml, is to to read it into a string buffer and then parse it. With large data, this reduces the likelihood of a reset since your server connections will be much shorter than when you're parsing as you go. I'm thinking here of a scenario where the tcp window is closed down for a long time while you're parsing and eventually the other side decides you're dead and resets the connection.

respondido 09 mar '12, 16:03

@JarleHansen Why is it a bad idea to catch errors? If it's an exception you can handle, why not catch it, retry x times, and re-throw if it still fails? - ebaxt

@JarleHansen Of course, it is a "serious problem" that the remote hung up on the client, but perhaps the server was busy just then? It is eminently a good idea to catch the error in this case and retry a sensible number of times. - alfa cero

You guys are right, seems like this is a case where you actually need to catch the AssertionError. My mistake on this issue. - jarle hansen

AssertionError provides a standard way to warn that an assertion that the programmer has made is incorrect.

So when well used, they are saying "there is a coding bug here" (because you throw them in places that you assert are unreacheable), and that is the reason why AssertionError is an (extends) Error y no un Exception: they inform about a non recoverable (at runtime) failure (since you have to recode the algorithm).

Other usages of this error are just wrong because they are violating its contract.

So, answering your question, you can handle it in to ways:

  • If the code throwing the error is yours (I doubt this is the case given your question, but in the future should be): Review and correct your algorithm.
  • If it is from a third-party library: Register the bug to its author (or try to solve it by your own)

But you should not handle it in your code.

As an additional note: your case makes me doubt about if android.util.Xml.parse() is making a correct usage of it. It is very strange that an AssertionError having a cause (having been constructed from another Throwable), so that is another option to have in mind: maybe this library is not well implemented...

Respondido 27 Feb 15, 17:02

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.