Skip to content
Permalink
Browse files
8286807: Revert experimental special treatment given to new Object() …
…instantiation.
  • Loading branch information
Srikanth Adayapalam committed May 18, 2022
1 parent 4165ca0 commit b4f0a6e327213d76b8a86e3ad648747d842cc80e
Showing 45 changed files with 59 additions and 188 deletions.
@@ -267,7 +267,7 @@ define SetupJavaCompilationBody
JAVA_WARNINGS_ARE_ERRORS ?= -Werror

# Tell javac to do exactly as told and no more
PARANOIA_FLAGS := -implicit:none -Xprefer:source -XDignore.symbol.file=true -XDtolerateObjectInstantiation -encoding ascii
PARANOIA_FLAGS := -implicit:none -Xprefer:source -XDignore.symbol.file=true -encoding ascii

$1_FLAGS += -g -Xlint:all $$($1_TARGET_RELEASE) $$(PARANOIA_FLAGS) $$(JAVA_WARNINGS_ARE_ERRORS)
$1_FLAGS += $$($1_JAVAC_FLAGS)
@@ -24,10 +24,10 @@
#

#javac configuration for "normal build" (these will be passed to the bootstrap compiler):
javac.opts = -XDignore.symbol.file=true -Xlint:all,-deprecation,-exports -XDtolerateObjectInstantiation -Werror -g:source,lines,vars
javac.opts = -XDignore.symbol.file=true -Xlint:all,-deprecation,-exports -Werror -g:source,lines,vars

#version used to compile build tools
javac.build.opts = -XDignore.symbol.file=true -Xlint:all,-deprecation,-options -XDtolerateObjectInstantiation -Werror -g:source,lines,vars
javac.build.opts = -XDignore.symbol.file=true -Xlint:all,-deprecation,-options -Werror -g:source,lines,vars
javac.build.source = 8
javac.build.target = 8

