aboutsummaryrefslogtreecommitdiff
path: root/src/share/vm/memory/filemap.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/share/vm/memory/filemap.cpp')
-rw-r--r--src/share/vm/memory/filemap.cpp45
1 files changed, 35 insertions, 10 deletions
diff --git a/src/share/vm/memory/filemap.cpp b/src/share/vm/memory/filemap.cpp
index c3d1bf5f9..11b395776 100644
--- a/src/share/vm/memory/filemap.cpp
+++ b/src/share/vm/memory/filemap.cpp
@@ -25,6 +25,7 @@
#include "precompiled.hpp"
#include "classfile/classLoader.hpp"
#include "classfile/symbolTable.hpp"
+#include "classfile/altHashing.hpp"
#include "memory/filemap.hpp"
#include "runtime/arguments.hpp"
#include "runtime/java.hpp"
@@ -82,9 +83,38 @@ void FileMapInfo::fail_continue(const char *msg, ...) {
close();
}
-
// Fill in the fileMapInfo structure with data about this VM instance.
+// This method copies the vm version info into header_version. If the version is too
+// long then a truncated version, which has a hash code appended to it, is copied.
+//
+// Using a template enables this method to verify that header_version is an array of
+// length JVM_IDENT_MAX. This ensures that the code that writes to the CDS file and
+// the code that reads the CDS file will both use the same size buffer. Hence, will
+// use identical truncation. This is necessary for matching of truncated versions.
+template <int N> static void get_header_version(char (&header_version) [N]) {
+ assert(N == JVM_IDENT_MAX, "Bad header_version size");
+
+ const char *vm_version = VM_Version::internal_vm_info_string();
+ const int version_len = (int)strlen(vm_version);
+
+ if (version_len < (JVM_IDENT_MAX-1)) {
+ strcpy(header_version, vm_version);
+
+ } else {
+ // Get the hash value. Use a static seed because the hash needs to return the same
+ // value over multiple jvm invocations.
+ unsigned int hash = AltHashing::murmur3_32(8191, (const jbyte*)vm_version, version_len);
+
+ // Truncate the ident, saving room for the 8 hex character hash value.
+ strncpy(header_version, vm_version, JVM_IDENT_MAX-9);
+
+ // Append the hash code as eight hex digits.
+ sprintf(&header_version[JVM_IDENT_MAX-9], "%08x", hash);
+ header_version[JVM_IDENT_MAX-1] = 0; // Null terminate.
+ }
+}
+
void FileMapInfo::populate_header(size_t alignment) {
_header._magic = 0xf00baba2;
_header._version = _current_version;
@@ -95,13 +125,7 @@ void FileMapInfo::populate_header(size_t alignment) {
// invoked with.
// JVM version string ... changes on each build.
- const char *vm_version = VM_Version::internal_vm_info_string();
- if (strlen(vm_version) < (JVM_IDENT_MAX-1)) {
- strcpy(_header._jvm_ident, vm_version);
- } else {
- fail_stop("JVM Ident field for shared archive is too long"
- " - truncated to <%s>", _header._jvm_ident);
- }
+ get_header_version(_header._jvm_ident);
// Build checks on classpath and jar files
_header._num_jars = 0;
@@ -434,8 +458,9 @@ bool FileMapInfo::validate() {
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) {
+ char header_version[JVM_IDENT_MAX];
+ get_header_version(header_version);
+ if (strncmp(_header._jvm_ident, header_version, JVM_IDENT_MAX-1) != 0) {
fail_continue("The shared archive file was created by a different"
" version or build of HotSpot.");
return false;