# HG changeset patch # User coleenp # Date 1354121006 28800 # Node ID b51dc8df86e54881a9887187352e47559206a6ae # Parent 5de2a5bd519ede7ffb6596243c8b4c7287b779a7# Parent fe81517cfb779a1c8a70a0ee9e6c5b4f972e1950 Merge diff -r 5de2a5bd519e -r b51dc8df86e5 src/share/vm/memory/filemap.cpp --- a/src/share/vm/memory/filemap.cpp Wed Nov 28 06:42:03 2012 -0800 +++ b/src/share/vm/memory/filemap.cpp Wed Nov 28 08:43:26 2012 -0800 @@ -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,8 +83,37 @@ close(); } +// Fill in the fileMapInfo structure with data about this VM instance. -// 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 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; @@ -95,13 +125,7 @@ // 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 @@ 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;