6721093: -XX:AppendRatio=N not supported
Summary: Add mechanism to ignore unsupported flags for a set period of time
Reviewed-by: acorn, never, coleenp
--- a/hotspot/src/os/linux/vm/os_linux.cpp Sat Jul 19 17:38:22 2008 -0400
+++ b/hotspot/src/os/linux/vm/os_linux.cpp Mon Jul 28 14:07:44 2008 -0400
@@ -94,6 +94,9 @@
static int SR_signum = SIGUSR2;
sigset_t SR_sigset;
+/* Used to protect dlsym() calls */
+static pthread_mutex_t dl_mutex;
+
////////////////////////////////////////////////////////////////////////////////
// utility functions
@@ -1493,6 +1496,24 @@
const char* os::get_temp_directory() { return "/tmp/"; }
+void os::dll_build_name(
+ char* buffer, size_t buflen, const char* pname, const char* fname) {
+ // copied from libhpi
+ const size_t pnamelen = pname ? strlen(pname) : 0;
+
+ /* Quietly truncate on buffer overflow. Should be an error. */
+ if (pnamelen + strlen(fname) + 10 > (size_t) buflen) {
+ *buffer = '\0';
+ return;
+ }
+
+ if (pnamelen == 0) {
+ sprintf(buffer, "lib%s.so", fname);
+ } else {
+ sprintf(buffer, "%s/lib%s.so", pname, fname);
+ }
+}
+
const char* os::get_current_directory(char *buf, int buflen) {
return getcwd(buf, buflen);
}
@@ -1742,7 +1763,17 @@
return NULL;
}
-
+/*
+ * glibc-2.0 libdl is not MT safe. If you are building with any glibc,
+ * chances are you might want to run the generated bits against glibc-2.0
+ * libdl.so, so always use locking for any version of glibc.
+ */
+void* os::dll_lookup(void* handle, const char* name) {
+ pthread_mutex_lock(&dl_mutex);
+ void* res = dlsym(handle, name);
+ pthread_mutex_unlock(&dl_mutex);
+ return res;
+}
bool _print_ascii_file(const char* filename, outputStream* st) {
@@ -3581,6 +3612,7 @@
Linux::clock_init();
initial_time_count = os::elapsed_counter();
+ pthread_mutex_init(&dl_mutex, NULL);
}
// To install functions for atexit system call
--- a/hotspot/src/os/solaris/vm/os_solaris.cpp Sat Jul 19 17:38:22 2008 -0400
+++ b/hotspot/src/os/solaris/vm/os_solaris.cpp Mon Jul 28 14:07:44 2008 -0400
@@ -1783,6 +1783,24 @@
const char* os::get_temp_directory() { return "/tmp/"; }
+void os::dll_build_name(
+ char* buffer, size_t buflen, const char* pname, const char* fname) {
+ // copied from libhpi
+ const size_t pnamelen = pname ? strlen(pname) : 0;
+
+ /* Quietly truncate on buffer overflow. Should be an error. */
+ if (pnamelen + strlen(fname) + 10 > (size_t) buflen) {
+ *buffer = '\0';
+ return;
+ }
+
+ if (pnamelen == 0) {
+ sprintf(buffer, "lib%s.so", fname);
+ } else {
+ sprintf(buffer, "%s/lib%s.so", pname, fname);
+ }
+}
+
const char* os::get_current_directory(char *buf, int buflen) {
return getcwd(buf, buflen);
}
@@ -2034,6 +2052,9 @@
return NULL;
}
+void* os::dll_lookup(void* handle, const char* name) {
+ return dlsym(handle, name);
+}
bool _print_ascii_file(const char* filename, outputStream* st) {
--- a/hotspot/src/os/windows/vm/os_windows.cpp Sat Jul 19 17:38:22 2008 -0400
+++ b/hotspot/src/os/windows/vm/os_windows.cpp Mon Jul 28 14:07:44 2008 -0400
@@ -985,6 +985,28 @@
}
}
+void os::dll_build_name(char *holder, size_t holderlen,
+ const char* pname, const char* fname)
+{
+ // copied from libhpi
+ const size_t pnamelen = pname ? strlen(pname) : 0;
+ const char c = (pnamelen > 0) ? pname[pnamelen-1] : 0;
+
+ /* Quietly truncates on buffer overflow. Should be an error. */
+ if (pnamelen + strlen(fname) + 10 > holderlen) {
+ *holder = '\0';
+ return;
+ }
+
+ if (pnamelen == 0) {
+ sprintf(holder, "%s.dll", fname);
+ } else if (c == ':' || c == '\\') {
+ sprintf(holder, "%s%s.dll", pname, fname);
+ } else {
+ sprintf(holder, "%s\\%s.dll", pname, fname);
+ }
+}
+
// Needs to be in os specific directory because windows requires another
// header file <direct.h>
const char* os::get_current_directory(char *buf, int buflen) {
@@ -1248,6 +1270,10 @@
return false;
}
+void* os::dll_lookup(void* handle, const char* name) {
+ return GetProcAddress((HMODULE)handle, name);
+}
+
// save the start and end address of jvm.dll into param[0] and param[1]
static int _locate_jvm_dll(int pid, char* mod_fname, address base_addr,
unsigned size, void * param) {
--- a/hotspot/src/share/vm/classfile/javaClasses.cpp Sat Jul 19 17:38:22 2008 -0400
+++ b/hotspot/src/share/vm/classfile/javaClasses.cpp Mon Jul 28 14:07:44 2008 -0400
@@ -649,8 +649,8 @@
}
oop java_lang_Thread::park_blocker(oop java_thread) {
- assert(JDK_Version::supports_thread_park_blocker() && _park_blocker_offset != 0,
- "Must support parkBlocker field");
+ assert(JDK_Version::current().supports_thread_park_blocker() &&
+ _park_blocker_offset != 0, "Must support parkBlocker field");
if (_park_blocker_offset > 0) {
return java_thread->obj_field(_park_blocker_offset);
--- a/hotspot/src/share/vm/includeDB_core Sat Jul 19 17:38:22 2008 -0400
+++ b/hotspot/src/share/vm/includeDB_core Mon Jul 28 14:07:44 2008 -0400
@@ -178,6 +178,7 @@
arguments.cpp universe.inline.hpp
arguments.cpp vm_version_<arch_model>.hpp
+arguments.hpp java.hpp
arguments.hpp perfData.hpp
arguments.hpp top.hpp
--- a/hotspot/src/share/vm/memory/universe.cpp Sat Jul 19 17:38:22 2008 -0400
+++ b/hotspot/src/share/vm/memory/universe.cpp Mon Jul 28 14:07:44 2008 -0400
@@ -367,26 +367,31 @@
// Only 1.3 or later has the java.lang.Shutdown class.
// Only 1.4 or later has the java.lang.CharSequence interface.
// Only 1.5 or later has the java.lang.management.MemoryUsage class.
- if (JDK_Version::is_pre_jdk16_version()) {
- klassOop k = SystemDictionary::resolve_or_null(vmSymbolHandles::java_lang_management_MemoryUsage(), THREAD);
+ if (JDK_Version::is_partially_initialized()) {
+ uint8_t jdk_version;
+ klassOop k = SystemDictionary::resolve_or_null(
+ vmSymbolHandles::java_lang_management_MemoryUsage(), THREAD);
CLEAR_PENDING_EXCEPTION; // ignore exceptions
if (k == NULL) {
- k = SystemDictionary::resolve_or_null(vmSymbolHandles::java_lang_CharSequence(), THREAD);
+ k = SystemDictionary::resolve_or_null(
+ vmSymbolHandles::java_lang_CharSequence(), THREAD);
CLEAR_PENDING_EXCEPTION; // ignore exceptions
if (k == NULL) {
- k = SystemDictionary::resolve_or_null(vmSymbolHandles::java_lang_Shutdown(), THREAD);
+ k = SystemDictionary::resolve_or_null(
+ vmSymbolHandles::java_lang_Shutdown(), THREAD);
CLEAR_PENDING_EXCEPTION; // ignore exceptions
if (k == NULL) {
- JDK_Version::set_jdk12x_version();
+ jdk_version = 2;
} else {
- JDK_Version::set_jdk13x_version();
+ jdk_version = 3;
}
} else {
- JDK_Version::set_jdk14x_version();
+ jdk_version = 4;
}
} else {
- JDK_Version::set_jdk15x_version();
+ jdk_version = 5;
}
+ JDK_Version::fully_initialize(jdk_version);
}
#ifdef ASSERT
--- a/hotspot/src/share/vm/runtime/arguments.cpp Sat Jul 19 17:38:22 2008 -0400
+++ b/hotspot/src/share/vm/runtime/arguments.cpp Mon Jul 28 14:07:44 2008 -0400
@@ -153,37 +153,56 @@
os::init_system_properties_values();
}
-// String containing commands that will be ignored and cause a
-// warning to be issued. These commands should be accepted
-// for 1.6 but not 1.7. The string should be cleared at the
-// beginning of 1.7.
-static const char* obsolete_jvm_flags_1_5_0[] = {
- "UseTrainGC",
- "UseSpecialLargeObjectHandling",
- "UseOversizedCarHandling",
- "TraceCarAllocation",
- "PrintTrainGCProcessingStats",
- "LogOfCarSpaceSize",
- "OversizedCarThreshold",
- "MinTickInterval",
- "DefaultTickInterval",
- "MaxTickInterval",
- "DelayTickAdjustment",
- "ProcessingToTenuringRatio",
- "MinTrainLength",
- 0};
+/**
+ * Provide a slightly more user-friendly way of eliminating -XX flags.
+ * When a flag is eliminated, it can be added to this list in order to
+ * continue accepting this flag on the command-line, while issuing a warning
+ * and ignoring the value. Once the JDK version reaches the 'accept_until'
+ * limit, we flatly refuse to admit the existence of the flag. This allows
+ * a flag to die correctly over JDK releases using HSX.
+ */
+typedef struct {
+ const char* name;
+ JDK_Version obsoleted_in; // when the flag went away
+ JDK_Version accept_until; // which version to start denying the existence
+} ObsoleteFlag;
-bool Arguments::made_obsolete_in_1_5_0(const char *s) {
+static ObsoleteFlag obsolete_jvm_flags[] = {
+ { "UseTrainGC", JDK_Version::jdk(5), JDK_Version::jdk(7) },
+ { "UseSpecialLargeObjectHandling", JDK_Version::jdk(5), JDK_Version::jdk(7) },
+ { "UseOversizedCarHandling", JDK_Version::jdk(5), JDK_Version::jdk(7) },
+ { "TraceCarAllocation", JDK_Version::jdk(5), JDK_Version::jdk(7) },
+ { "PrintTrainGCProcessingStats", JDK_Version::jdk(5), JDK_Version::jdk(7) },
+ { "LogOfCarSpaceSize", JDK_Version::jdk(5), JDK_Version::jdk(7) },
+ { "OversizedCarThreshold", JDK_Version::jdk(5), JDK_Version::jdk(7) },
+ { "MinTickInterval", JDK_Version::jdk(5), JDK_Version::jdk(7) },
+ { "DefaultTickInterval", JDK_Version::jdk(5), JDK_Version::jdk(7) },
+ { "MaxTickInterval", JDK_Version::jdk(5), JDK_Version::jdk(7) },
+ { "DelayTickAdjustment", JDK_Version::jdk(5), JDK_Version::jdk(7) },
+ { "ProcessingToTenuringRatio", JDK_Version::jdk(5), JDK_Version::jdk(7) },
+ { "MinTrainLength", JDK_Version::jdk(5), JDK_Version::jdk(7) },
+ { "AppendRatio", JDK_Version::jdk_update(6,10), JDK_Version::jdk(7) },
+ { NULL, JDK_Version(0), JDK_Version(0) }
+};
+
+// Returns true if the flag is obsolete and fits into the range specified
+// for being ignored. In the case that the flag is ignored, the 'version'
+// value is filled in with the version number when the flag became
+// obsolete so that that value can be displayed to the user.
+bool Arguments::is_newly_obsolete(const char *s, JDK_Version* version) {
int i = 0;
- while (obsolete_jvm_flags_1_5_0[i] != NULL) {
+ assert(version != NULL, "Must provide a version buffer");
+ while (obsolete_jvm_flags[i].name != NULL) {
+ const ObsoleteFlag& flag_status = obsolete_jvm_flags[i];
// <flag>=xxx form
// [-|+]<flag> form
- if ((strncmp(obsolete_jvm_flags_1_5_0[i], s,
- strlen(obsolete_jvm_flags_1_5_0[i])) == 0) ||
+ if ((strncmp(flag_status.name, s, strlen(flag_status.name)) == 0) ||
((s[0] == '+' || s[0] == '-') &&
- (strncmp(obsolete_jvm_flags_1_5_0[i], &s[1],
- strlen(obsolete_jvm_flags_1_5_0[i])) == 0))) {
- return true;
+ (strncmp(flag_status.name, &s[1], strlen(flag_status.name)) == 0))) {
+ if (JDK_Version::current().compare(flag_status.accept_until) == -1) {
+ *version = flag_status.obsoleted_in;
+ return true;
+ }
}
i++;
}
@@ -705,14 +724,20 @@
}
}
-bool Arguments::process_argument(const char* arg, jboolean ignore_unrecognized, FlagValueOrigin origin) {
+bool Arguments::process_argument(const char* arg,
+ jboolean ignore_unrecognized, FlagValueOrigin origin) {
+
+ JDK_Version since = JDK_Version();
if (parse_argument(arg, origin)) {
// do nothing
- } else if (made_obsolete_in_1_5_0(arg)) {
+ } else if (is_newly_obsolete(arg, &since)) {
+ enum { bufsize = 256 };
+ char buffer[bufsize];
+ since.to_string(buffer, bufsize);
jio_fprintf(defaultStream::error_stream(),
- "Warning: The flag %s has been EOL'd as of 1.5.0 and will"
- " be ignored\n", arg);
+ "Warning: The flag %s has been EOL'd as of %s and will"
+ " be ignored\n", arg, buffer);
} else {
if (!ignore_unrecognized) {
jio_fprintf(defaultStream::error_stream(),
--- a/hotspot/src/share/vm/runtime/arguments.hpp Sat Jul 19 17:38:22 2008 -0400
+++ b/hotspot/src/share/vm/runtime/arguments.hpp Mon Jul 28 14:07:44 2008 -0400
@@ -357,9 +357,11 @@
short* methodsNum, short* methodsMax, char*** methods, bool** allClasses
);
- // Returns true if the string s is in the list of
- // flags made obsolete in 1.5.0.
- static bool made_obsolete_in_1_5_0(const char* s);
+ // Returns true if the string s is in the list of flags that have recently
+ // been made obsolete. If we detect one of these flags on the command
+ // line, instead of failing we print a warning message and ignore the
+ // flag. This gives the user a release or so to stop using the flag.
+ static bool is_newly_obsolete(const char* s, JDK_Version* buffer);
static short CompileOnlyClassesNum;
static short CompileOnlyClassesMax;
--- a/hotspot/src/share/vm/runtime/init.cpp Sat Jul 19 17:38:22 2008 -0400
+++ b/hotspot/src/share/vm/runtime/init.cpp Mon Jul 28 14:07:44 2008 -0400
@@ -39,7 +39,6 @@
void classLoader_init();
void codeCache_init();
void VM_Version_init();
-void JDK_Version_init();
void stubRoutines_init1();
jint universe_init(); // dependent on codeCache_init and stubRoutines_init
void interpreter_init(); // before any methods loaded
@@ -88,7 +87,6 @@
classLoader_init();
codeCache_init();
VM_Version_init();
- JDK_Version_init();
stubRoutines_init1();
jint status = universe_init(); // dependent on codeCache_init and stubRoutines_init
if (status != JNI_OK)
--- a/hotspot/src/share/vm/runtime/java.cpp Sat Jul 19 17:38:22 2008 -0400
+++ b/hotspot/src/share/vm/runtime/java.cpp Mon Jul 28 14:07:44 2008 -0400
@@ -563,32 +563,104 @@
vm_shutdown();
}
-jdk_version_info JDK_Version::_version_info = {0};
-bool JDK_Version::_pre_jdk16_version = false;
-int JDK_Version::_jdk_version = 0;
+JDK_Version JDK_Version::_current;
void JDK_Version::initialize() {
+ jdk_version_info info;
+ assert(!_current.is_valid(), "Don't initialize twice");
+
void *lib_handle = os::native_java_library();
- jdk_version_info_fn_t func =
- CAST_TO_FN_PTR(jdk_version_info_fn_t, hpi::dll_lookup(lib_handle, "JDK_GetVersionInfo0"));
+ jdk_version_info_fn_t func = CAST_TO_FN_PTR(jdk_version_info_fn_t,
+ os::dll_lookup(lib_handle, "JDK_GetVersionInfo0"));
if (func == NULL) {
// JDK older than 1.6
- _pre_jdk16_version = true;
- return;
- }
+ _current._partially_initialized = true;
+ } else {
+ (*func)(&info, sizeof(info));
- if (func != NULL) {
- (*func)(&_version_info, sizeof(_version_info));
+ int major = JDK_VERSION_MAJOR(info.jdk_version);
+ int minor = JDK_VERSION_MINOR(info.jdk_version);
+ int micro = JDK_VERSION_MICRO(info.jdk_version);
+ int build = JDK_VERSION_BUILD(info.jdk_version);
+ if (major == 1 && minor > 4) {
+ // We represent "1.5.0" as "5.0", but 1.4.2 as itself.
+ major = minor;
+ minor = micro;
+ micro = 0;
+ }
+ _current = JDK_Version(major, minor, micro, info.update_version,
+ info.special_update_version, build,
+ info.thread_park_blocker == 1);
}
- if (jdk_major_version() == 1) {
- _jdk_version = jdk_minor_version();
- } else {
- // If the release version string is changed to n.x.x (e.g. 7.0.0) in a future release
- _jdk_version = jdk_major_version();
+}
+
+void JDK_Version::fully_initialize(
+ uint8_t major, uint8_t minor, uint8_t micro, uint8_t update) {
+ // This is only called when current is less than 1.6 and we've gotten
+ // far enough in the initialization to determine the exact version.
+ assert(major < 6, "not needed for JDK version >= 6");
+ assert(is_partially_initialized(), "must not initialize");
+ if (major < 5) {
+ // JDK verison sequence: 1.2.x, 1.3.x, 1.4.x, 5.0.x, 6.0.x, etc.
+ micro = minor;
+ minor = major;
+ major = 1;
}
+ _current = JDK_Version(major, minor, micro, update);
}
void JDK_Version_init() {
JDK_Version::initialize();
}
+
+static int64_t encode_jdk_version(const JDK_Version& v) {
+ return
+ ((int64_t)v.major_version() << (BitsPerByte * 5)) |
+ ((int64_t)v.minor_version() << (BitsPerByte * 4)) |
+ ((int64_t)v.micro_version() << (BitsPerByte * 3)) |
+ ((int64_t)v.update_version() << (BitsPerByte * 2)) |
+ ((int64_t)v.special_update_version() << (BitsPerByte * 1)) |
+ ((int64_t)v.build_number() << (BitsPerByte * 0));
+}
+
+int JDK_Version::compare(const JDK_Version& other) const {
+ assert(is_valid() && other.is_valid(), "Invalid version (uninitialized?)");
+ if (!is_partially_initialized() && other.is_partially_initialized()) {
+ return -(other.compare(*this)); // flip the comparators
+ }
+ assert(!other.is_partially_initialized(), "Not initialized yet");
+ if (is_partially_initialized()) {
+ assert(other.major_version() >= 6,
+ "Invalid JDK version comparison during initialization");
+ return -1;
+ } else {
+ uint64_t e = encode_jdk_version(*this);
+ uint64_t o = encode_jdk_version(other);
+ return (e > o) ? 1 : ((e == o) ? 0 : -1);
+ }
+}
+
+void JDK_Version::to_string(char* buffer, size_t buflen) const {
+ size_t index = 0;
+ if (!is_valid()) {
+ jio_snprintf(buffer, buflen, "%s", "(uninitialized)");
+ } else if (is_partially_initialized()) {
+ jio_snprintf(buffer, buflen, "%s", "(uninitialized) pre-1.6.0");
+ } else {
+ index += jio_snprintf(
+ &buffer[index], buflen - index, "%d.%d", _major, _minor);
+ if (_micro > 0) {
+ index += jio_snprintf(&buffer[index], buflen - index, ".%d", _micro);
+ }
+ if (_update > 0) {
+ index += jio_snprintf(&buffer[index], buflen - index, "_%02d", _update);
+ }
+ if (_special > 0) {
+ index += jio_snprintf(&buffer[index], buflen - index, "%c", _special);
+ }
+ if (_build > 0) {
+ index += jio_snprintf(&buffer[index], buflen - index, "-b%02d", _build);
+ }
+ }
+}
--- a/hotspot/src/share/vm/runtime/java.hpp Sat Jul 19 17:38:22 2008 -0400
+++ b/hotspot/src/share/vm/runtime/java.hpp Mon Jul 28 14:07:44 2008 -0400
@@ -48,100 +48,163 @@
extern void vm_exit_during_initialization(const char* error, const char* message = NULL);
extern void vm_shutdown_during_initialization(const char* error, const char* message = NULL);
-class JDK_Version : AllStatic {
+/**
+ * Discovering the JDK_Version during initialization is tricky when the
+ * running JDK is less than JDK6. For JDK6 and greater, a "GetVersion"
+ * function exists in libjava.so and we simply call it during the
+ * 'initialize()' call to find the version. For JDKs with version < 6, no
+ * such call exists and we have to probe the JDK in order to determine
+ * the exact version. This probing cannot happen during late in
+ * the VM initialization process so there's a period of time during
+ * initialization when we don't know anything about the JDK version other than
+ * that it less than version 6. This is the "partially initialized" time,
+ * when we can answer only certain version queries (such as, is the JDK
+ * version greater than 5? Answer: no). Once the JDK probing occurs, we
+ * know the version and are considered fully initialized.
+ */
+class JDK_Version VALUE_OBJ_CLASS_SPEC {
friend class VMStructs;
+ friend class Universe;
+ friend void JDK_Version_init();
private:
- static jdk_version_info _version_info;
- static bool _pre_jdk16_version;
- static int _jdk_version; // JDK version number representing the release
- // i.e. n in 1.n.x (= jdk_minor_version())
+
+ static JDK_Version _current;
+
+ // In this class, we promote the minor version of release to be the
+ // major version for releases >= 5 in anticipation of the JDK doing the
+ // same thing. For example, we represent "1.5.0" as major version 5 (we
+ // drop the leading 1 and use 5 as the 'major').
+
+ uint8_t _major;
+ uint8_t _minor;
+ uint8_t _micro;
+ uint8_t _update;
+ uint8_t _special;
+ uint8_t _build;
+
+ // If partially initialized, the above fields are invalid and we know
+ // that we're less than major version 6.
+ bool _partially_initialized;
+
+ bool _thread_park_blocker;
+
+ bool is_valid() const {
+ return (_major != 0 || _partially_initialized);
+ }
+
+ // initializes or partially initializes the _current static field
+ static void initialize();
+
+ // Completes initialization for a pre-JDK6 version.
+ static void fully_initialize(uint8_t major, uint8_t minor = 0,
+ uint8_t micro = 0, uint8_t update = 0);
public:
- static void initialize();
- static int jdk_major_version() { return JDK_VERSION_MAJOR(_version_info.jdk_version); }
- static int jdk_minor_version() { return JDK_VERSION_MINOR(_version_info.jdk_version); }
- static int jdk_micro_version() { return JDK_VERSION_MICRO(_version_info.jdk_version); }
- static int jdk_build_number() { return JDK_VERSION_BUILD(_version_info.jdk_version); }
+
+ // Returns true if the the current version has only been partially initialized
+ static bool is_partially_initialized() {
+ return _current._partially_initialized;
+ }
+
+ JDK_Version() : _major(0), _minor(0), _micro(0), _update(0),
+ _special(0), _build(0), _partially_initialized(false),
+ _thread_park_blocker(false) {}
- static bool is_pre_jdk16_version() { return _pre_jdk16_version; }
- static bool is_jdk12x_version() { assert(is_jdk_version_initialized(), "must have been initialized"); return _jdk_version == 2; }
- static bool is_jdk13x_version() { assert(is_jdk_version_initialized(), "must have been initialized"); return _jdk_version == 3; }
- static bool is_jdk14x_version() { assert(is_jdk_version_initialized(), "must have been initialized"); return _jdk_version == 4; }
- static bool is_jdk15x_version() { assert(is_jdk_version_initialized(), "must have been initialized"); return _jdk_version == 5; }
+ JDK_Version(uint8_t major, uint8_t minor = 0, uint8_t micro = 0,
+ uint8_t update = 0, uint8_t special = 0, uint8_t build = 0,
+ bool thread_park_blocker = false) :
+ _major(major), _minor(minor), _micro(micro), _update(update),
+ _special(special), _build(build), _partially_initialized(false),
+ _thread_park_blocker(thread_park_blocker) {}
- static bool is_jdk16x_version() {
- if (is_jdk_version_initialized()) {
- return _jdk_version == 6;
- } else {
- assert(is_pre_jdk16_version(), "must have been initialized");
- return false;
- }
+ // Returns the current running JDK version
+ static JDK_Version current() { return _current; }
+
+ // Factory methods for convenience
+ static JDK_Version jdk(uint8_t m) {
+ return JDK_Version(m);
+ }
+
+ static JDK_Version jdk_update(uint8_t major, uint8_t update_number) {
+ return JDK_Version(major, 0, 0, update_number);
}
- static bool is_jdk17x_version() {
- if (is_jdk_version_initialized()) {
- return _jdk_version == 7;
+ uint8_t major_version() const { return _major; }
+ uint8_t minor_version() const { return _minor; }
+ uint8_t micro_version() const { return _micro; }
+ uint8_t update_version() const { return _update; }
+ uint8_t special_update_version() const { return _special; }
+ uint8_t build_number() const { return _build; }
+
+ bool supports_thread_park_blocker() const {
+ return _thread_park_blocker;
+ }
+
+ // Performs a full ordering comparison using all fields (update, build, etc.)
+ int compare(const JDK_Version& other) const;
+
+ /**
+ * Performs comparison using only the major version, returning negative
+ * if the major version of 'this' is less than the parameter, 0 if it is
+ * equal, and a positive value if it is greater.
+ */
+ int compare_major(int version) const {
+ if (_partially_initialized) {
+ if (version >= 6) {
+ return -1;
+ } else {
+ assert(false, "Can't make this comparison during init time");
+ return -1; // conservative
+ }
} else {
- assert(is_pre_jdk16_version(), "must have been initialized");
- return false;
+ return major_version() - version;
}
}
- static bool supports_thread_park_blocker() { return _version_info.thread_park_blocker; }
+ void to_string(char* buffer, size_t buflen) const;
+
+ // Convenience methods for queries on the current major/minor version
+ static bool is_jdk12x_version() {
+ return current().compare_major(2) == 0;
+ }
+
+ static bool is_jdk13x_version() {
+ return current().compare_major(3) == 0;
+ }
+
+ static bool is_jdk14x_version() {
+ return current().compare_major(4) == 0;
+ }
+
+ static bool is_jdk15x_version() {
+ return current().compare_major(5) == 0;
+ }
+
+ static bool is_jdk16x_version() {
+ return current().compare_major(6) == 0;
+ }
+
+ static bool is_jdk17x_version() {
+ return current().compare_major(7) == 0;
+ }
+
+ static bool is_gte_jdk13x_version() {
+ return current().compare_major(3) >= 0;
+ }
static bool is_gte_jdk14x_version() {
- // Keep the semantics of this that the version number is >= 1.4
- assert(is_jdk_version_initialized(), "Not initialized");
- return _jdk_version >= 4;
- }
- static bool is_gte_jdk15x_version() {
- // Keep the semantics of this that the version number is >= 1.5
- assert(is_jdk_version_initialized(), "Not initialized");
- return _jdk_version >= 5;
+ return current().compare_major(4) >= 0;
}
+
+ static bool is_gte_jdk15x_version() {
+ return current().compare_major(5) >= 0;
+ }
+
static bool is_gte_jdk16x_version() {
- // Keep the semantics of this that the version number is >= 1.6
- if (is_jdk_version_initialized()) {
- return _jdk_version >= 6;
- } else {
- assert(is_pre_jdk16_version(), "Not initialized");
- return false;
- }
+ return current().compare_major(6) >= 0;
}
static bool is_gte_jdk17x_version() {
- // Keep the semantics of this that the version number is >= 1.7
- if (is_jdk_version_initialized()) {
- return _jdk_version >= 7;
- } else {
- assert(is_pre_jdk16_version(), "Not initialized");
- return false;
- }
- }
-
- static bool is_jdk_version_initialized() {
- return _jdk_version > 0;
- }
-
- // These methods are defined to deal with pre JDK 1.6 versions
- static void set_jdk12x_version() {
- assert(_pre_jdk16_version && !is_jdk_version_initialized(), "must not initialize");
- _jdk_version = 2;
- _version_info.jdk_version = (1 << 24) | (2 << 16);
- }
- static void set_jdk13x_version() {
- assert(_pre_jdk16_version && !is_jdk_version_initialized(), "must not initialize");
- _jdk_version = 3;
- _version_info.jdk_version = (1 << 24) | (3 << 16);
- }
- static void set_jdk14x_version() {
- assert(_pre_jdk16_version && !is_jdk_version_initialized(), "must not initialize");
- _jdk_version = 4;
- _version_info.jdk_version = (1 << 24) | (4 << 16);
- }
- static void set_jdk15x_version() {
- assert(_pre_jdk16_version && !is_jdk_version_initialized(), "must not initialize");
- _jdk_version = 5;
- _version_info.jdk_version = (1 << 24) | (5 << 16);
+ return current().compare_major(7) >= 0;
}
};
--- a/hotspot/src/share/vm/runtime/os.cpp Sat Jul 19 17:38:22 2008 -0400
+++ b/hotspot/src/share/vm/runtime/os.cpp Mon Jul 28 14:07:44 2008 -0400
@@ -336,29 +336,38 @@
char buffer[JVM_MAXPATHLEN];
char ebuf[1024];
- // Try to load verify dll first. In 1.3 java dll depends on it and is not always
- // able to find it when the loading executable is outside the JDK.
+ // Try to load verify dll first. In 1.3 java dll depends on it and is not
+ // always able to find it when the loading executable is outside the JDK.
// In order to keep working with 1.2 we ignore any loading errors.
- hpi::dll_build_name(buffer, sizeof(buffer), Arguments::get_dll_dir(), "verify");
- hpi::dll_load(buffer, ebuf, sizeof(ebuf));
+ dll_build_name(buffer, sizeof(buffer), Arguments::get_dll_dir(), "verify");
+ dll_load(buffer, ebuf, sizeof(ebuf));
// Load java dll
- hpi::dll_build_name(buffer, sizeof(buffer), Arguments::get_dll_dir(), "java");
- _native_java_library = hpi::dll_load(buffer, ebuf, sizeof(ebuf));
+ dll_build_name(buffer, sizeof(buffer), Arguments::get_dll_dir(), "java");
+ _native_java_library = dll_load(buffer, ebuf, sizeof(ebuf));
if (_native_java_library == NULL) {
vm_exit_during_initialization("Unable to load native library", ebuf);
}
- // The JNI_OnLoad handling is normally done by method load in java.lang.ClassLoader$NativeLibrary,
- // but the VM loads the base library explicitly so we have to check for JNI_OnLoad as well
- const char *onLoadSymbols[] = JNI_ONLOAD_SYMBOLS;
- JNI_OnLoad_t JNI_OnLoad = CAST_TO_FN_PTR(JNI_OnLoad_t, hpi::dll_lookup(_native_java_library, onLoadSymbols[0]));
- if (JNI_OnLoad != NULL) {
- JavaThread* thread = JavaThread::current();
- ThreadToNativeFromVM ttn(thread);
- HandleMark hm(thread);
- jint ver = (*JNI_OnLoad)(&main_vm, NULL);
- if (!Threads::is_supported_jni_version_including_1_1(ver)) {
- vm_exit_during_initialization("Unsupported JNI version");
+ }
+ static jboolean onLoaded = JNI_FALSE;
+ if (onLoaded) {
+ // We may have to wait to fire OnLoad until TLS is initialized.
+ if (ThreadLocalStorage::is_initialized()) {
+ // The JNI_OnLoad handling is normally done by method load in
+ // java.lang.ClassLoader$NativeLibrary, but the VM loads the base library
+ // explicitly so we have to check for JNI_OnLoad as well
+ const char *onLoadSymbols[] = JNI_ONLOAD_SYMBOLS;
+ JNI_OnLoad_t JNI_OnLoad = CAST_TO_FN_PTR(
+ JNI_OnLoad_t, dll_lookup(_native_java_library, onLoadSymbols[0]));
+ if (JNI_OnLoad != NULL) {
+ JavaThread* thread = JavaThread::current();
+ ThreadToNativeFromVM ttn(thread);
+ HandleMark hm(thread);
+ jint ver = (*JNI_OnLoad)(&main_vm, NULL);
+ onLoaded = JNI_TRUE;
+ if (!Threads::is_supported_jni_version_including_1_1(ver)) {
+ vm_exit_during_initialization("Unsupported JNI version");
+ }
}
}
}
--- a/hotspot/src/share/vm/runtime/os.hpp Sat Jul 19 17:38:22 2008 -0400
+++ b/hotspot/src/share/vm/runtime/os.hpp Mon Jul 28 14:07:44 2008 -0400
@@ -390,6 +390,10 @@
static const char* get_temp_directory();
static const char* get_current_directory(char *buf, int buflen);
+ // Builds a platform-specific full library path given a ld path and lib name
+ static void dll_build_name(char* buffer, size_t size,
+ const char* pathname, const char* fname);
+
// Symbol lookup, find nearest function name; basically it implements
// dladdr() for all platforms. Name of the nearest function is copied
// to buf. Distance from its base address is returned as offset.
@@ -413,6 +417,9 @@
// same architecture as Hotspot is running on
static void* dll_load(const char *name, char *ebuf, int ebuflen);
+ // lookup symbol in a shared library
+ static void* dll_lookup(void* handle, const char* name);
+
// Print out system information; they are called by fatal error handler.
// Output format may be different on different platforms.
static void print_os_info(outputStream* st);
--- a/hotspot/src/share/vm/runtime/thread.cpp Sat Jul 19 17:38:22 2008 -0400
+++ b/hotspot/src/share/vm/runtime/thread.cpp Mon Jul 28 14:07:44 2008 -0400
@@ -2578,7 +2578,8 @@
oop JavaThread::current_park_blocker() {
// Support for JSR-166 locks
oop thread_oop = threadObj();
- if (thread_oop != NULL && JDK_Version::supports_thread_park_blocker()) {
+ if (thread_oop != NULL &&
+ JDK_Version::current().supports_thread_park_blocker()) {
return java_lang_Thread::park_blocker(thread_oop);
}
return NULL;
@@ -2761,6 +2762,8 @@
jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
+ extern void JDK_Version_init();
+
// Check version
if (!is_supported_jni_version(args->version)) return JNI_EVERSION;
@@ -2776,6 +2779,9 @@
// Initialize system properties.
Arguments::init_system_properties();
+ // So that JDK version can be used as a discrimintor when parsing arguments
+ JDK_Version_init();
+
// Parse arguments
jint parse_result = Arguments::parse(args);
if (parse_result != JNI_OK) return parse_result;
--- a/hotspot/src/share/vm/runtime/threadLocalStorage.cpp Sat Jul 19 17:38:22 2008 -0400
+++ b/hotspot/src/share/vm/runtime/threadLocalStorage.cpp Mon Jul 28 14:07:44 2008 -0400
@@ -42,8 +42,13 @@
}
void ThreadLocalStorage::init() {
- assert(ThreadLocalStorage::thread_index() == -1, "More than one attempt to initialize threadLocalStorage");
+ assert(!is_initialized(),
+ "More than one attempt to initialize threadLocalStorage");
pd_init();
set_thread_index(os::allocate_thread_local_storage());
generate_code_for_get_thread();
}
+
+bool ThreadLocalStorage::is_initialized() {
+ return (thread_index() != -1);
+}
--- a/hotspot/src/share/vm/runtime/threadLocalStorage.hpp Sat Jul 19 17:38:22 2008 -0400
+++ b/hotspot/src/share/vm/runtime/threadLocalStorage.hpp Mon Jul 28 14:07:44 2008 -0400
@@ -47,6 +47,7 @@
// Initialization
// Called explicitly from VMThread::activate_system instead of init_globals.
static void init();
+ static bool is_initialized();
private:
static int _thread_index;
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp Sat Jul 19 17:38:22 2008 -0400
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Mon Jul 28 14:07:44 2008 -0400
@@ -761,8 +761,9 @@
static_field(Abstract_VM_Version, _vm_minor_version, int) \
static_field(Abstract_VM_Version, _vm_build_number, int) \
\
- static_field(JDK_Version, _pre_jdk16_version, bool) \
- static_field(JDK_Version, _jdk_version, int) \
+ static_field(JDK_Version, _current, JDK_Version) \
+ nonstatic_field(JDK_Version, _partially_initialized, bool) \
+ nonstatic_field(JDK_Version, _major, unsigned char) \
\
\
\
--- a/hotspot/src/share/vm/services/threadService.cpp Sat Jul 19 17:38:22 2008 -0400
+++ b/hotspot/src/share/vm/services/threadService.cpp Mon Jul 28 14:07:44 2008 -0400
@@ -744,7 +744,7 @@
}
// Support for JSR-166 locks
- if (JDK_Version::supports_thread_park_blocker() &&
+ if (JDK_Version::current().supports_thread_park_blocker() &&
(_thread_status == java_lang_Thread::PARKED ||
_thread_status == java_lang_Thread::PARKED_TIMED)) {