# HG changeset patch # User mcimadamore # Date 1469187486 -3600 # Node ID d290bef927c4b61f5dc001592fbbae4465540bdc # Parent 74b7aea686d8cff3ab216842ec37fd5030b51c7a 8161985: Spurious override of Object.getClass leads to NPE Summary: Attr.adjustMethodReturnType() tweaks return types w/o checking what method is being patched Reviewed-by: vromero diff -r 74b7aea686d8 -r d290bef927c4 langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Thu Jul 21 07:43:17 2016 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Fri Jul 22 12:38:06 2016 +0100 @@ -1900,7 +1900,8 @@ Type qualifier = (tree.meth.hasTag(SELECT)) ? ((JCFieldAccess) tree.meth).selected.type : env.enclClass.sym.type; - restype = adjustMethodReturnType(qualifier, methName, argtypes, restype); + Symbol msym = TreeInfo.symbol(tree.meth); + restype = adjustMethodReturnType(msym, qualifier, methName, argtypes, restype); chk.checkRefTypes(tree.typeargs, typeargtypes); @@ -1912,19 +1913,25 @@ chk.validate(tree.typeargs, localEnv); } //where - Type adjustMethodReturnType(Type qualifierType, Name methodName, List argtypes, Type restype) { - if (methodName == names.clone && types.isArray(qualifierType)) { + Type adjustMethodReturnType(Symbol msym, Type qualifierType, Name methodName, List argtypes, Type restype) { + if (msym != null && + msym.owner == syms.objectType.tsym && + methodName == names.getClass && + argtypes.isEmpty()) { + // as a special case, x.getClass() has type Class + return new ClassType(restype.getEnclosingType(), + List.of(new WildcardType(types.erasure(qualifierType), + BoundKind.EXTENDS, + syms.boundClass)), + restype.tsym, + restype.getMetadata()); + } else if (msym != null && + msym.owner == syms.arrayClass && + methodName == names.clone && + types.isArray(qualifierType)) { // as a special case, array.clone() has a result that is // the same as static type of the array being cloned return qualifierType; - } else if (methodName == names.getClass && argtypes.isEmpty()) { - // as a special case, x.getClass() has type Class - return new ClassType(restype.getEnclosingType(), - List.of(new WildcardType(types.erasure(qualifierType), - BoundKind.EXTENDS, - syms.boundClass)), - restype.tsym, - restype.getMetadata()); } else { return restype; } @@ -2989,7 +2996,7 @@ if (!refType.isErroneous()) { refType = types.createMethodTypeWithReturn(refType, - adjustMethodReturnType(lookupHelper.site, that.name, checkInfo.pt.getParameterTypes(), refType.getReturnType())); + adjustMethodReturnType(refSym, lookupHelper.site, that.name, checkInfo.pt.getParameterTypes(), refType.getReturnType())); } //go ahead with standard method reference compatibility check - note that param check diff -r 74b7aea686d8 -r d290bef927c4 langtools/test/tools/javac/8161985/T8161985a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/8161985/T8161985a.java Fri Jul 22 12:38:06 2016 +0100 @@ -0,0 +1,28 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8161985 + * @summary Spurious override of Object.getClass leads to NPE + * @compile/fail/ref=T8161985a.out -XDrawDiagnostics T8161985a.java + */ + +class T8161985 { + public static void main(String [] arg) { + T8161985 t = new T8161985(); + t.getClass(); + + } + public void getClass() { + Fred1 f = new Fred1(); + System.out.println( "fred classname: " + f.getClassName()); + } + + + abstract class Fred { + public String getClassName() { + return this.getClass().getSimpleName(); + } + } + + class Fred1 extends Fred { + } +} diff -r 74b7aea686d8 -r d290bef927c4 langtools/test/tools/javac/8161985/T8161985a.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/8161985/T8161985a.out Fri Jul 22 12:38:06 2016 +0100 @@ -0,0 +1,2 @@ +T8161985a.java:14:17: compiler.err.override.meth: (compiler.misc.cant.override: getClass(), T8161985, getClass(), java.lang.Object), final +1 error diff -r 74b7aea686d8 -r d290bef927c4 langtools/test/tools/javac/8161985/T8161985b.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/8161985/T8161985b.java Fri Jul 22 12:38:06 2016 +0100 @@ -0,0 +1,14 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8161985 + * @summary Spurious override of Object.getClass leads to NPE + * @compile/fail/ref=T8161985b.out -XDrawDiagnostics T8161985b.java + */ + +class T8161985b { + public String getClass() { return ""; } + + void test() { + this.getClass().getSimpleName(); + } +} diff -r 74b7aea686d8 -r d290bef927c4 langtools/test/tools/javac/8161985/T8161985b.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/8161985/T8161985b.out Fri Jul 22 12:38:06 2016 +0100 @@ -0,0 +1,3 @@ +T8161985b.java:9:18: compiler.err.override.meth: (compiler.misc.cant.override: getClass(), T8161985b, getClass(), java.lang.Object), final +T8161985b.java:12:22: compiler.err.cant.resolve.location.args: kindname.method, getSimpleName, , , (compiler.misc.location: kindname.class, java.lang.String, null) +2 errors