115 sprintf(&header_version[JVM_IDENT_MAX-9], "%08x", hash); |
134 sprintf(&header_version[JVM_IDENT_MAX-9], "%08x", hash); |
116 header_version[JVM_IDENT_MAX-1] = 0; // Null terminate. |
135 header_version[JVM_IDENT_MAX-1] = 0; // Null terminate. |
117 } |
136 } |
118 } |
137 } |
119 |
138 |
|
139 FileMapInfo::FileMapInfo() { |
|
140 assert(_current_info == NULL, "must be singleton"); // not thread safe |
|
141 _current_info = this; |
|
142 memset(this, 0, sizeof(FileMapInfo)); |
|
143 _file_offset = 0; |
|
144 _file_open = false; |
|
145 _header = SharedClassUtil::allocate_file_map_header(); |
|
146 _header->_version = _invalid_version; |
|
147 } |
|
148 |
|
149 FileMapInfo::~FileMapInfo() { |
|
150 assert(_current_info == this, "must be singleton"); // not thread safe |
|
151 _current_info = NULL; |
|
152 } |
|
153 |
120 void FileMapInfo::populate_header(size_t alignment) { |
154 void FileMapInfo::populate_header(size_t alignment) { |
121 _header._magic = 0xf00baba2; |
155 _header->populate(this, alignment); |
122 _header._version = _current_version; |
156 } |
123 _header._alignment = alignment; |
157 |
124 _header._obj_alignment = ObjectAlignmentInBytes; |
158 size_t FileMapInfo::FileMapHeader::data_size() { |
|
159 return SharedClassUtil::file_map_header_size() - sizeof(FileMapInfo::FileMapHeaderBase); |
|
160 } |
|
161 |
|
162 void FileMapInfo::FileMapHeader::populate(FileMapInfo* mapinfo, size_t alignment) { |
|
163 _magic = 0xf00baba2; |
|
164 _version = _current_version; |
|
165 _alignment = alignment; |
|
166 _obj_alignment = ObjectAlignmentInBytes; |
|
167 _classpath_entry_table_size = mapinfo->_classpath_entry_table_size; |
|
168 _classpath_entry_table = mapinfo->_classpath_entry_table; |
|
169 _classpath_entry_size = mapinfo->_classpath_entry_size; |
125 |
170 |
126 // The following fields are for sanity checks for whether this archive |
171 // The following fields are for sanity checks for whether this archive |
127 // will function correctly with this JVM and the bootclasspath it's |
172 // will function correctly with this JVM and the bootclasspath it's |
128 // invoked with. |
173 // invoked with. |
129 |
174 |
130 // JVM version string ... changes on each build. |
175 // JVM version string ... changes on each build. |
131 get_header_version(_header._jvm_ident); |
176 get_header_version(_jvm_ident); |
132 |
177 } |
133 // Build checks on classpath and jar files |
178 |
134 _header._num_jars = 0; |
179 void FileMapInfo::allocate_classpath_entry_table() { |
135 ClassPathEntry *cpe = ClassLoader::classpath_entry(0); |
180 int bytes = 0; |
136 for ( ; cpe != NULL; cpe = cpe->next()) { |
181 int count = 0; |
137 |
182 char* strptr = NULL; |
138 if (cpe->is_jar_file()) { |
183 char* strptr_max = NULL; |
139 if (_header._num_jars >= JVM_SHARED_JARS_MAX) { |
184 Thread* THREAD = Thread::current(); |
140 fail_stop("Too many jar files to share.", NULL); |
185 |
|
186 ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data(); |
|
187 size_t entry_size = SharedClassUtil::shared_class_path_entry_size(); |
|
188 |
|
189 for (int pass=0; pass<2; pass++) { |
|
190 ClassPathEntry *cpe = ClassLoader::classpath_entry(0); |
|
191 |
|
192 for (int cur_entry = 0 ; cpe != NULL; cpe = cpe->next(), cur_entry++) { |
|
193 const char *name = cpe->name(); |
|
194 int name_bytes = (int)(strlen(name) + 1); |
|
195 |
|
196 if (pass == 0) { |
|
197 count ++; |
|
198 bytes += (int)entry_size; |
|
199 bytes += name_bytes; |
|
200 if (TraceClassPaths || (TraceClassLoading && Verbose)) { |
|
201 tty->print_cr("[Add main shared path (%s) %s]", (cpe->is_jar_file() ? "jar" : "dir"), name); |
|
202 } |
|
203 } else { |
|
204 SharedClassPathEntry* ent = shared_classpath(cur_entry); |
|
205 if (cpe->is_jar_file()) { |
|
206 struct stat st; |
|
207 if (os::stat(name, &st) != 0) { |
|
208 // The file/dir must exist, or it would not have been added |
|
209 // into ClassLoader::classpath_entry(). |
|
210 // |
|
211 // If we can't access a jar file in the boot path, then we can't |
|
212 // make assumptions about where classes get loaded from. |
|
213 FileMapInfo::fail_stop("Unable to open jar file %s.", name); |
|
214 } |
|
215 |
|
216 EXCEPTION_MARK; // The following call should never throw, but would exit VM on error. |
|
217 SharedClassUtil::update_shared_classpath(cpe, ent, st.st_mtime, st.st_size, THREAD); |
|
218 } else { |
|
219 ent->_filesize = -1; |
|
220 if (!os::dir_is_empty(name)) { |
|
221 ClassLoader::exit_with_path_failure("Cannot have non-empty directory in archived classpaths", name); |
|
222 } |
|
223 } |
|
224 ent->_name = strptr; |
|
225 if (strptr + name_bytes <= strptr_max) { |
|
226 strncpy(strptr, name, (size_t)name_bytes); // name_bytes includes trailing 0. |
|
227 strptr += name_bytes; |
|
228 } else { |
|
229 assert(0, "miscalculated buffer size"); |
|
230 } |
141 } |
231 } |
142 |
232 } |
143 // Jar file - record timestamp and file size. |
233 |
144 struct stat st; |
234 if (pass == 0) { |
145 const char *path = cpe->name(); |
235 EXCEPTION_MARK; // The following call should never throw, but would exit VM on error. |
146 if (os::stat(path, &st) != 0) { |
236 Array<u8>* arr = MetadataFactory::new_array<u8>(loader_data, (bytes + 7)/8, THREAD); |
147 // If we can't access a jar file in the boot path, then we can't |
237 strptr = (char*)(arr->data()); |
148 // make assumptions about where classes get loaded from. |
238 strptr_max = strptr + bytes; |
149 fail_stop("Unable to open jar file %s.", path); |
239 SharedClassPathEntry* table = (SharedClassPathEntry*)strptr; |
|
240 strptr += entry_size * count; |
|
241 |
|
242 _classpath_entry_table_size = count; |
|
243 _classpath_entry_table = table; |
|
244 _classpath_entry_size = entry_size; |
|
245 } |
|
246 } |
|
247 } |
|
248 |
|
249 bool FileMapInfo::validate_classpath_entry_table() { |
|
250 _validating_classpath_entry_table = true; |
|
251 |
|
252 int count = _header->_classpath_entry_table_size; |
|
253 |
|
254 _classpath_entry_table = _header->_classpath_entry_table; |
|
255 _classpath_entry_size = _header->_classpath_entry_size; |
|
256 |
|
257 for (int i=0; i<count; i++) { |
|
258 SharedClassPathEntry* ent = shared_classpath(i); |
|
259 struct stat st; |
|
260 const char* name = ent->_name; |
|
261 bool ok = true; |
|
262 if (TraceClassPaths || (TraceClassLoading && Verbose)) { |
|
263 tty->print_cr("[Checking shared classpath entry: %s]", name); |
|
264 } |
|
265 if (os::stat(name, &st) != 0) { |
|
266 fail_continue("Required classpath entry does not exist: %s", name); |
|
267 ok = false; |
|
268 } else if (ent->is_dir()) { |
|
269 if (!os::dir_is_empty(name)) { |
|
270 fail_continue("directory is not empty: %s", name); |
|
271 ok = false; |
150 } |
272 } |
151 _header._jar[_header._num_jars]._timestamp = st.st_mtime; |
|
152 _header._jar[_header._num_jars]._filesize = st.st_size; |
|
153 _header._num_jars++; |
|
154 } else { |
273 } else { |
155 |
274 if (ent->_timestamp != st.st_mtime || |
156 // If directories appear in boot classpath, they must be empty to |
275 ent->_filesize != st.st_size) { |
157 // avoid having to verify each individual class file. |
276 ok = false; |
158 const char* name = ((ClassPathDirEntry*)cpe)->name(); |
277 if (PrintSharedArchiveAndExit) { |
159 if (!os::dir_is_empty(name)) { |
278 fail_continue(ent->_timestamp != st.st_mtime ? |
160 fail_stop("Boot classpath directory %s is not empty.", name); |
279 "Timestamp mismatch" : |
|
280 "File size mismatch"); |
|
281 } else { |
|
282 fail_continue("A jar file is not the one used while building" |
|
283 " the shared archive file: %s", name); |
|
284 } |
161 } |
285 } |
162 } |
286 } |
163 } |
287 if (ok) { |
|
288 if (TraceClassPaths || (TraceClassLoading && Verbose)) { |
|
289 tty->print_cr("[ok]"); |
|
290 } |
|
291 } else if (!PrintSharedArchiveAndExit) { |
|
292 _validating_classpath_entry_table = false; |
|
293 return false; |
|
294 } |
|
295 } |
|
296 |
|
297 _classpath_entry_table_size = _header->_classpath_entry_table_size; |
|
298 _validating_classpath_entry_table = false; |
|
299 return true; |
164 } |
300 } |
165 |
301 |
166 |
302 |
167 // Read the FileMapInfo information from the file. |
303 // Read the FileMapInfo information from the file. |
168 |
304 |
169 bool FileMapInfo::init_from_file(int fd) { |
305 bool FileMapInfo::init_from_file(int fd) { |
170 |
306 size_t sz = _header->data_size(); |
171 size_t n = read(fd, &_header, sizeof(struct FileMapHeader)); |
307 char* addr = _header->data(); |
172 if (n != sizeof(struct FileMapHeader)) { |
308 size_t n = os::read(fd, addr, (unsigned int)sz); |
|
309 if (n != sz) { |
173 fail_continue("Unable to read the file header."); |
310 fail_continue("Unable to read the file header."); |
174 return false; |
311 return false; |
175 } |
312 } |
176 if (_header._version != current_version()) { |
313 if (_header->_version != current_version()) { |
177 fail_continue("The shared archive file has the wrong version."); |
314 fail_continue("The shared archive file has the wrong version."); |
178 return false; |
315 return false; |
179 } |
316 } |
180 _file_offset = (long)n; |
317 _file_offset = (long)n; |
|
318 |
|
319 size_t info_size = _header->_paths_misc_info_size; |
|
320 _paths_misc_info = NEW_C_HEAP_ARRAY_RETURN_NULL(char, info_size, mtClass); |
|
321 if (_paths_misc_info == NULL) { |
|
322 fail_continue("Unable to read the file header."); |
|
323 return false; |
|
324 } |
|
325 n = os::read(fd, _paths_misc_info, (unsigned int)info_size); |
|
326 if (n != info_size) { |
|
327 fail_continue("Unable to read the shared path info header."); |
|
328 FREE_C_HEAP_ARRAY(char, _paths_misc_info, mtClass); |
|
329 _paths_misc_info = NULL; |
|
330 return false; |
|
331 } |
|
332 |
|
333 _file_offset += (long)n; |
181 return true; |
334 return true; |
182 } |
335 } |
183 |
336 |
184 |
337 |
185 // Read the FileMapInfo information from the file. |
338 // Read the FileMapInfo information from the file. |
230 |
383 |
231 |
384 |
232 // Write the header to the file, seek to the next allocation boundary. |
385 // Write the header to the file, seek to the next allocation boundary. |
233 |
386 |
234 void FileMapInfo::write_header() { |
387 void FileMapInfo::write_header() { |
235 write_bytes_aligned(&_header, sizeof(FileMapHeader)); |
388 int info_size = ClassLoader::get_shared_paths_misc_info_size(); |
|
389 |
|
390 _header->_paths_misc_info_size = info_size; |
|
391 |
|
392 align_file_position(); |
|
393 size_t sz = _header->data_size(); |
|
394 char* addr = _header->data(); |
|
395 write_bytes(addr, (int)sz); // skip the C++ vtable |
|
396 write_bytes(ClassLoader::get_shared_paths_misc_info(), info_size); |
|
397 align_file_position(); |
236 } |
398 } |
237 |
399 |
238 |
400 |
239 // Dump shared spaces to file. |
401 // Dump shared spaces to file. |
240 |
402 |
241 void FileMapInfo::write_space(int i, Metaspace* space, bool read_only) { |
403 void FileMapInfo::write_space(int i, Metaspace* space, bool read_only) { |
242 align_file_position(); |
404 align_file_position(); |
243 size_t used = space->used_bytes_slow(Metaspace::NonClassType); |
405 size_t used = space->used_bytes_slow(Metaspace::NonClassType); |
244 size_t capacity = space->capacity_bytes_slow(Metaspace::NonClassType); |
406 size_t capacity = space->capacity_bytes_slow(Metaspace::NonClassType); |
245 struct FileMapInfo::FileMapHeader::space_info* si = &_header._space[i]; |
407 struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[i]; |
246 write_region(i, (char*)space->bottom(), used, capacity, read_only, false); |
408 write_region(i, (char*)space->bottom(), used, capacity, read_only, false); |
247 } |
409 } |
248 |
410 |
249 |
411 |
250 // Dump region to file. |
412 // Dump region to file. |
251 |
413 |
252 void FileMapInfo::write_region(int region, char* base, size_t size, |
414 void FileMapInfo::write_region(int region, char* base, size_t size, |
253 size_t capacity, bool read_only, |
415 size_t capacity, bool read_only, |
254 bool allow_exec) { |
416 bool allow_exec) { |
255 struct FileMapInfo::FileMapHeader::space_info* si = &_header._space[region]; |
417 struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[region]; |
256 |
418 |
257 if (_file_open) { |
419 if (_file_open) { |
258 guarantee(si->_file_offset == _file_offset, "file offset mismatch."); |
420 guarantee(si->_file_offset == _file_offset, "file offset mismatch."); |
259 if (PrintSharedSpaces) { |
421 if (PrintSharedSpaces) { |
260 tty->print_cr("Shared file region %d: 0x%6x bytes, addr " INTPTR_FORMAT |
422 tty->print_cr("Shared file region %d: 0x%6x bytes, addr " INTPTR_FORMAT |
444 if (!open_for_read()) { |
615 if (!open_for_read()) { |
445 return false; |
616 return false; |
446 } |
617 } |
447 |
618 |
448 init_from_file(_fd); |
619 init_from_file(_fd); |
449 if (!validate()) { |
620 if (!validate_header()) { |
450 return false; |
621 return false; |
451 } |
622 } |
452 |
623 |
453 SharedReadOnlySize = _header._space[0]._capacity; |
624 SharedReadOnlySize = _header->_space[0]._capacity; |
454 SharedReadWriteSize = _header._space[1]._capacity; |
625 SharedReadWriteSize = _header->_space[1]._capacity; |
455 SharedMiscDataSize = _header._space[2]._capacity; |
626 SharedMiscDataSize = _header->_space[2]._capacity; |
456 SharedMiscCodeSize = _header._space[3]._capacity; |
627 SharedMiscCodeSize = _header->_space[3]._capacity; |
457 return true; |
628 return true; |
458 } |
629 } |
459 |
630 |
460 |
631 bool FileMapInfo::FileMapHeader::validate() { |
461 bool FileMapInfo::validate() { |
632 if (_version != current_version()) { |
462 if (_header._version != current_version()) { |
633 FileMapInfo::fail_continue("The shared archive file is the wrong version."); |
463 fail_continue("The shared archive file is the wrong version."); |
634 return false; |
464 return false; |
635 } |
465 } |
636 if (_magic != (int)0xf00baba2) { |
466 if (_header._magic != (int)0xf00baba2) { |
637 FileMapInfo::fail_continue("The shared archive file has a bad magic number."); |
467 fail_continue("The shared archive file has a bad magic number."); |
|
468 return false; |
638 return false; |
469 } |
639 } |
470 char header_version[JVM_IDENT_MAX]; |
640 char header_version[JVM_IDENT_MAX]; |
471 get_header_version(header_version); |
641 get_header_version(header_version); |
472 if (strncmp(_header._jvm_ident, header_version, JVM_IDENT_MAX-1) != 0) { |
642 if (strncmp(_jvm_ident, header_version, JVM_IDENT_MAX-1) != 0) { |
473 fail_continue("The shared archive file was created by a different" |
643 if (TraceClassPaths) { |
474 " version or build of HotSpot."); |
644 tty->print_cr("Expected: %s", header_version); |
475 return false; |
645 tty->print_cr("Actual: %s", _jvm_ident); |
476 } |
646 } |
477 if (_header._obj_alignment != ObjectAlignmentInBytes) { |
647 FileMapInfo::fail_continue("The shared archive file was created by a different" |
478 fail_continue("The shared archive file's ObjectAlignmentInBytes of %d" |
648 " version or build of HotSpot"); |
|
649 return false; |
|
650 } |
|
651 if (_obj_alignment != ObjectAlignmentInBytes) { |
|
652 FileMapInfo::fail_continue("The shared archive file's ObjectAlignmentInBytes of %d" |
479 " does not equal the current ObjectAlignmentInBytes of %d.", |
653 " does not equal the current ObjectAlignmentInBytes of %d.", |
480 _header._obj_alignment, ObjectAlignmentInBytes); |
654 _obj_alignment, ObjectAlignmentInBytes); |
481 return false; |
655 return false; |
482 } |
656 } |
483 |
657 |
484 // Cannot verify interpreter yet, as it can only be created after the GC |
658 return true; |
485 // heap has been initialized. |
659 } |
486 |
660 |
487 if (_header._num_jars >= JVM_SHARED_JARS_MAX) { |
661 bool FileMapInfo::validate_header() { |
488 fail_continue("Too many jar files to share."); |
662 bool status = _header->validate(); |
489 return false; |
663 |
490 } |
664 if (status) { |
491 |
665 if (!ClassLoader::check_shared_paths_misc_info(_paths_misc_info, _header->_paths_misc_info_size)) { |
492 // Build checks on classpath and jar files |
666 if (!PrintSharedArchiveAndExit) { |
493 int num_jars_now = 0; |
667 fail_continue("shared class paths mismatch (hint: enable -XX:+TraceClassPaths to diagnose the failure)"); |
494 ClassPathEntry *cpe = ClassLoader::classpath_entry(0); |
668 status = false; |
495 for ( ; cpe != NULL; cpe = cpe->next()) { |
|
496 |
|
497 if (cpe->is_jar_file()) { |
|
498 if (num_jars_now < _header._num_jars) { |
|
499 |
|
500 // Jar file - verify timestamp and file size. |
|
501 struct stat st; |
|
502 const char *path = cpe->name(); |
|
503 if (os::stat(path, &st) != 0) { |
|
504 fail_continue("Unable to open jar file %s.", path); |
|
505 return false; |
|
506 } |
|
507 if (_header._jar[num_jars_now]._timestamp != st.st_mtime || |
|
508 _header._jar[num_jars_now]._filesize != st.st_size) { |
|
509 fail_continue("A jar file is not the one used while building" |
|
510 " the shared archive file."); |
|
511 return false; |
|
512 } |
|
513 } |
669 } |
514 ++num_jars_now; |
670 } |
515 } else { |
671 } |
516 |
672 |
517 // If directories appear in boot classpath, they must be empty to |
673 if (_paths_misc_info != NULL) { |
518 // avoid having to verify each individual class file. |
674 FREE_C_HEAP_ARRAY(char, _paths_misc_info, mtClass); |
519 const char* name = ((ClassPathDirEntry*)cpe)->name(); |
675 _paths_misc_info = NULL; |
520 if (!os::dir_is_empty(name)) { |
676 } |
521 fail_continue("Boot classpath directory %s is not empty.", name); |
677 return status; |
522 return false; |
|
523 } |
|
524 } |
|
525 } |
|
526 if (num_jars_now < _header._num_jars) { |
|
527 fail_continue("The number of jar files in the boot classpath is" |
|
528 " less than the number the shared archive was created with."); |
|
529 return false; |
|
530 } |
|
531 |
|
532 return true; |
|
533 } |
678 } |
534 |
679 |
535 // The following method is provided to see whether a given pointer |
680 // The following method is provided to see whether a given pointer |
536 // falls in the mapped shared space. |
681 // falls in the mapped shared space. |
537 // Param: |
682 // Param: |
538 // p, The given pointer |
683 // p, The given pointer |
539 // Return: |
684 // Return: |
540 // True if the p is within the mapped shared space, otherwise, false. |
685 // True if the p is within the mapped shared space, otherwise, false. |
541 bool FileMapInfo::is_in_shared_space(const void* p) { |
686 bool FileMapInfo::is_in_shared_space(const void* p) { |
542 for (int i = 0; i < MetaspaceShared::n_regions; i++) { |
687 for (int i = 0; i < MetaspaceShared::n_regions; i++) { |
543 if (p >= _header._space[i]._base && |
688 if (p >= _header->_space[i]._base && |
544 p < _header._space[i]._base + _header._space[i]._used) { |
689 p < _header->_space[i]._base + _header->_space[i]._used) { |
545 return true; |
690 return true; |
546 } |
691 } |
547 } |
692 } |
548 |
693 |
549 return false; |
694 return false; |
550 } |
695 } |
551 |
696 |
552 void FileMapInfo::print_shared_spaces() { |
697 void FileMapInfo::print_shared_spaces() { |
553 gclog_or_tty->print_cr("Shared Spaces:"); |
698 gclog_or_tty->print_cr("Shared Spaces:"); |
554 for (int i = 0; i < MetaspaceShared::n_regions; i++) { |
699 for (int i = 0; i < MetaspaceShared::n_regions; i++) { |
555 struct FileMapInfo::FileMapHeader::space_info* si = &_header._space[i]; |
700 struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[i]; |
556 gclog_or_tty->print(" %s " INTPTR_FORMAT "-" INTPTR_FORMAT, |
701 gclog_or_tty->print(" %s " INTPTR_FORMAT "-" INTPTR_FORMAT, |
557 shared_region_name[i], |
702 shared_region_name[i], |
558 si->_base, si->_base + si->_used); |
703 si->_base, si->_base + si->_used); |
559 } |
704 } |
560 } |
705 } |