23 */ |
23 */ |
24 |
24 |
25 #include "precompiled.hpp" |
25 #include "precompiled.hpp" |
26 #include "jvm.h" |
26 #include "jvm.h" |
27 #include "classfile/classLoader.inline.hpp" |
27 #include "classfile/classLoader.inline.hpp" |
|
28 #include "classfile/classLoaderExt.hpp" |
28 #include "classfile/compactHashtable.inline.hpp" |
29 #include "classfile/compactHashtable.inline.hpp" |
29 #include "classfile/sharedClassUtil.hpp" |
|
30 #include "classfile/stringTable.hpp" |
30 #include "classfile/stringTable.hpp" |
31 #include "classfile/symbolTable.hpp" |
31 #include "classfile/symbolTable.hpp" |
32 #include "classfile/systemDictionaryShared.hpp" |
32 #include "classfile/systemDictionaryShared.hpp" |
33 #include "classfile/altHashing.hpp" |
33 #include "classfile/altHashing.hpp" |
34 #include "logging/log.hpp" |
34 #include "logging/log.hpp" |
157 assert(_current_info == NULL, "must be singleton"); // not thread safe |
157 assert(_current_info == NULL, "must be singleton"); // not thread safe |
158 _current_info = this; |
158 _current_info = this; |
159 memset((void*)this, 0, sizeof(FileMapInfo)); |
159 memset((void*)this, 0, sizeof(FileMapInfo)); |
160 _file_offset = 0; |
160 _file_offset = 0; |
161 _file_open = false; |
161 _file_open = false; |
162 _header = SharedClassUtil::allocate_file_map_header(); |
162 _header = new FileMapHeader(); |
163 _header->_version = _invalid_version; |
163 _header->_version = _invalid_version; |
|
164 _header->_has_platform_or_app_classes = true; |
164 } |
165 } |
165 |
166 |
166 FileMapInfo::~FileMapInfo() { |
167 FileMapInfo::~FileMapInfo() { |
167 assert(_current_info == this, "must be singleton"); // not thread safe |
168 assert(_current_info == this, "must be singleton"); // not thread safe |
168 _current_info = NULL; |
169 _current_info = NULL; |
169 } |
170 } |
170 |
171 |
171 void FileMapInfo::populate_header(size_t alignment) { |
172 void FileMapInfo::populate_header(size_t alignment) { |
172 _header->populate(this, alignment); |
173 _header->populate(this, alignment); |
173 } |
|
174 |
|
175 size_t FileMapInfo::FileMapHeader::data_size() { |
|
176 return SharedClassUtil::file_map_header_size() - sizeof(FileMapInfo::FileMapHeaderBase); |
|
177 } |
174 } |
178 |
175 |
179 void FileMapInfo::FileMapHeader::populate(FileMapInfo* mapinfo, size_t alignment) { |
176 void FileMapInfo::FileMapHeader::populate(FileMapInfo* mapinfo, size_t alignment) { |
180 _magic = 0xf00baba2; |
177 _magic = 0xf00baba2; |
181 _version = _current_version; |
178 _version = _current_version; |
276 ClassPathEntry* jrt = ClassLoader::get_jrt_entry(); |
281 ClassPathEntry* jrt = ClassLoader::get_jrt_entry(); |
277 |
282 |
278 assert(jrt != NULL, |
283 assert(jrt != NULL, |
279 "No modular java runtime image present when allocating the CDS classpath entry table"); |
284 "No modular java runtime image present when allocating the CDS classpath entry table"); |
280 |
285 |
281 size_t entry_size = SharedClassUtil::shared_class_path_entry_size(); // assert ( should be 8 byte aligned??) |
286 size_t entry_size = sizeof(SharedClassPathEntry); // assert ( should be 8 byte aligned??) |
282 int num_boot_classpath_entries = ClassLoader::num_boot_classpath_entries(); |
287 int num_boot_classpath_entries = ClassLoader::num_boot_classpath_entries(); |
283 int num_app_classpath_entries = ClassLoader::num_app_classpath_entries(); |
288 int num_app_classpath_entries = ClassLoader::num_app_classpath_entries(); |
284 int num_module_path_entries = ClassLoader::num_module_path_entries(); |
289 int num_module_path_entries = ClassLoader::num_module_path_entries(); |
285 int num_entries = num_boot_classpath_entries + num_app_classpath_entries + num_module_path_entries; |
290 int num_entries = num_boot_classpath_entries + num_app_classpath_entries + num_module_path_entries; |
286 size_t bytes = entry_size * num_entries; |
291 size_t bytes = entry_size * num_entries; |
297 log_info(class, path)("add main shared path (%s) %s", type, cpe->name()); |
302 log_info(class, path)("add main shared path (%s) %s", type, cpe->name()); |
298 SharedClassPathEntry* ent = shared_path(i); |
303 SharedClassPathEntry* ent = shared_path(i); |
299 ent->init(cpe->name(), THREAD); |
304 ent->init(cpe->name(), THREAD); |
300 if (cpe != jrt) { // No need to do jimage. |
305 if (cpe != jrt) { // No need to do jimage. |
301 EXCEPTION_MARK; // The following call should never throw, but would exit VM on error. |
306 EXCEPTION_MARK; // The following call should never throw, but would exit VM on error. |
302 SharedClassUtil::update_shared_classpath(cpe, ent, THREAD); |
307 update_shared_classpath(cpe, ent, THREAD); |
303 } |
308 } |
304 cpe = ClassLoader::get_next_boot_classpath_entry(cpe); |
309 cpe = ClassLoader::get_next_boot_classpath_entry(cpe); |
305 i++; |
310 i++; |
306 } |
311 } |
307 assert(i == num_boot_classpath_entries, |
312 assert(i == num_boot_classpath_entries, |
358 if (has_nonempty_dir) { |
363 if (has_nonempty_dir) { |
359 ClassLoader::exit_with_path_failure("Cannot have non-empty directory in paths", NULL); |
364 ClassLoader::exit_with_path_failure("Cannot have non-empty directory in paths", NULL); |
360 } |
365 } |
361 } |
366 } |
362 |
367 |
|
368 class ManifestStream: public ResourceObj { |
|
369 private: |
|
370 u1* _buffer_start; // Buffer bottom |
|
371 u1* _buffer_end; // Buffer top (one past last element) |
|
372 u1* _current; // Current buffer position |
|
373 |
|
374 public: |
|
375 // Constructor |
|
376 ManifestStream(u1* buffer, int length) : _buffer_start(buffer), |
|
377 _current(buffer) { |
|
378 _buffer_end = buffer + length; |
|
379 } |
|
380 |
|
381 static bool is_attr(u1* attr, const char* name) { |
|
382 return strncmp((const char*)attr, name, strlen(name)) == 0; |
|
383 } |
|
384 |
|
385 static char* copy_attr(u1* value, size_t len) { |
|
386 char* buf = NEW_RESOURCE_ARRAY(char, len + 1); |
|
387 strncpy(buf, (char*)value, len); |
|
388 buf[len] = 0; |
|
389 return buf; |
|
390 } |
|
391 |
|
392 // The return value indicates if the JAR is signed or not |
|
393 bool check_is_signed() { |
|
394 u1* attr = _current; |
|
395 bool isSigned = false; |
|
396 while (_current < _buffer_end) { |
|
397 if (*_current == '\n') { |
|
398 *_current = '\0'; |
|
399 u1* value = (u1*)strchr((char*)attr, ':'); |
|
400 if (value != NULL) { |
|
401 assert(*(value+1) == ' ', "Unrecognized format" ); |
|
402 if (strstr((char*)attr, "-Digest") != NULL) { |
|
403 isSigned = true; |
|
404 break; |
|
405 } |
|
406 } |
|
407 *_current = '\n'; // restore |
|
408 attr = _current + 1; |
|
409 } |
|
410 _current ++; |
|
411 } |
|
412 return isSigned; |
|
413 } |
|
414 }; |
|
415 |
|
416 void FileMapInfo::update_shared_classpath(ClassPathEntry *cpe, SharedClassPathEntry* ent, TRAPS) { |
|
417 ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data(); |
|
418 ResourceMark rm(THREAD); |
|
419 jint manifest_size; |
|
420 bool isSigned; |
|
421 |
|
422 if (cpe->is_jar_file()) { |
|
423 char* manifest = ClassLoaderExt::read_manifest(cpe, &manifest_size, CHECK); |
|
424 if (manifest != NULL) { |
|
425 ManifestStream* stream = new ManifestStream((u1*)manifest, |
|
426 manifest_size); |
|
427 isSigned = stream->check_is_signed(); |
|
428 if (isSigned) { |
|
429 ent->set_is_signed(true); |
|
430 } else { |
|
431 // Copy the manifest into the shared archive |
|
432 manifest = ClassLoaderExt::read_raw_manifest(cpe, &manifest_size, CHECK); |
|
433 Array<u1>* buf = MetadataFactory::new_array<u1>(loader_data, |
|
434 manifest_size, |
|
435 THREAD); |
|
436 char* p = (char*)(buf->data()); |
|
437 memcpy(p, manifest, manifest_size); |
|
438 ent->set_manifest(buf); |
|
439 ent->set_is_signed(false); |
|
440 } |
|
441 } |
|
442 } |
|
443 } |
|
444 |
|
445 |
363 bool FileMapInfo::validate_shared_path_table() { |
446 bool FileMapInfo::validate_shared_path_table() { |
364 assert(UseSharedSpaces, "runtime only"); |
447 assert(UseSharedSpaces, "runtime only"); |
365 |
448 |
366 _validating_shared_path_table = true; |
449 _validating_shared_path_table = true; |
367 _shared_path_table = _header->_shared_path_table; |
450 _shared_path_table = _header->_shared_path_table; |
368 _shared_path_entry_size = _header->_shared_path_entry_size; |
451 _shared_path_entry_size = _header->_shared_path_entry_size; |
369 _shared_path_table_size = _header->_shared_path_table_size; |
452 _shared_path_table_size = _header->_shared_path_table_size; |
370 |
453 |
371 FileMapHeaderExt* header = (FileMapHeaderExt*)FileMapInfo::current_info()->header(); |
454 int module_paths_start_index = _header->_app_module_paths_start_index; |
372 int module_paths_start_index = header->_app_module_paths_start_index; |
|
373 |
455 |
374 // If the shared archive contain app or platform classes, validate all entries |
456 // If the shared archive contain app or platform classes, validate all entries |
375 // in the shared path table. Otherwise, only validate the boot path entries (with |
457 // in the shared path table. Otherwise, only validate the boot path entries (with |
376 // entry index < _app_class_paths_start_index). |
458 // entry index < _app_class_paths_start_index). |
377 int count = header->has_platform_or_app_classes() ? |
459 int count = _header->has_platform_or_app_classes() ? |
378 _shared_path_table_size : header->_app_class_paths_start_index; |
460 _shared_path_table_size : _header->_app_class_paths_start_index; |
379 |
461 |
380 for (int i=0; i<count; i++) { |
462 for (int i=0; i<count; i++) { |
381 if (i < module_paths_start_index) { |
463 if (i < module_paths_start_index) { |
382 if (shared_path(i)->validate()) { |
464 if (shared_path(i)->validate()) { |
383 log_info(class, path)("ok"); |
465 log_info(class, path)("ok"); |
1076 _compact_strings ? "enabled" : "disabled", |
1158 _compact_strings ? "enabled" : "disabled", |
1077 CompactStrings ? "enabled" : "disabled"); |
1159 CompactStrings ? "enabled" : "disabled"); |
1078 return false; |
1160 return false; |
1079 } |
1161 } |
1080 |
1162 |
|
1163 // This must be done after header validation because it might change the |
|
1164 // header data |
|
1165 const char* prop = Arguments::get_property("java.system.class.loader"); |
|
1166 if (prop != NULL) { |
|
1167 warning("Archived non-system classes are disabled because the " |
|
1168 "java.system.class.loader property is specified (value = \"%s\"). " |
|
1169 "To use archived non-system classes, this property must be not be set", prop); |
|
1170 _has_platform_or_app_classes = false; |
|
1171 } |
|
1172 |
|
1173 // For backwards compatibility, we don't check the verification setting |
|
1174 // if the archive only contains system classes. |
|
1175 if (_has_platform_or_app_classes && |
|
1176 ((!_verify_local && BytecodeVerificationLocal) || |
|
1177 (!_verify_remote && BytecodeVerificationRemote))) { |
|
1178 FileMapInfo::fail_continue("The shared archive file was created with less restrictive " |
|
1179 "verification setting than the current setting."); |
|
1180 return false; |
|
1181 } |
|
1182 |
1081 return true; |
1183 return true; |
1082 } |
1184 } |
1083 |
1185 |
1084 bool FileMapInfo::validate_header() { |
1186 bool FileMapInfo::validate_header() { |
1085 bool status = _header->validate(); |
1187 bool status = _header->validate(); |