From a7d413b7909618a1490fe63da607e543c5aa9e13 Mon Sep 17 00:00:00 2001 From: kamg Date: Fri, 4 Mar 2011 14:40:46 -0500 Subject: [PATCH] 6845426: non-static method with no args is called during the class initialization process Summary: Only call with ACC_STATIC for classfiles with version > 50 Reviewed-by: acorn, dholmes, coleenp --- src/share/vm/classfile/classFileParser.cpp | 9 +++++++-- src/share/vm/oops/instanceKlass.cpp | 7 ++++++- src/share/vm/oops/klassVtable.cpp | 6 +++--- src/share/vm/oops/methodOop.cpp | 15 ++++++++++++++- src/share/vm/oops/methodOop.hpp | 7 +++++++ 5 files changed, 37 insertions(+), 7 deletions(-) diff --git a/src/share/vm/classfile/classFileParser.cpp b/src/share/vm/classfile/classFileParser.cpp index 3aacf66ff..d111242c9 100644 --- a/src/share/vm/classfile/classFileParser.cpp +++ b/src/share/vm/classfile/classFileParser.cpp @@ -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)); } diff --git a/src/share/vm/oops/instanceKlass.cpp b/src/share/vm/oops/instanceKlass.cpp index 73f4d97df..81bc8165a 100644 --- a/src/share/vm/oops/instanceKlass.cpp +++ b/src/share/vm/oops/instanceKlass.cpp @@ -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) { diff --git a/src/share/vm/oops/klassVtable.cpp b/src/share/vm/oops/klassVtable.cpp index f0939cb69..4c11ed4f9 100644 --- a/src/share/vm/oops/klassVtable.cpp +++ b/src/share/vm/oops/klassVtable.cpp @@ -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 , 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 , 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++; } diff --git a/src/share/vm/oops/methodOop.cpp b/src/share/vm/oops/methodOop.cpp index dad734460..2d88b57e7 100644 --- a/src/share/vm/oops/methodOop.cpp +++ b/src/share/vm/oops/methodOop.cpp @@ -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 "" are not static + // initializers. (older classfiles exempted for backward compatibility) + return name() == vmSymbols::class_initializer_name() && + has_valid_initializer_flags(); } diff --git a/src/share/vm/oops/methodOop.hpp b/src/share/vm/oops/methodOop.hpp index 3b2ed3355..b49a4eacc 100644 --- a/src/share/vm/oops/methodOop.hpp +++ b/src/share/vm/oops/methodOop.hpp @@ -497,6 +497,13 @@ class methodOopDesc : public oopDesc { // returns true if the method is an initializer ( or ). 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 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. -- GitLab