What is the effect of final variable declaration in methods? - java

Classic example of a simple server:
class ThreadPerTaskSocketServer {
public static void main(String[] args) throws IOException {
ServerSocket socket = new ServerSocket(80);
while (true) {
final Socket connection = socket.accept();
Runnable task = new Runnable() {
public void run() {
handleRequest(connection);
}
};
new Thread(task).start();
}
}
}
Why should the Socket be declared as final? Is it because the new Thread that handles the request could refer back to the socket variable in the method and cause some sort of ConcurrentModificationException?

In this case, the variable must be final to be used inside the anonymous Runnable implmentation.
This is because that object will exist when the variable has already gone out of scope and has thus disappeared. The object gets a copy of the variable. In order to hide this, the variable must be final so that nobody can expect changes in one copy to be visible to the other.

Consider this example:
class A {
B foo() {
final C c;
return new B() {
void goo() {
// do something with c
}
}
}
}
// somewhere else in the code
A a = new A();
B b = a.foo();
b.goo();
If c was not final, when you reach b.goo(), it would point to junk, since that c would be garbage-collected - A local variable after the end of a method call.

You need to declare it final, not only should. Without that, the compiler cannot use it in the anonymous Runnable class implementation.

declaring a method variable final means that it's value can't change; that it can only be set once. how does that apply in this context?
i have known about this restriction with anonymous classes for some time, but i never quite understood why. i see that no one else really does either from the responses so far. some googling turned up the below which i think does a good job of explaining it.
An anonymous local class can use local
variables because the compiler
automatically gives the class a
private instance field to hold a copy
of each local variable the class uses.
The compiler also adds hidden
parameters to each constructor to
initialize these automatically created
private fields. Thus, a local class
does not actually access local
variables, but merely its own private
copies of them. The only way this can
work correctly is if the local
variables are declared final, so that
they are guaranteed not to change.
With this guarantee in place, the
local class is assured that its
internal copies of the variables
accurately reflect the actual local
variables.
credit to:
http://renaud.waldura.com/doc/java/final-keyword.shtml#vars
certainly not obvious and something that i think the compiler really should be hiding from developers.

Local variables are not shared between threads. (A local variable is a part of the activation record, and each thread has its own activation record).
Since connection is a local variable, it's not possible to share it between threads. Since its not shared between threads, you need to make it final, so it doesn't matter that it's a local variable (it can be seen more like a constant value).

It is not intended to solve ConcurrentModificationException. Any local variable used inside a method-nested-class (such as an anonymous inner class) must be declared as final. See a similar discussion from the last week here:
method local innerclasses accessing the local variables of the method
Actually in case of threads there is a minor contribution here for thread safety; there will be no visibility issues on the final variable between the threads. However, this does not guarantee thread safety at all.

Related

Why variable used in lambda expression should be final or effectively final

