提交 a7d413b7 编写于 作者: K kamg

6845426: non-static <clinit> method with no args is called during the class initialization process

Summary: Only call <clinit> with ACC_STATIC for classfiles with version > 50
Reviewed-by: acorn, dholmes, coleenp
上级 f38fb765
...@@ -1616,8 +1616,13 @@ methodHandle ClassFileParser::parse_method(constantPoolHandle cp, bool is_interf ...@@ -1616,8 +1616,13 @@ methodHandle ClassFileParser::parse_method(constantPoolHandle cp, bool is_interf
AccessFlags access_flags; AccessFlags access_flags;
if (name == vmSymbols::class_initializer_name()) { if (name == vmSymbols::class_initializer_name()) {
// We ignore the access flags for a class initializer. (JVM Spec. p. 116) // We ignore the other access flags for a valid class initializer.
flags = JVM_ACC_STATIC; // (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 { } else {
verify_legal_method_modifiers(flags, is_interface, name, CHECK_(nullHandle)); verify_legal_method_modifiers(flags, is_interface, name, CHECK_(nullHandle));
} }
......
...@@ -735,7 +735,12 @@ void instanceKlass::call_class_initializer(TRAPS) { ...@@ -735,7 +735,12 @@ void instanceKlass::call_class_initializer(TRAPS) {
static int call_class_initializer_impl_counter = 0; // for debugging static int call_class_initializer_impl_counter = 0; // for debugging
methodOop instanceKlass::class_initializer() { 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) { 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 ...@@ -883,7 +883,7 @@ void klassItable::initialize_itable_for_interface(int method_table_offset, Klass
int ime_num = 0; int ime_num = 0;
// Skip first methodOop if it is a class initializer // 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 // m, method_name, method_signature, klass reset each loop so they
// don't need preserving across check_signature_loaders call // don't need preserving across check_signature_loaders call
...@@ -1121,7 +1121,7 @@ int klassItable::compute_itable_index(methodOop m) { ...@@ -1121,7 +1121,7 @@ int klassItable::compute_itable_index(methodOop m) {
assert(index < methods->length(), "should find index for resolve_invoke"); assert(index < methods->length(), "should find index for resolve_invoke");
} }
// Adjust for <clinit>, which is left out of table if first method // 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--; index--;
} }
return index; return index;
...@@ -1135,7 +1135,7 @@ methodOop klassItable::method_for_itable_index(klassOop intf, int itable_index) ...@@ -1135,7 +1135,7 @@ methodOop klassItable::method_for_itable_index(klassOop intf, int itable_index)
int index = itable_index; int index = itable_index;
// Adjust for <clinit>, which is left out of table if first method // 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++; index++;
} }
......
...@@ -466,7 +466,20 @@ bool methodOopDesc::is_accessor() const { ...@@ -466,7 +466,20 @@ bool methodOopDesc::is_accessor() const {
bool methodOopDesc::is_initializer() 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 { ...@@ -497,6 +497,13 @@ class methodOopDesc : public oopDesc {
// returns true if the method is an initializer (<init> or <clinit>). // returns true if the method is an initializer (<init> or <clinit>).
bool is_initializer() const; 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 // compiled code support
// NOTE: code() is inherently racy as deopt can be clearing code // NOTE: code() is inherently racy as deopt can be clearing code
// simultaneously. Use with caution. // simultaneously. Use with caution.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册