Skip to content

Commit

Permalink
JDK-8243204 add class load time checking of abstract super classes of…
Browse files Browse the repository at this point in the history
… inline types
  • Loading branch information
hseigel committed May 4, 2020
1 parent 6742fab commit 9418ed0
Show file tree
Hide file tree
Showing 13 changed files with 1,631 additions and 209 deletions.
53 changes: 49 additions & 4 deletions src/hotspot/share/classfile/classFileParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6874,6 +6874,50 @@ void ClassFileParser::parse_stream(const ClassFileStream* const stream,
// all bytes in stream read and parsed
}

// Check that super class of an inline type is abstract, has no instance fields,
// has an empty body-less no-arg constructor, and no synchronized instance methods.
// Otherwise, throw ICCE.
void ClassFileParser::check_super_of_inline_type(const InstanceKlass* super_klass, TRAPS) {
const char* icce_msg = NULL;

if (!super_klass->is_abstract()) {
icce_msg = "that is not abstract";

} else if (super_klass->has_nonstatic_fields()) {
icce_msg = "containing instance fields";

} else {
Array<Method*>* methods = super_klass->methods();
// Look at each method.
for (int x = 0; x < methods->length(); x++) {
const Method* const method = methods->at(x);
if (method->is_synchronized() && !method->is_static()) {
icce_msg = "containing a synchronized instance method";
break;

} else if (method->name() == vmSymbols::object_initializer_name()) {
if (method->signature() != vmSymbols::void_method_signature()) {
icce_msg = "containing a constructor with a non-void signature";
break;
} else if (!method->is_vanilla_constructor()) {
icce_msg = "containing a non-empty constructor";
break;
}
}
}
}
if (icce_msg != NULL) {
ResourceMark rm(THREAD);
Exceptions::fthrow(
THREAD_AND_LOCATION,
vmSymbols::java_lang_IncompatibleClassChangeError(),
"inline class %s has a super class %s %s",
_class_name->as_klass_external_name(),
super_klass->external_name(),
icce_msg);
}
}