@@ -38,7 +38,7 @@
* @see java.lang.Class
* @since 1.0
*/
public abstract class Object {
public class Object {

/**
* Constructs a new object.
@@ -152,14 +152,12 @@ private static RuntimeException newIAE(String message, Throwable cause) {
return new IllegalArgumentException(message, cause);
}

private static class CacheHolder {
static final Function<Object, Object> CREATE = new Function<>() {
@Override
public Object apply(Object key) {
return new CacheHolder();
}
};
}
private static final Function<Object, Object> CREATE_RESERVATION = new Function<>() {
@Override
public Object apply(Object key) {
return new Object();
}
};

public final S findSpecies(K key) {
// Note: Species instantiation may throw VirtualMachineError because of
@@ -182,12 +180,12 @@ public final S findSpecies(K key) {
// concrete class if ever.
// The concrete class is published via SpeciesData instance
// returned here only after the class and species data are linked together.
Object speciesDataOrReservation = cache.computeIfAbsent(key, CacheHolder.CREATE);
Object speciesDataOrReservation = cache.computeIfAbsent(key, CREATE_RESERVATION);
// Separating the creation of a placeholder SpeciesData instance above
// from the loading and linking a real one below ensures we can never
// accidentally call computeIfAbsent recursively.
S speciesData;
if (speciesDataOrReservation.getClass() == CacheHolder.class) {
if (speciesDataOrReservation.getClass() == Object.class) {
synchronized (speciesDataOrReservation) {
Object existingSpeciesData = cache.get(key);
if (existingSpeciesData == speciesDataOrReservation) { // won the race
@@ -59,7 +59,6 @@

import com.sun.tools.javac.resources.CompilerProperties.Errors;
import com.sun.tools.javac.resources.CompilerProperties.Fragments;
import com.sun.tools.javac.resources.CompilerProperties.Notes;
import com.sun.tools.javac.resources.CompilerProperties.Warnings;
import com.sun.tools.javac.tree.*;
import com.sun.tools.javac.tree.JCTree.*;
@@ -179,7 +178,7 @@ protected Attr(Context context) {
Feature.PATTERN_SWITCH.allowedInSource(source);
sourceName = source.name;
useBeforeDeclarationWarning = options.isSet("useBeforeDeclarationWarning");
tolerateObjectInstantiation = options.isSet("tolerateObjectInstantiation");

statInfo = new ResultInfo(KindSelector.NIL, Type.noType);
varAssignmentInfo = new ResultInfo(KindSelector.ASG, Type.noType);
unknownExprInfo = new ResultInfo(KindSelector.VAL, Type.noType);
@@ -231,12 +230,6 @@ protected Attr(Context context) {
*/
boolean useBeforeDeclarationWarning;

/**
* Switch: warn about use of new Object() ? By default, Yes;
* but not if -XDtolerateObjectInstantiation is in effect
*/
boolean tolerateObjectInstantiation;

/**
* Switch: name of source level; used for error reporting.
*/
@@ -2788,9 +2781,6 @@ public void visitNewClass(final JCNewClass tree) {
clazztype = TreeInfo.isEnumInit(env.tree) ?
attribIdentAsEnumType(env, (JCIdent)clazz) :
attribType(clazz, env);
if (!tolerateObjectInstantiation && clazztype.tsym == syms.objectType.tsym && cdef == null && !tree.classDeclRemoved()) {
log.note(tree.pos(), Notes.CantInstantiateObjectDirectly);
}
} finally {
env.info.isNewClass = false;
}
@@ -2847,7 +2837,7 @@ public void visitNewClass(final JCNewClass tree) {
}
// Check that class is not abstract
if (cdef == null && !isSpeculativeDiamondInferenceRound && // class body may be nulled out in speculative tree copy
(clazztype.tsym.flags() & (ABSTRACT | INTERFACE)) != 0 && clazztype.tsym != syms.objectType.tsym) { // tolerate abstract Object
(clazztype.tsym.flags() & (ABSTRACT | INTERFACE)) != 0) {
log.error(tree.pos(),
Errors.AbstractCantBeInstantiated(clazztype.tsym));
skipNonDiamondPath = true;
@@ -44,7 +44,6 @@
import com.sun.tools.javac.jvm.*;
import com.sun.tools.javac.resources.CompilerProperties.Errors;
import com.sun.tools.javac.resources.CompilerProperties.Fragments;
import com.sun.tools.javac.resources.CompilerProperties.Notes;
import com.sun.tools.javac.resources.CompilerProperties.Warnings;
import com.sun.tools.javac.tree.*;
import com.sun.tools.javac.util.*;
@@ -108,13 +107,6 @@ public class Check {
private final Preview preview;
private final boolean warnOnAnyAccessToMembers;

/**
* Switch: warn about use of new Object() ? By default, Yes;
* but not if -XDtolerateObjectInstantiation is in effect
*/
boolean tolerateObjectInstantiation;


// The set of lint options currently in effect. It is initialized
// from the context, and then is set/reset as needed by Attr as it
// visits all the various parts of the trees during attribution.
@@ -151,7 +143,6 @@ protected Check(Context context) {
source = Source.instance(context);
target = Target.instance(context);
warnOnAnyAccessToMembers = options.isSet("warnOnAccessToMembers");
tolerateObjectInstantiation = options.isSet("tolerateObjectInstantiation");
Target target = Target.instance(context);
syntheticNameChar = target.syntheticNameChar();

@@ -811,12 +802,7 @@ void checkSuperConstraintsOfValueClass(DiagnosticPosition pos, ClassSymbol c) {
Type checkConstructorRefType(JCExpression expr, Type t) {
t = checkClassOrArrayType(expr, t);
if (t.hasTag(CLASS)) {
/* Tolerate an encounter with abstract Object, we will mutate the constructor reference
to an invocation of java.util.Objects.newIdentity downstream.
*/
if (!tolerateObjectInstantiation && t.tsym == syms.objectType.tsym)
log.note(expr.pos(), Notes.CantInstantiateObjectDirectly);
if ((t.tsym.flags() & (ABSTRACT | INTERFACE)) != 0 && t.tsym != syms.objectType.tsym) {
if ((t.tsym.flags() & (ABSTRACT | INTERFACE)) != 0) {
log.error(expr, Errors.AbstractCantBeInstantiated(t.tsym));
t = types.createErrorType(t);
} else if ((t.tsym.flags() & ENUM) != 0) {
@@ -521,11 +521,6 @@ public void visitReference(JCMemberReference tree) {
List<JCExpression> indy_args = init==null? List.nil() : translate(List.of(init), localContext.prev);


if (refSym.isConstructor() && tree.expr.type.tsym == syms.objectType.tsym) {
if (tree.mode == ReferenceMode.NEW && tree.kind == ReferenceKind.TOPLEVEL) {
refSym = rs.resolveInternalMethod(tree, attrEnv, syms.objectsType, names.newIdentity, List.nil(), List.nil());
}
}
//build a sam instance using an indy call to the meta-factory
result = makeMetafactoryIndyCall(localContext, refSym.asHandle(), indy_args);
}
@@ -2876,12 +2876,7 @@ public void visitNewClass(JCNewClass tree) {
} else {
tree.clazz = access(c, tree.clazz, enclOp, false);
}
if (tree.clazz.type.tsym == syms.objectType.tsym) {
Assert.check(tree.def == null && tree.encl == null);
result = makeCall(make.Ident(syms.objectsType.tsym), names.newIdentity, List.nil());
} else {
result = tree;
}
result = tree;
}

// Simplify conditionals with known constant controlling expressions.
@@ -3998,9 +3998,6 @@ compiler.warn.declared.using.preview=\
compiler.warn.attempt.to.synchronize.on.instance.of.value.based.class=\
attempt to synchronize on an instance of a value-based class

compiler.note.cant.instantiate.object.directly=\
Object cannot be instantiated directly; a subclass of Object will be instantiated instead, by invoking java.util.Objects.newIdentity()

# 0: type
compiler.err.enclosing.class.type.non.denotable=\
enclosing class type: {0}\n\
@@ -40,7 +40,7 @@ public class IntHashTable {
protected int[] ints; // the image set
protected int mask; // used to clip int's into the domain
protected int num_bindings; // the number of mappings (including DELETED)
private static final Object DELETED = new Object() {};
private static final Object DELETED = new Object();

/**
* Construct an Object {@literal ->} int hash table.
@@ -94,7 +94,6 @@ public static Names instance(Context context) {
public final Name init;
public final Name iterator;
public final Name length;
public final Name newIdentity;
public final Name next;
public final Name ordinal;
public final Name provider;
@@ -290,7 +289,6 @@ public Names(Context context) {
iterator = fromString("iterator");
length = fromString("length");
next = fromString("next");
newIdentity = fromString("newIdentity");
ordinal = fromString("ordinal");
provider = fromString("provider");
serialVersionUID = fromString("serialVersionUID");
@@ -208,7 +208,7 @@ public boolean transform(final CompilationService sjavac,

// Prepare compilation calls
List<Callable<CompilationSubResult>> compilationCalls = new ArrayList<>();
final Object lock = new Object() {};
final Object lock = new Object();
for (int i = 0; i < numCompiles; i++) {
CompileChunk cc = compileChunks[i];
if (cc.srcs.isEmpty()) {
@@ -36,10 +36,10 @@
package compiler.escapeAnalysis;

public class TestGetClass {
static Object obj = new Object() {};
static Object obj = new Object();

public static boolean test() {
if (obj.getClass().getSuperclass() == Object.class) {
if (obj.getClass() == Object.class) {
synchronized (obj) {
return true;
}
@@ -30,7 +30,7 @@ public class ForObjectDataProvider {
public static Object[][] forObjectDataProvider() {
return new Object[][]{
{TestHelper.DUMMY_CLASS_INSTANCE.objectField,
"Object[Identity@" + TestHelper.DUMMY_CLASS_INSTANCE.objectField.hashCode() + "]"},
"Object[Object@" + TestHelper.DUMMY_CLASS_INSTANCE.objectField.hashCode() + "]"},
{TestHelper.DUMMY_CLASS_INSTANCE.stringField,
"Object[String:\"" + TestHelper.DUMMY_CLASS_INSTANCE.stringField + "\"]"},
{TestHelper.DUMMY_CLASS_INSTANCE.booleanField,
@@ -73,7 +73,7 @@ public static void main(String[] args) throws Throwable {
}

// Try to cast using a different mechanism.
new java.lang.Object() {}.getClass().getSuperclass().cast(hiddenClassObj);
new java.lang.Object().getClass().cast(hiddenClassObj);
}

}
@@ -59,7 +59,7 @@ public static void main(String[] args) throws Throwable {
}

public static void invalidObjectToDerived() {
java.lang.Object instance = java.util.Objects.newIdentity();
java.lang.Object instance = new java.lang.Object();
int left = 23;
int right = 42;
try {
@@ -69,7 +69,7 @@ public static void invalidObjectToDerived() {
throw new RuntimeException("ClassCastException wasn't thrown, test failed.");
} catch (ClassCastException cce) {
System.out.println(cce.toString());
if (!cce.getMessage().contains("class java.lang.Identity cannot be cast to class Derived (java.lang.Identity is in module java.base of loader 'bootstrap'; Derived is in unnamed module of loader 'app')")) {
if (!cce.getMessage().contains("class java.lang.Object cannot be cast to class Derived (java.lang.Object is in module java.base of loader 'bootstrap'; Derived is in unnamed module of loader 'app')")) {
throw new RuntimeException("Wrong message: " + cce.getMessage());
}
}
@@ -80,7 +80,7 @@ public void run(CommandExecutor executor, String classHistogramArgs, String expa
output.shouldMatch("^\\s+\\d+:\\s+\\d+\\s+\\d+\\s+java.lang.String " + moduleRegex + "\\s*$");

/* Require at least one java.lang.Object */
output.shouldMatch("^\\s+\\d+:\\s+\\d+\\s+\\d+\\s+java.lang.Identity " + moduleRegex + "\\s*$");
output.shouldMatch("^\\s+\\d+:\\s+\\d+\\s+\\d+\\s+java.lang.Object " + moduleRegex + "\\s*$");

/* Require at exactly one TestClass[] */
output.shouldMatch("^\\s+\\d+:\\s+1\\s+\\d+\\s+" +
@@ -38,8 +38,8 @@

public class WaitNotifyThreadTest {

private Object monitor = java.util.Objects.newIdentity();
private final String OBJECT = "a java.lang.Identity";
private Object monitor = new Object();;
private final String OBJECT = "a java.lang.Object";
private final String OBJECT_WAIT = "java.lang.Object.wait";
private final String RUN_METHOD = "WaitNotifyThreadTest$WaitThread.run";

@@ -179,28 +179,26 @@ public void afterTest() {
this.linker = null;
}

private static class TestObject {}

@Test(dataProvider = "flags")
public void getPropertyTest(final boolean publicLookup) throws Throwable {
final MethodType mt = MethodType.methodType(Object.class, Object.class, String.class);
final CallSite cs = createCallSite(publicLookup, GET_PROPERTY, mt);
Assert.assertEquals(cs.getTarget().invoke(new TestObject(), "class"), TestObject.class);
Assert.assertEquals(cs.getTarget().invoke(new Object(), "class"), Object.class);
Assert.assertEquals(cs.getTarget().invoke(new Date(), "class"), Date.class);
}

@Test(dataProvider = "flags")
public void getPropertyNegativeTest(final boolean publicLookup) throws Throwable {
final MethodType mt = MethodType.methodType(Object.class, Object.class, String.class);
final CallSite cs = createCallSite(publicLookup, GET_PROPERTY, mt);
Assert.assertNull(cs.getTarget().invoke(new TestObject(), "DOES_NOT_EXIST"));
Assert.assertNull(cs.getTarget().invoke(new Object(), "DOES_NOT_EXIST"));
}

@Test(dataProvider = "flags")
public void getPropertyTest2(final boolean publicLookup) throws Throwable {
final MethodType mt = MethodType.methodType(Object.class, Object.class);
final CallSite cs = createCallSite(publicLookup, GET_PROPERTY, "class", mt);
Assert.assertEquals(cs.getTarget().invoke(new TestObject()), TestObject.class);
Assert.assertEquals(cs.getTarget().invoke(new Object()), Object.class);
Assert.assertEquals(cs.getTarget().invoke(new Date()), Date.class);
}

@@ -210,7 +208,7 @@ public void getPropertyNegativeTest2(final boolean publicLookup) throws Throwabl
final CallSite cs = createCallSite(publicLookup, GET_PROPERTY, "DOES_NOT_EXIST", mt);

try {
cs.getTarget().invoke(new TestObject());
cs.getTarget().invoke(new Object());
throw new RuntimeException("Expected NoSuchDynamicMethodException");
} catch (final Throwable th) {
Assert.assertTrue(th instanceof NoSuchDynamicMethodException);
@@ -177,8 +177,6 @@ public void priorityAndFallbackLinkerTest() {
Assert.assertEquals(linkerReachCounter[0], 2);
}

private static class TestObject {}

@Test
public void prelinkTransformerTest() throws Throwable {
final DynamicLinkerFactory factory = newDynamicLinkerFactory(true);
@@ -195,7 +193,7 @@ public void prelinkTransformerTest() throws Throwable {
final CallSite cs = linker.link(new SimpleRelinkableCallSite(new CallSiteDescriptor(
MethodHandles.publicLookup(), GET_PROPERTY, mt)));
Assert.assertFalse(reachedPrelinkTransformer[0]);
Assert.assertEquals(cs.getTarget().invoke(new TestObject(), "class"), TestObject.class);
Assert.assertEquals(cs.getTarget().invoke(new Object(), "class"), Object.class);
Assert.assertTrue(reachedPrelinkTransformer[0]);
}

@@ -214,13 +212,13 @@ public void internalObjectsFilterTest() throws Throwable {
final CallSite cs = linker.link(new SimpleRelinkableCallSite(new CallSiteDescriptor(
MethodHandles.publicLookup(), GET_PROPERTY, mt)));
Assert.assertFalse(reachedInternalObjectsFilter[0]);
Assert.assertEquals(cs.getTarget().invoke(new TestObject(), "class"), TestObject.class);
Assert.assertEquals(cs.getTarget().invoke(new Object(), "class"), Object.class);
Assert.assertTrue(reachedInternalObjectsFilter[0]);
}

@Test
public void autoLoadedLinkerTest() {
testAutoLoadedLinkerInvoked(new TestObject(), "toString");
testAutoLoadedLinkerInvoked(new Object(), "toString");
}

@Test
@@ -51,7 +51,7 @@ public void testTypeInference() {
assertEval("import java.util.ArrayList;");
assertEval("import java.util.Arrays;");

assertType("new Object() {}.getClass().getSuperclass().getSuperclass() ", "Class<?>");
assertType("new Object().getClass().getSuperclass() ", "Class<?>");
assertType("new ArrayList().getClass().getSuperclass()", "Class<?>");
assertType("new ArrayList().getClass()", "Class<? extends ArrayList>");
assertType("ArrayList.class", "Class<ArrayList>");
@@ -509,7 +509,7 @@ public void varDeclRedefNoInit() {
assertVarDeclRedefNoInit("double", "d", "3.1415926", "0.0");
assertVarDeclRedefNoInit("boolean", "n", "true", "false");
assertVarDeclRedefNoInit("char", "c", "'x'", "'\\000'");
assertVarDeclRedefNoInit("Object", "o", "new String()", IGNORE_VALUE, "null");
assertVarDeclRedefNoInit("Object", "o", "new Object()", IGNORE_VALUE, "null");
assertVarDeclRedefNoInit("String", "s", "\"hi\"", "null");
}

0 comments on commit b4f0a6e

Please sign in to comment.