java nullpointerexception ibm java.util.concurrent

java - Imposible(?): NullPointerException en ConcurrentLinkedQueue.size()



ibm java.util.concurrent (2)

Obtengo este NPE en IBM JVM, 1.6 :

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

La fuente relevante muestra que la línea # 274 arroja un miembro " cabeza " nulo. La búsqueda de usos muestra que este miembro está configurado en un nuevo nodo () según sea necesario, pero nunca se anula.

¿Cómo es posible? ¿Qué me estoy perdiendo?

... No puedo reproducir esto cuando estoy en modo de depuración. A esta cola se accede desde múltiples hilos.

Fragmento (fuentes de Sun e IBM idénticas excepto por comentarios que cambian un poco los números de línea):

Node<E> first() { for (;;) { Node<E> h = head; Node<E> t = tail; Node<E> first = h.getNext(); // line #274 on IBM, #263 on Sun ... } }


Los errores de este tipo a menudo provienen del compilador JIT, que obtiene una optimización arcana incorrecta.

Hay poco que puedas hacer; error de registro con IBM, ellos lo guiarán a lo largo del proceso sobre cómo recopilar suficiente información para que puedan depurar el problema.

Nota: en los últimos años, presentamos dos de estos problemas. Por lo tanto, no son tan poco comunes, incluso teniendo en cuenta el enorme esfuerzo de prueba que IBM realiza en su máquina virtual .


Un escenario oscuro que podría causar esto:

Una clase A contiene una cola estática que podría tardar un tiempo en inicializarse.

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>();

Una clase B accede a la cola.

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

El hilo T1 es el primero en acceder a la clase A, comenzando así su proceso de inicialización.

Object o = A.o;

El hilo T2 accede a la cola mientras aún se está inicializando.

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

Así que, básicamente, estás viendo una condición de carrera entre dos hilos en la que uno cree que la cola se inicializa mientras que la otra sigue ejecutándose.

Tenga en cuenta que el hecho de que el nombre del objeto comience con Concurrent no significa que toda la funcionalidad del objeto es segura para subprocesos.

Supongo que otra alternativa podría ser que solo tienes referencias débiles en la cola y estás intentando acceder a ella después de haber sido aprobada por GC, pero esperaría que lo menciones en tu pregunta.