[14] RFR(M): 8211723: AppCDS: referring to a jar file in any way other than exactly how it was done during dumping doesn't work
Calvin Cheung
calvin.cheung at oracle.com
Thu Jun 27 18:56:58 UTC 2019
On 6/26/19, 5:38 PM, Jiangli Zhou wrote:
> Hi Calvin,
>
> On Wed, Jun 26, 2019 at 3:49 PM Calvin Cheung<calvin.cheung at oracle.com> wrote:
>> Hi Jiangli,
>>
>> Thanks for your review!
>>
>> On 6/26/19, 11:14 AM, Jiangli Zhou wrote:
>>> Hi Calvin,
>>>
>>> Thank you for working on this. Really glad to see this finally being
>>> done! I meant to review this earlier, but was delayed. Thank you for
>>> being patient.
>>>
>>> - src/hotspot/share/classfile/classLoader.hpp
>>>
>>> 960 bool ClassLoader::update_class_path_entry_list(const char *path,
>>> 961 bool check_for_duplicates,
>>> 962 bool is_boot_append,
>>> 963 bool from_class_path_attr,
>>> 964 bool throw_exception) {
>>> ...
>>>
>>> 984 #if INCLUDE_CDS
>>> 985 if (DumpSharedSpaces || DynamicDumpSharedSpaces) {
>>> 986 _shared_paths_misc_info->add_nonexist_path(path);
>>> 987 }
>>> 988 #endif
>>>
>>> The above code for _shared_paths_misc_info can be eliminated now. If a
>>> path does not exist at dump time but exists at runtime, it should be
>>> caught by the runtime shared path table check. I think the new check
>>> you added for the shared path table does cover that case. We should
>>> make sure we have sufficient test cases for that. It's good to also
>>> add comments to the shared path table check to describe all cases.
>> I don't think we can remove the above code because it will also update
>> the class path entry list for the jar files which are found from the
>> "Class-Path" attribute of a jar manifest.
>>
>> Below is the various call paths to the function (note the call from
>> process_jar_manifest):
>>
>> ClassLoader::update_class_path_entry_list(const char *, bool, bool,
>> bool, bool) : bool
>> ClassLoader::setup_app_search_path(const char *) : void
>> ClassLoader::setup_boot_search_path(const char *) : void
>> ClassLoaderExt::process_jar_manifest(ClassPathEntry *, bool) : void
>> ClassLoader::add_to_app_classpath_entries(const char *,
>> ClassPathEntry *, bool) : void
>> ClassLoader::update_class_path_entry_list(const char *,
>> bool, bool, bool, bool) : bool
> I was referring to the #if INCLUDED_CDS code for
> _shared_paths_misc_info. It's no longer needed.
>
> 984 #if INCLUDE_CDS
> 985 if (DumpSharedSpaces || DynamicDumpSharedSpaces) {
> 986 _shared_paths_misc_info->add_nonexist_path(path);
> 987 }
> 988 #endif
>
> The rest of ClassLoader::update_class_path_entry_list() is still needed.
Without the above code, it will fail with the following sceanrio:
non-existing jar during dump time but jar exists during runtime
I've added 2 test scenarios in the AppendClasspath.java test.
Updated webrevs:
incremental: http://cr.openjdk.java.net/~ccheung/8211723/delta_01_02/
full: http://cr.openjdk.java.net/~ccheung/8211723/webrev.02/
>
>>>
>>> - src/hotspot/share/memory/filemap.hpp
>>>
>>> 63 void init(const char* name, bool is_modules_image,
>>> ClassPathEntry* cpe, TRAPS);
>>>
>>> The 'name' argument can be removed since it can be retrieved from
>>> 'cpe', as you are passing the ClassPathEntry now.
>> I've made the change.
>>> - src/hotspot/share/classfile/sharedPathsMiscInfo.cpp
>>>
>>> With the removal of the problematic file name string comparison, the
>>> SharedPathsMiscInfo::check() becomes basically a no-op now. It should
>>> be removed now.
>>>
>>> 156 bool SharedPathsMiscInfo::check(jint type, const char* path, bool
>>> is_static) {
>>> 157 assert(UseSharedSpaces, "runtime only");
>>> 158 switch (type) {
>>> 159 case BOOT_PATH:
>>> 160 break;
>>> 161 case NON_EXIST:
>>> 162 {
>>> 163 struct stat st;
>>> 164 if (os::stat(path,&st) == 0) {
>>> 165 // The file actually exists
>>> 166 // But we want it to not exist -> fail
>>> 167 return fail("File must not exist");
>>> 168 }
>>> 169 }
>>> 170 break;
>>> 171 case APP_PATH:
>>> 172 break;
>>> 173 default:
>>> 174 return fail("Corrupted archive file header");
>>> 175 }
>>> 176
>>> 177 return true;
>>> 178 }
>>>
>>> The following function should also be removed:
>>> 107 bool SharedPathsMiscInfo::check(bool is_static) {
>> The above functions can't be removed yet due to the same reasoning as
>> above. It ensures the non-existing of the jar file(s) found in the
>> "Class-Path" attributes.
> I think we can enhance your current change to record the
> 'non-existing' manifest Class-Path header referenced JAR files in the
> shared path table at dump time. An entry can be added to the table and
> flagged as 'non-existing' if one is such a case. At runtime, you can
> check for that then. Please let me know if it's a bit vague, I can add
> more details.
As per our off-list discussion, this could be done in a follow-up RFE.
I'll ask you for more details when I file the RFE.
thanks,
Calvin
>
> Best regards,
> Jiangli
>> Call paths to the function:
>>
>> SharedPathsMiscInfo::check(jint, const char *, bool) : bool
>> SharedPathsMiscInfo::check(bool) : bool
>> ClassLoader::check_shared_paths_misc_info(void *, int, bool) : bool
>> FileMapInfo::validate_header(bool) : bool
>> FileMapInfo::initialize(bool) : bool
>> DynamicArchive::map_impl(FileMapInfo *) : address
>>
>> MetaspaceShared::initialize_runtime_shared_and_meta_spaces() : void
>>> There are quite some additional SharedPathsMiscInfo cleanup and
>>> removal needed. If you want to do those in separate changeset, that is
>>> also okay. The cleanups will help make the CDS code more maintainable.
>> I agree that cleaning up SharedPathsMiscInfo is possible but more
>> thinking is required. So it should be done as a separate RFE/changeset.
>>
>>> - src/hotspot/os/posix/os_posix.cpp
>>>
>>> 1463 ret1 = os::stat(file1,&st1);
>>> 1464 ret2 = os::stat(file2,&st2);
>>> 1465 if (ret1< 0 || ret2< 0) {
>>> 1466 // one of the files is invalid. So they are not the same.
>>> 1467 is_same = false;
>>> 1468 } else if (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino) {
>>> 1469 // different files
>>> 1470 is_same = false;
>>> 1471 } else if (st1.st_dev == st2.st_dev&& st1.st_ino == st2.st_ino) {
>>> 1472 // same files
>>> 1473 is_same = true;
>>> 1474 }
>>> 1475 return is_same;
>>>
>>> The 'is_same' is initialized to false, so the cases where the files
>>> are different do not need to be checked explicitly. We just need to
>>> make sure 'is_same' is set to true for the case where the two files
>>> are the same. So you can simplify and optimize the above a bit:
>>>
>>> if (os::stat(file1,&st1) != 0) {
>>> return false;
>>> }
>>> if (os::stat(file2,&st2) != 0) {
>>> return false;
>>> }
>>> if (st1.st_dev == st2.st_dev&& st1.st_ino == st2.st_ino) {
>>> is_same = true;
>>> }
>>> return is_same;
>> I've made the above change but checking the return status of os::stat as
>> what I had before because ::stat returns -1 on failure:
>> if (os::stat(file1,&st1)< 0) {
>> return false;
>> }
>>
>> if (os::stat(file2,&st2)< 0) {
>> return false;
>> }
>>
>>
>> So far I've changed:
>> M src/hotspot/os/posix/os_posix.cpp
>> M src/hotspot/share/memory/filemap.cpp
>> M src/hotspot/share/memory/filemap.hpp
>>
>> I'll do more testing before sending an updated webrevs.
>>
>> thanks,
>> Calvin
>>> Best regards,
>>>
>>> Jiangli
More information about the hotspot-runtime-dev
mailing list