From georgiy.rakov at oracle.com Mon Aug 3 12:46:05 2015 From: georgiy.rakov at oracle.com (Georgiy Rakov) Date: Mon, 3 Aug 2015 15:46:05 +0300 Subject: The supertype of anonymous class is expected to be a raw type Message-ID: <55BF628D.7070502@oracle.com> Hello, let's consider following example: import java.lang.reflect.Type;import java.lang.reflect.ParameterizedType;class MyType {}public class Test22 {public static void main(String argv[]) {Bar foo = new Bar("str", new MyType()){ };Type actualSuperType = foo.getClass().getGenericSuperclass();if ( actualSuperType instanceof ParameterizedType ) {System.out.println("Parameterized");}}}class Bar {public Bar(T a1, MyType a2){ }} When compiled and run by JDK9b75 "Parameterized" is printed. However according to my understanding it shouldn't have to. The reasons for this are presented below: 1. According to the following assertion specified in JDK-8073593 the superclass of anonymous class should be equal to the return type of the method derived from Bar class constructor: - The superclass or superinterface type of the anonymous class is the return type, T, determined for mj (15.12.2.6). 2. The second actual argument for the constructor is of a raw type MyType while the corresponding formal parameter is a parameterized type MyType. So unchecked conversion is necessary in order for the only Bar constructor to become applicable for the provided invocation. 3. According to assertion presented above the return type is determined by 15.12.2.6 which states following: * If the chosen method is generic and the method invocation provides explicit type arguments, let Pi be the type parameters of the method and let Ti be the explicit type arguments provided for the method invocation (1 ? i ? p). Then: o If unchecked conversion was necessary for the method to be applicable, then the invocation type's parameter types are obtained by applying the substitution [P1:=T1, ..., Pp:=Tp] to the parameter types of the method's type, and the invocation type's return type and thrown types are given by the erasure of the return type and thrown types of the method's type. Namely it says that the return type of the invocation type is the erasure of the return type of the method's type, provided unchecked conversion was necessary for the method to be applicable. According to step 2 unchecked conversion was necessary for the method to be applicable so the return type of the method is the erasure of MyType, i.e. MyType. 4. So according to step 1 given above the superclass of the anonymous class is MyType which is a raw type, that is, it shouldn't not considered as a parameterized one. 5. As a resultgetGenericSuperclass method should return an instance of a class not implementing ParameterizedType interface, but actually it returns an instance of a class implementing ParameterizedType interface. Could you please tell if you consider this as a bug. Please note that javap prints following when it runs against anonymous class Test22$1: final class Test22$1 extends *Bar* { Test22$1(java.lang.String, MyType);} So if this is a bug it seems to be javac bug. Thanks, Georgiy. -------------- next part -------------- An HTML attachment was scrubbed... URL: From konstantin.barzilovich at oracle.com Mon Aug 3 12:47:54 2015 From: konstantin.barzilovich at oracle.com (konstantin barzilovich) Date: Mon, 3 Aug 2015 15:47:54 +0300 Subject: Number of formal parameters of anonymous class constructor Message-ID: <55BF62FA.9090908@oracle.com> Hello Dan, In chapter 15.9.5.1 in JLS signature of anonymous constructor is described. In case S is inner non-static class (see the minimal example) class Outer { public Outer() {} class A { public A() {} } public void foo(){ A a =new Outer().new A(){}; } } we expect to have one formal parameter of type Outer according to jls-15.9.5.1-100-B and jls-15.9.5.1-100-B.1. But I try to get parameters of constructor via reflection and it has two parameters both of type Outer. I guess, the second one is a receiver parameter, but it isn't mentioned in jls-15.9.5.1-100-B.1. Could you please clarify this situation? Thanks, Konstantin. -------------- next part -------------- An HTML attachment was scrubbed... URL: From alex.buckley at oracle.com Mon Aug 3 18:33:16 2015 From: alex.buckley at oracle.com (Alex Buckley) Date: Mon, 03 Aug 2015 11:33:16 -0700 Subject: Number of formal parameters of anonymous class constructor In-Reply-To: <55BF62FA.9090908@oracle.com> References: <55BF62FA.9090908@oracle.com> Message-ID: <55BFB3EC.80209@oracle.com> On 8/3/2015 5:47 AM, konstantin barzilovich wrote: > In chapter 15.9.5.1 in JLS signature of anonymous constructor is described. > In case S is inner non-static class (see the minimal example) > > classOuter { > publicOuter() {} > classA { > publicA() {} > } > public voidfoo(){ > A a =newOuter().newA(){}; > } > } > > we expect to have one formal parameter of type Outer according to > jls-15.9.5.1-100-B and jls-15.9.5.1-100-B.1. Let's look at what we have. 'S' is the class A, and with i as the newly created instance of the anonymous class: a) The immediately enclosing instance of i is the instance of Outer on which foo() was called. b) The immediately enclosing instance of i-with-respect-to-A is the instance of Outer produced by "new Outer()". In 15.9.5.1, the JLS prescribes the form of the anonymous class ctor (note the phrase "implicitly declared"). In particular, the JLS prescribes that (b) is encoded as the first formal parameter of the ctor. I guess you could call it the "receiver parameter" but I won't. You can see the encoding of (b) via reflection. Compile Outer.java with javac -parameters, then reflect over the anonymous class to get its java.lang.reflect.Constructor, then call getParameters(). Element 0 should return true for isImplicit(). > But I try to get parameters of constructor via reflection and it has two > parameters both of type Outer. > I guess, the second one is a receiver parameter, but it isn't mentioned > in jls-15.9.5.1-100-B.1. > Could you please clarify this situation? The JLS does not prescribe the encoding of (a) into the ctor. It is likely that javac is storing (a) as the second parameter, but that's an implementation detail which javac is free to change. I guess you could call it the "environment parameter" but I won't. Point is, JLS 15.9.5.1 does not prohibit the existence of the second parameter. If you reflect with getParameters(), element 1 should return false for isImplicit() and true for isSynthetic(). Alex From alex.buckley at oracle.com Mon Aug 3 18:53:42 2015 From: alex.buckley at oracle.com (Alex Buckley) Date: Mon, 03 Aug 2015 11:53:42 -0700 Subject: The supertype of anonymous class is expected to be a raw type In-Reply-To: <55BF628D.7070502@oracle.com> References: <55BF628D.7070502@oracle.com> Message-ID: <55BFB8B6.6030705@oracle.com> Georgiy, Good analysis but you have a non-generic ctor in class Bar (the class is generic but the ctor isn't). You also seem to say that the return type of the method derived from the ctor is MyType, but it's obviously Bar. I don't actually disagree with your conclusion since 15.12.2.6 would still give raw Bar as the return type for the non-generic ctor. But it would be helpful to clarify your mail and restart the thread. Alex On 8/3/2015 5:46 AM, Georgiy Rakov wrote: > Hello, > > let's consider following example: > > importjava.lang.reflect.Type; > importjava.lang.reflect.ParameterizedType; > > classMyType {} > > public classTest22 { > public static voidmain(String argv[]) { > Bar foo =newBar("str",newMyType()){ }; > Type actualSuperType = foo.getClass().getGenericSuperclass(); > if( actualSuperTypeinstanceofParameterizedType ) { > System.out.println("Parameterized"); > } > } > } > > classBar { > publicBar(Ta1, MyType a2){ } > } > > When compiled and run by JDK9b75 "Parameterized" is printed. However > according to my understanding it shouldn't have to. The reasons for this > are presented below: 1. According to the following assertion specified > in JDK-8073593 > > the superclass of anonymous class should be equal to the return type of > the method derived from Bar class constructor: > > - The superclass or superinterface type of the anonymous class is > the return type, T, determined for mj (15.12.2.6). > > 2. The second actual argument for the constructor is of a raw type > MyType while the corresponding formal parameter is a parameterized type > MyType. So unchecked conversion is necessary in order for the > only Bar constructor to become applicable for the provided invocation. > 3. According to assertion presented above the return type is determined > by 15.12.2.6 which states following: > > * If the chosen method is generic and the method invocation provides > explicit type arguments, let Pi be the type parameters of the method > and let Ti be the explicit type arguments provided for the method > invocation (1 ? i ? p). Then: > o If unchecked conversion was necessary for the method to be > applicable, then the invocation type's parameter types are > obtained by applying the substitution [P1:=T1, ..., Pp:=Tp] to > the parameter types of the method's type, and the invocation > type's return type and thrown types are given by the erasure of > the return type and thrown types of the method's type. > > Namely it says that the return type of the invocation type is the > erasure of the return type of the method's type, provided unchecked > conversion was necessary for the method to be applicable. According to > step 2 unchecked conversion was necessary for the method to be > applicable so the return type of the method is the erasure of MyType T>, i .e. MyType. 4. So according to step 1 given above the superclass > of the anonymous class is MyType which is a raw type, that is, it > shouldn't not considered as a parameterized one. 5. As a > resultgetGenericSuperclass method should return an instance of a class > not implementing ParameterizedType interface, but actually it returns an > instance of a class implementing ParameterizedType interface. Could you > please tell if you consider this as a bug. Please note that javap prints > following when it runs against anonymous class Test22$1: > > final class Test22$1 extends *Bar* { > Test22$1(java.lang.String, MyType);} > > So if this is a bug it seems to be javac bug. Thanks, Georgiy. From cushon at google.com Mon Aug 3 21:21:02 2015 From: cushon at google.com (Liam Miller-Cushon) Date: Mon, 3 Aug 2015 14:21:02 -0700 Subject: Redundant bridge methods in nested classes In-Reply-To: <55BB662A.6040608@oracle.com> References: <55B96262.7080403@oracle.com> <55BB4B8C.1060905@oracle.com> <55BB662A.6040608@oracle.com> Message-ID: I'm still absorbing some of the details, but (2) sounds appealing. It doesn't preclude making other changes to avoid compilation order issues, and cleaning up bridge generation would be nice. I appreciate that it's a risky change, though. For what it's worth, I'd be happy to help test changes to bridge generation against a large real world codebase. A couple of other notes: I realize the cycle example I gave doesn't affect bridges, I was just trying to say that linearizing the graph is hard. (Or impossible, as you showed. I wasn't aware of the ordering requirements for Lower.) I wrote an ASM pass to post process javac's output and work-around JDK-8132776, so that I have a reference implementation to test changes against. It removes bridge methods where there's an identical inherited bridge (i.e. same name and descriptor, and invokes the same method). Does that sound plausible? On Fri, Jul 31, 2015 at 5:12 AM, Maurizio Cimadamore < maurizio.cimadamore at oracle.com> wrote: > > > On 31/07/15 11:18, Maurizio Cimadamore wrote: > >> As you noticed, this order doesn't sit well with a tree visitor, as >> there's no way i.e. to visit B without also doing B.Nested - which will >> mess up the order completely (as is the case now). What this means is that >> TransTypes should probably NOT translate class recursively. I think that >> such an approach would have more chances to succeed than the existing one. >> > Thinking more about this, while it's probably not a big deal to turn > TransType into something that handles one class at a time (like Attr for > instance), doing so for Lower will probably be a major undertaking; a lot > of the state variables in Lower assume that you visit the enclosing classes > before you reach inner classes - stuff like 'outerThisStack'; additionally, > some of the desugared code in lower always ends up in the toplevel class, > no matter the nesting (see the constructor tag class, which is always a > static inner class of the toplevel). Pulling out these pieces so that Lower > is well-behaved will be generally very very hard. > > If this can't be done, of course we need a dependency from inner to outer > (as now), and that means that we start getting cycles in our graph: > > transtypes: > > A -> I > A.Nested -> B > B -> I > B.Nested -> A > > lower: > > A -> A.Nested > B -> B.Nested > > Meaning the order now is: > > I, { A, A.Nested, B, B.Nested } > > In other words, there's a cycle now - meaning you can disentangle the mess > using some heuristics (as we do now), but there will be cases where > compilation order will show up. > > I see few solutions out of this: > > (1) make Lower and TransTypes smarter, so that they do not rely on any > dependencies; then we can process classes in any order > (2) make only one of them smarter and sort dependencies accordingly; i.e. > if TransTypes is rewritten so that it doesn't rely on actual members, we > can just get rid of all transtypes-like dependencies > (3) split desugar into two steps - one does erasure, and sorts envs using > transtypes dependencies; another does lowering and sorts envs using lower > dependencies > > Of these, (1) looks the most disruptive, while (3) seems the most > straightforward, albeit I don't think (3) can be made to work alongside > different compilation policies; i.e. (3) would work fine using a policy > like SIMPLE (where all classes to be compiled are advanced to the next > stage before any other action is taken); for policies such as BY_FILE or > BY_TODO (the default), things are harder, as things are pushed down the > pipeline eagerly - i.e. you can have one class in the code generation step, > while another class has not even been attributed. Note that such policies > are fare better when it comes to memory footprint, as ASTs are typically > discarded after code generation; so, when compiling a large number of files > at once, the sooner you hit code generation, the better (memory-wise). (2) > seems like a fair balance, but it's still a lot of work (see my previous > email). > > Maurizio > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From cushon at google.com Mon Aug 3 21:26:32 2015 From: cushon at google.com (Liam Miller-Cushon) Date: Mon, 3 Aug 2015 14:26:32 -0700 Subject: Issue with hypothetical bridge methods and JDK-6342411 Message-ID: I think I found a bug in the interaction between 'hypothetical' bridge methods and the workaround for JDK-6342411. A hypothetical bridge method "is not strictly necessary in the binary, but is represented in the symbol table to detect erasure clashes." [1] Bridges are required to work around JDK-6342411 when a non-public super class declares a public method that's inherited into a public derived class. Without the bridge, reflectively invoking the method on the derived class fails with `IllegalAccessException: can not access a member with modifiers "public"`. [2][3] The issue I found occurs when a bridge method candidate qualifies as a hypothetical bridge *and* is necessary to work around JDK-6342411. The path for hypothetical bridges wins, so the bridge is entered in the symbol table but not generated in the binary, and attempts to invoke it reflectively fail. I've attached a patch with a regression test and a possible fix. Here's the repro: === ./p/I.java === package p; public interface I { void f(T t); } === ./p/B.java === package p; public class B extends A {} === ./p/A.java === package p; class A implements I { public void f(T t) {} } === ./Test.java === import java.lang.reflect.Method; public class Test { public static void main(String[] args) throws Exception { Method m = Class.forName("p.B").getMethod("f", Object.class); m.invoke(new p.B(), new Object[]{null}); } } === $ javac p/I.java p/A.java p/B.java Test.java $ java Test Exception in thread "main" java.lang.IllegalAccessException: Class Test can not access a member of class p.A with modifiers "public" at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:101) at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:295) at java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:287) at java.lang.reflect.Method.invoke(Method.java:476) at Test.main(Test.java:6) [1] http://hg.openjdk.java.net/jdk9/dev/langtools/file/7eef740c1482/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java#l238 [2] http://hg.openjdk.java.net/jdk9/dev/langtools/file/7eef740c1482/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java#l364 [3] https://bugs.openjdk.java.net/browse/JDK-6342411 -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: HypotheticalBridge6342411.patch Type: application/octet-stream Size: 8394 bytes Desc: not available URL: From konstantin.barzilovich at oracle.com Tue Aug 4 14:06:59 2015 From: konstantin.barzilovich at oracle.com (konstantin barzilovich) Date: Tue, 4 Aug 2015 17:06:59 +0300 Subject: Number of formal parameters of anonymous class constructor In-Reply-To: <55BFB3EC.80209@oracle.com> References: <55BF62FA.9090908@oracle.com> <55BFB3EC.80209@oracle.com> Message-ID: <55C0C703.208@oracle.com> Hello Alex, Thank you for quick response. I agree that JLS 15.9.5.1 does not prohibit the existence of additional parameter, but lets consider A ctor with one explicit formal parameter public A (Integer i) {} and anonymous class instance creation expression is: A a = newOuter().newA(5) {}; In this case, following jls-15.9.5.1-100-B.1: "...The n'th formal parameter e corresponds to the n-1'th actual argument" we expect anonymous ctor with second parameter of type Integer. But the second parameter will be synthetic Outer. Doesn't it contradict the assertion? If it is implementation-free, then we don't know what type of second parameter should be. Thanks, Konstantin. On 03.08.2015 21:33, Alex Buckley wrote: > On 8/3/2015 5:47 AM, konstantin barzilovich wrote: >> In chapter 15.9.5.1 in JLS signature of anonymous constructor is >> described. >> In case S is inner non-static class (see the minimal example) >> >> classOuter { >> publicOuter() {} >> classA { >> publicA() {} >> } >> public voidfoo(){ >> A a =newOuter().newA(){}; >> } >> } >> >> we expect to have one formal parameter of type Outer according to >> jls-15.9.5.1-100-B and jls-15.9.5.1-100-B.1. > > Let's look at what we have. 'S' is the class A, and with i as the > newly created instance of the anonymous class: > > a) The immediately enclosing instance of i is the instance of Outer on > which foo() was called. > b) The immediately enclosing instance of i-with-respect-to-A is the > instance of Outer produced by "new Outer()". > > In 15.9.5.1, the JLS prescribes the form of the anonymous class ctor > (note the phrase "implicitly declared"). In particular, the JLS > prescribes that (b) is encoded as the first formal parameter of the > ctor. I guess you could call it the "receiver parameter" but I won't. > > You can see the encoding of (b) via reflection. Compile Outer.java > with javac -parameters, then reflect over the anonymous class to get > its java.lang.reflect.Constructor, then call getParameters(). Element > 0 should return true for isImplicit(). > >> But I try to get parameters of constructor via reflection and it has two >> parameters both of type Outer. >> I guess, the second one is a receiver parameter, but it isn't mentioned >> in jls-15.9.5.1-100-B.1. >> Could you please clarify this situation? > > The JLS does not prescribe the encoding of (a) into the ctor. It is > likely that javac is storing (a) as the second parameter, but that's > an implementation detail which javac is free to change. I guess you > could call it the "environment parameter" but I won't. Point is, JLS > 15.9.5.1 does not prohibit the existence of the second parameter. > > If you reflect with getParameters(), element 1 should return false for > isImplicit() and true for isSynthetic(). > > Alex From georgiy.rakov at oracle.com Tue Aug 4 16:08:42 2015 From: georgiy.rakov at oracle.com (Georgiy Rakov) Date: Tue, 4 Aug 2015 19:08:42 +0300 Subject: The supertype of anonymous class is expected to be a raw type In-Reply-To: <55BFB8B6.6030705@oracle.com> References: <55BF628D.7070502@oracle.com> <55BFB8B6.6030705@oracle.com> Message-ID: <55C0E38A.3050105@oracle.com> Hello Alex, sorry for the mistakes made.... but it seems another one has been made..... that is assertion I specified in step 1 covers diamond-expression-cases only, namely this assertion: - The superclass or superinterface type of the anonymous class is the return type, T, determined for mj (15.12.2.6). but the original example provided type arguments instead; so the consequent steps (that is all of them) were wrong and according to following assertions the supertypes of anonymous classes should be parameterized when type arguments for class are provided: If ***'Identifier' refers to*** a class, ***C***, then an anonymous direct subclass of ***C*** is declared. ***/_*The type arguments to C, if any, are given by [TypeArgumentsOrDiamond]*_/, or, if this denotes '<>', will be inferred in 15.9.3.*** The body of the subclass is the ClassBody given in the class instance creation expression. ***If 'Identifier' refers to an interface, I, then an anonymous direct subclass of 'Object' that implements I is declared. /_*The type arguments to I, if any, are given by [TypeArgumentsOrDiamond]*_/, or, if this denotes '<>', will be inferred in 15.9.3. The body of the anonymous class is the ClassBody given in the class instance creation expression.*** .... it seems it's better to continue this thread because of the mess having been discovered; and thanks, I've taken into account the issues you found in my original letter ..... So the conclusion I made earlier seems to be wrong now. However it looks strange that, say, constructor invocation type, determines anonymous class supertypes for diamond cases only. So could you please tell if this is really the intention of the spec. For instance code below outputs that just for diamond case anonymous class super class is not parameterized: When class type arguments are given, the super type is parameterized. When class type arguments and ctor type arguments are given, the super type is parameterized. When diamond is used, the super type is /_*not*_/ parameterized. The code: import java.lang.reflect.ParameterizedType; class MyType {} public class Test24 { public static void main(String argv[]) { Bar foo; boolean isParameterized; foo =new Bar("str",new MyType()){ }; isParameterized = foo.getClass().getGenericSuperclass()instanceof ParameterizedType; System.out.println("When class type arguments are given, the super type is " + (isParameterized?"":"not ") +"parameterized."); foo =new Bar("str",new MyType()){ }; isParameterized = foo.getClass().getGenericSuperclass()instanceof ParameterizedType; System.out.println("When class type arguments and ctor type arguments are given, the super type is " + (isParameterized?"":"not ") +"parameterized."); foo =new Bar<>("str",new MyType()){ }; isParameterized = foo.getClass().getGenericSuperclass()instanceof ParameterizedType; System.out.println("When diamond is used, the super type is " + (isParameterized?"":"not ") +"parameterized."); } } class Bar { public Bar(T a1, MyType a2){ } } Thanks, Georgiy. On 03.08.2015 21:53, Alex Buckley wrote: > Georgiy, Good analysis but you have a non-generic ctor in class Bar > (the class is generic but the ctor isn't). You also seem to say that > the return type of the method derived from the ctor is MyType, but > it's obviously Bar. I don't actually disagree with your conclusion > since 15.12.2.6 would still give raw Bar as the return type for the > non-generic ctor. But it would be helpful to clarify your mail and > restart the thread. Alex On 8/3/2015 5:46 AM, Georgiy Rakov wrote: >> Hello, let's consider following example: >> importjava.lang.reflect.Type; >> importjava.lang.reflect.ParameterizedType; classMyType {} >> public classTest22 { public static voidmain(String argv[]) >> { Bar foo =newBar("str",newMyType()){ }; >> Type actualSuperType = >> foo.getClass().getGenericSuperclass(); if( >> actualSuperTypeinstanceofParameterizedType ) { >> System.out.println("Parameterized"); } } } >> classBar { publicBar(Ta1, MyType a2){ } } >> When compiled and run by JDK9b75 "Parameterized" is printed. However >> according to my understanding it shouldn't have to. The reasons for >> this are presented below: 1. According to the following assertion >> specified in JDK-8073593 >> >> the superclass of anonymous class should be equal to the return type >> of the method derived from Bar class constructor: - The >> superclass or superinterface type of the anonymous class is the >> return type, T, determined for mj (15.12.2.6). 2. The second actual >> argument for the constructor is of a raw type MyType while the >> corresponding formal parameter is a parameterized type >> MyType. So unchecked conversion is necessary in order for the >> only Bar constructor to become applicable for the provided >> invocation. 3. According to assertion presented above the return type >> is determined by 15.12.2.6 which states following: * If the chosen >> method is generic and the method invocation provides explicit >> type arguments, let Pi be the type parameters of the method and >> let Ti be the explicit type arguments provided for the method >> invocation (1 ? i ? p). Then: o If unchecked conversion was >> necessary for the method to be applicable, then the >> invocation type's parameter types are obtained by applying >> the substitution [P1:=T1, ..., Pp:=Tp] to the parameter types >> of the method's type, and the invocation type's return type >> and thrown types are given by the erasure of the return type >> and thrown types of the method's type. Namely it says that the return >> type of the invocation type is the erasure of the return type of the >> method's type, provided unchecked conversion was necessary for the >> method to be applicable. According to step 2 unchecked conversion was >> necessary for the method to be applicable so the return type of the >> method is the erasure of MyType, i .e. MyType. 4. So according >> to step 1 given above the superclass of the anonymous class is MyType >> which is a raw type, that is, it shouldn't not considered as a >> parameterized one. 5. As a resultgetGenericSuperclass method should >> return an instance of a class not implementing ParameterizedType >> interface, but actually it returns an instance of a class >> implementing ParameterizedType interface. Could you please tell if >> you consider this as a bug. Please note that javap prints following >> when it runs against anonymous class Test22$1: final class >> Test22$1 extends *Bar* { >> Test22$1(java.lang.String, MyType);} So if this is a bug it seems to >> be javac bug. Thanks, Georgiy. -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- import java.lang.reflect.ParameterizedType; class MyType {} public class Test24 { public static void main(String argv[]) { Bar foo; boolean isParameterized; foo = new Bar("str", new MyType()){ }; isParameterized = foo.getClass().getGenericSuperclass() instanceof ParameterizedType; System.out.println("When class type arguments are given, the super type is " + (isParameterized? "": "not ") + "parameterized."); foo = new Bar("str", new MyType()){ }; isParameterized = foo.getClass().getGenericSuperclass() instanceof ParameterizedType; System.out.println("When class type arguments and ctor type arguments are given, the super type is " + (isParameterized? "": "not ") + "parameterized."); foo = new Bar<>("str", new MyType()){ }; isParameterized = foo.getClass().getGenericSuperclass() instanceof ParameterizedType; System.out.println("When diamond is used, the super type is " + (isParameterized? "": "not ") + "parameterized."); } } class Bar { public Bar(T a1, MyType a2){ } } From alex.buckley at oracle.com Tue Aug 4 18:12:55 2015 From: alex.buckley at oracle.com (Alex Buckley) Date: Tue, 04 Aug 2015 11:12:55 -0700 Subject: Number of formal parameters of anonymous class constructor In-Reply-To: <55C0C703.208@oracle.com> References: <55BF62FA.9090908@oracle.com> <55BFB3EC.80209@oracle.com> <55C0C703.208@oracle.com> Message-ID: <55C100A7.4020507@oracle.com> Here's one possible answer: --- Yes, the second parameter being the synthetic Outer contradicts the JLS. No, I don't expect javac to change. No, I don't expect the JLS to change. First, the contradiction doesn't matter -- an anonymous class can only be instantiated at the point where it's declared, so the only compiler which needs to pass arguments to the ctor is the compiler which generated the ctor. Second, any alternative text which allows javac's current behavior will be looser than the current text, so it will be even less testable by JCK. This is the danger of hiding a compiler spec inside a language spec, but we're stuck with it. --- Here's another possible answer: --- No, the second parameter being the synthetic Outer does not contradict the JLS, because the only compiler which needs to pass arguments to the ctor is the compiler which generated the ctor, and thus synthetic parameters are implementation details "below" the level of things specified by the JLS. Yes, it would be cleaner if javac changed to follow 15.9.5.1 exactly. --- Alex On 8/4/2015 7:06 AM, konstantin barzilovich wrote: > Hello Alex, > > Thank you for quick response. > I agree that JLS 15.9.5.1 does not prohibit the existence of additional > parameter, but lets consider A ctor with one explicit formal parameter > > public A (Integer i) {} > > and anonymous class instance creation expression is: > > A a = newOuter().newA(5) {}; > > In this case, following jls-15.9.5.1-100-B.1: > > "...The n'th formal parameter e corresponds to the n-1'th actual argument" > > we expect anonymous ctor with second parameter of type Integer. But the > second parameter will be synthetic Outer. > Doesn't it contradict the assertion? > If it is implementation-free, then we don't know what type of second > parameter should be. > > Thanks, > Konstantin. > > On 03.08.2015 21:33, Alex Buckley wrote: >> On 8/3/2015 5:47 AM, konstantin barzilovich wrote: >>> In chapter 15.9.5.1 in JLS signature of anonymous constructor is >>> described. >>> In case S is inner non-static class (see the minimal example) >>> >>> classOuter { >>> publicOuter() {} >>> classA { >>> publicA() {} >>> } >>> public voidfoo(){ >>> A a =newOuter().newA(){}; >>> } >>> } >>> >>> we expect to have one formal parameter of type Outer according to >>> jls-15.9.5.1-100-B and jls-15.9.5.1-100-B.1. >> >> Let's look at what we have. 'S' is the class A, and with i as the >> newly created instance of the anonymous class: >> >> a) The immediately enclosing instance of i is the instance of Outer on >> which foo() was called. >> b) The immediately enclosing instance of i-with-respect-to-A is the >> instance of Outer produced by "new Outer()". >> >> In 15.9.5.1, the JLS prescribes the form of the anonymous class ctor >> (note the phrase "implicitly declared"). In particular, the JLS >> prescribes that (b) is encoded as the first formal parameter of the >> ctor. I guess you could call it the "receiver parameter" but I won't. >> >> You can see the encoding of (b) via reflection. Compile Outer.java >> with javac -parameters, then reflect over the anonymous class to get >> its java.lang.reflect.Constructor, then call getParameters(). Element >> 0 should return true for isImplicit(). >> >>> But I try to get parameters of constructor via reflection and it has two >>> parameters both of type Outer. >>> I guess, the second one is a receiver parameter, but it isn't mentioned >>> in jls-15.9.5.1-100-B.1. >>> Could you please clarify this situation? >> >> The JLS does not prescribe the encoding of (a) into the ctor. It is >> likely that javac is storing (a) as the second parameter, but that's >> an implementation detail which javac is free to change. I guess you >> could call it the "environment parameter" but I won't. Point is, JLS >> 15.9.5.1 does not prohibit the existence of the second parameter. >> >> If you reflect with getParameters(), element 1 should return false for >> isImplicit() and true for isSynthetic(). >> >> Alex > From georgiy.rakov at oracle.com Wed Aug 5 11:59:51 2015 From: georgiy.rakov at oracle.com (Georgiy Rakov) Date: Wed, 5 Aug 2015 14:59:51 +0300 Subject: Please reply to my JDK-8059640 issue comment In-Reply-To: References: <559AB728.80105@oracle.com> Message-ID: <55C1FAB7.4020302@oracle.com> Just a friendly reminder, Thanks, Georgiy. On 09.07.2015 2:23, Dan Smith wrote: >> On Jul 6, 2015, at 10:13 AM, Georgiy Rakov >> wrote: >> >> Hello, >> >> could you please reply to my following comment >> >> I made to JDK-8059640; quoting it: >> >> Suggested spec change states that 15.13.3 will contain following >> assertion: >> >> LinkageError may occur due to inconsistencies between compile >> time and run time (in the referenced method, the functional >> interface, or the argument types of either). >> >> The details are provided in parenthesis: "in the referenced >> method, the functional interface, or the argument types of >> either". It seems that these details don't extend to following >> case specified in jls-15.12.4.3-120: >> >> If the invocation mode is interface, then the implementation must >> also check that the target reference type still implements the >> specified interface. If the target reference type does not still >> implement the interface, then an IncompatibleClassChangeError occurs. >> >> I believe they should. >> >> Namely, could you please tell if you agree that spec change suggested >> in the issue description doesn't extend to the case specified in >> jls-15.12.4.3-120. If you agree I would appreciate greatly if you >> could modify the suggested spec change so that it extends to >> jls-15.12.4.3-120 case. >> > > I think these are two different kinds of errors. > > JDK-8059640 is about BootstrapMethodErrors that can occur upon > *evaluation of* a method reference expression, but that aren't > specified to occur. > > The check you describe is an ICCE that can happen upon *invocation of* > the method of an object derived from a method reference expression. > > Please correct me if you're seeing different behavior, but my > expectation is that the invocation will behave exactly as specified: > per 15.13.3, the body of the method is via an invocation that proceeds > according to 15.12.4.3; per 15.12.4.3, the ICCE can occur. > > Example: > > interface I { int x(); } > interface Func { int apply(I arg); } > > Func f2 = I::x; > System.out.println(f2); > // no errors yet > System.out.println(f2.apply(new C())); > // ICCE if C was originally declared to implement I, but no longer does > > So I don't think there's a bug here, either in the spec or the > implementation. In the example you provided inconsistency occurs at the point of *invocation of* the method of an object derived from a method reference expression. But we can consider another example which contains inconsistency occurring at the point of *evaluation of* a method reference expression: interface MethodSupplier { void m(int a);} interface MyFunctionalInterface {int invokeMethodReference(int a);} class MethodSupplierImpl implements MethodSupplier { @Override public void m(int a) {} } MyFunctionalInterface instance = null; MethodSupplier ms = new MethodSupplierImpl(); instance = ms::m; //inconsistency occurs here instance.invokeMethodReference(1); Currently the behavior is Ok, that is provided MethodSupplierImpl is recompiled without implementing MethodSupplier, ICCE is thrown when executing "instance.invokeMethodReference(1)". But potentially it looks possible for the error to be thrown during executing "instance = ms::m" and suggested spec change doesn't encompass this case. So I wonder if it's worth encompassing such case for the suggested spec change. Could you please also tell if I understand correctly that suggested spec change specifies the possibility of throwing LinkageError during *evaluation of* method reference and not during *invocation of* the method of an object derived from a method reference expression. Thank you, Georgiy. > > ?Dan -------------- next part -------------- An HTML attachment was scrubbed... URL: From maurizio.cimadamore at oracle.com Wed Aug 5 20:55:58 2015 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Wed, 05 Aug 2015 21:55:58 +0100 Subject: Redundant bridge methods in nested classes In-Reply-To: References: <55B96262.7080403@oracle.com> <55BB4B8C.1060905@oracle.com> <55BB662A.6040608@oracle.com> Message-ID: <55C2785E.7010106@oracle.com> On 03/08/15 22:21, Liam Miller-Cushon wrote: > I wrote an ASM pass to post process javac's output and work-around > JDK-8132776, so that I have a reference implementation to test changes > against. It removes bridge methods where there's an identical > inherited bridge (i.e. same name and descriptor, and invokes the same > method). Does that sound plausible? Yep - modulo accessibility bridge (public members inherited from non public classes need to be bridged, otherwise reflection doesn't work), this is accurate. Maurizio From maurizio.cimadamore at oracle.com Wed Aug 5 20:58:31 2015 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Wed, 05 Aug 2015 21:58:31 +0100 Subject: Issue with hypothetical bridge methods and JDK-6342411 In-Reply-To: References: Message-ID: <55C278F7.8000805@oracle.com> This is related to the discussion we had; a long tail of the current approach for bridge calculation is that sometimes we need hypothetical stuff which is there just to make Symbol.binaryOverrides work correctly. I'm not completely surprised this sometimes lead to unexpected behavior... Maurizio On 03/08/15 22:26, Liam Miller-Cushon wrote: > I think I found a bug in the interaction between 'hypothetical' bridge > methods and the workaround for JDK-6342411. > > A hypothetical bridge method "is not strictly necessary in the binary, > but is represented in the symbol table to detect erasure clashes." [1] > > Bridges are required to work around JDK-6342411 when a non-public > super class declares a public method that's inherited into a public > derived class. Without the bridge, reflectively invoking the method on > the derived class fails with `IllegalAccessException: can not access a > member with modifiers "public"`. [2][3] > > The issue I found occurs when a bridge method candidate qualifies as a > hypothetical bridge *and* is necessary to work around JDK-6342411. The > path for hypothetical bridges wins, so the bridge is entered in the > symbol table but not generated in the binary, and attempts to invoke > it reflectively fail. > > I've attached a patch with a regression test and a possible fix. > > Here's the repro: > > === ./p/I.java === > package p; > > public interface I { > void f(T t); > } > === ./p/B.java === > package p; > > public class B extends A {} > === ./p/A.java === > package p; > > class A implements I { > public void f(T t) {} > } > === ./Test.java === > import java.lang.reflect.Method; > > public class Test { > public static void main(String[] args) throws Exception { > Method m = Class.forName("p.B").getMethod("f", Object.class); > m.invoke(new p.B(), new Object[]{null}); > } > } > === > > $ javac p/I.java p/A.java p/B.java Test.java > $ java Test > Exception in thread "main" java.lang.IllegalAccessException: Class > Test can not access a member of class p.A with modifiers "public" > at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:101) > at > java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:295) > at > java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:287) > at java.lang.reflect.Method.invoke(Method.java:476) > at Test.main(Test.java:6) > > [1] > http://hg.openjdk.java.net/jdk9/dev/langtools/file/7eef740c1482/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java#l238 > [2] > http://hg.openjdk.java.net/jdk9/dev/langtools/file/7eef740c1482/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java#l364 > [3] https://bugs.openjdk.java.net/browse/JDK-6342411 From sam.munkes at gmail.com Thu Aug 6 00:28:11 2015 From: sam.munkes at gmail.com (Sam Munkes) Date: Wed, 5 Aug 2015 17:28:11 -0700 Subject: Must autoboxing call valueOf? Message-ID: Hi - A colleague of mine was wondering if the following statements are guaranteed to be true: ((Boolean)true) == Boolean.TRUE ((Boolean)true) == Boolean.valueOf(true) ((Integer)1) == Integer.valueOf(1) javac does indeed call valueOf() for autoboxing, but is this behavior mandated by the JLS? The answers on stackoverflow http://stackoverflow.com/questions/31445024/does-autoboxing-call-valueof agree that although in practice the compilers use valueOf(), the JLS does not mandate it. Does anyone here know more on the subject? Thanks Sam -------------- next part -------------- An HTML attachment was scrubbed... URL: From jonathan.gibbons at oracle.com Thu Aug 6 00:34:15 2015 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Wed, 05 Aug 2015 17:34:15 -0700 Subject: Must autoboxing call valueOf? In-Reply-To: References: Message-ID: <55C2AB87.7080505@oracle.com> Sam, The relevant text would appear to be in JLS 5.1.7, Boxing Conversion. https://docs.oracle.com/javase/specs/jls/se8/html/jls-5.html#jls-5.1.7 -- Jon On 08/05/2015 05:28 PM, Sam Munkes wrote: > Hi - > > A colleague of mine was wondering if the following statements are > guaranteed to be true: > ((Boolean)true) == Boolean.TRUE > ((Boolean)true) == Boolean.valueOf(true) > ((Integer)1) == Integer.valueOf(1) > > javac does indeed call valueOf() for autoboxing, but is this behavior > mandated by the JLS? > > The answers on stackoverflow > http://stackoverflow.com/questions/31445024/does-autoboxing-call-valueof agree > that although in practice the compilers use valueOf(), the JLS does > not mandate it. > > Does anyone here know more on the subject? > > Thanks > > Sam -------------- next part -------------- An HTML attachment was scrubbed... URL: From sam.munkes at gmail.com Thu Aug 6 00:48:10 2015 From: sam.munkes at gmail.com (Sam Munkes) Date: Wed, 5 Aug 2015 17:48:10 -0700 Subject: Must autoboxing call valueOf? In-Reply-To: <55C2AB87.7080505@oracle.com> References: <55C2AB87.7080505@oracle.com> Message-ID: Thanks Jonathan, So those statements are not guaranteed to be true, since the JLS does not mandate that valueOf() be used (it only mandates ranges where 2 boxing conversions will return the same instance). On Wed, Aug 5, 2015 at 5:34 PM, Jonathan Gibbons < jonathan.gibbons at oracle.com> wrote: > Sam, > > The relevant text would appear to be in JLS 5.1.7, Boxing Conversion. > > https://docs.oracle.com/javase/specs/jls/se8/html/jls-5.html#jls-5.1.7 > > -- Jon > > > > > On 08/05/2015 05:28 PM, Sam Munkes wrote: > > Hi - > > A colleague of mine was wondering if the following statements are > guaranteed to be true: > ((Boolean)true) == Boolean.TRUE > ((Boolean)true) == Boolean.valueOf(true) > ((Integer)1) == Integer.valueOf(1) > > javac does indeed call valueOf() for autoboxing, but is this behavior > mandated by the JLS? > > The answers on stackoverflow > http://stackoverflow.com/questions/31445024/does-autoboxing-call-valueof agree > that although in practice the compilers use valueOf(), the JLS does not > mandate it. > > Does anyone here know more on the subject? > > Thanks > > Sam > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From georgiy.rakov at oracle.com Thu Aug 6 16:07:43 2015 From: georgiy.rakov at oracle.com (Georgiy Rakov) Date: Thu, 6 Aug 2015 19:07:43 +0300 Subject: The return type of instance creation expression with diamond and class body should be anonymous class type Message-ID: <55C3864F.9070504@oracle.com> Hello, let's consider following example: class List { List() {} List getThis() { return new List(); } } class Foo { public Foo(T a1){} } public class Test25 { public static List m1(T item) { List l = new List(); return l; } public static void m2(List list1, List list2) { } public static void test() { m2(new List>(), m1(new Foo<>("str"){ }).getThis()); } } This example compiles successfully on JDK9b75. But according to my understanding the compilation should have failed. The reasons for this are presented below: 1. JDK-8073593 specifies following assertion: ***If C is an anonymous class, then the chosen constructor is the constructor of the anonymous class. The return type is the anonymous class type.*** current JLS 9 15.9.1 spec defines following assertion: The type of the class instance creation expression is the return type of the chosen constructor, as defined above. so together these assertions lead to the fact that the type of instance creation expression "new Foo<>("str"){ } " is anonymous class type, let's denote it as "anonymous Foo". 2. Thus when m1 is invoked, that is "m1(new Foo<>("str"){ })", the invocation return type is List>. 3. Hence when getThis is invoked, that is "m1(new Foo<>("str"){ }).getThis()", the invocation return type is List> as well. 4. Finally when m2 method is invoked type inference cause two equality constraints to be created that is: U = Foo and U = (anonymous Foo), together they should lead to compilation failure, but compilation succeeds. This seems to be a javac bug. Could you please confirm if it really is. Please note, that if diamond is replaced with String type argument, that is "new Foo("str"){ }" the compilation fails as expected: Error:(19, 9) java: method m2 in class Test25 cannot be applied to given types; required: List,List found: List>,List<>> reason: inference variable U has incompatible equality constraints >,Foo Thank you, Georgiy. -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- class List { List() {} List getThis() { return new List(); } } class Foo { public Foo(T a1){} } public class Test25 { public static List m1(T item) { List l = new List(); return l; } public static void m2(List list1, List list2) { } public static void test() { m2(new List>(), m1(new Foo<>("str"){ }).getThis()); } } From cushon at google.com Fri Aug 7 17:16:28 2015 From: cushon at google.com (Liam Miller-Cushon) Date: Fri, 7 Aug 2015 10:16:28 -0700 Subject: Issue with hypothetical bridge methods and JDK-6342411 In-Reply-To: <55C278F7.8000805@oracle.com> References: <55C278F7.8000805@oracle.com> Message-ID: I think this is about as likely to be observed as JDK-6924232, which doesn't seem to be causing anyone major problems. On the other hand this issue would be very easy to fix. Do you think the current approach will be replaced soon enough that it isn't worth tracking this? If not, is anyone willing to file a tracking bug or review my patch? On Wed, Aug 5, 2015 at 1:58 PM, Maurizio Cimadamore < maurizio.cimadamore at oracle.com> wrote: > This is related to the discussion we had; a long tail of the current > approach for bridge calculation is that sometimes we need hypothetical > stuff which is there just to make Symbol.binaryOverrides work correctly. > I'm not completely surprised this sometimes lead to unexpected behavior... > > Maurizio > > > On 03/08/15 22:26, Liam Miller-Cushon wrote: > >> I think I found a bug in the interaction between 'hypothetical' bridge >> methods and the workaround for JDK-6342411. >> >> A hypothetical bridge method "is not strictly necessary in the binary, >> but is represented in the symbol table to detect erasure clashes." [1] >> >> Bridges are required to work around JDK-6342411 when a non-public super >> class declares a public method that's inherited into a public derived >> class. Without the bridge, reflectively invoking the method on the derived >> class fails with `IllegalAccessException: can not access a member with >> modifiers "public"`. [2][3] >> >> The issue I found occurs when a bridge method candidate qualifies as a >> hypothetical bridge *and* is necessary to work around JDK-6342411. The path >> for hypothetical bridges wins, so the bridge is entered in the symbol table >> but not generated in the binary, and attempts to invoke it reflectively >> fail. >> >> I've attached a patch with a regression test and a possible fix. >> >> Here's the repro: >> >> === ./p/I.java === >> package p; >> >> public interface I { >> void f(T t); >> } >> === ./p/B.java === >> package p; >> >> public class B extends A {} >> === ./p/A.java === >> package p; >> >> class A implements I { >> public void f(T t) {} >> } >> === ./Test.java === >> import java.lang.reflect.Method; >> >> public class Test { >> public static void main(String[] args) throws Exception { >> Method m = Class.forName("p.B").getMethod("f", Object.class); >> m.invoke(new p.B(), new Object[]{null}); >> } >> } >> === >> >> $ javac p/I.java p/A.java p/B.java Test.java >> $ java Test >> Exception in thread "main" java.lang.IllegalAccessException: Class Test >> can not access a member of class p.A with modifiers "public" >> at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:101) >> at >> java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:295) >> at >> java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:287) >> at java.lang.reflect.Method.invoke(Method.java:476) >> at Test.main(Test.java:6) >> >> [1] >> http://hg.openjdk.java.net/jdk9/dev/langtools/file/7eef740c1482/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java#l238 >> [2] >> http://hg.openjdk.java.net/jdk9/dev/langtools/file/7eef740c1482/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java#l364 >> [3] https://bugs.openjdk.java.net/browse/JDK-6342411 >> > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From cushon at google.com Fri Aug 7 19:26:56 2015 From: cushon at google.com (Liam Miller-Cushon) Date: Fri, 7 Aug 2015 12:26:56 -0700 Subject: Redundant bridge methods in nested classes In-Reply-To: <55C2785E.7010106@oracle.com> References: <55B96262.7080403@oracle.com> <55BB4B8C.1060905@oracle.com> <55BB662A.6040608@oracle.com> <55C2785E.7010106@oracle.com> Message-ID: On Wed, Aug 5, 2015 at 1:55 PM, Maurizio Cimadamore < maurizio.cimadamore at oracle.com> wrote: > On 03/08/15 22:21, Liam Miller-Cushon wrote: > >> I wrote an ASM pass to post process javac's output and work-around >> JDK-8132776, so that I have a reference implementation to test changes >> against. It removes bridge methods where there's an identical inherited >> bridge (i.e. same name and descriptor, and invokes the same method). Does >> that sound plausible? >> > Yep - modulo accessibility bridge (public members inherited from non > public classes need to be bridged, otherwise reflection doesn't work), this > is accurate. Thanks for confirming. That approach seems to be working (with appropriate handling for accessibility bridges), although it's a little hard to test exhaustively. -------------- next part -------------- An HTML attachment was scrubbed... URL: From maurizio.cimadamore at oracle.com Mon Aug 10 09:36:59 2015 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Mon, 10 Aug 2015 10:36:59 +0100 Subject: Issue with hypothetical bridge methods and JDK-6342411 In-Reply-To: References: <55C278F7.8000805@oracle.com> Message-ID: <55C870BB.6020502@oracle.com> Filed: https://bugs.openjdk.java.net/browse/JDK-8133247 Maurizio On 07/08/15 18:16, Liam Miller-Cushon wrote: > I think this is about as likely to be observed as JDK-6924232, which > doesn't seem to be causing anyone major problems. On the other hand > this issue would be very easy to fix. > > Do you think the current approach will be replaced soon enough that it > isn't worth tracking this? If not, is anyone willing to file a > tracking bug or review my patch? > > On Wed, Aug 5, 2015 at 1:58 PM, Maurizio Cimadamore > > wrote: > > This is related to the discussion we had; a long tail of the > current approach for bridge calculation is that sometimes we need > hypothetical stuff which is there just to make > Symbol.binaryOverrides work correctly. I'm not completely > surprised this sometimes lead to unexpected behavior... > > Maurizio > > > On 03/08/15 22:26, Liam Miller-Cushon wrote: > > I think I found a bug in the interaction between > 'hypothetical' bridge methods and the workaround for JDK-6342411. > > A hypothetical bridge method "is not strictly necessary in the > binary, but is represented in the symbol table to detect > erasure clashes." [1] > > Bridges are required to work around JDK-6342411 when a > non-public super class declares a public method that's > inherited into a public derived class. Without the bridge, > reflectively invoking the method on the derived class fails > with `IllegalAccessException: can not access a member with > modifiers "public"`. [2][3] > > The issue I found occurs when a bridge method candidate > qualifies as a hypothetical bridge *and* is necessary to work > around JDK-6342411. The path for hypothetical bridges wins, so > the bridge is entered in the symbol table but not generated in > the binary, and attempts to invoke it reflectively fail. > > I've attached a patch with a regression test and a possible fix. > > Here's the repro: > > === ./p/I.java === > package p; > > public interface I { > void f(T t); > } > === ./p/B.java === > package p; > > public class B extends A {} > === ./p/A.java === > package p; > > class A implements I { > public void f(T t) {} > } > === ./Test.java === > import java.lang.reflect.Method; > > public class Test { > public static void main(String[] args) throws Exception { > Method m = Class.forName("p.B").getMethod("f", Object.class); > m.invoke(new p.B(), new Object[]{null}); > } > } > === > > $ javac p/I.java p/A.java p/B.java Test.java > $ java Test > Exception in thread "main" java.lang.IllegalAccessException: > Class Test can not access a member of class p.A with modifiers > "public" > at > sun.reflect.Reflection.ensureMemberAccess(Reflection.java:101) > at > java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:295) > at > java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:287) > at java.lang.reflect.Method.invoke(Method.java:476) > at Test.main(Test.java:6) > > [1] > http://hg.openjdk.java.net/jdk9/dev/langtools/file/7eef740c1482/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java#l238 > [2] > http://hg.openjdk.java.net/jdk9/dev/langtools/file/7eef740c1482/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java#l364 > [3] https://bugs.openjdk.java.net/browse/JDK-6342411 > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From anthony.vanelverdinghe at gmail.com Mon Aug 10 18:11:34 2015 From: anthony.vanelverdinghe at gmail.com (Anthony Vanelverdinghe) Date: Mon, 10 Aug 2015 20:11:34 +0200 Subject: JDK-8133168 was wrongly closed as Cannot Reproduce Message-ID: <55C8E956.20108@gmail.com> Hi The compiler issue JDK-8133168 [1] was wrongly closed: it actually is reproducable and should therefore be re-evaluated. To be able to reproduce, Foo.java & VisibilityBridgeTest.java must be in different packages. This is the case for the reporter's example [2], but it isn't the case for the example that was used to evaluate the issue. PS: I don't know if this is a regression or not, but the regression version information is wrong either way [1] https://bugs.openjdk.java.net/browse/JDK-8133168 [2] https://gist.github.com/raphw/7d10ae082ace5886d601 Kind regards, Anthony From cushon at google.com Mon Aug 10 18:25:35 2015 From: cushon at google.com (Liam Miller-Cushon) Date: Mon, 10 Aug 2015 11:25:35 -0700 Subject: JDK-8133168 was wrongly closed as Cannot Reproduce In-Reply-To: <55C8E956.20108@gmail.com> References: <55C8E956.20108@gmail.com> Message-ID: JDK-8133168 looks like a duplicate of: https://bugs.openjdk.java.net/browse/JDK-6924232. On Mon, Aug 10, 2015 at 11:11 AM, Anthony Vanelverdinghe < anthony.vanelverdinghe at gmail.com> wrote: > Hi > > The compiler issue JDK-8133168 [1] was wrongly closed: it actually is > reproducable and should therefore be re-evaluated. To be able to reproduce, > Foo.java & VisibilityBridgeTest.java must be in different packages. This is > the case for the reporter's example [2], but it isn't the case for the > example that was used to evaluate the issue. > > PS: I don't know if this is a regression or not, but the regression > version information is wrong either way > > [1] https://bugs.openjdk.java.net/browse/JDK-8133168 > [2] https://gist.github.com/raphw/7d10ae082ace5886d601 > > Kind regards, > Anthony > -------------- next part -------------- An HTML attachment was scrubbed... URL: From georgiy.rakov at oracle.com Wed Aug 12 13:59:01 2015 From: georgiy.rakov at oracle.com (Georgiy Rakov) Date: Wed, 12 Aug 2015 16:59:01 +0300 Subject: The type of instance creation expression with types arguments provided is not affected by 15.12.2.6? Message-ID: <55CB5125.7030105@oracle.com> Hello, following new spec presented in JDK-8073593 states: Otherwise, the class instance creation expression does not use <> to elide class ***or interface*** type arguments. ***If C is not an anonymous class,*** let T be the type denoted by C followed by any class type arguments in the expression. The process specified in ?15.12.2, modified to handle constructors, is used to select one of the constructors of T and determine its throws clause. ... Otherwise, the return type is T. ... The type of the class instance creation expression is the return type of the chosen constructor, as defined above. In particular it says that 15.12.2 is applied in order to determine the throws clause. If I understand correctly it means that the throws types can be changed by 15.12.2.6 if unchecked conversion was necessary for the chosen method (ctor) to be applicable. But 15.12.2.6 also changes the return type in the same case; yet the assertion presented above doesn't mention that the return type is determined by the process specified in 15.12.2 (only throws clause is mentioned). So could you please tell if I understand correctly that it means that the return type of instance creation expression is not changed as per 15.12.2.6 in this case. I'm asking about this because I've come across the fact that following code compiles successfully on JDK9b76: class MyType {}class List {List copyThis() { return null; }}public class Test28 {static void m2(List list1, List list2) {}static List m1(U item) {return null;}static void test() {m2(new List>(), m1(new Foo(new MyType()).copyThis()).copyThis());}}class Foo { Foo(MyType a2){}Foo copyThis() {return null;}} In this code unchecked conversion is necessary in order for the Foo constructor to be applicable, so if 15.12.2.6 were to change the return type of constructor it would be raw type Foo, which finally would cause compilation failure due to the incompatible equality constraints on T inferred. So could you please also confirm that this is not a bug and javac behaves according to spec for the reasons presented above. Thank you, Georgiy. -------------- next part -------------- An HTML attachment was scrubbed... URL: From aleksey.shipilev at oracle.com Mon Aug 17 12:33:58 2015 From: aleksey.shipilev at oracle.com (Aleksey Shipilev) Date: Mon, 17 Aug 2015 15:33:58 +0300 Subject: RFR 8129547 (S): Excess entries in BootstrapMethods with the same (bsm, bsmKind, bsmStaticArgs), but different dynamicArgs Message-ID: <55D1D4B6.6090303@oracle.com> Hi, This issue gets into way with my current work: https://bugs.openjdk.java.net/browse/JDK-8129547 There is a proof-of-concept patch: http://cr.openjdk.java.net/~shade/8129547/webrev.00/ The crux of an issue seems to be the Method.equals() call in DynamicMethod.equals(), that compares the type. The type of DynamicMethod includes the DynamicMethodSymbol.type, that includes dynamic args. It seems DynamicMethodSymbol is a better fit for BootstrapMethod table key, since it includes BSM symbol and static arguments only. I would be grateful if somebody from compiler team can help me out with this. Is this the fix above valid? Can you do it better? How would one write a regression test for it? My cursory grep through langtools tests does not yield a clear way to emit a special-shaped indy for such a test. Thanks, -Aleksey -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: OpenPGP digital signature URL: From maurizio.cimadamore at oracle.com Mon Aug 17 13:48:09 2015 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Mon, 17 Aug 2015 14:48:09 +0100 Subject: RFR 8129547 (S): Excess entries in BootstrapMethods with the same (bsm, bsmKind, bsmStaticArgs), but different dynamicArgs In-Reply-To: <55D1D4B6.6090303@oracle.com> References: <55D1D4B6.6090303@oracle.com> Message-ID: <55D1E619.1070201@oracle.com> Hi Alex, the only dfference I see between your patch and the current code is that the current code is comparing the invokedType, while yours is not - am I reading your patch correctly? If that's the case, wouldn't dropping the call to super.equals from Pool.DynamicMethod also resolve the issue? I'm, saying this because, from a design perspective, javac symbols usually don't care about uniqueness etc. - that's an extra value added when storing them into a constant pool. Maurizio On 17/08/15 13:33, Aleksey Shipilev wrote: > Hi, > > This issue gets into way with my current work: > https://bugs.openjdk.java.net/browse/JDK-8129547 > > There is a proof-of-concept patch: > http://cr.openjdk.java.net/~shade/8129547/webrev.00/ > > The crux of an issue seems to be the Method.equals() call in > DynamicMethod.equals(), that compares the type. The type of > DynamicMethod includes the DynamicMethodSymbol.type, that includes > dynamic args. It seems DynamicMethodSymbol is a better fit for > BootstrapMethod table key, since it includes BSM symbol and static > arguments only. > > I would be grateful if somebody from compiler team can help me out with > this. Is this the fix above valid? Can you do it better? > > How would one write a regression test for it? My cursory grep through > langtools tests does not yield a clear way to emit a special-shaped indy > for such a test. > > Thanks, > -Aleksey > From maurizio.cimadamore at oracle.com Mon Aug 17 14:15:39 2015 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Mon, 17 Aug 2015 15:15:39 +0100 Subject: RFR 8129547 (S): Excess entries in BootstrapMethods with the same (bsm, bsmKind, bsmStaticArgs), but different dynamicArgs In-Reply-To: <55D1E619.1070201@oracle.com> References: <55D1D4B6.6090303@oracle.com> <55D1E619.1070201@oracle.com> Message-ID: <55D1EC8B.7090400@oracle.com> Ok, I think I know what you meant now; DynamicMethod is used for two different purposes: * for the NameAndType CP entry associated with an invokedynamic instruction (pointed by the CONSTANT_InvokeDynamic entry); this bit _requires_ dynamic info to be taken into account - as different invoked types need to map to different entries - even if their underlying BSM entry is the same. * as keys in the BootstrapMethod attribute; in this case you want the dynamic info to be gone, as all it's going to be stored in the table is a bsmKind + static args list. How about something like this: http://cr.openjdk.java.net/~mcimadamore/8129547/ Maurizio On 17/08/15 14:48, Maurizio Cimadamore wrote: > Hi Alex, > the only dfference I see between your patch and the current code is > that the current code is comparing the invokedType, while yours is not > - am I reading your patch correctly? > > If that's the case, wouldn't dropping the call to super.equals from > Pool.DynamicMethod also resolve the issue? > > I'm, saying this because, from a design perspective, javac symbols > usually don't care about uniqueness etc. - that's an extra value added > when storing them into a constant pool. > > Maurizio > > On 17/08/15 13:33, Aleksey Shipilev wrote: >> Hi, >> >> This issue gets into way with my current work: >> https://bugs.openjdk.java.net/browse/JDK-8129547 >> >> There is a proof-of-concept patch: >> http://cr.openjdk.java.net/~shade/8129547/webrev.00/ >> >> The crux of an issue seems to be the Method.equals() call in >> DynamicMethod.equals(), that compares the type. The type of >> DynamicMethod includes the DynamicMethodSymbol.type, that includes >> dynamic args. It seems DynamicMethodSymbol is a better fit for >> BootstrapMethod table key, since it includes BSM symbol and static >> arguments only. >> >> I would be grateful if somebody from compiler team can help me out with >> this. Is this the fix above valid? Can you do it better? >> >> How would one write a regression test for it? My cursory grep through >> langtools tests does not yield a clear way to emit a special-shaped indy >> for such a test. >> >> Thanks, >> -Aleksey >> > From anna.kozlova at jetbrains.com Mon Aug 17 17:46:56 2015 From: anna.kozlova at jetbrains.com (anna.kozlova at jetbrains.com) Date: Mon, 17 Aug 2015 19:46:56 +0200 Subject: IllegalAccessError on runtime with inaccessible vararg type In-Reply-To: <55D1EC8B.7090400@oracle.com> References: <55D1D4B6.6090303@oracle.com> <55D1E619.1070201@oracle.com> <55D1EC8B.7090400@oracle.com> Message-ID: Hi, Given package local abstract class with 2 public inheritors: package p; abstract class A {} public class B extends A {} public class C extends A {} and usage in another package: Arrays.asList(new B(), new C()) compiles with javac 1.8.0_51 with target 1.8 (at runtime: Exception in thread "main" java.lang.IllegalAccessError: tried to access class p.A from class p1.MyClass); though with target 1.7 javac produces Error:(11, 15) java: method asList in class java.util.Arrays cannot be applied to given types; required: T[] found: p.B,p.C reason: formal varargs element type p.A is not accessible from class p1.MyClass which looks correct. Is it a known issue or is it a desired behaviour? Thanks, Anna From aleksey.shipilev at oracle.com Mon Aug 17 19:24:47 2015 From: aleksey.shipilev at oracle.com (Aleksey Shipilev) Date: Mon, 17 Aug 2015 22:24:47 +0300 Subject: RFR 8129547 (S): Excess entries in BootstrapMethods with the same (bsm, bsmKind, bsmStaticArgs), but different dynamicArgs In-Reply-To: <55D1EC8B.7090400@oracle.com> References: <55D1D4B6.6090303@oracle.com> <55D1E619.1070201@oracle.com> <55D1EC8B.7090400@oracle.com> Message-ID: <55D234FF.6000209@oracle.com> Hi Maurizio, Thanks for an idea! It almost works, but not quite: super.equals() from Method checks the type, so we need to guard super.*, as you did in hashCode(). We also need a proper subclass check for the keys alone, which means we might move equals() there, and make key a proper subclass to gain access to "other". In short, this version works: http://cr.openjdk.java.net/~shade/8129547/webrev.01/ Thanks, -Aleksey On 17.08.2015 17:15, Maurizio Cimadamore wrote: > Ok, I think I know what you meant now; DynamicMethod is used for two > different purposes: > > * for the NameAndType CP entry associated with an invokedynamic > instruction (pointed by the CONSTANT_InvokeDynamic entry); this bit > _requires_ dynamic info to be taken into account - as different invoked > types need to map to different entries - even if their underlying BSM > entry is the same. > > * as keys in the BootstrapMethod attribute; in this case you want the > dynamic info to be gone, as all it's going to be stored in the table is > a bsmKind + static args list. > > How about something like this: > > http://cr.openjdk.java.net/~mcimadamore/8129547/ > > Maurizio > > > > On 17/08/15 14:48, Maurizio Cimadamore wrote: >> Hi Alex, >> the only dfference I see between your patch and the current code is >> that the current code is comparing the invokedType, while yours is not >> - am I reading your patch correctly? >> >> If that's the case, wouldn't dropping the call to super.equals from >> Pool.DynamicMethod also resolve the issue? >> >> I'm, saying this because, from a design perspective, javac symbols >> usually don't care about uniqueness etc. - that's an extra value added >> when storing them into a constant pool. >> >> Maurizio >> >> On 17/08/15 13:33, Aleksey Shipilev wrote: >>> Hi, >>> >>> This issue gets into way with my current work: >>> https://bugs.openjdk.java.net/browse/JDK-8129547 >>> >>> There is a proof-of-concept patch: >>> http://cr.openjdk.java.net/~shade/8129547/webrev.00/ >>> >>> The crux of an issue seems to be the Method.equals() call in >>> DynamicMethod.equals(), that compares the type. The type of >>> DynamicMethod includes the DynamicMethodSymbol.type, that includes >>> dynamic args. It seems DynamicMethodSymbol is a better fit for >>> BootstrapMethod table key, since it includes BSM symbol and static >>> arguments only. >>> >>> I would be grateful if somebody from compiler team can help me out with >>> this. Is this the fix above valid? Can you do it better? >>> >>> How would one write a regression test for it? My cursory grep through >>> langtools tests does not yield a clear way to emit a special-shaped indy >>> for such a test. >>> >>> Thanks, >>> -Aleksey >>> >> > -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: OpenPGP digital signature URL: From maurizio.cimadamore at oracle.com Mon Aug 17 21:23:03 2015 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Mon, 17 Aug 2015 22:23:03 +0100 Subject: RFR 8129547 (S): Excess entries in BootstrapMethods with the same (bsm, bsmKind, bsmStaticArgs), but different dynamicArgs In-Reply-To: <55D234FF.6000209@oracle.com> References: <55D1D4B6.6090303@oracle.com> <55D1E619.1070201@oracle.com> <55D1EC8B.7090400@oracle.com> <55D234FF.6000209@oracle.com> Message-ID: <55D250B7.5050108@oracle.com> Whoops - that's what I meant to write, sorry; I'm glad you like the overall scheme. I will cook up a test tomorrow - we do have one test which attaches fake dynamic symbols to AST nodes, (using an annotation processor) then invokes code generation and checks the resulting bytecode [1]. I think one such test might be useful here. [1] - http://hg.openjdk.java.net/jdk9/jdk9/langtools/file/tip/test/tools/javac/lambda/TestInvokeDynamic.java Maurizio On 17/08/15 20:24, Aleksey Shipilev wrote: > Hi Maurizio, > > Thanks for an idea! It almost works, but not quite: super.equals() from > Method checks the type, so we need to guard super.*, as you did in > hashCode(). We also need a proper subclass check for the keys alone, > which means we might move equals() there, and make key a proper subclass > to gain access to "other". > > In short, this version works: > http://cr.openjdk.java.net/~shade/8129547/webrev.01/ > > Thanks, > -Aleksey > > On 17.08.2015 17:15, Maurizio Cimadamore wrote: >> Ok, I think I know what you meant now; DynamicMethod is used for two >> different purposes: >> >> * for the NameAndType CP entry associated with an invokedynamic >> instruction (pointed by the CONSTANT_InvokeDynamic entry); this bit >> _requires_ dynamic info to be taken into account - as different invoked >> types need to map to different entries - even if their underlying BSM >> entry is the same. >> >> * as keys in the BootstrapMethod attribute; in this case you want the >> dynamic info to be gone, as all it's going to be stored in the table is >> a bsmKind + static args list. >> >> How about something like this: >> >> http://cr.openjdk.java.net/~mcimadamore/8129547/ >> >> Maurizio >> >> >> >> On 17/08/15 14:48, Maurizio Cimadamore wrote: >>> Hi Alex, >>> the only dfference I see between your patch and the current code is >>> that the current code is comparing the invokedType, while yours is not >>> - am I reading your patch correctly? >>> >>> If that's the case, wouldn't dropping the call to super.equals from >>> Pool.DynamicMethod also resolve the issue? >>> >>> I'm, saying this because, from a design perspective, javac symbols >>> usually don't care about uniqueness etc. - that's an extra value added >>> when storing them into a constant pool. >>> >>> Maurizio >>> >>> On 17/08/15 13:33, Aleksey Shipilev wrote: >>>> Hi, >>>> >>>> This issue gets into way with my current work: >>>> https://bugs.openjdk.java.net/browse/JDK-8129547 >>>> >>>> There is a proof-of-concept patch: >>>> http://cr.openjdk.java.net/~shade/8129547/webrev.00/ >>>> >>>> The crux of an issue seems to be the Method.equals() call in >>>> DynamicMethod.equals(), that compares the type. The type of >>>> DynamicMethod includes the DynamicMethodSymbol.type, that includes >>>> dynamic args. It seems DynamicMethodSymbol is a better fit for >>>> BootstrapMethod table key, since it includes BSM symbol and static >>>> arguments only. >>>> >>>> I would be grateful if somebody from compiler team can help me out with >>>> this. Is this the fix above valid? Can you do it better? >>>> >>>> How would one write a regression test for it? My cursory grep through >>>> langtools tests does not yield a clear way to emit a special-shaped indy >>>> for such a test. >>>> >>>> Thanks, >>>> -Aleksey >>>> > From john.r.rose at oracle.com Tue Aug 18 05:15:47 2015 From: john.r.rose at oracle.com (John Rose) Date: Mon, 17 Aug 2015 22:15:47 -0700 Subject: RFR 8129547 (S): Excess entries in BootstrapMethods with the same (bsm, bsmKind, bsmStaticArgs), but different dynamicArgs In-Reply-To: <55D250B7.5050108@oracle.com> References: <55D1D4B6.6090303@oracle.com> <55D1E619.1070201@oracle.com> <55D1EC8B.7090400@oracle.com> <55D234FF.6000209@oracle.com> <55D250B7.5050108@oracle.com> Message-ID: <9826D5FF-6AC3-4F54-8EFC-F2F1331BB769@oracle.com> I think one reason this issue comes up is that the elements of the BootstrapMethods array seems to be different from the other entries in the constant pool. Logically, it would be reasonable to define a CONSTANT_BootstrapMethod which would consist (uniquely) of a CONSTANT_MethodHandle plus a counted array of (0 to N, N ~~ 252) additional constant pool references. The JSR 292 EG decided to put these guys into a separate constant pool attribute, not because they are not logically part of the constant pool, but because they markedly different in structure from all other constant pool entries. Note that all constant pool entries are either leaf nodes (utf8, integer, etc.) or else are a tagged structure of one or two constant pool references. A bootstrap method specifier is a structure of up to 1+N constant pool references. The Pack200 format deals with BootstrapMethods like this: >

