mirror of
https://github.com/openjdk/jdk.git
synced 2026-01-29 20:48:29 +00:00
6845426: non-static <clinit> method with no args is called during the class initialization process
Only call <clinit> with ACC_STATIC for classfiles with version > 50 Reviewed-by: acorn, dholmes, coleenp
This commit is contained in:
parent
3ebf2446ee
commit
fac0855180
@ -1616,8 +1616,13 @@ methodHandle ClassFileParser::parse_method(constantPoolHandle cp, bool is_interf
|
||||
|
||||
AccessFlags access_flags;
|
||||
if (name == vmSymbols::class_initializer_name()) {
|
||||
// We ignore the access flags for a class initializer. (JVM Spec. p. 116)
|
||||
flags = JVM_ACC_STATIC;
|
||||
// We ignore the other access flags for a valid class initializer.
|
||||
// (JVM Spec 2nd ed., chapter 4.6)
|
||||
if (_major_version < 51) { // backward compatibility
|
||||
flags = JVM_ACC_STATIC;
|
||||
} else if ((flags & JVM_ACC_STATIC) == JVM_ACC_STATIC) {
|
||||
flags &= JVM_ACC_STATIC | JVM_ACC_STRICT;
|
||||
}
|
||||
} else {
|
||||
verify_legal_method_modifiers(flags, is_interface, name, CHECK_(nullHandle));
|
||||
}
|
||||
|
||||
@ -735,7 +735,12 @@ void instanceKlass::call_class_initializer(TRAPS) {
|
||||
static int call_class_initializer_impl_counter = 0; // for debugging
|
||||
|
||||
methodOop instanceKlass::class_initializer() {
|
||||
return find_method(vmSymbols::class_initializer_name(), vmSymbols::void_method_signature());
|
||||
methodOop clinit = find_method(
|
||||
vmSymbols::class_initializer_name(), vmSymbols::void_method_signature());
|
||||
if (clinit != NULL && clinit->has_valid_initializer_flags()) {
|
||||
return clinit;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void instanceKlass::call_class_initializer_impl(instanceKlassHandle this_oop, TRAPS) {
|
||||
|
||||
@ -883,7 +883,7 @@ void klassItable::initialize_itable_for_interface(int method_table_offset, Klass
|
||||
int ime_num = 0;
|
||||
|
||||
// Skip first methodOop if it is a class initializer
|
||||
int i = ((methodOop)methods()->obj_at(0))->name() != vmSymbols::class_initializer_name() ? 0 : 1;
|
||||
int i = ((methodOop)methods()->obj_at(0))->is_static_initializer() ? 1 : 0;
|
||||
|
||||
// m, method_name, method_signature, klass reset each loop so they
|
||||
// don't need preserving across check_signature_loaders call
|
||||
@ -1121,7 +1121,7 @@ int klassItable::compute_itable_index(methodOop m) {
|
||||
assert(index < methods->length(), "should find index for resolve_invoke");
|
||||
}
|
||||
// Adjust for <clinit>, which is left out of table if first method
|
||||
if (methods->length() > 0 && ((methodOop)methods->obj_at(0))->name() == vmSymbols::class_initializer_name()) {
|
||||
if (methods->length() > 0 && ((methodOop)methods->obj_at(0))->is_static_initializer()) {
|
||||
index--;
|
||||
}
|
||||
return index;
|
||||
@ -1135,7 +1135,7 @@ methodOop klassItable::method_for_itable_index(klassOop intf, int itable_index)
|
||||
|
||||
int index = itable_index;
|
||||
// Adjust for <clinit>, which is left out of table if first method
|
||||
if (methods->length() > 0 && ((methodOop)methods->obj_at(0))->name() == vmSymbols::class_initializer_name()) {
|
||||
if (methods->length() > 0 && ((methodOop)methods->obj_at(0))->is_static_initializer()) {
|
||||
index++;
|
||||
}
|
||||
|
||||
|
||||
@ -466,7 +466,20 @@ bool methodOopDesc::is_accessor() const {
|
||||
|
||||
|
||||
bool methodOopDesc::is_initializer() const {
|
||||
return name() == vmSymbols::object_initializer_name() || name() == vmSymbols::class_initializer_name();
|
||||
return name() == vmSymbols::object_initializer_name() || is_static_initializer();
|
||||
}
|
||||
|
||||
bool methodOopDesc::has_valid_initializer_flags() const {
|
||||
return (is_static() ||
|
||||
instanceKlass::cast(method_holder())->major_version() < 51);
|
||||
}
|
||||
|
||||
bool methodOopDesc::is_static_initializer() const {
|
||||
// For classfiles version 51 or greater, ensure that the clinit method is
|
||||
// static. Non-static methods with the name "<clinit>" are not static
|
||||
// initializers. (older classfiles exempted for backward compatibility)
|
||||
return name() == vmSymbols::class_initializer_name() &&
|
||||
has_valid_initializer_flags();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -497,6 +497,13 @@ class methodOopDesc : public oopDesc {
|
||||
// returns true if the method is an initializer (<init> or <clinit>).
|
||||
bool is_initializer() const;
|
||||
|
||||
// returns true if the method is static OR if the classfile version < 51
|
||||
bool has_valid_initializer_flags() const;
|
||||
|
||||
// returns true if the method name is <clinit> and the method has
|
||||
// valid static initializer flags.
|
||||
bool is_static_initializer() const;
|
||||
|
||||
// compiled code support
|
||||
// NOTE: code() is inherently racy as deopt can be clearing code
|
||||
// simultaneously. Use with caution.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user