From carlos at keysoft.pt Thu Apr 8 02:55:58 2010 From: carlos at keysoft.pt (Carlos Costa e Silva) Date: Thu, 8 Apr 2010 10:55:58 +0100 Subject: ARM: preserve supressed exceptions due to throw in finally block Message-ID: Hi everyone, Small suggestion for an improvement in the ARM proposal. In a try/finally block: try { // try code } finally { // finally code } If an exception is thrown in the finally block, any exception thrown in the try block is lost. As the ARM proposal adds suppressed exceptions, how about adding the "try" exception to the suppressed exceptions of the "finally" exception? Compiler generated pseudo code: try { // try code } finally { Throwable tryException = (exception thrown in try block, if any); try { // finally code } catch (Throwable t) { if (tryException != null) { t.addSupressedException(tryException); } throw t; } } IMHO, this is a small change and would help catch some non obvious mistakes. Carlos From jjb at google.com Thu Apr 8 11:10:58 2010 From: jjb at google.com (Joshua Bloch) Date: Thu, 8 Apr 2010 11:10:58 -0700 Subject: ARM: preserve supressed exceptions due to throw in finally block In-Reply-To: References: Message-ID: Carlos, I like it, but it scares me a bit: there are billions (literally) of try-finally blocks out there, and this would change the code emitted by all of them. It would, without question, increase the size of the class files emitted by many (most?) Java programs. Hopefully it wouldn't slow them down, but you never know until you measure. Josh On Thu, Apr 8, 2010 at 2:55 AM, Carlos Costa e Silva wrote: > Hi everyone, > > Small suggestion for an improvement in the ARM proposal. > > In a try/finally block: > > try { > // try code > } > finally { > // finally code > } > > > If an exception is thrown in the finally block, any exception thrown in > the try block is lost. > > > As the ARM proposal adds suppressed exceptions, how about adding the > "try" exception to the suppressed exceptions of the "finally" exception? > > > Compiler generated pseudo code: > > try { > // try code > } > finally { > > Throwable tryException = (exception thrown in try block, if any); > try { > // finally code > } > catch (Throwable t) { > if (tryException != null) { > t.addSupressedException(tryException); > } > throw t; > } > } > > > IMHO, this is a small change and would help catch some non obvious > mistakes. > > Carlos > > > From neal at gafter.com Thu Apr 8 11:27:06 2010 From: neal at gafter.com (Neal Gafter) Date: Thu, 8 Apr 2010 11:27:06 -0700 Subject: ARM: preserve supressed exceptions due to throw in finally block In-Reply-To: References: Message-ID: Carlos- This has the same problem as the proposal for handling suppressed exceptions in ARM: we have no experience to suggest that this way of preserving suppressed exceptions is usable in realistic programs. This software-engineering aspect of ARM language design seems to have been largely ignored. I think more study of such software engineering aspects would be well advised before ARM or any extensions to it are moved into the jdk. Cheers, Neal On Thu, Apr 8, 2010 at 2:55 AM, Carlos Costa e Silva wrote: > Hi everyone, > > Small suggestion for an improvement in the ARM proposal. > > In a try/finally block: > > try { > // try code > } > finally { > // finally code > } > > > If an exception is thrown in the finally block, any exception thrown in > the try block is lost. > > > As the ARM proposal adds suppressed exceptions, how about adding the > "try" exception to the suppressed exceptions of the "finally" exception? > > > Compiler generated pseudo code: > > try { > // try code > } > finally { > > Throwable tryException = (exception thrown in try block, if any); > try { > // finally code > } > catch (Throwable t) { > if (tryException != null) { > t.addSupressedException(tryException); > } > throw t; > } > } > > > IMHO, this is a small change and would help catch some non obvious > mistakes. > > Carlos > > > From opinali at gmail.com Thu Apr 8 11:45:36 2010 From: opinali at gmail.com (Osvaldo Doederlein) Date: Thu, 8 Apr 2010 15:45:36 -0300 Subject: ARM: preserve supressed exceptions due to throw in finally block In-Reply-To: References: Message-ID: There is already some "previous art" in making try/finally blocks larger -- the suppression of JSR bytecode (mandatory in JavaSE6). But for the issue of suppressed exceptions, I guess the JVM could just handle this dynamically, perhaps when started in debug mode or with -ea or some new options like -verbose:exceptions. (And I could add more scenarios to be detected/logged by such options; e.g. empty catch blocks that swallow exceptions without any action.) Java is a dynamic platform, let's use this to our advantage. I see no reason to make everybody's code more bloated, all the time, just to support some feature that's clearly only useful for development or monitoring/troubleshooting. Just add a JMX hook that allows me to enable/disable "verbose exceptions" from VisualVM or other monitoring app. A+ Osvaldo 2010/4/8 Neal Gafter > Carlos- > > This has the same problem as the proposal for handling suppressed > exceptions > in ARM: we have no experience to suggest that this way of preserving > suppressed exceptions is usable in realistic programs. This > software-engineering aspect of ARM language design seems to have been > largely ignored. I think more study of such software engineering aspects > would be well advised before ARM or any extensions to it are moved into the > jdk. > > Cheers, > Neal > > On Thu, Apr 8, 2010 at 2:55 AM, Carlos Costa e Silva >wrote: > > > Hi everyone, > > > > Small suggestion for an improvement in the ARM proposal. > > > > In a try/finally block: > > > > try { > > // try code > > } > > finally { > > // finally code > > } > > > > > > If an exception is thrown in the finally block, any exception thrown in > > the try block is lost. > > > > > > As the ARM proposal adds suppressed exceptions, how about adding the > > "try" exception to the suppressed exceptions of the "finally" exception? > > > > > > Compiler generated pseudo code: > > > > try { > > // try code > > } > > finally { > > > > Throwable tryException = (exception thrown in try block, if any); > > try { > > // finally code > > } > > catch (Throwable t) { > > if (tryException != null) { > > t.addSupressedException(tryException); > > } > > throw t; > > } > > } > > > > > > IMHO, this is a small change and would help catch some non obvious > > mistakes. > > > > Carlos > > > > > > > > From Joe.Darcy at Sun.COM Thu Apr 8 12:44:00 2010 From: Joe.Darcy at Sun.COM (Joe Darcy) Date: Thu, 08 Apr 2010 12:44:00 -0700 Subject: ARM: preserve supressed exceptions due to throw in finally block In-Reply-To: References: Message-ID: <4BBE3200.5030609@sun.com> On 04/08/10 11:27 AM, Neal Gafter wrote: > Carlos- > > This has the same problem as the proposal for handling suppressed exceptions > in ARM: we have no experience to suggest that this way of preserving > suppressed exceptions is usable in realistic programs. This > software-engineering aspect of ARM language design seems to have been > largely ignored. I think more study of such software engineering aspects > would be well advised before ARM or any extensions to it are moved into the > jdk. > > Cheers, > Neal > > On Thu, Apr 8, 2010 at 2:55 AM, Carlos Costa e Silva wrote: > > > I would expect such study to be able to commence in earnest after there is a version of ARM available in the JDK for people to play with. Language features of course evolve and are tuned as people gain experience with them; this was true of generics I would expect this to be true of ARM too. -Joe From neal at gafter.com Thu Apr 8 15:45:24 2010 From: neal at gafter.com (Neal Gafter) Date: Thu, 8 Apr 2010 15:45:24 -0700 Subject: ARM: preserve supressed exceptions due to throw in finally block In-Reply-To: <4BBE3200.5030609@sun.com> References: <4BBE3200.5030609@sun.com> Message-ID: On Thu, Apr 8, 2010 at 12:44 PM, Joe Darcy wrote: > On 04/08/10 11:27 AM, Neal Gafter wrote: > >> Carlos- >> >> This has the same problem as the proposal for handling suppressed >> exceptions >> in ARM: we have no experience to suggest that this way of preserving >> suppressed exceptions is usable in realistic programs. This >> software-engineering aspect of ARM language design seems to have been >> largely ignored. I think more study of such software engineering aspects >> would be well advised before ARM or any extensions to it are moved into >> the >> jdk. >> >> Cheers, >> Neal >> >> On Thu, Apr 8, 2010 at 2:55 AM, Carlos Costa e Silva > >wrote: >> >> >> >> > > I would expect such study to be able to commence in earnest after there is > a version of ARM available in the JDK for people to play with. > It is unfortunate that such experience is not developed before being moved into the jdk. There have not even been any proposed guidelines for how to program in the presence of this mechanism. Such guidelines would not depend on having a prototype, and could be analyzed for their compositional properties before a prototype is committed to the JDK. The complete absence of such guidelines is most troubling and should signal a warning message about the language construct itself. Language features of course evolve and are tuned as people gain experience > with them; this was true of generics I would expect this to be true of ARM > too. > Generics prototypes were available for years before appearing in the JDK. At least with generics we had a significant body of experience with their use (yes, including wildcards) before the language construct appeared in the jdk. But in this case we do not even have the kinds of early programming guidelines for the use of the construct in realistic software engineering scenarios that we had for generics. This reminds me a bit of the discussion surrounding erasure (vs reification). Some people who had a naive view of the problem thought we were needlessly throwing away information, and "just" wanted us to preserve it. I jokingly offered to have the compiler email the erased type parameters to them. This is a joke because the information in that form is useless to them. Similarly, although we desire not to lose information about "discarded" exceptions, there is no evidence that preserving them in the way that is proposed will be useful except in very narrow circumstances. "Wait and see" isn't a very satisfying answer; we should have more principled reasons to believe in a proposed solution. Cheers, Neal From tball at google.com Thu Apr 8 16:12:47 2010 From: tball at google.com (Tom Ball) Date: Thu, 8 Apr 2010 16:12:47 -0700 Subject: ARM: preserve supressed exceptions due to throw in finally block In-Reply-To: References: <4BBE3200.5030609@sun.com> Message-ID: There is a big difference in the small impact of how secondary exceptions are stored and printed compared to how generics affected the Java developer experience. On the scale of Java changes, ARM's impact should be closer to enhanced for loops than generics. Let's also remember the point of having ARM support: most Java developers (including myself) can't write truly correct management of nested resource classes. Whether this feature can guarantee perfect code or optimally manages nested exceptions is arguably less important then the fact that it should emit better code than the developer with a much smaller time investment on his or her part. Platform and library writers often forget that there is a large class of developers who have a schedule gun to their heads to crank out applications quickly (I can smell gun oil as I write this), so any small language improvement that reduces development time and improves reliability is a big win. My personal regret isn't that more time isn't being spent on debating this feature, but instead that it's not already available for my code. Tom On Thu, Apr 8, 2010 at 3:45 PM, Neal Gafter wrote: > On Thu, Apr 8, 2010 at 12:44 PM, Joe Darcy wrote: > > > On 04/08/10 11:27 AM, Neal Gafter wrote: > > > >> Carlos- > >> > >> This has the same problem as the proposal for handling suppressed > >> exceptions > >> in ARM: we have no experience to suggest that this way of preserving > >> suppressed exceptions is usable in realistic programs. This > >> software-engineering aspect of ARM language design seems to have been > >> largely ignored. I think more study of such software engineering > aspects > >> would be well advised before ARM or any extensions to it are moved into > >> the > >> jdk. > >> > >> Cheers, > >> Neal > >> > >> On Thu, Apr 8, 2010 at 2:55 AM, Carlos Costa e Silva >> >wrote: > >> > >> > >> > >> > > > > I would expect such study to be able to commence in earnest after there > is > > a version of ARM available in the JDK for people to play with. > > > > It is unfortunate that such experience is not developed before being moved > into the jdk. There have not even been any proposed guidelines for how to > program in the presence of this mechanism. Such guidelines would not > depend > on having a prototype, and could be analyzed for their compositional > properties before a prototype is committed to the JDK. The complete > absence > of such guidelines is most troubling and should signal a warning message > about the language construct itself. > > Language features of course evolve and are tuned as people gain experience > > with them; this was true of generics I would expect this to be true of > ARM > > too. > > > > Generics prototypes were available for years before appearing in the JDK. > At least with generics we had a significant body of experience with their > use (yes, including wildcards) before the language construct appeared in > the > jdk. But in this case we do not even have the kinds of early programming > guidelines for the use of the construct in realistic software engineering > scenarios that we had for generics. > > This reminds me a bit of the discussion surrounding erasure (vs > reification). Some people who had a naive view of the problem thought we > were needlessly throwing away information, and "just" wanted us to preserve > it. I jokingly offered to have the compiler email the erased type > parameters to them. This is a joke because the information in that form is > useless to them. Similarly, although we desire not to lose information > about "discarded" exceptions, there is no evidence that preserving them in > the way that is proposed will be useful except in very narrow > circumstances. "Wait and see" isn't a very satisfying answer; we should > have more principled reasons to believe in a proposed solution. > > Cheers, > Neal > > From neal at gafter.com Thu Apr 8 16:26:53 2010 From: neal at gafter.com (Neal Gafter) Date: Thu, 8 Apr 2010 16:26:53 -0700 Subject: ARM: preserve supressed exceptions due to throw in finally block In-Reply-To: References: <4BBE3200.5030609@sun.com> Message-ID: On Thu, Apr 8, 2010 at 4:12 PM, Tom Ball wrote: > There is a big difference in the small impact of how secondary exceptions > are stored and printed compared to how generics affected the Java developer > experience. On the scale of Java changes, ARM's impact should be closer to > enhanced for loops than generics. > Should be, true. And yet we don't even have any proposed guidelines for programming in the presence of the proposed handling of suppressed exceptions. > Whether this feature can guarantee perfect code or optimally > manages nested exceptions is arguably less important then the fact that it > should emit better code than the developer with a much smaller time > investment on his or her part. I wasn't expecting optimality. I'd settle for composable and usable. But we don't even have any reason to believe it will be that. > Platform and library writers often forget > that there is a large class of developers who have a schedule gun to their > heads to crank out applications quickly (I can smell gun oil as I write > this), so any small language improvement that reduces development time and > improves reliability is a big win. The proposed handling of suppressed exceptions isn't that by any stretch of the imagination. At least, not based on anything written about it so far. My personal regret isn't that more time > isn't being spent on debating this feature, but instead that it's not > already available for my code. > I understand the attraction of just-get-something-working-now-and-worry-about-it-later. That works very well for web-based applications where compatibility isn't important. But it doesn't work so well with programming languages. Your six months of glad would lead to six+ years of regret. From ramesh.mandaleeka at gmail.com Fri Apr 9 08:46:57 2010 From: ramesh.mandaleeka at gmail.com (Ramesh Mandaleeka) Date: Fri, 9 Apr 2010 11:46:57 -0400 Subject: instanceof Operator Message-ID: Hi, Why there is not instanceOf() method in java.lang.Object just like equals() method. Why we need an operator? A class can tell if it equals to other object or not but why not an instanceOf(Object obj) method ( I guess it should be final too). Regards, Ramesh From jonathan.gibbons at oracle.com Fri Apr 9 08:54:29 2010 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Fri, 09 Apr 2010 08:54:29 -0700 Subject: instanceof Operator In-Reply-To: References: Message-ID: <4BBF4DB5.7050709@oracle.com> Ramesh Mandaleeka wrote: > Hi, > > Why there is not instanceOf() method in java.lang.Object just like equals() > method. Why we need an operator? A class can tell if it equals to other > object or not but why not an instanceOf(Object obj) method ( I guess it > should be final too). > > Regards, > Ramesh > > If this message was not off-topic for the list, I would reply that it's there and called isAssignableFrom. -- Jon From serge.boulay at gmail.com Fri Apr 9 09:20:12 2010 From: serge.boulay at gmail.com (Serge Boulay) Date: Fri, 9 Apr 2010 12:20:12 -0400 Subject: ARM: preserve supressed exceptions due to throw in finally block In-Reply-To: References: <4BBE3200.5030609@sun.com> Message-ID: Doesn't .net's "using block" do the same thing with suppressed exceptions as the ARM proposal? That is, if you wanted access to the suppressed exception you're basically back to resource handling without the using block? On Thu, Apr 8, 2010 at 7:26 PM, Neal Gafter wrote: > On Thu, Apr 8, 2010 at 4:12 PM, Tom Ball wrote: > > > There is a big difference in the small impact of how secondary exceptions > > are stored and printed compared to how generics affected the Java > developer > > experience. On the scale of Java changes, ARM's impact should be closer > to > > enhanced for loops than generics. > > > > Should be, true. And yet we don't even have any proposed guidelines for > programming in the presence of the proposed handling of suppressed > exceptions. > > > > Whether this feature can guarantee perfect code or optimally > > manages nested exceptions is arguably less important then the fact that > it > > should emit better code than the developer with a much smaller time > > investment on his or her part. > > > I wasn't expecting optimality. I'd settle for composable and usable. But > we don't even have any reason to believe it will be that. > > > > Platform and library writers often forget > > that there is a large class of developers who have a schedule gun to > their > > heads to crank out applications quickly (I can smell gun oil as I write > > this), so any small language improvement that reduces development time > and > > improves reliability is a big win. > > > The proposed handling of suppressed exceptions isn't that by any stretch of > the imagination. At least, not based on anything written about it so far. > > My personal regret isn't that more time > > isn't being spent on debating this feature, but instead that it's not > > already available for my code. > > > > I understand the attraction of > just-get-something-working-now-and-worry-about-it-later. That works very > well for web-based applications where compatibility isn't important. But > it > doesn't work so well with programming languages. Your six months of glad > would lead to six+ years of regret. > > From ramesh.mandaleeka at gmail.com Fri Apr 9 09:45:35 2010 From: ramesh.mandaleeka at gmail.com (Ramesh Mandaleeka) Date: Fri, 9 Apr 2010 12:45:35 -0400 Subject: instanceof Operator In-Reply-To: <4BBF4DB5.7050709@oracle.com> References: <4BBF4DB5.7050709@oracle.com> Message-ID: Thank you Jonathan. But the method you are referring is in java.lang.Class class not java.lang.Object. Isn't it nice to have final public boolean isInstanceOf(Object obj) as a method in java.lang.Object class? Note: Hope this is right forum to ask. If not please let me know I will cross post on the appropriate forum. Thanks, Ramesh On Fri, Apr 9, 2010 at 11:54 AM, Jonathan Gibbons < jonathan.gibbons at oracle.com> wrote: > Ramesh Mandaleeka wrote: > >> Hi, >> >> Why there is not instanceOf() method in java.lang.Object just like >> equals() >> method. Why we need an operator? A class can tell if it equals to other >> object or not but why not an instanceOf(Object obj) method ( I guess it >> should be final too). >> >> Regards, >> Ramesh >> >> >> > If this message was not off-topic for the list, I would reply that it's > there and called isAssignableFrom. > > -- Jon > From joe.darcy at oracle.com Fri Apr 9 09:51:45 2010 From: joe.darcy at oracle.com (Joe Darcy) Date: Fri, 09 Apr 2010 09:51:45 -0700 Subject: instanceof Operator In-Reply-To: References: <4BBF4DB5.7050709@oracle.com> Message-ID: <4BBF5B21.9030403@oracle.com> Ramesh Mandaleeka wrote: > Thank you Jonathan. But the method you are referring is in java.lang.Class > class not java.lang.Object. Isn't it nice to have final public boolean > isInstanceOf(Object obj) as a method in java.lang.Object class? > > Note: Hope this is right forum to ask. If not please let me know I will > cross post on the appropriate forum. > It is not the right forum. -Joe From mleodaalder at gmail.com Fri Apr 9 09:51:59 2010 From: mleodaalder at gmail.com (MLeo) Date: Fri, 9 Apr 2010 18:51:59 +0200 Subject: instanceof Operator In-Reply-To: References: <4BBF4DB5.7050709@oracle.com> Message-ID: Because invoking an instanceOf method on null would produce a NullPointerException, and using the keyword would yield false. I suppose you could do it if the MVLM interface injection works out. Hope that helps. On Fri, Apr 9, 2010 at 18:45, Ramesh Mandaleeka wrote: > Thank you Jonathan. But the method you are referring is in java.lang.Class > class not java.lang.Object. Isn't it nice to have final public boolean > isInstanceOf(Object obj) as a method in java.lang.Object class? > > Note: Hope this is right forum to ask. If not please let me know I will > cross post on the appropriate forum. > > Thanks, > Ramesh > > On Fri, Apr 9, 2010 at 11:54 AM, Jonathan Gibbons < > jonathan.gibbons at oracle.com> wrote: > > > Ramesh Mandaleeka wrote: > > > >> Hi, > >> > >> Why there is not instanceOf() method in java.lang.Object just like > >> equals() > >> method. Why we need an operator? A class can tell if it equals to other > >> object or not but why not an instanceOf(Object obj) method ( I guess it > >> should be final too). > >> > >> Regards, > >> Ramesh > >> > >> > >> > > If this message was not off-topic for the list, I would reply that it's > > there and called isAssignableFrom. > > > > -- Jon > > > > From maurizio.cimadamore at oracle.com Fri Apr 9 10:14:13 2010 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Fri, 09 Apr 2010 18:14:13 +0100 Subject: diamond operator and non-denotable types Message-ID: <4BBF6065.6040804@oracle.com> Hi, in the process of switching the implementation of the diamond algorithm (following the discussion in [1]), we discovered a problem in the specification of the diamond operator; more specifically, there are cases in which diamond can end up inferring non-denotable types (see below). Our proposed solution is to reject such cases, as the semantics of instance creation expression involving non-denotable types is not clear. Moreover, we have carried out additional benchmarks in order to ensure that this restriction does not significantly alter the ease of use of the diamond operator. The results, as you can read below, are extremely positive. As I said, there are two cases in which the diamond operator causes a non-denotable type to be inferred in an instance creation expression: *) intersection types in type-variable bounds: EXAMPLE class Foo { ... } Foo foo = new Foo<>(); in this case the non-denotable type Foo is inferred for X. *) captured types in constructor arguments EXAMPLE class Foo { Foo(X x) { ... } } Foo fi = ... Foo f = new Foo<>(fi); In this case the non-denotable type Foo> is inferred for X [where #1 <: Integer] Despite attribution does not have problems with non-denotable types in instance creation expressions, there are circumstances in which such types cause problems in code generation --- this happens e.g. if a non-denotable type is inferred in an anonymous class creation expression; in this case the compiler will try to emit a classfile Signature attribute for a non-denotable type, which is not allowed. Moreover non-denotable types doesn't seem to comply with the set of acceptable types in an instance creation expression (see JLS 15.9); despite there's no explicit statement in the JLS forbidding e.g. an intersection type as part of an instance creation expression, it seems sensible to statically forbid these occurrence, as the semantics of such types is not crystal clear --- these types are introduced as compile-time artifacts in order to enhance the applicability of compiler checks, but it is not clear what their behavior should look like. The most straightforward solution (see above) is to issue an error when a non-denotable type is returned as result of the diamond inference scheme. In other words, I propose to change the current spec draft to include a statement like: "If the diamond algorithm infers a non-denotable type, an error must be issued by the compiler". I was worried that this spec change would have caused major disruption in our diamond statistics, so I took some time in order to re-run my diamond finder on the JDK... these are the results: total instance creation expression: 5201 compatible types inferred with diamond: 4606 (88.56%) non-denotable types: 0 incompatible types inferred with diamond: 595 non-denotable types: 1 In other words it seems like this spec change does not alter the measurements we took sometime ago. In particular there is just one case in which diamond yields a non-denotable type --- but in this case the type is not compatible with the given assignment context (as such it would have been rejected anyway). I'd say this doesn't look bad at all, and that it has the obvious advantage of fixing the spec problem discussed above. The proposed changeset for the new diamond implementation can be found in [2] while the changeset for reverting the current diamond implementation is given, for completeness, in [3]. [1] http://mail.openjdk.java.net/pipermail/coin-dev/2009-November/002393.html [2] http://cr.openjdk.java.net/~mcimadamore/6939620/webrev.1/ [3] http://cr.openjdk.java.net/~mcimadamore/6939618/webrev.0/ Thanks Maurizio From ramesh.mandaleeka at gmail.com Fri Apr 9 10:22:14 2010 From: ramesh.mandaleeka at gmail.com (Ramesh Mandaleeka) Date: Fri, 9 Apr 2010 13:22:14 -0400 Subject: instanceof Operator In-Reply-To: References: <4BBF4DB5.7050709@oracle.com> <4BBF5C6A.8050703@oracle.com> Message-ID: Thanks you all for the input. I submitted an enhancement request with a view that it would be natural to work with methods when interacting with objects instead of an operator. The Review ID: 1750219 Regards, Ramesh On Fri, Apr 9, 2010 at 1:16 PM, Ramesh Mandaleeka < ramesh.mandaleeka at gmail.com> wrote: > My apology for posting here. I submitted an enhancement request with a view > that it would be natural to work with methods when interacting with objects. > > > -Ramesh > > > On Fri, Apr 9, 2010 at 12:57 PM, Jonathan Gibbons < > jonathan.gibbons at oracle.com> wrote: > >> If you really want to follow up on this, the correct way would be to file >> an issue on bugs.sun.com. >> >> However, given the easy workaround using isAssignableFrom, I'm not sure >> the issue would gain much traction. >> >> -- Jon >> >> >> >> Ramesh Mandaleeka wrote: >> >> Thank you Jonathan. But the method you are referring is in java.lang.Class >> class not java.lang.Object. Isn't it nice to have final public boolean >> isInstanceOf(Object obj) as a method in java.lang.Object class? >> >> Note: Hope this is right forum to ask. If not please let me know I will >> cross post on the appropriate forum. >> >> Thanks, >> Ramesh >> >> On Fri, Apr 9, 2010 at 11:54 AM, Jonathan Gibbons wrote: >> >> >> >> Ramesh Mandaleeka wrote: >> >> >> >> Hi, >> >> Why there is not instanceOf() method in java.lang.Object just like >> equals() >> method. Why we need an operator? A class can tell if it equals to other >> object or not but why not an instanceOf(Object obj) method ( I guess it >> should be final too). >> >> Regards, >> Ramesh >> >> >> >> >> >> If this message was not off-topic for the list, I would reply that it's >> there and called isAssignableFrom. >> >> -- Jon >> >> >> >> >> > From neal at gafter.com Fri Apr 9 11:30:36 2010 From: neal at gafter.com (Neal Gafter) Date: Fri, 9 Apr 2010 11:30:36 -0700 Subject: diamond operator and non-denotable types In-Reply-To: <4BBF6065.6040804@oracle.com> References: <4BBF6065.6040804@oracle.com> Message-ID: Maurizio- How are these cases handed with static factories? Why should it be handled differently between static factories and constructors? It seems that the diamond operator should be capable of inferring any type arguments a static factory could infer. Is there any reason for the diamond operator to be less powerful? The exceptions are due to restrictions on construction. "new ArrayList()" isn't legal, therefore "new ArrayList<>()" should not be capable of inferring "? extends Number" for the type argument. On Fri, Apr 9, 2010 at 10:14 AM, Maurizio Cimadamore < maurizio.cimadamore at oracle.com> wrote: > Despite attribution does not have problems with non-denotable types in > instance creation expressions, there are circumstances in which such > types cause problems in code generation --- this happens e.g. if a > non-denotable type is inferred in an anonymous class creation > expression; in this case the compiler will try to emit a classfile > Signature attribute for a non-denotable type, which is not allowed. > That suggests that the restriction should be applied only to anonymous class creation expressions. Moreover non-denotable types doesn't seem to comply with the set of > acceptable types in an instance creation expression (see JLS 15.9); > despite there's no explicit statement in the JLS forbidding e.g. an > intersection type as part of an instance creation expression, it seems > sensible to statically forbid these occurrence, as the semantics of such > types is not crystal clear --- these types are introduced as > compile-time artifacts in order to enhance the applicability of compiler > checks, but it is not clear what their behavior should look like. > All generics are compile-time artifacts in order to enhance the applicability of compiler checks. Intersection types are specified, representable in the class file, and erased at runtime too. Where's the problem? > The most straightforward solution (see above) is to issue an error when > a non-denotable type is returned as result of the diamond inference > scheme. In other words, I propose to change the current spec draft to > include a statement like: > > "If the diamond algorithm infers a non-denotable type, an error must be > issued by the compiler". > "It is an error if the inferred class type parameters are not denotable and a class body is present." This requires a formal definition of "denotable". Because it should not include wildcards, which can be denoted in source, denotable is probably not the right word. Cheers, Neal From neal at gafter.com Fri Apr 9 11:38:44 2010 From: neal at gafter.com (Neal Gafter) Date: Fri, 9 Apr 2010 11:38:44 -0700 Subject: ARM: preserve supressed exceptions due to throw in finally block In-Reply-To: References: <4BBE3200.5030609@sun.com> Message-ID: On Fri, Apr 9, 2010 at 9:20 AM, Serge Boulay wrote: > Doesn't .net's "using block" do the same thing with suppressed exceptions as > the ARM proposal? That is, if you wanted access to the suppressed exception > you're?basically?back to resource handling without the using block? No, it does not do the same thing as .NET. The ARM proposal does not discard the exception, but attaches it to another exception. From maurizio.cimadamore at oracle.com Fri Apr 9 11:46:12 2010 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Fri, 09 Apr 2010 19:46:12 +0100 Subject: diamond operator and non-denotable types In-Reply-To: References: <4BBF6065.6040804@oracle.com> Message-ID: <4BBF75F4.2060401@oracle.com> Neal Gafter wrote: > Maurizio- > > How are these cases handed with static factories? Why should it be handled > differently between static factories and constructors? It seems that the > diamond operator should be capable of inferring any type arguments a static > factory could infer. Is there any reason for the diamond operator to be less > powerful? > The problem is with anonymous inner class creation; consider the following code: class Foo {} Foo f = new Foo<>(); The inferred type would be Foo. This is problematic, because this type (Foo) will be also the supertype of the anonymous inner class. Unfortunately, this kind of type cannot be expressed under the current specification of the classfile Signature attribute, so this code lead to a code generation failure. The same holds for captured-types. Intersection types are allowed in the Signature attribute only as a way for representing type-variable bounds. Generalized intersection types do not have a corresponding representation in the classfile. The compiler always erases an intersection type to the most appropriate type needed in order to preserve the semantics of the program. Maurizio > The exceptions are due to restrictions on construction. "new ArrayList extends Number>()" isn't legal, therefore "new ArrayList<>()" should not be > capable of inferring "? extends Number" for the type argument. > > On Fri, Apr 9, 2010 at 10:14 AM, Maurizio Cimadamore < > maurizio.cimadamore at oracle.com> wrote: > > >> Despite attribution does not have problems with non-denotable types in >> instance creation expressions, there are circumstances in which such >> types cause problems in code generation --- this happens e.g. if a >> non-denotable type is inferred in an anonymous class creation >> expression; in this case the compiler will try to emit a classfile >> Signature attribute for a non-denotable type, which is not allowed. >> >> > > That suggests that the restriction should be applied only to anonymous class > creation expressions. > > Moreover non-denotable types doesn't seem to comply with the set of > >> acceptable types in an instance creation expression (see JLS 15.9); >> despite there's no explicit statement in the JLS forbidding e.g. an >> intersection type as part of an instance creation expression, it seems >> sensible to statically forbid these occurrence, as the semantics of such >> types is not crystal clear --- these types are introduced as >> compile-time artifacts in order to enhance the applicability of compiler >> checks, but it is not clear what their behavior should look like. >> >> > > All generics are compile-time artifacts in order to enhance the > applicability of compiler checks. Intersection types are specified, > representable in the class file, and erased at runtime too. Where's the > problem? > > > >> The most straightforward solution (see above) is to issue an error when >> a non-denotable type is returned as result of the diamond inference >> scheme. In other words, I propose to change the current spec draft to >> include a statement like: >> >> "If the diamond algorithm infers a non-denotable type, an error must be >> issued by the compiler". >> >> > > "It is an error if the inferred class type parameters are not denotable and > a class body is present." > > This requires a formal definition of "denotable". Because it should not > include wildcards, which can be denoted in source, denotable is probably not > the right word. > > Cheers, > Neal > > From neal at gafter.com Fri Apr 9 13:03:43 2010 From: neal at gafter.com (Neal Gafter) Date: Fri, 9 Apr 2010 13:03:43 -0700 Subject: diamond operator and non-denotable types In-Reply-To: <4BBF75F4.2060401@oracle.com> References: <4BBF6065.6040804@oracle.com> <4BBF75F4.2060401@oracle.com> Message-ID: On Fri, Apr 9, 2010 at 11:46 AM, Maurizio Cimadamore wrote: > Neal Gafter wrote: >> >> Maurizio- >> >> How are these cases handed with static factories? ?Why should it be >> handled >> differently between static factories and constructors? ?It seems that the >> diamond operator should be capable of inferring any type arguments a >> static >> factory could infer. Is there any reason for the diamond operator to be >> less >> powerful? >> > > The problem is with anonymous inner class creation Then the solution should be with anonymous inner class creation as well. Cheers, Neal From brucechapman at paradise.net.nz Tue Apr 13 00:04:23 2010 From: brucechapman at paradise.net.nz (Bruce Chapman) Date: Tue, 13 Apr 2010 19:04:23 +1200 Subject: Combined grammar changes for binary literals and underscores in literals In-Reply-To: <4A661ED9.4060004@sun.com> References: <4A5E4898.5000708@sun.com> <4A661ED9.4060004@sun.com> Message-ID: <4BC41777.3040103@paradise.net.nz> Joe, Derek et al, I am just writing up the combined integer literal omnibus proposal. A couple of questions about this grammar 1) considering DecimalNumeral 0 NonZeroDigit Digits_opt NonZeroDigit Underscores Digits // New (1) Underscores _ Underscores _ Digits: Digit Digit DigitsAndUnderscores_opt Digit (2) I think we can drop rule (1) above, if rule (2) is changed to DigitsAndUnderscores_opt Digit since there is already a leading NonZeroDigit, so we can start a "Digits" with an underscore, so we don't need the special rule to allow for an underscore immediately after the NonZeroDigit. Agreed? If so we can also make corresponding change for Octal rules then drop the Underscores production as these are the only places it is used. 2) I am wondering whether it would enhance grokkability of we renamed the productions HexDigitsAndUnderscores (and other radix friends, and corresponding singular forms) to be (eg) HexMidDigits because it can't be used at either end of the HexDigits, but can be in the middle. - if we did this the hex rules would change from HexDigits: HexDigit HexDigit HexDigitsAndUnderscores_opt HexDigit HexDigitsAndUnderscores: HexDigitOrUnderscore HexDigitsAndUnderscores HexDigitOrUnderscore HexDigitOrUnderscore HexDigit _ to HexDigits: HexDigit HexDigit HexMidDigits_opt HexDigit HexMidDigits: HexMidDigit HexMidDigits HexMidDigit (but actually vice versa as previously discussed off-list with Alex Buckley) HexMidDigit HexDigit _ Comments? Bruce Joe Darcy wrote: > Hello. > > It has been pointed out to me off-list that the grammar as written below > would disallow two-digit numbers, which is not desired. This problem is > corrected by changing the productions like > > Digit DigitsAndUnderscores Digit > > to be > > Digit DigitsAndUnderscores_opt Digit > > -Joe > > On 07/15/09 02:22 PM, Joseph D. Darcy wrote: > >> Hello. >> >> Getting around to some grammatical hacking, below is a grammar I think >> properly captures the desired changes for combining the binary >> literals and underscores in literals proposals. This grammar does >> *not* include support for unsigned literals or autosizing literals. >> >> The basic approach is to redefine the FooDigits productions to be a >> non-empty sequence of Foo digits and underscores starting and ending >> with a Foo digit rather than just a non-empty sequence Foo digits. >> Each FooDigits nonterminal has two rules, one for a single digit and >> one for two or more digits. The rules for two or more digits force a >> true digit, rather than an underscore, as the first and last character. >> >> Changing the FooDigits definitions allows underscores in both integer >> and floating-point literals. In more detail: >> >> * Replace the productions Digits, HexDigits, OctalDigits, and in >> JLSv3 3.10.1 as shown below >> * Add productions for BinaryDigits >> * Add rules for FooDigitsAndUnderscores and FooDigitOrUnderscore >> * Add productions to DecimalNumeral and OctalNumeral: >> * Add a rule for Underscores >> >> IntegerLiteral: >> DecimalIntegerLiteral >> HexIntegerLiteral >> OctalIntegerLiteral >> BinaryIntegerLiteral // New >> >> BinaryIntegerLiteral: >> BinaryNumeral IntegerTypeSuffix_opt >> >> BinaryNumeral: >> 0 b BinaryDigits >> 0 B BinaryDigits >> >> >> DecimalNumeral >> 0 >> NonZeroDigit Digits_opt >> NonZeroDigit Underscores Digits // New >> >> Underscores >> _ >> Underscores _ >> >> Digits: >> Digit >> Digit DigitsAndUnderscores Digit >> >> DigitsAndUnderscores: >> DigitOrUnderscore >> DigitsAndUnderscores DigitOrUnderscore >> >> DigitOrUnderscore >> Digit >> _ >> >> >> HexDigits: >> HexDigit >> HexDigit HexDigitsAndUnderscores HexDigit >> >> HexDigitsAndUnderscores: >> HexDigitOrUnderscore >> HexDigitsAndUnderscores HexDigitOrUnderscore >> >> HexDigitOrUnderscore >> HexDigit >> _ >> >> OctalNumeral: >> 0 OctalDigits >> 0 Underscores OctalDigits // New >> >> OctalDigits: >> OctalDigit >> OctalDigit OctalDigitsAndUnderscores OctalDigit >> >> OctalDigitsAndUnderscores: >> OctalDigitOrUnderscore >> OctalDigitsAndUnderscores OctalDigitOrUnderscore >> >> OctalDigitOrUnderscore >> OctalDigit >> _ >> >> BinaryDigits: >> BinaryDigit >> BinaryDigit BinaryDigitsAndUnderscores BinaryDigit >> >> BinaryDigitsAndUnderscores: >> BinaryDigitOrUnderscore >> BinaryDigitsAndUnderscores BinaryDigitOrUnderscore >> >> BinaryDigitOrUnderscore >> BinaryDigit >> _ >> >> BinaryDigit: one of >> 0 1 >> >> -Joe >> > > > > From joe.darcy at oracle.com Tue Apr 13 01:05:03 2010 From: joe.darcy at oracle.com (Joe Darcy) Date: Tue, 13 Apr 2010 01:05:03 -0700 Subject: Combined grammar changes for binary literals and underscores in literals In-Reply-To: <4BC41777.3040103@paradise.net.nz> References: <4A5E4898.5000708@sun.com> <4A661ED9.4060004@sun.com> <4BC41777.3040103@paradise.net.nz> Message-ID: <4BC425AF.7070803@oracle.com> Welcome back Bruce! Bruce Chapman wrote: > Joe, Derek et al, > > I am just writing up the combined integer literal omnibus proposal. > > A couple of questions about this grammar > > > 1) > > considering > > DecimalNumeral > 0 > NonZeroDigit Digits_opt > NonZeroDigit Underscores Digits // New (1) > > Underscores > _ > Underscores _ > > Digits: > Digit > Digit DigitsAndUnderscores_opt Digit (2) > > > I think we can drop rule (1) above, if rule (2) is changed to > > DigitsAndUnderscores_opt Digit > > since there is already a leading NonZeroDigit, so we can start a > "Digits" with an underscore, so we don't need the special rule to allow > for an underscore immediately after the NonZeroDigit. > > Agreed? > > If so we can also make corresponding change for Octal rules then drop > the Underscores production as these are the only places it is used. > > > 2) > > I am wondering whether it would enhance grokkability of we renamed the > productions > > HexDigitsAndUnderscores (and other radix friends, and corresponding singular forms) > > > to be (eg) > HexMidDigits > > because it can't be used at either end of the HexDigits, but can be in > the middle. > > - if we did this the hex rules would change from > > HexDigits: > HexDigit > HexDigit HexDigitsAndUnderscores_opt HexDigit > > HexDigitsAndUnderscores: > HexDigitOrUnderscore > HexDigitsAndUnderscores HexDigitOrUnderscore > > HexDigitOrUnderscore > HexDigit > _ > > > > to > > HexDigits: > HexDigit > HexDigit HexMidDigits_opt HexDigit > > HexMidDigits: > HexMidDigit > HexMidDigits HexMidDigit (but actually vice versa as previously > discussed off-list with Alex Buckley) > > HexMidDigit > HexDigit > _ > > > > > Comments? > > One advantage of the way I wrote up the grammar is that the other appearances of Digits and HexDigits, such as in floating-point literals in section 3.10.2, automatically inherit the underscore policy without having to having leading digit guard productions in all places. The current implementation does allow underscores in floating-point literals too, which is tested for in the regression tests. -Joe > Bruce > > > > > > > Joe Darcy wrote: > >> Hello. >> >> It has been pointed out to me off-list that the grammar as written below >> would disallow two-digit numbers, which is not desired. This problem is >> corrected by changing the productions like >> >> Digit DigitsAndUnderscores Digit >> >> to be >> >> Digit DigitsAndUnderscores_opt Digit >> >> -Joe >> >> On 07/15/09 02:22 PM, Joseph D. Darcy wrote: >> >> >>> Hello. >>> >>> Getting around to some grammatical hacking, below is a grammar I think >>> properly captures the desired changes for combining the binary >>> literals and underscores in literals proposals. This grammar does >>> *not* include support for unsigned literals or autosizing literals. >>> >>> The basic approach is to redefine the FooDigits productions to be a >>> non-empty sequence of Foo digits and underscores starting and ending >>> with a Foo digit rather than just a non-empty sequence Foo digits. >>> Each FooDigits nonterminal has two rules, one for a single digit and >>> one for two or more digits. The rules for two or more digits force a >>> true digit, rather than an underscore, as the first and last character. >>> >>> Changing the FooDigits definitions allows underscores in both integer >>> and floating-point literals. In more detail: >>> >>> * Replace the productions Digits, HexDigits, OctalDigits, and in >>> JLSv3 3.10.1 as shown below >>> * Add productions for BinaryDigits >>> * Add rules for FooDigitsAndUnderscores and FooDigitOrUnderscore >>> * Add productions to DecimalNumeral and OctalNumeral: >>> * Add a rule for Underscores >>> >>> IntegerLiteral: >>> DecimalIntegerLiteral >>> HexIntegerLiteral >>> OctalIntegerLiteral >>> BinaryIntegerLiteral // New >>> >>> BinaryIntegerLiteral: >>> BinaryNumeral IntegerTypeSuffix_opt >>> >>> BinaryNumeral: >>> 0 b BinaryDigits >>> 0 B BinaryDigits >>> >>> >>> DecimalNumeral >>> 0 >>> NonZeroDigit Digits_opt >>> NonZeroDigit Underscores Digits // New >>> >>> Underscores >>> _ >>> Underscores _ >>> >>> Digits: >>> Digit >>> Digit DigitsAndUnderscores Digit >>> >>> DigitsAndUnderscores: >>> DigitOrUnderscore >>> DigitsAndUnderscores DigitOrUnderscore >>> >>> DigitOrUnderscore >>> Digit >>> _ >>> >>> >>> HexDigits: >>> HexDigit >>> HexDigit HexDigitsAndUnderscores HexDigit >>> >>> HexDigitsAndUnderscores: >>> HexDigitOrUnderscore >>> HexDigitsAndUnderscores HexDigitOrUnderscore >>> >>> HexDigitOrUnderscore >>> HexDigit >>> _ >>> >>> OctalNumeral: >>> 0 OctalDigits >>> 0 Underscores OctalDigits // New >>> >>> OctalDigits: >>> OctalDigit >>> OctalDigit OctalDigitsAndUnderscores OctalDigit >>> >>> OctalDigitsAndUnderscores: >>> OctalDigitOrUnderscore >>> OctalDigitsAndUnderscores OctalDigitOrUnderscore >>> >>> OctalDigitOrUnderscore >>> OctalDigit >>> _ >>> >>> BinaryDigits: >>> BinaryDigit >>> BinaryDigit BinaryDigitsAndUnderscores BinaryDigit >>> >>> BinaryDigitsAndUnderscores: >>> BinaryDigitOrUnderscore >>> BinaryDigitsAndUnderscores BinaryDigitOrUnderscore >>> >>> BinaryDigitOrUnderscore >>> BinaryDigit >>> _ >>> >>> BinaryDigit: one of >>> 0 1 >>> >>> -Joe >>> >>> >> >> >> > > > From pbenedict at apache.org Tue Apr 13 05:12:11 2010 From: pbenedict at apache.org (Paul Benedict) Date: Tue, 13 Apr 2010 07:12:11 -0500 Subject: diamond operator and non-denotable types In-Reply-To: <4BC2D84D.6020502@oracle.com> References: <4BC2D84D.6020502@oracle.com> Message-ID: Maurizio, Good response. Would you able to make the compiler's error diagnostic verbose enough to emit an error such as: "Construction with 'new Foo<>()' cannot determine type from "Number&Comparator". Please use normal construction syntax." This would help the user, like me, determine the possible types being expected. Paul On Mon, Apr 12, 2010 at 3:22 AM, Maurizio Cimadamore wrote: > Paul Benedict wrote: >>> >>> The compiler >>> always erases an intersection type to the most appropriate type needed >>> in order to preserve the semantics of the program. >>> >> >> Maurizio, >> >> The diamond operator is supposed to be syntactic sugar, right? I don't >> think the class file is the problem here; let the compiler collapse >> the type as if you were not using the operator. >> >> Foo f = new Foo<>(); >> >> Just rewrite it like someone would write it in Java 5: >> Foo f = new Foo(); >> > > Hi Paul, > if the inference algorithm yields e.g. Foo>, how > do you exactly go from this type to a type that the user would write? You'd > have to choose between Number and Comparator, meaning that, > depending on your choice, the members of one class or the other will be > available for use --- which seems arbitrary, and not consistent with what we > do with generic methods. Also consider that it's ot only about intersection > types; there are also captured types which might be even harder to > 'simplify' (e.g. do you propose to use the upper or lower bound? What if the > bound is itself non-denotable?) > > However, if you decide to keep Foo> as is, you > encounter a problem when you try to generate the classfile, in case the > diamond operator is of the kind: > > new Foo<>() {} //anon class > > in fact, this generates a class of the kind: > > class Anon$Foo extends Foo> { ... } > > Which is rather weird --- in fact, there's no way to represent this in the > classfile without extending the classfile format and the Signature attribute > format, which is way outside the scope of the coin project. > > Back to your question; is diamond syntactic sugar? On the one hand yes; it > provides a way to avoid the need of manually specifying type parameters on > class instantiation. However there's a subtle point here: the set of types > returned by the inference algorithm is larger than the set of types that can > be used in a correct Java programs. What do we do in such cases? > > In my original email I suggested to reject the program (because it has no > equivalent Java counterpart); on the other hand Neal would like to have the > program accepted as long as this doesn't interfere with code generation; > this means only rejecting the case of anonymous inner class creation. > > Maurizio > >> Paul >> > > From maurizio.cimadamore at oracle.com Tue Apr 13 05:49:39 2010 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Tue, 13 Apr 2010 13:49:39 +0100 Subject: diamond operator and non-denotable types In-Reply-To: References: <4BC2D84D.6020502@oracle.com> Message-ID: <4BC46863.2080300@oracle.com> Paul Benedict wrote: > Maurizio, > > Good response. Would you able to make the compiler's error diagnostic > verbose enough to emit an error such as: > > "Construction with 'new Foo<>()' cannot determine type from > "Number&Comparator". Please use normal construction syntax." > Hi Paul, the error message that is currently generated is something like: TestX.java:4: cannot infer a denotable type argument for Foo<>; Foo f = new Foo<>() {}; ^ reason: type argument INT#1 inferred for Foo<> is not denotable where INT#1 is an intersection type: INT#1 extends Number,Comparator 1 error The error message is taking advantage of the improved diagnostic support --- the intersection type is explicitly described in a 'where' clause generated by the compiler, listing all the upper bounds of the type. Maurizio > This would help the user, like me, determine the possible types being expected. > > Paul > > On Mon, Apr 12, 2010 at 3:22 AM, Maurizio Cimadamore > wrote: > >> Paul Benedict wrote: >> >>>> The compiler >>>> always erases an intersection type to the most appropriate type needed >>>> in order to preserve the semantics of the program. >>>> >>>> >>> Maurizio, >>> >>> The diamond operator is supposed to be syntactic sugar, right? I don't >>> think the class file is the problem here; let the compiler collapse >>> the type as if you were not using the operator. >>> >>> Foo f = new Foo<>(); >>> >>> Just rewrite it like someone would write it in Java 5: >>> Foo f = new Foo(); >>> >>> >> Hi Paul, >> if the inference algorithm yields e.g. Foo>, how >> do you exactly go from this type to a type that the user would write? You'd >> have to choose between Number and Comparator, meaning that, >> depending on your choice, the members of one class or the other will be >> available for use --- which seems arbitrary, and not consistent with what we >> do with generic methods. Also consider that it's ot only about intersection >> types; there are also captured types which might be even harder to >> 'simplify' (e.g. do you propose to use the upper or lower bound? What if the >> bound is itself non-denotable?) >> >> However, if you decide to keep Foo> as is, you >> encounter a problem when you try to generate the classfile, in case the >> diamond operator is of the kind: >> >> new Foo<>() {} //anon class >> >> in fact, this generates a class of the kind: >> >> class Anon$Foo extends Foo> { ... } >> >> Which is rather weird --- in fact, there's no way to represent this in the >> classfile without extending the classfile format and the Signature attribute >> format, which is way outside the scope of the coin project. >> >> Back to your question; is diamond syntactic sugar? On the one hand yes; it >> provides a way to avoid the need of manually specifying type parameters on >> class instantiation. However there's a subtle point here: the set of types >> returned by the inference algorithm is larger than the set of types that can >> be used in a correct Java programs. What do we do in such cases? >> >> In my original email I suggested to reject the program (because it has no >> equivalent Java counterpart); on the other hand Neal would like to have the >> program accepted as long as this doesn't interfere with code generation; >> this means only rejecting the case of anonymous inner class creation. >> >> Maurizio >> >> >>> Paul >>> >>> >> From pbenedict at apache.org Tue Apr 13 06:31:13 2010 From: pbenedict at apache.org (Paul Benedict) Date: Tue, 13 Apr 2010 08:31:13 -0500 Subject: diamond operator and non-denotable types In-Reply-To: <4BC46863.2080300@oracle.com> References: <4BC2D84D.6020502@oracle.com> <4BC46863.2080300@oracle.com> Message-ID: I think the message is clear from the technical sense, but may I suggest an improvement? I do not believe most programmers would understand "denotable type" or "intersection type" and I would like to see an alternative wording. Paul On Tue, Apr 13, 2010 at 7:49 AM, Maurizio Cimadamore wrote: > Paul Benedict wrote: >> >> Maurizio, >> >> Good response. Would you able to make the compiler's error diagnostic >> verbose enough to emit an error such as: >> >> "Construction with 'new Foo<>()' cannot determine type from >> "Number&Comparator". Please use normal construction syntax." >> > > Hi Paul, > the error message that is currently generated is something like: > > TestX.java:4: cannot infer a denotable type argument for Foo<>; > Foo f = new Foo<>() {}; > ? ? ? ? ? ? ? ? ^ > ?reason: type argument INT#1 inferred for Foo<> is not denotable > ?where INT#1 is an intersection type: > ? INT#1 extends Number,Comparator > 1 error > > The error message is taking advantage of the improved diagnostic support --- > the intersection type is explicitly described in a 'where' clause generated > by the compiler, listing all the upper bounds of the type. > > Maurizio > >> This would help the user, like me, determine the possible types being >> expected. >> >> Paul >> >> On Mon, Apr 12, 2010 at 3:22 AM, Maurizio Cimadamore >> wrote: >> >>> >>> Paul Benedict wrote: >>> >>>>> >>>>> The compiler >>>>> always erases an intersection type to the most appropriate type needed >>>>> in order to preserve the semantics of the program. >>>>> >>>>> >>>> >>>> Maurizio, >>>> >>>> The diamond operator is supposed to be syntactic sugar, right? I don't >>>> think the class file is the problem here; let the compiler collapse >>>> the type as if you were not using the operator. >>>> >>>> Foo f = new Foo<>(); >>>> >>>> Just rewrite it like someone would write it in Java 5: >>>> Foo f = new Foo(); >>>> >>>> >>> >>> Hi Paul, >>> if the inference algorithm yields e.g. Foo>, >>> how >>> do you exactly go from this type to a type that the user would write? >>> You'd >>> have to choose between Number and Comparator, meaning that, >>> depending on your choice, the members of one class or the other will be >>> available for use --- which seems arbitrary, and not consistent with what >>> we >>> do with generic methods. Also consider that it's ot only about >>> intersection >>> types; there are also captured types which might be even harder to >>> 'simplify' (e.g. do you propose to use the upper or lower bound? What if >>> the >>> bound is itself non-denotable?) >>> >>> However, if you decide to keep Foo> as is, you >>> encounter a problem when you try to generate the classfile, in case the >>> diamond operator is of the kind: >>> >>> new Foo<>() {} //anon class >>> >>> in fact, this generates a class of the kind: >>> >>> class Anon$Foo extends Foo> { ... } >>> >>> Which is rather weird --- in fact, there's no way to represent this in >>> the >>> classfile without extending the classfile format and the Signature >>> attribute >>> format, which is way outside the scope of the coin project. >>> >>> Back to your question; is diamond syntactic sugar? On the one hand yes; >>> it >>> provides a way to avoid the need of manually specifying type parameters >>> on >>> class instantiation. However there's a subtle point here: the set of >>> types >>> returned by the inference algorithm is larger than the set of types that >>> can >>> be used in a correct Java programs. What do we do in such cases? >>> >>> In my original email I suggested to reject the program (because it has no >>> equivalent Java counterpart); on the other hand Neal would like to have >>> the >>> program accepted as long as this doesn't interfere with code generation; >>> this means only rejecting the case of anonymous inner class creation. >>> >>> Maurizio >>> >>> >>>> >>>> Paul >>>> >>>> >>> >>> > > From maurizio.cimadamore at oracle.com Tue Apr 13 06:44:06 2010 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Tue, 13 Apr 2010 14:44:06 +0100 Subject: diamond operator and non-denotable types In-Reply-To: References: <4BC2D84D.6020502@oracle.com> <4BC46863.2080300@oracle.com> Message-ID: <4BC47526.4010009@oracle.com> Paul Benedict wrote: > I think the message is clear from the technical sense, but may I > suggest an improvement? I do not believe most programmers would > understand "denotable type" or "intersection type" and I would like to > see an alternative wording. > The wording for 'denotable type' is likely to change; as Neal pointed out, it's not correct in the technical sense either, as a wildcard type would be equally invalid, while being denotable. I'll probably generate a more general error message of the kind 'invalid type inferred for Foo<>' and then leave to the 'where clause' the burden of going into the gory details of that type. On the other hand, the word 'intersection type' comes from the JLS. Note that the 'where clause' section of an error message is intended to provide additional specific information about types; in this respect 'intersection type' is the name of a type, pretty much like 'type-variable' and 'captured-type'. In any case, I think the current wording is more expressive than just 'Number&Comparable'. Maurizio > Paul > > On Tue, Apr 13, 2010 at 7:49 AM, Maurizio Cimadamore > wrote: > >> Paul Benedict wrote: >> >>> Maurizio, >>> >>> Good response. Would you able to make the compiler's error diagnostic >>> verbose enough to emit an error such as: >>> >>> "Construction with 'new Foo<>()' cannot determine type from >>> "Number&Comparator". Please use normal construction syntax." >>> >>> >> Hi Paul, >> the error message that is currently generated is something like: >> >> TestX.java:4: cannot infer a denotable type argument for Foo<>; >> Foo f = new Foo<>() {}; >> ^ >> reason: type argument INT#1 inferred for Foo<> is not denotable >> where INT#1 is an intersection type: >> INT#1 extends Number,Comparator >> 1 error >> >> The error message is taking advantage of the improved diagnostic support --- >> the intersection type is explicitly described in a 'where' clause generated >> by the compiler, listing all the upper bounds of the type. >> >> Maurizio >> >> >>> This would help the user, like me, determine the possible types being >>> expected. >>> >>> Paul >>> >>> On Mon, Apr 12, 2010 at 3:22 AM, Maurizio Cimadamore >>> wrote: >>> >>> >>>> Paul Benedict wrote: >>>> >>>> >>>>>> The compiler >>>>>> always erases an intersection type to the most appropriate type needed >>>>>> in order to preserve the semantics of the program. >>>>>> >>>>>> >>>>>> >>>>> Maurizio, >>>>> >>>>> The diamond operator is supposed to be syntactic sugar, right? I don't >>>>> think the class file is the problem here; let the compiler collapse >>>>> the type as if you were not using the operator. >>>>> >>>>> Foo f = new Foo<>(); >>>>> >>>>> Just rewrite it like someone would write it in Java 5: >>>>> Foo f = new Foo(); >>>>> >>>>> >>>>> >>>> Hi Paul, >>>> if the inference algorithm yields e.g. Foo>, >>>> how >>>> do you exactly go from this type to a type that the user would write? >>>> You'd >>>> have to choose between Number and Comparator, meaning that, >>>> depending on your choice, the members of one class or the other will be >>>> available for use --- which seems arbitrary, and not consistent with what >>>> we >>>> do with generic methods. Also consider that it's ot only about >>>> intersection >>>> types; there are also captured types which might be even harder to >>>> 'simplify' (e.g. do you propose to use the upper or lower bound? What if >>>> the >>>> bound is itself non-denotable?) >>>> >>>> However, if you decide to keep Foo> as is, you >>>> encounter a problem when you try to generate the classfile, in case the >>>> diamond operator is of the kind: >>>> >>>> new Foo<>() {} //anon class >>>> >>>> in fact, this generates a class of the kind: >>>> >>>> class Anon$Foo extends Foo> { ... } >>>> >>>> Which is rather weird --- in fact, there's no way to represent this in >>>> the >>>> classfile without extending the classfile format and the Signature >>>> attribute >>>> format, which is way outside the scope of the coin project. >>>> >>>> Back to your question; is diamond syntactic sugar? On the one hand yes; >>>> it >>>> provides a way to avoid the need of manually specifying type parameters >>>> on >>>> class instantiation. However there's a subtle point here: the set of >>>> types >>>> returned by the inference algorithm is larger than the set of types that >>>> can >>>> be used in a correct Java programs. What do we do in such cases? >>>> >>>> In my original email I suggested to reject the program (because it has no >>>> equivalent Java counterpart); on the other hand Neal would like to have >>>> the >>>> program accepted as long as this doesn't interfere with code generation; >>>> this means only rejecting the case of anonymous inner class creation. >>>> >>>> Maurizio >>>> >>>> >>>> >>>>> Paul >>>>> >>>>> >>>>> >>>> >> From vapor1 at teleport.com Tue Apr 20 23:38:36 2010 From: vapor1 at teleport.com (Derek Foster) Date: Wed, 21 Apr 2010 02:38:36 -0400 (EDT) Subject: Combined grammar changes for binary literals and underscores in literals Message-ID: <22874293.1271831916210.JavaMail.root@wamui-haziran.atl.sa.earthlink.net> Hi, Bruce. It's good to hear from you again! Regarding your suggested changes to the grammar in the proposal, I admit to being a bit skeptical that they really add enough value to compensate for the decrease in readability. I tend to agree with Joe's assessment: >One advantage of the way I wrote up the grammar is that the other >appearances of Digits and HexDigits, such as in floating-point literals >in section 3.10.2, automatically inherit the underscore policy without >having to having leading digit guard productions in all places. The >current implementation does allow underscores in floating-point literals >too, which is tested for in the regression tests. Specifically, I think that although the grammar changes you propose may be "simpler" in terms of having fewer productions, it is also a little bit harder to understand, and easier to make mistakes with. Given that this is a specification rather than an implementation, I think that it is most important in this case to be clear and comprehensible, so that various people can implement it correctly and be confident that they have done so. A compiler vendor can always massage the grammar as necessary in order to lead to more efficient code if desired. I'm not dead-set against the changes you propose -- they just seem somewhat unnecessary to me, and I'm hesitant to make any unnecessary changes at this late stage, since it would be very easy to accidentally insert a mistake into the specification right before it's finalized. Derek -----Original Message----- >From: Joe Darcy >Sent: Apr 13, 2010 4:05 AM >To: Bruce Chapman >Cc: coin-dev >Subject: Re: Combined grammar changes for binary literals and underscores in literals > >Welcome back Bruce! > >Bruce Chapman wrote: >> Joe, Derek et al, >> >> I am just writing up the combined integer literal omnibus proposal. >> >> A couple of questions about this grammar >> >> >> 1) >> >> considering >> >> DecimalNumeral >> 0 >> NonZeroDigit Digits_opt >> NonZeroDigit Underscores Digits // New (1) >> >> Underscores >> _ >> Underscores _ >> >> Digits: >> Digit >> Digit DigitsAndUnderscores_opt Digit (2) >> >> >> I think we can drop rule (1) above, if rule (2) is changed to >> >> DigitsAndUnderscores_opt Digit >> >> since there is already a leading NonZeroDigit, so we can start a >> "Digits" with an underscore, so we don't need the special rule to allow >> for an underscore immediately after the NonZeroDigit. >> >> Agreed? >> >> If so we can also make corresponding change for Octal rules then drop >> the Underscores production as these are the only places it is used. >> >> >> 2) >> >> I am wondering whether it would enhance grokkability of we renamed the >> productions >> >> HexDigitsAndUnderscores (and other radix friends, and corresponding singular forms) >> >> >> to be (eg) >> HexMidDigits >> >> because it can't be used at either end of the HexDigits, but can be in >> the middle. >> >> - if we did this the hex rules would change from >> >> HexDigits: >> HexDigit >> HexDigit HexDigitsAndUnderscores_opt HexDigit >> >> HexDigitsAndUnderscores: >> HexDigitOrUnderscore >> HexDigitsAndUnderscores HexDigitOrUnderscore >> >> HexDigitOrUnderscore >> HexDigit >> _ >> >> >> >> to >> >> HexDigits: >> HexDigit >> HexDigit HexMidDigits_opt HexDigit >> >> HexMidDigits: >> HexMidDigit >> HexMidDigits HexMidDigit (but actually vice versa as previously >> discussed off-list with Alex Buckley) >> >> HexMidDigit >> HexDigit >> _ >> >> >> >> >> Comments? >> >> > >One advantage of the way I wrote up the grammar is that the other >appearances of Digits and HexDigits, such as in floating-point literals >in section 3.10.2, automatically inherit the underscore policy without >having to having leading digit guard productions in all places. The >current implementation does allow underscores in floating-point literals >too, which is tested for in the regression tests. > >-Joe > > >> Bruce >> >> >> >> >> >> >> Joe Darcy wrote: >> >>> Hello. >>> >>> It has been pointed out to me off-list that the grammar as written below >>> would disallow two-digit numbers, which is not desired. This problem is >>> corrected by changing the productions like >>> >>> Digit DigitsAndUnderscores Digit >>> >>> to be >>> >>> Digit DigitsAndUnderscores_opt Digit >>> >>> -Joe >>> >>> On 07/15/09 02:22 PM, Joseph D. Darcy wrote: >>> >>> >>>> Hello. >>>> >>>> Getting around to some grammatical hacking, below is a grammar I think >>>> properly captures the desired changes for combining the binary >>>> literals and underscores in literals proposals. This grammar does >>>> *not* include support for unsigned literals or autosizing literals. >>>> >>>> The basic approach is to redefine the FooDigits productions to be a >>>> non-empty sequence of Foo digits and underscores starting and ending >>>> with a Foo digit rather than just a non-empty sequence Foo digits. >>>> Each FooDigits nonterminal has two rules, one for a single digit and >>>> one for two or more digits. The rules for two or more digits force a >>>> true digit, rather than an underscore, as the first and last character. >>>> >>>> Changing the FooDigits definitions allows underscores in both integer >>>> and floating-point literals. In more detail: >>>> >>>> * Replace the productions Digits, HexDigits, OctalDigits, and in >>>> JLSv3 3.10.1 as shown below >>>> * Add productions for BinaryDigits >>>> * Add rules for FooDigitsAndUnderscores and FooDigitOrUnderscore >>>> * Add productions to DecimalNumeral and OctalNumeral: >>>> * Add a rule for Underscores >>>> >>>> IntegerLiteral: >>>> DecimalIntegerLiteral >>>> HexIntegerLiteral >>>> OctalIntegerLiteral >>>> BinaryIntegerLiteral // New >>>> >>>> BinaryIntegerLiteral: >>>> BinaryNumeral IntegerTypeSuffix_opt >>>> >>>> BinaryNumeral: >>>> 0 b BinaryDigits >>>> 0 B BinaryDigits >>>> >>>> >>>> DecimalNumeral >>>> 0 >>>> NonZeroDigit Digits_opt >>>> NonZeroDigit Underscores Digits // New >>>> >>>> Underscores >>>> _ >>>> Underscores _ >>>> >>>> Digits: >>>> Digit >>>> Digit DigitsAndUnderscores Digit >>>> >>>> DigitsAndUnderscores: >>>> DigitOrUnderscore >>>> DigitsAndUnderscores DigitOrUnderscore >>>> >>>> DigitOrUnderscore >>>> Digit >>>> _ >>>> >>>> >>>> HexDigits: >>>> HexDigit >>>> HexDigit HexDigitsAndUnderscores HexDigit >>>> >>>> HexDigitsAndUnderscores: >>>> HexDigitOrUnderscore >>>> HexDigitsAndUnderscores HexDigitOrUnderscore >>>> >>>> HexDigitOrUnderscore >>>> HexDigit >>>> _ >>>> >>>> OctalNumeral: >>>> 0 OctalDigits >>>> 0 Underscores OctalDigits // New >>>> >>>> OctalDigits: >>>> OctalDigit >>>> OctalDigit OctalDigitsAndUnderscores OctalDigit >>>> >>>> OctalDigitsAndUnderscores: >>>> OctalDigitOrUnderscore >>>> OctalDigitsAndUnderscores OctalDigitOrUnderscore >>>> >>>> OctalDigitOrUnderscore >>>> OctalDigit >>>> _ >>>> >>>> BinaryDigits: >>>> BinaryDigit >>>> BinaryDigit BinaryDigitsAndUnderscores BinaryDigit >>>> >>>> BinaryDigitsAndUnderscores: >>>> BinaryDigitOrUnderscore >>>> BinaryDigitsAndUnderscores BinaryDigitOrUnderscore >>>> >>>> BinaryDigitOrUnderscore >>>> BinaryDigit >>>> _ >>>> >>>> BinaryDigit: one of >>>> 0 1 >>>> >>>> -Joe >>>> >>>> >>> >>> >>> >> >> >> > > From john.r.rose at oracle.com Thu Apr 22 12:11:04 2010 From: john.r.rose at oracle.com (John Rose) Date: Thu, 22 Apr 2010 12:11:04 -0700 Subject: JSR 292 support, minor change to specification Message-ID: <7B0E5BA5-7543-4BF7-9D3A-8BD262D3DDDB@oracle.com> The JSR 292 EG has made a minor naming change to the signature-polymorphic methods that Java needs to recognize for JSR 292. I've updated the wiki page, and have enclosed the changed specification here for the record. http://wikis.sun.com/display/mlvm/InterfaceDynamic (also enclosed) Key changes to the document: 1. Split MH.invoke into MH.invokeExact and MH.invokeGeneric, per EG request. 2. Specify an explicit marking for these methods, and the InvokeDynamic class, in source code and class files. 3. Discuss briefly alternatives to signature polymorphic invocation as currently specified. 4. Added a brief discussion about the syntax of exotic identifiers. Item 1 is the language change. Item 2 uses an annotation to make the required mark, which is a related language change, but not one which affects any user, since the annotation is private to the java.dyn package. The main impact is on tools, which may prefer to use the explicit marking instead of matching names. Items 3 and 4 are rationale. Best wishes, -- John From brucechapman at paradise.net.nz Thu Apr 22 12:26:25 2010 From: brucechapman at paradise.net.nz (Bruce Chapman) Date: Fri, 23 Apr 2010 07:26:25 +1200 Subject: Omnibus Integer Literals Message-ID: <4BD0A2E1.2050502@paradise.net.nz> Attached is the combined version of the Integer literals proposals. I have an implementation and tests patch for the remaining part for openJDK ready once someone processes the bug report. Bruce -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: MergedIntegerLiteralsProposals.txt Url: http://mail.openjdk.java.net/pipermail/coin-dev/attachments/20100423/a345b427/MergedIntegerLiteralsProposals.txt From forax at univ-mlv.fr Thu Apr 22 13:32:11 2010 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Thu, 22 Apr 2010 22:32:11 +0200 Subject: JSR 292 support, minor change to specification In-Reply-To: <7B0E5BA5-7543-4BF7-9D3A-8BD262D3DDDB@oracle.com> References: <7B0E5BA5-7543-4BF7-9D3A-8BD262D3DDDB@oracle.com> Message-ID: <4BD0B24B.1030408@univ-mlv.fr> Hi John, for item 1.3, I think that defaulting to Object is rough. Knowing that the diamond operator uses the type of the lhs part of an assignation I wonder if Invokedynamic.foo if no return type is specified should not use the same algorithm. int i = Invokeynamic.foo(2); should be encoded as invokedynamic (I)I R?mi Le 22/04/2010 21:11, John Rose a ?crit : > The JSR 292 EG has made a minor naming change to the signature-polymorphic methods that Java needs to recognize for JSR 292. I've updated the wiki page, and have enclosed the changed specification here for the record. > > http://wikis.sun.com/display/mlvm/InterfaceDynamic (also enclosed) > > Key changes to the document: > > 1. Split MH.invoke into MH.invokeExact and MH.invokeGeneric, per EG request. > 2. Specify an explicit marking for these methods, and the InvokeDynamic class, in source code and class files. > 3. Discuss briefly alternatives to signature polymorphic invocation as currently specified. > 4. Added a brief discussion about the syntax of exotic identifiers. > > Item 1 is the language change. Item 2 uses an annotation to make the required mark, which is a related language change, but not one which affects any user, since the annotation is private to the java.dyn package. The main impact is on tools, which may prefer to use the explicit marking instead of matching names. Items 3 and 4 are rationale. > > Best wishes, > -- John > > > > > > From john.r.rose at oracle.com Thu Apr 22 13:59:51 2010 From: john.r.rose at oracle.com (John Rose) Date: Thu, 22 Apr 2010 13:59:51 -0700 Subject: JSR 292 support, minor change to specification In-Reply-To: <4BD0B24B.1030408@univ-mlv.fr> References: <7B0E5BA5-7543-4BF7-9D3A-8BD262D3DDDB@oracle.com> <4BD0B24B.1030408@univ-mlv.fr> Message-ID: On Apr 22, 2010, at 1:32 PM, R?mi Forax wrote: > for item 1.3, I think that defaulting to Object is rough. > Knowing that the diamond operator uses the type of the lhs part of an > assignation > I wonder if Invokedynamic.foo if no return type is specified should not > use the same algorithm. That sounds very reasonable and probable to me; I would like it better than defaulting to Object. I don't understand the new defaulting rule enough to know if there would be problems with that. The interactions between diamond and primitive return types might have to be different for signature-polymorphic calls. As far as the type system is concerned MH.invoke{Exact,Generic} and InvokeDynamic.foo return an unconstrained result like the following method, which is unrelated to any other type or type variable: class Foo { static T nothingParticular(int a, String b) { return null; } } Float i = nothingParticular(123, "456"); Integer i = nothingParticular(123, "456"); int j = nothingParticular(123, "456"); -- John From neal at gafter.com Thu Apr 22 14:04:31 2010 From: neal at gafter.com (Neal Gafter) Date: Thu, 22 Apr 2010 14:04:31 -0700 Subject: JSR 292 support, minor change to specification In-Reply-To: References: <7B0E5BA5-7543-4BF7-9D3A-8BD262D3DDDB@oracle.com> <4BD0B24B.1030408@univ-mlv.fr> Message-ID: On Thu, Apr 22, 2010 at 1:59 PM, John Rose wrote: > As far as the type system is concerned MH.invoke{Exact,Generic} and > InvokeDynamic.foo return an unconstrained result like the following method, > which is unrelated to any other type or type variable: > That is not correct. Every type variable extends java.lang.Object and is extended by the null type. That is necessary because local type inference requires that the type universe be a lattice. That is achieved by restricting attention to the reference types. > class Foo { > static T nothingParticular(int a, String b) { return null; } > } > > Float i = nothingParticular(123, "456"); > Integer i = nothingParticular(123, "456"); > int j = nothingParticular(123, "456"); > From pbenedict at apache.org Thu Apr 22 14:32:33 2010 From: pbenedict at apache.org (Paul Benedict) Date: Thu, 22 Apr 2010 16:32:33 -0500 Subject: JSR 292 support, minor change to specification (John Rose) Message-ID: John, Has anymore thought gone into changing the syntax of the exotic identifier? It was once brought up a few months ago. I think using back ticks would be more appropriate than the pound sign + apostrophe -- especially if the # becomes a method handle. Paul From john.r.rose at oracle.com Thu Apr 22 18:04:05 2010 From: john.r.rose at oracle.com (John Rose) Date: Thu, 22 Apr 2010 18:04:05 -0700 Subject: JSR 292 support, minor change to specification Message-ID: P.S. Here is the document. -- John AUTHOR(S): John Rose OVERVIEW Create source-code syntaxes for using new JVM features from JSR 292. These are invokedynamic instructions, method handle invocation, certain relaxed conversions, and exotic identifiers. (Change Notes: Part 4, the proposed relaxed conversion and invocation rules for Dynamic, has been moved to a separate proposal. The marker type for dynamic invocations has been renamed to InvokeDynamic, and made a non-instantiated class with no public members.) BACKGROUND: At the JVM level, an invokedynamic instruction is used to call methods which have linkage and dispatch semantics defined by non-Java languages. Again, a JVM-level invokevirtual instruction has slightly altered linkage rules when the target class method is java.dyn.MethodHandle.invokeExact or java.dyn.MethodHandle.invokeGeneric: The change is that any type signature is acceptable, and the JVM will make a type-safe method call, regardless of the signature. In addition, the JVM already accepts (since Java 5) any of a large set of strings as field, method, and class identifiers, and many languages will use such identifiers beyond the limits of the Java identifier syntax. (Note: An earlier version of the JVM specification treated only java.dyn.MethodHandle.invoke as special. This has since been split into two sibling methods, with slightly differing invocation semantics. The differences are irrelevant to the present discussion of language support.) FEATURE SUMMARY: We will make small, localized modifications the Java language to make it easy to with with these JVM features (old and new). This will allow Java code to interoperate with and/or implement libraries in non-Java languages. The changes are as follows: 1. dynamic invocation The static-only class java.dyn.InvokeDynamic may be used with the static call syntax to form an invokedynamic call site. The method name may be any Java identifier (including an exotic one; see point 3). The arguments may be of any number and type. A type argument can optionally supply the return type, in the existing syntax. In effect, java.dyn.InvokeDynamic appears to have an infinite number of static methods, of every possible name and signature. More details are given below, but here is a first example: Object x = InvokeDynamic.getMeSomething(); (As defined by JSR 292, an invokedynamic call site is linked to a target method under the control of an application-defined bootstrap method. The linkage state is determined by a method handle with the same type descriptor as the call site itself.) 2. method handle invocation Method handles (class java.dyn.MethodHandle) provide the "plumbing" behind any invokedynamic instruction. There are library routines for creating and adapting them, as specified by JSR 292. In addition, it is necessary to provide a way of invoking a method handle as an explicit target, rather than implicitly as the linked target of an invokedynamic instruction. Since a method handle invocation (like invokedynamic itself) can have any argument types and return value, method handles also need a special extension for invocation. As for type InvokeDynamic, the type MethodHandle accepts an infinite variety of non-static calls to the methods named invokeExact and invokeGeneric. The argument and return types for the descriptor presented to the JVM are determined as for invokedynamic calls. Here is a first example: MethodHandle mh = ...; mh.invokeExact(); 3. exotic identifiers The grammar for Java identifiers is extended to include "exotic identifiers", whose spellings can be any sequence of characters, as long as they avoid certain minor restrictions imposed by the JVM. An exotic identifier is introduced by a hash mark, which is immediately followed by a string literal. No special treatment is given to the identifier, other than ensuring that its spelling contains exactly the character sequence denoted by the string literal. Details are given below; here is an example: int #"strange variable name" = 42; System.out.println(#"strange variable name"); // prints 42 MAJOR ADVANTAGE: These changes allow full access to invokedynamic and related new JVM features from JSR 292. This allows Java to interoperate with new JVM languages. It also enables Java to serve well as an language implementation or systems programming language. MAJOR BENEFIT: Much greater ease of creating, for the JVM, with javac, new programming languages and language runtimes. (The potential opportunity cost is that language implementors who presently use Java as a systems programming language will be forced to stay down at the bytecode assembly level, making them slower to adopt the JVM for their work.) MAJOR DISADVANTAGE: The JLS gets more complicated. ALTERNATIVES: The only viable alternative is assembly coding parts of the system which must interoperate with new languages. This will discourage the creation of common runtimes and libraries, and greatly reduce the synergy between languages. Comment added 4/2010: There are many degrees of syntactic freedom for designing this new type of expression. Here are some of the alternatives. The first is the present proposal, and the others are roads not taken: /*A*/ InvokeDynamic.greet("hello", "world", 123); //recommended /*B*/ InvokeDynamic.invoke("greet", new Class[]{ Object.class, String.class, String.Class, int.class }, new Object[] {"hello", "world", 123 }); //reflective formulation /*C*/ $invokedynamic Object greet("hello", "world", 123); //new keyword /*D*/ $invokedynamic Object(String,String,int) greet("hello", "world", 123); //explicit signature /*E*/ $asm { push "hello"; push "world"; push 123; invokedynamic greet:Object(String,String,int); pop result; } //asm statement Case A uses static types and names to fill in the required name and signature information for the bytecode. Case B is a different extreme: Every natural degree of freedom is expressed by a reflective expression. Case C uses a keyword rather than a "magic class", though there is ample precedent in the Java language for special treatment of known magic classes (like Integer or String). It is not clear with the reflective formulations what limitations (if any) are to be imposed on the reflective subexpressions. What happens if the method name or type signature is specified by a non-constant expression? Must the array expressions always be explicit subexpressions, or may they be bound as constants to temporary names? Is the statically bound invokedynamic instruction simply an optimization of a more general reflective facility, and if so, how can a user reliably get this optimization (if at all)? Must operands like 123 be autoboxed, even though the invokedynamic instruction does not box its primitive arguments? Modeling an invokedynamic instruction reflectively makes it compatible with the existing Java language; the features of autoboxing and varargs (not used here) can even make the expressions of tolerable brevity, but there it is very difficult to mesh such expressions with the static typing guarantees inherent to the invokedynamic instruction. Cases B and D make the invokedynamic instruction signature explicit. The instruction is polymorphic across all VM-level signatures, so somehow each dynamic invocation expression must specify (implicitly or explicitly) the signature to use. Moreover, the arguments and return value must agree with that signature. (The JVM verifier ensures this for invokedynamic instructions just as for other invoke instructions.) Given that there must be matching arguments at the call site, the argument type information is already present, and need not be redundantly specified via an explicit signature. This is the root cause for some of the problems with B and D: Not only are they verbose because they specify the argument types two different ways (explicitly and implicitly in the argument types), but they are also buggy and complex because those redundant specifications might fail to coincide. At minimum, only the intended return type needs to be specified explicitly. In the current proposal this is done via an optional type parameter which defaults (helpfully) to Object. In case C, it is done by a type name following the new keyword. In case A, the type parameter has a peculiar feature that, as a literal part of the invokedynamic signature, it can be a primitive type or void, as well as any reference type. The last case E presupposes a way to inline bytecode assembly code into a Java program. If there were such a thing, perhaps that would be the most natural way to introduce dynamic call sites. However, there is no such thing proposed for the Java language, and designing such a thing would be a much larger undertaking than the present one. All of these observations (except those about the variable method name) apply to the signature-polymorphic methods of MethodHandle, namely, invokeExact and invokeGeneric (or just invoke, in earlier versions of this proposal). EXAMPLES: See above and below (in the specification) for one-line examples demonstrating each aspect of the syntax and type rules. void test(MethodHandle mh) { mh.invoke("world", 123); // previous line generates invokevirtual MethodHandle.invoke(String,int)Object InvokeDynamic.greet("hello", "world", 123); // previous line generates invokedynamic greet(Object,String,int)Object // enclosing class must register a bootstrap method (handle) to link InvokeDynamic.greet } BEFORE/AFTER There are no concise before/after examples for these language features per se, because without the new syntax, dynamic language implementors must resort to assembly code. But, here is a mocked up example that shows how call site caches can be created before and after JSR 292. This is for no particular language; call it MyScript. Note the use of the proposed features to form and manage dynamic call sites. class Foo { // compiled method for def ready? = lambda (x) { print "Hello, " + x } private static Object method56(Object x) { System.out.println("Hello, "+x); return null; } // function pointer, old style: public static Method1 bind_ready__63() { /*ready?*/ return new Method1() { // there is a new classfile per expression reference public Object apply(Object arg) { return method56(arg); } } } // function pointer, new style: public static MethodHandle #"bind:ready?"() { // it all happens in one classfile return MethodHandles.findStatic(Foo.class, "method56", MethodTypes.makeGeneric(1)); } // Note: the language runtime uses Java reflection to help it link. } class Bar { // compiled method for lambda (x) { x . ready? } // call-site cache, old style: private static Method1 csc42 = null; private static Object method2(Object x) { Method1 tem = csc42; // complex machinery with little hope of optimization if (tem == null) csc42 = tem = MOP.resolveCallSite(Foo.class, "ready?", x); return tem.apply(x); } // call-site cache, new style: private static Object method2(Object x) { // native to the JVM and the JIT return InvokeDynamic.#"myscript:ready?"(x); } static { Linkage.registerBootstrapMethod("bootstrapInvokeDynamic"); } // Note: The Linkage API is subject to change. private static Object bootstrapInvokeDynamic(java.dyn.CallSite site, Object... args) { return MOP.executeCallSite(site, args); } } class MOP { // shared logic for resolving call sites public static executeCallSite(java.dyn.CallSite site, Object... args) { MethodHandle target = site.target(); if (target == null) { target = resolveCallSite(site.callerClass(), site.name(), args); site.setTarget(target); // next time it will be a direct call } return MethodHandles.invoke(target, args); } } SIMPLE EXAMPLE: This example greets the world using (a) normal static linkage, (b) direct method handle invocation, and (c) a lazily linked call site (invokedynamic). The output from the "bootstrap" routine appears only once, after which the linked call site runs by directly calling the target method, with no reflection. import java.dyn.*; public class Hello { public static void main(String... av) throws Throwable { if (av.length == 0) av = new String[] { "world" }; greeter(av[0] + " (from a statically linked call site)"); for (String whom : av) { greeter.invokeExact(whom); // strongly typed direct call // previous line generates invokevirtual MethodHandle.invokeExact(String)void Object x = whom; InvokeDynamic.hail(x); // weakly typed invokedynamic // previous line generates invokedynamic hail(Object)Object } } static void greeter(String x) { System.out.println("Hello, "+x); } // intentionally pun between the method and its reified handle: static MethodHandle greeter = MethodHandles.lookup().findStatic(Hello.class, "greeter", MethodType.methodType(void.class, String.class)); // Set up a class-local bootstrap method. static { Linkage.registerBootstrapMethod("bootstrapDynamic"); } private static CallSite bootstrapDynamic(Class caller, String name, MethodType type) { assert(type.parameterCount() == 1 && name.equals("hail")); // in lieu of MOP System.out.println("set target to adapt "+greeter); return new CallSite(greeter.asType(type)); } } ADVANCED EXAMPLE: (See before-and-after MOP example above.) DETAILS SPECIFICATION: 1.1 The type java.dyn.InvokeDynamic shall be defined as an empty class with no supertypes (other than Object) and no constructors (other than a private one, as required by the language). This static-only pattern is like that of java.util.Collections, except that there are no statically defined methods at all. It is an error if InvokeDynamic is defined as an interface, or if it has any supertypes, or if it has any explicit member definitions (other than a private constructor). Although it has the usual implicit supertype of Object, it inherits no static methods from its supertype (which, indeed, has none to bequeath). package java.dyn; @MethodHandle.PolymorphicSignature public final class InvokeDynamic /*must be empty*/ { private InvokeDynamic() { } /*must be empty except for private constructor*/ } (Note that InvokeDynamic is not useful as a reference type. Like java.util.Collections, it is a non-instantiated class.) As an aid to implementations, the source code for class InvokeDynamic must include an annotation of @MethodHandle.PolymorphicSignature, and the classfile for InvokeDynamic must contain a zero-length classfile attribute named PolymorphicSignature. The annotation (described in 2.1 below) is a private type, and therefore is not part of the public API of InvokeDynamic. 1.2 The type name InvokeDynamic may serve as a qualifier to any method name whatever, and invoked on any number and type of arguments. The call always resolves to an implicitly defined static method. Instead of an invokestatic call, however, the compiler generates an invokedynamic call site with the given name and a descriptor (symbolic type signature) derived from the erasure of the static types of all the arguments. In this way, an invokedynamic instruction can be written in Java to use any of the full range of calling sequences (i.e., descriptors) supported by the JVM. Neither the JVM instruction nor the Java syntax is limited in its use of argument types. InvokeDynamic.anyNameWhatever(); // no argument types InvokeDynamic.anotherName("foo", 42); // argument types (String, int) 1.3 Any call to a static method in InvokeDynamic accepts an optional type parameter which specifies the return type of the call site's descriptor. The type parameter may any type whatever, including void or a primitive type. If it is omitted it defaults to the type Object itself. Object x = InvokeDynamic.myGetCurrentThing(); // type () -> Object InvokeDynamic.myPutCurrentThing(x); // type (Object) -> void int y = InvokeDynamic.myHashCode(x); // type (Object) -> int boolean z = InvokeDynamic.myEquals(x, y); // type (Object, int) -> boolean (Rationale: Although it is strange for non-references to appear in the syntactic position of type arguments, this design is far simpler than inventing a completely new syntax for specifying the return type of the call site, as some early prototypes did.) 1.4 For the purposes of determining the descriptor of the invokedynamic instruction, null arguments (unless casted to some other type) are deemed to be of reference type java.lang.Null, if this type exists. The type java.lang.Null will appear only to the bootstrap method, and will serve notice that the call site contains an untyped null reference, rather than an explicitly typed reference. InvokeDynamic.myPrintLine(null); // type (Null) -> Object InvokeDynamic.foo((String)null, null); // type (String, Null) -> void 1.5 As the JVM executes, checked or unchecked exceptions may be produced by any invokedynamic call. However, there is (currently) no way to statically infer which exceptions may be thrown at any given call site. Therefore, all signature polymorphic methods throw the most general type, Throwable. InvokeDynamic.write(out, "foo"); // might throw any checked exception try { InvokeDynamic.foo(); } catch (IOException ee) { } // must be accepted, and still throws Throwable try { "foo".hashCode(); } catch (IOException ee) { } // a compile-time error (Note: This means that methods containing invokedynamic calls will generally throw Throwable, or else include some complicated catch-all logic around their dynamic call sites. This limits but does not destroy the usefulness of InvokeDynamic calls.) 2.1 The class java.dyn.MethodHandle shall be defined to contain methods named invokeExact and invokeGeneric, as follows: package java.dyn; public class MethodHandle { @interface PolymorphicSignature { } // non-public, used only as directed in this proposal public final native @PolymorphicSignature R invokeExact(A... args) throws Throwable; public final native @PolymorphicSignature R invokeGeneric(A... args) throws Throwable; ... } As an aid to implementations, these methods shall be marked (in the source code) with a non-public empty annotation MethodHandle.PolymorphicSignature. They shall be marked (in the classfile for MethodHandle) with a zero-length classfile attribute named PolymorphicSignature. It is an error if MethodHandle or any of its subtypes or supertypes define a method named invokeExact or invokeGeneric. (In any case, such supertypes or subtypes are a fixed part of the Java APIs and/or implementations. JSR 292 happens to define several other methods on method handles.) It is an error if the annotation PolymorphicSignature is used other than as specified in this proposal. (In any case, since it is non-public, the uses cannot be relevant to application code.) 2.2 Any reference of type MethodHandle may serve as a qualifier to the method name invokeExact or invokeGeneric and invoked on any number and type of arguments. Only the methods named invokeExact and invokeGeneric are treated this new way. All other expressions involving MethodHandle are unchanged in meaning, including selection of members other than invokeExact or invokeGeneric, casting, and the instanceof operator. MethodHandle mh = ...; mh.invokeExact("foo", 42); // argument types (String, int) MethodType mtype = mh.type(); // no new rules here; see JSR 292 javadocs mh.neverBeforeSeenName(); // no new rules; must raise an error In effect, java.dyn.MethodHandle appears to have an infinite number of non-static methods named invokeExact and invokeGeneric, of every possible (erased) signature. (In fact, JSR 292 specifies that each individual method handle has a unique type signature, and may be invoked only under that specific type. This type is checked on every method handle call. JSR 292 guarantees runtime type safety by requiring that an exception be thrown if a method handle caller and callee do not agree exactly on the argument and return types. The details of this check are not part of this specification, but rather of the MethodHandle API.) 2.3 A method handle call on invokeExact or invokeGeneric accepts an optional type parameter to specify the return type. As with InvokeDynamic, the type parameter to MethodHandle.invokeExact or MethodHandle.invokeGeneric may be any type, including void or a primitive type. If it is omitted it defaults to Object. MethodHandle mh1, mh2, mh3, mh4; ... Object x = mh1.invokeGeneric(); // type () -> Object mh2.invoke(x); // type (Object) -> void int y = mh3.invokeExact(x); // type (Object) -> int boolean z = mh4.invokeGeneric(x, y); // type (Object, int) -> boolean 2.4 As with InvokeDynamic, otherwise untyped null argument values are treated as if they were of type Void. mh1.invokeExact(null); // type (Void) -> Object mh2.invokeGeneric((String)null, null); // type (String, Void) -> void 2.5 As the JVM executes, checked or unchecked exceptions may be produced by any virtual call. However, there is (currently) no way to statically infer which exceptions may be thrown at any given method handle invocation. Therefore, all signature polymorphic methods throw the most general type, Throwable. writeMH.invokeExact(out, "foo"); // might throw a checked exception try { mh.invokeGeneric(); } catch (IOException ee) { } // must be accepted, and still throws Throwable try { "foo".hashCode(); } catch (IOException ee) { } // a compile-time error (Note: This means that methods containing method handle invocations will generally throw Throwable, or else include some complicated catch-all logic around their method handle call sites. This limits but does not destroy the usefulness of method handle calls.) 2.6 As usual, if a null value typed as a method handle qualifies the method name invoke, the expression must terminate abnormally with a NullPointerException. MethodHandle nmh = null; nmh.invokeGeneric(); // must produce a NullPointerException 2.7 If a class extends MethodHandle, it does not inherit any of the implicitly defined invokeExact or invokeGeneric methods. To invoke a subclass of a method handle, it must first be cast to MethodHandle per se. (Non-inheritance of invokeExact and invokeGeneric methods prevents MethodHandle from disturbing static scoping of any type other than MethodHandle itself. Note that public method handle subclasses are not necessarily a feature of JSR 292.) class MySpecialMethodHandle extends MethodHandle { ... } MySpecialMethodHandle dmh = mh; mh.invokeGeneric(); // must be rejected: special MH.invokeGeneric not visible here 2.8 The bytecode emitted for any call to MethodHandle.invokeExact or MethodHandle.invokeGeneric is an invokevirtual instruction, exactly as if a public virtual method of the desired descriptor were already present in java.dyn.MethodHandle. mh.invokeExact(1); // produces an invokevirtual instruction class MethodHandle { ... public abstract void invoke(int x); ... } // hypothetical overloading of 'invoke' mh.invokeGeneric(1); // would produce an identical invokevirtual, if that overloading could exist 3.1 The two-character sequence '#' '"' (hash and string-quote, or ASCII code points 35 and 24) introduces a new token similar in structure to a Java string literal. The token is in fact an identifier (JLS 3.8), which may be used for all the same syntactic purposes as ordinary identifiers are used for. int #"strange variable name" = 42; System.out.println(#"strange variable name"); // prints 42 This is true whether or not the characters are alphanumeric, or whether they happen (when unquoted) to spell any Java Java keyword or token. int #"+", #"\\", #"42" = 24; System.out.println(#"42" * 100); // prints 2400 // another take on java.lang.Integer: class #"int" extends Number { final int #"int"; #"int"(int #"int") { this.#"int" = #"int"; } static #"int" valueOf(int #"int") { return new #"int"(#"int"); } public int intValue() { return #"int"; } public long longValue() { return #"int"; } public float floatValue() { return #"int"; } public double doubleValue() { return #"int"; } public String toString() { return String.valueOf(#"int"); } } 3.2 The spelling of the identifier is obtained by collecting all the characters between the string quotes. Every string escape sequence (JLS 3.10.6) is replaced by the characters they refer to. As with other tokens, this character collection occurs after Unicode escape replacement is complete (JLS 3.3). int #"\'\t" = 5; // a two-character identifier System.out.println(#"'\u0009"); // prints 5 3.3 In particular, if the resulting sequence of characters happens to be a previously valid Java identifier, both normal and exotic forms of the same identifier token may be freely mixed. int #"num" = 42, scale = 100; System.out.println(num * #"scale"); // prints 4200 3.4 An exotic identifier may not be empty. That is, there must be at least one character between the opening and closing quotes. int #""; // must be rejected 3.5 Certain characters are treated specially within exotic identifiers even though they are not specially treated in string or character literals. The following so-called "dangerous characters" are illegal in an exotic identifier unless preceded by a backslash: / . ; < > [ ]. If a dangerous character is preceded by a backslash, the backslash is elided and the character is collected anyway. Depending on the ultimate use of the identifier, the program may be eventually rejected with an error. This must happen if and only if the escaped character would otherwise participate in a bytecode name forbidden by the Java 5 JVM specification. class #"foo/Bar" { } // not a package qualifier, must be rejected class #"foo.Bar" { } // not a package qualifier, must be rejected x.#""(); // not a method call; must be rejected x.#"f(Ljava/lang/Long;)"(0); // not a method descriptor; must be rejected 3.5.1 Specifically, the compiler must reject a program containing an exotic identifier with an escaped dangerous character happen if any of these is true: (a) the identifier is used as part or all of the bytecode name of a class or interface, and it contains any of / . ; [, or (b) the identifier is used as a part or all of the bytecode name of a method, and it contains any of / . ; < >, or (c) the identifier is used as a part or all of the bytecode name of a field, and it contains any of / . ;. Note that close bracket ] will always pass through; it is included in these rules simply for symmetry with open bracket [. class #"java/io" { } // must be rejected class #"java\/io" { } // must be rejected (perhaps in an assembly phase) class #"" { } // must be rejected class #"\" { } // legal (but probably a bad idea) void f() { int #"¥" = '\u00A5'; } // must be rejected void f() { int #"¥\;" = '\u00A5'; } // legal (but probably a bad idea) class #"]" { int #"]"; void #"]"() {} } // must be rejected class #"\]" { int #"\]"; void #"\]"() {} } // legal (but probably a bad idea) These rules support the need for avoiding dangerous characters as a general rule, while permitting occasional expert use of names known to be legal to the JVM. However, there is no provision for uttering the method names "" or "". Nor may package prefixes ever be encoded within exotic identifiers. 3.6 Any ASCII punctuation character not otherwise affected by these rules may serve as a so-called "exotic escape character". That is, it may be preceded by a backslash; in this case both it and the backslash is collected (as a pair of characters) into the exotic identifier. Specifically, these characters are ! # $ % & ( ) * + , - : = ? @ ^ _ ` { | } ~ and no others. int #"=" = 42; int #"\=" = 99; System.out.println(#"="); // must print 42 not 99 These escapes are passed through to the bytecode level for further use by reflective applications, such as a bootstrap linker for invokedynamic. Such escapes are necessary at the level of bytecode names in order to encode (mangle) the dangerous characters. By sending both the backslash and the exotic escape character through to the bytecode level, we avoid the problem of multiple escaping (as is seen, for example, with regexp packages). Although Java has not worked this way in the past, the need for multiple phases of escaping motivates it here and now. Compare this quoting behavior with that of the Unix shells, which perform delayed escaping for similar reasons: $ echo "test: \$NL = '\12'" test: $NL = '\12' (See http://blogs.sun.com/jrose/entry/symbolic_freedom_in_the_vm for a proposal that manages bytecode-level mangling of exotic names. This proposal is independent of the present specification.) 3.7 Here is the combined grammar for exotic identifiers, starting with a new clause for Identifier (JLS 3.8): Identifier: ... ExoticIdentifier ExoticIdentifier: # " ExoticIdentifierCharacters " ExoticIdentifierCharacters: ExoticIdentifierCharacter ExoticIdentifierCharacters ExoticIdentifierCharacter: StringCharacter but not DangerousCharacter \ DangerousCharacter /* the backslash is elided and the character is collected */ \ ExoticEscapeChar /* both the backslash and the character are collected */ DangerousCharacter: one of / . ; < > [ ] ExoticEscapeChar: one of ! # $ % & ( ) * + , - : = ? @ ^ _ ` { | } ~ 3.8 This construct does not conflict with any other existing or proposed use of the hash character. In particular, if the hash character were to be defined as a new sort of Java operator, it would not conflict with this specification. Even if it were to be a construct which could validly be followed by a normal Java string literal, any ambiguity between the constructs could be resolved in favor of the operator by inserting whitespace between the hash and the opening quote of the string literal. 3.9 Exotic identifiers are occasionally useful for creating dynamically linkable classes or methods whose names are determined by naming scheme external to Java. (They may also be used for occasionally avoiding Java keywords, although a leading underscore will usually do just as well.) They are most crucially useful for forming invokedynamic calls, when the method name must refer to an entity in another language, or must contain structured information relevant to a metaobject protocol. package my.xml.tags; class #"\" { ... } package my.sql.bindings; interface Document { String title(); Text #"abstract"(); int #"class"(); ... } Object mySchemeVector = ...; Object x = InvokeDynamic.#"scheme:vector-ref"(mySchemeVector, 42); COMPILATION: See JSR 292 for the specification of invokedynamic instructions. In brief, they begin with a new opcode, a CONSTANT_NameAndType index, and end with two required zero bytes. Method handle invocation is just an ordinary invokevirtual instruction, whose class is java.dyn.MethodHandle, whose name is invokeExact or invokeGeneric, and whose descriptor signature is completely arbitrary; this requires no special compilation support beyond putting a loophole in the method lookup logic. Exotic identifiers require no compilation support beyond the lexer. (This assumes Unicode-clean symbol tables all the way to the backend.) There must be a final validity check in the class file assembler; this can (and should) be copied from the JVM specification. TESTING: Testing will be done the usual way, via unit tests exercising a broad variety of signatures and name spellings, and by early access customers experimenting with the new facilities. LIBRARY SUPPORT: The JVM-level behavior of the type java.dyn.MethodHandle is defined by JSR 292. Its language integration should be defined by an expert group with language expertise. JSR 292 per se involves extensive libraries for the functionality it defines, but they are not prerequisites to the features specified here. Other than exotic identifiers, the features described here have no impact except when the java.dyn types exist in the compilation environment. REFLECTIVE APIS: The method java.lang.Class.getDeclaredMethod must be special-cased to always succeed for MethodHandle.invokeExact and MethodHandle.invokeGeneric and for InvokeDynamic (any method name), regardless of signature. The JSR 292 JVM has such logic already, but it must be exposed out through the Class API. Only single-result reflection lookups need to be changed. Multiple-method lookups should not produce implicitly defined methods. The javax.lang.model API (which is used internally by javac) does not need specialization, because the implicitly defined methods of MethodHandle and InvokeDynamic do not ever need to mix with other more normal methods. The static (compile-time) model of InvokeDynamic may not present any enclosed elements, while that of MethodHandle must not present any methods named invokeExact or invokeGeneric, other than the generic native definitions mandated above. OTHER CHANGES: Javap needs to disassemble invokedynamic instructions. Javap needs to be robust about unusual identifier spellings. (It already is, mostly.) There may be bugs in some implementations of javac when processing identifiers not previously seen. For example, javac should have Unicode-clean symbol tables all the way to the backend. As another example, some spellings (mis-)used internally, like #""*, could cause bugs in some implementations. For example: import pkg1.*; // may accidentally import only pkg1.#"*", not pkg1.#"+" import pkg2.#"*"; // may accidentally import pkg2.#"+" MIGRATION: The feature is for new code only. These language features, along with the related JVM extensions, will make it possible for dynamic language implementations (a) to continue to be coded in Java, but (b) to avoid the performance and complexity overhead of the Core Reflection API. COMPATIBILITY BREAKING CHANGES: None. All changes are associated with previously unused types and/or syntaxes. EXISTING PROGRAMS: No special interaction. In earlier class files 186, the code point used by invokedynamic, is an illegal opcode, and java.dyn.InvokeDynamic and java.dyn.MethodHandle are previously unused type names. REFERENCES EXISTING BUGS: 6754038: writing libraries in Java for non-Java languages requires method handle invocation 6746458: writing libraries in Java for non-Java languages requires support for exotic identifiers URL FOR PROTOTYPE: General: http://hg.openjdk.java.net/mlvm/mlvm/langtools http://hg.openjdk.java.net/mlvm/mlvm/langtools/file/tip/nb-javac/ Invokedynamic and method handles: http://hg.openjdk.java.net/mlvm/mlvm/langtools/file/tip/meth.txt http://hg.openjdk.java.net/mlvm/mlvm/langtools/file/tip/meth.patch Exotic identifiers: http://hg.openjdk.java.net/mlvm/mlvm/langtools/file/tip/quid.txt http://hg.openjdk.java.net/mlvm/mlvm/langtools/file/tip/quid.patch FAQ (This is not a part of the specification. It captures some reviewer comments and responses.) Q: Why is this proposal in multiple parts? (R?mi Forax) A: There are three separable aspects to dynamic language support. The first is simply forming the new kind of dynamic invocation from Java code, while the second is the closely aligned need to form invocations on the composable units of dynamic invocation behavior (method handles). The third aspect is the need to use and define names which are native to languages other than Java. Thesepurposes overlap and synergize in the formation of invokedynamic instructions, because these are likely to use the method name to transmit critical information to the runtime linkage software (typically a metaobject protocol), and because the user code which handles invokedynamic calls is likely to form direct (non-dynamically linked) calls to method handles. Q: Where did the the interface Dynamic go? An earlier version of this proposal contained a dynamic wildcard type (interface Dynamic) also useful for composing dynamic invocation sites. This has been moved into its own separate proposal. Q: Why is null being inferred as Null instead the compiler raising an error? Let the user cast it to Object, etc. (R?mi Forax) A: I went back and forth on this point while I was working with the code. At first (a) null was implicitly Object, then (b) it caused an error (as you suggest), then (c) it used a marker type Void. The most correct thing is (d) to use Neal Gafter's marker type Null, so this spec. will interoperate with that type, when it is added. Staying with case (b) ruins the use-case of simulating Java call sites, since null is fundamentally different from any other type; therefore it needs to be reified somehow. Q: Why didn't you choose to allow catching checked exceptions from InvokeDynamic method calls? (Josh Suereth) A: That's a very good point. In fact, invokedynamic (like any other invoke instruction) can throw any kind of exception at the JVM level. Since at the Java level it is untyped and therefore not statically checked, it must be possible, though not required, to catch checked exceptions. (Incorporated above in 1.5 and 2.5.) Q: Why didn't you pick a better syntax for exotic identifiers? A: This question has many variants, because for different questioners "better" might mean more standard or prettier or less confusing or more concise or similar to another language the questioner admires. But the various questions all have one answer. The key requirement is to push some required bytecode name through the Java language, even though it is not a valid Java identifier. Such bytecode names, though perfectly valid in the JVM, are (by definition) second-class citizens in the Java language. It is would therefore be a blunder to express them with any syntax which might be more useful for other purposes. This anti-goal trumps the goal of making exotic identifers look elegant, standard, or non-confusing. After all, the identifier itself is likely to contain highly inelegant, non-standard, and confusing-looking characters. Therefore, we use three characters #"" to set apart the exotic bytecode name, instead of one or two, so that exotic identifiers are clearly distinguished from other constructs. Groovy and Scala have syntaxes for exotic identifiers which using a pair of quotes (of some kind), and this could be made to work for Java also, but the result would be a needless elegance in the appearance of the exotic identifiers, at the cost of greater lexical ambiguity, or (for backquote) the consumption of a character better used for other purposes. We choose characters which are already in use (double quotes) or likely to be in use soon (hash for closures). We do not attempt to choose some character which we hope nobody is using (backquote, backslash). Such "unused" characters, precisely because they are unused by Java, are sometimes useful for combining Java fragments with other languages, or making experimental extensions to Java. An infrequently used feature like exotic identifiers should not consume such a character. The supposed confusion of hash with its use by closures is a non-issue in practice. Given the limited number of characters in the ASCII set, programmers are not disturbed by seeing one character used in several ways in a language, as long as the associated lexical rules keep the uses distinct. (When was the last time you were offended that the Java comment characters are also used for multiply and divide?) In this case, the lexical rule is simple, unambiguous, and easy to perceive by eye or by parser: Hash with a quote is an exotic identifier, while hash with something else is something else. From john.r.rose at oracle.com Thu Apr 22 18:13:11 2010 From: john.r.rose at oracle.com (John Rose) Date: Thu, 22 Apr 2010 18:13:11 -0700 Subject: JSR 292 support, minor change to specification (John Rose) In-Reply-To: References: Message-ID: Hi Paul. I added some rationale on that subject to the updated document I sent out. See also: http://mail.openjdk.java.net/pipermail/mlvm-dev/2010-April/001676.html I fully expect that no matter what syntax we choose lots of people will hate it. I'm not looking to please people with exotic identifiers, but rather to reserve a character sequence (NOT a single character, mind you) which is highly unlikely to be required elsewhere. #" is such a sequence. Yes, there are many other such sequences, but we have to choose one. I'm sorry to disappoint anyone that has passionate syntactic sensibilities on this, but please: Let's exercise our creativity on deeper issues. -- John On Apr 22, 2010, at 2:32 PM, Paul Benedict wrote: > John, > > Has anymore thought gone into changing the syntax of the exotic > identifier? It was once brought up a few months ago. I think using > back ticks would be more appropriate than the pound sign + apostrophe > -- especially if the # becomes a method handle. > > Paul > From brucechapman at paradise.net.nz Fri Apr 23 02:25:16 2010 From: brucechapman at paradise.net.nz (Bruce Chapman) Date: Fri, 23 Apr 2010 21:25:16 +1200 Subject: JSR 292 support, minor change to specification In-Reply-To: <7B0E5BA5-7543-4BF7-9D3A-8BD262D3DDDB@oracle.com> References: <7B0E5BA5-7543-4BF7-9D3A-8BD262D3DDDB@oracle.com> Message-ID: <4BD1677C.4000202@paradise.net.nz> Minor typo in the spec at http://wikis.sun.com/display/mlvm/InterfaceDynamic " to make it easy to with with these JVM features" maybe the first "with" should be "work" or maybe something else? Bruce From Ulf.Zibis at gmx.de Mon Apr 26 09:26:53 2010 From: Ulf.Zibis at gmx.de (Ulf Zibis) Date: Mon, 26 Apr 2010 18:26:53 +0200 Subject: Proposal: Collection Literals - prehash at compile time In-Reply-To: <17b2302a0903301630w70b9283at4e8f54d1db9c6d57@mail.gmail.com> References: <17b2302a0903301630w70b9283at4e8f54d1db9c6d57@mail.gmail.com> Message-ID: <4BD5BECD.60503@gmx.de> Hi, I'm not sure, if collection literals are now accepted for J7, but if, I like to share an implementation idea. In the code base there is sun.util.PreHashMap. Why not initialize literally defined collections at compile time? -Ulf