Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unused referenced variables always captured in Java

Tags:

java

java-8

I wanted to know if this is an implementation detail...

In Java, used local variables are captured for anonymous classes, and lambdas. For anonymous classes, the this is also captured in a non static context whether needed or not.

It appears, however, any local variable referenced is captured even if not used for Oracle JDK 8 update 181.

public static void main(String[] args) {
    Thread t = Thread.currentThread();
    Runnable run = new Runnable() {
        @Override
        public void run() {
            t.yield();
        }
    };
    Runnable run2 = () -> t.yield();
    run.run();
    run2.run();
}

the byte code for the anonymous Runnable is

  // access flags 0x1
  public run()V
   L0
    LINENUMBER 8 L0
    ALOAD 0
    GETFIELD UnusedLocalVariable$1.val$t : Ljava/lang/Thread;
    POP
    INVOKESTATIC java/lang/Thread.yield ()V
   L1
    LINENUMBER 9 L1
    RETURN
   L2
    LOCALVARIABLE this LUnusedLocalVariable$1; L0 L2 0
    MAXSTACK = 1
    MAXLOCALS = 1

As you can see, it captures the local variable which it loads, but always discards at runtime.

The lambda does much the same, also capturing the variable.

Is this always the case, or an implementation detail?

like image 332
Peter Lawrey Avatar asked Nov 08 '18 10:11

Peter Lawrey


People also ask

How do I get rid of the unused variable warning?

If there are a large number of unused variables or functions, which can happen with ported code, you can add the -Wno-unused compiler option to your makefile. This option suppresses all unused warnings.

What is captured variable in Java?

A captured variable is one that has been copied so it can be used in a nested class. The reason it has to be copied is the object may out live the current context. It has to be final (or effectively final in Java 8) so there is no confusion about whether changes to the variable will be seen (because they won't)

What is an unused variable?

Unused variables are a waste of space in the source; a decent compiler won't create them in the object file. Unused parameters when the functions have to meet an externally imposed interface are a different problem; they can't be avoided as easily because to remove them would be to change the interface.


1 Answers

The specification makes no difference between “referencing” and “using” a variable. In that regard, you are using the variable by invoking t.yield(), despite you’re invoking a static method. For this scenario, the specification says

JLS §15.12.4.1, 15.12.4.1. Compute Target Reference (If Necessary):
  • If form is ExpressionName . [TypeArguments] Identifier, then:
    • If the invocation mode is static, then there is no target reference. The ExpressionName is evaluated, but the result is then discarded.
    • Otherwise, the target reference is the value denoted by ExpressionName.

so the behavior is in line with the specification.

While it’s clear that the evaluation must happen, when it has side effects, I would not go so far to conclude that the bytecode sequence ALOAD 0, GETFIELD, POP is strictly required to fulfill the formal rule that the variable is evaluated and the result is discarded, as that code has no effect at all.

But regardless of whether these instruction are present, the variable t is used and hence subject to the formal requirements, i.e. it must be effective final.

Whether this mandated behavior has to result in capturing the value within the instance of the inner class resp. the class generated for the lambda expression, is, perhaps surprisingly, entirely unspecified. The Java Language Specification does not say anything about it.

In other words, while you are asking about a corner case of the value capturing, i.e. the value of a variable which is referenced but not needed, even the general case, i.e. the well-known rule that inner classes always keep a reference to the enclosing this, even if unneeded, while lambda expression do not, does not appear anywhere in the official specification.

like image 87
Holger Avatar answered Sep 29 '22 08:09

Holger