Intermittent NPE in java.io.reader

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Intermittent NPE in java.io.reader

Andy Dennie
Hi, I'm hoping maybe this problem looks familiar to somebody out there..

I'm using Restlet 2.1.4 on GAE, and I'm seeing intermittent NPEs with the (partial) stack trace below.  This is happening on about 1% of requests.

17:00:19.465 org.restlet.engine.io.BioUtils getReader: The GAE edition is unable to return a reader for a writer representation.
   E 17:00:19.465 org.restlet.engine.adapter.ServerAdapter commit: An exception occured writing the response entity
java.lang.NullPointerException
        at java.io.Reader.<init>(Reader.java:78)
        at java.io.BufferedReader.<init>(BufferedReader.java:94)
        at org.restlet.engine.io.ReaderInputStream.<init>(ReaderInputStream.java:101)
        at org.restlet.engine.io.BioUtils.getStream(BioUtils.java:354)
        at org.restlet.representation.CharacterRepresentation.getStream(CharacterRepresentation.java:70)
        at org.restlet.util.WrapperRepresentation.getStream(WrapperRepresentation.java:151)
        at org.restlet.engine.application.RangeRepresentation.getStream(RangeRepresentation.java:117)
        at org.restlet.engine.application.RangeRepresentation.write(RangeRepresentation.java:146)
        at org.restlet.engine.adapter.ServerCall.writeResponseBody(ServerCall.java:510)
        at org.restlet.engine.adapter.ServerCall.sendResponse(ServerCall.java:454)

In the full stack trace further below, I've interspersed the source code at each stack level.  Here's my analysis so far:

The Reader constructor has received a null "lock" parameter from its caller.
BufferedReader is just passing its first argument ("in", a Reader) to super, so "in" must be null.
which means that in ReaderInputStream's constructor, "reader" is null
which means that in BioUtils.getStream, "reader" (its first arg) is null
which means that in CharacterRepresentation.getStream, getReader() is returning null

CharacterRepresentation is abstract and doesn't implement getReader, so its implementation is coming from one of its subclasses.
Since it is getting called from WrapperRepresentation.getStream, that indicates that the CharacterRepresentation is a wrapped representation.
Since that is getting called from RangeRepresentation.getStream, we know that the wrapper is a RangeRepresentation, although we don't know what the wrapped representation is (other than it is derived from CharacterRepresentation)
Since that is getting called from ServerCall.writeResponseBody, for the object "entity", we know that "entity" is a RangeRepresentation.

The problem is that I'm expecting "entity" to be a JacksonRepresentation, not a RangeRepresentation.  And I can't find any code that instantiates a RangeRepresention outside of RangeFilter, which I'm not using (to my knowledge).

Any ideas?

-Andy


   W 17:00:19.465 org.restlet.engine.io.BioUtils getReader: The GAE edition is unable to return a reader for a writer representation.
   E 17:00:19.465 org.restlet.engine.adapter.ServerAdapter commit: An exception occured writing the response entity
java.lang.NullPointerException
        at java.io.Reader.<init>(Reader.java:78)

