views:

61

answers:

2

Somehow, I'm getting a null pointer exception here with JDK 1.6.0_14:

HttpSession session = request.getSession(true);
LinkedList<MyObject> list = (LinkedList<MyObject>) session.getAttribute(MY_LIST_KEY);
....
list.addFirst( new MyObject(str1, str2, map) );

Then, I get this:

 at java.util.LinkedList.addBefore(LinkedList.java:779)

Here's the method:

private Entry<E> addBefore(E e, Entry<E> entry) {
    Entry<E> newEntry = new Entry<E>(e, entry, entry.previous);
    newEntry.previous.next = newEntry;//this line NPEs
    newEntry.next.previous = newEntry;
    size++;
    modCount++;
    return newEntry;
}

which is called by

public void addFirst(E e) {
    addBefore(e, header.next);
}

Is there any weird way the list can be serialized/deserialized to break the header entry to cause this to happen? I don't see how this could possibly be failing.

Here's the serialization methods for LinkedList

private void writeObject(java.io.ObjectOutputStream s)
    throws java.io.IOException {
    // Write out any hidden serialization magic
    s.defaultWriteObject();

    // Write out size
    s.writeInt(size);

    // Write out all elements in the proper order.
    for (Entry e = header.next; e != header; e = e.next)
        s.writeObject(e.element);
}

private void readObject(java.io.ObjectInputStream s)
    throws java.io.IOException, ClassNotFoundException {
    // Read in any hidden serialization magic
    s.defaultReadObject();

    // Read in size
    int size = s.readInt();

    // Initialize header
    header = new Entry<E>(null, null, null);
    header.next = header.previous = header;

    // Read in all elements in the proper order.
    for (int i=0; i<size; i++)
        addBefore((E)s.readObject(), header);
}
A: 

Most probably, (LinkedList<MyObject>) session.getAttribute(MY_LIST_KEY) returned null.
Update: As correctly pointed out in comments, null can not be returned by getAttribute() here, otherwise stacktrace wouldn't point into internals of LinkedList. So, my suggestion is wrong.

Victor Sorokin
the stacktrace would point at his own code then, not at a line in the LinkedList class.
matt b
if list would be null then the NPE could not come from list addBefore() method.
Neeme Praks
Sorry, overlooked that :) Please, disregard my answer.
Victor Sorokin
+2  A: 

My guess would be improper sharing of the List across multiple threads. I would guess the list is being simultaneously modified by two different threads.

james
How would that invalidate the head element? I don't see a code path here that ever lets header be null, ever.
Stefan Kendall
@Stefan Kendall, If 2 threads concurrently call `readObject()` and `addFirst()` and the 1st blocks right at `header.next = /* right here*/ header.previous = header;` you would have such a case.
rsp
Hm, that seems reasonable. I'll switch to a synchronized list and retest. Good freakin' catch.
Stefan Kendall