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.
|
||||
*/
|
||||
public final Type objectType;
|
||||
public final Type objectsType;
|
||||
public final Type classType;
|
||||
public final Type classLoaderType;
|
||||
public final Type stringType;
|
||||
@ -408,6 +409,7 @@ public class Symtab {
|
||||
|
||||
// Enter predefined classes.
|
||||
objectType = enterClass("java.lang.Object");
|
||||
objectsType = enterClass("java.util.Objects");
|
||||
classType = enterClass("java.lang.Class");
|
||||
stringType = enterClass("java.lang.String");
|
||||
stringBufferType = enterClass("java.lang.StringBuffer");
|
||||
|
@ -124,6 +124,7 @@ public class Gen extends JCTree.Visitor {
|
||||
genCrt = options.isSet(XJCOV);
|
||||
debugCode = options.isSet("debugcode");
|
||||
allowInvokedynamic = target.hasInvokedynamic() || options.isSet("invokedynamic");
|
||||
allowBetterNullChecks = target.hasObjects();
|
||||
pool = new Pool(types);
|
||||
|
||||
// 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 debugCode;
|
||||
private final boolean allowInvokedynamic;
|
||||
private final boolean allowBetterNullChecks;
|
||||
|
||||
/** Default limit of (approximate) size of finalizer to inline.
|
||||
* 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. */
|
||||
private void genNullCheck(DiagnosticPosition pos) {
|
||||
callMethod(pos, syms.objectType, names.getClass,
|
||||
List.<Type>nil(), false);
|
||||
if (allowBetterNullChecks) {
|
||||
callMethod(pos, syms.objectsType, names.requireNonNull,
|
||||
List.of(syms.objectType), true);
|
||||
} else {
|
||||
callMethod(pos, syms.objectType, names.getClass,
|
||||
List.<Type>nil(), false);
|
||||
}
|
||||
code.emitop0(pop);
|
||||
}
|
||||
|
||||
|
@ -121,6 +121,12 @@ public enum Target {
|
||||
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?
|
||||
* Affects the linkage information output to the classfile.
|
||||
* 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 ex;
|
||||
public final Name package_info;
|
||||
public final Name requireNonNull;
|
||||
|
||||
//lambda-related
|
||||
public final Name lambda;
|
||||
@ -307,6 +308,7 @@ public class Names {
|
||||
deprecated = fromString("deprecated");
|
||||
ex = fromString("ex");
|
||||
package_info = fromString("package-info");
|
||||
requireNonNull = fromString("requireNonNull");
|
||||
|
||||
//lambda-related
|
||||
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…
Reference in New Issue
Block a user