protected Reader(Object lock) {
    if (lock == null) {
        throw new NullPointerException();

        at java.io.BufferedReader.<init>(BufferedReader.java:94)

super(in);

        at org.restlet.engine.io.ReaderInputStream.<init>(ReaderInputStream.java:101)

reader = (reader instanceof BufferedReader) ? (BufferedReader) reader : new BufferedReader(reader, IoUtils.BUFFER_SIZE);

        at org.restlet.engine.io.BioUtils.getStream(BioUtils.java:354)

result = new ReaderInputStream(reader, characterSet);

        at org.restlet.representation.CharacterRepresentation.getStream(CharacterRepresentation.java:70)

return BioUtils.getStream(getReader(), getCharacterSet());

        at org.restlet.util.WrapperRepresentation.getStream(WrapperRepresentation.java:151)

return getWrappedRepresentation().getStream();

        at org.restlet.engine.application.RangeRepresentation.getStream(RangeRepresentation.java:117)

return new RangeInputStream(super.getStream(), getSize(), getRange());

        at org.restlet.engine.application.RangeRepresentation.write(RangeRepresentation.java:146)

BioUtils.copy(getStream(), outputStream);

        at org.restlet.engine.adapter.ServerCall.writeResponseBody(ServerCall.java:510)

entity.write(responseEntityStream);

        at org.restlet.engine.adapter.ServerCall.sendResponse(ServerCall.java:454)
        at org.restlet.ext.servlet.internal.ServletCall.sendResponse(ServletCall.java:459)
        at org.restlet.engine.adapter.ServerAdapter.commit(ServerAdapter.java:196)
        at org.restlet.engine.adapter.HttpServerHelper.handle(HttpServerHelper.java:153)
        at org.restlet.ext.servlet.ServerServlet.service(ServerServlet.java:1089)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
        at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511)
        at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166)
        at com.googlecode.objectify.cache.AsyncCacheFilter.doFilter(AsyncCacheFilter.java:59)
        at com.googlecode.objectify.ObjectifyFilter.doFilter(ObjectifyFilter.java:49)
        at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
        at com.google.apphosting.utils.servlet.ParseBlobUploadFilter.doFilter(ParseBlobUploadFilter.java:125)
        at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
        at com.google.apphosting.runtime.jetty.SaveSessionFilter.doFilter(SaveSessionFilter.java:35)
        at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
        at com.google.apphosting.utils.servlet.JdbcMySqlConnectionCleanupFilter.doFilter(JdbcMySqlConnectionCleanupFilter.java:60)
        at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
        at com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:43)
        at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
        at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388)
        at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
        at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)
        at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
        at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418)
        at com.google.apphosting.runtime.jetty.AppVersionHandlerMap.handle(AppVersionHandlerMap.java:266)
        at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
        at org.mortbay.jetty.Server.handle(Server.java:326)
        at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
        at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:923)
        at com.google.apphosting.runtime.jetty.RpcRequestParser.parseAvailable(RpcRequestParser.java:76)
        at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
        at com.google.apphosting.runtime.jetty.JettyServletEngineAdapter.serviceRequest(JettyServletEngineAdapter.java:146)
        at com.google.apphosting.runtime.JavaRuntime$RequestRunnable.run(JavaRuntime.java:446)
        at com.google.tracing.TraceContext$TraceContextRunnable.runInContext(TraceContext.java:437)
        at com.google.tracing.TraceContext$TraceContextRunnable$1.run(TraceContext.java:444)
        at com.google.tracing.CurrentContext.runInContext(CurrentContext.java:188)
        at com.google.tracing.TraceContext$AbstractTraceContextCallback.runInInheritedContextNoUnref(TraceContext.java:308)
        at com.google.tracing.TraceContext$AbstractTraceContextCallback.runInInheritedContext(TraceContext.java:300)
        at com.google.tracing.TraceContext$TraceContextRunnable.run(TraceContext.java:441)
        at com.google.apphosting.runtime.ThreadGroupPool$PoolEntry.run(ThreadGroupPool.java:251)
        at java.lang.Thread.run(Thread.java:724)

------------------------------------------------------
http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447&dsMessageId=3077086
Reply | Threaded
Open this post in threaded view
|

Re: Intermittent NPE in java.io.reader

Jerome Louvel-3
Hi Andy,

I'm not aware of this issue. It might be a bug so I encourage you to file a GitHub issue.
Otherwise, have you tried to migrate to 2.1.7 or better to 2.2.0?

Regarding the range representation, you might want to try disable the RangeService which filters all the API calls.
Just call getRangeService().setEnabled(false) on your Application subclass.




On Fri, Apr 25, 2014 at 3:11 PM, Andy Dennie <[hidden email]> wrote:
Hi, I'm hoping maybe this problem looks familiar to somebody out there..

I'm using Restlet 2.1.4 on GAE, and I'm seeing intermittent NPEs with the (partial) stack trace below.  This is happening on about 1% of requests.

17:00:19.465 org.restlet.engine.io.BioUtils getReader: The GAE edition is unable to return a reader for a writer representation.
   E 17:00:19.465 org.restlet.engine.adapter.ServerAdapter commit: An exception occured writing the response entity
java.lang.NullPointerException
        at java.io.Reader.<init>(Reader.java:78)
        at java.io.BufferedReader.<init>(BufferedReader.java:94)
        at org.restlet.engine.io.ReaderInputStream.<init>(ReaderInputStream.java:101)
        at org.restlet.engine.io.BioUtils.getStream(BioUtils.java:354)
        at org.restlet.representation.CharacterRepresentation.getStream(CharacterRepresentation.java:70)
        at org.restlet.util.WrapperRepresentation.getStream(WrapperRepresentation.java:151)
        at org.restlet.engine.application.RangeRepresentation.getStream(RangeRepresentation.java:117)
        at org.restlet.engine.application.RangeRepresentation.write(RangeRepresentation.java:146)
        at org.restlet.engine.adapter.ServerCall.writeResponseBody(ServerCall.java:510)
        at org.restlet.engine.adapter.ServerCall.sendResponse(ServerCall.java:454)

In the full stack trace further below, I've interspersed the source code at each stack level.  Here's my analysis so far:

The Reader constructor has received a null "lock" parameter from its caller.
BufferedReader is just passing its first argument ("in", a Reader) to super, so "in" must be null.
which means that in ReaderInputStream's constructor, "reader" is null
which means that in BioUtils.getStream, "reader" (its first arg) is null
which means that in CharacterRepresentation.getStream, getReader() is returning null

CharacterRepresentation is abstract and doesn't implement getReader, so its implementation is coming from one of its subclasses.
Since it is getting called from WrapperRepresentation.getStream, that indicates that the CharacterRepresentation is a wrapped representation.
Since that is getting called from RangeRepresentation.getStream, we know that the wrapper is a RangeRepresentation, although we don't know what the wrapped representation is (other than it is derived from CharacterRepresentation)
Since that is getting called from ServerCall.writeResponseBody, for the object "entity", we know that "entity" is a RangeRepresentation.

