From damarasekara at typefi.com Tue Aug 12 01:37:05 2014 From: damarasekara at typefi.com (Dinesh Amarasekara) Date: Tue, 12 Aug 2014 11:37:05 +1000 Subject: FreeMarker issue with Java 8 Message-ID: Hi, It seems to be FreeMarker does not call the get method for Java Object. For instance when I use student.name with FreeMarker it should call the method getName from Student class. However it does not happen with Java 8. This worked fine with Java 7. Any input for this is highly appreciated. Thanks And Best Regards, Dinesh. From blackdrag at gmx.org Tue Aug 12 10:59:51 2014 From: blackdrag at gmx.org (Jochen Theodorou) Date: Tue, 12 Aug 2014 12:59:51 +0200 Subject: Lambdas not integrated with annotations In-Reply-To: <53D936DC.30406@univ-mlv.fr> References: <32F15738E8E5524DA4F01A0FA4A8E490C97BC12A@HQMBX5.eur.ad.sag> <1D79688C-705E-4A25-BFD1-F8503EA7ADDB@oracle.com> <53D92FBD.8040504@gmx.org> <53D936DC.30406@univ-mlv.fr> Message-ID: <53E9F3A7.9020105@gmx.org> Sorry, for the very late reply, but I did only now see this mail... Am 30.07.2014 20:18, schrieb Remi Forax: > > On 07/30/2014 07:47 PM, Jochen Theodorou wrote: >> Am 30.07.2014 16:09, schrieb Brian Goetz: >>>> why has it not been made possible to supply lambdas as annotation >>>> parameters? Would it have required too many changes to the language >>>> spec? Not deemed worthwhile? >>> >>> One significant impediment was: Annotation parameters are restricted >>> to the set of values that can be represented in classifies as >>> constants: integers, strings, classes, etc. This would have required >>> significant changes to the JVM spec. >> >> MethodHandles can be constant pool elements too - afaik. > > yes, and a lambda inside an annotation will never capture local value > thus can be represented as a constant method handle. > > But a constant lambda is not enough to reference a lambda, you need 4 > informations (the constant method handle, the functional interface, the > single abstrat method descriptor and a reified version of this very same > descriptor). The later 3 are required for lambdas in Java, not MethodHandles. I was getting to that in the later part of my post. > So the question is how to store a constant method handle and 2 method > types (the method descriptors) as an annotation value > (the functional interface is stored as the type of the annotation > parameter). If you could store the MethodHandle as MethodHandle, you could still make the needed transformation at runtime yourself. [...] > The real issue is that adding a new type of annotation value will > require to update all tools that read annotations, > all the VMs, all the bytecode transformers, all the annotation processor, > so the question was does lambdas in annotation worth the trouble to > update all annotation tools. > > the lambda EG answers 'no' to that question. well... there are many people seeing that different ;) > Note that instead of trying to represent a JUnit test as a lambda, > it's better to create a new tool for doing unit testing that works like > Ruby Rspec, > their way to describe an unit test is in my opinion better than what we > can do with JUnit. Maybe, there are also things in the Groovy world like http://gcontracts.org/ bye Jochen -- Jochen "blackdrag" Theodorou - Groovy Project Tech Lead blog: http://blackdragsview.blogspot.com/ german groovy discussion newsgroup: de.comp.lang.misc For Groovy programming sources visit http://groovy-lang.org From richard.warburton at gmail.com Wed Aug 20 22:00:49 2014 From: richard.warburton at gmail.com (Richard Warburton) Date: Wed, 20 Aug 2014 23:00:49 +0100 Subject: Allocation of Lambdas that capture "this" Message-ID: Hi, I've recently being using Java 8 in a fairly performance critical project. We make extensive use of lambdas to implement callback handlers. For the most part this works well and the no-allocation on non-capturing lambdas makes for significantly nicer code than implementing the equivalent in Java 7. Unfortunately we still have quite a few callbacks where we capture no local variables, but want to refer to a field of the current class or even just call a method on the current class. Under the current implementation this still seems to require allocation. In our case we've hoisted up the code into the constructor and assigned it to a field, we then refer directly to the field at the callsite. Here's a pseudocode example just to clarify what I'm talking about. Allocating: public Foo() {} public int read() { return queue.read(obj -> { this.doSomethingWith(obj); ... }); } Non-allocating: private final Consumer readHandler; public Foo() { readHandler = obj -> { this.doSomethingWith(obj); ... }; } public int read() { return queue.read(readHandler); } Now this isn't the end of the world but it is choosing to write non-idiomatic code for purely performance reasons. Maybe I've missed something here and there are subtleties that I'm missing - I'm always happy to be corrected if I've misunderstood something. I'm sure people have thought about this one before and I'm bring up this specific issue not because "it looks like the JDK isn't doing something optimal" but because this was a problem in a concrete scenario. I spent a few hours this afternoon doing some memory profiling and this pattern was responsible for 6 or the top 8 allocation sites. regards, Richard Warburton http://insightfullogic.com @RichardWarburto From brian.goetz at oracle.com Wed Aug 20 22:43:34 2014 From: brian.goetz at oracle.com (Brian Goetz) Date: Wed, 20 Aug 2014 18:43:34 -0400 Subject: Allocation of Lambdas that capture "this" In-Reply-To: References: Message-ID: <53F52496.7020608@oracle.com> This is a classic tradeoff; you're loading down the Foo footprint (N more fields) and per-instance instantiation cost (eagerly instantiating N capturing lambdas per Foo instance at Foo-allocation time) by pre-computing all the this-capturing lambdas (or this-bound method references) you might need. In your case, when your Foo objects are long-lived and these lambdas are re-used many times on the critical path, and you have real performance constraints, I could see it being a win. (Of course I wouldn't recommend this approach for the other 99.999% of cases.) On 8/20/2014 6:00 PM, Richard Warburton wrote: > Hi, > > I've recently being using Java 8 in a fairly performance critical project. > We make extensive use of lambdas to implement callback handlers. For the > most part this works well and the no-allocation on non-capturing lambdas > makes for significantly nicer code than implementing the equivalent in Java > 7. > > Unfortunately we still have quite a few callbacks where we capture no local > variables, but want to refer to a field of the current class or even just > call a method on the current class. Under the current implementation this > still seems to require allocation. In our case we've hoisted up the code > into the constructor and assigned it to a field, we then refer directly to > the field at the callsite. Here's a pseudocode example just to clarify what > I'm talking about. > > Allocating: > > public Foo() {} > > public int read() { > return queue.read(obj -> { > this.doSomethingWith(obj); > ... > }); > } > > Non-allocating: > > private final Consumer readHandler; > > public Foo() { > readHandler = obj -> { > this.doSomethingWith(obj); > ... > }; > } > > public int read() { > return queue.read(readHandler); > } > > Now this isn't the end of the world but it is choosing to write > non-idiomatic code for purely performance reasons. Maybe I've missed > something here and there are subtleties that I'm missing - I'm always happy > to be corrected if I've misunderstood something. > > I'm sure people have thought about this one before and I'm bring up this > specific issue not because "it looks like the JDK isn't doing something > optimal" but because this was a problem in a concrete scenario. I spent a > few hours this afternoon doing some memory profiling and this pattern was > responsible for 6 or the top 8 allocation sites. > > regards, > > Richard Warburton > > http://insightfullogic.com > @RichardWarburto > From zhong.j.yu at gmail.com Wed Aug 20 23:58:31 2014 From: zhong.j.yu at gmail.com (Zhong Yu) Date: Wed, 20 Aug 2014 18:58:31 -0500 Subject: Allocation of Lambdas that capture "this" In-Reply-To: References: Message-ID: On Wed, Aug 20, 2014 at 5:00 PM, Richard Warburton wrote: > Hi, > > I've recently being using Java 8 in a fairly performance critical project. > We make extensive use of lambdas to implement callback handlers. For the > most part this works well and the no-allocation on non-capturing lambdas > makes for significantly nicer code than implementing the equivalent in Java > 7. > > Unfortunately we still have quite a few callbacks where we capture no local > variables, but want to refer to a field of the current class or even just > call a method on the current class. Under the current implementation this > still seems to require allocation. In our case we've hoisted up the code > into the constructor and assigned it to a field, we then refer directly to > the field at the callsite. Here's a pseudocode example just to clarify what > I'm talking about. > > Allocating: > > public Foo() {} > > public int read() { > return queue.read(obj -> { > this.doSomethingWith(obj); > ... > }); > } > > Non-allocating: > > private final Consumer readHandler; > > public Foo() { > readHandler = obj -> { > this.doSomethingWith(obj); > ... > }; > } > > public int read() { > return queue.read(readHandler); > } > > Now this isn't the end of the world but it is choosing to write > non-idiomatic code for purely performance reasons. Maybe I've missed Lambda field could become an idiom. Is there any reason not to initialize the field directly? like public int read() { return queue.read(readHandler); } final Consumer readHandler = (Msg obj)-> { this.doSomethingWith(obj); ... }; Zhong Yu bayou.io > something here and there are subtleties that I'm missing - I'm always happy > to be corrected if I've misunderstood something. > > I'm sure people have thought about this one before and I'm bring up this > specific issue not because "it looks like the JDK isn't doing something > optimal" but because this was a problem in a concrete scenario. I spent a > few hours this afternoon doing some memory profiling and this pattern was > responsible for 6 or the top 8 allocation sites. > > regards, > > Richard Warburton > > http://insightfullogic.com > @RichardWarburto > From davmac at bluej.org Thu Aug 21 16:18:35 2014 From: davmac at bluej.org (Davin McCall) Date: Thu, 21 Aug 2014 17:18:35 +0100 Subject: Java 8 language spec flaw/bug Message-ID: <53F61BDB.4060704@bluej.org> Hi, Apologies if this is the wrong place for this. I'm concerned with this bug: https://bugs.openjdk.java.net/browse/JDK-8044053 It concerns changes in the language spec (and the compiler) that cause some backwards incompatibility between Java 7 and Java 8. The example in the bug ticket uses the trinary conditional operator but I believe this is a red herring, that is, the same problem occurs when not using the conditional operator. Specifically, the following compiles with Java 7 but not 8: |--- begin --- public class Foo { public static void main(String[] args) throws Exception { // compiles fine in Java 7 and Java 8: Class aClass= ternary(true, String.class, StringBuilder.class); CharSequence foo= foo(aClass); // Inlining the variable using 'ternary' method // Compiles with Java 7 but not with 8: CharSequence foo2= foo(ternary(true, String.class, StringBuilder.class)); } static T foo(Class clazz) throws Exception { return clazz.newInstance(); } static T ternary(boolean cond, T a, T b) { if (cond) return a; else return b; } } --- end --- | I'm worried about the comments in the bug, but I'm unable to make comment myself (I don't have an OpenJDK account and it doesn't appear to be possible for general members of the public to sign up). See Dan Smith's comment: > In general, the use of context provided by the new strategy is > valuable, but in this case it interferes with the opportunity for > capture. It might be possible to use a strategy similar to 18.5.2 in > order to recognize situations in which eager bottom-up typing and > capture is the more useful approach. Ultimately, this comes down to > whether we consider the conditional expression to be a poly expression > or not (see 15.25.3). (But changing the simple rule, "A reference > conditional expression is a poly expression if it appears in an > assignment context or an invocation context," to something more > complex may not be worthwhile.) This is, in my opinion, bogus. The problem is not in how conditional expressions are treated at all - as I have demonstrated above, the problem also occurs with generic methods. In fact the issue is with section 18.2.3 of the JLS: --- begin --- 18.2.3. Subtyping Constraints ... A constraint formula of the form ?S |<=| T?, where S and T are type arguments (?4.5.1 ), is reduced as follows: If T is a type: * If S is a type, the constraint reduces to ?S = T?. --- end --- This turns a 'contains' constraint directly into an 'equals' constraint, which is precisely what causes the problem. I can see no justification for this. It should instead imply a sub-type constraint, that is, it should reduce to ?S |<:| T?. At this point the problem goes away, without - as far as I can see - having any negative impact on the enhanced type inference that Java 8 provides. Instead of getting two conflicting equality constraints for the T in the Foo example above (T=String and T=StringBuilder), we would get two subtype constraints (String <: T and StringBuilder <: T), which from a theoretical perspective is perfectly correct. Section 18.4 then details how to resolve the two constraints and applies the lub function, just as would be done in the Java 7 language spec. Am I crazy? It seems fundamentally obvious to me that a contains constraint shouldn't be turned into an equality constraint, but everyone else involved seems to be overlooking that. I'd appreciate if someone can either set me straight, or add an appropriate comment to the ticket at https://bugs.openjdk.java.net/browse/JDK-8044053. I'd hate to see this getting "fixed" by changing "whether we consider the conditional expression to be a poly expression or not". Thanks, Davin From brian.goetz at oracle.com Thu Aug 21 16:46:46 2014 From: brian.goetz at oracle.com (Brian Goetz) Date: Thu, 21 Aug 2014 12:46:46 -0400 Subject: Java 8 language spec flaw/bug In-Reply-To: <53F61BDB.4060704@bluej.org> References: <53F61BDB.4060704@bluej.org> Message-ID: <53F62276.7020803@oracle.com> > Apologies if this is the wrong place for this. For the record, now that Project Lambda has concluded, the right place for these comments is probably the newly-created: jls-spec-comments at openjdk.java.net It's also fair play to post your comments in the bug record (if you have sufficient access rights in OpenJDK.) But, the relevant people are also here, so carry on... > > I'm concerned with this bug: > https://bugs.openjdk.java.net/browse/JDK-8044053 > > It concerns changes in the language spec (and the compiler) that cause > some backwards incompatibility between Java 7 and Java 8. The example in > the bug ticket uses the trinary conditional operator but I believe this > is a red herring, that is, the same problem occurs when not using the > conditional operator. Specifically, the following compiles with Java 7 > but not 8: > > |--- begin --- > public class Foo { > > public static void main(String[] args) throws Exception { > // compiles fine in Java 7 and Java 8: > Class aClass= ternary(true, > String.class, StringBuilder.class); > CharSequence foo= foo(aClass); > > // Inlining the variable using 'ternary' method > // Compiles with Java 7 but not with 8: > CharSequence foo2= foo(ternary(true, String.class, > StringBuilder.class)); > } > > static T foo(Class clazz) throws Exception { > return clazz.newInstance(); > } > > static T ternary(boolean cond, T a, T b) { > if (cond) return a; > else return b; > } > } > --- end --- > | > > > I'm worried about the comments in the bug, but I'm unable to make > comment myself (I don't have an OpenJDK account and it doesn't appear to > be possible for general members of the public to sign up). See Dan > Smith's comment: > >> In general, the use of context provided by the new strategy is >> valuable, but in this case it interferes with the opportunity for >> capture. It might be possible to use a strategy similar to 18.5.2 in >> order to recognize situations in which eager bottom-up typing and >> capture is the more useful approach. Ultimately, this comes down to >> whether we consider the conditional expression to be a poly expression >> or not (see 15.25.3). (But changing the simple rule, "A reference >> conditional expression is a poly expression if it appears in an >> assignment context or an invocation context," to something more >> complex may not be worthwhile.) > > This is, in my opinion, bogus. The problem is not in how conditional > expressions are treated at all - as I have demonstrated above, the > problem also occurs with generic methods. In fact the issue is with > section 18.2.3 of the JLS: > > --- begin --- > > > 18.2.3. Subtyping Constraints > > ... > > A constraint formula of the form ?S |<=| T?, where S and T are type > arguments (?4.5.1 > > ), > is reduced as follows: > > If T is a type: > > * If S is a type, the constraint reduces to ?S = T?. > > --- end --- > > > This turns a 'contains' constraint directly into an 'equals' constraint, > which is precisely what causes the problem. I can see no justification > for this. It should instead imply a sub-type constraint, that is, it > should reduce to ?S |<:| T?. At this point the problem goes away, > without - as far as I can see - having any negative impact on the > enhanced type inference that Java 8 provides. Instead of getting two > conflicting equality constraints for the T in the Foo example above > (T=String and T=StringBuilder), we would get two subtype constraints > (String <: T and StringBuilder <: T), which from a theoretical > perspective is perfectly correct. > > Section 18.4 then details how to resolve the two constraints and applies > the lub function, just as would be done in the Java 7 language spec. > > Am I crazy? It seems fundamentally obvious to me that a contains > constraint shouldn't be turned into an equality constraint, but everyone > else involved seems to be overlooking that. I'd appreciate if someone > can either set me straight, or add an appropriate comment to the ticket > at https://bugs.openjdk.java.net/browse/JDK-8044053. I'd hate to see > this getting "fixed" by changing "whether we consider the conditional > expression to be a poly expression or not". > > Thanks, > > Davin > > > > From zhong.j.yu at gmail.com Fri Aug 22 02:54:58 2014 From: zhong.j.yu at gmail.com (Zhong Yu) Date: Thu, 21 Aug 2014 21:54:58 -0500 Subject: Java 8 language spec flaw/bug In-Reply-To: <53F61BDB.4060704@bluej.org> References: <53F61BDB.4060704@bluej.org> Message-ID: Since we have forfeited the bottom-up principle in java8, expressions appear to be more ambiguous to programmers. One programmer reading the example code may as well try to parse it top-down, and come to the conclusion that T cannot be resolved. Another programmer may have the opposite conclusion. In that sense, the code is "practically ambiguous", regardless what the spec actually says. Therefore the choice of rejecting the code is not unreasonable. One workaround is to loosen the signature of foo(Class) to foo(Class). One may object the change because the new signature is not semantically as precise as the old one. We can counter that by saying the method is likely subject to type inference therefore it's nice to give the compiler a little more room to work with. Zhong Yu bayou.io From maurizio.cimadamore at oracle.com Fri Aug 22 09:23:52 2014 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Fri, 22 Aug 2014 10:23:52 +0100 Subject: Java 8 language spec flaw/bug In-Reply-To: <53F62276.7020803@oracle.com> References: <53F61BDB.4060704@bluej.org> <53F62276.7020803@oracle.com> Message-ID: <53F70C28.9090702@oracle.com> I believe the spec is correct as is - note that '<=' denotes a 'type-containment' constraint, not a subtyping constraint. To think about type-containment it is sometimes useful think about types in terms of 'ranges' over simple hierarchies of types (we can let alone interfaces, which only makes everything more complex in this regard). If you think about an imaginary line that goes from Object to 'nulltype' - you will have the following: Object ... Number ... Integer ... nulltype Now, ordinary type (such as Number, Integer) can be thought as 'points' in this imaginary line. On the other hand, wildcard type-arguments are ranges or intervals on this line. For instance, the wildcard '? extends Number' is the interval that goes from Number down to nulltype. Type-containment answers a very simple question: is the interval denoted by one type contained into the interval denoted by another type? Now, using the above metaphore, it is easy to see that if you have a point-like type in the RHS of a containment-test: "is a type T contained in Integer?" The only possible answer is: "yes, only if T == Integer." Hence the spec derivation of the equality constraint. I hope this helps. Maurizio On 21/08/14 17:46, Brian Goetz wrote: > This turns a 'contains' constraint directly into an 'equals' constraint, > which is precisely what causes the problem. I can see no justification > for this. It should instead imply a sub-type constraint, that is, it > should reduce to ?S |<:| T?. At this point the problem goes away, > without - as far as I can see - having any negative impact on the > enhanced type inference that Java 8 provides. Instead of getting two > conflicting equality constraints for the T in the Foo example above > (T=String and T=StringBuilder), we would get two subtype constraints > (String <: T and StringBuilder <: T), which from a theoretical > perspective is perfectly correct. From timo.kinnunen at gmail.com Fri Aug 22 10:48:24 2014 From: timo.kinnunen at gmail.com (=?utf-8?Q?Timo_Kinnunen?=) Date: Fri, 22 Aug 2014 10:48:24 +0000 Subject: =?utf-8?Q?Re:_Java_8_language_spec_flaw/bug?= In-Reply-To: <53F70C28.9090702@oracle.com> References: <53F61BDB.4060704@bluej.org> <53F62276.7020803@oracle.com>,<53F70C28.9090702@oracle.com> Message-ID: <0ac9df8d6a944c96b986cbcceb5a6f3e@gmail.com> Hi, This reminds me of the JEP draft: Improved variance for generic classes and interfaces at http://openjdk.java.net/jeps/8043488 It even says this in the part about type-checking which seems directly relevant: ?Enhanced subtyping: When subtyping encounters two parameterizations of the same class type, it performs a pairwise comparison of the type arguments using type argument containment. The intuition is that a wildcard can "contain" a range of types, while a type can only "contain" itself. By enhancing this relation, we might allow one type to "contain" another if the corresponding type parameter is variant and an appropriate subtyping relationship holds between the two types. With this approach, it might also be useful to define type equality such that a wildcard-parameterized type is considered the same as that type with the wildcards removed.? This regression would then be a concrete incentive towards that JEP. Perhaps one of the ?rules governing appropriate usage of type variables? would be to have a Class be treated as Class, similarly to the proposed rules for Iterator as-if Iterator and Predicate as-if Predicate? -- Have a nice day, Timo. Sent from Windows Mail From: Maurizio Cimadamore Sent: ?Friday?, ?August? ?22?, ?2014 ?12?:?23 To: Brian Goetz, Davin McCall, lambda-dev at openjdk.java.net I believe the spec is correct as is - note that '<=' denotes a 'type-containment' constraint, not a subtyping constraint. To think about type-containment it is sometimes useful think about types in terms of 'ranges' over simple hierarchies of types (we can let alone interfaces, which only makes everything more complex in this regard). If you think about an imaginary line that goes from Object to 'nulltype' - you will have the following: Object ... Number ... Integer ... nulltype Now, ordinary type (such as Number, Integer) can be thought as 'points' in this imaginary line. On the other hand, wildcard type-arguments are ranges or intervals on this line. For instance, the wildcard '? extends Number' is the interval that goes from Number down to nulltype. Type-containment answers a very simple question: is the interval denoted by one type contained into the interval denoted by another type? Now, using the above metaphore, it is easy to see that if you have a point-like type in the RHS of a containment-test: "is a type T contained in Integer?" The only possible answer is: "yes, only if T == Integer." Hence the spec derivation of the equality constraint. I hope this helps. Maurizio On 21/08/14 17:46, Brian Goetz wrote: > This turns a 'contains' constraint directly into an 'equals' constraint, > which is precisely what causes the problem. I can see no justification > for this. It should instead imply a sub-type constraint, that is, it > should reduce to ?S |<:| T?. At this point the problem goes away, > without - as far as I can see - having any negative impact on the > enhanced type inference that Java 8 provides. Instead of getting two > conflicting equality constraints for the T in the Foo example above > (T=String and T=StringBuilder), we would get two subtype constraints > (String <: T and StringBuilder <: T), which from a theoretical > perspective is perfectly correct. From davmac at bluej.org Fri Aug 22 12:49:01 2014 From: davmac at bluej.org (Davin McCall) Date: Fri, 22 Aug 2014 13:49:01 +0100 Subject: Java 8 language spec flaw/bug In-Reply-To: <53F70C28.9090702@oracle.com> References: <53F61BDB.4060704@bluej.org> <53F62276.7020803@oracle.com> <53F70C28.9090702@oracle.com> Message-ID: <53F73C3D.9080605@bluej.org> In the example I gave, the two 'contains' constraints are: T contains String T contains StringBuilder So while you are correct in saying that: > "is a type T contained in Integer?" > > The only possible answer is: > > "yes, only if T == Integer." ... the constraint is the wrong way around in your example, compared to the example I posted. It should rather be: "is the type Integer contained in T?" In this case the answer is "yes, if T is Integer, or a wildcard '? extends (some supertype of Integer)'. > Hence the spec derivation of the equality constraint. This derivation of an equality constraint is too strong, as I have shown; containment is not equality. I do however take your point about changing the contains constraint to a sub-type constraint being an incorrect solution. I suspect now that a full solution would require significant changes to the current wording of the spec. Thanks, Davin On 22/08/14 10:23, Maurizio Cimadamore wrote: > I believe the spec is correct as is - note that '<=' denotes a > 'type-containment' constraint, not a subtyping constraint. To think > about type-containment it is sometimes useful think about types in > terms of 'ranges' over simple hierarchies of types (we can let alone > interfaces, which only makes everything more complex in this regard). > If you think about an imaginary line that goes from Object to > 'nulltype' - you will have the following: > > Object > ... > Number > ... > Integer > ... > nulltype > > Now, ordinary type (such as Number, Integer) can be thought as > 'points' in this imaginary line. On the other hand, wildcard > type-arguments are ranges or intervals on this line. For instance, the > wildcard '? extends Number' is the interval that goes from Number down > to nulltype. Type-containment answers a very simple question: is the > interval denoted by one type contained into the interval denoted by > another type? > > Now, using the above metaphore, it is easy to see that if you have a > point-like type in the RHS of a containment-test: > > "is a type T contained in Integer?" > > The only possible answer is: > > "yes, only if T == Integer." > > Hence the spec derivation of the equality constraint. > > I hope this helps. > > Maurizio > > > On 21/08/14 17:46, Brian Goetz wrote: >> This turns a 'contains' constraint directly into an 'equals' constraint, >> which is precisely what causes the problem. I can see no justification >> for this. It should instead imply a sub-type constraint, that is, it >> should reduce to ?S |<:| T?. At this point the problem goes away, >> without - as far as I can see - having any negative impact on the >> enhanced type inference that Java 8 provides. Instead of getting two >> conflicting equality constraints for the T in the Foo example above >> (T=String and T=StringBuilder), we would get two subtype constraints >> (String <: T and StringBuilder <: T), which from a theoretical >> perspective is perfectly correct. > From davmac at bluej.org Fri Aug 22 12:52:21 2014 From: davmac at bluej.org (Davin McCall) Date: Fri, 22 Aug 2014 13:52:21 +0100 Subject: Java 8 language spec flaw/bug In-Reply-To: References: <53F61BDB.4060704@bluej.org> Message-ID: <53F73D05.6080905@bluej.org> On 22/08/14 03:54, Zhong Yu wrote: > Since we have forfeited the bottom-up principle in java8, expressions > appear to be more ambiguous to programmers. One programmer reading the > example code may as well try to parse it top-down, and come to the > conclusion that T cannot be resolved. I'm not sure how one could come to this conclusion, to be honest. Whether you look at it top-down or bottom-up it's still just constraints being implied and resolved. The constraints, in this case, are satisfiable, but the spec does not currently allow for that resolution. Davin From maurizio.cimadamore at oracle.com Fri Aug 22 13:13:12 2014 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Fri, 22 Aug 2014 14:13:12 +0100 Subject: Java 8 language spec flaw/bug In-Reply-To: <53F73C3D.9080605@bluej.org> References: <53F61BDB.4060704@bluej.org> <53F62276.7020803@oracle.com> <53F70C28.9090702@oracle.com> <53F73C3D.9080605@bluej.org> Message-ID: <53F741E8.5040909@oracle.com> On 22/08/14 13:49, Davin McCall wrote: > In the example I gave, the two 'contains' constraints are: > > T contains String > T contains StringBuilder > > So while you are correct in saying that: > >> "is a type T contained in Integer?" >> >> The only possible answer is: >> >> "yes, only if T == Integer." > > ... the constraint is the wrong way around in your example, compared > to the example I posted. It should rather be: > > "is the type Integer contained in T?" Ah right - I inverted the terms - but same conclusion holds. If both terms of a containment test are proper types (not wildcard type-arguments), S <= T implies S == T. Maurizio > > In this case the answer is > > "yes, if T is Integer, or a wildcard '? extends (some supertype of > Integer)'. No - only Integer, as a 'wildcard' won't be a 'type' - wildcards are said to be type-arguments in the JLS lingo. They are not types. Which means the paragraph you quoted only speaks about S and T being proper types such as String, Integer. > > >> Hence the spec derivation of the equality constraint. > > This derivation of an equality constraint is too strong, as I have > shown; containment is not equality. I do however take your point > about changing the contains constraint to a sub-type constraint being > an incorrect solution. I suspect now that a full solution would > require significant changes to the current wording of the spec. Why is it 'too strong' ? Maurizio > > Thanks, > > Davin > > > On 22/08/14 10:23, Maurizio Cimadamore wrote: >> I believe the spec is correct as is - note that '<=' denotes a >> 'type-containment' constraint, not a subtyping constraint. To think >> about type-containment it is sometimes useful think about types in >> terms of 'ranges' over simple hierarchies of types (we can let alone >> interfaces, which only makes everything more complex in this regard). >> If you think about an imaginary line that goes from Object to >> 'nulltype' - you will have the following: >> >> Object >> ... >> Number >> ... >> Integer >> ... >> nulltype >> >> Now, ordinary type (such as Number, Integer) can be thought as >> 'points' in this imaginary line. On the other hand, wildcard >> type-arguments are ranges or intervals on this line. For instance, >> the wildcard '? extends Number' is the interval that goes from Number >> down to nulltype. Type-containment answers a very simple question: is >> the interval denoted by one type contained into the interval denoted >> by another type? >> >> Now, using the above metaphore, it is easy to see that if you have a >> point-like type in the RHS of a containment-test: >> >> "is a type T contained in Integer?" >> >> The only possible answer is: >> >> "yes, only if T == Integer." >> >> Hence the spec derivation of the equality constraint. >> >> I hope this helps. >> >> Maurizio >> >> >> On 21/08/14 17:46, Brian Goetz wrote: >>> This turns a 'contains' constraint directly into an 'equals' >>> constraint, >>> which is precisely what causes the problem. I can see no justification >>> for this. It should instead imply a sub-type constraint, that is, it >>> should reduce to ?S |<:| T?. At this point the problem goes away, >>> without - as far as I can see - having any negative impact on the >>> enhanced type inference that Java 8 provides. Instead of getting two >>> conflicting equality constraints for the T in the Foo example above >>> (T=String and T=StringBuilder), we would get two subtype constraints >>> (String <: T and StringBuilder <: T), which from a theoretical >>> perspective is perfectly correct. >> > From davmac at bluej.org Fri Aug 22 14:11:48 2014 From: davmac at bluej.org (Davin McCall) Date: Fri, 22 Aug 2014 15:11:48 +0100 Subject: Java 8 language spec flaw/bug In-Reply-To: <53F741E8.5040909@oracle.com> References: <53F61BDB.4060704@bluej.org> <53F62276.7020803@oracle.com> <53F70C28.9090702@oracle.com> <53F73C3D.9080605@bluej.org> <53F741E8.5040909@oracle.com> Message-ID: <53F74FA4.8080800@bluej.org> > >> >> In this case the answer is >> >> "yes, if T is Integer, or a wildcard '? extends (some supertype of >> Integer)'. > No - only Integer, as a 'wildcard' won't be a 'type' - wildcards are > said to be type-arguments in the JLS lingo. They are not types. Yes, but: > Which means the paragraph you quoted only speaks about S and T being > proper types such as String, Integer. No! the paragraph I quoted was: ---begin--- A constraint formula of the form ?S |<=| T?, where S and T are type arguments (?4.5.1 ), is reduced as follows: If T is a type: * If S is a type, the constraint reduces to ?S = T?. ---end--- My assumption is that in: static T foo(Class clazz) { ... } static U ternary(boolean cond, U a, U b) {...} foo(ternary(true, String.class, StringBuilder.class)); The type arguments are those of Class - i.e. String and StringBuilder (from Class and Class, being the types of String.class and StringBuilder.class respectively). These are used to impose constraints on the type variable T (for the foo function). So the constraints are: ?String |<=| T? and ?StringBuilder |<=| T?. Are you saying that the paragraph I quoted does not apply, since 'T' is a type variable and not a proper type? In that case should I apply instead: ---begin--- A constraint formula of the form ?S |<:| T? is reduced as follows: ... (some snipped) ... * Otherwise, if T is an inference variable, ?, the constraint reduces to the bound S |<:| ?. ---end--- If I apply this, the resolution succeeds, I think. Why then does compilation fail? >> >> This derivation of an equality constraint is too strong, as I have >> shown; containment is not equality. I do however take your point >> about changing the contains constraint to a sub-type constraint being >> an incorrect solution. I suspect now that a full solution would >> require significant changes to the current wording of the spec. > Why is it 'too strong' ? Because it requires that a type variable be resolved to a specific, proper type, rather than allowing it to be a capture of a range of types. (Unless I was wrong and this paragraph does not apply at all for the example I am concerned with). If it is applied only to proper types which are not type variables, then it is not too strong. The problem occurs when it is applied to type variables. I hope this makes sense, Davin From maurizio.cimadamore at oracle.com Fri Aug 22 14:23:12 2014 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Fri, 22 Aug 2014 15:23:12 +0100 Subject: Java 8 language spec flaw/bug In-Reply-To: <53F74FA4.8080800@bluej.org> References: <53F61BDB.4060704@bluej.org> <53F62276.7020803@oracle.com> <53F70C28.9090702@oracle.com> <53F73C3D.9080605@bluej.org> <53F741E8.5040909@oracle.com> <53F74FA4.8080800@bluej.org> Message-ID: <53F75250.4060205@oracle.com> On 22/08/14 15:11, Davin McCall wrote: > The type arguments are those of Class - i.e. String and StringBuilder > (from Class and Class, being the types of > String.class and StringBuilder.class respectively). These are used to > impose constraints on the type variable T (for the foo function). So > the constraints are: ?String |<=| T? and ?StringBuilder |<=| T?. Are > you saying that the paragraph I quoted does not apply, since 'T' is a > type variable and not a proper type? In that case should I apply instead: The paragraph applies, since it speaks about 'type'. An inference variable is a type. A type-variable is a type. String is a type. ? extends Something is _not_ a type. So, the constraints should be reduced as equality constraints. And that's the right thing to do - the results of type inference should be proper types - a wildcard is not an acceptable inference result (as, again, it's not a type...). Can think of a type T that is not a wildcard and yet it contains both String and StringBuilder? Maurizio From davmac at bluej.org Fri Aug 22 15:28:33 2014 From: davmac at bluej.org (Davin McCall) Date: Fri, 22 Aug 2014 16:28:33 +0100 Subject: Java 8 language spec flaw/bug In-Reply-To: <53F75250.4060205@oracle.com> References: <53F61BDB.4060704@bluej.org> <53F62276.7020803@oracle.com> <53F70C28.9090702@oracle.com> <53F73C3D.9080605@bluej.org> <53F741E8.5040909@oracle.com> <53F74FA4.8080800@bluej.org> <53F75250.4060205@oracle.com> Message-ID: <53F761A1.9050707@bluej.org> On 22/08/14 15:23, Maurizio Cimadamore wrote: > > On 22/08/14 15:11, Davin McCall wrote: >> The type arguments are those of Class - i.e. String and StringBuilder >> (from Class and Class, being the types of >> String.class and StringBuilder.class respectively). These are used to >> impose constraints on the type variable T (for the foo function). So >> the constraints are: ?String |<=| T? and ?StringBuilder |<=| T?. Are >> you saying that the paragraph I quoted does not apply, since 'T' is a >> type variable and not a proper type? In that case should I apply instead: > The paragraph applies, since it speaks about 'type'. An inference > variable is a type. A type-variable is a type. String is a type. ? > extends Something is _not_ a type. > So, the constraints should be reduced as equality constraints. And > that's the right thing to do - the results of type inference should be > proper types - a wildcard is not an acceptable inference result (as, > again, it's not a type...). > > Can think of a type T that is not a wildcard and yet it contains both > String and StringBuilder? No. But, if 'contains' constraints must always be reduced to 'equals' constraints, then the problem is that there should be no 'contains' constraint in the first place. In Java 7 the type of T could be inferred to be a /capture/ of a wildcard expression, i.e. a capture of '? extends ...' where the wildcard contained both String and StringBuilder. Look again at the method signatures, and the call that causes an error: static T foo(Class clazz) static U ternary(boolean cond, U a, U b) foo(ternary(true, String.class, StringBuilder.class)); (I've changed the name of the type variable of the 'ternary' method from T to U, to avoid confusion). Clearly U can be inferred to be 'Class'. T can be inferred to be a capture of the wildcard in U. It won't be true that T=String, T=StringBuilder, String |<=| T, nor StringBuilder |<=| T, yet clearly the type system is sound. The constraints on T _should_ be: String <: T StringBuilder <: T I'm reading through the spec again now to try and see where it's going wrong. Davin From maurizio.cimadamore at oracle.com Fri Aug 22 16:42:55 2014 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Fri, 22 Aug 2014 17:42:55 +0100 Subject: Java 8 language spec flaw/bug In-Reply-To: <53F761A1.9050707@bluej.org> References: <53F61BDB.4060704@bluej.org> <53F62276.7020803@oracle.com> <53F70C28.9090702@oracle.com> <53F73C3D.9080605@bluej.org> <53F741E8.5040909@oracle.com> <53F74FA4.8080800@bluej.org> <53F75250.4060205@oracle.com> <53F761A1.9050707@bluej.org> Message-ID: <53F7730F.2010405@oracle.com> On 22/08/14 16:28, Davin McCall wrote: > static T foo(Class clazz) > static U ternary(boolean cond, U a, U b) > foo(ternary(true, String.class, StringBuilder.class)); This _does_ compile (at least it does in 9) and it is a very different example from the one quoted in the bug you mentioned [1], which has Class as formals, not just bare U as here. [1] - https://bugs.openjdk.java.net/browse/JDK-8044053 From davmac at bluej.org Fri Aug 22 16:45:49 2014 From: davmac at bluej.org (Davin McCall) Date: Fri, 22 Aug 2014 17:45:49 +0100 Subject: Java 8 language spec flaw/bug In-Reply-To: <53F761A1.9050707@bluej.org> References: <53F61BDB.4060704@bluej.org> <53F62276.7020803@oracle.com> <53F70C28.9090702@oracle.com> <53F73C3D.9080605@bluej.org> <53F741E8.5040909@oracle.com> <53F74FA4.8080800@bluej.org> <53F75250.4060205@oracle.com> <53F761A1.9050707@bluej.org> Message-ID: <53F773BD.1030604@bluej.org> > I'm reading through the spec again now to try and see where it's going > wrong. Urgh. The spec is not going wrong at all (at least not for the case of generic methods). I followed the spec closely and discovered that it does in fact appear to do the right thing - it resolves the return type of the inner method first, and doesn't apply equality constraints to the T parameter of the "foo" method. It appears I was seeing a compiler bug which has since been fixed, because in Jdk 8u20 the problem no longer manifests. Apologies if I've wasted anyone's time. Using the ternary operator, however, still fails. I don't see why it shouldn't behave in exactly the same way as the "ternary" method I defined in my example, however. I am somewhat suspicious that perhaps the compiler, and not the spec, is again to blame. Davin From maurizio.cimadamore at oracle.com Fri Aug 22 16:56:57 2014 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Fri, 22 Aug 2014 17:56:57 +0100 Subject: Java 8 language spec flaw/bug In-Reply-To: <53F773BD.1030604@bluej.org> References: <53F61BDB.4060704@bluej.org> <53F62276.7020803@oracle.com> <53F70C28.9090702@oracle.com> <53F73C3D.9080605@bluej.org> <53F741E8.5040909@oracle.com> <53F74FA4.8080800@bluej.org> <53F75250.4060205@oracle.com> <53F761A1.9050707@bluej.org> <53F773BD.1030604@bluej.org> Message-ID: <53F77659.90504@oracle.com> On 22/08/14 17:45, Davin McCall wrote: > Using the ternary operator, however, still fails. I don't see why it > shouldn't behave in exactly the same way as the "ternary" method I > defined in my example, however. I am somewhat suspicious that perhaps > the compiler, and not the spec, is again to blame. Well, if you look at Dan's eval of 8044053, he explains that the conditional is missing the same subtle check that has been applied for nested method calls - i.e. a reference conditional is always a poly conditional - it's never type-checked bottom up; on the other hand, for nested method calls there is some extra analysis to prevent constraint propagation and to allow for more compatibility. I think that, in the case of conditionals, there's a design tension between being able to define a granular enough classification (poly vs. standalone) that will allow 'reasonable' code to compile vs. defining a classification analysis that's easy to spot when you read the code. Maurizio From daniel.smith at oracle.com Fri Aug 22 17:25:00 2014 From: daniel.smith at oracle.com (Dan Smith) Date: Fri, 22 Aug 2014 11:25:00 -0600 Subject: Java 8 language spec flaw/bug In-Reply-To: <53F61BDB.4060704@bluej.org> References: <53F61BDB.4060704@bluej.org> Message-ID: <0D453D18-6E40-4C73-AD7D-D8964AFA3F2A@oracle.com> I think this has been sorted out, but let me just offer some point-by-point comments. On Aug 21, 2014, at 10:18 AM, Davin McCall wrote: > I'm concerned with this bug: > https://bugs.openjdk.java.net/browse/JDK-8044053 > > It concerns changes in the language spec (and the compiler) that cause some backwards incompatibility between Java 7 and Java 8. The example in the bug ticket uses the trinary conditional operator but I believe this is a red herring, that is, the same problem occurs when not using the conditional operator. > > Specifically, the following compiles with Java 7 but not 8: > > |--- begin --- > public class Foo { > > public static void main(String[] args) throws Exception { > // compiles fine in Java 7 and Java 8: > Class aClass= ternary(true, String.class, StringBuilder.class); > CharSequence foo= foo(aClass); > > // Inlining the variable using 'ternary' method > // Compiles with Java 7 but not with 8: > CharSequence foo2= foo(ternary(true, String.class, StringBuilder.class)); > } > > static T foo(Class clazz) throws Exception { > return clazz.newInstance(); > } > > static T ternary(boolean cond, T a, T b) { > if (cond) return a; > else return b; > } > } > --- end --- This is a compiler bug, fixed by JDK-8030741. The relevant spec is here: http://docs.oracle.com/javase/specs/jls/se8/html/jls-18.html#jls-18.5.2 "Otherwise, if R ? is an inference variable ?, and ... T is a reference type, but is not a wildcard-parameterized type, and ... B2 contains two bounds of the forms S1 <: ? and S2 <: ?, where S1 and S2 have supertypes that are two different parameterizations of the same generic class or interface" In these circumstances, ? is resolved immediately, and capture is performed. Applied to your example: R (return type) = T (type parameter of 'ternary') R ? = t1 (an inference variable substituted for T) T (target type) = Class (where t2 is an inference variable substituted for T, the type parameter of 'foo') B2 = { t1 <: Object, Class <: t1, Class <: t1 } S1 = Class S2 = Class So t1 must be resolved immediately, producing 'Class'; then we capture this, and get the constraint 'Class --> Class'. > I'm worried about the comments in the bug, but I'm unable to make comment myself (I don't have an OpenJDK account and it doesn't appear to be possible for general members of the public to sign up). See Dan Smith's comment: > >> In general, the use of context provided by the new strategy is valuable, but in this case it interferes with the opportunity for capture. It might be possible to use a strategy similar to 18.5.2 in order to recognize situations in which eager bottom-up typing and capture is the more useful approach. Ultimately, this comes down to whether we consider the conditional expression to be a poly expression or not (see 15.25.3). (But changing the simple rule, "A reference conditional expression is a poly expression if it appears in an assignment context or an invocation context," to something more complex may not be worthwhile.) > > This is, in my opinion, bogus. The problem is not in how conditional expressions are treated at all - as I have demonstrated above, the problem also occurs with generic methods. As you've seen, no, the example you provide is a separate bug from 8044053, and is just a compiler bug. The conditional operator is an essential part of 8044053, and unfortunately that case is not a simple matter of making javac conform to the spec. > In fact the issue is with section 18.2.3 of the JLS: > > --- begin --- > > > 18.2.3. Subtyping Constraints > > ... > > A constraint formula of the form ?S |<=| T?, where S and T are type > arguments (?4.5.1 > ), > is reduced as follows: > > If T is a type: > > * If S is a type, the constraint reduces to ?S = T?. > > --- end --- > > > This turns a 'contains' constraint directly into an 'equals' constraint, which is precisely what causes the problem. I can see no justification for this. It should instead imply a sub-type constraint, that is, it should reduce to ?S |<:| T?. There's been some discussion about this, but to be clear: you're misunderstanding the meaning of "contains" and/or the meaning of inference variables. http://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.5.1 defines containment. http://docs.oracle.com/javase/specs/jls/se8/html/jls-18.html#jls-18.1.1 defines inference variables. Note that inference variables represent some unknown type, and in particular, an inference variable cannot represent a wildcard. The only rule in 4.5.1 that applies to two different types (not wildcards) is this: T <= T Or, in other words, S <= T iff S = T ?Dan From davmac at bluej.org Fri Aug 22 19:20:25 2014 From: davmac at bluej.org (Davin McCall) Date: Fri, 22 Aug 2014 20:20:25 +0100 Subject: Java 8 language spec flaw/bug In-Reply-To: <53F77659.90504@oracle.com> References: <53F61BDB.4060704@bluej.org> <53F62276.7020803@oracle.com> <53F70C28.9090702@oracle.com> <53F73C3D.9080605@bluej.org> <53F741E8.5040909@oracle.com> <53F74FA4.8080800@bluej.org> <53F75250.4060205@oracle.com> <53F761A1.9050707@bluej.org> <53F773BD.1030604@bluej.org> <53F77659.90504@oracle.com> Message-ID: <53F797F9.7020802@bluej.org> On 22/08/14 17:56, Maurizio Cimadamore wrote: > > Well, if you look at Dan's eval of 8044053, he explains that the > conditional is missing the same subtle check that has been applied for > nested method calls - i.e. a reference conditional is always a poly > conditional - it's never type-checked bottom up; on the other hand, > for nested method calls there is some extra analysis to prevent > constraint propagation and to allow for more compatibility. I think > that, in the case of conditionals, there's a design tension between > being able to define a granular enough classification (poly vs. > standalone) that will allow 'reasonable' code to compile vs. defining > a classification analysis that's easy to spot when you read the code. Ok, got it (I think). Thanks for your time, this has been very helpful for me in understanding the type inference process generally. Davin From Sebastian.Millies at softwareag.com Sun Aug 24 18:21:08 2014 From: Sebastian.Millies at softwareag.com (Millies, Sebastian) Date: Sun, 24 Aug 2014 18:21:08 +0000 Subject: CompletableFuture with delay Message-ID: <32F15738E8E5524DA4F01A0FA4A8E490DF0FA267@HQMBX5.eur.ad.sag> Hello there, I'd like to simulate asynchronous IO events in a test system (without actual IO). For this purpose, I have defined a method that creates a future which returns a value after a delay. In contrast to Future#get(Long,TimeUnit) this method does not wait, but uses a separate ScheduledFuture to complete the future. Code is shown below. So far, so good. But I also want to cancel the scheduled task (the ScheduledFuture returned from ScheduledExecutorService#schedule()) when the future is cancelled before the timeout. (So that I can keep my timeout tasks from piling up when timeouts are long in relation to the real computations.) Please look at the code below, where I create an additional future with whenComplete and use that to cancel the task. Is that a correct solution? Or could this additional future be optimized away or be garbage collected? Does the variable "future" that is returned from the method hold a reference to the additional future? I couldn't tell from the source code of CompletableFuture. private static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(TIMER_THREADS); public static CompletableFuture delayedSuccess(T value, int delay, TimeUnit unit) { CompletableFuture future = new CompletableFuture(); ScheduledFuture task = scheduler.schedule(() -> future.complete(value), delay, unit); future.whenComplete((t, ex) -> { if (future.isCancelled()) task.cancel(true); // <== HERE }); return future; } I fear that this might no longer be the place to ask such questions. If so, could you point me to an appropriate forum, where I would also be likely to receive an answer? Sebastian Millies Expert Java Business Analytics Phone: +49 681 210 3221 | Fax: +49 681 210 1801 | Sebastian.Millies at softwareag.com Software AG ? Sitz/Registered office: Uhlandstra?e 12, 64297 Darmstadt, Germany ? Registergericht/Commercial register: Darmstadt HRB 1562 - Vorstand/Management Board: Karl-Heinz Streibich (Vorsitzender/Chairman), Dr. Wolfram Jost, Arnd Zinnhardt; - Aufsichtsratsvorsitzender/Chairman of the Supervisory Board: Dr. Andreas Bereczky - http://www.softwareag.com From david.holmes at oracle.com Mon Aug 25 02:26:18 2014 From: david.holmes at oracle.com (David Holmes) Date: Mon, 25 Aug 2014 12:26:18 +1000 Subject: CompletableFuture with delay In-Reply-To: <32F15738E8E5524DA4F01A0FA4A8E490DF0FA267@HQMBX5.eur.ad.sag> References: <32F15738E8E5524DA4F01A0FA4A8E490DF0FA267@HQMBX5.eur.ad.sag> Message-ID: <53FA9ECA.8060504@oracle.com> Hi Sebastian, lambda-dev has never been the place to discuss java.util.concurrent classes. Such discussion is best done on Doug Lea's concurrency-interest at cs.oswego.edu list. Cheers, David Holmes On 25/08/2014 4:21 AM, Millies, Sebastian wrote: > Hello there, > > I'd like to simulate asynchronous IO events in a test system (without actual IO). > For this purpose, I have defined a method that creates a future which returns a value after a delay. > In contrast to Future#get(Long,TimeUnit) this method does not wait, but uses a separate ScheduledFuture > to complete the future. Code is shown below. > > So far, so good. But I also want to cancel the scheduled task (the ScheduledFuture returned from > ScheduledExecutorService#schedule()) when the future is cancelled before the timeout. (So that > I can keep my timeout tasks from piling up when timeouts are long in relation to the real > computations.) > > Please look at the code below, where I create an additional future with whenComplete and use > that to cancel the task. Is that a correct solution? Or could this additional future be optimized > away or be garbage collected? Does the variable "future" that is returned from the method hold a > reference to the additional future? I couldn't tell from the source code of CompletableFuture. > > private static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(TIMER_THREADS); > > public static CompletableFuture delayedSuccess(T value, int delay, TimeUnit unit) { > CompletableFuture future = new CompletableFuture(); > ScheduledFuture task = scheduler.schedule(() -> future.complete(value), delay, unit); > future.whenComplete((t, ex) -> { > if (future.isCancelled()) > task.cancel(true); // <== HERE > }); > return future; > } > > I fear that this might no longer be the place to ask such questions. If so, could you point > me to an appropriate forum, where I would also be likely to receive an answer? > > Sebastian Millies > Expert Java Business Analytics > Phone: +49 681 210 3221 | Fax: +49 681 210 1801 | Sebastian.Millies at softwareag.com > > > > Software AG ? Sitz/Registered office: Uhlandstra?e 12, 64297 Darmstadt, Germany ? Registergericht/Commercial register: Darmstadt HRB 1562 - Vorstand/Management Board: Karl-Heinz Streibich (Vorsitzender/Chairman), Dr. Wolfram Jost, Arnd Zinnhardt; - Aufsichtsratsvorsitzender/Chairman of the Supervisory Board: Dr. Andreas Bereczky - http://www.softwareag.com > >