Пример #1
0
bool FileMapInfo::validate_header() {
  bool status = _header->validate();

  if (status) {
    if (!ClassLoader::check_shared_paths_misc_info(_paths_misc_info, _header->_paths_misc_info_size)) {
      if (!PrintSharedArchiveAndExit) {
        fail_continue("shared class paths mismatch (hint: enable -XX:+TraceClassPaths to diagnose the failure)");
        status = false;
      }
    }
  }

  if (_paths_misc_info != NULL) {
    FREE_C_HEAP_ARRAY(char, _paths_misc_info);
    _paths_misc_info = NULL;
  }
  return status;
}
Пример #2
0
// Map the whole region at once, assumed to be allocated contiguously.
ReservedSpace FileMapInfo::reserve_shared_memory() {
  struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[0];
  char* requested_addr = si->_base;

  size_t size = FileMapInfo::shared_spaces_size();

  // Reserve the space first, then map otherwise map will go right over some
  // other reserved memory (like the code cache).
  ReservedSpace rs(size, os::vm_allocation_granularity(), false, requested_addr);
  if (!rs.is_reserved()) {
    fail_continue("Unable to reserve shared space at required address " INTPTR_FORMAT, requested_addr);
    return rs;
  }
  // the reserved virtual memory is for mapping class data sharing archive
  MemTracker::record_virtual_memory_type((address)rs.base(), mtClassShared);

  return rs;
}
Пример #3
0
bool FileMapInfo::verify_region_checksum(int i) {
  if (!VerifySharedSpaces) {
    return true;
  }

  size_t sz = _header->_space[i]._used;

  if (sz == 0) {
    return true; // no data
  }
  if (MetaspaceShared::is_string_region(i) && StringTable::shared_string_ignored()) {
    return true; // shared string data are not mapped
  }
  const char* buf = _header->region_addr(i);
  int crc = ClassLoader::crc32(0, buf, (jint)sz);
  if (crc != _header->_space[i]._crc) {
    fail_continue("Checksum verification failed.");
    return false;
  }
  return true;
}
Пример #4
0
char* FileMapInfo::map_region(int i) {
  struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[i];
  size_t used = si->_used;
  size_t alignment = os::vm_allocation_granularity();
  size_t size = align_size_up(used, alignment);
  char *requested_addr = si->_base;

  // map the contents of the CDS archive in this memory
  char *base = os::map_memory(_fd, _full_path, si->_file_offset,
                              requested_addr, size, si->_read_only,
                              si->_allow_exec);
  if (base == NULL || base != si->_base) {
    fail_continue(err_msg("Unable to map %s shared space at required address.", shared_region_name[i]));
    return NULL;
  }
#ifdef _WINDOWS
  // This call is Windows-only because the memory_type gets recorded for the other platforms
  // in method FileMapInfo::reserve_shared_memory(), which is not called on Windows.
  MemTracker::record_virtual_memory_type((address)base, mtClassShared);
#endif
  return base;
}
Пример #5
0
// Open the shared archive file, read and validate the header
// information (version, boot classpath, etc.).  If initialization
// fails, shared spaces are disabled and the file is closed. [See
// fail_continue.]
//
// Validation of the archive is done in two steps:
//
// [1] validate_header() - done here. This checks the header, including _paths_misc_info.
// [2] validate_classpath_entry_table - this is done later, because the table is in the RW
//     region of the archive, which is not mapped yet.
bool FileMapInfo::initialize() {
  assert(UseSharedSpaces, "UseSharedSpaces expected.");

  if (JvmtiExport::can_modify_any_class() || JvmtiExport::can_walk_any_space()) {
    fail_continue("Tool agent requires sharing to be disabled.");
    return false;
  }

  if (!open_for_read()) {
    return false;
  }

  init_from_file(_fd);
  if (!validate_header()) {
    return false;
  }

  SharedReadOnlySize =  _header->_space[0]._capacity;
  SharedReadWriteSize = _header->_space[1]._capacity;
  SharedMiscDataSize =  _header->_space[2]._capacity;
  SharedMiscCodeSize =  _header->_space[3]._capacity;
  return true;
}
Пример #6
0
/**
 * 检查jar包是否可共享
 */
