Hi all, bug https://bugs.openjdk.java.net/browse/JDK-8054213
I have reworked previous patch to conform with JLS 13.1 paragraph 1 and also JVMS 4.2.1. For now in case of parametrized types inner type name consists of normal binary name of immediately enclosing type, followed by $, followed by simple name of the member type. Patch with changes attached. I am looking for reviews and for sponsor to push this one. Thanks, Sergey. 2016-03-12 18:41 GMT+03:00 Sergey Ustimenko <merke...@gmail.com>: > Hi all, > > Please review this patch. I'm also looking for sponsor for this one. > > The unexpected duplication of owner type was produced by Method.toString() > for static > classes and interfaces. Problem is fixed by slightly changing the way of > obtaining > simple name of static nested type and concatenating it with owner type. > > > diff --git > a/src/java.base/share/classes/sun/reflect/generics/reflectiveObjects/ParameterizedTypeImpl.java > b/src/java.base/share/classes/sun/reflect/generics/reflectiveObjects/ParameterizedTypeImpl.java > --- > a/src/java.base/share/classes/sun/reflect/generics/reflectiveObjects/ParameterizedTypeImpl.java > +++ > b/src/java.base/share/classes/sun/reflect/generics/reflectiveObjects/ParameterizedTypeImpl.java > @@ -212,15 +212,14 @@ > else > sb.append(ownerType.toString()); > > - sb.append("."); > - > - if (ownerType instanceof ParameterizedTypeImpl) { > + if (ownerType instanceof ParameterizedTypeImpl) > // Find simple name of nested type by removing the > // shared prefix with owner. > - sb.append(rawType.getName().replace( > ((ParameterizedTypeImpl)ownerType).rawType.getName() + "$", > - "")); > - } else > - sb.append(rawType.getName()); > + sb.append(".").append( > + > > rawType.getName().replace(((ParameterizedTypeImpl)ownerType).rawType.getName() > + "$", "") > + ); > + else > + sb.append("$").append(rawType.getSimpleName()); > } else > sb.append(rawType.getName()); > > diff --git a/test/java/lang/reflect/Method/TestReturnTypeDuplication.java > b/test/java/lang/reflect/Method/TestReturnTypeDuplication.java > new file mode 100644 > --- /dev/null > +++ b/test/java/lang/reflect/Method/TestReturnTypeDuplication.java > @@ -0,0 +1,72 @@ > +/* > + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. > + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. > + * > + * This code is free software; you can redistribute it and/or modify it > + * under the terms of the GNU General Public License version 2 only, as > + * published by the Free Software Foundation. > + * > + * This code is distributed in the hope that it will be useful, but > WITHOUT > + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or > + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License > + * version 2 for more details (a copy is included in the LICENSE file that > + * accompanied this code). > + * > + * You should have received a copy of the GNU General Public License > version > + * 2 along with this work; if not, write to the Free Software Foundation, > + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. > + * > + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA > + * or visit www.oracle.com if you need additional information or have any > + * questions. > + */ > + > +/* > + * @test > + * @bug 8054213 > + * @summary Check that Type.toString() generates valid > + * output for static classes and interfaces > + * @author Sergey Ustimenko > + */ > +public class TestReturnTypeDuplication { > + > + private static final String[] SIGNATURES = { > + "TestReturnTypeDuplication$Static", > + > "TestReturnTypeDuplication$StaticParametrised<java.lang.String>", > + "TestReturnTypeDuplication$Interface", > + > "TestReturnTypeDuplication$InterfaceParametrised<java.lang.String>" > + }; > + > + > + public static void main(String[] args) throws Exception { > + boolean passed = > SIGNATURES[0].equals(getFooGenericReturnType("foo0")) && > + SIGNATURES[1].equals(getFooGenericReturnType("foo1")) && > + SIGNATURES[2].equals(getFooGenericReturnType("foo2")) && > + SIGNATURES[3].equals(getFooGenericReturnType("foo3")); > + > + if(!passed) { > + throw new RuntimeException("Generated type names are > invalid!"); > + } > + } > + > + private static String getFooGenericReturnType(String foo) throws > Exception { > + return > TestReturnTypeDuplication.class.getMethod(foo).getGenericReturnType().getTypeName(); > + } > + > + static class Static {} > + > + static class StaticParametrised<T> {} > + > + interface Interface {} > + > + interface InterfaceParametrised<T> {} > + > + public TestReturnTypeDuplication.Static foo0(){return null;} > + > + public TestReturnTypeDuplication.StaticParametrised<String> > foo1(){return null;} > + > + public TestReturnTypeDuplication.Interface foo2(){return null;} > + > + public TestReturnTypeDuplication.InterfaceParametrised<String> > foo3(){return null;} > + > +} >
diff --git a/src/java.base/share/classes/sun/reflect/generics/reflectiveObjects/ParameterizedTypeImpl.java b/src/java.base/share/classes/sun/reflect/generics/reflectiveObjects/ParameterizedTypeImpl.java --- a/src/java.base/share/classes/sun/reflect/generics/reflectiveObjects/ParameterizedTypeImpl.java +++ b/src/java.base/share/classes/sun/reflect/generics/reflectiveObjects/ParameterizedTypeImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,10 +25,7 @@ package sun.reflect.generics.reflectiveObjects; -import sun.reflect.generics.tree.FieldTypeSignature; - import java.lang.reflect.MalformedParameterizedTypeException; -import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; @@ -212,15 +209,16 @@ else sb.append(ownerType.toString()); - sb.append("."); + sb.append("$"); - if (ownerType instanceof ParameterizedTypeImpl) { + if (ownerType instanceof ParameterizedTypeImpl) // Find simple name of nested type by removing the // shared prefix with owner. - sb.append(rawType.getName().replace( ((ParameterizedTypeImpl)ownerType).rawType.getName() + "$", - "")); - } else - sb.append(rawType.getName()); + sb.append( + rawType.getName().replace(((ParameterizedTypeImpl) ownerType).rawType.getName() + "$", "") + ); + else + sb.append(rawType.getSimpleName()); } else sb.append(rawType.getName()); diff --git a/test/java/lang/reflect/Method/TestReturnTypeDuplication.java b/test/java/lang/reflect/Method/TestReturnTypeDuplication.java new file mode 100644 --- /dev/null +++ b/test/java/lang/reflect/Method/TestReturnTypeDuplication.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8054213 + * @summary Check that Type.toString() generates valid + * output for static classes and interfaces + * @author Sergey Ustimenko + */ +public class TestReturnTypeDuplication<F> { + + private static final String[] SIGNATURES = { + "TestReturnTypeDuplication$Static$A", + "TestReturnTypeDuplication$StaticParametrised<java.lang.String>$A", + "TestReturnTypeDuplication$Interface", + "TestReturnTypeDuplication$InterfaceParametrised<java.lang.String>", + "TestReturnTypeDuplication<java.lang.String>$Inner$A", + "TestReturnTypeDuplication<java.lang.String>$InnerParametrised<java.lang.String>$A" + }; + + + public static void main(String[] args) throws Exception { + check(SIGNATURES[0], getFooGenericReturnType("foo0")); + check(SIGNATURES[1], getFooGenericReturnType("foo1")); + check(SIGNATURES[2], getFooGenericReturnType("foo2")); + check(SIGNATURES[3], getFooGenericReturnType("foo3")); + check(SIGNATURES[4], getFooGenericReturnType("foo4")); + check(SIGNATURES[5], getFooGenericReturnType("foo5")); + } + + private static void check(String expected, String actual) { + if (!expected.equals(actual)) { + throw new RuntimeException(String.format("TypeName invalid! Expected {%s}, got {%s}", expected, actual)); + } + } + + private static String getFooGenericReturnType(String foo) throws Exception { + return TestReturnTypeDuplication.class.getMethod(foo).getGenericReturnType().getTypeName(); + } + + class Inner {class A{}} + + class InnerParametrised<T> {class A{}} + + static class Static {class A{}} + + static class StaticParametrised<T> {class A{}} + + interface Interface {} + + interface InterfaceParametrised<T> {} + + public TestReturnTypeDuplication.Static.A foo0(){return null;} + + public TestReturnTypeDuplication.StaticParametrised<String>.A foo1(){return null;} + + public TestReturnTypeDuplication.Interface foo2(){return null;} + + public TestReturnTypeDuplication.InterfaceParametrised<String> foo3(){return null;} + + public TestReturnTypeDuplication<String>.Inner.A foo4(){return null;} + + public TestReturnTypeDuplication<String>.InnerParametrised<String>.A foo5(){return null;} + +}