The problem is that I'm expecting "entity" to be a JacksonRepresentation, not a RangeRepresentation.  And I can't find any code that instantiates a RangeRepresention outside of RangeFilter, which I'm not using (to my knowledge).

Any ideas?

-Andy


   W 17:00:19.465 org.restlet.engine.io.BioUtils getReader: The GAE edition is unable to return a reader for a writer representation.
   E 17:00:19.465 org.restlet.engine.adapter.ServerAdapter commit: An exception occured writing the response entity
java.lang.NullPointerException
        at java.io.Reader.<init>(Reader.java:78)

protected Reader(Object lock) {
    if (lock == null) {
        throw new NullPointerException();

        at java.io.BufferedReader.<init>(BufferedReader.java:94)

super(in);

        at org.restlet.engine.io.ReaderInputStream.<init>(ReaderInputStream.java:101)

reader = (reader instanceof BufferedReader) ? (BufferedReader) reader : new BufferedReader(reader, IoUtils.BUFFER_SIZE);

        at org.restlet.engine.io.BioUtils.getStream(BioUtils.java:354)

result = new ReaderInputStream(reader, characterSet);

        at org.restlet.representation.CharacterRepresentation.getStream(CharacterRepresentation.java:70)

return BioUtils.getStream(getReader(), getCharacterSet());

        at org.restlet.util.WrapperRepresentation.getStream(WrapperRepresentation.java:151)

return getWrappedRepresentation().getStream();

        at org.restlet.engine.application.RangeRepresentation.getStream(RangeRepresentation.java:117)

return new RangeInputStream(super.getStream(), getSize(), getRange());

        at org.restlet.engine.application.RangeRepresentation.write(RangeRepresentation.java:146)

BioUtils.copy(getStream(), outputStream);

        at org.restlet.engine.adapter.ServerCall.writeResponseBody(ServerCall.java:510)

entity.write(responseEntityStream);

        at org.restlet.engine.adapter.ServerCall.sendResponse(ServerCall.java:454)
        at org.restlet.ext.servlet.internal.ServletCall.sendResponse(ServletCall.java:459)
        at org.restlet.engine.adapter.ServerAdapter.commit(ServerAdapter.java:196)
        at org.restlet.engine.adapter.HttpServerHelper.handle(HttpServerHelper.java:153)
        at org.restlet.ext.servlet.ServerServlet.service(ServerServlet.java:1089)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
        at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511)
        at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166)
        at com.googlecode.objectify.cache.AsyncCacheFilter.doFilter(AsyncCacheFilter.java:59)
        at com.googlecode.objectify.ObjectifyFilter.doFilter(ObjectifyFilter.java:49)
        at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
        at com.google.apphosting.utils.servlet.ParseBlobUploadFilter.doFilter(ParseBlobUploadFilter.java:125)
        at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
        at com.google.apphosting.runtime.jetty.SaveSessionFilter.doFilter(SaveSessionFilter.java:35)
        at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
        at com.google.apphosting.utils.servlet.JdbcMySqlConnectionCleanupFilter.doFilter(JdbcMySqlConnectionCleanupFilter.java:60)
        at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
        at com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:43)
        at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
        at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388)
        at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
        at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)
        at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
        at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418)
        at com.google.apphosting.runtime.jetty.AppVersionHandlerMap.handle(AppVersionHandlerMap.java:266)
        at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
        at org.mortbay.jetty.Server.handle(Server.java:326)
        at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
        at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:923)
        at com.google.apphosting.runtime.jetty.RpcRequestParser.parseAvailable(RpcRequestParser.java:76)
        at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
        at com.google.apphosting.runtime.jetty.JettyServletEngineAdapter.serviceRequest(JettyServletEngineAdapter.java:146)
        at com.google.apphosting.runtime.JavaRuntime$RequestRunnable.run(JavaRuntime.java:446)
        at com.google.tracing.TraceContext$TraceContextRunnable.runInContext(TraceContext.java:437)
        at com.google.tracing.TraceContext$TraceContextRunnable$1.run(TraceContext.java:444)
        at com.google.tracing.CurrentContext.runInContext(CurrentContext.java:188)
        at com.google.tracing.TraceContext$AbstractTraceContextCallback.runInInheritedContextNoUnref(TraceContext.java:308)
        at com.google.tracing.TraceContext$AbstractTraceContextCallback.runInInheritedContext(TraceContext.java:300)
        at com.google.tracing.TraceContext$TraceContextRunnable.run(TraceContext.java:441)
        at com.google.apphosting.runtime.ThreadGroupPool$PoolEntry.run(ThreadGroupPool.java:251)
        at java.lang.Thread.run(Thread.java:724)

------------------------------------------------------
http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447&dsMessageId=3077086