diff --git a/vm/vmcore/include/Class.h b/vm/vmcore/include/Class.h index 7dd4df6..47f05a1 100644 --- a/vm/vmcore/include/Class.h +++ b/vm/vmcore/include/Class.h @@ -894,6 +894,7 @@ public: bool is_public() {return (_access_flags&ACC_PUBLIC)?true:false;} bool is_private() {return (_access_flags&ACC_PRIVATE)?true:false;} bool is_protected() {return (_access_flags&ACC_PROTECTED)?true:false;} + bool is_package_private() {return !(is_public()||is_protected()||is_public())?true:false;} bool is_static() {return (_access_flags&ACC_STATIC)?true:false;} bool is_final() {return (_access_flags&ACC_FINAL)?true:false;} bool is_strict() {return (_access_flags&ACC_STRICT)?true:false;} diff --git a/vm/vmcore/src/class_support/Prepare.cpp b/vm/vmcore/src/class_support/Prepare.cpp index 4d04006..b256c58 100644 --- a/vm/vmcore/src/class_support/Prepare.cpp +++ b/vm/vmcore/src/class_support/Prepare.cpp @@ -858,9 +858,25 @@ #endif for (j = 0; j < n_super_virtual_method_entries; j++) { Method *m = super_vtable_descriptors[j]; if (name == m->get_name() && desc == m->get_descriptor()) { - if( m->is_final() && !m->is_private() ) { - clss->state = ST_Error; - return; + if(m->is_final()) { + if(m->is_private() + || (m->is_package_private() + && m->get_class()->package != method.get_class()->package)) + { + // We allow to override private final and + // default (package private) final methods + // from superclasses since they are not accessible + // from descendants. + // Note: for package private methods this statement + // is true only for classes from different packages + } else { + REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, + "java/lang/VerifyError", + "An attempt is made to override final method " + << m->get_class()->name->bytes << "." + << m->get_name()->bytes << m->get_descriptor()->bytes); + return; + } } // method doesn't override m if method has package access // and is in a different runtime package than m. @@ -1373,8 +1389,6 @@ bool class_prepare(Global_Env* env, Clas // assign_offsets_to_class_methods(clss); if(clss->state == ST_Error) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, - "java/lang/IncompatibleClassChangeError", clss->name->bytes); return false; } //