From jonathan.gibbons at oracle.com Tue Jan 2 21:49:19 2018 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Tue, 02 Jan 2018 13:49:19 -0800 Subject: RFR: JDK-8183964: Bad lexing of javadoc comments (change in parsing/rendering of backslashes in javadoc) Message-ID: <5A4BFE5F.20404@oracle.com> Please review this simple fix in the tokenizer for reading javadoc comments. The fix is just to add a missing 'break' statement. JBS: https://bugs.openjdk.java.net/browse/JDK-8183964 Webrev: http://cr.openjdk.java.net/~jjg/8183961/webrev.00 -- Jon From vicente.romero at oracle.com Tue Jan 2 22:02:15 2018 From: vicente.romero at oracle.com (Vicente Romero) Date: Tue, 2 Jan 2018 17:02:15 -0500 Subject: RFR: JDK-8183964: Bad lexing of javadoc comments (change in parsing/rendering of backslashes in javadoc) In-Reply-To: <5A4BFE5F.20404@oracle.com> References: <5A4BFE5F.20404@oracle.com> Message-ID: <969f55e8-2030-ccd4-90cd-d81db5d272e8@oracle.com> looks good, Vicente On 01/02/2018 04:49 PM, Jonathan Gibbons wrote: > Please review this simple fix in the tokenizer for reading javadoc > comments. > The fix is just to add a missing 'break' statement. > > JBS: https://bugs.openjdk.java.net/browse/JDK-8183964 > Webrev: http://cr.openjdk.java.net/~jjg/8183961/webrev.00 > > -- Jon From cushon at google.com Tue Jan 2 22:55:35 2018 From: cushon at google.com (Liam Miller-Cushon) Date: Tue, 2 Jan 2018 17:55:35 -0500 Subject: RFR: JDK-8183964: Bad lexing of javadoc comments (change in parsing/rendering of backslashes in javadoc) In-Reply-To: <969f55e8-2030-ccd4-90cd-d81db5d272e8@oracle.com> References: <5A4BFE5F.20404@oracle.com> <969f55e8-2030-ccd4-90cd-d81db5d272e8@oracle.com> Message-ID: Looks good to me too, for what that's worth. Is this a good candidate for backporting to 9u? On Tue, Jan 2, 2018 at 5:02 PM, Vicente Romero wrote: > looks good, > Vicente > > > On 01/02/2018 04:49 PM, Jonathan Gibbons wrote: > >> Please review this simple fix in the tokenizer for reading javadoc >> comments. >> The fix is just to add a missing 'break' statement. >> >> JBS: https://bugs.openjdk.java.net/browse/JDK-8183964 >> Webrev: http://cr.openjdk.java.net/~jjg/8183961/webrev.00 >> >> -- Jon >> > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From jonathan.gibbons at oracle.com Tue Jan 2 23:00:55 2018 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Tue, 2 Jan 2018 15:00:55 -0800 Subject: RFR: JDK-8183964: Bad lexing of javadoc comments (change in parsing/rendering of backslashes in javadoc) In-Reply-To: References: <5A4BFE5F.20404@oracle.com> <969f55e8-2030-ccd4-90cd-d81db5d272e8@oracle.com> Message-ID: Thanks for checking this out. I agree it seems a reasonable candidate to backport, but I'd have to check the latest policies for backporting issues. -- Jon On 1/2/18 2:55 PM, Liam Miller-Cushon wrote: > Looks good to me too, for what that's worth. > > Is this a good candidate for backporting to 9u? > > On Tue, Jan 2, 2018 at 5:02 PM, Vicente Romero > > wrote: > > looks good, > Vicente > > > On 01/02/2018 04:49 PM, Jonathan Gibbons wrote: > > Please review this simple fix in the tokenizer for reading > javadoc comments. > The fix is just to add a missing 'break' statement. > > JBS: https://bugs.openjdk.java.net/browse/JDK-8183964 > > Webrev: http://cr.openjdk.java.net/~jjg/8183961/webrev.00 > > > -- Jon > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From jonathan.gibbons at oracle.com Wed Jan 3 00:53:26 2018 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Tue, 02 Jan 2018 16:53:26 -0800 Subject: RFR: JDK-8193125: javac should not compile a module if it requires java.base with modifiers Message-ID: <5A4C2986.70201@oracle.com> Please review a relatively simple change to javac, to track changes in the JLS for JDK 10. Source and class files that "require" java.base with either the static or transitive modifiers will be rejected. The code is complicated a bit for source files because of the different ways of handling the two different modifiers. This affects both the detection and the diagnostic generation. The new test generates various source files and compiles them under different source versions. It also uses the classfile library to generate various classfiles via mutation to to be read by other files. JBS: https://bugs.openjdk.java.net/browse/JDK-8193125 Webrev: http://cr.openjdk.java.net/~jjg/8193125/webrev.00 -- Jon From vicente.romero at oracle.com Wed Jan 3 01:37:37 2018 From: vicente.romero at oracle.com (Vicente Romero) Date: Tue, 2 Jan 2018 20:37:37 -0500 Subject: RFR: JDK-8193125: javac should not compile a module if it requires java.base with modifiers In-Reply-To: <5A4C2986.70201@oracle.com> References: <5A4C2986.70201@oracle.com> Message-ID: <5cc7759e-715b-693b-c481-1a53813aa22e@oracle.com> looks good, some minor indentation issues but probably because of tabs Thanks, Vicente On 01/02/2018 07:53 PM, Jonathan Gibbons wrote: > Please review a relatively simple change to javac, to track changes in > the JLS for JDK 10. > > Source and class files that "require" java.base with either the static > or transitive modifiers will be rejected. > > The code is complicated a bit for source files because of the > different ways of handling the two different modifiers. This affects > both the detection and the diagnostic generation. > > The new test generates various source files and compiles them under > different source versions. It also uses the classfile library to > generate various classfiles via mutation to to be read by other files. > > JBS: https://bugs.openjdk.java.net/browse/JDK-8193125 > Webrev: http://cr.openjdk.java.net/~jjg/8193125/webrev.00 > > -- Jon > > From jonathan.gibbons at oracle.com Wed Jan 3 16:40:46 2018 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Wed, 3 Jan 2018 08:40:46 -0800 Subject: bash configure fails on missing javah In-Reply-To: <70aed935-bf11-1efb-d4c9-ed72f3b46d6d@oracle.com> References: <70aed935-bf11-1efb-d4c9-ed72f3b46d6d@oracle.com> Message-ID: <75e17ef6-7af3-ac95-6e11-b6a42e3a76e1@oracle.com> Note the corollary is that this impacts when javac can use recent language features.? i.e. in order to build the "interim javac", the? javac source code must be compatible with the "boot JDK". There's nothing inherently new in that, but the new release schedule is definitely going to have an impact here. -- Jon On 1/3/18 12:12 AM, Erik Joelsson wrote: > The build hasn't used javah in a long time, so the configure check for > it is just a left over that we forgot to clean up. It should certainly > be removed and we will be forced to do it once we switch to JDK 10 as > boot jdk for 11. > > Note though that we will not switch to JDK 10 as boot for 11 until we > have an actual release of 10. Until then, the boot JDK for the > development of 11 will remain as 9. In the past, this interim > situation was pretty limited in time so we rarely had to deal with it. > With the new release schedule, we are going to be in this situation a > lot more, so the build documentation needs to be updated to explain this. > > /Erik > > > On 2018-01-03 05:05, Martin Buchholz wrote: >> I agree configure should not fail if javah is not found.? A high quality >> configure test would first check if javac -h works, then fall back to >> javah >> if that works, regardless of the boot jdk's version. >> >> On Tue, Jan 2, 2018 at 6:33 AM, Nir Lisker wrote: >> >>> I'm trying to build OpenJDK 11 as instructed here: >>> http://hg.openjdk.java.net/jdk/jdk/raw-file/tip/doc/building.html. >>> >>> When executing `bash configure >>> --with-import-modules=jfx_path\rt\build\modular-sdk` >>> (I've build JavaFX) the build fails: >>> >>> checking for java in Boot JDK... ok >>> checking for javac in Boot JDK... ok >>> checking for javah in Boot JDK... not found >>> configure: Your Boot JDK seems broken. This might be fixed by >>> explicitly >>> setting --with-boot-jdk >>> configure: error: Could not find javah in the Boot JDK >>> configure exiting with result code 1 >>> >>> The boot JDK is 10, which does not have javah anymore, so it is no >>> surprise. I could point boot JDK to a previous version, but I don't >>> think I >>> should need to. What I should do? >>> >>> Nir >>> > From joe.darcy at oracle.com Wed Jan 3 18:32:22 2018 From: joe.darcy at oracle.com (joe darcy) Date: Wed, 3 Jan 2018 10:32:22 -0800 Subject: Re Take 2 of JDK 10 RFR of 8187951: Update javax.lang.model.SourceVersion for "var" name In-Reply-To: <59DEBDFC.6060405@oracle.com> References: <1f9b858d-4e43-8c9d-cbc1-60c728380bdc@oracle.com> <67ca68b6-46f3-1be6-5607-c59ce97407e3@oracle.com> <72dda0f6-7317-c538-8d4d-6029c872602c@oracle.com> <59DEBDFC.6060405@oracle.com> Message-ID: <9120e194-ac5d-6f06-000c-d65c7b69f27e@oracle.com> Hello, A second iteration for your consideration: http://cr.openjdk.java.net/~darcy/8187951.1/ In a specification sense, this iteration of the proposed change just documents the existing behavior on the string "var" and tests are added to verify that behavior. The handling of "var" is analogous to the handling of restricted keywords. (The webrev is generated against JDK 11, but I'll rebase to JDK 10 before pushing.) Corresponding CSR for review at: https://bugs.openjdk.java.net/browse/JDK-8194523 Thanks, -Joe From jonathan.gibbons at oracle.com Wed Jan 3 21:44:38 2018 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Wed, 03 Jan 2018 13:44:38 -0800 Subject: RFR: JDK-8194141: Remove JDK9Wrappers Message-ID: <5A4D4EC6.8020606@oracle.com> Please review this code to remove a "temporary" class from javac, to provide reflective access to JDK 9 API, so that javac itself could be built with JDK 8. This temporary class is no longer required, now that the boot JDK for JDK 10 onwards is JDK 9. This is primarily about replacing the use of a javac internal class with the underlying direct API calls. However, a minor change to the autoconf spec is also required, to grant compile-time access to some internal JDK API. Some comments from the jdk.compiler module-info are also updated. The fix is proposed for JDK 11. JBS: https://bugs.openjdk.java.net/browse/JDK-8194141 Webrev: http://cr.openjdk.java.net/~jjg/8194141/webrev.00 -- Jon From jonathan.gibbons at oracle.com Wed Jan 3 22:42:18 2018 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Wed, 03 Jan 2018 14:42:18 -0800 Subject: RFR: JDK-8194141: Remove JDK9Wrappers In-Reply-To: <5A4D4EC6.8020606@oracle.com> References: <5A4D4EC6.8020606@oracle.com> Message-ID: <5A4D5C4A.2000509@oracle.com> Updated webrev, reverting unnecessary change to generated-configure.sh http://cr.openjdk.java.net/~jjg/8194141/webrev.01/ -- Jon On 01/03/2018 01:44 PM, Jonathan Gibbons wrote: > Please review this code to remove a "temporary" class from javac, to > provide reflective access to JDK 9 API, so that javac itself could be > built with JDK 8. This temporary class is no longer required, now > that the boot JDK for JDK 10 onwards is JDK 9. > > This is primarily about replacing the use of a javac internal class > with the underlying direct API calls. However, a minor change to the > autoconf spec is also required, to grant compile-time access to some > internal JDK API. Some comments from the jdk.compiler module-info are > also updated. > > The fix is proposed for JDK 11. > > JBS: https://bugs.openjdk.java.net/browse/JDK-8194141 > Webrev: http://cr.openjdk.java.net/~jjg/8194141/webrev.00 > > -- Jon > > From Alan.Bateman at oracle.com Thu Jan 4 07:53:06 2018 From: Alan.Bateman at oracle.com (Alan Bateman) Date: Thu, 4 Jan 2018 07:53:06 +0000 Subject: RFR: JDK-8194141: Remove JDK9Wrappers In-Reply-To: <5A4D5C4A.2000509@oracle.com> References: <5A4D4EC6.8020606@oracle.com> <5A4D5C4A.2000509@oracle.com> Message-ID: On 03/01/2018 22:42, Jonathan Gibbons wrote: > Updated webrev, reverting unnecessary change to generated-configure.sh > > http://cr.openjdk.java.net/~jjg/8194141/webrev.01/ This cleanup looks good to me. -Alan From erik.joelsson at oracle.com Thu Jan 4 08:33:14 2018 From: erik.joelsson at oracle.com (Erik Joelsson) Date: Thu, 4 Jan 2018 09:33:14 +0100 Subject: RFR: JDK-8194141: Remove JDK9Wrappers In-Reply-To: <5A4D5C4A.2000509@oracle.com> References: <5A4D4EC6.8020606@oracle.com> <5A4D5C4A.2000509@oracle.com> Message-ID: Looks good to me. /Erik On 2018-01-03 23:42, Jonathan Gibbons wrote: > Updated webrev, reverting unnecessary change to generated-configure.sh > > http://cr.openjdk.java.net/~jjg/8194141/webrev.01/ > > -- Jon > > On 01/03/2018 01:44 PM, Jonathan Gibbons wrote: >> Please review this code to remove a "temporary" class from javac, to >> provide reflective access to JDK 9 API, so that javac itself could be >> built with JDK 8.? This temporary class is no longer required, now >> that the boot JDK for JDK 10 onwards is JDK 9. >> >> This is primarily about replacing the use of a javac internal class >> with the underlying direct API calls. However, a minor change to the >> autoconf spec is also required, to grant compile-time access to some >> internal JDK API. Some comments from the jdk.compiler module-info are >> also updated. >> >> The fix is proposed for JDK 11. >> >> JBS: https://bugs.openjdk.java.net/browse/JDK-8194141 >> Webrev: http://cr.openjdk.java.net/~jjg/8194141/webrev.00 >> >> -- Jon >> >> > From jonathan.gibbons at oracle.com Fri Jan 5 00:54:38 2018 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Thu, 04 Jan 2018 16:54:38 -0800 Subject: RFR: 8191637: Interface with defaults invalid compiler warning for Serializable Message-ID: <5A4ECCCE.9030206@oracle.com> Please review this fix for JDK-8191637, which modifies an earlier fix for JDK-6356530. Prior to the fix for JDK-6356530, all abstract classes (including interfaces) were excluded from the check for serialVersionUID. The fix for JDK-6356530 modified the check, but focussed on concrete methods (including default methods for interfaces) instead of serializable fields. This fix updates the check so that interfaces are never checked, and abstract classes are only checked if they have serializable (non-static, non-transient) fields. JBS 1: https://bugs.openjdk.java.net/browse/JDK-8191637 JBS 2: https://bugs.openjdk.java.net/browse/JDK-6356530 Webrev: http://cr.openjdk.java.net/~jjg/8191637/webrev.00/ -- Jon From vicente.romero at oracle.com Fri Jan 5 01:30:36 2018 From: vicente.romero at oracle.com (Vicente Romero) Date: Thu, 4 Jan 2018 20:30:36 -0500 Subject: RFR: 8191637: Interface with defaults invalid compiler warning for Serializable In-Reply-To: <5A4ECCCE.9030206@oracle.com> References: <5A4ECCCE.9030206@oracle.com> Message-ID: <5e56a882-18a0-1614-a6aa-4d43ec98ae07@oracle.com> looks good, Vicente On 01/04/2018 07:54 PM, Jonathan Gibbons wrote: > Please review this fix for JDK-8191637, which modifies an earlier fix > for JDK-6356530. > > Prior to the fix for JDK-6356530, all abstract classes (including > interfaces) were excluded from the check for serialVersionUID. The fix > for JDK-6356530 modified the check, but focussed on concrete methods > (including default methods for interfaces) instead of serializable > fields. > > This fix updates the check so that interfaces are never checked, and > abstract classes are only checked if they have serializable > (non-static, non-transient) fields. > > JBS 1: https://bugs.openjdk.java.net/browse/JDK-8191637 > JBS 2: https://bugs.openjdk.java.net/browse/JDK-6356530 > Webrev: http://cr.openjdk.java.net/~jjg/8191637/webrev.00/ > > -- Jon From jonathan.gibbons at oracle.com Fri Jan 5 19:33:30 2018 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Fri, 05 Jan 2018 11:33:30 -0800 Subject: RFR: 8191637: Interface with defaults invalid compiler warning for Serializable In-Reply-To: <5A4ECCCE.9030206@oracle.com> References: <5A4ECCCE.9030206@oracle.com> Message-ID: <5A4FD30A.30700@oracle.com> Updated webrev, based on feedback from serialization folk. Interfaces need never have a serialVersionIUID. All serializable classes (i.e. either concrete or abstract) are candidates to be checked for the presence of a serialVersionUID Webrev: http://cr.openjdk.java.net/~jjg/8191637/webrev.01/ -- Jon On 01/04/2018 04:54 PM, Jonathan Gibbons wrote: > Please review this fix for JDK-8191637, which modifies an earlier fix > for JDK-6356530. > > Prior to the fix for JDK-6356530, all abstract classes (including > interfaces) were excluded from the check for serialVersionUID. The fix > for JDK-6356530 modified the check, but focussed on concrete methods > (including default methods for interfaces) instead of serializable > fields. > > This fix updates the check so that interfaces are never checked, and > abstract classes are only checked if they have serializable > (non-static, non-transient) fields. > > JBS 1: https://bugs.openjdk.java.net/browse/JDK-8191637 > JBS 2: https://bugs.openjdk.java.net/browse/JDK-6356530 > Webrev: http://cr.openjdk.java.net/~jjg/8191637/webrev.00/ > > -- Jon From vicente.romero at oracle.com Fri Jan 5 20:56:17 2018 From: vicente.romero at oracle.com (Vicente Romero) Date: Fri, 5 Jan 2018 15:56:17 -0500 Subject: RFR: 8191637: Interface with defaults invalid compiler warning for Serializable In-Reply-To: <5A4FD30A.30700@oracle.com> References: <5A4ECCCE.9030206@oracle.com> <5A4FD30A.30700@oracle.com> Message-ID: <371efea2-54fd-e1ed-9979-1e2154b2ef4d@oracle.com> this one looks even better ;) Vicente On 01/05/2018 02:33 PM, Jonathan Gibbons wrote: > Updated webrev, based on feedback from serialization folk. > > Interfaces need never have a serialVersionIUID. > All serializable classes (i.e. either concrete or abstract) are > candidates to be checked for the presence of a serialVersionUID > > Webrev: http://cr.openjdk.java.net/~jjg/8191637/webrev.01/ > > -- Jon > > On 01/04/2018 04:54 PM, Jonathan Gibbons wrote: >> Please review this fix for JDK-8191637, which modifies an earlier fix >> for JDK-6356530. >> >> Prior to the fix for JDK-6356530, all abstract classes (including >> interfaces) were excluded from the check for serialVersionUID. The >> fix for JDK-6356530 modified the check, but focussed on concrete >> methods (including default methods for interfaces) instead of >> serializable fields. >> >> This fix updates the check so that interfaces are never checked, and >> abstract classes are only checked if they have serializable >> (non-static, non-transient) fields. >> >> JBS 1: https://bugs.openjdk.java.net/browse/JDK-8191637 >> JBS 2: https://bugs.openjdk.java.net/browse/JDK-6356530 >> Webrev: http://cr.openjdk.java.net/~jjg/8191637/webrev.00/ >> >> -- Jon > From maurizio.cimadamore at oracle.com Mon Jan 8 11:51:30 2018 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Mon, 8 Jan 2018 11:51:30 +0000 Subject: Re Take 2 of JDK 10 RFR of 8187951: Update javax.lang.model.SourceVersion for "var" name In-Reply-To: <9120e194-ac5d-6f06-000c-d65c7b69f27e@oracle.com> References: <1f9b858d-4e43-8c9d-cbc1-60c728380bdc@oracle.com> <67ca68b6-46f3-1be6-5607-c59ce97407e3@oracle.com> <72dda0f6-7317-c538-8d4d-6029c872602c@oracle.com> <59DEBDFC.6060405@oracle.com> <9120e194-ac5d-6f06-000c-d65c7b69f27e@oracle.com> Message-ID: <81328974-222c-3e19-4631-1ea78053f218@oracle.com> Looks good Maurizio On 03/01/18 18:32, joe darcy wrote: > Hello, > > A second iteration for your consideration: > > ??? http://cr.openjdk.java.net/~darcy/8187951.1/ > > In a specification sense, this iteration of the proposed change just > documents the existing behavior on the string "var" and tests are > added to verify that behavior. The handling of "var" is analogous to > the handling of restricted keywords. (The webrev is generated against > JDK 11, but I'll rebase to JDK 10 before pushing.) > > Corresponding CSR for review at: > > ??? https://bugs.openjdk.java.net/browse/JDK-8194523 > > Thanks, > > -Joe > > From cushon at google.com Mon Jan 8 19:39:59 2018 From: cushon at google.com (Liam Miller-Cushon) Date: Mon, 8 Jan 2018 11:39:59 -0800 Subject: spec clarification: type annotations on static nested types In-Reply-To: References: Message-ID: Hello, does anyone have thoughts on whether this is a javac issue, or a spec and core reflection issue? Thanks, On Thu, Nov 30, 2017 at 11:04 AM, Liam Miller-Cushon wrote: > JVMS 9 4.7.20.2-A says that a type_path_kind value of 1 is used to > indicate a type annotation "is deeper in a nested type". I believe this > should be "deeper in a *non-static* nested type". A comment in JDK-8027263 > confirms that type path entries are used for inner classes, but not for > static nested classes. > > Example: > > ``` > import static java.lang.annotation.ElementType.TYPE_USE; > import static java.lang.annotation.RetentionPolicy.RUNTIME; > > import java.lang.annotation.Retention; > import java.lang.annotation.Target; > import java.lang.reflect.AnnotatedType; > import java.util.Arrays; > > class T { > @Retention(RUNTIME) > @Target(TYPE_USE) > @interface A {} > > class One {} > > static class Two {} > > void f(@A One x) {} > > void g(@A Two x) {} > > public static void main(String[] args) throws Exception { > debug(T.class.getDeclaredMethod("f", One.class). > getAnnotatedParameterTypes()[0]); > debug(T.class.getDeclaredMethod("g", Two.class). > getAnnotatedParameterTypes()[0]); > } > > static void debug(AnnotatedType type) { > System.err.println("type annotations: " + Arrays.toString(type. > getAnnotations())); > System.err.println( > "owner type annotations: " > + Arrays.toString(type.getAnnotatedOwnerType().getAnnotations())); > } > } > ``` > > Using type_path_kind=1 for inner classes, but not for static member > classes, is consistent with current javac behaviour. In the example, the > type path for the annotation on `@A One` is `[INNER_TYPE]` (One is an inner > class), and the type path for the annotation on `@A Two` is empty (Two is a > static member class): > > $ javap -v T > ... > void f(T$One); > ... > RuntimeVisibleTypeAnnotations: > 0: #31(): METHOD_FORMAL_PARAMETER, param_index=0, > location=[INNER_TYPE] > ... > void g(T$Two); > ... > RuntimeVisibleTypeAnnotations: > 0: #31(): METHOD_FORMAL_PARAMETER, param_index=0 > > Using type_path_kind=1 for inner classes is not consistent with the > current behaviour of core reflection. sun.reflect.annotation.AnnotatedTypeFactory > adjusts type paths in the implementation of getAnnotatedOwnerType() for > AnnotatedType and AnnotatedParameterizedType, and when handling > ParameterizedTypes in nestingForType, without considering whether the > nested type is static. This leads to apparently incorrect results for > getAnnotations(). Note that the type annotations on `@A Two` are reported > as being on both `Two` and its enclosing type `T`: > > $ javac T.java && java T. > # `@A One` > type annotations: [@T$A()] > owner type annotations: [] > # `@A Two` > type annotations: [@T$A()] > owner type annotations: [@T$A()] > > My questions are: > * if my understanding of JVMS 9 4.7.20.2-A is correct, can the spec be > updated to clarify that type_path_kind=1 means "deeper in a non-static > nested type", not "deeper in a nested type"? > * is javac's output for this example correct, and if so is this a bug in > AnnotatedTypeFactory? > > Thanks, > -------------- next part -------------- An HTML attachment was scrubbed... URL: From cushon at google.com Mon Jan 8 19:42:25 2018 From: cushon at google.com (Liam Miller-Cushon) Date: Mon, 8 Jan 2018 11:42:25 -0800 Subject: RFR: 8193037 package-info annotations are not reported when annotation processing is enabled In-Reply-To: References: Message-ID: Is anyone interested in sponsoring this patch? On Tue, Dec 5, 2017 at 5:49 PM, Liam Miller-Cushon wrote: > Hello, > > Please review the following fix for JDK-8193037. > > javac should only reset package-info symbols between annotation processing > rounds if > the package-info is being compiled from source. Previously package-infos > loaded from > the classpath were reset and not reinitialized, leading to package > annotations being > unavailable during later annotation processing rounds. > > I included an additional test case to ensure that package-infos are still > reset when > necessary. Related discussion: > http://mail.openjdk.java.net/pipermail/compiler-dev/2017- > December/011398.html > > bug: https://bugs.openjdk.java.net/browse/JDK-8193037 > webrev: http://cr.openjdk.java.net/~cushon/8193037/webrev.00/ > -------------- next part -------------- An HTML attachment was scrubbed... URL: From alex.buckley at oracle.com Mon Jan 8 20:42:46 2018 From: alex.buckley at oracle.com (Alex Buckley) Date: Mon, 08 Jan 2018 12:42:46 -0800 Subject: spec clarification: type annotations on static nested types In-Reply-To: References: Message-ID: <5A53D7C6.1070809@oracle.com> A type annotation can apply to a type that's nested (i.e. deeper) in a *static* type though. Adapting an example from JLS 9.7.4: --- import java.lang.annotation.ElementType; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Retention; import java.lang.annotation.Target; @Target(ElementType.TYPE_USE) @Retention(RetentionPolicy.RUNTIME) @interface Foo {} class Test { static class C { class D {} } @Foo C . D x; // Legal. @Foo annotates the type which occurs in a field declaration. C . @Foo D y; // Legal. @Foo annotates the type of a non-static member of C. } --- In the second case, the nested type which is being annotated is "C . D". The D part denotes a non-static nested type, yes, but the first type that we hit when stepping through the path -- C -- is static. The storage of @Foo thus involves a type_path that descends "deeper in a nested type" -- mentioning anything about static here would be wrong. As a separate issue, the location where we ultimately find @Foo is, in fact, a non-static member type, so javap helpfully shows that location as INNER_TYPE: Test$C$D y; RuntimeVisibleTypeAnnotations: 0: #12(): FIELD, location=[INNER_TYPE] (More below) On 1/8/2018 11:39 AM, Liam Miller-Cushon wrote: > Hello, does anyone have thoughts on whether this is a javac issue, or a > spec and core reflection issue? > > Thanks, > > On Thu, Nov 30, 2017 at 11:04 AM, Liam Miller-Cushon > wrote: > > JVMS 9 4.7.20.2-A says that a type_path_kind value of 1 is used to > indicate a type annotation "is deeper in a nested type". I believe > this should be "deeper in a *non-static* nested type". A comment in > JDK-8027263 confirms that type path entries are used for inner > classes, but not for static nested classes. > > Example: > > ``` > import static java.lang.annotation.ElementType.TYPE_USE; > import static java.lang.annotation.RetentionPolicy.RUNTIME; > > import java.lang.annotation.Retention; > import java.lang.annotation.Target; > import java.lang.reflect.AnnotatedType; > import java.util.Arrays; > > class T { > @Retention(RUNTIME) > @Target(TYPE_USE) > @interface A {} > > class One {} > > static class Two {} > > void f(@A One x) {} > > void g(@A Two x) {} > > public static void main(String[] args) throws Exception { > debug(T.class.getDeclaredMethod("f", > One.class).getAnnotatedParameterTypes()[0]); > debug(T.class.getDeclaredMethod("g", > Two.class).getAnnotatedParameterTypes()[0]); > } > > static void debug(AnnotatedType type) { > System.err.println("type annotations: " + > Arrays.toString(type.getAnnotations())); > System.err.println( > "owner type annotations: " > + > Arrays.toString(type.getAnnotatedOwnerType().getAnnotations())); > } > } > ``` > > Using type_path_kind=1 for inner classes, but not for static member > classes, is consistent with current javac behaviour. In the example, > the type path for the annotation on `@A One` is `[INNER_TYPE]` (One > is an inner class), and the type path for the annotation on `@A Two` > is empty (Two is a static member class): > > $ javap -v T > ... > void f(T$One); > ... > RuntimeVisibleTypeAnnotations: > 0: #31(): METHOD_FORMAL_PARAMETER, param_index=0, > location=[INNER_TYPE] > ... > void g(T$Two); > ... > RuntimeVisibleTypeAnnotations: > 0: #31(): METHOD_FORMAL_PARAMETER, param_index=0 I don't like how @A has been bounced out of the nested type "T . Two" so that it allegedly applies to the type of the formal parameter as a whole. @A actually applies to the type of the static member Two that is declared by T. It's fine to annotate the type of a static member. What the admissibility rule in JLS 9.7.4 is trying to prevent is annotating that type from too far away: T. at A One yy; // Legal T. at A Two zz; // Legal @A T.One yyy; // Legal @A T.Two zzz; // Not legal. Because Two is static, T is deemed to be more of a scoping construct than a type, so type annotations shan't apply. Alex > Using type_path_kind=1 for inner classes is not consistent with the > current behaviour of core reflection. > sun.reflect.annotation.AnnotatedTypeFactory adjusts type paths in > the implementation of getAnnotatedOwnerType() for AnnotatedType and > AnnotatedParameterizedType, and when handling ParameterizedTypes in > nestingForType, without considering whether the nested type is > static. This leads to apparently incorrect results for > getAnnotations(). Note that the type annotations on `@A Two` are > reported as being on both `Two` and its enclosing type `T`: > > $ javac T.java && java T. > # `@A One` > type annotations: [@T$A()] > owner type annotations: [] > # `@A Two` > type annotations: [@T$A()] > owner type annotations: [@T$A()] > > My questions are: > * if my understanding of JVMS 9 4.7.20.2-A is correct, can the spec > be updated to clarify that type_path_kind=1 means "deeper in a > non-static nested type", not "deeper in a nested type"? > * is javac's output for this example correct, and if so is this a > bug in AnnotatedTypeFactory? > > Thanks, > > From cushon at google.com Mon Jan 8 22:25:07 2018 From: cushon at google.com (Liam Miller-Cushon) Date: Mon, 8 Jan 2018 14:25:07 -0800 Subject: spec clarification: type annotations on static nested types In-Reply-To: <5A53D7C6.1070809@oracle.com> References: <5A53D7C6.1070809@oracle.com> Message-ID: Thanks! I have some follow-up questions inline - On Mon, Jan 8, 2018 at 12:42 PM, Alex Buckley wrote: > A type annotation can apply to a type that's nested (i.e. deeper) in a > *static* type though. Adapting an example from JLS 9.7.4: > ... In the second case, the nested type which is being annotated is "C . D". > The D part denotes a non-static nested type, yes, but the first type that > we hit when stepping through the path -- C -- is static. The storage of > @Foo thus involves a type_path that descends "deeper in a nested type" -- > mentioning anything about static here would be wrong. As a separate issue, > the location where we ultimately find @Foo is, in fact, a non-static member > type, so javap helpfully shows that location as INNER_TYPE: > I didn't express what I was thinking, sorry. I agree we're not interested in the static-ness of the outer type. I think javac currently emits type_path_kind=1 steps only when descending in to a member type that is non-static, and that the "location=[INNER_TYPE]" bit of javap's output corresponds directly to the type_path structure in the class file. Is that accurate, and if so is it to spec? My understanding of the `@Foo C . D x;` example was that no type_path is necessary even though C is a member of Test, because C is a static member and Test is 'scoping construct' that is not a valid type annotation target. I don't like how @A has been bounced out of the nested type "T . Two" so > that it allegedly applies to the type of the formal parameter as a whole. > @A actually applies to the type of the static member Two that is declared > by T. > Similar to the other example, isn't "@A actually applies to the type of the static member Two" the only interpretation for a type annotation attribute that applies to `T . Two`, since T is a scoping construct and is not a valid type annotation target? -------------- next part -------------- An HTML attachment was scrubbed... URL: From schaef at amazon.com Tue Jan 9 17:52:53 2018 From: schaef at amazon.com (Schaef, Martin) Date: Tue, 9 Jan 2018 17:52:53 +0000 Subject: Fixing JDK-8130493 Message-ID: Hi, We have some users suffering from JDK-8130493 (their builds succeed, but the compiler actually failed). I did some digging and the following sequence happens: A ClassNotFoundException is thrown in JavaProcessingEnvironment.ServiceIterator.next() and re-thrown as an Abort. This Abort reaches JavaCompiler.processAnnotations() and is finally caught in JavaCompiler.compile() by the following snippet: try { initProcessAnnotations(processors); // These method calls must be chained to avoid memory leaks delegateCompiler = processAnnotations( //<<<<<< ABORT COMES OUT HERE enterTrees(stopIfError(CompileState.PARSE, parseFiles(sourceFileObjects))), classnames); ? } catch (Abort ex) { if (devVerbose) ex.printStackTrace(System.err); } finally { and swallowed ... but it's printed if XDev is set. What is a proper way to fix this? Is it correct to wrap all exceptions in JavaProcessingEnvironmentServiceIterator into aborts? Or would it be better to distinguish different Aborts in JavaCompiler.java? -------------- next part -------------- An HTML attachment was scrubbed... URL: From jonathan.gibbons at oracle.com Tue Jan 9 18:15:53 2018 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Tue, 9 Jan 2018 10:15:53 -0800 Subject: Fixing JDK-8130493 In-Reply-To: References: Message-ID: <91b1156a-6ec3-6717-4ce4-204258f2ce43@oracle.com> What is the class triggering the ClassNotFoundException? If it is a user class not being found, it should be wrapped in a ClientCodeException.?? If it is a javac class not being found, it is reasonable to wrap it in an Abort. -- Jon On 1/9/18 9:52 AM, Schaef, Martin wrote: > > Hi, > > We have some users suffering from JDK-8130493 > (their builds > succeed, but the compiler actually failed). I did some digging and the > following sequence happens: > > A ClassNotFoundException is thrown in > JavaProcessingEnvironment.ServiceIterator.next() > > and re-thrown as an Abort. > > This Abort reaches JavaCompiler.processAnnotations() > > and is finally caught in JavaCompiler.compile() > ?by > the following snippet: > > ??????? try { > > initProcessAnnotations(processors); > > ??????????? // These method calls must be chained to avoid memory leaks > > ??????????? delegateCompiler = > > processAnnotations( //<<<<<< ABORT COMES OUT HERE > > enterTrees(stopIfError(CompileState.PARSE, > parseFiles(sourceFileObjects))), > > classnames); > > ? > > ??????? } catch (Abort ex) { > > ??????????? if (devVerbose) > > ex.printStackTrace(System.err); > > ??????? } finally { > > and swallowed ... but it's printed if XDev?is set. > > What is a proper way to fix this? Is it correct to wrap all exceptions > in JavaProcessingEnvironmentServiceIterator into aborts? Or would it > be better to distinguish different Aborts in JavaCompiler.java? > -------------- next part -------------- An HTML attachment was scrubbed... URL: From joe.darcy at oracle.com Tue Jan 9 18:28:04 2018 From: joe.darcy at oracle.com (joe darcy) Date: Tue, 9 Jan 2018 10:28:04 -0800 Subject: JDK 10/11 RFR of JDK-8189146: Have use of "var" in 9 and earlier source versions issue a warning Message-ID: Hello, When the possibility of "_" being removed from the future set of valid identifiers was determined, javac was updated to issue a warning to that effect in JDK 8. Underscore was removed from the set of valid identifiers as of JDK 9. With local variable type inference, the name "var" should be given similar treatment in source versions 9 and earlier. Please review the webrev which implements this: http://cr.openjdk.java.net/~darcy/8189146.0/ As written, the patch warns for a type or type variable named "var"; it would be possible to expand the patch to warn about other uses of "var" that would conflict with the JDK 10 feature. As a aid to reviewing, the non-raw diagnostic output from test/langtools/tools/javac/lvti/ParserTest.java under --release 9 is listed below. IMO It would be preferable to issue this kind of warning in the context of an -Xlint:future category (JDK-8189145), but until that feature is developed, it is still better to issue the warning than to not issue it. The webrev as presented is based off of JDK 11. Upon a successful code review, I will explore getting the change into JDK 10 as an RFE and make any needed adjustments to rebase the patch. If that is not fruitful, I'll push the change to JDK 11. Thanks, -Joe ParserTest.java:14: warning: as of release 10, 'var' is a restricted local variable type and cannot be used for type declarations class ParserTest { ^ ParserTest.java:16: warning: as of release 10, 'var' is a restricted local variable type and cannot be used for type declarations static class var { } //illegal ^ ParserTest.java:20: warning: as of release 10, 'var' is a restricted local variable type and cannot be used for type declarations interface var { } //illegal ^ ParserTest.java:24: warning: as of release 10, 'var' is a restricted local variable type and cannot be used for type declarations enum var { } //illegal ^ ParserTest.java:28: warning: as of release 10, 'var' is a restricted local variable type and cannot be used for type declarations @interface var { } //illegal ^ ParserTest.java:36: warning: as of release 10, 'var' is a restricted local variable type and cannot be used for type declarations static class var extends RuntimeException { } //illegal ^ 6 warnings From maurizio.cimadamore at oracle.com Tue Jan 9 18:49:19 2018 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Tue, 9 Jan 2018 18:49:19 +0000 Subject: JDK 10/11 RFR of JDK-8189146: Have use of "var" in 9 and earlier source versions issue a warning In-Reply-To: References: Message-ID: <9475d5e8-977d-4c84-6a19-b368834cce33@oracle.com> Hi Joe, I'm a bit unsure about having a retroactive warning in JDK 10 - e.g. I'm not sure how useful that would be, but I get the spirit of what you're getting at. In terms of code, I think your warning should go inside the isRestrictedLocalVarTypeName(Name), which is called in a few places (not just the one you have touched). For instance, I don't think your patch will cover this case: List l = null; So, the code for isRestrictedLocalVarTypeName(Name) is currently: return allowLocalVariableTypeInference && name == names.var; I think it should be updated to: if (name == names.var) { ??????????? if (allowLocalVariableTypeInference) { ??????????????? return true; ??????????? } else { ??????????????? warning(pos, "var.not.allowed", name); ??????????? } ??????? } ??????? return false; Of course you need to enhance the method to take an extra position argument (pos). Maurizio On 09/01/18 18:28, joe darcy wrote: > Hello, > > When the possibility of "_" being removed from the future set of valid > identifiers was determined, javac was updated to issue a warning to > that effect in JDK 8. Underscore was removed from the set of valid > identifiers as of JDK 9. > > With local variable type inference, the name "var" should be given > similar treatment in source versions 9 and earlier. Please review the > webrev which implements this: > > ??? http://cr.openjdk.java.net/~darcy/8189146.0/ > > As written, the patch warns for a type or type variable named "var"; > it would be possible to expand the patch to warn about other uses of > "var" that would conflict with the JDK 10 feature. As a aid to > reviewing, the non-raw diagnostic output from > test/langtools/tools/javac/lvti/ParserTest.java under --release 9 is > listed below. > > IMO It would be preferable to issue this kind of warning in the > context of an -Xlint:future category (JDK-8189145), but until that > feature is developed, it is still better to issue the warning than to > not issue it. > > The webrev as presented is based off of JDK 11. Upon a successful code > review, I will explore getting the change into JDK 10 as an RFE and > make any needed adjustments to rebase the patch. If that is not > fruitful, I'll push the change to JDK 11. > > Thanks, > > -Joe > > > ParserTest.java:14: warning: as of release 10, 'var' is a restricted > local variable type and cannot be used for type declarations > class ParserTest { > ???????????????? ^ > ParserTest.java:16: warning: as of release 10, 'var' is a restricted > local variable type and cannot be used for type declarations > ??????? static class var { } //illegal > ???????????????????? ^ > ParserTest.java:20: warning: as of release 10, 'var' is a restricted > local variable type and cannot be used for type declarations > ??????? interface var { } //illegal > ????????????????? ^ > ParserTest.java:24: warning: as of release 10, 'var' is a restricted > local variable type and cannot be used for type declarations > ??????? enum var { } //illegal > ???????????? ^ > ParserTest.java:28: warning: as of release 10, 'var' is a restricted > local variable type and cannot be used for type declarations > ??????? @interface var { } //illegal > ?????????????????? ^ > ParserTest.java:36: warning: as of release 10, 'var' is a restricted > local variable type and cannot be used for type declarations > ??? static class var extends RuntimeException { } //illegal > ???????????????? ^ > 6 warnings > From schaef at amazon.com Tue Jan 9 20:36:17 2018 From: schaef at amazon.com (Schaef, Martin) Date: Tue, 9 Jan 2018 20:36:17 +0000 Subject: Fixing JDK-8130493 In-Reply-To: <91b1156a-6ec3-6717-4ce4-204258f2ce43@oracle.com> References: <91b1156a-6ec3-6717-4ce4-204258f2ce43@oracle.com> Message-ID: <95ED4B91-B07C-4275-B0F1-AA392CB8D5B4@amazon.com> It?s a user class. See full stack trace below. The problem is that the ClassNotFound is already caught at com.sun.tools.javac.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:255) which already wraps it in a ServiceConfigurationError in the fail method. That is, the exception gets wrapped twice. First, LazyIterator.next wraps it in a ServieConfigurationError, then ServiceIterator.next wraps it in an Abort. Is it safe to change both wrappings? com.sun.tools.javac.util.Abort: java.lang.NoClassDefFoundError: com/amazon/coral/util/reflection/AnnotatedManifestAnnotationProcessor at com.sun.tools.javac.processing.JavacProcessingEnvironment$ServiceIterator.next(JavacProcessingEnvironment.java:364) at com.sun.tools.javac.processing.JavacProcessingEnvironment$ServiceIterator.next(JavacProcessingEnvironment.java:325) at com.sun.tools.javac.processing.JavacProcessingEnvironment$DiscoveredProcessors$ProcessorStateIterator.next(JavacProcessingEnvironment.java:597) at com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:690) at com.sun.tools.javac.processing.JavacProcessingEnvironment.access$1800(JavacProcessingEnvironment.java:91) at com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1035) at com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1176) at com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1170) at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:856) at com.sun.tools.javac.main.Main.compile(Main.java:523) at com.sun.tools.javac.main.Main.compile(Main.java:381) at com.sun.tools.javac.main.Main.compile(Main.java:370) at com.sun.tools.javac.main.Main.compile(Main.java:361) at com.sun.tools.javac.Main.compile(Main.java:56) at com.sun.tools.javac.Main.main(Main.java:42) Caused by: java.lang.NoClassDefFoundError: com/amazon/coral/util/reflection/AnnotatedManifestAnnotationProcessor at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:763) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) at java.net.URLClassLoader.defineClass(URLClassLoader.java:467) at java.net.URLClassLoader.access$100(URLClassLoader.java:73) at java.net.URLClassLoader$1.run(URLClassLoader.java:368) at java.net.URLClassLoader$1.run(URLClassLoader.java:362) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:361) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:348) at com.sun.tools.javac.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:255) at com.sun.tools.javac.util.ServiceLoader$1.next(ServiceLoader.java:337) at com.sun.tools.javac.processing.JavacProcessingEnvironment$ServiceIterator.next(JavacProcessingEnvironment.java:359) ... 14 more Caused by: java.lang.ClassNotFoundException: com.amazon.coral.util.reflection.AnnotatedManifestAnnotationProcessor at java.net.URLClassLoader.findClass(URLClassLoader.java:381) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) From: Jonathan Gibbons Date: Tuesday, January 9, 2018 at 1:19 PM To: "Schaef, Martin" , "compiler-dev at openjdk.java.net" Subject: Re: Fixing JDK-8130493 What is the class triggering the ClassNotFoundException? If it is a user class not being found, it should be wrapped in a ClientCodeException. If it is a javac class not being found, it is reasonable to wrap it in an Abort. -- Jon On 1/9/18 9:52 AM, Schaef, Martin wrote: Hi, We have some users suffering from JDK-8130493 (their builds succeed, but the compiler actually failed). I did some digging and the following sequence happens: A ClassNotFoundException is thrown in JavaProcessingEnvironment.ServiceIterator.next() and re-thrown as an Abort. This Abort reaches JavaCompiler.processAnnotations() and is finally caught in JavaCompiler.compile() by the following snippet: try { initProcessAnnotations(processors); // These method calls must be chained to avoid memory leaks delegateCompiler = processAnnotations( //<<<<<< ABORT COMES OUT HERE enterTrees(stopIfError(CompileState.PARSE, parseFiles(sourceFileObjects))), classnames); ? } catch (Abort ex) { if (devVerbose) ex.printStackTrace(System.err); } finally { and swallowed ... but it's printed if XDev is set. What is a proper way to fix this? Is it correct to wrap all exceptions in JavaProcessingEnvironmentServiceIterator into aborts? Or would it be better to distinguish different Aborts in JavaCompiler.java? -------------- next part -------------- An HTML attachment was scrubbed... URL: From jonathan.gibbons at oracle.com Tue Jan 9 21:39:35 2018 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Tue, 09 Jan 2018 13:39:35 -0800 Subject: RFR: JDK-8182107: javax.tools.ToolProvider should detect if jdk.compiler matches the version of java.compiler Message-ID: <5A553697.9040504@oracle.com> Please review this simple fix for javax.tools.ToolProvider, to verify that if a candidate impl of JavaCompiler is found, it is in a module with the sane version as that of the java.compiler module. The fix also changes the code to use direct API to access module details, instead of reflection, which is no longer necessary. The new test performs a "control" experiment to verify that ToolProvider continues to work as expected in a normal system image. It then creates an updated modular jar containing the classes for java.compiler, but with an updated module version, and verifies that when using this module on the upgrade module path, the jdk.compiler in the system image is ignored. JBS: https://bugs.openjdk.java.net/browse/JDK-8182107 Webrev: http://cr.openjdk.java.net/~jjg/8182107/webrev.00/ -- Jon From joe.darcy at oracle.com Tue Jan 9 22:29:31 2018 From: joe.darcy at oracle.com (joe darcy) Date: Tue, 9 Jan 2018 14:29:31 -0800 Subject: JDK 10/11 RFR of JDK-8189146: Have use of "var" in 9 and earlier source versions issue a warning In-Reply-To: <9475d5e8-977d-4c84-6a19-b368834cce33@oracle.com> References: <9475d5e8-977d-4c84-6a19-b368834cce33@oracle.com> Message-ID: Hi Maurizio, On 1/9/2018 10:49 AM, Maurizio Cimadamore wrote: > Hi Joe, > I'm a bit unsure about having a retroactive warning in JDK 10 - e.g. > I'm not sure how useful that would be, but I get the spirit of what > you're getting at. I think this kind of warning allows a smoother cross-release transition. > > In terms of code, I think your warning should go inside the > isRestrictedLocalVarTypeName(Name), which is called in a few places > (not just the one you have touched). For instance, I don't think your > patch will cover this case: > > List l = null; > > So, the code for isRestrictedLocalVarTypeName(Name) is currently: > > return allowLocalVariableTypeInference && name == names.var; > > I think it should be updated to: > > if (name == names.var) { > if (allowLocalVariableTypeInference) { > return true; > } else { > warning(pos, "var.not.allowed", name); > } > } > return false; > > > Of course you need to enhance the method to take an extra position > argument (pos). > > Webrev updated as suggested: http://cr.openjdk.java.net/~darcy/8189146.1/ That does emit more warnings than the earlier iteration in ParserTest, 17 rather than 6. As a review aid, the 17 expanded non-raw warnings are listed below. Under release 10, there are 24 errors generated for the file, including different error messages. Thanks, -Joe /home/darcy/JDK/10/hg/test/langtools/tools/javac/lvti/ParserTest.java:14: warning: as of release 10, 'var' is a restricted local variable type and cannot be used for type declarations class ParserTest { ^ /home/darcy/JDK/10/hg/test/langtools/tools/javac/lvti/ParserTest.java:16: warning: as of release 10, 'var' is a restricted local variable type and cannot be used for type declarations static class var { } //illegal ^ /home/darcy/JDK/10/hg/test/langtools/tools/javac/lvti/ParserTest.java:20: warning: as of release 10, 'var' is a restricted local variable type and cannot be used for type declarations interface var { } //illegal ^ /home/darcy/JDK/10/hg/test/langtools/tools/javac/lvti/ParserTest.java:24: warning: as of release 10, 'var' is a restricted local variable type and cannot be used for type declarations enum var { } //illegal ^ /home/darcy/JDK/10/hg/test/langtools/tools/javac/lvti/ParserTest.java:28: warning: as of release 10, 'var' is a restricted local variable type and cannot be used for type declarations @interface var { } //illegal ^ /home/darcy/JDK/10/hg/test/langtools/tools/javac/lvti/ParserTest.java:36: warning: as of release 10, 'var' is a restricted local variable type and cannot be used for type declarations static class var extends RuntimeException { } //illegal ^ /home/darcy/JDK/10/hg/test/langtools/tools/javac/lvti/ParserTest.java:38: warning: as of release 10, 'var' is a restricted local variable type and cannot be used for type declarations var x = null; //illegal ^ /home/darcy/JDK/10/hg/test/langtools/tools/javac/lvti/ParserTest.java:54: warning: as of release 10, 'var' is a restricted local variable type and cannot be used for type declarations var m() { //illegal ^ /home/darcy/JDK/10/hg/test/langtools/tools/javac/lvti/ParserTest.java:58: warning: as of release 10, 'var' is a restricted local variable type and cannot be used for type declarations void test2(var x) { //error ^ /home/darcy/JDK/10/hg/test/langtools/tools/javac/lvti/ParserTest.java:59: warning: as of release 10, 'var' is a restricted local variable type and cannot be used for type declarations List l1; //error ^ /home/darcy/JDK/10/hg/test/langtools/tools/javac/lvti/ParserTest.java:60: warning: as of release 10, 'var' is a restricted local variable type and cannot be used for type declarations List l2; //error ^ /home/darcy/JDK/10/hg/test/langtools/tools/javac/lvti/ParserTest.java:61: warning: as of release 10, 'var' is a restricted local variable type and cannot be used for type declarations List l3; //error ^ /home/darcy/JDK/10/hg/test/langtools/tools/javac/lvti/ParserTest.java:63: warning: as of release 10, 'var' is a restricted local variable type and cannot be used for type declarations Function f = (var x2) -> ""; //error ^ /home/darcy/JDK/10/hg/test/langtools/tools/javac/lvti/ParserTest.java:63: warning: as of release 10, 'var' is a restricted local variable type and cannot be used for type declarations Function f = (var x2) -> ""; //error ^ /home/darcy/JDK/10/hg/test/langtools/tools/javac/lvti/ParserTest.java:64: warning: as of release 10, 'var' is a restricted local variable type and cannot be used for type declarations } catch (var ex) { } //error ^ /home/darcy/JDK/10/hg/test/langtools/tools/javac/lvti/ParserTest.java:68: warning: as of release 10, 'var' is a restricted local variable type and cannot be used for type declarations boolean b1 = o instanceof var; //error ^ /home/darcy/JDK/10/hg/test/langtools/tools/javac/lvti/ParserTest.java:69: warning: as of release 10, 'var' is a restricted local variable type and cannot be used for type declarations Object o2 = (var)o; //error ^ 17 warnings From mandy.chung at oracle.com Tue Jan 9 23:08:10 2018 From: mandy.chung at oracle.com (mandy chung) Date: Tue, 9 Jan 2018 15:08:10 -0800 Subject: RFR: JDK-8182107: javax.tools.ToolProvider should detect if jdk.compiler matches the version of java.compiler In-Reply-To: <5A553697.9040504@oracle.com> References: <5A553697.9040504@oracle.com> Message-ID: <7a62be7a-2b76-9234-b295-748d482cde62@oracle.com> On 1/9/18 1:39 PM, Jonathan Gibbons wrote: > Please review this simple fix for javax.tools.ToolProvider, to verify > that if a candidate impl of > JavaCompiler is found, it is in a module with the sane version as that > of the java.compiler module. > > The fix also changes the code to use direct API to access module > details, instead of reflection, > which is no longer necessary. > > The new test performs a "control" experiment to verify that > ToolProvider continues to work as > expected in a normal system image. It then creates an updated modular > jar containing the > classes for java.compiler, but with an updated module version, and > verifies that when using this > module on the upgrade module path, the jdk.compiler in the system > image is ignored. > > JBS: https://bugs.openjdk.java.net/browse/JDK-8182107 > Webrev: http://cr.openjdk.java.net/~jjg/8182107/webrev.00/ > Making sure that the module version matching the version of java.compiler module is reasonable.? I think @implNote of getSystemXXXTool may need to be updated to mention the module version check.? I wondered if it should support interim release (i.e. match the feature version rather than the entire string) but it does not seem necessary since the primary use case is for IDE to upgrade a newer version of java.compiler which is a feature release.? So the check is fine. Is useLegacy still needed?? If only supporting to run on JDK N-1, then it can be removed? Nit: you could do ToolProvider.class.getModule().getDescriptor().version().orElse(null) so that the matches method can take Version instead of Optional VersionTest.java 83 String thisVersion = System.getProperty("java.specification.version"); 84 String nextVersion = String.valueOf(Integer.parseInt(thisVersion) + 1); An alternative way is Runtime.version().feature() + 1; Mandy -------------- next part -------------- An HTML attachment was scrubbed... URL: From jonathan.gibbons at oracle.com Wed Jan 10 00:38:58 2018 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Tue, 09 Jan 2018 16:38:58 -0800 Subject: RFR: JDK-8185986: redundant/obsolete overview.html pages Message-ID: <5A5560A2.4080907@oracle.com> Please review a trivial patch to just remove three very old/obsolete "overview.html" files from the source tree. JBS: https://bugs.openjdk.java.net/browse/JDK-8185986 Webrev: http://cr.openjdk.java.net/~jjg/8185986/webrev/ -- Jon From maurizio.cimadamore at oracle.com Wed Jan 10 00:39:51 2018 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Wed, 10 Jan 2018 00:39:51 +0000 Subject: JDK 10/11 RFR of JDK-8189146: Have use of "var" in 9 and earlier source versions issue a warning In-Reply-To: References: <9475d5e8-977d-4c84-6a19-b368834cce33@oracle.com> Message-ID: <665b4df5-a855-133b-8725-14e366600516@oracle.com> Thanks for the update. This is close, but compared to the existing golden file, as you noticed, there are missing warnings, esp. when 'var' is used as an array element type. I believe the issue is with this code: if (Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source) && elemType.hasTag(IDENT)) { 2998 Name typeName = ((JCIdent)elemType).name; 2999 if (isRestrictedLocalVarTypeName(typeName, pos)) { 3000 if (type.hasTag(TYPEARRAY)) { 3001 //error - 'var' and arrays 3002 reportSyntaxError(pos, "var.not.allowed.array"); 3003 } else { 3004 startPos = TreeInfo.getStartPos(mods); 3005 if (startPos == Position.NOPOS) 3006 startPos = TreeInfo.getStartPos(type); 3007 //implicit type 3008 type = null; 3009 } 3010 } 3011 } Here, if LVTI is disabled, the 'isRestrictedLocalVarTypeName' call would not even take place, hence the missing warnings. I suggest to shuffle as follows: if (elemType.hasTag(IDENT)) { 2998 Name typeName = ((JCIdent)elemType).name; 2999 if (isRestrictedLocalVarTypeName(typeName, pos)) { 3000 if (type.hasTag(TYPEARRAY)) { 3001 //error - 'var' and arrays 3002 reportSyntaxError(pos, "var.not.allowed.array"); 3003 } else { 3004 startPos = TreeInfo.getStartPos(mods); 3005 if (startPos == Position.NOPOS) 3006 startPos = TreeInfo.getStartPos(type); 3007 //implicit type 3008 type = null; 3009 } 3010 } 3011 } This should be more or less equivalent, behavior-wise (isRestrictedLocalVarTypeName returns 'false' if lvti is disabled, so that makes it equivalent to what was there before), but it will execute the test regardless of whether LVTI is disabled or not, which is what you want. There is another 'special' case where the parser reject 'var' and that is with the compound case (e.g. 'var x, y = ...'), but I think that's a corner^3 case and we can live w/o the warning there. But if you want to get there, this is the code to tweak: boolean implicit = Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source) && head.vartype == null; 2960 vdefs.append(head); 2961 while (token.kind == COMMA) { 2962 if (implicit) { 2963 reportSyntaxError(pos, "var.not.allowed.compound"); 2964 } 2965 // All but last of multiple declarators subsume a comma 2966 storeEnd((JCTree)vdefs.last(), token.endPos); 2967 nextToken(); 2968 vdefs.append(variableDeclarator(mods, type, reqInit, dc, localDecl)); 2969 } Again, the name of the game is to make sure that we issue the warning regardless of whether lvti is enable or not. This should do: 2960 vdefs.append(head); 2961 while (token.kind == COMMA) { 2962 if (isRestrictedLocalVarTypeName (type)) { 2963 reportSyntaxError(pos, "var.not.allowed.compound"); 2964 } 2965 // All but last of multiple declarators subsume a comma 2966 storeEnd((JCTree)vdefs.last(), token.endPos); 2967 nextToken(); 2968 vdefs.append(variableDeclarator(mods, type, reqInit, dc, localDecl)); 2969 } I'm less sure about this last one, so take it for a spin and see what happens. Maurizio On 09/01/18 22:29, joe darcy wrote: > Hi Maurizio, > > > On 1/9/2018 10:49 AM, Maurizio Cimadamore wrote: >> Hi Joe, >> I'm a bit unsure about having a retroactive warning in JDK 10 - e.g. >> I'm not sure how useful that would be, but I get the spirit of what >> you're getting at. > > I think this kind of warning allows a smoother cross-release transition. > >> >> In terms of code, I think your warning should go inside the >> isRestrictedLocalVarTypeName(Name), which is called in a few places >> (not just the one you have touched). For instance, I don't think your >> patch will cover this case: >> >> List l = null; >> >> So, the code for isRestrictedLocalVarTypeName(Name) is currently: >> >> return allowLocalVariableTypeInference && name == names.var; >> >> I think it should be updated to: >> >> if (name == names.var) { >> ??????????? if (allowLocalVariableTypeInference) { >> ??????????????? return true; >> ??????????? } else { >> ??????????????? warning(pos, "var.not.allowed", name); >> ??????????? } >> ??????? } >> ??????? return false; >> >> >> Of course you need to enhance the method to take an extra position >> argument (pos). >> >> > > Webrev updated as suggested: > > ??? http://cr.openjdk.java.net/~darcy/8189146.1/ > > That does emit more warnings than the earlier iteration in ParserTest, > 17 rather than 6. As a review aid, the 17 expanded non-raw warnings > are listed below. Under release 10, there are 24 errors generated for > the file, including different error messages. > > Thanks, > > -Joe > > /home/darcy/JDK/10/hg/test/langtools/tools/javac/lvti/ParserTest.java:14: > warning: as of release 10, 'var' is a restricted local variable type > and cannot be used for type declarations > class ParserTest { > ???????????????? ^ > /home/darcy/JDK/10/hg/test/langtools/tools/javac/lvti/ParserTest.java:16: > warning: as of release 10, 'var' is a restricted local variable type > and cannot be used for type declarations > ??????? static class var { } //illegal > ???????????????????? ^ > /home/darcy/JDK/10/hg/test/langtools/tools/javac/lvti/ParserTest.java:20: > warning: as of release 10, 'var' is a restricted local variable type > and cannot be used for type declarations > ??????? interface var { } //illegal > ????????????????? ^ > /home/darcy/JDK/10/hg/test/langtools/tools/javac/lvti/ParserTest.java:24: > warning: as of release 10, 'var' is a restricted local variable type > and cannot be used for type declarations > ??????? enum var { } //illegal > ???????????? ^ > /home/darcy/JDK/10/hg/test/langtools/tools/javac/lvti/ParserTest.java:28: > warning: as of release 10, 'var' is a restricted local variable type > and cannot be used for type declarations > ??????? @interface var { } //illegal > ?????????????????? ^ > /home/darcy/JDK/10/hg/test/langtools/tools/javac/lvti/ParserTest.java:36: > warning: as of release 10, 'var' is a restricted local variable type > and cannot be used for type declarations > ??? static class var extends RuntimeException { } //illegal > ???????????????? ^ > /home/darcy/JDK/10/hg/test/langtools/tools/javac/lvti/ParserTest.java:38: > warning: as of release 10, 'var' is a restricted local variable type > and cannot be used for type declarations > ??? var x = null; //illegal > ??? ^ > /home/darcy/JDK/10/hg/test/langtools/tools/javac/lvti/ParserTest.java:54: > warning: as of release 10, 'var' is a restricted local variable type > and cannot be used for type declarations > ??? var m() { //illegal > ??? ^ > /home/darcy/JDK/10/hg/test/langtools/tools/javac/lvti/ParserTest.java:58: > warning: as of release 10, 'var' is a restricted local variable type > and cannot be used for type declarations > ??? void test2(var x) { //error > ?????????????? ^ > /home/darcy/JDK/10/hg/test/langtools/tools/javac/lvti/ParserTest.java:59: > warning: as of release 10, 'var' is a restricted local variable type > and cannot be used for type declarations > ??????? List l1; //error > ???????????? ^ > /home/darcy/JDK/10/hg/test/langtools/tools/javac/lvti/ParserTest.java:60: > warning: as of release 10, 'var' is a restricted local variable type > and cannot be used for type declarations > ??????? List l2; //error > ?????????????????????? ^ > /home/darcy/JDK/10/hg/test/langtools/tools/javac/lvti/ParserTest.java:61: > warning: as of release 10, 'var' is a restricted local variable type > and cannot be used for type declarations > ??????? List l3; //error > ???????????????????? ^ > /home/darcy/JDK/10/hg/test/langtools/tools/javac/lvti/ParserTest.java:63: > warning: as of release 10, 'var' is a restricted local variable type > and cannot be used for type declarations > ??????????? Function f = (var x2) -> ""; //error > ???????????????????? ^ > /home/darcy/JDK/10/hg/test/langtools/tools/javac/lvti/ParserTest.java:63: > warning: as of release 10, 'var' is a restricted local variable type > and cannot be used for type declarations > ??????????? Function f = (var x2) -> ""; //error > ?????????????????????????????????????? ^ > /home/darcy/JDK/10/hg/test/langtools/tools/javac/lvti/ParserTest.java:64: > warning: as of release 10, 'var' is a restricted local variable type > and cannot be used for type declarations > ??????? } catch (var ex) { } //error > ???????????????? ^ > /home/darcy/JDK/10/hg/test/langtools/tools/javac/lvti/ParserTest.java:68: > warning: as of release 10, 'var' is a restricted local variable type > and cannot be used for type declarations > ??????? boolean b1 = o instanceof var; //error > ????????????????????????????????? ^ > /home/darcy/JDK/10/hg/test/langtools/tools/javac/lvti/ParserTest.java:69: > warning: as of release 10, 'var' is a restricted local variable type > and cannot be used for type declarations > ??????? Object o2 = (var)o; //error > ???????????????????? ^ > 17 warnings > From joe.darcy at oracle.com Wed Jan 10 00:44:50 2018 From: joe.darcy at oracle.com (Joseph D. Darcy) Date: Tue, 09 Jan 2018 16:44:50 -0800 Subject: RFR: JDK-8185986: redundant/obsolete overview.html pages In-Reply-To: <5A5560A2.4080907@oracle.com> References: <5A5560A2.4080907@oracle.com> Message-ID: <5A556202.4070400@oracle.com> +1 -Joe On 1/9/2018 4:38 PM, Jonathan Gibbons wrote: > Please review a trivial patch to just remove three very old/obsolete > "overview.html" files from the source tree. > > JBS: https://bugs.openjdk.java.net/browse/JDK-8185986 > Webrev: http://cr.openjdk.java.net/~jjg/8185986/webrev/ > > -- Jon > From schaef at amazon.com Wed Jan 10 16:17:02 2018 From: schaef at amazon.com (Schaef, Martin) Date: Wed, 10 Jan 2018 16:17:02 +0000 Subject: Fixing JDK-8130493 In-Reply-To: <95ED4B91-B07C-4275-B0F1-AA392CB8D5B4@amazon.com> References: <91b1156a-6ec3-6717-4ce4-204258f2ce43@oracle.com> <95ED4B91-B07C-4275-B0F1-AA392CB8D5B4@amazon.com> Message-ID: <1341C4E9-1F39-400C-9F3C-31E28E606555@amazon.com> Let me revise that: In JavacProcessingEnvironment.initProcessorIterator the code chooses one of two types of iterators: The NameProcessIterator if ther -processor flag is given or the ServiceIterator. If we look at the NameProcessIterator.hasNext() implementation, it checks if there is a next name AND checks if this class name can be loaded. That is, if the class is not present, the hasNext() method already returns false (or, in our case, throws the NoClassDefFoundError which gets wrapped into an AnnotationProcessingError). If we look at the ServiceIterator together with the stack trace from my previous email, we see that the .hasNext() and .next() calls get forwarded into the ServiceLoader.LazyIterator. This behaves different than the NameProcessIterator: hasNext() only checks if a next name exists and would not throw a NoClassDefFoundError. Then next() throws the NoClassDefFoundError which gets caught by the catch-all in JavaProcessingEnvironment.ServiceIterator.next() and wrapped into an Abort. So, to summarize: For a NameProcessIterator, a missing class causes a AnnotationProcessingError thrown from NameProcessIterator.hasNext() and for ServiceIterator, it causes a Abert thrown by JavaProcessingEnvironment.ServiceIterator.next(). I could fix my problem and JDK-8130493 by checking if the class can be loaded in the hasNext method and changing the exception handling in JavaProcessingEnvironment.ServiceIterator.next(). The problem with that is that the lazy iterator is not lazy anymore. Is there a reason why this Iterator has to be lazy? I attached a patch that solves the issue for me. Feedback would be great. Cheers, Martin From: compiler-dev on behalf of "Schaef, Martin" Date: Tuesday, January 9, 2018 at 3:37 PM To: Jonathan Gibbons , "compiler-dev at openjdk.java.net" Subject: Re: Fixing JDK-8130493 It?s a user class. See full stack trace below. The problem is that the ClassNotFound is already caught at com.sun.tools.javac.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:255) which already wraps it in a ServiceConfigurationError in the fail method. That is, the exception gets wrapped twice. First, LazyIterator.next wraps it in a ServieConfigurationError, then ServiceIterator.next wraps it in an Abort. Is it safe to change both wrappings? com.sun.tools.javac.util.Abort: java.lang.NoClassDefFoundError: com/amazon/coral/util/reflection/AnnotatedManifestAnnotationProcessor at com.sun.tools.javac.processing.JavacProcessingEnvironment$ServiceIterator.next(JavacProcessingEnvironment.java:364) at com.sun.tools.javac.processing.JavacProcessingEnvironment$ServiceIterator.next(JavacProcessingEnvironment.java:325) at com.sun.tools.javac.processing.JavacProcessingEnvironment$DiscoveredProcessors$ProcessorStateIterator.next(JavacProcessingEnvironment.java:597) at com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:690) at com.sun.tools.javac.processing.JavacProcessingEnvironment.access$1800(JavacProcessingEnvironment.java:91) at com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1035) at com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1176) at com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1170) at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:856) at com.sun.tools.javac.main.Main.compile(Main.java:523) at com.sun.tools.javac.main.Main.compile(Main.java:381) at com.sun.tools.javac.main.Main.compile(Main.java:370) at com.sun.tools.javac.main.Main.compile(Main.java:361) at com.sun.tools.javac.Main.compile(Main.java:56) at com.sun.tools.javac.Main.main(Main.java:42) Caused by: java.lang.NoClassDefFoundError: com/amazon/coral/util/reflection/AnnotatedManifestAnnotationProcessor at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:763) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) at java.net.URLClassLoader.defineClass(URLClassLoader.java:467) at java.net.URLClassLoader.access$100(URLClassLoader.java:73) at java.net.URLClassLoader$1.run(URLClassLoader.java:368) at java.net.URLClassLoader$1.run(URLClassLoader.java:362) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:361) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:348) at com.sun.tools.javac.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:255) at com.sun.tools.javac.util.ServiceLoader$1.next(ServiceLoader.java:337) at com.sun.tools.javac.processing.JavacProcessingEnvironment$ServiceIterator.next(JavacProcessingEnvironment.java:359) ... 14 more Caused by: java.lang.ClassNotFoundException: com.amazon.coral.util.reflection.AnnotatedManifestAnnotationProcessor at java.net.URLClassLoader.findClass(URLClassLoader.java:381) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) From: Jonathan Gibbons Date: Tuesday, January 9, 2018 at 1:19 PM To: "Schaef, Martin" , "compiler-dev at openjdk.java.net" Subject: Re: Fixing JDK-8130493 What is the class triggering the ClassNotFoundException? If it is a user class not being found, it should be wrapped in a ClientCodeException. If it is a javac class not being found, it is reasonable to wrap it in an Abort. -- Jon On 1/9/18 9:52 AM, Schaef, Martin wrote: Hi, We have some users suffering from JDK-8130493 (their builds succeed, but the compiler actually failed). I did some digging and the following sequence happens: A ClassNotFoundException is thrown in JavaProcessingEnvironment.ServiceIterator.next() and re-thrown as an Abort. This Abort reaches JavaCompiler.processAnnotations() and is finally caught in JavaCompiler.compile() by the following snippet: try { initProcessAnnotations(processors); // These method calls must be chained to avoid memory leaks delegateCompiler = processAnnotations( //<<<<<< ABORT COMES OUT HERE enterTrees(stopIfError(CompileState.PARSE, parseFiles(sourceFileObjects))), classnames); ? } catch (Abort ex) { if (devVerbose) ex.printStackTrace(System.err); } finally { and swallowed ... but it's printed if XDev is set. What is a proper way to fix this? Is it correct to wrap all exceptions in JavaProcessingEnvironmentServiceIterator into aborts? Or would it be better to distinguish different Aborts in JavaCompiler.java? -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: jdk-8130493.patch Type: application/octet-stream Size: 3380 bytes Desc: jdk-8130493.patch URL: From jonathan.gibbons at oracle.com Wed Jan 10 16:33:11 2018 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Wed, 10 Jan 2018 08:33:11 -0800 Subject: Fixing JDK-8130493 In-Reply-To: <1341C4E9-1F39-400C-9F3C-31E28E606555@amazon.com> References: <91b1156a-6ec3-6717-4ce4-204258f2ce43@oracle.com> <95ED4B91-B07C-4275-B0F1-AA392CB8D5B4@amazon.com> <1341C4E9-1F39-400C-9F3C-31E28E606555@amazon.com> Message-ID: <506c86c4-a749-73c8-afa6-c05ccf8404a9@oracle.com> Martin, I have not read your patch, but changing the semantics of the iterator sounds like a step too far. Without trying to implement the following yet, I would expect the general direction of a solution to be to one of the following: 1. if the exception should be fatal, allow it to propagate up to JavaCompiler, (similar to as now) but maybe with a custom new wrapper exception 2. if the exception should not be fatal, translate it to an error message (log.error(...)) and continue. It probably needs more analysis and discussion to determine which of those two directions to take. -- Jon On 1/10/18 8:17 AM, Schaef, Martin wrote: > > Let me revise that: > > In JavacProcessingEnvironment.initProcessorIterator > > the code chooses one of two types of iterators: > > The NameProcessIterator > > if ther -processor flag is given or the ServiceIterator > . > > If we look at the NameProcessIterator.hasNext() > > implementation, it checks if there is a next name AND checks if this > class name can be loaded. That is, if the class is not present, the > hasNext() method already returns false (or, in our case, throws the > NoClassDefFoundError which gets wrapped into an > AnnotationProcessingError). > > If we look at the ServiceIterator together with the stack trace from > my previous email, we see that the .hasNext() and .next() calls get > forwarded into the ServiceLoader.LazyIterator > . > This behaves different than the NameProcessIterator: hasNext() > > only checks if a next name exists and would not throw a > NoClassDefFoundError. Then next() > > throws the NoClassDefFoundError which gets caught by the catch-all in > JavaProcessingEnvironment.ServiceIterator.next() > > and wrapped into an Abort. > > So, to summarize: > > For a NameProcessIterator, a missing class causes a > AnnotationProcessingError thrown from NameProcessIterator.hasNext() > > and for ServiceIterator, it causes a Abert thrown by > JavaProcessingEnvironment.ServiceIterator.next() > . > > I could fix my problem and JDK-8130493 > by checking if the > class can be loaded in the hasNext method and changing the exception > handling in JavaProcessingEnvironment.ServiceIterator.next() > . > The problem with that is that the lazy iterator is not lazy anymore. > Is there a reason why this Iterator has to be lazy? > > I attached a patch that solves the issue for me. Feedback would be great. > > Cheers, > > Martin > > *From: *compiler-dev on behalf > of "Schaef, Martin" > *Date: *Tuesday, January 9, 2018 at 3:37 PM > *To: *Jonathan Gibbons , > "compiler-dev at openjdk.java.net" > *Subject: *Re: Fixing JDK-8130493 > > It?s a user class. See full stack trace below. > > The problem is that the ClassNotFound is already caught at > com.sun.tools.javac.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:255) > > which already wraps it in a ServiceConfigurationError > > in the fail method. That is, the exception gets wrapped twice. First, > LazyIterator.next wraps it in a ServieConfigurationError, then > ServiceIterator.next wraps it in an Abort. > > Is it safe to change both wrappings? > > com.sun.tools.javac.util.Abort: java.lang.NoClassDefFoundError: > com/amazon/coral/util/reflection/AnnotatedManifestAnnotationProcessor > > ??? at > com.sun.tools.javac.processing.JavacProcessingEnvironment$ServiceIterator.next(JavacProcessingEnvironment.java:364) > > ??? at > com.sun.tools.javac.processing.JavacProcessingEnvironment$ServiceIterator.next(JavacProcessingEnvironment.java:325) > > ??? at > com.sun.tools.javac.processing.JavacProcessingEnvironment$DiscoveredProcessors$ProcessorStateIterator.next(JavacProcessingEnvironment.java:597) > > ??? at > com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:690) > > ??? at > com.sun.tools.javac.processing.JavacProcessingEnvironment.access$1800(JavacProcessingEnvironment.java:91) > > ??? at > com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1035) > > ??? at > com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1176) > > ??? at > com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1170) > > ??? at > com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:856) > > ??? at com.sun.tools.javac.main.Main.compile(Main.java:523) > > ??? at com.sun.tools.javac.main.Main.compile(Main.java:381) > > ??? at com.sun.tools.javac.main.Main.compile(Main.java:370) > > ??? at com.sun.tools.javac.main.Main.compile(Main.java:361) > > ??? at com.sun.tools.javac.Main.compile(Main.java:56) > > ??? at com.sun.tools.javac.Main.main(Main.java:42) > > Caused by: java.lang.NoClassDefFoundError: > com/amazon/coral/util/reflection/AnnotatedManifestAnnotationProcessor > > ??? at java.lang.ClassLoader.defineClass1(Native Method) > > ??? at java.lang.ClassLoader.defineClass(ClassLoader.java:763) > > ??? at > java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) > > ??? at java.net.URLClassLoader.defineClass(URLClassLoader.java:467) > > ??? at java.net.URLClassLoader.access$100(URLClassLoader.java:73) > > ??? at java.net.URLClassLoader$1.run(URLClassLoader.java:368) > > ??? at java.net.URLClassLoader$1.run(URLClassLoader.java:362) > > ??? at java.security.AccessController.doPrivileged(Native Method) > > ??? at java.net.URLClassLoader.findClass(URLClassLoader.java:361) > > ??? at java.lang.ClassLoader.loadClass(ClassLoader.java:424) > > ??? at java.lang.ClassLoader.loadClass(ClassLoader.java:357) > > ??? at java.lang.Class.forName0(Native Method) > > ??? at java.lang.Class.forName(Class.java:348) > > ??? at > com.sun.tools.javac.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:255) > > ??? at > com.sun.tools.javac.util.ServiceLoader$1.next(ServiceLoader.java:337) > > ??? at > com.sun.tools.javac.processing.JavacProcessingEnvironment$ServiceIterator.next(JavacProcessingEnvironment.java:359) > > ??? ... 14 more > > Caused by: java.lang.ClassNotFoundException: > com.amazon.coral.util.reflection.AnnotatedManifestAnnotationProcessor > > ??? at java.net.URLClassLoader.findClass(URLClassLoader.java:381) > > ??? at java.lang.ClassLoader.loadClass(ClassLoader.java:424) > > ???at java.lang.ClassLoader.loadClass(ClassLoader.java:357) > > *From: *Jonathan Gibbons > *Date: *Tuesday, January 9, 2018 at 1:19 PM > *To: *"Schaef, Martin" , > "compiler-dev at openjdk.java.net" > *Subject: *Re: Fixing JDK-8130493 > > What is the class triggering the ClassNotFoundException? > > If it is a user class not being found, it should be wrapped in a > ClientCodeException.?? If it is a javac class not being found, it is > reasonable to wrap it in an Abort. > > -- Jon > > On 1/9/18 9:52 AM, Schaef, Martin wrote: > > Hi, > > We have some users suffering from JDK-8130493 > (their builds > succeed, but the compiler actually failed). I did some digging and > the following sequence happens: > > A ClassNotFoundException is thrown in > JavaProcessingEnvironment.ServiceIterator.next() > > and re-thrown as an Abort. > > This Abort reaches JavaCompiler.processAnnotations() > > and is finally caught in JavaCompiler.compile() > ?by > the following snippet: > > ??????? try { > > initProcessAnnotations(processors); > > ??????????? // These method calls must be chained to avoid memory > leaks > > ??????????? delegateCompiler = > > processAnnotations( //<<<<<< ABORT COMES OUT HERE > > enterTrees(stopIfError(CompileState.PARSE, > parseFiles(sourceFileObjects))), > > classnames); > > ? > > ??????? } catch (Abort ex) { > > ??????????? if (devVerbose) > > ex.printStackTrace(System.err); > > ??????? } finally { > > and swallowed ... but it's printed if XDev?is set. > > What is a proper way to fix this? Is it correct to wrap all > exceptions in JavaProcessingEnvironmentServiceIterator into > aborts? Or would it be better to distinguish different Aborts in > JavaCompiler.java? > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From schaef at amazon.com Wed Jan 10 17:13:41 2018 From: schaef at amazon.com (Schaef, Martin) Date: Wed, 10 Jan 2018 17:13:41 +0000 Subject: Fixing JDK-8130493 In-Reply-To: <506c86c4-a749-73c8-afa6-c05ccf8404a9@oracle.com> References: <91b1156a-6ec3-6717-4ce4-204258f2ce43@oracle.com> <95ED4B91-B07C-4275-B0F1-AA392CB8D5B4@amazon.com> <1341C4E9-1F39-400C-9F3C-31E28E606555@amazon.com> <506c86c4-a749-73c8-afa6-c05ccf8404a9@oracle.com> Message-ID: <9C1302C8-EE80-4866-96E8-B26F329B7104@amazon.com> I understand. The bare minimum that fixes the test cases would be to change the exception handling in the constructor of ServiceIterator: http://hg.openjdk.java.net/jdk8u/jdk8u/langtools/file/989188d1a978/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java#l340 and in ServiceIterator.next(): http://hg.openjdk.java.net/jdk8u/jdk8u/langtools/file/989188d1a978/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java#l363 from } catch (Throwable t) { log.error("proc.service.problem"); throw new Abort(t); to } catch (Exception t) { log.error("proc.service.problem"); throw new Abort(t); } catch (Throwable t) { log.error("Some error text"); throw new AnnotationProcessingError (t); With this change, the exit code of javac is 3 instead of 0. Does that sound like something you could support? If so, what should go in the log.error messages? Cheers, Martin From: Jonathan Gibbons Date: Wednesday, January 10, 2018 at 11:39 AM To: "Schaef, Martin" , "compiler-dev at openjdk.java.net" Cc: "Hohensee, Paul" Subject: Re: Fixing JDK-8130493 Martin, I have not read your patch, but changing the semantics of the iterator sounds like a step too far. Without trying to implement the following yet, I would expect the general direction of a solution to be to one of the following: 1. if the exception should be fatal, allow it to propagate up to JavaCompiler, (similar to as now) but maybe with a custom new wrapper exception 2. if the exception should not be fatal, translate it to an error message (log.error(...)) and continue. It probably needs more analysis and discussion to determine which of those two directions to take. -- Jon On 1/10/18 8:17 AM, Schaef, Martin wrote: Let me revise that: In JavacProcessingEnvironment.initProcessorIterator the code chooses one of two types of iterators: The NameProcessIterator if ther -processor flag is given or the ServiceIterator. If we look at the NameProcessIterator.hasNext() implementation, it checks if there is a next name AND checks if this class name can be loaded. That is, if the class is not present, the hasNext() method already returns false (or, in our case, throws the NoClassDefFoundError which gets wrapped into an AnnotationProcessingError). If we look at the ServiceIterator together with the stack trace from my previous email, we see that the .hasNext() and .next() calls get forwarded into the ServiceLoader.LazyIterator. This behaves different than the NameProcessIterator: hasNext() only checks if a next name exists and would not throw a NoClassDefFoundError. Then next() throws the NoClassDefFoundError which gets caught by the catch-all in JavaProcessingEnvironment.ServiceIterator.next() and wrapped into an Abort. So, to summarize: For a NameProcessIterator, a missing class causes a AnnotationProcessingError thrown from NameProcessIterator.hasNext() and for ServiceIterator, it causes a Abert thrown by JavaProcessingEnvironment.ServiceIterator.next(). I could fix my problem and JDK-8130493 by checking if the class can be loaded in the hasNext method and changing the exception handling in JavaProcessingEnvironment.ServiceIterator.next(). The problem with that is that the lazy iterator is not lazy anymore. Is there a reason why this Iterator has to be lazy? I attached a patch that solves the issue for me. Feedback would be great. Cheers, Martin From: compiler-dev on behalf of "Schaef, Martin" Date: Tuesday, January 9, 2018 at 3:37 PM To: Jonathan Gibbons , "compiler-dev at openjdk.java.net" Subject: Re: Fixing JDK-8130493 It?s a user class. See full stack trace below. The problem is that the ClassNotFound is already caught at com.sun.tools.javac.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:255) which already wraps it in a ServiceConfigurationError in the fail method. That is, the exception gets wrapped twice. First, LazyIterator.next wraps it in a ServieConfigurationError, then ServiceIterator.next wraps it in an Abort. Is it safe to change both wrappings? com.sun.tools.javac.util.Abort: java.lang.NoClassDefFoundError: com/amazon/coral/util/reflection/AnnotatedManifestAnnotationProcessor at com.sun.tools.javac.processing.JavacProcessingEnvironment$ServiceIterator.next(JavacProcessingEnvironment.java:364) at com.sun.tools.javac.processing.JavacProcessingEnvironment$ServiceIterator.next(JavacProcessingEnvironment.java:325) at com.sun.tools.javac.processing.JavacProcessingEnvironment$DiscoveredProcessors$ProcessorStateIterator.next(JavacProcessingEnvironment.java:597) at com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:690) at com.sun.tools.javac.processing.JavacProcessingEnvironment.access$1800(JavacProcessingEnvironment.java:91) at com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1035) at com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1176) at com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1170) at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:856) at com.sun.tools.javac.main.Main.compile(Main.java:523) at com.sun.tools.javac.main.Main.compile(Main.java:381) at com.sun.tools.javac.main.Main.compile(Main.java:370) at com.sun.tools.javac.main.Main.compile(Main.java:361) at com.sun.tools.javac.Main.compile(Main.java:56) at com.sun.tools.javac.Main.main(Main.java:42) Caused by: java.lang.NoClassDefFoundError: com/amazon/coral/util/reflection/AnnotatedManifestAnnotationProcessor at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:763) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) at java.net.URLClassLoader.defineClass(URLClassLoader.java:467) at java.net.URLClassLoader.access$100(URLClassLoader.java:73) at java.net.URLClassLoader$1.run(URLClassLoader.java:368) at java.net.URLClassLoader$1.run(URLClassLoader.java:362) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:361) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:348) at com.sun.tools.javac.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:255) at com.sun.tools.javac.util.ServiceLoader$1.next(ServiceLoader.java:337) at com.sun.tools.javac.processing.JavacProcessingEnvironment$ServiceIterator.next(JavacProcessingEnvironment.java:359) ... 14 more Caused by: java.lang.ClassNotFoundException: com.amazon.coral.util.reflection.AnnotatedManifestAnnotationProcessor at java.net.URLClassLoader.findClass(URLClassLoader.java:381) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) From: Jonathan Gibbons Date: Tuesday, January 9, 2018 at 1:19 PM To: "Schaef, Martin" , "compiler-dev at openjdk.java.net" Subject: Re: Fixing JDK-8130493 What is the class triggering the ClassNotFoundException? If it is a user class not being found, it should be wrapped in a ClientCodeException. If it is a javac class not being found, it is reasonable to wrap it in an Abort. -- Jon On 1/9/18 9:52 AM, Schaef, Martin wrote: Hi, We have some users suffering from JDK-8130493 (their builds succeed, but the compiler actually failed). I did some digging and the following sequence happens: A ClassNotFoundException is thrown in JavaProcessingEnvironment.ServiceIterator.next() and re-thrown as an Abort. This Abort reaches JavaCompiler.processAnnotations() and is finally caught in JavaCompiler.compile() by the following snippet: try { initProcessAnnotations(processors); // These method calls must be chained to avoid memory leaks delegateCompiler = processAnnotations( //<<<<<< ABORT COMES OUT HERE enterTrees(stopIfError(CompileState.PARSE, parseFiles(sourceFileObjects))), classnames); ? } catch (Abort ex) { if (devVerbose) ex.printStackTrace(System.err); } finally { and swallowed ... but it's printed if XDev is set. What is a proper way to fix this? Is it correct to wrap all exceptions in JavaProcessingEnvironmentServiceIterator into aborts? Or would it be better to distinguish different Aborts in JavaCompiler.java? -------------- next part -------------- An HTML attachment was scrubbed... URL: From jonathan.gibbons at oracle.com Wed Jan 10 17:23:38 2018 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Wed, 10 Jan 2018 09:23:38 -0800 Subject: Fixing JDK-8130493 In-Reply-To: <9C1302C8-EE80-4866-96E8-B26F329B7104@amazon.com> References: <91b1156a-6ec3-6717-4ce4-204258f2ce43@oracle.com> <95ED4B91-B07C-4275-B0F1-AA392CB8D5B4@amazon.com> <1341C4E9-1F39-400C-9F3C-31E28E606555@amazon.com> <506c86c4-a749-73c8-afa6-c05ccf8404a9@oracle.com> <9C1302C8-EE80-4866-96E8-B26F329B7104@amazon.com> Message-ID: Why would you not just change from } catch (Throwable t) { log.error("proc.service.problem"); throw new Abort(t); to } catch (Throwable t) { log.error("proc.service.problem"); throw new AnnotationProcessingError(t); and then briefly, concisely, handle AnnotationProcessingError in JavaCompiler. -- Jon On 1/10/18 9:13 AM, Schaef, Martin wrote: > > I understand. The bare minimum that fixes the test cases would be to > change the exception handling in the constructor of ServiceIterator: > > http://hg.openjdk.java.net/jdk8u/jdk8u/langtools/file/989188d1a978/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java#l340 > > and in ServiceIterator.next(): > > http://hg.openjdk.java.net/jdk8u/jdk8u/langtools/file/989188d1a978/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java#l363 > > from > > } catch (Throwable t) { > > log.error("proc.service.problem"); > > throw new Abort(t); > > to > > } catch (Exception t) { > > log.error("proc.service.problem"); > > throw new Abort(t); > > } catch (Throwable t) { > > log.error("Some error text"); > > throw new AnnotationProcessingError (t); > > With this change, the exit code of javac is 3 instead of 0. > > Does that sound like something you could support? If so, what should > go in the log.error messages? > > Cheers, > > Martin > > *From: *Jonathan Gibbons > *Date: *Wednesday, January 10, 2018 at 11:39 AM > *To: *"Schaef, Martin" , > "compiler-dev at openjdk.java.net" > *Cc: *"Hohensee, Paul" > *Subject: *Re: Fixing JDK-8130493 > > Martin, > > I have not read your patch, but changing the semantics of the iterator > sounds like a step too far. > > Without trying to implement the following yet, I would expect the > general direction of a solution to be to one of the following: > > 1. if the exception should be fatal, allow it to propagate up to > JavaCompiler, (similar to as now) but maybe with a custom new wrapper > exception > > 2. if the exception should not be fatal, translate it to an error > message (log.error(...)) and continue. > > It probably needs more analysis and discussion to determine which of > those two directions to take. > > -- Jon > > On 1/10/18 8:17 AM, Schaef, Martin wrote: > > Let me revise that: > > In JavacProcessingEnvironment.initProcessorIterator > > the code chooses one of two types of iterators: > > The NameProcessIterator > > if ther -processor flag is given or the ServiceIterator > . > > If we look at the NameProcessIterator.hasNext() > > implementation, it checks if there is a next name AND checks if > this class name can be loaded. That is, if the class is not > present, the hasNext() method already returns false (or, in our > case, throws the NoClassDefFoundError which gets wrapped into an > AnnotationProcessingError). > > If we look at the ServiceIterator together with the stack trace > from my previous email, we see that the .hasNext() and .next() > calls get forwarded into the ServiceLoader.LazyIterator > . > This behaves different than the NameProcessIterator: hasNext() > > only checks if a next name exists and would not throw a > NoClassDefFoundError. Then next() > > throws the NoClassDefFoundError which gets caught by the catch-all > in JavaProcessingEnvironment.ServiceIterator.next() > > and wrapped into an Abort. > > So, to summarize: > > For a NameProcessIterator, a missing class causes a > AnnotationProcessingError thrown from > NameProcessIterator.hasNext() > > and for ServiceIterator, it causes a Abert thrown by > JavaProcessingEnvironment.ServiceIterator.next() > . > > I could fix my problem and JDK-8130493 > by checking if > the class can be loaded in the hasNext method and changing the > exception handling in > JavaProcessingEnvironment.ServiceIterator.next() > . > The problem with that is that the lazy iterator is not lazy > anymore. Is there a reason why this Iterator has to be lazy? > > I attached a patch that solves the issue for me. Feedback would be > great. > > Cheers, > > Martin > > *From: *compiler-dev > on behalf of > "Schaef, Martin" > *Date: *Tuesday, January 9, 2018 at 3:37 PM > *To: *Jonathan Gibbons > , > "compiler-dev at openjdk.java.net" > > > *Subject: *Re: Fixing JDK-8130493 > > It?s a user class. See full stack trace below. > > The problem is that the ClassNotFound is already caught at > com.sun.tools.javac.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:255) > > which already wraps it in a ServiceConfigurationError > > in the fail method. That is, the exception gets wrapped twice. > First, LazyIterator.next wraps it in a ServieConfigurationError, > then ServiceIterator.next wraps it in an Abort. > > Is it safe to change both wrappings? > > com.sun.tools.javac.util.Abort: java.lang.NoClassDefFoundError: > com/amazon/coral/util/reflection/AnnotatedManifestAnnotationProcessor > > ??? at > com.sun.tools.javac.processing.JavacProcessingEnvironment$ServiceIterator.next(JavacProcessingEnvironment.java:364) > > ??? at > com.sun.tools.javac.processing.JavacProcessingEnvironment$ServiceIterator.next(JavacProcessingEnvironment.java:325) > > ??? at > com.sun.tools.javac.processing.JavacProcessingEnvironment$DiscoveredProcessors$ProcessorStateIterator.next(JavacProcessingEnvironment.java:597) > > ??? at > com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:690) > > ??? at > com.sun.tools.javac.processing.JavacProcessingEnvironment.access$1800(JavacProcessingEnvironment.java:91) > > ??? at > com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1035) > > ??? at > com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1176) > > ??? at > com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1170) > > ??? at > com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:856) > > ??? at com.sun.tools.javac.main.Main.compile(Main.java:523) > > ??? at com.sun.tools.javac.main.Main.compile(Main.java:381) > > ??? at com.sun.tools.javac.main.Main.compile(Main.java:370) > > ??? at com.sun.tools.javac.main.Main.compile(Main.java:361) > > ??? at com.sun.tools.javac.Main.compile(Main.java:56) > > ??? at com.sun.tools.javac.Main.main(Main.java:42) > > Caused by: java.lang.NoClassDefFoundError: > com/amazon/coral/util/reflection/AnnotatedManifestAnnotationProcessor > > ??? at java.lang.ClassLoader.defineClass1(Native Method) > > ??? at java.lang.ClassLoader.defineClass(ClassLoader.java:763) > > ??? at > java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) > > ??? at java.net.URLClassLoader.defineClass(URLClassLoader.java:467) > > ??? at java.net.URLClassLoader.access$100(URLClassLoader.java:73) > > ??? at java.net.URLClassLoader$1.run(URLClassLoader.java:368) > > ??? at java.net.URLClassLoader$1.run(URLClassLoader.java:362) > > ??? at java.security.AccessController.doPrivileged(Native Method) > > ??? at java.net.URLClassLoader.findClass(URLClassLoader.java:361) > > ??? at java.lang.ClassLoader.loadClass(ClassLoader.java:424) > > ??? at java.lang.ClassLoader.loadClass(ClassLoader.java:357) > > ??? at java.lang.Class.forName0(Native Method) > > ??? at java.lang.Class.forName(Class.java:348) > > ??? at > com.sun.tools.javac.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:255) > > ??? at > com.sun.tools.javac.util.ServiceLoader$1.next(ServiceLoader.java:337) > > ??? at > com.sun.tools.javac.processing.JavacProcessingEnvironment$ServiceIterator.next(JavacProcessingEnvironment.java:359) > > ??? ... 14 more > > Caused by: java.lang.ClassNotFoundException: > com.amazon.coral.util.reflection.AnnotatedManifestAnnotationProcessor > > ??? at java.net.URLClassLoader.findClass(URLClassLoader.java:381) > > ??? at java.lang.ClassLoader.loadClass(ClassLoader.java:424) > > ???at java.lang.ClassLoader.loadClass(ClassLoader.java:357) > > *From: *Jonathan Gibbons > > *Date: *Tuesday, January 9, 2018 at 1:19 PM > *To: *"Schaef, Martin" > , "compiler-dev at openjdk.java.net" > > > *Subject: *Re: Fixing JDK-8130493 > > What is the class triggering the ClassNotFoundException? > > If it is a user class not being found, it should be wrapped in a > ClientCodeException.?? If it is a javac class not being found, it > is reasonable to wrap it in an Abort. > > -- Jon > > On 1/9/18 9:52 AM, Schaef, Martin wrote: > > Hi, > > We have some users suffering from JDK-8130493 > (their > builds succeed, but the compiler actually failed). I did some > digging and the following sequence happens: > > A ClassNotFoundException is thrown in > JavaProcessingEnvironment.ServiceIterator.next() > > and re-thrown as an Abort. > > This Abort reaches JavaCompiler.processAnnotations() > > and is finally caught in JavaCompiler.compile() > ?by > the following snippet: > > ??????? try { > > initProcessAnnotations(processors); > > ??????????? // These method calls must be chained to avoid > memory leaks > > delegateCompiler = > > processAnnotations( //<<<<<< ABORT COMES OUT HERE > > enterTrees(stopIfError(CompileState.PARSE, > parseFiles(sourceFileObjects))), > > classnames); > > ? > > ??????? } catch (Abort ex) { > > ??????????? if (devVerbose) > > ex.printStackTrace(System.err); > > ??????? } finally { > > and swallowed ... but it's printed if XDev?is set. > > What is a proper way to fix this? Is it correct to wrap all > exceptions in JavaProcessingEnvironmentServiceIterator into > aborts? Or would it be better to distinguish different Aborts > in JavaCompiler.java? > > > > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From schaef at amazon.com Wed Jan 10 17:38:09 2018 From: schaef at amazon.com (Schaef, Martin) Date: Wed, 10 Jan 2018 17:38:09 +0000 Subject: Fixing JDK-8130493 In-Reply-To: References: <91b1156a-6ec3-6717-4ce4-204258f2ce43@oracle.com> <95ED4B91-B07C-4275-B0F1-AA392CB8D5B4@amazon.com> <1341C4E9-1F39-400C-9F3C-31E28E606555@amazon.com> <506c86c4-a749-73c8-afa6-c05ccf8404a9@oracle.com> <9C1302C8-EE80-4866-96E8-B26F329B7104@amazon.com> Message-ID: <5A28B7F9-C499-4342-90E3-9FFB0CEE869E@amazon.com> Mostly because I cannot see if there are other Exceptions that should be wrapped into Abort. I saw other places that throw AnnotationProcessingError, so I thought this would be a good way forward. Do you think that I can safely wrap all exceptions into an Error at this point? If so, I?ll adjust my patch. From: Jonathan Gibbons Date: Wednesday, January 10, 2018 at 12:24 PM To: "Schaef, Martin" , "compiler-dev at openjdk.java.net" Cc: "Hohensee, Paul" Subject: Re: Fixing JDK-8130493 Why would you not just change from } catch (Throwable t) { log.error("proc.service.problem"); throw new Abort(t); to } catch (Throwable t) { log.error("proc.service.problem"); throw new AnnotationProcessingError(t); and then briefly, concisely, handle AnnotationProcessingError in JavaCompiler. -- Jon On 1/10/18 9:13 AM, Schaef, Martin wrote: I understand. The bare minimum that fixes the test cases would be to change the exception handling in the constructor of ServiceIterator: http://hg.openjdk.java.net/jdk8u/jdk8u/langtools/file/989188d1a978/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java#l340 and in ServiceIterator.next(): http://hg.openjdk.java.net/jdk8u/jdk8u/langtools/file/989188d1a978/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java#l363 from } catch (Throwable t) { log.error("proc.service.problem"); throw new Abort(t); to } catch (Exception t) { log.error("proc.service.problem"); throw new Abort(t); } catch (Throwable t) { log.error("Some error text"); throw new AnnotationProcessingError (t); With this change, the exit code of javac is 3 instead of 0. Does that sound like something you could support? If so, what should go in the log.error messages? Cheers, Martin From: Jonathan Gibbons Date: Wednesday, January 10, 2018 at 11:39 AM To: "Schaef, Martin" , "compiler-dev at openjdk.java.net" Cc: "Hohensee, Paul" Subject: Re: Fixing JDK-8130493 Martin, I have not read your patch, but changing the semantics of the iterator sounds like a step too far. Without trying to implement the following yet, I would expect the general direction of a solution to be to one of the following: 1. if the exception should be fatal, allow it to propagate up to JavaCompiler, (similar to as now) but maybe with a custom new wrapper exception 2. if the exception should not be fatal, translate it to an error message (log.error(...)) and continue. It probably needs more analysis and discussion to determine which of those two directions to take. -- Jon On 1/10/18 8:17 AM, Schaef, Martin wrote: Let me revise that: In JavacProcessingEnvironment.initProcessorIterator the code chooses one of two types of iterators: The NameProcessIterator if ther -processor flag is given or the ServiceIterator. If we look at the NameProcessIterator.hasNext() implementation, it checks if there is a next name AND checks if this class name can be loaded. That is, if the class is not present, the hasNext() method already returns false (or, in our case, throws the NoClassDefFoundError which gets wrapped into an AnnotationProcessingError). If we look at the ServiceIterator together with the stack trace from my previous email, we see that the .hasNext() and .next() calls get forwarded into the ServiceLoader.LazyIterator. This behaves different than the NameProcessIterator: hasNext() only checks if a next name exists and would not throw a NoClassDefFoundError. Then next() throws the NoClassDefFoundError which gets caught by the catch-all in JavaProcessingEnvironment.ServiceIterator.next() and wrapped into an Abort. So, to summarize: For a NameProcessIterator, a missing class causes a AnnotationProcessingError thrown from NameProcessIterator.hasNext() and for ServiceIterator, it causes a Abert thrown by JavaProcessingEnvironment.ServiceIterator.next(). I could fix my problem and JDK-8130493 by checking if the class can be loaded in the hasNext method and changing the exception handling in JavaProcessingEnvironment.ServiceIterator.next(). The problem with that is that the lazy iterator is not lazy anymore. Is there a reason why this Iterator has to be lazy? I attached a patch that solves the issue for me. Feedback would be great. Cheers, Martin From: compiler-dev on behalf of "Schaef, Martin" Date: Tuesday, January 9, 2018 at 3:37 PM To: Jonathan Gibbons , "compiler-dev at openjdk.java.net" Subject: Re: Fixing JDK-8130493 It?s a user class. See full stack trace below. The problem is that the ClassNotFound is already caught at com.sun.tools.javac.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:255) which already wraps it in a ServiceConfigurationError in the fail method. That is, the exception gets wrapped twice. First, LazyIterator.next wraps it in a ServieConfigurationError, then ServiceIterator.next wraps it in an Abort. Is it safe to change both wrappings? com.sun.tools.javac.util.Abort: java.lang.NoClassDefFoundError: com/amazon/coral/util/reflection/AnnotatedManifestAnnotationProcessor at com.sun.tools.javac.processing.JavacProcessingEnvironment$ServiceIterator.next(JavacProcessingEnvironment.java:364) at com.sun.tools.javac.processing.JavacProcessingEnvironment$ServiceIterator.next(JavacProcessingEnvironment.java:325) at com.sun.tools.javac.processing.JavacProcessingEnvironment$DiscoveredProcessors$ProcessorStateIterator.next(JavacProcessingEnvironment.java:597) at com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:690) at com.sun.tools.javac.processing.JavacProcessingEnvironment.access$1800(JavacProcessingEnvironment.java:91) at com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1035) at com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1176) at com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1170) at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:856) at com.sun.tools.javac.main.Main.compile(Main.java:523) at com.sun.tools.javac.main.Main.compile(Main.java:381) at com.sun.tools.javac.main.Main.compile(Main.java:370) at com.sun.tools.javac.main.Main.compile(Main.java:361) at com.sun.tools.javac.Main.compile(Main.java:56) at com.sun.tools.javac.Main.main(Main.java:42) Caused by: java.lang.NoClassDefFoundError: com/amazon/coral/util/reflection/AnnotatedManifestAnnotationProcessor at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:763) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) at java.net.URLClassLoader.defineClass(URLClassLoader.java:467) at java.net.URLClassLoader.access$100(URLClassLoader.java:73) at java.net.URLClassLoader$1.run(URLClassLoader.java:368) at java.net.URLClassLoader$1.run(URLClassLoader.java:362) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:361) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:348) at com.sun.tools.javac.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:255) at com.sun.tools.javac.util.ServiceLoader$1.next(ServiceLoader.java:337) at com.sun.tools.javac.processing.JavacProcessingEnvironment$ServiceIterator.next(JavacProcessingEnvironment.java:359) ... 14 more Caused by: java.lang.ClassNotFoundException: com.amazon.coral.util.reflection.AnnotatedManifestAnnotationProcessor at java.net.URLClassLoader.findClass(URLClassLoader.java:381) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) From: Jonathan Gibbons Date: Tuesday, January 9, 2018 at 1:19 PM To: "Schaef, Martin" , "compiler-dev at openjdk.java.net" Subject: Re: Fixing JDK-8130493 What is the class triggering the ClassNotFoundException? If it is a user class not being found, it should be wrapped in a ClientCodeException. If it is a javac class not being found, it is reasonable to wrap it in an Abort. -- Jon On 1/9/18 9:52 AM, Schaef, Martin wrote: Hi, We have some users suffering from JDK-8130493 (their builds succeed, but the compiler actually failed). I did some digging and the following sequence happens: A ClassNotFoundException is thrown in JavaProcessingEnvironment.ServiceIterator.next() and re-thrown as an Abort. This Abort reaches JavaCompiler.processAnnotations() and is finally caught in JavaCompiler.compile() by the following snippet: try { initProcessAnnotations(processors); // These method calls must be chained to avoid memory leaks delegateCompiler = processAnnotations( //<<<<<< ABORT COMES OUT HERE enterTrees(stopIfError(CompileState.PARSE, parseFiles(sourceFileObjects))), classnames); ? } catch (Abort ex) { if (devVerbose) ex.printStackTrace(System.err); } finally { and swallowed ... but it's printed if XDev is set. What is a proper way to fix this? Is it correct to wrap all exceptions in JavaProcessingEnvironmentServiceIterator into aborts? Or would it be better to distinguish different Aborts in JavaCompiler.java? -------------- next part -------------- An HTML attachment was scrubbed... URL: From jan.lahoda at oracle.com Wed Jan 10 17:41:36 2018 From: jan.lahoda at oracle.com (Jan Lahoda) Date: Wed, 10 Jan 2018 18:41:36 +0100 Subject: Fixing JDK-8130493 In-Reply-To: References: <91b1156a-6ec3-6717-4ce4-204258f2ce43@oracle.com> <95ED4B91-B07C-4275-B0F1-AA392CB8D5B4@amazon.com> <1341C4E9-1F39-400C-9F3C-31E28E606555@amazon.com> <506c86c4-a749-73c8-afa6-c05ccf8404a9@oracle.com> <9C1302C8-EE80-4866-96E8-B26F329B7104@amazon.com> Message-ID: <5A565050.6030707@oracle.com> For a minimal change, I think it should be enough to change (in ServiceIterator) the existing: --- } catch (Throwable t) { throw new Abort(t); } --- to --- } catch (Throwable t) { throw new AnnotationProcessingError(t); } --- AnnotationProcessingError is handled both in JavacTaskImpl and com.sun.tools.javac.main.Main. For command line javac, this would get an output like: --- An annotation processor threw an uncaught exception. Consult the following stack trace for details. java.lang.ClassFormatError: Truncated class file [stacktrace] --- Which is in line with the behavior when -processor is used (NameProcessIterator). But I guess it would be good to improve consistency of error handling in JavacProcessingEnvironment at some point. Jan On 10.1.2018 18:23, Jonathan Gibbons wrote: > Why would you not just change > > > from > > } catch (Throwable t) { > > log.error("proc.service.problem"); > > throw new Abort(t); > > to > > } catch (Throwable t) { > > log.error("proc.service.problem"); > > throw new AnnotationProcessingError(t); > > > and then briefly, concisely, handle AnnotationProcessingError in > JavaCompiler. > > -- Jon > > > On 1/10/18 9:13 AM, Schaef, Martin wrote: >> >> I understand. The bare minimum that fixes the test cases would be to >> change the exception handling in the constructor of ServiceIterator: >> >> http://hg.openjdk.java.net/jdk8u/jdk8u/langtools/file/989188d1a978/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java#l340 >> >> and in ServiceIterator.next(): >> >> http://hg.openjdk.java.net/jdk8u/jdk8u/langtools/file/989188d1a978/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java#l363 >> >> from >> >> } catch (Throwable t) { >> >> log.error("proc.service.problem"); >> >> throw new Abort(t); >> >> to >> >> } catch (Exception t) { >> >> log.error("proc.service.problem"); >> >> throw new Abort(t); >> >> } catch (Throwable t) { >> >> log.error("Some error text"); >> >> throw new AnnotationProcessingError (t); >> >> With this change, the exit code of javac is 3 instead of 0. >> >> Does that sound like something you could support? If so, what should >> go in the log.error messages? >> >> Cheers, >> >> Martin >> >> *From: *Jonathan Gibbons >> *Date: *Wednesday, January 10, 2018 at 11:39 AM >> *To: *"Schaef, Martin" , >> "compiler-dev at openjdk.java.net" >> *Cc: *"Hohensee, Paul" >> *Subject: *Re: Fixing JDK-8130493 >> >> Martin, >> >> I have not read your patch, but changing the semantics of the iterator >> sounds like a step too far. >> >> Without trying to implement the following yet, I would expect the >> general direction of a solution to be to one of the following: >> >> 1. if the exception should be fatal, allow it to propagate up to >> JavaCompiler, (similar to as now) but maybe with a custom new wrapper >> exception >> >> 2. if the exception should not be fatal, translate it to an error >> message (log.error(...)) and continue. >> >> It probably needs more analysis and discussion to determine which of >> those two directions to take. >> >> -- Jon >> >> On 1/10/18 8:17 AM, Schaef, Martin wrote: >> >> Let me revise that: >> >> In JavacProcessingEnvironment.initProcessorIterator >> >> the code chooses one of two types of iterators: >> >> The NameProcessIterator >> >> if ther -processor flag is given or the ServiceIterator >> . >> >> If we look at the NameProcessIterator.hasNext() >> >> implementation, it checks if there is a next name AND checks if >> this class name can be loaded. That is, if the class is not >> present, the hasNext() method already returns false (or, in our >> case, throws the NoClassDefFoundError which gets wrapped into an >> AnnotationProcessingError). >> >> If we look at the ServiceIterator together with the stack trace >> from my previous email, we see that the .hasNext() and .next() >> calls get forwarded into the ServiceLoader.LazyIterator >> . >> This behaves different than the NameProcessIterator: hasNext() >> >> only checks if a next name exists and would not throw a >> NoClassDefFoundError. Then next() >> >> throws the NoClassDefFoundError which gets caught by the catch-all >> in JavaProcessingEnvironment.ServiceIterator.next() >> >> and wrapped into an Abort. >> >> So, to summarize: >> >> For a NameProcessIterator, a missing class causes a >> AnnotationProcessingError thrown from >> NameProcessIterator.hasNext() >> >> and for ServiceIterator, it causes a Abert thrown by >> JavaProcessingEnvironment.ServiceIterator.next() >> . >> >> I could fix my problem and JDK-8130493 >> by checking if >> the class can be loaded in the hasNext method and changing the >> exception handling in >> JavaProcessingEnvironment.ServiceIterator.next() >> . >> The problem with that is that the lazy iterator is not lazy >> anymore. Is there a reason why this Iterator has to be lazy? >> >> I attached a patch that solves the issue for me. Feedback would be >> great. >> >> Cheers, >> >> Martin >> >> *From: *compiler-dev >> on behalf of >> "Schaef, Martin" >> *Date: *Tuesday, January 9, 2018 at 3:37 PM >> *To: *Jonathan Gibbons >> , >> "compiler-dev at openjdk.java.net" >> >> >> *Subject: *Re: Fixing JDK-8130493 >> >> It?s a user class. See full stack trace below. >> >> The problem is that the ClassNotFound is already caught at >> com.sun.tools.javac.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:255) >> >> which already wraps it in a ServiceConfigurationError >> >> in the fail method. That is, the exception gets wrapped twice. >> First, LazyIterator.next wraps it in a ServieConfigurationError, >> then ServiceIterator.next wraps it in an Abort. >> >> Is it safe to change both wrappings? >> >> com.sun.tools.javac.util.Abort: java.lang.NoClassDefFoundError: >> com/amazon/coral/util/reflection/AnnotatedManifestAnnotationProcessor >> >> at >> com.sun.tools.javac.processing.JavacProcessingEnvironment$ServiceIterator.next(JavacProcessingEnvironment.java:364) >> >> at >> com.sun.tools.javac.processing.JavacProcessingEnvironment$ServiceIterator.next(JavacProcessingEnvironment.java:325) >> >> at >> com.sun.tools.javac.processing.JavacProcessingEnvironment$DiscoveredProcessors$ProcessorStateIterator.next(JavacProcessingEnvironment.java:597) >> >> at >> com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:690) >> >> at >> com.sun.tools.javac.processing.JavacProcessingEnvironment.access$1800(JavacProcessingEnvironment.java:91) >> >> at >> com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1035) >> >> at >> com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1176) >> >> at >> com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1170) >> >> at >> com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:856) >> >> at com.sun.tools.javac.main.Main.compile(Main.java:523) >> >> at com.sun.tools.javac.main.Main.compile(Main.java:381) >> >> at com.sun.tools.javac.main.Main.compile(Main.java:370) >> >> at com.sun.tools.javac.main.Main.compile(Main.java:361) >> >> at com.sun.tools.javac.Main.compile(Main.java:56) >> >> at com.sun.tools.javac.Main.main(Main.java:42) >> >> Caused by: java.lang.NoClassDefFoundError: >> com/amazon/coral/util/reflection/AnnotatedManifestAnnotationProcessor >> >> at java.lang.ClassLoader.defineClass1(Native Method) >> >> at java.lang.ClassLoader.defineClass(ClassLoader.java:763) >> >> at >> java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) >> >> at java.net.URLClassLoader.defineClass(URLClassLoader.java:467) >> >> at java.net.URLClassLoader.access$100(URLClassLoader.java:73) >> >> at java.net.URLClassLoader$1.run(URLClassLoader.java:368) >> >> at java.net.URLClassLoader$1.run(URLClassLoader.java:362) >> >> at java.security.AccessController.doPrivileged(Native Method) >> >> at java.net.URLClassLoader.findClass(URLClassLoader.java:361) >> >> at java.lang.ClassLoader.loadClass(ClassLoader.java:424) >> >> at java.lang.ClassLoader.loadClass(ClassLoader.java:357) >> >> at java.lang.Class.forName0(Native Method) >> >> at java.lang.Class.forName(Class.java:348) >> >> at >> com.sun.tools.javac.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:255) >> >> at >> com.sun.tools.javac.util.ServiceLoader$1.next(ServiceLoader.java:337) >> >> at >> com.sun.tools.javac.processing.JavacProcessingEnvironment$ServiceIterator.next(JavacProcessingEnvironment.java:359) >> >> ... 14 more >> >> Caused by: java.lang.ClassNotFoundException: >> com.amazon.coral.util.reflection.AnnotatedManifestAnnotationProcessor >> >> at java.net.URLClassLoader.findClass(URLClassLoader.java:381) >> >> at java.lang.ClassLoader.loadClass(ClassLoader.java:424) >> >> at java.lang.ClassLoader.loadClass(ClassLoader.java:357) >> >> *From: *Jonathan Gibbons >> >> *Date: *Tuesday, January 9, 2018 at 1:19 PM >> *To: *"Schaef, Martin" >> , "compiler-dev at openjdk.java.net" >> >> >> *Subject: *Re: Fixing JDK-8130493 >> >> What is the class triggering the ClassNotFoundException? >> >> If it is a user class not being found, it should be wrapped in a >> ClientCodeException. If it is a javac class not being found, it >> is reasonable to wrap it in an Abort. >> >> -- Jon >> >> On 1/9/18 9:52 AM, Schaef, Martin wrote: >> >> Hi, >> >> We have some users suffering from JDK-8130493 >> (their >> builds succeed, but the compiler actually failed). I did some >> digging and the following sequence happens: >> >> A ClassNotFoundException is thrown in >> JavaProcessingEnvironment.ServiceIterator.next() >> >> and re-thrown as an Abort. >> >> This Abort reaches JavaCompiler.processAnnotations() >> >> and is finally caught in JavaCompiler.compile() >> by >> the following snippet: >> >> try { >> >> initProcessAnnotations(processors); >> >> // These method calls must be chained to avoid >> memory leaks >> >> delegateCompiler = >> >> processAnnotations( //<<<<<< ABORT COMES OUT HERE >> >> enterTrees(stopIfError(CompileState.PARSE, >> parseFiles(sourceFileObjects))), >> >> classnames); >> >> ? >> >> } catch (Abort ex) { >> >> if (devVerbose) >> >> ex.printStackTrace(System.err); >> >> } finally { >> >> and swallowed ... but it's printed if XDev is set. >> >> What is a proper way to fix this? Is it correct to wrap all >> exceptions in JavaProcessingEnvironmentServiceIterator into >> aborts? Or would it be better to distinguish different Aborts >> in JavaCompiler.java? >> >> >> >> >> >> >> > From schaef at amazon.com Wed Jan 10 18:27:31 2018 From: schaef at amazon.com (Schaef, Martin) Date: Wed, 10 Jan 2018 18:27:31 +0000 Subject: Fixing JDK-8130493 In-Reply-To: <5A565050.6030707@oracle.com> References: <91b1156a-6ec3-6717-4ce4-204258f2ce43@oracle.com> <95ED4B91-B07C-4275-B0F1-AA392CB8D5B4@amazon.com> <1341C4E9-1F39-400C-9F3C-31E28E606555@amazon.com> <506c86c4-a749-73c8-afa6-c05ccf8404a9@oracle.com> <9C1302C8-EE80-4866-96E8-B26F329B7104@amazon.com> <5A565050.6030707@oracle.com> Message-ID: <2C2A3485-3C77-42EE-AFD7-B3FD97B97E1E@amazon.com> Tested it, and it works for my use case and the example in JDK-8130493. See patch below. Want to go forward with this? diff --new-file --unified --recursive --exclude='*.autotools' --exclude='*.cproject' --exclude='*.project' ./langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java ./langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java --- ./langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java 2017-10-20 20:28:37.000000000 +0000 +++ ./langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java 2018-01-10 16:46:52.798017039 +0000 a 2018-01-10 17:50:25.093338055 +0000 @@ -339,7 +339,7 @@ } } catch (Throwable t) { log.error("proc.service.problem"); - throw new Abort(t); + throw new AnnotationProcessingError(t); } } @@ -361,7 +361,7 @@ log.error("proc.bad.config.file", sce.getLocalizedMessage()); throw new Abort(sce); } catch (Throwable t) { - throw new Abort(t); + throw new AnnotationProcessingError(t); } } On 1/10/18, 12:42 PM, "Jan Lahoda" wrote: For a minimal change, I think it should be enough to change (in ServiceIterator) the existing: --- } catch (Throwable t) { throw new Abort(t); } --- to --- } catch (Throwable t) { throw new AnnotationProcessingError(t); } --- AnnotationProcessingError is handled both in JavacTaskImpl and com.sun.tools.javac.main.Main. For command line javac, this would get an output like: --- An annotation processor threw an uncaught exception. Consult the following stack trace for details. java.lang.ClassFormatError: Truncated class file [stacktrace] --- Which is in line with the behavior when -processor is used (NameProcessIterator). But I guess it would be good to improve consistency of error handling in JavacProcessingEnvironment at some point. Jan On 10.1.2018 18:23, Jonathan Gibbons wrote: > Why would you not just change > > > from > > } catch (Throwable t) { > > log.error("proc.service.problem"); > > throw new Abort(t); > > to > > } catch (Throwable t) { > > log.error("proc.service.problem"); > > throw new AnnotationProcessingError(t); > > > and then briefly, concisely, handle AnnotationProcessingError in > JavaCompiler. > > -- Jon > > > On 1/10/18 9:13 AM, Schaef, Martin wrote: >> >> I understand. The bare minimum that fixes the test cases would be to >> change the exception handling in the constructor of ServiceIterator: >> >> http://hg.openjdk.java.net/jdk8u/jdk8u/langtools/file/989188d1a978/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java#l340 >> >> and in ServiceIterator.next(): >> >> http://hg.openjdk.java.net/jdk8u/jdk8u/langtools/file/989188d1a978/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java#l363 >> >> from >> >> } catch (Throwable t) { >> >> log.error("proc.service.problem"); >> >> throw new Abort(t); >> >> to >> >> } catch (Exception t) { >> >> log.error("proc.service.problem"); >> >> throw new Abort(t); >> >> } catch (Throwable t) { >> >> log.error("Some error text"); >> >> throw new AnnotationProcessingError (t); >> >> With this change, the exit code of javac is 3 instead of 0. >> >> Does that sound like something you could support? If so, what should >> go in the log.error messages? >> >> Cheers, >> >> Martin >> >> *From: *Jonathan Gibbons >> *Date: *Wednesday, January 10, 2018 at 11:39 AM >> *To: *"Schaef, Martin" , >> "compiler-dev at openjdk.java.net" >> *Cc: *"Hohensee, Paul" >> *Subject: *Re: Fixing JDK-8130493 >> >> Martin, >> >> I have not read your patch, but changing the semantics of the iterator >> sounds like a step too far. >> >> Without trying to implement the following yet, I would expect the >> general direction of a solution to be to one of the following: >> >> 1. if the exception should be fatal, allow it to propagate up to >> JavaCompiler, (similar to as now) but maybe with a custom new wrapper >> exception >> >> 2. if the exception should not be fatal, translate it to an error >> message (log.error(...)) and continue. >> >> It probably needs more analysis and discussion to determine which of >> those two directions to take. >> >> -- Jon >> >> On 1/10/18 8:17 AM, Schaef, Martin wrote: >> >> Let me revise that: >> >> In JavacProcessingEnvironment.initProcessorIterator >> >> the code chooses one of two types of iterators: >> >> The NameProcessIterator >> >> if ther -processor flag is given or the ServiceIterator >> . >> >> If we look at the NameProcessIterator.hasNext() >> >> implementation, it checks if there is a next name AND checks if >> this class name can be loaded. That is, if the class is not >> present, the hasNext() method already returns false (or, in our >> case, throws the NoClassDefFoundError which gets wrapped into an >> AnnotationProcessingError). >> >> If we look at the ServiceIterator together with the stack trace >> from my previous email, we see that the .hasNext() and .next() >> calls get forwarded into the ServiceLoader.LazyIterator >> . >> This behaves different than the NameProcessIterator: hasNext() >> >> only checks if a next name exists and would not throw a >> NoClassDefFoundError. Then next() >> >> throws the NoClassDefFoundError which gets caught by the catch-all >> in JavaProcessingEnvironment.ServiceIterator.next() >> >> and wrapped into an Abort. >> >> So, to summarize: >> >> For a NameProcessIterator, a missing class causes a >> AnnotationProcessingError thrown from >> NameProcessIterator.hasNext() >> >> and for ServiceIterator, it causes a Abert thrown by >> JavaProcessingEnvironment.ServiceIterator.next() >> . >> >> I could fix my problem and JDK-8130493 >> by checking if >> the class can be loaded in the hasNext method and changing the >> exception handling in >> JavaProcessingEnvironment.ServiceIterator.next() >> . >> The problem with that is that the lazy iterator is not lazy >> anymore. Is there a reason why this Iterator has to be lazy? >> >> I attached a patch that solves the issue for me. Feedback would be >> great. >> >> Cheers, >> >> Martin >> >> *From: *compiler-dev >> on behalf of >> "Schaef, Martin" >> *Date: *Tuesday, January 9, 2018 at 3:37 PM >> *To: *Jonathan Gibbons >> , >> "compiler-dev at openjdk.java.net" >> >> >> *Subject: *Re: Fixing JDK-8130493 >> >> It?s a user class. See full stack trace below. >> >> The problem is that the ClassNotFound is already caught at >> com.sun.tools.javac.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:255) >> >> which already wraps it in a ServiceConfigurationError >> >> in the fail method. That is, the exception gets wrapped twice. >> First, LazyIterator.next wraps it in a ServieConfigurationError, >> then ServiceIterator.next wraps it in an Abort. >> >> Is it safe to change both wrappings? >> >> com.sun.tools.javac.util.Abort: java.lang.NoClassDefFoundError: >> com/amazon/coral/util/reflection/AnnotatedManifestAnnotationProcessor >> >> at >> com.sun.tools.javac.processing.JavacProcessingEnvironment$ServiceIterator.next(JavacProcessingEnvironment.java:364) >> >> at >> com.sun.tools.javac.processing.JavacProcessingEnvironment$ServiceIterator.next(JavacProcessingEnvironment.java:325) >> >> at >> com.sun.tools.javac.processing.JavacProcessingEnvironment$DiscoveredProcessors$ProcessorStateIterator.next(JavacProcessingEnvironment.java:597) >> >> at >> com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:690) >> >> at >> com.sun.tools.javac.processing.JavacProcessingEnvironment.access$1800(JavacProcessingEnvironment.java:91) >> >> at >> com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1035) >> >> at >> com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1176) >> >> at >> com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1170) >> >> at >> com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:856) >> >> at com.sun.tools.javac.main.Main.compile(Main.java:523) >> >> at com.sun.tools.javac.main.Main.compile(Main.java:381) >> >> at com.sun.tools.javac.main.Main.compile(Main.java:370) >> >> at com.sun.tools.javac.main.Main.compile(Main.java:361) >> >> at com.sun.tools.javac.Main.compile(Main.java:56) >> >> at com.sun.tools.javac.Main.main(Main.java:42) >> >> Caused by: java.lang.NoClassDefFoundError: >> com/amazon/coral/util/reflection/AnnotatedManifestAnnotationProcessor >> >> at java.lang.ClassLoader.defineClass1(Native Method) >> >> at java.lang.ClassLoader.defineClass(ClassLoader.java:763) >> >> at >> java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) >> >> at java.net.URLClassLoader.defineClass(URLClassLoader.java:467) >> >> at java.net.URLClassLoader.access$100(URLClassLoader.java:73) >> >> at java.net.URLClassLoader$1.run(URLClassLoader.java:368) >> >> at java.net.URLClassLoader$1.run(URLClassLoader.java:362) >> >> at java.security.AccessController.doPrivileged(Native Method) >> >> at java.net.URLClassLoader.findClass(URLClassLoader.java:361) >> >> at java.lang.ClassLoader.loadClass(ClassLoader.java:424) >> >> at java.lang.ClassLoader.loadClass(ClassLoader.java:357) >> >> at java.lang.Class.forName0(Native Method) >> >> at java.lang.Class.forName(Class.java:348) >> >> at >> com.sun.tools.javac.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:255) >> >> at >> com.sun.tools.javac.util.ServiceLoader$1.next(ServiceLoader.java:337) >> >> at >> com.sun.tools.javac.processing.JavacProcessingEnvironment$ServiceIterator.next(JavacProcessingEnvironment.java:359) >> >> ... 14 more >> >> Caused by: java.lang.ClassNotFoundException: >> com.amazon.coral.util.reflection.AnnotatedManifestAnnotationProcessor >> >> at java.net.URLClassLoader.findClass(URLClassLoader.java:381) >> >> at java.lang.ClassLoader.loadClass(ClassLoader.java:424) >> >> at java.lang.ClassLoader.loadClass(ClassLoader.java:357) >> >> *From: *Jonathan Gibbons >> >> *Date: *Tuesday, January 9, 2018 at 1:19 PM >> *To: *"Schaef, Martin" >> , "compiler-dev at openjdk.java.net" >> >> >> *Subject: *Re: Fixing JDK-8130493 >> >> What is the class triggering the ClassNotFoundException? >> >> If it is a user class not being found, it should be wrapped in a >> ClientCodeException. If it is a javac class not being found, it >> is reasonable to wrap it in an Abort. >> >> -- Jon >> >> On 1/9/18 9:52 AM, Schaef, Martin wrote: >> >> Hi, >> >> We have some users suffering from JDK-8130493 >> (their >> builds succeed, but the compiler actually failed). I did some >> digging and the following sequence happens: >> >> A ClassNotFoundException is thrown in >> JavaProcessingEnvironment.ServiceIterator.next() >> >> and re-thrown as an Abort. >> >> This Abort reaches JavaCompiler.processAnnotations() >> >> and is finally caught in JavaCompiler.compile() >> by >> the following snippet: >> >> try { >> >> initProcessAnnotations(processors); >> >> // These method calls must be chained to avoid >> memory leaks >> >> delegateCompiler = >> >> processAnnotations( //<<<<<< ABORT COMES OUT HERE >> >> enterTrees(stopIfError(CompileState.PARSE, >> parseFiles(sourceFileObjects))), >> >> classnames); >> >> ? >> >> } catch (Abort ex) { >> >> if (devVerbose) >> >> ex.printStackTrace(System.err); >> >> } finally { >> >> and swallowed ... but it's printed if XDev is set. >> >> What is a proper way to fix this? Is it correct to wrap all >> exceptions in JavaProcessingEnvironmentServiceIterator into >> aborts? Or would it be better to distinguish different Aborts >> in JavaCompiler.java? >> >> >> >> >> >> >> > From jonathan.gibbons at oracle.com Wed Jan 10 18:31:49 2018 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Wed, 10 Jan 2018 10:31:49 -0800 Subject: Fixing JDK-8130493 In-Reply-To: <2C2A3485-3C77-42EE-AFD7-B3FD97B97E1E@amazon.com> References: <91b1156a-6ec3-6717-4ce4-204258f2ce43@oracle.com> <95ED4B91-B07C-4275-B0F1-AA392CB8D5B4@amazon.com> <1341C4E9-1F39-400C-9F3C-31E28E606555@amazon.com> <506c86c4-a749-73c8-afa6-c05ccf8404a9@oracle.com> <9C1302C8-EE80-4866-96E8-B26F329B7104@amazon.com> <5A565050.6030707@oracle.com> <2C2A3485-3C77-42EE-AFD7-B3FD97B97E1E@amazon.com> Message-ID: <5A565C15.8090107@oracle.com> I would still like to examine this problem further. I would like to understand the right solution, and not just go for the minimal solution. -- Jon On 01/10/2018 10:27 AM, Schaef, Martin wrote: > Tested it, and it works for my use case and the example in JDK-8130493. See patch below. > Want to go forward with this? > > > diff --new-file --unified --recursive --exclude='*.autotools' --exclude='*.cproject' --exclude='*.project' ./langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java ./langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java > --- ./langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java 2017-10-20 20:28:37.000000000 +0000 > +++ ./langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java 2018-01-10 16:46:52.798017039 +0000 > a 2018-01-10 17:50:25.093338055 +0000 > @@ -339,7 +339,7 @@ > } > } catch (Throwable t) { > log.error("proc.service.problem"); > - throw new Abort(t); > + throw new AnnotationProcessingError(t); > } > } > > @@ -361,7 +361,7 @@ > log.error("proc.bad.config.file", sce.getLocalizedMessage()); > throw new Abort(sce); > } catch (Throwable t) { > - throw new Abort(t); > + throw new AnnotationProcessingError(t); > } > } > > > On 1/10/18, 12:42 PM, "Jan Lahoda" wrote: > > For a minimal change, I think it should be enough to change (in > ServiceIterator) the existing: > --- > } catch (Throwable t) { > throw new Abort(t); > } > --- > to > --- > } catch (Throwable t) { > throw new AnnotationProcessingError(t); > } > --- > > AnnotationProcessingError is handled both in JavacTaskImpl and > com.sun.tools.javac.main.Main. For command line javac, this would get an > output like: > --- > An annotation processor threw an uncaught exception. > Consult the following stack trace for details. > java.lang.ClassFormatError: Truncated class file > [stacktrace] > --- > > Which is in line with the behavior when -processor is used > (NameProcessIterator). > > But I guess it would be good to improve consistency of error handling in > JavacProcessingEnvironment at some point. > > Jan > > On 10.1.2018 18:23, Jonathan Gibbons wrote: > > Why would you not just change > > > > > > from > > > > } catch (Throwable t) { > > > > log.error("proc.service.problem"); > > > > throw new Abort(t); > > > > to > > > > } catch (Throwable t) { > > > > log.error("proc.service.problem"); > > > > throw new AnnotationProcessingError(t); > > > > > > and then briefly, concisely, handle AnnotationProcessingError in > > JavaCompiler. > > > > -- Jon > > > > > > On 1/10/18 9:13 AM, Schaef, Martin wrote: > >> > >> I understand. The bare minimum that fixes the test cases would be to > >> change the exception handling in the constructor of ServiceIterator: > >> > >> http://hg.openjdk.java.net/jdk8u/jdk8u/langtools/file/989188d1a978/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java#l340 > >> > >> and in ServiceIterator.next(): > >> > >> http://hg.openjdk.java.net/jdk8u/jdk8u/langtools/file/989188d1a978/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java#l363 > >> > >> from > >> > >> } catch (Throwable t) { > >> > >> log.error("proc.service.problem"); > >> > >> throw new Abort(t); > >> > >> to > >> > >> } catch (Exception t) { > >> > >> log.error("proc.service.problem"); > >> > >> throw new Abort(t); > >> > >> } catch (Throwable t) { > >> > >> log.error("Some error text"); > >> > >> throw new AnnotationProcessingError (t); > >> > >> With this change, the exit code of javac is 3 instead of 0. > >> > >> Does that sound like something you could support? If so, what should > >> go in the log.error messages? > >> > >> Cheers, > >> > >> Martin > >> > >> *From: *Jonathan Gibbons > >> *Date: *Wednesday, January 10, 2018 at 11:39 AM > >> *To: *"Schaef, Martin" , > >> "compiler-dev at openjdk.java.net" > >> *Cc: *"Hohensee, Paul" > >> *Subject: *Re: Fixing JDK-8130493 > >> > >> Martin, > >> > >> I have not read your patch, but changing the semantics of the iterator > >> sounds like a step too far. > >> > >> Without trying to implement the following yet, I would expect the > >> general direction of a solution to be to one of the following: > >> > >> 1. if the exception should be fatal, allow it to propagate up to > >> JavaCompiler, (similar to as now) but maybe with a custom new wrapper > >> exception > >> > >> 2. if the exception should not be fatal, translate it to an error > >> message (log.error(...)) and continue. > >> > >> It probably needs more analysis and discussion to determine which of > >> those two directions to take. > >> > >> -- Jon > >> > >> On 1/10/18 8:17 AM, Schaef, Martin wrote: > >> > >> Let me revise that: > >> > >> In JavacProcessingEnvironment.initProcessorIterator > >> > >> the code chooses one of two types of iterators: > >> > >> The NameProcessIterator > >> > >> if ther -processor flag is given or the ServiceIterator > >> . > >> > >> If we look at the NameProcessIterator.hasNext() > >> > >> implementation, it checks if there is a next name AND checks if > >> this class name can be loaded. That is, if the class is not > >> present, the hasNext() method already returns false (or, in our > >> case, throws the NoClassDefFoundError which gets wrapped into an > >> AnnotationProcessingError). > >> > >> If we look at the ServiceIterator together with the stack trace > >> from my previous email, we see that the .hasNext() and .next() > >> calls get forwarded into the ServiceLoader.LazyIterator > >> . > >> This behaves different than the NameProcessIterator: hasNext() > >> > >> only checks if a next name exists and would not throw a > >> NoClassDefFoundError. Then next() > >> > >> throws the NoClassDefFoundError which gets caught by the catch-all > >> in JavaProcessingEnvironment.ServiceIterator.next() > >> > >> and wrapped into an Abort. > >> > >> So, to summarize: > >> > >> For a NameProcessIterator, a missing class causes a > >> AnnotationProcessingError thrown from > >> NameProcessIterator.hasNext() > >> > >> and for ServiceIterator, it causes a Abert thrown by > >> JavaProcessingEnvironment.ServiceIterator.next() > >> . > >> > >> I could fix my problem and JDK-8130493 > >> by checking if > >> the class can be loaded in the hasNext method and changing the > >> exception handling in > >> JavaProcessingEnvironment.ServiceIterator.next() > >> . > >> The problem with that is that the lazy iterator is not lazy > >> anymore. Is there a reason why this Iterator has to be lazy? > >> > >> I attached a patch that solves the issue for me. Feedback would be > >> great. > >> > >> Cheers, > >> > >> Martin > >> > >> *From: *compiler-dev > >> on behalf of > >> "Schaef, Martin" > >> *Date: *Tuesday, January 9, 2018 at 3:37 PM > >> *To: *Jonathan Gibbons > >> , > >> "compiler-dev at openjdk.java.net" > >> > >> > >> *Subject: *Re: Fixing JDK-8130493 > >> > >> It?s a user class. See full stack trace below. > >> > >> The problem is that the ClassNotFound is already caught at > >> com.sun.tools.javac.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:255) > >> > >> which already wraps it in a ServiceConfigurationError > >> > >> in the fail method. That is, the exception gets wrapped twice. > >> First, LazyIterator.next wraps it in a ServieConfigurationError, > >> then ServiceIterator.next wraps it in an Abort. > >> > >> Is it safe to change both wrappings? > >> > >> com.sun.tools.javac.util.Abort: java.lang.NoClassDefFoundError: > >> com/amazon/coral/util/reflection/AnnotatedManifestAnnotationProcessor > >> > >> at > >> com.sun.tools.javac.processing.JavacProcessingEnvironment$ServiceIterator.next(JavacProcessingEnvironment.java:364) > >> > >> at > >> com.sun.tools.javac.processing.JavacProcessingEnvironment$ServiceIterator.next(JavacProcessingEnvironment.java:325) > >> > >> at > >> com.sun.tools.javac.processing.JavacProcessingEnvironment$DiscoveredProcessors$ProcessorStateIterator.next(JavacProcessingEnvironment.java:597) > >> > >> at > >> com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:690) > >> > >> at > >> com.sun.tools.javac.processing.JavacProcessingEnvironment.access$1800(JavacProcessingEnvironment.java:91) > >> > >> at > >> com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1035) > >> > >> at > >> com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1176) > >> > >> at > >> com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1170) > >> > >> at > >> com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:856) > >> > >> at com.sun.tools.javac.main.Main.compile(Main.java:523) > >> > >> at com.sun.tools.javac.main.Main.compile(Main.java:381) > >> > >> at com.sun.tools.javac.main.Main.compile(Main.java:370) > >> > >> at com.sun.tools.javac.main.Main.compile(Main.java:361) > >> > >> at com.sun.tools.javac.Main.compile(Main.java:56) > >> > >> at com.sun.tools.javac.Main.main(Main.java:42) > >> > >> Caused by: java.lang.NoClassDefFoundError: > >> com/amazon/coral/util/reflection/AnnotatedManifestAnnotationProcessor > >> > >> at java.lang.ClassLoader.defineClass1(Native Method) > >> > >> at java.lang.ClassLoader.defineClass(ClassLoader.java:763) > >> > >> at > >> java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) > >> > >> at java.net.URLClassLoader.defineClass(URLClassLoader.java:467) > >> > >> at java.net.URLClassLoader.access$100(URLClassLoader.java:73) > >> > >> at java.net.URLClassLoader$1.run(URLClassLoader.java:368) > >> > >> at java.net.URLClassLoader$1.run(URLClassLoader.java:362) > >> > >> at java.security.AccessController.doPrivileged(Native Method) > >> > >> at java.net.URLClassLoader.findClass(URLClassLoader.java:361) > >> > >> at java.lang.ClassLoader.loadClass(ClassLoader.java:424) > >> > >> at java.lang.ClassLoader.loadClass(ClassLoader.java:357) > >> > >> at java.lang.Class.forName0(Native Method) > >> > >> at java.lang.Class.forName(Class.java:348) > >> > >> at > >> com.sun.tools.javac.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:255) > >> > >> at > >> com.sun.tools.javac.util.ServiceLoader$1.next(ServiceLoader.java:337) > >> > >> at > >> com.sun.tools.javac.processing.JavacProcessingEnvironment$ServiceIterator.next(JavacProcessingEnvironment.java:359) > >> > >> ... 14 more > >> > >> Caused by: java.lang.ClassNotFoundException: > >> com.amazon.coral.util.reflection.AnnotatedManifestAnnotationProcessor > >> > >> at java.net.URLClassLoader.findClass(URLClassLoader.java:381) > >> > >> at java.lang.ClassLoader.loadClass(ClassLoader.java:424) > >> > >> at java.lang.ClassLoader.loadClass(ClassLoader.java:357) > >> > >> *From: *Jonathan Gibbons > >> > >> *Date: *Tuesday, January 9, 2018 at 1:19 PM > >> *To: *"Schaef, Martin" > >> , "compiler-dev at openjdk.java.net" > >> > >> > >> *Subject: *Re: Fixing JDK-8130493 > >> > >> What is the class triggering the ClassNotFoundException? > >> > >> If it is a user class not being found, it should be wrapped in a > >> ClientCodeException. If it is a javac class not being found, it > >> is reasonable to wrap it in an Abort. > >> > >> -- Jon > >> > >> On 1/9/18 9:52 AM, Schaef, Martin wrote: > >> > >> Hi, > >> > >> We have some users suffering from JDK-8130493 > >> (their > >> builds succeed, but the compiler actually failed). I did some > >> digging and the following sequence happens: > >> > >> A ClassNotFoundException is thrown in > >> JavaProcessingEnvironment.ServiceIterator.next() > >> > >> and re-thrown as an Abort. > >> > >> This Abort reaches JavaCompiler.processAnnotations() > >> > >> and is finally caught in JavaCompiler.compile() > >> by > >> the following snippet: > >> > >> try { > >> > >> initProcessAnnotations(processors); > >> > >> // These method calls must be chained to avoid > >> memory leaks > >> > >> delegateCompiler = > >> > >> processAnnotations( //<<<<<< ABORT COMES OUT HERE > >> > >> enterTrees(stopIfError(CompileState.PARSE, > >> parseFiles(sourceFileObjects))), > >> > >> classnames); > >> > >> ? > >> > >> } catch (Abort ex) { > >> > >> if (devVerbose) > >> > >> ex.printStackTrace(System.err); > >> > >> } finally { > >> > >> and swallowed ... but it's printed if XDev is set. > >> > >> What is a proper way to fix this? Is it correct to wrap all > >> exceptions in JavaProcessingEnvironmentServiceIterator into > >> aborts? Or would it be better to distinguish different Aborts > >> in JavaCompiler.java? > >> > >> > >> > >> > >> > >> > >> > > > > From jonathan.gibbons at oracle.com Wed Jan 10 18:43:11 2018 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Wed, 10 Jan 2018 10:43:11 -0800 Subject: Fixing JDK-8130493 In-Reply-To: <95ED4B91-B07C-4275-B0F1-AA392CB8D5B4@amazon.com> References: <91b1156a-6ec3-6717-4ce4-204258f2ce43@oracle.com> <95ED4B91-B07C-4275-B0F1-AA392CB8D5B4@amazon.com> Message-ID: <5A565EBF.6090905@oracle.com> This problem just got more complicated. It looks like you're reporting a problem in an older version of JDK. You reference com.sun.tools.javac.util.ServiceLoader, but that class no longer exists. (At this point in javac, it was a temporary "replacement" for java.util.ServiceLoader.) So, that doesn't invalidate the general problem report, but it does mean that we are less likely to patch an older version for this issue. -- Jon On 01/09/2018 12:36 PM, Schaef, Martin wrote: > > It?s a user class. See full stack trace below. > > The problem is that the ClassNotFound is already caught at > com.sun.tools.javac.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:255) > > which already wraps it in a ServiceConfigurationError > > in the fail method. That is, the exception gets wrapped twice. First, > LazyIterator.next wraps it in a ServieConfigurationError, then > ServiceIterator.next wraps it in an Abort. > > Is it safe to change both wrappings? > > com.sun.tools.javac.util.Abort: java.lang.NoClassDefFoundError: > com/amazon/coral/util/reflection/AnnotatedManifestAnnotationProcessor > > at > com.sun.tools.javac.processing.JavacProcessingEnvironment$ServiceIterator.next(JavacProcessingEnvironment.java:364) > > at > com.sun.tools.javac.processing.JavacProcessingEnvironment$ServiceIterator.next(JavacProcessingEnvironment.java:325) > > at > com.sun.tools.javac.processing.JavacProcessingEnvironment$DiscoveredProcessors$ProcessorStateIterator.next(JavacProcessingEnvironment.java:597) > > at > com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:690) > > at > com.sun.tools.javac.processing.JavacProcessingEnvironment.access$1800(JavacProcessingEnvironment.java:91) > > at > com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1035) > > at > com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1176) > > at > com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1170) > > at > com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:856) > > at com.sun.tools.javac.main.Main.compile(Main.java:523) > > at com.sun.tools.javac.main.Main.compile(Main.java:381) > > at com.sun.tools.javac.main.Main.compile(Main.java:370) > > at com.sun.tools.javac.main.Main.compile(Main.java:361) > > at com.sun.tools.javac.Main.compile(Main.java:56) > > at com.sun.tools.javac.Main.main(Main.java:42) > > Caused by: java.lang.NoClassDefFoundError: > com/amazon/coral/util/reflection/AnnotatedManifestAnnotationProcessor > > at java.lang.ClassLoader.defineClass1(Native Method) > > at java.lang.ClassLoader.defineClass(ClassLoader.java:763) > > at > java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) > > at java.net.URLClassLoader.defineClass(URLClassLoader.java:467) > > at java.net.URLClassLoader.access$100(URLClassLoader.java:73) > > at java.net.URLClassLoader$1.run(URLClassLoader.java:368) > > at java.net.URLClassLoader$1.run(URLClassLoader.java:362) > > at java.security.AccessController.doPrivileged(Native Method) > > at java.net.URLClassLoader.findClass(URLClassLoader.java:361) > > at java.lang.ClassLoader.loadClass(ClassLoader.java:424) > > at java.lang.ClassLoader.loadClass(ClassLoader.java:357) > > at java.lang.Class.forName0(Native Method) > > at java.lang.Class.forName(Class.java:348) > > at > com.sun.tools.javac.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:255) > > at > com.sun.tools.javac.util.ServiceLoader$1.next(ServiceLoader.java:337) > > at > com.sun.tools.javac.processing.JavacProcessingEnvironment$ServiceIterator.next(JavacProcessingEnvironment.java:359) > > ... 14 more > > Caused by: java.lang.ClassNotFoundException: > com.amazon.coral.util.reflection.AnnotatedManifestAnnotationProcessor > > at java.net.URLClassLoader.findClass(URLClassLoader.java:381) > > at java.lang.ClassLoader.loadClass(ClassLoader.java:424) > > at java.lang.ClassLoader.loadClass(ClassLoader.java:357) > > *From: *Jonathan Gibbons > *Date: *Tuesday, January 9, 2018 at 1:19 PM > *To: *"Schaef, Martin" , > "compiler-dev at openjdk.java.net" > *Subject: *Re: Fixing JDK-8130493 > > What is the class triggering the ClassNotFoundException? > > If it is a user class not being found, it should be wrapped in a > ClientCodeException. If it is a javac class not being found, it is > reasonable to wrap it in an Abort. > > -- Jon > > On 1/9/18 9:52 AM, Schaef, Martin wrote: > > Hi, > > We have some users suffering from JDK-8130493 > (their builds > succeed, but the compiler actually failed). I did some digging and > the following sequence happens: > > A ClassNotFoundException is thrown in > JavaProcessingEnvironment.ServiceIterator.next() > > and re-thrown as an Abort. > > This Abort reaches JavaCompiler.processAnnotations() > > and is finally caught in JavaCompiler.compile() > by > the following snippet: > > try { > > initProcessAnnotations(processors); > > // These method calls must be chained to avoid memory > leaks > > delegateCompiler = > > processAnnotations( //<<<<<< ABORT COMES OUT HERE > > enterTrees(stopIfError(CompileState.PARSE, > parseFiles(sourceFileObjects))), > > classnames); > > ? > > } catch (Abort ex) { > > if (devVerbose) > > ex.printStackTrace(System.err); > > } finally { > > and swallowed ... but it's printed if XDev is set. > > What is a proper way to fix this? Is it correct to wrap all > exceptions in JavaProcessingEnvironmentServiceIterator into > aborts? Or would it be better to distinguish different Aborts in > JavaCompiler.java? > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From schaef at amazon.com Wed Jan 10 18:43:43 2018 From: schaef at amazon.com (Schaef, Martin) Date: Wed, 10 Jan 2018 18:43:43 +0000 Subject: Fixing JDK-8130493 In-Reply-To: <5A565C15.8090107@oracle.com> References: <91b1156a-6ec3-6717-4ce4-204258f2ce43@oracle.com> <95ED4B91-B07C-4275-B0F1-AA392CB8D5B4@amazon.com> <1341C4E9-1F39-400C-9F3C-31E28E606555@amazon.com> <506c86c4-a749-73c8-afa6-c05ccf8404a9@oracle.com> <9C1302C8-EE80-4866-96E8-B26F329B7104@amazon.com> <5A565050.6030707@oracle.com> <2C2A3485-3C77-42EE-AFD7-B3FD97B97E1E@amazon.com> <5A565C15.8090107@oracle.com> Message-ID: <0B351538-7878-41F3-8B16-4183751770BE@amazon.com> My first question would be, what is the use case where iterating through annotation processors should Abort the compiler and exit without error message? Currently, I can?t think of a case where this is expected. I would assume that the idea behind the lazy iterator in ?hasNext? is that some annotation processors can be discovered but not loaded. But for this case, the ?next? method shouldn?t just throw all the way up to Main. Otherwise, you don?t really need lazy loading. Can you think of a scenario where a processor is discovered but cannot be loaded? What?s the expected behavior? On 1/10/18, 1:32 PM, "Jonathan Gibbons" wrote: I would still like to examine this problem further. I would like to understand the right solution, and not just go for the minimal solution. -- Jon On 01/10/2018 10:27 AM, Schaef, Martin wrote: > Tested it, and it works for my use case and the example in JDK-8130493. See patch below. > Want to go forward with this? > > > diff --new-file --unified --recursive --exclude='*.autotools' --exclude='*.cproject' --exclude='*.project' ./langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java ./langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java > --- ./langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java 2017-10-20 20:28:37.000000000 +0000 > +++ ./langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java 2018-01-10 16:46:52.798017039 +0000 > a 2018-01-10 17:50:25.093338055 +0000 > @@ -339,7 +339,7 @@ > } > } catch (Throwable t) { > log.error("proc.service.problem"); > - throw new Abort(t); > + throw new AnnotationProcessingError(t); > } > } > > @@ -361,7 +361,7 @@ > log.error("proc.bad.config.file", sce.getLocalizedMessage()); > throw new Abort(sce); > } catch (Throwable t) { > - throw new Abort(t); > + throw new AnnotationProcessingError(t); > } > } > > > On 1/10/18, 12:42 PM, "Jan Lahoda" wrote: > > For a minimal change, I think it should be enough to change (in > ServiceIterator) the existing: > --- > } catch (Throwable t) { > throw new Abort(t); > } > --- > to > --- > } catch (Throwable t) { > throw new AnnotationProcessingError(t); > } > --- > > AnnotationProcessingError is handled both in JavacTaskImpl and > com.sun.tools.javac.main.Main. For command line javac, this would get an > output like: > --- > An annotation processor threw an uncaught exception. > Consult the following stack trace for details. > java.lang.ClassFormatError: Truncated class file > [stacktrace] > --- > > Which is in line with the behavior when -processor is used > (NameProcessIterator). > > But I guess it would be good to improve consistency of error handling in > JavacProcessingEnvironment at some point. > > Jan > > On 10.1.2018 18:23, Jonathan Gibbons wrote: > > Why would you not just change > > > > > > from > > > > } catch (Throwable t) { > > > > log.error("proc.service.problem"); > > > > throw new Abort(t); > > > > to > > > > } catch (Throwable t) { > > > > log.error("proc.service.problem"); > > > > throw new AnnotationProcessingError(t); > > > > > > and then briefly, concisely, handle AnnotationProcessingError in > > JavaCompiler. > > > > -- Jon > > > > > > On 1/10/18 9:13 AM, Schaef, Martin wrote: > >> > >> I understand. The bare minimum that fixes the test cases would be to > >> change the exception handling in the constructor of ServiceIterator: > >> > >> http://hg.openjdk.java.net/jdk8u/jdk8u/langtools/file/989188d1a978/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java#l340 > >> > >> and in ServiceIterator.next(): > >> > >> http://hg.openjdk.java.net/jdk8u/jdk8u/langtools/file/989188d1a978/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java#l363 > >> > >> from > >> > >> } catch (Throwable t) { > >> > >> log.error("proc.service.problem"); > >> > >> throw new Abort(t); > >> > >> to > >> > >> } catch (Exception t) { > >> > >> log.error("proc.service.problem"); > >> > >> throw new Abort(t); > >> > >> } catch (Throwable t) { > >> > >> log.error("Some error text"); > >> > >> throw new AnnotationProcessingError (t); > >> > >> With this change, the exit code of javac is 3 instead of 0. > >> > >> Does that sound like something you could support? If so, what should > >> go in the log.error messages? > >> > >> Cheers, > >> > >> Martin > >> > >> *From: *Jonathan Gibbons > >> *Date: *Wednesday, January 10, 2018 at 11:39 AM > >> *To: *"Schaef, Martin" , > >> "compiler-dev at openjdk.java.net" > >> *Cc: *"Hohensee, Paul" > >> *Subject: *Re: Fixing JDK-8130493 > >> > >> Martin, > >> > >> I have not read your patch, but changing the semantics of the iterator > >> sounds like a step too far. > >> > >> Without trying to implement the following yet, I would expect the > >> general direction of a solution to be to one of the following: > >> > >> 1. if the exception should be fatal, allow it to propagate up to > >> JavaCompiler, (similar to as now) but maybe with a custom new wrapper > >> exception > >> > >> 2. if the exception should not be fatal, translate it to an error > >> message (log.error(...)) and continue. > >> > >> It probably needs more analysis and discussion to determine which of > >> those two directions to take. > >> > >> -- Jon > >> > >> On 1/10/18 8:17 AM, Schaef, Martin wrote: > >> > >> Let me revise that: > >> > >> In JavacProcessingEnvironment.initProcessorIterator > >> > >> the code chooses one of two types of iterators: > >> > >> The NameProcessIterator > >> > >> if ther -processor flag is given or the ServiceIterator > >> . > >> > >> If we look at the NameProcessIterator.hasNext() > >> > >> implementation, it checks if there is a next name AND checks if > >> this class name can be loaded. That is, if the class is not > >> present, the hasNext() method already returns false (or, in our > >> case, throws the NoClassDefFoundError which gets wrapped into an > >> AnnotationProcessingError). > >> > >> If we look at the ServiceIterator together with the stack trace > >> from my previous email, we see that the .hasNext() and .next() > >> calls get forwarded into the ServiceLoader.LazyIterator > >> . > >> This behaves different than the NameProcessIterator: hasNext() > >> > >> only checks if a next name exists and would not throw a > >> NoClassDefFoundError. Then next() > >> > >> throws the NoClassDefFoundError which gets caught by the catch-all > >> in JavaProcessingEnvironment.ServiceIterator.next() > >> > >> and wrapped into an Abort. > >> > >> So, to summarize: > >> > >> For a NameProcessIterator, a missing class causes a > >> AnnotationProcessingError thrown from > >> NameProcessIterator.hasNext() > >> > >> and for ServiceIterator, it causes a Abert thrown by > >> JavaProcessingEnvironment.ServiceIterator.next() > >> . > >> > >> I could fix my problem and JDK-8130493 > >> by checking if > >> the class can be loaded in the hasNext method and changing the > >> exception handling in > >> JavaProcessingEnvironment.ServiceIterator.next() > >> . > >> The problem with that is that the lazy iterator is not lazy > >> anymore. Is there a reason why this Iterator has to be lazy? > >> > >> I attached a patch that solves the issue for me. Feedback would be > >> great. > >> > >> Cheers, > >> > >> Martin > >> > >> *From: *compiler-dev > >> on behalf of > >> "Schaef, Martin" > >> *Date: *Tuesday, January 9, 2018 at 3:37 PM > >> *To: *Jonathan Gibbons > >> , > >> "compiler-dev at openjdk.java.net" > >> > >> > >> *Subject: *Re: Fixing JDK-8130493 > >> > >> It?s a user class. See full stack trace below. > >> > >> The problem is that the ClassNotFound is already caught at > >> com.sun.tools.javac.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:255) > >> > >> which already wraps it in a ServiceConfigurationError > >> > >> in the fail method. That is, the exception gets wrapped twice. > >> First, LazyIterator.next wraps it in a ServieConfigurationError, > >> then ServiceIterator.next wraps it in an Abort. > >> > >> Is it safe to change both wrappings? > >> > >> com.sun.tools.javac.util.Abort: java.lang.NoClassDefFoundError: > >> com/amazon/coral/util/reflection/AnnotatedManifestAnnotationProcessor > >> > >> at > >> com.sun.tools.javac.processing.JavacProcessingEnvironment$ServiceIterator.next(JavacProcessingEnvironment.java:364) > >> > >> at > >> com.sun.tools.javac.processing.JavacProcessingEnvironment$ServiceIterator.next(JavacProcessingEnvironment.java:325) > >> > >> at > >> com.sun.tools.javac.processing.JavacProcessingEnvironment$DiscoveredProcessors$ProcessorStateIterator.next(JavacProcessingEnvironment.java:597) > >> > >> at > >> com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:690) > >> > >> at > >> com.sun.tools.javac.processing.JavacProcessingEnvironment.access$1800(JavacProcessingEnvironment.java:91) > >> > >> at > >> com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1035) > >> > >> at > >> com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1176) > >> > >> at > >> com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1170) > >> > >> at > >> com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:856) > >> > >> at com.sun.tools.javac.main.Main.compile(Main.java:523) > >> > >> at com.sun.tools.javac.main.Main.compile(Main.java:381) > >> > >> at com.sun.tools.javac.main.Main.compile(Main.java:370) > >> > >> at com.sun.tools.javac.main.Main.compile(Main.java:361) > >> > >> at com.sun.tools.javac.Main.compile(Main.java:56) > >> > >> at com.sun.tools.javac.Main.main(Main.java:42) > >> > >> Caused by: java.lang.NoClassDefFoundError: > >> com/amazon/coral/util/reflection/AnnotatedManifestAnnotationProcessor > >> > >> at java.lang.ClassLoader.defineClass1(Native Method) > >> > >> at java.lang.ClassLoader.defineClass(ClassLoader.java:763) > >> > >> at > >> java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) > >> > >> at java.net.URLClassLoader.defineClass(URLClassLoader.java:467) > >> > >> at java.net.URLClassLoader.access$100(URLClassLoader.java:73) > >> > >> at java.net.URLClassLoader$1.run(URLClassLoader.java:368) > >> > >> at java.net.URLClassLoader$1.run(URLClassLoader.java:362) > >> > >> at java.security.AccessController.doPrivileged(Native Method) > >> > >> at java.net.URLClassLoader.findClass(URLClassLoader.java:361) > >> > >> at java.lang.ClassLoader.loadClass(ClassLoader.java:424) > >> > >> at java.lang.ClassLoader.loadClass(ClassLoader.java:357) > >> > >> at java.lang.Class.forName0(Native Method) > >> > >> at java.lang.Class.forName(Class.java:348) > >> > >> at > >> com.sun.tools.javac.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:255) > >> > >> at > >> com.sun.tools.javac.util.ServiceLoader$1.next(ServiceLoader.java:337) > >> > >> at > >> com.sun.tools.javac.processing.JavacProcessingEnvironment$ServiceIterator.next(JavacProcessingEnvironment.java:359) > >> > >> ... 14 more > >> > >> Caused by: java.lang.ClassNotFoundException: > >> com.amazon.coral.util.reflection.AnnotatedManifestAnnotationProcessor > >> > >> at java.net.URLClassLoader.findClass(URLClassLoader.java:381) > >> > >> at java.lang.ClassLoader.loadClass(ClassLoader.java:424) > >> > >> at java.lang.ClassLoader.loadClass(ClassLoader.java:357) > >> > >> *From: *Jonathan Gibbons > >> > >> *Date: *Tuesday, January 9, 2018 at 1:19 PM > >> *To: *"Schaef, Martin" > >> , "compiler-dev at openjdk.java.net" > >> > >> > >> *Subject: *Re: Fixing JDK-8130493 > >> > >> What is the class triggering the ClassNotFoundException? > >> > >> If it is a user class not being found, it should be wrapped in a > >> ClientCodeException. If it is a javac class not being found, it > >> is reasonable to wrap it in an Abort. > >> > >> -- Jon > >> > >> On 1/9/18 9:52 AM, Schaef, Martin wrote: > >> > >> Hi, > >> > >> We have some users suffering from JDK-8130493 > >> (their > >> builds succeed, but the compiler actually failed). I did some > >> digging and the following sequence happens: > >> > >> A ClassNotFoundException is thrown in > >> JavaProcessingEnvironment.ServiceIterator.next() > >> > >> and re-thrown as an Abort. > >> > >> This Abort reaches JavaCompiler.processAnnotations() > >> > >> and is finally caught in JavaCompiler.compile() > >> by > >> the following snippet: > >> > >> try { > >> > >> initProcessAnnotations(processors); > >> > >> // These method calls must be chained to avoid > >> memory leaks > >> > >> delegateCompiler = > >> > >> processAnnotations( //<<<<<< ABORT COMES OUT HERE > >> > >> enterTrees(stopIfError(CompileState.PARSE, > >> parseFiles(sourceFileObjects))), > >> > >> classnames); > >> > >> ? > >> > >> } catch (Abort ex) { > >> > >> if (devVerbose) > >> > >> ex.printStackTrace(System.err); > >> > >> } finally { > >> > >> and swallowed ... but it's printed if XDev is set. > >> > >> What is a proper way to fix this? Is it correct to wrap all > >> exceptions in JavaProcessingEnvironmentServiceIterator into > >> aborts? Or would it be better to distinguish different Aborts > >> in JavaCompiler.java? > >> > >> > >> > >> > >> > >> > >> > > > > From jonathan.gibbons at oracle.com Wed Jan 10 18:53:32 2018 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Wed, 10 Jan 2018 10:53:32 -0800 Subject: Fixing JDK-8130493 In-Reply-To: <0B351538-7878-41F3-8B16-4183751770BE@amazon.com> References: <91b1156a-6ec3-6717-4ce4-204258f2ce43@oracle.com> <95ED4B91-B07C-4275-B0F1-AA392CB8D5B4@amazon.com> <1341C4E9-1F39-400C-9F3C-31E28E606555@amazon.com> <506c86c4-a749-73c8-afa6-c05ccf8404a9@oracle.com> <9C1302C8-EE80-4866-96E8-B26F329B7104@amazon.com> <5A565050.6030707@oracle.com> <2C2A3485-3C77-42EE-AFD7-B3FD97B97E1E@amazon.com> <5A565C15.8090107@oracle.com> <0B351538-7878-41F3-8B16-4183751770BE@amazon.com> Message-ID: <5A56612C.1040907@oracle.com> Martin, Your first question is the key question, although maybe not in the sense you mean. > My first question would be, what is the use case where iterating through annotation processors should Abort the compiler/ and exit without error message/? Note the emphasis is on "exiting without an error message". That is the bug that needs to be fixed. In general, Abort should be used to halt the compilation/after reporting an informative error message/. I see a number of use-sites in the JavacProcessingEnvironment class where this pattern is not followed correctly, and that hints at the correct solution. If an error message is reported, that will (a) not surprise the user that the compiler seems to ignore the issue , and (b) will cause a non-zero exit code from javac. -- Jon On 01/10/2018 10:43 AM, Schaef, Martin wrote: > My first question would be, what is the use case where iterating through annotation processors should Abort the compiler and exit without error message? > Currently, I can?t think of a case where this is expected. > I would assume that the idea behind the lazy iterator in ?hasNext? is that some annotation processors can be discovered but not loaded. But for this case, the ?next? method shouldn?t just throw all the way up to Main. Otherwise, you don?t really need lazy loading. > > Can you think of a scenario where a processor is discovered but cannot be loaded? What?s the expected behavior? > > > On 1/10/18, 1:32 PM, "Jonathan Gibbons" wrote: > > I would still like to examine this problem further. I would like to > understand the right solution, and not just go for the minimal solution. > > -- Jon > > On 01/10/2018 10:27 AM, Schaef, Martin wrote: > > Tested it, and it works for my use case and the example in JDK-8130493. See patch below. > > Want to go forward with this? > > > > > > diff --new-file --unified --recursive --exclude='*.autotools' --exclude='*.cproject' --exclude='*.project' ./langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java ./langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java > > --- ./langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java 2017-10-20 20:28:37.000000000 +0000 > > +++ ./langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java 2018-01-10 16:46:52.798017039 +0000 > > a 2018-01-10 17:50:25.093338055 +0000 > > @@ -339,7 +339,7 @@ > > } > > } catch (Throwable t) { > > log.error("proc.service.problem"); > > - throw new Abort(t); > > + throw new AnnotationProcessingError(t); > > } > > } > > > > @@ -361,7 +361,7 @@ > > log.error("proc.bad.config.file", sce.getLocalizedMessage()); > > throw new Abort(sce); > > } catch (Throwable t) { > > - throw new Abort(t); > > + throw new AnnotationProcessingError(t); > > } > > } > > > > > > On 1/10/18, 12:42 PM, "Jan Lahoda" wrote: > > > > For a minimal change, I think it should be enough to change (in > > ServiceIterator) the existing: > > --- > > } catch (Throwable t) { > > throw new Abort(t); > > } > > --- > > to > > --- > > } catch (Throwable t) { > > throw new AnnotationProcessingError(t); > > } > > --- > > > > AnnotationProcessingError is handled both in JavacTaskImpl and > > com.sun.tools.javac.main.Main. For command line javac, this would get an > > output like: > > --- > > An annotation processor threw an uncaught exception. > > Consult the following stack trace for details. > > java.lang.ClassFormatError: Truncated class file > > [stacktrace] > > --- > > > > Which is in line with the behavior when -processor is used > > (NameProcessIterator). > > > > But I guess it would be good to improve consistency of error handling in > > JavacProcessingEnvironment at some point. > > > > Jan > > > > On 10.1.2018 18:23, Jonathan Gibbons wrote: > > > Why would you not just change > > > > > > > > > from > > > > > > } catch (Throwable t) { > > > > > > log.error("proc.service.problem"); > > > > > > throw new Abort(t); > > > > > > to > > > > > > } catch (Throwable t) { > > > > > > log.error("proc.service.problem"); > > > > > > throw new AnnotationProcessingError(t); > > > > > > > > > and then briefly, concisely, handle AnnotationProcessingError in > > > JavaCompiler. > > > > > > -- Jon > > > > > > > > > On 1/10/18 9:13 AM, Schaef, Martin wrote: > > >> > > >> I understand. The bare minimum that fixes the test cases would be to > > >> change the exception handling in the constructor of ServiceIterator: > > >> > > >> http://hg.openjdk.java.net/jdk8u/jdk8u/langtools/file/989188d1a978/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java#l340 > > >> > > >> and in ServiceIterator.next(): > > >> > > >> http://hg.openjdk.java.net/jdk8u/jdk8u/langtools/file/989188d1a978/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java#l363 > > >> > > >> from > > >> > > >> } catch (Throwable t) { > > >> > > >> log.error("proc.service.problem"); > > >> > > >> throw new Abort(t); > > >> > > >> to > > >> > > >> } catch (Exception t) { > > >> > > >> log.error("proc.service.problem"); > > >> > > >> throw new Abort(t); > > >> > > >> } catch (Throwable t) { > > >> > > >> log.error("Some error text"); > > >> > > >> throw new AnnotationProcessingError (t); > > >> > > >> With this change, the exit code of javac is 3 instead of 0. > > >> > > >> Does that sound like something you could support? If so, what should > > >> go in the log.error messages? > > >> > > >> Cheers, > > >> > > >> Martin > > >> > > >> *From: *Jonathan Gibbons > > >> *Date: *Wednesday, January 10, 2018 at 11:39 AM > > >> *To: *"Schaef, Martin" , > > >> "compiler-dev at openjdk.java.net" > > >> *Cc: *"Hohensee, Paul" > > >> *Subject: *Re: Fixing JDK-8130493 > > >> > > >> Martin, > > >> > > >> I have not read your patch, but changing the semantics of the iterator > > >> sounds like a step too far. > > >> > > >> Without trying to implement the following yet, I would expect the > > >> general direction of a solution to be to one of the following: > > >> > > >> 1. if the exception should be fatal, allow it to propagate up to > > >> JavaCompiler, (similar to as now) but maybe with a custom new wrapper > > >> exception > > >> > > >> 2. if the exception should not be fatal, translate it to an error > > >> message (log.error(...)) and continue. > > >> > > >> It probably needs more analysis and discussion to determine which of > > >> those two directions to take. > > >> > > >> -- Jon > > >> > > >> On 1/10/18 8:17 AM, Schaef, Martin wrote: > > >> > > >> Let me revise that: > > >> > > >> In JavacProcessingEnvironment.initProcessorIterator > > >> > > >> the code chooses one of two types of iterators: > > >> > > >> The NameProcessIterator > > >> > > >> if ther -processor flag is given or the ServiceIterator > > >> . > > >> > > >> If we look at the NameProcessIterator.hasNext() > > >> > > >> implementation, it checks if there is a next name AND checks if > > >> this class name can be loaded. That is, if the class is not > > >> present, the hasNext() method already returns false (or, in our > > >> case, throws the NoClassDefFoundError which gets wrapped into an > > >> AnnotationProcessingError). > > >> > > >> If we look at the ServiceIterator together with the stack trace > > >> from my previous email, we see that the .hasNext() and .next() > > >> calls get forwarded into the ServiceLoader.LazyIterator > > >> . > > >> This behaves different than the NameProcessIterator: hasNext() > > >> > > >> only checks if a next name exists and would not throw a > > >> NoClassDefFoundError. Then next() > > >> > > >> throws the NoClassDefFoundError which gets caught by the catch-all > > >> in JavaProcessingEnvironment.ServiceIterator.next() > > >> > > >> and wrapped into an Abort. > > >> > > >> So, to summarize: > > >> > > >> For a NameProcessIterator, a missing class causes a > > >> AnnotationProcessingError thrown from > > >> NameProcessIterator.hasNext() > > >> > > >> and for ServiceIterator, it causes a Abert thrown by > > >> JavaProcessingEnvironment.ServiceIterator.next() > > >> . > > >> > > >> I could fix my problem and JDK-8130493 > > >> by checking if > > >> the class can be loaded in the hasNext method and changing the > > >> exception handling in > > >> JavaProcessingEnvironment.ServiceIterator.next() > > >> . > > >> The problem with that is that the lazy iterator is not lazy > > >> anymore. Is there a reason why this Iterator has to be lazy? > > >> > > >> I attached a patch that solves the issue for me. Feedback would be > > >> great. > > >> > > >> Cheers, > > >> > > >> Martin > > >> > > >> *From: *compiler-dev > > >> on behalf of > > >> "Schaef, Martin" > > >> *Date: *Tuesday, January 9, 2018 at 3:37 PM > > >> *To: *Jonathan Gibbons > > >> , > > >> "compiler-dev at openjdk.java.net" > > >> > > >> > > >> *Subject: *Re: Fixing JDK-8130493 > > >> > > >> It?s a user class. See full stack trace below. > > >> > > >> The problem is that the ClassNotFound is already caught at > > >> com.sun.tools.javac.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:255) > > >> > > >> which already wraps it in a ServiceConfigurationError > > >> > > >> in the fail method. That is, the exception gets wrapped twice. > > >> First, LazyIterator.next wraps it in a ServieConfigurationError, > > >> then ServiceIterator.next wraps it in an Abort. > > >> > > >> Is it safe to change both wrappings? > > >> > > >> com.sun.tools.javac.util.Abort: java.lang.NoClassDefFoundError: > > >> com/amazon/coral/util/reflection/AnnotatedManifestAnnotationProcessor > > >> > > >> at > > >> com.sun.tools.javac.processing.JavacProcessingEnvironment$ServiceIterator.next(JavacProcessingEnvironment.java:364) > > >> > > >> at > > >> com.sun.tools.javac.processing.JavacProcessingEnvironment$ServiceIterator.next(JavacProcessingEnvironment.java:325) > > >> > > >> at > > >> com.sun.tools.javac.processing.JavacProcessingEnvironment$DiscoveredProcessors$ProcessorStateIterator.next(JavacProcessingEnvironment.java:597) > > >> > > >> at > > >> com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:690) > > >> > > >> at > > >> com.sun.tools.javac.processing.JavacProcessingEnvironment.access$1800(JavacProcessingEnvironment.java:91) > > >> > > >> at > > >> com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1035) > > >> > > >> at > > >> com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1176) > > >> > > >> at > > >> com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1170) > > >> > > >> at > > >> com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:856) > > >> > > >> at com.sun.tools.javac.main.Main.compile(Main.java:523) > > >> > > >> at com.sun.tools.javac.main.Main.compile(Main.java:381) > > >> > > >> at com.sun.tools.javac.main.Main.compile(Main.java:370) > > >> > > >> at com.sun.tools.javac.main.Main.compile(Main.java:361) > > >> > > >> at com.sun.tools.javac.Main.compile(Main.java:56) > > >> > > >> at com.sun.tools.javac.Main.main(Main.java:42) > > >> > > >> Caused by: java.lang.NoClassDefFoundError: > > >> com/amazon/coral/util/reflection/AnnotatedManifestAnnotationProcessor > > >> > > >> at java.lang.ClassLoader.defineClass1(Native Method) > > >> > > >> at java.lang.ClassLoader.defineClass(ClassLoader.java:763) > > >> > > >> at > > >> java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) > > >> > > >> at java.net.URLClassLoader.defineClass(URLClassLoader.java:467) > > >> > > >> at java.net.URLClassLoader.access$100(URLClassLoader.java:73) > > >> > > >> at java.net.URLClassLoader$1.run(URLClassLoader.java:368) > > >> > > >> at java.net.URLClassLoader$1.run(URLClassLoader.java:362) > > >> > > >> at java.security.AccessController.doPrivileged(Native Method) > > >> > > >> at java.net.URLClassLoader.findClass(URLClassLoader.java:361) > > >> > > >> at java.lang.ClassLoader.loadClass(ClassLoader.java:424) > > >> > > >> at java.lang.ClassLoader.loadClass(ClassLoader.java:357) > > >> > > >> at java.lang.Class.forName0(Native Method) > > >> > > >> at java.lang.Class.forName(Class.java:348) > > >> > > >> at > > >> com.sun.tools.javac.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:255) > > >> > > >> at > > >> com.sun.tools.javac.util.ServiceLoader$1.next(ServiceLoader.java:337) > > >> > > >> at > > >> com.sun.tools.javac.processing.JavacProcessingEnvironment$ServiceIterator.next(JavacProcessingEnvironment.java:359) > > >> > > >> ... 14 more > > >> > > >> Caused by: java.lang.ClassNotFoundException: > > >> com.amazon.coral.util.reflection.AnnotatedManifestAnnotationProcessor > > >> > > >> at java.net.URLClassLoader.findClass(URLClassLoader.java:381) > > >> > > >> at java.lang.ClassLoader.loadClass(ClassLoader.java:424) > > >> > > >> at java.lang.ClassLoader.loadClass(ClassLoader.java:357) > > >> > > >> *From: *Jonathan Gibbons > > >> > > >> *Date: *Tuesday, January 9, 2018 at 1:19 PM > > >> *To: *"Schaef, Martin" > > >> , "compiler-dev at openjdk.java.net" > > >> > > >> > > >> *Subject: *Re: Fixing JDK-8130493 > > >> > > >> What is the class triggering the ClassNotFoundException? > > >> > > >> If it is a user class not being found, it should be wrapped in a > > >> ClientCodeException. If it is a javac class not being found, it > > >> is reasonable to wrap it in an Abort. > > >> > > >> -- Jon > > >> > > >> On 1/9/18 9:52 AM, Schaef, Martin wrote: > > >> > > >> Hi, > > >> > > >> We have some users suffering from JDK-8130493 > > >> (their > > >> builds succeed, but the compiler actually failed). I did some > > >> digging and the following sequence happens: > > >> > > >> A ClassNotFoundException is thrown in > > >> JavaProcessingEnvironment.ServiceIterator.next() > > >> > > >> and re-thrown as an Abort. > > >> > > >> This Abort reaches JavaCompiler.processAnnotations() > > >> > > >> and is finally caught in JavaCompiler.compile() > > >> by > > >> the following snippet: > > >> > > >> try { > > >> > > >> initProcessAnnotations(processors); > > >> > > >> // These method calls must be chained to avoid > > >> memory leaks > > >> > > >> delegateCompiler = > > >> > > >> processAnnotations( //<<<<<< ABORT COMES OUT HERE > > >> > > >> enterTrees(stopIfError(CompileState.PARSE, > > >> parseFiles(sourceFileObjects))), > > >> > > >> classnames); > > >> > > >> ? > > >> > > >> } catch (Abort ex) { > > >> > > >> if (devVerbose) > > >> > > >> ex.printStackTrace(System.err); > > >> > > >> } finally { > > >> > > >> and swallowed ... but it's printed if XDev is set. > > >> > > >> What is a proper way to fix this? Is it correct to wrap all > > >> exceptions in JavaProcessingEnvironmentServiceIterator into > > >> aborts? Or would it be better to distinguish different Aborts > > >> in JavaCompiler.java? > > >> > > >> > > >> > > >> > > >> > > >> > > >> > > > > > > > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From jonathan.gibbons at oracle.com Wed Jan 10 19:06:25 2018 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Wed, 10 Jan 2018 11:06:25 -0800 Subject: Fixing JDK-8130493 In-Reply-To: <5A565050.6030707@oracle.com> References: <91b1156a-6ec3-6717-4ce4-204258f2ce43@oracle.com> <95ED4B91-B07C-4275-B0F1-AA392CB8D5B4@amazon.com> <1341C4E9-1F39-400C-9F3C-31E28E606555@amazon.com> <506c86c4-a749-73c8-afa6-c05ccf8404a9@oracle.com> <9C1302C8-EE80-4866-96E8-B26F329B7104@amazon.com> <5A565050.6030707@oracle.com> Message-ID: <5A566431.30004@oracle.com> Jan, javac should not generate a stacktrace in this situation. This case is about a bad class file, and so javac should generate an informative message, in the family of "bad class file" or "class not found" messages. javac should only resort to stacktraces when code has crashed or otherwise behaved unexpectedly, such that javac cannot provide a helpful message. There are two sub-cases here ... the crash is in javac code or libraries that it might call, in which case the message is, "oops, our fault, please report a bug", or the crash is in user code, in which case, the message is effectively, "it's your problem , not javac" -- Jon On 01/10/2018 09:41 AM, Jan Lahoda wrote: > For a minimal change, I think it should be enough to change (in > ServiceIterator) the existing: > --- > } catch (Throwable t) { > throw new Abort(t); > } > --- > to > --- > } catch (Throwable t) { > throw new AnnotationProcessingError(t); > } > --- > > AnnotationProcessingError is handled both in JavacTaskImpl and > com.sun.tools.javac.main.Main. For command line javac, this would get > an output like: > --- > An annotation processor threw an uncaught exception. > Consult the following stack trace for details. > java.lang.ClassFormatError: Truncated class file > [stacktrace] > --- > > Which is in line with the behavior when -processor is used > (NameProcessIterator). > > But I guess it would be good to improve consistency of error handling > in JavacProcessingEnvironment at some point. > > Jan > > On 10.1.2018 18:23, Jonathan Gibbons wrote: >> Why would you not just change >> >> >> from >> >> } catch (Throwable t) { >> >> log.error("proc.service.problem"); >> >> throw new Abort(t); >> >> to >> >> } catch (Throwable t) { >> >> log.error("proc.service.problem"); >> >> throw new AnnotationProcessingError(t); >> >> >> and then briefly, concisely, handle AnnotationProcessingError in >> JavaCompiler. >> >> -- Jon >> >> >> On 1/10/18 9:13 AM, Schaef, Martin wrote: >>> >>> I understand. The bare minimum that fixes the test cases would be to >>> change the exception handling in the constructor of ServiceIterator: >>> >>> http://hg.openjdk.java.net/jdk8u/jdk8u/langtools/file/989188d1a978/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java#l340 >>> >>> >>> and in ServiceIterator.next(): >>> >>> http://hg.openjdk.java.net/jdk8u/jdk8u/langtools/file/989188d1a978/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java#l363 >>> >>> >>> from >>> >>> } catch (Throwable t) { >>> >>> log.error("proc.service.problem"); >>> >>> throw new Abort(t); >>> >>> to >>> >>> } catch (Exception t) { >>> >>> log.error("proc.service.problem"); >>> >>> throw new Abort(t); >>> >>> } catch (Throwable t) { >>> >>> log.error("Some error text"); >>> >>> throw new AnnotationProcessingError (t); >>> >>> With this change, the exit code of javac is 3 instead of 0. >>> >>> Does that sound like something you could support? If so, what should >>> go in the log.error messages? >>> >>> Cheers, >>> >>> Martin >>> >>> *From: *Jonathan Gibbons >>> *Date: *Wednesday, January 10, 2018 at 11:39 AM >>> *To: *"Schaef, Martin" , >>> "compiler-dev at openjdk.java.net" >>> *Cc: *"Hohensee, Paul" >>> *Subject: *Re: Fixing JDK-8130493 >>> >>> Martin, >>> >>> I have not read your patch, but changing the semantics of the iterator >>> sounds like a step too far. >>> >>> Without trying to implement the following yet, I would expect the >>> general direction of a solution to be to one of the following: >>> >>> 1. if the exception should be fatal, allow it to propagate up to >>> JavaCompiler, (similar to as now) but maybe with a custom new wrapper >>> exception >>> >>> 2. if the exception should not be fatal, translate it to an error >>> message (log.error(...)) and continue. >>> >>> It probably needs more analysis and discussion to determine which of >>> those two directions to take. >>> >>> -- Jon >>> >>> On 1/10/18 8:17 AM, Schaef, Martin wrote: >>> >>> Let me revise that: >>> >>> In JavacProcessingEnvironment.initProcessorIterator >>> >>> the code chooses one of two types of iterators: >>> >>> The NameProcessIterator >>> >>> if ther -processor flag is given or the ServiceIterator >>> . >>> >>> If we look at the NameProcessIterator.hasNext() >>> >>> implementation, it checks if there is a next name AND checks if >>> this class name can be loaded. That is, if the class is not >>> present, the hasNext() method already returns false (or, in our >>> case, throws the NoClassDefFoundError which gets wrapped into an >>> AnnotationProcessingError). >>> >>> If we look at the ServiceIterator together with the stack trace >>> from my previous email, we see that the .hasNext() and .next() >>> calls get forwarded into the ServiceLoader.LazyIterator >>> . >>> This behaves different than the NameProcessIterator: hasNext() >>> >>> only checks if a next name exists and would not throw a >>> NoClassDefFoundError. Then next() >>> >>> throws the NoClassDefFoundError which gets caught by the catch-all >>> in JavaProcessingEnvironment.ServiceIterator.next() >>> >>> and wrapped into an Abort. >>> >>> So, to summarize: >>> >>> For a NameProcessIterator, a missing class causes a >>> AnnotationProcessingError thrown from >>> NameProcessIterator.hasNext() >>> >>> and for ServiceIterator, it causes a Abert thrown by >>> JavaProcessingEnvironment.ServiceIterator.next() >>> . >>> >>> I could fix my problem and JDK-8130493 >>> by checking if >>> the class can be loaded in the hasNext method and changing the >>> exception handling in >>> JavaProcessingEnvironment.ServiceIterator.next() >>> . >>> The problem with that is that the lazy iterator is not lazy >>> anymore. Is there a reason why this Iterator has to be lazy? >>> >>> I attached a patch that solves the issue for me. Feedback would be >>> great. >>> >>> Cheers, >>> >>> Martin >>> >>> *From: *compiler-dev >>> on behalf of >>> "Schaef, Martin" >>> *Date: *Tuesday, January 9, 2018 at 3:37 PM >>> *To: *Jonathan Gibbons >>> , >>> "compiler-dev at openjdk.java.net" >>> >>> >>> >>> *Subject: *Re: Fixing JDK-8130493 >>> >>> It?s a user class. See full stack trace below. >>> >>> The problem is that the ClassNotFound is already caught at >>> com.sun.tools.javac.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:255) >>> >>> which already wraps it in a ServiceConfigurationError >>> >>> in the fail method. That is, the exception gets wrapped twice. >>> First, LazyIterator.next wraps it in a ServieConfigurationError, >>> then ServiceIterator.next wraps it in an Abort. >>> >>> Is it safe to change both wrappings? >>> >>> com.sun.tools.javac.util.Abort: java.lang.NoClassDefFoundError: >>> com/amazon/coral/util/reflection/AnnotatedManifestAnnotationProcessor >>> >>> at >>> com.sun.tools.javac.processing.JavacProcessingEnvironment$ServiceIterator.next(JavacProcessingEnvironment.java:364) >>> >>> at >>> com.sun.tools.javac.processing.JavacProcessingEnvironment$ServiceIterator.next(JavacProcessingEnvironment.java:325) >>> >>> at >>> com.sun.tools.javac.processing.JavacProcessingEnvironment$DiscoveredProcessors$ProcessorStateIterator.next(JavacProcessingEnvironment.java:597) >>> >>> at >>> com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:690) >>> >>> at >>> com.sun.tools.javac.processing.JavacProcessingEnvironment.access$1800(JavacProcessingEnvironment.java:91) >>> >>> at >>> com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1035) >>> >>> at >>> com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1176) >>> >>> at >>> com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1170) >>> >>> at >>> com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:856) >>> >>> at com.sun.tools.javac.main.Main.compile(Main.java:523) >>> >>> at com.sun.tools.javac.main.Main.compile(Main.java:381) >>> >>> at com.sun.tools.javac.main.Main.compile(Main.java:370) >>> >>> at com.sun.tools.javac.main.Main.compile(Main.java:361) >>> >>> at com.sun.tools.javac.Main.compile(Main.java:56) >>> >>> at com.sun.tools.javac.Main.main(Main.java:42) >>> >>> Caused by: java.lang.NoClassDefFoundError: >>> com/amazon/coral/util/reflection/AnnotatedManifestAnnotationProcessor >>> >>> at java.lang.ClassLoader.defineClass1(Native Method) >>> >>> at java.lang.ClassLoader.defineClass(ClassLoader.java:763) >>> >>> at >>> java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) >>> >>> at java.net.URLClassLoader.defineClass(URLClassLoader.java:467) >>> >>> at java.net.URLClassLoader.access$100(URLClassLoader.java:73) >>> >>> at java.net.URLClassLoader$1.run(URLClassLoader.java:368) >>> >>> at java.net.URLClassLoader$1.run(URLClassLoader.java:362) >>> >>> at java.security.AccessController.doPrivileged(Native Method) >>> >>> at java.net.URLClassLoader.findClass(URLClassLoader.java:361) >>> >>> at java.lang.ClassLoader.loadClass(ClassLoader.java:424) >>> >>> at java.lang.ClassLoader.loadClass(ClassLoader.java:357) >>> >>> at java.lang.Class.forName0(Native Method) >>> >>> at java.lang.Class.forName(Class.java:348) >>> >>> at >>> com.sun.tools.javac.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:255) >>> >>> at >>> com.sun.tools.javac.util.ServiceLoader$1.next(ServiceLoader.java:337) >>> >>> at >>> com.sun.tools.javac.processing.JavacProcessingEnvironment$ServiceIterator.next(JavacProcessingEnvironment.java:359) >>> >>> ... 14 more >>> >>> Caused by: java.lang.ClassNotFoundException: >>> com.amazon.coral.util.reflection.AnnotatedManifestAnnotationProcessor >>> >>> at java.net.URLClassLoader.findClass(URLClassLoader.java:381) >>> >>> at java.lang.ClassLoader.loadClass(ClassLoader.java:424) >>> >>> at java.lang.ClassLoader.loadClass(ClassLoader.java:357) >>> >>> *From: *Jonathan Gibbons >>> >>> *Date: *Tuesday, January 9, 2018 at 1:19 PM >>> *To: *"Schaef, Martin" >>> , "compiler-dev at openjdk.java.net" >>> >>> >>> >>> *Subject: *Re: Fixing JDK-8130493 >>> >>> What is the class triggering the ClassNotFoundException? >>> >>> If it is a user class not being found, it should be wrapped in a >>> ClientCodeException. If it is a javac class not being found, it >>> is reasonable to wrap it in an Abort. >>> >>> -- Jon >>> >>> On 1/9/18 9:52 AM, Schaef, Martin wrote: >>> >>> Hi, >>> >>> We have some users suffering from JDK-8130493 >>> (their >>> builds succeed, but the compiler actually failed). I did some >>> digging and the following sequence happens: >>> >>> A ClassNotFoundException is thrown in >>> JavaProcessingEnvironment.ServiceIterator.next() >>> >>> and re-thrown as an Abort. >>> >>> This Abort reaches JavaCompiler.processAnnotations() >>> >>> and is finally caught in JavaCompiler.compile() >>> >>> by >>> the following snippet: >>> >>> try { >>> >>> initProcessAnnotations(processors); >>> >>> // These method calls must be chained to avoid >>> memory leaks >>> >>> delegateCompiler = >>> >>> processAnnotations( //<<<<<< ABORT COMES OUT HERE >>> >>> enterTrees(stopIfError(CompileState.PARSE, >>> parseFiles(sourceFileObjects))), >>> >>> classnames); >>> >>> ? >>> >>> } catch (Abort ex) { >>> >>> if (devVerbose) >>> >>> ex.printStackTrace(System.err); >>> >>> } finally { >>> >>> and swallowed ... but it's printed if XDev is set. >>> >>> What is a proper way to fix this? Is it correct to wrap all >>> exceptions in JavaProcessingEnvironmentServiceIterator into >>> aborts? Or would it be better to distinguish different Aborts >>> in JavaCompiler.java? >>> >>> >>> >>> >>> >>> >>> >> From jan.lahoda at oracle.com Wed Jan 10 20:25:18 2018 From: jan.lahoda at oracle.com (Jan Lahoda) Date: Wed, 10 Jan 2018 21:25:18 +0100 Subject: Fixing JDK-8130493 In-Reply-To: <5A566431.30004@oracle.com> References: <91b1156a-6ec3-6717-4ce4-204258f2ce43@oracle.com> <95ED4B91-B07C-4275-B0F1-AA392CB8D5B4@amazon.com> <1341C4E9-1F39-400C-9F3C-31E28E606555@amazon.com> <506c86c4-a749-73c8-afa6-c05ccf8404a9@oracle.com> <9C1302C8-EE80-4866-96E8-B26F329B7104@amazon.com> <5A565050.6030707@oracle.com> <5A566431.30004@oracle.com> Message-ID: <5A5676AE.6030206@oracle.com> On 10.1.2018 20:06, Jonathan Gibbons wrote: > Jan, > > javac should not generate a stacktrace in this situation. This case is > about a bad class file, and so javac should generate an informative > message, in the family of "bad class file" or "class not found" messages. > > javac should only resort to stacktraces when code has crashed or > otherwise behaved unexpectedly, such that javac cannot provide a helpful > message. There are two sub-cases here ... the crash is in javac code or > libraries that it might call, in which case the message is, "oops, our > fault, please report a bug", or the crash is in user code, in which > case, the message is effectively, "it's your problem , not javac" (Especially for the exception from JDK-8130493.) I think this case is close to the "it's your problem , not javac" - the problem happens when the ServiceLoader tries to load a user's class into the VM (putting aside that it wasn't wrapped in the ServiceConfigurationError, as I'd expect based on the ServiceLoader javadoc) and it fails. So, while the specific stacktrace in the bug does not seem particularly useful, in other cases the exception may be useful for the user to diagnose the problem. I'd assume that this situation is fairly rare, and so I personally wouldn't mind more detailed output that could help to determine what is the cause of the problem. Jan > > -- Jon > > On 01/10/2018 09:41 AM, Jan Lahoda wrote: >> For a minimal change, I think it should be enough to change (in >> ServiceIterator) the existing: >> --- >> } catch (Throwable t) { >> throw new Abort(t); >> } >> --- >> to >> --- >> } catch (Throwable t) { >> throw new AnnotationProcessingError(t); >> } >> --- >> >> AnnotationProcessingError is handled both in JavacTaskImpl and >> com.sun.tools.javac.main.Main. For command line javac, this would get >> an output like: >> --- >> An annotation processor threw an uncaught exception. >> Consult the following stack trace for details. >> java.lang.ClassFormatError: Truncated class file >> [stacktrace] >> --- >> >> Which is in line with the behavior when -processor is used >> (NameProcessIterator). >> >> But I guess it would be good to improve consistency of error handling >> in JavacProcessingEnvironment at some point. >> >> Jan >> >> On 10.1.2018 18:23, Jonathan Gibbons wrote: >>> Why would you not just change >>> >>> >>> from >>> >>> } catch (Throwable t) { >>> >>> log.error("proc.service.problem"); >>> >>> throw new Abort(t); >>> >>> to >>> >>> } catch (Throwable t) { >>> >>> log.error("proc.service.problem"); >>> >>> throw new AnnotationProcessingError(t); >>> >>> >>> and then briefly, concisely, handle AnnotationProcessingError in >>> JavaCompiler. >>> >>> -- Jon >>> >>> >>> On 1/10/18 9:13 AM, Schaef, Martin wrote: >>>> >>>> I understand. The bare minimum that fixes the test cases would be to >>>> change the exception handling in the constructor of ServiceIterator: >>>> >>>> http://hg.openjdk.java.net/jdk8u/jdk8u/langtools/file/989188d1a978/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java#l340 >>>> >>>> >>>> and in ServiceIterator.next(): >>>> >>>> http://hg.openjdk.java.net/jdk8u/jdk8u/langtools/file/989188d1a978/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java#l363 >>>> >>>> >>>> from >>>> >>>> } catch (Throwable t) { >>>> >>>> log.error("proc.service.problem"); >>>> >>>> throw new Abort(t); >>>> >>>> to >>>> >>>> } catch (Exception t) { >>>> >>>> log.error("proc.service.problem"); >>>> >>>> throw new Abort(t); >>>> >>>> } catch (Throwable t) { >>>> >>>> log.error("Some error text"); >>>> >>>> throw new AnnotationProcessingError (t); >>>> >>>> With this change, the exit code of javac is 3 instead of 0. >>>> >>>> Does that sound like something you could support? If so, what should >>>> go in the log.error messages? >>>> >>>> Cheers, >>>> >>>> Martin >>>> >>>> *From: *Jonathan Gibbons >>>> *Date: *Wednesday, January 10, 2018 at 11:39 AM >>>> *To: *"Schaef, Martin" , >>>> "compiler-dev at openjdk.java.net" >>>> *Cc: *"Hohensee, Paul" >>>> *Subject: *Re: Fixing JDK-8130493 >>>> >>>> Martin, >>>> >>>> I have not read your patch, but changing the semantics of the iterator >>>> sounds like a step too far. >>>> >>>> Without trying to implement the following yet, I would expect the >>>> general direction of a solution to be to one of the following: >>>> >>>> 1. if the exception should be fatal, allow it to propagate up to >>>> JavaCompiler, (similar to as now) but maybe with a custom new wrapper >>>> exception >>>> >>>> 2. if the exception should not be fatal, translate it to an error >>>> message (log.error(...)) and continue. >>>> >>>> It probably needs more analysis and discussion to determine which of >>>> those two directions to take. >>>> >>>> -- Jon >>>> >>>> On 1/10/18 8:17 AM, Schaef, Martin wrote: >>>> >>>> Let me revise that: >>>> >>>> In JavacProcessingEnvironment.initProcessorIterator >>>> >>>> >>>> the code chooses one of two types of iterators: >>>> >>>> The NameProcessIterator >>>> >>>> >>>> if ther -processor flag is given or the ServiceIterator >>>> . >>>> >>>> >>>> If we look at the NameProcessIterator.hasNext() >>>> >>>> >>>> implementation, it checks if there is a next name AND checks if >>>> this class name can be loaded. That is, if the class is not >>>> present, the hasNext() method already returns false (or, in our >>>> case, throws the NoClassDefFoundError which gets wrapped into an >>>> AnnotationProcessingError). >>>> >>>> If we look at the ServiceIterator together with the stack trace >>>> from my previous email, we see that the .hasNext() and .next() >>>> calls get forwarded into the ServiceLoader.LazyIterator >>>> . >>>> >>>> This behaves different than the NameProcessIterator: hasNext() >>>> >>>> >>>> only checks if a next name exists and would not throw a >>>> NoClassDefFoundError. Then next() >>>> >>>> >>>> throws the NoClassDefFoundError which gets caught by the catch-all >>>> in JavaProcessingEnvironment.ServiceIterator.next() >>>> >>>> >>>> and wrapped into an Abort. >>>> >>>> So, to summarize: >>>> >>>> For a NameProcessIterator, a missing class causes a >>>> AnnotationProcessingError thrown from >>>> NameProcessIterator.hasNext() >>>> >>>> >>>> and for ServiceIterator, it causes a Abert thrown by >>>> JavaProcessingEnvironment.ServiceIterator.next() >>>> . >>>> >>>> >>>> I could fix my problem and JDK-8130493 >>>> by checking if >>>> the class can be loaded in the hasNext method and changing the >>>> exception handling in >>>> JavaProcessingEnvironment.ServiceIterator.next() >>>> . >>>> >>>> The problem with that is that the lazy iterator is not lazy >>>> anymore. Is there a reason why this Iterator has to be lazy? >>>> >>>> I attached a patch that solves the issue for me. Feedback would be >>>> great. >>>> >>>> Cheers, >>>> >>>> Martin >>>> >>>> *From: *compiler-dev >>>> on behalf of >>>> "Schaef, Martin" >>>> *Date: *Tuesday, January 9, 2018 at 3:37 PM >>>> *To: *Jonathan Gibbons >>>> , >>>> "compiler-dev at openjdk.java.net" >>>> >>>> >>>> >>>> *Subject: *Re: Fixing JDK-8130493 >>>> >>>> It?s a user class. See full stack trace below. >>>> >>>> The problem is that the ClassNotFound is already caught at >>>> com.sun.tools.javac.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:255) >>>> >>>> >>>> >>>> which already wraps it in a ServiceConfigurationError >>>> >>>> >>>> in the fail method. That is, the exception gets wrapped twice. >>>> First, LazyIterator.next wraps it in a ServieConfigurationError, >>>> then ServiceIterator.next wraps it in an Abort. >>>> >>>> Is it safe to change both wrappings? >>>> >>>> com.sun.tools.javac.util.Abort: java.lang.NoClassDefFoundError: >>>> com/amazon/coral/util/reflection/AnnotatedManifestAnnotationProcessor >>>> >>>> at >>>> com.sun.tools.javac.processing.JavacProcessingEnvironment$ServiceIterator.next(JavacProcessingEnvironment.java:364) >>>> >>>> >>>> at >>>> com.sun.tools.javac.processing.JavacProcessingEnvironment$ServiceIterator.next(JavacProcessingEnvironment.java:325) >>>> >>>> >>>> at >>>> com.sun.tools.javac.processing.JavacProcessingEnvironment$DiscoveredProcessors$ProcessorStateIterator.next(JavacProcessingEnvironment.java:597) >>>> >>>> >>>> at >>>> com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:690) >>>> >>>> >>>> at >>>> com.sun.tools.javac.processing.JavacProcessingEnvironment.access$1800(JavacProcessingEnvironment.java:91) >>>> >>>> >>>> at >>>> com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1035) >>>> >>>> >>>> at >>>> com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1176) >>>> >>>> >>>> at >>>> com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1170) >>>> >>>> >>>> at >>>> com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:856) >>>> >>>> at com.sun.tools.javac.main.Main.compile(Main.java:523) >>>> >>>> at com.sun.tools.javac.main.Main.compile(Main.java:381) >>>> >>>> at com.sun.tools.javac.main.Main.compile(Main.java:370) >>>> >>>> at com.sun.tools.javac.main.Main.compile(Main.java:361) >>>> >>>> at com.sun.tools.javac.Main.compile(Main.java:56) >>>> >>>> at com.sun.tools.javac.Main.main(Main.java:42) >>>> >>>> Caused by: java.lang.NoClassDefFoundError: >>>> com/amazon/coral/util/reflection/AnnotatedManifestAnnotationProcessor >>>> >>>> at java.lang.ClassLoader.defineClass1(Native Method) >>>> >>>> at java.lang.ClassLoader.defineClass(ClassLoader.java:763) >>>> >>>> at >>>> java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) >>>> >>>> at java.net.URLClassLoader.defineClass(URLClassLoader.java:467) >>>> >>>> at java.net.URLClassLoader.access$100(URLClassLoader.java:73) >>>> >>>> at java.net.URLClassLoader$1.run(URLClassLoader.java:368) >>>> >>>> at java.net.URLClassLoader$1.run(URLClassLoader.java:362) >>>> >>>> at java.security.AccessController.doPrivileged(Native Method) >>>> >>>> at java.net.URLClassLoader.findClass(URLClassLoader.java:361) >>>> >>>> at java.lang.ClassLoader.loadClass(ClassLoader.java:424) >>>> >>>> at java.lang.ClassLoader.loadClass(ClassLoader.java:357) >>>> >>>> at java.lang.Class.forName0(Native Method) >>>> >>>> at java.lang.Class.forName(Class.java:348) >>>> >>>> at >>>> com.sun.tools.javac.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:255) >>>> >>>> >>>> at >>>> com.sun.tools.javac.util.ServiceLoader$1.next(ServiceLoader.java:337) >>>> >>>> at >>>> com.sun.tools.javac.processing.JavacProcessingEnvironment$ServiceIterator.next(JavacProcessingEnvironment.java:359) >>>> >>>> >>>> ... 14 more >>>> >>>> Caused by: java.lang.ClassNotFoundException: >>>> com.amazon.coral.util.reflection.AnnotatedManifestAnnotationProcessor >>>> >>>> at java.net.URLClassLoader.findClass(URLClassLoader.java:381) >>>> >>>> at java.lang.ClassLoader.loadClass(ClassLoader.java:424) >>>> >>>> at java.lang.ClassLoader.loadClass(ClassLoader.java:357) >>>> >>>> *From: *Jonathan Gibbons >>>> >>>> *Date: *Tuesday, January 9, 2018 at 1:19 PM >>>> *To: *"Schaef, Martin" >>>> , "compiler-dev at openjdk.java.net" >>>> >>>> >>>> >>>> *Subject: *Re: Fixing JDK-8130493 >>>> >>>> What is the class triggering the ClassNotFoundException? >>>> >>>> If it is a user class not being found, it should be wrapped in a >>>> ClientCodeException. If it is a javac class not being found, it >>>> is reasonable to wrap it in an Abort. >>>> >>>> -- Jon >>>> >>>> On 1/9/18 9:52 AM, Schaef, Martin wrote: >>>> >>>> Hi, >>>> >>>> We have some users suffering from JDK-8130493 >>>> (their >>>> builds succeed, but the compiler actually failed). I did some >>>> digging and the following sequence happens: >>>> >>>> A ClassNotFoundException is thrown in >>>> JavaProcessingEnvironment.ServiceIterator.next() >>>> >>>> >>>> and re-thrown as an Abort. >>>> >>>> This Abort reaches JavaCompiler.processAnnotations() >>>> >>>> >>>> and is finally caught in JavaCompiler.compile() >>>> >>>> by >>>> the following snippet: >>>> >>>> try { >>>> >>>> initProcessAnnotations(processors); >>>> >>>> // These method calls must be chained to avoid >>>> memory leaks >>>> >>>> delegateCompiler = >>>> >>>> processAnnotations( //<<<<<< ABORT COMES OUT HERE >>>> >>>> enterTrees(stopIfError(CompileState.PARSE, >>>> parseFiles(sourceFileObjects))), >>>> >>>> classnames); >>>> >>>> ? >>>> >>>> } catch (Abort ex) { >>>> >>>> if (devVerbose) >>>> >>>> ex.printStackTrace(System.err); >>>> >>>> } finally { >>>> >>>> and swallowed ... but it's printed if XDev is set. >>>> >>>> What is a proper way to fix this? Is it correct to wrap all >>>> exceptions in JavaProcessingEnvironmentServiceIterator into >>>> aborts? Or would it be better to distinguish different Aborts >>>> in JavaCompiler.java? >>>> >>>> >>>> >>>> >>>> >>>> >>>> >>> > From jonathan.gibbons at oracle.com Wed Jan 10 21:46:27 2018 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Wed, 10 Jan 2018 13:46:27 -0800 Subject: RFR: JDK-8194893: javac -verbose prints wrong paths for output files Message-ID: <5A5689B3.9060400@oracle.com> Please review a trivial fix and test for the output from "javac -verbose". JBS: https://bugs.openjdk.java.net/browse/JDK-8194893 Webrev: http://cr.openjdk.java.net/~jjg/8194893/webrev.00/index.html -- Jon From jonathan.gibbons at oracle.com Wed Jan 10 22:43:00 2018 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Wed, 10 Jan 2018 14:43:00 -0800 Subject: Fixing JDK-8130493 In-Reply-To: <5A5676AE.6030206@oracle.com> References: <91b1156a-6ec3-6717-4ce4-204258f2ce43@oracle.com> <95ED4B91-B07C-4275-B0F1-AA392CB8D5B4@amazon.com> <1341C4E9-1F39-400C-9F3C-31E28E606555@amazon.com> <506c86c4-a749-73c8-afa6-c05ccf8404a9@oracle.com> <9C1302C8-EE80-4866-96E8-B26F329B7104@amazon.com> <5A565050.6030707@oracle.com> <5A566431.30004@oracle.com> <5A5676AE.6030206@oracle.com> Message-ID: <5A5696F4.30007@oracle.com> In this case, it's definitely the user's problem, because it's a bad class file being provided, but I don't think there's any merit in providing a stacktrace. It's not like there's an unexpected error such that it helps us or the user know where in the code the problem occurred. A clear message about the offending class (file) should be sufficient. This may mean we need catch blocks for recognized exceptions as well as better handling of Throwable. It's a strongly-related issue that there are instances of "throw new Abort" without a message. -- Jon On 01/10/2018 12:25 PM, Jan Lahoda wrote: > On 10.1.2018 20:06, Jonathan Gibbons wrote: >> Jan, >> >> javac should not generate a stacktrace in this situation. This case is >> about a bad class file, and so javac should generate an informative >> message, in the family of "bad class file" or "class not found" >> messages. >> >> javac should only resort to stacktraces when code has crashed or >> otherwise behaved unexpectedly, such that javac cannot provide a helpful >> message. There are two sub-cases here ... the crash is in javac code or >> libraries that it might call, in which case the message is, "oops, our >> fault, please report a bug", or the crash is in user code, in which >> case, the message is effectively, "it's your problem , not javac" > > (Especially for the exception from JDK-8130493.) I think this case is > close to the "it's your problem , not javac" - the problem happens > when the ServiceLoader tries to load a user's class into the VM > (putting aside that it wasn't wrapped in the > ServiceConfigurationError, as I'd expect based on the ServiceLoader > javadoc) and it fails. So, while the specific stacktrace in the bug > does not seem particularly useful, in other cases the exception may be > useful for the user to diagnose the problem. I'd assume that this > situation is fairly rare, and so I personally wouldn't mind more > detailed output that could help to determine what is the cause of the > problem. > > Jan > >> >> -- Jon >> >> On 01/10/2018 09:41 AM, Jan Lahoda wrote: >>> For a minimal change, I think it should be enough to change (in >>> ServiceIterator) the existing: >>> --- >>> } catch (Throwable t) { >>> throw new Abort(t); >>> } >>> --- >>> to >>> --- >>> } catch (Throwable t) { >>> throw new AnnotationProcessingError(t); >>> } >>> --- >>> >>> AnnotationProcessingError is handled both in JavacTaskImpl and >>> com.sun.tools.javac.main.Main. For command line javac, this would get >>> an output like: >>> --- >>> An annotation processor threw an uncaught exception. >>> Consult the following stack trace for details. >>> java.lang.ClassFormatError: Truncated class file >>> [stacktrace] >>> --- >>> >>> Which is in line with the behavior when -processor is used >>> (NameProcessIterator). >>> >>> But I guess it would be good to improve consistency of error handling >>> in JavacProcessingEnvironment at some point. >>> >>> Jan >>> >>> On 10.1.2018 18:23, Jonathan Gibbons wrote: >>>> Why would you not just change >>>> >>>> >>>> from >>>> >>>> } catch (Throwable t) { >>>> >>>> log.error("proc.service.problem"); >>>> >>>> throw new Abort(t); >>>> >>>> to >>>> >>>> } catch (Throwable t) { >>>> >>>> log.error("proc.service.problem"); >>>> >>>> throw new AnnotationProcessingError(t); >>>> >>>> >>>> and then briefly, concisely, handle AnnotationProcessingError in >>>> JavaCompiler. >>>> >>>> -- Jon >>>> >>>> >>>> On 1/10/18 9:13 AM, Schaef, Martin wrote: >>>>> >>>>> I understand. The bare minimum that fixes the test cases would be to >>>>> change the exception handling in the constructor of ServiceIterator: >>>>> >>>>> http://hg.openjdk.java.net/jdk8u/jdk8u/langtools/file/989188d1a978/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java#l340 >>>>> >>>>> >>>>> >>>>> and in ServiceIterator.next(): >>>>> >>>>> http://hg.openjdk.java.net/jdk8u/jdk8u/langtools/file/989188d1a978/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java#l363 >>>>> >>>>> >>>>> >>>>> from >>>>> >>>>> } catch (Throwable t) { >>>>> >>>>> log.error("proc.service.problem"); >>>>> >>>>> throw new Abort(t); >>>>> >>>>> to >>>>> >>>>> } catch (Exception t) { >>>>> >>>>> log.error("proc.service.problem"); >>>>> >>>>> throw new Abort(t); >>>>> >>>>> } catch (Throwable t) { >>>>> >>>>> log.error("Some error text"); >>>>> >>>>> throw new AnnotationProcessingError (t); >>>>> >>>>> With this change, the exit code of javac is 3 instead of 0. >>>>> >>>>> Does that sound like something you could support? If so, what should >>>>> go in the log.error messages? >>>>> >>>>> Cheers, >>>>> >>>>> Martin >>>>> >>>>> *From: *Jonathan Gibbons >>>>> *Date: *Wednesday, January 10, 2018 at 11:39 AM >>>>> *To: *"Schaef, Martin" , >>>>> "compiler-dev at openjdk.java.net" >>>>> *Cc: *"Hohensee, Paul" >>>>> *Subject: *Re: Fixing JDK-8130493 >>>>> >>>>> Martin, >>>>> >>>>> I have not read your patch, but changing the semantics of the >>>>> iterator >>>>> sounds like a step too far. >>>>> >>>>> Without trying to implement the following yet, I would expect the >>>>> general direction of a solution to be to one of the following: >>>>> >>>>> 1. if the exception should be fatal, allow it to propagate up to >>>>> JavaCompiler, (similar to as now) but maybe with a custom new wrapper >>>>> exception >>>>> >>>>> 2. if the exception should not be fatal, translate it to an error >>>>> message (log.error(...)) and continue. >>>>> >>>>> It probably needs more analysis and discussion to determine which of >>>>> those two directions to take. >>>>> >>>>> -- Jon >>>>> >>>>> On 1/10/18 8:17 AM, Schaef, Martin wrote: >>>>> >>>>> Let me revise that: >>>>> >>>>> In JavacProcessingEnvironment.initProcessorIterator >>>>> >>>>> >>>>> >>>>> the code chooses one of two types of iterators: >>>>> >>>>> The NameProcessIterator >>>>> >>>>> >>>>> >>>>> if ther -processor flag is given or the ServiceIterator >>>>> . >>>>> >>>>> >>>>> >>>>> If we look at the NameProcessIterator.hasNext() >>>>> >>>>> >>>>> >>>>> implementation, it checks if there is a next name AND checks if >>>>> this class name can be loaded. That is, if the class is not >>>>> present, the hasNext() method already returns false (or, in our >>>>> case, throws the NoClassDefFoundError which gets wrapped into an >>>>> AnnotationProcessingError). >>>>> >>>>> If we look at the ServiceIterator together with the stack trace >>>>> from my previous email, we see that the .hasNext() and .next() >>>>> calls get forwarded into the ServiceLoader.LazyIterator >>>>> . >>>>> >>>>> >>>>> This behaves different than the NameProcessIterator: hasNext() >>>>> >>>>> >>>>> >>>>> only checks if a next name exists and would not throw a >>>>> NoClassDefFoundError. Then next() >>>>> >>>>> >>>>> >>>>> throws the NoClassDefFoundError which gets caught by the >>>>> catch-all >>>>> in JavaProcessingEnvironment.ServiceIterator.next() >>>>> >>>>> >>>>> >>>>> and wrapped into an Abort. >>>>> >>>>> So, to summarize: >>>>> >>>>> For a NameProcessIterator, a missing class causes a >>>>> AnnotationProcessingError thrown from >>>>> NameProcessIterator.hasNext() >>>>> >>>>> >>>>> >>>>> and for ServiceIterator, it causes a Abert thrown by >>>>> JavaProcessingEnvironment.ServiceIterator.next() >>>>> . >>>>> >>>>> >>>>> >>>>> I could fix my problem and JDK-8130493 >>>>> by checking if >>>>> the class can be loaded in the hasNext method and changing the >>>>> exception handling in >>>>> JavaProcessingEnvironment.ServiceIterator.next() >>>>> . >>>>> >>>>> >>>>> The problem with that is that the lazy iterator is not lazy >>>>> anymore. Is there a reason why this Iterator has to be lazy? >>>>> >>>>> I attached a patch that solves the issue for me. Feedback >>>>> would be >>>>> great. >>>>> >>>>> Cheers, >>>>> >>>>> Martin >>>>> >>>>> *From: *compiler-dev >>>>> on behalf of >>>>> "Schaef, Martin" >>>>> *Date: *Tuesday, January 9, 2018 at 3:37 PM >>>>> *To: *Jonathan Gibbons >>>>> , >>>>> "compiler-dev at openjdk.java.net" >>>>> >>>>> >>>>> >>>>> *Subject: *Re: Fixing JDK-8130493 >>>>> >>>>> It?s a user class. See full stack trace below. >>>>> >>>>> The problem is that the ClassNotFound is already caught at >>>>> com.sun.tools.javac.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:255) >>>>> >>>>> >>>>> >>>>> >>>>> >>>>> which already wraps it in a ServiceConfigurationError >>>>> >>>>> >>>>> >>>>> in the fail method. That is, the exception gets wrapped twice. >>>>> First, LazyIterator.next wraps it in a ServieConfigurationError, >>>>> then ServiceIterator.next wraps it in an Abort. >>>>> >>>>> Is it safe to change both wrappings? >>>>> >>>>> com.sun.tools.javac.util.Abort: java.lang.NoClassDefFoundError: >>>>> com/amazon/coral/util/reflection/AnnotatedManifestAnnotationProcessor >>>>> >>>>> at >>>>> com.sun.tools.javac.processing.JavacProcessingEnvironment$ServiceIterator.next(JavacProcessingEnvironment.java:364) >>>>> >>>>> >>>>> >>>>> at >>>>> com.sun.tools.javac.processing.JavacProcessingEnvironment$ServiceIterator.next(JavacProcessingEnvironment.java:325) >>>>> >>>>> >>>>> >>>>> at >>>>> com.sun.tools.javac.processing.JavacProcessingEnvironment$DiscoveredProcessors$ProcessorStateIterator.next(JavacProcessingEnvironment.java:597) >>>>> >>>>> >>>>> >>>>> at >>>>> com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:690) >>>>> >>>>> >>>>> >>>>> at >>>>> com.sun.tools.javac.processing.JavacProcessingEnvironment.access$1800(JavacProcessingEnvironment.java:91) >>>>> >>>>> >>>>> >>>>> at >>>>> com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1035) >>>>> >>>>> >>>>> >>>>> at >>>>> com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1176) >>>>> >>>>> >>>>> >>>>> at >>>>> com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1170) >>>>> >>>>> >>>>> >>>>> at >>>>> com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:856) >>>>> >>>>> at com.sun.tools.javac.main.Main.compile(Main.java:523) >>>>> >>>>> at com.sun.tools.javac.main.Main.compile(Main.java:381) >>>>> >>>>> at com.sun.tools.javac.main.Main.compile(Main.java:370) >>>>> >>>>> at com.sun.tools.javac.main.Main.compile(Main.java:361) >>>>> >>>>> at com.sun.tools.javac.Main.compile(Main.java:56) >>>>> >>>>> at com.sun.tools.javac.Main.main(Main.java:42) >>>>> >>>>> Caused by: java.lang.NoClassDefFoundError: >>>>> com/amazon/coral/util/reflection/AnnotatedManifestAnnotationProcessor >>>>> >>>>> at java.lang.ClassLoader.defineClass1(Native Method) >>>>> >>>>> at java.lang.ClassLoader.defineClass(ClassLoader.java:763) >>>>> >>>>> at >>>>> java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) >>>>> >>>>> >>>>> at >>>>> java.net.URLClassLoader.defineClass(URLClassLoader.java:467) >>>>> >>>>> at java.net.URLClassLoader.access$100(URLClassLoader.java:73) >>>>> >>>>> at java.net.URLClassLoader$1.run(URLClassLoader.java:368) >>>>> >>>>> at java.net.URLClassLoader$1.run(URLClassLoader.java:362) >>>>> >>>>> at java.security.AccessController.doPrivileged(Native Method) >>>>> >>>>> at java.net.URLClassLoader.findClass(URLClassLoader.java:361) >>>>> >>>>> at java.lang.ClassLoader.loadClass(ClassLoader.java:424) >>>>> >>>>> at java.lang.ClassLoader.loadClass(ClassLoader.java:357) >>>>> >>>>> at java.lang.Class.forName0(Native Method) >>>>> >>>>> at java.lang.Class.forName(Class.java:348) >>>>> >>>>> at >>>>> com.sun.tools.javac.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:255) >>>>> >>>>> >>>>> >>>>> at >>>>> com.sun.tools.javac.util.ServiceLoader$1.next(ServiceLoader.java:337) >>>>> >>>>> at >>>>> com.sun.tools.javac.processing.JavacProcessingEnvironment$ServiceIterator.next(JavacProcessingEnvironment.java:359) >>>>> >>>>> >>>>> >>>>> ... 14 more >>>>> >>>>> Caused by: java.lang.ClassNotFoundException: >>>>> com.amazon.coral.util.reflection.AnnotatedManifestAnnotationProcessor >>>>> >>>>> at java.net.URLClassLoader.findClass(URLClassLoader.java:381) >>>>> >>>>> at java.lang.ClassLoader.loadClass(ClassLoader.java:424) >>>>> >>>>> at java.lang.ClassLoader.loadClass(ClassLoader.java:357) >>>>> >>>>> *From: *Jonathan Gibbons >>>>> >>>>> *Date: *Tuesday, January 9, 2018 at 1:19 PM >>>>> *To: *"Schaef, Martin" >>>>> , "compiler-dev at openjdk.java.net" >>>>> >>>>> >>>>> >>>>> *Subject: *Re: Fixing JDK-8130493 >>>>> >>>>> What is the class triggering the ClassNotFoundException? >>>>> >>>>> If it is a user class not being found, it should be wrapped in a >>>>> ClientCodeException. If it is a javac class not being found, it >>>>> is reasonable to wrap it in an Abort. >>>>> >>>>> -- Jon >>>>> >>>>> On 1/9/18 9:52 AM, Schaef, Martin wrote: >>>>> >>>>> Hi, >>>>> >>>>> We have some users suffering from JDK-8130493 >>>>> (their >>>>> builds succeed, but the compiler actually failed). I did some >>>>> digging and the following sequence happens: >>>>> >>>>> A ClassNotFoundException is thrown in >>>>> JavaProcessingEnvironment.ServiceIterator.next() >>>>> >>>>> >>>>> >>>>> and re-thrown as an Abort. >>>>> >>>>> This Abort reaches JavaCompiler.processAnnotations() >>>>> >>>>> >>>>> >>>>> and is finally caught in JavaCompiler.compile() >>>>> >>>>> >>>>> by >>>>> the following snippet: >>>>> >>>>> try { >>>>> >>>>> initProcessAnnotations(processors); >>>>> >>>>> // These method calls must be chained to avoid >>>>> memory leaks >>>>> >>>>> delegateCompiler = >>>>> >>>>> processAnnotations( //<<<<<< ABORT COMES OUT HERE >>>>> >>>>> enterTrees(stopIfError(CompileState.PARSE, >>>>> parseFiles(sourceFileObjects))), >>>>> >>>>> classnames); >>>>> >>>>> ? >>>>> >>>>> } catch (Abort ex) { >>>>> >>>>> if (devVerbose) >>>>> >>>>> ex.printStackTrace(System.err); >>>>> >>>>> } finally { >>>>> >>>>> and swallowed ... but it's printed if XDev is set. >>>>> >>>>> What is a proper way to fix this? Is it correct to wrap all >>>>> exceptions in JavaProcessingEnvironmentServiceIterator into >>>>> aborts? Or would it be better to distinguish different Aborts >>>>> in JavaCompiler.java? >>>>> >>>>> >>>>> >>>>> >>>>> >>>>> >>>>> >>>> >> From jonathan.gibbons at oracle.com Wed Jan 10 22:57:55 2018 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Wed, 10 Jan 2018 14:57:55 -0800 Subject: RFR: JDK-8194901: remove interim code from javax.tools.ToolProvider In-Reply-To: <5A553697.9040504@oracle.com> References: <5A553697.9040504@oracle.com> Message-ID: <5A569A73.3000804@oracle.com> This is a subset of an earlier review, the remainder of which has been deferred to JDK 11, pending design and spec clarifications. This review just removes some interim code that was necessary in JDK 9. JBS: https://bugs.openjdk.java.net/browse/JDK-8194901 Webrev: http://cr.openjdk.java.net/~jjg/8194901/webrev.00/ -- Jon From mandy.chung at oracle.com Wed Jan 10 23:03:14 2018 From: mandy.chung at oracle.com (mandy chung) Date: Wed, 10 Jan 2018 15:03:14 -0800 Subject: RFR: JDK-8194901: remove interim code from javax.tools.ToolProvider In-Reply-To: <5A569A73.3000804@oracle.com> References: <5A553697.9040504@oracle.com> <5A569A73.3000804@oracle.com> Message-ID: <514cd4ab-2f55-5710-b128-5a7a7c80ba19@oracle.com> On 1/10/18 2:57 PM, Jonathan Gibbons wrote: > This is a subset of an earlier review, the remainder of which has been > deferred to JDK 11, > pending design and spec clarifications. > > This review just removes some interim code that was necessary in JDK 9. > > JBS: https://bugs.openjdk.java.net/browse/JDK-8194901 > Webrev: http://cr.openjdk.java.net/~jjg/8194901/webrev.00/ > Looks good. Mandy -------------- next part -------------- An HTML attachment was scrubbed... URL: From schaef at amazon.com Wed Jan 10 23:29:43 2018 From: schaef at amazon.com (Schaef, Martin) Date: Wed, 10 Jan 2018 23:29:43 +0000 Subject: Fixing JDK-8130493 In-Reply-To: <5A5696F4.30007@oracle.com> References: <91b1156a-6ec3-6717-4ce4-204258f2ce43@oracle.com> <95ED4B91-B07C-4275-B0F1-AA392CB8D5B4@amazon.com> <1341C4E9-1F39-400C-9F3C-31E28E606555@amazon.com> <506c86c4-a749-73c8-afa6-c05ccf8404a9@oracle.com> <9C1302C8-EE80-4866-96E8-B26F329B7104@amazon.com> <5A565050.6030707@oracle.com> <5A566431.30004@oracle.com> <5A5676AE.6030206@oracle.com> <5A5696F4.30007@oracle.com> Message-ID: Fwiw, in the old code, Main already catches AnnotationProcessingErrors: http://hg.openjdk.java.net/jdk8u/jdk8u/langtools/file/989188d1a978/src/share/classes/com/sun/tools/javac/main/Main.java#l551 But they don?t make it there because of the issue we discussed that Errors get swallowed and turned into Aborts which get swallowed here: http://hg.openjdk.java.net/jdk8u/jdk8u/langtools/file/989188d1a978/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java#l863 However, AnnotationProcessingErrors do print a stacktrace, so its not perfect either. On 1/10/18, 5:43 PM, "Jonathan Gibbons" wrote: In this case, it's definitely the user's problem, because it's a bad class file being provided, but I don't think there's any merit in providing a stacktrace. It's not like there's an unexpected error such that it helps us or the user know where in the code the problem occurred. A clear message about the offending class (file) should be sufficient. This may mean we need catch blocks for recognized exceptions as well as better handling of Throwable. It's a strongly-related issue that there are instances of "throw new Abort" without a message. -- Jon On 01/10/2018 12:25 PM, Jan Lahoda wrote: > On 10.1.2018 20:06, Jonathan Gibbons wrote: >> Jan, >> >> javac should not generate a stacktrace in this situation. This case is >> about a bad class file, and so javac should generate an informative >> message, in the family of "bad class file" or "class not found" >> messages. >> >> javac should only resort to stacktraces when code has crashed or >> otherwise behaved unexpectedly, such that javac cannot provide a helpful >> message. There are two sub-cases here ... the crash is in javac code or >> libraries that it might call, in which case the message is, "oops, our >> fault, please report a bug", or the crash is in user code, in which >> case, the message is effectively, "it's your problem , not javac" > > (Especially for the exception from JDK-8130493.) I think this case is > close to the "it's your problem , not javac" - the problem happens > when the ServiceLoader tries to load a user's class into the VM > (putting aside that it wasn't wrapped in the > ServiceConfigurationError, as I'd expect based on the ServiceLoader > javadoc) and it fails. So, while the specific stacktrace in the bug > does not seem particularly useful, in other cases the exception may be > useful for the user to diagnose the problem. I'd assume that this > situation is fairly rare, and so I personally wouldn't mind more > detailed output that could help to determine what is the cause of the > problem. > > Jan > >> >> -- Jon >> >> On 01/10/2018 09:41 AM, Jan Lahoda wrote: >>> For a minimal change, I think it should be enough to change (in >>> ServiceIterator) the existing: >>> --- >>> } catch (Throwable t) { >>> throw new Abort(t); >>> } >>> --- >>> to >>> --- >>> } catch (Throwable t) { >>> throw new AnnotationProcessingError(t); >>> } >>> --- >>> >>> AnnotationProcessingError is handled both in JavacTaskImpl and >>> com.sun.tools.javac.main.Main. For command line javac, this would get >>> an output like: >>> --- >>> An annotation processor threw an uncaught exception. >>> Consult the following stack trace for details. >>> java.lang.ClassFormatError: Truncated class file >>> [stacktrace] >>> --- >>> >>> Which is in line with the behavior when -processor is used >>> (NameProcessIterator). >>> >>> But I guess it would be good to improve consistency of error handling >>> in JavacProcessingEnvironment at some point. >>> >>> Jan >>> >>> On 10.1.2018 18:23, Jonathan Gibbons wrote: >>>> Why would you not just change >>>> >>>> >>>> from >>>> >>>> } catch (Throwable t) { >>>> >>>> log.error("proc.service.problem"); >>>> >>>> throw new Abort(t); >>>> >>>> to >>>> >>>> } catch (Throwable t) { >>>> >>>> log.error("proc.service.problem"); >>>> >>>> throw new AnnotationProcessingError(t); >>>> >>>> >>>> and then briefly, concisely, handle AnnotationProcessingError in >>>> JavaCompiler. >>>> >>>> -- Jon >>>> >>>> >>>> On 1/10/18 9:13 AM, Schaef, Martin wrote: >>>>> >>>>> I understand. The bare minimum that fixes the test cases would be to >>>>> change the exception handling in the constructor of ServiceIterator: >>>>> >>>>> http://hg.openjdk.java.net/jdk8u/jdk8u/langtools/file/989188d1a978/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java#l340 >>>>> >>>>> >>>>> >>>>> and in ServiceIterator.next(): >>>>> >>>>> http://hg.openjdk.java.net/jdk8u/jdk8u/langtools/file/989188d1a978/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java#l363 >>>>> >>>>> >>>>> >>>>> from >>>>> >>>>> } catch (Throwable t) { >>>>> >>>>> log.error("proc.service.problem"); >>>>> >>>>> throw new Abort(t); >>>>> >>>>> to >>>>> >>>>> } catch (Exception t) { >>>>> >>>>> log.error("proc.service.problem"); >>>>> >>>>> throw new Abort(t); >>>>> >>>>> } catch (Throwable t) { >>>>> >>>>> log.error("Some error text"); >>>>> >>>>> throw new AnnotationProcessingError (t); >>>>> >>>>> With this change, the exit code of javac is 3 instead of 0. >>>>> >>>>> Does that sound like something you could support? If so, what should >>>>> go in the log.error messages? >>>>> >>>>> Cheers, >>>>> >>>>> Martin >>>>> >>>>> *From: *Jonathan Gibbons >>>>> *Date: *Wednesday, January 10, 2018 at 11:39 AM >>>>> *To: *"Schaef, Martin" , >>>>> "compiler-dev at openjdk.java.net" >>>>> *Cc: *"Hohensee, Paul" >>>>> *Subject: *Re: Fixing JDK-8130493 >>>>> >>>>> Martin, >>>>> >>>>> I have not read your patch, but changing the semantics of the >>>>> iterator >>>>> sounds like a step too far. >>>>> >>>>> Without trying to implement the following yet, I would expect the >>>>> general direction of a solution to be to one of the following: >>>>> >>>>> 1. if the exception should be fatal, allow it to propagate up to >>>>> JavaCompiler, (similar to as now) but maybe with a custom new wrapper >>>>> exception >>>>> >>>>> 2. if the exception should not be fatal, translate it to an error >>>>> message (log.error(...)) and continue. >>>>> >>>>> It probably needs more analysis and discussion to determine which of >>>>> those two directions to take. >>>>> >>>>> -- Jon >>>>> >>>>> On 1/10/18 8:17 AM, Schaef, Martin wrote: >>>>> >>>>> Let me revise that: >>>>> >>>>> In JavacProcessingEnvironment.initProcessorIterator >>>>> >>>>> >>>>> >>>>> the code chooses one of two types of iterators: >>>>> >>>>> The NameProcessIterator >>>>> >>>>> >>>>> >>>>> if ther -processor flag is given or the ServiceIterator >>>>> . >>>>> >>>>> >>>>> >>>>> If we look at the NameProcessIterator.hasNext() >>>>> >>>>> >>>>> >>>>> implementation, it checks if there is a next name AND checks if >>>>> this class name can be loaded. That is, if the class is not >>>>> present, the hasNext() method already returns false (or, in our >>>>> case, throws the NoClassDefFoundError which gets wrapped into an >>>>> AnnotationProcessingError). >>>>> >>>>> If we look at the ServiceIterator together with the stack trace >>>>> from my previous email, we see that the .hasNext() and .next() >>>>> calls get forwarded into the ServiceLoader.LazyIterator >>>>> . >>>>> >>>>> >>>>> This behaves different than the NameProcessIterator: hasNext() >>>>> >>>>> >>>>> >>>>> only checks if a next name exists and would not throw a >>>>> NoClassDefFoundError. Then next() >>>>> >>>>> >>>>> >>>>> throws the NoClassDefFoundError which gets caught by the >>>>> catch-all >>>>> in JavaProcessingEnvironment.ServiceIterator.next() >>>>> >>>>> >>>>> >>>>> and wrapped into an Abort. >>>>> >>>>> So, to summarize: >>>>> >>>>> For a NameProcessIterator, a missing class causes a >>>>> AnnotationProcessingError thrown from >>>>> NameProcessIterator.hasNext() >>>>> >>>>> >>>>> >>>>> and for ServiceIterator, it causes a Abert thrown by >>>>> JavaProcessingEnvironment.ServiceIterator.next() >>>>> . >>>>> >>>>> >>>>> >>>>> I could fix my problem and JDK-8130493 >>>>> by checking if >>>>> the class can be loaded in the hasNext method and changing the >>>>> exception handling in >>>>> JavaProcessingEnvironment.ServiceIterator.next() >>>>> . >>>>> >>>>> >>>>> The problem with that is that the lazy iterator is not lazy >>>>> anymore. Is there a reason why this Iterator has to be lazy? >>>>> >>>>> I attached a patch that solves the issue for me. Feedback >>>>> would be >>>>> great. >>>>> >>>>> Cheers, >>>>> >>>>> Martin >>>>> >>>>> *From: *compiler-dev >>>>> on behalf of >>>>> "Schaef, Martin" >>>>> *Date: *Tuesday, January 9, 2018 at 3:37 PM >>>>> *To: *Jonathan Gibbons >>>>> , >>>>> "compiler-dev at openjdk.java.net" >>>>> >>>>> >>>>> >>>>> *Subject: *Re: Fixing JDK-8130493 >>>>> >>>>> It?s a user class. See full stack trace below. >>>>> >>>>> The problem is that the ClassNotFound is already caught at >>>>> com.sun.tools.javac.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:255) >>>>> >>>>> >>>>> >>>>> >>>>> >>>>> which already wraps it in a ServiceConfigurationError >>>>> >>>>> >>>>> >>>>> in the fail method. That is, the exception gets wrapped twice. >>>>> First, LazyIterator.next wraps it in a ServieConfigurationError, >>>>> then ServiceIterator.next wraps it in an Abort. >>>>> >>>>> Is it safe to change both wrappings? >>>>> >>>>> com.sun.tools.javac.util.Abort: java.lang.NoClassDefFoundError: >>>>> com/amazon/coral/util/reflection/AnnotatedManifestAnnotationProcessor >>>>> >>>>> at >>>>> com.sun.tools.javac.processing.JavacProcessingEnvironment$ServiceIterator.next(JavacProcessingEnvironment.java:364) >>>>> >>>>> >>>>> >>>>> at >>>>> com.sun.tools.javac.processing.JavacProcessingEnvironment$ServiceIterator.next(JavacProcessingEnvironment.java:325) >>>>> >>>>> >>>>> >>>>> at >>>>> com.sun.tools.javac.processing.JavacProcessingEnvironment$DiscoveredProcessors$ProcessorStateIterator.next(JavacProcessingEnvironment.java:597) >>>>> >>>>> >>>>> >>>>> at >>>>> com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:690) >>>>> >>>>> >>>>> >>>>> at >>>>> com.sun.tools.javac.processing.JavacProcessingEnvironment.access$1800(JavacProcessingEnvironment.java:91) >>>>> >>>>> >>>>> >>>>> at >>>>> com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1035) >>>>> >>>>> >>>>> >>>>> at >>>>> com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1176) >>>>> >>>>> >>>>> >>>>> at >>>>> com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1170) >>>>> >>>>> >>>>> >>>>> at >>>>> com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:856) >>>>> >>>>> at com.sun.tools.javac.main.Main.compile(Main.java:523) >>>>> >>>>> at com.sun.tools.javac.main.Main.compile(Main.java:381) >>>>> >>>>> at com.sun.tools.javac.main.Main.compile(Main.java:370) >>>>> >>>>> at com.sun.tools.javac.main.Main.compile(Main.java:361) >>>>> >>>>> at com.sun.tools.javac.Main.compile(Main.java:56) >>>>> >>>>> at com.sun.tools.javac.Main.main(Main.java:42) >>>>> >>>>> Caused by: java.lang.NoClassDefFoundError: >>>>> com/amazon/coral/util/reflection/AnnotatedManifestAnnotationProcessor >>>>> >>>>> at java.lang.ClassLoader.defineClass1(Native Method) >>>>> >>>>> at java.lang.ClassLoader.defineClass(ClassLoader.java:763) >>>>> >>>>> at >>>>> java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) >>>>> >>>>> >>>>> at >>>>> java.net.URLClassLoader.defineClass(URLClassLoader.java:467) >>>>> >>>>> at java.net.URLClassLoader.access$100(URLClassLoader.java:73) >>>>> >>>>> at java.net.URLClassLoader$1.run(URLClassLoader.java:368) >>>>> >>>>> at java.net.URLClassLoader$1.run(URLClassLoader.java:362) >>>>> >>>>> at java.security.AccessController.doPrivileged(Native Method) >>>>> >>>>> at java.net.URLClassLoader.findClass(URLClassLoader.java:361) >>>>> >>>>> at java.lang.ClassLoader.loadClass(ClassLoader.java:424) >>>>> >>>>> at java.lang.ClassLoader.loadClass(ClassLoader.java:357) >>>>> >>>>> at java.lang.Class.forName0(Native Method) >>>>> >>>>> at java.lang.Class.forName(Class.java:348) >>>>> >>>>> at >>>>> com.sun.tools.javac.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:255) >>>>> >>>>> >>>>> >>>>> at >>>>> com.sun.tools.javac.util.ServiceLoader$1.next(ServiceLoader.java:337) >>>>> >>>>> at >>>>> com.sun.tools.javac.processing.JavacProcessingEnvironment$ServiceIterator.next(JavacProcessingEnvironment.java:359) >>>>> >>>>> >>>>> >>>>> ... 14 more >>>>> >>>>> Caused by: java.lang.ClassNotFoundException: >>>>> com.amazon.coral.util.reflection.AnnotatedManifestAnnotationProcessor >>>>> >>>>> at java.net.URLClassLoader.findClass(URLClassLoader.java:381) >>>>> >>>>> at java.lang.ClassLoader.loadClass(ClassLoader.java:424) >>>>> >>>>> at java.lang.ClassLoader.loadClass(ClassLoader.java:357) >>>>> >>>>> *From: *Jonathan Gibbons >>>>> >>>>> *Date: *Tuesday, January 9, 2018 at 1:19 PM >>>>> *To: *"Schaef, Martin" >>>>> , "compiler-dev at openjdk.java.net" >>>>> >>>>> >>>>> >>>>> *Subject: *Re: Fixing JDK-8130493 >>>>> >>>>> What is the class triggering the ClassNotFoundException? >>>>> >>>>> If it is a user class not being found, it should be wrapped in a >>>>> ClientCodeException. If it is a javac class not being found, it >>>>> is reasonable to wrap it in an Abort. >>>>> >>>>> -- Jon >>>>> >>>>> On 1/9/18 9:52 AM, Schaef, Martin wrote: >>>>> >>>>> Hi, >>>>> >>>>> We have some users suffering from JDK-8130493 >>>>> (their >>>>> builds succeed, but the compiler actually failed). I did some >>>>> digging and the following sequence happens: >>>>> >>>>> A ClassNotFoundException is thrown in >>>>> JavaProcessingEnvironment.ServiceIterator.next() >>>>> >>>>> >>>>> >>>>> and re-thrown as an Abort. >>>>> >>>>> This Abort reaches JavaCompiler.processAnnotations() >>>>> >>>>> >>>>> >>>>> and is finally caught in JavaCompiler.compile() >>>>> >>>>> >>>>> by >>>>> the following snippet: >>>>> >>>>> try { >>>>> >>>>> initProcessAnnotations(processors); >>>>> >>>>> // These method calls must be chained to avoid >>>>> memory leaks >>>>> >>>>> delegateCompiler = >>>>> >>>>> processAnnotations( //<<<<<< ABORT COMES OUT HERE >>>>> >>>>> enterTrees(stopIfError(CompileState.PARSE, >>>>> parseFiles(sourceFileObjects))), >>>>> >>>>> classnames); >>>>> >>>>> ? >>>>> >>>>> } catch (Abort ex) { >>>>> >>>>> if (devVerbose) >>>>> >>>>> ex.printStackTrace(System.err); >>>>> >>>>> } finally { >>>>> >>>>> and swallowed ... but it's printed if XDev is set. >>>>> >>>>> What is a proper way to fix this? Is it correct to wrap all >>>>> exceptions in JavaProcessingEnvironmentServiceIterator into >>>>> aborts? Or would it be better to distinguish different Aborts >>>>> in JavaCompiler.java? >>>>> >>>>> >>>>> >>>>> >>>>> >>>>> >>>>> >>>> >> From jonathan.gibbons at oracle.com Thu Jan 11 00:34:33 2018 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Wed, 10 Jan 2018 16:34:33 -0800 Subject: RFR: JDK-8151850: eliminate javax.tools.FileManagerUtils Message-ID: <5A56B119.1090009@oracle.com> Please review a simple cleanup fix, that uses private interface methods to replace the use of a package-private class, that was previously necessary. JBS: https://bugs.openjdk.java.net/browse/JDK-8151850 Webrev: http://cr.openjdk.java.net/~jjg/8151850/webrev.00/ -- Jon From ogierke at pivotal.io Thu Jan 11 09:10:29 2018 From: ogierke at pivotal.io (Oliver Gierke) Date: Thu, 11 Jan 2018 10:10:29 +0100 Subject: Issues with generic type detection of SAM types implemented using lambdas In-Reply-To: <63C94B5C-4E18-4500-9203-15408B98D5EA@pivotal.io> References: <4E1C251C-163A-4093-855F-CEDC043B8524@pivotal.io> <63C94B5C-4E18-4500-9203-15408B98D5EA@pivotal.io> Message-ID: <997D0DBE-4E96-446B-94D7-2800187622E5@pivotal.io> Hi all, I hate to bring this up again but as the adoption of Java 8 is growing significantly, this problem now comes up at least every other week and I can really understand the pain of our users. Find one example here [0]. Is there really no chance this is ever going to change? Cheers, Ollie [0] https://github.com/spring-projects/spring-hateoas/issues/688 > Am 19.01.2017 um 08:40 schrieb Oliver Gierke : > > Hi Maurizio, > > thanks again for you in-depth explanation. I get all that and the design considerations behind the decisions that were made. I just wanted to point out that an ordinary user -- in general client code that uses APIs with SAM types -- *has to implicitly know* whether *any code* (potentially Java 6 based) downstream might attempt generics resolution before she can decide whether to use a Lambda with this SAM type. > > I think that's a very fundamental usability problem because it doesn't even need some arbitrary corner case. If there's a piece of code attempting the resolution anywhere downstream, it just won't work. Never. The only similar scenario (in terms of some parts of the reflection API not working as others) I remember is debug symbols on interface methods. That was changed in Java 8 with the -parameters flag. So I thought, it might be worth bringing this one up here as maybe the context has or will have changed for Java 9 / 10. > > Cheers, > Ollie > >> Am 19.01.2017 um 02:52 schrieb Maurizio Cimadamore : >> >> Hi Oliver, >> this request seems to be similar to other requests expressed in the past: >> >> Signature attribute on lambda method: >> >> http://mail.openjdk.java.net/pipermail/compiler-dev/2015-January/009220.html >> >> Annotations on lambdas: >> >> http://mail.openjdk.java.net/pipermail/compiler-dev/2015-July/009662.html >> >> >> The recurring theme is that we don't want to make promises on implementation details - that is how is a lambda implemented. For now, a lambda is implemented as a (dynamically generated) anonymous class instance - so certain requests seem to make sense. But as the implementation will get better at sharing, having to expose details such as signature attributes and such will become an obstacle to further improvements. >> >> For instance, the runtime does NOT have to distinguish between a Supplier and a Supplier - example: >> >> class Test { >> void test() { >> Supplier ss = this::m; >> Supplier si = this::m; >> } >> >> String m() { return ""; } >> } >> >> This gives the following bytceode: >> >> void test(); >> descriptor: ()V >> flags: >> Code: >> stack=1, locals=3, args_size=1 >> 0: aload_0 >> 1: invokedynamic #2, 0 // InvokeDynamic #0:get:(LTest;)Ljava/util/function/Supplier; >> 6: astore_1 >> 7: aload_0 >> 8: invokedynamic #3, 0 // InvokeDynamic #1:get:(LTest;)Ljava/util/function/Supplier; >> 13: astore_2 >> 14: return >> >> BootstrapMethods: >> 0: #18 invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; >> Method arguments: >> #19 ()Ljava/lang/Object; >> #20 invokevirtual Test.m:()Ljava/lang/String; >> #21 ()Ljava/lang/String; >> 1: #18 invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; >> Method arguments: >> #19 ()Ljava/lang/Object; >> #20 invokevirtual Test.m:()Ljava/lang/String; >> #19 ()Ljava/lang/Object; >> >> >> As you can see, both invokedynamic share the same SAM type - the erased java/util/function/Supplier. The only difference between the two indys is the method type passed as 3rd static argument - in one case ()String is passed, in the other ()Object is passed - that dictates the signature of the dynamically generated method implementing the sam type. >> >> In other words, if the lambda metafactory used the same instance for both method references, everything would still work (in fact, the generated bytecode is the same for both classes!). >> >> Maurizio >> >> >> >> On 18/01/17 18:06, Oliver Gierke wrote: >>> Hi again, >>> >>> didn't get much response but it looks like there are some improvements for lambdas planned for at least JDK10 [0]. Is what I asked for below maybe a candidate for inclusion into those efforts? >>> >>> Is there maybe a better place to ask for this? >>> >>> Cheers, >>> Ollie >>> >>> [0] https://www.infoq.com/news/2017/01/java10-lambda-leftovers >>> >>>> Am 23.12.2016 um 12:22 schrieb Oliver Gierke : >>>> >>>> Hi all, >>>> >>>> Lambda based implementations of SAM types currently don't support inspecting the type for generic type parameters. This can cause unexpected surprise as some high-level API taking a SAM type as parameter is usually an indicator to users, that they can be used with Lambdas. If the object passed in is then inspected for generic types somewhere down the call stack this causes issues. Handing in a dedicated implementation of the SAM type is a workaround bit I think that's highly confusing and can be a source of errors hard to understand and debug. >>>> >>>> I've added an example below. >>>> >>>> Cheers, >>>> Ollie >>>> >>>> public class LambdaTypeDetectionSample { >>>> >>>> public static void main(String[] args) { >>>> >>>> Function lambdaFunction = i -> i.toString(); >>>> Function oldschoolFunction = new Function() { >>>> >>>> public String apply(Integer t) { >>>> return t.toString(); >>>> } >>>> }; >>>> >>>> printTypeArguments(oldschoolFunction); >>>> >>>> // Yields: >>>> // java.util.function.Function is a class sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl >>>> // class java.lang.Integer >>>> // class java.lang.String >>>> >>>> printTypeArguments(lambdaFunction); >>>> >>>> // Yields: >>>> // interface java.util.function.Function is a class java.lang.Class >>>> } >>>> >>>> private static void printTypeArguments(Function function) { >>>> >>>> Type type = function.getClass().getGenericInterfaces()[0]; >>>> >>>> System.out.println(type + " is a " + type.getClass()); >>>> >>>> if (type instanceof ParameterizedType) { >>>> >>>> ParameterizedType functionInterface = (ParameterizedType) type; >>>> Arrays.stream(functionInterface.getActualTypeArguments()).forEach(System.out::println); >>>> } >>>> } >>>> } >> > -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: Message signed with OpenPGP URL: From maurizio.cimadamore at oracle.com Thu Jan 11 11:18:34 2018 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 11 Jan 2018 11:18:34 +0000 Subject: Issues with generic type detection of SAM types implemented using lambdas In-Reply-To: <997D0DBE-4E96-446B-94D7-2800187622E5@pivotal.io> References: <4E1C251C-163A-4093-855F-CEDC043B8524@pivotal.io> <63C94B5C-4E18-4500-9203-15408B98D5EA@pivotal.io> <997D0DBE-4E96-446B-94D7-2800187622E5@pivotal.io> Message-ID: I think I still stand by the answers provided. Brian's comment here is particularly insightful: http://mail.openjdk.java.net/pipermail/compiler-dev/2015-January/009268.html E.g. it's not much that we're saying "works as designed" - it's more that we see this as some kind of short-term relief that is unavoidably cause much worse problems later down the road. So, I see two options: we add all the required attributes/annotations, and commit to never change the implementation strategy again (ouch!); or we leave freedom for the implementation to come up with more efficient runtime strategies - which unfortunately works against the use case you are presenting. That said, I agree with what's said in the evaluation you point at - the fact that many tools out there (IDEs) suggest you to turn all anon inner classes into lambdas might lead to people doing the refactoring w/o really understanding the implications for the framework they're working on. I wonder whether some other resolution - e.g. an explicit mechanism to opt out of the functional interface business would help? E.g. if a functional interface is marked with @NoFunctionalInterface (provisional name of course), then the compiler (and the IDE) should refuse to consider this interface a suitable target type for a lambda expression/method reference. Would that mitigate the pain? Maurizio On 11/01/18 09:10, Oliver Gierke wrote: > Hi all, > > I hate to bring this up again but as the adoption of Java 8 is growing significantly, this problem now comes up at least every other week and I can really understand the pain of our users. Find one example here [0]. > > Is there really no chance this is ever going to change? > > Cheers, > Ollie > > [0] https://github.com/spring-projects/spring-hateoas/issues/688 > >> Am 19.01.2017 um 08:40 schrieb Oliver Gierke : >> >> Hi Maurizio, >> >> thanks again for you in-depth explanation. I get all that and the design considerations behind the decisions that were made. I just wanted to point out that an ordinary user -- in general client code that uses APIs with SAM types -- *has to implicitly know* whether *any code* (potentially Java 6 based) downstream might attempt generics resolution before she can decide whether to use a Lambda with this SAM type. >> >> I think that's a very fundamental usability problem because it doesn't even need some arbitrary corner case. If there's a piece of code attempting the resolution anywhere downstream, it just won't work. Never. The only similar scenario (in terms of some parts of the reflection API not working as others) I remember is debug symbols on interface methods. That was changed in Java 8 with the -parameters flag. So I thought, it might be worth bringing this one up here as maybe the context has or will have changed for Java 9 / 10. >> >> Cheers, >> Ollie >> >>> Am 19.01.2017 um 02:52 schrieb Maurizio Cimadamore : >>> >>> Hi Oliver, >>> this request seems to be similar to other requests expressed in the past: >>> >>> Signature attribute on lambda method: >>> >>> http://mail.openjdk.java.net/pipermail/compiler-dev/2015-January/009220.html >>> >>> Annotations on lambdas: >>> >>> http://mail.openjdk.java.net/pipermail/compiler-dev/2015-July/009662.html >>> >>> >>> The recurring theme is that we don't want to make promises on implementation details - that is how is a lambda implemented. For now, a lambda is implemented as a (dynamically generated) anonymous class instance - so certain requests seem to make sense. But as the implementation will get better at sharing, having to expose details such as signature attributes and such will become an obstacle to further improvements. >>> >>> For instance, the runtime does NOT have to distinguish between a Supplier and a Supplier - example: >>> >>> class Test { >>> void test() { >>> Supplier ss = this::m; >>> Supplier si = this::m; >>> } >>> >>> String m() { return ""; } >>> } >>> >>> This gives the following bytceode: >>> >>> void test(); >>> descriptor: ()V >>> flags: >>> Code: >>> stack=1, locals=3, args_size=1 >>> 0: aload_0 >>> 1: invokedynamic #2, 0 // InvokeDynamic #0:get:(LTest;)Ljava/util/function/Supplier; >>> 6: astore_1 >>> 7: aload_0 >>> 8: invokedynamic #3, 0 // InvokeDynamic #1:get:(LTest;)Ljava/util/function/Supplier; >>> 13: astore_2 >>> 14: return >>> >>> BootstrapMethods: >>> 0: #18 invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; >>> Method arguments: >>> #19 ()Ljava/lang/Object; >>> #20 invokevirtual Test.m:()Ljava/lang/String; >>> #21 ()Ljava/lang/String; >>> 1: #18 invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; >>> Method arguments: >>> #19 ()Ljava/lang/Object; >>> #20 invokevirtual Test.m:()Ljava/lang/String; >>> #19 ()Ljava/lang/Object; >>> >>> >>> As you can see, both invokedynamic share the same SAM type - the erased java/util/function/Supplier. The only difference between the two indys is the method type passed as 3rd static argument - in one case ()String is passed, in the other ()Object is passed - that dictates the signature of the dynamically generated method implementing the sam type. >>> >>> In other words, if the lambda metafactory used the same instance for both method references, everything would still work (in fact, the generated bytecode is the same for both classes!). >>> >>> Maurizio >>> >>> >>> >>> On 18/01/17 18:06, Oliver Gierke wrote: >>>> Hi again, >>>> >>>> didn't get much response but it looks like there are some improvements for lambdas planned for at least JDK10 [0]. Is what I asked for below maybe a candidate for inclusion into those efforts? >>>> >>>> Is there maybe a better place to ask for this? >>>> >>>> Cheers, >>>> Ollie >>>> >>>> [0] https://www.infoq.com/news/2017/01/java10-lambda-leftovers >>>> >>>>> Am 23.12.2016 um 12:22 schrieb Oliver Gierke : >>>>> >>>>> Hi all, >>>>> >>>>> Lambda based implementations of SAM types currently don't support inspecting the type for generic type parameters. This can cause unexpected surprise as some high-level API taking a SAM type as parameter is usually an indicator to users, that they can be used with Lambdas. If the object passed in is then inspected for generic types somewhere down the call stack this causes issues. Handing in a dedicated implementation of the SAM type is a workaround bit I think that's highly confusing and can be a source of errors hard to understand and debug. >>>>> >>>>> I've added an example below. >>>>> >>>>> Cheers, >>>>> Ollie >>>>> >>>>> public class LambdaTypeDetectionSample { >>>>> >>>>> public static void main(String[] args) { >>>>> >>>>> Function lambdaFunction = i -> i.toString(); >>>>> Function oldschoolFunction = new Function() { >>>>> >>>>> public String apply(Integer t) { >>>>> return t.toString(); >>>>> } >>>>> }; >>>>> >>>>> printTypeArguments(oldschoolFunction); >>>>> >>>>> // Yields: >>>>> // java.util.function.Function is a class sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl >>>>> // class java.lang.Integer >>>>> // class java.lang.String >>>>> >>>>> printTypeArguments(lambdaFunction); >>>>> >>>>> // Yields: >>>>> // interface java.util.function.Function is a class java.lang.Class >>>>> } >>>>> >>>>> private static void printTypeArguments(Function function) { >>>>> >>>>> Type type = function.getClass().getGenericInterfaces()[0]; >>>>> >>>>> System.out.println(type + " is a " + type.getClass()); >>>>> >>>>> if (type instanceof ParameterizedType) { >>>>> >>>>> ParameterizedType functionInterface = (ParameterizedType) type; >>>>> Arrays.stream(functionInterface.getActualTypeArguments()).forEach(System.out::println); >>>>> } >>>>> } >>>>> } From ogierke at pivotal.io Thu Jan 11 11:38:40 2018 From: ogierke at pivotal.io (Oliver Gierke) Date: Thu, 11 Jan 2018 12:38:40 +0100 Subject: Issues with generic type detection of SAM types implemented using lambdas In-Reply-To: References: <4E1C251C-163A-4093-855F-CEDC043B8524@pivotal.io> <63C94B5C-4E18-4500-9203-15408B98D5EA@pivotal.io> <997D0DBE-4E96-446B-94D7-2800187622E5@pivotal.io> Message-ID: <1E71C73F-B646-45B1-8888-89A5D6A05A07@pivotal.io> The problem with that approach is that whether Lambda usage is working does not depend on the declared interface but whether other code - potentially living somewhere completely else - is attempting generics resolution. I.e. the interface designer might not know up front. In cases where the interface provider also is in charge of the processing code, the special annotation would certainly help. I am planning to add a bit of defensive code to the processing side of things to reject runtime instances that lack the required generics information. Is there a canonical resource besides this mailing list thread I could refer to to explain why we need to reject those instances (a section in the spec or the like)? Cheers, Ollie > Am 11.01.2018 um 12:18 schrieb Maurizio Cimadamore : > > I think I still stand by the answers provided. > > Brian's comment here is particularly insightful: > > http://mail.openjdk.java.net/pipermail/compiler-dev/2015-January/009268.html > > E.g. it's not much that we're saying "works as designed" - it's more that we see this as some kind of short-term relief that is unavoidably cause much worse problems later down the road. > > So, I see two options: we add all the required attributes/annotations, and commit to never change the implementation strategy again (ouch!); or we leave freedom for the implementation to come up with more efficient runtime strategies - which unfortunately works against the use case you are presenting. > > That said, I agree with what's said in the evaluation you point at - the fact that many tools out there (IDEs) suggest you to turn all anon inner classes into lambdas might lead to people doing the refactoring w/o really understanding the implications for the framework they're working on. > > I wonder whether some other resolution - e.g. an explicit mechanism to opt out of the functional interface business would help? E.g. if a functional interface is marked with @NoFunctionalInterface (provisional name of course), then the compiler (and the IDE) should refuse to consider this interface a suitable target type for a lambda expression/method reference. Would that mitigate the pain? > > Maurizio > > On 11/01/18 09:10, Oliver Gierke wrote: >> Hi all, >> >> I hate to bring this up again but as the adoption of Java 8 is growing significantly, this problem now comes up at least every other week and I can really understand the pain of our users. Find one example here [0]. >> >> Is there really no chance this is ever going to change? >> >> Cheers, >> Ollie >> >> [0] https://github.com/spring-projects/spring-hateoas/issues/688 >> >>> Am 19.01.2017 um 08:40 schrieb Oliver Gierke : >>> >>> Hi Maurizio, >>> >>> thanks again for you in-depth explanation. I get all that and the design considerations behind the decisions that were made. I just wanted to point out that an ordinary user -- in general client code that uses APIs with SAM types -- *has to implicitly know* whether *any code* (potentially Java 6 based) downstream might attempt generics resolution before she can decide whether to use a Lambda with this SAM type. >>> >>> I think that's a very fundamental usability problem because it doesn't even need some arbitrary corner case. If there's a piece of code attempting the resolution anywhere downstream, it just won't work. Never. The only similar scenario (in terms of some parts of the reflection API not working as others) I remember is debug symbols on interface methods. That was changed in Java 8 with the -parameters flag. So I thought, it might be worth bringing this one up here as maybe the context has or will have changed for Java 9 / 10. >>> >>> Cheers, >>> Ollie >>> >>>> Am 19.01.2017 um 02:52 schrieb Maurizio Cimadamore : >>>> >>>> Hi Oliver, >>>> this request seems to be similar to other requests expressed in the past: >>>> >>>> Signature attribute on lambda method: >>>> >>>> http://mail.openjdk.java.net/pipermail/compiler-dev/2015-January/009220.html >>>> >>>> Annotations on lambdas: >>>> >>>> http://mail.openjdk.java.net/pipermail/compiler-dev/2015-July/009662.html >>>> >>>> >>>> The recurring theme is that we don't want to make promises on implementation details - that is how is a lambda implemented. For now, a lambda is implemented as a (dynamically generated) anonymous class instance - so certain requests seem to make sense. But as the implementation will get better at sharing, having to expose details such as signature attributes and such will become an obstacle to further improvements. >>>> >>>> For instance, the runtime does NOT have to distinguish between a Supplier and a Supplier - example: >>>> >>>> class Test { >>>> void test() { >>>> Supplier ss = this::m; >>>> Supplier si = this::m; >>>> } >>>> >>>> String m() { return ""; } >>>> } >>>> >>>> This gives the following bytceode: >>>> >>>> void test(); >>>> descriptor: ()V >>>> flags: >>>> Code: >>>> stack=1, locals=3, args_size=1 >>>> 0: aload_0 >>>> 1: invokedynamic #2, 0 // InvokeDynamic #0:get:(LTest;)Ljava/util/function/Supplier; >>>> 6: astore_1 >>>> 7: aload_0 >>>> 8: invokedynamic #3, 0 // InvokeDynamic #1:get:(LTest;)Ljava/util/function/Supplier; >>>> 13: astore_2 >>>> 14: return >>>> >>>> BootstrapMethods: >>>> 0: #18 invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; >>>> Method arguments: >>>> #19 ()Ljava/lang/Object; >>>> #20 invokevirtual Test.m:()Ljava/lang/String; >>>> #21 ()Ljava/lang/String; >>>> 1: #18 invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; >>>> Method arguments: >>>> #19 ()Ljava/lang/Object; >>>> #20 invokevirtual Test.m:()Ljava/lang/String; >>>> #19 ()Ljava/lang/Object; >>>> >>>> >>>> As you can see, both invokedynamic share the same SAM type - the erased java/util/function/Supplier. The only difference between the two indys is the method type passed as 3rd static argument - in one case ()String is passed, in the other ()Object is passed - that dictates the signature of the dynamically generated method implementing the sam type. >>>> >>>> In other words, if the lambda metafactory used the same instance for both method references, everything would still work (in fact, the generated bytecode is the same for both classes!). >>>> >>>> Maurizio >>>> >>>> >>>> >>>> On 18/01/17 18:06, Oliver Gierke wrote: >>>>> Hi again, >>>>> >>>>> didn't get much response but it looks like there are some improvements for lambdas planned for at least JDK10 [0]. Is what I asked for below maybe a candidate for inclusion into those efforts? >>>>> >>>>> Is there maybe a better place to ask for this? >>>>> >>>>> Cheers, >>>>> Ollie >>>>> >>>>> [0] https://www.infoq.com/news/2017/01/java10-lambda-leftovers >>>>> >>>>>> Am 23.12.2016 um 12:22 schrieb Oliver Gierke : >>>>>> >>>>>> Hi all, >>>>>> >>>>>> Lambda based implementations of SAM types currently don't support inspecting the type for generic type parameters. This can cause unexpected surprise as some high-level API taking a SAM type as parameter is usually an indicator to users, that they can be used with Lambdas. If the object passed in is then inspected for generic types somewhere down the call stack this causes issues. Handing in a dedicated implementation of the SAM type is a workaround bit I think that's highly confusing and can be a source of errors hard to understand and debug. >>>>>> >>>>>> I've added an example below. >>>>>> >>>>>> Cheers, >>>>>> Ollie >>>>>> >>>>>> public class LambdaTypeDetectionSample { >>>>>> >>>>>> public static void main(String[] args) { >>>>>> >>>>>> Function lambdaFunction = i -> i.toString(); >>>>>> Function oldschoolFunction = new Function() { >>>>>> >>>>>> public String apply(Integer t) { >>>>>> return t.toString(); >>>>>> } >>>>>> }; >>>>>> >>>>>> printTypeArguments(oldschoolFunction); >>>>>> >>>>>> // Yields: >>>>>> // java.util.function.Function is a class sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl >>>>>> // class java.lang.Integer >>>>>> // class java.lang.String >>>>>> >>>>>> printTypeArguments(lambdaFunction); >>>>>> >>>>>> // Yields: >>>>>> // interface java.util.function.Function is a class java.lang.Class >>>>>> } >>>>>> >>>>>> private static void printTypeArguments(Function function) { >>>>>> >>>>>> Type type = function.getClass().getGenericInterfaces()[0]; >>>>>> >>>>>> System.out.println(type + " is a " + type.getClass()); >>>>>> >>>>>> if (type instanceof ParameterizedType) { >>>>>> >>>>>> ParameterizedType functionInterface = (ParameterizedType) type; >>>>>> Arrays.stream(functionInterface.getActualTypeArguments()).forEach(System.out::println); >>>>>> } >>>>>> } >>>>>> } > -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: Message signed with OpenPGP URL: From maurizio.cimadamore at oracle.com Thu Jan 11 11:44:19 2018 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 11 Jan 2018 11:44:19 +0000 Subject: Issues with generic type detection of SAM types implemented using lambdas In-Reply-To: <1E71C73F-B646-45B1-8888-89A5D6A05A07@pivotal.io> References: <4E1C251C-163A-4093-855F-CEDC043B8524@pivotal.io> <63C94B5C-4E18-4500-9203-15408B98D5EA@pivotal.io> <997D0DBE-4E96-446B-94D7-2800187622E5@pivotal.io> <1E71C73F-B646-45B1-8888-89A5D6A05A07@pivotal.io> Message-ID: <3c8cd082-3245-4a24-f7eb-79ea65bcb3f6@oracle.com> On 11/01/18 11:38, Oliver Gierke wrote: > The problem with that approach is that whether Lambda usage is working does not depend on the declared interface but whether other code - potentially living somewhere completely else - is attempting generics resolution. I.e. the interface designer might not know up front. > > In cases where the interface provider also is in charge of the processing code, the special annotation would certainly help. > > I am planning to add a bit of defensive code to the processing side of things to reject runtime instances that lack the required generics information. Is there a canonical resource besides this mailing list thread I could refer to to explain why we need to reject those instances (a section in the spec or the like)? I'm not aware of anything specific, but the spec certainly does a lot of work to deliberately _avoid_ saying what the runtime artifact associated with a lambda expression actually is. See: https://docs.oracle.com/javase/specs/jls/se9/html/jls-15.html#jls-15.27.4 And more specifically, the bullets: " * A new object need not be allocated on every evaluation. * Objects produced by different lambda expressions need not belong to different classes (if the bodies are identical, for example). * Every object produced by evaluation need not belong to the same class (captured local variables might be inlined, for example). * If an "existing instance" is available, it need not have been created at a previous lambda evaluation (it might have been allocated during the enclosing class's initialization, for example). " I believe esp. the second bullet goes against the kind of meta-info you would like to be associated with lambda expressions. Maurizio > > Cheers, > Ollie > >> Am 11.01.2018 um 12:18 schrieb Maurizio Cimadamore : >> >> I think I still stand by the answers provided. >> >> Brian's comment here is particularly insightful: >> >> http://mail.openjdk.java.net/pipermail/compiler-dev/2015-January/009268.html >> >> E.g. it's not much that we're saying "works as designed" - it's more that we see this as some kind of short-term relief that is unavoidably cause much worse problems later down the road. >> >> So, I see two options: we add all the required attributes/annotations, and commit to never change the implementation strategy again (ouch!); or we leave freedom for the implementation to come up with more efficient runtime strategies - which unfortunately works against the use case you are presenting. >> >> That said, I agree with what's said in the evaluation you point at - the fact that many tools out there (IDEs) suggest you to turn all anon inner classes into lambdas might lead to people doing the refactoring w/o really understanding the implications for the framework they're working on. >> >> I wonder whether some other resolution - e.g. an explicit mechanism to opt out of the functional interface business would help? E.g. if a functional interface is marked with @NoFunctionalInterface (provisional name of course), then the compiler (and the IDE) should refuse to consider this interface a suitable target type for a lambda expression/method reference. Would that mitigate the pain? >> >> Maurizio >> >> On 11/01/18 09:10, Oliver Gierke wrote: >>> Hi all, >>> >>> I hate to bring this up again but as the adoption of Java 8 is growing significantly, this problem now comes up at least every other week and I can really understand the pain of our users. Find one example here [0]. >>> >>> Is there really no chance this is ever going to change? >>> >>> Cheers, >>> Ollie >>> >>> [0] https://github.com/spring-projects/spring-hateoas/issues/688 >>> >>>> Am 19.01.2017 um 08:40 schrieb Oliver Gierke : >>>> >>>> Hi Maurizio, >>>> >>>> thanks again for you in-depth explanation. I get all that and the design considerations behind the decisions that were made. I just wanted to point out that an ordinary user -- in general client code that uses APIs with SAM types -- *has to implicitly know* whether *any code* (potentially Java 6 based) downstream might attempt generics resolution before she can decide whether to use a Lambda with this SAM type. >>>> >>>> I think that's a very fundamental usability problem because it doesn't even need some arbitrary corner case. If there's a piece of code attempting the resolution anywhere downstream, it just won't work. Never. The only similar scenario (in terms of some parts of the reflection API not working as others) I remember is debug symbols on interface methods. That was changed in Java 8 with the -parameters flag. So I thought, it might be worth bringing this one up here as maybe the context has or will have changed for Java 9 / 10. >>>> >>>> Cheers, >>>> Ollie >>>> >>>>> Am 19.01.2017 um 02:52 schrieb Maurizio Cimadamore : >>>>> >>>>> Hi Oliver, >>>>> this request seems to be similar to other requests expressed in the past: >>>>> >>>>> Signature attribute on lambda method: >>>>> >>>>> http://mail.openjdk.java.net/pipermail/compiler-dev/2015-January/009220.html >>>>> >>>>> Annotations on lambdas: >>>>> >>>>> http://mail.openjdk.java.net/pipermail/compiler-dev/2015-July/009662.html >>>>> >>>>> >>>>> The recurring theme is that we don't want to make promises on implementation details - that is how is a lambda implemented. For now, a lambda is implemented as a (dynamically generated) anonymous class instance - so certain requests seem to make sense. But as the implementation will get better at sharing, having to expose details such as signature attributes and such will become an obstacle to further improvements. >>>>> >>>>> For instance, the runtime does NOT have to distinguish between a Supplier and a Supplier - example: >>>>> >>>>> class Test { >>>>> void test() { >>>>> Supplier ss = this::m; >>>>> Supplier si = this::m; >>>>> } >>>>> >>>>> String m() { return ""; } >>>>> } >>>>> >>>>> This gives the following bytceode: >>>>> >>>>> void test(); >>>>> descriptor: ()V >>>>> flags: >>>>> Code: >>>>> stack=1, locals=3, args_size=1 >>>>> 0: aload_0 >>>>> 1: invokedynamic #2, 0 // InvokeDynamic #0:get:(LTest;)Ljava/util/function/Supplier; >>>>> 6: astore_1 >>>>> 7: aload_0 >>>>> 8: invokedynamic #3, 0 // InvokeDynamic #1:get:(LTest;)Ljava/util/function/Supplier; >>>>> 13: astore_2 >>>>> 14: return >>>>> >>>>> BootstrapMethods: >>>>> 0: #18 invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; >>>>> Method arguments: >>>>> #19 ()Ljava/lang/Object; >>>>> #20 invokevirtual Test.m:()Ljava/lang/String; >>>>> #21 ()Ljava/lang/String; >>>>> 1: #18 invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; >>>>> Method arguments: >>>>> #19 ()Ljava/lang/Object; >>>>> #20 invokevirtual Test.m:()Ljava/lang/String; >>>>> #19 ()Ljava/lang/Object; >>>>> >>>>> >>>>> As you can see, both invokedynamic share the same SAM type - the erased java/util/function/Supplier. The only difference between the two indys is the method type passed as 3rd static argument - in one case ()String is passed, in the other ()Object is passed - that dictates the signature of the dynamically generated method implementing the sam type. >>>>> >>>>> In other words, if the lambda metafactory used the same instance for both method references, everything would still work (in fact, the generated bytecode is the same for both classes!). >>>>> >>>>> Maurizio >>>>> >>>>> >>>>> >>>>> On 18/01/17 18:06, Oliver Gierke wrote: >>>>>> Hi again, >>>>>> >>>>>> didn't get much response but it looks like there are some improvements for lambdas planned for at least JDK10 [0]. Is what I asked for below maybe a candidate for inclusion into those efforts? >>>>>> >>>>>> Is there maybe a better place to ask for this? >>>>>> >>>>>> Cheers, >>>>>> Ollie >>>>>> >>>>>> [0] https://www.infoq.com/news/2017/01/java10-lambda-leftovers >>>>>> >>>>>>> Am 23.12.2016 um 12:22 schrieb Oliver Gierke : >>>>>>> >>>>>>> Hi all, >>>>>>> >>>>>>> Lambda based implementations of SAM types currently don't support inspecting the type for generic type parameters. This can cause unexpected surprise as some high-level API taking a SAM type as parameter is usually an indicator to users, that they can be used with Lambdas. If the object passed in is then inspected for generic types somewhere down the call stack this causes issues. Handing in a dedicated implementation of the SAM type is a workaround bit I think that's highly confusing and can be a source of errors hard to understand and debug. >>>>>>> >>>>>>> I've added an example below. >>>>>>> >>>>>>> Cheers, >>>>>>> Ollie >>>>>>> >>>>>>> public class LambdaTypeDetectionSample { >>>>>>> >>>>>>> public static void main(String[] args) { >>>>>>> >>>>>>> Function lambdaFunction = i -> i.toString(); >>>>>>> Function oldschoolFunction = new Function() { >>>>>>> >>>>>>> public String apply(Integer t) { >>>>>>> return t.toString(); >>>>>>> } >>>>>>> }; >>>>>>> >>>>>>> printTypeArguments(oldschoolFunction); >>>>>>> >>>>>>> // Yields: >>>>>>> // java.util.function.Function is a class sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl >>>>>>> // class java.lang.Integer >>>>>>> // class java.lang.String >>>>>>> >>>>>>> printTypeArguments(lambdaFunction); >>>>>>> >>>>>>> // Yields: >>>>>>> // interface java.util.function.Function is a class java.lang.Class >>>>>>> } >>>>>>> >>>>>>> private static void printTypeArguments(Function function) { >>>>>>> >>>>>>> Type type = function.getClass().getGenericInterfaces()[0]; >>>>>>> >>>>>>> System.out.println(type + " is a " + type.getClass()); >>>>>>> >>>>>>> if (type instanceof ParameterizedType) { >>>>>>> >>>>>>> ParameterizedType functionInterface = (ParameterizedType) type; >>>>>>> Arrays.stream(functionInterface.getActualTypeArguments()).forEach(System.out::println); >>>>>>> } >>>>>>> } >>>>>>> } -------------- next part -------------- An HTML attachment was scrubbed... URL: From ogierke at pivotal.io Thu Jan 11 11:48:14 2018 From: ogierke at pivotal.io (Oliver Gierke) Date: Thu, 11 Jan 2018 12:48:14 +0100 Subject: Issues with generic type detection of SAM types implemented using lambdas In-Reply-To: References: <4E1C251C-163A-4093-855F-CEDC043B8524@pivotal.io> <63C94B5C-4E18-4500-9203-15408B98D5EA@pivotal.io> <997D0DBE-4E96-446B-94D7-2800187622E5@pivotal.io> Message-ID: I fear that's quite a mouthful of internals thrown into a user's face, especially as everyone has literally learned for so many years that "SAM type -> Lambda", but I guess it's the best reference I can make. Thanks, Maurizio! > Am 11.01.2018 um 12:18 schrieb Maurizio Cimadamore : > > I think I still stand by the answers provided. > > Brian's comment here is particularly insightful: > > http://mail.openjdk.java.net/pipermail/compiler-dev/2015-January/009268.html > > E.g. it's not much that we're saying "works as designed" - it's more that we see this as some kind of short-term relief that is unavoidably cause much worse problems later down the road. > > So, I see two options: we add all the required attributes/annotations, and commit to never change the implementation strategy again (ouch!); or we leave freedom for the implementation to come up with more efficient runtime strategies - which unfortunately works against the use case you are presenting. > > That said, I agree with what's said in the evaluation you point at - the fact that many tools out there (IDEs) suggest you to turn all anon inner classes into lambdas might lead to people doing the refactoring w/o really understanding the implications for the framework they're working on. > > I wonder whether some other resolution - e.g. an explicit mechanism to opt out of the functional interface business would help? E.g. if a functional interface is marked with @NoFunctionalInterface (provisional name of course), then the compiler (and the IDE) should refuse to consider this interface a suitable target type for a lambda expression/method reference. Would that mitigate the pain? > > Maurizio > > On 11/01/18 09:10, Oliver Gierke wrote: >> Hi all, >> >> I hate to bring this up again but as the adoption of Java 8 is growing significantly, this problem now comes up at least every other week and I can really understand the pain of our users. Find one example here [0]. >> >> Is there really no chance this is ever going to change? >> >> Cheers, >> Ollie >> >> [0] https://github.com/spring-projects/spring-hateoas/issues/688 >> >>> Am 19.01.2017 um 08:40 schrieb Oliver Gierke : >>> >>> Hi Maurizio, >>> >>> thanks again for you in-depth explanation. I get all that and the design considerations behind the decisions that were made. I just wanted to point out that an ordinary user -- in general client code that uses APIs with SAM types -- *has to implicitly know* whether *any code* (potentially Java 6 based) downstream might attempt generics resolution before she can decide whether to use a Lambda with this SAM type. >>> >>> I think that's a very fundamental usability problem because it doesn't even need some arbitrary corner case. If there's a piece of code attempting the resolution anywhere downstream, it just won't work. Never. The only similar scenario (in terms of some parts of the reflection API not working as others) I remember is debug symbols on interface methods. That was changed in Java 8 with the -parameters flag. So I thought, it might be worth bringing this one up here as maybe the context has or will have changed for Java 9 / 10. >>> >>> Cheers, >>> Ollie >>> >>>> Am 19.01.2017 um 02:52 schrieb Maurizio Cimadamore : >>>> >>>> Hi Oliver, >>>> this request seems to be similar to other requests expressed in the past: >>>> >>>> Signature attribute on lambda method: >>>> >>>> http://mail.openjdk.java.net/pipermail/compiler-dev/2015-January/009220.html >>>> >>>> Annotations on lambdas: >>>> >>>> http://mail.openjdk.java.net/pipermail/compiler-dev/2015-July/009662.html >>>> >>>> >>>> The recurring theme is that we don't want to make promises on implementation details - that is how is a lambda implemented. For now, a lambda is implemented as a (dynamically generated) anonymous class instance - so certain requests seem to make sense. But as the implementation will get better at sharing, having to expose details such as signature attributes and such will become an obstacle to further improvements. >>>> >>>> For instance, the runtime does NOT have to distinguish between a Supplier and a Supplier - example: >>>> >>>> class Test { >>>> void test() { >>>> Supplier ss = this::m; >>>> Supplier si = this::m; >>>> } >>>> >>>> String m() { return ""; } >>>> } >>>> >>>> This gives the following bytceode: >>>> >>>> void test(); >>>> descriptor: ()V >>>> flags: >>>> Code: >>>> stack=1, locals=3, args_size=1 >>>> 0: aload_0 >>>> 1: invokedynamic #2, 0 // InvokeDynamic #0:get:(LTest;)Ljava/util/function/Supplier; >>>> 6: astore_1 >>>> 7: aload_0 >>>> 8: invokedynamic #3, 0 // InvokeDynamic #1:get:(LTest;)Ljava/util/function/Supplier; >>>> 13: astore_2 >>>> 14: return >>>> >>>> BootstrapMethods: >>>> 0: #18 invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; >>>> Method arguments: >>>> #19 ()Ljava/lang/Object; >>>> #20 invokevirtual Test.m:()Ljava/lang/String; >>>> #21 ()Ljava/lang/String; >>>> 1: #18 invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; >>>> Method arguments: >>>> #19 ()Ljava/lang/Object; >>>> #20 invokevirtual Test.m:()Ljava/lang/String; >>>> #19 ()Ljava/lang/Object; >>>> >>>> >>>> As you can see, both invokedynamic share the same SAM type - the erased java/util/function/Supplier. The only difference between the two indys is the method type passed as 3rd static argument - in one case ()String is passed, in the other ()Object is passed - that dictates the signature of the dynamically generated method implementing the sam type. >>>> >>>> In other words, if the lambda metafactory used the same instance for both method references, everything would still work (in fact, the generated bytecode is the same for both classes!). >>>> >>>> Maurizio >>>> >>>> >>>> >>>> On 18/01/17 18:06, Oliver Gierke wrote: >>>>> Hi again, >>>>> >>>>> didn't get much response but it looks like there are some improvements for lambdas planned for at least JDK10 [0]. Is what I asked for below maybe a candidate for inclusion into those efforts? >>>>> >>>>> Is there maybe a better place to ask for this? >>>>> >>>>> Cheers, >>>>> Ollie >>>>> >>>>> [0] https://www.infoq.com/news/2017/01/java10-lambda-leftovers >>>>> >>>>>> Am 23.12.2016 um 12:22 schrieb Oliver Gierke : >>>>>> >>>>>> Hi all, >>>>>> >>>>>> Lambda based implementations of SAM types currently don't support inspecting the type for generic type parameters. This can cause unexpected surprise as some high-level API taking a SAM type as parameter is usually an indicator to users, that they can be used with Lambdas. If the object passed in is then inspected for generic types somewhere down the call stack this causes issues. Handing in a dedicated implementation of the SAM type is a workaround bit I think that's highly confusing and can be a source of errors hard to understand and debug. >>>>>> >>>>>> I've added an example below. >>>>>> >>>>>> Cheers, >>>>>> Ollie >>>>>> >>>>>> public class LambdaTypeDetectionSample { >>>>>> >>>>>> public static void main(String[] args) { >>>>>> >>>>>> Function lambdaFunction = i -> i.toString(); >>>>>> Function oldschoolFunction = new Function() { >>>>>> >>>>>> public String apply(Integer t) { >>>>>> return t.toString(); >>>>>> } >>>>>> }; >>>>>> >>>>>> printTypeArguments(oldschoolFunction); >>>>>> >>>>>> // Yields: >>>>>> // java.util.function.Function is a class sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl >>>>>> // class java.lang.Integer >>>>>> // class java.lang.String >>>>>> >>>>>> printTypeArguments(lambdaFunction); >>>>>> >>>>>> // Yields: >>>>>> // interface java.util.function.Function is a class java.lang.Class >>>>>> } >>>>>> >>>>>> private static void printTypeArguments(Function function) { >>>>>> >>>>>> Type type = function.getClass().getGenericInterfaces()[0]; >>>>>> >>>>>> System.out.println(type + " is a " + type.getClass()); >>>>>> >>>>>> if (type instanceof ParameterizedType) { >>>>>> >>>>>> ParameterizedType functionInterface = (ParameterizedType) type; >>>>>> Arrays.stream(functionInterface.getActualTypeArguments()).forEach(System.out::println); >>>>>> } >>>>>> } >>>>>> } > -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: Message signed with OpenPGP URL: From ogierke at pivotal.io Thu Jan 11 13:49:41 2018 From: ogierke at pivotal.io (Oliver Gierke) Date: Thu, 11 Jan 2018 14:49:41 +0100 Subject: Issues with generic type detection of SAM types implemented using lambdas In-Reply-To: References: <4E1C251C-163A-4093-855F-CEDC043B8524@pivotal.io> <63C94B5C-4E18-4500-9203-15408B98D5EA@pivotal.io> <997D0DBE-4E96-446B-94D7-2800187622E5@pivotal.io> Message-ID: <2A134D0C-A08E-486A-BC3A-CD999DF74B6D@pivotal.io> While I am currently investigating how to actually detect a lambda defined instance: is there a more reliable way than checking the class name to contain "$Lambda$"? Cheers, Ollie > Am 11.01.2018 um 12:48 schrieb Oliver Gierke : > > I fear that's quite a mouthful of internals thrown into a user's face, especially as everyone has literally learned for so many years that "SAM type -> Lambda", but I guess it's the best reference I can make. > > Thanks, Maurizio! > >> Am 11.01.2018 um 12:18 schrieb Maurizio Cimadamore : >> >> I think I still stand by the answers provided. >> >> Brian's comment here is particularly insightful: >> >> http://mail.openjdk.java.net/pipermail/compiler-dev/2015-January/009268.html >> >> E.g. it's not much that we're saying "works as designed" - it's more that we see this as some kind of short-term relief that is unavoidably cause much worse problems later down the road. >> >> So, I see two options: we add all the required attributes/annotations, and commit to never change the implementation strategy again (ouch!); or we leave freedom for the implementation to come up with more efficient runtime strategies - which unfortunately works against the use case you are presenting. >> >> That said, I agree with what's said in the evaluation you point at - the fact that many tools out there (IDEs) suggest you to turn all anon inner classes into lambdas might lead to people doing the refactoring w/o really understanding the implications for the framework they're working on. >> >> I wonder whether some other resolution - e.g. an explicit mechanism to opt out of the functional interface business would help? E.g. if a functional interface is marked with @NoFunctionalInterface (provisional name of course), then the compiler (and the IDE) should refuse to consider this interface a suitable target type for a lambda expression/method reference. Would that mitigate the pain? >> >> Maurizio >> >> On 11/01/18 09:10, Oliver Gierke wrote: >>> Hi all, >>> >>> I hate to bring this up again but as the adoption of Java 8 is growing significantly, this problem now comes up at least every other week and I can really understand the pain of our users. Find one example here [0]. >>> >>> Is there really no chance this is ever going to change? >>> >>> Cheers, >>> Ollie >>> >>> [0] https://github.com/spring-projects/spring-hateoas/issues/688 >>> >>>> Am 19.01.2017 um 08:40 schrieb Oliver Gierke : >>>> >>>> Hi Maurizio, >>>> >>>> thanks again for you in-depth explanation. I get all that and the design considerations behind the decisions that were made. I just wanted to point out that an ordinary user -- in general client code that uses APIs with SAM types -- *has to implicitly know* whether *any code* (potentially Java 6 based) downstream might attempt generics resolution before she can decide whether to use a Lambda with this SAM type. >>>> >>>> I think that's a very fundamental usability problem because it doesn't even need some arbitrary corner case. If there's a piece of code attempting the resolution anywhere downstream, it just won't work. Never. The only similar scenario (in terms of some parts of the reflection API not working as others) I remember is debug symbols on interface methods. That was changed in Java 8 with the -parameters flag. So I thought, it might be worth bringing this one up here as maybe the context has or will have changed for Java 9 / 10. >>>> >>>> Cheers, >>>> Ollie >>>> >>>>> Am 19.01.2017 um 02:52 schrieb Maurizio Cimadamore : >>>>> >>>>> Hi Oliver, >>>>> this request seems to be similar to other requests expressed in the past: >>>>> >>>>> Signature attribute on lambda method: >>>>> >>>>> http://mail.openjdk.java.net/pipermail/compiler-dev/2015-January/009220.html >>>>> >>>>> Annotations on lambdas: >>>>> >>>>> http://mail.openjdk.java.net/pipermail/compiler-dev/2015-July/009662.html >>>>> >>>>> >>>>> The recurring theme is that we don't want to make promises on implementation details - that is how is a lambda implemented. For now, a lambda is implemented as a (dynamically generated) anonymous class instance - so certain requests seem to make sense. But as the implementation will get better at sharing, having to expose details such as signature attributes and such will become an obstacle to further improvements. >>>>> >>>>> For instance, the runtime does NOT have to distinguish between a Supplier and a Supplier - example: >>>>> >>>>> class Test { >>>>> void test() { >>>>> Supplier ss = this::m; >>>>> Supplier si = this::m; >>>>> } >>>>> >>>>> String m() { return ""; } >>>>> } >>>>> >>>>> This gives the following bytceode: >>>>> >>>>> void test(); >>>>> descriptor: ()V >>>>> flags: >>>>> Code: >>>>> stack=1, locals=3, args_size=1 >>>>> 0: aload_0 >>>>> 1: invokedynamic #2, 0 // InvokeDynamic #0:get:(LTest;)Ljava/util/function/Supplier; >>>>> 6: astore_1 >>>>> 7: aload_0 >>>>> 8: invokedynamic #3, 0 // InvokeDynamic #1:get:(LTest;)Ljava/util/function/Supplier; >>>>> 13: astore_2 >>>>> 14: return >>>>> >>>>> BootstrapMethods: >>>>> 0: #18 invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; >>>>> Method arguments: >>>>> #19 ()Ljava/lang/Object; >>>>> #20 invokevirtual Test.m:()Ljava/lang/String; >>>>> #21 ()Ljava/lang/String; >>>>> 1: #18 invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; >>>>> Method arguments: >>>>> #19 ()Ljava/lang/Object; >>>>> #20 invokevirtual Test.m:()Ljava/lang/String; >>>>> #19 ()Ljava/lang/Object; >>>>> >>>>> >>>>> As you can see, both invokedynamic share the same SAM type - the erased java/util/function/Supplier. The only difference between the two indys is the method type passed as 3rd static argument - in one case ()String is passed, in the other ()Object is passed - that dictates the signature of the dynamically generated method implementing the sam type. >>>>> >>>>> In other words, if the lambda metafactory used the same instance for both method references, everything would still work (in fact, the generated bytecode is the same for both classes!). >>>>> >>>>> Maurizio >>>>> >>>>> >>>>> >>>>> On 18/01/17 18:06, Oliver Gierke wrote: >>>>>> Hi again, >>>>>> >>>>>> didn't get much response but it looks like there are some improvements for lambdas planned for at least JDK10 [0]. Is what I asked for below maybe a candidate for inclusion into those efforts? >>>>>> >>>>>> Is there maybe a better place to ask for this? >>>>>> >>>>>> Cheers, >>>>>> Ollie >>>>>> >>>>>> [0] https://www.infoq.com/news/2017/01/java10-lambda-leftovers >>>>>> >>>>>>> Am 23.12.2016 um 12:22 schrieb Oliver Gierke : >>>>>>> >>>>>>> Hi all, >>>>>>> >>>>>>> Lambda based implementations of SAM types currently don't support inspecting the type for generic type parameters. This can cause unexpected surprise as some high-level API taking a SAM type as parameter is usually an indicator to users, that they can be used with Lambdas. If the object passed in is then inspected for generic types somewhere down the call stack this causes issues. Handing in a dedicated implementation of the SAM type is a workaround bit I think that's highly confusing and can be a source of errors hard to understand and debug. >>>>>>> >>>>>>> I've added an example below. >>>>>>> >>>>>>> Cheers, >>>>>>> Ollie >>>>>>> >>>>>>> public class LambdaTypeDetectionSample { >>>>>>> >>>>>>> public static void main(String[] args) { >>>>>>> >>>>>>> Function lambdaFunction = i -> i.toString(); >>>>>>> Function oldschoolFunction = new Function() { >>>>>>> >>>>>>> public String apply(Integer t) { >>>>>>> return t.toString(); >>>>>>> } >>>>>>> }; >>>>>>> >>>>>>> printTypeArguments(oldschoolFunction); >>>>>>> >>>>>>> // Yields: >>>>>>> // java.util.function.Function is a class sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl >>>>>>> // class java.lang.Integer >>>>>>> // class java.lang.String >>>>>>> >>>>>>> printTypeArguments(lambdaFunction); >>>>>>> >>>>>>> // Yields: >>>>>>> // interface java.util.function.Function is a class java.lang.Class >>>>>>> } >>>>>>> >>>>>>> private static void printTypeArguments(Function function) { >>>>>>> >>>>>>> Type type = function.getClass().getGenericInterfaces()[0]; >>>>>>> >>>>>>> System.out.println(type + " is a " + type.getClass()); >>>>>>> >>>>>>> if (type instanceof ParameterizedType) { >>>>>>> >>>>>>> ParameterizedType functionInterface = (ParameterizedType) type; >>>>>>> Arrays.stream(functionInterface.getActualTypeArguments()).forEach(System.out::println); >>>>>>> } >>>>>>> } >>>>>>> } >> > -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: Message signed with OpenPGP URL: From david.lloyd at redhat.com Thu Jan 11 13:56:50 2018 From: david.lloyd at redhat.com (David Lloyd) Date: Thu, 11 Jan 2018 07:56:50 -0600 Subject: Issues with generic type detection of SAM types implemented using lambdas In-Reply-To: <997D0DBE-4E96-446B-94D7-2800187622E5@pivotal.io> References: <4E1C251C-163A-4093-855F-CEDC043B8524@pivotal.io> <63C94B5C-4E18-4500-9203-15408B98D5EA@pivotal.io> <997D0DBE-4E96-446B-94D7-2800187622E5@pivotal.io> Message-ID: On Thu, Jan 11, 2018 at 3:10 AM, Oliver Gierke wrote: > Lambda based implementations of SAM types currently don't support inspecting the type for generic type parameters. This can cause unexpected surprise... Here's a non-lambda example that demonstrates that inspecting *any* class for generic type parameters is fragile and not a good idea: public final class Hasher implements ToIntFunction { int applyAsInt(T value) { return value.hashCode(); } } Oops, now all my concrete implementations have generic parameters. Telling users they cannot have generic parameters on their implementation classes is poor API design. -- - DML From ogierke at pivotal.io Thu Jan 11 14:03:26 2018 From: ogierke at pivotal.io (Oliver Gierke) Date: Thu, 11 Jan 2018 15:03:26 +0100 Subject: Issues with generic type detection of SAM types implemented using lambdas In-Reply-To: References: <4E1C251C-163A-4093-855F-CEDC043B8524@pivotal.io> <63C94B5C-4E18-4500-9203-15408B98D5EA@pivotal.io> <997D0DBE-4E96-446B-94D7-2800187622E5@pivotal.io> Message-ID: <402E5B8E-743B-4D88-B060-B66836C9616A@pivotal.io> > Am 11.01.2018 um 14:56 schrieb David Lloyd : > > On Thu, Jan 11, 2018 at 3:10 AM, Oliver Gierke wrote: >> Lambda based implementations of SAM types currently don't support inspecting the type for generic type parameters. This can cause unexpected surprise... > > Here's a non-lambda example that demonstrates that inspecting *any* > class for generic type parameters is fragile and not a good idea: > > public final class Hasher implements ToIntFunction { > int applyAsInt(T value) { return value.hashCode(); } > } > > Oops, now all my concrete implementations have generic parameters. I'm afraid I can't follow. > Telling users they cannot have generic parameters on their > implementation classes is poor API design. Who is actually doing that? Cheers, Ollie -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: Message signed with OpenPGP URL: From maurizio.cimadamore at oracle.com Thu Jan 11 14:09:35 2018 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 11 Jan 2018 14:09:35 +0000 Subject: Issues with generic type detection of SAM types implemented using lambdas In-Reply-To: <2A134D0C-A08E-486A-BC3A-CD999DF74B6D@pivotal.io> References: <4E1C251C-163A-4093-855F-CEDC043B8524@pivotal.io> <63C94B5C-4E18-4500-9203-15408B98D5EA@pivotal.io> <997D0DBE-4E96-446B-94D7-2800187622E5@pivotal.io> <2A134D0C-A08E-486A-BC3A-CD999DF74B6D@pivotal.io> Message-ID: I think that's your best bet. The name should contain $$Lambda$ followed by some number. Of course this is very impl specific, and it would be possible for other runtimes to do different things (e.g. the name is not specified anywhere). Maurizio On 11/01/18 13:49, Oliver Gierke wrote: > While I am currently investigating how to actually detect a lambda defined instance: is there a more reliable way than checking the class name to contain "$Lambda$"? > > Cheers, > Ollie > >> Am 11.01.2018 um 12:48 schrieb Oliver Gierke : >> >> I fear that's quite a mouthful of internals thrown into a user's face, especially as everyone has literally learned for so many years that "SAM type -> Lambda", but I guess it's the best reference I can make. >> >> Thanks, Maurizio! >> >>> Am 11.01.2018 um 12:18 schrieb Maurizio Cimadamore : >>> >>> I think I still stand by the answers provided. >>> >>> Brian's comment here is particularly insightful: >>> >>> http://mail.openjdk.java.net/pipermail/compiler-dev/2015-January/009268.html >>> >>> E.g. it's not much that we're saying "works as designed" - it's more that we see this as some kind of short-term relief that is unavoidably cause much worse problems later down the road. >>> >>> So, I see two options: we add all the required attributes/annotations, and commit to never change the implementation strategy again (ouch!); or we leave freedom for the implementation to come up with more efficient runtime strategies - which unfortunately works against the use case you are presenting. >>> >>> That said, I agree with what's said in the evaluation you point at - the fact that many tools out there (IDEs) suggest you to turn all anon inner classes into lambdas might lead to people doing the refactoring w/o really understanding the implications for the framework they're working on. >>> >>> I wonder whether some other resolution - e.g. an explicit mechanism to opt out of the functional interface business would help? E.g. if a functional interface is marked with @NoFunctionalInterface (provisional name of course), then the compiler (and the IDE) should refuse to consider this interface a suitable target type for a lambda expression/method reference. Would that mitigate the pain? >>> >>> Maurizio >>> >>> On 11/01/18 09:10, Oliver Gierke wrote: >>>> Hi all, >>>> >>>> I hate to bring this up again but as the adoption of Java 8 is growing significantly, this problem now comes up at least every other week and I can really understand the pain of our users. Find one example here [0]. >>>> >>>> Is there really no chance this is ever going to change? >>>> >>>> Cheers, >>>> Ollie >>>> >>>> [0] https://github.com/spring-projects/spring-hateoas/issues/688 >>>> >>>>> Am 19.01.2017 um 08:40 schrieb Oliver Gierke : >>>>> >>>>> Hi Maurizio, >>>>> >>>>> thanks again for you in-depth explanation. I get all that and the design considerations behind the decisions that were made. I just wanted to point out that an ordinary user -- in general client code that uses APIs with SAM types -- *has to implicitly know* whether *any code* (potentially Java 6 based) downstream might attempt generics resolution before she can decide whether to use a Lambda with this SAM type. >>>>> >>>>> I think that's a very fundamental usability problem because it doesn't even need some arbitrary corner case. If there's a piece of code attempting the resolution anywhere downstream, it just won't work. Never. The only similar scenario (in terms of some parts of the reflection API not working as others) I remember is debug symbols on interface methods. That was changed in Java 8 with the -parameters flag. So I thought, it might be worth bringing this one up here as maybe the context has or will have changed for Java 9 / 10. >>>>> >>>>> Cheers, >>>>> Ollie >>>>> >>>>>> Am 19.01.2017 um 02:52 schrieb Maurizio Cimadamore : >>>>>> >>>>>> Hi Oliver, >>>>>> this request seems to be similar to other requests expressed in the past: >>>>>> >>>>>> Signature attribute on lambda method: >>>>>> >>>>>> http://mail.openjdk.java.net/pipermail/compiler-dev/2015-January/009220.html >>>>>> >>>>>> Annotations on lambdas: >>>>>> >>>>>> http://mail.openjdk.java.net/pipermail/compiler-dev/2015-July/009662.html >>>>>> >>>>>> >>>>>> The recurring theme is that we don't want to make promises on implementation details - that is how is a lambda implemented. For now, a lambda is implemented as a (dynamically generated) anonymous class instance - so certain requests seem to make sense. But as the implementation will get better at sharing, having to expose details such as signature attributes and such will become an obstacle to further improvements. >>>>>> >>>>>> For instance, the runtime does NOT have to distinguish between a Supplier and a Supplier - example: >>>>>> >>>>>> class Test { >>>>>> void test() { >>>>>> Supplier ss = this::m; >>>>>> Supplier si = this::m; >>>>>> } >>>>>> >>>>>> String m() { return ""; } >>>>>> } >>>>>> >>>>>> This gives the following bytceode: >>>>>> >>>>>> void test(); >>>>>> descriptor: ()V >>>>>> flags: >>>>>> Code: >>>>>> stack=1, locals=3, args_size=1 >>>>>> 0: aload_0 >>>>>> 1: invokedynamic #2, 0 // InvokeDynamic #0:get:(LTest;)Ljava/util/function/Supplier; >>>>>> 6: astore_1 >>>>>> 7: aload_0 >>>>>> 8: invokedynamic #3, 0 // InvokeDynamic #1:get:(LTest;)Ljava/util/function/Supplier; >>>>>> 13: astore_2 >>>>>> 14: return >>>>>> >>>>>> BootstrapMethods: >>>>>> 0: #18 invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; >>>>>> Method arguments: >>>>>> #19 ()Ljava/lang/Object; >>>>>> #20 invokevirtual Test.m:()Ljava/lang/String; >>>>>> #21 ()Ljava/lang/String; >>>>>> 1: #18 invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; >>>>>> Method arguments: >>>>>> #19 ()Ljava/lang/Object; >>>>>> #20 invokevirtual Test.m:()Ljava/lang/String; >>>>>> #19 ()Ljava/lang/Object; >>>>>> >>>>>> >>>>>> As you can see, both invokedynamic share the same SAM type - the erased java/util/function/Supplier. The only difference between the two indys is the method type passed as 3rd static argument - in one case ()String is passed, in the other ()Object is passed - that dictates the signature of the dynamically generated method implementing the sam type. >>>>>> >>>>>> In other words, if the lambda metafactory used the same instance for both method references, everything would still work (in fact, the generated bytecode is the same for both classes!). >>>>>> >>>>>> Maurizio >>>>>> >>>>>> >>>>>> >>>>>> On 18/01/17 18:06, Oliver Gierke wrote: >>>>>>> Hi again, >>>>>>> >>>>>>> didn't get much response but it looks like there are some improvements for lambdas planned for at least JDK10 [0]. Is what I asked for below maybe a candidate for inclusion into those efforts? >>>>>>> >>>>>>> Is there maybe a better place to ask for this? >>>>>>> >>>>>>> Cheers, >>>>>>> Ollie >>>>>>> >>>>>>> [0] https://www.infoq.com/news/2017/01/java10-lambda-leftovers >>>>>>> >>>>>>>> Am 23.12.2016 um 12:22 schrieb Oliver Gierke : >>>>>>>> >>>>>>>> Hi all, >>>>>>>> >>>>>>>> Lambda based implementations of SAM types currently don't support inspecting the type for generic type parameters. This can cause unexpected surprise as some high-level API taking a SAM type as parameter is usually an indicator to users, that they can be used with Lambdas. If the object passed in is then inspected for generic types somewhere down the call stack this causes issues. Handing in a dedicated implementation of the SAM type is a workaround bit I think that's highly confusing and can be a source of errors hard to understand and debug. >>>>>>>> >>>>>>>> I've added an example below. >>>>>>>> >>>>>>>> Cheers, >>>>>>>> Ollie >>>>>>>> >>>>>>>> public class LambdaTypeDetectionSample { >>>>>>>> >>>>>>>> public static void main(String[] args) { >>>>>>>> >>>>>>>> Function lambdaFunction = i -> i.toString(); >>>>>>>> Function oldschoolFunction = new Function() { >>>>>>>> >>>>>>>> public String apply(Integer t) { >>>>>>>> return t.toString(); >>>>>>>> } >>>>>>>> }; >>>>>>>> >>>>>>>> printTypeArguments(oldschoolFunction); >>>>>>>> >>>>>>>> // Yields: >>>>>>>> // java.util.function.Function is a class sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl >>>>>>>> // class java.lang.Integer >>>>>>>> // class java.lang.String >>>>>>>> >>>>>>>> printTypeArguments(lambdaFunction); >>>>>>>> >>>>>>>> // Yields: >>>>>>>> // interface java.util.function.Function is a class java.lang.Class >>>>>>>> } >>>>>>>> >>>>>>>> private static void printTypeArguments(Function function) { >>>>>>>> >>>>>>>> Type type = function.getClass().getGenericInterfaces()[0]; >>>>>>>> >>>>>>>> System.out.println(type + " is a " + type.getClass()); >>>>>>>> >>>>>>>> if (type instanceof ParameterizedType) { >>>>>>>> >>>>>>>> ParameterizedType functionInterface = (ParameterizedType) type; >>>>>>>> Arrays.stream(functionInterface.getActualTypeArguments()).forEach(System.out::println); >>>>>>>> } >>>>>>>> } >>>>>>>> } From david.lloyd at redhat.com Thu Jan 11 14:20:42 2018 From: david.lloyd at redhat.com (David Lloyd) Date: Thu, 11 Jan 2018 08:20:42 -0600 Subject: Issues with generic type detection of SAM types implemented using lambdas In-Reply-To: <402E5B8E-743B-4D88-B060-B66836C9616A@pivotal.io> References: <4E1C251C-163A-4093-855F-CEDC043B8524@pivotal.io> <63C94B5C-4E18-4500-9203-15408B98D5EA@pivotal.io> <997D0DBE-4E96-446B-94D7-2800187622E5@pivotal.io> <402E5B8E-743B-4D88-B060-B66836C9616A@pivotal.io> Message-ID: On Thu, Jan 11, 2018 at 8:03 AM, Oliver Gierke wrote: >> Am 11.01.2018 um 14:56 schrieb David Lloyd : >> >> On Thu, Jan 11, 2018 at 3:10 AM, Oliver Gierke wrote: >>> Lambda based implementations of SAM types currently don't support inspecting the type for generic type parameters. This can cause unexpected surprise... >> >> Here's a non-lambda example that demonstrates that inspecting *any* >> class for generic type parameters is fragile and not a good idea: >> >> public final class Hasher implements ToIntFunction { >> int applyAsInt(T value) { return value.hashCode(); } >> } >> >> Oops, now all my concrete implementations have generic parameters. > > I'm afraid I can't follow. Your example code which prints the actual type arguments will fail because there is no actual type argument declared on the generic *type*, only the *instance*. If you create an API which relies on getting actual types off of an object instance's class, you've made a usability mistake. >> Telling users they cannot have generic parameters on their >> implementation classes is poor API design. > > Who is actually doing that? "I just wanted to point out that an ordinary user -- in general client code that uses APIs with SAM types -- *has to implicitly know* whether *any code* (potentially Java 6 based) downstream might attempt generics resolution before she can decide whether to use a Lambda with this SAM type." Anyone who wrote one of these APIs is actually doing that. It has nothing to do with lambdas, and everything to do with APIs relying on the assumption that implementation classes will have actual values for every type parameter that it may inherit. This assumption is flawed because it's completely normal for a user to have a single function implementation that works for many types; this is a solid memory-conserving technique. The only thing broken by this are "clever" APIs that require usage of getActualTypeArguments() to get necessary information from the user. -- - DML From ogierke at pivotal.io Thu Jan 11 15:34:26 2018 From: ogierke at pivotal.io (Oliver Gierke) Date: Thu, 11 Jan 2018 16:34:26 +0100 Subject: Issues with generic type detection of SAM types implemented using lambdas In-Reply-To: References: <4E1C251C-163A-4093-855F-CEDC043B8524@pivotal.io> <63C94B5C-4E18-4500-9203-15408B98D5EA@pivotal.io> <997D0DBE-4E96-446B-94D7-2800187622E5@pivotal.io> <402E5B8E-743B-4D88-B060-B66836C9616A@pivotal.io> Message-ID: <45FB6F6B-2242-49A6-A8B1-51423D94C53C@pivotal.io> Again, I think we're discussing different things here. You refer to the fact that from an instance of a generic class, without creating an anonymous subtype, there's no way to find out about the generic type they've been bound to. That's fine and - I guess - common knowledge amongst Java developers. I am looking a different case and thus a different problem: Lambdas have been advertised as a direct alternative to anonymous classes (see [0], esp. section 12), and that's the reason IDEs unconditionally recommend to convert the latter into the former. However, for a given generic interface, reflecting over the declared generics in the Lambda variant behaves fundamentally different compared to an anonymous implementation. So I am pretty passionless on whether that's "trying to be clever" or "bad". I was merely pointing out an inconsistency. Cheers, Ollie [0] http://cr.openjdk.java.net/~briangoetz/lambda/lambda-state-final.html > Am 11.01.2018 um 15:20 schrieb David Lloyd : > > On Thu, Jan 11, 2018 at 8:03 AM, Oliver Gierke wrote: >>> Am 11.01.2018 um 14:56 schrieb David Lloyd : >>> >>> On Thu, Jan 11, 2018 at 3:10 AM, Oliver Gierke wrote: >>>> Lambda based implementations of SAM types currently don't support inspecting the type for generic type parameters. This can cause unexpected surprise... >>> >>> Here's a non-lambda example that demonstrates that inspecting *any* >>> class for generic type parameters is fragile and not a good idea: >>> >>> public final class Hasher implements ToIntFunction { >>> int applyAsInt(T value) { return value.hashCode(); } >>> } >>> >>> Oops, now all my concrete implementations have generic parameters. >> >> I'm afraid I can't follow. > > Your example code which prints the actual type arguments will fail > because there is no actual type argument declared on the generic > *type*, only the *instance*. If you create an API which relies on > getting actual types off of an object instance's class, you've made a > usability mistake. > >>> Telling users they cannot have generic parameters on their >>> implementation classes is poor API design. >> >> Who is actually doing that? > > "I just wanted to point out that an ordinary user -- in general client > code that uses APIs with SAM types -- *has to implicitly know* whether > *any code* (potentially Java 6 based) downstream might attempt > generics resolution before she can decide whether to use a Lambda with > this SAM type." > > Anyone who wrote one of these APIs is actually doing that. It has > nothing to do with lambdas, and everything to do with APIs relying on > the assumption that implementation classes will have actual values for > every type parameter that it may inherit. This assumption is flawed > because it's completely normal for a user to have a single function > implementation that works for many types; this is a solid > memory-conserving technique. The only thing broken by this are > "clever" APIs that require usage of getActualTypeArguments() to get > necessary information from the user. > > -- > - DML -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: Message signed with OpenPGP URL: From eliasvasylenko at gmail.com Thu Jan 11 16:08:22 2018 From: eliasvasylenko at gmail.com (elias vasylenko) Date: Thu, 11 Jan 2018 16:08:22 +0000 Subject: Issues with generic type detection of SAM types implemented using lambdas In-Reply-To: <45FB6F6B-2242-49A6-A8B1-51423D94C53C@pivotal.io> References: <4E1C251C-163A-4093-855F-CEDC043B8524@pivotal.io> <63C94B5C-4E18-4500-9203-15408B98D5EA@pivotal.io> <997D0DBE-4E96-446B-94D7-2800187622E5@pivotal.io> <402E5B8E-743B-4D88-B060-B66836C9616A@pivotal.io> <45FB6F6B-2242-49A6-A8B1-51423D94C53C@pivotal.io> Message-ID: I don't think you are discussing different things at all, Oliver. You have presented your argument from two points of view: - Users can't pass lambdas to methods unless they know for sure that the implementation isn't relying on being able to reflect over generic type parameters. - As a result, library implementors / API designers can't rely on generic type information being available. David's point is that *both of these statements were already true* for regular classes before lambdas came along. What difference does it make if you have one more special case you need your users to avoid? Either you already properly document these awkward restrictions of argument types where it is not obvious and deem it an acceptable risk, in which case you only need to make a minor change to this documentation, or your API was already broken. On Thu, 11 Jan 2018 at 15:34 Oliver Gierke wrote: > Again, I think we're discussing different things here. You refer to the > fact that from an instance of a generic class, without creating an > anonymous subtype, there's no way to find out about the generic type > they've been bound to. That's fine and - I guess - common knowledge amongst > Java developers. > > I am looking a different case and thus a different problem: Lambdas have > been advertised as a direct alternative to anonymous classes (see [0], esp. > section 12), and that's the reason IDEs unconditionally recommend to > convert the latter into the former. However, for a given generic interface, > reflecting over the declared generics in the Lambda variant behaves > fundamentally different compared to an anonymous implementation. > > So I am pretty passionless on whether that's "trying to be clever" or > "bad". I was merely pointing out an inconsistency. > > Cheers, > Ollie > > [0] http://cr.openjdk.java.net/~briangoetz/lambda/lambda-state-final.html > > > Am 11.01.2018 um 15:20 schrieb David Lloyd : > > > > On Thu, Jan 11, 2018 at 8:03 AM, Oliver Gierke > wrote: > >>> Am 11.01.2018 um 14:56 schrieb David Lloyd : > >>> > >>> On Thu, Jan 11, 2018 at 3:10 AM, Oliver Gierke > wrote: > >>>> Lambda based implementations of SAM types currently don't support > inspecting the type for generic type parameters. This can cause unexpected > surprise... > >>> > >>> Here's a non-lambda example that demonstrates that inspecting *any* > >>> class for generic type parameters is fragile and not a good idea: > >>> > >>> public final class Hasher implements ToIntFunction { > >>> int applyAsInt(T value) { return value.hashCode(); } > >>> } > >>> > >>> Oops, now all my concrete implementations have generic parameters. > >> > >> I'm afraid I can't follow. > > > > Your example code which prints the actual type arguments will fail > > because there is no actual type argument declared on the generic > > *type*, only the *instance*. If you create an API which relies on > > getting actual types off of an object instance's class, you've made a > > usability mistake. > > > >>> Telling users they cannot have generic parameters on their > >>> implementation classes is poor API design. > >> > >> Who is actually doing that? > > > > "I just wanted to point out that an ordinary user -- in general client > > code that uses APIs with SAM types -- *has to implicitly know* whether > > *any code* (potentially Java 6 based) downstream might attempt > > generics resolution before she can decide whether to use a Lambda with > > this SAM type." > > > > Anyone who wrote one of these APIs is actually doing that. It has > > nothing to do with lambdas, and everything to do with APIs relying on > > the assumption that implementation classes will have actual values for > > every type parameter that it may inherit. This assumption is flawed > > because it's completely normal for a user to have a single function > > implementation that works for many types; this is a solid > > memory-conserving technique. The only thing broken by this are > > "clever" APIs that require usage of getActualTypeArguments() to get > > necessary information from the user. > > > > -- > > - DML > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From ogierke at pivotal.io Thu Jan 11 16:47:43 2018 From: ogierke at pivotal.io (Oliver Gierke) Date: Thu, 11 Jan 2018 17:47:43 +0100 Subject: Issues with generic type detection of SAM types implemented using lambdas In-Reply-To: References: <4E1C251C-163A-4093-855F-CEDC043B8524@pivotal.io> <63C94B5C-4E18-4500-9203-15408B98D5EA@pivotal.io> <997D0DBE-4E96-446B-94D7-2800187622E5@pivotal.io> <402E5B8E-743B-4D88-B060-B66836C9616A@pivotal.io> <45FB6F6B-2242-49A6-A8B1-51423D94C53C@pivotal.io> Message-ID: Yes, and no. You basically argue we're discussing the same things, immediately describing two *different* things being discussed: 1. There's a difference between instances of a generic type and anonymous (or plain implementation) classes and that has always been the case. Essentially "new ArrayList();" VS "new ArrayList() {}" (mind the curly braces). Yes. That's correct. Nobody is disputing that. We can assume Java developers being familiar with that distinction. There's no one arguing the two are exchangeable in terms of generics resolution. 2. There's a difference between Lambdas and anonymous classes. The former are widely presented as equivalent of the latter *That* is my point. As I see every other week, in contrast to the one above, not a lot of Java developers are familiar with *that* difference and caught by surprise. Function lambdaFunction = i -> i.toString(); Function oldschoolFunction = new Function() { public String apply(Integer t) { return t.toString(); } }; Basically, 2 is invalidating 1 *if* we assume that the expressions in 2 are equivalent and virtually *every* resource around lambdas on the web suggest that they are. The upper right side (i -> ?) is supposed to be a direct replace for the lower (new Function "The upper is equivalent to the lower" -> "The upper is creating type information to allow generics resolution". You might think that's crazily naive to assume that as you're all familiar with the complex intrinsics of all of that but it seems to be a very common source of confusion. Anyway, I guess I've made my point an we're just gonna have to agree to disagree here :). Cheers, Ollie > Am 11.01.2018 um 17:08 schrieb elias vasylenko : > > I don't think you are discussing different things at all, Oliver. > > You have presented your argument from two points of view: > > - Users can't pass lambdas to methods unless they know for sure that the implementation isn't relying on being able to reflect over generic type parameters. > > - As a result, library implementors / API designers can't rely on generic type information being available. > > David's point is that both of these statements were already true for regular classes before lambdas came along. > > What difference does it make if you have one more special case you need your users to avoid? Either you already properly document these awkward restrictions of argument types where it is not obvious and deem it an acceptable risk, in which case you only need to make a minor change to this documentation, or your API was already broken. > > On Thu, 11 Jan 2018 at 15:34 Oliver Gierke wrote: > Again, I think we're discussing different things here. You refer to the fact that from an instance of a generic class, without creating an anonymous subtype, there's no way to find out about the generic type they've been bound to. That's fine and - I guess - common knowledge amongst Java developers. > > I am looking a different case and thus a different problem: Lambdas have been advertised as a direct alternative to anonymous classes (see [0], esp. section 12), and that's the reason IDEs unconditionally recommend to convert the latter into the former. However, for a given generic interface, reflecting over the declared generics in the Lambda variant behaves fundamentally different compared to an anonymous implementation. > > So I am pretty passionless on whether that's "trying to be clever" or "bad". I was merely pointing out an inconsistency. > > Cheers, > Ollie > > [0] http://cr.openjdk.java.net/~briangoetz/lambda/lambda-state-final.html > > > Am 11.01.2018 um 15:20 schrieb David Lloyd : > > > > On Thu, Jan 11, 2018 at 8:03 AM, Oliver Gierke wrote: > >>> Am 11.01.2018 um 14:56 schrieb David Lloyd : > >>> > >>> On Thu, Jan 11, 2018 at 3:10 AM, Oliver Gierke wrote: > >>>> Lambda based implementations of SAM types currently don't support inspecting the type for generic type parameters. This can cause unexpected surprise... > >>> > >>> Here's a non-lambda example that demonstrates that inspecting *any* > >>> class for generic type parameters is fragile and not a good idea: > >>> > >>> public final class Hasher implements ToIntFunction { > >>> int applyAsInt(T value) { return value.hashCode(); } > >>> } > >>> > >>> Oops, now all my concrete implementations have generic parameters. > >> > >> I'm afraid I can't follow. > > > > Your example code which prints the actual type arguments will fail > > because there is no actual type argument declared on the generic > > *type*, only the *instance*. If you create an API which relies on > > getting actual types off of an object instance's class, you've made a > > usability mistake. > > > >>> Telling users they cannot have generic parameters on their > >>> implementation classes is poor API design. > >> > >> Who is actually doing that? > > > > "I just wanted to point out that an ordinary user -- in general client > > code that uses APIs with SAM types -- *has to implicitly know* whether > > *any code* (potentially Java 6 based) downstream might attempt > > generics resolution before she can decide whether to use a Lambda with > > this SAM type." > > > > Anyone who wrote one of these APIs is actually doing that. It has > > nothing to do with lambdas, and everything to do with APIs relying on > > the assumption that implementation classes will have actual values for > > every type parameter that it may inherit. This assumption is flawed > > because it's completely normal for a user to have a single function > > implementation that works for many types; this is a solid > > memory-conserving technique. The only thing broken by this are > > "clever" APIs that require usage of getActualTypeArguments() to get > > necessary information from the user. > > > > -- > > - DML > -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: Message signed with OpenPGP URL: From vicente.romero at oracle.com Thu Jan 11 16:54:18 2018 From: vicente.romero at oracle.com (Vicente Romero) Date: Thu, 11 Jan 2018 11:54:18 -0500 Subject: RFR: JDK-8194893: javac -verbose prints wrong paths for output files In-Reply-To: <5A5689B3.9060400@oracle.com> References: <5A5689B3.9060400@oracle.com> Message-ID: looks good, Vicente On 01/10/2018 04:46 PM, Jonathan Gibbons wrote: > Please review a trivial fix and test for the output from "javac > -verbose". > > JBS: https://bugs.openjdk.java.net/browse/JDK-8194893 > Webrev: http://cr.openjdk.java.net/~jjg/8194893/webrev.00/index.html > > -- Jon From vicente.romero at oracle.com Thu Jan 11 17:03:28 2018 From: vicente.romero at oracle.com (Vicente Romero) Date: Thu, 11 Jan 2018 12:03:28 -0500 Subject: RFR: JDK-8151850: eliminate javax.tools.FileManagerUtils In-Reply-To: <5A56B119.1090009@oracle.com> References: <5A56B119.1090009@oracle.com> Message-ID: <2edcd963-8ef9-f2d1-7de4-7c3c8c266242@oracle.com> looks good On 01/10/2018 07:34 PM, Jonathan Gibbons wrote: > Please review a simple cleanup fix, that uses private interface > methods to replace the use of a package-private class, that was > previously necessary. > > JBS: https://bugs.openjdk.java.net/browse/JDK-8151850 > Webrev: http://cr.openjdk.java.net/~jjg/8151850/webrev.00/ > > -- Jon From maurizio.cimadamore at oracle.com Thu Jan 11 18:20:04 2018 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 11 Jan 2018 18:20:04 +0000 Subject: RFR 8194932: no ambuguity error is emitted if classfile contains two identical methods with different return types Message-ID: <818ceef3-a5ce-a394-e85e-b7b4a55fa43c@oracle.com> Hi, this is a fix for an issue that has to do with compilation from classfile. While typically it is not possible for a Java source to contain two override equivalent method (as that would be flagged as method clash by javac), when a classfile contains two methods that have the same signature but different return types (which is possible at the classfile level), javac doesn't generate an ambiguity error when such method is called. Instead, javac non-deterministically resolves the call to the first method being declared in the classfile. The solution is to omit a part of the override check that is run in Resolve::mostSpecific (**). That is, this part should be disabled if the owner of both potentially ambiguous methods is the same. Extra code was added to handle the case of statically imported methods, in which case javac clones the imported method symbols and replaces their owner to make sure that the bytecode comes out in a certain way. So, if javac detects that the 'base' symbol of both methods is indeed the same - it means that the same symol was imported (and cloned) twice, so we can just return either. At this point, we should never have a case where we have two maximally specific concrete methods with same owner (unless we are in the classfile case). http://cr.openjdk.java.net/~mcimadamore/8194932/ (**) the override check performed by javac is outside the spec, but necessary because javac doesn't filter overload candidates by accessibility - that is, overridden methods are played through the javac overload resoluytion machinery, and javac prefers the overridden version of a method; this is an unfortunate, but historical, javac design choice. Cheers Maurizio From maurizio.cimadamore at oracle.com Thu Jan 11 18:22:42 2018 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 11 Jan 2018 18:22:42 +0000 Subject: RFR 8194932: no ambuguity error is emitted if classfile contains two identical methods with different return types In-Reply-To: <818ceef3-a5ce-a394-e85e-b7b4a55fa43c@oracle.com> References: <818ceef3-a5ce-a394-e85e-b7b4a55fa43c@oracle.com> Message-ID: <739041c0-fcfe-4264-e3df-95f35096ab94@oracle.com> On 11/01/18 18:20, Maurizio Cimadamore wrote: > and javac prefers the overridden version of a method; Whoops - obviously I meant 'prefers the overridding version...' Maurizio From joe.darcy at oracle.com Thu Jan 11 22:52:52 2018 From: joe.darcy at oracle.com (joe darcy) Date: Thu, 11 Jan 2018 14:52:52 -0800 Subject: JDK 10/11 RFR of JDK-8189146: Have use of "var" in 9 and earlier source versions issue a warning In-Reply-To: <665b4df5-a855-133b-8725-14e366600516@oracle.com> References: <9475d5e8-977d-4c84-6a19-b368834cce33@oracle.com> <665b4df5-a855-133b-8725-14e366600516@oracle.com> Message-ID: <345994a8-4fd9-97a9-98bf-81ab3fbdc8a4@oracle.com> Hi Maurizio, On 1/9/2018 4:39 PM, Maurizio Cimadamore wrote: > Thanks for the update. This is close, but compared to the existing > golden file, as you noticed, there are missing warnings, esp. when > 'var' is used as an array element type. > > I believe the issue is with this code: > > if (Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source) && > elemType.hasTag(IDENT)) { > 2998 Name typeName = ((JCIdent)elemType).name; > 2999 if (isRestrictedLocalVarTypeName(typeName, pos)) { > 3000 if (type.hasTag(TYPEARRAY)) { > 3001 //error - 'var' and arrays > 3002 reportSyntaxError(pos, "var.not.allowed.array"); > 3003 } else { > 3004 startPos = TreeInfo.getStartPos(mods); > 3005 if (startPos == Position.NOPOS) > 3006 startPos = TreeInfo.getStartPos(type); > 3007 //implicit type > 3008 type = null; > 3009 } > 3010 } > 3011 } > > > Here, if LVTI is disabled, the 'isRestrictedLocalVarTypeName' call > would not even take place, hence the missing warnings. I suggest to > shuffle as follows: > > if (elemType.hasTag(IDENT)) { > 2998 Name typeName = ((JCIdent)elemType).name; > 2999 if (isRestrictedLocalVarTypeName(typeName, pos)) { > 3000 if (type.hasTag(TYPEARRAY)) { > 3001 //error - 'var' and arrays > 3002 reportSyntaxError(pos, "var.not.allowed.array"); > 3003 } else { > 3004 startPos = TreeInfo.getStartPos(mods); > 3005 if (startPos == Position.NOPOS) > 3006 startPos = TreeInfo.getStartPos(type); > 3007 //implicit type > 3008 type = null; > 3009 } > 3010 } > 3011 } When I tried that out, there were more warnings; too many actually, there were double warnings issued in some cases: /test/langtools/tools/javac/lvti/ParserTest.java:38: warning: as of release 10, 'var' is a restricted local variable type and cannot be used for type declarations or as the element type of an array var x = null; //illegal ^ /test/langtools/tools/javac/lvti/ParserTest.java:38: warning: as of release 10, 'var' is a restricted local variable type and cannot be used for type declarations or as the element type of an array var x = null; //illegal ^ and /home/darcy/JDK/10/hg/test/langtools/tools/javac/lvti/ParserTest.java:49: warning: as of release 10, 'var' is a restricted local variable type and cannot be used for type declarations or as the element type of an array var x9 = null, y = null; //illegal ^ /home/darcy/JDK/10/hg/test/langtools/tools/javac/lvti/ParserTest.java:49: warning: as of release 10, 'var' is a restricted local variable type and cannot be used for type declarations or as the element type of an array var x9 = null, y = null; //illegal ^ Stepping back a bit, if "var" were added as a full new keyword then the check for a use of "var" could occur within the ident() method, as is done for underscore. However, since "var" is allowed its traditional use in some contexts, the error/warning checks need to be dependent on the syntactic context. For pre-10, only a syntactic check needs occur, e.g. a construct like "var x = 5, y = 6" does not merit a warning about y having a var type; although that check is needed in 10 and later. Therefore I moved a check out to the method for the containing grammar production: http://cr.openjdk.java.net/~darcy/8189146.3/ I also changed the wording of the warning message slightly to be more inclusive of the situations it was covering. (More precisely worded warning could be given for different situations, but I don't think that is strictly necessary.) One "var" warning/error check occurs now in typeName, which catches class/interface/enum/annotation/type var declaration usage, and needs to occur in some way for at least certain idents occurring in variable declarations, including in try-with-resources. I made some updates to the ParserTest to better cover try-with-resources and took a somewhat different tack to attempt to get the right set of warnings issues. Unfortunately, there were duplicates here as well: /test/langtools/tools/javac/lvti/ParserTest.java:38: warning: as of release 10, 'var' is a restricted local variable type and cannot be used for type declarations or as the element type of an array var x = null; //illegal ^ /test/langtools/tools/javac/lvti/ParserTest.java:38: warning: as of release 10, 'var' is a restricted local variable type and cannot be used for type declarations or as the element type of an array var x = null; //illegal ^ /test/langtools/tools/javac/lvti/ParserTest.java:50: warning: as of release 10, 'var' is a restricted local variable type and cannot be used for type declarations or as the element type of an array final @DA var x10 = m(); //ok ^ /test/langtools/tools/javac/lvti/ParserTest.java:50: warning: as of release 10, 'var' is a restricted local variable type and cannot be used for type declarations or as the element type of an array final @DA var x10 = m(); //ok ^ /test/langtools/tools/javac/lvti/ParserTest.java:51: warning: as of release 10, 'var' is a restricted local variable type and cannot be used for type declarations or as the element type of an array @DA final var x11 = m(); //ok ^ /test/langtools/tools/javac/lvti/ParserTest.java:51: warning: as of release 10, 'var' is a restricted local variable type and cannot be used for type declarations or as the element type of an array @DA final var x11 = m(); //ok Hopefully any additional modifications needed will be minor! Thanks, -Joe From maurizio.cimadamore at oracle.com Thu Jan 11 23:56:39 2018 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 11 Jan 2018 23:56:39 +0000 Subject: JDK 10/11 RFR of JDK-8189146: Have use of "var" in 9 and earlier source versions issue a warning In-Reply-To: <345994a8-4fd9-97a9-98bf-81ab3fbdc8a4@oracle.com> References: <9475d5e8-977d-4c84-6a19-b368834cce33@oracle.com> <665b4df5-a855-133b-8725-14e366600516@oracle.com> <345994a8-4fd9-97a9-98bf-81ab3fbdc8a4@oracle.com> Message-ID: On 11/01/18 22:52, joe darcy wrote: > Hi Maurizio, > > On 1/9/2018 4:39 PM, Maurizio Cimadamore wrote: >> Thanks for the update. This is close, but compared to the existing >> golden file, as you noticed, there are missing warnings, esp. when >> 'var' is used as an array element type. >> >> I believe the issue is with this code: >> >> if (Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source) && >> elemType.hasTag(IDENT)) { >> 2998???????????? Name typeName = ((JCIdent)elemType).name; >> 2999???????????? if (isRestrictedLocalVarTypeName(typeName, pos)) { >> 3000???????????????? if (type.hasTag(TYPEARRAY)) { >> 3001???????????????????? //error - 'var' and arrays >> 3002???????????????????? reportSyntaxError(pos, >> "var.not.allowed.array"); >> 3003???????????????? } else { >> 3004???????????????????? startPos = TreeInfo.getStartPos(mods); >> 3005???????????????????? if (startPos == Position.NOPOS) >> 3006???????????????????????? startPos = TreeInfo.getStartPos(type); >> 3007???????????????????? //implicit type >> 3008???????????????????? type = null; >> 3009???????????????? } >> 3010???????????? } >> 3011???????? } >> >> >> Here, if LVTI is disabled, the 'isRestrictedLocalVarTypeName' call >> would not even take place, hence the missing warnings. I suggest to >> shuffle as follows: >> >> if (elemType.hasTag(IDENT)) { >> 2998???????????? Name typeName = ((JCIdent)elemType).name; >> 2999???????????? if (isRestrictedLocalVarTypeName(typeName, pos)) { >> 3000???????????????? if (type.hasTag(TYPEARRAY)) { >> 3001???????????????????? //error - 'var' and arrays >> 3002???????????????????? reportSyntaxError(pos, >> "var.not.allowed.array"); >> 3003???????????????? } else { >> 3004???????????????????? startPos = TreeInfo.getStartPos(mods); >> 3005???????????????????? if (startPos == Position.NOPOS) >> 3006???????????????????????? startPos = TreeInfo.getStartPos(type); >> 3007???????????????????? //implicit type >> 3008???????????????????? type = null; >> 3009???????????????? } >> 3010???????????? } >> 3011???????? } > > When I tried that out, there were more warnings; too many actually, > there were double warnings issued in some cases: > > /test/langtools/tools/javac/lvti/ParserTest.java:38: warning: as of > release 10, 'var' is a restricted local variable type and cannot be > used for type declarations or as the element type of an array > ??? var x = null; //illegal > ??? ^ > /test/langtools/tools/javac/lvti/ParserTest.java:38: warning: as of > release 10, 'var' is a restricted local variable type and cannot be > used for type declarations or as the element type of an array > ??? var x = null; //illegal > ??????? ^ > and > > /home/darcy/JDK/10/hg/test/langtools/tools/javac/lvti/ParserTest.java:49: > warning: as of release 10, 'var' is a restricted local variable type > and cannot be used for type declarations or as the element type of an > array > ??????? var x9 = null, y = null; //illegal > ??????????? ^ > /home/darcy/JDK/10/hg/test/langtools/tools/javac/lvti/ParserTest.java:49: > warning: as of release 10, 'var' is a restricted local variable type > and cannot be used for type declarations or as the element type of an > array > ??????? var x9 = null, y = null; //illegal > ?????????????????????? ^ I will think about this a bit more - this (or something very similar) should work. Maurizio > > Stepping back a bit, if "var" were added as a full new keyword then > the check for a use of "var" could occur within the ident() method, as > is done for underscore. However, since "var" is allowed its > traditional use in some contexts, the error/warning checks need to be > dependent on the syntactic context. For pre-10, only a syntactic check > needs occur, e.g. a construct like "var x = 5, y = 6" does not merit a > warning about y having a var type; although that check is needed in 10 > and later. Therefore I moved a check out to the method for the > containing grammar production: > > ??? http://cr.openjdk.java.net/~darcy/8189146.3/ > > I also changed the wording of the warning message slightly to be more > inclusive of the situations it was covering. (More precisely worded > warning could be given for different situations, but I don't think > that is strictly necessary.) > > One "var" warning/error check occurs now in typeName, which catches > class/interface/enum/annotation/type var declaration usage, and needs > to occur in some way for at least certain idents occurring in variable > declarations, including in try-with-resources. > > I made some updates to the ParserTest to better cover > try-with-resources and took a somewhat different tack to attempt to > get the right set of warnings issues. Unfortunately, there were > duplicates here as well: > > /test/langtools/tools/javac/lvti/ParserTest.java:38: warning: as of > release 10, 'var' is a restricted local variable type and cannot be > used for type declarations or as the element type of an array > ??? var x = null; //illegal > ??? ^ > /test/langtools/tools/javac/lvti/ParserTest.java:38: warning: as of > release 10, 'var' is a restricted local variable type and cannot be > used for type declarations or as the element type of an array > ??? var x = null; //illegal > ??? ^ > > /test/langtools/tools/javac/lvti/ParserTest.java:50: warning: as of > release 10, 'var' is a restricted local variable type and cannot be > used for type declarations or as the element type of an array > ??????? final @DA var x10 = m(); //ok > ????????????????? ^ > /test/langtools/tools/javac/lvti/ParserTest.java:50: warning: as of > release 10, 'var' is a restricted local variable type and cannot be > used for type declarations or as the element type of an array > ??????? final @DA var x10 = m(); //ok > ????????????????? ^ > /test/langtools/tools/javac/lvti/ParserTest.java:51: warning: as of > release 10, 'var' is a restricted local variable type and cannot be > used for type declarations or as the element type of an array > ??????? @DA final var x11 = m(); //ok > ????????????????? ^ > /test/langtools/tools/javac/lvti/ParserTest.java:51: warning: as of > release 10, 'var' is a restricted local variable type and cannot be > used for type declarations or as the element type of an array > ??????? @DA final var x11 = m(); //ok > > Hopefully any additional modifications needed will be minor! > > Thanks, > > -Joe > From cushon at google.com Fri Jan 12 06:12:17 2018 From: cushon at google.com (Liam Miller-Cushon) Date: Thu, 11 Jan 2018 22:12:17 -0800 Subject: RFR: JDK-8179373: javac -verbose logs the class path multiple times Message-ID: Please review (another) trivial fix for the output from "javac -verbose". bug: https://bugs.openjdk.java.net/browse/JDK-8179373 webrev: http://cr.openjdk.java.net/~cushon/8179373/webrev.00/ Thanks, Liam -------------- next part -------------- An HTML attachment was scrubbed... URL: From maurizio.cimadamore at oracle.com Fri Jan 12 13:13:09 2018 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Fri, 12 Jan 2018 13:13:09 +0000 Subject: JDK 10/11 RFR of JDK-8189146: Have use of "var" in 9 and earlier source versions issue a warning In-Reply-To: References: <9475d5e8-977d-4c84-6a19-b368834cce33@oracle.com> <665b4df5-a855-133b-8725-14e366600516@oracle.com> <345994a8-4fd9-97a9-98bf-81ab3fbdc8a4@oracle.com> Message-ID: Hey Joe, here's my take on the patch: http://cr.openjdk.java.net/~mcimadamore/8189146/ it is similar to what I initially proposed, but I had to fight a bit with the parser in order to get rid of the duplicate warnings. The issue is that warnings can be reported both through the 'parseType' path and the 'variableDeclaratorRest' path, as the overlapping between the two is non trivial (sometimes javac parses a local var decl type as a type, sometimes as an expr, depending on whether javac is 'sure' that the thing is a variable decl - whose production is ambiguous with almost anything else :-)). The solution is to add a flag to the isRestrictedLocalVarName so that in certain cases the warning generation is suppressed. I have also consolidated the treatment of the errors occurring because of the use of 'var' in a compound declaration - now the errors are reported in the same place where errors about 'var and array' is reported, which makes a bunch of things easier. Lastly, I've cleaned up some of the diagnostic used - as they were using a diagnostic argument which was alway set to the name 'var'. I believe that's a leftover of when we accepted both 'var' and 'val', and I have now removed it. I believe what comes out of the compiler is in sync with what you wanted, but the patch is not as trivial as we originally had hoped, which, in my mind, makes it more for 11 than for 10. Cheers Maurizio On 11/01/18 23:56, Maurizio Cimadamore wrote: > > > On 11/01/18 22:52, joe darcy wrote: >> Hi Maurizio, >> >> On 1/9/2018 4:39 PM, Maurizio Cimadamore wrote: >>> Thanks for the update. This is close, but compared to the existing >>> golden file, as you noticed, there are missing warnings, esp. when >>> 'var' is used as an array element type. >>> >>> I believe the issue is with this code: >>> >>> if (Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source) && >>> elemType.hasTag(IDENT)) { >>> 2998???????????? Name typeName = ((JCIdent)elemType).name; >>> 2999???????????? if (isRestrictedLocalVarTypeName(typeName, pos)) { >>> 3000???????????????? if (type.hasTag(TYPEARRAY)) { >>> 3001???????????????????? //error - 'var' and arrays >>> 3002???????????????????? reportSyntaxError(pos, >>> "var.not.allowed.array"); >>> 3003???????????????? } else { >>> 3004???????????????????? startPos = TreeInfo.getStartPos(mods); >>> 3005???????????????????? if (startPos == Position.NOPOS) >>> 3006???????????????????????? startPos = TreeInfo.getStartPos(type); >>> 3007???????????????????? //implicit type >>> 3008???????????????????? type = null; >>> 3009???????????????? } >>> 3010???????????? } >>> 3011???????? } >>> >>> >>> Here, if LVTI is disabled, the 'isRestrictedLocalVarTypeName' call >>> would not even take place, hence the missing warnings. I suggest to >>> shuffle as follows: >>> >>> if (elemType.hasTag(IDENT)) { >>> 2998???????????? Name typeName = ((JCIdent)elemType).name; >>> 2999???????????? if (isRestrictedLocalVarTypeName(typeName, pos)) { >>> 3000???????????????? if (type.hasTag(TYPEARRAY)) { >>> 3001???????????????????? //error - 'var' and arrays >>> 3002???????????????????? reportSyntaxError(pos, >>> "var.not.allowed.array"); >>> 3003???????????????? } else { >>> 3004???????????????????? startPos = TreeInfo.getStartPos(mods); >>> 3005???????????????????? if (startPos == Position.NOPOS) >>> 3006???????????????????????? startPos = TreeInfo.getStartPos(type); >>> 3007???????????????????? //implicit type >>> 3008???????????????????? type = null; >>> 3009???????????????? } >>> 3010???????????? } >>> 3011???????? } >> >> When I tried that out, there were more warnings; too many actually, >> there were double warnings issued in some cases: >> >> /test/langtools/tools/javac/lvti/ParserTest.java:38: warning: as of >> release 10, 'var' is a restricted local variable type and cannot be >> used for type declarations or as the element type of an array >> ??? var x = null; //illegal >> ??? ^ >> /test/langtools/tools/javac/lvti/ParserTest.java:38: warning: as of >> release 10, 'var' is a restricted local variable type and cannot be >> used for type declarations or as the element type of an array >> ??? var x = null; //illegal >> ??????? ^ >> and >> >> /home/darcy/JDK/10/hg/test/langtools/tools/javac/lvti/ParserTest.java:49: >> warning: as of release 10, 'var' is a restricted local variable type >> and cannot be used for type declarations or as the element type of an >> array >> ??????? var x9 = null, y = null; //illegal >> ??????????? ^ >> /home/darcy/JDK/10/hg/test/langtools/tools/javac/lvti/ParserTest.java:49: >> warning: as of release 10, 'var' is a restricted local variable type >> and cannot be used for type declarations or as the element type of an >> array >> ??????? var x9 = null, y = null; //illegal >> ?????????????????????? ^ > I will think about this a bit more - this (or something very similar) > should work. > > Maurizio >> >> Stepping back a bit, if "var" were added as a full new keyword then >> the check for a use of "var" could occur within the ident() method, >> as is done for underscore. However, since "var" is allowed its >> traditional use in some contexts, the error/warning checks need to be >> dependent on the syntactic context. For pre-10, only a syntactic >> check needs occur, e.g. a construct like "var x = 5, y = 6" does not >> merit a warning about y having a var type; although that check is >> needed in 10 and later. Therefore I moved a check out to the method >> for the containing grammar production: >> >> ??? http://cr.openjdk.java.net/~darcy/8189146.3/ >> >> I also changed the wording of the warning message slightly to be more >> inclusive of the situations it was covering. (More precisely worded >> warning could be given for different situations, but I don't think >> that is strictly necessary.) >> >> One "var" warning/error check occurs now in typeName, which catches >> class/interface/enum/annotation/type var declaration usage, and needs >> to occur in some way for at least certain idents occurring in >> variable declarations, including in try-with-resources. >> >> I made some updates to the ParserTest to better cover >> try-with-resources and took a somewhat different tack to attempt to >> get the right set of warnings issues. Unfortunately, there were >> duplicates here as well: >> >> /test/langtools/tools/javac/lvti/ParserTest.java:38: warning: as of >> release 10, 'var' is a restricted local variable type and cannot be >> used for type declarations or as the element type of an array >> ??? var x = null; //illegal >> ??? ^ >> /test/langtools/tools/javac/lvti/ParserTest.java:38: warning: as of >> release 10, 'var' is a restricted local variable type and cannot be >> used for type declarations or as the element type of an array >> ??? var x = null; //illegal >> ??? ^ >> >> /test/langtools/tools/javac/lvti/ParserTest.java:50: warning: as of >> release 10, 'var' is a restricted local variable type and cannot be >> used for type declarations or as the element type of an array >> ??????? final @DA var x10 = m(); //ok >> ????????????????? ^ >> /test/langtools/tools/javac/lvti/ParserTest.java:50: warning: as of >> release 10, 'var' is a restricted local variable type and cannot be >> used for type declarations or as the element type of an array >> ??????? final @DA var x10 = m(); //ok >> ????????????????? ^ >> /test/langtools/tools/javac/lvti/ParserTest.java:51: warning: as of >> release 10, 'var' is a restricted local variable type and cannot be >> used for type declarations or as the element type of an array >> ??????? @DA final var x11 = m(); //ok >> ????????????????? ^ >> /test/langtools/tools/javac/lvti/ParserTest.java:51: warning: as of >> release 10, 'var' is a restricted local variable type and cannot be >> used for type declarations or as the element type of an array >> ??????? @DA final var x11 = m(); //ok >> >> Hopefully any additional modifications needed will be minor! >> >> Thanks, >> >> -Joe >> > From jan.lahoda at oracle.com Fri Jan 12 13:42:23 2018 From: jan.lahoda at oracle.com (Jan Lahoda) Date: Fri, 12 Jan 2018 14:42:23 +0100 Subject: RFR 8194932: no ambuguity error is emitted if classfile contains two identical methods with different return types In-Reply-To: <818ceef3-a5ce-a394-e85e-b7b4a55fa43c@oracle.com> References: <818ceef3-a5ce-a394-e85e-b7b4a55fa43c@oracle.com> Message-ID: <5A58BB3F.2090002@oracle.com> To me, looks OK. Jan On 11.1.2018 19:20, Maurizio Cimadamore wrote: > Hi, > this is a fix for an issue that has to do with compilation from > classfile. While typically it is not possible for a Java source to > contain two override equivalent method (as that would be flagged as > method clash by javac), when a classfile contains two methods that have > the same signature but different return types (which is possible at the > classfile level), javac doesn't generate an ambiguity error when such > method is called. Instead, javac non-deterministically resolves the call > to the first method being declared in the classfile. > > The solution is to omit a part of the override check that is run in > Resolve::mostSpecific (**). That is, this part should be disabled if the > owner of both potentially ambiguous methods is the same. Extra code was > added to handle the case of statically imported methods, in which case > javac clones the imported method symbols and replaces their owner to > make sure that the bytecode comes out in a certain way. So, if javac > detects that the 'base' symbol of both methods is indeed the same - it > means that the same symol was imported (and cloned) twice, so we can > just return either. At this point, we should never have a case where we > have two maximally specific concrete methods with same owner (unless we > are in the classfile case). > > http://cr.openjdk.java.net/~mcimadamore/8194932/ > > (**) the override check performed by javac is outside the spec, but > necessary because javac doesn't filter overload candidates by > accessibility - that is, overridden methods are played through the javac > overload resoluytion machinery, and javac prefers the overridden version > of a method; this is an unfortunate, but historical, javac design choice. > > Cheers > Maurizio > From vicente.romero at oracle.com Fri Jan 12 14:20:33 2018 From: vicente.romero at oracle.com (Vicente Romero) Date: Fri, 12 Jan 2018 09:20:33 -0500 Subject: RFR 8194932: no ambuguity error is emitted if classfile contains two identical methods with different return types In-Reply-To: <818ceef3-a5ce-a394-e85e-b7b4a55fa43c@oracle.com> References: <818ceef3-a5ce-a394-e85e-b7b4a55fa43c@oracle.com> Message-ID: looks good, Vicente On 01/11/2018 01:20 PM, Maurizio Cimadamore wrote: > Hi, > this is a fix for an issue that has to do with compilation from > classfile. While typically it is not possible for a Java source to > contain two override equivalent method (as that would be flagged as > method clash by javac), when a classfile contains two methods that > have the same signature but different return types (which is possible > at the classfile level), javac doesn't generate an ambiguity error > when such method is called. Instead, javac non-deterministically > resolves the call to the first method being declared in the classfile. > > The solution is to omit a part of the override check that is run in > Resolve::mostSpecific (**). That is, this part should be disabled if > the owner of both potentially ambiguous methods is the same. Extra > code was added to handle the case of statically imported methods, in > which case javac clones the imported method symbols and replaces their > owner to make sure that the bytecode comes out in a certain way. So, > if javac detects that the 'base' symbol of both methods is indeed the > same - it means that the same symol was imported (and cloned) twice, > so we can just return either. At this point, we should never have a > case where we have two maximally specific concrete methods with same > owner (unless we are in the classfile case). > > http://cr.openjdk.java.net/~mcimadamore/8194932/ > > (**) the override check performed by javac is outside the spec, but > necessary because javac doesn't filter overload candidates by > accessibility - that is, overridden methods are played through the > javac overload resoluytion machinery, and javac prefers the overridden > version of a method; this is an unfortunate, but historical, javac > design choice. > > Cheers > Maurizio > From martinrb at google.com Fri Jan 12 14:51:06 2018 From: martinrb at google.com (Martin Buchholz) Date: Fri, 12 Jan 2018 06:51:06 -0800 Subject: RFR: JDK-8179373: javac -verbose logs the class path multiple times In-Reply-To: References: Message-ID: Looks good. Maybe add comment + verbosePath = false; // print once per compile Maybe rename "l" to "line". On Thu, Jan 11, 2018 at 10:12 PM, Liam Miller-Cushon wrote: > Please review (another) trivial fix for the output from "javac -verbose". > > bug: https://bugs.openjdk.java.net/browse/JDK-8179373 > webrev: http://cr.openjdk.java.net/~cushon/8179373/webrev.00/ > > Thanks, > Liam > -------------- next part -------------- An HTML attachment was scrubbed... URL: From cushon at google.com Fri Jan 12 16:31:42 2018 From: cushon at google.com (Liam Miller-Cushon) Date: Fri, 12 Jan 2018 08:31:42 -0800 Subject: RFR: JDK-8179373: javac -verbose logs the class path multiple times In-Reply-To: References: Message-ID: Thanks, done: http://cr.openjdk.java.net/~cushon/8179373/webrev.01/ On Fri, Jan 12, 2018 at 6:51 AM, Martin Buchholz wrote: > Looks good. > > Maybe add comment > > + verbosePath = false; // print once per compile > > Maybe rename "l" to "line". > > On Thu, Jan 11, 2018 at 10:12 PM, Liam Miller-Cushon > wrote: > >> Please review (another) trivial fix for the output from "javac -verbose". >> >> bug: https://bugs.openjdk.java.net/browse/JDK-8179373 >> webrev: http://cr.openjdk.java.net/~cushon/8179373/webrev.00/ >> >> Thanks, >> Liam >> > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From vicente.romero at oracle.com Fri Jan 12 18:23:23 2018 From: vicente.romero at oracle.com (Vicente Romero) Date: Fri, 12 Jan 2018 13:23:23 -0500 Subject: [private] Re: RFR 8194932: no ambuguity error is emitted if classfile contains two identical methods with different return types In-Reply-To: References: <818ceef3-a5ce-a394-e85e-b7b4a55fa43c@oracle.com> Message-ID: <1f444be4-1377-42b0-9a65-aba5a693cabd@oracle.com> I just saw that there is a typo in the bug title ambuguity -> ambiguity, just in case you haven't pushed yet. Vicente On 01/12/2018 09:20 AM, Vicente Romero wrote: > looks good, > Vicente > > On 01/11/2018 01:20 PM, Maurizio Cimadamore wrote: >> Hi, >> this is a fix for an issue that has to do with compilation from >> classfile. While typically it is not possible for a Java source to >> contain two override equivalent method (as that would be flagged as >> method clash by javac), when a classfile contains two methods that >> have the same signature but different return types (which is possible >> at the classfile level), javac doesn't generate an ambiguity error >> when such method is called. Instead, javac non-deterministically >> resolves the call to the first method being declared in the classfile. >> >> The solution is to omit a part of the override check that is run in >> Resolve::mostSpecific (**). That is, this part should be disabled if >> the owner of both potentially ambiguous methods is the same. Extra >> code was added to handle the case of statically imported methods, in >> which case javac clones the imported method symbols and replaces >> their owner to make sure that the bytecode comes out in a certain >> way. So, if javac detects that the 'base' symbol of both methods is >> indeed the same - it means that the same symol was imported (and >> cloned) twice, so we can just return either. At this point, we should >> never have a case where we have two maximally specific concrete >> methods with same owner (unless we are in the classfile case). >> >> http://cr.openjdk.java.net/~mcimadamore/8194932/ >> >> (**) the override check performed by javac is outside the spec, but >> necessary because javac doesn't filter overload candidates by >> accessibility - that is, overridden methods are played through the >> javac overload resoluytion machinery, and javac prefers the >> overridden version of a method; this is an unfortunate, but >> historical, javac design choice. >> >> Cheers >> Maurizio >> > From joe.darcy at oracle.com Fri Jan 12 19:13:50 2018 From: joe.darcy at oracle.com (joe darcy) Date: Fri, 12 Jan 2018 11:13:50 -0800 Subject: JDK 10/11 RFR of JDK-8189146: Have use of "var" in 9 and earlier source versions issue a warning In-Reply-To: References: <9475d5e8-977d-4c84-6a19-b368834cce33@oracle.com> <665b4df5-a855-133b-8725-14e366600516@oracle.com> <345994a8-4fd9-97a9-98bf-81ab3fbdc8a4@oracle.com> Message-ID: <7cf89577-01ed-9687-8c8f-176f2d9d4ea2@oracle.com> Hi Maurizio, On 1/12/2018 5:13 AM, Maurizio Cimadamore wrote: > Hey Joe, > here's my take on the patch: > > http://cr.openjdk.java.net/~mcimadamore/8189146/ > > it is similar to what I initially proposed, but I had to fight a bit > with the parser in order to get rid of the duplicate warnings. The > issue is that warnings can be reported both through the 'parseType' > path and the 'variableDeclaratorRest' path, as the overlapping between > the two is non trivial (sometimes javac parses a local var decl type > as a type, sometimes as an expr, depending on whether javac is 'sure' > that the thing is a variable decl - whose production is ambiguous with > almost anything else :-)). Yes, the simple correspondence between the grammar productions and the code gets fuzzy without an unambiguous lookahead token to force a unique code path ;-) > > The solution is to add a flag to the isRestrictedLocalVarName so that > in certain cases the warning generation is suppressed. I have also > consolidated the treatment of the errors occurring because of the use > of 'var' in a compound declaration - now the errors are reported in > the same place where errors about 'var and array' is reported, which > makes a bunch of things easier. > > Lastly, I've cleaned up some of the diagnostic used - as they were > using a diagnostic argument which was alway set to the name 'var'. I > believe that's a leftover of when we accepted both 'var' and 'val', > and I have now removed it. I was curious about that; an artifact of supporting "val" and "var" makes sense. > > I believe what comes out of the compiler is in sync with what you > wanted, but the patch is not as trivial as we originally had hoped, > which, in my mind, makes it more for 11 than for 10. Hmm. I agree the current patch is more intricate than desired for this stage of JDK 10. Arguably the largest compatibility impact from var is no longer being able to use var as a type name, at least it is the impact that might be hardest to overcome in terms of having to rename a type rather than rename a variable. So for a patch appropriate for 10 at this stage, I'll prepare a simple patch for consideration that just warns on type name. Then if that is acceptable for 10, your patch could go into JDK 11 under a follow-up bug. Thanks, -Joe From joe.darcy at oracle.com Fri Jan 12 19:59:03 2018 From: joe.darcy at oracle.com (joe darcy) Date: Fri, 12 Jan 2018 11:59:03 -0800 Subject: JDK 10/11 RFR of JDK-8189146: Have use of "var" in 9 and earlier source versions issue a warning In-Reply-To: <7cf89577-01ed-9687-8c8f-176f2d9d4ea2@oracle.com> References: <9475d5e8-977d-4c84-6a19-b368834cce33@oracle.com> <665b4df5-a855-133b-8725-14e366600516@oracle.com> <345994a8-4fd9-97a9-98bf-81ab3fbdc8a4@oracle.com> <7cf89577-01ed-9687-8c8f-176f2d9d4ea2@oracle.com> Message-ID: <4ed26ea3-d43f-4174-dbbf-03521e8fa325@oracle.com> PS Link to webrev below. On 1/12/2018 11:13 AM, joe darcy wrote: > Hi Maurizio, > > > [snip] > >> >> I believe what comes out of the compiler is in sync with what you >> wanted, but the patch is not as trivial as we originally had hoped, >> which, in my mind, makes it more for 11 than for 10. > > Hmm. I agree the current patch is more intricate than desired for this > stage of JDK 10. > > Arguably the largest compatibility impact from var is no longer being > able to use var as a type name, at least it is the impact that might > be hardest to overcome in terms of having to rename a type rather than > rename a variable. So for a patch appropriate for 10 at this stage, > I'll prepare a simple patch for consideration that just warns on type > name. Then if that is acceptable for 10, your patch could go into JDK > 11 under a follow-up bug. > The iteration at http://cr.openjdk.java.net/~darcy/8189146.4/ goes back to the initial limited attempt at only warning for type names (which also covers type variables) but preserves the more precise testing developed in subsequent iterations. Thanks, -Joe From jonathan.gibbons at oracle.com Fri Jan 12 22:31:39 2018 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Fri, 12 Jan 2018 14:31:39 -0800 Subject: RFR(XXS) : 8195067 : problem list tools/javac/jvm/VerboseOutTest.java In-Reply-To: References: Message-ID: <5A59374B.2040002@oracle.com> OK. Sorry for the bad test. -- Jon On 01/12/2018 02:29 PM, Igor Ignatyev wrote: > http://cr.openjdk.java.net/~iignatyev//8195067/webrev.00/index.html >> 2 lines changed: 1 ins; 0 del; 1 mod; > Hi all, > > could you please review this tiny fix which put tools/javac/jvm/VerboseOutTest.java into the problem list till 8194968 is fixed? > > webrev: http://cr.openjdk.java.net/~iignatyev//8195067/webrev.00/index.html > JBS: https://bugs.openjdk.java.net/browse/JDK-8195067 > > Thanks, > -- Igor From maurizio.cimadamore at oracle.com Sat Jan 13 00:36:56 2018 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Sat, 13 Jan 2018 00:36:56 +0000 Subject: JDK 10/11 RFR of JDK-8189146: Have use of "var" in 9 and earlier source versions issue a warning In-Reply-To: <4ed26ea3-d43f-4174-dbbf-03521e8fa325@oracle.com> References: <9475d5e8-977d-4c84-6a19-b368834cce33@oracle.com> <665b4df5-a855-133b-8725-14e366600516@oracle.com> <345994a8-4fd9-97a9-98bf-81ab3fbdc8a4@oracle.com> <7cf89577-01ed-9687-8c8f-176f2d9d4ea2@oracle.com> <4ed26ea3-d43f-4174-dbbf-03521e8fa325@oracle.com> Message-ID: Looks good - and I agree it's a less risky path. Thanks Maurizio On 12/01/18 19:59, joe darcy wrote: > PS Link to webrev below. > > > On 1/12/2018 11:13 AM, joe darcy wrote: >> Hi Maurizio, >> >> >> > > [snip] > >> >>> >>> I believe what comes out of the compiler is in sync with what you >>> wanted, but the patch is not as trivial as we originally had hoped, >>> which, in my mind, makes it more for 11 than for 10. >> >> Hmm. I agree the current patch is more intricate than desired for >> this stage of JDK 10. >> >> Arguably the largest compatibility impact from var is no longer being >> able to use var as a type name, at least it is the? impact that might >> be hardest to overcome in terms of having to rename a type rather >> than rename a variable. So for a patch appropriate for 10 at this >> stage, I'll prepare a simple patch for consideration that just warns >> on type name. Then if that is acceptable for 10, your patch could go >> into JDK 11 under a follow-up bug. >> > > The iteration at > > ??? http://cr.openjdk.java.net/~darcy/8189146.4/ > > goes back to the initial limited attempt at only warning for type > names (which also covers type variables) but preserves the more > precise testing developed in subsequent iterations. > > Thanks, > > -Joe From jnape09 at gmail.com Sun Jan 14 21:38:26 2018 From: jnape09 at gmail.com (John Napier) Date: Sun, 14 Jan 2018 15:38:26 -0600 Subject: JDK-8188144 regression in method reference type-checking Message-ID: Hello Maurizio, I was the original reporter of JDK-8188144 to the JetBrains folks, who ultimately forwarded it over to you all, where it seems you?ve fixed it (Thank you!). It?s logged as a P3 that is targeting 10 but was resolved in build b26; wasn?t that one of the old Java9 early access builds? Is this bug fix planned for the next patch release of 9, or is it only targeted for 10? Cheers, John -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: Message signed with OpenPGP URL: From maurizio.cimadamore at oracle.com Mon Jan 15 11:02:09 2018 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Mon, 15 Jan 2018 11:02:09 +0000 Subject: JDK-8188144 regression in method reference type-checking In-Reply-To: References: Message-ID: Hi John, unfortunately the only planned update to JDK 9 is shipping very soon, and it's too late now to integrate fix on it. So, the next planned release with the fix is gonna be JDK 10 (unless a new maintainer for JDK 9 is going to step forward) - see: http://mail.openjdk.java.net/pipermail/jdk-updates-dev/2017-November/000024.html Also, a related (and recent) thread (thanks to Sean Coffey to point that out): http://mail.openjdk.java.net/pipermail/jdk-updates-dev/2018-January/000028.html Thanks Maurizio On 14/01/18 21:38, John Napier wrote: > Hello Maurizio, > > I was the original reporter of JDK-8188144 to the JetBrains folks, who ultimately forwarded it over to you all, where it seems you?ve fixed it (Thank you!). It?s logged as a P3 that is targeting 10 but was resolved in build b26; wasn?t that one of the old Java9 early access builds? Is this bug fix planned for the next patch release of 9, or is it only targeted for 10? > > Cheers, > John From goetz.lindenmaier at sap.com Tue Jan 16 07:47:41 2018 From: goetz.lindenmaier at sap.com (Lindenmaier, Goetz) Date: Tue, 16 Jan 2018 07:47:41 +0000 Subject: RFR: 8189102: All tools should support -?, -h and --help Message-ID: Hi, The CSR for this change is approved now. https://bugs.openjdk.java.net/browse/JDK-8191477 If there aren't any more objections, I will push this. Webrev rebased and with updated 2018 copyright messages: http://cr.openjdk.java.net/~goetz/wr17/8189102-helpMessage/webrev.08/ Best regards, Goetz. -------------- next part -------------- An HTML attachment was scrubbed... URL: From cushon at google.com Tue Jan 16 18:10:52 2018 From: cushon at google.com (Liam Miller-Cushon) Date: Tue, 16 Jan 2018 10:10:52 -0800 Subject: MethodParameters attributes in v51 classfiles In-Reply-To: References: <5822706D.1000504@oracle.com> Message-ID: This ended up getting filed as https://bugs.openjdk.java.net/browse/JDK-8190452. I've seen a few other reports of it. > Since the code that generates the warning is a general warning for any future attribute, and not specific to MethodParameters, it would seem more appropriate to not generate the attribute for versions for which it is not appropriate. Since this didn't get fixed in time for 9, and there are now class files in the wild that have this issue, would you consider relaxing the warning for MethodParameters attributes? I'm interested in contributing a fix (to relax the warning and/or only emit the attributes for appropriate class file versions) if someone is interested in sponsoring it. Thanks, On Tue, Nov 8, 2016 at 5:22 PM, Liam Miller-Cushon wrote: > I'd be happy to have MethodParameters attributes in older class file > versions, but not wanting to special-case future attribute diagnostics > makes sense. > > This came up because of a bad interaction between future attribute > diagnostics and rawtypes warnings. The same issue might affect other future > attribute warnings or other diagnostic kinds, so it's probably worth > tracking separately: > > public class A { public A(F f) {} } > public class B { public void t(int i) {} } > public class Test { > public void f() { > new A(new B()); > } > } > > javac -parameters -source 7 -target 7 A.java B.java > javac -Xlint:all -sourcepath : Test.java > ./A.class: warning: [classfile] MethodParameters attribute introduced in > version 52.0 class files is ignored in version 51.0 class files > ./B.class: warning: [classfile] MethodParameters attribute introduced in > version 52.0 class files is ignored in version 51.0 class files > 2 warnings > An exception has occurred in the compiler (9-ea). Please file a bug > against the Java compiler via the Java bug reporting page ( > http://bugreport.java.com) after checking the Bug Database ( > http://bugs.java.com) for duplicates. Include your program and the > following diagnostic in your report. Thank you. > java.lang.AssertionError: Missing type variable in where clause: E > at com.sun.tools.javac.util.RichDiagnosticFormatter. > unique(jdk.compiler at 9-ea/RichDiagnosticFormatter.java:247) > at com.sun.tools.javac.util.RichDiagnosticFormatter. > access$100(jdk.compiler at 9-ea/RichDiagnosticFormatter.java:71) > at com.sun.tools.javac.util.RichDiagnosticFormatter$ > RichPrinter.visitTypeVar(jdk.compiler at 9-ea/RichDiagnosticFormatter.java: > 398) > at com.sun.tools.javac.util.RichDiagnosticFormatter$ > RichPrinter.visitTypeVar(jdk.compiler at 9-ea/RichDiagnosticFormatter.java: > 340) > > > > On Tue, Nov 8, 2016 at 4:40 PM, Jonathan Gibbons < > jonathan.gibbons at oracle.com> wrote: > >> >> >> On 11/08/2016 04:31 PM, Liam Miller-Cushon wrote: >> >>> If -parameters is passed, javac will write MethodParameters attributes >>> when source/target < 8. It also reports -Xlint:classfile warnings about >>> MethodParameters attributes in < v52 classfiles: >>> >>> class X { >>> void f(int a) {} >>> } >>> class Y { >>> X x; >>> } >>> >>> $ javac -source 7 -target 7 -parameters X.java >>> $ javac -Xlint:classfile -sourcepath : Y.java >>> ./X.class: warning: [classfile] MethodParameters attribute introduced in >>> version 52.0 class files is ignored in version 51.0 class files >>> >>> Is that deliberate? I expected it to either not write the attribute for >>> old classfile versions, or not warn about it. >>> >> >> Since the code that generates the warning is a general warning for any >> future attribute, and not specific to MethodParameters, it would seem more >> appropriate to not generate the attribute for versions for which it is not >> appropriate. >> >> -- Jon >> > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From jonathan.gibbons at oracle.com Tue Jan 16 18:52:13 2018 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Tue, 16 Jan 2018 10:52:13 -0800 Subject: JDK 10/11 RFR of JDK-8189146: Have use of "var" in 9 and earlier source versions issue a warning In-Reply-To: <4ed26ea3-d43f-4174-dbbf-03521e8fa325@oracle.com> References: <9475d5e8-977d-4c84-6a19-b368834cce33@oracle.com> <665b4df5-a855-133b-8725-14e366600516@oracle.com> <345994a8-4fd9-97a9-98bf-81ab3fbdc8a4@oracle.com> <7cf89577-01ed-9687-8c8f-176f2d9d4ea2@oracle.com> <4ed26ea3-d43f-4174-dbbf-03521e8fa325@oracle.com> Message-ID: <5A5E49DD.2030103@oracle.com> On 01/12/2018 11:59 AM, joe darcy wrote: > PS Link to webrev below. > > > On 1/12/2018 11:13 AM, joe darcy wrote: >> Hi Maurizio, >> >> >> > > [snip] > >> >>> >>> I believe what comes out of the compiler is in sync with what you >>> wanted, but the patch is not as trivial as we originally had hoped, >>> which, in my mind, makes it more for 11 than for 10. >> >> Hmm. I agree the current patch is more intricate than desired for >> this stage of JDK 10. >> >> Arguably the largest compatibility impact from var is no longer being >> able to use var as a type name, at least it is the impact that might >> be hardest to overcome in terms of having to rename a type rather >> than rename a variable. So for a patch appropriate for 10 at this >> stage, I'll prepare a simple patch for consideration that just warns >> on type name. Then if that is acceptable for 10, your patch could go >> into JDK 11 under a follow-up bug. >> > > The iteration at > > http://cr.openjdk.java.net/~darcy/8189146.4/ > > goes back to the initial limited attempt at only warning for type > names (which also covers type variables) but preserves the more > precise testing developed in subsequent iterations. > > Thanks, > > -Joe OK. It is a general rule for javac that javac should be able to compile a program without generating any warnings. Any warnings should be suppressible either by using @SuppressWarnings, or a command-line option, or (in a few cases) changing the source code to something equivalent, without changing the intended functionality. I can see how it would be difficult to use the Lint mechanism in the parser, since even the deferred-lint-warnings mechanism doesn't kick in until later. So that means in this case, the remediation to avoid this proposed new warning is to change the source code in question. And that is acceptable, in part because of the expected low number of occurrences of this warning, and because the code will have to be changed eventually anyway, in later releases where the warning is promoted to an error. -- Jon From maurizio.cimadamore at oracle.com Wed Jan 17 15:31:19 2018 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Wed, 17 Jan 2018 15:31:19 +0000 Subject: RFR 8195598: Reference to overloaded method is ambiguous with 3 methods but works with 2 Message-ID: <6613be3f-9f5e-fc63-eb41-d650d87ff996@oracle.com> Hi, this is a fix related to the most specific selection between functional interfaces. The most specific functional interface analysis needs access to the speculative tree determined during overload resolution; such info is only available if a given argument is pertinent to applicability w.r.t. a given method. Unfortunately, the fix for JDK-8154180 introduced a single shared flag called 'pertinentToApplicability' which is unset whenever a given argument is found to be stuck. Now, the issue here is that the flag should not be shared across all possible targets an actual is checked against. That is, for each target there should be a separate flag. Since the flag is shared, a single target which makes the argument stuck is sufficient to make the most specific process fail, even if other applicable targets were found in the process (depending on the order). The solution is to use a set to keep track of the targets for which the argument was NOT pertinent to applicability (e.g. stuck). This brings the compiler back in sync with the spec. Webrev: http://cr.openjdk.java.net/~mcimadamore/8195598/ Cheers Maurizio -------------- next part -------------- An HTML attachment was scrubbed... URL: From david.lloyd at redhat.com Wed Jan 17 17:37:16 2018 From: david.lloyd at redhat.com (David Lloyd) Date: Wed, 17 Jan 2018 11:37:16 -0600 Subject: Problems building with --release=8 Message-ID: I'm trying to create some MR JARs for projects which use sun.misc.Unsafe and sun.reflect.ReflectionFactory (both of which exist in the jdk.unsupported module). For the Java 8 portion, I'm attempting to move from using the Java 8 javac to Java 9 (or later). However I'm running into a problem where these classes are not available when I compile with --release=8. As a workaround, I created a JAR which stubbed these two classes and included it on the compile class path. However, it seems that they were actively filtered out or ignored somehow. Removing --release=8 and just using -source 8 -target 8 allowed the compilation to succeed, however I want to be sure that no 9+ classes sneak into the 8 part so I want to use --release=8 if possible. If jdk.unsupported is allowed for Java 9+, then surely these two classes should be included in the Java 8 image. Did I make some kind of mistake or is this a legitimate bug? -- - DML From jonathan.gibbons at oracle.com Wed Jan 17 17:43:15 2018 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Wed, 17 Jan 2018 09:43:15 -0800 Subject: Problems building with --release=8 In-Reply-To: References: Message-ID: <5c0ad745-def9-6617-96a3-ce9bc20fe349@oracle.com> On 1/17/18 9:37 AM, David Lloyd wrote: > I'm trying to create some MR JARs for projects which use > sun.misc.Unsafe and sun.reflect.ReflectionFactory (both of which exist > in the jdk.unsupported module). For the Java 8 portion, I'm > attempting to move from using the Java 8 javac to Java 9 (or later). > However I'm running into a problem where these classes are not > available when I compile with --release=8. > > As a workaround, I created a JAR which stubbed these two classes and > included it on the compile class path. However, it seems that they > were actively filtered out or ignored somehow. Removing --release=8 > and just using -source 8 -target 8 allowed the compilation to succeed, > however I want to be sure that no 9+ classes sneak into the 8 part so > I want to use --release=8 if possible. > > If jdk.unsupported is allowed for Java 9+, then surely these two > classes should be included in the Java 8 image. > > Did I make some kind of mistake or is this a legitimate bug? It doesn't sound like you made a mistake, but this is not a bug. Generally, the spec for --release N is to provide access to the public documented API for JDK N. That being said, there has been discussion recently about providing access to some of the API that precedes jdk.unsupported, as a special case. -- Jon From david.lloyd at redhat.com Wed Jan 17 17:49:22 2018 From: david.lloyd at redhat.com (David Lloyd) Date: Wed, 17 Jan 2018 11:49:22 -0600 Subject: Problems building with --release=8 In-Reply-To: <5c0ad745-def9-6617-96a3-ce9bc20fe349@oracle.com> References: <5c0ad745-def9-6617-96a3-ce9bc20fe349@oracle.com> Message-ID: On Wed, Jan 17, 2018 at 11:43 AM, Jonathan Gibbons wrote: > On 1/17/18 9:37 AM, David Lloyd wrote: > >> I'm trying to create some MR JARs for projects which use >> sun.misc.Unsafe and sun.reflect.ReflectionFactory (both of which exist >> in the jdk.unsupported module). For the Java 8 portion, I'm >> attempting to move from using the Java 8 javac to Java 9 (or later). >> However I'm running into a problem where these classes are not >> available when I compile with --release=8. >> >> As a workaround, I created a JAR which stubbed these two classes and >> included it on the compile class path. However, it seems that they >> were actively filtered out or ignored somehow. Removing --release=8 >> and just using -source 8 -target 8 allowed the compilation to succeed, >> however I want to be sure that no 9+ classes sneak into the 8 part so >> I want to use --release=8 if possible. >> >> If jdk.unsupported is allowed for Java 9+, then surely these two >> classes should be included in the Java 8 image. >> >> Did I make some kind of mistake or is this a legitimate bug? > > > It doesn't sound like you made a mistake, but this is not a bug. > Generally, the spec for --release N is to provide access to the > public documented API for JDK N. I'm on board with that, however it is also preventing me from adding my own sun.misc etc. on the class path. Surely _that_ is a bug? > That being said, there has been discussion recently about providing > access to some of the API that precedes jdk.unsupported, as a special > case. That would be nice. -- - DML From david.lloyd at redhat.com Wed Jan 17 17:56:34 2018 From: david.lloyd at redhat.com (David Lloyd) Date: Wed, 17 Jan 2018 11:56:34 -0600 Subject: Problems building with --release=8 In-Reply-To: References: <5c0ad745-def9-6617-96a3-ce9bc20fe349@oracle.com> Message-ID: On Wed, Jan 17, 2018 at 11:49 AM, David Lloyd wrote: > On Wed, Jan 17, 2018 at 11:43 AM, Jonathan Gibbons > wrote: >> On 1/17/18 9:37 AM, David Lloyd wrote: >> >>> I'm trying to create some MR JARs for projects which use >>> sun.misc.Unsafe and sun.reflect.ReflectionFactory (both of which exist >>> in the jdk.unsupported module). For the Java 8 portion, I'm >>> attempting to move from using the Java 8 javac to Java 9 (or later). >>> However I'm running into a problem where these classes are not >>> available when I compile with --release=8. >>> >>> As a workaround, I created a JAR which stubbed these two classes and >>> included it on the compile class path. However, it seems that they >>> were actively filtered out or ignored somehow. Removing --release=8 >>> and just using -source 8 -target 8 allowed the compilation to succeed, >>> however I want to be sure that no 9+ classes sneak into the 8 part so >>> I want to use --release=8 if possible. >>> >>> If jdk.unsupported is allowed for Java 9+, then surely these two >>> classes should be included in the Java 8 image. >>> >>> Did I make some kind of mistake or is this a legitimate bug? >> >> >> It doesn't sound like you made a mistake, but this is not a bug. >> Generally, the spec for --release N is to provide access to the >> public documented API for JDK N. > > I'm on board with that, however it is also preventing me from adding > my own sun.misc etc. on the class path. Surely _that_ is a bug? Never mind, this was my mistake, a typo in my build file. So, the stub-JAR solution is working OK for me. >> That being said, there has been discussion recently about providing >> access to some of the API that precedes jdk.unsupported, as a special >> case. > > That would be nice. -- - DML From jonathan.gibbons at oracle.com Wed Jan 17 18:03:28 2018 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Wed, 17 Jan 2018 10:03:28 -0800 Subject: Problems building with --release=8 In-Reply-To: References: <5c0ad745-def9-6617-96a3-ce9bc20fe349@oracle.com> Message-ID: <623ce973-cf82-9ca1-ea62-fd4a18a263ee@oracle.com> On 1/17/18 9:56 AM, David Lloyd wrote: > On Wed, Jan 17, 2018 at 11:49 AM, David Lloyd wrote: >> On Wed, Jan 17, 2018 at 11:43 AM, Jonathan Gibbons >> wrote: >>> On 1/17/18 9:37 AM, David Lloyd wrote: >>> >>>> I'm trying to create some MR JARs for projects which use >>>> sun.misc.Unsafe and sun.reflect.ReflectionFactory (both of which exist >>>> in the jdk.unsupported module). For the Java 8 portion, I'm >>>> attempting to move from using the Java 8 javac to Java 9 (or later). >>>> However I'm running into a problem where these classes are not >>>> available when I compile with --release=8. >>>> >>>> As a workaround, I created a JAR which stubbed these two classes and >>>> included it on the compile class path. However, it seems that they >>>> were actively filtered out or ignored somehow. Removing --release=8 >>>> and just using -source 8 -target 8 allowed the compilation to succeed, >>>> however I want to be sure that no 9+ classes sneak into the 8 part so >>>> I want to use --release=8 if possible. >>>> >>>> If jdk.unsupported is allowed for Java 9+, then surely these two >>>> classes should be included in the Java 8 image. >>>> >>>> Did I make some kind of mistake or is this a legitimate bug? >>> >>> It doesn't sound like you made a mistake, but this is not a bug. >>> Generally, the spec for --release N is to provide access to the >>> public documented API for JDK N. >> I'm on board with that, however it is also preventing me from adding >> my own sun.misc etc. on the class path. Surely _that_ is a bug? > Never mind, this was my mistake, a typo in my build file. So, the > stub-JAR solution is working OK for me. Thanks for the update/correction. > >>> That being said, there has been discussion recently about providing >>> access to some of the API that precedes jdk.unsupported, as a special >>> case. >> That would be nice. From vicente.romero at oracle.com Wed Jan 17 19:15:31 2018 From: vicente.romero at oracle.com (Vicente Romero) Date: Wed, 17 Jan 2018 14:15:31 -0500 Subject: RFR 8195598: Reference to overloaded method is ambiguous with 3 methods but works with 2 In-Reply-To: <6613be3f-9f5e-fc63-eb41-d650d87ff996@oracle.com> References: <6613be3f-9f5e-fc63-eb41-d650d87ff996@oracle.com> Message-ID: the fix looks good, Vicente On 01/17/2018 10:31 AM, Maurizio Cimadamore wrote: > > Hi, > this is a fix related to the most specific selection between > functional interfaces. The most specific functional interface analysis > needs access to the speculative tree determined during overload > resolution; such info is only available if a given argument is > pertinent to applicability w.r.t. a given method. > > Unfortunately, the fix for JDK-8154180 > introduced a single > shared flag called 'pertinentToApplicability' which is unset whenever > a given argument is found to be stuck. Now, the issue here is that the > flag should not be shared across all possible targets an actual is > checked against. That is, for each target there should be a separate > flag. Since the flag is shared, a single target which makes the > argument stuck is sufficient to make the most specific process fail, > even if other applicable targets were found in the process (depending > on the order). > > The solution is to use a set to keep track of the targets for which > the argument was NOT pertinent to applicability (e.g. stuck). This > brings the compiler back in sync with the spec. > > Webrev: > > http://cr.openjdk.java.net/~mcimadamore/8195598/ > > Cheers > Maurizio > -------------- next part -------------- An HTML attachment was scrubbed... URL: From cushon at google.com Wed Jan 17 19:51:05 2018 From: cushon at google.com (Liam Miller-Cushon) Date: Wed, 17 Jan 2018 11:51:05 -0800 Subject: RFR: JDK-8190452: javac should not add MethodParameters attributes to v51 and earlier class files Message-ID: Please review a fix for JDK-8190452. The change causes javac to not emit MethodParameters attributes when targeting v51 class files. The change implements the suggestion from this thread: http://mail.openjdk.java.net/pipermail/compiler-dev/2018-January/011579.html There are two related changes that may be worth considering: * now that -parameters will be ignored when compiling with --release < 8, should this combination of flags result in a warning if -Xlint:options is enabled? * since this wasn't fixed in JDK 9, there are v51 class files in the wild that contain unexpected MethodParameters attributes. Should -Xlint:classfile be relaxed to avoid warning on those? bug: https://bugs.openjdk.java.net/browse/JDK-8190452 webrev: http://cr.openjdk.java.net/~cushon/8190452/webrev.00/ -------------- next part -------------- An HTML attachment was scrubbed... URL: From joe.darcy at oracle.com Thu Jan 18 00:33:01 2018 From: joe.darcy at oracle.com (Joseph D. Darcy) Date: Wed, 17 Jan 2018 16:33:01 -0800 Subject: =?UTF-8?B?SkRLIDEwIFJGUiBvZiBKREstODE5MTgzOTogTW9kdWxlRWxlbWVudC4=?= =?UTF-8?B?RGlyZWN0aXZlVmlzaXRvciA6OiB2aXNpdOKAiygpIG1ldGhvZCBiZWhhdmlvciA=?= =?UTF-8?B?aXMgZGV2aWF0aW5nIGZyb20gdGhlIHNwZWMu?= Message-ID: <5A5FEB3D.70506@oracle.com> Hello, Please review the doc-only changes for JDK-8191839: ModuleElement.DirectiveVisitor :: visit?() method behavior is deviating from the spec. http://cr.openjdk.java.net/~darcy/8191839.0/ In brief, the bug observes an inconsistency between the @implSpec tag and the mainline requirements for one of the default method in DirectiveVisitor. After doing a few greps over the javax.lang.model code, I found a case of a missing @implSpec tag for a default method and change the wording of a few @implSpec tags to be more consistent with the conventions in the rest of the API. Thanks, -Joe From jonathan.gibbons at oracle.com Thu Jan 18 00:56:43 2018 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Wed, 17 Jan 2018 16:56:43 -0800 Subject: =?UTF-8?B?UmU6IEpESyAxMCBSRlIgb2YgSkRLLTgxOTE4Mzk6IE1vZHVsZUVsZW0=?= =?UTF-8?B?ZW50LkRpcmVjdGl2ZVZpc2l0b3IgOjogdmlzaXTigIsoKSBtZXRob2QgYmVoYXY=?= =?UTF-8?B?aW9yIGlzIGRldmlhdGluZyBmcm9tIHRoZSBzcGVjLg==?= In-Reply-To: <5A5FEB3D.70506@oracle.com> References: <5A5FEB3D.70506@oracle.com> Message-ID: <5A5FF0CB.90004@oracle.com> OK. I note, with regret, the lack of consistency across the platform for how to phrase the text after @implSpec. -- Jon On 01/17/2018 04:33 PM, Joseph D. Darcy wrote: > Hello, > > Please review the doc-only changes for > > JDK-8191839: ModuleElement.DirectiveVisitor :: visit?() method > behavior is deviating from the spec. > http://cr.openjdk.java.net/~darcy/8191839.0/ > > In brief, the bug observes an inconsistency between the @implSpec tag > and the mainline requirements for one of the default method in > DirectiveVisitor. After doing a few greps over the javax.lang.model > code, I found a case of a missing @implSpec tag for a default method > and change the wording of a few @implSpec tags to be more consistent > with the conventions in the rest of the API. > > Thanks, > > -Joe > From joe.darcy at oracle.com Thu Jan 18 01:46:03 2018 From: joe.darcy at oracle.com (Joseph D. Darcy) Date: Wed, 17 Jan 2018 17:46:03 -0800 Subject: =?UTF-8?B?UmU6IEpESyAxMCBSRlIgb2YgSkRLLTgxOTE4Mzk6IE1vZHVsZUVsZW0=?= =?UTF-8?B?ZW50LkRpcmVjdGl2ZVZpc2l0b3IgOjogdmlzaXTigIsoKSBtZXRob2QgYmVoYXY=?= =?UTF-8?B?aW9yIGlzIGRldmlhdGluZyBmcm9tIHRoZSBzcGVjLg==?= In-Reply-To: <5A5FF0CB.90004@oracle.com> References: <5A5FEB3D.70506@oracle.com> <5A5FF0CB.90004@oracle.com> Message-ID: <5A5FFC5B.8020103@oracle.com> On 1/17/2018 4:56 PM, Jonathan Gibbons wrote: > OK. > > I note, with regret, the lack of consistency across the platform for > how to phrase the text after @implSpec. > Sorry I didn't notice the local inconsistency with those default methods came in; an item to keep in mind for the API development checklist! -Joe From mernst at cs.washington.edu Thu Jan 18 00:05:02 2018 From: mernst at cs.washington.edu (Michael Ernst) Date: Wed, 17 Jan 2018 16:05:02 -0800 (PST) Subject: Receiver parameter for a method of an anonymous class Message-ID: <20180117.160502.253875054391501528.mernst@cs.washington.edu> It is not possible to write a receiver parameter for a method of an anonymous class. I have filed two bugs about this: Here is a specification/language bug to change JLS 8.4.1: https://bugs.openjdk.java.net/browse/JDK-8195645 Here is a tools/javac bug to make javac conform to the changed JLS: https://bugs.openjdk.java.net/browse/JDK-8195646 -Mike From bsrbnd at gmail.com Sat Jan 20 22:17:07 2018 From: bsrbnd at gmail.com (B. Blaser) Date: Sat, 20 Jan 2018 23:17:07 +0100 Subject: Types.isSameType() unification Message-ID: Hi, As noted previously in [1], 'isSameTypeLoose' doesn't work properly with '==' instances of a same type variable with recursive bounds which is indeed wrong. Moreover, 'isSameType' should be the unique 'isSameTypeStrict' relation as explained in [2]. So, I simply tried to remove 'isSameTypeLoose' but I got, of course, some failing tests like [3] & [4]. As it seems that 'isSameTypeStrict' is too strict for wildcards I kept the default behavior in such cases, as here under. I did this experiment on a quite old JDK10 revision (sorry) with encouraging test results (nothing seems to be broken). What do you think? Thanks, Bernard [1] http://mail.openjdk.java.net/pipermail/compiler-dev/2017-November/011291.html [2] http://mail.openjdk.java.net/pipermail/compiler-dev/2017-November/011296.html [3] tools/javac/generics/wildcards/neg/CastTest.java [4] tools/javac/generics/wildcards/pos/CastTest.java diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java @@ -1031,9 +1031,7 @@ return isSameType(t, s, false); } public boolean isSameType(Type t, Type s, boolean strict) { - return strict ? - isSameTypeStrict.visit(t, s) : - isSameTypeLoose.visit(t, s); + return isSameTypeStrict.visit(t, s); } // where abstract class SameTypeVisitor extends TypeRelation { @@ -1177,44 +1175,6 @@ } /** - * Standard type-equality relation - type variables are considered - * equals if they share the same type symbol. - */ - TypeRelation isSameTypeLoose = new LooseSameTypeVisitor(); - - private class LooseSameTypeVisitor extends SameTypeVisitor { - - /** cache of the type-variable pairs being (recursively) tested. */ - private Set cache = new HashSet<>(); - - @Override - boolean sameTypeVars(TypeVar tv1, TypeVar tv2) { - return tv1.tsym == tv2.tsym && checkSameBounds(tv1, tv2); - } - @Override - protected boolean containsTypes(List ts1, List ts2) { - return containsTypeEquivalent(ts1, ts2); - } - - /** - * Since type-variable bounds can be recursive, we need to protect against - * infinite loops - where the same bounds are checked over and over recursively. - */ - private boolean checkSameBounds(TypeVar tv1, TypeVar tv2) { - TypePair p = new TypePair(tv1, tv2, true); - if (cache.add(p)) { - try { - return visit(tv1.getUpperBound(), tv2.getUpperBound()); - } finally { - cache.remove(p); - } - } else { - return false; - } - } - }; - - /** * Strict type-equality relation - type variables are considered * equals if they share the same object identity. */ @@ -1227,17 +1187,6 @@ protected boolean containsTypes(List ts1, List ts2) { return isSameTypes(ts1, ts2, true); } - - @Override - public Boolean visitWildcardType(WildcardType t, Type s) { - if (!s.hasTag(WILDCARD)) { - return false; - } else { - WildcardType t2 = (WildcardType)s; - return t.kind == t2.kind && - isSameType(t.type, t2.type, true); - } - } }; // From maurizio.cimadamore at oracle.com Mon Jan 22 09:34:47 2018 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Mon, 22 Jan 2018 09:34:47 +0000 Subject: Types.isSameType() unification In-Reply-To: References: Message-ID: <08e6fa5a-12af-6f7b-57d6-4b763feb9c1f@oracle.com> Hi B. interesting approach, thanks for the patch; digging a bit into the history the loose vs. strict dichotomy started here: http://hg.openjdk.java.net/lambda/lambda/langtools/rev/1df20330f6bd#l1.63 As you can see, javac started out with a loose behavior, but then a stricter semantics (closer to JLS) was required during incorporation: e.g. a new bound should be added to an inference var only if this bound is different from the existing ones; the loose same-ness check would consider cloned inference-vars equivalent and, as such, was missing out on some extra constraints - hence the strict version. At the time it did not occur to me that, maybe, the loose version was just wrong and the compiler could be better off with the stricter version; also, since we were in the middle of replacing an inference engine with a new one, we were trying to limit the impact of new changes as much as possible. Since your patch makes strict behavior the only choice, the problem with inference variable bounds is naturally addressed - but of course all code calling isSameTypes normally would now see a change in behavior, so we need to make sure that the new behavior is acceptable in all cases. But your analysis seems to suggest that most of the stuff just works and that was just me being overly conservative at the time - in which case we can happily change the code, and eliminate this source of complexity. I'll do some more tests on your patch and see how it goes. Maurizio On 20/01/18 22:17, B. Blaser wrote: > Hi, > > As noted previously in [1], 'isSameTypeLoose' doesn't work properly > with '==' instances of a same type variable with recursive bounds > which is indeed wrong. > > Moreover, 'isSameType' should be the unique 'isSameTypeStrict' > relation as explained in [2]. > > So, I simply tried to remove 'isSameTypeLoose' but I got, of course, > some failing tests like [3] & [4]. > > As it seems that 'isSameTypeStrict' is too strict for wildcards I kept > the default behavior in such cases, as here under. > > I did this experiment on a quite old JDK10 revision (sorry) with > encouraging test results (nothing seems to be broken). > > What do you think? > > Thanks, > Bernard > > [1] http://mail.openjdk.java.net/pipermail/compiler-dev/2017-November/011291.html > [2] http://mail.openjdk.java.net/pipermail/compiler-dev/2017-November/011296.html > [3] tools/javac/generics/wildcards/neg/CastTest.java > [4] tools/javac/generics/wildcards/pos/CastTest.java > > diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java > b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java > --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java > +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java > @@ -1031,9 +1031,7 @@ > return isSameType(t, s, false); > } > public boolean isSameType(Type t, Type s, boolean strict) { > - return strict ? > - isSameTypeStrict.visit(t, s) : > - isSameTypeLoose.visit(t, s); > + return isSameTypeStrict.visit(t, s); > } > // where > abstract class SameTypeVisitor extends TypeRelation { > @@ -1177,44 +1175,6 @@ > } > > /** > - * Standard type-equality relation - type variables are considered > - * equals if they share the same type symbol. > - */ > - TypeRelation isSameTypeLoose = new LooseSameTypeVisitor(); > - > - private class LooseSameTypeVisitor extends SameTypeVisitor { > - > - /** cache of the type-variable pairs being (recursively) tested. */ > - private Set cache = new HashSet<>(); > - > - @Override > - boolean sameTypeVars(TypeVar tv1, TypeVar tv2) { > - return tv1.tsym == tv2.tsym && checkSameBounds(tv1, tv2); > - } > - @Override > - protected boolean containsTypes(List ts1, List ts2) { > - return containsTypeEquivalent(ts1, ts2); > - } > - > - /** > - * Since type-variable bounds can be recursive, we need > to protect against > - * infinite loops - where the same bounds are checked > over and over recursively. > - */ > - private boolean checkSameBounds(TypeVar tv1, TypeVar tv2) { > - TypePair p = new TypePair(tv1, tv2, true); > - if (cache.add(p)) { > - try { > - return visit(tv1.getUpperBound(), tv2.getUpperBound()); > - } finally { > - cache.remove(p); > - } > - } else { > - return false; > - } > - } > - }; > - > - /** > * Strict type-equality relation - type variables are considered > * equals if they share the same object identity. > */ > @@ -1227,17 +1187,6 @@ > protected boolean containsTypes(List ts1, List ts2) { > return isSameTypes(ts1, ts2, true); > } > - > - @Override > - public Boolean visitWildcardType(WildcardType t, Type s) { > - if (!s.hasTag(WILDCARD)) { > - return false; > - } else { > - WildcardType t2 = (WildcardType)s; > - return t.kind == t2.kind && > - isSameType(t.type, t2.type, true); > - } > - } > }; > > // From maurizio.cimadamore at oracle.com Mon Jan 22 12:07:19 2018 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Mon, 22 Jan 2018 12:07:19 +0000 Subject: Types.isSameType() unification In-Reply-To: <08e6fa5a-12af-6f7b-57d6-4b763feb9c1f@oracle.com> References: <08e6fa5a-12af-6f7b-57d6-4b763feb9c1f@oracle.com> Message-ID: Quick update, I was unable to build the JDK with the patch you sent; the issue was that the patch alters the loose behaviro of type equality used in subtyping tests, so tests like the one below: class Foo> <: Comparator> Started to fail. While this is ok spec-wise, the compiler currently tries to detect cases where two type arguments are effectively the same thing by using info on declared bounds. This is done in Types::containsTypeEquivalent, which is not used with a strict check. We might or might not want to get rid of that one too, but that's a battle for another day :-) The solution was to reinstate the use of containsTypeEquivalent in the type argument check in the sametype visitor. That gets the build going. I'm now running the tests and see where we're at. Maurizio On 22/01/18 09:34, Maurizio Cimadamore wrote: > Hi B. > > interesting approach, thanks for the patch; digging a bit into the > history the loose vs. strict dichotomy started here: > > http://hg.openjdk.java.net/lambda/lambda/langtools/rev/1df20330f6bd#l1.63 > > As you can see, javac started out with a loose behavior, but then a > stricter semantics (closer to JLS) was required during incorporation: > e.g. a new bound should be added to an inference var only if this > bound is different from the existing ones; the loose same-ness check > would consider cloned inference-vars equivalent and, as such, was > missing out on some extra constraints - hence the strict version. > > At the time it did not occur to me that, maybe, the loose version was > just wrong and the compiler could be better off with the stricter > version; also, since we were in the middle of replacing an inference > engine with a new one, we were trying to limit the impact of new > changes as much as possible. > > Since your patch makes strict behavior the only choice, the problem > with inference variable bounds is naturally addressed - but of course > all code calling isSameTypes normally would now see a change in > behavior, so we need to make sure that the new behavior is acceptable > in all cases. But your analysis seems to suggest that most of the > stuff just works and that was just me being overly conservative at the > time - in which case we can happily change the code, and eliminate > this source of complexity. > > I'll do some more tests on your patch and see how it goes. > > Maurizio > > > On 20/01/18 22:17, B. Blaser wrote: >> Hi, >> >> As noted previously in [1], 'isSameTypeLoose' doesn't work properly >> with '==' instances of a same type variable with recursive bounds >> which is indeed wrong. >> >> Moreover, 'isSameType' should be the unique 'isSameTypeStrict' >> relation as explained in [2]. >> >> So, I simply tried to remove 'isSameTypeLoose' but I got, of course, >> some failing tests like [3] & [4]. >> >> As it seems that 'isSameTypeStrict' is too strict for wildcards I kept >> the default behavior in such cases, as here under. >> >> I did this experiment on a quite old JDK10 revision (sorry) with >> encouraging test results (nothing seems to be broken). >> >> What do you think? >> >> Thanks, >> Bernard >> >> [1] >> http://mail.openjdk.java.net/pipermail/compiler-dev/2017-November/011291.html >> [2] >> http://mail.openjdk.java.net/pipermail/compiler-dev/2017-November/011296.html >> [3] tools/javac/generics/wildcards/neg/CastTest.java >> [4] tools/javac/generics/wildcards/pos/CastTest.java >> >> diff --git >> a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java >> b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java >> --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java >> +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java >> @@ -1031,9 +1031,7 @@ >> ????????? return isSameType(t, s, false); >> ????? } >> ????? public boolean isSameType(Type t, Type s, boolean strict) { >> -??????? return strict ? >> -??????????????? isSameTypeStrict.visit(t, s) : >> -??????????????? isSameTypeLoose.visit(t, s); >> +??????? return isSameTypeStrict.visit(t, s); >> ????? } >> ????? // where >> ????????? abstract class SameTypeVisitor extends TypeRelation { >> @@ -1177,44 +1175,6 @@ >> ????????? } >> >> ????????? /** >> -???????? * Standard type-equality relation - type variables are >> considered >> -???????? * equals if they share the same type symbol. >> -???????? */ >> -??????? TypeRelation isSameTypeLoose = new LooseSameTypeVisitor(); >> - >> -??????? private class LooseSameTypeVisitor extends SameTypeVisitor { >> - >> -??????????? /** cache of the type-variable pairs being (recursively) >> tested. */ >> -??????????? private Set cache = new HashSet<>(); >> - >> -??????????? @Override >> -??????????? boolean sameTypeVars(TypeVar tv1, TypeVar tv2) { >> -??????????????? return tv1.tsym == tv2.tsym && checkSameBounds(tv1, >> tv2); >> -??????????? } >> -??????????? @Override >> -??????????? protected boolean containsTypes(List ts1, >> List ts2) { >> -??????????????? return containsTypeEquivalent(ts1, ts2); >> -??????????? } >> - >> -??????????? /** >> -???????????? * Since type-variable bounds can be recursive, we need >> to protect against >> -???????????? * infinite loops - where the same bounds are checked >> over and over recursively. >> -???????????? */ >> -??????????? private boolean checkSameBounds(TypeVar tv1, TypeVar tv2) { >> -??????????????? TypePair p = new TypePair(tv1, tv2, true); >> -??????????????? if (cache.add(p)) { >> -??????????????????? try { >> -??????????????????????? return visit(tv1.getUpperBound(), >> tv2.getUpperBound()); >> -??????????????????? } finally { >> -??????????????????????? cache.remove(p); >> -??????????????????? } >> -??????????????? } else { >> -??????????????????? return false; >> -??????????????? } >> -??????????? } >> -??????? }; >> - >> -??????? /** >> ?????????? * Strict type-equality relation - type variables are >> considered >> ?????????? * equals if they share the same object identity. >> ?????????? */ >> @@ -1227,17 +1187,6 @@ >> ????????????? protected boolean containsTypes(List ts1, >> List ts2) { >> ????????????????? return isSameTypes(ts1, ts2, true); >> ????????????? } >> - >> -??????????? @Override >> -??????????? public Boolean visitWildcardType(WildcardType t, Type s) { >> -??????????????? if (!s.hasTag(WILDCARD)) { >> -??????????????????? return false; >> -??????????????? } else { >> -??????????????????? WildcardType t2 = (WildcardType)s; >> -??????????????????? return t.kind == t2.kind && >> -??????????????????????????? isSameType(t.type, t2.type, true); >> -??????????????? } >> -??????????? } >> ????????? }; >> >> ????? // > From maurizio.cimadamore at oracle.com Mon Jan 22 13:01:44 2018 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Mon, 22 Jan 2018 13:01:44 +0000 Subject: Types.isSameType() unification In-Reply-To: References: <08e6fa5a-12af-6f7b-57d6-4b763feb9c1f@oracle.com> Message-ID: <5dc109c2-d682-cc05-974e-167e999b9c2d@oracle.com> The attached patch looks good test-wise; apart from the containsTypeEquivalent change (discussed in earlier email) I've also done some cosmetic changes to get rid of redundant code. Vicente, could you please take a second look? Cheers Maurizio On 22/01/18 12:07, Maurizio Cimadamore wrote: > Quick update, > I was unable to build the JDK with the patch you sent; the issue was > that the patch alters the loose behaviro of type equality used in > subtyping tests, so tests like the one below: > > class Foo > Comparator> <: Comparator> > > Started to fail. While this is ok spec-wise, the compiler currently > tries to detect cases where two type arguments are effectively the > same thing by using info on declared bounds. This is done in > Types::containsTypeEquivalent, which is not used with a strict check. > We might or might not want to get rid of that one too, but that's a > battle for another day :-) > > The solution was to reinstate the use of containsTypeEquivalent in the > type argument check in the sametype visitor. That gets the build > going. I'm now running the tests and see where we're at. > > Maurizio > > > > On 22/01/18 09:34, Maurizio Cimadamore wrote: >> Hi B. >> >> interesting approach, thanks for the patch; digging a bit into the >> history the loose vs. strict dichotomy started here: >> >> http://hg.openjdk.java.net/lambda/lambda/langtools/rev/1df20330f6bd#l1.63 >> >> >> As you can see, javac started out with a loose behavior, but then a >> stricter semantics (closer to JLS) was required during incorporation: >> e.g. a new bound should be added to an inference var only if this >> bound is different from the existing ones; the loose same-ness check >> would consider cloned inference-vars equivalent and, as such, was >> missing out on some extra constraints - hence the strict version. >> >> At the time it did not occur to me that, maybe, the loose version was >> just wrong and the compiler could be better off with the stricter >> version; also, since we were in the middle of replacing an inference >> engine with a new one, we were trying to limit the impact of new >> changes as much as possible. >> >> Since your patch makes strict behavior the only choice, the problem >> with inference variable bounds is naturally addressed - but of course >> all code calling isSameTypes normally would now see a change in >> behavior, so we need to make sure that the new behavior is acceptable >> in all cases. But your analysis seems to suggest that most of the >> stuff just works and that was just me being overly conservative at >> the time - in which case we can happily change the code, and >> eliminate this source of complexity. >> >> I'll do some more tests on your patch and see how it goes. >> >> Maurizio >> >> >> On 20/01/18 22:17, B. Blaser wrote: >>> Hi, >>> >>> As noted previously in [1], 'isSameTypeLoose' doesn't work properly >>> with '==' instances of a same type variable with recursive bounds >>> which is indeed wrong. >>> >>> Moreover, 'isSameType' should be the unique 'isSameTypeStrict' >>> relation as explained in [2]. >>> >>> So, I simply tried to remove 'isSameTypeLoose' but I got, of course, >>> some failing tests like [3] & [4]. >>> >>> As it seems that 'isSameTypeStrict' is too strict for wildcards I kept >>> the default behavior in such cases, as here under. >>> >>> I did this experiment on a quite old JDK10 revision (sorry) with >>> encouraging test results (nothing seems to be broken). >>> >>> What do you think? >>> >>> Thanks, >>> Bernard >>> >>> [1] >>> http://mail.openjdk.java.net/pipermail/compiler-dev/2017-November/011291.html >>> [2] >>> http://mail.openjdk.java.net/pipermail/compiler-dev/2017-November/011296.html >>> [3] tools/javac/generics/wildcards/neg/CastTest.java >>> [4] tools/javac/generics/wildcards/pos/CastTest.java >>> >>> diff --git >>> a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java >>> b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java >>> --- >>> a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java >>> +++ >>> b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java >>> @@ -1031,9 +1031,7 @@ >>> ????????? return isSameType(t, s, false); >>> ????? } >>> ????? public boolean isSameType(Type t, Type s, boolean strict) { >>> -??????? return strict ? >>> -??????????????? isSameTypeStrict.visit(t, s) : >>> -??????????????? isSameTypeLoose.visit(t, s); >>> +??????? return isSameTypeStrict.visit(t, s); >>> ????? } >>> ????? // where >>> ????????? abstract class SameTypeVisitor extends TypeRelation { >>> @@ -1177,44 +1175,6 @@ >>> ????????? } >>> >>> ????????? /** >>> -???????? * Standard type-equality relation - type variables are >>> considered >>> -???????? * equals if they share the same type symbol. >>> -???????? */ >>> -??????? TypeRelation isSameTypeLoose = new LooseSameTypeVisitor(); >>> - >>> -??????? private class LooseSameTypeVisitor extends SameTypeVisitor { >>> - >>> -??????????? /** cache of the type-variable pairs being >>> (recursively) tested. */ >>> -??????????? private Set cache = new HashSet<>(); >>> - >>> -??????????? @Override >>> -??????????? boolean sameTypeVars(TypeVar tv1, TypeVar tv2) { >>> -??????????????? return tv1.tsym == tv2.tsym && checkSameBounds(tv1, >>> tv2); >>> -??????????? } >>> -??????????? @Override >>> -??????????? protected boolean containsTypes(List ts1, >>> List ts2) { >>> -??????????????? return containsTypeEquivalent(ts1, ts2); >>> -??????????? } >>> - >>> -??????????? /** >>> -???????????? * Since type-variable bounds can be recursive, we need >>> to protect against >>> -???????????? * infinite loops - where the same bounds are checked >>> over and over recursively. >>> -???????????? */ >>> -??????????? private boolean checkSameBounds(TypeVar tv1, TypeVar >>> tv2) { >>> -??????????????? TypePair p = new TypePair(tv1, tv2, true); >>> -??????????????? if (cache.add(p)) { >>> -??????????????????? try { >>> -??????????????????????? return visit(tv1.getUpperBound(), >>> tv2.getUpperBound()); >>> -??????????????????? } finally { >>> -??????????????????????? cache.remove(p); >>> -??????????????????? } >>> -??????????????? } else { >>> -??????????????????? return false; >>> -??????????????? } >>> -??????????? } >>> -??????? }; >>> - >>> -??????? /** >>> ?????????? * Strict type-equality relation - type variables are >>> considered >>> ?????????? * equals if they share the same object identity. >>> ?????????? */ >>> @@ -1227,17 +1187,6 @@ >>> ????????????? protected boolean containsTypes(List ts1, >>> List ts2) { >>> ????????????????? return isSameTypes(ts1, ts2, true); >>> ????????????? } >>> - >>> -??????????? @Override >>> -??????????? public Boolean visitWildcardType(WildcardType t, Type s) { >>> -??????????????? if (!s.hasTag(WILDCARD)) { >>> -??????????????????? return false; >>> -??????????????? } else { >>> -??????????????????? WildcardType t2 = (WildcardType)s; >>> -??????????????????? return t.kind == t2.kind && >>> -??????????????????????????? isSameType(t.type, t2.type, true); >>> -??????????????? } >>> -??????????? } >>> ????????? }; >>> >>> ????? // >> > -------------- next part -------------- A non-text attachment was scrubbed... Name: sameTypes-v2.patch Type: text/x-patch Size: 10141 bytes Desc: not available URL: From bsrbnd at gmail.com Mon Jan 22 13:25:16 2018 From: bsrbnd at gmail.com (B. Blaser) Date: Mon, 22 Jan 2018 14:25:16 +0100 Subject: Types.isSameType() unification In-Reply-To: <5dc109c2-d682-cc05-974e-167e999b9c2d@oracle.com> References: <08e6fa5a-12af-6f7b-57d6-4b763feb9c1f@oracle.com> <5dc109c2-d682-cc05-974e-167e999b9c2d@oracle.com> Message-ID: Looks good to me (thanks for all relevant updates). Cheers, Bernard On 22 January 2018 at 14:01, Maurizio Cimadamore wrote: > The attached patch looks good test-wise; apart from the > containsTypeEquivalent change (discussed in earlier email) I've also done > some cosmetic changes to get rid of redundant code. > > Vicente, could you please take a second look? > > Cheers > Maurizio > > > > On 22/01/18 12:07, Maurizio Cimadamore wrote: >> >> Quick update, >> I was unable to build the JDK with the patch you sent; the issue was that >> the patch alters the loose behaviro of type equality used in subtyping >> tests, so tests like the one below: >> >> class Foo> >> Comparator> <: Comparator> >> >> Started to fail. While this is ok spec-wise, the compiler currently tries >> to detect cases where two type arguments are effectively the same thing by >> using info on declared bounds. This is done in >> Types::containsTypeEquivalent, which is not used with a strict check. We >> might or might not want to get rid of that one too, but that's a battle for >> another day :-) >> >> The solution was to reinstate the use of containsTypeEquivalent in the >> type argument check in the sametype visitor. That gets the build going. I'm >> now running the tests and see where we're at. >> >> Maurizio >> >> >> >> On 22/01/18 09:34, Maurizio Cimadamore wrote: >>> >>> Hi B. >>> >>> interesting approach, thanks for the patch; digging a bit into the >>> history the loose vs. strict dichotomy started here: >>> >>> http://hg.openjdk.java.net/lambda/lambda/langtools/rev/1df20330f6bd#l1.63 >>> >>> As you can see, javac started out with a loose behavior, but then a >>> stricter semantics (closer to JLS) was required during incorporation: e.g. a >>> new bound should be added to an inference var only if this bound is >>> different from the existing ones; the loose same-ness check would consider >>> cloned inference-vars equivalent and, as such, was missing out on some extra >>> constraints - hence the strict version. >>> >>> At the time it did not occur to me that, maybe, the loose version was >>> just wrong and the compiler could be better off with the stricter version; >>> also, since we were in the middle of replacing an inference engine with a >>> new one, we were trying to limit the impact of new changes as much as >>> possible. >>> >>> Since your patch makes strict behavior the only choice, the problem with >>> inference variable bounds is naturally addressed - but of course all code >>> calling isSameTypes normally would now see a change in behavior, so we need >>> to make sure that the new behavior is acceptable in all cases. But your >>> analysis seems to suggest that most of the stuff just works and that was >>> just me being overly conservative at the time - in which case we can happily >>> change the code, and eliminate this source of complexity. >>> >>> I'll do some more tests on your patch and see how it goes. >>> >>> Maurizio >>> >>> >>> On 20/01/18 22:17, B. Blaser wrote: >>>> >>>> Hi, >>>> >>>> As noted previously in [1], 'isSameTypeLoose' doesn't work properly >>>> with '==' instances of a same type variable with recursive bounds >>>> which is indeed wrong. >>>> >>>> Moreover, 'isSameType' should be the unique 'isSameTypeStrict' >>>> relation as explained in [2]. >>>> >>>> So, I simply tried to remove 'isSameTypeLoose' but I got, of course, >>>> some failing tests like [3] & [4]. >>>> >>>> As it seems that 'isSameTypeStrict' is too strict for wildcards I kept >>>> the default behavior in such cases, as here under. >>>> >>>> I did this experiment on a quite old JDK10 revision (sorry) with >>>> encouraging test results (nothing seems to be broken). >>>> >>>> What do you think? >>>> >>>> Thanks, >>>> Bernard >>>> >>>> [1] >>>> http://mail.openjdk.java.net/pipermail/compiler-dev/2017-November/011291.html >>>> [2] >>>> http://mail.openjdk.java.net/pipermail/compiler-dev/2017-November/011296.html >>>> [3] tools/javac/generics/wildcards/neg/CastTest.java >>>> [4] tools/javac/generics/wildcards/pos/CastTest.java >>>> >>>> diff --git >>>> a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java >>>> b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java >>>> --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java >>>> +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java >>>> @@ -1031,9 +1031,7 @@ >>>> return isSameType(t, s, false); >>>> } >>>> public boolean isSameType(Type t, Type s, boolean strict) { >>>> - return strict ? >>>> - isSameTypeStrict.visit(t, s) : >>>> - isSameTypeLoose.visit(t, s); >>>> + return isSameTypeStrict.visit(t, s); >>>> } >>>> // where >>>> abstract class SameTypeVisitor extends TypeRelation { >>>> @@ -1177,44 +1175,6 @@ >>>> } >>>> >>>> /** >>>> - * Standard type-equality relation - type variables are >>>> considered >>>> - * equals if they share the same type symbol. >>>> - */ >>>> - TypeRelation isSameTypeLoose = new LooseSameTypeVisitor(); >>>> - >>>> - private class LooseSameTypeVisitor extends SameTypeVisitor { >>>> - >>>> - /** cache of the type-variable pairs being (recursively) >>>> tested. */ >>>> - private Set cache = new HashSet<>(); >>>> - >>>> - @Override >>>> - boolean sameTypeVars(TypeVar tv1, TypeVar tv2) { >>>> - return tv1.tsym == tv2.tsym && checkSameBounds(tv1, >>>> tv2); >>>> - } >>>> - @Override >>>> - protected boolean containsTypes(List ts1, List >>>> ts2) { >>>> - return containsTypeEquivalent(ts1, ts2); >>>> - } >>>> - >>>> - /** >>>> - * Since type-variable bounds can be recursive, we need >>>> to protect against >>>> - * infinite loops - where the same bounds are checked >>>> over and over recursively. >>>> - */ >>>> - private boolean checkSameBounds(TypeVar tv1, TypeVar tv2) { >>>> - TypePair p = new TypePair(tv1, tv2, true); >>>> - if (cache.add(p)) { >>>> - try { >>>> - return visit(tv1.getUpperBound(), >>>> tv2.getUpperBound()); >>>> - } finally { >>>> - cache.remove(p); >>>> - } >>>> - } else { >>>> - return false; >>>> - } >>>> - } >>>> - }; >>>> - >>>> - /** >>>> * Strict type-equality relation - type variables are >>>> considered >>>> * equals if they share the same object identity. >>>> */ >>>> @@ -1227,17 +1187,6 @@ >>>> protected boolean containsTypes(List ts1, List >>>> ts2) { >>>> return isSameTypes(ts1, ts2, true); >>>> } >>>> - >>>> - @Override >>>> - public Boolean visitWildcardType(WildcardType t, Type s) { >>>> - if (!s.hasTag(WILDCARD)) { >>>> - return false; >>>> - } else { >>>> - WildcardType t2 = (WildcardType)s; >>>> - return t.kind == t2.kind && >>>> - isSameType(t.type, t2.type, true); >>>> - } >>>> - } >>>> }; >>>> >>>> // >>> >>> >> > From vicente.romero at oracle.com Mon Jan 22 15:26:07 2018 From: vicente.romero at oracle.com (Vicente Romero) Date: Mon, 22 Jan 2018 10:26:07 -0500 Subject: Types.isSameType() unification In-Reply-To: <5dc109c2-d682-cc05-974e-167e999b9c2d@oracle.com> References: <08e6fa5a-12af-6f7b-57d6-4b763feb9c1f@oracle.com> <5dc109c2-d682-cc05-974e-167e999b9c2d@oracle.com> Message-ID: <13472c2d-de9f-946a-0ee4-f62f9102dc5e@oracle.com> On 01/22/2018 08:01 AM, Maurizio Cimadamore wrote: > The attached patch looks good test-wise; apart from the > containsTypeEquivalent change (discussed in earlier email) I've also > done some cosmetic changes to get rid of redundant code. > > Vicente, could you please take a second look? the patch looks OK modulo some documentation, inline comments, that applied to the old settings and that could be updated, > > Cheers > Maurizio Thanks, Vicente > > > On 22/01/18 12:07, Maurizio Cimadamore wrote: >> Quick update, >> I was unable to build the JDK with the patch you sent; the issue was >> that the patch alters the loose behaviro of type equality used in >> subtyping tests, so tests like the one below: >> >> class Foo> >> Comparator> <: Comparator> >> >> Started to fail. While this is ok spec-wise, the compiler currently >> tries to detect cases where two type arguments are effectively the >> same thing by using info on declared bounds. This is done in >> Types::containsTypeEquivalent, which is not used with a strict check. >> We might or might not want to get rid of that one too, but that's a >> battle for another day :-) >> >> The solution was to reinstate the use of containsTypeEquivalent in >> the type argument check in the sametype visitor. That gets the build >> going. I'm now running the tests and see where we're at. >> >> Maurizio >> >> >> >> On 22/01/18 09:34, Maurizio Cimadamore wrote: >>> Hi B. >>> >>> interesting approach, thanks for the patch; digging a bit into the >>> history the loose vs. strict dichotomy started here: >>> >>> http://hg.openjdk.java.net/lambda/lambda/langtools/rev/1df20330f6bd#l1.63 >>> >>> >>> As you can see, javac started out with a loose behavior, but then a >>> stricter semantics (closer to JLS) was required during >>> incorporation: e.g. a new bound should be added to an inference var >>> only if this bound is different from the existing ones; the loose >>> same-ness check would consider cloned inference-vars equivalent and, >>> as such, was missing out on some extra constraints - hence the >>> strict version. >>> >>> At the time it did not occur to me that, maybe, the loose version >>> was just wrong and the compiler could be better off with the >>> stricter version; also, since we were in the middle of replacing an >>> inference engine with a new one, we were trying to limit the impact >>> of new changes as much as possible. >>> >>> Since your patch makes strict behavior the only choice, the problem >>> with inference variable bounds is naturally addressed - but of >>> course all code calling isSameTypes normally would now see a change >>> in behavior, so we need to make sure that the new behavior is >>> acceptable in all cases. But your analysis seems to suggest that >>> most of the stuff just works and that was just me being overly >>> conservative at the time - in which case we can happily change the >>> code, and eliminate this source of complexity. >>> >>> I'll do some more tests on your patch and see how it goes. >>> >>> Maurizio >>> >>> >>> On 20/01/18 22:17, B. Blaser wrote: >>>> Hi, >>>> >>>> As noted previously in [1], 'isSameTypeLoose' doesn't work properly >>>> with '==' instances of a same type variable with recursive bounds >>>> which is indeed wrong. >>>> >>>> Moreover, 'isSameType' should be the unique 'isSameTypeStrict' >>>> relation as explained in [2]. >>>> >>>> So, I simply tried to remove 'isSameTypeLoose' but I got, of course, >>>> some failing tests like [3] & [4]. >>>> >>>> As it seems that 'isSameTypeStrict' is too strict for wildcards I kept >>>> the default behavior in such cases, as here under. >>>> >>>> I did this experiment on a quite old JDK10 revision (sorry) with >>>> encouraging test results (nothing seems to be broken). >>>> >>>> What do you think? >>>> >>>> Thanks, >>>> Bernard >>>> >>>> [1] >>>> http://mail.openjdk.java.net/pipermail/compiler-dev/2017-November/011291.html >>>> [2] >>>> http://mail.openjdk.java.net/pipermail/compiler-dev/2017-November/011296.html >>>> [3] tools/javac/generics/wildcards/neg/CastTest.java >>>> [4] tools/javac/generics/wildcards/pos/CastTest.java >>>> >>>> diff --git >>>> a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java >>>> b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java >>>> --- >>>> a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java >>>> +++ >>>> b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java >>>> @@ -1031,9 +1031,7 @@ >>>> ????????? return isSameType(t, s, false); >>>> ????? } >>>> ????? public boolean isSameType(Type t, Type s, boolean strict) { >>>> -??????? return strict ? >>>> -??????????????? isSameTypeStrict.visit(t, s) : >>>> -??????????????? isSameTypeLoose.visit(t, s); >>>> +??????? return isSameTypeStrict.visit(t, s); >>>> ????? } >>>> ????? // where >>>> ????????? abstract class SameTypeVisitor extends TypeRelation { >>>> @@ -1177,44 +1175,6 @@ >>>> ????????? } >>>> >>>> ????????? /** >>>> -???????? * Standard type-equality relation - type variables are >>>> considered >>>> -???????? * equals if they share the same type symbol. >>>> -???????? */ >>>> -??????? TypeRelation isSameTypeLoose = new LooseSameTypeVisitor(); >>>> - >>>> -??????? private class LooseSameTypeVisitor extends SameTypeVisitor { >>>> - >>>> -??????????? /** cache of the type-variable pairs being >>>> (recursively) tested. */ >>>> -??????????? private Set cache = new HashSet<>(); >>>> - >>>> -??????????? @Override >>>> -??????????? boolean sameTypeVars(TypeVar tv1, TypeVar tv2) { >>>> -??????????????? return tv1.tsym == tv2.tsym && >>>> checkSameBounds(tv1, tv2); >>>> -??????????? } >>>> -??????????? @Override >>>> -??????????? protected boolean containsTypes(List ts1, >>>> List ts2) { >>>> -??????????????? return containsTypeEquivalent(ts1, ts2); >>>> -??????????? } >>>> - >>>> -??????????? /** >>>> -???????????? * Since type-variable bounds can be recursive, we need >>>> to protect against >>>> -???????????? * infinite loops - where the same bounds are checked >>>> over and over recursively. >>>> -???????????? */ >>>> -??????????? private boolean checkSameBounds(TypeVar tv1, TypeVar >>>> tv2) { >>>> -??????????????? TypePair p = new TypePair(tv1, tv2, true); >>>> -??????????????? if (cache.add(p)) { >>>> -??????????????????? try { >>>> -??????????????????????? return visit(tv1.getUpperBound(), >>>> tv2.getUpperBound()); >>>> -??????????????????? } finally { >>>> -??????????????????????? cache.remove(p); >>>> -??????????????????? } >>>> -??????????????? } else { >>>> -??????????????????? return false; >>>> -??????????????? } >>>> -??????????? } >>>> -??????? }; >>>> - >>>> -??????? /** >>>> ?????????? * Strict type-equality relation - type variables are >>>> considered >>>> ?????????? * equals if they share the same object identity. >>>> ?????????? */ >>>> @@ -1227,17 +1187,6 @@ >>>> ????????????? protected boolean containsTypes(List ts1, >>>> List ts2) { >>>> ????????????????? return isSameTypes(ts1, ts2, true); >>>> ????????????? } >>>> - >>>> -??????????? @Override >>>> -??????????? public Boolean visitWildcardType(WildcardType t, Type >>>> s) { >>>> -??????????????? if (!s.hasTag(WILDCARD)) { >>>> -??????????????????? return false; >>>> -??????????????? } else { >>>> -??????????????????? WildcardType t2 = (WildcardType)s; >>>> -??????????????????? return t.kind == t2.kind && >>>> -??????????????????????????? isSameType(t.type, t2.type, true); >>>> -??????????????? } >>>> -??????????? } >>>> ????????? }; >>>> >>>> ????? // >>> >> > From jonathan.gibbons at oracle.com Mon Jan 22 15:34:54 2018 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Mon, 22 Jan 2018 07:34:54 -0800 Subject: Bug in javac release flag? In-Reply-To: References: Message-ID: Forwarding to compiler-dev, which is a better place to discuss this issue. -- Jon On 1/22/18 7:11 AM, Stephen Colebourne wrote: > I think I have a problem with the java release flag, reported by a user here: > https://github.com/ThreeTen/threeten-extra/issues/91 > > The particular case that is a problem are the new methods on java.lang.Math. > > Java 8 had these methods: > floorDiv(long,long) > floorDiv(int,int) > > Java 9 has these methods: > floorDiv(long,long) > floorDiv(int,int) > floorDiv(long,int) > > (there are similar new overloads for other method names) > > Clearly, if you build on Java 9, code can link to the new(long,int) > overload, but that code will get a NoSuchMethodError on Java 8. > > But, I am using Java 9 with the javac release flag set to be 8. If I > understand the release flag correctly, the (long,int) overload should > not be visible, and thus a different overload should be selected. > > So, is this a bug? Perhaps the tool that captures new method > signatures doesn't handle overloads? > > (ThreeTen-Extra v1.3 was built using Maven on Java 9 using Maven's > implementation of the release flag, so it could be Maven that is > buggy, but I don't think so as it produces the correct classfile > version number). > > thanks > Stephen From jan.lahoda at oracle.com Mon Jan 22 16:33:38 2018 From: jan.lahoda at oracle.com (Jan Lahoda) Date: Mon, 22 Jan 2018 17:33:38 +0100 Subject: Bug in javac release flag? In-Reply-To: References: Message-ID: <5A661262.7060608@oracle.com> Hi Stephen, I was looking at the historical data for 8 and 9 in JDK10, and the JDK 8 data appears to only declare the two overloads: http://hg.openjdk.java.net/jdk/jdk10/file/48ce4b11bc17/make/data/symbols/java.base-8.sym.txt#l2361 And the JDK 9 data appears to add the additional overload: http://hg.openjdk.java.net/jdk/jdk10/file/48ce4b11bc17/make/data/symbols/java.base-9.sym.txt#l525 So these appear to me to be OK. I also checked the content of the ct.sym, and the sig files in there appear to be OK as well - the JDK 8 version contains only two [overloads, while the JDK 9 version contains three overloads. So this appears to be reasonable. I also tried to compile and run: --- public class M { public static void main(String... args) { System.err.println(Math.floorDiv(0L, 1)); } } --- --- $ javac -fullversion javac full version "9+181" $ javac --release 8 M.java $ java -fullversion java full version "1.8.0_121-b13" $ java M 0 --- So that appears to be OK as well. I tried to compile the project using maven, and in debug output, I was able to find "--release 9", but not "--release 8", only "-target 1.8 -source 1.8". This will produce JDK 8 classfiles, but compile against the JDK 9 system modules. To get the new --release behavior, "--release " must be used. Jan On 22.1.2018 16:34, Jonathan Gibbons wrote: > Forwarding to compiler-dev, which is a better place to discuss this issue. > > -- Jon > > > On 1/22/18 7:11 AM, Stephen Colebourne wrote: >> I think I have a problem with the java release flag, reported by a >> user here: >> https://github.com/ThreeTen/threeten-extra/issues/91 >> >> The particular case that is a problem are the new methods on >> java.lang.Math. >> >> Java 8 had these methods: >> floorDiv(long,long) >> floorDiv(int,int) >> >> Java 9 has these methods: >> floorDiv(long,long) >> floorDiv(int,int) >> floorDiv(long,int) >> >> (there are similar new overloads for other method names) >> >> Clearly, if you build on Java 9, code can link to the new(long,int) >> overload, but that code will get a NoSuchMethodError on Java 8. >> >> But, I am using Java 9 with the javac release flag set to be 8. If I >> understand the release flag correctly, the (long,int) overload should >> not be visible, and thus a different overload should be selected. >> >> So, is this a bug? Perhaps the tool that captures new method >> signatures doesn't handle overloads? >> >> (ThreeTen-Extra v1.3 was built using Maven on Java 9 using Maven's >> implementation of the release flag, so it could be Maven that is >> buggy, but I don't think so as it produces the correct classfile >> version number). >> >> thanks >> Stephen > From scolebourne at joda.org Mon Jan 22 17:24:36 2018 From: scolebourne at joda.org (Stephen Colebourne) Date: Mon, 22 Jan 2018 17:24:36 +0000 Subject: Bug in javac release flag? In-Reply-To: <5A661262.7060608@oracle.com> References: <5A661262.7060608@oracle.com> Message-ID: On 22 January 2018 at 16:33, Jan Lahoda wrote: > I tried to compile the project using maven, and in debug output, I was able > to find "--release 9", but not "--release 8", only "-target 1.8 -source > 1.8". This will produce JDK 8 classfiles, but compile against the JDK 9 > system modules. To get the new --release behavior, "--release " > must be used. Thanks for looking. Why oh why is Maven implemented incorrectly.... thanks Stephen From brian.goetz at oracle.com Mon Jan 22 18:58:50 2018 From: brian.goetz at oracle.com (Brian Goetz) Date: Mon, 22 Jan 2018 13:58:50 -0500 Subject: Fwd: Bug in javac release flag? In-Reply-To: References: Message-ID: <83fbb3c3-ef75-9cb4-f3da-997587bb2413@oracle.com> Moving to compiler-dev. -------- Forwarded Message -------- Subject: Bug in javac release flag? Date: Mon, 22 Jan 2018 15:11:03 +0000 From: Stephen Colebourne To: core-libs-dev I think I have a problem with the java release flag, reported by a user here: https://github.com/ThreeTen/threeten-extra/issues/91 The particular case that is a problem are the new methods on java.lang.Math. Java 8 had these methods: floorDiv(long,long) floorDiv(int,int) Java 9 has these methods: floorDiv(long,long) floorDiv(int,int) floorDiv(long,int) (there are similar new overloads for other method names) Clearly, if you build on Java 9, code can link to the new(long,int) overload, but that code will get a NoSuchMethodError on Java 8. But, I am using Java 9 with the javac release flag set to be 8. If I understand the release flag correctly, the (long,int) overload should not be visible, and thus a different overload should be selected. So, is this a bug? Perhaps the tool that captures new method signatures doesn't handle overloads? (ThreeTen-Extra v1.3 was built using Maven on Java 9 using Maven's implementation of the release flag, so it could be Maven that is buggy, but I don't think so as it produces the correct classfile version number). thanks Stephen -------------- next part -------------- An HTML attachment was scrubbed... URL: From cushon at google.com Mon Jan 22 21:30:04 2018 From: cushon at google.com (Liam Miller-Cushon) Date: Mon, 22 Jan 2018 13:30:04 -0800 Subject: spec clarification: type annotations on static nested types In-Reply-To: References: <5A53D7C6.1070809@oracle.com> Message-ID: I double-checked that the type paths in the class file javac emits are: void f(@A One x) {} ... type_path_length 1 type path entry [0]: type_path_kind: 1, type_path_index: 0 void g(@A Two x) {} ... type_path_length 0 My understanding is still that javac uses type_path_kind=1 to step in to (non-static) inner classes, and reflection interprets type_path_kind=1 as stepping in to member classes (both non-static and static). Is this a javac bug, or a reflection bug, or am I confused? Thanks, On Mon, Jan 8, 2018 at 2:25 PM, Liam Miller-Cushon wrote: > Thanks! I have some follow-up questions inline - > > On Mon, Jan 8, 2018 at 12:42 PM, Alex Buckley > wrote: > >> A type annotation can apply to a type that's nested (i.e. deeper) in a >> *static* type though. Adapting an example from JLS 9.7.4: >> ... > > In the second case, the nested type which is being annotated is "C . D". >> The D part denotes a non-static nested type, yes, but the first type that >> we hit when stepping through the path -- C -- is static. The storage of >> @Foo thus involves a type_path that descends "deeper in a nested type" -- >> mentioning anything about static here would be wrong. As a separate issue, >> the location where we ultimately find @Foo is, in fact, a non-static member >> type, so javap helpfully shows that location as INNER_TYPE: >> > > I didn't express what I was thinking, sorry. I agree we're not interested > in the static-ness of the outer type. > > I think javac currently emits type_path_kind=1 steps only when descending > in to a member type that is non-static, and that the > "location=[INNER_TYPE]" bit of javap's output corresponds directly to the > type_path structure in the class file. > > Is that accurate, and if so is it to spec? > > My understanding of the `@Foo C . D x;` example was that no type_path is > necessary even though C is a member of Test, because C is a static member > and Test is 'scoping construct' that is not a valid type annotation target. > > I don't like how @A has been bounced out of the nested type "T . Two" so >> that it allegedly applies to the type of the formal parameter as a whole. >> @A actually applies to the type of the static member Two that is declared >> by T. >> > > Similar to the other example, isn't "@A actually applies to the type of > the static member Two" the only interpretation for a type annotation > attribute that applies to `T . Two`, since T is a scoping construct and is > not a valid type annotation target? > -------------- next part -------------- An HTML attachment was scrubbed... URL: From maurizio.cimadamore at oracle.com Wed Jan 24 15:58:01 2018 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Wed, 24 Jan 2018 15:58:01 +0000 Subject: RFR 8196074: Remove uses of loose type equality tests Message-ID: <472c8a1e-6ad0-8001-e8ca-907729ce0450@oracle.com> Hi, this patch is the result of the discussion we had in this thread: http://mail.openjdk.java.net/pipermail/compiler-dev/2018-January/011593.html The goal is to remove the 'loose' type equality check from javac, in order to achieve better alignment with the spec. Thanks to B. Blaser for contributing to this effort. Patch here: http://cr.openjdk.java.net/~mcimadamore/8196074/ Cheers Maurizio From vicente.romero at oracle.com Wed Jan 24 17:22:31 2018 From: vicente.romero at oracle.com (Vicente Romero) Date: Wed, 24 Jan 2018 12:22:31 -0500 Subject: RFR 8196074: Remove uses of loose type equality tests In-Reply-To: <472c8a1e-6ad0-8001-e8ca-907729ce0450@oracle.com> References: <472c8a1e-6ad0-8001-e8ca-907729ce0450@oracle.com> Message-ID: looks good, Vicente On 01/24/2018 10:58 AM, Maurizio Cimadamore wrote: > Hi, > this patch is the result of the discussion we had in this thread: > > http://mail.openjdk.java.net/pipermail/compiler-dev/2018-January/011593.html > > > The goal is to remove the 'loose' type equality check from javac, in > order to achieve better alignment with the spec. > > Thanks to B. Blaser for contributing to this effort. > > Patch here: > > http://cr.openjdk.java.net/~mcimadamore/8196074/ > > Cheers > Maurizio > From srinivas.dama at oracle.com Thu Jan 25 08:19:20 2018 From: srinivas.dama at oracle.com (Srinivas Dama) Date: Thu, 25 Jan 2018 00:19:20 -0800 (PST) Subject: RFR: 8152616: com.sun.tools.javac.tree.Pretty generates nested comments for enum Message-ID: <96910f02-a090-41b6-b7e9-53bfc18935f1@default> Hi, Please review http://cr.openjdk.java.net/~sdama/8152616/webrev.00/ for https://bugs.openjdk.java.net/browse/JDK-8152616 Regards, Srinivas -------------- next part -------------- An HTML attachment was scrubbed... URL: From maurizio.cimadamore at oracle.com Thu Jan 25 11:17:54 2018 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 25 Jan 2018 11:17:54 +0000 Subject: RFR: 8152616: com.sun.tools.javac.tree.Pretty generates nested comments for enum In-Reply-To: <96910f02-a090-41b6-b7e9-53bfc18935f1@default> References: <96910f02-a090-41b6-b7e9-53bfc18935f1@default> Message-ID: Hi Srinivas, two comments: * why the logic for printing the enum constant constructor type arguments? It is not possible to specify explicit constructor arguments on enum constants. (Funnily, javac attempts to parse them, but the attempt fails because the parser mode is wrong, so an error is generated). The spec has no place for them in the grammar: https://docs.oracle.com/javase/specs/jls/se9/html/jls-8.html#jls-8.9.1 * I believe your end of block comment is misplaced, and it skips enum constructor arguments - that is, I see that '*/' is put AFTER the constructor arguments and before the '{' if any. Now, that doesn't affect your test, because the constants in the test don't have constructor arguments, but I believe there's bug lurking in here? Cheers Maurizio On 25/01/18 08:19, Srinivas Dama wrote: > > Hi, > > Please review http://cr.openjdk.java.net/~sdama/8152616/webrev.00/ > for > https://bugs.openjdk.java.net/browse/JDK-8152616 > > Regards, > > Srinivas > -------------- next part -------------- An HTML attachment was scrubbed... URL: From jan.lahoda at oracle.com Thu Jan 25 17:44:30 2018 From: jan.lahoda at oracle.com (Jan Lahoda) Date: Thu, 25 Jan 2018 18:44:30 +0100 Subject: RFR JDK-8194764: javac incorrectly flags deprecated for removal imports Message-ID: <5A6A177E.7040300@oracle.com> Hi, For a sample code like: --- D.java package a; @Deprecated(forRemoval=true) public class D {} ---A.java package a; import a.D; public class A { public static void main(String[] args) { D d; } } --- When javac is invoked (on JDK 10+) with -source 9, there is an incorrect deprecation warning on import (this warning should not be printed, and was not printed on JDK 9): --- $ javac -source 9 D.java A.java warning: [options] bootstrap class path not set in conjunction with -source 9 A.java:3: warning: [removal] D in a has been deprecated and marked for removal import a.D; ^ A.java:7: warning: [removal] D in a has been deprecated and marked for removal D d; ^ 3 warnings --- This appears to be caused by small mistake that enabled deprecation warnings for source levels up to 9, inclusive, while it should be enabled only for source levels up to 8, inclusive. Proposed webrev: http://cr.openjdk.java.net/~jlahoda/8194764/webrev.00/ Bug: https://bugs.openjdk.java.net/browse/JDK-8194764 How does this look? Thanks, Jan From maurizio.cimadamore at oracle.com Thu Jan 25 17:54:07 2018 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 25 Jan 2018 17:54:07 +0000 Subject: RFR JDK-8194764: javac incorrectly flags deprecated for removal imports In-Reply-To: <5A6A177E.7040300@oracle.com> References: <5A6A177E.7040300@oracle.com> Message-ID: Looks good, sorry for the mistake :-) Maurizio On 25/01/18 17:44, Jan Lahoda wrote: > Hi, > > For a sample code like: > --- D.java > package a; > > @Deprecated(forRemoval=true) > public class D {} > ---A.java > package a; > > import a.D; > > public class A { > ??? public static void main(String[] args) { > ??????? D d; > ??? } > } > --- > > When javac is invoked (on JDK 10+) with -source 9, there is an > incorrect deprecation warning on import (this warning should not be > printed, and was not printed on JDK 9): > --- > $ javac -source 9 D.java A.java > warning: [options] bootstrap class path not set in conjunction with > -source 9 > A.java:3: warning: [removal] D in a has been deprecated and marked for > removal > import a.D; > ??????? ^ > A.java:7: warning: [removal] D in a has been deprecated and marked for > removal > ??????? D d; > ??????? ^ > 3 warnings > --- > > This appears to be caused by small mistake that enabled deprecation > warnings for source levels up to 9, inclusive, while it should be > enabled only for source levels up to 8, inclusive. > > Proposed webrev: http://cr.openjdk.java.net/~jlahoda/8194764/webrev.00/ > Bug: https://bugs.openjdk.java.net/browse/JDK-8194764 > > How does this look? > > Thanks, > ??? Jan From cushon at google.com Thu Jan 25 18:27:29 2018 From: cushon at google.com (Liam Miller-Cushon) Date: Thu, 25 Jan 2018 10:27:29 -0800 Subject: RFR 8194268: Incorrect parameter names for synthetic methods In-Reply-To: References: Message-ID: Bump. On Fri, Dec 29, 2017 at 2:24 PM, Liam Miller-Cushon wrote: > Hello, > > This fixes a mistake in http://hg.openjdk.java.net/ > jdk/jdk/rev/89f6aa26fd6c > that caused incorrect parameter names to be generated for synthetic > methods. > As I mentioned in the bug I don't think it's a regression, but it still > seems > worth cleaning up. > > bug: https://bugs.openjdk.java.net/browse/JDK-8194268 > webrev: http://cr.openjdk.java.net/~cushon/8194268/webrev.00/ > > Thanks, > Liam > -------------- next part -------------- An HTML attachment was scrubbed... URL: From cushon at google.com Thu Jan 25 18:27:40 2018 From: cushon at google.com (Liam Miller-Cushon) Date: Thu, 25 Jan 2018 10:27:40 -0800 Subject: RFR: 8193037 package-info annotations are not reported when annotation processing is enabled In-Reply-To: References: Message-ID: Friendly ping. On Mon, Jan 8, 2018 at 11:42 AM, Liam Miller-Cushon wrote: > Is anyone interested in sponsoring this patch? > > On Tue, Dec 5, 2017 at 5:49 PM, Liam Miller-Cushon > wrote: > >> Hello, >> >> Please review the following fix for JDK-8193037. >> >> javac should only reset package-info symbols between annotation >> processing rounds if >> the package-info is being compiled from source. Previously package-infos >> loaded from >> the classpath were reset and not reinitialized, leading to package >> annotations being >> unavailable during later annotation processing rounds. >> >> I included an additional test case to ensure that package-infos are still >> reset when >> necessary. Related discussion: >> http://mail.openjdk.java.net/pipermail/compiler-dev/2017-Dec >> ember/011398.html >> >> bug: https://bugs.openjdk.java.net/browse/JDK-8193037 >> webrev: http://cr.openjdk.java.net/~cushon/8193037/webrev.00/ >> > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From cushon at google.com Thu Jan 25 23:19:43 2018 From: cushon at google.com (Liam Miller-Cushon) Date: Thu, 25 Jan 2018 15:19:43 -0800 Subject: RFR: JDK-8179373: javac -verbose logs the class path multiple times In-Reply-To: References: Message-ID: The changeset is attached and ready to push. On Fri, Jan 12, 2018 at 8:31 AM, Liam Miller-Cushon wrote: > Thanks, done: > http://cr.openjdk.java.net/~cushon/8179373/webrev.01/ > > On Fri, Jan 12, 2018 at 6:51 AM, Martin Buchholz > wrote: > >> Looks good. >> >> Maybe add comment >> >> + verbosePath = false; // print once per compile >> >> Maybe rename "l" to "line". >> >> On Thu, Jan 11, 2018 at 10:12 PM, Liam Miller-Cushon >> wrote: >> >>> Please review (another) trivial fix for the output from "javac -verbose". >>> >>> bug: https://bugs.openjdk.java.net/browse/JDK-8179373 >>> webrev: http://cr.openjdk.java.net/~cushon/8179373/webrev.00/ >>> >>> Thanks, >>> Liam >>> >> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 8179373.patch Type: text/x-patch Size: 4235 bytes Desc: not available URL: From jan.lahoda at oracle.com Fri Jan 26 18:34:35 2018 From: jan.lahoda at oracle.com (Jan Lahoda) Date: Fri, 26 Jan 2018 19:34:35 +0100 Subject: RFR 8194268: Incorrect parameter names for synthetic methods In-Reply-To: References: Message-ID: <5A6B74BB.1040200@oracle.com> Sorry for delay. Seems OK to me, I'll run tests and push early next week. Thanks, Jan On 25.1.2018 19:27, Liam Miller-Cushon wrote: > Bump. > > On Fri, Dec 29, 2017 at 2:24 PM, Liam Miller-Cushon > wrote: > > Hello, > > This fixes a mistake in > http://hg.openjdk.java.net/jdk/jdk/rev/89f6aa26fd6c > > that caused incorrect parameter names to be generated for synthetic > methods. > As I mentioned in the bug I don't think it's a regression, but it > still seems > worth cleaning up. > > bug: https://bugs.openjdk.java.net/browse/JDK-8194268 > > webrev: http://cr.openjdk.java.net/~cushon/8194268/webrev.00/ > > > Thanks, > Liam > > From cushon at google.com Fri Jan 26 19:30:12 2018 From: cushon at google.com (Liam Miller-Cushon) Date: Fri, 26 Jan 2018 11:30:12 -0800 Subject: RFR 8194268: Incorrect parameter names for synthetic methods In-Reply-To: <5A6B74BB.1040200@oracle.com> References: <5A6B74BB.1040200@oracle.com> Message-ID: Thanks! The changeset is attached. On Fri, Jan 26, 2018 at 10:34 AM, Jan Lahoda wrote: > Sorry for delay. Seems OK to me, I'll run tests and push early next week. > > Thanks, > Jan > > On 25.1.2018 19:27, Liam Miller-Cushon wrote: > >> Bump. >> >> On Fri, Dec 29, 2017 at 2:24 PM, Liam Miller-Cushon > > wrote: >> >> Hello, >> >> This fixes a mistake in >> http://hg.openjdk.java.net/jdk/jdk/rev/89f6aa26fd6c >> >> that caused incorrect parameter names to be generated for synthetic >> methods. >> As I mentioned in the bug I don't think it's a regression, but it >> still seems >> worth cleaning up. >> >> bug: https://bugs.openjdk.java.net/browse/JDK-8194268 >> >> webrev: http://cr.openjdk.java.net/~cushon/8194268/webrev.00/ >> >> >> Thanks, >> Liam >> >> >> -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 8194268.patch Type: text/x-patch Size: 4412 bytes Desc: not available URL: From jnape09 at gmail.com Sun Jan 28 02:40:28 2018 From: jnape09 at gmail.com (John Napier) Date: Sat, 27 Jan 2018 18:40:28 -0800 Subject: JDK-8188144 regression in method reference type-checking In-Reply-To: References: Message-ID: <066AD689-9C32-47AF-8761-AEED4D50FA0B@gmail.com> Thanks very much for the follow up, Maurizio. I?m sad to hear that, as this bug bit me fairly severely, but c'est la vie. I?m glad at least it will be fixed in 10. For my own edification, how early could I have reported it do you think for it to have made it in to the 9 patch release? I knew about it for a few weeks before I got up the energy to try to shrink the problem down to the least amount of essential code and put together a proper test case. I ask because there are other bugs I?d like to report that are of the same ilk, and I?m curious to know what kind of time line I should be observing (relative to the release schedule) to maximize my chance of getting them fixed in the next release. Did it miss the patch because of severity, or because it missed some 6 month cut off, or some combination of the two? Thanks again, cheers! > On Jan 15, 2018, at 3:02 AM, Maurizio Cimadamore wrote: > > Hi John, > unfortunately the only planned update to JDK 9 is shipping very soon, and it's too late now to integrate fix on it. So, the next planned release with the fix is gonna be JDK 10 (unless a new maintainer for JDK 9 is going to step forward) - see: > > http://mail.openjdk.java.net/pipermail/jdk-updates-dev/2017-November/000024.html > > Also, a related (and recent) thread (thanks to Sean Coffey to point that out): > > http://mail.openjdk.java.net/pipermail/jdk-updates-dev/2018-January/000028.html > > Thanks > Maurizio > > > > > On 14/01/18 21:38, John Napier wrote: >> Hello Maurizio, >> >> I was the original reporter of JDK-8188144 to the JetBrains folks, who ultimately forwarded it over to you all, where it seems you?ve fixed it (Thank you!). It?s logged as a P3 that is targeting 10 but was resolved in build b26; wasn?t that one of the old Java9 early access builds? Is this bug fix planned for the next patch release of 9, or is it only targeted for 10? >> >> Cheers, >> John > -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: Message signed with OpenPGP URL: From maurizio.cimadamore at oracle.com Mon Jan 29 10:04:34 2018 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Mon, 29 Jan 2018 10:04:34 +0000 Subject: JDK-8188144 regression in method reference type-checking In-Reply-To: <066AD689-9C32-47AF-8761-AEED4D50FA0B@gmail.com> References: <066AD689-9C32-47AF-8761-AEED4D50FA0B@gmail.com> Message-ID: <7a7b46ff-077f-3975-6dd3-c81be2121e3a@oracle.com> Hi John, there are few things to considered when backporting a bug fix; not all bugs are created equals, so, for instance, types system issues (such as this one) require more 'bake time' to make sure the fix doesn't accidentally introduce further regressions; in this case, I see that the bug has been fixed in October, so one could argue that we had enough bake time. Another factor that we consider is how severe the bug appears to be; are there workarounds? Is it likely to impact a lot of developers? If the answer is likely to be negative on both fronts, then it's typically not worth the risk backporting the fix (given it might also have a chance to unsettle things), That said, these judgements do not occur in a vacuum - that is, they are affected by emails we receive and other bugs we see reported - so, if a bug has 12 duplicates, we can infer that there's a demand for the fix; if we receive many complaints over a specific bug in the mailing list we might equally infer that it's worth backporting. In this case it was a close call; there was indeed a duplicate, but looking a the test case, they didn't strike us as something that was in urgent need to be fixed - which might or might not have been the right call (with with not much data it's always hard to get it right). I think what you did was fine - it was just bad luck; note that for every new release there will be two updates, and that updates take place quarterly (Jan, Apr, Jul, Oct), so it should be easy to figure out, from release date of JDK N, what the last update of N would be (and workout some kind of 'deadline' for bug reports that you would like to see making through the update). I hope this helps Maurizio On 28/01/18 02:40, John Napier wrote: > Thanks very much for the follow up, Maurizio. > > I?m sad to hear that, as this bug bit me fairly severely, but c'est la vie. I?m glad at least it will be fixed in 10. > > For my own edification, how early could I have reported it do you think for it to have made it in to the 9 patch release? I knew about it for a few weeks before I got up the energy to try to shrink the problem down to the least amount of essential code and put together a proper test case. I ask because there are other bugs I?d like to report that are of the same ilk, and I?m curious to know what kind of time line I should be observing (relative to the release schedule) to maximize my chance of getting them fixed in the next release. > > Did it miss the patch because of severity, or because it missed some 6 month cut off, or some combination of the two? > > Thanks again, cheers! > >> On Jan 15, 2018, at 3:02 AM, Maurizio Cimadamore wrote: >> >> Hi John, >> unfortunately the only planned update to JDK 9 is shipping very soon, and it's too late now to integrate fix on it. So, the next planned release with the fix is gonna be JDK 10 (unless a new maintainer for JDK 9 is going to step forward) - see: >> >> http://mail.openjdk.java.net/pipermail/jdk-updates-dev/2017-November/000024.html >> >> Also, a related (and recent) thread (thanks to Sean Coffey to point that out): >> >> http://mail.openjdk.java.net/pipermail/jdk-updates-dev/2018-January/000028.html >> >> Thanks >> Maurizio >> >> >> >> >> On 14/01/18 21:38, John Napier wrote: >>> Hello Maurizio, >>> >>> I was the original reporter of JDK-8188144 to the JetBrains folks, who ultimately forwarded it over to you all, where it seems you?ve fixed it (Thank you!). It?s logged as a P3 that is targeting 10 but was resolved in build b26; wasn?t that one of the old Java9 early access builds? Is this bug fix planned for the next patch release of 9, or is it only targeted for 10? >>> >>> Cheers, >>> John From jnape09 at gmail.com Mon Jan 29 20:56:47 2018 From: jnape09 at gmail.com (John Napier) Date: Mon, 29 Jan 2018 14:56:47 -0600 Subject: JDK-8188144 regression in method reference type-checking In-Reply-To: <7a7b46ff-077f-3975-6dd3-c81be2121e3a@oracle.com> References: <066AD689-9C32-47AF-8761-AEED4D50FA0B@gmail.com> <7a7b46ff-077f-3975-6dd3-c81be2121e3a@oracle.com> Message-ID: That explanation is eminently helpful Maurizio, thanks for the thorough and thoughtful reply. As you say, this one seems like bad luck that I?m so susceptible to this and the community perhaps isn?t. Oh well. I think I?m all set. Thanks again. > On Jan 29, 2018, at 4:04 AM, Maurizio Cimadamore wrote: > > Hi John, > there are few things to considered when backporting a bug fix; not all bugs are created equals, so, for instance, types system issues (such as this one) require more 'bake time' to make sure the fix doesn't accidentally introduce further regressions; in this case, I see that the bug has been fixed in October, so one could argue that we had enough bake time. > > Another factor that we consider is how severe the bug appears to be; are there workarounds? Is it likely to impact a lot of developers? If the answer is likely to be negative on both fronts, then it's typically not worth the risk backporting the fix (given it might also have a chance to unsettle things), > > That said, these judgements do not occur in a vacuum - that is, they are affected by emails we receive and other bugs we see reported - so, if a bug has 12 duplicates, we can infer that there's a demand for the fix; if we receive many complaints over a specific bug in the mailing list we might equally infer that it's worth backporting. > > In this case it was a close call; there was indeed a duplicate, but looking a the test case, they didn't strike us as something that was in urgent need to be fixed - which might or might not have been the right call (with with not much data it's always hard to get it right). > > I think what you did was fine - it was just bad luck; note that for every new release there will be two updates, and that updates take place quarterly (Jan, Apr, Jul, Oct), so it should be easy to figure out, from release date of JDK N, what the last update of N would be (and workout some kind of 'deadline' for bug reports that you would like to see making through the update). > > I hope this helps > Maurizio > > > >> On 28/01/18 02:40, John Napier wrote: >> Thanks very much for the follow up, Maurizio. >> >> I?m sad to hear that, as this bug bit me fairly severely, but c'est la vie. I?m glad at least it will be fixed in 10. >> >> For my own edification, how early could I have reported it do you think for it to have made it in to the 9 patch release? I knew about it for a few weeks before I got up the energy to try to shrink the problem down to the least amount of essential code and put together a proper test case. I ask because there are other bugs I?d like to report that are of the same ilk, and I?m curious to know what kind of time line I should be observing (relative to the release schedule) to maximize my chance of getting them fixed in the next release. >> >> Did it miss the patch because of severity, or because it missed some 6 month cut off, or some combination of the two? >> >> Thanks again, cheers! >> >>> On Jan 15, 2018, at 3:02 AM, Maurizio Cimadamore wrote: >>> >>> Hi John, >>> unfortunately the only planned update to JDK 9 is shipping very soon, and it's too late now to integrate fix on it. So, the next planned release with the fix is gonna be JDK 10 (unless a new maintainer for JDK 9 is going to step forward) - see: >>> >>> http://mail.openjdk.java.net/pipermail/jdk-updates-dev/2017-November/000024.html >>> >>> Also, a related (and recent) thread (thanks to Sean Coffey to point that out): >>> >>> http://mail.openjdk.java.net/pipermail/jdk-updates-dev/2018-January/000028.html >>> >>> Thanks >>> Maurizio >>> >>> >>> >>> >>>> On 14/01/18 21:38, John Napier wrote: >>>> Hello Maurizio, >>>> >>>> I was the original reporter of JDK-8188144 to the JetBrains folks, who ultimately forwarded it over to you all, where it seems you?ve fixed it (Thank you!). It?s logged as a P3 that is targeting 10 but was resolved in build b26; wasn?t that one of the old Java9 early access builds? Is this bug fix planned for the next patch release of 9, or is it only targeted for 10? >>>> >>>> Cheers, >>>> John > From martinrb at google.com Mon Jan 29 21:49:18 2018 From: martinrb at google.com (Martin Buchholz) Date: Mon, 29 Jan 2018 13:49:18 -0800 Subject: RFR: JDK-8179373: javac -verbose logs the class path multiple times In-Reply-To: References: Message-ID: Pushed by this semi-imposter javac engineer. On Thu, Jan 25, 2018 at 3:19 PM, Liam Miller-Cushon wrote: > The changeset is attached and ready to push. > > On Fri, Jan 12, 2018 at 8:31 AM, Liam Miller-Cushon > wrote: > >> Thanks, done: >> http://cr.openjdk.java.net/~cushon/8179373/webrev.01/ >> >> On Fri, Jan 12, 2018 at 6:51 AM, Martin Buchholz >> wrote: >> >>> Looks good. >>> >>> Maybe add comment >>> >>> + verbosePath = false; // print once per compile >>> >>> Maybe rename "l" to "line". >>> >>> On Thu, Jan 11, 2018 at 10:12 PM, Liam Miller-Cushon >>> wrote: >>> >>>> Please review (another) trivial fix for the output from "javac >>>> -verbose". >>>> >>>> bug: https://bugs.openjdk.java.net/browse/JDK-8179373 >>>> webrev: http://cr.openjdk.java.net/~cushon/8179373/webrev.00/ >>>> >>>> Thanks, >>>> Liam >>>> >>> >>> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From vicente.romero at oracle.com Tue Jan 30 13:42:29 2018 From: vicente.romero at oracle.com (Vicente Romero) Date: Tue, 30 Jan 2018 08:42:29 -0500 Subject: RFR 8194268: Incorrect parameter names for synthetic methods In-Reply-To: References: <5A6B74BB.1040200@oracle.com> Message-ID: looks good, I can help pushing it Vicente On 01/26/2018 02:30 PM, Liam Miller-Cushon wrote: > Thanks! The changeset is attached. > > On Fri, Jan 26, 2018 at 10:34 AM, Jan Lahoda > wrote: > > Sorry for delay. Seems OK to me, I'll run tests and push early > next week. > > Thanks, > ? ? ?Jan > > On 25.1.2018 19:27, Liam Miller-Cushon wrote: > > Bump. > > On Fri, Dec 29, 2017 at 2:24 PM, Liam Miller-Cushon > > >> wrote: > > ? ? Hello, > > ? ? This fixes a mistake in > http://hg.openjdk.java.net/jdk/jdk/rev/89f6aa26fd6c > > ? ? > > ? ? that caused incorrect parameter names to be generated for > synthetic > ? ? methods. > ? ? As I mentioned in the bug I don't think it's a regression, > but it > ? ? still seems > ? ? worth cleaning up. > > ? ? bug: https://bugs.openjdk.java.net/browse/JDK-8194268 > > ? ? > > ? ? webrev: > http://cr.openjdk.java.net/~cushon/8194268/webrev.00/ > > ? ? > > > ? ? Thanks, > ? ? Liam > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From jan.lahoda at oracle.com Tue Jan 30 14:38:07 2018 From: jan.lahoda at oracle.com (Jan Lahoda) Date: Tue, 30 Jan 2018 15:38:07 +0100 Subject: RFR 8194268: Incorrect parameter names for synthetic methods In-Reply-To: References: <5A6B74BB.1040200@oracle.com> Message-ID: <5A70834F.2090907@oracle.com> I've just pushed the change: http://hg.openjdk.java.net/jdk/jdk/rev/b2f2bdba0472 Thanks for the patch and for the offer for help. Jan On 30.1.2018 14:42, Vicente Romero wrote: > looks good, I can help pushing it > > Vicente > > On 01/26/2018 02:30 PM, Liam Miller-Cushon wrote: >> Thanks! The changeset is attached. >> >> On Fri, Jan 26, 2018 at 10:34 AM, Jan Lahoda > > wrote: >> >> Sorry for delay. Seems OK to me, I'll run tests and push early >> next week. >> >> Thanks, >> Jan >> >> On 25.1.2018 19:27, Liam Miller-Cushon wrote: >> >> Bump. >> >> On Fri, Dec 29, 2017 at 2:24 PM, Liam Miller-Cushon >> >> >> wrote: >> >> Hello, >> >> This fixes a mistake in >> http://hg.openjdk.java.net/jdk/jdk/rev/89f6aa26fd6c >> >> > > >> that caused incorrect parameter names to be generated for >> synthetic >> methods. >> As I mentioned in the bug I don't think it's a regression, >> but it >> still seems >> worth cleaning up. >> >> bug: https://bugs.openjdk.java.net/browse/JDK-8194268 >> >> > > >> webrev: >> http://cr.openjdk.java.net/~cushon/8194268/webrev.00/ >> >> > > >> >> Thanks, >> Liam >> >> >> > From paul.sandoz at oracle.com Wed Jan 31 17:07:14 2018 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Wed, 31 Jan 2018 09:07:14 -0800 Subject: RFR 8196508 Add jdeprscan test TestRelease.java to the problem list Message-ID: <6591CD48-B459-47A5-B293-7A75D30266D4@oracle.com> Hi, I am blocked pushing the change sets to constant dynamic due to the failure of jdeprscan test TestRelease.java. So i would like to add this to the problem list, push to the hs repo, and then i can push constant dynamic to hs. I have conservatively used a separate issue to that of another possibly related test on the problem list. Without further investigation it?s hard to tell if the two are related and i would prefer not to get side-tracked right now. Paul. # jdeps tools/jdeprscan/tests/jdk/jdeprscan/TestNotFound.java 8193784 generic-all temporary until support for --release 11 is worked out +tools/jdeprscan/tests/jdk/jdeprscan/TestRelease.java 8196479 generic-all temporary until support for --release 11 is worked out From stuart.marks at oracle.com Wed Jan 31 18:35:08 2018 From: stuart.marks at oracle.com (Stuart Marks) Date: Wed, 31 Jan 2018 10:35:08 -0800 Subject: RFR 8196508 Add jdeprscan test TestRelease.java to the problem list In-Reply-To: <6591CD48-B459-47A5-B293-7A75D30266D4@oracle.com> References: <6591CD48-B459-47A5-B293-7A75D30266D4@oracle.com> Message-ID: <2842cafe-b87e-55cb-33b1-d97ac37e4a46@oracle.com> Hi Paul, This looks fine. I think it makes sense to use a separate bug for this, since JDK-8193784 seems to cover --release support for tools in general, and JDK-8196479 covers specific jdeprscan changes. Thanks, s'marks On 1/31/18 9:07 AM, Paul Sandoz wrote: > Hi, > > I am blocked pushing the change sets to constant dynamic due to the failure of jdeprscan test TestRelease.java. > > So i would like to add this to the problem list, push to the hs repo, and then i can push constant dynamic to hs. > > I have conservatively used a separate issue to that of another possibly related test on the problem list. Without further investigation it?s hard to tell if the two are related and i would prefer not to get side-tracked right now. > > Paul. > > # jdeps > > tools/jdeprscan/tests/jdk/jdeprscan/TestNotFound.java 8193784 generic-all temporary until support for --release 11 is worked out > +tools/jdeprscan/tests/jdk/jdeprscan/TestRelease.java 8196479 generic-all temporary until support for --release 11 is worked out >