Bug 44428 - FunctionMapperImpl.Function throws a NPE in certain circumstances
Summary: FunctionMapperImpl.Function throws a NPE in certain circumstances
Status: RESOLVED FIXED
Alias: None
Product: Tomcat 6
Classification: Unclassified
Component: Servlet & JSP API (show other bugs)
Version: 6.0.14
Hardware: PC Windows Vista
: P2 normal (vote)
Target Milestone: default
Assignee: Tomcat Developers Mailing List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2008-02-15 02:36 UTC by Lee Smith
Modified: 2008-04-17 10:25 UTC (History)
0 users



Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Lee Smith 2008-02-15 02:36:16 UTC
In FunctionMapperImpl.Function it is possible for writeExternal to fail if the
class has just been de-serialised and is then serialised again.

If you look at writeExternal:

   public void writeExternal(ObjectOutput out) throws IOException {
      out.writeUTF((this.prefix != null) ? this.prefix : "");
      out.writeUTF(this.localName);
      out.writeUTF(this.m.getDeclaringClass().getName());
      out.writeUTF(this.m.getName());
      out.writeObject(ReflectionUtil.toTypeNameArray(
         this.m.getParameterTypes()));
   }

you can see that it externalises the function to be invoked by using the
reference to the Method itself.

If you look at readExternal however:

   public void readExternal(ObjectInput in) throws IOException,
         ClassNotFoundException {
            
      this.prefix = in.readUTF();
      if ("".equals(this.prefix)) this.prefix = null;
      this.localName = in.readUTF();
      this.owner = in.readUTF();
      this.name = in.readUTF();
      this.types = (String[]) in.readObject();
   }

You can see that it doesn't restore the Method after deserialisation. The method
is restored if it is accessed, however if it's not and then serialisation is
performed writeExternal will throw a NPE (as m is still null).

The fix is to either get the method to be reconstructed as soon as
deserialisation completes - or perhaps to be a bit more efficient, in
writeExternal change it such that if m is null it externalises using the
components of the method:

   public void writeExternal(ObjectOutput out) throws IOException {
      out.writeUTF((this.prefix != null) ? this.prefix : "");
      out.writeUTF(this.localName);
      if (m == null) {
         out.writeUTF(this.owner);
         out.writeUTF(this.name);
         out.writeObject(this.types);
      } else if (this.m != null) {
         out.writeUTF(this.m.getDeclaringClass().getName());
         out.writeUTF(this.m.getName());
         out.writeObject(ReflectionUtil.toTypeNameArray(
            this.m.getParameterTypes()));
      }
   }
Comment 1 Mark Thomas 2008-04-09 15:31:05 UTC
Fixed in trunk with a different patch. I went with simple that didn't duplicate code. I have proposed the patch for 6.0.x.
Comment 2 Mark Thomas 2008-04-17 10:25:44 UTC
This bug has been fixed in svn and will be in 6.0.17 onwards.