From neal at gafter.com Thu Jun 10 10:06:33 2010 From: neal at gafter.com (Neal Gafter) Date: Thu, 10 Jun 2010 10:06:33 -0700 Subject: Project Coin: Inducing contributory heap pollution Message-ID: Re: http://blogs.sun.com/darcy/entry/projectcoin_inducing_contributory_pollution I thought technical documents for project Coin were supposed to be published here? A nit: the @Inherited annotation "has no effect if [...] used to annotate anything other than a class", and so can't be used for the purpose described. Inheriting the diagnostic-suppression annotation would be a great way to induce contributory heap pollution. All you have to do is extend a class with a warning-suppressed varargs method, providing an unsafe overriding implementation, and voila! Heap pollution without a warning. From joe.darcy at oracle.com Thu Jun 10 10:15:10 2010 From: joe.darcy at oracle.com (Joe Darcy) Date: Thu, 10 Jun 2010 10:15:10 -0700 Subject: Project Coin: Inducing contributory heap pollution In-Reply-To: References: Message-ID: <4C111D9E.4020709@oracle.com> Neal Gafter wrote: > Re: http://blogs.sun.com/darcy/entry/projectcoin_inducing_contributory_pollution > > I thought technical documents for project Coin were supposed to be > published here? > I was planning to post on the list later today. > A nit: the @Inherited annotation "has no effect if [...] used to > annotate anything other than a class", and so can't be used for the > purpose described. > Yes, that is a complication. > Inheriting the diagnostic-suppression annotation would be a great way > to induce contributory heap pollution. All you have to do is extend a > class with a warning-suppressed varargs method, providing an unsafe > overriding implementation, and voila! Heap pollution without a > warning. > I was thinking that the spec for the annotation would allow compilers to issue errors if they could prove bad things actually happen in an implementation of a so annotated method. -Joe From forax at univ-mlv.fr Thu Jun 10 10:50:50 2010 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Thu, 10 Jun 2010 19:50:50 +0200 Subject: Project Coin: Inducing contributory heap pollution In-Reply-To: References: Message-ID: <4C1125FA.3020003@univ-mlv.fr> Le 10/06/2010 19:06, Neal Gafter a ?crit : > Re: http://blogs.sun.com/darcy/entry/projectcoin_inducing_contributory_pollution > > I thought technical documents for project Coin were supposed to be > published here? > > A nit: the @Inherited annotation "has no effect if [...] used to > annotate anything other than a class", and so can't be used for the > purpose described. > I have never understood why ? > Inheriting the diagnostic-suppression annotation would be a great way > to induce contributory heap pollution. All you have to do is extend a > class with a warning-suppressed varargs method, providing an unsafe > overriding implementation, and voila! Heap pollution without a > warning. > > I think that the idea is to say, if an implementation is tagged as safe, all methods that override this implementation must be safe. If you guarantee that and if @SuppressWarnings("varargs") is a runtime annotation (visible or invisible) then you can avoid to warn at all call sites of the method. R?mi From neal at gafter.com Thu Jun 10 10:51:15 2010 From: neal at gafter.com (Neal Gafter) Date: Thu, 10 Jun 2010 10:51:15 -0700 Subject: Project Coin: Inducing contributory heap pollution In-Reply-To: <4C111D9E.4020709@oracle.com> References: <4C111D9E.4020709@oracle.com> Message-ID: On Thu, Jun 10, 2010 at 10:15 AM, Joe Darcy wrote: > > Inheriting the diagnostic-suppression annotation would be a great way >> to induce contributory heap pollution. All you have to do is extend a >> class with a warning-suppressed varargs method, providing an unsafe >> overriding implementation, and voila! Heap pollution without a >> warning. >> >> > > I was thinking that the spec for the annotation would allow compilers to > issue errors if they could prove bad things actually happen in an > implementation of a so annotated method. > That's conservative in the wrong direction. Allowing errors [sic; warnings] isn't good enough. You have to require them when there's any possibility of heap pollution. In other words, you'd have to require the diagnostic unless the compiler can prove that bad things won't happen. For code portability, you'd have to specify what "the compiler can prove" means, precisely. And if we could do that, then we wouldn't need any of these annotations in the first place. "If I could walk that way I would not need talcum powder!" -Neal From neal at gafter.com Thu Jun 10 10:54:25 2010 From: neal at gafter.com (Neal Gafter) Date: Thu, 10 Jun 2010 10:54:25 -0700 Subject: Project Coin: Inducing contributory heap pollution In-Reply-To: <4C1125FA.3020003@univ-mlv.fr> References: <4C1125FA.3020003@univ-mlv.fr> Message-ID: On Thu, Jun 10, 2010 at 10:50 AM, R?mi Forax wrote: > Le 10/06/2010 19:06, Neal Gafter a ?crit : > > Re: > http://blogs.sun.com/darcy/entry/projectcoin_inducing_contributory_pollution > > > > I thought technical documents for project Coin were supposed to be > > published here? > > > > A nit: the @Inherited annotation "has no effect if [...] used to > > annotate anything other than a class", and so can't be used for the > > purpose described. > > > > I have never understood why ? > What if a method overrides more than one method, and one is annotated @InheritedAnnotation("Foo") and the other @InheritedAnnotation("Bar")? > > Inheriting the diagnostic-suppression annotation would be a great way > > to induce contributory heap pollution. All you have to do is extend a > > class with a warning-suppressed varargs method, providing an unsafe > > overriding implementation, and voila! Heap pollution without a > > warning. > > > > > > I think that the idea is to say, if an implementation is tagged as safe, > all methods that override this implementation must be safe. > Yes, they should be, but they might not be. > If you guarantee that ... > How? From forax at univ-mlv.fr Thu Jun 10 11:08:04 2010 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Thu, 10 Jun 2010 20:08:04 +0200 Subject: Project Coin: Inducing contributory heap pollution In-Reply-To: References: <4C1125FA.3020003@univ-mlv.fr> Message-ID: <4C112A04.7040906@univ-mlv.fr> Le 10/06/2010 19:54, Neal Gafter a ?crit : > On Thu, Jun 10, 2010 at 10:50 AM, R?mi Forax > wrote: > > Le 10/06/2010 19:06, Neal Gafter a ?crit : > > Re: > http://blogs.sun.com/darcy/entry/projectcoin_inducing_contributory_pollution > > > > I thought technical documents for project Coin were supposed to be > > published here? > > > > A nit: the @Inherited annotation "has no effect if [...] used to > > annotate anything other than a class", and so can't be used for the > > purpose described. > > > > I have never understood why ? > > > What if a method overrides more than one method, and one is annotated > @InheritedAnnotation("Foo") and the other @InheritedAnnotation("Bar")? why not @InheritedAnnotation("FooBar") :) More seriously, it should not compile. It's like trying to override a method but with the wrong visibility modifier. > > Inheriting the diagnostic-suppression annotation would be a > great way > > to induce contributory heap pollution. All you have to do is > extend a > > class with a warning-suppressed varargs method, providing an unsafe > > overriding implementation, and voila! Heap pollution without a > > warning. > > > > > > I think that the idea is to say, if an implementation is tagged as > safe, > all methods that override this implementation must be safe. > > > Yes, they should be, but they might not be. > > If you guarantee that ... > > > How? Me because I will use an annotation saying that explicitly. The idea is if you tag a method with @SuppressWarnings("unsafe") all methods that override that method must also be tagged with this annotation. If you don't guarantee that it will not compile. R?mi From neal at gafter.com Thu Jun 10 11:21:26 2010 From: neal at gafter.com (Neal Gafter) Date: Thu, 10 Jun 2010 11:21:26 -0700 Subject: Project Coin: Inducing contributory heap pollution In-Reply-To: <4C112A04.7040906@univ-mlv.fr> References: <4C1125FA.3020003@univ-mlv.fr> <4C112A04.7040906@univ-mlv.fr> Message-ID: On Thu, Jun 10, 2010 at 11:08 AM, R?mi Forax wrote: > Le 10/06/2010 19:54, Neal Gafter a ?crit : > > What if a method overrides more than one method, and one is annotated > @InheritedAnnotation("Foo") and the other @InheritedAnnotation("Bar")? > > > why not @InheritedAnnotation("FooBar") :) > More seriously, it should not compile. > It's like trying to override a method but with the wrong visibility > modifier. > So we have a whole new set of ways of breaking source compatibility... like adding @SuppressWarnings("safe") to a varargs method (it might end up being the second one overridden in some subclass). > > > >> > Inheriting the diagnostic-suppression annotation would be a great way >> > to induce contributory heap pollution. All you have to do is extend a >> > class with a warning-suppressed varargs method, providing an unsafe >> > overriding implementation, and voila! Heap pollution without a >> > warning. >> > >> > >> >> I think that the idea is to say, if an implementation is tagged as safe, >> all methods that override this implementation must be safe. >> > > Yes, they should be, but they might not be. > > >> If you guarantee that ... >> > > How? > > > Me because I will use an annotation saying that explicitly. > The idea is if you tag a method with @SuppressWarnings("unsafe") > all methods that override that method must also be tagged with this > annotation. > If you don't guarantee that it will not compile. > Then you don't need it to be inherited. From reinier at zwitserloot.com Thu Jun 10 11:47:03 2010 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Thu, 10 Jun 2010 20:47:03 +0200 Subject: Project Coin: Inducing contributory heap pollution In-Reply-To: <4C111D9E.4020709@oracle.com> References: <4C111D9E.4020709@oracle.com> Message-ID: As I've mentioned before in regards to this topic, there's a list of things you can do to a potentially polluted array that are perfectly safe (or at least as safe as anything else with generics is): 1. ask for its length: param.length 2. iterate over it in a foreach: for (Whatever x : param) { ... } 3. read (not write) a value from it: Whatever x = param[whatever]; 4. use it as parameter to another method where that parameter is also marked as "polluted array safe" - e.g. @SuppressWarnings("varargs"). For example, if Arrays.asList() is given the marker (which it should, nothing bad happens), then calling Arrays.asList(param) can't result in bad things either. I posit that less than 1 in 50 uses of varargs out in the wild today stray from this list. Instead of having @SuppressWarnings("varargs"), imagine we have @VarargsSafe instead. The compiler can then implicitly add a @VarargsSafe annotation to any varargs-accepting method if it detects that the varargs variable is only used in ways listed in the list above, and generate a warning when compiling a varargs method that strays from the list. There's a bit of a risk here in that "@VarargsSafe" is technically part of the public API and thus shouldn't be removed in a later version, but that might nevertheless happen "silently" by introducing an operation on the variable that isn't in the list. However, heap pollution can also occur in mixed class files situations (mixing class files produced in different compile runs), interacting with class files produced by compilers other than javac (e.g. jython), and in general it would seem to be acceptable to introduce unwarned heap pollution if the odds of it actually being a problem are spectacularly low, which it would be for this. The notion that this is part of public API also highlights what Remi mentioned: Any overloading of a @VarargsSafe method must deal with the fact that his array's runtime component type is unreliable, because callers are relying on it not being a problem. It is perhaps prudent to remember that the current situation isn't actually avoiding any of the problems that rule 4.12.2.1 is meant to avoid. It follows the letter but not the spirit of that rule. Those folks that run into this warning can do absolutely nothing about it. In other words, if the conclusion is that nothing we do ends up fully following both the letter and the spirit of rule 4.12.2.1, then something that follows the spirit and 99% of the letter is a lot better than the status quo. --Reinier Zwitserloot On Thu, Jun 10, 2010 at 7:15 PM, Joe Darcy wrote: > Neal Gafter wrote: > > Re: > http://blogs.sun.com/darcy/entry/projectcoin_inducing_contributory_pollution > > > > I thought technical documents for project Coin were supposed to be > > published here? > > > > I was planning to post on the list later today. > > > A nit: the @Inherited annotation "has no effect if [...] used to > > annotate anything other than a class", and so can't be used for the > > purpose described. > > > > Yes, that is a complication. > > > Inheriting the diagnostic-suppression annotation would be a great way > > to induce contributory heap pollution. All you have to do is extend a > > class with a warning-suppressed varargs method, providing an unsafe > > overriding implementation, and voila! Heap pollution without a > > warning. > > > > I was thinking that the spec for the annotation would allow compilers to > issue errors if they could prove bad things actually happen in an > implementation of a so annotated method. > > -Joe > > From joe.darcy at oracle.com Thu Jun 10 13:04:28 2010 From: joe.darcy at oracle.com (Joe Darcy) Date: Thu, 10 Jun 2010 13:04:28 -0700 Subject: Project Coin: Inducing contributory heap pollution In-Reply-To: <4C112A04.7040906@univ-mlv.fr> References: <4C1125FA.3020003@univ-mlv.fr> <4C112A04.7040906@univ-mlv.fr> Message-ID: <4C11454C.1020004@oracle.com> R?mi Forax wrote: > Le 10/06/2010 19:54, Neal Gafter a ?crit : > >> On Thu, Jun 10, 2010 at 10:50 AM, R?mi Forax > > wrote: >> >> Le 10/06/2010 19:06, Neal Gafter a ?crit : >> > Re: >> http://blogs.sun.com/darcy/entry/projectcoin_inducing_contributory_pollution >> > >> > I thought technical documents for project Coin were supposed to be >> > published here? >> > >> > A nit: the @Inherited annotation "has no effect if [...] used to >> > annotate anything other than a class", and so can't be used for the >> > purpose described. >> > >> >> I have never understood why ? >> >> >> What if a method overrides more than one method, and one is annotated >> @InheritedAnnotation("Foo") and the other @InheritedAnnotation("Bar")? >> > > why not @InheritedAnnotation("FooBar") :) > More seriously, it should not compile. > It's like trying to override a method but with the wrong visibility > modifier. > > The topic of annotation inheritance was discussed at length in the JSR 175 expert group and some of the rational for the design decisions are included in the documentation of the JRS's intermediary drafts. As Neal has alluded to, the main reason was to avoid having to define semantics for cases like diamond "inheritance" of methods through interfaces. -Joe From joe.darcy at oracle.com Thu Jun 10 19:45:42 2010 From: joe.darcy at oracle.com (Joe Darcy) Date: Thu, 10 Jun 2010 19:45:42 -0700 Subject: Project Coin: Inducing contributory heap pollution In-Reply-To: References: <4C111D9E.4020709@oracle.com> Message-ID: <4C11A356.1020803@oracle.com> Neal Gafter wrote: > On Thu, Jun 10, 2010 at 10:15 AM, Joe Darcy > wrote: > > Inheriting the diagnostic-suppression annotation would be a > great way > to induce contributory heap pollution. All you have to do is > extend a > class with a warning-suppressed varargs method, providing an > unsafe > overriding implementation, and voila! Heap pollution without a > warning. > > > > I was thinking that the spec for the annotation would allow > compilers to issue errors if they could prove bad things actually > happen in an implementation of a so annotated method. > > > That's conservative in the wrong direction. Yes, I understand that such a proposal would not be sound with respect to heap pollution. > Allowing errors [sic; warnings] isn't good enough. You have to > require them when there's any possibility of heap pollution. Unless the heap pollution contract is changed. (There is already a small hole in the contract due to a few core reflection methods with signatures like "public TypeVariable>[] java.lang.reflect.Constructor.getTypeParameters()".) The checked exception analysis is another analysis with a contract with a few holes; "Java Puzzlers" -- Puzzle 43 "Exceptionally Unsafe" gives two examples. Recent discussion on lambda-dev give a few more. > In other words, you'd have to require the diagnostic unless the > compiler can prove that bad things won't happen. For code > portability, you'd have to specify what "the compiler can prove" > means, precisely. And if we could do that, then we wouldn't need any > of these annotations in the first place. It is technically feasible to define another dataflow-style analysis that would recognize a (hopefully useful) subset of the "definitely safe" uses of arrays from varargs, as Reinier as started sketching out. Similarly, a "definitely unsafe" analysis could be defined too. Here is a strawman version of the new annotation type, name for discussion purposes only: @Documented // Part of the method's public contract @Target(ElementType.METHOD) // Only meaningful on methods & constructors @Retention(RetentionPolicy.RUNTIME) // Could get away with SOURCE, but might want runtime checking public @interface TrustMeOnVarargs {} Since the annotation type is only usable on methods and not classes, annotation inheritance is not applicable since only annotations on classes can be inherited. (So my blog post was incorrect to call for an @Inherited annotation on a method; when writing the entry I had forgotten about the class inheritance only restriction.) The lack of inheritance might not be much of an issue in practice if most of the methods that would be useful to annotate are static methods or constructors. -Joe From joe.darcy at oracle.com Thu Jun 10 19:50:23 2010 From: joe.darcy at oracle.com (Joe Darcy) Date: Thu, 10 Jun 2010 19:50:23 -0700 Subject: Project Coin: Inducing contributory heap pollution In-Reply-To: References: <4C111D9E.4020709@oracle.com> Message-ID: <4C11A46F.7040001@oracle.com> Reinier Zwitserloot wrote: > As I've mentioned before in regards to this topic, there's a list of > things you can do to a potentially polluted array that are perfectly > safe (or at least as safe as anything else with generics is): > > 1. ask for its length: param.length > 2. iterate over it in a foreach: for (Whatever x : param) { ... } > 3. read (not write) a value from it: Whatever x = param[whatever]; > 4. use it as parameter to another method where that parameter is also > marked as "polluted array safe" - e.g. @SuppressWarnings("varargs"). > For example, if Arrays.asList() is given the marker (which it should, > nothing bad happens), then calling Arrays.asList(param) can't result > in bad things either. Just noting that given the defined semantics of the for-each loop on an array, point 2 would be implied by points 1 and 3; although it is good to call out separately. A good start at validating such rules is looking at the implementations of the JDK methods where the TrustMeOnVarargs annotation would be helpful; iterating over the elements in a for-each loop and passing the array along as a method parameter are the operations that occur in the three methods. -Joe From joe.darcy at oracle.com Wed Jun 23 17:08:44 2010 From: joe.darcy at oracle.com (Joe Darcy) Date: Wed, 23 Jun 2010 17:08:44 -0700 Subject: ARM API Support Message-ID: <4C22A20C.3080106@oracle.com> Greetings The initial API changes to support the Project Coin feature automatic resource management (ARM) blocks have been pushed into JDK 7 [1] and will appear in subsequent builds. The corresponding compiler changes to support the actual language feature remain in progress. The initial API work to support ARM was divided into two pieces, essential API support and retrofitting platform classes. The essential support includes: * A new interface java.lang.AutoCloseable which defines a single method void close() throws Exception * A new enum constant in the language model: javax.lang.model.element.ElementKind.RESOURCE_VARIABLE * Methods on java.lang.Throwable to add and retrieve information about suppressed exceptions, including printing out suppressed exceptions in stack traces. The retrofitting includes: * Having java.io.Closeable extend java.lang.AutoCloseable. (From a typing perspective, a subtype of AutoCloseable can be declared to throw fewer exceptions than the supertype. Therefore is is fine for the close method in AutoCloseable to throw Exception and the close method in Closeable to throw the more specific IOException. It would even be fine for the close method in a subtype of AutoCloseable to be declared to throw no exceptions at all.) * Adding a close method to java.nio.channels.FileLock and having FileLock implement AutoCloseable. * Adding Closeable as an interface implemented by javax.imageio.stream.ImageInputStream. Other platform classes may be retrofitted to implement AutoCloseable or Closable in future builds. Compared to the API support in earlier versions of the ARM proposal, the top-level interface to mark participation in ARM is in package java.lang rather than its own package and, after consultation with the JDBC and graphics teams, neither java.sql.* nor java.awt.Graphics were retrofitted for ARM. -Joe [1] http://hg.openjdk.java.net/jdk7/tl/jdk/rev/c4d60bcce958 http://hg.openjdk.java.net/jdk7/tl/langtools/rev/be5cafeb318d From neal at gafter.com Wed Jun 23 17:17:57 2010 From: neal at gafter.com (Neal Gafter) Date: Wed, 23 Jun 2010 17:17:57 -0700 Subject: ARM API Support In-Reply-To: <4C22A20C.3080106@oracle.com> References: <4C22A20C.3080106@oracle.com> Message-ID: Do you have any explanation for the Graphics and AWT teams' decisions not to retrofit for ARM? Several changes from project lambda (notably defender methods and exception transparency) could be taken advantage of to provide a much more flexible ARM construct (e.g., that supports the whole spectrum of identified resource APIs). This falls into the general category of adapting the specifications based on unexpected interactions between separately developed features. How and when do you expect investigation of this to be occur? Cheers, Neal On Wed, Jun 23, 2010 at 5:08 PM, Joe Darcy wrote: > Greetings > > The initial API changes to support the Project Coin feature automatic > resource management (ARM) blocks have been pushed into JDK 7 [1] and > will appear in subsequent builds. The corresponding compiler changes to > support the actual language feature remain in progress. > > The initial API work to support ARM was divided into two pieces, > essential API support and retrofitting platform classes. The essential > support includes: > > * A new interface java.lang.AutoCloseable which defines a single method > ?void close() throws Exception > > * A new enum constant in the language model: > ?javax.lang.model.element.ElementKind.RESOURCE_VARIABLE > > * Methods on java.lang.Throwable to add and retrieve information about > suppressed exceptions, including printing out suppressed exceptions in > stack traces. > > The retrofitting includes: > > * Having java.io.Closeable extend java.lang.AutoCloseable. (From a > typing perspective, a subtype of AutoCloseable can be declared to throw > fewer exceptions than the supertype. Therefore is is fine for the close > method in AutoCloseable to throw Exception and the close method in > Closeable to throw the more specific IOException. It would even be fine > for the close method in a subtype of AutoCloseable to be declared to > throw no exceptions at all.) > > * Adding a close method to java.nio.channels.FileLock and having > FileLock implement AutoCloseable. > > * Adding Closeable as an interface implemented by > javax.imageio.stream.ImageInputStream. > > Other platform classes may be retrofitted to implement AutoCloseable or > Closable in future builds. > > Compared to the API support in earlier versions of the ARM proposal, the > top-level interface to mark participation in ARM is in package java.lang > rather than its own package and, after consultation with the JDBC and > graphics teams, neither java.sql.* nor java.awt.Graphics were > retrofitted for ARM. > > -Joe > > [1] http://hg.openjdk.java.net/jdk7/tl/jdk/rev/c4d60bcce958 > ? ?http://hg.openjdk.java.net/jdk7/tl/langtools/rev/be5cafeb318d > > > From joe.darcy at oracle.com Wed Jun 23 17:36:48 2010 From: joe.darcy at oracle.com (Joe Darcy) Date: Wed, 23 Jun 2010 17:36:48 -0700 Subject: ARM API Support In-Reply-To: References: <4C22A20C.3080106@oracle.com> Message-ID: <4C22A8A0.7000709@oracle.com> Neal Gafter wrote: > Do you have any explanation for the Graphics and AWT teams' decisions > not to retrofit for ARM? > There were compatabilty concerns with adding a close method to those classes and from an implementation perspective the existing "dispose" method has not been needed to be called to free resources since 1.2. -Joe From tronicek at fit.cvut.cz Wed Jun 23 23:11:17 2010 From: tronicek at fit.cvut.cz (=?utf-8?B?IlpkZW7Em2sgVHJvbsOtxI1layI=?=) Date: Thu, 24 Jun 2010 08:11:17 +0200 Subject: ARM API Support In-Reply-To: <4C22A8A0.7000709@oracle.com> References: <4C22A20C.3080106@oracle.com> <4C22A8A0.7000709@oracle.com> Message-ID: Really? When a window which you did not call dispose() on is deallocated? As far as I know, this is a memory leak: static void showWindow() { JFrame f = new JFrame("test"); f.setSize(100, 100); f.setVisible(true); ... // no f.dispose() here f.setVisible(false); } Z. -- Zdenek Tronicek FIT CTU in Prague http://kenai.com/projects/refactoringng - the refactoring tool for compiler guys Joe Darcy napsal(a): > Neal Gafter wrote: >> Do you have any explanation for the Graphics and AWT teams' decisions >> not to retrofit for ARM? >> > > There were compatabilty concerns with adding a close method to those > classes and from an implementation perspective the existing "dispose" > method has not been needed to be called to free resources since 1.2. > > -Joe > > > From tom.hawtin at oracle.com Thu Jun 24 03:08:37 2010 From: tom.hawtin at oracle.com (tom.hawtin at oracle.com) Date: Thu, 24 Jun 2010 11:08:37 +0100 Subject: ARM API Support In-Reply-To: <4C22A8A0.7000709@oracle.com> References: <4C22A20C.3080106@oracle.com> <4C22A8A0.7000709@oracle.com> Message-ID: <4C232EA5.3090103@oracle.com> On 24/06/2010 01:36, Joe Darcy wrote: > Neal Gafter wrote: >> Do you have any explanation for the Graphics and AWT teams' decisions >> not to retrofit for ARM? >> > > There were compatabilty concerns with adding a close method to those > classes and from an implementation perspective the existing "dispose" > method has not been needed to be called to free resources since 1.2. Will the documentation be changed from: "For efficiency, programmers should call dispose when finished using a Graphics object only if it was created directly from a component or another Graphics object." Zden?k Tron??ek's example needs to be changed to use modal dialogs to make sense (Swing vs EDT), but I don't think modal dialogs are something to be encouraged. Tom From tronicek at fit.cvut.cz Thu Jun 24 04:04:36 2010 From: tronicek at fit.cvut.cz (=?utf-8?B?IlpkZW7Em2sgVHJvbsOtxI1layI=?=) Date: Thu, 24 Jun 2010 13:04:36 +0200 Subject: ARM API Support In-Reply-To: <4C232EA5.3090103@oracle.com> References: <4C22A20C.3080106@oracle.com> <4C22A8A0.7000709@oracle.com> <4C232EA5.3090103@oracle.com> Message-ID: <1ec9ceb391279829b12c4e217a8225d3.squirrel@imap.fit.cvut.cz> We do not discuss here how to use Swing properly. This discussion is about whether you have to call dispose() or not. So, I do not understand your arguments. Z. -- Zdenek Tronicek FIT CTU in Prague http://kenai.com/projects/refactoringng - the refactoring tool for compiler guys tom.hawtin at oracle.com napsal(a): > On 24/06/2010 01:36, Joe Darcy wrote: >> Neal Gafter wrote: >>> Do you have any explanation for the Graphics and AWT teams' decisions >>> not to retrofit for ARM? >>> >> >> There were compatabilty concerns with adding a close method to those >> classes and from an implementation perspective the existing "dispose" >> method has not been needed to be called to free resources since 1.2. > > Will the documentation be changed from: > > "For efficiency, programmers should call dispose when finished using > a Graphics object only if it was created directly from a component or > another Graphics object." > > Zden?k Tron??ek's example needs to be changed to use modal dialogs to > make sense (Swing vs EDT), but I don't think modal dialogs are something > to be encouraged. > > Tom > > From forax at univ-mlv.fr Thu Jun 24 07:42:50 2010 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Thu, 24 Jun 2010 16:42:50 +0200 Subject: ARM API Support In-Reply-To: <4C22A20C.3080106@oracle.com> References: <4C22A20C.3080106@oracle.com> Message-ID: <4C236EEA.1090808@univ-mlv.fr> Le 24/06/2010 02:08, Joe Darcy a ?crit : > Greetings > > The initial API changes to support the Project Coin feature automatic > resource management (ARM) blocks have been pushed into JDK 7 [1] and > will appear in subsequent builds. The corresponding compiler changes to > support the actual language feature remain in progress. > > The initial API work to support ARM was divided into two pieces, > essential API support and retrofitting platform classes. The essential > support includes: > > * A new interface java.lang.AutoCloseable which defines a single method > void close() throws Exception > > * A new enum constant in the language model: > javax.lang.model.element.ElementKind.RESOURCE_VARIABLE > > * Methods on java.lang.Throwable to add and retrieve information about > suppressed exceptions, including printing out suppressed exceptions in > stack traces. > > The retrofitting includes: > > * Having java.io.Closeable extend java.lang.AutoCloseable. (From a > typing perspective, a subtype of AutoCloseable can be declared to throw > fewer exceptions than the supertype. Therefore is is fine for the close > method in AutoCloseable to throw Exception and the close method in > Closeable to throw the more specific IOException. It would even be fine > for the close method in a subtype of AutoCloseable to be declared to > throw no exceptions at all.) > > * Adding a close method to java.nio.channels.FileLock and having > FileLock implement AutoCloseable. > > * Adding Closeable as an interface implemented by > javax.imageio.stream.ImageInputStream. > > Other platform classes may be retrofitted to implement AutoCloseable or > Closable in future builds. > > Compared to the API support in earlier versions of the ARM proposal, the > top-level interface to mark participation in ARM is in package java.lang > rather than its own package and, after consultation with the JDBC and > graphics teams, neither java.sql.* nor java.awt.Graphics were > retrofitted for ARM. > > -Joe > > [1] http://hg.openjdk.java.net/jdk7/tl/jdk/rev/c4d60bcce958 > http://hg.openjdk.java.net/jdk7/tl/langtools/rev/be5cafeb318d > There is a bug in printStackTrace(PrintStreamOrWriter) Set dejaVu = new HashSet(); should be: Set dejaVu = Collections.newSetFromMap( new IdentityHashMap()); The current code doesn't work as expected if an exception overrides Throwable.equals. R?mi From joe.darcy at oracle.com Thu Jun 24 07:57:39 2010 From: joe.darcy at oracle.com (Joe Darcy) Date: Thu, 24 Jun 2010 07:57:39 -0700 Subject: ARM API Support In-Reply-To: <4C236EEA.1090808@univ-mlv.fr> References: <4C22A20C.3080106@oracle.com> <4C236EEA.1090808@univ-mlv.fr> Message-ID: <4C237263.6000908@oracle.com> R?mi Forax wrote: > Le 24/06/2010 02:08, Joe Darcy a ?crit : > >> Greetings >> >> The initial API changes to support the Project Coin feature automatic >> resource management (ARM) blocks have been pushed into JDK 7 [1] and >> will appear in subsequent builds. The corresponding compiler changes to >> support the actual language feature remain in progress. >> >> The initial API work to support ARM was divided into two pieces, >> essential API support and retrofitting platform classes. The essential >> support includes: >> >> * A new interface java.lang.AutoCloseable which defines a single method >> void close() throws Exception >> >> * A new enum constant in the language model: >> javax.lang.model.element.ElementKind.RESOURCE_VARIABLE >> >> * Methods on java.lang.Throwable to add and retrieve information about >> suppressed exceptions, including printing out suppressed exceptions in >> stack traces. >> >> The retrofitting includes: >> >> * Having java.io.Closeable extend java.lang.AutoCloseable. (From a >> typing perspective, a subtype of AutoCloseable can be declared to throw >> fewer exceptions than the supertype. Therefore is is fine for the close >> method in AutoCloseable to throw Exception and the close method in >> Closeable to throw the more specific IOException. It would even be fine >> for the close method in a subtype of AutoCloseable to be declared to >> throw no exceptions at all.) >> >> * Adding a close method to java.nio.channels.FileLock and having >> FileLock implement AutoCloseable. >> >> * Adding Closeable as an interface implemented by >> javax.imageio.stream.ImageInputStream. >> >> Other platform classes may be retrofitted to implement AutoCloseable or >> Closable in future builds. >> >> Compared to the API support in earlier versions of the ARM proposal, the >> top-level interface to mark participation in ARM is in package java.lang >> rather than its own package and, after consultation with the JDBC and >> graphics teams, neither java.sql.* nor java.awt.Graphics were >> retrofitted for ARM. >> >> -Joe >> >> [1] http://hg.openjdk.java.net/jdk7/tl/jdk/rev/c4d60bcce958 >> http://hg.openjdk.java.net/jdk7/tl/langtools/rev/be5cafeb318d >> >> > > There is a bug in printStackTrace(PrintStreamOrWriter) > > Set dejaVu = new HashSet(); > should be: > Set dejaVu = Collections.newSetFromMap( > new IdentityHashMap()); > > The current code doesn't work as expected if an exception overrides > Throwable.equals. > Hi R?mi, Thanks for catching this bug. I'll correct that when I next edit the file -- I plan to change the addSuppressedException method to throw an exception if the exception tries to suppress itself. -Joe From pbenedict at apache.org Thu Jun 24 08:15:27 2010 From: pbenedict at apache.org (Paul Benedict) Date: Thu, 24 Jun 2010 10:15:27 -0500 Subject: ARM API Support Message-ID: I would like to ask a philosophical question. What exactly is the philosophical difference between a suppressed exception and a exception's root cause(s)? I see them as near identical. If you can justify why they are actually quite different, are they different enough to call out a distinction? >From a colloquial perspective, I can see someone reasonably explaining that when he caught exception X and wrapped it in exception Y (with root cause of X), he actually "suppressed" the X exception. Paul From neal at gafter.com Thu Jun 24 08:39:17 2010 From: neal at gafter.com (Neal Gafter) Date: Thu, 24 Jun 2010 08:39:17 -0700 Subject: ARM API Support In-Reply-To: References: Message-ID: Suppression occurs due to the constructs of the language (the ARM try), in which an exception propogating out of the implied finally block simply discards (suppresses) any exceptions from the try block without any programmer expression of this intent. Moreover, more than one exceptions can be suppressed. This is completely different from exception causes, which are explicit user expression of intent that one exception was the cause of the other. On Thu, Jun 24, 2010 at 8:15 AM, Paul Benedict wrote: > I would like to ask a philosophical question. What exactly is the > philosophical difference between a suppressed exception and a > exception's root cause(s)? I see them as near identical. If you can > justify why they are actually quite different, are they different > enough to call out a distinction? > > >From a colloquial perspective, I can see someone reasonably explaining > that when he caught exception X and wrapped it in exception Y (with > root cause of X), he actually "suppressed" the X exception. > > Paul > > From pbenedict at apache.org Thu Jun 24 08:48:16 2010 From: pbenedict at apache.org (Paul Benedict) Date: Thu, 24 Jun 2010 10:48:16 -0500 Subject: ARM API Support In-Reply-To: References: Message-ID: I understand the technical difference, but do you see my point that "suppressed" vs. "cause" is a very thin difference? I can use English to actually express both ARM and root causes and be correct -- if not imprecise technically. Conversely, if I catch X and throw Y without setting X as a root cause, I actually suppressed X. I don't have a better word choice for you at this time, but it's something for everyone to think about. On Thu, Jun 24, 2010 at 10:39 AM, Neal Gafter wrote: > Suppression occurs due to the constructs of the language (the ARM try), in > which an exception propogating out of the implied finally block simply > discards (suppresses) any exceptions from the try block without any > programmer expression of this intent.? Moreover, more than one exceptions > can be suppressed.? This is completely different from exception causes, > which are explicit user expression of intent that one exception was the > cause of the other. > > On Thu, Jun 24, 2010 at 8:15 AM, Paul Benedict wrote: >> >> I would like to ask a philosophical question. What exactly is the >> philosophical difference between a suppressed exception and a >> exception's root cause(s)? I see them as near identical. If you can >> justify why they are actually quite different, are they different >> enough to call out a distinction? >> >> >From a colloquial perspective, I can see someone reasonably explaining >> that when he caught exception X and wrapped it in exception Y (with >> root cause of X), he actually "suppressed" the X exception. >> >> Paul >> > > From forax at univ-mlv.fr Thu Jun 24 10:54:59 2010 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Thu, 24 Jun 2010 19:54:59 +0200 Subject: ARM API Support In-Reply-To: <4C237263.6000908@oracle.com> References: <4C22A20C.3080106@oracle.com> <4C236EEA.1090808@univ-mlv.fr> <4C237263.6000908@oracle.com> Message-ID: <4C239BF3.30104@univ-mlv.fr> Le 24/06/2010 16:57, Joe Darcy a ?crit : > R?mi Forax wrote: >> Le 24/06/2010 02:08, Joe Darcy a ?crit : >>> Greetings >>> >>> The initial API changes to support the Project Coin feature automatic >>> resource management (ARM) blocks have been pushed into JDK 7 [1] and >>> will appear in subsequent builds. The corresponding compiler changes to >>> support the actual language feature remain in progress. >>> >>> The initial API work to support ARM was divided into two pieces, >>> essential API support and retrofitting platform classes. The essential >>> support includes: >>> >>> * A new interface java.lang.AutoCloseable which defines a single method >>> void close() throws Exception >>> >>> * A new enum constant in the language model: >>> javax.lang.model.element.ElementKind.RESOURCE_VARIABLE >>> >>> * Methods on java.lang.Throwable to add and retrieve information about >>> suppressed exceptions, including printing out suppressed exceptions in >>> stack traces. >>> >>> The retrofitting includes: >>> >>> * Having java.io.Closeable extend java.lang.AutoCloseable. (From a >>> typing perspective, a subtype of AutoCloseable can be declared to throw >>> fewer exceptions than the supertype. Therefore is is fine for the close >>> method in AutoCloseable to throw Exception and the close method in >>> Closeable to throw the more specific IOException. It would even be fine >>> for the close method in a subtype of AutoCloseable to be declared to >>> throw no exceptions at all.) >>> >>> * Adding a close method to java.nio.channels.FileLock and having >>> FileLock implement AutoCloseable. >>> >>> * Adding Closeable as an interface implemented by >>> javax.imageio.stream.ImageInputStream. >>> >>> Other platform classes may be retrofitted to implement AutoCloseable or >>> Closable in future builds. >>> >>> Compared to the API support in earlier versions of the ARM proposal, >>> the >>> top-level interface to mark participation in ARM is in package >>> java.lang >>> rather than its own package and, after consultation with the JDBC and >>> graphics teams, neither java.sql.* nor java.awt.Graphics were >>> retrofitted for ARM. >>> >>> -Joe >>> >>> [1] http://hg.openjdk.java.net/jdk7/tl/jdk/rev/c4d60bcce958 >>> http://hg.openjdk.java.net/jdk7/tl/langtools/rev/be5cafeb318d >> >> There is a bug in printStackTrace(PrintStreamOrWriter) >> >> Set dejaVu = new HashSet(); >> should be: >> Set dejaVu = Collections.newSetFromMap( >> new IdentityHashMap()); >> >> The current code doesn't work as expected if an exception overrides >> Throwable.equals. > > Hi R?mi, > > Thanks for catching this bug. I'll correct that when I next edit the > file -- I plan to change the addSuppressedException method to throw an > exception if the exception tries to suppress itself. > > -Joe I also think you can get ride of the PrintStream/PrintWriter adapters. Both implements Appendable, and you can synchronize on that appendable. println(s) can be replaced by append(s).append(lineSeparator), the lineSeparator is available with this code: lineSeparator = java.security.AccessController.doPrivileged( new sun.security.action.GetPropertyAction("line.separator")); Perhaps it can be stored in a public static final variable. R?mi From pbenedict at apache.org Thu Jun 24 12:19:33 2010 From: pbenedict at apache.org (Paul Benedict) Date: Thu, 24 Jun 2010 14:19:33 -0500 Subject: ARM API Support In-Reply-To: References: Message-ID: I would like to submit the following addition. I feel the current JavaDoc can benefit from a clearer explanation that differentiates the two. I also would like to credit Patrick Wright for a great offline explanation which helped me craft this. To add at the bottom of the Javadoc: *