Three more constant pools hold constants defined as part of the > Java 7 classfile format (major version 51 or later). One more > constant pool holds constants to be assembled into the > BootstrapMethods attribute, which may be viewed as an > appendix to the classfile constant pool.

http://docs.oracle.com/javase/8/docs/technotes/guides/pack200/pack-spec.html (The constant pool is a single heterogeneous array, except for the BSMs attribute, which is a homogeneous array that adds to the constant pool. If I were king of all classfile formats, and it was time to revolutionize my kingdom, I would reorganize the constant pool into a cadre of homogeneous arrays, as in the Pack200 format.) ? John On Aug 17, 2015, at 2:23 PM, Maurizio Cimadamore wrote: > > Whoops - that's what I meant to write, sorry; I'm glad you like the overall scheme. I will cook up a test tomorrow - we do have one test which attaches fake dynamic symbols to AST nodes, (using an annotation processor) then invokes code generation and checks the resulting bytecode [1]. I think one such test might be useful here. > > [1] - http://hg.openjdk.java.net/jdk9/jdk9/langtools/file/tip/test/tools/javac/lambda/TestInvokeDynamic.java > > Maurizio > > On 17/08/15 20:24, Aleksey Shipilev wrote: >> Hi Maurizio, >> >> Thanks for an idea! It almost works, but not quite: super.equals() from >> Method checks the type, so we need to guard super.*, as you did in >> hashCode(). We also need a proper subclass check for the keys alone, >> which means we might move equals() there, and make key a proper subclass >> to gain access to "other". >> >> In short, this version works: >> http://cr.openjdk.java.net/~shade/8129547/webrev.01/ >> >> Thanks, >> -Aleksey >> >> On 17.08.2015 17:15, Maurizio Cimadamore wrote: >>> Ok, I think I know what you meant now; DynamicMethod is used for two >>> different purposes: >>> >>> * for the NameAndType CP entry associated with an invokedynamic >>> instruction (pointed by the CONSTANT_InvokeDynamic entry); this bit >>> _requires_ dynamic info to be taken into account - as different invoked >>> types need to map to different entries - even if their underlying BSM >>> entry is the same. >>> >>> * as keys in the BootstrapMethod attribute; in this case you want the >>> dynamic info to be gone, as all it's going to be stored in the table is >>> a bsmKind + static args list. >>> >>> How about something like this: >>> >>> http://cr.openjdk.java.net/~mcimadamore/8129547/ >>> >>> Maurizio >>> >>> >>> >>> On 17/08/15 14:48, Maurizio Cimadamore wrote: >>>> Hi Alex, >>>> the only dfference I see between your patch and the current code is >>>> that the current code is comparing the invokedType, while yours is not >>>> - am I reading your patch correctly? >>>> >>>> If that's the case, wouldn't dropping the call to super.equals from >>>> Pool.DynamicMethod also resolve the issue? >>>> >>>> I'm, saying this because, from a design perspective, javac symbols >>>> usually don't care about uniqueness etc. - that's an extra value added >>>> when storing them into a constant pool. >>>> >>>> Maurizio >>>> >>>> On 17/08/15 13:33, Aleksey Shipilev wrote: >>>>> Hi, >>>>> >>>>> This issue gets into way with my current work: >>>>> https://bugs.openjdk.java.net/browse/JDK-8129547 >>>>> >>>>> There is a proof-of-concept patch: >>>>> http://cr.openjdk.java.net/~shade/8129547/webrev.00/ >>>>> >>>>> The crux of an issue seems to be the Method.equals() call in >>>>> DynamicMethod.equals(), that compares the type. The type of >>>>> DynamicMethod includes the DynamicMethodSymbol.type, that includes >>>>> dynamic args. It seems DynamicMethodSymbol is a better fit for >>>>> BootstrapMethod table key, since it includes BSM symbol and static >>>>> arguments only. >>>>> >>>>> I would be grateful if somebody from compiler team can help me out with >>>>> this. Is this the fix above valid? Can you do it better? >>>>> >>>>> How would one write a regression test for it? My cursory grep through >>>>> langtools tests does not yield a clear way to emit a special-shaped indy >>>>> for such a test. >>>>> >>>>> Thanks, >>>>> -Aleksey >>>>> >> > From georgiy.rakov at oracle.com Wed Aug 19 12:31:24 2015 From: georgiy.rakov at oracle.com (Georgiy Rakov) Date: Wed, 19 Aug 2015 15:31:24 +0300 Subject: The return type of instance creation expression with diamond and class body should be anonymous class type In-Reply-To: <55C3864F.9070504@oracle.com> References: <55C3864F.9070504@oracle.com> Message-ID: <55D4771C.1020009@oracle.com> Hello, FYI: I've filed the issue about this: https://bugs.openjdk.java.net/browse/JDK-8133936 Thanks, Georgiy. On 06.08.2015 19:07, Georgiy Rakov wrote: > Hello, > > let's consider following example: > class List { > List() {} > List getThis() { > return new List(); > } > } > > class Foo { > public Foo(T a1){} > } > > public class Test25 { > public static List m1(T item) { > List l = new List(); > return l; > } > public static void m2(List list1, List list2) { } > public static void test() { > m2(new List>(), m1(new Foo<>("str"){ }).getThis()); > } > } > > This example compiles successfully on JDK9b75. But according to my > understanding the compilation should have failed. The reasons for this > are presented below: > > 1. JDK-8073593 > > specifies following assertion: > > ***If C is an anonymous class, then the chosen constructor is the > constructor of the anonymous class. The return type is the > anonymous class type.*** > > current JLS 9 15.9.1 spec defines following assertion: > > The type of the class instance creation expression is the return > type of the chosen constructor, as defined above. > > so together these assertions lead to the fact that the type of > instance creation expression "new Foo<>("str"){ } " is anonymous class > type, let's denote it as "anonymous Foo". > > 2. Thus when m1 is invoked, that is "m1(new Foo<>("str"){ })", the > invocation return type is List>. > > 3. Hence when getThis is invoked, that is "m1(new Foo<>("str"){ > }).getThis()", the invocation return type is List Foo> as well. > > 4. Finally when m2 method is invoked type inference cause two equality > constraints to be created that is: U = Foo and U = (anonymous > Foo), together they should lead to compilation failure, but > compilation succeeds. > > This seems to be a javac bug. Could you please confirm if it really is. > > Please note, that if diamond is replaced with String type argument, > that is "new Foo("str"){ }" the compilation fails as expected: > > Error:(19, 9) java: method m2 in class Test25 cannot be applied to > given types; > required: List,List > found: List>,List< Foo>> > reason: inference variable U has incompatible equality > constraints >,Foo > > Thank you, > Georgiy. > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From bsrbnd at gmail.com Wed Aug 19 17:33:30 2015 From: bsrbnd at gmail.com (bsrbnd) Date: Wed, 19 Aug 2015 19:33:30 +0200 Subject: [PATCH] 8074570: Javac does not get membership right when it comes to erased supertypes Message-ID: Hi, As explained in issue 8074570 the following code doesn't compile because javac looses all type parameters when it comes to an erased supertype: interface Sup { boolean m(X x); } interface Sub extends Sup { boolean m(String s); } class Test { void test() { Sub s = new Sub() { // new Sub compiles.. @Override public boolean m(String o) {return true;} }; } } In this example, when all type parameters are erased, interface "Sup" defines abstract method "boolean m(Object x)" which is not overriden in our anonymous class. If you give a type parameter to "Sub" (for example: new Sub() {...}), all compiles fine because type parameters are not erased. The problem occures in Types.memberType(Type, Symbol) when javac searches for an implementation of Sup.m(X x). The call to Types.asOuterSuper(Type, Symbol) erases type parameters. The following patch replaces undefined type parameters with Object parameters instead of erasing them in Types.supertype(Type) and Types.interfaces(Type). I'm not sure if this is very clean, but it seems that it corrects the problem. It is also possible that this fix is too global and could be made more locally to avoid side effects. 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 @@ -2211,6 +2211,23 @@ public List erasureRecursive(List ts) { return erasure.visit(ts, true); } + + private List erasureWithObjects(List ts, List formals) { + Type[] objectParams = new Type[formals.length()]; + for (int i=0; i subt = subst(ts, formals, List.from(objectParams)); + return subt; + } + private Type erasureWithObjects(Type t, List formals) { + Type[] objectParams = new Type[formals.length()]; + for (int i=0; i // @@ -2281,7 +2298,7 @@ List actuals = classBound(t).allparams(); List formals = t.tsym.type.allparams(); if (t.hasErasedSupertypes()) { - t.supertype_field = erasureRecursive(supertype); + t.supertype_field = erasureWithObjects(supertype, formals); } else if (formals.nonEmpty()) { t.supertype_field = subst(supertype, formals, actuals); } @@ -2362,7 +2379,7 @@ List actuals = t.allparams(); List formals = t.tsym.type.allparams(); if (t.hasErasedSupertypes()) { - t.interfaces_field = erasureRecursive(interfaces); + t.interfaces_field = erasureWithObjects(interfaces, formals); } else if (formals.nonEmpty()) { t.interfaces_field = subst(interfaces, formals, actuals); } Regards, bsrbnd From maurizio.cimadamore at oracle.com Thu Aug 20 00:57:54 2015 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 20 Aug 2015 01:57:54 +0100 Subject: [PATCH] 8074570: Javac does not get membership right when it comes to erased supertypes In-Reply-To: References: Message-ID: <55D52612.20507@oracle.com> Hi, I think javac is behaving according to the JLS - section 4.8 (raw types): "The superclasses (respectively, superinterfaces) of a raw type are the erasures of the superclasses (superinterfaces) of any of the parameterizations of the generic type. " This seems to imply that the supertype of Sub (raw) is just Sup; I agree this is confusing and a lot of people trip over this - but that's what the spec mandates. That said, we are aware of this and we'd like to improve over this - but it will take a while to figure out a plausible compatibility story. Maurizio On 19/08/15 18:33, bsrbnd wrote: > Hi, > > As explained in issue 8074570 the following code doesn't compile > because javac looses all type parameters when it comes to an erased > supertype: > > interface Sup { > boolean m(X x); > } > > interface Sub extends Sup { > boolean m(String s); > } > > class Test { > void test() { > Sub s = new Sub() { // new Sub compiles.. > @Override > public boolean m(String o) {return true;} > }; > } > } > > In this example, when all type parameters are erased, interface "Sup" > defines abstract method "boolean m(Object x)" which is not overriden > in our anonymous class. > If you give a type parameter to "Sub" (for example: new Sub() > {...}), all compiles fine because type parameters are not erased. > > The problem occures in Types.memberType(Type, Symbol) when javac > searches for an implementation of Sup.m(X x). > The call to Types.asOuterSuper(Type, Symbol) erases type parameters. > > The following patch replaces undefined type parameters with Object > parameters instead of erasing them in Types.supertype(Type) and > Types.interfaces(Type). > > I'm not sure if this is very clean, but it seems that it corrects the problem. > It is also possible that this fix is too global and could be made more > locally to avoid side effects. > > 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 > @@ -2211,6 +2211,23 @@ > public List erasureRecursive(List ts) { > return erasure.visit(ts, true); > } > + > + private List erasureWithObjects(List ts, List formals) { > + Type[] objectParams = new Type[formals.length()]; > + for (int i=0; i + objectParams[i] = syms.objectType; > + } > + List subt = subst(ts, formals, List.from(objectParams)); > + return subt; > + } > + private Type erasureWithObjects(Type t, List formals) { > + Type[] objectParams = new Type[formals.length()]; > + for (int i=0; i + objectParams[i] = syms.objectType; > + } > + Type subt = subst(t, formals, List.from(objectParams)); > + return subt; > + } > // > > // > @@ -2281,7 +2298,7 @@ > List actuals = classBound(t).allparams(); > List formals = t.tsym.type.allparams(); > if (t.hasErasedSupertypes()) { > - t.supertype_field = erasureRecursive(supertype); > + t.supertype_field = > erasureWithObjects(supertype, formals); > } else if (formals.nonEmpty()) { > t.supertype_field = subst(supertype, > formals, actuals); > } > @@ -2362,7 +2379,7 @@ > List actuals = t.allparams(); > List formals = t.tsym.type.allparams(); > if (t.hasErasedSupertypes()) { > - t.interfaces_field = erasureRecursive(interfaces); > + t.interfaces_field = > erasureWithObjects(interfaces, formals); > } else if (formals.nonEmpty()) { > t.interfaces_field = subst(interfaces, > formals, actuals); > } > > > Regards, > > bsrbnd From rob.mckenna at oracle.com Thu Aug 20 15:09:12 2015 From: rob.mckenna at oracle.com (Rob McKenna) Date: Thu, 20 Aug 2015 16:09:12 +0100 Subject: RFR: 8071291 - Compiler crashes trying to cast UnionType to IntersectionClassType Message-ID: <55D5ED98.4050809@oracle.com> Hi folks, Looking to backport this change to 8. There is a slight difference in the fix between 8 & 9 in that makeIntersectionType(Type bound1, Type bound2) (n?e makeCompoundType(Type bound1, Type bound2)) is still in use in 8. http://cr.openjdk.java.net/~robm/8071291/webrev/ -Rob From maurizio.cimadamore at oracle.com Thu Aug 20 21:52:16 2015 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 20 Aug 2015 22:52:16 +0100 Subject: RFR: 8071291 - Compiler crashes trying to cast UnionType to IntersectionClassType In-Reply-To: <55D5ED98.4050809@oracle.com> References: <55D5ED98.4050809@oracle.com> Message-ID: <55D64C10.2030007@oracle.com> Looks good - thanks! Maurizio On 20/08/15 16:09, Rob McKenna wrote: > Hi folks, > > Looking to backport this change to 8. There is a slight difference in > the fix between 8 & 9 in that makeIntersectionType(Type bound1, Type > bound2) (n?e makeCompoundType(Type bound1, Type bound2)) is still in > use in 8. > > http://cr.openjdk.java.net/~robm/8071291/webrev/ > > -Rob From cushon at google.com Fri Aug 21 00:21:52 2015 From: cushon at google.com (Liam Miller-Cushon) Date: Thu, 20 Aug 2015 17:21:52 -0700 Subject: attributing files with syntax errors Message-ID: I spent some time yesterday being surprised by the behaviour of -XDcompilePolicy=todo: $ cat Test.java import no.such.pkg.MissingSymbol; class Test {{ new MissingSymbol(); }} $ javac -XDshouldStopPolicyIfError=INIT -XDcompilePolicy=todo Test.java Test.java:1: error: package no.such.pkg does not exist Test.java:4: error: cannot find symbol $ javac -XDshouldStopPolicyIfError=ATTR -XDcompilePolicy=todo Test.java Test.java:1: error: package no.such.pkg does not exist Test.java:4: error: cannot find symbol $ javac -XDshouldStopPolicyIfError=INIT -XDcompilePolicy=byfile Test.java Test.java:1: error: package no.such.pkg does not exist $ javac -XDshouldStopPolicyIfError=ATTR -XDcompilePolicy=byfile Test.java Test.java:1: error: package no.such.pkg does not exist Test.java:4: error: cannot find symbol In the first compilation, the 'cannot find symbol' error is emitted despite -XDshouldStopPolicyIfError=INIT. I expected the output to look like it does with a byfile policy (the third example). This appears to be a known issue: "in bytodo mode, javac will still attribute files after syntax errors. Changing that behavior may surprise existing users, so for now, we work around it." [1] This seems to affect all policies except byfile. Is there any chance this can be fixed? It's a simple patch, which I'd be happy to contribute. Most of the work is fixing up existing tests that produce different diagnostics after the fix. If the fix is still too risky, is it worth considering changing byfile to match the other policies? I think the difference between policies is more surprising than fixing the bug would be. If that isn't an option either, it'd be nice to at least create a tracking bug and document the issue somewhere more discoverable. Thanks, Liam [1] http://hg.openjdk.java.net/jdk9/dev/langtools/file/eaab8a16dcfb/test/tools/javac/policy/test3/Test.java#l98 -------------- next part -------------- An HTML attachment was scrubbed... URL: From jonathan.gibbons at oracle.com Fri Aug 21 01:04:05 2015 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Thu, 20 Aug 2015 18:04:05 -0700 Subject: attributing files with syntax errors In-Reply-To: References: Message-ID: <55D67905.7010905@oracle.com> Liam, Interesting issue. Filed as https://bugs.openjdk.java.net/browse/JDK-8134117. Twiddling the CompilePolicy is an "internal" knob, controlled by a "hidden" (-XD) option. That being said, my primary concern about changing the bytodo policy is that it is the default policy, so changing it will potentially affect everyone, even those who don't know about the CompilePolicy. And _that_ being said, the original intent of providing the CompilePolicy was to address bugs in which a file had multiple top level classes, and some could have classes generated before errors were detected in other classes in the same file. Hence the byfile policy. But for various reasons, byfile never became the default. I seem to recall it was at least in part due to memory usage, which is less of a concern today than it was back then. The other area where this might be relevant is annotation processing, where the original code was not so good back then at differentiating different types of errors, and so we wanted compilation to continue more often than we do now. Nowadays, javac has a better concept of "recoverable errors", and so javac is better at not proceeding unnecessarily. So I guess I'd be interested to see the patch, although to prevent unnecessary work up front, it may be worth posting the src/ patch first, with some info on just how many and which tests need fixing. The more tests that need fixup, the more carefully we should review the change in behavior. -- Jon On 08/20/2015 05:21 PM, Liam Miller-Cushon wrote: > I spent some time yesterday being surprised by the behaviour of > -XDcompilePolicy=todo: > > $ cat Test.java > import no.such.pkg.MissingSymbol; > > class Test {{ > new MissingSymbol(); > }} > > $ javac -XDshouldStopPolicyIfError=INIT -XDcompilePolicy=todo Test.java > Test.java:1: error: package no.such.pkg does not exist > Test.java:4: error: cannot find symbol > > $ javac -XDshouldStopPolicyIfError=ATTR -XDcompilePolicy=todo Test.java > Test.java:1: error: package no.such.pkg does not exist > Test.java:4: error: cannot find symbol > > $ javac -XDshouldStopPolicyIfError=INIT -XDcompilePolicy=byfile Test.java > Test.java:1: error: package no.such.pkg does not exist > > $ javac -XDshouldStopPolicyIfError=ATTR -XDcompilePolicy=byfile Test.java > Test.java:1: error: package no.such.pkg does not exist > Test.java:4: error: cannot find symbol > > In the first compilation, the 'cannot find symbol' error is emitted > despite -XDshouldStopPolicyIfError=INIT. I expected the output to look > like it does with a byfile policy (the third example). > > This appears to be a known issue: "in bytodo mode, javac will still > attribute files after syntax errors. Changing that behavior may > surprise existing users, so for now, we work around it." [1] This > seems to affect all policies except byfile. > > Is there any chance this can be fixed? It's a simple patch, which I'd > be happy to contribute. Most of the work is fixing up existing tests > that produce different diagnostics after the fix. > > If the fix is still too risky, is it worth considering changing byfile > to match the other policies? I think the difference between policies > is more surprising than fixing the bug would be. If that isn't an > option either, it'd be nice to at least create a tracking bug and > document the issue somewhere more discoverable. > > Thanks, > Liam > > [1] > http://hg.openjdk.java.net/jdk9/dev/langtools/file/eaab8a16dcfb/test/tools/javac/policy/test3/Test.java#l98 From cushon at google.com Fri Aug 21 01:27:36 2015 From: cushon at google.com (Liam Miller-Cushon) Date: Thu, 20 Aug 2015 18:27:36 -0700 Subject: attributing files with syntax errors In-Reply-To: <55D67905.7010905@oracle.com> References: <55D67905.7010905@oracle.com> Message-ID: Thanks for taking a look. On Thu, Aug 20, 2015 at 6:04 PM, Jonathan Gibbons < jonathan.gibbons at oracle.com> wrote: > Twiddling the CompilePolicy is an "internal" knob, controlled by a > "hidden" (-XD) option. That being said, my primary concern about changing > the bytodo policy is that it is the default policy, so changing it will > potentially affect everyone, even those who don't know about the > CompilePolicy. > Understood. It's possible that showing errors from attr is actually better for most people, since the extra information could be helpful when fixing compilation errors. One way to minimize the impact would be to change the default shouldStopPolicyIfError mode to attr at the same time the bug was fixed, so the default behaviour was unchanged. > And _that_ being said, the original intent of providing the CompilePolicy > was to address bugs in which a file had multiple top level classes, and > some could have classes generated before errors were detected in other > classes in the same file. Hence the byfile policy. But for various > reasons, byfile never became the default. I seem to recall it was at least > in part due to memory usage, which is less of a concern today than it was > back then. > The other area where this might be relevant is annotation processing, > where the original code was not so good back then at differentiating > different types of errors, and so we wanted compilation to continue more > often than we do now. Nowadays, javac has a better concept of "recoverable > errors", and so javac is better at not proceeding unnecessarily. > Interesting. The reason we came across this and were experimenting with byfile is for error prone. It's occasionally useful to inspect an entire compilation unit instead of individual top-level declarations, and with the bytodo policy top-level declarations are lowered one at time, so by the time everything in a compilation unit has gone through flow some things have already been lowered. (I think the plugin api makes it harder to observe that by associating events with top-level declarations, and discouraging inspecting compilation units.) > So I guess I'd be interested to see the patch, although to prevent > unnecessary work up front, it may be worth posting the src/ patch first, > with some info on just how many and which tests need fixing. The more > tests that need fixup, the more carefully we should review the change in > behavior. > Here's the trivial fix I was testing, which just replicates the logic in byfile for todo. I realized after doing this that the same issue affects all of the other policies, so the check should probably be moved higher up. diff -r eaab8a16dcfb src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java Thu Aug 20 11:38:24 2015 -0700 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java Thu Aug 20 18:09:00 2015 -0700 @@ -867,7 +867,7 @@ break; case BY_TODO: - while (!todo.isEmpty()) + while (!todo.isEmpty() && !shouldStop(CompileState.ATTR)) generate(desugar(flow(attribute(todo.remove())))); break; I counted 37 test failures, excluding two that test compilation policies. The list is attached. -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- Ambig3.java FlatnameClash2.java NestedInnerClassNames.java OverridePosition.java T6326754.java 4980495/std/Test.java 6304921/T6304921.java 7086595/T7086595.java 8052070/DuplicateTypeParameter.java ExtendsAccess/ExtendsAccess.java QualifiedAccess/QualifiedAccess_1.java QualifiedAccess/QualifiedAccess_2.java annotations/neg/NoDefault.java annotations/neg/NoStatic.java annotations/repeatingAnnotations/MissingDefaultCase1.java annotations/repeatingAnnotations/MissingDefaultCase2.java annotations/repeatingAnnotations/MissingValueMethod.java annotations/repeatingAnnotations/UseWrongRepeatable.java annotations/repeatingAnnotations/WrongReturnTypeForValue.java annotations/repeatingAnnotations/8029017/TypeUseTargetNeg.java annotations/typeAnnotations/DeclVsUseErrorMessage.java defaultMethods/Neg13.java defaultMethods/private/Private02.java defaultMethods/private/Private06.java defaultMethods/private/Private08.java enum/Enum2.java enum/T5081785.java generics/InheritanceConflict3.java generics/inference/4972073/T4972073.java generics/rawOverride/7157798/Test3.java generics/rawOverride/7157798/Test4.java lambda/FunctionalInterfaceAnno.java lambda/LambdaConv18.java lambda/funcInterfaces/NonSAM2.java protectedAccess/ProtectedMemberAccess2.java protectedAccess/ProtectedMemberAccess3.java staticImport/ImportPrivate.java From aleksey.shipilev at oracle.com Fri Aug 21 15:10:08 2015 From: aleksey.shipilev at oracle.com (Aleksey Shipilev) Date: Fri, 21 Aug 2015 18:10:08 +0300 Subject: RFR 8129547 (S): Excess entries in BootstrapMethods with the same (bsm, bsmKind, bsmStaticArgs), but different dynamicArgs In-Reply-To: <55D250B7.5050108@oracle.com> References: <55D1D4B6.6090303@oracle.com> <55D1E619.1070201@oracle.com> <55D1EC8B.7090400@oracle.com> <55D234FF.6000209@oracle.com> <55D250B7.5050108@oracle.com> Message-ID: <55D73F50.8000904@oracle.com> Hey Maurizio, I have tried to slim down TestInvokeDynamic to make a regression test. It fails on current javac, and passes on a patched one: http://cr.openjdk.java.net/~shade/8129547/webrev.02/ Thanks, -Aleksey On 08/18/2015 12:23 AM, Maurizio Cimadamore wrote: > Whoops - that's what I meant to write, sorry; I'm glad you like the > overall scheme. I will cook up a test tomorrow - we do have one test > which attaches fake dynamic symbols to AST nodes, (using an annotation > processor) then invokes code generation and checks the resulting > bytecode [1]. I think one such test might be useful here. > > [1] - > http://hg.openjdk.java.net/jdk9/jdk9/langtools/file/tip/test/tools/javac/lambda/TestInvokeDynamic.java > > > Maurizio > > On 17/08/15 20:24, Aleksey Shipilev wrote: >> Hi Maurizio, >> >> Thanks for an idea! It almost works, but not quite: super.equals() from >> Method checks the type, so we need to guard super.*, as you did in >> hashCode(). We also need a proper subclass check for the keys alone, >> which means we might move equals() there, and make key a proper subclass >> to gain access to "other". >> >> In short, this version works: >> http://cr.openjdk.java.net/~shade/8129547/webrev.01/ >> >> Thanks, >> -Aleksey >> >> On 17.08.2015 17:15, Maurizio Cimadamore wrote: >>> Ok, I think I know what you meant now; DynamicMethod is used for two >>> different purposes: >>> >>> * for the NameAndType CP entry associated with an invokedynamic >>> instruction (pointed by the CONSTANT_InvokeDynamic entry); this bit >>> _requires_ dynamic info to be taken into account - as different invoked >>> types need to map to different entries - even if their underlying BSM >>> entry is the same. >>> >>> * as keys in the BootstrapMethod attribute; in this case you want the >>> dynamic info to be gone, as all it's going to be stored in the table is >>> a bsmKind + static args list. >>> >>> How about something like this: >>> >>> http://cr.openjdk.java.net/~mcimadamore/8129547/ >>> >>> Maurizio >>> >>> >>> >>> On 17/08/15 14:48, Maurizio Cimadamore wrote: >>>> Hi Alex, >>>> the only dfference I see between your patch and the current code is >>>> that the current code is comparing the invokedType, while yours is not >>>> - am I reading your patch correctly? >>>> >>>> If that's the case, wouldn't dropping the call to super.equals from >>>> Pool.DynamicMethod also resolve the issue? >>>> >>>> I'm, saying this because, from a design perspective, javac symbols >>>> usually don't care about uniqueness etc. - that's an extra value added >>>> when storing them into a constant pool. >>>> >>>> Maurizio >>>> >>>> On 17/08/15 13:33, Aleksey Shipilev wrote: >>>>> Hi, >>>>> >>>>> This issue gets into way with my current work: >>>>> https://bugs.openjdk.java.net/browse/JDK-8129547 >>>>> >>>>> There is a proof-of-concept patch: >>>>> http://cr.openjdk.java.net/~shade/8129547/webrev.00/ >>>>> >>>>> The crux of an issue seems to be the Method.equals() call in >>>>> DynamicMethod.equals(), that compares the type. The type of >>>>> DynamicMethod includes the DynamicMethodSymbol.type, that includes >>>>> dynamic args. It seems DynamicMethodSymbol is a better fit for >>>>> BootstrapMethod table key, since it includes BSM symbol and static >>>>> arguments only. >>>>> >>>>> I would be grateful if somebody from compiler team can help me out >>>>> with >>>>> this. Is this the fix above valid? Can you do it better? >>>>> >>>>> How would one write a regression test for it? My cursory grep through >>>>> langtools tests does not yield a clear way to emit a special-shaped >>>>> indy >>>>> for such a test. >>>>> >>>>> Thanks, >>>>> -Aleksey >>>>> >> > -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: OpenPGP digital signature URL: From maurizio.cimadamore at oracle.com Fri Aug 21 15:42:46 2015 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Fri, 21 Aug 2015 16:42:46 +0100 Subject: RFR 8129547 (S): Excess entries in BootstrapMethods with the same (bsm, bsmKind, bsmStaticArgs), but different dynamicArgs In-Reply-To: <55D73F50.8000904@oracle.com> References: <55D1D4B6.6090303@oracle.com> <55D1E619.1070201@oracle.com> <55D1EC8B.7090400@oracle.com> <55D234FF.6000209@oracle.com> <55D250B7.5050108@oracle.com> <55D73F50.8000904@oracle.com> Message-ID: <55D746F6.3090301@oracle.com> Cool - many thanks! I'd say we can go ahead with this. Maurizio On 21/08/15 16:10, Aleksey Shipilev wrote: > Hey Maurizio, > > I have tried to slim down TestInvokeDynamic to make a regression test. > It fails on current javac, and passes on a patched one: > http://cr.openjdk.java.net/~shade/8129547/webrev.02/ > > Thanks, > -Aleksey > > On 08/18/2015 12:23 AM, Maurizio Cimadamore wrote: >> Whoops - that's what I meant to write, sorry; I'm glad you like the >> overall scheme. I will cook up a test tomorrow - we do have one test >> which attaches fake dynamic symbols to AST nodes, (using an annotation >> processor) then invokes code generation and checks the resulting >> bytecode [1]. I think one such test might be useful here. >> >> [1] - >> http://hg.openjdk.java.net/jdk9/jdk9/langtools/file/tip/test/tools/javac/lambda/TestInvokeDynamic.java >> >> >> Maurizio >> >> On 17/08/15 20:24, Aleksey Shipilev wrote: >>> Hi Maurizio, >>> >>> Thanks for an idea! It almost works, but not quite: super.equals() from >>> Method checks the type, so we need to guard super.*, as you did in >>> hashCode(). We also need a proper subclass check for the keys alone, >>> which means we might move equals() there, and make key a proper subclass >>> to gain access to "other". >>> >>> In short, this version works: >>> http://cr.openjdk.java.net/~shade/8129547/webrev.01/ >>> >>> Thanks, >>> -Aleksey >>> >>> On 17.08.2015 17:15, Maurizio Cimadamore wrote: >>>> Ok, I think I know what you meant now; DynamicMethod is used for two >>>> different purposes: >>>> >>>> * for the NameAndType CP entry associated with an invokedynamic >>>> instruction (pointed by the CONSTANT_InvokeDynamic entry); this bit >>>> _requires_ dynamic info to be taken into account - as different invoked >>>> types need to map to different entries - even if their underlying BSM >>>> entry is the same. >>>> >>>> * as keys in the BootstrapMethod attribute; in this case you want the >>>> dynamic info to be gone, as all it's going to be stored in the table is >>>> a bsmKind + static args list. >>>> >>>> How about something like this: >>>> >>>> http://cr.openjdk.java.net/~mcimadamore/8129547/ >>>> >>>> Maurizio >>>> >>>> >>>> >>>> On 17/08/15 14:48, Maurizio Cimadamore wrote: >>>>> Hi Alex, >>>>> the only dfference I see between your patch and the current code is >>>>> that the current code is comparing the invokedType, while yours is not >>>>> - am I reading your patch correctly? >>>>> >>>>> If that's the case, wouldn't dropping the call to super.equals from >>>>> Pool.DynamicMethod also resolve the issue? >>>>> >>>>> I'm, saying this because, from a design perspective, javac symbols >>>>> usually don't care about uniqueness etc. - that's an extra value added >>>>> when storing them into a constant pool. >>>>> >>>>> Maurizio >>>>> >>>>> On 17/08/15 13:33, Aleksey Shipilev wrote: >>>>>> Hi, >>>>>> >>>>>> This issue gets into way with my current work: >>>>>> https://bugs.openjdk.java.net/browse/JDK-8129547 >>>>>> >>>>>> There is a proof-of-concept patch: >>>>>> http://cr.openjdk.java.net/~shade/8129547/webrev.00/ >>>>>> >>>>>> The crux of an issue seems to be the Method.equals() call in >>>>>> DynamicMethod.equals(), that compares the type. The type of >>>>>> DynamicMethod includes the DynamicMethodSymbol.type, that includes >>>>>> dynamic args. It seems DynamicMethodSymbol is a better fit for >>>>>> BootstrapMethod table key, since it includes BSM symbol and static >>>>>> arguments only. >>>>>> >>>>>> I would be grateful if somebody from compiler team can help me out >>>>>> with >>>>>> this. Is this the fix above valid? Can you do it better? >>>>>> >>>>>> How would one write a regression test for it? My cursory grep through >>>>>> langtools tests does not yield a clear way to emit a special-shaped >>>>>> indy >>>>>> for such a test. >>>>>> >>>>>> Thanks, >>>>>> -Aleksey >>>>>> > From aleksey.shipilev at oracle.com Fri Aug 21 15:51:33 2015 From: aleksey.shipilev at oracle.com (Aleksey Shipilev) Date: Fri, 21 Aug 2015 18:51:33 +0300 Subject: RFR 8129547 (S): Excess entries in BootstrapMethods with the same (bsm, bsmKind, bsmStaticArgs), but different dynamicArgs In-Reply-To: <55D746F6.3090301@oracle.com> References: <55D1D4B6.6090303@oracle.com> <55D1E619.1070201@oracle.com> <55D1EC8B.7090400@oracle.com> <55D234FF.6000209@oracle.com> <55D250B7.5050108@oracle.com> <55D73F50.8000904@oracle.com> <55D746F6.3090301@oracle.com> Message-ID: <55D74905.3010102@oracle.com> I agree. Please sponsor? Not sure what pre-commit checks are needed to be run. I have only tested with that regression test, plus some other related ones for indy string concat. -Aleksey On 08/21/2015 06:42 PM, Maurizio Cimadamore wrote: > Cool - many thanks! > > I'd say we can go ahead with this. > > Maurizio > > On 21/08/15 16:10, Aleksey Shipilev wrote: >> Hey Maurizio, >> >> I have tried to slim down TestInvokeDynamic to make a regression test. >> It fails on current javac, and passes on a patched one: >> http://cr.openjdk.java.net/~shade/8129547/webrev.02/ >> >> Thanks, >> -Aleksey >> >> On 08/18/2015 12:23 AM, Maurizio Cimadamore wrote: >>> Whoops - that's what I meant to write, sorry; I'm glad you like the >>> overall scheme. I will cook up a test tomorrow - we do have one test >>> which attaches fake dynamic symbols to AST nodes, (using an annotation >>> processor) then invokes code generation and checks the resulting >>> bytecode [1]. I think one such test might be useful here. >>> >>> [1] - >>> http://hg.openjdk.java.net/jdk9/jdk9/langtools/file/tip/test/tools/javac/lambda/TestInvokeDynamic.java >>> >>> >>> >>> Maurizio >>> >>> On 17/08/15 20:24, Aleksey Shipilev wrote: >>>> Hi Maurizio, >>>> >>>> Thanks for an idea! It almost works, but not quite: super.equals() from >>>> Method checks the type, so we need to guard super.*, as you did in >>>> hashCode(). We also need a proper subclass check for the keys alone, >>>> which means we might move equals() there, and make key a proper >>>> subclass >>>> to gain access to "other". >>>> >>>> In short, this version works: >>>> http://cr.openjdk.java.net/~shade/8129547/webrev.01/ >>>> >>>> Thanks, >>>> -Aleksey >>>> >>>> On 17.08.2015 17:15, Maurizio Cimadamore wrote: >>>>> Ok, I think I know what you meant now; DynamicMethod is used for two >>>>> different purposes: >>>>> >>>>> * for the NameAndType CP entry associated with an invokedynamic >>>>> instruction (pointed by the CONSTANT_InvokeDynamic entry); this bit >>>>> _requires_ dynamic info to be taken into account - as different >>>>> invoked >>>>> types need to map to different entries - even if their underlying BSM >>>>> entry is the same. >>>>> >>>>> * as keys in the BootstrapMethod attribute; in this case you want the >>>>> dynamic info to be gone, as all it's going to be stored in the >>>>> table is >>>>> a bsmKind + static args list. >>>>> >>>>> How about something like this: >>>>> >>>>> http://cr.openjdk.java.net/~mcimadamore/8129547/ >>>>> >>>>> Maurizio >>>>> >>>>> >>>>> >>>>> On 17/08/15 14:48, Maurizio Cimadamore wrote: >>>>>> Hi Alex, >>>>>> the only dfference I see between your patch and the current code is >>>>>> that the current code is comparing the invokedType, while yours is >>>>>> not >>>>>> - am I reading your patch correctly? >>>>>> >>>>>> If that's the case, wouldn't dropping the call to super.equals from >>>>>> Pool.DynamicMethod also resolve the issue? >>>>>> >>>>>> I'm, saying this because, from a design perspective, javac symbols >>>>>> usually don't care about uniqueness etc. - that's an extra value >>>>>> added >>>>>> when storing them into a constant pool. >>>>>> >>>>>> Maurizio >>>>>> >>>>>> On 17/08/15 13:33, Aleksey Shipilev wrote: >>>>>>> Hi, >>>>>>> >>>>>>> This issue gets into way with my current work: >>>>>>> https://bugs.openjdk.java.net/browse/JDK-8129547 >>>>>>> >>>>>>> There is a proof-of-concept patch: >>>>>>> http://cr.openjdk.java.net/~shade/8129547/webrev.00/ >>>>>>> >>>>>>> The crux of an issue seems to be the Method.equals() call in >>>>>>> DynamicMethod.equals(), that compares the type. The type of >>>>>>> DynamicMethod includes the DynamicMethodSymbol.type, that includes >>>>>>> dynamic args. It seems DynamicMethodSymbol is a better fit for >>>>>>> BootstrapMethod table key, since it includes BSM symbol and static >>>>>>> arguments only. >>>>>>> >>>>>>> I would be grateful if somebody from compiler team can help me out >>>>>>> with >>>>>>> this. Is this the fix above valid? Can you do it better? >>>>>>> >>>>>>> How would one write a regression test for it? My cursory grep >>>>>>> through >>>>>>> langtools tests does not yield a clear way to emit a special-shaped >>>>>>> indy >>>>>>> for such a test. >>>>>>> >>>>>>> Thanks, >>>>>>> -Aleksey >>>>>>> >> > -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: OpenPGP digital signature URL: From maurizio.cimadamore at oracle.com Fri Aug 21 16:29:27 2015 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Fri, 21 Aug 2015 17:29:27 +0100 Subject: RFR 8129547 (S): Excess entries in BootstrapMethods with the same (bsm, bsmKind, bsmStaticArgs), but different dynamicArgs In-Reply-To: <55D74905.3010102@oracle.com> References: <55D1D4B6.6090303@oracle.com> <55D1E619.1070201@oracle.com> <55D1EC8B.7090400@oracle.com> <55D234FF.6000209@oracle.com> <55D250B7.5050108@oracle.com> <55D73F50.8000904@oracle.com> <55D746F6.3090301@oracle.com> <55D74905.3010102@oracle.com> Message-ID: <55D751E7.7010108@oracle.com> I will put everything together, run tests and submit a review - is that ok? Maurizio On 21/08/15 16:51, Aleksey Shipilev wrote: > I agree. Please sponsor? > > Not sure what pre-commit checks are needed to be run. I have only tested > with that regression test, plus some other related ones for indy string > concat. > > -Aleksey > > On 08/21/2015 06:42 PM, Maurizio Cimadamore wrote: >> Cool - many thanks! >> >> I'd say we can go ahead with this. >> >> Maurizio >> >> On 21/08/15 16:10, Aleksey Shipilev wrote: >>> Hey Maurizio, >>> >>> I have tried to slim down TestInvokeDynamic to make a regression test. >>> It fails on current javac, and passes on a patched one: >>> http://cr.openjdk.java.net/~shade/8129547/webrev.02/ >>> >>> Thanks, >>> -Aleksey >>> >>> On 08/18/2015 12:23 AM, Maurizio Cimadamore wrote: >>>> Whoops - that's what I meant to write, sorry; I'm glad you like the >>>> overall scheme. I will cook up a test tomorrow - we do have one test >>>> which attaches fake dynamic symbols to AST nodes, (using an annotation >>>> processor) then invokes code generation and checks the resulting >>>> bytecode [1]. I think one such test might be useful here. >>>> >>>> [1] - >>>> http://hg.openjdk.java.net/jdk9/jdk9/langtools/file/tip/test/tools/javac/lambda/TestInvokeDynamic.java >>>> >>>> >>>> >>>> Maurizio >>>> >>>> On 17/08/15 20:24, Aleksey Shipilev wrote: >>>>> Hi Maurizio, >>>>> >>>>> Thanks for an idea! It almost works, but not quite: super.equals() from >>>>> Method checks the type, so we need to guard super.*, as you did in >>>>> hashCode(). We also need a proper subclass check for the keys alone, >>>>> which means we might move equals() there, and make key a proper >>>>> subclass >>>>> to gain access to "other". >>>>> >>>>> In short, this version works: >>>>> http://cr.openjdk.java.net/~shade/8129547/webrev.01/ >>>>> >>>>> Thanks, >>>>> -Aleksey >>>>> >>>>> On 17.08.2015 17:15, Maurizio Cimadamore wrote: >>>>>> Ok, I think I know what you meant now; DynamicMethod is used for two >>>>>> different purposes: >>>>>> >>>>>> * for the NameAndType CP entry associated with an invokedynamic >>>>>> instruction (pointed by the CONSTANT_InvokeDynamic entry); this bit >>>>>> _requires_ dynamic info to be taken into account - as different >>>>>> invoked >>>>>> types need to map to different entries - even if their underlying BSM >>>>>> entry is the same. >>>>>> >>>>>> * as keys in the BootstrapMethod attribute; in this case you want the >>>>>> dynamic info to be gone, as all it's going to be stored in the >>>>>> table is >>>>>> a bsmKind + static args list. >>>>>> >>>>>> How about something like this: >>>>>> >>>>>> http://cr.openjdk.java.net/~mcimadamore/8129547/ >>>>>> >>>>>> Maurizio >>>>>> >>>>>> >>>>>> >>>>>> On 17/08/15 14:48, Maurizio Cimadamore wrote: >>>>>>> Hi Alex, >>>>>>> the only dfference I see between your patch and the current code is >>>>>>> that the current code is comparing the invokedType, while yours is >>>>>>> not >>>>>>> - am I reading your patch correctly? >>>>>>> >>>>>>> If that's the case, wouldn't dropping the call to super.equals from >>>>>>> Pool.DynamicMethod also resolve the issue? >>>>>>> >>>>>>> I'm, saying this because, from a design perspective, javac symbols >>>>>>> usually don't care about uniqueness etc. - that's an extra value >>>>>>> added >>>>>>> when storing them into a constant pool. >>>>>>> >>>>>>> Maurizio >>>>>>> >>>>>>> On 17/08/15 13:33, Aleksey Shipilev wrote: >>>>>>>> Hi, >>>>>>>> >>>>>>>> This issue gets into way with my current work: >>>>>>>> https://bugs.openjdk.java.net/browse/JDK-8129547 >>>>>>>> >>>>>>>> There is a proof-of-concept patch: >>>>>>>> http://cr.openjdk.java.net/~shade/8129547/webrev.00/ >>>>>>>> >>>>>>>> The crux of an issue seems to be the Method.equals() call in >>>>>>>> DynamicMethod.equals(), that compares the type. The type of >>>>>>>> DynamicMethod includes the DynamicMethodSymbol.type, that includes >>>>>>>> dynamic args. It seems DynamicMethodSymbol is a better fit for >>>>>>>> BootstrapMethod table key, since it includes BSM symbol and static >>>>>>>> arguments only. >>>>>>>> >>>>>>>> I would be grateful if somebody from compiler team can help me out >>>>>>>> with >>>>>>>> this. Is this the fix above valid? Can you do it better? >>>>>>>> >>>>>>>> How would one write a regression test for it? My cursory grep >>>>>>>> through >>>>>>>> langtools tests does not yield a clear way to emit a special-shaped >>>>>>>> indy >>>>>>>> for such a test. >>>>>>>> >>>>>>>> Thanks, >>>>>>>> -Aleksey >>>>>>>> > From aleksey.shipilev at oracle.com Fri Aug 21 16:30:27 2015 From: aleksey.shipilev at oracle.com (Aleksey Shipilev) Date: Fri, 21 Aug 2015 19:30:27 +0300 Subject: RFR 8129547 (S): Excess entries in BootstrapMethods with the same (bsm, bsmKind, bsmStaticArgs), but different dynamicArgs In-Reply-To: <55D751E7.7010108@oracle.com> References: <55D1D4B6.6090303@oracle.com> <55D1E619.1070201@oracle.com> <55D1EC8B.7090400@oracle.com> <55D234FF.6000209@oracle.com> <55D250B7.5050108@oracle.com> <55D73F50.8000904@oracle.com> <55D746F6.3090301@oracle.com> <55D74905.3010102@oracle.com> <55D751E7.7010108@oracle.com> Message-ID: <55D75223.6010102@oracle.com> Yes, please! Thanks, -Aleksey On 08/21/2015 07:29 PM, Maurizio Cimadamore wrote: > I will put everything together, run tests and submit a review - is that ok? > > Maurizio > > On 21/08/15 16:51, Aleksey Shipilev wrote: >> I agree. Please sponsor? >> >> Not sure what pre-commit checks are needed to be run. I have only tested >> with that regression test, plus some other related ones for indy string >> concat. >> >> -Aleksey >> >> On 08/21/2015 06:42 PM, Maurizio Cimadamore wrote: >>> Cool - many thanks! >>> >>> I'd say we can go ahead with this. >>> >>> Maurizio >>> >>> On 21/08/15 16:10, Aleksey Shipilev wrote: >>>> Hey Maurizio, >>>> >>>> I have tried to slim down TestInvokeDynamic to make a regression test. >>>> It fails on current javac, and passes on a patched one: >>>> http://cr.openjdk.java.net/~shade/8129547/webrev.02/ >>>> >>>> Thanks, >>>> -Aleksey >>>> >>>> On 08/18/2015 12:23 AM, Maurizio Cimadamore wrote: >>>>> Whoops - that's what I meant to write, sorry; I'm glad you like the >>>>> overall scheme. I will cook up a test tomorrow - we do have one test >>>>> which attaches fake dynamic symbols to AST nodes, (using an annotation >>>>> processor) then invokes code generation and checks the resulting >>>>> bytecode [1]. I think one such test might be useful here. >>>>> >>>>> [1] - >>>>> http://hg.openjdk.java.net/jdk9/jdk9/langtools/file/tip/test/tools/javac/lambda/TestInvokeDynamic.java >>>>> >>>>> >>>>> >>>>> >>>>> Maurizio >>>>> >>>>> On 17/08/15 20:24, Aleksey Shipilev wrote: >>>>>> Hi Maurizio, >>>>>> >>>>>> Thanks for an idea! It almost works, but not quite: super.equals() >>>>>> from >>>>>> Method checks the type, so we need to guard super.*, as you did in >>>>>> hashCode(). We also need a proper subclass check for the keys alone, >>>>>> which means we might move equals() there, and make key a proper >>>>>> subclass >>>>>> to gain access to "other". >>>>>> >>>>>> In short, this version works: >>>>>> http://cr.openjdk.java.net/~shade/8129547/webrev.01/ >>>>>> >>>>>> Thanks, >>>>>> -Aleksey >>>>>> >>>>>> On 17.08.2015 17:15, Maurizio Cimadamore wrote: >>>>>>> Ok, I think I know what you meant now; DynamicMethod is used for two >>>>>>> different purposes: >>>>>>> >>>>>>> * for the NameAndType CP entry associated with an invokedynamic >>>>>>> instruction (pointed by the CONSTANT_InvokeDynamic entry); this bit >>>>>>> _requires_ dynamic info to be taken into account - as different >>>>>>> invoked >>>>>>> types need to map to different entries - even if their underlying >>>>>>> BSM >>>>>>> entry is the same. >>>>>>> >>>>>>> * as keys in the BootstrapMethod attribute; in this case you want >>>>>>> the >>>>>>> dynamic info to be gone, as all it's going to be stored in the >>>>>>> table is >>>>>>> a bsmKind + static args list. >>>>>>> >>>>>>> How about something like this: >>>>>>> >>>>>>> http://cr.openjdk.java.net/~mcimadamore/8129547/ >>>>>>> >>>>>>> Maurizio >>>>>>> >>>>>>> >>>>>>> >>>>>>> On 17/08/15 14:48, Maurizio Cimadamore wrote: >>>>>>>> Hi Alex, >>>>>>>> the only dfference I see between your patch and the current code is >>>>>>>> that the current code is comparing the invokedType, while yours is >>>>>>>> not >>>>>>>> - am I reading your patch correctly? >>>>>>>> >>>>>>>> If that's the case, wouldn't dropping the call to super.equals from >>>>>>>> Pool.DynamicMethod also resolve the issue? >>>>>>>> >>>>>>>> I'm, saying this because, from a design perspective, javac symbols >>>>>>>> usually don't care about uniqueness etc. - that's an extra value >>>>>>>> added >>>>>>>> when storing them into a constant pool. >>>>>>>> >>>>>>>> Maurizio >>>>>>>> >>>>>>>> On 17/08/15 13:33, Aleksey Shipilev wrote: >>>>>>>>> Hi, >>>>>>>>> >>>>>>>>> This issue gets into way with my current work: >>>>>>>>> https://bugs.openjdk.java.net/browse/JDK-8129547 >>>>>>>>> >>>>>>>>> There is a proof-of-concept patch: >>>>>>>>> http://cr.openjdk.java.net/~shade/8129547/webrev.00/ >>>>>>>>> >>>>>>>>> The crux of an issue seems to be the Method.equals() call in >>>>>>>>> DynamicMethod.equals(), that compares the type. The type of >>>>>>>>> DynamicMethod includes the DynamicMethodSymbol.type, that includes >>>>>>>>> dynamic args. It seems DynamicMethodSymbol is a better fit for >>>>>>>>> BootstrapMethod table key, since it includes BSM symbol and static >>>>>>>>> arguments only. >>>>>>>>> >>>>>>>>> I would be grateful if somebody from compiler team can help me out >>>>>>>>> with >>>>>>>>> this. Is this the fix above valid? Can you do it better? >>>>>>>>> >>>>>>>>> How would one write a regression test for it? My cursory grep >>>>>>>>> through >>>>>>>>> langtools tests does not yield a clear way to emit a >>>>>>>>> special-shaped >>>>>>>>> indy >>>>>>>>> for such a test. >>>>>>>>> >>>>>>>>> Thanks, >>>>>>>>> -Aleksey >>>>>>>>> >> > -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: OpenPGP digital signature URL: From maurizio.cimadamore at oracle.com Fri Aug 21 17:58:02 2015 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Fri, 21 Aug 2015 18:58:02 +0100 Subject: RFR JDK-8129547: Excess entries in BootstrapMethods with the same (bsm, bsmKind, bsmStaticArgs), but different dynamicArgs Message-ID: <55D766AA.3090109@oracle.com> Hello, This is a fix for: https://bugs.openjdk.java.net/browse/JDK-8129547 which has been discussed on this list recently. The problem is sometimes javac generates duplicate BSM entries in the bootstrap method attribute, due to the fact that the equals/hashing function for such entries takes into account the invokedType while it shouldn't. A webrev with the fix is here: http://cr.openjdk.java.net/~mcimadamore/8129547/ Feedback welcome. Cheers Maurizio From cushon at google.com Fri Aug 21 23:33:01 2015 From: cushon at google.com (Liam Miller-Cushon) Date: Fri, 21 Aug 2015 16:33:01 -0700 Subject: attributing files with syntax errors In-Reply-To: References: <55D67905.7010905@oracle.com> Message-ID: A couple of additions: Changing the default value of shouldStopPolicyIfError to ATTR isn't a good idea, because the policy was always being checked correctly between parsing and entering the trees. The bug I noticed only affects the transitive from enter to attr. I don't see a non-hacky way to preserve the existing default behaviour. Here's a better version of the patch that fixes the issue for all of the policies (not just byfile and bytodo), and changes attribute to use the same stop-on-error logic as flow: diff -r eaab8a16dcfb src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java Thu Aug 20 11:38:24 2015 -0700 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java Fri Aug 21 16:30:00 2015 -0700 @@ -860,7 +860,7 @@ case BY_FILE: { Queue>> q = todo.groupByFile(); - while (!q.isEmpty() && !shouldStop(CompileState.ATTR)) { + while (!q.isEmpty()) { generate(desugar(flow(attribute(q.remove())))); } } @@ -1198,7 +1198,7 @@ public Queue> attribute(Queue> envs) { ListBuffer> results = new ListBuffer<>(); while (!envs.isEmpty()) - results.append(attribute(envs.remove())); + attribute(envs.remove(), results); return stopIfError(CompileState.ATTR, results); } @@ -1206,9 +1206,24 @@ * Attribute a parse tree. * @return the attributed parse tree */ - public Env attribute(Env env) { - if (compileStates.isDone(env, CompileState.ATTR)) - return env; + public Queue> attribute(Env env) { + ListBuffer> results = new ListBuffer<>(); + attribute(env, results); + return stopIfError(CompileState.ATTR, results); + } + + /** + * Attribute a parse tree. + */ + protected void attribute(Env env, Queue> results) { + + if (compileStates.isDone(env, CompileState.ATTR)) { + results.add(env); + return; + } + + if (shouldStop(CompileState.ATTR)) + return; if (verboseCompilePolicy) printNote("[attribute " + env.enclClass.sym + "]"); @@ -1237,7 +1252,8 @@ log.useSource(prev); } - return env; + results.add(env); + return; } /** On Thu, Aug 20, 2015 at 6:27 PM, Liam Miller-Cushon wrote: > Thanks for taking a look. > > On Thu, Aug 20, 2015 at 6:04 PM, Jonathan Gibbons < > jonathan.gibbons at oracle.com> wrote: > >> Twiddling the CompilePolicy is an "internal" knob, controlled by a >> "hidden" (-XD) option. That being said, my primary concern about changing >> the bytodo policy is that it is the default policy, so changing it will >> potentially affect everyone, even those who don't know about the >> CompilePolicy. >> > > Understood. It's possible that showing errors from attr is actually better > for most people, since the extra information could be helpful when fixing > compilation errors. One way to minimize the impact would be to change the > default shouldStopPolicyIfError mode to attr at the same time the bug was > fixed, so the default behaviour was unchanged. > > >> And _that_ being said, the original intent of providing the CompilePolicy >> was to address bugs in which a file had multiple top level classes, and >> some could have classes generated before errors were detected in other >> classes in the same file. Hence the byfile policy. But for various >> reasons, byfile never became the default. I seem to recall it was at least >> in part due to memory usage, which is less of a concern today than it was >> back then. > > >> The other area where this might be relevant is annotation processing, >> where the original code was not so good back then at differentiating >> different types of errors, and so we wanted compilation to continue more >> often than we do now. Nowadays, javac has a better concept of "recoverable >> errors", and so javac is better at not proceeding unnecessarily. >> > > Interesting. The reason we came across this and were experimenting with > byfile is for error prone. It's occasionally useful to inspect an entire > compilation unit instead of individual top-level declarations, and with the > bytodo policy top-level declarations are lowered one at time, so by the > time everything in a compilation unit has gone through flow some things > have already been lowered. (I think the plugin api makes it harder to > observe that by associating events with top-level declarations, and > discouraging inspecting compilation units.) > > >> So I guess I'd be interested to see the patch, although to prevent >> unnecessary work up front, it may be worth posting the src/ patch first, >> with some info on just how many and which tests need fixing. The more >> tests that need fixup, the more carefully we should review the change in >> behavior. >> > > Here's the trivial fix I was testing, which just replicates the logic in > byfile for todo. I realized after doing this that the same issue affects > all of the other policies, so the check should probably be moved higher up. > > diff -r eaab8a16dcfb > src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java > --- > a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java > Thu Aug 20 11:38:24 2015 -0700 > +++ > b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java > Thu Aug 20 18:09:00 2015 -0700 > @@ -867,7 +867,7 @@ > break; > > case BY_TODO: > - while (!todo.isEmpty()) > + while (!todo.isEmpty() && !shouldStop(CompileState.ATTR)) > generate(desugar(flow(attribute(todo.remove())))); > break; > > I counted 37 test failures, excluding two that test compilation policies. > The list is attached. > -------------- next part -------------- An HTML attachment was scrubbed... URL: From bsrbnd at gmail.com Sat Aug 22 11:51:44 2015 From: bsrbnd at gmail.com (bsrbnd) Date: Sat, 22 Aug 2015 13:51:44 +0200 Subject: [PATCH] 8074570: Javac does not get membership right when it comes to erased supertypes In-Reply-To: <55D52612.20507@oracle.com> References: <55D52612.20507@oracle.com> Message-ID: I think you're right. Jls example 4.8-2 demonstrates clearly the behavior of javac: "The raw type RawMembers inherits iterator() from Collection, the erasure of Collection, which means that the return type of iterator() in RawMembers is Iterator." Nevertheless, without knowing all the compatibility reasons behind this, I think it could be meaningful to keep unrelated (to the raw type) used parameters and replace all (related or not) unused parameters with "Object" the same way it is already done for the classes and interfaces members of a raw type (and his super-classes/interfaces members). But, as you said, it will take time to improve this. Moreover, as written in jls 4.8, "The use of raw types is allowed only as a concession to compatibility of legacy code. [...] It is possible that future versions of Java programming language will disallow the use of raw types". Regards, bsrbnd 2015-08-20 2:57 GMT+02:00 Maurizio Cimadamore : > Hi, > I think javac is behaving according to the JLS - section 4.8 (raw types): > > "The superclasses (respectively, superinterfaces) of a raw type are the > erasures of the superclasses (superinterfaces) of any of the > parameterizations of the generic type. " > > This seems to imply that the supertype of Sub (raw) is just Sup; I agree > this is confusing and a lot of people trip over this - but that's what the > spec mandates. That said, we are aware of this and we'd like to improve over > this - but it will take a while to figure out a plausible compatibility > story. > > Maurizio > > > On 19/08/15 18:33, bsrbnd wrote: >> >> Hi, >> >> As explained in issue 8074570 the following code doesn't compile >> because javac looses all type parameters when it comes to an erased >> supertype: >> >> interface Sup { >> boolean m(X x); >> } >> >> interface Sub extends Sup { >> boolean m(String s); >> } >> >> class Test { >> void test() { >> Sub s = new Sub() { // new Sub compiles.. >> @Override >> public boolean m(String o) {return true;} >> }; >> } >> } >> >> In this example, when all type parameters are erased, interface "Sup" >> defines abstract method "boolean m(Object x)" which is not overriden >> in our anonymous class. >> If you give a type parameter to "Sub" (for example: new Sub() >> {...}), all compiles fine because type parameters are not erased. >> >> The problem occures in Types.memberType(Type, Symbol) when javac >> searches for an implementation of Sup.m(X x). >> The call to Types.asOuterSuper(Type, Symbol) erases type parameters. >> >> The following patch replaces undefined type parameters with Object >> parameters instead of erasing them in Types.supertype(Type) and >> Types.interfaces(Type). >> >> I'm not sure if this is very clean, but it seems that it corrects the >> problem. >> It is also possible that this fix is too global and could be made more >> locally to avoid side effects. >> >> 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 >> @@ -2211,6 +2211,23 @@ >> public List erasureRecursive(List ts) { >> return erasure.visit(ts, true); >> } >> + >> + private List erasureWithObjects(List ts, List >> formals) { >> + Type[] objectParams = new Type[formals.length()]; >> + for (int i=0; i> + objectParams[i] = syms.objectType; >> + } >> + List subt = subst(ts, formals, List.from(objectParams)); >> + return subt; >> + } >> + private Type erasureWithObjects(Type t, List formals) { >> + Type[] objectParams = new Type[formals.length()]; >> + for (int i=0; i> + objectParams[i] = syms.objectType; >> + } >> + Type subt = subst(t, formals, List.from(objectParams)); >> + return subt; >> + } >> // >> >> // > desc="makeIntersectionType"> >> @@ -2281,7 +2298,7 @@ >> List actuals = classBound(t).allparams(); >> List formals = t.tsym.type.allparams(); >> if (t.hasErasedSupertypes()) { >> - t.supertype_field = >> erasureRecursive(supertype); >> + t.supertype_field = >> erasureWithObjects(supertype, formals); >> } else if (formals.nonEmpty()) { >> t.supertype_field = subst(supertype, >> formals, actuals); >> } >> @@ -2362,7 +2379,7 @@ >> List actuals = t.allparams(); >> List formals = t.tsym.type.allparams(); >> if (t.hasErasedSupertypes()) { >> - t.interfaces_field = >> erasureRecursive(interfaces); >> + t.interfaces_field = >> erasureWithObjects(interfaces, formals); >> } else if (formals.nonEmpty()) { >> t.interfaces_field = subst(interfaces, >> formals, actuals); >> } >> >> >> Regards, >> >> bsrbnd > > From aleksey.shipilev at oracle.com Mon Aug 24 08:37:25 2015 From: aleksey.shipilev at oracle.com (Aleksey Shipilev) Date: Mon, 24 Aug 2015 11:37:25 +0300 Subject: RFR JDK-8129547: Excess entries in BootstrapMethods with the same (bsm, bsmKind, bsmStaticArgs), but different dynamicArgs In-Reply-To: <55D766AA.3090109@oracle.com> References: <55D766AA.3090109@oracle.com> Message-ID: <55DAD7C5.2090604@oracle.com> On 08/21/2015 08:58 PM, Maurizio Cimadamore wrote: > A webrev with the fix is here: > > http://cr.openjdk.java.net/~mcimadamore/8129547/ Thanks, Maurizio! The fix still looks good. -Aleksey -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: OpenPGP digital signature URL: From jan.lahoda at oracle.com Mon Aug 24 10:12:32 2015 From: jan.lahoda at oracle.com (Jan Lahoda) Date: Mon, 24 Aug 2015 12:12:32 +0200 Subject: RFR JDK-8129547: Excess entries in BootstrapMethods with the same (bsm, bsmKind, bsmStaticArgs), but different dynamicArgs In-Reply-To: <55DAD7C5.2090604@oracle.com> References: <55D766AA.3090109@oracle.com> <55DAD7C5.2090604@oracle.com> Message-ID: <55DAEE10.7040001@oracle.com> Looks OK to me. Jan On 24.8.2015 10:37, Aleksey Shipilev wrote: > On 08/21/2015 08:58 PM, Maurizio Cimadamore wrote: >> A webrev with the fix is here: >> >> http://cr.openjdk.java.net/~mcimadamore/8129547/ > > Thanks, Maurizio! The fix still looks good. > > -Aleksey > > From maurizio.cimadamore at oracle.com Mon Aug 24 12:15:43 2015 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Mon, 24 Aug 2015 13:15:43 +0100 Subject: RFR JDK-8129547: Excess entries in BootstrapMethods with the same (bsm, bsmKind, bsmStaticArgs), but different dynamicArgs In-Reply-To: <55DAEE10.7040001@oracle.com> References: <55D766AA.3090109@oracle.com> <55DAD7C5.2090604@oracle.com> <55DAEE10.7040001@oracle.com> Message-ID: <55DB0AEF.5020505@oracle.com> Pushed. Thanks Maurizio On 24/08/15 11:12, Jan Lahoda wrote: > Looks OK to me. > > Jan > > On 24.8.2015 10:37, Aleksey Shipilev wrote: >> On 08/21/2015 08:58 PM, Maurizio Cimadamore wrote: >>> A webrev with the fix is here: >>> >>> http://cr.openjdk.java.net/~mcimadamore/8129547/ >> >> Thanks, Maurizio! The fix still looks good. >> >> -Aleksey >> >> From maurizio.cimadamore at oracle.com Tue Aug 25 11:40:24 2015 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Tue, 25 Aug 2015 12:40:24 +0100 Subject: RFR JDK-8134329: TeeOpTest.java fails across platforms after fix for JDK-8129547 Message-ID: <55DC5428.60502@oracle.com> Hello, This is a fix for: https://bugs.openjdk.java.net/browse/JDK-8134329 which has been introduced by the recent fix for JDK-8129547. The problem is that the recent fix changed the hashCode/equals properties of a BSM key object; such properties used to be identical to those of the corresponding CONSTANT_InvokeDynamic_info entry, where dynamic arguments are also taken into account. The fix changed that to only consider static arguments for BSM key hashCode/equals computation. While this is the correct behavior, this led to an issue in ClassWriter.writePool, as the following code: poolbuf.appendByte(CONSTANT_InvokeDynamic); poolbuf.appendChar(bootstrapMethods.size() - 1); poolbuf.appendChar(pool.put(nameType(dynSym))); Makes the implicit assumption that, whenever a new CONSTANT_InvokeDynamic_info entry is being added, a new BSM entry will also be added (so that the index of the indy entry is set to point to the last element of the BSM array). Now that hashCode/equals for BSM keys is different than that of the corresponding CONSTANT_InvokeDynamic_info entry, there could be cases in which a new CONSTANT_InvokeDynamic_info is added, but no new BSM key is created (as an existing key can be reused). This happens for instance when the invokedynamic associated with the capture of two method references features same static arguments but different dynamic arguments (see test). A webrev with the fix is here: http://cr.openjdk.java.net/~mcimadamore/8134329/ Feedback welcome. Cheers Maurizio From aleksey.shipilev at oracle.com Tue Aug 25 13:37:22 2015 From: aleksey.shipilev at oracle.com (Aleksey Shipilev) Date: Tue, 25 Aug 2015 16:37:22 +0300 Subject: RFR JDK-8134329: TeeOpTest.java fails across platforms after fix for JDK-8129547 In-Reply-To: <55DC5428.60502@oracle.com> References: <55DC5428.60502@oracle.com> Message-ID: <55DC6F92.4030102@oracle.com> On 08/25/2015 02:40 PM, Maurizio Cimadamore wrote: > http://cr.openjdk.java.net/~mcimadamore/8134329/ > Feedback welcome. Thanks for taking care of this. Looks good to me! -Aleksey -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: OpenPGP digital signature URL: From sundararajan.athijegannathan at oracle.com Tue Aug 25 13:56:10 2015 From: sundararajan.athijegannathan at oracle.com (Sundararajan Athijegannathan) Date: Tue, 25 Aug 2015 19:26:10 +0530 Subject: RFR JDK-8134329: TeeOpTest.java fails across platforms after fix for JDK-8129547 In-Reply-To: <55DC5428.60502@oracle.com> References: <55DC5428.60502@oracle.com> Message-ID: <55DC73FA.6070105@oracle.com> Looks good to me. -Sundar On 8/25/2015 5:10 PM, Maurizio Cimadamore wrote: > Hello, > > This is a fix for: > > https://bugs.openjdk.java.net/browse/JDK-8134329 > > which has been introduced by the recent fix for JDK-8129547. > > The problem is that the recent fix changed the hashCode/equals > properties of a BSM key object; such properties used to be identical > to those of the corresponding CONSTANT_InvokeDynamic_info entry, where > dynamic arguments are also taken into account. The fix changed that to > only consider static arguments for BSM key hashCode/equals computation. > > While this is the correct behavior, this led to an issue in > ClassWriter.writePool, as the following code: > > poolbuf.appendByte(CONSTANT_InvokeDynamic); > poolbuf.appendChar(bootstrapMethods.size() - 1); > poolbuf.appendChar(pool.put(nameType(dynSym))); > > Makes the implicit assumption that, whenever a new > CONSTANT_InvokeDynamic_info entry is being added, a new BSM entry will > also be added (so that the index of the indy entry is set to point to > the last element of the BSM array). > > Now that hashCode/equals for BSM keys is different than that of the > corresponding CONSTANT_InvokeDynamic_info entry, there could be cases > in which a new CONSTANT_InvokeDynamic_info is added, but no new BSM > key is created (as an existing key can be reused). This happens for > instance when the invokedynamic associated with the capture of two > method references features same static arguments but different dynamic > arguments (see test). > > A webrev with the fix is here: > > http://cr.openjdk.java.net/~mcimadamore/8134329/ > > Feedback welcome. > > Cheers > Maurizio From maurizio.cimadamore at oracle.com Tue Aug 25 14:36:59 2015 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Tue, 25 Aug 2015 15:36:59 +0100 Subject: RFR JDK-8134329: TeeOpTest.java fails across platforms after fix for JDK-8129547 In-Reply-To: <55DC73FA.6070105@oracle.com> References: <55DC5428.60502@oracle.com> <55DC73FA.6070105@oracle.com> Message-ID: <55DC7D8B.3010205@oracle.com> Thanks! Pushed. Maurizio On 25/08/15 14:56, Sundararajan Athijegannathan wrote: > Looks good to me. > > -Sundar > > On 8/25/2015 5:10 PM, Maurizio Cimadamore wrote: >> Hello, >> >> This is a fix for: >> >> https://bugs.openjdk.java.net/browse/JDK-8134329 >> >> which has been introduced by the recent fix for JDK-8129547. >> >> The problem is that the recent fix changed the hashCode/equals >> properties of a BSM key object; such properties used to be identical >> to those of the corresponding CONSTANT_InvokeDynamic_info entry, >> where dynamic arguments are also taken into account. The fix changed >> that to only consider static arguments for BSM key hashCode/equals >> computation. >> >> While this is the correct behavior, this led to an issue in >> ClassWriter.writePool, as the following code: >> >> poolbuf.appendByte(CONSTANT_InvokeDynamic); >> poolbuf.appendChar(bootstrapMethods.size() - 1); >> poolbuf.appendChar(pool.put(nameType(dynSym))); >> >> Makes the implicit assumption that, whenever a new >> CONSTANT_InvokeDynamic_info entry is being added, a new BSM entry >> will also be added (so that the index of the indy entry is set to >> point to the last element of the BSM array). >> >> Now that hashCode/equals for BSM keys is different than that of the >> corresponding CONSTANT_InvokeDynamic_info entry, there could be cases >> in which a new CONSTANT_InvokeDynamic_info is added, but no new BSM >> key is created (as an existing key can be reused). This happens for >> instance when the invokedynamic associated with the capture of two >> method references features same static arguments but different >> dynamic arguments (see test). >> >> A webrev with the fix is here: >> >> http://cr.openjdk.java.net/~mcimadamore/8134329/ >> >> Feedback welcome. >> >> Cheers >> Maurizio > From jonathan.gibbons at oracle.com Tue Aug 25 23:42:37 2015 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Tue, 25 Aug 2015 16:42:37 -0700 Subject: RFR: 8059976 Convert JavacFileManager to use java.nio.file internally In-Reply-To: <55A04629.4050401@oracle.com> References: <55A03ED4.6040201@oracle.com> <55A03FD7.7020604@oracle.com> <55A04629.4050401@oracle.com> Message-ID: <55DCFD6D.7010401@oracle.com> I've posted a fix to convert JavacFileManager to use java.nio.file.Path internally for accessing jar files, instead of using javac's old internal code to access zip files. There's more cleanup that can be done eventually, such as merging or all of PathFileObject, RegularFileObject and BaseFileObject, but the goal for this round of work has been leave existing behavior unchanged as much as possible. Bug: https://bugs.openjdk.java.net/browse/JDK-8059976 Webrev: http://cr.openjdk.java.net/~jjg/8059976/webrev.00/ I'd be particularly interested in feedback from folk developing custom file managers based on top of nio FileSystems. -- Jon On 07/10/2015 03:24 PM, Jonathan Gibbons wrote: > Now tracked as https://bugs.openjdk.java.net/browse/JDK-8130944 > > -- Jon > > On 07/10/2015 02:57 PM, Jonathan Gibbons wrote: >> FWIW, the scary big deal about fixing 8059976 is that clients will >> need to be more careful to ensure that file managers are closed after >> use, so that the file manager can close any file systems that have >> been opened internally (primarily meaning, jar file systems). Right >> now, with the old fashioned support for jar files, that is not the case. >> >> -- Jon >> >> >> On 07/10/2015 02:53 PM, Jonathan Gibbons wrote: >>> Liam, >>> >>> Thanks for the feedback. Obviously the intent is that you should be >>> able to use Paths that don't rely on the use of the default >>> filesystem, so this needs to be fixed. >>> >>> -- Jon >>> >>> >>> On 07/10/2015 02:24 PM, Liam Miller-Cushon wrote: >>>> I've been using JavacPathFileManager and an in-memory filesystem >>>> (github.com/google/jimfs ) for >>>> testing some code that uses the compiler API. >>>> >>>> I noticed that JDK-8076420 deleted JavacPathFileManager and moved >>>> the Path-based methods into the regular JavacFileManager. I think >>>> that's great, but I'm having trouble using the Path-based API in >>>> JavacFileManager. The implementation uses Path#toFile(), which only >>>> works with the default filesystem. >>>> >>>> Is this a known issue? JDK-8059976 looks like it would probably fix it. >>>> >>>> Repro: >>>> >>>> === >>>> import com.google.common.jimfs.Configuration; >>>> import com.google.common.jimfs.Jimfs; >>>> >>>> import static java.nio.charset.StandardCharsets.UTF_8; >>>> >>>> import com.sun.tools.javac.file.JavacFileManager; >>>> import com.sun.tools.javac.util.Context; >>>> import com.sun.tools.javac.util.Log; >>>> >>>> import java.nio.file.FileSystem; >>>> import java.io.OutputStreamWriter; >>>> import java.io.PrintWriter; >>>> import java.io.IOException; >>>> import java.nio.file.Files; >>>> import java.nio.file.Path; >>>> import java.util.Arrays; >>>> import java.util.Locale; >>>> >>>> import javax.tools.StandardLocation; >>>> >>>> public class Test { >>>> public static void main(String[] args) throws IOException { >>>> FileSystem fs = Jimfs.newFileSystem(Configuration.unix()); >>>> >>>> Path foo = fs.getPath("/foo"); >>>> Files.createDirectory(foo); >>>> Path hello = foo.resolve("hello.jar"); >>>> Files.write(hello, Arrays.asList("hello world"), UTF_8); >>>> >>>> Context context = new Context(); >>>> context.put(Log.outKey, new PrintWriter(new >>>> OutputStreamWriter(System.err, UTF_8), true)); >>>> JavacFileManager jfm = new JavacFileManager(context, true, UTF_8); >>>> >>>> jfm.setLocationFromPaths(StandardLocation.CLASS_PATH, >>>> Arrays.asList(hello)); >>>> } >>>> } >>>> === >>>> >>>> $ javac -cp jimfs.jar:javac.jar Test.java >>>> $ java -cp jimfs.jar:javac.jar:guava.jar:. Test >>>> Exception in thread "main" java.lang.UnsupportedOperationException >>>> at com.google.common.jimfs.JimfsPath.toFile(JimfsPath.java:397) >>>> at >>>> com.sun.tools.javac.file.FSInfo.getJarClassPath(FSInfo.java:69) >>>> at >>>> com.sun.tools.javac.file.Locations$SearchPath.addJarClassPath(Locations.java:321) >>>> at >>>> com.sun.tools.javac.file.Locations$SearchPath.addFile(Locations.java:311) >>>> at >>>> com.sun.tools.javac.file.Locations$SearchPath.addFiles(Locations.java:250) >>>> at >>>> com.sun.tools.javac.file.Locations$SearchPath.addFiles(Locations.java:257) >>>> at >>>> com.sun.tools.javac.file.Locations$SimpleLocationHandler.setLocation(Locations.java:463) >>>> at >>>> com.sun.tools.javac.file.Locations.setLocation(Locations.java:783) >>>> at >>>> com.sun.tools.javac.file.JavacFileManager.setLocationFromPaths(JavacFileManager.java:914) >>>> at Test.main(Test.java:34) >>> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From alex.buckley at oracle.com Wed Aug 26 19:51:58 2015 From: alex.buckley at oracle.com (Alex Buckley) Date: Wed, 26 Aug 2015 12:51:58 -0700 Subject: U60 change makes annotations visible in synthesized methods, causes CDI to see lambdas as observer methods In-Reply-To: References: Message-ID: <55DE18DE.2050908@oracle.com> Jan, The mail below was sent to lambda-dev [1] and subsequently core-libs-dev [2]. While CDI should be ignoring synthetic methods, there is still the question of why the synthetic method representing the d->... lambda has a RuntimeVisibleParameterAnnotations attribute. It looks like the @Observes annotation from the first processBean parameter has mysteriously made its way to the first lambda$processBean$4 parameter. I'm wondering if this is related to your 8u60 backport of JDK-8037546 ? Alex [1] http://mail.openjdk.java.net/pipermail/lambda-dev/2015-August/012146.html [2] http://mail.openjdk.java.net/pipermail/core-libs-dev/2015-August/034990.html > *From: *arjan tijms > > *Subject: **U60 change makes annotations visible in synthesized > methods, causes CDI to see lambdas as observer methods* > *Date: *August 26, 2015 at 10:04:22 AM EDT > *To: *lambda-dev at openjdk.java.net > > Hi, > > I'm with the JSF EG/Mojarra team and we're seeing what looks like a > problematic regression in JDK8 u60. > > In a CDI extension we have the following observer method: > > public void processBean(@Observes ProcessBean event, > BeanManager beanManager) { > getAnnotation(beanManager, event.getAnnotated(), > FacesDataModel.class) > .ifPresent(d -> > forClassToDataModelClass.put( > d.forClass(), > (Class>) > event.getBean().getBeanClass() > ) > ); > } > > With u45 and below this will generate the following (decompiled the > class with javap -v -p -s -c) > > private void > lambda$processBean$4(javax.enterprise.inject.spi.ProcessBean, > javax.faces.model.FacesDataModel); > descriptor: > (Ljavax/enterprise/inject/spi/ProcessBean;Ljavax/faces/model/FacesDataModel;)V > flags: ACC_PRIVATE, ACC_SYNTHETIC > Code: > stack=3, locals=3, args_size=3 > 0: aload_0 > 1: getfield #4 // Field > forClassToDataModelClass:Ljava/util/Map; > 4: aload_2 > 5: invokeinterface #57, 1 // InterfaceMethod > javax/faces/model/FacesDataModel.forClass:()Ljava/lang/Class; > 10: aload_1 > 11: invokeinterface #58, 1 // InterfaceMethod > javax/enterprise/inject/spi/ProcessBean.getBean:()Ljavax/enterprise/inject/spi/Bean; > 16: invokeinterface #59, 1 // InterfaceMethod > javax/enterprise/inject/spi/Bean.getBeanClass:()Ljava/lang/Class; > 21: invokeinterface #55, 3 // InterfaceMethod > java/util/Map.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; > 26: checkcast #45 // class java/lang/Class > 29: pop > 30: return > LineNumberTable: > line 110: 0 > line 111: 5 > line 112: 11 > line 110: 21 > LocalVariableTable: > Start Length Slot Name Signature > 0 31 0 this Lcom/sun/faces/cdi/CdiExtension; > 0 31 2 d Ljavax/faces/model/FacesDataModel; > > > U60 however generates the following: > > private void > lambda$processBean$4(javax.enterprise.inject.spi.ProcessBean, > javax.faces.model.FacesDataModel); > descriptor: > (Ljavax/enterprise/inject/spi/ProcessBean;Ljavax/faces/model/FacesDataModel;)V > flags: ACC_PRIVATE, ACC_SYNTHETIC > Code: > stack=3, locals=3, args_size=3 > 0: aload_0 > 1: getfield #4 // Field > forClassToDataModelClass:Ljava/util/Map; > 4: aload_2 > 5: invokeinterface #57, 1 // InterfaceMethod > javax/faces/model/FacesDataModel.forClass:()Ljava/lang/Class; > 10: aload_1 > 11: invokeinterface #58, 1 // InterfaceMethod > javax/enterprise/inject/spi/ProcessBean.getBean:()Ljavax/enterprise/inject/spi/Bean; > 16: invokeinterface #59, 1 // InterfaceMethod > javax/enterprise/inject/spi/Bean.getBeanClass:()Ljava/lang/Class; > 21: invokeinterface #55, 3 // InterfaceMethod > java/util/Map.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; > 26: checkcast #45 // class java/lang/Class > 29: pop > 30: return > LineNumberTable: > line 110: 0 > line 111: 5 > line 112: 11 > line 110: 21 > LocalVariableTable: > Start Length Slot Name Signature > 0 31 0 this Lcom/sun/faces/cdi/CdiExtension; > 0 31 1 event > Ljavax/enterprise/inject/spi/ProcessBean; > 0 31 2 d Ljavax/faces/model/FacesDataModel; > RuntimeVisibleParameterAnnotations: > parameter 0: > 0: #79() > parameter 1: > > The difference is that the parameter annotation is made visible for > this synthesized method. The result is that CDI subsequently scans > this class and sees the synthesized method for the lambda as an > observer method, which is of course not the intention. In this > particular case it will result in a definition error: > > "Error occurred during deployment: Exception while loading the app : > > CDI definition failure: > > WELD-000409: Observer method for container lifecycle event > [[BackedAnnotatedMethod] > > private com.sun.faces.cdi.CdiExtension.lambda$processBean$4(@Observes > ProcessBean, FacesDataModel)] can only inject BeanManager.." > > I think that if the synthesized method happened to be a correct > observer method, e.g. for a no-parameter lambda or one that happens to > have the BeanManager as its first and only parameter, then CDI would > silently start to call this method in response to events, which too is > highly undesirable. > > Kind regards, > Arjan Tijms > From georgiy.rakov at oracle.com Fri Aug 28 13:02:43 2015 From: georgiy.rakov at oracle.com (Georgiy Rakov) Date: Fri, 28 Aug 2015 16:02:43 +0300 Subject: Non generic constructor thrown type (class type variable) is not erased despite of unchecked conversion Message-ID: <55E05BF3.2030903@oracle.com> Hello, let's consider following example. class MyException extends Exception {}class MyDerivedException extends MyException {}class MyType {MyType(T t) {}}public class Test31 {public static void test() {try {MyDerivedException e1 = new MyDerivedException();Foo foo = new Foo(e1, new MyType(""));} catch (MyDerivedException e2) {}}}class Foo {public Foo(E1 e, MyType a) throws E1 {throw e;}} It compiles successfully on JDK9b78. Now let's consider reasoning presented below. 1. According to following assertion, 15.12.2 is used in order to determine the constructor thrown types: ***If C is not an anonymous class,*** let T be the type denoted by C followed by any class type arguments in the expression. The process specified in ?15.12.2, modified to handle constructors, is used to select one of the constructors of T and /_*determine its throws clause*_/ [jls-15.9.3-120-B.1 ] 2. According to my understanding the types in throws clause are determined in the last subsection of 15.12.2, that is in 15.12.2.6, which states: If the chosen method is not generic, then [jls-15.12.2.6-100-C ]: If /_*unchecked conversion*_/ was necessary for the method to be applicable, the parameter types of the invocation type are the parameter types of the method's type, and the return type and /_*thrown types*_/ are given by the erasures of the return type and thrown types of the method's type [jls-15.12.2.6-100-C-A ]. 3. So unchecked conversion is necessary in order for the constructor to be applicable because expression 'new MyType("")' of a raw type is passed to parameterized parameter 'MyType a'. Could you please tell if I understand correctly that JLS implies that when erasing constructor thrown types, the actual type which is erased is not E1 but E1 with following substitution applied [E1 := MyDerivedException]. According to my understanding JLS doesn't specify this explicitly, but as I see it such clarification could be useful. Could you please also tell if you think it's worth filing P4 issue about this. Thank you, Gosha. -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- class MyException extends Exception {} class MyDerivedException extends MyException {} class MyType { MyType(T t) {} } public class Test31 { public static void test() { try { MyDerivedException e1 = new MyDerivedException(); Foo foo = new Foo(e1, new MyType("")); } catch (MyDerivedException e2) { } } } class Foo { public Foo(E1 e, MyType a) throws E1 { throw e; } } From georgiy.rakov at oracle.com Fri Aug 28 15:33:38 2015 From: georgiy.rakov at oracle.com (Georgiy Rakov) Date: Fri, 28 Aug 2015 18:33:38 +0300 Subject: Generic constructor thrown type (constructor type variable) is not erased despite of unchecked conversion Message-ID: <55E07F52.8030904@oracle.com> Hello, let's consider following example. class MyExceptionextends Exception {} class MyDerivedExceptionextends MyException {} class MyType { MyType(T t) {} } public class Test32 { public static void test() { try { MyDerivedException e1 =new MyDerivedException(); Foo foo =new Foo(e1,new MyType("")); }catch (MyDerivedException e2) { } } } class Foo { public Foo(E1 e, MyType a)throws E1 { throw e; } } It compiles successfully on JDK9b78. Now let's consider reasoning presented below. 1. According to following assertion, 15.12.2 is used in order to determine the constructor thrown types: ***If C is not an anonymous class,*** let T be the type denoted by C followed by any class type arguments in the expression. The process specified in ?15.12.2, modified to handle constructors, is used to select one of the constructors of T and /_*determine its throws clause*_/. 2. According to my understanding the types in throws clause are determined in the last subsection of 15.12.2, that is in 15.12.2.6, which states: If the chosen method is generic and the method invocation does not provide explicit type arguments, the invocation type is inferred as specified in ?18.5.2. 3. 18.5.2 contains following assertion: If unchecked conversion was necessary for the method to be applicable during constraint set reduction in ?18.5.1, then the parameter types of the invocation type of m are obtained by applying a' to the parameter types of m's type, and the return type and thrown types of the invocation type of m are given by the erasure of the return type and thrown types of m's type. (jls-18.5.2-100-F.1-A) and 18.2.2. contains following assertions: A constraint formula of the form ?S ? T? is reduced as follows: (jls-18.2.2-100) Otherwise, if Tis a parameterized type of the form G|<|T_1 , ..., T_n |>|, and there exists no type of the form G|<|...|>|that is a supertype of S, but the raw type Gis a supertype of S, then the constraint reduces to /true/. (jls-18.2.2-100-D) The fourth and fifth cases are implicit uses of unchecked conversion (?5.1.9). These, along with any use of unchecked conversion in the first case, may result in compile-time unchecked warnings, and may influence a method's invocation type (?15.12.2.6). (jls-18.2.2-110) 3.1. During reduction constraint [new MyType("") -> MyType] is reduced to [MyType -> MyType]. 3.2. [MyType -> MyType] is reduced to true according to jls-18.2.2-100-D. 3.3. Thus according to jls-18.2.2-110 step 3.2 is considered as applying unchecked conversion. 3.4. Hence according to jls-18.5.2-100-F.1-Athe constructor exception type should be erased that is E1 should be erased to MyException which should have caused compilation failure, but compilation succeeds. 3.5. So if I understand correctly javac behaves as if jls-18.5.2-100-F.1-A specified that substitution a' is applied to m's thrown type first, and only after that ctorthrown type is erased.This looks like a spec issue, that is spec should have specified something like: "and the return type and thrown types of the invocation type of m are given by the erasure of the return type and thrown types of m2 where m2 is the result of applying a' to m's type" (I guess the same is true for the return type). Could you please tell if you agree that this is really a spec issue. Thank you, Georgiy. -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- class MyException extends Exception {} class MyDerivedException extends MyException {} class MyType { MyType(T t) {} } public class Test32 { public static void test() { try { MyDerivedException e1 = new MyDerivedException(); Foo foo = new Foo(e1, new MyType("")); } catch (MyDerivedException e2) { } } } class Foo { public Foo(E1 e, MyType a) throws E1 { throw e; } } From aleksey.shipilev at oracle.com Fri Aug 28 22:30:09 2015 From: aleksey.shipilev at oracle.com (Aleksey Shipilev) Date: Sat, 29 Aug 2015 01:30:09 +0300 Subject: Indify String Concat progress Message-ID: <55E0E0F1.4090907@oracle.com> Hi, I have finally found time to further hack on this: https://bugs.openjdk.java.net/browse/JDK-8085796 Also, redone experiments and rewritten the experimental notes: http://cr.openjdk.java.net/~shade/8085796/notes.txt Notable improvements: * The implementation was moved to Sandbox. Build instructions are inline in JEP itself. It builds almost like a usual OpenJDK now. If you face trouble building it, or experience failing tests, please contact me privately. * Renamed the strategies to more sensible names, see StringConcatFactory.Strategy enum. * javac now accepts -XstringConcat:{inline,indy,indyStatic}: - "inline" is the current desugaring scheme; - "indy" is blindly calling the BSM with all arguments collected by javac; - "indyStatic" is collecting special arguments (e.g. constants) and passing them once to BSM. This is something that Remi and Peter suggested earlier as an interesting option to try. * Added a large stress test that kinked out multiple bugs from the strategy implementations. There were no bugs in the javac implementation, which is good news itself. * The indy callsite for "indyStatic" indeed looks better in bytecode now (see experimental notes, "Footprint considerations / Bytecode shapes"), especially when there are lots of String constants. However, I found that it does not improve the performance much -- it would seem JIT compilers are already good at optimizing these cases. So, my hunch is that complicating the implementation and bytecode protocol might not worth it? Maybe there are cases which I am overlooking? You are very welcome to build the current implementation and play with it. * Tried to mix this prototype with Compact Strings prototype: http://openjdk.java.net/jeps/254 Most strategies improve a lot from that change, because the footprint is even better. Some strategies, like Peter's MH_INLINE_SIZED_EXACT assume a particular String shape, and we would need to tune it after the Compact Strings land. But the good news, it would not require any further changes in javac (d'uh!). Comments, suggestions, etc. are welcome. I am contemplating to "submit" the JEP early next week, pending no blockers. Cheers, and have a good weekend. Thanks, -Aleksey -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: OpenPGP digital signature URL: From bsrbnd at gmail.com Mon Aug 31 13:40:55 2015 From: bsrbnd at gmail.com (bsrbnd) Date: Mon, 31 Aug 2015 15:40:55 +0200 Subject: [PATCH] 8133135: NPE on anonymous class defined by qualified instance creation expression with diamond Message-ID: Hi, As explained in issue 8133135, the following code produces a null pointer exception because the symbol of the anonymous class is not set during the attribute phase: class List {} class ClassOut { class ClassIn { public ClassIn() {}} } public class TestBug { public static List m(List list, T item) {return list;} public static void main(String[] args) { m(new List>(), new ClassOut().new ClassIn<>(){}); } } Method Attr.visitAnonymousClassDefinition() doesn't perform well type inference with diamond. Recurcivity condition on tree.clazz.type seems to be wrong because it never changes... instead, it should be made on clazz.type (or clazztype) to go deeper on the type resolution. The following patch shows a possible solution, I think (to be checked by someone who knows the code better than me...): diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java @@ -2173,7 +2173,7 @@ final boolean isDiamond = TreeInfo.isDiamond(tree); if (isDiamond && ((tree.constructorType != null && inferenceContext.free(tree.constructorType)) - || (tree.clazz.type != null && inferenceContext.free(tree.clazz.type)))) { + || (clazz.type != null && inferenceContext.free(clazz.type)))) { final ResultInfo resultInfoForClassDefinition = this.resultInfo; inferenceContext.addFreeTypeListener(List.of(tree.constructorType, tree.clazz.type), instantiatedContext -> { Regards, bsrbnd From maurizio.cimadamore at oracle.com Mon Aug 31 14:32:32 2015 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Mon, 31 Aug 2015 15:32:32 +0100 Subject: [PATCH] 8133135: NPE on anonymous class defined by qualified instance creation expression with diamond In-Reply-To: References: Message-ID: <55E46580.8070705@oracle.com> Thanks, I'll take a look. Maurizio On 31/08/15 14:40, bsrbnd wrote: > Hi, > > As explained in issue 8133135, the following code produces a null > pointer exception because the symbol of the anonymous class is not set > during the attribute phase: > > class List {} > > class ClassOut { > class ClassIn { public ClassIn() {}} > } > > public class TestBug { > public static List m(List list, T item) {return list;} > > > public static void main(String[] args) { > m(new List>(), new ClassOut().new > ClassIn<>(){}); > } > } > > Method Attr.visitAnonymousClassDefinition() doesn't perform well type > inference with diamond. Recurcivity condition on tree.clazz.type seems > to be wrong because it never changes... instead, it should be made on > clazz.type (or clazztype) to go deeper on the type resolution. > > The following patch shows a possible solution, I think (to be checked > by someone who knows the code better than me...): > > diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java > b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java > --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java > +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java > @@ -2173,7 +2173,7 @@ > final boolean isDiamond = TreeInfo.isDiamond(tree); > if (isDiamond > && ((tree.constructorType != null && > inferenceContext.free(tree.constructorType)) > - || (tree.clazz.type != null && > inferenceContext.free(tree.clazz.type)))) { > + || (clazz.type != null && > inferenceContext.free(clazz.type)))) { > final ResultInfo resultInfoForClassDefinition = > this.resultInfo; > > inferenceContext.addFreeTypeListener(List.of(tree.constructorType, > tree.clazz.type), > instantiatedContext -> { > > Regards, > > bsrbnd