3

I'm getting this NPE on IBM JVM, 1.6:

java.lang.NullPointerException at java.util.concurrent.ConcurrentLinkedQueue.first(ConcurrentLinkedQueue.java:274) at java.util.concurrent.ConcurrentLinkedQueue.size(ConcurrentLinkedQueue.java:315) . . .

Relevant source shows that line #274 throws on a null "head" member. Search for usages shows this member is set to a new node() as needed, but is never nullified.

How could that be? What am I missing?

... I cannot reproduce this when in debug mode. This queue is accessed from multiple threads.

Snippet (Sun&IBM sources identical except for comments that change line numbers a bit):

     Node<E> first() {
                for (;;) {
                    Node<E> h = head;
                    Node<E> t = tail;
                    Node<E> first = h.getNext(); // line #274 on IBM, #263 on Sun
...
    }
    }
JoshMc
  • 10,239
  • 2
  • 19
  • 38
adaf
  • 258
  • 1
  • 8
  • 2
    If you're using IBM's Java, then surely you're using one of their products (such as WAS). Don't you therefore have a support contract? If so, just raise a PMR with IBM, they have hordes of developers just sitting around waiting for things like this :-) – paxdiablo Apr 29 '13 at 07:24
  • Thanks, indeed am using WAS, but I don't think it is related, and would like to use and enrich the community, not just IBM... The source for this class in Sun and IBM is identical (except comments which move the line numbers around). – adaf Apr 29 '13 at 07:34
  • Well, you could enrich the community once IBM got back to you with the response. I would think with the huge amount of money IBM make from maint contracts, they should fix their _own_ software. – paxdiablo Apr 29 '13 at 07:51

2 Answers2

1

Errors like that often come from the JIT compiler which gets some arcane optimization wrong.

There is little you can do; log error with IBM, they will then guide you through the process how to collect enough information for them to debug the issue.

Note: In the last years, we filed two such issues. So they aren't that uncommon even taking into account the enormous testing effort that IBM spends on their VM.

Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
  • Thanks, Aaron. JIT, yes, did not think about that, it used to give us a lot of strange problems in the past. I can try and disable it and see if it helps (can it be disabled for a single method? class?). Will see if IBM has anything clever to say about this, but I cannot force my customers to disable JITor install a JVM patch from IBM, even if they produce one... My app runs on a WAS I do not own :-( – adaf Apr 29 '13 at 10:53
  • You can't force your customer but you can't fix the issue either. They could force you to rewrite the code to avoid `ConcurrentLinkedQueue` but that doesn't solve anything - they might get the same problem in a different place. So it's important for you to communicate to them that this issue is out of your scope to fix in any reasonable way. – Aaron Digulla Apr 29 '13 at 11:42
0

One obscure scenario that could cause this:

An class A holds a static queue that could take a while to be initialised.

class A {
  // Long process which makes a second thread access `q` while it is still being constructed.
  public Object o = aLongProcess();
  public static Queue q = new ConcurrentLinkedQueue<String>();

A class B accesses the queue.

class B {
  ...
  void doSomething () {
    String s = A.q.first();
  }

Thread T1 is first to access class A - thus beginning its initialisation process.

Object o = A.o;

Thread T2 accesses the queue while it is still being initialised.

B b = new B();
b.doSomething();

So basically you are looking at a race condition between two threads where one thinks the Queue is initialised while the other is still making it.

Note that just because the object name starts with Concurrent does not mean all functionality of the object is thread safe.

I suppose another alternative could be that you only hold weak references to the queue and you are attempting to access it after it has been GC'd but I would expect you would mention that in your question.

OldCurmudgeon
  • 64,482
  • 16
  • 119
  • 213
  • Thanks, OldCurmudgeon. This is not it - the exception occurs some time after the queue has beein initalized and used. No weak-ref to the queue, and also, we know queue itself is alive, only its "head" is null... – adaf Apr 29 '13 at 10:50
  • @adaf - If the IBM one is truly the same as [this](http://fuseyism.com/classpath/doc/java/util/concurrent/ConcurrentLinkedQueue-source.html) then `head` is initialised on construction and never changed. What you are describing is therefore not possible unless 1. its a race condition or 2. it is different. – OldCurmudgeon Apr 29 '13 at 11:00
  • code is truly the same and you're right, while "head" is not final, it is only set on construction and de-serialization (or by unfriendly reflection). Still this error happens, and I guess JIT is indeed the answer. – adaf Apr 30 '13 at 11:28