Em ArrayBlockingQueue, por que copiar o campo do membro final na variável final local?

Em ArrayBlockingQueue , todos os methods que requerem o bloqueio copiam para uma variável final local antes de chamar lock() .

 public boolean offer(E e) { if (e == null) throw new NullPointerException(); final ReentrantLock lock = this.lock; lock.lock(); try { if (count == items.length) return false; else { insert(e); return true; } } finally { lock.unlock(); } } 

Existe alguma razão para copiar this.lock para um lock variável local quando o campo this.lock é final ?

Além disso, ele também usa uma cópia local de E[] antes de agir:

 private E extract() { final E[] items = this.items; E x = items[takeIndex]; items[takeIndex] = null; takeIndex = inc(takeIndex); --count; notFull.signal(); return x; } 

Existe alguma razão para copiar um campo final para uma variável final local?

    É uma otimização extrema que Doug Lea, o autor da turma, gosta de usar. Aqui está uma postagem em um tópico recente na lista de discussão core-libs-dev sobre esse assunto exato, que responde muito bem à sua pergunta.

    do post:

    … copiar para locais produz o menor bytecode, e para código de baixo nível é legal escrever código que é um pouco mais próximo da máquina

    Este tópico fornece algumas respostas. Na substância:

    • o compilador não pode provar facilmente que um campo final não muda dentro de um método (devido a reflection / serialização etc.)
    • a maioria dos compiladores atuais, na verdade, não tentam e, portanto, teriam que recarregar o campo final toda vez que ele é usado, o que poderia levar a uma falta de cache ou a uma falha de página
    • armazená-lo em uma variável local força a JVM a executar apenas uma carga