On Thu, 17 Apr 2025 07:14:25 GMT, Timofei Pushkin <tpush...@openjdk.org> wrote:

>> src/hotspot/share/cds/classListParser.cpp line 517:
>> 
>>> 515:     return;
>>> 516:   }
>>> 517:   assert(!supertype->is_shared_unregistered_class(), "unregistered 
>>> supertype cannot be overshadowed");
>> 
>> Does this always prevent an unregistered class to use any other unregistered 
>> class as its super type?
>> 
>> I think a better check would be here:
>> 
>> 
>>     if (!k->local_interfaces()->contains(specified_interface)) {
>> +     jio_fprintf(defaultStream::error_stream(), "Specified interface %s (id 
>> %d) is not directly implemented\n",
>> +           specified_interface->external_name(), _interfaces->at(i));
>>       print_specified_interfaces();
>>       print_actual_interfaces(k);
>> +     throw exception .....      
>> -     error("Specified interface %s (id %d) is not directly implemented",
>> -           specified_interface->external_name(), _interfaces->at(i));
>>       }
>
> Overshadowing should be checked before attempting to load the class. 
> Otherwise if the wrongly used super has a different classfile than the 
> specified super we may get class loading errors (see JVMS 5.3.5.3 and 
> 5.3.5.4), e.g. if the specified super wasn't final but we try to use a final 
> class instead of it. I'll extend the related explanation comments in the code.
> 
>> Does this always prevent an unregistered class to use any other unregistered 
>> class as its super type?
> 
> The only way I see for another class to be used instead is for the 
> unregistered class being loaded to reference supertypes of unexpected names 
> in its classfile. But this is an error and it will be detected as such in the 
> C++ code you've cited. If you have any other cases in mind please share.

Sorry I didn't notice the `overshadower == supertype` check. Now I understand 
how it works.

However, I think the logic of the code isn't expressed in the same way as 
mentioned in the comments. That's why I misread it. I would suggest 
restructuring it like this for clarity.

Also, the opposite to "unregistered" is "built-in". We used to have a third 
type (classes for "registered" custom class loaders) but that has been removed, 
leaving us the odd terminology. Maybe we'll clean that up when more support is 
added to custom loaders in Leyden.

BTW, I think we should use "shadow" instead of "overshadow" for brevity.


void ClassListParser::check_supertype_overshadowing(int supertype_id, const 
InstanceKlass* specified_supertype, TRAPS) {
  if (!specified_supertype->is_shared_unregistered_class()) {
    const InstanceKlass* overshadower = 
SystemDictionaryShared::get_unregistered_class(specified_supertype->name());
    if (overshadower != nullptr) {
      // If an unregistered class U is specified to have a built-in supertype S1
      // named SN but an unregistered class S2 also named SN has already been 
loaded
      // S2 will be incorrectly resolved as the supertype of U instead of S1 
due to
      // limitations in the loading mechanism of unregistered classes.
      // This happens very rarely and we don't support such use cases in the 
CDS archive.
      ResourceMark rm;
      THROW_MSG(vmSymbols::java_lang_UnsupportedOperationException(),
                err_msg("%s (id %d) has super-type %s (id %d) overshadowed by 
another class with the same name",
                        _class_name, _id, supertype->external_name(), 
supertype_id));
    }
  }
}

-------------

PR Review Comment: https://git.openjdk.org/jdk/pull/24223#discussion_r2049723549

Reply via email to