8073432: Object.getClass() throws stackless NPE, due to C2 intrinsic
Javac should generate NPE checks using Objects.requireNonNull if -target >= 7 Reviewed-by: jlahoda
This commit is contained in:
parent
1114c26925
commit
89cc77c8cb
@ -147,6 +147,7 @@ public class Symtab {
|
|||||||
/** Predefined types.
|
/** Predefined types.
|
||||||
*/
|
*/
|
||||||
public final Type objectType;
|
public final Type objectType;
|
||||||
|
public final Type objectsType;
|
||||||
public final Type classType;
|
public final Type classType;
|
||||||
public final Type classLoaderType;
|
public final Type classLoaderType;
|
||||||
public final Type stringType;
|
public final Type stringType;
|
||||||
@ -408,6 +409,7 @@ public class Symtab {
|
|||||||
|
|
||||||
// Enter predefined classes.
|
// Enter predefined classes.
|
||||||
objectType = enterClass("java.lang.Object");
|
objectType = enterClass("java.lang.Object");
|
||||||
|
objectsType = enterClass("java.util.Objects");
|
||||||
classType = enterClass("java.lang.Class");
|
classType = enterClass("java.lang.Class");
|
||||||
stringType = enterClass("java.lang.String");
|
stringType = enterClass("java.lang.String");
|
||||||
stringBufferType = enterClass("java.lang.StringBuffer");
|
stringBufferType = enterClass("java.lang.StringBuffer");
|
||||||
|
@ -124,6 +124,7 @@ public class Gen extends JCTree.Visitor {
|
|||||||
genCrt = options.isSet(XJCOV);
|
genCrt = options.isSet(XJCOV);
|
||||||
debugCode = options.isSet("debugcode");
|
debugCode = options.isSet("debugcode");
|
||||||
allowInvokedynamic = target.hasInvokedynamic() || options.isSet("invokedynamic");
|
allowInvokedynamic = target.hasInvokedynamic() || options.isSet("invokedynamic");
|
||||||
|
allowBetterNullChecks = target.hasObjects();
|
||||||
pool = new Pool(types);
|
pool = new Pool(types);
|
||||||
|
|
||||||
// ignore cldc because we cannot have both stackmap formats
|
// ignore cldc because we cannot have both stackmap formats
|
||||||
@ -150,6 +151,7 @@ public class Gen extends JCTree.Visitor {
|
|||||||
private final boolean genCrt;
|
private final boolean genCrt;
|
||||||
private final boolean debugCode;
|
private final boolean debugCode;
|
||||||
private final boolean allowInvokedynamic;
|
private final boolean allowInvokedynamic;
|
||||||
|
private final boolean allowBetterNullChecks;
|
||||||
|
|
||||||
/** Default limit of (approximate) size of finalizer to inline.
|
/** Default limit of (approximate) size of finalizer to inline.
|
||||||
* Zero means always use jsr. 100 or greater means never use
|
* Zero means always use jsr. 100 or greater means never use
|
||||||
@ -1983,8 +1985,13 @@ public class Gen extends JCTree.Visitor {
|
|||||||
|
|
||||||
/** Generate a null check from the object value at stack top. */
|
/** Generate a null check from the object value at stack top. */
|
||||||
private void genNullCheck(DiagnosticPosition pos) {
|
private void genNullCheck(DiagnosticPosition pos) {
|
||||||
|
if (allowBetterNullChecks) {
|
||||||
|
callMethod(pos, syms.objectsType, names.requireNonNull,
|
||||||
|
List.of(syms.objectType), true);
|
||||||
|
} else {
|
||||||
callMethod(pos, syms.objectType, names.getClass,
|
callMethod(pos, syms.objectType, names.getClass,
|
||||||
List.<Type>nil(), false);
|
List.<Type>nil(), false);
|
||||||
|
}
|
||||||
code.emitop0(pop);
|
code.emitop0(pop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,6 +121,12 @@ public enum Target {
|
|||||||
return compareTo(JDK1_7) >= 0;
|
return compareTo(JDK1_7) >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Does the target JDK contains the java.util.Objects class?
|
||||||
|
*/
|
||||||
|
public boolean hasObjects() {
|
||||||
|
return compareTo(JDK1_7) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
/** Does the VM support polymorphic method handle invocation?
|
/** Does the VM support polymorphic method handle invocation?
|
||||||
* Affects the linkage information output to the classfile.
|
* Affects the linkage information output to the classfile.
|
||||||
* An alias for {@code hasInvokedynamic}, since all the JSR 292 features appear together.
|
* An alias for {@code hasInvokedynamic}, since all the JSR 292 features appear together.
|
||||||
|
@ -171,6 +171,7 @@ public class Names {
|
|||||||
public final Name deprecated;
|
public final Name deprecated;
|
||||||
public final Name ex;
|
public final Name ex;
|
||||||
public final Name package_info;
|
public final Name package_info;
|
||||||
|
public final Name requireNonNull;
|
||||||
|
|
||||||
//lambda-related
|
//lambda-related
|
||||||
public final Name lambda;
|
public final Name lambda;
|
||||||
@ -307,6 +308,7 @@ public class Names {
|
|||||||
deprecated = fromString("deprecated");
|
deprecated = fromString("deprecated");
|
||||||
ex = fromString("ex");
|
ex = fromString("ex");
|
||||||
package_info = fromString("package-info");
|
package_info = fromString("package-info");
|
||||||
|
requireNonNull = fromString("requireNonNull");
|
||||||
|
|
||||||
//lambda-related
|
//lambda-related
|
||||||
lambda = fromString("lambda$");
|
lambda = fromString("lambda$");
|
||||||
|
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, 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. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* 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 8074306
|
||||||
|
* @summary NULLCHK is emitted as Object.getClass
|
||||||
|
* @compile -source 6 -target 6 TestSyntheticNullChecks.java
|
||||||
|
* @run main TestSyntheticNullChecks 6
|
||||||
|
* @clean TestSyntheticNullChecks*
|
||||||
|
* @compile -source 7 -target 7 TestSyntheticNullChecks.java
|
||||||
|
* @run main TestSyntheticNullChecks 7
|
||||||
|
* @clean TestSyntheticNullChecks*
|
||||||
|
* @compile TestSyntheticNullChecks.java
|
||||||
|
* @run main TestSyntheticNullChecks 9
|
||||||
|
*/
|
||||||
|
public class TestSyntheticNullChecks {
|
||||||
|
|
||||||
|
class Inner { }
|
||||||
|
|
||||||
|
static void generateSyntheticNPE(TestSyntheticNullChecks outer) {
|
||||||
|
outer.new Inner(); //javac will generate a synthetic NPE check for 'outer'
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
int version = Integer.valueOf(args[0]);
|
||||||
|
boolean useObjects = version >= 7;
|
||||||
|
try {
|
||||||
|
generateSyntheticNPE(null);
|
||||||
|
} catch (NullPointerException npe) {
|
||||||
|
boolean hasRequireNotNull = false;
|
||||||
|
for (StackTraceElement e : npe.getStackTrace()) {
|
||||||
|
if (e.getClassName().equals("java.util.Objects") &&
|
||||||
|
e.getMethodName().equals("requireNonNull")) {
|
||||||
|
hasRequireNotNull = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hasRequireNotNull != useObjects) {
|
||||||
|
throw new AssertionError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user