1.1 --- a/src/share/vm/memory/filemap.cpp Tue Nov 27 07:57:57 2012 -0800 1.2 +++ b/src/share/vm/memory/filemap.cpp Wed Nov 28 08:17:59 2012 -0500 1.3 @@ -25,6 +25,7 @@ 1.4 #include "precompiled.hpp" 1.5 #include "classfile/classLoader.hpp" 1.6 #include "classfile/symbolTable.hpp" 1.7 +#include "classfile/altHashing.hpp" 1.8 #include "memory/filemap.hpp" 1.9 #include "runtime/arguments.hpp" 1.10 #include "runtime/java.hpp" 1.11 @@ -82,8 +83,37 @@ 1.12 close(); 1.13 } 1.14 1.15 +// Fill in the fileMapInfo structure with data about this VM instance. 1.16 1.17 -// Fill in the fileMapInfo structure with data about this VM instance. 1.18 +// This method copies the vm version info into header_version. If the version is too 1.19 +// long then a truncated version, which has a hash code appended to it, is copied. 1.20 +// 1.21 +// Using a template enables this method to verify that header_version is an array of 1.22 +// length JVM_IDENT_MAX. This ensures that the code that writes to the CDS file and 1.23 +// the code that reads the CDS file will both use the same size buffer. Hence, will 1.24 +// use identical truncation. This is necessary for matching of truncated versions. 1.25 +template <int N> static void get_header_version(char (&header_version) [N]) { 1.26 + assert(N == JVM_IDENT_MAX, "Bad header_version size"); 1.27 + 1.28 + const char *vm_version = VM_Version::internal_vm_info_string(); 1.29 + const int version_len = (int)strlen(vm_version); 1.30 + 1.31 + if (version_len < (JVM_IDENT_MAX-1)) { 1.32 + strcpy(header_version, vm_version); 1.33 + 1.34 + } else { 1.35 + // Get the hash value. Use a static seed because the hash needs to return the same 1.36 + // value over multiple jvm invocations. 1.37 + unsigned int hash = AltHashing::murmur3_32(8191, (const jbyte*)vm_version, version_len); 1.38 + 1.39 + // Truncate the ident, saving room for the 8 hex character hash value. 1.40 + strncpy(header_version, vm_version, JVM_IDENT_MAX-9); 1.41 + 1.42 + // Append the hash code as eight hex digits. 1.43 + sprintf(&header_version[JVM_IDENT_MAX-9], "%08x", hash); 1.44 + header_version[JVM_IDENT_MAX-1] = 0; // Null terminate. 1.45 + } 1.46 +} 1.47 1.48 void FileMapInfo::populate_header(size_t alignment) { 1.49 _header._magic = 0xf00baba2; 1.50 @@ -95,13 +125,7 @@ 1.51 // invoked with. 1.52 1.53 // JVM version string ... changes on each build. 1.54 - const char *vm_version = VM_Version::internal_vm_info_string(); 1.55 - if (strlen(vm_version) < (JVM_IDENT_MAX-1)) { 1.56 - strcpy(_header._jvm_ident, vm_version); 1.57 - } else { 1.58 - fail_stop("JVM Ident field for shared archive is too long" 1.59 - " - truncated to <%s>", _header._jvm_ident); 1.60 - } 1.61 + get_header_version(_header._jvm_ident); 1.62 1.63 // Build checks on classpath and jar files 1.64 _header._num_jars = 0; 1.65 @@ -434,8 +458,9 @@ 1.66 fail_continue("The shared archive file has a bad magic number."); 1.67 return false; 1.68 } 1.69 - if (strncmp(_header._jvm_ident, VM_Version::internal_vm_info_string(), 1.70 - JVM_IDENT_MAX-1) != 0) { 1.71 + char header_version[JVM_IDENT_MAX]; 1.72 + get_header_version(header_version); 1.73 + if (strncmp(_header._jvm_ident, header_version, JVM_IDENT_MAX-1) != 0) { 1.74 fail_continue("The shared archive file was created by a different" 1.75 " version or build of HotSpot."); 1.76 return false;