< prev index next >

src/hotspot/share/classfile/classFileParser.cpp

Print this page
rev 55090 : secret-sfac

*** 760,777 **** const int name_and_type_ref_index = cp->name_and_type_ref_index_at(ref_index); const int name_ref_index = cp->name_ref_index_at(name_and_type_ref_index); const Symbol* const name = cp->symbol_at(name_ref_index); - if (ref_kind == JVM_REF_newInvokeSpecial) { if (name != vmSymbols::object_initializer_name()) { classfile_parse_error( "Bad constructor name at constant pool index %u in class file %s", name_ref_index, CHECK); } } else { ! if (name == vmSymbols::object_initializer_name()) { classfile_parse_error( "Bad method name at constant pool index %u in class file %s", name_ref_index, CHECK); } } --- 760,788 ---- const int name_and_type_ref_index = cp->name_and_type_ref_index_at(ref_index); const int name_ref_index = cp->name_ref_index_at(name_and_type_ref_index); const Symbol* const name = cp->symbol_at(name_ref_index); if (name != vmSymbols::object_initializer_name()) { + if (ref_kind == JVM_REF_newInvokeSpecial) { classfile_parse_error( "Bad constructor name at constant pool index %u in class file %s", name_ref_index, CHECK); } } else { ! // The allowed invocation mode of <init> depends on its signature. ! // This test corresponds to verify_invoke_instructions in the verifier. ! const int signature_ref_index = ! cp->signature_ref_index_at(name_and_type_ref_index); ! const Symbol* const signature = cp->symbol_at(signature_ref_index); ! if (signature->is_void_method_signature() ! && ref_kind == JVM_REF_newInvokeSpecial) { ! // OK, could be a constructor call ! } else if (!signature->is_void_method_signature() ! && ref_kind == JVM_REF_invokeStatic) { ! // also OK, could be a static factory call ! } else { classfile_parse_error( "Bad method name at constant pool index %u in class file %s", name_ref_index, CHECK); } }
*** 2091,2105 **** const Symbol* sig, TRAPS) const { assert(name != NULL, "invariant"); assert(sig != NULL, "invariant"); ResourceMark rm(THREAD); Exceptions::fthrow(THREAD_AND_LOCATION, vmSymbols::java_lang_ClassFormatError(), ! "%s \"%s\" in class %s has illegal signature \"%s\"", type, ! name->as_C_string(), _class_name->as_C_string(), sig->as_C_string()); } AnnotationCollector::ID AnnotationCollector::annotation_index(const ClassLoaderData* loader_data, const Symbol* name) { --- 2102,2121 ---- const Symbol* sig, TRAPS) const { assert(name != NULL, "invariant"); assert(sig != NULL, "invariant"); + const char* class_note = ""; + if (is_value_type() && name == vmSymbols::object_initializer_name()) { + class_note = " (an inline class)"; + } + ResourceMark rm(THREAD); Exceptions::fthrow(THREAD_AND_LOCATION, vmSymbols::java_lang_ClassFormatError(), ! "%s \"%s\" in class %s%s has illegal signature \"%s\"", type, ! name->as_C_string(), _class_name->as_C_string(), class_note, sig->as_C_string()); } AnnotationCollector::ID AnnotationCollector::annotation_index(const ClassLoaderData* loader_data, const Symbol* name) {
*** 2406,2420 **** } if (name == vmSymbols::object_initializer_name()) { if (is_interface) { classfile_parse_error("Interface cannot have a method named <init>, class file %s", CHECK_NULL); ! /* TBD: uncomment when javac stops generating <init>() for value types. ! } else if (is_value_type) { ! classfile_parse_error("Value Type cannot have a method named <init>, class file %s", CHECK_NULL); ! */ } } int args_size = -1; // only used when _need_verify is true if (_need_verify) { args_size = ((flags & JVM_ACC_STATIC) ? 0 : 1) + --- 2422,2471 ---- } if (name == vmSymbols::object_initializer_name()) { if (is_interface) { classfile_parse_error("Interface cannot have a method named <init>, class file %s", CHECK_NULL); ! } else if (!is_value_type && signature->is_void_method_signature()) { ! // OK, a constructor ! } else if (is_value_type && !signature->is_void_method_signature()) { ! // also OK, a static factory, as long as the return value is good ! bool ok = false; ! SignatureStream ss((Symbol*) signature, true); ! while (!ss.at_return_type()) ss.next(); ! if (ss.is_object()) { ! TempNewSymbol ret = ss.as_symbol_or_null(); ! const Symbol* required = class_name(); ! if (is_unsafe_anonymous()) { ! // nobody can mention such a class name ! required = vmSymbols::java_lang_Object(); ! } ! ok = (ret == required); ! } ! if (!ok) { ! throwIllegalSignature("Method", name, signature, CHECK_0); ! } ! } else { ! // not OK, so throw the same error as in verify_legal_method_signature. ! throwIllegalSignature("Method", name, signature, CHECK_0); } + // A declared <init> method must always be either a non-static + // object constructor, with a void return, or else it must be a + // static factory method, with a non-void return. No other + // definition of <init> is possible. + // + // The verifier (in verify_invoke_instructions) will inspect the + // signature of any attempt to invoke <init>, and ensures that it + // returns non-void if and only if it is being invoked by + // invokestatic, and void if and only if it is being invoked by + // invokespecial. + // + // When a symbolic reference to <init> is resolved for a + // particular invocation mode (special or static), the mode is + // matched to the JVM_ACC_STATIC modifier of the <init> method. + // Thus, it is impossible to statically invoke a constructor, and + // impossible to "new + invokespecial" a static factory, either + // through bytecode or through reflection. } int args_size = -1; // only used when _need_verify is true if (_need_verify) { args_size = ((flags & JVM_ACC_STATIC) ? 0 : 1) +
*** 5007,5021 **** (is_interface && !is_abstract) || (is_interface && major_gte_15 && (is_super || is_enum)) || (!is_interface && major_gte_15 && is_annotation) || (is_value_type && (is_interface || is_abstract || is_enum || !is_final))) { ResourceMark rm(THREAD); Exceptions::fthrow( THREAD_AND_LOCATION, vmSymbols::java_lang_ClassFormatError(), ! "Illegal class modifiers in class %s: 0x%X", ! _class_name->as_C_string(), flags ); return; } } --- 5058,5074 ---- (is_interface && !is_abstract) || (is_interface && major_gte_15 && (is_super || is_enum)) || (!is_interface && major_gte_15 && is_annotation) || (is_value_type && (is_interface || is_abstract || is_enum || !is_final))) { ResourceMark rm(THREAD); + const char* class_note = ""; + if (is_value_type) class_note = " (an inline class)"; Exceptions::fthrow( THREAD_AND_LOCATION, vmSymbols::java_lang_ClassFormatError(), ! "Illegal class modifiers in class %s%s: 0x%X", ! _class_name->as_C_string(), class_note, flags ); return; } }
*** 5154,5163 **** --- 5207,5218 ---- const bool major_gte_8 = _major_version >= JAVA_8_VERSION; const bool is_initializer = (name == vmSymbols::object_initializer_name()); bool is_illegal = false; + const char* class_note = ""; + if (is_interface) { if (major_gte_8) { // Class file version is JAVA_8_VERSION or later Methods of // interfaces may set any of the flags except ACC_PROTECTED, // ACC_FINAL, ACC_NATIVE, and ACC_SYNCHRONIZED; they must
*** 5188,5204 **** } else { // not interface if (has_illegal_visibility(flags)) { is_illegal = true; } else { if (is_initializer) { ! if (is_static || is_final || is_synchronized || is_native || is_abstract || (major_gte_15 && is_bridge)) { is_illegal = true; } } else { // not initializer if (is_value_type && is_synchronized && !is_static) { is_illegal = true; } else { if (is_abstract) { if ((is_final || is_native || is_private || is_static || (major_gte_15 && (is_synchronized || is_strict)))) { is_illegal = true; --- 5243,5269 ---- } else { // not interface if (has_illegal_visibility(flags)) { is_illegal = true; } else { if (is_initializer) { ! if (is_final || is_synchronized || is_native || is_abstract || (major_gte_15 && is_bridge)) { is_illegal = true; } + if (!is_static && !is_value_type) { + // OK, an object constructor in a regular class + } else if (is_static && is_value_type) { + // OK, a static init factory in an inline class + } else { + // but no other combinations are allowed + is_illegal = true; + class_note = (is_value_type ? " (an inline class)" : " (not an inline class)"); + } } else { // not initializer if (is_value_type && is_synchronized && !is_static) { is_illegal = true; + class_note = " (an inline class)"; } else { if (is_abstract) { if ((is_final || is_native || is_private || is_static || (major_gte_15 && (is_synchronized || is_strict)))) { is_illegal = true;
*** 5212,5223 **** if (is_illegal) { ResourceMark rm(THREAD); Exceptions::fthrow( THREAD_AND_LOCATION, vmSymbols::java_lang_ClassFormatError(), ! "Method %s in class %s has illegal modifiers: 0x%X", ! name->as_C_string(), _class_name->as_C_string(), flags); return; } } void ClassFileParser::verify_legal_utf8(const unsigned char* buffer, --- 5277,5288 ---- if (is_illegal) { ResourceMark rm(THREAD); Exceptions::fthrow( THREAD_AND_LOCATION, vmSymbols::java_lang_ClassFormatError(), ! "Method %s in class %s%s has illegal modifiers: 0x%X", ! name->as_C_string(), _class_name->as_C_string(), class_note, flags); return; } } void ClassFileParser::verify_legal_utf8(const unsigned char* buffer,
*** 5596,5609 **** } // The first non-signature thing better be a ')' if ((length > 0) && (*p++ == JVM_SIGNATURE_ENDFUNC)) { length--; if (name->utf8_length() > 0 && name->char_at(0) == '<') { ! // All internal methods must return void if ((length == 1) && (p[0] == JVM_SIGNATURE_VOID)) { return args_size; } } else { // Now we better just have a return value nextp = skip_over_field_signature(p, true, length, CHECK_0); if (nextp && ((int)length == (nextp - p))) { return args_size; --- 5661,5690 ---- } // The first non-signature thing better be a ')' if ((length > 0) && (*p++ == JVM_SIGNATURE_ENDFUNC)) { length--; if (name->utf8_length() > 0 && name->char_at(0) == '<') { ! // All constructor methods must return void if ((length == 1) && (p[0] == JVM_SIGNATURE_VOID)) { return args_size; } + // All static init methods must return the current class + if ((length >= 3) && (p[length-1] == JVM_SIGNATURE_ENDCLASS) + && name == vmSymbols::object_initializer_name()) { + nextp = skip_over_field_signature(p, true, length, CHECK_0); + if (nextp && ((int)length == (nextp - p))) { + // The actual class will be checked against current class + // when the method is defined (see parse_method). + // A reference to a static init with a bad return type + // will load and verify OK, but will fail to link. + return args_size; + } + } + // The distinction between static factory methods and + // constructors depends on the JVM_ACC_STATIC modifier. + // This distinction must be reflected in a void or non-void + // return. For declared methods, the check is in parse_method. } else { // Now we better just have a return value nextp = skip_over_field_signature(p, true, length, CHECK_0); if (nextp && ((int)length == (nextp - p))) { return args_size;
< prev index next >