Take care to differentiate between the root cause exception and suppressed * exceptions. The root cause is the fundamental reason of the main exception. * Suppressed exceptions have no direct relation, but are captured and ignored * during during post-processing (such as in a {@code finally} block} of the main * exception.

* *

As demonstrated in the above example, the "main" Exception was thrown by * the application, but there were additional problems cleaning up some * automatic resources. These additional exceptions were captured and * suppressed because, although they occurred, they did not contribute to, * cause, or prevent the main exception.

On Thu, Jun 24, 2010 at 10:48 AM, Paul Benedict wrote: > I understand the technical difference, but do you see my point that > "suppressed" vs. "cause" is a very thin difference? I can use English > to actually express both ARM and root causes and be correct -- if not > imprecise technically. Conversely, if I catch X and throw Y without > setting X as a root cause, I actually suppressed X. > > I don't have a better word choice for you at this time, but it's > something for everyone to think about. > > On Thu, Jun 24, 2010 at 10:39 AM, Neal Gafter wrote: >> Suppression occurs due to the constructs of the language (the ARM try), in >> which an exception propogating out of the implied finally block simply >> discards (suppresses) any exceptions from the try block without any >> programmer expression of this intent.? Moreover, more than one exceptions >> can be suppressed.? This is completely different from exception causes, >> which are explicit user expression of intent that one exception was the >> cause of the other. >> From mclark at apache.org Mon Jun 28 16:46:39 2010 From: mclark at apache.org (Mike Clark) Date: Mon, 28 Jun 2010 17:46:39 -0600 Subject: ARM and thread interruption Message-ID: I am little concerned about ARM suppressing java.lang.InterruptedException and thread interruption status. When a thread is interrupted, its interrupt flag is set to true until an InterruptedException can be raised and the interrupt flag reset. It is notable that the interrupt flag is reset after an InterruptedException has been raised, because then the only remaining indication that an interrupt occurred is the presence of the InterruptedException. Now consider that in an ARM block, the InterruptedException may be relegated to a collection of suppressed exceptions. In this case, today's existing code would not notice the InterruptedException and thus may not notice that its thread was interrupted, preventing the thread from taking its interruption code path. Of course this problem of exception priority is present amongst any two exceptions that occur during ARM -- not just InterruptedExceptions. However, because InterruptedException plays a special role in the runtime's threading model, I think perhaps this particular case may be worth considering on its own. Code which must be responsive to interruption might need to introduce a third strategy: upon catching an exception, it could iterate over the suppressed exceptions and search for an exception that is instanceof InterruptedException. If such an exception is present, the code can assume that an interrupt occurred. The problem with this approach is a problem of ownership of the interruption policy of the thread. Before suppressed InterruptedExceptions, we could trust that, in general, a InterruptedException would travel up to code that implemented the thread's interruption policy. Now the InterruptedException may end up in a lower-level catch block, as a suppressed throwable of some other type of exception. And that catch block may not even know to search for the InterruptedException, let alone what to do with it. That catch block may be in code that you do not control. One idea I was thinking about was having ARM blocks re-assert the interrupt status on a thread if the ARM block knows that it suppressed an InterruptedException. This wouldn't stop InterruptedExceptions from sometimes getting relegated to suppressed exceptions, but it would at least give the thread a second chance to assert a new InterruptedException at a later statement. I am not sure exactly what to do about this particular issue. I realize this is all a bit of an edge case, but as someone who has written (and fixed) a lot of thread-interrupt code, it does concern me a little, and I wanted to at least see if anyone else thinks this an issue worth discussing. best regards, Mike From jjb at google.com Mon Jun 28 17:05:14 2010 From: jjb at google.com (Joshua Bloch) Date: Mon, 28 Jun 2010 17:05:14 -0700 Subject: ARM and thread interruption In-Reply-To: References: Message-ID: Mike, This is a very good point! Thanks for bringing it up. I do believe that ARM blocks should "reassert" InterruptedException (via Thread.currentThread().interrupt()) rather than suppressing it. Once pointed out, it seems like a no-brainer to me. I'm strongly in favor of it, and will do my best to make it happen (unless someone comes up with a reason that it isn't a good idea). Thanks again, Josh On Mon, Jun 28, 2010 at 4:46 PM, Mike Clark wrote: > I am little concerned about ARM suppressing > java.lang.InterruptedException and thread interruption status. When > a thread is interrupted, its interrupt flag is set to true until an > InterruptedException can be raised and the interrupt flag reset. It > is notable that the interrupt flag is reset after an > InterruptedException has been raised, because then the only remaining > indication that an interrupt occurred is the presence of the > InterruptedException. Now consider that in an ARM block, the > InterruptedException may be relegated to a collection of suppressed > exceptions. In this case, today's existing code would not notice the > InterruptedException and thus may not notice that its thread was > interrupted, preventing the thread from taking its interruption code > path. > > Of course this problem of exception priority is present amongst any > two exceptions that occur during ARM -- not just > InterruptedExceptions. However, because InterruptedException plays a > special role in the runtime's threading model, I think perhaps this > particular case may be worth considering on its own. > > Code which must be responsive to interruption might need to introduce > a third strategy: upon catching an exception, it could iterate over > the suppressed exceptions and search for an exception that is > instanceof InterruptedException. If such an exception is present, the > code can assume that an interrupt occurred. The problem with this > approach is a problem of ownership of the interruption policy of the > thread. Before suppressed InterruptedExceptions, we could trust that, > in general, a InterruptedException would travel up to code that > implemented the thread's interruption policy. Now the > InterruptedException may end up in a lower-level catch block, as a > suppressed throwable of some other type of exception. And that catch > block may not even know to search for the InterruptedException, let > alone what to do with it. That catch block may be in code that you do > not control. > > One idea I was thinking about was having ARM blocks re-assert the > interrupt status on a thread if the ARM block knows that it suppressed > an InterruptedException. This wouldn't stop InterruptedExceptions > from sometimes getting relegated to suppressed exceptions, but it > would at least give the thread a second chance to assert a new > InterruptedException at a later statement. > > I am not sure exactly what to do about this particular issue. I > realize this is all a bit of an edge case, but as someone who has > written (and fixed) a lot of thread-interrupt code, it does concern me > a little, and I wanted to at least see if anyone else thinks this an > issue worth discussing. > > best regards, > Mike > > From carlos at keysoft.pt Mon Jun 28 18:44:08 2010 From: carlos at keysoft.pt (Carlos Costa e Silva) Date: Tue, 29 Jun 2010 02:44:08 +0100 Subject: ARM and thread interruption In-Reply-To: Message-ID: -----Original Message----- From: Mike Clark [mailto:mclark at apache.org] Sent: ter?a-feira, 29 de Junho de 2010 00:47 To: coin-dev at openjdk.java.net Subject: ARM and thread interruption I am little concerned about ARM suppressing java.lang.InterruptedException ... -------------------------- Hmm, and how is that different from what happens now? try { // wait until interrupted } finally { throw RuntimeException("Oops, InterruptedException thrown away"); } Suppressed exceptions represent a bug in the program (an uncaught exception happened in the finally block) and imho 99% of the time are only useful for debugging/logging (the same as happens to exception causes). In fact adding behavior (this restoring the interrupt flag) to ARM suppression handling is counter-intuitive making ARM blocks behave very different from traditional try/finally blocks where no such handling is done. Or am I missing something here (quite possible :) ? Carlos From mclark at apache.org Mon Jun 28 22:36:46 2010 From: mclark at apache.org (Mike Clark) Date: Mon, 28 Jun 2010 23:36:46 -0600 Subject: ARM and thread interruption In-Reply-To: References: Message-ID: On Mon, Jun 28, 2010 at 7:44 PM, Carlos Costa e Silva wrote: > -----Original Message----- > From: Mike Clark [mailto:mclark at apache.org] > Sent: ter?a-feira, 29 de Junho de 2010 00:47 > To: coin-dev at openjdk.java.net > Subject: ARM and thread interruption > > I am little concerned about ARM suppressing > java.lang.InterruptedException ... > -------------------------- > > Hmm, and how is that different from what happens now? Well, you're right. ?ARM is -- as currently specified -- not too much different with regards to interrupt handling than a naively written try/finally. ? My original phrasing may have made it sound like ARM could cause a problem that doesn't exist today with try/finally. ?This is not true, and I'm sorry if I was misleading. However, I think that -- just like ARM can help us write correct try/finally constructs for resource cleanup -- ARM can also help us write code that correctly and reliably preserves interrupt status on a thread. Your code: > try { > ? ? ? ?// wait until interrupted > } finally { > ? ? ? ?throw RuntimeException("Oops, InterruptedException thrown away"); > } Could be modified in this way: boolean interrupted = false; try { ? ?// wait until interrupted } catch(InterruptedException ioe) { ? ?interrupted = true; } finally { ? ?try { ? ? ? ?throw RuntimeException("exception thrown from finally," + " but interrupt status will be preserved"); ? ?} finally { ? ? ? ?if (interrupted) { ? ? ? ? ? ?Thread.currentThread().interrupt(); ? ? ? ?} ? ?} } This code may seem ugly and obtuse. ?But I have written code like this before to improve reliability and speed of interrupt processing. Assume ARM is a macro for a properly written try/finally construct. The question becomes: does a properly written try/finally construct preserve thread interrupt status? ?I think it should. > In fact adding behavior (this restoring the interrupt flag) to ARM > suppression handling is counter-intuitive making ARM blocks behave very > different from traditional try/finally blocks where no such handling is > done. Point taken. ?But then again ARM already behaves significantly differently from traditional try/finally: Under ARM, an exception in an ARM block is thrown in favor of an exception in the cleanup block. This is the opposite of traditional try/finally, where an exception in the finally will be thrown in favor of an exception in the try. ?So I am not sure if "different from traditional try/catch" is a major strike against. > Or am I missing something here (quite possible :) ? While I feel strongly that interrupt statuses should always be preserved until handled by policy-setting code, not everyone may share this viewpoint. ?I do not think this is a cut-and-dry issue. ?However, all the best-practice material I have read (e.g. [1]) strongly suggests that code which does not set the interruption policy for a thread, should -- upon receiving an InterruptedException -- either re-throw the exception to code which implements the thread's interruption policy, or if unable to do that (as in the case of ARM), re-assert the interrupt status on the thread. [1] "A task should not assume anything about the interruption policy of its executing thread unless it is explicitly designed to run within a service that has a specific interruption policy. Whether a task interprets interruption as cancellation or takes some other action on interruption, it should take care to preserve the executing thread's interruption status. If it is not simply going to propagate InterruptedException to its caller, it should restore the interruption status after catching InterruptedException" -Java Concurrency In Practice, section 7.1.2 In fairness, it seems entirely possible for a programmer to devise a strategy which uses ARM and also preserves interrupt status: try { ? ?try (Resource r = new Resource()) { ? ? ? ?r.methodThatMightThrowInterruptedException(); ? ?} } catch (Exception e) { ? ?// Re-assert interrupt flag if an InterruptedException was suppressed ? ?for(Throwable ex : e.getSuppressedExceptions()) { ? ? ? ?if (ex instanceof InterruptedException) { ? ? ? ? ? ?Thread.currentThread().interrupt(); ? ? ? ? ? ?break; ? ? ? ?} ? ?} ? ?// OK now we can throw the main ARM exception // (might be some trouble with losing compatibility // with method's throws clause) ? ?throw e; } And maybe this whole situation is so niche that we should let programmers implement the above by hand, when they anticipate that interruption will be used with their code. But if we can agree that such preservation of interrupt status is almost universally desirable (which I believe it is), then why not build the preservation of interrupt status into the ARM template itself? Some reasons for keeping it out are: 1) The overhead of tracking interrupt status for all ARM blocks might be considered too high 2) There are important enough or numerous enough cases where re-asserting the interrupt would for some reason be undesirable 3) It deviates too far from traditional try/finally (the danger there being that programmers intuitively expect one thing, but get another, thus possibly leading to misunderstandings and mistakes) 4) It complicates ARM too much, or is outside the scope of ARM And I would answer: 1) The overhead should be minimal. ?But that must perhaps be weighed against the fact that this whole scenario is an edge-case: a) interruptions must be in use, and b) the interrupt must timed such that it arrives during resource cleanup, and c) the cleanup block must contain resources that actually throw InterruptedException out of .close() Only under these conditions would ARM interrupt-tracking result in anything additional happening. ?Is the overhead introduced into every ARM block worth the correctness in this edge case? 2) I do not know of any cases where preserving the interrupt status would be undesirable 3) I think that this issue may be so obscure that the vast majority of programmers do not have any behavioral expectations, and thus there is not a great deal of risk in violating those expectations 4) Subjective > Carlos thanks for your feedback, Carlos Mike From carlos at keysoft.pt Mon Jun 28 23:27:42 2010 From: carlos at keysoft.pt (Carlos Costa e Silva) Date: Tue, 29 Jun 2010 07:27:42 +0100 Subject: ARM and thread interruption In-Reply-To: Message-ID: -----Original Message----- From: Mike Clark [mailto:mclark at apache.org] [...SNIP...] But then again ARM already behaves significantly differently from traditional try/finally: Under ARM, an exception in an ARM block is thrown in favor of an exception in the cleanup block. This is the opposite of traditional try/finally, where an exception in the finally will be thrown in favor of an exception in the try. So I am not sure if "different from traditional try/catch" is a major strike against. > Or am I missing something here (quite possible :) ? [...SNIP...] -------------------------- Turns out I _really_ was missing something. Or rather, two somethings... First, and most important, was that the suppressed exception was thrown in localVar.close() inside the finally block instead of one thrown on the try block as would be the case in a "standard" try/(bugged)finally block[1]. Second mistake was thinking that you where advocating turning on the interrupt flag when an InterruptedException was thrown in the try block [which after finding the first mistake is obviously not the case here]. With this new light, this proposal seems much more reasonable. Thanks for the enlightenment and go ahead with restoring the interrupt flag :) Carlos [1] Note to self: next time read the proposal document with less pre-conceived notions so that I read is what's written not what's already in my head.