This question has been previously asked over here
My question regarding why which was answered over here
But I have some doubts about the answer.
The answer provided mentions-
Although other answers prove the requirement, they don't explain why the requirement exists.
The JLS mentions why in §15.27.2:
The restriction to effectively final variables prohibits access to dynamically-changing local variables, whose capture would likely introduce concurrency problems.
To lower the risk of bugs, they decided to ensure captured variables are never mutated.
I am confused by the statement that it would lead to concurrency problems.
I read the article about concurrency problems on Baeldung but still, I am a bit confused about how it will cause concurrency problems, can anybody help me out with an example.
Thanks in advance.
I'd like to preface this answer by saying what I show below is not actually how lambdas are implemented. The actual implementation involves java.lang.invoke.LambdaMetafactory if I'm not mistaken. My answer makes use of some inaccuracies to better demonstrate the point.
Let's say you have the following:
public static void main(String[] args) {
String foo = "Hello, World!";
Runnable r = () -> System.out.println(foo);
r.run();
}
Remember that a lambda expression is shorthand for declaring an implementation of a functional interface. The lambda body is the implementation of the single abstract method of said functional interface. At run-time an actual object is created. So the above results in an object whose class implements Runnable.
Now, the above lambda body references a local variable from the enclosing method. The instance created as a result of the lambda expression "captures" the value of that local variable. It's almost (but not really) like you have the following:
public static void main(String[] args) {
String foo = "Hello, World!";
final class GeneratedClass implements Runnable {
private final String generatedField;
private GeneratedClass(String generatedParam) {
generatedField = generatedParam;
}
#Override
public void run() {
System.out.println(generatedField);
}
}
Runnable r = new GeneratedClass(foo);
r.run();
}
And now it should be easier to see the problems with supporting concurrency here:
Local variables are not considered "shared variables". This is stated in §17.4.1 of the Java Language Specification:
Memory that can be shared between threads is called shared memory or heap memory.
All instance fields, static fields, and array elements are stored in heap memory. In this chapter, we use the term variable to refer to both fields and array elements.
Local variables (§14.4), formal method parameters (§8.4.1), and exception handler parameters (§14.20) are never shared between threads and are unaffected by the memory model.
In other words, local variables are not covered by the concurrency rules of Java and cannot be shared between threads.
At a source code level you only have access to the local variable. You don't see the generated field.
I suppose Java could be designed so that modifying the local variable inside the lambda body only writes to the generated field, and modifying the local variable outside the lambda body only writes to the local variable. But as you can probably imagine that'd be confusing and counterintuitive. You'd have two variables that appear to be one variable based on the source code. And what's worse those two variables can diverge in value.
The other option is to have no generated field. But consider the following:
public static void main(String[] args) {
String foo = "Hello, World!";
Runnable r = () -> {
foo = "Goodbye, World!"; // won't compile
System.out.println(foo);
}
new Thread(r).start();
System.out.println(foo);
}
What is supposed to happen here? If there is no generated field then the local variable is being modified by a second thread. But local variables cannot be shared between threads. Thus this approach is not possible, at least not without a likely non-trivial change to Java and the JVM.
So, as I understand it, the designers put in the rule that the local variable must be final or effectively final in this context in order to avoid concurrency problems and confusing developers with esoteric problems.
When an instance of a lambda expression is created, any variables in the enclosing scope that it refers are copied into it. Now, suppose if that were allowed to modify, and now you are working with a stale value which is there in that copy. On the other hand, suppose the copy is modified inside the lambda, and still the value in the enclosing scope is not updated, leaving an inconsistency. Thus, to prevent such occurrences, the language designers have imposed this restriction. It would probably have made their life easier too. A related answer for an anonymous inner class can be found here.
Another point is that you will be able to pass the lambda expression around and if it is escaped and a different thread executes it, while current thread is updating the same local variable, then there will be some concurrency issues too.
It is for the same reason the anonymous classes require the variables used in their coming out from the scope of themselves must be read-only -> final.
final int finalInt = 0;
int effectivelyFinalInt = 0;
int brokenInt = 0;
brokenInt = 0;
Supplier<Integer> supplier = new Supplier<Integer>() {
#Override
public Integer get() {
return finalInt; // compiles
return effectivelyFinalInt; // compiles
return brokenInt; // doesn't compile
}
};
Lambda expressions are only shortcuts for instances implementing the interface with only one abstract method (#FunctionalInterface).
Supplier<Integer> supplier = () -> brokenInt; // compiles
Supplier<Integer> supplier = () -> brokenInt; // compiles
Supplier<Integer> supplier = () -> brokenInt; // doesn't compile
I struggle to read the Java Language specification to provide support to my statements below, however, they are logical:
Note that evaluation of a lambda expression produces an instance of a functional interface.
Note that instantiating an interface requires implementing all its abstract methods. Doing as an expression produces an anonymous class.
Note that an anonymous class is always an inner class.
Each inner class can access only final or effectively-final variables outside of its scope: Accessing Members of an Enclosing Class
In addition, a local class has access to local variables. However, a local class can only access local variables that are declared final. When a local class accesses a local variable or parameter of the enclosing block, it captures that variable or parameter.

Why does java allow class level variables to be reassigned in anonymous inner class, whereas same is not allowed for local variables [duplicate]

This question already has answers here:
How can non-final fields be used in a anonymous class class if their value can change?
(1 answer)
Lambdas: local variables need final, instance variables don't
(10 answers)
Why can an anonymous class access non-final class member of the enclosing class
(4 answers)
Closed 4 years ago.
This question is similar to Lambdas: local variables need final, instance variables don't,but the only difference is this question is valid even without lambda expressions i.e. valid even on Java7.
Here is the code snippet below.
public class MyClass {
Integer globalInteger = new Integer(1);
public void someMethod() {
Integer localInt = new Integer(2);
Runnable runnable = new Runnable() {
#Override
public void run() {
globalInteger = new Integer(11);//no error
localInt = new Integer(22);//error here
}
};
}
}
I am allowed to reassign globalInteger a new value but not to localInteger. Why is this difference?
To understand why non-local variables are allowed to change, we first need to understand why local variables aren't. And that's because local variables are stored on the stack (which instance (or static) variables aren't).
The problem with stack variables is that they're going to disappear once their containing method returns. However the instance of your anonymous class might live longer than that. So if accessing local variables were implemented naively, using the local variable from inside the inner class after the method returned would access a variable on a stack frame that no longer exists. That would either lead to a crash, an exception or undefined behavior depending on the exact implementation. Since that's clearly bad, access to local variables is implemented via copying instead. That is, all the local variables that are used by the class (including the special variable this) are copied into the anonymous object. So when a method of the inner class accesses a local variable x, it's not actually accessing that local variable. It's accessing a copy of it stored inside the object.
But what would happen if a local variable changed after the object was created or if a method of the object changed the variable? Well, the former would cause the local variable to change, but not the copy in the object, and the latter would change the copy, but not the original. So either way the two versions of the variable would no longer be the same, which would be very counter-intuitive to any programmer who doesn't know about the copying going on. So to avoid this problem, you're only allowed to access local variables if their value is never changed.
Instance variables don't need to be copied because they won't disappear until their containing object is garbage collected (and static variables never disappear) - since the anonymous object will contain a reference to the outer this, this won't happen until the anonymous object is garbage collected as well. So since they aren't copied, modifying them doesn't cause any issues and there's no reason to disallow it.
Because JVM has no machine instruction to assign a variable located at any stack frame which is different from the current stack frame.
because the lambda function is not part of the class.
Think about the following code (small changes of yours):
public Runnable func() {
Integer localInt = new Integer(2);
Runnable runnable = new Runnable() {
#Override
public void run() {
globalInteger = new Integer(11);//no error
localInt = new Integer(22);//error here
}
};
return runnable;
}
//Somewhere in the code:
Runnable r = func();
r.run(); // At this point localInt is not defined.
The complier tells you the error that variable in inner class must be final or effectively final. This is due to Java's 8 closure and how JVM captures the reference. The restriction is that the reference captured in the lambda body must be final (not re-assignable), and complier needs to ensure it doesn't reference copies of local variables.
so if you access instance variable, your lambda is really referencing this instance of the surrounding class, which is effective final (non-changing reference). In addition, if you use a wrapper class or array, the complier error also goes away.

What are captured variables in Java Local Classes

The Java documentation for Local Classes says that:
In addition, a local class has access to local variables. However, a
local class can only access local variables that are declared final.
When a local class accesses a local variable or parameter of the
enclosing block, it captures that variable or parameter. For example,
the PhoneNumber constructor can access the local variable numberLength
because it is declared final; numberLength is a captured variable.
What is captured variable,what is its use and why is that needed? Please help me in understanding the concept of it.
What is captured variable,what is its use and why is that needed?
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)
Note: Groovy does have this rule and a change to the local variable can mean a change to the value in the enclosing class which is especially confusing if multiple threads are involved.
An example of capture variable.
public void writeToDataBase(final Object toWrite) {
executor.submit(new Runnable() {
public void run() {
writeToDBNow(toWrite);
}
});
// if toWrite were mutable and you changed it now, what would happen !?
}
// after the method returns toWrite no longer exists for the this thread...
Here is a post describing it: http://www.devcodenote.com/2015/04/variable-capture-in-java.html
Here is a snippet from the post:
”It is imposed as a mandate by Java that if an inner class defined within a method references a local variable of that method, that local variable should be defined as final.”
This is because the function may complete execution and get removed from the process stack, with all the variables destroyed but it may be the case that objects of the inner class are still on the heap referencing a particular local variable of that function. To counter this, Java makes a copy of the local variable and gives that as a reference to the inner class. To maintain consistency between the 2 copies, the local variable is mandated to be “final” and non-modifiable.
A captured variable is one from the outside of your local class - one declared in the surrounding block. In some languages this is called a closure.
In the example from the Oracle Docs (simplified) the variable numberLength, declared outside of class PhoneNumber, is "captured".
final int numberLength = 10; // in JDK7 and earlier must be final...
class PhoneNumber {
// you can refer to numberLength here... it has been "captured"
}

non-final non-local variable inside anonymous class

As I understand it, Java does not have true closures. You can pass a function by chaperoning them with a class; however, not only is it verbose but also (because of Java's memory model) any references in the anonymous class to variables defined in the environment where it was constructed are passed as copies. The language encourages us to remember this by only allowing anonymous classes to refer to final variables.
Which brings me to this code snippet I found in Bloch's Effective Java:
import java.util.concurrent.*;
public class StopThread {
private static boolean stopRequested;
public static void main(String[] args)
throws InterruptedException {
Thread backgroundThread = new Thread(new Runnable() {
public void run() {
int i = 0;
while (!stopRequested)
i++;
}
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
stopRequested = true;
}
}
First, I expected the compiler to complain because stopRequested is nonfinal and I refer to it inside the anonymous class. My compiler didn't complain.
Second, I expected the program to loop forever since, well, Java doesn't support closures and if the anonymous class really is referring to the actual stopRequested variable from the environment it was constructed (and not a simple copy) then it seems like we have a closure here. Joshua Bloch also said the program loops forever on his computer. But mine runs for about a second and exits.
What part of the memory model am I misunderstanding?
The key thing you're missing is that the anonymous class is a nested class. As such, it has an implicit reference to the instance of the containing class, and therefore members of the class.
It is only local variables which are required to be final for use by anonymous classes.
It loops for me and the reason is to do with CPU cache, not anonymous methods.
With this it always exits:
private volatile static boolean stopRequested;
First, I expected the compiler to complain because stopRequested is
nonfinal and I refer to it inside the anonymous class. My compiler
didn't complain.
stopRequested is a static variable.
Second, I expected the program to loop forever since, well, Java
doesn't support closures and if the anonymous class really is
referring to the actual stopRequested variable from the environment it
was constructed (and not a simple copy) then it seems like we have a
closure here. Joshua Bloch also said the program loops forever on his
computer. But mine runs for about a second and exits
stopRequested is not a volatile variable. Therefore, it may run forever(flag hoisting optimization. (run with -server mode) ).
Therefore, the below code
while (!stopRequested)
i++;
can be reordered as
boolean status = !stopRequested;
while(status)
i++;
What you're misunderstanding is that only local variables are passed as copies to an inner class, because those exist on the stack and thus will be gone when the method call returns.
True closures "magically" provide a context for all captured variables to survive. But for non-local variables, this is not really necessary; they exist on the heap as part of their object or class, so Java permits them to be non-final and still used in an inner class.
What I think Bloch's code example is supposed to demonstrate is a completely different thing: different threads may have local copies of any variable (local, instance, or static) in their CPU's cache, and changes one thread makes may not be visible to other threads for an arbitrarily long time. To ensure that local copies are synced, the change either has to happen in a synchronized block/method, or the variable has to be declared volatile.
You can access fields via a reference (implicitly to OuterClass.this) or static field by class. It is only non-final variables you cannot reference. Note: If this final reference points to something mutable you can change it.
final int[] i = { 0 };
new Thread(new Runnable() {
public void run() {
i[0] = 1;
}
}).start();
while(i[0] == 0);
System.out.println("i= " + i[0]);
stopRequested is not a local variable it is a static variable so it need not be final. The program may loop forever because stopRequested is not declared volatile and thus it is not guaranteed that changes to stopRequested made by one thread will ever be seen in another thread. If you declare stopRequested volatile the program will not run forever.
Expecting the compiler to complain in this example is unusual. Usual expectation is that the program will terminate soon after start. Bloch shows that it may not be the case (which usually astonishes the reader) and then explains why. Bloch is a fairly advanced reading, you may want to try other books on Java first.

method local innerclasses accessing the local variables of the method

Hi I was going through the SCJP book about the innerclasses, and found this statement, it goes something like this.
A method local class can only refer to the local variables which are marked final
and in the explanation the reason specified is about the scope and lifetime of the local class object and the local variables on the heap, but I am unable to understand that. Am I missing anything here about final??
The reason is, when the method local class instance is created, all the method local variables it refers to are actually copied into it by the compiler. That is why only final variables can be accessed. A final variable or reference is immutable, so it stays in sync with its copy within the method local object. Were it not so, the original value / reference could be changed after the creation of the method local class, giving way to confusing behaviour and subtle bugs.
Consider this example from the JavaSpecialist newsletter no. 25:
public class Access1 {
public void f() {
final int i = 3;
Runnable runnable = new Runnable() {
public void run() {
System.out.println(i);
}
};
}
}
The compiler turns the inner class into this:
class Access1$1 implements Runnable {
Access1$1(Access1 access1) {
this$0 = access1;
}
public void run() {
System.out.println(3);
}
private final Access1 this$0;
}
Since the value of i is final, the compiler can "inline" it into the inner class.
As I see it, accessing local variables from method-local-classes (e.g. anonymous class) is a risky thing. It is allowed by the compiler, but it requires good understanding of what is going on.
When the inner class is instantiated, all the references to local variables it uses are copied, and passed as implicit constructor parameters (check the bytecode). Actually the compiler could have allowed making the references non-final, but it would be confusing, since it would not be clear what happens if the method alters the references after the instantiation.
However, making the reference final does not eliminate all problems. While the reference is immutable, the object behind the reference may still be mutable. Any mutations of the object done between the instantiation of the inner class until its activation will be seen by the inner class, and sometimes this is not the intention of the programmer.

Categories