void ClassFileParser::post_process_parsed_stream(const ClassFileStream* const stream,
ConstantPool* cp,
TRAPS) {
Expand Down Expand Up @@ -6930,10 +6974,11 @@ void ClassFileParser::post_process_parsed_stream(const ClassFileStream* const st
// For an inline class, only java/lang/Object or special abstract classes
// are acceptable super classes.
if (_access_flags.get_flags() & JVM_ACC_VALUE) {
if (_super_klass->name() != vmSymbols::java_lang_Object()) {
guarantee_property(_super_klass->is_abstract(),
"Inline type must have java.lang.Object or an abstract class as its superclass, class file %s",
CHECK);
const InstanceKlass* super_ik = _super_klass;
while (super_ik->name() != vmSymbols::java_lang_Object()) {
check_super_of_inline_type(super_ik, CHECK);
super_ik = super_ik->java_super();
assert(super_ik != NULL, "Unexpected NULL super class");
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/hotspot/share/classfile/classFileParser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,8 @@ class ClassFileParser {
bool _has_vanilla_constructor;
int _max_bootstrap_specifier_index; // detects BSS values

void check_super_of_inline_type(const InstanceKlass* super_klass, TRAPS);

void parse_stream(const ClassFileStream* const stream, TRAPS);

void post_process_parsed_stream(const ClassFileStream* const stream,
Expand Down
5 changes: 3 additions & 2 deletions src/hotspot/share/oops/method.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -629,7 +629,7 @@ bool Method::is_vanilla_constructor() const {
// which only calls the superclass vanilla constructor and possibly does stores of
// zero constants to local fields:
//
// aload_0
// aload_0, _fast_aload_0, or _nofast_aload_0
// invokespecial
// indexbyte1
// indexbyte2
Expand All @@ -653,7 +653,8 @@ bool Method::is_vanilla_constructor() const {
if (size == 0 || size % 5 != 0) return false;
address cb = code_base();
int last = size - 1;
if (cb[0] != Bytecodes::_aload_0 || cb[1] != Bytecodes::_invokespecial || cb[last] != Bytecodes::_return) {
if ((cb[0] != Bytecodes::_aload_0 && cb[0] != Bytecodes::_fast_aload_0 && cb[0] != Bytecodes::_nofast_aload_0) ||
cb[1] != Bytecodes::_invokespecial || cb[last] != Bytecodes::_return) {
// Does not call superclass default constructor
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,6 @@ public static void main(String[] args) throws Exception {
runTest("ValueMethodSynch",
"Method getInt in class ValueMethodSynch (an inline class) has illegal modifiers");

runTest("ValueSuperClass",
"Inline type must have java.lang.Object or an abstract class as its superclass");

// Test that ClassCircularityError gets detected for instance fields.
System.out.println("Testing ClassCircularityError for instance fields");
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -840,206 +840,6 @@ class ValueMethodSynch {

//////////////////////////////////////////////////////////////////////

// Test that an inline type's super class must be java.lang.Object.
//
// final inline class ValueSuperClass {
// final int int_v;
//
// ValueSuperClass() { int_v = 1; }
// }

class ValueSuperClass {
0xCAFEBABE;
0; // minor version
59; // version
[44] { // Constant Pool
; // first element is empty
class #21; // #1 at 0x0A
Field #1 #22; // #2 at 0x0D
InvokeDynamic 0s #25; // #3 at 0x12
InvokeDynamic 0s #26; // #4 at 0x17
InvokeDynamic 0s #27; // #5 at 0x1C
class #28; // #6 at 0x21
Utf8 "int_v"; // #7 at 0x24
Utf8 "I"; // #8 at 0x2C
Utf8 "hashCode"; // #9 at 0x30
Utf8 "()I"; // #10 at 0x3B
Utf8 "Code"; // #11 at 0x41
Utf8 "LineNumberTable"; // #12 at 0x48
Utf8 "equals"; // #13 at 0x5A
Utf8 "(Ljava/lang/Object;)Z"; // #14 at 0x63
Utf8 "toString"; // #15 at 0x7B
Utf8 "()Ljava/lang/String;"; // #16 at 0x86
Utf8 "<init>"; // #17 at 0x9D
Utf8 "()QValueSuperClass;"; // #18 at 0xA6
Utf8 "SourceFile"; // #19 at 0xBC
Utf8 "ValueSuperClass.java"; // #20 at 0xC9
Utf8 "ValueSuperClass"; // #21 at 0xE0
NameAndType #7 #8; // #22 at 0xF2
Utf8 "BootstrapMethods"; // #23 at 0xF7
MethodHandle 6b #29; // #24 at 0x010A
NameAndType #9 #30; // #25 at 0x010E
NameAndType #13 #31; // #26 at 0x0113
NameAndType #15 #32; // #27 at 0x0118
Utf8 "java/lang/Object"; // #28 at 0x011D
Method #33 #34; // #29 at 0x0130
Utf8 "(QValueSuperClass;)I"; // #30 at 0x0135
Utf8 "(QValueSuperClass;Ljava/lang/Object;)Z"; // #31 at 0x014C
Utf8 "(QValueSuperClass;)Ljava/lang/String;"; // #32 at 0x0175
class #35; // #33 at 0x019D
NameAndType #36 #40; // #34 at 0x01A0
Utf8 "java/lang/invoke/ValueBootstrapMethods"; // #35 at 0x01A5
Utf8 "makeBootstrapMethod"; // #36 at 0x01CE
class #42; // #37 at 0x01E4
Utf8 "Lookup"; // #38 at 0x01E7
Utf8 "InnerClasses"; // #39 at 0x01F0
Utf8 "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;"; // #40 at 0x01FF
class #43; // #41 at 0x0275
Utf8 "java/lang/invoke/MethodHandles$Lookup"; // #42 at 0x0278
Utf8 "java/lang/invoke/MethodHandles"; // #43 at 0x02A0
} // Constant Pool

0x0130; // access [ ACC_SUPER ACC_FINAL ]
#1;// this_cpx
#37;// super_cpx // bad: was #6

[0] { // Interfaces
} // Interfaces

[1] { // fields
{ // Member at 0x02CB
0x0010; // access
#7; // name_cpx
#8; // sig_cpx
[0] { // Attributes
} // Attributes
} // Member
} // fields

[4] { // methods
{ // Member at 0x02D5
0x0011; // access
#9; // name_cpx
#10; // sig_cpx
[1] { // Attributes
Attr(#11, 31) { // Code at 0x02DD
1; // max_stack
1; // max_locals
Bytes[7]{
0x2ABA00030000AC;
};
[0] { // Traps
} // end Traps
[1] { // Attributes
Attr(#12, 6) { // LineNumberTable at 0x02F6
[1] { // LineNumberTable
0 1; // at 0x0302
}
} // end LineNumberTable
} // Attributes
} // end Code
} // Attributes
} // Member
;
{ // Member at 0x0302
0x0011; // access
#13; // name_cpx
#14; // sig_cpx
[1] { // Attributes
Attr(#11, 32) { // Code at 0x030A
2; // max_stack
2; // max_locals
Bytes[8]{
0x2A2BBA00040000AC;
};
[0] { // Traps
} // end Traps
[1] { // Attributes
Attr(#12, 6) { // LineNumberTable at 0x0324
[1] { // LineNumberTable
0 1; // at 0x0330
}
} // end LineNumberTable
} // Attributes
} // end Code
} // Attributes
} // Member
;
{ // Member at 0x0330
0x0011; // access
#15; // name_cpx
#16; // sig_cpx
[1] { // Attributes
Attr(#11, 31) { // Code at 0x0338
1; // max_stack
1; // max_locals
Bytes[7]{
0x2ABA00050000B0;
};
[0] { // Traps
} // end Traps
[1] { // Attributes
Attr(#12, 6) { // LineNumberTable at 0x0351
[1] { // LineNumberTable
0 1; // at 0x035D
}
} // end LineNumberTable
} // Attributes
} // end Code
} // Attributes
} // Member
;
{ // Member at 0x035D
0x0008; // access
#17; // name_cpx
#18; // sig_cpx
[1] { // Attributes
Attr(#11, 37) { // Code at 0x0365
2; // max_stack
1; // max_locals
Bytes[13]{
0xCB00014B042A5FCC;
0x00024B2AB0;
};
[0] { // Traps
} // end Traps
[1] { // Attributes
Attr(#12, 6) { // LineNumberTable at 0x0384
[1] { // LineNumberTable
0 4; // at 0x0390
}
} // end LineNumberTable
} // Attributes
} // end Code
} // Attributes
} // Member
} // methods

[3] { // Attributes
Attr(#19, 2) { // SourceFile at 0x0392
#20;
} // end SourceFile
;
Attr(#39, 10) { // InnerClasses at 0x039A
[1] { // InnerClasses
#37 #41 #38 25; // at 0x03AA
}
} // end InnerClasses
;
Attr(#23, 6) { // BootstrapMethods at 0x03AA
[1] { // bootstrap_methods
{ // bootstrap_method
#24; // bootstrap_method_ref
[0] { // bootstrap_arguments
} // bootstrap_arguments
} // bootstrap_method
}
} // end BootstrapMethods
} // Attributes
} // end class ValueSuperClass

//////////////////////////////////////////////////////////////////////

// Value types Circ and Circ2 have fields of each other's type. This should
// cause a ClassCircularityError exception when one of them is being loaded.
//
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright (c) 2020, 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.
*
* 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.
*
*/

public abstract class CtorHasArgs {
CtorHasArgs(String x) { }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright (c) 2020, 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.
*
* 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.
*
*/

public abstract class CtorIsNotEmpty {
CtorIsNotEmpty() {
System.out.println("CtorIsNotEmpty");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright (c) 2020, 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.
*
* 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.
*
*/

public abstract class HasNonStaticFields {
String hi;
}
Loading

0 comments on commit 9418ed0

Please sign in to comment.