@@ -204,6 +204,7 @@ void FileMapInfo::populate_header(size_t core_region_alignment) {
204
204
size_t header_size;
205
205
size_t base_archive_name_size = 0 ;
206
206
size_t base_archive_name_offset = 0 ;
207
+ size_t longest_common_prefix_size = 0 ;
207
208
if (is_static ()) {
208
209
c_header_size = sizeof (FileMapHeader);
209
210
header_size = c_header_size;
@@ -221,24 +222,30 @@ void FileMapInfo::populate_header(size_t core_region_alignment) {
221
222
}
222
223
FREE_C_HEAP_ARRAY (const char , default_base_archive_name);
223
224
}
225
+ ResourceMark rm;
226
+ GrowableArray<const char *>* app_cp_array = create_dumptime_app_classpath_array ();
227
+ int len = app_cp_array->length ();
228
+ longest_common_prefix_size = longest_common_app_classpath_prefix_len (len, app_cp_array);
224
229
_header = (FileMapHeader*)os::malloc (header_size, mtInternal);
225
230
memset ((void *)_header, 0 , header_size);
226
231
_header->populate (this ,
227
232
core_region_alignment,
228
233
header_size,
229
234
base_archive_name_size,
230
- base_archive_name_offset);
235
+ base_archive_name_offset,
236
+ longest_common_prefix_size);
231
237
}
232
238
233
239
void FileMapHeader::populate (FileMapInfo *info, size_t core_region_alignment,
234
240
size_t header_size, size_t base_archive_name_size,
235
- size_t base_archive_name_offset) {
241
+ size_t base_archive_name_offset, size_t common_app_classpath_prefix_size ) {
236
242
// 1. We require _generic_header._magic to be at the beginning of the file
237
243
// 2. FileMapHeader also assumes that _generic_header is at the beginning of the file
238
244
assert (offset_of (FileMapHeader, _generic_header) == 0 , " must be" );
239
245
set_header_size ((unsigned int )header_size);
240
246
set_base_archive_name_offset ((unsigned int )base_archive_name_offset);
241
247
set_base_archive_name_size ((unsigned int )base_archive_name_size);
248
+ set_common_app_classpath_prefix_size ((unsigned int )common_app_classpath_prefix_size);
242
249
set_magic (DynamicDumpSharedSpaces ? CDS_DYNAMIC_ARCHIVE_MAGIC : CDS_ARCHIVE_MAGIC);
243
250
set_version (CURRENT_CDS_ARCHIVE_VERSION);
244
251
@@ -311,6 +318,7 @@ void FileMapHeader::print(outputStream* st) {
311
318
st->print_cr (" - crc: 0x%08x" , crc ());
312
319
st->print_cr (" - version: 0x%x" , version ());
313
320
st->print_cr (" - header_size: " UINT32_FORMAT, header_size ());
321
+ st->print_cr (" - common_app_classpath_size: " UINT32_FORMAT, common_app_classpath_prefix_size ());
314
322
st->print_cr (" - base_archive_name_offset: " UINT32_FORMAT, base_archive_name_offset ());
315
323
st->print_cr (" - base_archive_name_size: " UINT32_FORMAT, base_archive_name_size ());
316
324
@@ -808,6 +816,17 @@ bool FileMapInfo::check_paths_existence(const char* paths) {
808
816
return exist;
809
817
}
810
818
819
+ GrowableArray<const char *>* FileMapInfo::create_dumptime_app_classpath_array () {
820
+ Arguments::assert_is_dumping_archive ();
821
+ GrowableArray<const char *>* path_array = new GrowableArray<const char *>(10 );
822
+ ClassPathEntry* cpe = ClassLoader::app_classpath_entries ();
823
+ while (cpe != NULL ) {
824
+ path_array->append (cpe->name ());
825
+ cpe = cpe->next ();
826
+ }
827
+ return path_array;
828
+ }
829
+
811
830
GrowableArray<const char *>* FileMapInfo::create_path_array (const char * paths) {
812
831
GrowableArray<const char *>* path_array = new GrowableArray<const char *>(10 );
813
832
JavaThread* current = JavaThread::current ();
@@ -842,23 +861,48 @@ bool FileMapInfo::classpath_failure(const char* msg, const char* name) {
842
861
return false ;
843
862
}
844
863
845
- bool FileMapInfo::check_paths (int shared_path_start_idx, int num_paths, GrowableArray<const char *>* rp_array) {
864
+ unsigned int FileMapInfo::longest_common_app_classpath_prefix_len (int num_paths,
865
+ GrowableArray<const char *>* rp_array) {
866
+ if (num_paths == 0 ) {
867
+ return 0 ;
868
+ }
869
+ unsigned int pos;
870
+ for (pos = 0 ; ; pos++) {
871
+ for (int i = 0 ; i < num_paths; i++) {
872
+ if (rp_array->at (i)[pos] != ' \0 ' && rp_array->at (i)[pos] == rp_array->at (0 )[pos]) {
873
+ continue ;
874
+ }
875
+
876
+ // search backward for the pos before the file separator char
877
+ while (pos > 0 && rp_array->at (0 )[--pos] != *os::file_separator ());
878
+ // return the file separator char position
879
+ return pos + 1 ;
880
+ }
881
+ }
882
+ return 0 ;
883
+ }
884
+
885
+ bool FileMapInfo::check_paths (int shared_path_start_idx, int num_paths, GrowableArray<const char *>* rp_array,
886
+ unsigned int dumptime_prefix_len, unsigned int runtime_prefix_len) {
846
887
int i = 0 ;
847
888
int j = shared_path_start_idx;
848
- bool mismatch = false ;
849
- while (i < num_paths && !mismatch) {
889
+ while (i < num_paths) {
850
890
while (shared_path (j)->from_class_path_attr ()) {
851
891
// shared_path(j) was expanded from the JAR file attribute "Class-Path:"
852
892
// during dump time. It's not included in the -classpath VM argument.
853
893
j++;
854
894
}
855
- if (!os::same_files (shared_path (j)->name (), rp_array->at (i))) {
856
- mismatch = true ;
895
+ assert (strlen (shared_path (j)->name ()) > (size_t )dumptime_prefix_len, " sanity" );
896
+ const char * dumptime_path = shared_path (j)->name () + dumptime_prefix_len;
897
+ assert (strlen (rp_array->at (i)) > (size_t )runtime_prefix_len, " sanity" );
898
+ const char * runtime_path = runtime_path = rp_array->at (i) + runtime_prefix_len;
899
+ if (!os::same_files (dumptime_path, runtime_path)) {
900
+ return true ;
857
901
}
858
902
i++;
859
903
j++;
860
904
}
861
- return mismatch ;
905
+ return false ;
862
906
}
863
907
864
908
bool FileMapInfo::validate_boot_class_paths () {
@@ -912,7 +956,7 @@ bool FileMapInfo::validate_boot_class_paths() {
912
956
// check the full runtime boot path, must match with dump time
913
957
num = rp_len;
914
958
}
915
- mismatch = check_paths (1 , num, rp_array);
959
+ mismatch = check_paths (1 , num, rp_array, 0 , 0 );
916
960
} else {
917
961
// create_path_array() ignores non-existing paths. Although the dump time and runtime boot classpath lengths
918
962
// are the same initially, after the call to create_path_array(), the runtime boot classpath length could become
@@ -961,9 +1005,20 @@ bool FileMapInfo::validate_app_class_paths(int shared_app_paths_len) {
961
1005
// run 2: -cp x.jar:NE4:b.jar -> x.jar:b.jar -> mismatched
962
1006
963
1007
int j = header ()->app_class_paths_start_index ();
964
- mismatch = check_paths (j, shared_app_paths_len, rp_array);
1008
+ mismatch = check_paths (j, shared_app_paths_len, rp_array, 0 , 0 );
965
1009
if (mismatch) {
966
- return classpath_failure (" [APP classpath mismatch, actual: -Djava.class.path=" , appcp);
1010
+ // To facilitate app deployment, we allow the JAR files to be moved *together* to
1011
+ // a different location, as long as they are still stored under the same directory
1012
+ // structure. E.g., the following is OK.
1013
+ // java -Xshare:dump -cp /a/Foo.jar:/a/b/Bar.jar ...
1014
+ // java -Xshare:auto -cp /x/y/Foo.jar:/x/y/b/Bar.jar ...
1015
+ unsigned int dumptime_prefix_len = header ()->common_app_classpath_prefix_size ();
1016
+ unsigned int runtime_prefix_len = longest_common_app_classpath_prefix_len (shared_app_paths_len, rp_array);
1017
+ mismatch = check_paths (j, shared_app_paths_len, rp_array,
1018
+ dumptime_prefix_len, runtime_prefix_len);
1019
+ if (mismatch) {
1020
+ return classpath_failure (" [APP classpath mismatch, actual: -Djava.class.path=" , appcp);
1021
+ }
967
1022
}
968
1023
}
969
1024
return true ;
@@ -991,7 +1046,7 @@ bool FileMapInfo::check_module_paths() {
991
1046
}
992
1047
ResourceMark rm;
993
1048
GrowableArray<const char *>* rp_array = create_path_array (rp);
994
- return check_paths (header ()->app_module_paths_start_index (), num_paths, rp_array);
1049
+ return check_paths (header ()->app_module_paths_start_index (), num_paths, rp_array, 0 , 0 );
995
1050
}
996
1051
997
1052
bool FileMapInfo::validate_shared_path_table () {
@@ -1205,6 +1260,10 @@ class FileHeaderHelper {
1205
1260
return false ;
1206
1261
}
1207
1262
1263
+ if (!check_common_app_classpath_prefix_len ()) {
1264
+ return false ;
1265
+ }
1266
+
1208
1267
// All fields in the GenericCDSFileMapHeader has been validated.
1209
1268
_is_valid = true ;
1210
1269
return true ;
@@ -1282,6 +1341,16 @@ class FileHeaderHelper {
1282
1341
_base_archive_name = name;
1283
1342
}
1284
1343
}
1344
+
1345
+ return true ;
1346
+ }
1347
+
1348
+ bool check_common_app_classpath_prefix_len () {
1349
+ int common_path_size = _header->_common_app_classpath_prefix_size ;
1350
+ if (common_path_size < 0 ) {
1351
+ FileMapInfo::fail_continue (" common app classpath prefix len < 0" );
1352
+ return false ;
1353
+ }
1285
1354
return true ;
1286
1355
}
1287
1356
};
@@ -1364,8 +1433,9 @@ bool FileMapInfo::init_from_file(int fd) {
1364
1433
if (base_offset != 0 && name_size != 0 ) {
1365
1434
if (header_size != base_offset + name_size) {
1366
1435
log_info (cds)(" _header_size: " UINT32_FORMAT, header_size);
1367
- log_info (cds)(" base_archive_name_size: " UINT32_FORMAT, name_size);
1368
- log_info (cds)(" base_archive_name_offset: " UINT32_FORMAT, base_offset);
1436
+ log_info (cds)(" common_app_classpath_size: " UINT32_FORMAT, header ()->common_app_classpath_prefix_size ());
1437
+ log_info (cds)(" base_archive_name_size: " UINT32_FORMAT, header ()->base_archive_name_size ());
1438
+ log_info (cds)(" base_archive_name_offset: " UINT32_FORMAT, header ()->base_archive_name_offset ());
1369
1439
FileMapInfo::fail_continue (" The shared archive file has an incorrect header size." );
1370
1440
return false ;
1371
1441
}
0 commit comments