8140001: _allocateInstance intrinsic does not throw InstantiationException for abstract classes and interfaces
Reviewed-by: kvn, shade
--- a/hotspot/src/share/vm/ci/ciInstanceKlass.hpp Fri Jan 15 16:36:43 2016 +0300
+++ b/hotspot/src/share/vm/ci/ciInstanceKlass.hpp Fri Jan 15 21:56:40 2016 +0300
@@ -174,7 +174,6 @@
return 2;
}
}
-
bool has_default_methods() {
assert(is_loaded(), "must be loaded");
return _has_default_methods;
@@ -261,6 +260,11 @@
return NULL;
}
+ bool can_be_instantiated() {
+ assert(is_loaded(), "must be loaded");
+ return !is_interface() && !is_abstract();
+ }
+
// Dump the current state of this klass for compilation replay.
virtual void dump_replay_data(outputStream* out);
};
--- a/hotspot/src/share/vm/opto/escape.cpp Fri Jan 15 16:36:43 2016 +0300
+++ b/hotspot/src/share/vm/opto/escape.cpp Fri Jan 15 21:56:40 2016 +0300
@@ -810,6 +810,7 @@
if (cik->is_subclass_of(_compile->env()->Thread_klass()) ||
cik->is_subclass_of(_compile->env()->Reference_klass()) ||
!cik->is_instance_klass() || // StressReflectiveCode
+ !cik->as_instance_klass()->can_be_instantiated() ||
cik->as_instance_klass()->has_finalizer()) {
es = PointsToNode::GlobalEscape;
}
--- a/hotspot/src/share/vm/opto/graphKit.cpp Fri Jan 15 16:36:43 2016 +0300
+++ b/hotspot/src/share/vm/opto/graphKit.cpp Fri Jan 15 21:56:40 2016 +0300
@@ -3407,8 +3407,7 @@
if (layout_is_con) {
assert(!StressReflectiveCode, "stress mode does not use these paths");
bool must_go_slow = Klass::layout_helper_needs_slow_path(layout_con);
- initial_slow_test = must_go_slow? intcon(1): extra_slow_test;
-
+ initial_slow_test = must_go_slow ? intcon(1) : extra_slow_test;
} else { // reflective case
// This reflective path is used by Unsafe.allocateInstance.
// (It may be stress-tested by specifying StressReflectiveCode.)
--- a/hotspot/test/runtime/Unsafe/AllocateInstance.java Fri Jan 15 16:36:43 2016 +0300
+++ b/hotspot/test/runtime/Unsafe/AllocateInstance.java Fri Jan 15 21:56:40 2016 +0300
@@ -35,21 +35,7 @@
import static jdk.test.lib.Asserts.*;
public class AllocateInstance {
- public static void main(String args[]) throws Exception {
- Unsafe unsafe = Utils.getUnsafe();
-
- // allocateInstance() should not result in a call to the constructor
- TestClass tc = (TestClass)unsafe.allocateInstance(TestClass.class);
- assertFalse(tc.calledConstructor);
-
- // allocateInstance() on an abstract class should result in an InstantiationException
- try {
- AbstractClass ac = (AbstractClass)unsafe.allocateInstance(AbstractClass.class);
- throw new RuntimeException("Did not get expected InstantiationException");
- } catch (InstantiationException e) {
- // Expected
- }
- }
+ static final Unsafe UNSAFE = Utils.getUnsafe();
class TestClass {
public boolean calledConstructor = false;
@@ -59,7 +45,41 @@
}
}
+ static void testConstructorCall() throws InstantiationException {
+ // allocateInstance() should not result in a call to the constructor
+ TestClass tc = (TestClass)UNSAFE.allocateInstance(TestClass.class);
+ assertFalse(tc.calledConstructor);
+ }
+
abstract class AbstractClass {
public AbstractClass() {}
}
+
+ static void testAbstractClass() {
+ try {
+ AbstractClass ac = (AbstractClass) UNSAFE.allocateInstance(AbstractClass.class);
+ throw new AssertionError("Should throw InstantiationException for an abstract class");
+ } catch (InstantiationException e) {
+ // Expected
+ }
+ }
+
+ interface AnInterface {}
+
+ static void testInterface() {
+ try {
+ AnInterface ai = (AnInterface) UNSAFE.allocateInstance(AnInterface.class);
+ throw new AssertionError("Should throw InstantiationException for an interface");
+ } catch (InstantiationException e) {
+ // Expected
+ }
+ }
+
+ public static void main(String args[]) throws Exception {
+ for (int i = 0; i < 20_000; i++) {
+ testConstructorCall();
+ testAbstractClass();
+ testInterface();
+ }
+ }
}