bool FileMapInfo::validate() {
  if (_header._version != current_version()) {
    fail_continue("The shared archive file is the wrong version.");
    return false;
  }

  if (_header._magic != (int)0xf00baba2) {
    fail_continue("The shared archive file has a bad magic number.");
    return false;
  }

  if (strncmp(_header._jvm_ident, VM_Version::internal_vm_info_string(),
              JVM_IDENT_MAX-1) != 0) {
    fail_continue("The shared archive file was created by a different"
                  " version or build of HotSpot.");
    return false;
  }

  // Cannot verify interpreter yet, as it can only be created after the GC
  // heap has been initialized.

  if (_header._num_jars >= JVM_SHARED_JARS_MAX) {
    fail_continue("Too many jar files to share.");
    return false;
  }

  // Build checks on classpath and jar files
  int num_jars_now = 0;
  ClassPathEntry *cpe = ClassLoader::classpath_entry(0);
  for ( ; cpe != NULL; cpe = cpe->next()) {

    if (cpe->is_jar_file()) {	//jar包文件
      if (num_jars_now < _header._num_jars) {

        // Jar file - verify timestamp and file size.
        struct stat st;
        const char *path = cpe->name();
        if (os::stat(path, &st) != 0) {
          fail_continue("Unable to open jar file %s.", path);
          return false;
        }

        //jar包已被修改,不能共享
        if (_header._jar[num_jars_now]._timestamp != st.st_mtime ||
            _header._jar[num_jars_now]._filesize != st.st_size) {
          fail_continue("A jar file is not the one used while building"
                        " the shared archive file.");
          return false;
        }
      }
      ++num_jars_now;

    } else {

      // If directories appear in boot classpath, they must be empty to
      // avoid having to verify each individual class file.
      const char* name = ((ClassPathDirEntry*)cpe)->name();
      if (!os::dir_is_empty(name)) {	//类路径
        fail_continue("Boot classpath directory %s is not empty.", name);
        return false;
      }
    }
  }

  if (num_jars_now < _header._num_jars) {
    fail_continue("The number of jar files in the boot classpath is"
                  " less than the number the shared archive was created with.");
    return false;
  }

  return true;
}
Пример #7
0
bool FileMapInfo::map_string_regions() {
#if INCLUDE_ALL_GCS
  if (UseG1GC && UseCompressedOops && UseCompressedClassPointers) {
    // Check that all the narrow oop and klass encodings match the archive
    if (narrow_oop_mode() != Universe::narrow_oop_mode() ||
        narrow_oop_shift() != Universe::narrow_oop_shift() ||
        narrow_klass_base() != Universe::narrow_klass_base() ||
        narrow_klass_shift() != Universe::narrow_klass_shift()) {
      if (PrintSharedSpaces && _header->_space[MetaspaceShared::first_string]._used > 0) {
        tty->print_cr("Shared string data from the CDS archive is being ignored. "
                     "The current CompressedOops/CompressedClassPointers encoding differs from "
                     "that archived due to heap size change. The archive was dumped using max heap "
                     "size %dM.", max_heap_size()/M);
      }
    } else {
      string_ranges = new MemRegion[MetaspaceShared::max_strings];
      struct FileMapInfo::FileMapHeader::space_info* si;

      for (int i = MetaspaceShared::first_string;
               i < MetaspaceShared::first_string + MetaspaceShared::max_strings; i++) {
        si = &_header->_space[i];
        size_t used = si->_used;
        if (used > 0) {
          size_t size = used;
          char* requested_addr = (char*)((void*)oopDesc::decode_heap_oop_not_null(
                                                 (narrowOop)si->_addr._offset));
          string_ranges[num_ranges] = MemRegion((HeapWord*)requested_addr, size / HeapWordSize);
          num_ranges ++;
        }
      }

      if (num_ranges == 0) {
        StringTable::ignore_shared_strings(true);
        return true; // no shared string data
      }

      // Check that ranges are within the java heap
      if (!G1CollectedHeap::heap()->check_archive_addresses(string_ranges, num_ranges)) {
        fail_continue("Unable to allocate shared string space: range is not "
                      "within java heap.");
        return false;
      }

      // allocate from java heap
      if (!G1CollectedHeap::heap()->alloc_archive_regions(string_ranges, num_ranges)) {
        fail_continue("Unable to allocate shared string space: range is "
                      "already in use.");
        return false;
      }

      // Map the string data. No need to call MemTracker::record_virtual_memory_type()
      // for mapped string regions as they are part of the reserved java heap, which
      // is already recorded.
      for (int i = 0; i < num_ranges; i++) {
        si = &_header->_space[MetaspaceShared::first_string + i];
        char* addr = (char*)string_ranges[i].start();
        char* base = os::map_memory(_fd, _full_path, si->_file_offset,
                                    addr, string_ranges[i].byte_size(), si->_read_only,
                                    si->_allow_exec);
        if (base == NULL || base != addr) {
          fail_continue("Unable to map shared string space at required address.");
          return false;
        }
      }

      if (!verify_string_regions()) {
        fail_continue("Shared string regions are corrupt");
        return false;
      }

      // the shared string data is mapped successfully
      return true;
    }
  } else {
    if (PrintSharedSpaces && _header->_space[MetaspaceShared::first_string]._used > 0) {
      tty->print_cr("Shared string data from the CDS archive is being ignored. UseG1GC, "
                    "UseCompressedOops and UseCompressedClassPointers are required.");
    }
  }

  // if we get here, the shared string data is not mapped
  assert(string_ranges == NULL && num_ranges == 0, "sanity");
  StringTable::ignore_shared_strings(true);
#endif
  return true;
}