From forax at univ-mlv.fr Thu Jan 13 12:02:12 2011 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Thu, 13 Jan 2011 21:02:12 +0100 Subject: Project Coin: JSR 334 EDR now available Message-ID: <4D2F5A44.3080407@univ-mlv.fr> http://blogs.sun.com/darcy/entry/project_coin_edr R?mi From joe.darcy at oracle.com Thu Jan 13 12:46:46 2011 From: joe.darcy at oracle.com (Joe Darcy) Date: Thu, 13 Jan 2011 12:46:46 -0800 Subject: Project Coin: JSR 334 EDR now available In-Reply-To: <4D2F5A44.3080407@univ-mlv.fr> References: <4D2F5A44.3080407@univ-mlv.fr> Message-ID: <4D2F64B6.7010900@oracle.com> R?mi Forax wrote: > http://blogs.sun.com/darcy/entry/project_coin_edr > > R?mi > > Thanks for sending the pointer Remi; I plan to post some suggestions for given feedback on the EDR in the next day or two. -Joe From fweimer at bfk.de Tue Jan 18 00:58:47 2011 From: fweimer at bfk.de (Florian Weimer) Date: Tue, 18 Jan 2011 08:58:47 +0000 Subject: Project Coin: JSR 334 EDR now available In-Reply-To: <4D2F64B6.7010900@oracle.com> (Joe Darcy's message of "Thu\, 13 Jan 2011 12\:46\:46 -0800") References: <4D2F5A44.3080407@univ-mlv.fr> <4D2F64B6.7010900@oracle.com> Message-ID: <82mxmyh9ko.fsf@mid.bfk.de> * Joe Darcy: > Thanks for sending the pointer Remi; I plan to post some suggestions for > given feedback on the EDR in the next day or two. Could you contribute the document to OpenJDK, please? It seems that it is impossible to access this document without rescinding our OpenJDK redistribution rights. -- Florian Weimer BFK edv-consulting GmbH http://www.bfk.de/ Kriegsstra?e 100 tel: +49-721-96201-1 D-76133 Karlsruhe fax: +49-721-96201-99 From forax at univ-mlv.fr Fri Jan 21 08:34:22 2011 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Fri, 21 Jan 2011 17:34:22 +0100 Subject: SafeVarargs classfile encoding Message-ID: <4D39B58E.10800@univ-mlv.fr> I wonder if encoding @SafeVarargs as a runtime annotation in the classfile is a good idea. A runtime visible annotation is fat. In my opinion, @SafeVarargs should be an annotation with retention SOURCE, translated by the compiler to an empty SafeVarargs method attribute. Is there a use case where this annotation is needed at runtime ? R?mi From forax at univ-mlv.fr Fri Jan 21 09:12:53 2011 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Fri, 21 Jan 2011 18:12:53 +0100 Subject: try-with-resources and null resource Message-ID: <4D39BE95.60903@univ-mlv.fr> I think try-with-resources should do a null check before entering in the try block. 4. try(AutoCloseable c = null) { 5. // nothing 6. } $ java TryWithresourceNPE Exception in thread "main" java.lang.NullPointerException at TryWithresourceNPE.main(TryWithresourceNPE.java:6) I got a NPE from the ends of the try block, I think it will be better to detect the case before entering in the try block like foreach or switch does. And with this code: 5. try(InputStream i = null) { 6. i.available(); 7. } I got the exception below which is not understandable if you don't know how try-with-resources is translated. $ java TryWithresourceNPE Exception in thread "main" java.lang.NullPointerException at TryWithresourceNPE.main(TryWithresourceNPE.java:6) Suppressed: java.lang.NullPointerException at TryWithresourceNPE.main(TryWithresourceNPE.java:7) If the nullcheck is done before entering in the try block, the exception will be: Exception in thread "main" java.lang.NullPointerException at TryWithresourceNPE.main(TryWithresourceNPE.java:5) which is in my opinion much better. R?mi PS: the nullcheck can be done easily by calling getClass() on the expression 4. try(AutoCloseable c = null) { 5. // nothing 6. } will be translated to aconst_null dup invokevirtual java/lang/Object getClass ()Ljava/lang/Class; astore local_slot_of_c From pbenedict at apache.org Fri Jan 21 10:24:49 2011 From: pbenedict at apache.org (Paul Benedict) Date: Fri, 21 Jan 2011 12:24:49 -0600 Subject: try-with-resources and null resource In-Reply-To: <4D39BE95.60903@univ-mlv.fr> References: <4D39BE95.60903@univ-mlv.fr> Message-ID: The NPE is more useful than the language silently doing nothing with a null pointer. While your idea is convenient, I believe it assumes too much. If anything, perhaps the language shouldn't allow an explicit null assignment in a try-with-resources block. On Fri, Jan 21, 2011 at 11:12 AM, R?mi Forax wrote: > I think try-with-resources should do a null check before entering in the > try block. > > 4. try(AutoCloseable c = null) { > 5. // nothing > 6. } > > $ java TryWithresourceNPE > Exception in thread "main" java.lang.NullPointerException > at TryWithresourceNPE.main(TryWithresourceNPE.java:6) > > I got a NPE from the ends of the try block, I think it will be better to > detect the case > before entering in the try block like foreach or switch does. > > And with this code: > > 5. try(InputStream i = null) { > 6. i.available(); > 7. } > > I got the exception below which is not understandable if you don't know > how try-with-resources is translated. > > $ java TryWithresourceNPE > Exception in thread "main" java.lang.NullPointerException > at TryWithresourceNPE.main(TryWithresourceNPE.java:6) > Suppressed: java.lang.NullPointerException > at TryWithresourceNPE.main(TryWithresourceNPE.java:7) > > If the nullcheck is done before entering in the try block, > the exception will be: > Exception in thread "main" java.lang.NullPointerException > at TryWithresourceNPE.main(TryWithresourceNPE.java:5) > which is in my opinion much better. > > R?mi > PS: the nullcheck can be done easily by calling getClass() on the > expression > > 4. try(AutoCloseable c = null) { > 5. // nothing > 6. } > > will be translated to > > aconst_null > dup > invokevirtual java/lang/Object getClass ()Ljava/lang/Class; > astore local_slot_of_c > > > From forax at univ-mlv.fr Fri Jan 21 10:28:24 2011 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Fri, 21 Jan 2011 19:28:24 +0100 Subject: try-with-resources and null resource In-Reply-To: References: <4D39BE95.60903@univ-mlv.fr> Message-ID: <4D39D048.1030908@univ-mlv.fr> On 01/21/2011 07:24 PM, Paul Benedict wrote: > The NPE is more useful than the language silently doing nothing with a > null pointer. While your idea is convenient, I believe it assumes too > much. If anything, perhaps the language shouldn't allow an explicit > null assignment in a try-with-resources block. Hi Paul, the null assignement is just an example. Perhaps, you prefer this one: 4. try(AutoCloseable c = getAnAutoCloseableThatMayBeNull()) { 5. // nothing 6. } R?mi > > On Fri, Jan 21, 2011 at 11:12 AM, R?mi Forax > wrote: > > I think try-with-resources should do a null check before entering > in the > try block. > > 4. try(AutoCloseable c = null) { > 5. // nothing > 6. } > > $ java TryWithresourceNPE > Exception in thread "main" java.lang.NullPointerException > at TryWithresourceNPE.main(TryWithresourceNPE.java:6) > > I got a NPE from the ends of the try block, I think it will be > better to > detect the case > before entering in the try block like foreach or switch does. > > And with this code: > > 5. try(InputStream i = null) { > 6. i.available(); > 7. } > > I got the exception below which is not understandable if you don't > know > how try-with-resources is translated. > > $ java TryWithresourceNPE > Exception in thread "main" java.lang.NullPointerException > at TryWithresourceNPE.main(TryWithresourceNPE.java:6) > Suppressed: java.lang.NullPointerException > at TryWithresourceNPE.main(TryWithresourceNPE.java:7) > > If the nullcheck is done before entering in the try block, > the exception will be: > Exception in thread "main" java.lang.NullPointerException > at TryWithresourceNPE.main(TryWithresourceNPE.java:5) > which is in my opinion much better. > > R?mi > PS: the nullcheck can be done easily by calling getClass() on the > expression > > 4. try(AutoCloseable c = null) { > 5. // nothing > 6. } > > will be translated to > > aconst_null > dup > invokevirtual java/lang/Object getClass ()Ljava/lang/Class; > astore local_slot_of_c > > > From tom.hawtin at oracle.com Fri Jan 21 10:46:06 2011 From: tom.hawtin at oracle.com (Tom Hawtin) Date: Fri, 21 Jan 2011 18:46:06 +0000 Subject: try-with-resources and null resource In-Reply-To: <4D39BE95.60903@univ-mlv.fr> References: <4D39BE95.60903@univ-mlv.fr> Message-ID: <4D39D46E.5070501@oracle.com> A compiler or other static checker following [inactive] JSR305 or similar @Nonnull, should find this problem no problem. Having the language spec forcing an ignore of the bug would be a bad thing, IMNSHO. Tom On 21/01/2011 17:12, R?mi Forax wrote: > I think try-with-resources should do a null check before entering in the > try block. > > 4. try(AutoCloseable c = null) { > 5. // nothing > 6. } > > $ java TryWithresourceNPE > Exception in thread "main" java.lang.NullPointerException > at TryWithresourceNPE.main(TryWithresourceNPE.java:6) > > I got a NPE from the ends of the try block, I think it will be better to > detect the case > before entering in the try block like foreach or switch does. > > And with this code: > > 5. try(InputStream i = null) { > 6. i.available(); > 7. } > > I got the exception below which is not understandable if you don't know > how try-with-resources is translated. > > $ java TryWithresourceNPE > Exception in thread "main" java.lang.NullPointerException > at TryWithresourceNPE.main(TryWithresourceNPE.java:6) > Suppressed: java.lang.NullPointerException > at TryWithresourceNPE.main(TryWithresourceNPE.java:7) > > If the nullcheck is done before entering in the try block, > the exception will be: > Exception in thread "main" java.lang.NullPointerException > at TryWithresourceNPE.main(TryWithresourceNPE.java:5) > which is in my opinion much better. > > R?mi > PS: the nullcheck can be done easily by calling getClass() on the expression > > 4. try(AutoCloseable c = null) { > 5. // nothing > 6. } > > will be translated to > > aconst_null > dup > invokevirtual java/lang/Object getClass ()Ljava/lang/Class; > astore local_slot_of_c > > From joe.darcy at Oracle.com Fri Jan 21 10:50:06 2011 From: joe.darcy at Oracle.com (Joe Darcy) Date: Fri, 21 Jan 2011 10:50:06 -0800 Subject: SafeVarargs classfile encoding In-Reply-To: <4D39B58E.10800@univ-mlv.fr> References: <4D39B58E.10800@univ-mlv.fr> Message-ID: <4D39D55E.3010602@oracle.com> Hi R?mi. A few comments, in the entirety of the "jdk" repository, there were a total of five methods where it was appropriate to add this annotation, which is not a very high density! For Coin, to keep the features small, we're avoiding JVM changes and defining a new attribute is a JVM changes of sorts. The SafeVarargs information is needed in the class file in some fashion to so that compilers can know to omit unchecked warnings that would otherwise have to be emitted. Additionally, having the information in the class file enables tools like findbugs to do additional checking on the operations of the SafeVarargs methods. Using an annotation to store this information avoids the need to add a new core reflection API to access it, Method.isSafeVarargs, etc. -Joe R?mi Forax wrote: > I wonder if encoding @SafeVarargs as a runtime annotation > in the classfile is a good idea. A runtime visible annotation is fat. > > In my opinion, @SafeVarargs should be an annotation with > retention SOURCE, translated by the compiler to an empty SafeVarargs > method attribute. > > Is there a use case where this annotation is needed at runtime ? > > R?mi > > From pbenedict at apache.org Fri Jan 21 10:54:30 2011 From: pbenedict at apache.org (Paul Benedict) Date: Fri, 21 Jan 2011 12:54:30 -0600 Subject: SafeVarargs classfile encoding In-Reply-To: <4D39D55E.3010602@oracle.com> References: <4D39B58E.10800@univ-mlv.fr> <4D39D55E.3010602@oracle.com> Message-ID: Joe, Will there be any language restriction on using @SafeVarargs for non-var arg methods? After all, it's just an annotation so I wonder if normal annotation rules apply or it has restricted syntax. Paul On Fri, Jan 21, 2011 at 12:50 PM, Joe Darcy wrote: > Hi R?mi. > > A few comments, in the entirety of the "jdk" repository, there were a > total of five methods where it was appropriate to add this annotation, > which is not a very high density! For Coin, to keep the features small, > we're avoiding JVM changes and defining a new attribute is a JVM changes > of sorts. > > The SafeVarargs information is needed in the class file in some fashion > to so that compilers can know to omit unchecked warnings that would > otherwise have to be emitted. Additionally, having the information in > the class file enables tools like findbugs to do additional checking on > the operations of the SafeVarargs methods. > > Using an annotation to store this information avoids the need to add a > new core reflection API to access it, Method.isSafeVarargs, etc. > > -Joe > > R?mi Forax wrote: > > I wonder if encoding @SafeVarargs as a runtime annotation > > in the classfile is a good idea. A runtime visible annotation is fat. > > > > In my opinion, @SafeVarargs should be an annotation with > > retention SOURCE, translated by the compiler to an empty SafeVarargs > > method attribute. > > > > Is there a use case where this annotation is needed at runtime ? > > > > R?mi > > > > > > > From joe.darcy at oracle.com Fri Jan 21 10:56:59 2011 From: joe.darcy at oracle.com (Joe Darcy) Date: Fri, 21 Jan 2011 10:56:59 -0800 Subject: SafeVarargs classfile encoding In-Reply-To: References: <4D39B58E.10800@univ-mlv.fr> <4D39D55E.3010602@oracle.com> Message-ID: <4D39D6FB.6040809@oracle.com> Paul, The additional restrictions are given in the specification of the annotation type: http://download.java.net/jdk7/docs/api/java/lang/SafeVarargs.html > > In addition to the usage restrictions imposed by its @Target > meta-annotation, compilers are required to implement additional usage > restrictions on this annotation type; it is a compile-time error if a > method or constructor declaration is annotated with a @SafeVarargs > annotation, and either: > > * the declaration is a fixed-arity method or constructor > * the declaration is a variable-arity method that is neither > static nor final. -Joe Paul Benedict wrote: > Joe, > > Will there be any language restriction on using @SafeVarargs for > non-var arg methods? After all, it's just an annotation so I wonder if > normal annotation rules apply or it has restricted syntax. > > Paul > > On Fri, Jan 21, 2011 at 12:50 PM, Joe Darcy > wrote: > > Hi R?mi. > > A few comments, in the entirety of the "jdk" repository, there were a > total of five methods where it was appropriate to add this annotation, > which is not a very high density! For Coin, to keep the features > small, > we're avoiding JVM changes and defining a new attribute is a JVM > changes > of sorts. > > The SafeVarargs information is needed in the class file in some > fashion > to so that compilers can know to omit unchecked warnings that would > otherwise have to be emitted. Additionally, having the information in > the class file enables tools like findbugs to do additional > checking on > the operations of the SafeVarargs methods. > > Using an annotation to store this information avoids the need to add a > new core reflection API to access it, Method.isSafeVarargs, etc. > > -Joe > > R?mi Forax wrote: > > I wonder if encoding @SafeVarargs as a runtime annotation > > in the classfile is a good idea. A runtime visible annotation is > fat. > > > > In my opinion, @SafeVarargs should be an annotation with > > retention SOURCE, translated by the compiler to an empty SafeVarargs > > method attribute. > > > > Is there a use case where this annotation is needed at runtime ? > > > > R?mi > > > > > > > From forax at univ-mlv.fr Fri Jan 21 11:22:30 2011 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Fri, 21 Jan 2011 20:22:30 +0100 Subject: SafeVarargs classfile encoding In-Reply-To: <4D39D55E.3010602@oracle.com> References: <4D39B58E.10800@univ-mlv.fr> <4D39D55E.3010602@oracle.com> Message-ID: <4D39DCF6.5060502@univ-mlv.fr> On 01/21/2011 07:50 PM, Joe Darcy wrote: > Hi R?mi. > > A few comments, in the entirety of the "jdk" repository, there were a > total of five methods where it was appropriate to add this annotation, > which is not a very high density! For Coin, to keep the features > small, we're avoiding JVM changes and defining a new attribute is a > JVM changes of sorts. Here is the JVM spec change: The SafeVarargs attribute is a fixed-length attribute in the |attributes| table of |||||method_info| (?4.6) structures. SafeVarargs is an attribute corresponding to the annotation SafeVarargs that the body of the annotated method or constructor does not perform potentially unsafe operations on its varargs parameter. The SafeVarargs attribute has the following format: SafeVarargs|_attribute { | | u2 attribute_name_index; | | u4 attribute_length; | |} | The items of the SafeVarargs|| structure are as follows: |attribute_name_index| The value of the |attribute_name_index| item must be a valid index into the |constant_pool| table. The |constant_pool| entry at that index must be a |CONSTANT_Utf8_info| (?4.4.7) structure representing the string |"|SafeVarargs|"|. |attribute_length| The value of the |attribute_length| item is zero. > > The SafeVarargs information is needed in the class file in some > fashion to so that compilers can know to omit unchecked warnings that > would otherwise have to be emitted. Additionally, having the > information in the class file enables tools like findbugs to do > additional checking on the operations of the SafeVarargs methods. findbugs crawle the bytecode, so encoding SafeVarargs as an annotation or an attribute doesn't matter. > > Using an annotation to store this information avoids the need to add a > new core reflection API to access it, Method.isSafeVarargs, etc. Why SafeVarargs need to be visible using reflection API ? By example, Synthetic attribute is not visible using reflection API. > > -Joe R?mi > > R?mi Forax wrote: >> I wonder if encoding @SafeVarargs as a runtime annotation >> in the classfile is a good idea. A runtime visible annotation is fat. >> >> In my opinion, @SafeVarargs should be an annotation with >> retention SOURCE, translated by the compiler to an empty SafeVarargs >> method attribute. >> >> Is there a use case where this annotation is needed at runtime ? >> >> R?mi >> > From joe.darcy at oracle.com Fri Jan 21 11:34:45 2011 From: joe.darcy at oracle.com (Joe Darcy) Date: Fri, 21 Jan 2011 11:34:45 -0800 Subject: SafeVarargs classfile encoding In-Reply-To: <4D39DCF6.5060502@univ-mlv.fr> References: <4D39B58E.10800@univ-mlv.fr> <4D39D55E.3010602@oracle.com> <4D39DCF6.5060502@univ-mlv.fr> Message-ID: <4D39DFD5.7050205@oracle.com> R?mi Forax wrote: > On 01/21/2011 07:50 PM, Joe Darcy wrote: >> Hi R?mi. >> >> A few comments, in the entirety of the "jdk" repository, there were a >> total of five methods where it was appropriate to add this >> annotation, which is not a very high density! For Coin, to keep the >> features small, we're avoiding JVM changes and defining a new >> attribute is a JVM changes of sorts. > > Here is the JVM spec change: [sni] The size of the JVM change is not the problem; the fact that potentially all class file consuming tools would need to know about the attribute is. Additionally, this would be a new kind of side-effect of annotating a method. > >> >> Using an annotation to store this information avoids the need to add >> a new core reflection API to access it, Method.isSafeVarargs, etc. > > Why SafeVarargs need to be visible using reflection API ? Why should the information be excluded? This annotation is a statement about the semantics of the method. > By example, Synthetic attribute is not visible using reflection API. > Some synthetic information is exposed in core reflection: http://download.java.net/jdk7/docs/api/java/lang/Class.html#isSynthetic() http://download.java.net/jdk7/docs/api/java/lang/reflect/Constructor.html#isSynthetic() http://download.java.net/jdk7/docs/api/java/lang/reflect/Method.html#isSynthetic() http://download.java.net/jdk7/docs/api/java/lang/reflect/Field.html#isSynthetic() -Joe From joe.darcy at oracle.com Fri Jan 21 11:38:31 2011 From: joe.darcy at oracle.com (Joe Darcy) Date: Fri, 21 Jan 2011 11:38:31 -0800 Subject: try-with-resources and null resource In-Reply-To: <4D39BE95.60903@univ-mlv.fr> References: <4D39BE95.60903@univ-mlv.fr> Message-ID: <4D39E0B7.40306@oracle.com> R?mi Forax wrote: > I think try-with-resources should do a null check before entering in the > try block. > > 4. try(AutoCloseable c = null) { > 5. // nothing > 6. } > > $ java TryWithresourceNPE > Exception in thread "main" java.lang.NullPointerException > at TryWithresourceNPE.main(TryWithresourceNPE.java:6) > > I got a NPE from the ends of the try block, I think it will be better to > detect the case > before entering in the try block like foreach or switch does. > > And with this code: > > 5. try(InputStream i = null) { > 6. i.available(); > 7. } > > I got the exception below which is not understandable if you don't know > how try-with-resources is translated. > > $ java TryWithresourceNPE > Exception in thread "main" java.lang.NullPointerException > at TryWithresourceNPE.main(TryWithresourceNPE.java:6) > Suppressed: java.lang.NullPointerException > at TryWithresourceNPE.main(TryWithresourceNPE.java:7) > I'm not too concerned about that stacktrace since the primary exception points to the right location. > If the nullcheck is done before entering in the try block, > the exception will be: > Exception in thread "main" java.lang.NullPointerException > at TryWithresourceNPE.main(TryWithresourceNPE.java:5) > which is in my opinion much better. > > R?mi > PS: the nullcheck can be done easily by calling getClass() on the expression > > 4. try(AutoCloseable c = null) { > 5. // nothing > 6. } > > will be translated to > > aconst_null > dup > invokevirtual java/lang/Object getClass ()Ljava/lang/Class; > astore local_slot_of_c > > Yes, javac internal uses that idiom for null checks and the JVM knows how to optimize this well :-) -Joe From forax at univ-mlv.fr Fri Jan 21 11:53:16 2011 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Fri, 21 Jan 2011 20:53:16 +0100 Subject: SafeVarargs classfile encoding In-Reply-To: <4D39DFD5.7050205@oracle.com> References: <4D39B58E.10800@univ-mlv.fr> <4D39D55E.3010602@oracle.com> <4D39DCF6.5060502@univ-mlv.fr> <4D39DFD5.7050205@oracle.com> Message-ID: <4D39E42C.6060608@univ-mlv.fr> On 01/21/2011 08:34 PM, Joe Darcy wrote: > R?mi Forax wrote: >> On 01/21/2011 07:50 PM, Joe Darcy wrote: >>> Hi R?mi. >>> >>> A few comments, in the entirety of the "jdk" repository, there were >>> a total of five methods where it was appropriate to add this >>> annotation, which is not a very high density! For Coin, to keep the >>> features small, we're avoiding JVM changes and defining a new >>> attribute is a JVM changes of sorts. >> >> Here is the JVM spec change: > > [snip] > > The size of the JVM change is not the problem; the fact that > potentially all class file consuming tools would need to know about > the attribute is. No because it's an empty attribute. I will be ignored by classfile reader, and copied by classfile read/writer. see section 4.7.1 of the VM spec. > Additionally, this would be a new kind of side-effect of annotating > a method. I don't understand your point here. SafeVarargs doesn't alter the semantics of a method for the VM, like Deprecated or Synthetic which are already defined as attribute. > >> >>> >>> Using an annotation to store this information avoids the need to add >>> a new core reflection API to access it, Method.isSafeVarargs, etc. >> >> Why SafeVarargs need to be visible using reflection API ? > > Why should the information be excluded? This annotation is a > statement about the semantics of the method. This annotation doesn't alter the *runtime* semantics of a method. > >> By example, Synthetic attribute is not visible using reflection API. >> > > Some synthetic information is exposed in core reflection: > > http://download.java.net/jdk7/docs/api/java/lang/Class.html#isSynthetic() > http://download.java.net/jdk7/docs/api/java/lang/reflect/Constructor.html#isSynthetic() > > http://download.java.net/jdk7/docs/api/java/lang/reflect/Method.html#isSynthetic() > > http://download.java.net/jdk7/docs/api/java/lang/reflect/Field.html#isSynthetic() > Ok, bad example. > > -Joe R?mi From joe.darcy at oracle.com Fri Jan 21 12:03:53 2011 From: joe.darcy at oracle.com (Joe Darcy) Date: Fri, 21 Jan 2011 12:03:53 -0800 Subject: SafeVarargs classfile encoding In-Reply-To: <4D39E42C.6060608@univ-mlv.fr> References: <4D39B58E.10800@univ-mlv.fr> <4D39D55E.3010602@oracle.com> <4D39DCF6.5060502@univ-mlv.fr> <4D39DFD5.7050205@oracle.com> <4D39E42C.6060608@univ-mlv.fr> Message-ID: <4D39E6A9.3040609@oracle.com> R?mi Forax wrote: > On 01/21/2011 08:34 PM, Joe Darcy wrote: >> R?mi Forax wrote: >>> On 01/21/2011 07:50 PM, Joe Darcy wrote: >>>> Hi R?mi. >>>> >>>> A few comments, in the entirety of the "jdk" repository, there were >>>> a total of five methods where it was appropriate to add this >>>> annotation, which is not a very high density! For Coin, to keep >>>> the features small, we're avoiding JVM changes and defining a new >>>> attribute is a JVM changes of sorts. >>> >>> Here is the JVM spec change: >> >> [snip] >> >> The size of the JVM change is not the problem; the fact that >> potentially all class file consuming tools would need to know about >> the attribute is. > > No because it's an empty attribute. I will be ignored by classfile > reader, and copied by classfile read/writer. > see section 4.7.1 of the VM spec. Tools like pack200 would have to be updated to know to preserve the attribute as opposed to dropping it on the floor, etc. > >> Additionally, this would be a new kind of side-effect of annotating >> a method. > > I don't understand your point here. > SafeVarargs doesn't alter the semantics of a method for the VM, > like Deprecated or Synthetic which are already defined as attribute. Perhaps other than @Deprecated (I'm not going to look up to verify the situation right now), there is no case where putting an annotation on a method has the side-effect of altering the generated class file in a way other than having the annotation represented in the class file, if appropriate. >>>> >>>> Using an annotation to store this information avoids the need to >>>> add a new core reflection API to access it, Method.isSafeVarargs, etc. >>> >>> Why SafeVarargs need to be visible using reflection API ? >> >> Why should the information be excluded? This annotation is a >> statement about the semantics of the method. > > This annotation doesn't alter the *runtime* semantics of a method. However the annotation is an assertion about the runtime semantics of a method, an assertion someone introspecting on the method may be interested in knowing. -Joe From joe.darcy at oracle.com Fri Jan 21 15:22:10 2011 From: joe.darcy at oracle.com (Joe Darcy) Date: Fri, 21 Jan 2011 15:22:10 -0800 Subject: Update on JSR 334 Expert Group activities Message-ID: <4D3A1522.40901@oracle.com> Hello. Besides working to address issues identified in the EDR draft [1], such as refining the diamond specification, the JSR 334 expert group has been considering other matters as well. One change being contemplated is removing the ability to have multiple underscores between digits of a literal; under that possible change, no underscore or a single underscore would be allowed. The primary consideration here is to prevent abuses of the underscores in literal feature that would obscure program meaning; on the other hand, there may be reasonable uses of repeated underscores that are desirable to allow. The expert group has agreed to one significant change from the EDR draft: as called out as a possibility in the draft, support has been dropped for the general expression form of the try-with-resources statement. That is, support has been removed for passing a resource as a general expression without an accompanying explicit variable declaration. Several technical problems were identified with allowing a general expression: * Syntactic ambiguity: In the parser, it was not always possible to distinguish with one-token look-ahead between the start of an Expression and the start of a Type. Consider code like try(i < j // Ternary operator on variables i and j ? new Resource1() : new Resource2()) {...} compared to code like try(Box < Resource // Simple generic wrapper around a resource > resourceBox = Box<>(new Resource1())) {...} A natural grammatical fallback short of banning Expression would be to only allow a more restricted expression, such as Identifier. However, that restricted grammar would require compiler changes to alert programmers to some surprising legal code, as given in the following examples. * Usability issues: Consider a try-with-resources statement being used to manage an existing variable where the variable is mutated inside the try block: public class TwrExamples implements AutoCloseable { public static void main(String... args) { TwrExamples twrEg1 = new TwrExamples(); System.out.println(twrEg1.hashCode()); try(twrEg1) { twrEg1 = new TwrExamples(); // Mutating the variable! System.out.println(twrEg1.hashCode()); } } @Override public void close() { System.out.println(hashCode()); } } As try-with-resources was previously specified, this would cause close to be called on the original value, not the value twrEg1 pointed to at the time the try block finishes. In this case, the printed output of the program may be something like: 1607576787 1051296202 1607576787 which indicates that while close was called on the original value, close was not called on the new TwrExamples object created inside the try-with-resources block. Either policy of calling code on the original value or the value on exit of the block could be problematic. The compiler did not issue any warnings about this situation and warnings should be added if this feature were to be kept. (Mutating a resource variable declared as part of the try-with-resources statement is illegal since such variables are implicitly or explicitly final). Other complications that stemmed from supporting a general expression as a resource were making sure the specification and implementation accepted both try(null) {...} and try(myGenericMethodThatInfersTheTypeOfItsResult()) {} as valid programs. The main rationale for supporting general expressions was to allow non-Closeable objects, such as locks, to be easily wrapped in a suitable type to enjoy the call-method-on-block-exit guarantees of try-with-resources. When this is desirable, the same effect can still be achieved with an explicit resource declaration. As experience is gained with try-with-resources, extensions to support other usage patterns will be considered in future releases. I'm working with the javac team to remove support for this feature in an upcoming JDK 7 build. -Joe [1] http://mail.openjdk.java.net/pipermail/coin-dev/2011-January/002956.html From forax at univ-mlv.fr Sat Jan 22 05:09:31 2011 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Sat, 22 Jan 2011 14:09:31 +0100 Subject: try-with-resources and null resource In-Reply-To: <4D39E0B7.40306@oracle.com> References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> Message-ID: <4D3AD70B.2020300@univ-mlv.fr> On 01/21/2011 08:38 PM, Joe Darcy wrote: > R?mi Forax wrote: >> I think try-with-resources should do a null check before entering in >> the try block. >> >> 4. try(AutoCloseable c = null) { >> 5. // nothing >> 6. } >> >> $ java TryWithresourceNPE >> Exception in thread "main" java.lang.NullPointerException >> at TryWithresourceNPE.main(TryWithresourceNPE.java:6) >> >> I got a NPE from the ends of the try block, I think it will be better >> to detect the case >> before entering in the try block like foreach or switch does. >> >> And with this code: >> >> 5. try(InputStream i = null) { >> 6. i.available(); >> 7. } >> >> I got the exception below which is not understandable if you don't know >> how try-with-resources is translated. >> >> $ java TryWithresourceNPE >> Exception in thread "main" java.lang.NullPointerException >> at TryWithresourceNPE.main(TryWithresourceNPE.java:6) >> Suppressed: java.lang.NullPointerException >> at TryWithresourceNPE.main(TryWithresourceNPE.java:7) > > I'm not too concerned about that stacktrace since the primary > exception points to the right location. But the suppressed exception occurs in a generated code that the user don't write. I don't like the idea that a user mistake blow up in a generated code, try-with-resources should protect itself. http://www.google.com/search?q=Throw+early+catch+late > >> If the nullcheck is done before entering in the try block, >> the exception will be: >> Exception in thread "main" java.lang.NullPointerException >> at TryWithresourceNPE.main(TryWithresourceNPE.java:5) >> which is in my opinion much better. >> >> R?mi >> PS: the nullcheck can be done easily by calling getClass() on the >> expression >> >> 4. try(AutoCloseable c = null) { >> 5. // nothing >> 6. } >> >> will be translated to >> >> aconst_null >> dup >> invokevirtual java/lang/Object getClass ()Ljava/lang/Class; >> astore local_slot_of_c >> > > Yes, javac internal uses that idiom for null checks and the JVM knows > how to optimize this well :-) > > -Joe > R?mi From peter.levart at gmail.com Sat Jan 22 09:10:15 2011 From: peter.levart at gmail.com (Peter Levart) Date: Sat, 22 Jan 2011 18:10:15 +0100 Subject: try-with-resources and null resource In-Reply-To: <4D3AD70B.2020300@univ-mlv.fr> References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> Message-ID: <201101221810.16183.peter.levart@gmail.com> Perhaps the check for null should be done at cleanup time and do nothing if resource is null. A null value can be considered as a "valid" resource and the cleanup should not throw NPE if this is the case... Peter On Saturday, January 22, 2011 02:09:31 pm R?mi Forax wrote: > On 01/21/2011 08:38 PM, Joe Darcy wrote: > > R?mi Forax wrote: > >> I think try-with-resources should do a null check before entering in > >> the try block. > >> > >> 4. try(AutoCloseable c = null) { > >> 5. // nothing > >> 6. } > >> > >> $ java TryWithresourceNPE > >> Exception in thread "main" java.lang.NullPointerException > >> > >> at TryWithresourceNPE.main(TryWithresourceNPE.java:6) > >> > >> I got a NPE from the ends of the try block, I think it will be better > >> to detect the case > >> before entering in the try block like foreach or switch does. > >> > >> And with this code: > >> > >> 5. try(InputStream i = null) { > >> 6. i.available(); > >> 7. } > >> > >> I got the exception below which is not understandable if you don't know > >> how try-with-resources is translated. > >> > >> $ java TryWithresourceNPE > >> Exception in thread "main" java.lang.NullPointerException > >> > >> at TryWithresourceNPE.main(TryWithresourceNPE.java:6) > >> Suppressed: java.lang.NullPointerException > >> > >> at TryWithresourceNPE.main(TryWithresourceNPE.java:7) > > > > I'm not too concerned about that stacktrace since the primary > > exception points to the right location. > > But the suppressed exception occurs in a generated code that the user > don't write. > I don't like the idea that a user mistake blow up in a generated code, > try-with-resources should protect itself. > > http://www.google.com/search?q=Throw+early+catch+late > > >> If the nullcheck is done before entering in the try block, > >> the exception will be: > >> Exception in thread "main" java.lang.NullPointerException > >> > >> at TryWithresourceNPE.main(TryWithresourceNPE.java:5) > >> > >> which is in my opinion much better. > >> > >> R?mi > >> PS: the nullcheck can be done easily by calling getClass() on the > >> expression > >> > >> 4. try(AutoCloseable c = null) { > >> 5. // nothing > >> 6. } > >> > >> will be translated to > >> > >> aconst_null > >> dup > >> invokevirtual java/lang/Object getClass ()Ljava/lang/Class; > >> astore local_slot_of_c > > > > Yes, javac internal uses that idiom for null checks and the JVM knows > > how to optimize this well :-) > > > > -Joe > > R?mi From forax at univ-mlv.fr Sat Jan 22 09:15:36 2011 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Sat, 22 Jan 2011 18:15:36 +0100 Subject: try-with-resources and null resource In-Reply-To: <201101221810.16183.peter.levart@gmail.com> References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <201101221810.16183.peter.levart@gmail.com> Message-ID: <4D3B10B8.7070706@univ-mlv.fr> On 01/22/2011 06:10 PM, Peter Levart wrote: > Perhaps the check for null should be done at cleanup time and do nothing if resource is null. A > null value can be considered as a "valid" resource and the cleanup should not throw NPE if this > is the case... > > Peter The same argument was rejected for enhanced for loop. I believe that throwing a NPE is more consistent with rest of the language, unboxing, for(:) or switch on enum/string throws a NPE if the value is null. R?mi > > On Saturday, January 22, 2011 02:09:31 pm R?mi Forax wrote: >> On 01/21/2011 08:38 PM, Joe Darcy wrote: >>> R?mi Forax wrote: >>>> I think try-with-resources should do a null check before entering in >>>> the try block. >>>> >>>> 4. try(AutoCloseable c = null) { >>>> 5. // nothing >>>> 6. } >>>> >>>> $ java TryWithresourceNPE >>>> Exception in thread "main" java.lang.NullPointerException >>>> >>>> at TryWithresourceNPE.main(TryWithresourceNPE.java:6) >>>> >>>> I got a NPE from the ends of the try block, I think it will be better >>>> to detect the case >>>> before entering in the try block like foreach or switch does. >>>> >>>> And with this code: >>>> >>>> 5. try(InputStream i = null) { >>>> 6. i.available(); >>>> 7. } >>>> >>>> I got the exception below which is not understandable if you don't know >>>> how try-with-resources is translated. >>>> >>>> $ java TryWithresourceNPE >>>> Exception in thread "main" java.lang.NullPointerException >>>> >>>> at TryWithresourceNPE.main(TryWithresourceNPE.java:6) >>>> Suppressed: java.lang.NullPointerException >>>> >>>> at TryWithresourceNPE.main(TryWithresourceNPE.java:7) >>> I'm not too concerned about that stacktrace since the primary >>> exception points to the right location. >> But the suppressed exception occurs in a generated code that the user >> don't write. >> I don't like the idea that a user mistake blow up in a generated code, >> try-with-resources should protect itself. >> >> http://www.google.com/search?q=Throw+early+catch+late >> >>>> If the nullcheck is done before entering in the try block, >>>> the exception will be: >>>> Exception in thread "main" java.lang.NullPointerException >>>> >>>> at TryWithresourceNPE.main(TryWithresourceNPE.java:5) >>>> >>>> which is in my opinion much better. >>>> >>>> R?mi >>>> PS: the nullcheck can be done easily by calling getClass() on the >>>> expression >>>> >>>> 4. try(AutoCloseable c = null) { >>>> 5. // nothing >>>> 6. } >>>> >>>> will be translated to >>>> >>>> aconst_null >>>> dup >>>> invokevirtual java/lang/Object getClass ()Ljava/lang/Class; >>>> astore local_slot_of_c >>> Yes, javac internal uses that idiom for null checks and the JVM knows >>> how to optimize this well :-) >>> >>> -Joe >> R?mi From joe.darcy at oracle.com Mon Jan 24 11:00:20 2011 From: joe.darcy at oracle.com (Joe Darcy) Date: Mon, 24 Jan 2011 11:00:20 -0800 Subject: try-with-resources and null resource In-Reply-To: <4D3AD70B.2020300@univ-mlv.fr> References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> Message-ID: <4D3DCC44.8030302@oracle.com> On 1/22/2011 5:09 AM, R?mi Forax wrote: > On 01/21/2011 08:38 PM, Joe Darcy wrote: >> R?mi Forax wrote: >>> I think try-with-resources should do a null check before entering in >>> the try block. >>> >>> 4. try(AutoCloseable c = null) { >>> 5. // nothing >>> 6. } >>> >>> $ java TryWithresourceNPE >>> Exception in thread "main" java.lang.NullPointerException >>> at TryWithresourceNPE.main(TryWithresourceNPE.java:6) >>> >>> I got a NPE from the ends of the try block, I think it will be >>> better to detect the case >>> before entering in the try block like foreach or switch does. >>> >>> And with this code: >>> >>> 5. try(InputStream i = null) { >>> 6. i.available(); >>> 7. } >>> >>> I got the exception below which is not understandable if you don't know >>> how try-with-resources is translated. >>> >>> $ java TryWithresourceNPE >>> Exception in thread "main" java.lang.NullPointerException >>> at TryWithresourceNPE.main(TryWithresourceNPE.java:6) >>> Suppressed: java.lang.NullPointerException >>> at TryWithresourceNPE.main(TryWithresourceNPE.java:7) >> >> I'm not too concerned about that stacktrace since the primary >> exception points to the right location. > > But the suppressed exception occurs in a generated code that the user > don't write. But that is the whole point of try-with-resources, to allow users to not have to write the messy and error-prone clean-up code. > I don't like the idea that a user mistake blow up in a generated code, > try-with-resources should protect itself. I think this stack trace can easily be explained to programmers by saying "the suppressed exception comes from the close call you did have to write yourself." -Joe From tim at peierls.net Mon Jan 24 11:30:11 2011 From: tim at peierls.net (Tim Peierls) Date: Mon, 24 Jan 2011 14:30:11 -0500 Subject: try-with-resources and null resource In-Reply-To: <4D3DCC44.8030302@oracle.com> References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> Message-ID: On Mon, Jan 24, 2011 at 2:00 PM, Joe Darcy wrote: > I think this stack trace can easily be explained to programmers by > saying "the suppressed exception comes from the close call you did have > to write yourself." > Agreed on all points, except I think you meant: s/did/didn't/ --tim From joe.darcy at oracle.com Mon Jan 24 11:37:18 2011 From: joe.darcy at oracle.com (Joe Darcy) Date: Mon, 24 Jan 2011 11:37:18 -0800 Subject: try-with-resources and null resource In-Reply-To: References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> Message-ID: <4D3DD4EE.8080803@oracle.com> Tim Peierls wrote: > On Mon, Jan 24, 2011 at 2:00 PM, Joe Darcy > wrote: > > I think this stack trace can easily be explained to programmers by > saying "the suppressed exception comes from the close call you did > have > to write yourself." > > > Agreed on all points, except I think you meant: s/did/didn't/ > Yes, I did mean "didn't" :-) -Joe From forax at univ-mlv.fr Mon Jan 24 11:36:42 2011 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Mon, 24 Jan 2011 20:36:42 +0100 Subject: try-with-resources and null resource In-Reply-To: <4D3DCC44.8030302@oracle.com> References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> Message-ID: <4D3DD4CA.1070802@univ-mlv.fr> On 01/24/2011 08:00 PM, Joe Darcy wrote: > On 1/22/2011 5:09 AM, R?mi Forax wrote: >> On 01/21/2011 08:38 PM, Joe Darcy wrote: >>> R?mi Forax wrote: >>>> I think try-with-resources should do a null check before entering >>>> in the try block. >>>> >>>> 4. try(AutoCloseable c = null) { >>>> 5. // nothing >>>> 6. } >>>> >>>> $ java TryWithresourceNPE >>>> Exception in thread "main" java.lang.NullPointerException >>>> at TryWithresourceNPE.main(TryWithresourceNPE.java:6) >>>> >>>> I got a NPE from the ends of the try block, I think it will be >>>> better to detect the case >>>> before entering in the try block like foreach or switch does. >>>> >>>> And with this code: >>>> >>>> 5. try(InputStream i = null) { >>>> 6. i.available(); >>>> 7. } >>>> >>>> I got the exception below which is not understandable if you don't >>>> know >>>> how try-with-resources is translated. >>>> >>>> $ java TryWithresourceNPE >>>> Exception in thread "main" java.lang.NullPointerException >>>> at TryWithresourceNPE.main(TryWithresourceNPE.java:6) >>>> Suppressed: java.lang.NullPointerException >>>> at TryWithresourceNPE.main(TryWithresourceNPE.java:7) >>> >>> I'm not too concerned about that stacktrace since the primary >>> exception points to the right location. >> >> But the suppressed exception occurs in a generated code that the user >> don't write. > > But that is the whole point of try-with-resources, to allow users to > not have to write the messy and error-prone clean-up code. I have no problem if the error come from the close() itself, the stacktrace will be explicit in that case. But here it comes because the spec allows try(...) to be used with null, oh no wait! the generated finally block doesn't allow it. If you take a look to how try/finally are coded now, you will find a nullcheck before the try or in the finally block. > >> I don't like the idea that a user mistake blow up in a generated code, >> try-with-resources should protect itself. > > I think this stack trace can easily be explained to programmers by > saying "the suppressed exception comes from the close call you did > have to write yourself." You don't have to explain something which is not surprising. > > -Joe > R?mi From forax at univ-mlv.fr Mon Jan 24 11:53:12 2011 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Mon, 24 Jan 2011 20:53:12 +0100 Subject: try-with-resources and null resource In-Reply-To: References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> Message-ID: <4D3DD8A8.9020307@univ-mlv.fr> On 01/24/2011 08:30 PM, Tim Peierls wrote: > On Mon, Jan 24, 2011 at 2:00 PM, Joe Darcy wrote: > >> I think this stack trace can easily be explained to programmers by >> saying "the suppressed exception comes from the close call you did have >> to write yourself." >> > Agreed on all points, except I think you meant: s/did/didn't/ Am I the only one to think that having a generated code that throw an exception lately is a bad idea ? > --tim > R?mi From joe.darcy at oracle.com Mon Jan 24 12:00:50 2011 From: joe.darcy at oracle.com (Joe Darcy) Date: Mon, 24 Jan 2011 12:00:50 -0800 Subject: try-with-resources and null resource In-Reply-To: <4D3DD4CA.1070802@univ-mlv.fr> References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> <4D3DD4CA.1070802@univ-mlv.fr> Message-ID: <4D3DDA72.4040603@oracle.com> R?mi Forax wrote: > On 01/24/2011 08:00 PM, Joe Darcy wrote: >> On 1/22/2011 5:09 AM, R?mi Forax wrote: >>> On 01/21/2011 08:38 PM, Joe Darcy wrote: >>>> R?mi Forax wrote: >>>>> I think try-with-resources should do a null check before entering >>>>> in the try block. >>>>> >>>>> 4. try(AutoCloseable c = null) { >>>>> 5. // nothing >>>>> 6. } >>>>> >>>>> $ java TryWithresourceNPE >>>>> Exception in thread "main" java.lang.NullPointerException >>>>> at TryWithresourceNPE.main(TryWithresourceNPE.java:6) >>>>> >>>>> I got a NPE from the ends of the try block, I think it will be >>>>> better to detect the case >>>>> before entering in the try block like foreach or switch does. >>>>> >>>>> And with this code: >>>>> >>>>> 5. try(InputStream i = null) { >>>>> 6. i.available(); >>>>> 7. } >>>>> >>>>> I got the exception below which is not understandable if you don't >>>>> know >>>>> how try-with-resources is translated. >>>>> >>>>> $ java TryWithresourceNPE >>>>> Exception in thread "main" java.lang.NullPointerException >>>>> at TryWithresourceNPE.main(TryWithresourceNPE.java:6) >>>>> Suppressed: java.lang.NullPointerException >>>>> at TryWithresourceNPE.main(TryWithresourceNPE.java:7) >>>> >>>> I'm not too concerned about that stacktrace since the primary >>>> exception points to the right location. >>> >>> But the suppressed exception occurs in a generated code that the >>> user don't write. >> >> But that is the whole point of try-with-resources, to allow users to >> not have to write the messy and error-prone clean-up code. > > I have no problem if the error come from the close() itself, > the stacktrace will be explicit in that case. > > But here it comes because the spec allows try(...) to be used with null, > oh no wait! the generated finally block doesn't allow it. I would assign the responsibility differently: because the programmer uses a null expression to initialize a variable, a NullPointerException is generated when the variable is used. If the null-initialized variable is used inside the statement, there is an additional suppressed exception because of the guarantee to implicitly call close on the value when the block is exited. > > If you take a look to how try/finally are coded now, you will find a > nullcheck > before the try or in the finally block. > >> >>> I don't like the idea that a user mistake blow up in a generated code, >>> try-with-resources should protect itself. >> >> I think this stack trace can easily be explained to programmers by >> saying "the suppressed exception comes from the close call you did >> have to write yourself." > > You don't have to explain something which is not surprising. New features should be expected to require nonzero explanation simply by virtue of being new. -Joe From scolebourne at joda.org Mon Jan 24 12:24:39 2011 From: scolebourne at joda.org (Stephen Colebourne) Date: Mon, 24 Jan 2011 20:24:39 +0000 Subject: try-with-resources and null resource In-Reply-To: <4D3DD8A8.9020307@univ-mlv.fr> References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> <4D3DD8A8.9020307@univ-mlv.fr> Message-ID: On 24 January 2011 19:53, R?mi Forax wrote: > On 01/24/2011 08:30 PM, Tim Peierls wrote: >> On Mon, Jan 24, 2011 at 2:00 PM, Joe Darcy ?wrote: >> >>> I think this stack trace can easily be explained to programmers by >>> saying "the suppressed exception comes from the close call you did have >>> to write yourself." >>> >> Agreed on all points, except I think you meant: s/did/didn't/ > > Am I the only one to think that having a generated code that throw an > exception lately is a bad idea ? No you're not alone. Having the exception thrown at the first line that the null is invalid would be preferable, as in enums. The current behaviour isn't too bad, just non-optimal. For a new feature, I'd prefer it was optimal. Stephen From pbenedict at apache.org Mon Jan 24 12:36:51 2011 From: pbenedict at apache.org (Paul Benedict) Date: Mon, 24 Jan 2011 14:36:51 -0600 Subject: try-with-resources and null resource In-Reply-To: References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> <4D3DD8A8.9020307@univ-mlv.fr> Message-ID: +1 for a simple null check. The NPE with a suppressed NPE is just asking for a human interpreter. On Mon, Jan 24, 2011 at 2:24 PM, Stephen Colebourne wrote: > On 24 January 2011 19:53, R?mi Forax wrote: > > On 01/24/2011 08:30 PM, Tim Peierls wrote: > >> On Mon, Jan 24, 2011 at 2:00 PM, Joe Darcy > wrote: > >> > >>> I think this stack trace can easily be explained to programmers by > >>> saying "the suppressed exception comes from the close call you did have > >>> to write yourself." > >>> > >> Agreed on all points, except I think you meant: s/did/didn't/ > > > > Am I the only one to think that having a generated code that throw an > > exception lately is a bad idea ? > > No you're not alone. Having the exception thrown at the first line > that the null is invalid would be preferable, as in enums. > > The current behaviour isn't too bad, just non-optimal. For a new > feature, I'd prefer it was optimal. > > Stephen > > From pdoubleya at gmail.com Mon Jan 24 13:08:56 2011 From: pdoubleya at gmail.com (Patrick Wright) Date: Mon, 24 Jan 2011 22:08:56 +0100 Subject: try-with-resources and null resource In-Reply-To: <4D3DD8A8.9020307@univ-mlv.fr> References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> <4D3DD8A8.9020307@univ-mlv.fr> Message-ID: > Am I the only one to think that having a generated code that throw an > exception lately is a bad idea ? No, I agree with you on this. In particular because the paint is not yet dry on the code. I'd actually prefer if the spec just disallowed nulls in this case, and the exception stated that - "Illegal null pointer passed to try with resources" or something like that. But second best would be to see the line number associated with the try in the exception message. Patrick From tim at peierls.net Mon Jan 24 14:32:57 2011 From: tim at peierls.net (Tim Peierls) Date: Mon, 24 Jan 2011 17:32:57 -0500 Subject: try-with-resources and null resource In-Reply-To: References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> <4D3DD8A8.9020307@univ-mlv.fr> Message-ID: On Mon, Jan 24, 2011 at 3:24 PM, Stephen Colebourne wrote: > The current behaviour isn't too bad, just non-optimal. For a new feature, > I'd prefer it was optimal. > I don't think we have a consensus on the metric yet. My feeling: The current approach preserves options for everyone. Those who want a null check at resource init time can easily provide one: try (Resource r = checkNotNull(provideInitialResourceValue())) { // body } Those who don't want it don't have it forced on them. If the null check were always performed, I'd have no way to use try-with-resources *and* get the side-effects of executing the body up to the point where the null Resource is dereferenced. (Not saying one always wants to do this, or even that one often wants to do this, just that try-with-resources shouldn't prevent it.) --tim From isidore at setgame.com Mon Jan 24 14:32:58 2011 From: isidore at setgame.com (Llewellyn Falco) Date: Mon, 24 Jan 2011 14:32:58 -0800 Subject: try-with-resources and null resource In-Reply-To: <4D3DDF29.7060108@oracle.com> References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> <1CD26E8A-DF58-4EFF-BDFD-F4A25AF6FE50@setgame.com> <4D3DDF29.7060108@oracle.com> Message-ID: My option is; although this is odd code, it should not through an NPE exception. On Mon, Jan 24, 2011 at 12:20 PM, Joe Darcy wrote: > Print "hello from inside" and then throw an NPE from calling close on the > null resource. (Beforehand, javac will warn you don't use variable c inside > the block.) > > -Joe > > > Llewellyn Falco wrote: > >> What should the following do? >> Llewellyn >> >> Try(AutoCloseable c = null) >> { >> System.out.print("hello from inside"); >> } >> >> >> From forax at univ-mlv.fr Mon Jan 24 15:40:35 2011 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Tue, 25 Jan 2011 00:40:35 +0100 Subject: try-with-resources and null resource In-Reply-To: <4D3DDA72.4040603@oracle.com> References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> <4D3DD4CA.1070802@univ-mlv.fr> <4D3DDA72.4040603@oracle.com> Message-ID: <4D3E0DF3.8080100@univ-mlv.fr> On 01/24/2011 09:00 PM, Joe Darcy wrote: > R?mi Forax wrote: >> On 01/24/2011 08:00 PM, Joe Darcy wrote: >>> On 1/22/2011 5:09 AM, R?mi Forax wrote: >>>> On 01/21/2011 08:38 PM, Joe Darcy wrote: >>>>> R?mi Forax wrote: >>>>>> I think try-with-resources should do a null check before entering >>>>>> in the try block. >>>>>> >>>>>> 4. try(AutoCloseable c = null) { >>>>>> 5. // nothing >>>>>> 6. } >>>>>> >>>>>> $ java TryWithresourceNPE >>>>>> Exception in thread "main" java.lang.NullPointerException >>>>>> at TryWithresourceNPE.main(TryWithresourceNPE.java:6) >>>>>> >>>>>> I got a NPE from the ends of the try block, I think it will be >>>>>> better to detect the case >>>>>> before entering in the try block like foreach or switch does. >>>>>> >>>>>> And with this code: >>>>>> >>>>>> 5. try(InputStream i = null) { >>>>>> 6. i.available(); >>>>>> 7. } >>>>>> >>>>>> I got the exception below which is not understandable if you >>>>>> don't know >>>>>> how try-with-resources is translated. >>>>>> >>>>>> $ java TryWithresourceNPE >>>>>> Exception in thread "main" java.lang.NullPointerException >>>>>> at TryWithresourceNPE.main(TryWithresourceNPE.java:6) >>>>>> Suppressed: java.lang.NullPointerException >>>>>> at TryWithresourceNPE.main(TryWithresourceNPE.java:7) >>>>> >>>>> I'm not too concerned about that stacktrace since the primary >>>>> exception points to the right location. >>>> >>>> But the suppressed exception occurs in a generated code that the >>>> user don't write. >>> >>> But that is the whole point of try-with-resources, to allow users to >>> not have to write the messy and error-prone clean-up code. >> >> I have no problem if the error come from the close() itself, >> the stacktrace will be explicit in that case. >> >> But here it comes because the spec allows try(...) to be used with null, >> oh no wait! the generated finally block doesn't allow it. > > I would assign the responsibility differently: because the programmer > uses a null expression to initialize a variable, a > NullPointerException is generated when the variable is used. If the > null-initialized variable is used inside the statement, there is an > additional suppressed exception because of the guarantee to implicitly > call close on the value when the block is exited. The main problem is what if a try-with-resources have a body that don't use the variable. Let suppose I design this interface: interface Transaction extends AutoCloseable { public void close() throw TransactionException; } I want to use it with a try-with-resources to use its marvellous suppressed exceptions management: try(Transaction t = Transactions.getTransaction()) { // I don't use 't' here } here if the transaction is null, it will execute the body and then throws a NPE as a sidekick. I don't think it's the behaviour we want. > >> >> If you take a look to how try/finally are coded now, you will find a >> nullcheck >> before the try or in the finally block. >> >>> >>>> I don't like the idea that a user mistake blow up in a generated code, >>>> try-with-resources should protect itself. >>> >>> I think this stack trace can easily be explained to programmers by >>> saying "the suppressed exception comes from the close call you did >>> have to write yourself." >> >> You don't have to explain something which is not surprising. > > New features should be expected to require nonzero explanation simply > by virtue of being new. I have no problem to teach why try-with-resources was introduced or when to use it. I just don't want to explain why try-with-resources doesn't behave like all other Java constructs. They all works in a similar way: synchronized(null) { }, for(Object o: null) { }, switch(null) { } why try(Object o = null) {} should have a different semantics ? > > -Joe R?mi From forax at univ-mlv.fr Mon Jan 24 15:49:20 2011 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Tue, 25 Jan 2011 00:49:20 +0100 Subject: try-with-resources and null resource In-Reply-To: References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> <4D3DD8A8.9020307@univ-mlv.fr> Message-ID: <4D3E1000.6080309@univ-mlv.fr> On 01/24/2011 11:32 PM, Tim Peierls wrote: > On Mon, Jan 24, 2011 at 3:24 PM, Stephen Colebournewrote: > >> The current behaviour isn't too bad, just non-optimal. For a new feature, >> I'd prefer it was optimal. >> > I don't think we have a consensus on the metric yet. > > My feeling: The current approach preserves options for everyone. Those who > want a null check at resource init time can easily provide one: > > try (Resource r = checkNotNull(provideInitialResourceValue())) { > // body > } > > Those who don't want it don't have it forced on them. If the null check were > always performed, I'd have no way to use try-with-resources *and* get the > side-effects of executing the body up to the point where the null Resource > is dereferenced. side-effects => hours of debugging > (Not saying one always wants to do this, or even that one > often wants to do this, just that try-with-resources shouldn't prevent it.) Do you have a use case for that ? And even if you find a twisted use case, do you really think anyone will be able to understand that code ? > --tim R?mi From tim at peierls.net Mon Jan 24 16:43:15 2011 From: tim at peierls.net (Tim Peierls) Date: Mon, 24 Jan 2011 19:43:15 -0500 Subject: try-with-resources and null resource In-Reply-To: <4D3E1000.6080309@univ-mlv.fr> References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> <4D3DD8A8.9020307@univ-mlv.fr> <4D3E1000.6080309@univ-mlv.fr> Message-ID: On Mon, Jan 24, 2011 at 6:49 PM, R?mi Forax wrote: > > Those who don't want it don't have it forced on them. If the null check > were > > always performed, I'd have no way to use try-with-resources *and* get the > > side-effects of executing the body up to the point where the null > Resource > > is dereferenced. > > side-effects => hours of debugging > Maybe, but once it's debugged you don't want those side-effects to disappear because of magical null checks. > > (Not saying one always wants to do this, or even that one > > often wants to do this, just that try-with-resources shouldn't prevent > it.) > > Do you have a use case for that ? > Burden of proof goes the other way: There's a lot of existing code out there that could be rewritten to use try-with-resources, and I'd to have to bet that none of it would be better off waiting until the first attempt to dereference to throw NPE. > And even if you find a twisted use case, do you really think anyone will be > able to understand that code ? > The harder the code is to understand, the more important it is not to risk changing its behavior through over-protectiveness. If you want a null check at initialization, add it -- it's 14 characters if you use Guava. You can claim that you'll always want to check early, but you can't dictate that no one else should ever want to defer the check. --tim From tim at peierls.net Mon Jan 24 16:44:01 2011 From: tim at peierls.net (Tim Peierls) Date: Mon, 24 Jan 2011 19:44:01 -0500 Subject: try-with-resources and null resource In-Reply-To: References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> <4D3DD8A8.9020307@univ-mlv.fr> <4D3E1000.6080309@univ-mlv.fr> Message-ID: On Mon, Jan 24, 2011 at 7:43 PM, Tim Peierls wrote: > Burden of proof goes the other way: There's a lot of existing code out > there that could be rewritten to use try-with-resources, and I'd to have to > bet that none of it would be better off waiting until the first attempt to > dereference to throw NPE. > I'd *hate to* have to bet. :-) --tim From joe.darcy at oracle.com Mon Jan 24 18:16:05 2011 From: joe.darcy at oracle.com (Joe Darcy) Date: Mon, 24 Jan 2011 18:16:05 -0800 Subject: try-with-resources and null resource In-Reply-To: <4D3E0DF3.8080100@univ-mlv.fr> References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> <4D3DD4CA.1070802@univ-mlv.fr> <4D3DDA72.4040603@oracle.com> <4D3E0DF3.8080100@univ-mlv.fr> Message-ID: <4D3E3265.6050901@oracle.com> R?mi Forax wrote: > On 01/24/2011 09:00 PM, Joe Darcy wrote: >> R?mi Forax wrote: >>> On 01/24/2011 08:00 PM, Joe Darcy wrote: >>>> On 1/22/2011 5:09 AM, R?mi Forax wrote: >>>>> On 01/21/2011 08:38 PM, Joe Darcy wrote: >>>>>> R?mi Forax wrote: >>>>>>> I think try-with-resources should do a null check before >>>>>>> entering in the try block. >>>>>>> >>>>>>> 4. try(AutoCloseable c = null) { >>>>>>> 5. // nothing >>>>>>> 6. } >>>>>>> >>>>>>> $ java TryWithresourceNPE >>>>>>> Exception in thread "main" java.lang.NullPointerException >>>>>>> at TryWithresourceNPE.main(TryWithresourceNPE.java:6) >>>>>>> >>>>>>> I got a NPE from the ends of the try block, I think it will be >>>>>>> better to detect the case >>>>>>> before entering in the try block like foreach or switch does. >>>>>>> >>>>>>> And with this code: >>>>>>> >>>>>>> 5. try(InputStream i = null) { >>>>>>> 6. i.available(); >>>>>>> 7. } >>>>>>> >>>>>>> I got the exception below which is not understandable if you >>>>>>> don't know >>>>>>> how try-with-resources is translated. >>>>>>> >>>>>>> $ java TryWithresourceNPE >>>>>>> Exception in thread "main" java.lang.NullPointerException >>>>>>> at TryWithresourceNPE.main(TryWithresourceNPE.java:6) >>>>>>> Suppressed: java.lang.NullPointerException >>>>>>> at TryWithresourceNPE.main(TryWithresourceNPE.java:7) >>>>>> >>>>>> I'm not too concerned about that stacktrace since the primary >>>>>> exception points to the right location. >>>>> >>>>> But the suppressed exception occurs in a generated code that the >>>>> user don't write. >>>> >>>> But that is the whole point of try-with-resources, to allow users >>>> to not have to write the messy and error-prone clean-up code. >>> >>> I have no problem if the error come from the close() itself, >>> the stacktrace will be explicit in that case. >>> >>> But here it comes because the spec allows try(...) to be used with >>> null, >>> oh no wait! the generated finally block doesn't allow it. >> >> I would assign the responsibility differently: because the programmer >> uses a null expression to initialize a variable, a >> NullPointerException is generated when the variable is used. If the >> null-initialized variable is used inside the statement, there is an >> additional suppressed exception because of the guarantee to >> implicitly call close on the value when the block is exited. > > The main problem is what if a try-with-resources have a body that > don't use the variable. > Let suppose I design this interface: > > interface Transaction extends AutoCloseable { > public void close() throw TransactionException; > } > > I want to use it with a try-with-resources to use its marvellous > suppressed exceptions management: > > try(Transaction t = Transactions.getTransaction()) { > // I don't use 't' here > } Javac will warn you about this situation. > > here if the transaction is null, it will execute the body and then > throws a NPE as a sidekick. Yes, that is what the specification and implementation currently require. > I don't think it's the behaviour we want. > >> >>> >>> If you take a look to how try/finally are coded now, you will find a >>> nullcheck >>> before the try or in the finally block. >>> >>>> >>>>> I don't like the idea that a user mistake blow up in a generated >>>>> code, >>>>> try-with-resources should protect itself. >>>> >>>> I think this stack trace can easily be explained to programmers by >>>> saying "the suppressed exception comes from the close call you did >>>> have to write yourself." >>> >>> You don't have to explain something which is not surprising. >> >> New features should be expected to require nonzero explanation simply >> by virtue of being new. > > I have no problem to teach why try-with-resources was introduced or > when to use it. > I just don't want to explain why try-with-resources doesn't behave > like all other Java constructs. > They all works in a similar way: > synchronized(null) { }, for(Object o: null) { }, switch(null) { } > why try(Object o = null) {} should have a different semantics ? > From a certain point of view, try with resource does have the same semantics, you get the NPE from the location at which you go do something with the null value. If you don't use the null resource variable inside the try-with-resources block, you'll get the NPE in the compiler-generated call to close. If you use the null value inside the try-with-resources block, you'll get the first NPE in the block. I'll consider adding an explicit null check in the generated before calling close to generate a better exception message, something like "Attempt to call close on null resource " + r.name()) or "Attempt to call close on null resource at position " + i + " of " + n " resources." However, I don't plan to change the overall semantics of the feature to build in an up-front null-check. -Joe From joe.darcy at oracle.com Mon Jan 24 22:59:45 2011 From: joe.darcy at oracle.com (Joe Darcy) Date: Mon, 24 Jan 2011 22:59:45 -0800 Subject: Safe Varargs In-Reply-To: <4D06A974.6090003@oracle.com> References: <4D06A974.6090003@oracle.com> Message-ID: <4D3E74E1.6010000@oracle.com> FYI, I've pushed a changset [1] to annotate four core library methods with @SafeVarargs: * public static List java.util.Arrays.asList(T... a) * public static boolean java.util.Collections.addAll(Collection c, T... elements) * public static > java.util.EnumSet EnumSet.of(E first, E... rest) * protected final void javax.swing.SwingWorker.publish(V... chunks) I've also posted a description of the methodology used to find candidate methods to be so annotated [2]. -Joe [1] http://hg.openjdk.java.net/jdk7/tl/jdk/rev/dbfc1e419cb2 [2] "Project Coin: Safe Varargs in JDK Libraries" http://blogs.sun.com/darcy/entry/project_coin_safe_vararg_libraries On 12/13/2010 3:17 PM, Joe Darcy wrote: > Greetings. > > Following up on earlier work, the javac team has pushed a new > implementation of Project Coin's simplified varargs method invocation > feature. [1] The changes are scheduled to appear in the promotion of > JDK 7 b123. > > As envisioned previously, a new @Documented annotation type, > java.lang.SafeVararags, can be used to suppress warnings related to > unchecked warnings, both the new mandatory warnings at the declaration > site of a varargs method/constructor with a non-reifiable element type > and the existing unchecked warnings at the call sites of such methods. > A systematic application of this annotation to appropriate > declarations in the JDK libraries will follow as future work. > > Since new unchecked warnings are being introduced, those diligently > compiling with options like "-Xlint:unchecked -Werror" will see a > build error under JDK 7 if any of the suspicious varargs method > declarations are found. To address this, the @SafeVarargs annotation > can be applied to the declarations, if appropriate, or the > @SuppressWarnings({"unchecked", "varargs"}) annotation can be applied. > Unlike @SafeVarargs, the @SuppressWarnings annotation will not squelch > unchecked warnings at the call site of the annotated method. > > The specification of the new SafeVarargs annotation type is below. > > -Joe > > [1] http://hg.openjdk.java.net/jdk7/tl/jdk/rev/78885e69c42c > http://hg.openjdk.java.net/jdk7/tl/langtools/rev/7b99f98b3035 > > -=-=-=-=-=-=- > > Annotation Type SafeVarargs > > @Documented > @Retention(value=RUNTIME) > @Target(value={CONSTRUCTOR,METHOD}) > public @interface SafeVarargs > > A programmer assertion that the body of the annotated method or > constructor does not perform potentially unsafe operations on its > varargs parameter. Applying this annotation to a method or constructor > suppresses unchecked warnings about a non-reifiable variable-arity > (vararg) type and suppresses unchecked warnings about parameterized > array creation at call sites. > > In addition to the usage restrictions imposed by its @Target > meta-annotation, compilers are required to implement additional usage > restrictions on this annotation type; it is a compile-time error if a > method or constructor declaration is annotated with a @SafeVarargs > annotation, and either: > > * the declaration is a fixed-arity method or constructor > * the declaration is a variable-arity method that is neither > static nor final. > > Compilers are encouraged to issue warnings when this annotation type > is applied to a method or constructor declaration where: > > * The variable-arity parameter has a reifiable element type, > which includes primitive types, Object, and String. (The unchecked > warnings this annotation type suppresses already do not occur for a > reifiable element type.) > * The body of the method or constructor declaration performs > potentially unsafe operations, such as an assignment to an element of > the variable-arity parameter's array that generates an unchecked warning. > > Future versions of the platform may mandate compiler errors > for such unsafe operations. > > From reinier at zwitserloot.com Tue Jan 25 00:20:24 2011 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Tue, 25 Jan 2011 09:20:24 +0100 Subject: try-with-resources and null resource In-Reply-To: <4D3DCC44.8030302@oracle.com> References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> Message-ID: This reasoning (that the NPE on a line with just } on it is from the close() call you didn't have to write yourself) presupposes that everyone looking at an ARM block simply sees some syntactic sugar. This is true _now_. But will it still hold in 5 years? I surely hope not. When I'm looking at a foreach loop today, the notion "Iterator" doesn't even register in my mind anymore. Sure, you have to know how it works in plenty of circumstances - I'm not trying to argue that we'll eventually get to a place where a java developer can call himself that without even knowing about close(); methods. For example, if I attempt to foreach over a null ref, I interpret the NPE that results as caused by the fact that I tried to iterate over a null ref. I don't interpret it as the more technically correct: the .iterator() call that was generated failed, as it was called on a null ref. I've got a slight preference of simply not calling close() at all if the to-be-closed resource is a null pointer, but generating an exception that explicitly states the problem works too. --Reinier Zwitserloot On Mon, Jan 24, 2011 at 8:00 PM, Joe Darcy wrote: > On 1/22/2011 5:09 AM, R?mi Forax wrote: > > On 01/21/2011 08:38 PM, Joe Darcy wrote: > >> R?mi Forax wrote: > >>> I think try-with-resources should do a null check before entering in > >>> the try block. > >>> > >>> 4. try(AutoCloseable c = null) { > >>> 5. // nothing > >>> 6. } > >>> > >>> $ java TryWithresourceNPE > >>> Exception in thread "main" java.lang.NullPointerException > >>> at TryWithresourceNPE.main(TryWithresourceNPE.java:6) > >>> > >>> I got a NPE from the ends of the try block, I think it will be > >>> better to detect the case > >>> before entering in the try block like foreach or switch does. > >>> > >>> And with this code: > >>> > >>> 5. try(InputStream i = null) { > >>> 6. i.available(); > >>> 7. } > >>> > >>> I got the exception below which is not understandable if you don't know > >>> how try-with-resources is translated. > >>> > >>> $ java TryWithresourceNPE > >>> Exception in thread "main" java.lang.NullPointerException > >>> at TryWithresourceNPE.main(TryWithresourceNPE.java:6) > >>> Suppressed: java.lang.NullPointerException > >>> at TryWithresourceNPE.main(TryWithresourceNPE.java:7) > >> > >> I'm not too concerned about that stacktrace since the primary > >> exception points to the right location. > > > > But the suppressed exception occurs in a generated code that the user > > don't write. > > But that is the whole point of try-with-resources, to allow users to not > have to write the messy and error-prone clean-up code. > > > I don't like the idea that a user mistake blow up in a generated code, > > try-with-resources should protect itself. > > I think this stack trace can easily be explained to programmers by > saying "the suppressed exception comes from the close call you did have > to write yourself." > > -Joe > > > From reinier at zwitserloot.com Tue Jan 25 00:22:22 2011 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Tue, 25 Jan 2011 09:22:22 +0100 Subject: Update on JSR 334 Expert Group activities In-Reply-To: <4D3A1522.40901@oracle.com> References: <4D3A1522.40901@oracle.com> Message-ID: One good reason to disallow multiple underscores is to keep multiple underscores available for future language expansion. Presumably JDK7 isn't the last java release to have new language features. I admit I can't think of anything that would be best served by multiple underscores, but who knows what java needs 5 years from now? --Reinier Zwitserloot On Sat, Jan 22, 2011 at 12:22 AM, Joe Darcy wrote: > Hello. > > Besides working to address issues identified in the EDR draft [1], such > as refining the diamond specification, the JSR 334 expert group has been > considering other matters as well. One change being contemplated is > removing the ability to have multiple underscores between digits of a > literal; under that possible change, no underscore or a single > underscore would be allowed. The primary consideration here is to > prevent abuses of the underscores in literal feature that would obscure > program meaning; on the other hand, there may be reasonable uses of > repeated underscores that are desirable to allow. > > The expert group has agreed to one significant change from the EDR > draft: as called out as a possibility in the draft, support has been > dropped for the general expression form of the try-with-resources > statement. That is, support has been removed for passing a resource as a > general expression without an accompanying explicit variable declaration. > > Several technical problems were identified with allowing a general > expression: > > * Syntactic ambiguity: In the parser, it was not always possible to > distinguish with one-token look-ahead between the start of an Expression > and the start of a Type. Consider code like > > try(i < j // Ternary operator on variables i and j > ? new Resource1() : > new Resource2()) {...} > > compared to code like > > try(Box < Resource // Simple generic wrapper around a resource > > resourceBox = Box<>(new Resource1())) {...} > > A natural grammatical fallback short of banning Expression would be to > only allow a more restricted expression, such as Identifier. However, > that restricted grammar would require compiler changes to alert > programmers to some surprising legal code, as given in the following > examples. > > * Usability issues: Consider a try-with-resources statement being used > to manage an existing variable where the variable is mutated inside the > try block: > > public class TwrExamples implements AutoCloseable { > public static void main(String... args) { > TwrExamples twrEg1 = new TwrExamples(); > System.out.println(twrEg1.hashCode()); > > try(twrEg1) { > twrEg1 = new TwrExamples(); // Mutating the variable! > System.out.println(twrEg1.hashCode()); > } > } > > @Override > public void close() { > System.out.println(hashCode()); > } > } > > As try-with-resources was previously specified, this would cause close > to be called on the original value, not the value twrEg1 pointed to at > the time the try block finishes. In this case, the printed output of the > program may be something like: > 1607576787 > 1051296202 > 1607576787 > which indicates that while close was called on the original value, close > was not called on the new TwrExamples object created inside the > try-with-resources block. Either policy of calling code on the original > value or the value on exit of the block could be problematic. The > compiler did not issue any warnings about this situation and warnings > should be added if this feature were to be kept. (Mutating a resource > variable declared as part of the try-with-resources statement is illegal > since such variables are implicitly or explicitly final). > > Other complications that stemmed from supporting a general expression as > a resource were making sure the specification and implementation > accepted both > > try(null) {...} > > and > > try(myGenericMethodThatInfersTheTypeOfItsResult()) {} > > as valid programs. > > The main rationale for supporting general expressions was to allow > non-Closeable objects, such as locks, to be easily wrapped in a suitable > type to enjoy the call-method-on-block-exit guarantees of > try-with-resources. When this is desirable, the same effect can still be > achieved with an explicit resource declaration. As experience is gained > with try-with-resources, extensions to support other usage patterns will > be considered in future releases. > > I'm working with the javac team to remove support for this feature in an > upcoming JDK 7 build. > > -Joe > > [1] > http://mail.openjdk.java.net/pipermail/coin-dev/2011-January/002956.html > > > From brucechapman at paradise.net.nz Tue Jan 25 01:02:43 2011 From: brucechapman at paradise.net.nz (Bruce Chapman) Date: Tue, 25 Jan 2011 22:02:43 +1300 Subject: try-with-resources and null resource In-Reply-To: <4D3E0DF3.8080100@univ-mlv.fr> References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> <4D3DD4CA.1070802@univ-mlv.fr> <4D3DDA72.4040603@oracle.com> <4D3E0DF3.8080100@univ-mlv.fr> Message-ID: <4D3E91B3.4060506@paradise.net.nz> On 25/01/2011 12:40 p.m., R?mi Forax wrote: > On 01/24/2011 09:00 PM, Joe Darcy wrote: >> R?mi Forax wrote: >>> On 01/24/2011 08:00 PM, Joe Darcy wrote: >>>> On 1/22/2011 5:09 AM, R?mi Forax wrote: >>>>> On 01/21/2011 08:38 PM, Joe Darcy wrote: >>>>>> R?mi Forax wrote: >>>>>>> I think try-with-resources should do a null check before entering >>>>>>> in the try block. >>>>>>> >>>>>>> 4. try(AutoCloseable c = null) { >>>>>>> 5. // nothing >>>>>>> 6. } >>>>>>> >>>>>>> $ java TryWithresourceNPE >>>>>>> Exception in thread "main" java.lang.NullPointerException >>>>>>> at TryWithresourceNPE.main(TryWithresourceNPE.java:6) >>>>>>> >>>>>>> I got a NPE from the ends of the try block, I think it will be >>>>>>> better to detect the case >>>>>>> before entering in the try block like foreach or switch does. >>>>>>> >>>>>>> And with this code: >>>>>>> >>>>>>> 5. try(InputStream i = null) { >>>>>>> 6. i.available(); >>>>>>> 7. } >>>>>>> >>>>>>> I got the exception below which is not understandable if you >>>>>>> don't know >>>>>>> how try-with-resources is translated. >>>>>>> >>>>>>> $ java TryWithresourceNPE >>>>>>> Exception in thread "main" java.lang.NullPointerException >>>>>>> at TryWithresourceNPE.main(TryWithresourceNPE.java:6) >>>>>>> Suppressed: java.lang.NullPointerException >>>>>>> at TryWithresourceNPE.main(TryWithresourceNPE.java:7) >>>>>> I'm not too concerned about that stacktrace since the primary >>>>>> exception points to the right location. >>>>> But the suppressed exception occurs in a generated code that the >>>>> user don't write. >>>> But that is the whole point of try-with-resources, to allow users to >>>> not have to write the messy and error-prone clean-up code. >>> I have no problem if the error come from the close() itself, >>> the stacktrace will be explicit in that case. >>> >>> But here it comes because the spec allows try(...) to be used with null, >>> oh no wait! the generated finally block doesn't allow it. >> I would assign the responsibility differently: because the programmer >> uses a null expression to initialize a variable, a >> NullPointerException is generated when the variable is used. If the >> null-initialized variable is used inside the statement, there is an >> additional suppressed exception because of the guarantee to implicitly >> call close on the value when the block is exited. > The main problem is what if a try-with-resources have a body that don't > use the variable. > Let suppose I design this interface: > > interface Transaction extends AutoCloseable { > public void close() throw TransactionException; > } > > I want to use it with a try-with-resources to use its marvellous > suppressed exceptions management: > > try(Transaction t = Transactions.getTransaction()) { > // I don't use 't' here > } > > here if the transaction is null, it will execute the body and then > throws a NPE as a sidekick. > I don't think it's the behaviour we want. > >>> If you take a look to how try/finally are coded now, you will find a >>> nullcheck >>> before the try or in the finally block. >>> >>>>> I don't like the idea that a user mistake blow up in a generated code, >>>>> try-with-resources should protect itself. >>>> I think this stack trace can easily be explained to programmers by >>>> saying "the suppressed exception comes from the close call you did >>>> have to write yourself." >>> You don't have to explain something which is not surprising. >> New features should be expected to require nonzero explanation simply >> by virtue of being new. > I have no problem to teach why try-with-resources was introduced or when > to use it. > I just don't want to explain why try-with-resources doesn't behave like > all other Java constructs. > They all works in a similar way: > synchronized(null) { }, for(Object o: null) { }, switch(null) { } > why try(Object o = null) {} should have a different semantics ? It depends on your idea of "similar way'. The 'similar way' that correctly describes all these behaviours (including try) is "as soon as (but no sooner than) the value is dereferenced to access a field or call a method" To answer relative to your idea of 'similar way' which focuses on the syntactic parts of the statements, it is because all those examples require the null to be dereferenced prior to executing the block. 'synchronized' because you need to synchronize on an object (not null) before executing the block 'for' because you need to get an Iterator from the Iterable and call next() etc before executing the block 'switch' because you need to evaluate the null to determine which case block to execute (although if the language allowed null as a case then this requirement would disappear) 'try' however does not need to do anything with the null before executing the block. Basically it is just saying remember this till after the block then do something with it (close it). It is the semantics of those statements that requires the NPE for null before the block. Try doesn't have those semantics, switch could be designed either way, but was designed to require it, if it was designed to allow null case for String and enum, then there would be no NPE till maybe in the null case or default case blocks, making it like try. try behaves differently because the other constructs cannot behave like try. Bruce >> -Joe > R?mi > > > From brucechapman at paradise.net.nz Tue Jan 25 01:09:15 2011 From: brucechapman at paradise.net.nz (Bruce Chapman) Date: Tue, 25 Jan 2011 22:09:15 +1300 Subject: Update on JSR 334 Expert Group activities In-Reply-To: References: <4D3A1522.40901@oracle.com> Message-ID: <4D3E933B.2040506@paradise.net.nz> On 25/01/2011 9:22 p.m., Reinier Zwitserloot wrote: > One good reason to disallow multiple underscores is to keep multiple > underscores available for future language expansion. Presumably JDK7 isn't > the last java release to have new language features. I admit I can't think > of anything that would be best served by multiple underscores, but who knows > what java needs 5 years from now? so what future language expansion can you possibly foresee happening in the middle of a numeric literal? (which is the only place this single/multiple underscore issue relates to) It can't be used as a new operator because it is already a valid identifier. Bruce From tomasz.kowalczewski at gmail.com Tue Jan 25 01:57:06 2011 From: tomasz.kowalczewski at gmail.com (Tomasz Kowalczewski) Date: Tue, 25 Jan 2011 10:57:06 +0100 Subject: try-with-resources and null resource In-Reply-To: <4D3E91B3.4060506@paradise.net.nz> References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> <4D3DD4CA.1070802@univ-mlv.fr> <4D3DDA72.4040603@oracle.com> <4D3E0DF3.8080100@univ-mlv.fr> <4D3E91B3.4060506@paradise.net.nz> Message-ID: What if null is an expected (though maybe unwelcome) value and I want to do something with it inside try-with-resources: ClassLoader classLoader = ...; try(InputStream in = classLoader.getResourceAsStream("foo")) { // may return null if(in == null) { //let's fallback to some other resource searching scheme. } } My understanding is that 'in' is implicitly final and I cannot write any fallback code. When the resource is null I have no way of leaving the t-w-r block without generating exception. I cannot do: if(in == null) { in = new FakeInputStreamOrSomething(); } or: if(in == null) { in = classLoader.getResourceAsStream("some other resource"); } Of course I can do a proper null-checking logic before going into t-w-r: ClassLoader classLoader = ...; InputStream in = classLoader.getResourceAsStream("foo") if(in == null) { in = // fallback resource loading... } try(InputStream in2 = in) { } But that's still ugly. Thanks for listening, Tomek On Tue, Jan 25, 2011 at 10:02 AM, Bruce Chapman wrote: > On 25/01/2011 12:40 p.m., R?mi Forax wrote: >> On 01/24/2011 09:00 PM, Joe Darcy wrote: >>> R?mi Forax wrote: >>>> On 01/24/2011 08:00 PM, Joe Darcy wrote: >>>>> On 1/22/2011 5:09 AM, R?mi Forax wrote: >>>>>> On 01/21/2011 08:38 PM, Joe Darcy wrote: >>>>>>> R?mi Forax wrote: >>>>>>>> I think try-with-resources should do a null check before entering >>>>>>>> in the try block. >>>>>>>> >>>>>>>> 4. try(AutoCloseable c = null) { >>>>>>>> 5. ? ? // nothing >>>>>>>> 6. } >>>>>>>> >>>>>>>> $ java TryWithresourceNPE >>>>>>>> Exception in thread "main" java.lang.NullPointerException >>>>>>>> ? ? ? at TryWithresourceNPE.main(TryWithresourceNPE.java:6) >>>>>>>> >>>>>>>> I got a NPE from the ends of the try block, I think it will be >>>>>>>> better to detect the case >>>>>>>> before entering in the try block like foreach or switch does. >>>>>>>> >>>>>>>> And with this code: >>>>>>>> >>>>>>>> 5. try(InputStream i = null) { >>>>>>>> 6. ? ? ? i.available(); >>>>>>>> 7. } >>>>>>>> >>>>>>>> I got the exception below which is not understandable if you >>>>>>>> don't know >>>>>>>> how try-with-resources is translated. >>>>>>>> >>>>>>>> $ java TryWithresourceNPE >>>>>>>> Exception in thread "main" java.lang.NullPointerException >>>>>>>> ? ? ? at TryWithresourceNPE.main(TryWithresourceNPE.java:6) >>>>>>>> ? ? ? Suppressed: java.lang.NullPointerException >>>>>>>> ? ? ? ? ? at TryWithresourceNPE.main(TryWithresourceNPE.java:7) >>>>>>> I'm not too concerned about that stacktrace since the primary >>>>>>> exception points to the right location. >>>>>> But the suppressed exception occurs in a generated code that the >>>>>> user don't write. >>>>> But that is the whole point of try-with-resources, to allow users to >>>>> not have to write the messy and error-prone clean-up code. >>>> I have no problem if the error come from the close() itself, >>>> the stacktrace will be explicit in that case. >>>> >>>> But here it comes because the spec allows try(...) to be used with null, >>>> oh no wait! the generated finally block doesn't allow it. >>> I would assign the responsibility differently: because the programmer >>> uses a null expression to initialize a variable, a >>> NullPointerException is generated when the variable is used. ?If the >>> null-initialized variable is used inside the statement, there is an >>> additional suppressed exception because of the guarantee to implicitly >>> call close on the value when the block is exited. >> The main problem is what if a try-with-resources have a body that don't >> use the variable. >> Let suppose I design this interface: >> >> interface Transaction extends AutoCloseable { >> ? ? public void close() throw TransactionException; >> } >> >> I want to use it with a try-with-resources to use its marvellous >> suppressed exceptions management: >> >> try(Transaction t = Transactions.getTransaction()) { >> ? ? // I don't use 't' here >> } >> >> here if the transaction is null, it will execute the body and then >> throws a NPE as a sidekick. >> I don't think it's the behaviour we want. >> >>>> If you take a look to how try/finally are coded now, you will find a >>>> nullcheck >>>> before the try or in the finally block. >>>> >>>>>> I don't like the idea that a user mistake blow up in a generated code, >>>>>> try-with-resources should protect itself. >>>>> I think this stack trace can easily be explained to programmers by >>>>> saying "the suppressed exception comes from the close call you did >>>>> have to write yourself." >>>> You don't have to explain something which is not surprising. >>> New features should be expected to require nonzero explanation simply >>> by virtue of being new. >> I have no problem to teach why try-with-resources was introduced or when >> to use it. >> I just don't want to explain why try-with-resources doesn't behave like >> all other Java constructs. >> They all works in a similar way: >> ? ? synchronized(null) { }, for(Object o: null) { }, switch(null) { } >> why try(Object o = null) {} should have a different semantics ? > > It depends on your idea of "similar way'. The 'similar way' that > correctly describes all these behaviours (including try) is "as soon as > (but no sooner than) the value is dereferenced to access a field or call > a method" > > To answer relative to your idea of 'similar way' which focuses on the > syntactic parts of the statements, it is because all those examples > require the null to be dereferenced prior to executing the block. > > 'synchronized' because you need to synchronize on an object (not null) > before executing the block > 'for' because you need to get an Iterator from the Iterable and call > next() etc before executing the block > 'switch' because you need to evaluate the null to determine which case > block to execute (although if the language allowed null as a case then > this requirement would disappear) > > 'try' however does not need to do anything with the null before > executing the block. Basically it is just saying remember this till > after the block then do something with it (close it). > > It is the semantics of those statements that requires the NPE for null > before the block. Try doesn't have those semantics, switch could be > designed either way, but was designed to require it, if it was designed > to allow null case for String and enum, then there would be no NPE till > maybe in the null case or default case blocks, making it like try. > > try behaves differently because the other constructs cannot behave like try. > > Bruce >>> -Joe >> R?mi >> >> >> > > > -- Tomasz Kowalczewski From forax at univ-mlv.fr Tue Jan 25 04:14:31 2011 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Tue, 25 Jan 2011 13:14:31 +0100 Subject: try-with-resources and null resource In-Reply-To: <4D3E3265.6050901@oracle.com> References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> <4D3DD4CA.1070802@univ-mlv.fr> <4D3DDA72.4040603@oracle.com> <4D3E0DF3.8080100@univ-mlv.fr> <4D3E3265.6050901@oracle.com> Message-ID: <4D3EBEA7.8010008@univ-mlv.fr> On 01/25/2011 03:16 AM, Joe Darcy wrote: [...] >> >> The main problem is what if a try-with-resources have a body that >> don't use the variable. >> Let suppose I design this interface: >> >> interface Transaction extends AutoCloseable { >> public void close() throw TransactionException; >> } >> >> I want to use it with a try-with-resources to use its marvellous >> suppressed exceptions management: >> >> try(Transaction t = Transactions.getTransaction()) { >> // I don't use 't' here >> } > > > Javac will warn you about this situation. Why ? It's a fair code. And adding a new warning has a cost. If there is too much not-that-useful warnings, users will don't care about them or worst deactivate them all. If there is a warning, what is the way to fix it ? Introduce a t.getClass() ? try(Transaction t = Transactions.getTransaction()) { t.getClass(); // remove that stupid javac warning } That's exactly what I'm proposing :) > >> >> here if the transaction is null, it will execute the body and then >> throws a NPE as a sidekick. > > Yes, that is what the specification and implementation currently require. > >> I don't think it's the behaviour we want. >> >>> >>>> >>>> If you take a look to how try/finally are coded now, you will find >>>> a nullcheck >>>> before the try or in the finally block. >>>> >>>>> >>>>>> I don't like the idea that a user mistake blow up in a generated >>>>>> code, >>>>>> try-with-resources should protect itself. >>>>> >>>>> I think this stack trace can easily be explained to programmers by >>>>> saying "the suppressed exception comes from the close call you did >>>>> have to write yourself." >>>> >>>> You don't have to explain something which is not surprising. >>> >>> New features should be expected to require nonzero explanation >>> simply by virtue of being new. >> >> I have no problem to teach why try-with-resources was introduced or >> when to use it. >> I just don't want to explain why try-with-resources doesn't behave >> like all other Java constructs. >> They all works in a similar way: >> synchronized(null) { }, for(Object o: null) { }, switch(null) { } >> why try(Object o = null) {} should have a different semantics ? >> > > From a certain point of view, try with resource does have the same > semantics, you get the NPE from the location at which you go do > something with the null value. If you don't use the null resource > variable inside the try-with-resources block, you'll get the NPE in > the compiler-generated call to close. If you use the null value > inside the try-with-resources block, you'll get the first NPE in the > block. As Reinier said, I don't want to think about how the code is translated when I use a feature of a language. In my opinion, if you need to know how a feature is translated to use it, it's a design failure. Explaining bug 4030374 before it was fixed was a painful teaching moment. > > I'll consider adding an explicit null check in the generated before > calling close to generate a better exception message, something like > > "Attempt to call close on null resource " + r.name()) > > or > > "Attempt to call close on null resource at position " + i + " of " > + n " resources." That's better than nothing. But I don't like this solution because of the way the compiler translate try/finally. This check will appear two or more times in the bytecode. Also note that from the performance point of the doing the nullcheck up-front doesn't introduce any performance penalty because the VM has to do a nullcheck when calling close(). > > However, I don't plan to change the overall semantics of the feature > to build in an up-front null-check. try-with-resources fails to handle correctly nullable resource. You have no choice :) > > -Joe R?mi From reinier at zwitserloot.com Tue Jan 25 04:45:10 2011 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Tue, 25 Jan 2011 13:45:10 +0100 Subject: Update on JSR 334 Expert Group activities In-Reply-To: <4D3E933B.2040506@paradise.net.nz> References: <4D3A1522.40901@oracle.com> <4D3E933B.2040506@paradise.net.nz> Message-ID: Hmm, you're right. __ all by itself is an identifier. Nevermind. --Reinier Zwitserloot On Tue, Jan 25, 2011 at 10:09 AM, Bruce Chapman < brucechapman at paradise.net.nz> wrote: > On 25/01/2011 9:22 p.m., Reinier Zwitserloot wrote: > >> One good reason to disallow multiple underscores is to keep multiple >> underscores available for future language expansion. Presumably JDK7 isn't >> the last java release to have new language features. I admit I can't think >> of anything that would be best served by multiple underscores, but who >> knows >> what java needs 5 years from now? >> > > so what future language expansion can you possibly foresee happening in the > middle of a numeric literal? > (which is the only place this single/multiple underscore issue relates to) > > It can't be used as a new operator because it is already a valid > identifier. > > > Bruce > > From maurizio.cimadamore at oracle.com Tue Jan 25 04:45:58 2011 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Tue, 25 Jan 2011 12:45:58 +0000 Subject: try-with-resources and null resource In-Reply-To: <4D3EBEA7.8010008@univ-mlv.fr> References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> <4D3DD4CA.1070802@univ-mlv.fr> <4D3DDA72.4040603@oracle.com> <4D3E0DF3.8080100@univ-mlv.fr> <4D3E3265.6050901@oracle.com> <4D3EBEA7.8010008@univ-mlv.fr> Message-ID: <4D3EC606.7090603@oracle.com> >> Javac will warn you about this situation. > Why ? It's a fair code. > And adding a new warning has a cost. If there is too much > not-that-useful warnings, > users will don't care about them or worst deactivate them all. > If there is a warning, what is the way to fix it ? Introduce a > t.getClass() ? > > try(Transaction t = Transactions.getTransaction()) { > t.getClass(); // remove that stupid javac warning > } > > That's exactly what I'm proposing :) > Adding a warning has a cost, right - but this particular kind of warning can be activated on-demand using -Xlint:twr (and it's disabled by default). When do you say that the above code is fair, do you mean that it is a legal Java program or that it can actually achieve something good? I think the only case in which the above program is interesting is if Transaction.getTransactions() has some hidden side-effects. Otherwise the whole thing looks like a no-op (modulo Exceptions being thrown at runtime). We currently have some similar warnings in the following case: switch (xyz) { case 1: //do something here then fall-thorugh case 2: //do another thing } Which, to some extent, is another fair program... but I think that both programs (the one with unused twr variable and the one with fall-through) are somewhat suspicious enough to merit a 'style' warning. Moreover, this kind of warnings can be suppressed with the usual scheme - just add @SuppressWarnings("twr") to the enclosing method decl, and the warning will go away. Maurizio From forax at univ-mlv.fr Tue Jan 25 05:32:10 2011 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Tue, 25 Jan 2011 14:32:10 +0100 Subject: try-with-resources and null resource In-Reply-To: <4D3EC606.7090603@oracle.com> References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> <4D3DD4CA.1070802@univ-mlv.fr> <4D3DDA72.4040603@oracle.com> <4D3E0DF3.8080100@univ-mlv.fr> <4D3E3265.6050901@oracle.com> <4D3EBEA7.8010008@univ-mlv.fr> <4D3EC606.7090603@oracle.com> Message-ID: <4D3ED0DA.7060807@univ-mlv.fr> On 01/25/2011 01:45 PM, Maurizio Cimadamore wrote: > >>> Javac will warn you about this situation. >> Why ? It's a fair code. >> And adding a new warning has a cost. If there is too much >> not-that-useful warnings, >> users will don't care about them or worst deactivate them all. >> If there is a warning, what is the way to fix it ? Introduce a >> t.getClass() ? >> >> try(Transaction t = Transactions.getTransaction()) { >> t.getClass(); // remove that stupid javac warning >> } >> >> That's exactly what I'm proposing :) >> > Adding a warning has a cost, right - but this particular kind of > warning can be activated on-demand using -Xlint:twr (and it's disabled > by default). When do you say that the above code is fair, do you mean > that it is a legal Java program or that it can actually achieve > something good? Both. > I think the only case in which the above program is interesting is if > Transaction.getTransactions() has some hidden side-effects. Otherwise > the whole thing looks like a no-op (modulo Exceptions being thrown at > runtime). Usually the transaction is attached to the current thread using a thread-local value and the persistent manager can query it when necessary, by example, javax.persistentence.EntityTransaction works like that. > > We currently have some similar warnings in the following case: > > switch (xyz) { > case 1: //do something here then fall-thorugh > case 2: //do another thing > } > > > Which, to some extent, is another fair program... but I think that > both programs (the one with unused twr variable and the one with > fall-through) are somewhat suspicious enough to merit a 'style' warning. > > Moreover, this kind of warnings can be suppressed with the usual > scheme - just add @SuppressWarnings("twr") to the enclosing method > decl, and the warning will go away. > > Maurizio R?mi From mcnepp02 at googlemail.com Tue Jan 25 06:16:56 2011 From: mcnepp02 at googlemail.com (Gernot Neppert) Date: Tue, 25 Jan 2011 14:16:56 +0000 Subject: Safe Varargs In-Reply-To: <4D3E74E1.6010000@oracle.com> References: <4D06A974.6090003@oracle.com> <4D3E74E1.6010000@oracle.com> Message-ID: When reading the documentation for SafeVarargs, there were 2 things that I found noteworthy: 1. the distinction between mandatory compiler errors and recommended warnings seems somehow arbitrary: Why is the use of @SafeVarags on a method with reifiable variable-arity parameter not an error? Annotating such a method makes no more sense than annotating a method with fixed-arity! 2. On the contrary, the sentence 'Future versions of the platform may mandate compiler errors for such unsafe operations.' smells fishy: this would result in code that is perfectly safe as verified by the programmer to become illegal in a future version. The reason is that the compiler cannot possibly determine whether a 'potentially unsafe' operation is, in fact, unsafe. You need only have a look at java.util.Arrays.asList(T.. A) to see this: @SafeVarargs public static List asList(T... a) { return new ArrayList(a); } This would warrant a compiler warning since passing the variable-arity parameter to another method as an array is 'potentially unsafe'. It would be wrong, however, to reject the code 'in a future version'. 2011/1/25 Joe Darcy : >> In addition to the usage restrictions imposed by its @Target >> meta-annotation, compilers are required to implement additional usage >> restrictions on this annotation type; it is a compile-time error if a >> method or constructor declaration is annotated with a @SafeVarargs >> annotation, and either: >> >> ? ? ? ?* the declaration is a fixed-arity method or constructor >> ? ? ? ?* the declaration is a variable-arity method that is neither >> static nor final. >> >> Compilers are encouraged to issue warnings when this annotation type >> is applied to a method or constructor declaration where: >> >> ? ? ? ?* The variable-arity parameter has a reifiable element type, >> which includes primitive types, Object, and String. (The unchecked >> warnings this annotation type suppresses already do not occur for a >> reifiable element type.) >> ? ? ? ?* The body of the method or constructor declaration performs >> potentially unsafe operations, such as an assignment to an element of >> the variable-arity parameter's array that generates an unchecked warning. >> >> ? ? ? ? ?Future versions of the platform may mandate compiler errors >> for such unsafe operations. >> From forax at univ-mlv.fr Tue Jan 25 09:40:47 2011 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Tue, 25 Jan 2011 18:40:47 +0100 Subject: try-with-resources and null resource In-Reply-To: <4D3E91B3.4060506@paradise.net.nz> References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> <4D3DD4CA.1070802@univ-mlv.fr> <4D3DDA72.4040603@oracle.com> <4D3E0DF3.8080100@univ-mlv.fr> <4D3E91B3.4060506@paradise.net.nz> Message-ID: <4D3F0B1F.4050303@univ-mlv.fr> On 01/25/2011 10:02 AM, Bruce Chapman wrote: > On 25/01/2011 12:40 p.m., R?mi Forax wrote: >> On 01/24/2011 09:00 PM, Joe Darcy wrote: >>> R?mi Forax wrote: >>>> On 01/24/2011 08:00 PM, Joe Darcy wrote: >>>>> On 1/22/2011 5:09 AM, R?mi Forax wrote: >>>>>> On 01/21/2011 08:38 PM, Joe Darcy wrote: >>>>>>> R?mi Forax wrote: >>>>>>>> I think try-with-resources should do a null check before entering >>>>>>>> in the try block. >>>>>>>> >>>>>>>> 4. try(AutoCloseable c = null) { >>>>>>>> 5. // nothing >>>>>>>> 6. } >>>>>>>> >>>>>>>> $ java TryWithresourceNPE >>>>>>>> Exception in thread "main" java.lang.NullPointerException >>>>>>>> at TryWithresourceNPE.main(TryWithresourceNPE.java:6) >>>>>>>> >>>>>>>> I got a NPE from the ends of the try block, I think it will be >>>>>>>> better to detect the case >>>>>>>> before entering in the try block like foreach or switch does. >>>>>>>> >>>>>>>> And with this code: >>>>>>>> >>>>>>>> 5. try(InputStream i = null) { >>>>>>>> 6. i.available(); >>>>>>>> 7. } >>>>>>>> >>>>>>>> I got the exception below which is not understandable if you >>>>>>>> don't know >>>>>>>> how try-with-resources is translated. >>>>>>>> >>>>>>>> $ java TryWithresourceNPE >>>>>>>> Exception in thread "main" java.lang.NullPointerException >>>>>>>> at TryWithresourceNPE.main(TryWithresourceNPE.java:6) >>>>>>>> Suppressed: java.lang.NullPointerException >>>>>>>> at TryWithresourceNPE.main(TryWithresourceNPE.java:7) >>>>>>> I'm not too concerned about that stacktrace since the primary >>>>>>> exception points to the right location. >>>>>> But the suppressed exception occurs in a generated code that the >>>>>> user don't write. >>>>> But that is the whole point of try-with-resources, to allow users to >>>>> not have to write the messy and error-prone clean-up code. >>>> I have no problem if the error come from the close() itself, >>>> the stacktrace will be explicit in that case. >>>> >>>> But here it comes because the spec allows try(...) to be used with null, >>>> oh no wait! the generated finally block doesn't allow it. >>> I would assign the responsibility differently: because the programmer >>> uses a null expression to initialize a variable, a >>> NullPointerException is generated when the variable is used. If the >>> null-initialized variable is used inside the statement, there is an >>> additional suppressed exception because of the guarantee to implicitly >>> call close on the value when the block is exited. >> The main problem is what if a try-with-resources have a body that don't >> use the variable. >> Let suppose I design this interface: >> >> interface Transaction extends AutoCloseable { >> public void close() throw TransactionException; >> } >> >> I want to use it with a try-with-resources to use its marvellous >> suppressed exceptions management: >> >> try(Transaction t = Transactions.getTransaction()) { >> // I don't use 't' here >> } >> >> here if the transaction is null, it will execute the body and then >> throws a NPE as a sidekick. >> I don't think it's the behaviour we want. >> >>>> If you take a look to how try/finally are coded now, you will find a >>>> nullcheck >>>> before the try or in the finally block. >>>> >>>>>> I don't like the idea that a user mistake blow up in a generated code, >>>>>> try-with-resources should protect itself. >>>>> I think this stack trace can easily be explained to programmers by >>>>> saying "the suppressed exception comes from the close call you did >>>>> have to write yourself." >>>> You don't have to explain something which is not surprising. >>> New features should be expected to require nonzero explanation simply >>> by virtue of being new. >> I have no problem to teach why try-with-resources was introduced or when >> to use it. >> I just don't want to explain why try-with-resources doesn't behave like >> all other Java constructs. >> They all works in a similar way: >> synchronized(null) { }, for(Object o: null) { }, switch(null) { } >> why try(Object o = null) {} should have a different semantics ? > It depends on your idea of "similar way'. The 'similar way' that > correctly describes all these behaviours (including try) is "as soon as > (but no sooner than) the value is dereferenced to access a field or call > a method" > > To answer relative to your idea of 'similar way' which focuses on the > syntactic parts of the statements, it is because all those examples > require the null to be dereferenced prior to executing the block. > > 'synchronized' because you need to synchronize on an object (not null) > before executing the block > 'for' because you need to get an Iterator from the Iterable and call > next() etc before executing the block > 'switch' because you need to evaluate the null to determine which case > block to execute (although if the language allowed null as a case then > this requirement would disappear) > > 'try' however does not need to do anything with the null before > executing the block. Basically it is just saying remember this till > after the block then do something with it (close it). > > It is the semantics of those statements that requires the NPE for null > before the block. Try doesn't have those semantics, switch could be > designed either way, but was designed to require it, if it was designed > to allow null case for String and enum, then there would be no NPE till > maybe in the null case or default case blocks, making it like try. > > try behaves differently because the other constructs cannot behave like try. > > Bruce All cited construct including try() may dereference a value hence throw a NPE. switch(null) can jump to default or at the end of the switch block, if there is no default. for(Object o:null) { } can do not execute it's body. synchronized(null) can synchronized to a special token. try(Object o = null) { } can do not execute it's body But for switch, for and synchronized it was chosen to throw a NPE. R?mi From tim at peierls.net Tue Jan 25 10:09:30 2011 From: tim at peierls.net (Tim Peierls) Date: Tue, 25 Jan 2011 13:09:30 -0500 Subject: try-with-resources and null resource In-Reply-To: <4D3F0B1F.4050303@univ-mlv.fr> References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> <4D3DD4CA.1070802@univ-mlv.fr> <4D3DDA72.4040603@oracle.com> <4D3E0DF3.8080100@univ-mlv.fr> <4D3E91B3.4060506@paradise.net.nz> <4D3F0B1F.4050303@univ-mlv.fr> Message-ID: On Tue, Jan 25, 2011 at 12:40 PM, R?mi Forax wrote: > All cited construct including try() may dereference a value hence throw a > NPE. > > switch(null) can jump to default or at the end of the switch block, if > there is no default. > for(Object o:null) { } can do not execute its body. > synchronized(null) can synchronized to a special token. > try(Object o = null) { } can do not execute its body > > But for switch, for and synchronized it was chosen to throw a NPE. > This is a misleading analogy. The thing that a resource declaration most resembles is not try, switch, for, or synchronized, but an ordinary variable declaration with initializer. This code doesn't throw NPE when initializing r with null: R r = get(); try { maybeUse(r); } finally { r.close(); } Nor should this code: try ( R r = get(); ) { maybeUse(r); } --tim From joe.darcy at oracle.com Tue Jan 25 10:40:33 2011 From: joe.darcy at oracle.com (Joe Darcy) Date: Tue, 25 Jan 2011 10:40:33 -0800 Subject: Safe Varargs In-Reply-To: References: <4D06A974.6090003@oracle.com> <4D3E74E1.6010000@oracle.com> Message-ID: <4D3F1921.7020704@oracle.com> Gernot Neppert wrote: > When reading the documentation for SafeVarargs, there were 2 things > that I found noteworthy: > > 1. the distinction between mandatory compiler errors and recommended > warnings seems somehow arbitrary: > Why is the use of @SafeVarags on a method with reifiable > variable-arity parameter not an error? > Annotating such a method makes no more sense than annotating a method > with fixed-arity! > That is true, but is it is much easier for most Java programmers to tell whether or not a method is varargs then to tell whether or not the element type of the varargs parameters is reifiable. Quick, is Class reifiable or not? > 2. On the contrary, the sentence 'Future versions of the platform may > mandate compiler errors for such unsafe operations.' smells fishy: > this would result in code that is perfectly safe as verified by the > programmer to become illegal in a future version. The reason is that > the compiler cannot possibly determine whether a 'potentially unsafe' > operation is, in fact, unsafe. > For some definition of unsafe, there are classes of operations a compiler could determine were unsafe. Conversely for some definition of safe. > You need only have a look at java.util.Arrays.asList(T.. A) to see this: > > @SafeVarargs public static List asList(T... a) { > return new ArrayList(a); > } > > This would warrant a compiler warning since passing the variable-arity > parameter to another method as an array is 'potentially unsafe'. It > would be wrong, however, to reject the code 'in a future version'. > Arrays.asList is anomalous in its use of varargs since it explicitly wants to alias the the argument to serve as the backing store of a new collection. Typically, varargs methods just iterate over the elements of the array. -Joe From cay.horstmann at gmail.com Tue Jan 25 20:52:51 2011 From: cay.horstmann at gmail.com (Cay Horstmann) Date: Wed, 26 Jan 2011 11:52:51 +0700 Subject: Update on JSR 334 Expert Group activities In-Reply-To: <4D3E933B.2040506@paradise.net.nz> References: <4D3A1522.40901@oracle.com> <4D3E933B.2040506@paradise.net.nz> Message-ID: > On 25/01/2011 9:22 p.m., Reinier Zwitserloot wrote: > One good reason to disallow multiple underscores is to keep multiple > underscores available for future language expansion. Presumably JDK7 isn't > the last java release to have new language features. I admit I can't think > of anything that would be best served by multiple underscores, but who knows > what java needs 5 years from now? Morse code literals, ._.. .. _._ . _ .... .. ... Cheers, _._. ._ _.__ From fweimer at bfk.de Wed Jan 26 01:16:06 2011 From: fweimer at bfk.de (Florian Weimer) Date: Wed, 26 Jan 2011 09:16:06 +0000 Subject: try-with-resources and null resource In-Reply-To: (Tim Peierls's message of "Tue\, 25 Jan 2011 13\:09\:30 -0500") References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> <4D3DD4CA.1070802@univ-mlv.fr> <4D3DDA72.4040603@oracle.com> <4D3E0DF3.8080100@univ-mlv.fr> <4D3E91B3.4060506@paradise.net.nz> <4D3F0B1F.4050303@univ-mlv.fr> Message-ID: <828vy8auuh.fsf@mid.bfk.de> * Tim Peierls: > This is a misleading analogy. The thing that a resource declaration most > resembles is not try, switch, for, or synchronized, but an ordinary variable > declaration with initializer. > > This code doesn't throw NPE when initializing r with null: > > R r = get(); > try { > maybeUse(r); > } finally { > r.close(); > } But if R is a primitive type, it can throw during initialization. 8-) -- Florian Weimer BFK edv-consulting GmbH http://www.bfk.de/ Kriegsstra?e 100 tel: +49-721-96201-1 D-76133 Karlsruhe fax: +49-721-96201-99 From brucechapman at paradise.net.nz Wed Jan 26 01:23:50 2011 From: brucechapman at paradise.net.nz (Bruce Chapman) Date: Wed, 26 Jan 2011 22:23:50 +1300 Subject: try-with-resources and null resource In-Reply-To: References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> <4D3DD4CA.1070802@univ-mlv.fr> <4D3DDA72.4040603@oracle.com> <4D3E0DF3.8080100@univ-mlv.fr> <4D3E91B3.4060506@paradise.net.nz> Message-ID: <4D3FE826.1030707@paradise.net.nz> On 25/01/2011 10:57 p.m., Tomasz Kowalczewski wrote: > What if null is an expected (though maybe unwelcome) value and I want > to do something with it inside try-with-resources: > > ClassLoader classLoader = ...; > try(InputStream in = classLoader.getResourceAsStream("foo")) { // may > return null > > if(in == null) { > //let's fallback to some other resource searching scheme. > } > > } > > My understanding is that 'in' is implicitly final and I cannot write > any fallback code. 'in' is implicitly final but fallback can be done - see below. > When the resource is null I have no way of leaving > the t-w-r block without generating exception. That is correct. Maybe null resources should have close() skipped - that way it is up to you. > I cannot do: > > if(in == null) { > in = new FakeInputStreamOrSomething(); > } > > or: > > if(in == null) { > in = classLoader.getResourceAsStream("some other resource"); > } > > Of course I can do a proper null-checking logic before going into t-w-r: > > ClassLoader classLoader = ...; > InputStream in = classLoader.getResourceAsStream("foo") > > if(in == null) { > in = // fallback resource loading... > } > > try(InputStream in2 = in) { > } > > But that's still ugly. I'd solve most of this problem by putting the primary and fallback resource finding logic in a separate method and call that method as the resource initializer expression. However, as you said, that will still cause the t-w-r to always NPE if you cannot find any resource so return null. 'Always NPE on null' stops you from coding this in any way approaching a nice form. - unless of course null didn't NPE from any of the t-w-r implementation/background code, only from the block. That option might be worth further consideration. Bruce > Thanks for listening, > Tomek > From forax at univ-mlv.fr Wed Jan 26 05:58:14 2011 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Wed, 26 Jan 2011 14:58:14 +0100 Subject: try-with-resources and null resource In-Reply-To: References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> <4D3DD4CA.1070802@univ-mlv.fr> <4D3DDA72.4040603@oracle.com> <4D3E0DF3.8080100@univ-mlv.fr> <4D3E91B3.4060506@paradise.net.nz> <4D3F0B1F.4050303@univ-mlv.fr> Message-ID: <4D402876.1030804@univ-mlv.fr> On 01/25/2011 07:09 PM, Tim Peierls wrote: > On Tue, Jan 25, 2011 at 12:40 PM, R?mi Forax > wrote: > > All cited construct including try() may dereference a value hence > throw a NPE. > > switch(null) can jump to default or at the end of the switch > block, if there is no default. > for(Object o:null) { } can do not execute its body. > synchronized(null) can synchronized to a special token. > try(Object o = null) { } can do not execute its body > > But for switch, for and synchronized it was chosen to throw a NPE. > > > This is a misleading analogy. The thing that a resource declaration > most resembles is not try, switch, for, or synchronized, but an > ordinary variable declaration with initializer. > > This code doesn't throw NPE when initializing r with null: > > R r = get(); > try { > maybeUse(r); > } finally { > r.close(); > } > > Nor should this code: > > try ( > R r = get(); > ) { > maybeUse(r); > } > > --tim Again, your talking about implementation of the construct and not semantics of the construct. Perhaps, it's because try-with-resources reuses the same keyword as try/finally which doesn't help. try-with-resources is a new construct of the language, the question is what should this construct do if the resource is null. To make things crystal-clear, what should you be the semantics of: using(R r = get()) { maybeUse(r); } if get() returns null. R?mi From jesper.oqvist at cs.lth.se Wed Jan 26 07:53:19 2011 From: jesper.oqvist at cs.lth.se (=?ISO-8859-1?Q?Jesper_=D6qvist?=) Date: Wed, 26 Jan 2011 16:53:19 +0100 Subject: try-with-resources and null resource In-Reply-To: <4D39D048.1030908@univ-mlv.fr> References: <4D39BE95.60903@univ-mlv.fr> <4D39D048.1030908@univ-mlv.fr> Message-ID: <4D40436F.4030503@cs.lth.se> R?mi Forax wrote: > On 01/21/2011 07:24 PM, Paul Benedict wrote: > >> The NPE is more useful than the language silently doing nothing with a >> null pointer. While your idea is convenient, I believe it assumes too >> much. If anything, perhaps the language shouldn't allow an explicit >> null assignment in a try-with-resources block. >> > > Hi Paul, > the null assignement is just an example. Perhaps, you prefer this one: > > 4. try(AutoCloseable c = getAnAutoCloseableThatMayBeNull()) { > 5. // nothing > 6. } > > R?mi > I am concerned about the consistency between what the programmer expects and what the compiler produces. It seems to me that the following code should be legal, and execute without throwing an NPE: try (Resource r = null) { r = new SomeResource(); } However with a null check in the try part of the try-with-resource statement, or an NPE, execution might not pass through the statement as the programmer expects it to. Jesper From pbenedict at apache.org Wed Jan 26 08:04:15 2011 From: pbenedict at apache.org (Paul Benedict) Date: Wed, 26 Jan 2011 10:04:15 -0600 Subject: try-with-resources and null resource In-Reply-To: <4D40436F.4030503@cs.lth.se> References: <4D39BE95.60903@univ-mlv.fr> <4D39D048.1030908@univ-mlv.fr> <4D40436F.4030503@cs.lth.se> Message-ID: Jesper, I don't see how ignoring null helps the programmer. What does such a syntax mean? As I see it, try-with-resources is about obtaining a resource, doing work, and closing it. And since you can't obtain a resource out of a null reference, I think that is an error. That's why I prefer NPE. Paul 2011/1/26 Jesper ?qvist > R?mi Forax wrote: > >> On 01/21/2011 07:24 PM, Paul Benedict wrote: >> >> >>> The NPE is more useful than the language silently doing nothing with a >>> null pointer. While your idea is convenient, I believe it assumes too much. >>> If anything, perhaps the language shouldn't allow an explicit null >>> assignment in a try-with-resources block. >>> >>> >> >> Hi Paul, >> the null assignement is just an example. Perhaps, you prefer this one: >> >> 4. try(AutoCloseable c = getAnAutoCloseableThatMayBeNull()) { >> 5. // nothing >> 6. } >> >> R?mi >> >> > > I am concerned about the consistency between what the programmer expects > and what the compiler produces. > > It seems to me that the following code should be legal, and execute without > throwing an NPE: > > try (Resource r = null) { > r = new SomeResource(); > } > > However with a null check in the try part of the try-with-resource > statement, or an NPE, execution might not pass through the statement as the > programmer expects it to. > > Jesper > From serge.boulay at gmail.com Wed Jan 26 08:43:18 2011 From: serge.boulay at gmail.com (Serge Boulay) Date: Wed, 26 Jan 2011 11:43:18 -0500 Subject: try-with-resources and null resource In-Reply-To: References: <4D39BE95.60903@univ-mlv.fr> <4D39D048.1030908@univ-mlv.fr> <4D40436F.4030503@cs.lth.se> Message-ID: true, but that same example works in c# as Jesper has pointed out. Not that we are trying to copy the exact semantics of c# but I do wonder what their rational was. Perhaps we can learn from some of the decisions they made (good & bad). using (IDisposable x = null) { Console.WriteLine("we got here"); } This example writes "we got here". On Wed, Jan 26, 2011 at 11:04 AM, Paul Benedict wrote: > Jesper, > > I don't see how ignoring null helps the programmer. What does such a syntax > mean? As I see it, try-with-resources is about obtaining a resource, doing > work, and closing it. And since you can't obtain a resource out of a null > reference, I think that is an error. That's why I prefer NPE. > > Paul > > 2011/1/26 Jesper ?qvist > > > R?mi Forax wrote: > > > >> On 01/21/2011 07:24 PM, Paul Benedict wrote: > >> > >> > >>> The NPE is more useful than the language silently doing nothing with a > >>> null pointer. While your idea is convenient, I believe it assumes too > much. > >>> If anything, perhaps the language shouldn't allow an explicit null > >>> assignment in a try-with-resources block. > >>> > >>> > >> > >> Hi Paul, > >> the null assignement is just an example. Perhaps, you prefer this one: > >> > >> 4. try(AutoCloseable c = getAnAutoCloseableThatMayBeNull()) { > >> 5. // nothing > >> 6. } > >> > >> R?mi > >> > >> > > > > I am concerned about the consistency between what the programmer expects > > and what the compiler produces. > > > > It seems to me that the following code should be legal, and execute > without > > throwing an NPE: > > > > try (Resource r = null) { > > r = new SomeResource(); > > } > > > > However with a null check in the try part of the try-with-resource > > statement, or an NPE, execution might not pass through the statement as > the > > programmer expects it to. > > > > Jesper > > > > From joe.darcy at oracle.com Wed Jan 26 10:01:23 2011 From: joe.darcy at oracle.com (Joe Darcy) Date: Wed, 26 Jan 2011 10:01:23 -0800 Subject: try-with-resources and null resource In-Reply-To: <4D40436F.4030503@cs.lth.se> References: <4D39BE95.60903@univ-mlv.fr> <4D39D048.1030908@univ-mlv.fr> <4D40436F.4030503@cs.lth.se> Message-ID: <4D406173.3010300@oracle.com> On 1/26/2011 7:53 AM, Jesper ?qvist wrote: > R?mi Forax wrote: >> On 01/21/2011 07:24 PM, Paul Benedict wrote: >> >>> The NPE is more useful than the language silently doing nothing with a >>> null pointer. While your idea is convenient, I believe it assumes too >>> much. If anything, perhaps the language shouldn't allow an explicit >>> null assignment in a try-with-resources block. >>> >> Hi Paul, >> the null assignement is just an example. Perhaps, you prefer this one: >> >> 4. try(AutoCloseable c = getAnAutoCloseableThatMayBeNull()) { >> 5. // nothing >> 6. } >> >> R?mi >> > I am concerned about the consistency between what the programmer expects > and what the compiler produces. > > It seems to me that the following code should be legal, and execute > without throwing an NPE: > > try (Resource r = null) { > r = new SomeResource(); > } This code will be rejected by the compiler since r is implicitly final and thus the assignment to r inside the block will be reported as erroneous. -Joe From tim at peierls.net Wed Jan 26 10:05:21 2011 From: tim at peierls.net (Tim Peierls) Date: Wed, 26 Jan 2011 13:05:21 -0500 Subject: try-with-resources and null resource In-Reply-To: <4D402876.1030804@univ-mlv.fr> References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> <4D3DD4CA.1070802@univ-mlv.fr> <4D3DDA72.4040603@oracle.com> <4D3E0DF3.8080100@univ-mlv.fr> <4D3E91B3.4060506@paradise.net.nz> <4D3F0B1F.4050303@univ-mlv.fr> <4D402876.1030804@univ-mlv.fr> Message-ID: On Wed, Jan 26, 2011 at 8:58 AM, R?mi Forax wrote: > This code doesn't throw NPE when initializing r with null: > > R r = get(); > try { > maybeUse(r); > } finally { > r.close(); > } > > Nor should this code: > > try ( > R r = get(); > ) { > maybeUse(r); > } > > --tim > > > Again, you're talking about implementation of the construct and not > semantics of the construct. > No, I am writing about what I think the semantics of the construct should be. I'm drawing an analogy between two constructs, one old, one new, that many users will see as similar, rightly or wrongly. Their expectations for the new construct's semantics will be shaped by this perception. I claim that most users won't expect NPE to be thrown immediately if the initializer is null, and that they will expect NPE to be thrown on the first attempt to dereference a null. They'll expect this because that's what happens in the analogous case. You can say the analogy is false, you can say that people should approach this construct as being radically different from try-finally, you can even say that most people are sloppy thinkers. But you can't change how they think by wishing, and it would be wrong to design the feature without taking such people into account. (You could also claim that I'm wrong about how the average user will respond to this new feature. But it doesn't sound like you're trying to make that case.) > Perhaps it's because try-with-resources reuses the same keyword as > try/finally, which doesn't help. > To the contrary, I think this re-use of the try keyword will be very helpful to users trying to understand the new construct. I don't think most people will think about the new feature as being similar to things like switch or enhanced for. Switch takes an expression, and enhanced for uses a colon rather than equals, and thus doesn't look like a regular declaration. (If anything, they'll see a connection between t-w-r and the initialization clause of a traditional for loop.) To make things crystal-clear, what should you [sic] be the semantics of: > using(R r = get()) { > maybeUse(r); > } > if get() returns null? > I think you're asking whether the users' expectations would be different if the construct used a different keyword. My answer: Maybe, but how is this relevant? People won't be thinking about alternative design choices when attempting to understand how the feature behaves. It is crystal clear that if you were designing this language feature you'd do it differently! :-) --tim From brucechapman at paradise.net.nz Wed Jan 26 10:00:15 2011 From: brucechapman at paradise.net.nz (Bruce Chapman) Date: Thu, 27 Jan 2011 07:00:15 +1300 Subject: try-with-resources and null resource In-Reply-To: <4D40436F.4030503@cs.lth.se> References: <4D39BE95.60903@univ-mlv.fr> <4D39D048.1030908@univ-mlv.fr> <4D40436F.4030503@cs.lth.se> Message-ID: <4D40612F.20009@paradise.net.nz> On 27/01/2011 4:53 a.m., Jesper ?qvist wrote: > R?mi Forax wrote: >> On 01/21/2011 07:24 PM, Paul Benedict wrote: >> >>> The NPE is more useful than the language silently doing nothing with a >>> null pointer. While your idea is convenient, I believe it assumes too >>> much. If anything, perhaps the language shouldn't allow an explicit >>> null assignment in a try-with-resources block. >>> >> Hi Paul, >> the null assignement is just an example. Perhaps, you prefer this one: >> >> 4. try(AutoCloseable c = getAnAutoCloseableThatMayBeNull()) { >> 5. // nothing >> 6. } >> >> R?mi >> > I am concerned about the consistency between what the programmer expects > and what the compiler produces. > > It seems to me that the following code should be legal, and execute > without throwing an NPE: > > try (Resource r = null) { > r = new SomeResource(); > } Jesper, you missed the point that the resource variable is effectively final, so you are not allowed to assign another value to it later (that would cause another whole can of worms) Bruce > However with a null check in the try part of the try-with-resource > statement, or an NPE, execution might not pass through the statement as > the programmer expects it to. > > Jesper > > From jesper.oqvist at cs.lth.se Wed Jan 26 10:15:28 2011 From: jesper.oqvist at cs.lth.se (=?ISO-8859-1?Q?Jesper_=D6qvist?=) Date: Wed, 26 Jan 2011 19:15:28 +0100 Subject: try-with-resources and null resource In-Reply-To: <4D406173.3010300@oracle.com> References: <4D39BE95.60903@univ-mlv.fr> <4D39D048.1030908@univ-mlv.fr> <4D40436F.4030503@cs.lth.se> <4D406173.3010300@oracle.com> Message-ID: <4D4064C0.3060702@cs.lth.se> On 2011-01-26 19:01, Joe Darcy wrote: > On 1/26/2011 7:53 AM, Jesper ?qvist wrote: >> R?mi Forax wrote: >>> On 01/21/2011 07:24 PM, Paul Benedict wrote: >>> >>>> The NPE is more useful than the language silently doing nothing with a >>>> null pointer. While your idea is convenient, I believe it assumes too >>>> much. If anything, perhaps the language shouldn't allow an explicit >>>> null assignment in a try-with-resources block. >>>> >>> Hi Paul, >>> the null assignement is just an example. Perhaps, you prefer this one: >>> >>> 4. try(AutoCloseable c = getAnAutoCloseableThatMayBeNull()) { >>> 5. // nothing >>> 6. } >>> >>> R?mi >>> >> I am concerned about the consistency between what the programmer expects >> and what the compiler produces. >> >> It seems to me that the following code should be legal, and execute >> without throwing an NPE: >> >> try (Resource r = null) { >> r = new SomeResource(); >> } > > This code will be rejected by the compiler since r is implicitly final > and thus the assignment to r inside the block will be reported as > erroneous. > > -Joe I did not know the resource would be implicitly final. An oversight on my part. Thanks for clearing this up! Jesper From joe.darcy at oracle.com Wed Jan 26 12:12:00 2011 From: joe.darcy at oracle.com (Joe Darcy) Date: Wed, 26 Jan 2011 12:12:00 -0800 Subject: Update on JSR 334 Expert Group activities In-Reply-To: References: <4D3A1522.40901@oracle.com> <4D3E933B.2040506@paradise.net.nz> Message-ID: <4D408010.4060304@oracle.com> On 1/25/2011 8:52 PM, Cay Horstmann wrote: >> On 25/01/2011 9:22 p.m., Reinier Zwitserloot wrote: >> One good reason to disallow multiple underscores is to keep multiple >> underscores available for future language expansion. Presumably JDK7 isn't >> the last java release to have new language features. I admit I can't think >> of anything that would be best served by multiple underscores, but who knows >> what java needs 5 years from now? > Morse code literals, ._.. .. _._ . _ .... .. ... > > Cheers, > > _._. ._ _.__ ..-. .-- .. .--, given that the FCC has dropped the Morse code requirement to obtain an amateur radio license in the US [1], I don't see a growing need for Morse code literals five years hence! -Joe [1] http://en.wikipedia.org/wiki/Amateur_radio_licensing_in_the_United_States#Technician:_the_first_license_without_Morse_code From jjb at google.com Wed Jan 26 16:14:54 2011 From: jjb at google.com (Joshua Bloch) Date: Wed, 26 Jan 2011 16:14:54 -0800 Subject: Update on JSR 334 Expert Group activities In-Reply-To: <4D408010.4060304@oracle.com> References: <4D3A1522.40901@oracle.com> <4D3E933B.2040506@paradise.net.nz> <4D408010.4060304@oracle.com> Message-ID: Joe, Well, after the impending EMP destroys all digital devices, perhaps there will be a resurgence of Morse Code. But on the other hand, there won't be any CPUs to take advantage of our fine specifications. Josh On Wed, Jan 26, 2011 at 12:12 PM, Joe Darcy wrote: > On 1/25/2011 8:52 PM, Cay Horstmann wrote: > >> On 25/01/2011 9:22 p.m., Reinier Zwitserloot wrote: > >> One good reason to disallow multiple underscores is to keep multiple > >> underscores available for future language expansion. Presumably JDK7 > isn't > >> the last java release to have new language features. I admit I can't > think > >> of anything that would be best served by multiple underscores, but who > knows > >> what java needs 5 years from now? > > Morse code literals, ._.. .. _._ . _ .... .. ... > > > > Cheers, > > > > _._. ._ _.__ > > ..-. .-- .. .--, given that the FCC has dropped the Morse code > requirement to obtain an amateur radio license in the US [1], I don't > see a growing need for Morse code literals five years hence! > > -Joe > > [1] > > http://en.wikipedia.org/wiki/Amateur_radio_licensing_in_the_United_States#Technician:_the_first_license_without_Morse_code > > > From joe.darcy at oracle.com Wed Jan 26 16:47:30 2011 From: joe.darcy at oracle.com (Joe Darcy) Date: Wed, 26 Jan 2011 16:47:30 -0800 Subject: Update on JSR 334 Expert Group activities In-Reply-To: References: <4D3A1522.40901@oracle.com> <4D3E933B.2040506@paradise.net.nz> <4D408010.4060304@oracle.com> Message-ID: <4D40C0A2.1060204@oracle.com> And the resources that need managing in that situation will not be AutoCloseable ones! -Joe Joshua Bloch wrote: > Joe, > > > Well, after the impending EMP destroys all digital devices, perhaps > there will be a resurgence of Morse Code. But on the other hand, > there won't be any CPUs to take advantage of our fine specifications. > > Josh > > On Wed, Jan 26, 2011 at 12:12 PM, Joe Darcy > wrote: > > On 1/25/2011 8:52 PM, Cay Horstmann wrote: > >> On 25/01/2011 9:22 p.m., Reinier Zwitserloot wrote: > >> One good reason to disallow multiple underscores is to keep > multiple > >> underscores available for future language expansion. Presumably > JDK7 isn't > >> the last java release to have new language features. I admit I > can't think > >> of anything that would be best served by multiple underscores, > but who knows > >> what java needs 5 years from now? > > Morse code literals, ._.. .. _._ . _ .... .. ... > > > > Cheers, > > > > _._. ._ _.__ > > ..-. .-- .. .--, given that the FCC has dropped the Morse code > requirement to obtain an amateur radio license in the US [1], I don't > see a growing need for Morse code literals five years hence! > > -Joe > > [1] > http://en.wikipedia.org/wiki/Amateur_radio_licensing_in_the_United_States#Technician:_the_first_license_without_Morse_code > > > From scolebourne at joda.org Thu Jan 27 01:10:31 2011 From: scolebourne at joda.org (Stephen Colebourne) Date: Thu, 27 Jan 2011 09:10:31 +0000 Subject: try-with-resources and null resource In-Reply-To: References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> <4D3DD4CA.1070802@univ-mlv.fr> <4D3DDA72.4040603@oracle.com> <4D3E0DF3.8080100@univ-mlv.fr> <4D3E91B3.4060506@paradise.net.nz> <4D3F0B1F.4050303@univ-mlv.fr> <4D402876.1030804@univ-mlv.fr> Message-ID: On 26 January 2011 18:05, Tim Peierls wrote: > No, I am writing about what I think the semantics of the construct should > be. I'm drawing an analogy between two constructs, one old, one new, that > many users will see as similar, rightly or wrongly. Their expectations for > the new construct's semantics will be shaped by this perception. I claim > that most users won't expect NPE to be thrown immediately if the initializer > is null, and that they will expect NPE to be thrown on the first attempt to > dereference a null. They'll expect this because that's what happens in the > analogous case. > > You can say the analogy is false, you can say that people should approach > this construct as being radically different from try-finally, you can even > say that most people are sloppy thinkers. But you can't change how they > think by wishing, and it would be wrong to design the feature without taking > such people into account. Funnily enough, I have proposed similar analogies in the past. But they are seductively dangerous. How many devs looking at a foreach loop know it uses an iterator? Or an index if its an array? The same applies here. A similar case is closures/lambdas. There, the analogy is to inner classes, yet after much thought, Oracle has come to the same conclusion I did - that "this" within a lambda should not act as "this" does in an inner class. Sometimes, we have to break with the analogy to get the right result. Anyway, a real use case is far more helpful: Consider getResourceAsStream() which returns null if the resource does not exist: try (InputStream stream = getClass().getResourceAsStream("/com/foo/mightOrMightNotExist")) { if (stream != null) { readStream(stream); } } This will fail ATM, because of that null, yet the code is perfectly clear and readable. What's the alternative? InputStream stream = getClass().getResourceAsStream("/com/foo/mightOrMightNotExist"); if (stream != null) { try (InputStream stream2 = stream) { readStream(stream2); } } That now works, but is significantly less clear to read, more verbose and more prone to accidental refactoring. In fact, there was a bug when I first typed this email, as I wrote readStream(stream) rather than readStream(stream2). In this case, it would have no bad effects, but other similar cases might. In fact, I'd probably still write: InputStream stream = getClass().getResourceAsStream("/com/foo/mightOrMightNotExist"); try { if (stream != null) { readStream(stream); } finally { org.apache.commons.lang.IOUtils.closeQuietly(stream); } } as it is clearer than the t-w-r version. Executive summary: C# has got it right. Null resources should be silently be accepted. Priority. Initially I said this didn't matter much to me. With this new use case (straight out of my day job yesterday), I really care about my conclusion now. Please reconsider the semantics based on this use case. Stephen From forax at univ-mlv.fr Thu Jan 27 01:09:02 2011 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Thu, 27 Jan 2011 10:09:02 +0100 Subject: try-with-resources and null resource In-Reply-To: References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> <4D3DD4CA.1070802@univ-mlv.fr> <4D3DDA72.4040603@oracle.com> <4D3E0DF3.8080100@univ-mlv.fr> <4D3E91B3.4060506@paradise.net.nz> <4D3F0B1F.4050303@univ-mlv.fr> <4D402876.1030804@univ-mlv.fr> Message-ID: <4D41362E.6040802@univ-mlv.fr> On 01/26/2011 07:05 PM, Tim Peierls wrote: > On Wed, Jan 26, 2011 at 8:58 AM, R?mi Forax > wrote: > >> This code doesn't throw NPE when initializing r with null: >> >> R r = get(); >> try { >> maybeUse(r); >> } finally { >> r.close(); >> } >> >> Nor should this code: >> >> try ( >> R r = get(); >> ) { >> maybeUse(r); >> } >> >> --tim > > Again, you're talking about implementation of the construct and > not semantics of the construct. > > > No, I am writing about what I think the semantics of the construct > should be. I'm drawing an analogy between two constructs, one old, one > new, that many users will see as similar, rightly or wrongly. Their > expectations for the new construct's semantics will be shaped by this > perception. I claim that most users won't expect NPE to be thrown > immediately if the initializer is null, and that they will expect NPE > to be thrown on the first attempt to dereference a null. They'll > expect this because that's what happens in the analogous case. > > You can say the analogy is false, you can say that people should > approach this construct as being radically different from try-finally, > you can even say that most people are sloppy thinkers. But you can't > change how they think by wishing, and it would be wrong to design the > feature without taking such people into account. > > (You could also claim that I'm wrong about how the average user will > respond to this new feature. But it doesn't sound like you're trying > to make that case.) > > Perhaps it's because try-with-resources reuses the same keyword as > try/finally, which doesn't help. > > > To the contrary, I think this re-use of the try keyword will be very > helpful to users trying to understand the new construct. > > I don't think most people will think about the new feature as being > similar to things like switch or enhanced for. Switch takes an > expression, and enhanced for uses a colon rather than equals, and thus > doesn't look like a regular declaration. (If anything, they'll see a > connection between t-w-r and the initialization clause of a > traditional for loop.) > > To make things crystal-clear, what should you [sic] be the > semantics of: > using(R r = get()) { > maybeUse(r); > } > if get() returns null? > > > I think you're asking whether the users' expectations would be > different if the construct used a different keyword. My answer: Maybe, > but how is this relevant? People won't be thinking about alternative > design choices when attempting to understand how the feature behaves. > > It is crystal clear that if you were designing this language feature > you'd do it differently! :-) > > --tim Tim, try-with-resources is different from try/finally (not radically I agree) because try-with-resources encompass the declaration of the variable. try-with-resource not only manage the resource but also the variable; by example it declare it final implicitly; storing the resource. That's why I think try-with-resources should throw a NPE when trying to assign a non existing (null) resource to the variable it manage. R?mi From forax at univ-mlv.fr Thu Jan 27 01:20:26 2011 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Thu, 27 Jan 2011 10:20:26 +0100 Subject: try-with-resources and null resource In-Reply-To: References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> <4D3DD4CA.1070802@univ-mlv.fr> <4D3DDA72.4040603@oracle.com> <4D3E0DF3.8080100@univ-mlv.fr> <4D3E91B3.4060506@paradise.net.nz> <4D3F0B1F.4050303@univ-mlv.fr> <4D402876.1030804@univ-mlv.fr> Message-ID: <4D4138DA.5010009@univ-mlv.fr> On 01/27/2011 10:10 AM, Stephen Colebourne wrote: > On 26 January 2011 18:05, Tim Peierls wrote: >> No, I am writing about what I think the semantics of the construct should >> be. I'm drawing an analogy between two constructs, one old, one new, that >> many users will see as similar, rightly or wrongly. Their expectations for >> the new construct's semantics will be shaped by this perception. I claim >> that most users won't expect NPE to be thrown immediately if the initializer >> is null, and that they will expect NPE to be thrown on the first attempt to >> dereference a null. They'll expect this because that's what happens in the >> analogous case. >> >> You can say the analogy is false, you can say that people should approach >> this construct as being radically different from try-finally, you can even >> say that most people are sloppy thinkers. But you can't change how they >> think by wishing, and it would be wrong to design the feature without taking >> such people into account. > Funnily enough, I have proposed similar analogies in the past. But > they are seductively dangerous. How many devs looking at a foreach > loop know it uses an iterator? Or an index if its an array? The same > applies here. > > A similar case is closures/lambdas. There, the analogy is to inner > classes, yet after much thought, Oracle has come to the same > conclusion I did - that "this" within a lambda should not act as > "this" does in an inner class. Sometimes, we have to break with the > analogy to get the right result. > > Anyway, a real use case is far more helpful: > > Consider getResourceAsStream() which returns null if the resource does > not exist: > > try (InputStream stream = > getClass().getResourceAsStream("/com/foo/mightOrMightNotExist")) { > if (stream != null) { > readStream(stream); > } > } > > This will fail ATM, because of that null, yet the code is perfectly > clear and readable. What's the alternative? > > InputStream stream = > getClass().getResourceAsStream("/com/foo/mightOrMightNotExist"); > if (stream != null) { > try (InputStream stream2 = stream) { > readStream(stream2); > } > } > > That now works, but is significantly less clear to read, more verbose > and more prone to accidental refactoring. > > In fact, there was a bug when I first typed this email, as I wrote > readStream(stream) rather than readStream(stream2). In this case, it > would have no bad effects, but other similar cases might. > > In fact, I'd probably still write: > InputStream stream = > getClass().getResourceAsStream("/com/foo/mightOrMightNotExist"); > try { > if (stream != null) { > readStream(stream); > } finally { > org.apache.commons.lang.IOUtils.closeQuietly(stream); > } > } > > as it is clearer than the t-w-r version. but you lost the management of suppressed exceptions. > > Executive summary: C# has got it right. Null resources should be > silently be accepted. This other semantics is also acceptable. And better that the current specified semantics. > Priority. Initially I said this didn't matter much to me. With this > new use case (straight out of my day job yesterday), I really care > about my conclusion now. Please reconsider the semantics based on this > use case. > > Stephen R?mi From mcnepp02 at googlemail.com Thu Jan 27 04:19:16 2011 From: mcnepp02 at googlemail.com (Gernot Neppert) Date: Thu, 27 Jan 2011 12:19:16 +0000 Subject: try-with-resources and null resource In-Reply-To: References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> <4D3DD4CA.1070802@univ-mlv.fr> <4D3DDA72.4040603@oracle.com> <4D3E0DF3.8080100@univ-mlv.fr> <4D3E91B3.4060506@paradise.net.nz> <4D3F0B1F.4050303@univ-mlv.fr> <4D402876.1030804@univ-mlv.fr> Message-ID: I think the best compromise between 'concise' and 'readable' would be: URL resource = getClass().getResource("/com/foo/mightOrMightNotExist"); if (resource != null) { try (InputStream stream = url.openStream()) { readStream(stream); } } Actually, I think that Class.getResourceAsStream is a notable exception with its null-semantics. >From looking at my codecase I can see that the overwhelming majority of try-finally blocks act on non-nullable resources, such as: all sorts of newly allocated InputStreams, OutputStreams, Readers, Writers. java.sql.* related resources such as Statements, ResultSets. java.util.concurrent.Lock Thus, if I could vote I'd say built-in support for nullable resources was not necessary. 2011/1/27 Stephen Colebourne : > > InputStream stream = > getClass().getResourceAsStream("/com/foo/mightOrMightNotExist"); > if (stream != null) { > ?try (InputStream stream2 = stream) { > ? ?readStream(stream2); > ?} > } > > That now works, but is significantly less clear to read, more verbose > and more prone to accidental refactoring. > > In fact, there was a bug when I first typed this email, as I wrote > readStream(stream) rather than readStream(stream2). In this case, it > would have no bad effects, but other similar cases might. > > In fact, I'd probably still write: > InputStream stream = > getClass().getResourceAsStream("/com/foo/mightOrMightNotExist"); > try { > ?if (stream != null) { > ? ?readStream(stream); > ?} finally { > ? ?org.apache.commons.lang.IOUtils.closeQuietly(stream); > ?} > } > > as it is clearer than the t-w-r version. > > > Executive summary: C# has got it right. Null resources should be > silently be accepted. > > Priority. Initially I said this didn't matter much to me. With this > new use case (straight out of my day job yesterday), I really care > about my conclusion now. Please reconsider the semantics based on this > use case. > > Stephen > > From tom.hawtin at oracle.com Thu Jan 27 04:56:41 2011 From: tom.hawtin at oracle.com (tom.hawtin at oracle.com) Date: Thu, 27 Jan 2011 12:56:41 +0000 Subject: try-with-resources and null resource In-Reply-To: References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> <4D3DD4CA.1070802@univ-mlv.fr> <4D3DDA72.4040603@oracle.com> <4D3E0DF3.8080100@univ-mlv.fr> <4D3E91B3.4060506@paradise.net.nz> <4D3F0B1F.4050303@univ-mlv.fr> <4D402876.1030804@univ-mlv.fr> Message-ID: <4D416B89.7020402@oracle.com> On 27/01/2011 12:19, Gernot Neppert wrote: > Actually, I think that Class.getResourceAsStream is a notable > exception with its null-semantics. Indeed. It's a broken design. How often do you think the check is done (followed by a reasonable [in]action) and how often just an NPE on use? A resource missing can be considered much the same as a missing class, so an unchecked exception would have done the ticket. That's the past, so long as we know it is a weirdity and don't copy it. Tom From isidore at setgame.com Thu Jan 27 06:30:49 2011 From: isidore at setgame.com (Llewellyn Falco) Date: Thu, 27 Jan 2011 06:30:49 -0800 Subject: try-with-resources and null resource In-Reply-To: References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> <4D3DD4CA.1070802@univ-mlv.fr> <4D3DDA72.4040603@oracle.com> <4D3E0DF3.8080100@univ-mlv.fr> <4D3E91B3.4060506@paradise.net.nz> <4D3F0B1F.4050303@univ-mlv.fr> <4D402876.1030804@univ-mlv.fr> Message-ID: I very much agree. +1 try(null) does NOT throw exception I would also point out you could have coded it. > InputStream stream = > getClass().getResourceAsStream("/com/foo/mightOrMightNotExist"); try { try (InputStream stream2 = stream) { > > readStream(stream2); > } > } } catch(NullPointerException e) { // do nothing, try block is creating an exception } Sent from my iPad On Jan 27, 2011, at 1:10 AM, Stephen Colebourne wrote: > On 26 January 2011 18:05, Tim Peierls wrote: >> No, I am writing about what I think the semantics of the construct should >> be. I'm drawing an analogy between two constructs, one old, one new, that >> many users will see as similar, rightly or wrongly. Their expectations for >> the new construct's semantics will be shaped by this perception. I claim >> that most users won't expect NPE to be thrown immediately if the initializer >> is null, and that they will expect NPE to be thrown on the first attempt to >> dereference a null. They'll expect this because that's what happens in the >> analogous case. >> >> You can say the analogy is false, you can say that people should approach >> this construct as being radically different from try-finally, you can even >> say that most people are sloppy thinkers. But you can't change how they >> think by wishing, and it would be wrong to design the feature without taking >> such people into account. > > Funnily enough, I have proposed similar analogies in the past. But > they are seductively dangerous. How many devs looking at a foreach > loop know it uses an iterator? Or an index if its an array? The same > applies here. > > A similar case is closures/lambdas. There, the analogy is to inner > classes, yet after much thought, Oracle has come to the same > conclusion I did - that "this" within a lambda should not act as > "this" does in an inner class. Sometimes, we have to break with the > analogy to get the right result. > > Anyway, a real use case is far more helpful: > > Consider getResourceAsStream() which returns null if the resource does > not exist: > > try (InputStream stream = > getClass().getResourceAsStream("/com/foo/mightOrMightNotExist")) { > if (stream != null) { > readStream(stream); > } > } > > This will fail ATM, because of that null, yet the code is perfectly > clear and readable. What's the alternative? > > InputStream stream = > getClass().getResourceAsStream("/com/foo/mightOrMightNotExist"); > if (stream != null) { > try (InputStream stream2 = stream) { > readStream(stream2); > } > } > > That now works, but is significantly less clear to read, more verbose > and more prone to accidental refactoring. > > In fact, there was a bug when I first typed this email, as I wrote > readStream(stream) rather than readStream(stream2). In this case, it > would have no bad effects, but other similar cases might. > > In fact, I'd probably still write: > InputStream stream = > getClass().getResourceAsStream("/com/foo/mightOrMightNotExist"); > try { > if (stream != null) { > readStream(stream); > } finally { > org.apache.commons.lang.IOUtils.closeQuietly(stream); > } > } > > as it is clearer than the t-w-r version. > > > Executive summary: C# has got it right. Null resources should be > silently be accepted. > > Priority. Initially I said this didn't matter much to me. With this > new use case (straight out of my day job yesterday), I really care > about my conclusion now. Please reconsider the semantics based on this > use case. > > Stephen > From tim at peierls.net Thu Jan 27 06:47:54 2011 From: tim at peierls.net (Tim Peierls) Date: Thu, 27 Jan 2011 09:47:54 -0500 Subject: try-with-resources and null resource In-Reply-To: References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> <4D3DD4CA.1070802@univ-mlv.fr> <4D3DDA72.4040603@oracle.com> <4D3E0DF3.8080100@univ-mlv.fr> <4D3E91B3.4060506@paradise.net.nz> <4D3F0B1F.4050303@univ-mlv.fr> <4D402876.1030804@univ-mlv.fr> Message-ID: On Thu, Jan 27, 2011 at 4:10 AM, Stephen Colebourne wrote: > Funnily enough, I have proposed similar analogies in the past. But > they are seductively dangerous. How many devs looking at a foreach > loop know it uses an iterator? Or an index if its an array? The same > applies here. > I'm not saying that people _should_ make analogies to interpret unfamiliar constructs. I'm saying they _do_, and that ignoring that fact leads to designs that surprise everyone but the experts. > A similar case is closures/lambdas. There, the analogy is to inner > classes, yet after much thought, Oracle has come to the same > conclusion I did - that "this" within a lambda should not act as > "this" does in an inner class. Sometimes, we have to break with the > analogy to get the right result. > This was a case of designers letting go of an analogy. I don't think user expectations were ignored here. (Quite the contrary.) > try (InputStream stream = > getClass().getResourceAsStream("/com/foo/mightOrMightNotExist")) { > if (stream != null) { > readStream(stream); > } > } > > This will fail ATM, because of that null, yet the code is perfectly clear > and readable. What's the alternative? > Bruce Chapman already made a good case for not calling close on null resource. This code *would* work in that case. > Executive summary: C# has got it right. Null resources should be silently > be accepted. > I don't know about C#, but I like the formulation that can be sloppily summarized as "t-w-r calls close on non-null resources". Perhaps we violently agree? Priority. Initially I said this didn't matter much to me. With this > new use case (straight out of my day job yesterday), I really care > about my conclusion now. Please reconsider the semantics based on this > use case. > Is anyone actually against the "don't call close on null resource"? My first reaction was against, but Bruce convinced me easily. I'm against NPE on null initializer. --tim From scolebourne at joda.org Thu Jan 27 06:52:13 2011 From: scolebourne at joda.org (Stephen Colebourne) Date: Thu, 27 Jan 2011 14:52:13 +0000 Subject: try-with-resources and null resource In-Reply-To: References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> <4D3DD4CA.1070802@univ-mlv.fr> <4D3DDA72.4040603@oracle.com> <4D3E0DF3.8080100@univ-mlv.fr> <4D3E91B3.4060506@paradise.net.nz> <4D3F0B1F.4050303@univ-mlv.fr> <4D402876.1030804@univ-mlv.fr> Message-ID: On 27 January 2011 14:47, Tim Peierls wrote: > Bruce Chapman already made a good case for not calling close on null > resource. This code *would* work in that case. > >> Executive summary: C# has got it right. Null resources should be silently >> be accepted. > > I don't know about C#, but I like the formulation that can be sloppily > summarized as "t-w-r calls close on non-null resources". > > Perhaps we violently agree? Looks like we do agree. Stephen From R.Spilker at topdesk.com Thu Jan 27 07:44:43 2011 From: R.Spilker at topdesk.com (=?windows-1252?Q?Roel_Spilker?=) Date: Thu, 27 Jan 2011 16:44:43 +0100 Subject: try-with-resources and null resource In-Reply-To: Message-ID: > Is anyone actually against the "don't call close on null resource"? My first reaction was against, but Bruce convinced me easily. In Project Lombok (http://projectlombok.org) we have already about a year of field experience with ARM blocks using the @Cleanup annotation. We've added the null-check in the finally block at the request of our users. One thing to take into account is that code analysers that use the class file could warn that the null check is not necessary. In the class file there is no (reliable) distinction between a hand-coded try block and an ARM block. Just to be sure: I am all for "don't call close on null resource", I just wanted to give a "heads up". Roel From ian.clough at oracle.com Thu Jan 27 01:32:48 2011 From: ian.clough at oracle.com (Ian Clough) Date: Thu, 27 Jan 2011 09:32:48 +0000 Subject: try-with-resources and null resource In-Reply-To: References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> <4D3DD4CA.1070802@univ-mlv.fr> <4D3DDA72.4040603@oracle.com> <4D3E0DF3.8080100@univ-mlv.fr> <4D3E91B3.4060506@paradise.net.nz> <4D3F0B1F.4050303@univ-mlv.fr> <4D402876.1030804@univ-mlv.fr> Message-ID: <4D413BC0.2050507@oracle.com> On 27/01/2011 09:10, Stephen Colebourne wrote: > On 26 January 2011 18:05, Tim Peierls wrote: >> No, I am writing about what I think the semantics of the construct should >> be. I'm drawing an analogy between two constructs, one old, one new, that >> many users will see as similar, rightly or wrongly. Their expectations for >> the new construct's semantics will be shaped by this perception. I claim >> that most users won't expect NPE to be thrown immediately if the initializer >> is null, and that they will expect NPE to be thrown on the first attempt to >> dereference a null. They'll expect this because that's what happens in the >> analogous case. >> >> You can say the analogy is false, you can say that people should approach >> this construct as being radically different from try-finally, you can even >> say that most people are sloppy thinkers. But you can't change how they >> think by wishing, and it would be wrong to design the feature without taking >> such people into account. > Funnily enough, I have proposed similar analogies in the past. But > they are seductively dangerous. How many devs looking at a foreach > loop know it uses an iterator? Or an index if its an array? The same > applies here. And how many have tried to use an Iterator (or even Enumeration) in a foreach loop instead of an Iterable. In fact allowing an Iterator would be very useful as it would allow a non-default iterator (e.g a filtering Iterator) to be used without having to use an artificial intermediate container. Also you get the same exception if the Iterable itself is null or if the Iterator returned from calling iterator is null which confusing. > A similar case is closures/lambdas. There, the analogy is to inner > classes, yet after much thought, Oracle has come to the same > conclusion I did - that "this" within a lambda should not act as > "this" does in an inner class. Sometimes, we have to break with the > analogy to get the right result. > > Anyway, a real use case is far more helpful: > > Consider getResourceAsStream() which returns null if the resource does > not exist: > > try (InputStream stream = > getClass().getResourceAsStream("/com/foo/mightOrMightNotExist")) { > if (stream != null) { > readStream(stream); > } > } > > This will fail ATM, because of that null, yet the code is perfectly > clear and readable. What's the alternative? > > InputStream stream = > getClass().getResourceAsStream("/com/foo/mightOrMightNotExist"); > if (stream != null) { > try (InputStream stream2 = stream) { > readStream(stream2); > } > } > > That now works, but is significantly less clear to read, more verbose > and more prone to accidental refactoring. > > In fact, there was a bug when I first typed this email, as I wrote > readStream(stream) rather than readStream(stream2). In this case, it > would have no bad effects, but other similar cases might. > > In fact, I'd probably still write: > InputStream stream = > getClass().getResourceAsStream("/com/foo/mightOrMightNotExist"); > try { > if (stream != null) { > readStream(stream); > } finally { > org.apache.commons.lang.IOUtils.closeQuietly(stream); > } > } > > as it is clearer than the t-w-r version. > > > Executive summary: C# has got it right. Null resources should be > silently be accepted. > > Priority. Initially I said this didn't matter much to me. With this > new use case (straight out of my day job yesterday), I really care > about my conclusion now. Please reconsider the semantics based on this > use case. > > Stephen > > From reinier at zwitserloot.com Thu Jan 27 21:50:59 2011 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Fri, 28 Jan 2011 06:50:59 +0100 Subject: try-with-resources and null resource In-Reply-To: <4D3EC606.7090603@oracle.com> References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> <4D3DD4CA.1070802@univ-mlv.fr> <4D3DDA72.4040603@oracle.com> <4D3E0DF3.8080100@univ-mlv.fr> <4D3E3265.6050901@oracle.com> <4D3EBEA7.8010008@univ-mlv.fr> <4D3EC606.7090603@oracle.com> Message-ID: Would it help if I wrote it like this: try (Transaction t = Transactions.startTransaction()) { // Do all sorts of stuff, but 't' will never be touched. } I can see that being legal (and useful!). Let's not ditch the null problem by the wayside just because code checkers might flag this as 'no usage of t'. Because the 'expression only' variant of the ARM block has been removed, we _WILL_ see code that wanted an expression without an assignment to a newly declared variable - it'll most likely use a dummy variable declaration. I have a question, and, presupposing either answer, a followup question: 1. In the above snippet, is t final? 2 if yes: Well, then, calling a method that returns null, such as for example Class.getResourceAsStream, is going to be an unbelievable pain. As the NPE is then unavoidable, you'd need to assign it to a variable, check that variable, and if that variable is not null, start a try block, which REQUIRES that you create a NEW variable. urghhhhh!!!!!!! What do I name this? out1 and out2? I've got a very big problem with this. even if t is not final, I'd have to create a dummy input stream just to have something to close. 2 if no: What is closed? The object pointed to by variable 't' at the end of the try block / whenever the try block was exited, or, the object pointed at by 't' as it was at the start of the block (i.e. the result of the expression assigned to t). I guess I'm biased, but I see this as the only sensible way to go: A. 't' is final, whether you say so or not, and B. if 't' is null, then no close is called at all. No NPE occurs either. --Reinier Zwitserloot On Tue, Jan 25, 2011 at 1:45 PM, Maurizio Cimadamore < maurizio.cimadamore at oracle.com> wrote: > > >> Javac will warn you about this situation. > > Why ? It's a fair code. > > And adding a new warning has a cost. If there is too much > > not-that-useful warnings, > > users will don't care about them or worst deactivate them all. > > If there is a warning, what is the way to fix it ? Introduce a > > t.getClass() ? > > > > try(Transaction t = Transactions.getTransaction()) { > > t.getClass(); // remove that stupid javac warning > > } > > > > That's exactly what I'm proposing :) > > > Adding a warning has a cost, right - but this particular kind of warning > can be activated on-demand using -Xlint:twr (and it's disabled by > default). When do you say that the above code is fair, do you mean that > it is a legal Java program or that it can actually achieve something > good? I think the only case in which the above program is interesting is > if Transaction.getTransactions() has some hidden side-effects. Otherwise > the whole thing looks like a no-op (modulo Exceptions being thrown at > runtime). > > We currently have some similar warnings in the following case: > > switch (xyz) { > case 1: //do something here then fall-thorugh > case 2: //do another thing > } > > > Which, to some extent, is another fair program... but I think that both > programs (the one with unused twr variable and the one with > fall-through) are somewhat suspicious enough to merit a 'style' warning. > > Moreover, this kind of warnings can be suppressed with the usual scheme > - just add @SuppressWarnings("twr") to the enclosing method decl, and > the warning will go away. > > Maurizio > > From David.Holmes at oracle.com Thu Jan 27 22:38:33 2011 From: David.Holmes at oracle.com (David Holmes) Date: Fri, 28 Jan 2011 16:38:33 +1000 Subject: try-with-resources and null resource In-Reply-To: References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> <4D3DD4CA.1070802@univ-mlv.fr> <4D3DDA72.4040603@oracle.com> <4D3E0DF3.8080100@univ-mlv.fr> <4D3E91B3.4060506@paradise.net.nz> <4D3F0B1F.4050303@univ-mlv.fr> <4D402876.1030804@univ-mlv.fr> Message-ID: <4D426469.2060005@oracle.com> Tim Peierls said the following on 01/28/11 00:47: > I don't know about C#, but I like the formulation that can be sloppily > summarized as "t-w-r calls close on non-null resources". So to summarize there are three potential candidates for: try (Resource r = getResource() { // stuff here } I'm ignoring the suppressed exception aspects for simplicity: a) Simple transformation into try-finally (current implemented semantics) Resource r = getResource(); try { // stuff here } finally { r.close(); } b) Transformation into try-finally with explicit null-check on entry Resource r = getResource(); Objects.requireNonNull(r); // heh heh - couldn't resist! try { // stuff here } finally { r.close(); } c) Simple transformation into try-finally but only close a non-null resource Resource r = getResource(); try { // stuff here } finally { if (r != null) r.close(); } Option (a) is, perhaps, the most consistent with preserving the behaviour of current code that would be modified to use the new construct. This construct will be taught by analogy as it is the only effective way to explain things "try-with-resources behaves as-if you had written ....". That said I think existing code would have an explicit null-check to avoid the try-finally in the null case. And I think it is potentially risky to execute the try block only to have NPE thrown later. Option (c) seems appealing in some sense because there's no NPE's at all if you don't use "r", but I think that appeal is superficial. To me the fundamental question to ask is: what is try-with-resources for? And I believe the answer to that is to initialize, use and then clean-up an AutoCloseable object. So to me using try-with-resource on a resource that might be null is simply a mis-use of try-with-resources: if it can be null you can't autoclose it, so trying to is a programming error and programming errors should be detected and reported as early as possible. So to me option (b) is the preferred semantics for this new construct. David Holmes From reinier at zwitserloot.com Thu Jan 27 22:54:45 2011 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Fri, 28 Jan 2011 07:54:45 +0100 Subject: try-with-resources and null resource In-Reply-To: <4D426469.2060005@oracle.com> References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> <4D3DD4CA.1070802@univ-mlv.fr> <4D3DDA72.4040603@oracle.com> <4D3E0DF3.8080100@univ-mlv.fr> <4D3E91B3.4060506@paradise.net.nz> <4D3F0B1F.4050303@univ-mlv.fr> <4D402876.1030804@univ-mlv.fr> <4D426469.2060005@oracle.com> Message-ID: I don't understand why one couldn't explain t-w-r by showing "if (resource != null) resource.close();" in the finally block. It is then your opinion that this code is abusing the t-w-r construct, because Class.getResourceAsStream can return null? try (InputStream introTextStream = getClass().getResourceAsStream("intro.txt")) { ... } If so, we've clearly progressed into the "Everyone has their own 'feeling', none of them agree with each other, and making language decisions based on these feelings is a silly thing to do" phase. Let's check how often the above occurs. I'm betting it'll be "loads of times". Also contrast what you'd have to write if the above is not okay: InputStream introTextStream1 = getClass().getResourceAsStream(); if (introTextStream1 != null) { try (InputStream introTextStream2 = introTextStream1) { ... } } I assume I don't have to resort to 'feeling' to claim that the above is just bad. --Reinier Zwitserloot On Fri, Jan 28, 2011 at 7:38 AM, David Holmes wrote: > Tim Peierls said the following on 01/28/11 00:47: > > I don't know about C#, but I like the formulation that can be sloppily > > summarized as "t-w-r calls close on non-null resources". > > So to summarize there are three potential candidates for: > > try (Resource r = getResource() { > // stuff here > } > > I'm ignoring the suppressed exception aspects for simplicity: > > a) Simple transformation into try-finally (current implemented semantics) > > Resource r = getResource(); > try { > // stuff here > } > finally { > r.close(); > } > > b) Transformation into try-finally with explicit null-check on entry > > Resource r = getResource(); > Objects.requireNonNull(r); // heh heh - couldn't resist! > try { > // stuff here > } > finally { > r.close(); > } > > c) Simple transformation into try-finally but only close a non-null > resource > > Resource r = getResource(); > try { > // stuff here > } > finally { > if (r != null) > r.close(); > } > > > Option (a) is, perhaps, the most consistent with preserving the > behaviour of current code that would be modified to use the new > construct. This construct will be taught by analogy as it is the only > effective way to explain things "try-with-resources behaves as-if you > had written ....". That said I think existing code would have an > explicit null-check to avoid the try-finally in the null case. And I > think it is potentially risky to execute the try block only to have NPE > thrown later. > > Option (c) seems appealing in some sense because there's no NPE's at all > if you don't use "r", but I think that appeal is superficial. To me the > fundamental question to ask is: what is try-with-resources for? And I > believe the answer to that is to initialize, use and then clean-up an > AutoCloseable object. So to me using try-with-resource on a resource > that might be null is simply a mis-use of try-with-resources: if it can > be null you can't autoclose it, so trying to is a programming error and > programming errors should be detected and reported as early as possible. > So to me option (b) is the preferred semantics for this new construct. > > David Holmes > > From David.Holmes at oracle.com Thu Jan 27 23:18:41 2011 From: David.Holmes at oracle.com (David Holmes) Date: Fri, 28 Jan 2011 17:18:41 +1000 Subject: try-with-resources and null resource In-Reply-To: References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> <4D3DD4CA.1070802@univ-mlv.fr> <4D3DDA72.4040603@oracle.com> <4D3E0DF3.8080100@univ-mlv.fr> <4D3E91B3.4060506@paradise.net.nz> <4D3F0B1F.4050303@univ-mlv.fr> <4D402876.1030804@univ-mlv.fr> <4D426469.2060005@oracle.com> Message-ID: <4D426DD1.6050702@oracle.com> Reinier Zwitserloot said the following on 01/28/11 16:54: > I don't understand why one couldn't explain t-w-r by showing "if > (resource != null) resource.close();" in the finally block. One could of course do this. But most usages will involve accessing resource within the try block, which would result in NPE anyway. > It is then your opinion that this code is abusing the t-w-r construct, > because Class.getResourceAsStream can return null? > > try (InputStream introTextStream = > getClass().getResourceAsStream("intro.txt")) { > ... > } getResourceAsStream is a problematic example as it should not have been defined to return null. But that aside ... yes, that is my opinion. If the stream here may not exist I have to deal with that fact in my code. But you need to expand your example to show what the try block actually attempts to do with the stream that might be null. Your expectations in the null case will naturally influence what you expect the construct to do. > If so, we've clearly progressed into the "Everyone has their own > 'feeling', none of them agree with each other, and making language > decisions based on these feelings is a silly thing to do" phase. Let's > check how often the above occurs. I'm betting it'll be "loads of times". The question to answer is: what do those "loads of times" do if they encounter a null? > Also contrast what you'd have to write if the above is not okay: > > InputStream introTextStream1 = getClass().getResourceAsStream(); > if (introTextStream1 != null) { > try (InputStream introTextStream2 = introTextStream1) { > ... > } > } > > I assume I don't have to resort to 'feeling' to claim that the above is > just bad. What's the bad part? Having to declare a secondary variable? Certainly not ideal, but hardly fatal - we have to do that to capture locals as finals for inner class access. Also the secondary variable is a consequence of a different decision to limit the expression to be a local variable declaration. I wasn't involved in any discussions of that and I think it unfortunate that you can't use: final InputStream istream = getClass().getResourceAsStream(); if (istream != null) { try (istream) { ... } } provided istream is a reference to a final, or effectively final, value. To me a null reference is a bad input for try-with-resources and bad input should be rejected. David Holmes > --Reinier Zwitserloot > > > > On Fri, Jan 28, 2011 at 7:38 AM, David Holmes > wrote: > > Tim Peierls said the following on 01/28/11 00:47: > > I don't know about C#, but I like the formulation that can be > sloppily > > summarized as "t-w-r calls close on non-null resources". > > So to summarize there are three potential candidates for: > > try (Resource r = getResource() { > // stuff here > } > > I'm ignoring the suppressed exception aspects for simplicity: > > a) Simple transformation into try-finally (current implemented > semantics) > > Resource r = getResource(); > try { > // stuff here > } > finally { > r.close(); > } > > b) Transformation into try-finally with explicit null-check on entry > > Resource r = getResource(); > Objects.requireNonNull(r); // heh heh - couldn't resist! > try { > // stuff here > } > finally { > r.close(); > } > > c) Simple transformation into try-finally but only close a non-null > resource > > Resource r = getResource(); > try { > // stuff here > } > finally { > if (r != null) > r.close(); > } > > > Option (a) is, perhaps, the most consistent with preserving the > behaviour of current code that would be modified to use the new > construct. This construct will be taught by analogy as it is the only > effective way to explain things "try-with-resources behaves as-if you > had written ....". That said I think existing code would have an > explicit null-check to avoid the try-finally in the null case. And I > think it is potentially risky to execute the try block only to have NPE > thrown later. > > Option (c) seems appealing in some sense because there's no NPE's at all > if you don't use "r", but I think that appeal is superficial. To me the > fundamental question to ask is: what is try-with-resources for? And I > believe the answer to that is to initialize, use and then clean-up an > AutoCloseable object. So to me using try-with-resource on a resource > that might be null is simply a mis-use of try-with-resources: if it can > be null you can't autoclose it, so trying to is a programming error and > programming errors should be detected and reported as early as possible. > So to me option (b) is the preferred semantics for this new construct. > > David Holmes > > From reinier at zwitserloot.com Thu Jan 27 23:37:43 2011 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Fri, 28 Jan 2011 08:37:43 +0100 Subject: try-with-resources and null resource In-Reply-To: <4D426DD1.6050702@oracle.com> References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> <4D3DD4CA.1070802@univ-mlv.fr> <4D3DDA72.4040603@oracle.com> <4D3E0DF3.8080100@univ-mlv.fr> <4D3E91B3.4060506@paradise.net.nz> <4D3F0B1F.4050303@univ-mlv.fr> <4D402876.1030804@univ-mlv.fr> <4D426469.2060005@oracle.com> <4D426DD1.6050702@oracle.com> Message-ID: Using t-w-r with a null resource would do something other than throw an NPE in the body if the body contains an if-based null check, for example. --Reinier Zwitserloot On Fri, Jan 28, 2011 at 8:18 AM, David Holmes wrote: > Reinier Zwitserloot said the following on 01/28/11 16:54: > > I don't understand why one couldn't explain t-w-r by showing "if (resource >> != null) resource.close();" in the finally block. >> > > One could of course do this. But most usages will involve accessing > resource within the try block, which would result in NPE anyway. > > > It is then your opinion that this code is abusing the t-w-r construct, >> because Class.getResourceAsStream can return null? >> >> try (InputStream introTextStream = >> getClass().getResourceAsStream("intro.txt")) { >> ... >> } >> > > getResourceAsStream is a problematic example as it should not have been > defined to return null. But that aside ... yes, that is my opinion. If the > stream here may not exist I have to deal with that fact in my code. But you > need to expand your example to show what the try block actually attempts to > do with the stream that might be null. Your expectations in the null case > will naturally influence what you expect the construct to do. > > > If so, we've clearly progressed into the "Everyone has their own >> 'feeling', none of them agree with each other, and making language decisions >> based on these feelings is a silly thing to do" phase. Let's check how often >> the above occurs. I'm betting it'll be "loads of times". >> > > The question to answer is: what do those "loads of times" do if they > encounter a null? > > > Also contrast what you'd have to write if the above is not okay: >> >> InputStream introTextStream1 = getClass().getResourceAsStream(); >> if (introTextStream1 != null) { >> try (InputStream introTextStream2 = introTextStream1) { >> ... >> } >> } >> >> I assume I don't have to resort to 'feeling' to claim that the above is >> just bad. >> > > What's the bad part? Having to declare a secondary variable? Certainly not > ideal, but hardly fatal - we have to do that to capture locals as finals for > inner class access. Also the secondary variable is a consequence of a > different decision to limit the expression to be a local variable > declaration. I wasn't involved in any discussions of that and I think it > unfortunate that you can't use: > > final InputStream istream = getClass().getResourceAsStream(); > if (istream != null) { > try (istream) { > ... > } > } > > provided istream is a reference to a final, or effectively final, value. > > To me a null reference is a bad input for try-with-resources and bad input > should be rejected. > > David Holmes > > --Reinier Zwitserloot >> >> >> >> >> On Fri, Jan 28, 2011 at 7:38 AM, David Holmes > David.Holmes at oracle.com>> wrote: >> >> Tim Peierls said the following on 01/28/11 00:47: >> > I don't know about C#, but I like the formulation that can be >> sloppily >> > summarized as "t-w-r calls close on non-null resources". >> >> So to summarize there are three potential candidates for: >> >> try (Resource r = getResource() { >> // stuff here >> } >> >> I'm ignoring the suppressed exception aspects for simplicity: >> >> a) Simple transformation into try-finally (current implemented >> semantics) >> >> Resource r = getResource(); >> try { >> // stuff here >> } >> finally { >> r.close(); >> } >> >> b) Transformation into try-finally with explicit null-check on entry >> >> Resource r = getResource(); >> Objects.requireNonNull(r); // heh heh - couldn't resist! >> try { >> // stuff here >> } >> finally { >> r.close(); >> } >> >> c) Simple transformation into try-finally but only close a non-null >> resource >> >> Resource r = getResource(); >> try { >> // stuff here >> } >> finally { >> if (r != null) >> r.close(); >> } >> >> >> Option (a) is, perhaps, the most consistent with preserving the >> behaviour of current code that would be modified to use the new >> construct. This construct will be taught by analogy as it is the only >> effective way to explain things "try-with-resources behaves as-if you >> had written ....". That said I think existing code would have an >> explicit null-check to avoid the try-finally in the null case. And I >> think it is potentially risky to execute the try block only to have NPE >> thrown later. >> >> Option (c) seems appealing in some sense because there's no NPE's at >> all >> if you don't use "r", but I think that appeal is superficial. To me the >> fundamental question to ask is: what is try-with-resources for? And I >> believe the answer to that is to initialize, use and then clean-up an >> AutoCloseable object. So to me using try-with-resource on a resource >> that might be null is simply a mis-use of try-with-resources: if it can >> be null you can't autoclose it, so trying to is a programming error and >> programming errors should be detected and reported as early as >> possible. >> So to me option (b) is the preferred semantics for this new construct. >> >> David Holmes >> >> >> From mcnepp02 at googlemail.com Thu Jan 27 23:49:55 2011 From: mcnepp02 at googlemail.com (Gernot Neppert) Date: Fri, 28 Jan 2011 07:49:55 +0000 Subject: try-with-resources and null resource In-Reply-To: References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> <4D3DD4CA.1070802@univ-mlv.fr> <4D3DDA72.4040603@oracle.com> <4D3E0DF3.8080100@univ-mlv.fr> <4D3E91B3.4060506@paradise.net.nz> <4D3F0B1F.4050303@univ-mlv.fr> <4D402876.1030804@univ-mlv.fr> <4D426469.2060005@oracle.com> Message-ID: Have you ever browsed a reasonably large codebase and counted the occurrences of 'finally' blocks that deal with nullable resources? Well, I have, and I found the infamous Class.getResourceAsStream to be the _only_ example of such a construct. And even that is easy to forego without adding any substantial clutter. Simply test the existence of the resource before opening the InputStream: URL resource = getClass().getResource("resourceThatMayOrMayNotExist"); if(resource != null) { try(InputStream stream = resource.openStream()) { ... } } _All other_ uses of try-finally blocks in my code deal with resources that are guaranteed to be non-null, because they are initialized by 'new' expressions or factory functions: java.sql.Statements, ResultSets, InputStreams, OutputStreams, Readers, Writers, Locks... In practice, having to deal with null-resources will probably be as rare as having to deal with null-iterators in a foreach loop. 2011/1/28 Reinier Zwitserloot : > I don't understand why one couldn't explain t-w-r by showing "if (resource > != null) resource.close();" in the finally block. > > It is then your opinion that this code is abusing the t-w-r construct, > because Class.getResourceAsStream can return null? > > try (InputStream introTextStream = > getClass().getResourceAsStream("intro.txt")) { > ? ?... > } > > If so, we've clearly progressed into the "Everyone has their own 'feeling', > none of them agree with each other, and making language decisions based on > these feelings is a silly thing to do" phase. Let's check how often the > above occurs. I'm betting it'll be "loads of times". Also contrast what > you'd have to write if the above is not okay: > > InputStream introTextStream1 = getClass().getResourceAsStream(); > if (introTextStream1 != null) { > ? ?try (InputStream introTextStream2 = introTextStream1) { > ? ? ? ?... > ? ?} > } > > I assume I don't have to resort to 'feeling' to claim that the above is just > bad. > > ?--Reinier Zwitserloot > > > > On Fri, Jan 28, 2011 at 7:38 AM, David Holmes wrote: > >> Tim Peierls said the following on 01/28/11 00:47: >> > I don't know about C#, but I like the formulation that can be sloppily >> > summarized as "t-w-r calls close on non-null resources". >> >> So to summarize there are three potential candidates for: >> >> try (Resource r = getResource() { >> ? // stuff here >> } >> >> I'm ignoring the suppressed exception aspects for simplicity: >> >> a) Simple transformation into try-finally (current implemented semantics) >> >> ? Resource r = getResource(); >> ? try { >> ? ? // stuff here >> ? } >> ? finally { >> ? ? r.close(); >> ? } >> >> b) Transformation into try-finally with explicit null-check on entry >> >> ? Resource r = getResource(); >> ? Objects.requireNonNull(r); // heh heh - couldn't resist! >> ? try { >> ? ? // stuff here >> ? } >> ? finally { >> ? ? r.close(); >> ? } >> >> c) Simple transformation into try-finally but only close a non-null >> resource >> >> ? Resource r = getResource(); >> ? try { >> ? ? // stuff here >> ? } >> ? finally { >> ? ? if (r != null) >> ? ? ? r.close(); >> ? } >> >> >> Option (a) is, perhaps, the most consistent with preserving the >> behaviour of current code that would be modified to use the new >> construct. This construct will be taught by analogy as it is the only >> effective way to explain things "try-with-resources behaves as-if you >> had written ....". That said I think existing code would have an >> explicit null-check to avoid the try-finally in the null case. And I >> think it is potentially risky to execute the try block only to have NPE >> thrown later. >> >> Option (c) seems appealing in some sense because there's no NPE's at all >> if you don't use "r", but I think that appeal is superficial. To me the >> fundamental question to ask is: what is try-with-resources for? And I >> believe the answer to that is to initialize, use and then clean-up an >> AutoCloseable object. So to me using try-with-resource on a resource >> that might be null is simply a mis-use of try-with-resources: if it can >> be null you can't autoclose it, so trying to is a programming error and >> programming errors should be detected and reported as early as possible. >> So to me option (b) is the preferred semantics for this new construct. >> >> David Holmes >> >> > > From forax at univ-mlv.fr Fri Jan 28 01:26:07 2011 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Fri, 28 Jan 2011 10:26:07 +0100 Subject: try-with-resources and null resource In-Reply-To: <4D426469.2060005@oracle.com> References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> <4D3DD4CA.1070802@univ-mlv.fr> <4D3DDA72.4040603@oracle.com> <4D3E0DF3.8080100@univ-mlv.fr> <4D3E91B3.4060506@paradise.net.nz> <4D3F0B1F.4050303@univ-mlv.fr> <4D402876.1030804@univ-mlv.fr> <4D426469.2060005@oracle.com> Message-ID: <4D428BAF.90601@univ-mlv.fr> Le 28/01/2011 07:38, David Holmes a ?crit : > Tim Peierls said the following on 01/28/11 00:47: >> I don't know about C#, but I like the formulation that can be sloppily >> summarized as "t-w-r calls close on non-null resources". > So to summarize there are three potential candidates for: > > try (Resource r = getResource() { > // stuff here > } > > I'm ignoring the suppressed exception aspects for simplicity: > > a) Simple transformation into try-finally (current implemented semantics) > > Resource r = getResource(); > try { > // stuff here > } > finally { > r.close(); > } > > b) Transformation into try-finally with explicit null-check on entry > > Resource r = getResource(); > Objects.requireNonNull(r); // heh heh - couldn't resist! > try { > // stuff here > } > finally { > r.close(); > } > > c) Simple transformation into try-finally but only close a non-null resource > > Resource r = getResource(); > try { > // stuff here > } > finally { > if (r != null) > r.close(); > } > > > Option (a) is, perhaps, the most consistent with preserving the > behaviour of current code that would be modified to use the new > construct. This construct will be taught by analogy as it is the only > effective way to explain things "try-with-resources behaves as-if you > had written ....". That said I think existing code would have an > explicit null-check to avoid the try-finally in the null case. And I > think it is potentially risky to execute the try block only to have NPE > thrown later. > > Option (c) seems appealing in some sense because there's no NPE's at all > if you don't use "r", but I think that appeal is superficial. To me the > fundamental question to ask is: what is try-with-resources for? And I > believe the answer to that is to initialize, use and then clean-up an > AutoCloseable object. So to me using try-with-resource on a resource > that might be null is simply a mis-use of try-with-resources: if it can > be null you can't autoclose it, so trying to is a programming error and > programming errors should be detected and reported as early as possible. > So to me option (b) is the preferred semantics for this new construct. > > David Holmes +1 :) R?mi From fweimer at bfk.de Fri Jan 28 01:30:46 2011 From: fweimer at bfk.de (Florian Weimer) Date: Fri, 28 Jan 2011 09:30:46 +0000 Subject: try-with-resources and null resource In-Reply-To: (Reinier Zwitserloot's message of "Fri\, 28 Jan 2011 06\:50\:59 +0100") References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> <4D3DD4CA.1070802@univ-mlv.fr> <4D3DDA72.4040603@oracle.com> <4D3E0DF3.8080100@univ-mlv.fr> <4D3E3265.6050901@oracle.com> <4D3EBEA7.8010008@univ-mlv.fr> <4D3EC606.7090603@oracle.com> Message-ID: <8262t9l6ih.fsf@mid.bfk.de> * Reinier Zwitserloot: > 2 if yes: Well, then, calling a method that returns null, such as for > example Class.getResourceAsStream, is going to be an unbelievable pain. As > the NPE is then unavoidable, you'd need to assign it to a variable, check > that variable, and if that variable is not null, start a try block, which > REQUIRES that you create a NEW variable. urghhhhh!!!!!!! What do I name > this? out1 and out2? I've got a very big problem with this. even if t is not > final, I'd have to create a dummy input stream just to have something to > close. If t is not referenced (so its declared type does not matter) and can be null, use a utility method which returns a dummy AutoCloseable instance if the passed argument is null. If you reference t on some path, you need to generate a dynamic proxy for the null case which throws some suitable exception on all method calls except close(). It's ugly, but it's doable. I don't think it's necessary to have direct support for such an edge case. By the way, has anybody else seen this phenomenon in their code base? InputStream in = null; try { in = new FileInputStream(path); useFile(in); } finally { if (in != null) { in.close(); } } I'm wondering where this is coming from. -- Florian Weimer BFK edv-consulting GmbH http://www.bfk.de/ Kriegsstra?e 100 tel: +49-721-96201-1 D-76133 Karlsruhe fax: +49-721-96201-99 From mthornton at optrak.co.uk Fri Jan 28 01:53:50 2011 From: mthornton at optrak.co.uk (Mark Thornton) Date: Fri, 28 Jan 2011 09:53:50 +0000 Subject: try-with-resources and null resource In-Reply-To: <8262t9l6ih.fsf@mid.bfk.de> References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> <4D3DD4CA.1070802@univ-mlv.fr> <4D3DDA72.4040603@oracle.com> <4D3E0DF3.8080100@univ-mlv.fr> <4D3E3265.6050901@oracle.com> <4D3EBEA7.8010008@univ-mlv.fr> <4D3EC606.7090603@oracle.com> <8262t9l6ih.fsf@mid.bfk.de> Message-ID: <4D42922E.5080101@optrak.co.uk> On 28/01/2011 09:30, Florian Weimer wrote: > > By the way, has anybody else seen this phenomenon in their code base? > > InputStream in = null; > try { > in = new FileInputStream(path); > useFile(in); > } finally { > if (in != null) { > in.close(); > } > } > > I'm wondering where this is coming from. > In my experience, it arises where you have or might expect to extend to cases with more than one resource. You only need one try statement instead of a whole nest of them. Once you start doing this for the multi resource case I suspect there is a tendency to use the same style for single resources as well. Mark Thornton From jesper.oqvist at cs.lth.se Fri Jan 28 01:55:58 2011 From: jesper.oqvist at cs.lth.se (=?ISO-8859-1?Q?Jesper_=D6qvist?=) Date: Fri, 28 Jan 2011 10:55:58 +0100 Subject: try-with-resources and null resource In-Reply-To: References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> <4D3DD4CA.1070802@univ-mlv.fr> <4D3DDA72.4040603@oracle.com> <4D3E0DF3.8080100@univ-mlv.fr> <4D3E3265.6050901@oracle.com> <4D3EBEA7.8010008@univ-mlv.fr> <4D3EC606.7090603@oracle.com> Message-ID: <4D4292AE.80408@cs.lth.se> Hi Reinier, On 2011-01-28 06:50, Reinier Zwitserloot wrote: > I have a question, and, presupposing either answer, a followup question: > > 1. In the above snippet, is t final? Yes > 2 if yes: Well, then, calling a method that returns null, such as for > example Class.getResourceAsStream, is going to be an unbelievable pain. As > the NPE is then unavoidable, you'd need to assign it to a variable, check > that variable, and if that variable is not null, start a try block, which > REQUIRES that you create a NEW variable. urghhhhh!!!!!!! What do I name > this? out1 and out2? I've got a very big problem with this. even if t is not > final, I'd have to create a dummy input stream just to have something to > close. If Class.getResourceAsStream returns null, it means the resource could not be found. In _most_ cases you want to handle this scenario explicitly instead of skipping the resource entirely. If the try with resources-statement would silently ignore that the resource was null, then possible errors might go unnoticed by the programmer. I believe that suppressing NPEs just serves to obscure actual problems in the handling of your resources. This whole discussion highlights why programming with null is a bad idea, but if we must use null then there should be exceptions whenever we try to use null. Java is already a bit confused on this point - in some cases null means "nothing" while in other cases it means "invalid/error". Jesper From forax at univ-mlv.fr Fri Jan 28 02:03:37 2011 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Fri, 28 Jan 2011 11:03:37 +0100 Subject: try-with-resources and null resource In-Reply-To: <8262t9l6ih.fsf@mid.bfk.de> References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> <4D3DD4CA.1070802@univ-mlv.fr> <4D3DDA72.4040603@oracle.com> <4D3E0DF3.8080100@univ-mlv.fr> <4D3E3265.6050901@oracle.com> <4D3EBEA7.8010008@univ-mlv.fr> <4D3EC606.7090603@oracle.com> <8262t9l6ih.fsf@mid.bfk.de> Message-ID: <4D429479.3040907@univ-mlv.fr> Le 28/01/2011 10:30, Florian Weimer a ?crit : [...] > By the way, has anybody else seen this phenomenon in their code base? > > InputStream in = null; > try { > in = new FileInputStream(path); > useFile(in); > } finally { > if (in != null) { > in.close(); > } > } > > I'm wondering where this is coming from. You mean, instead of: InputStream in = new FileInputStream(path); try { useFile(in); } finally { in.close(); } This code is very common. I've spied my students to understand why. It's because FileInputStream throws an exception so you put it in the try block, after all try/finally is like try/catch. Then the IDE warn you that 'in' is not accessible in the finally block. So you put the declaration on top of the block. InputStream in; try { in = new FileInputStream(path); useFile(in); } finally { in.close(); } Here the IDE says that 'in' is not initialized if new FileInputStream throws an exception. So you initialize 'in' to null. And the IDE warn you because in.close() will throw a NPE. So you add a null check. It's the IDE's fault because it should not suggest to initialize 'in' with null and developer's fault because he blindly follows what the IDE says. R?mi From mcnepp02 at googlemail.com Fri Jan 28 02:20:23 2011 From: mcnepp02 at googlemail.com (Gernot Neppert) Date: Fri, 28 Jan 2011 10:20:23 +0000 Subject: try-with-resources and null resource In-Reply-To: <4D429479.3040907@univ-mlv.fr> References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> <4D3DD4CA.1070802@univ-mlv.fr> <4D3DDA72.4040603@oracle.com> <4D3E0DF3.8080100@univ-mlv.fr> <4D3E3265.6050901@oracle.com> <4D3EBEA7.8010008@univ-mlv.fr> <4D3EC606.7090603@oracle.com> <8262t9l6ih.fsf@mid.bfk.de> <4D429479.3040907@univ-mlv.fr> Message-ID: 2011/1/28 R?mi Forax : > ?Le 28/01/2011 10:30, Florian Weimer a ?crit : > > [...] > >> By the way, has anybody else seen this phenomenon in their code base? >> >> ? ?InputStream in = null; >> ? ?try { >> ? ? ?in = new FileInputStream(path); >> ? ? ?useFile(in); >> ? ?} finally { >> ? ? ?if (in != null) { >> ? ? ? ?in.close(); >> ? ? ?} >> ? ?} >> >> I'm wondering where this is coming from. > > You mean, instead of: > > ? InputStream in = new FileInputStream(path); > ? try { > ? ? useFile(in); > ? } finally { > ? ? in.close(); > ? } > > > This code is very common. I've spied my students to understand why. > It's because FileInputStream throws an exception so > you put it in the try block, after all try/finally is like try/catch. Yes, mostly this will be coupled with a 'catch' in order to deal with checked exceptions. Thus, instead of the canonical: try { final InputStream in = new FileInputStream(path); try { useFile(in); } finally { in.close(); } } catch(IOException e) { ... } ...people end up writing the deceptively 'more concise': InputStream in = null; try { in = new FileInputStream(path); useFile(in); } catch(IOException e) { ... } finally { if(in != null) in.close(); } ...which is all but impossible to get right if more than one resource is involved! > Then the IDE warn you that 'in' is not accessible in > the finally block. So you put the declaration on top of the block. > > ? InputStream in; > ? try { > ? ?in = new FileInputStream(path); > ? ?useFile(in); > ? } finally { > ? ? in.close(); > ? } > > Here the IDE says that 'in' is not initialized if new FileInputStream > throws an exception. So you initialize 'in' to null. > And the IDE warn you because in.close() will throw a NPE. > So you add a null check. > > It's the IDE's fault because it should not suggest to initialize 'in' > with null and developer's fault because he blindly follows what the IDE > says. > > R?mi It's not just the IDE that warns you. Once you decide to put the Variable declaration before the 'try' block, then you _must_ initialize the variable with 'null'. Otherwise, there'd be a codepath that would leave it uninitialized: if the constructor throws, the assignment will be skipped! Then, the 'finally' block has to be able to deal with the 'null' case. From scolebourne at joda.org Fri Jan 28 02:39:26 2011 From: scolebourne at joda.org (Stephen Colebourne) Date: Fri, 28 Jan 2011 10:39:26 +0000 Subject: try-with-resources and null resource In-Reply-To: <4D4292AE.80408@cs.lth.se> References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> <4D3DD4CA.1070802@univ-mlv.fr> <4D3DDA72.4040603@oracle.com> <4D3E0DF3.8080100@univ-mlv.fr> <4D3E3265.6050901@oracle.com> <4D3EBEA7.8010008@univ-mlv.fr> <4D3EC606.7090603@oracle.com> <4D4292AE.80408@cs.lth.se> Message-ID: On 28 January 2011 09:55, Jesper ?qvist wrote: > I believe that suppressing NPEs just serves to obscure actual problems > in the handling of your resources. > > This whole discussion highlights why programming with null is a bad > idea, but if we must use null then there should be exceptions whenever > we try to use null. Java is already a bit confused on this point - in > some cases null means ?"nothing" while in other cases it means > "invalid/error". Sadly, this list, Sun and Oracle continue to have trouble with null. As Brian Goetz said recently IIRC, the null genie is already out of the bottle. Null is used everywhere is real code (ie. code written by the 99.9% of people *not* on this list). I use null all the time, which frequently gets me criticised here. The reality is that null has valid meaning is enterprise coding, with JavaBeans being the key part. Here is a classic use case: /** * The set of security object identifiers, null to not limit by security object identifiers. * Note that an empty set will return no securities. */ @PropertyDefinition(set = "manual") private List _securityIds; /** * The security keys to match, null to not match on security keys. */ @PropertyDefinition private IdentifierSearch _securityKeys; /** * The security name, wildcards allowed, null to not match on name. */ @PropertyDefinition private String _name; Nulls are everywhere, and using null as a return type to indicate that something isn't present (like a resource) is very widespread. Now, many here take the view that using null in that way is a Bad Thing and should be stamped out. I'm here to tell you that its not going to be stamped out as (a) its use is too widespread and (b) its often better than the alternative. Language changes should be enhacing the language to help manage it better (cf the nul-handlinng operators I proposed for Coin, and Fantom's nullable types). Go to a conference with real developers, and you'll find they are crying out for this. I'm sorry, but it drives me mad to see null-purity being foisted on the desires of real developers. So, while getResourceAsStream() might be the only case in the JDK, and it might be the only case in some of this mailing lists participants, it most certainly isn't the only case overall. The alternative code to write when the resource is null, is dreadful, and bug-prone. Of David's three semantics, (c) is what users want, (b) is expainable but undesirable, and (a) is just enexpected and wrong. Stephen From mcnepp02 at googlemail.com Fri Jan 28 03:05:45 2011 From: mcnepp02 at googlemail.com (Gernot Neppert) Date: Fri, 28 Jan 2011 11:05:45 +0000 Subject: try-with-resources and null resource In-Reply-To: References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> <4D3DD4CA.1070802@univ-mlv.fr> <4D3DDA72.4040603@oracle.com> <4D3E0DF3.8080100@univ-mlv.fr> <4D3E3265.6050901@oracle.com> <4D3EBEA7.8010008@univ-mlv.fr> <4D3EC606.7090603@oracle.com> <4D4292AE.80408@cs.lth.se> Message-ID: 2011/1/28 Stephen Colebourne : > > Nulls are everywhere, and using null as a return type to indicate that > something isn't present (like a resource) is very widespread. > I don't think anybody in this discussion would dispute your doubtlessly correct observation. Of course nulls are prevalent throughout Java code, and they serve a good purpose! _But_: We're not talking about property getters returning null values here. We're talking about the expressions that initialize resources, a.k.a expressions that modify a resource so that it ends up being in a 'closeable' state. This is a very specific subset of expressions, for which the presupposition that it never returns null is IMHO very reasonable. From tom.hawtin at oracle.com Fri Jan 28 06:09:28 2011 From: tom.hawtin at oracle.com (tom.hawtin at oracle.com) Date: Fri, 28 Jan 2011 14:09:28 +0000 Subject: try-with-resources and null resource In-Reply-To: References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> <4D3DD4CA.1070802@univ-mlv.fr> <4D3DDA72.4040603@oracle.com> <4D3E0DF3.8080100@univ-mlv.fr> <4D3E91B3.4060506@paradise.net.nz> <4D3F0B1F.4050303@univ-mlv.fr> <4D402876.1030804@univ-mlv.fr> <4D426469.2060005@oracle.com> Message-ID: <4D42CE18.2010702@oracle.com> On 28/01/2011 06:54, Reinier Zwitserloot wrote: > InputStream introTextStream1 = getClass().getResourceAsStream(); > if (introTextStream1 != null) { > try (InputStream introTextStream2 = introTextStream1) { > ... > } > } So Class.getResourceAsStream is a poorly designed method. Wrap it in something better: public static @Nonnull InputStream openResource( @Nonnull Class clazz, /* @Nonnull ??? */ String name ) throws FileNotFoundException { InputStream stream = clazz.getResourceAsStream(name); if (stream == null) { // Put back a replacement for the swallowed exception. throw new FileNotFoundException( name ); } return stream; } (You are probably going to have to deal with IOException anyway. FileNotFoundException by analogy to 404 and 410 handling which may well have caused the null, but there probably should be a mezzanine IOException. Even with a quick look at the source, I can't see what is supposed to happen for a null resource path.) Tom From tom.hawtin at oracle.com Fri Jan 28 06:26:22 2011 From: tom.hawtin at oracle.com (tom.hawtin at oracle.com) Date: Fri, 28 Jan 2011 14:26:22 +0000 Subject: try-with-resources and null resource In-Reply-To: <4D42922E.5080101@optrak.co.uk> References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> <4D3DD4CA.1070802@univ-mlv.fr> <4D3DDA72.4040603@oracle.com> <4D3E0DF3.8080100@univ-mlv.fr> <4D3E3265.6050901@oracle.com> <4D3EBEA7.8010008@univ-mlv.fr> <4D3EC606.7090603@oracle.com> <8262t9l6ih.fsf@mid.bfk.de> <4D42922E.5080101@optrak.co.uk> Message-ID: <4D42D20E.9060704@oracle.com> On 28/01/2011 09:53, Mark Thornton wrote: > On 28/01/2011 09:30, Florian Weimer wrote: >> >> By the way, has anybody else seen this phenomenon in their code base? >> >> InputStream in = null; >> try { >> in = new FileInputStream(path); >> useFile(in); >> } finally { >> if (in != null) { >> in.close(); >> } >> } >> >> I'm wondering where this is coming from. This null-dance pops up frequently in Stack Overflow answers. Drives me nuts. The other day someone posted a link to page in the NIO docs where something similar is done - only attempting to catch and printf a checked exception, but not from the close! Swing locking does something similar, only releasing the lock even if the acquire failed. It seems to be an attempt to "handle" the exception in-method without adding another try block and level of indentation. I believe the old statistic was that two thirds of the finally blocks in the Java library are AWOL. So there is some improvement going on! > In my experience, it arises where you have or might expect to extend to > cases with more than one resource. You only need one try statement > instead of a whole nest of them. Once you start doing this for the multi > resource case I suspect there is a tendency to use the same style for > single resources as well. Oh, the classic first failed release skips further releases bug? Usually where the code isn't layered well - e.g. acquire driver & connection, statement and result set in one polyresponsible blob. I don't think this is a cause, because the null dance usually happens in the more common simple cases. Tom From jesper.oqvist at cs.lth.se Fri Jan 28 07:50:42 2011 From: jesper.oqvist at cs.lth.se (=?ISO-8859-1?Q?Jesper_=D6qvist?=) Date: Fri, 28 Jan 2011 16:50:42 +0100 Subject: try-with-resources and null resource In-Reply-To: References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> <4D3DD4CA.1070802@univ-mlv.fr> <4D3DDA72.4040603@oracle.com> <4D3E0DF3.8080100@univ-mlv.fr> <4D3E3265.6050901@oracle.com> <4D3EBEA7.8010008@univ-mlv.fr> <4D3EC606.7090603@oracle.com> <4D4292AE.80408@cs.lth.se> Message-ID: <4D42E5D2.406@cs.lth.se> Stephen Colebourne wrote: > On 28 January 2011 09:55, Jesper ?qvist wrote: > >> I believe that suppressing NPEs just serves to obscure actual problems >> in the handling of your resources. >> >> This whole discussion highlights why programming with null is a bad >> idea, but if we must use null then there should be exceptions whenever >> we try to use null. Java is already a bit confused on this point - in >> some cases null means "nothing" while in other cases it means >> "invalid/error". >> > > Sadly, this list, Sun and Oracle continue to have trouble with null. > As Brian Goetz said recently IIRC, the null genie is already out of > the bottle. > > Null is used everywhere is real code (ie. code written by the 99.9% of > people *not* on this list). I use null all the time, which frequently > gets me criticised here. > Stephen, Null is of course not such a Bad Thing if you are consistent about what using null actually means. Null commonly seems to mean "nothing" as in methods which can not complete some task and return a usable object will often return null to indicate that the result is "empty" in some sense (cf Map.get(key) ) On the other hand null is also an "error" in that it will cause NPEs if you try to use a null reference. My interpretation of null is the "error" meaning, and as such I think a try-with-resource statement should throw an NPE instead of silently ignoring null. I tried to express this opinion in my previous message but perhaps I was a bit too brief. Where the NPE should be thrown is another question. Jesper > The reality is that null has valid meaning is enterprise coding, with > JavaBeans being the key part. Here is a classic use case: > > /** > * The set of security object identifiers, null to not limit by > security object identifiers. > * Note that an empty set will return no securities. > */ > @PropertyDefinition(set = "manual") > private List _securityIds; > /** > * The security keys to match, null to not match on security keys. > */ > @PropertyDefinition > private IdentifierSearch _securityKeys; > /** > * The security name, wildcards allowed, null to not match on name. > */ > @PropertyDefinition > private String _name; > > Nulls are everywhere, and using null as a return type to indicate that > something isn't present (like a resource) is very widespread. > > Now, many here take the view that using null in that way is a Bad > Thing and should be stamped out. I'm here to tell you that its not > going to be stamped out as (a) its use is too widespread and (b) its > often better than the alternative. > > Language changes should be enhacing the language to help manage it > better (cf the nul-handlinng operators I proposed for Coin, and > Fantom's nullable types). Go to a conference with real developers, and > you'll find they are crying out for this. I'm sorry, but it drives me > mad to see null-purity being foisted on the desires of real > developers. > > So, while getResourceAsStream() might be the only case in the JDK, and > it might be the only case in some of this mailing lists participants, > it most certainly isn't the only case overall. The alternative code to > write when the resource is null, is dreadful, and bug-prone. > > Of David's three semantics, (c) is what users want, (b) is expainable > but undesirable, and (a) is just enexpected and wrong. > > Stephen > > From joe.darcy at oracle.com Fri Jan 28 10:03:37 2011 From: joe.darcy at oracle.com (Joe Darcy) Date: Fri, 28 Jan 2011 10:03:37 -0800 Subject: try-with-resources and null resource In-Reply-To: References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> <4D3DD4CA.1070802@univ-mlv.fr> <4D3DDA72.4040603@oracle.com> <4D3E0DF3.8080100@univ-mlv.fr> <4D3E91B3.4060506@paradise.net.nz> <4D3F0B1F.4050303@univ-mlv.fr> <4D402876.1030804@univ-mlv.fr> <4D426469.2060005@oracle.com> Message-ID: <4D4304F9.40206@oracle.com> Gernot, If you can share some statistics of the code base you looked at, lines of code, # of finally block, # of finally blocks dealing with nullable, resources, other informative things, I would find that to be an interesting data point. -Joe Gernot Neppert wrote: > Have you ever browsed a reasonably large codebase and counted the > occurrences of 'finally' blocks that deal with nullable resources? > Well, I have, and I found the infamous Class.getResourceAsStream to be > the _only_ example of such a construct. > And even that is easy to forego without adding any substantial > clutter. Simply test the existence of the resource before opening the > InputStream: > > URL resource = getClass().getResource("resourceThatMayOrMayNotExist"); > if(resource != null) { > try(InputStream stream = resource.openStream()) > { > ... > } > } > > _All other_ uses of try-finally blocks in my code deal with resources > that are guaranteed to be non-null, because they > are initialized by 'new' expressions or factory functions: > > java.sql.Statements, ResultSets, InputStreams, OutputStreams, Readers, > Writers, Locks... > > In practice, having to deal with null-resources will probably be as > rare as having to deal with null-iterators in a foreach loop. > > > 2011/1/28 Reinier Zwitserloot : > >> I don't understand why one couldn't explain t-w-r by showing "if (resource >> != null) resource.close();" in the finally block. >> >> It is then your opinion that this code is abusing the t-w-r construct, >> because Class.getResourceAsStream can return null? >> >> try (InputStream introTextStream = >> getClass().getResourceAsStream("intro.txt")) { >> ... >> } >> >> If so, we've clearly progressed into the "Everyone has their own 'feeling', >> none of them agree with each other, and making language decisions based on >> these feelings is a silly thing to do" phase. Let's check how often the >> above occurs. I'm betting it'll be "loads of times". Also contrast what >> you'd have to write if the above is not okay: >> >> InputStream introTextStream1 = getClass().getResourceAsStream(); >> if (introTextStream1 != null) { >> try (InputStream introTextStream2 = introTextStream1) { >> ... >> } >> } >> >> I assume I don't have to resort to 'feeling' to claim that the above is just >> bad. >> >> --Reinier Zwitserloot >> >> >> >> On Fri, Jan 28, 2011 at 7:38 AM, David Holmes wrote: >> >> >>> Tim Peierls said the following on 01/28/11 00:47: >>> >>>> I don't know about C#, but I like the formulation that can be sloppily >>>> summarized as "t-w-r calls close on non-null resources". >>>> >>> So to summarize there are three potential candidates for: >>> >>> try (Resource r = getResource() { >>> // stuff here >>> } >>> >>> I'm ignoring the suppressed exception aspects for simplicity: >>> >>> a) Simple transformation into try-finally (current implemented semantics) >>> >>> Resource r = getResource(); >>> try { >>> // stuff here >>> } >>> finally { >>> r.close(); >>> } >>> >>> b) Transformation into try-finally with explicit null-check on entry >>> >>> Resource r = getResource(); >>> Objects.requireNonNull(r); // heh heh - couldn't resist! >>> try { >>> // stuff here >>> } >>> finally { >>> r.close(); >>> } >>> >>> c) Simple transformation into try-finally but only close a non-null >>> resource >>> >>> Resource r = getResource(); >>> try { >>> // stuff here >>> } >>> finally { >>> if (r != null) >>> r.close(); >>> } >>> >>> >>> Option (a) is, perhaps, the most consistent with preserving the >>> behaviour of current code that would be modified to use the new >>> construct. This construct will be taught by analogy as it is the only >>> effective way to explain things "try-with-resources behaves as-if you >>> had written ....". That said I think existing code would have an >>> explicit null-check to avoid the try-finally in the null case. And I >>> think it is potentially risky to execute the try block only to have NPE >>> thrown later. >>> >>> Option (c) seems appealing in some sense because there's no NPE's at all >>> if you don't use "r", but I think that appeal is superficial. To me the >>> fundamental question to ask is: what is try-with-resources for? And I >>> believe the answer to that is to initialize, use and then clean-up an >>> AutoCloseable object. So to me using try-with-resource on a resource >>> that might be null is simply a mis-use of try-with-resources: if it can >>> be null you can't autoclose it, so trying to is a programming error and >>> programming errors should be detected and reported as early as possible. >>> So to me option (b) is the preferred semantics for this new construct. >>> >>> David Holmes >>> >>> >>> >> > > From brucechapman at paradise.net.nz Mon Jan 31 10:42:35 2011 From: brucechapman at paradise.net.nz (Bruce Chapman) Date: Tue, 01 Feb 2011 07:42:35 +1300 Subject: try-with-resources and null resource In-Reply-To: References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> <4D3DD4CA.1070802@univ-mlv.fr> <4D3DDA72.4040603@oracle.com> <4D3E0DF3.8080100@univ-mlv.fr> <4D3E3265.6050901@oracle.com> <4D3EBEA7.8010008@univ-mlv.fr> <4D3EC606.7090603@oracle.com> <4D4292AE.80408@cs.lth.se> Message-ID: <4D47029B.1070605@paradise.net.nz> On 29/01/2011 12:05 a.m., Gernot Neppert wrote: > 2011/1/28 Stephen Colebourne: >> Nulls are everywhere, and using null as a return type to indicate that >> something isn't present (like a resource) is very widespread. >> > I don't think anybody in this discussion would dispute your > doubtlessly correct observation. > Of course nulls are prevalent throughout Java code, and they serve a > good purpose! > > _But_: We're not talking about property getters returning null values here. > > We're talking about the expressions that initialize resources, a.k.a > expressions that modify a resource so that it ends up being in a > 'closeable' state. > This is a very specific subset of expressions, for which the > presupposition that it never returns null is IMHO very reasonable. > > But we are not designing a new language. We are trying to embody a common idiom that is difficult to get right in the current version of an existing language, so that it is easy to get right. So no matter how reasonable the presupposition might be (IYHO), it is still wrong on account of (at least) getResourceAsStream() (which, significantly, is in the java.lang package). Bruce From vimilsaju at yahoo.com Mon Jan 31 11:51:42 2011 From: vimilsaju at yahoo.com (Vimil Saju) Date: Mon, 31 Jan 2011 11:51:42 -0800 (PST) Subject: try-with-resources and null resource In-Reply-To: <4D42922E.5080101@optrak.co.uk> Message-ID: <906966.87507.qm@web161208.mail.bf1.yahoo.com> The following code pattern is present at many places in our code base. List records = new ArrayList(); ResultSet rs = null; try { rs = executeQuery(st); records = fetchRecords(rs, returnClass); } catch(Exception ex) { logDBError(ex); throw new DBException(ErrorCodes.DB_FETCH_ERROR, ex); } finally { freeUp(rs); } return records; How would the about code look like with the new try-with-resources syntax?? --- On Fri, 1/28/11, Mark Thornton wrote: From: Mark Thornton Subject: Re: try-with-resources and null resource To: coin-dev at openjdk.java.net Date: Friday, January 28, 2011, 1:53 AM On 28/01/2011 09:30, Florian Weimer wrote: > > By the way, has anybody else seen this phenomenon in their code base? > >? ? InputStream in = null; >? ? try { >? ? ? in = new FileInputStream(path); >? ? ? useFile(in); >? ? } finally { >? ? ? if (in != null) { >? ? ? ? in.close(); >? ? ? } >? ? } > > I'm wondering where this is coming from. > In my experience, it arises where you have or might expect to extend to cases with more than one resource. You only need one try statement instead of a whole nest of them. Once you start doing this for the multi resource case I suspect there is a tendency to use the same style for single resources as well. Mark Thornton From tom.hawtin at oracle.com Mon Jan 31 12:26:14 2011 From: tom.hawtin at oracle.com (Tom Hawtin) Date: Mon, 31 Jan 2011 20:26:14 +0000 Subject: try-with-resources and null resource In-Reply-To: <906966.87507.qm@web161208.mail.bf1.yahoo.com> References: <906966.87507.qm@web161208.mail.bf1.yahoo.com> Message-ID: <4D471AE6.1020605@oracle.com> On 31/01/2011 19:51, Vimil Saju wrote: > The following code pattern is present at many places in our code base. > List records = new ArrayList(); ResultSet rs = null; > try { rs = executeQuery(st); records = fetchRecords(rs, returnClass); } catch(Exception ex) { logDBError(ex); throw new DBException(ErrorCodes.DB_FETCH_ERROR, ex); } finally { freeUp(rs); } > return records; > How would the about code look like with the new try-with-resources syntax? Looks like copy-and-paste messed up the formatting: List records = new ArrayList(); ResultSet rs = null; try { rs = executeQuery(st); records = fetchRecords(rs, returnClass); } catch (Exception ex) { logDBError(ex); throw new DBException(ErrorCodes.DB_FETCH_ERROR, ex); } finally { freeUp(rs); } return records; I'm going to assume that executeQuery does not return null and that freeUp closes the ResultSet if non-null and wraps the SQLException as a DBException. try { try (ResultSet rs = executeQuery(st)) { return fetchRecords(rs, returnClass); } } catch (Exception ex) { logDBError(ex); throw new DBException(ErrorCodes.DB_FETCH_ERROR, ex); } (I've left catch Exception in, although usually such a broad catch would be considered a bad idea in most situations.) The Execute Around idiom is still a good idea. A better idea when we have concise anonymous inner class syntax/lambdas. (Or an ORM!) Tom From forax at univ-mlv.fr Mon Jan 31 12:30:01 2011 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Mon, 31 Jan 2011 21:30:01 +0100 Subject: try-with-resources and null resource In-Reply-To: <906966.87507.qm@web161208.mail.bf1.yahoo.com> References: <906966.87507.qm@web161208.mail.bf1.yahoo.com> Message-ID: <4D471BC9.1000001@univ-mlv.fr> On 01/31/2011 08:51 PM, Vimil Saju wrote: > The following code pattern is present at many places in our code base. > List records = new ArrayList(); ResultSet rs = null; > try { rs = executeQuery(st); records = fetchRecords(rs, returnClass); } catch(Exception ex) { logDBError(ex); throw new DBException(ErrorCodes.DB_FETCH_ERROR, ex); } finally { freeUp(rs); } > return records; > How would the about code look like with the new try-with-resources syntax? I suppose that freeUp(rs) is equivalent to rs.close(). try(ResultSet rs = executeQuery(st)) { return fetchRecords(rs, List.class); } catch(Exception ex) { logDBError(ex); throw new DBException(ErrorCodes.DB_FETCH_ERROR, ex); } R?mi From vimilsaju at yahoo.com Mon Jan 31 15:23:01 2011 From: vimilsaju at yahoo.com (Vimil Saju) Date: Mon, 31 Jan 2011 15:23:01 -0800 (PST) Subject: try-with-resources and null resource Message-ID: <213991.97406.qm@web161218.mail.bf1.yahoo.com> >--- On Mon, 1/31/11, R?mi Forax wrote: > >From: R?mi Forax >Subject: Re: try-with-resources and null resource >To: coin-dev at openjdk.java.net >Date: Monday, January 31, 2011, 12:30 PM > >On 01/31/2011 08:51 PM, Vimil Saju wrote: >> The following code pattern is present at many places in our code base. >> ??? List? records = new ArrayList();??? ResultSet rs = null; >> ??? try {??? ??? rs = executeQuery(st);??? ??? records = fetchRecords(rs, returnClass);??? }??? catch(Exception ex) {??? ??? logDBError(ex);??? ??? throw new DBException(ErrorCodes.DB_FETCH_ERROR, ex);??? }??? finally {??? ??? freeUp(rs);??? } >> ??? return records; >> How would the about code look like with the new try-with-resources syntax? > >I suppose that freeUp(rs) is equivalent to rs.close(). > >try(ResultSet rs = executeQuery(st)) { >???return fetchRecords(rs, List.class); >} catch(Exception ex) { >???logDBError(ex); >???throw new DBException(ErrorCodes.DB_FETCH_ERROR, ex); >} That looks good, I was a bit worried that a catch block couldn't be attached to the new try-with-resources construct From joe.darcy at oracle.com Mon Jan 31 16:00:37 2011 From: joe.darcy at oracle.com (Joe Darcy) Date: Mon, 31 Jan 2011 16:00:37 -0800 Subject: try-with-resources and null resource In-Reply-To: <213991.97406.qm@web161218.mail.bf1.yahoo.com> References: <213991.97406.qm@web161218.mail.bf1.yahoo.com> Message-ID: <4D474D25.20400@oracle.com> Vimil Saju wrote: >> --- On Mon, 1/31/11, R?mi Forax wrote: >> >> From: R?mi Forax >> Subject: Re: try-with-resources and null resource >> To: coin-dev at openjdk.java.net >> Date: Monday, January 31, 2011, 12:30 PM >> >> On 01/31/2011 08:51 PM, Vimil Saju wrote: >> >>> The following code pattern is present at many places in our code base. >>> List records = new ArrayList(); ResultSet rs = null; >>> try { rs = executeQuery(st); records = fetchRecords(rs, returnClass); } catch(Exception ex) { logDBError(ex); throw new DBException(ErrorCodes.DB_FETCH_ERROR, ex); } finally { freeUp(rs); } >>> return records; >>> How would the about code look like with the new try-with-resources syntax? >>> >> I suppose that freeUp(rs) is equivalent to rs.close(). >> >> try(ResultSet rs = executeQuery(st)) { >> return fetchRecords(rs, List.class); >> } catch(Exception ex) { >> logDBError(ex); >> throw new DBException(ErrorCodes.DB_FETCH_ERROR, ex); >> } >> > > That looks good, I was a bit worried that a catch block couldn't be attached to the new try-with-resources construct > > Since last July [1], JDK 7 builds with an implementation of try-with-resources have been available to download and people were invited to use that feature in particular and send in feedback. -Joe [1] "Project Coin ARM Implementation," http://blogs.sun.com/darcy/entry/project_coin_arm_implementation [2] "Project Coin: Try out try-with-resources", http://blogs.sun.com/darcy/entry/project_coin_try_out_try From joe.darcy at oracle.com Mon Jan 31 19:15:36 2011 From: joe.darcy at oracle.com (Joe Darcy) Date: Mon, 31 Jan 2011 19:15:36 -0800 Subject: How to terminate resources in try-with-resources Message-ID: <4D477AD8.3040303@oracle.com> Hello. In addition to mulling over nulling in the try-with-resources statement, the JSR 334 expert group has decided to slightly amend the syntax of try-with-resources statement: an optional trailing semicolon will now be allowed to terminate the list of resources. Previously, a semicolon could only be used as a separator between two resources as in try(Resource r0 = new Resource(); Resource r1 = new Resource(); Resource r2 = new Resource()) {...} or reformatted as try(Resource r0 = new Resource(); Resource r1 = new Resource(); Resource r2 = new Resource()) {...} However, including an extraneous semicolon at the end of the list would be rejected as a syntax error: try(Resource r0 = new Resource(); Resource r1 = new Resource(); Resource r2 = new Resource();) {...} // Illegal under JSR 334 EDR! While requiring a semicolon at the end of a list of resources would be excessive, especially when there is only a single resource being managed, optionally allowing a terminating resource offers several advantages. First, when adding a resource to the list of resources being managed, there are fewer necessary edits when cutting and pasting. More importantly, programmatic generation of code is simplified since the code generation logic does not need to know ahead of time whether or not a particular resource will be the last one when the declaration for that resource is generated. The simple rule "terminate a resource declaration with a semicolon" will result in acceptable code, even if the code is not ideal style-wise. Finally, allowing an optional trailing semicolon is consistent with the handling of commas in array initializers, int[] values = {1, 2, 3, // Legal }; and the handling of commas in the declaration of enum constants. enum PrimaryColor { RED, GREEN, BLUE, // Legal ; } The full amended grammar for try-with-resources which allows the optional trailing semicolon is: TryStatement: try Block Catches try Block Catches_opt Finally try ResourceSpecification Block Catches_opt Finally_opt ResourceSpecification: ( Resources ;_opt ) Resources: Resource Resource ; Resources Resource: VariableModifiers_opt Type VariableDeclaratorId = Expression The necessary compiler changes to implement the revised grammar have been pushed into a JDK 7 integration repository [1] and will appear in a promoted build in due course. -Joe [1] http://hg.openjdk.java.net/jdk7/tl/langtools/rev/2ab47c4cd618 From reinier at zwitserloot.com Mon Jan 31 19:24:11 2011 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Tue, 1 Feb 2011 04:24:11 +0100 Subject: try-with-resources and null resource In-Reply-To: <4D4292AE.80408@cs.lth.se> References: <4D39BE95.60903@univ-mlv.fr> <4D39E0B7.40306@oracle.com> <4D3AD70B.2020300@univ-mlv.fr> <4D3DCC44.8030302@oracle.com> <4D3DD4CA.1070802@univ-mlv.fr> <4D3DDA72.4040603@oracle.com> <4D3E0DF3.8080100@univ-mlv.fr> <4D3E3265.6050901@oracle.com> <4D3EBEA7.8010008@univ-mlv.fr> <4D3EC606.7090603@oracle.com> <4D4292AE.80408@cs.lth.se> Message-ID: Jesper, how? If I call getResourceAsStream, and I *NEVER* reference the resulting inputstream, that'd be very weird code. I can imagine, though, that I am going to nullcheck this resource and take some alternative action if the resource is missing. Or I presuppose it has to be there, and I'll get an NPE anyway (though at a much nicer point than the close brace!) - The point is, with 'nulls aren't closed', this is simple to write. With 'nulls cause NPEs', this is a major pain to write, requiring 2 variables, both of which take up a name. Having to come up with frivolous names does not feel like good design to me. You keep saying 'silently ignore', but this cannot happen. You open a resource, you'll read from it. The corner case of opening a 'resource' without the need to actually read from it, for example as some sort of transaction or custom implementation that feels a lot like java's synchronized () {} block, well, those blocks are yet to be built, and the library designers can keep in mind that returning nulls out of the 'createTransaction' method is a very bad idea. As Stephen said, just because gRAS is the only one a casual inspection can find in java.*, doesn't mean it'll be the only one in the greater java ecosystem. Also, personally I find gRAS enough of a use case even if it _IS_ the only one. Note that 'fixing' it by writing your own static wrapper sounds like a horrible idea (note how we're now attempting to fix the mistake of Collections.sort and friends by introducing defender methods), and we can't use the defender method JSR to fix this, as Class is not an interface. Certainly adding a new method to j.l.Class to replace gRAS is also not a good option, and, finally, FileNotFoundException is a bad name. It would have to be ResourceNotFoundException - thus adding a new class to java.lang, which is also a very bad idea. (Or, add it to java.io, which is still not entirely risk-free, and weird, as a java.lang class will be the only code that ever throws a java.io exception). --Reinier Zwitserloot On Fri, Jan 28, 2011 at 10:55 AM, Jesper ?qvist wrote: > Hi Reinier, > > On 2011-01-28 06:50, Reinier Zwitserloot wrote: > > I have a question, and, presupposing either answer, a followup question: > > > > 1. In the above snippet, is t final? > Yes > > 2 if yes: Well, then, calling a method that returns null, such as for > > example Class.getResourceAsStream, is going to be an unbelievable pain. > As > > the NPE is then unavoidable, you'd need to assign it to a variable, check > > that variable, and if that variable is not null, start a try block, which > > REQUIRES that you create a NEW variable. urghhhhh!!!!!!! What do I name > > this? out1 and out2? I've got a very big problem with this. even if t is > not > > final, I'd have to create a dummy input stream just to have something to > > close. > If Class.getResourceAsStream returns null, it means the resource could > not be found. In _most_ cases you want to handle this scenario > explicitly instead of skipping the resource entirely. > > If the try with resources-statement would silently ignore that the > resource was null, then possible errors might go unnoticed by the > programmer. > > I believe that suppressing NPEs just serves to obscure actual problems > in the handling of your resources. > > This whole discussion highlights why programming with null is a bad > idea, but if we must use null then there should be exceptions whenever > we try to use null. Java is already a bit confused on this point - in > some cases null means "nothing" while in other cases it means > "invalid/error". > > Jesper > >