194 |
196 |
195 // JVM version string ... changes on each build. |
197 // JVM version string ... changes on each build. |
196 get_header_version(_jvm_ident); |
198 get_header_version(_jvm_ident); |
197 } |
199 } |
198 |
200 |
|
201 void SharedClassPathEntry::init(const char* name, TRAPS) { |
|
202 _timestamp = 0; |
|
203 _filesize = 0; |
|
204 |
|
205 struct stat st; |
|
206 if (os::stat(name, &st) == 0) { |
|
207 if ((st.st_mode & S_IFMT) == S_IFDIR) { |
|
208 if (!os::dir_is_empty(name)) { |
|
209 ClassLoader::exit_with_path_failure( |
|
210 "Cannot have non-empty directory in archived classpaths", name); |
|
211 } |
|
212 _is_dir = true; |
|
213 } else { |
|
214 _is_dir = false; |
|
215 _timestamp = st.st_mtime; |
|
216 _filesize = st.st_size; |
|
217 } |
|
218 } else { |
|
219 // The file/dir must exist, or it would not have been added |
|
220 // into ClassLoader::classpath_entry(). |
|
221 // |
|
222 // If we can't access a jar file in the boot path, then we can't |
|
223 // make assumptions about where classes get loaded from. |
|
224 FileMapInfo::fail_stop("Unable to open file %s.", name); |
|
225 } |
|
226 |
|
227 size_t len = strlen(name) + 1; |
|
228 _name = MetadataFactory::new_array<char>(ClassLoaderData::the_null_class_loader_data(), (int)len, THREAD); |
|
229 strcpy(_name->data(), name); |
|
230 } |
|
231 |
|
232 bool SharedClassPathEntry::validate() { |
|
233 struct stat st; |
|
234 const char* name = this->name(); |
|
235 bool ok = true; |
|
236 log_info(class, path)("checking shared classpath entry: %s", name); |
|
237 if (os::stat(name, &st) != 0) { |
|
238 FileMapInfo::fail_continue("Required classpath entry does not exist: %s", name); |
|
239 ok = false; |
|
240 } else if (is_dir()) { |
|
241 if (!os::dir_is_empty(name)) { |
|
242 FileMapInfo::fail_continue("directory is not empty: %s", name); |
|
243 ok = false; |
|
244 } |
|
245 } else if (is_jar_or_bootimage()) { |
|
246 if (_timestamp != st.st_mtime || |
|
247 _filesize != st.st_size) { |
|
248 ok = false; |
|
249 if (PrintSharedArchiveAndExit) { |
|
250 FileMapInfo::fail_continue(_timestamp != st.st_mtime ? |
|
251 "Timestamp mismatch" : |
|
252 "File size mismatch"); |
|
253 } else { |
|
254 FileMapInfo::fail_continue("A jar/jimage file is not the one used while building" |
|
255 " the shared archive file: %s", name); |
|
256 } |
|
257 } |
|
258 } |
|
259 return ok; |
|
260 } |
|
261 |
|
262 void SharedClassPathEntry::metaspace_pointers_do(MetaspaceClosure* it) { |
|
263 it->push(&_name); |
|
264 it->push(&_manifest); |
|
265 } |
|
266 |
199 void FileMapInfo::allocate_classpath_entry_table() { |
267 void FileMapInfo::allocate_classpath_entry_table() { |
200 int bytes = 0; |
|
201 int count = 0; |
|
202 char* strptr = NULL; |
|
203 char* strptr_max = NULL; |
|
204 Thread* THREAD = Thread::current(); |
268 Thread* THREAD = Thread::current(); |
205 |
|
206 ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data(); |
269 ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data(); |
207 size_t entry_size = SharedClassUtil::shared_class_path_entry_size(); |
270 size_t entry_size = SharedClassUtil::shared_class_path_entry_size(); // assert ( should be 8 byte aligned??) |
208 |
271 int num_entries = ClassLoader::number_of_classpath_entries(); |
209 for (int pass=0; pass<2; pass++) { |
272 size_t bytes = entry_size * num_entries; |
210 |
273 |
211 // Process the modular java runtime image first |
274 _classpath_entry_table = MetadataFactory::new_array<u8>(loader_data, (int)(bytes + 7 / 8), THREAD); |
212 ClassPathEntry* jrt_entry = ClassLoader::get_jrt_entry(); |
275 _classpath_entry_table_size = num_entries; |
213 assert(jrt_entry != NULL, |
276 _classpath_entry_size = entry_size; |
214 "No modular java runtime image present when allocating the CDS classpath entry table"); |
277 |
215 const char *name = jrt_entry->name(); |
278 assert(ClassLoader::get_jrt_entry() != NULL, |
216 int name_bytes = (int)(strlen(name) + 1); |
279 "No modular java runtime image present when allocating the CDS classpath entry table"); |
217 if (pass == 0) { |
280 |
218 count++; |
281 for (int i=0; i<num_entries; i++) { |
219 bytes += (int)entry_size; |
282 ClassPathEntry *cpe = ClassLoader::classpath_entry(i); |
220 bytes += name_bytes; |
283 const char* type = ((i == 0) ? "jrt" : (cpe->is_jar_file() ? "jar" : "dir")); |
221 log_info(class, path)("add main shared path for modular java runtime image %s", name); |
284 |
222 } else { |
285 log_info(class, path)("add main shared path (%s) %s", type, cpe->name()); |
223 // The java runtime image is always in slot 0 on the shared class path. |
286 SharedClassPathEntry* ent = shared_classpath(i); |
224 SharedClassPathEntry* ent = shared_classpath(0); |
287 ent->init(cpe->name(), THREAD); |
225 struct stat st; |
288 |
226 if (os::stat(name, &st) == 0) { |
289 if (i > 0) { // No need to do jimage. |
227 ent->_timestamp = st.st_mtime; |
|
228 ent->_filesize = st.st_size; |
|
229 } |
|
230 if (ent->_filesize == 0) { |
|
231 // unknown |
|
232 ent->_filesize = -2; |
|
233 } |
|
234 ent->_name = strptr; |
|
235 assert(strptr + name_bytes <= strptr_max, "miscalculated buffer size"); |
|
236 strncpy(strptr, name, (size_t)name_bytes); // name_bytes includes trailing 0. |
|
237 strptr += name_bytes; |
|
238 } |
|
239 |
|
240 // Walk the appended entries, which includes the entries added for the classpath. |
|
241 ClassPathEntry *cpe = ClassLoader::classpath_entry(1); |
|
242 |
|
243 // Since the java runtime image is always in slot 0 on the shared class path, the |
|
244 // appended entries are started at slot 1 immediately after. |
|
245 for (int cur_entry = 1 ; cpe != NULL; cpe = cpe->next(), cur_entry++) { |
|
246 const char *name = cpe->name(); |
|
247 int name_bytes = (int)(strlen(name) + 1); |
|
248 assert(!cpe->is_jrt(), "A modular java runtime image is present on the list of appended entries"); |
|
249 |
|
250 if (pass == 0) { |
|
251 count ++; |
|
252 bytes += (int)entry_size; |
|
253 bytes += name_bytes; |
|
254 log_info(class, path)("add main shared path (%s) %s", (cpe->is_jar_file() ? "jar" : "dir"), name); |
|
255 } else { |
|
256 SharedClassPathEntry* ent = shared_classpath(cur_entry); |
|
257 if (cpe->is_jar_file()) { |
|
258 struct stat st; |
|
259 if (os::stat(name, &st) != 0) { |
|
260 // The file/dir must exist, or it would not have been added |
|
261 // into ClassLoader::classpath_entry(). |
|
262 // |
|
263 // If we can't access a jar file in the boot path, then we can't |
|
264 // make assumptions about where classes get loaded from. |
|
265 FileMapInfo::fail_stop("Unable to open jar file %s.", name); |
|
266 } |
|
267 |
|
268 EXCEPTION_MARK; // The following call should never throw, but would exit VM on error. |
|
269 SharedClassUtil::update_shared_classpath(cpe, ent, st.st_mtime, st.st_size, THREAD); |
|
270 } else { |
|
271 struct stat st; |
|
272 if (os::stat(name, &st) == 0) { |
|
273 if ((st.st_mode & S_IFMT) == S_IFDIR) { |
|
274 if (!os::dir_is_empty(name)) { |
|
275 ClassLoader::exit_with_path_failure( |
|
276 "Cannot have non-empty directory in archived classpaths", name); |
|
277 } |
|
278 ent->_filesize = -1; |
|
279 } |
|
280 } |
|
281 if (ent->_filesize == 0) { |
|
282 // unknown |
|
283 ent->_filesize = -2; |
|
284 } |
|
285 } |
|
286 ent->_name = strptr; |
|
287 if (strptr + name_bytes <= strptr_max) { |
|
288 strncpy(strptr, name, (size_t)name_bytes); // name_bytes includes trailing 0. |
|
289 strptr += name_bytes; |
|
290 } else { |
|
291 assert(0, "miscalculated buffer size"); |
|
292 } |
|
293 } |
|
294 } |
|
295 |
|
296 if (pass == 0) { |
|
297 EXCEPTION_MARK; // The following call should never throw, but would exit VM on error. |
290 EXCEPTION_MARK; // The following call should never throw, but would exit VM on error. |
298 Array<u8>* arr = MetadataFactory::new_array<u8>(loader_data, (bytes + 7)/8, THREAD); |
291 SharedClassUtil::update_shared_classpath(cpe, ent, THREAD); |
299 strptr = (char*)(arr->data()); |
|
300 strptr_max = strptr + bytes; |
|
301 SharedClassPathEntry* table = (SharedClassPathEntry*)strptr; |
|
302 strptr += entry_size * count; |
|
303 |
|
304 _classpath_entry_table_size = count; |
|
305 _classpath_entry_table = table; |
|
306 _classpath_entry_size = entry_size; |
|
307 } |
292 } |
308 } |
293 } |
309 } |
294 } |
310 |
295 |
311 bool FileMapInfo::validate_classpath_entry_table() { |
296 bool FileMapInfo::validate_classpath_entry_table() { |
313 |
298 |
314 int count = _header->_classpath_entry_table_size; |
299 int count = _header->_classpath_entry_table_size; |
315 |
300 |
316 _classpath_entry_table = _header->_classpath_entry_table; |
301 _classpath_entry_table = _header->_classpath_entry_table; |
317 _classpath_entry_size = _header->_classpath_entry_size; |
302 _classpath_entry_size = _header->_classpath_entry_size; |
|
303 _classpath_entry_table_size = _header->_classpath_entry_table_size; |
318 |
304 |
319 for (int i=0; i<count; i++) { |
305 for (int i=0; i<count; i++) { |
320 SharedClassPathEntry* ent = shared_classpath(i); |
306 if (shared_classpath(i)->validate()) { |
321 struct stat st; |
|
322 const char* name = ent->_name; |
|
323 bool ok = true; |
|
324 log_info(class, path)("checking shared classpath entry: %s", name); |
|
325 if (os::stat(name, &st) != 0) { |
|
326 fail_continue("Required classpath entry does not exist: %s", name); |
|
327 ok = false; |
|
328 } else if (ent->is_dir()) { |
|
329 if (!os::dir_is_empty(name)) { |
|
330 fail_continue("directory is not empty: %s", name); |
|
331 ok = false; |
|
332 } |
|
333 } else if (ent->is_jar_or_bootimage()) { |
|
334 if (ent->_timestamp != st.st_mtime || |
|
335 ent->_filesize != st.st_size) { |
|
336 ok = false; |
|
337 if (PrintSharedArchiveAndExit) { |
|
338 fail_continue(ent->_timestamp != st.st_mtime ? |
|
339 "Timestamp mismatch" : |
|
340 "File size mismatch"); |
|
341 } else { |
|
342 fail_continue("A jar/jimage file is not the one used while building" |
|
343 " the shared archive file: %s", name); |
|
344 } |
|
345 } |
|
346 } |
|
347 if (ok) { |
|
348 log_info(class, path)("ok"); |
307 log_info(class, path)("ok"); |
349 } else if (!PrintSharedArchiveAndExit) { |
308 } else if (!PrintSharedArchiveAndExit) { |
350 _validating_classpath_entry_table = false; |
309 _validating_classpath_entry_table = false; |
|
310 _classpath_entry_table = NULL; |
|
311 _classpath_entry_table_size = 0; |
351 return false; |
312 return false; |
352 } |
313 } |
353 } |
314 } |
354 |
315 |
355 _classpath_entry_table_size = _header->_classpath_entry_table_size; |
|
356 _validating_classpath_entry_table = false; |
316 _validating_classpath_entry_table = false; |
357 return true; |
317 return true; |
358 } |
318 } |
359 |
319 |
360 |
320 |
467 write_bytes(ClassLoader::get_shared_paths_misc_info(), info_size); |
427 write_bytes(ClassLoader::get_shared_paths_misc_info(), info_size); |
468 align_file_position(); |
428 align_file_position(); |
469 } |
429 } |
470 |
430 |
471 |
431 |
472 // Dump shared spaces to file. |
|
473 |
|
474 void FileMapInfo::write_space(int i, Metaspace* space, bool read_only) { |
|
475 align_file_position(); |
|
476 size_t used = space->used_bytes_slow(Metaspace::NonClassType); |
|
477 size_t capacity = space->capacity_bytes_slow(Metaspace::NonClassType); |
|
478 struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[i]; |
|
479 write_region(i, (char*)space->bottom(), used, capacity, read_only, false); |
|
480 } |
|
481 |
|
482 |
|
483 // Dump region to file. |
432 // Dump region to file. |
484 |
433 |
485 void FileMapInfo::write_region(int region, char* base, size_t size, |
434 void FileMapInfo::write_region(int region, char* base, size_t size, |
486 size_t capacity, bool read_only, |
435 bool read_only, bool allow_exec) { |
487 bool allow_exec) { |
|
488 struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[region]; |
436 struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[region]; |
489 |
437 |
490 if (_file_open) { |
438 if (_file_open) { |
491 guarantee(si->_file_offset == _file_offset, "file offset mismatch."); |
439 guarantee(si->_file_offset == _file_offset, "file offset mismatch."); |
492 log_info(cds)("Shared file region %d: " SIZE_FORMAT_HEX_W(6) |
440 log_info(cds)("Shared file region %d: " SIZE_FORMAT_HEX_W(08) |
493 " bytes, addr " INTPTR_FORMAT " file offset " SIZE_FORMAT_HEX_W(6), |
441 " bytes, addr " INTPTR_FORMAT " file offset " SIZE_FORMAT_HEX_W(08), |
494 region, size, p2i(base), _file_offset); |
442 region, size, p2i(base), _file_offset); |
495 } else { |
443 } else { |
496 si->_file_offset = _file_offset; |
444 si->_file_offset = _file_offset; |
497 } |
445 } |
498 if (MetaspaceShared::is_string_region(region)) { |
446 if (MetaspaceShared::is_string_region(region)) { |
521 // than one GC regions allocated for shared strings. The first/bottom GC region might |
468 // than one GC regions allocated for shared strings. The first/bottom GC region might |
522 // be a partial GC region with the empty portion at the higher address within that region. |
469 // be a partial GC region with the empty portion at the higher address within that region. |
523 // The non-empty portion of the first region is written into the archive as one string |
470 // The non-empty portion of the first region is written into the archive as one string |
524 // region. The rest are consecutive full GC regions if they exist, which can be written |
471 // region. The rest are consecutive full GC regions if they exist, which can be written |
525 // out in one chunk as another string region. |
472 // out in one chunk as another string region. |
526 void FileMapInfo::write_string_regions(GrowableArray<MemRegion> *regions) { |
473 // |
|
474 // Here's the mapping from (GrowableArray<MemRegion> *regions) -> (metaspace string regions). |
|
475 // + We have 1 or more heap regions: r0, r1, r2 ..... rn |
|
476 // + We have 2 metaspace string regions: s0 and s1 |
|
477 // |
|
478 // If there's a single heap region (r0), then s0 == r0, and s1 is empty. |
|
479 // Otherwise: |
|
480 // |
|
481 // "X" represented space that's occupied by heap objects. |
|
482 // "_" represented unused spaced in the heap region. |
|
483 // |
|
484 // |
|
485 // |r0 | r1 | r2 | ...... | rn | |
|
486 // |XXXXXX|__ |XXXXX|XXXX|XXXXXXXX|XXXX| |
|
487 // |<-s0->| |<- s1 ----------------->| |
|
488 // ^^^ |
|
489 // | |
|
490 // +-- unmapped space |
|
491 void FileMapInfo::write_string_regions(GrowableArray<MemRegion> *regions, |
|
492 char** st0_start, char** st0_top, char** st0_end, |
|
493 char** st1_start, char** st1_top, char** st1_end) { |
|
494 *st0_start = *st0_top = *st0_end = NULL; |
|
495 *st1_start = *st1_top = *st1_end = NULL; |
|
496 |
|
497 assert(MetaspaceShared::max_strings == 2, "this loop doesn't work for any other value"); |
527 for (int i = MetaspaceShared::first_string; |
498 for (int i = MetaspaceShared::first_string; |
528 i < MetaspaceShared::first_string + MetaspaceShared::max_strings; i++) { |
499 i < MetaspaceShared::first_string + MetaspaceShared::max_strings; i++) { |
529 char* start = NULL; |
500 char* start = NULL; |
530 size_t size = 0; |
501 size_t size = 0; |
531 if (regions->is_nonempty()) { |
502 int len = regions->length(); |
|
503 if (len > 0) { |
532 if (i == MetaspaceShared::first_string) { |
504 if (i == MetaspaceShared::first_string) { |
533 MemRegion first = regions->first(); |
505 MemRegion first = regions->first(); |
534 start = (char*)first.start(); |
506 start = (char*)first.start(); |
535 size = first.byte_size(); |
507 size = first.byte_size(); |
|
508 *st0_start = start; |
|
509 *st0_top = start + size; |
|
510 if (len > 1) { |
|
511 *st0_end = (char*)regions->at(1).start(); |
|
512 } else { |
|
513 *st0_end = start + size; |
|
514 } |
536 } else { |
515 } else { |
537 int len = regions->length(); |
516 assert(i == MetaspaceShared::first_string + 1, "must be"); |
538 if (len > 1) { |
517 if (len > 1) { |
539 start = (char*)regions->at(1).start(); |
518 start = (char*)regions->at(1).start(); |
540 size = (char*)regions->at(len - 1).end() - start; |
519 size = (char*)regions->at(len - 1).end() - start; |
|
520 *st1_start = start; |
|
521 *st1_top = start + size; |
|
522 *st1_end = start + size; |
541 } |
523 } |
542 } |
524 } |
543 } |
525 } |
544 write_region(i, start, size, size, false, false); |
526 log_info(cds)("String region %d " INTPTR_FORMAT " - " INTPTR_FORMAT " = " SIZE_FORMAT_W(8) " bytes", |
|
527 i, p2i(start), p2i(start + size), size); |
|
528 write_region(i, start, size, false, false); |
545 } |
529 } |
546 } |
530 } |
547 |
531 |
548 |
532 |
549 // Dump bytes to file -- at the current file position. |
533 // Dump bytes to file -- at the current file position. |