Method reference inside synchronized expression - java

Sorry guys, but I can not understand, on which object is synchronized block inside sync() method is synchronized:
public class TestLambda {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
new Thread(() -> {
try {
sync();
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
}
static void sync() throws InterruptedException {
synchronized ((Runnable)TestLambda::new) {
System.out.println("inside");
Thread.sleep(1000L);
}
}
}
If on method reference object, why I can not just write:
synchronized (TestLambda::new) ? (it will be compile-time-error).
Any ideas?
UPD: Just in case: it is really synchronized
UPD-2: For those, who is doubting, simple example:
C:\sandbox\research\learn8\src>"C:\Program Files\Java\jdk1.8.0_31\bin\"javac TestLambda.java
TestLambda.java:27: error: method reference not expected here
public class Test { { synchronized (Test::new) { System.out.println("sync"); } } }
^
1 error

Let's see the below 2 assignments:
Supplier<TestLambda> supp = TestLambda::new;
Runnable runnable = TestLambda::new;
both of them compiles fine. Basically because a lambda or a method reference can be compatible to multiple functional interfaces. That means, merely writing TestLambda::new doesn't tell us the exact runtime type of the object created. Which interface to instantiate is determined based on target type. And that target type should always be a functional interface, which is not the case in the below statement:
synchronized(TestLambda::new) {
}
So, the compiler wouldn't allow it, as the runtime wouldn't be able to decide which functional interface to instantiate. You give that information by casting the method reference to Runnable. So, in the below statement:
synchronized((Runnable) TestLambda::new) {
}
the runtime will instantiate an object of class implementing the Runnable interface. In a sense, the casting gives a concreteness to the method reference.
To give a vague idea, this could somewhat be translated like this:
class RuntimeClass implements Runnable {
public void run() {
TestLambda testLambda = new TestLambda();
}
}
synchronized(new RuntimeClass()) {
}
P.S: Actual instance of the RuntimeClass will be singleton (as we're using a stateless method expression) -- My original incorrect statement
P.P.S: As noted from comments by #Stuart, it is not guaranteed whether for a lambda or method reference, a new instance will be created or the same will be returned. So, you shouldn't synchronize on them.

JLS 14.19. The synchronized Statement
SynchronizedStatement:
synchronized ( Expression ) Block
The type of Expression must be a reference type, or a compile-time error occurs.
JLS 15.13.2. Type of a Method Reference
A method reference expression is compatible in an assignment context, invocation context, or casting context with a target type T if T is a functional interface type (§9.8) and the expression is congruent with the function type of the ground target type derived from T.
The above two stipulations should paint the picture: the synchronized statement takes any reference-typed expression, and a method reference is compatible with any target reference type T which is a functional interface. Note that Object does not satisfy this.
In other words, there is a degree of freedom left: which exactly reference type should the method reference be compatible with? This freedom must be taken away by an explicit type cast, which forces it into that particular type. Only then has the type of the whole expression become known.

Related

Lambda capturing instance variable

From reading the JLS after a frustrating debugging session I find that lambdas will capture the value of effectively-final local variables, but if you refer to an instance variable it captures a reference to the variable, which has serious implications for multi-threaded code.
For example, the following is an MCVE distilled from a much larger program:
public class LambdaCapture
{
public static void main(String[] args) throws Exception
{
Launcher i1 = new Launcher();
i1.launchAsynchTask();
}
public static class Launcher
{
private int value = 10;
public void launchAsynchTask() throws Exception
{
System.out.printf("In launchAsynchTask value is %s\n",value);
Thread t = new Thread(()->doSomething(value));
t.start();
value = -1;
t.join();
}
public void doSomething(int value)
{
System.out.printf("In asynch task, value is %s\n",value);
}
}
}
I found the output surprising. It is
In launchAsynchTask value is 10
In asynch task, value is -1
since I initially (prior to JLS research) and intuitively expected the lambda to capture the value of the variable value instead of a reference to it.
If I have to guarantee that the current value is captured instead of a reference the obvious solution is to create a local final temporary:
final int capture = this.value;
Thread t = new Thread(()->doSomething(capture));
My question: Is this the accepted idiomatic way to force value capture, or is there some other more natural way to do it?
I ... intuitively expected the lambda to capture the value of the variable value instead of a reference to it.
That (capturing the value) is what happens with local variables.
With fields, what is actually happening is that you are capturing a reference to the instance of the object that the field belongs to. In your case, it is a reference to the Launcher.this object. (The same thing happens when you declare an inner class.)
My question: Is this the accepted idiomatic way to force value capture, or is there some other more natural way to do it?
I can't think of a better way.
Because you're using shorthand syntax, it's not as obvious what is going on.
When you write value to access the field, it implicitly means this.value.
The lambda expression is capturing the absolutely final "local variable" this that is implicit to all non-static methods.
The lambda expression
()->doSomething(value)
is logically equivalent to
new Lambda$1(this)
where Lambda$1 is declared like this (using arbitrary names):
private static final class Lambda$1 implements Runnable {
private final Launcher ref;
Lambda$1(Launcher ref) {
this.ref = ref;
}
#Override
public void run() {
this.ref.doSomething(this.ref.value);
}
}
As you can see, the lambda expression ()->doSomething(value) is not actually capturing value. The unqualified field access is obscuring what is actually happening.
FYI: Hiding field value behind parameter value in the doSomething() method is a bad idea. The name conflict makes the code very vulnerable to misinterpretation by programmers, and good IDEs will warn you about it (unless you disabled that warning).
Hopefully that just happened by mistake here when creating an MCVE, and you wouldn't do that in real code. :-)
What I normally like to do is to minimize code parts that access fields directly, so you could wrap the part starting the thread in a function like this:
public void launchAsynchTask() throws Exception
{
System.out.printf("In launchAsynchTask value is %s\n", this.value);
Thread t = launchAsynchTaskWithValue(this.value);
this.value = -1;
t.join();
}
public Thread launchAsynchTaskWithValue(int launchValue) throws Exception
{
Thread t = new Thread(()->doSomething(launchValue));
t.start();
return t;
}

Generate lambda class for generic type variable using reflection

I am attempting to use Java interfaces as mixins in some high-level wrapper for type D.
interface WrapsD {
D getWrapped();
}
interface FeatureA extends WrapsD {
default ...
}
interface FeatureB extends WrapsD {
default ...
}
abstract class DWrapperFactory<T extends WrapsD> {
protected T doWrap(D d) {
return () -> d; // <- does not work
}
}
interface FeatureAB extends FeatureA, FeatureB {
}
class ProducingDWithFeatureAB extends DWrapperFactory<FeatureAB> {
protected FeatureAB doWrap(D d) {
return () -> d; // <- has to repeat this
}
}
As seen in ProducingDWithFeatureAB, doWrap has to be implemented in each sub-class even though the body is identical. (One more example of why Java generics is really broken.)
Since I already need to create concrete classes like ProducingDWithFeatureAB for other reasons and code exists in the JRE to sythesize lambda classes, it should be possible to write doWrap only once using reflection. I want to know how it can be done.
(doWrap used to be implemented using anonymous inner classes implementing the interface, which is even more biolderplate.)
This has nothing to do with generics; your generic example is just obfuscating the real issue.
Here's the core of the issue: lambda expressions need a target type that is a functional interface, and that target type must be statically known to the compiler. Your code doesn't provide that. For example, the following code would get the same error, for the same reason:
Object o = arg -> expr;
Here, Object is not a functional interface, and lambda expressions can only be used in a context whose type is a (compatible) functional interface.
The use of generics makes it more confusing (and I think you're also confusing yourself about how generics work), but ultimately this is going to be where this bottoms out.
The first thing you have to understand, is, that a method of the form
public Function<X,Y> fun() {
return arg -> expr;
}
is desugared to the equivalent of:
public Function<X,Y> fun() {
return DeclaringClass::lambda$fun$0;
}
private static Y lambda$fun$0(X arg) {
return expr;
}
whereas the types X and Y are derived from the functional signature of your target interface. While the actual instance of the functional interface is generated at runtime, you need a materialized target method to be executed, which is generated by the compiler.
You can generate instances of different interfaces for a single target method reflectively, but it still requires that all these functional interfaces have the same functional signature, e.g. mapping from X to Y, which reduces the usefulness of a dynamic solution.
In your case, where all target interfaces indeed have the same functional signature, it is possible, but I have to emphasize that the whole software design looks questionable to me.
For implementing the dynamic generation, we have to desugar the lambda expression as described above and add the captured variable d as an additional argument to the target method. Since your specific function has no arguments, it makes the captured d the sole method argument:
protected T doWrap(D d) {
Class<T> type=getActualT();
MethodHandles.Lookup l=MethodHandles.lookup();
try
{
MethodType fType = MethodType.methodType(D.class);
MethodType tType = fType.appendParameterTypes(D.class);
return type.cast(LambdaMetafactory.metafactory(l, "getWrapped",
tType.changeReturnType(type), fType,
l.findStatic(DWrapperFactory.class, "lambda$doWrap$0", tType), fType)
.getTarget().invoke(d));
}
catch(RuntimeException|Error t) { throw t; }
catch(Throwable t) { throw new IllegalStateException(t); }
}
private static D lambda$doWrap$0(D d) {
return d;
}
You have to implement the method getActualT() which ought to return the right class object, which is possible if the actual subclass of DWrapperFactory is a proper reifiable type, as you stated. Then, the method doWrap will dynamically generate a proper instance of T, invoking the desugared lambda expression’s method with the captured value of d—all assuming that the type T is indeed a functional interface, which cannot be proven at compile time.
Note that even at runtime, the LambdaMetafactory won’t check whether the invariants hold, you might get errors thrown at a later time if T isn’t a proper functional interface (and subclass of WrapsD).
Now compare to just repeating the method
protected SubtypeOfWrapsD doWrap(D d) {
return () -> d;
}
in each reifiable type that has to exist anyway…

Why can method reference use non-final variables?

I had some confusion about inner classes and lambda expression, and I tried to ask a question about that, but then another doubt arose, and It's probable better posting another question than commenting the previous one.
Straight to the point: I know (thank you Jon) that something like this won't compile
public class Main {
public static void main(String[] args) {
One one = new One();
F f = new F(){ //1
public void foo(){one.bar();} //compilation error
};
one = new One();
}
}
class One { void bar() {} }
interface F { void foo(); }
due to how Java manages closures, because one is not [effectively] final and so on.
But then, how come is this allowed?
public class Main {
public static void main(String[] args) {
One one = new One();
F f = one::bar; //2
one = new One();
}
}
class One { void bar() {} }
interface F { void foo(); }
Is not //2 equivalent to //1? Am I not, in the second case, facing the risks of "working with an out-of-date variable"?
I mean, in the latter case, after one = new One(); is executed f still have an out of date copy of one (i.e. references the old object). Isn't this the kind of ambiguity we're trying to avoid?
A method reference is not a lambda expression, although they can be used in the same way. I think that is what is causing the confusion. Below is a simplification of how Java works, it is not how it really works, but it is close enough.
Say we have a lambda expression:
Runnable f = () -> one.bar();
This is the equivalent of an anonymous class that implements Runnable:
Runnable f = new Runnable() {
public void run() {
one.bar();
}
}
Here the same rules apply as for an anonymous class (or method local class). This means that one needs to effectively final for it to work.
On the other hand the method handle:
Runnable f = one::bar;
Is more like:
Runnable f = new MethodHandle(one, one.getClass().getMethod("bar"));
With MethodHandle being:
public class MethodHandle implements Runnable {
private final Object object;
private final Method method;
public MethodHandle(Object object, java.lang.reflect.Method method) {
this.object = Object;
this.method = method;
}
#Override
public void run() {
method.invoke(object);
}
}
In this case, the object assigned to one is assigned as part of the method handle created, so one itself doesn't need to be effectively final for this to work.
Your second example is simply not a lambda expression. It's a method reference. In this particular case, it chooses a method from a particular object, which is currently referenced by the variable one. But the reference is to the object, not to the variable one.
This is the same as the classical Java case:
One one = new One();
One two = one;
one = new One();
two.bar();
So what if one changed? two references the object that one used to be, and can access its method.
Your first example, on the other hand, is an anonymous class, which is a classical Java structure that can refer to local variables around it. The code refers to the actual variable one, not the object to which it refers. This is restricted for the reasons that Jon mentioned in the answer you referred to. Note that the change in Java 8 is merely that the variable has to be effectively final. That is, it still can't be changed after initialization. The compiler simply became sophisticated enough to determine which cases will not be confusing even when the final modifier is not explicitly used.
The consensus appears to be that this is because when you do it using an anonymous class, one refers to a variable, whereas when you do it using a method reference, the value of one is captured when the method handle is created. In fact, I think that in both cases one is a value rather than a variable. Let's consider anonymous classes, lambda expressions and method references in a bit more detail.
Anonymous classes
Consider the following example:
static Supplier<String> getStringSupplier() {
final Object o = new Object();
return new Supplier<String>() {
#Override
public String get() {
return o.toString();
}
};
}
public static void main(String[] args) {
Supplier<String> supplier = getStringSupplier();
System.out.println(supplier.get()); // Use o after the getStringSupplier method returned.
}
In this example, we are calling toString on o after the method getStringSupplier has returned, so when it appears in the get method, o cannot refer to a local variable of the getStringSupplier method. In fact it is essentially equivalent to this:
static Supplier<String> getStringSupplier() {
final Object o = new Object();
return new StringSupplier(o);
}
private static class StringSupplier implements Supplier<String> {
private final Object o;
StringSupplier(Object o) {
this.o = o;
}
#Override
public String get() {
return o.toString();
}
}
Anonymous classes make it look as if you are using local variables, when in fact the values of these variables are captured.
In contrast to this, if a method of an anonymous class references the fields of the enclosing instance, the values of these fields are not captured, and the instance of the anonymous class does not hold references to them; instead the anonymous class holds a reference to the enclosing instance and can access its fields (either directly or via synthetic accessors, depending on the visibility). One advantage is that an extra reference to just one object, rather than several, is required.
Lambda expressions
Lambda expressions also close over values, not variables. The reason given by Brian Goetz here is that
idioms like this:
int sum = 0;
list.forEach(e -> { sum += e.size(); }); // ERROR
are fundamentally serial; it is quite difficult to write lambda bodies
like this that do not have race conditions. Unless we are willing to
enforce -- preferably at compile time -- that such a function cannot
escape its capturing thread, this feature may well cause more trouble
than it solves.
Method references
The fact that method references capture the value of the variable when the method handle is created is easy to check.
For example, the following code prints "a" twice:
String s = "a";
Supplier<String> supplier = s::toString;
System.out.println(supplier.get());
s = "b";
System.out.println(supplier.get());
Summary
So in summary, lambda expressions and method references close over values, not variables. Anonymous classes also close over values in the case of local variables. In the case of fields, the situation is more complicated, but the behaviour is essentially the same as capturing the values because the fields must be effectively final.
In view of this, the question is, why do the rules that apply to anonymous classes and lambda expressions not apply to method references, i.e. why are you allowed to write o::toString when o is not effectively final? I do not know the answer to that, but it does seem to me to be an inconsistency. I guess it's because you can't do as much harm with a method reference; examples like the one quoted above for lambda expressions do not apply.
No. In your first example you define the implementation of F inline and try to access the instance variable one.
In the second example you basically define your lambda expression to be the call of bar() on the object one.
Now this might be a bit confusing. The benefit of this notation is that you can define a method (most of the time it is a static method or in a static context) once and then reference the same method from various lambda expressions:
msg -> System.out::println(msg);

Java 8 Consumer/Function Lambda Ambiguity

I have an overloaded method that takes a Consumer and a Function object respectively and returns a generic type that matches the corresponding Consumer/Function. I thought this would be fine, but when I try to call either method with a lambda expression I get an error indicating the reference to the method is ambiguous.
Based on my reading of JLS §15.12.2.1. Identify Potentially Applicable Methods: it seems like the compiler should know that my lambda with a void block matches the Consumer method and my lambda with a return type matches the Function method.
I put together the following sample code that fails to compile:
import java.util.function.Consumer;
import java.util.function.Function;
public class AmbiguityBug {
public static void main(String[] args) {
doStuff(getPattern(x -> System.out.println(x)));
doStuff(getPattern(x -> String.valueOf(x)));
}
static Pattern<String, String> getPattern(Function<String, String> function) {
return new Pattern<>(function);
}
static ConsumablePattern<String> getPattern(Consumer<String> consumer) {
return new ConsumablePattern<>(consumer);
}
static void doStuff(Pattern<String, String> pattern) {
String result = pattern.apply("Hello World");
System.out.println(result);
}
static void doStuff(ConsumablePattern<String> consumablePattern) {
consumablePattern.consume("Hello World");
}
public static class Pattern<T, R> {
private final Function<T, R> function;
public Pattern(Function<T, R> function) {
this.function = function;
}
public R apply(T value) {
return function.apply(value);
}
}
public static class ConsumablePattern<T> {
private final Consumer<T> consumer;
public ConsumablePattern(Consumer<T> consumer) {
this.consumer = consumer;
}
public void consume(T value) {
consumer.accept(value);
}
}
}
I also found a similar stackoverflow post that turned out to be a compiler bug. My case is very similar, though a bit more complicated. To me this still looks like a bug, but I wanted to make sure I am not misunderstanding the language spec for lambdas. I'm using Java 8u45 which should have all of the latest fixes.
If I change my method calls to be wrapped in a block everything seems to compile, but this adds additional verbosity and many auto-formatters will reformat it into multiple lines.
doStuff(getPattern(x -> { System.out.println(x); }));
doStuff(getPattern(x -> { return String.valueOf(x); }));
This line is definitely ambiguous:
doStuff(getPattern(x -> String.valueOf(x)));
Reread this from the linked JLS chapter:
A lambda expression (§15.27) is potentially compatible with a functional interface type (§9.8) if all of the following are true:
The arity of the target type's function type is the same as the arity of the lambda expression.
If the target type's function type has a void return, then the lambda body is either a statement expression (§14.8) or a void-compatible block (§15.27.2).
If the target type's function type has a (non-void) return type, then the lambda body is either an expression or a value-compatible block (§15.27.2).
In your case for Consumer you have a statement expression as any method invocation can be used as statement expression even if the method is non-void. For example, you can simply write this:
public void test(Object x) {
String.valueOf(x);
}
It makes no sense, but compiles perfectly. Your method may have a side-effect, compiler doesn't know about it. For example, were it List.add which always returns true and nobody cares about its return value.
Of course this lambda also qualifies for Function as it's an expression. Thus it's ambigue. If you have something which is an expression, but not a statement expression, then the call will be mapped to Function without any problem:
doStuff(getPattern(x -> x == null ? "" : String.valueOf(x)));
When you change it to { return String.valueOf(x); }, you create a value-compatible block, so it matches the Function, but it does not qualify as a void-compatible block. However you may have problems with blocks as well:
doStuff(getPattern(x -> {throw new UnsupportedOperationException();}));
This block qualifies both as a value-compatible and a void-compatible, thus you have an ambiguity again. Another ambigue block example is an endless loop:
doStuff(getPattern(x -> {while(true) System.out.println(x);}));
As for System.out.println(x) case it's a little bit tricky. It surely qualifies as statement expression, so can be matched to Consumer, but seems that it matches to expression as well as spec says that method invocation is an expression. However it's an expression of limited use like 15.12.3 says:
If the compile-time declaration is void, then the method invocation must be a top level expression (that is, the Expression in an expression statement or in the ForInit or ForUpdate part of a for statement), or a compile-time error occurs. Such a method invocation produces no value and so must be used only in a situation where a value is not needed.
So compiler perfectly follows the specification. First it determines that your lambda body is qualified both as an expression (even though its return type is void: 15.12.2.1 makes no exception for this case) and a statement expression, so it's considered an ambiguity as well.
Thus for me both statements compile according to the specification. ECJ compiler produces the same error messages on this code.
In general I'd suggest you to avoid overloading your methods when your overloads has the same number of parameters and has the difference only in accepted functional interface. Even if these functional interfaces have different arity (for example, Consumer and BiConsumer): you will have no problems with lambda, but may have problems with method references. Just select different names for your methods in this case (for example, processStuff and consumeStuff).

Primitive wrappers and static "TYPE" Class object

See Boolean#TYPE for an example of what I'm referring to.
All of the wrapper classes (Boolean, Double, Integer, etc) have a static Class field associated with them called TYPE. What is the meaning of this?
Specifically, here are a few soft tests:
System.out.println(Boolean.class == Boolean.TYPE);
System.out.println(Boolean.TYPE.isInstance(Boolean.valueOf(true)));
Both evaluate as false. (And as a side note, an .equals comparison is unnecessary since Class does not override equals from Object.)
Both Boolean.class and Boolean.TYPE are Class<Boolean> because they are == comparable without an error. Comparing two objects with differently declared generic types is illegal.
On further inspection, the TYPE fields are retrieved by calling a package-private native method Class#getPrimitiveClass along the lines of the following:
public static final Class<Boolean> TYPE = Class.getPrimitiveClass("boolean");
The comment on the method itself is not particularly informative either. It says it returns the VM's class object for the type which is fairly obvious since it is a native method.
I can't find any documentation on this beyond the Java docs' vague allusion to "representing the primitive type". Is there some kind of use for this field? It's unused in the wrapper classes themselves.
(Edited)
System.out.println(boolean.class == Boolean.TYPE);
Is true.
Also one use is then reflection:
try {
Constructor ctor = Boolean.class.getConstructor(Boolean.class);
} catch (Exception e) {
System.out.println("NoSuchMethodException gets thrown");
}
try {
Constructor ctor = Boolean.class.getConstructor(Boolean.TYPE);
System.out.println(ctor.newInstance(true));
} catch (Exception e) {
// (no exception thrown)
}
And I've found some SO threads that cite that, such as this one. I guess I came from the "wrong end" of Google so-to-speak to not find any results on it.
But considering the existence of the "primitive classes" (boolean.class, int.class etc.) that doesn't really explain the TYPE field existence. Basically it's "just there"? I still don't really get it.
The class representing the primitive type is useful in specifying or examining methods that take or return primitives. For example, if your class has a method that looks like this
class Test {
static int round(float val) {...}
}
and you wish to access this method through reflection, you would need to do this:
Method round = Test.class.getMethod("round", Float.TYPE);
You can examine the return type, too:
if (round.getReturnType == Integer.TYPE) {
System.out.println("Method 'round' returns an int.");
}
Using Float.class instead
Method round = Test.class.getMethod("round", Float.class);
would not work, because that would pull a different method - this one:
static int round(Float val) {...}
(Don't have the rep to comment, so must answer.)
To put it succinctly: Float.TYPE == float.class, and Float.class != float.class. Consider:
class Test {
void func() {
Class clazz;
// The two statements do the same thing. On my system, they even compile
// to the same bytecode.
clazz = Integer.TYPE; // explicitly asking for this
clazz = int.class; // must yield the same object as above.
// Both of these below are valid, as the `true' is autoboxed. In
// Java < 1.5, both had to be explicitly boxed
Test.class.getMethod("test", Boolean.class).invoke(this, true);
// calls method A
Test.class.getMethod("test", boolean.class).invoke(this, true);
// calls method B. Could also use getMethod("test", Boolean.TYPE)
}
void test(Boolean b) { System.out.println("Method A"); }
void test(boolean b) { System.out.println("Method B"); }
}
I would assume both int.class andInteger.TYPE have been around from the beginning of Java, though I may be wrong. Integer.TYPE can be initially assigned with Class.getPrimitiveClass("int").

Categories

Resources