87

In ArrayBlockingQueue, all the methods that require the lock copy it to a local final variable before calling 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();
    }
}

Is there any reason to copy this.lock to a local variable lock when the field this.lock is final?

Additionally, it also uses a local copy of E[] before acting on it:

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

Is there any reason for copying a final field to a local final variable?

2 Answers 2

72

It's an extreme optimization Doug Lea, the author of the class, likes to use. Here's a post on a recent thread on the core-libs-dev mailing list about this exact subject which answers your question pretty well.

from the post:

...copying to locals produces the smallest bytecode, and for low-level code it's nice to write code that's a little closer to the machine

Sign up to request clarification or add additional context in comments.

9 Comments

Strong emphasis on "extreme"! This is not a general-purpose good programming practice that everyone should be emulating.
Random FYI: in some other cases when you see this done, it's because the field in question is volatile, and the method needs to make sure it's got a single consistent value or reference for it throughout.
I'll take this "extreme" optimization in a core class like this.
@zamza, local final variables are only used by java compiler, not the bytecode (i.e. JVM doesn't know if a local variable is final)
In addition to bytecode size, is this an optimization also for execution speed ?
|
13

This thread gives some answers. In substance:

  • the compiler can't easily prove that a final field does not change within a method (due to reflection / serialization etc.)
  • most current compilers actually don't try and would therefore have to reload the final field everytime it is used which could lead to a cache miss or a page fault
  • storing it in a local variable forces the JVM to perform only one load

1 Comment

I don't think a final variable has to be reloaded by the JVM. If you modify a final variable via reflection, you lose guarantee of your program working correctly (meaning the new value might not be taken into account in all cases).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.