--- a/.hgtags Thu Mar 21 08:41:10 2019 +0000
+++ b/.hgtags Thu Mar 21 18:04:01 2019 +0000
@@ -549,3 +549,5 @@
8e069f7b4fabfe05d9f500783e6d56cb0196d25c jdk-13+10
21ea4076a275a0f498afa517e9ee1b94a9cf0255 jdk-13+11
1d7aec80147a6d92b101a76aef92f3ddc88bedf4 jdk-13+12
+b67884871b5fff79c5ef3eb8ac74dd48d71ea9b1 jdk-12-ga
+83cace4142c8563b6a921787db02388e1bc48d01 jdk-13+13
--- a/make/conf/jib-profiles.js Thu Mar 21 08:41:10 2019 +0000
+++ b/make/conf/jib-profiles.js Thu Mar 21 18:04:01 2019 +0000
@@ -955,7 +955,8 @@
: input.target_platform);
var devkit_cross_prefix = "";
- if (input.target_platform != input.build_platform) {
+ if (input.build_platform != input.target_platform
+ && input.build_platform != devkit_platform) {
devkit_cross_prefix = input.build_platform + "-to-";
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/os/linux/gc/z/zLargePages_linux.cpp Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "precompiled.hpp"
+#include "gc/z/zLargePages.hpp"
+#include "runtime/globals.hpp"
+
+void ZLargePages::initialize_platform() {
+ if (UseLargePages) {
+ if (UseTransparentHugePages) {
+ _state = Transparent;
+ } else {
+ _state = Explicit;
+ }
+ } else {
+ _state = Disabled;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/os/linux/gc/z/zNUMA_linux.cpp Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "gc/z/zErrno.hpp"
+#include "gc/z/zCPU.hpp"
+#include "gc/z/zNUMA.hpp"
+#include "runtime/os.hpp"
+#include "utilities/debug.hpp"
+
+#include <unistd.h>
+#include <sys/syscall.h>
+
+#ifndef MPOL_F_NODE
+#define MPOL_F_NODE (1<<0) // Return next IL mode instead of node mask
+#endif
+
+#ifndef MPOL_F_ADDR
+#define MPOL_F_ADDR (1<<1) // Look up VMA using address
+#endif
+
+static int z_get_mempolicy(uint32_t* mode, const unsigned long *nmask, unsigned long maxnode, uintptr_t addr, int flags) {
+ return syscall(__NR_get_mempolicy, mode, nmask, maxnode, addr, flags);
+}
+
+void ZNUMA::initialize_platform() {
+ _enabled = UseNUMA;
+}
+
+uint32_t ZNUMA::count() {
+ if (!_enabled) {
+ // NUMA support not enabled
+ return 1;
+ }
+
+ return os::Linux::numa_max_node() + 1;
+}
+
+uint32_t ZNUMA::id() {
+ if (!_enabled) {
+ // NUMA support not enabled
+ return 0;
+ }
+
+ return os::Linux::get_node_by_cpu(ZCPU::id());
+}
+
+uint32_t ZNUMA::memory_id(uintptr_t addr) {
+ if (!_enabled) {
+ // NUMA support not enabled, assume everything belongs to node zero
+ return 0;
+ }
+
+ uint32_t id = (uint32_t)-1;
+
+ if (z_get_mempolicy(&id, NULL, 0, addr, MPOL_F_NODE | MPOL_F_ADDR) == -1) {
+ ZErrno err;
+ fatal("Failed to get NUMA id for memory at " PTR_FORMAT " (%s)", addr, err.to_string());
+ }
+
+ assert(id < count(), "Invalid NUMA id");
+
+ return id;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/os/linux/gc/z/zVirtualMemory_linux.cpp Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "precompiled.hpp"
+#include "gc/z/zVirtualMemory.hpp"
+#include "logging/log.hpp"
+
+#include <sys/mman.h>
+#include <sys/types.h>
+
+bool ZVirtualMemoryManager::reserve(uintptr_t start, size_t size) {
+ // Reserve address space
+ const uintptr_t actual_start = (uintptr_t)mmap((void*)start, size, PROT_NONE,
+ MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
+ if (actual_start != start) {
+ log_error(gc)("Failed to reserve address space for Java heap");
+ return false;
+ }
+
+ return true;
+}
--- a/src/hotspot/os/linux/osContainer_linux.cpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/os/linux/osContainer_linux.cpp Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -99,14 +99,14 @@
buf[MAXPATHLEN-1] = '\0';
_path = os::strdup(buf);
} else {
- char *p = strstr(_root, cgroup_path);
+ char *p = strstr(cgroup_path, _root);
if (p != NULL && p == _root) {
if (strlen(cgroup_path) > strlen(_root)) {
int buflen;
strncpy(buf, _mount_point, MAXPATHLEN);
buf[MAXPATHLEN-1] = '\0';
buflen = strlen(buf);
- if ((buflen + strlen(cgroup_path)) > (MAXPATHLEN-1)) {
+ if ((buflen + strlen(cgroup_path) - strlen(_root)) > (MAXPATHLEN-1)) {
return;
}
strncat(buf, cgroup_path + strlen(_root), MAXPATHLEN-buflen);
@@ -217,16 +217,11 @@
* we are running under cgroup control.
*/
void OSContainer::init() {
- int mountid;
- int parentid;
- int major;
- int minor;
FILE *mntinfo = NULL;
FILE *cgroup = NULL;
char buf[MAXPATHLEN+1];
char tmproot[MAXPATHLEN+1];
char tmpmount[MAXPATHLEN+1];
- char tmpbase[MAXPATHLEN+1];
char *p;
jlong mem_limit;
@@ -260,85 +255,24 @@
return;
}
- while ( (p = fgets(buf, MAXPATHLEN, mntinfo)) != NULL) {
- // Look for the filesystem type and see if it's cgroup
- char fstype[MAXPATHLEN+1];
- fstype[0] = '\0';
- char *s = strstr(p, " - ");
- if (s != NULL &&
- sscanf(s, " - %s", fstype) == 1 &&
- strcmp(fstype, "cgroup") == 0) {
+ while ((p = fgets(buf, MAXPATHLEN, mntinfo)) != NULL) {
+ char tmpcgroups[MAXPATHLEN+1];
+ char *cptr = tmpcgroups;
+ char *token;
- if (strstr(p, "memory") != NULL) {
- int matched = sscanf(p, "%d %d %d:%d %s %s",
- &mountid,
- &parentid,
- &major,
- &minor,
- tmproot,
- tmpmount);
- if (matched == 6) {
- memory = new CgroupSubsystem(tmproot, tmpmount);
- }
- else
- log_debug(os, container)("Incompatible str containing cgroup and memory: %s", p);
- } else if (strstr(p, "cpuset") != NULL) {
- int matched = sscanf(p, "%d %d %d:%d %s %s",
- &mountid,
- &parentid,
- &major,
- &minor,
- tmproot,
- tmpmount);
- if (matched == 6) {
- cpuset = new CgroupSubsystem(tmproot, tmpmount);
- }
- else {
- log_debug(os, container)("Incompatible str containing cgroup and cpuset: %s", p);
- }
- } else if (strstr(p, "cpu,cpuacct") != NULL || strstr(p, "cpuacct,cpu") != NULL) {
- int matched = sscanf(p, "%d %d %d:%d %s %s",
- &mountid,
- &parentid,
- &major,
- &minor,
- tmproot,
- tmpmount);
- if (matched == 6) {
- cpu = new CgroupSubsystem(tmproot, tmpmount);
- cpuacct = new CgroupSubsystem(tmproot, tmpmount);
- }
- else {
- log_debug(os, container)("Incompatible str containing cgroup and cpu,cpuacct: %s", p);
- }
- } else if (strstr(p, "cpuacct") != NULL) {
- int matched = sscanf(p, "%d %d %d:%d %s %s",
- &mountid,
- &parentid,
- &major,
- &minor,
- tmproot,
- tmpmount);
- if (matched == 6) {
- cpuacct = new CgroupSubsystem(tmproot, tmpmount);
- }
- else {
- log_debug(os, container)("Incompatible str containing cgroup and cpuacct: %s", p);
- }
- } else if (strstr(p, "cpu") != NULL) {
- int matched = sscanf(p, "%d %d %d:%d %s %s",
- &mountid,
- &parentid,
- &major,
- &minor,
- tmproot,
- tmpmount);
- if (matched == 6) {
- cpu = new CgroupSubsystem(tmproot, tmpmount);
- }
- else {
- log_debug(os, container)("Incompatible str containing cgroup and cpu: %s", p);
- }
+ // mountinfo format is documented at https://www.kernel.org/doc/Documentation/filesystems/proc.txt
+ if (sscanf(p, "%*d %*d %*d:%*d %s %s %*[^-]- cgroup %*s %s", tmproot, tmpmount, tmpcgroups) != 3) {
+ continue;
+ }
+ while ((token = strsep(&cptr, ",")) != NULL) {
+ if (strcmp(token, "memory") == 0) {
+ memory = new CgroupSubsystem(tmproot, tmpmount);
+ } else if (strcmp(token, "cpuset") == 0) {
+ cpuset = new CgroupSubsystem(tmproot, tmpmount);
+ } else if (strcmp(token, "cpu") == 0) {
+ cpu = new CgroupSubsystem(tmproot, tmpmount);
+ } else if (strcmp(token, "cpuacct") == 0) {
+ cpuacct= new CgroupSubsystem(tmproot, tmpmount);
}
}
}
@@ -392,30 +326,30 @@
return;
}
- while ( (p = fgets(buf, MAXPATHLEN, cgroup)) != NULL) {
- int cgno;
- int matched;
- char *controller;
+ while ((p = fgets(buf, MAXPATHLEN, cgroup)) != NULL) {
+ char *controllers;
+ char *token;
char *base;
/* Skip cgroup number */
strsep(&p, ":");
- /* Get controller and base */
- controller = strsep(&p, ":");
+ /* Get controllers and base */
+ controllers = strsep(&p, ":");
base = strsep(&p, "\n");
- if (controller != NULL) {
- if (strstr(controller, "memory") != NULL) {
+ if (controllers == NULL) {
+ continue;
+ }
+
+ while ((token = strsep(&controllers, ",")) != NULL) {
+ if (strcmp(token, "memory") == 0) {
memory->set_subsystem_path(base);
- } else if (strstr(controller, "cpuset") != NULL) {
+ } else if (strcmp(token, "cpuset") == 0) {
cpuset->set_subsystem_path(base);
- } else if (strstr(controller, "cpu,cpuacct") != NULL || strstr(controller, "cpuacct,cpu") != NULL) {
+ } else if (strcmp(token, "cpu") == 0) {
cpu->set_subsystem_path(base);
+ } else if (strcmp(token, "cpuacct") == 0) {
cpuacct->set_subsystem_path(base);
- } else if (strstr(controller, "cpuacct") != NULL) {
- cpuacct->set_subsystem_path(base);
- } else if (strstr(controller, "cpu") != NULL) {
- cpu->set_subsystem_path(base);
}
}
}
--- a/src/hotspot/os/linux/os_linux.cpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/os/linux/os_linux.cpp Thu Mar 21 18:04:01 2019 +0000
@@ -2140,46 +2140,87 @@
st->print("container (cgroup) information:\n");
const char *p_ct = OSContainer::container_type();
- st->print("container_type: %s\n", p_ct != NULL ? p_ct : "failed");
+ st->print("container_type: %s\n", p_ct != NULL ? p_ct : "not supported");
char *p = OSContainer::cpu_cpuset_cpus();
- st->print("cpu_cpuset_cpus: %s\n", p != NULL ? p : "failed");
+ st->print("cpu_cpuset_cpus: %s\n", p != NULL ? p : "not supported");
free(p);
p = OSContainer::cpu_cpuset_memory_nodes();
- st->print("cpu_memory_nodes: %s\n", p != NULL ? p : "failed");
+ st->print("cpu_memory_nodes: %s\n", p != NULL ? p : "not supported");
free(p);
int i = OSContainer::active_processor_count();
+ st->print("active_processor_count: ");
if (i > 0) {
- st->print("active_processor_count: %d\n", i);
+ st->print("%d\n", i);
} else {
- st->print("active_processor_count: failed\n");
+ st->print("not supported\n");
}
i = OSContainer::cpu_quota();
- st->print("cpu_quota: %d\n", i);
+ st->print("cpu_quota: ");
+ if (i > 0) {
+ st->print("%d\n", i);
+ } else {
+ st->print("%s\n", i == OSCONTAINER_ERROR ? "not supported" : "no quota");
+ }
i = OSContainer::cpu_period();
- st->print("cpu_period: %d\n", i);
+ st->print("cpu_period: ");
+ if (i > 0) {
+ st->print("%d\n", i);
+ } else {
+ st->print("%s\n", i == OSCONTAINER_ERROR ? "not supported" : "no period");
+ }
i = OSContainer::cpu_shares();
- st->print("cpu_shares: %d\n", i);
+ st->print("cpu_shares: ");
+ if (i > 0) {
+ st->print("%d\n", i);
+ } else {
+ st->print("%s\n", i == OSCONTAINER_ERROR ? "not supported" : "no shares");
+ }
jlong j = OSContainer::memory_limit_in_bytes();
- st->print("memory_limit_in_bytes: " JLONG_FORMAT "\n", j);
+ st->print("memory_limit_in_bytes: ");
+ if (j > 0) {
+ st->print(JLONG_FORMAT "\n", j);
+ } else {
+ st->print("%s\n", j == OSCONTAINER_ERROR ? "not supported" : "unlimited");
+ }
j = OSContainer::memory_and_swap_limit_in_bytes();
- st->print("memory_and_swap_limit_in_bytes: " JLONG_FORMAT "\n", j);
+ st->print("memory_and_swap_limit_in_bytes: ");
+ if (j > 0) {
+ st->print(JLONG_FORMAT "\n", j);
+ } else {
+ st->print("%s\n", j == OSCONTAINER_ERROR ? "not supported" : "unlimited");
+ }
j = OSContainer::memory_soft_limit_in_bytes();
- st->print("memory_soft_limit_in_bytes: " JLONG_FORMAT "\n", j);
+ st->print("memory_soft_limit_in_bytes: ");
+ if (j > 0) {
+ st->print(JLONG_FORMAT "\n", j);
+ } else {
+ st->print("%s\n", j == OSCONTAINER_ERROR ? "not supported" : "unlimited");
+ }
j = OSContainer::OSContainer::memory_usage_in_bytes();
- st->print("memory_usage_in_bytes: " JLONG_FORMAT "\n", j);
+ st->print("memory_usage_in_bytes: ");
+ if (j > 0) {
+ st->print(JLONG_FORMAT "\n", j);
+ } else {
+ st->print("%s\n", j == OSCONTAINER_ERROR ? "not supported" : "unlimited");
+ }
j = OSContainer::OSContainer::memory_max_usage_in_bytes();
- st->print("memory_max_usage_in_bytes: " JLONG_FORMAT "\n", j);
+ st->print("memory_max_usage_in_bytes: ");
+ if (j > 0) {
+ st->print(JLONG_FORMAT "\n", j);
+ } else {
+ st->print("%s\n", j == OSCONTAINER_ERROR ? "not supported" : "unlimited");
+ }
st->cr();
}
@@ -2292,7 +2333,7 @@
#elif defined(PPC64)
const char* search_string = "cpu";
#elif defined(S390)
-const char* search_string = "processor";
+const char* search_string = "machine =";
#elif defined(SPARC)
const char* search_string = "cpu";
#else
--- a/src/hotspot/os/posix/os_posix.cpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/os/posix/os_posix.cpp Thu Mar 21 18:04:01 2019 +0000
@@ -1671,6 +1671,8 @@
if ((status = pthread_mutexattr_settype(_mutexAttr, PTHREAD_MUTEX_NORMAL)) != 0) {
fatal("pthread_mutexattr_settype: %s", os::strerror(status));
}
+ // Solaris has it's own PlatformMonitor, distinct from the one for POSIX.
+ NOT_SOLARIS(os::PlatformMonitor::init();)
}
#ifndef SOLARIS
@@ -2250,20 +2252,64 @@
// Platform Monitor implementation
-os::PlatformMonitor::PlatformMonitor() {
+os::PlatformMonitor::Impl::Impl() : _next(NULL) {
int status = pthread_cond_init(&_cond, _condAttr);
assert_status(status == 0, status, "cond_init");
status = pthread_mutex_init(&_mutex, _mutexAttr);
assert_status(status == 0, status, "mutex_init");
}
-os::PlatformMonitor::~PlatformMonitor() {
+os::PlatformMonitor::Impl::~Impl() {
int status = pthread_cond_destroy(&_cond);
assert_status(status == 0, status, "cond_destroy");
status = pthread_mutex_destroy(&_mutex);
assert_status(status == 0, status, "mutex_destroy");
}
+#if PLATFORM_MONITOR_IMPL_INDIRECT
+
+pthread_mutex_t os::PlatformMonitor::_freelist_lock;
+os::PlatformMonitor::Impl* os::PlatformMonitor::_freelist = NULL;
+
+void os::PlatformMonitor::init() {
+ int status = pthread_mutex_init(&_freelist_lock, _mutexAttr);
+ assert_status(status == 0, status, "freelist lock init");
+}
+
+struct os::PlatformMonitor::WithFreeListLocked : public StackObj {
+ WithFreeListLocked() {
+ int status = pthread_mutex_lock(&_freelist_lock);
+ assert_status(status == 0, status, "freelist lock");
+ }
+
+ ~WithFreeListLocked() {
+ int status = pthread_mutex_unlock(&_freelist_lock);
+ assert_status(status == 0, status, "freelist unlock");
+ }
+};
+
+os::PlatformMonitor::PlatformMonitor() {
+ {
+ WithFreeListLocked wfl;
+ _impl = _freelist;
+ if (_impl != NULL) {
+ _freelist = _impl->_next;
+ _impl->_next = NULL;
+ return;
+ }
+ }
+ _impl = new Impl();
+}
+
+os::PlatformMonitor::~PlatformMonitor() {
+ WithFreeListLocked wfl;
+ assert(_impl->_next == NULL, "invariant");
+ _impl->_next = _freelist;
+ _freelist = _impl;
+}
+
+#endif // PLATFORM_MONITOR_IMPL_INDIRECT
+
// Must already be locked
int os::PlatformMonitor::wait(jlong millis) {
assert(millis >= 0, "negative timeout");
@@ -2278,7 +2324,7 @@
to_abstime(&abst, millis * (NANOUNITS / MILLIUNITS), false, false);
int ret = OS_TIMEOUT;
- int status = pthread_cond_timedwait(&_cond, &_mutex, &abst);
+ int status = pthread_cond_timedwait(cond(), mutex(), &abst);
assert_status(status == 0 || status == ETIMEDOUT,
status, "cond_timedwait");
if (status == 0) {
@@ -2286,7 +2332,7 @@
}
return ret;
} else {
- int status = pthread_cond_wait(&_cond, &_mutex);
+ int status = pthread_cond_wait(cond(), mutex());
assert_status(status == 0, status, "cond_wait");
return OS_OK;
}
--- a/src/hotspot/os/posix/os_posix.hpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/os/posix/os_posix.hpp Thu Mar 21 18:04:01 2019 +0000
@@ -232,15 +232,60 @@
PlatformParker();
};
+// Workaround for a bug in macOSX kernel's pthread support (fixed in Mojave?).
+// Avoid ever allocating a pthread_mutex_t at the same address as one of our
+// former pthread_cond_t, by using a freelist of mutex/condvar pairs.
+// Conditional to avoid extra indirection and padding loss on other platforms.
+#ifdef __APPLE__
+#define PLATFORM_MONITOR_IMPL_INDIRECT 1
+#else
+#define PLATFORM_MONITOR_IMPL_INDIRECT 0
+#endif
+
// Platform specific implementation that underpins VM Monitor/Mutex class
class PlatformMonitor : public CHeapObj<mtSynchronizer> {
- private:
- pthread_mutex_t _mutex; // Native mutex for locking
- pthread_cond_t _cond; // Native condition variable for blocking
+ class Impl : public CHeapObj<mtSynchronizer> {
+ public:
+ pthread_mutex_t _mutex;
+ pthread_cond_t _cond;
+ Impl* _next;
+
+ Impl();
+ ~Impl();
+ };
+
+#if PLATFORM_MONITOR_IMPL_INDIRECT
+
+ Impl* _impl;
+
+ pthread_mutex_t* mutex() { return &(_impl->_mutex); }
+ pthread_cond_t* cond() { return &(_impl->_cond); }
+
+ class WithFreeListLocked;
+ static pthread_mutex_t _freelist_lock;
+ static Impl* _freelist;
public:
- PlatformMonitor();
+ PlatformMonitor(); // Use freelist allocation of impl.
~PlatformMonitor();
+
+ static void init(); // Initialize the freelist.
+
+#else
+
+ Impl _impl;
+
+ pthread_mutex_t* mutex() { return &(_impl._mutex); }
+ pthread_cond_t* cond() { return &(_impl._cond); }
+
+ public:
+ static void init() {} // Nothing needed for the non-indirect case.
+
+ // Default constructor and destructor.
+
+#endif // PLATFORM_MONITOR_IMPL_INDIRECT
+
+ public:
void lock();
void unlock();
bool try_lock();
--- a/src/hotspot/os/posix/os_posix.inline.hpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/os/posix/os_posix.inline.hpp Thu Mar 21 18:04:01 2019 +0000
@@ -50,28 +50,28 @@
// Platform Monitor implementation
inline void os::PlatformMonitor::lock() {
- int status = pthread_mutex_lock(&_mutex);
+ int status = pthread_mutex_lock(mutex());
assert_status(status == 0, status, "mutex_lock");
}
inline void os::PlatformMonitor::unlock() {
- int status = pthread_mutex_unlock(&_mutex);
+ int status = pthread_mutex_unlock(mutex());
assert_status(status == 0, status, "mutex_unlock");
}
inline bool os::PlatformMonitor::try_lock() {
- int status = pthread_mutex_trylock(&_mutex);
+ int status = pthread_mutex_trylock(mutex());
assert_status(status == 0 || status == EBUSY, status, "mutex_trylock");
return status == 0;
}
inline void os::PlatformMonitor::notify() {
- int status = pthread_cond_signal(&_cond);
+ int status = pthread_cond_signal(cond());
assert_status(status == 0, status, "cond_signal");
}
inline void os::PlatformMonitor::notify_all() {
- int status = pthread_cond_broadcast(&_cond);
+ int status = pthread_cond_broadcast(cond());
assert_status(status == 0, status, "cond_broadcast");
}
--- a/src/hotspot/os_cpu/linux_x86/gc/z/zLargePages_linux_x86.cpp Thu Mar 21 08:41:10 2019 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include "precompiled.hpp"
-#include "gc/z/zLargePages.hpp"
-#include "runtime/globals.hpp"
-
-void ZLargePages::initialize_platform() {
- if (UseLargePages) {
- if (UseTransparentHugePages) {
- _state = Transparent;
- } else {
- _state = Explicit;
- }
- } else {
- _state = Disabled;
- }
-}
--- a/src/hotspot/os_cpu/linux_x86/gc/z/zNUMA_linux_x86.cpp Thu Mar 21 08:41:10 2019 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,83 +0,0 @@
-/*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include "gc/z/zErrno.hpp"
-#include "gc/z/zCPU.hpp"
-#include "gc/z/zNUMA.hpp"
-#include "runtime/os.hpp"
-#include "utilities/debug.hpp"
-
-#include <unistd.h>
-#include <sys/syscall.h>
-
-#ifndef MPOL_F_NODE
-#define MPOL_F_NODE (1<<0) // Return next IL mode instead of node mask
-#endif
-
-#ifndef MPOL_F_ADDR
-#define MPOL_F_ADDR (1<<1) // Look up VMA using address
-#endif
-
-static int z_get_mempolicy(uint32_t* mode, const unsigned long *nmask, unsigned long maxnode, uintptr_t addr, int flags) {
- return syscall(__NR_get_mempolicy, mode, nmask, maxnode, addr, flags);
-}
-
-void ZNUMA::initialize_platform() {
- _enabled = UseNUMA;
-}
-
-uint32_t ZNUMA::count() {
- if (!_enabled) {
- // NUMA support not enabled
- return 1;
- }
-
- return os::Linux::numa_max_node() + 1;
-}
-
-uint32_t ZNUMA::id() {
- if (!_enabled) {
- // NUMA support not enabled
- return 0;
- }
-
- return os::Linux::get_node_by_cpu(ZCPU::id());
-}
-
-uint32_t ZNUMA::memory_id(uintptr_t addr) {
- if (!_enabled) {
- // NUMA support not enabled, assume everything belongs to node zero
- return 0;
- }
-
- uint32_t id = (uint32_t)-1;
-
- if (z_get_mempolicy(&id, NULL, 0, addr, MPOL_F_NODE | MPOL_F_ADDR) == -1) {
- ZErrno err;
- fatal("Failed to get NUMA id for memory at " PTR_FORMAT " (%s)", addr, err.to_string());
- }
-
- assert(id < count(), "Invalid NUMA id");
-
- return id;
-}
--- a/src/hotspot/os_cpu/linux_x86/gc/z/zPhysicalMemoryBacking_linux_x86.cpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/os_cpu/linux_x86/gc/z/zPhysicalMemoryBacking_linux_x86.cpp Thu Mar 21 18:04:01 2019 +0000
@@ -237,8 +237,8 @@
}
void ZPhysicalMemoryBacking::map(ZPhysicalMemory pmem, uintptr_t offset) const {
- if (ZUnmapBadViews) {
- // Only map the good view, for debugging only
+ if (ZVerifyViews) {
+ // Map good view
map_view(pmem, ZAddress::good(offset), AlwaysPreTouch);
} else {
// Map all views
@@ -249,8 +249,8 @@
}
void ZPhysicalMemoryBacking::unmap(ZPhysicalMemory pmem, uintptr_t offset) const {
- if (ZUnmapBadViews) {
- // Only map the good view, for debugging only
+ if (ZVerifyViews) {
+ // Unmap good view
unmap_view(pmem, ZAddress::good(offset));
} else {
// Unmap all views
@@ -260,11 +260,14 @@
}
}
-void ZPhysicalMemoryBacking::flip(ZPhysicalMemory pmem, uintptr_t offset) const {
- assert(ZUnmapBadViews, "Should be enabled");
- const uintptr_t addr_good = ZAddress::good(offset);
- const uintptr_t addr_bad = ZAddress::is_marked(ZAddressGoodMask) ? ZAddress::remapped(offset) : ZAddress::marked(offset);
- // Map/Unmap views
- map_view(pmem, addr_good, false /* pretouch */);
- unmap_view(pmem, addr_bad);
+void ZPhysicalMemoryBacking::debug_map(ZPhysicalMemory pmem, uintptr_t offset) const {
+ // Map good view
+ assert(ZVerifyViews, "Should be enabled");
+ map_view(pmem, ZAddress::good(offset), false /* pretouch */);
}
+
+void ZPhysicalMemoryBacking::debug_unmap(ZPhysicalMemory pmem, uintptr_t offset) const {
+ // Unmap good view
+ assert(ZVerifyViews, "Should be enabled");
+ unmap_view(pmem, ZAddress::good(offset));
+}
--- a/src/hotspot/os_cpu/linux_x86/gc/z/zPhysicalMemoryBacking_linux_x86.hpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/os_cpu/linux_x86/gc/z/zPhysicalMemoryBacking_linux_x86.hpp Thu Mar 21 18:04:01 2019 +0000
@@ -58,7 +58,9 @@
void map(ZPhysicalMemory pmem, uintptr_t offset) const;
void unmap(ZPhysicalMemory pmem, uintptr_t offset) const;
- void flip(ZPhysicalMemory pmem, uintptr_t offset) const;
+
+ void debug_map(ZPhysicalMemory pmem, uintptr_t offset) const;
+ void debug_unmap(ZPhysicalMemory pmem, uintptr_t offset) const;
};
#endif // OS_CPU_LINUX_X86_GC_Z_ZPHYSICALMEMORYBACKING_LINUX_X86_HPP
--- a/src/hotspot/os_cpu/linux_x86/gc/z/zVirtualMemory_linux_x86.cpp Thu Mar 21 08:41:10 2019 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include "precompiled.hpp"
-#include "gc/z/zVirtualMemory.hpp"
-#include "logging/log.hpp"
-
-#include <sys/mman.h>
-#include <sys/types.h>
-
-bool ZVirtualMemoryManager::reserve(uintptr_t start, size_t size) {
- // Reserve address space
- const uintptr_t actual_start = (uintptr_t)mmap((void*)start, size, PROT_NONE,
- MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
- if (actual_start != start) {
- log_error(gc)("Failed to reserve address space for Java heap");
- return false;
- }
-
- return true;
-}
--- a/src/hotspot/share/c1/c1_LIRGenerator.cpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/c1/c1_LIRGenerator.cpp Thu Mar 21 18:04:01 2019 +0000
@@ -3279,7 +3279,14 @@
void LIRGenerator::increment_backedge_counter_conditionally(LIR_Condition cond, LIR_Opr left, LIR_Opr right, CodeEmitInfo* info, int left_bci, int right_bci, int bci) {
if (compilation()->count_backedges()) {
+#if defined(X86) && !defined(_LP64)
+ // BEWARE! On 32-bit x86 cmp clobbers its left argument so we need a temp copy.
+ LIR_Opr left_copy = new_register(left->type());
+ __ move(left, left_copy);
+ __ cmp(cond, left_copy, right);
+#else
__ cmp(cond, left, right);
+#endif
LIR_Opr step = new_register(T_INT);
LIR_Opr plus_one = LIR_OprFact::intConst(InvocationCounter::count_increment);
LIR_Opr zero = LIR_OprFact::intConst(0);
--- a/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp Thu Mar 21 18:04:01 2019 +0000
@@ -4248,7 +4248,7 @@
verify_overflow_empty();
if (should_unload_classes()) {
- heap->prune_nmethods();
+ heap->prune_scavengable_nmethods();
}
JvmtiExport::gc_epilogue();
--- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp Thu Mar 21 18:04:01 2019 +0000
@@ -717,10 +717,10 @@
}
void ParallelScavengeHeap::flush_nmethod(nmethod* nm) {
- ScavengableNMethods::flush_nmethod(nm);
+ // nothing particular
}
-void ParallelScavengeHeap::prune_nmethods() {
+void ParallelScavengeHeap::prune_scavengable_nmethods() {
ScavengableNMethods::prune_nmethods();
}
--- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp Thu Mar 21 18:04:01 2019 +0000
@@ -162,7 +162,7 @@
virtual void verify_nmethod(nmethod* nm);
virtual void flush_nmethod(nmethod* nm);
- void prune_nmethods();
+ void prune_scavengable_nmethods();
size_t max_capacity() const;
--- a/src/hotspot/share/gc/parallel/psMarkSweep.cpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/parallel/psMarkSweep.cpp Thu Mar 21 18:04:01 2019 +0000
@@ -254,7 +254,7 @@
MetaspaceUtils::verify_metrics();
BiasedLocking::restore_marks();
- heap->prune_nmethods();
+ heap->prune_scavengable_nmethods();
JvmtiExport::gc_epilogue();
#if COMPILER2_OR_JVMCI
--- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp Thu Mar 21 18:04:01 2019 +0000
@@ -1061,7 +1061,7 @@
ClassLoaderDataGraph::purge();
MetaspaceUtils::verify_metrics();
- heap->prune_nmethods();
+ heap->prune_scavengable_nmethods();
JvmtiExport::gc_epilogue();
#if COMPILER2_OR_JVMCI
--- a/src/hotspot/share/gc/parallel/psTasks.cpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/parallel/psTasks.cpp Thu Mar 21 18:04:01 2019 +0000
@@ -98,8 +98,8 @@
case code_cache:
{
- MarkingCodeBlobClosure each_scavengable_code_blob(&roots_to_old_closure, CodeBlobToOopClosure::FixRelocations);
- ScavengableNMethods::scavengable_nmethods_do(&each_scavengable_code_blob);
+ MarkingCodeBlobClosure code_closure(&roots_to_old_closure, CodeBlobToOopClosure::FixRelocations);
+ ScavengableNMethods::nmethods_do(&code_closure);
AOTLoader::oops_do(&roots_closure);
}
break;
--- a/src/hotspot/share/gc/serial/genMarkSweep.cpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/serial/genMarkSweep.cpp Thu Mar 21 18:04:01 2019 +0000
@@ -124,7 +124,7 @@
rs->invalidate_or_clear(old_gen);
}
- gch->prune_nmethods();
+ gch->prune_scavengable_nmethods();
JvmtiExport::gc_epilogue();
// refs processing: clean slate
--- a/src/hotspot/share/gc/shared/genCollectedHeap.cpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/shared/genCollectedHeap.cpp Thu Mar 21 18:04:01 2019 +0000
@@ -723,10 +723,10 @@
}
void GenCollectedHeap::flush_nmethod(nmethod* nm) {
- ScavengableNMethods::flush_nmethod(nm);
+ // Do nothing.
}
-void GenCollectedHeap::prune_nmethods() {
+void GenCollectedHeap::prune_scavengable_nmethods() {
ScavengableNMethods::prune_nmethods();
}
@@ -871,7 +871,7 @@
assert(code_roots != NULL, "must supply closure for code cache");
// We only visit parts of the CodeCache when scavenging.
- ScavengableNMethods::scavengable_nmethods_do(code_roots);
+ ScavengableNMethods::nmethods_do(code_roots);
}
if (so & SO_AllCodeCache) {
assert(code_roots != NULL, "must supply closure for code cache");
--- a/src/hotspot/share/gc/shared/genCollectedHeap.hpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/shared/genCollectedHeap.hpp Thu Mar 21 18:04:01 2019 +0000
@@ -255,7 +255,7 @@
virtual void verify_nmethod(nmethod* nm);
virtual void flush_nmethod(nmethod* nm);
- void prune_nmethods();
+ void prune_scavengable_nmethods();
// Iteration functions.
void oop_iterate(OopIterateClosure* cl);
--- a/src/hotspot/share/gc/shared/scavengableNMethods.cpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/shared/scavengableNMethods.cpp Thu Mar 21 18:04:01 2019 +0000
@@ -25,13 +25,10 @@
#include "precompiled.hpp"
#include "code/codeCache.hpp"
#include "code/nmethod.hpp"
-#include "compiler/compileTask.hpp"
-#include "gc/shared/collectedHeap.hpp"
#include "gc/shared/scavengableNMethods.hpp"
#include "gc/shared/scavengableNMethodsData.hpp"
-#include "logging/log.hpp"
-#include "logging/logStream.hpp"
#include "memory/universe.hpp"
+#include "runtime/mutexLocker.hpp"
#include "utilities/debug.hpp"
static ScavengableNMethodsData gc_data(nmethod* nm) {
@@ -60,12 +57,21 @@
data.set_next(_head);
_head = nm;
-
- CodeCache::print_trace("register_nmethod", nm);
}
void ScavengableNMethods::unregister_nmethod(nmethod* nm) {
- // Do nothing. Unlinking is currently delayed until the purge phase.
+ assert_locked_or_safepoint(CodeCache_lock);
+
+ if (gc_data(nm).on_list()) {
+ nmethod* prev = NULL;
+ for (nmethod* cur = _head; cur != NULL; cur = gc_data(cur).next()) {
+ if (cur == nm) {
+ unlist_nmethod(cur, prev);
+ return;
+ }
+ prev = cur;
+ }
+ }
}
#ifndef PRODUCT
@@ -112,57 +118,21 @@
#endif // PRODUCT
}
-void ScavengableNMethods::flush_nmethod(nmethod* nm) {
- assert_locked_or_safepoint(CodeCache_lock);
-
- // TODO: Should be done in unregister_nmethod, during the "unlink" phase.
- if (gc_data(nm).on_list()) {
- CodeCache::print_trace("flush_nmethod", nm);
- nmethod* prev = NULL;
- for (nmethod* cur = _head; cur != NULL; cur = gc_data(cur).next()) {
- if (cur == nm) {
- unlist_nmethod(cur, prev);
- return;
- }
- prev = cur;
- }
- }
-}
-
class HasScavengableOops: public OopClosure {
BoolObjectClosure* _is_scavengable;
bool _found;
- nmethod* _print_nm;
public:
HasScavengableOops(BoolObjectClosure* is_scavengable, nmethod* nm) :
_is_scavengable(is_scavengable),
- _found(false),
- _print_nm(nm) {}
+ _found(false) {}
bool found() { return _found; }
virtual void do_oop(oop* p) {
- if (*p != NULL && _is_scavengable->do_object_b(*p)) {
- NOT_PRODUCT(maybe_print(p));
+ if (!_found && *p != NULL && _is_scavengable->do_object_b(*p)) {
_found = true;
}
}
virtual void do_oop(narrowOop* p) { ShouldNotReachHere(); }
-
-#ifndef PRODUCT
- void maybe_print(oop* p) {
- LogTarget(Trace, gc, nmethod) lt;
- if (lt.is_enabled()) {
- LogStream ls(lt);
- if (!_found) {
- CompileTask::print(&ls, _print_nm, "new scavengable oop", /*short_form:*/ true);
- }
- ls.print("" PTR_FORMAT "[offset=%d] found scavengable oop " PTR_FORMAT " (found at " PTR_FORMAT ") ",
- p2i(_print_nm), (int)((intptr_t)p - (intptr_t)_print_nm),
- p2i(*p), p2i(p));
- ls.cr();
- }
- }
-#endif //PRODUCT
};
bool ScavengableNMethods::has_scavengable_oops(nmethod* nm) {
@@ -172,42 +142,32 @@
}
// Walk the list of methods which might contain oops to the java heap.
-void ScavengableNMethods::scavengable_nmethods_do(CodeBlobToOopClosure* f) {
+void ScavengableNMethods::nmethods_do_and_prune(CodeBlobToOopClosure* cl) {
assert_locked_or_safepoint(CodeCache_lock);
- const bool fix_relocations = f->fix_relocations();
debug_only(mark_on_list_nmethods());
nmethod* prev = NULL;
nmethod* cur = _head;
while (cur != NULL) {
+ assert(cur->is_alive(), "Must be");
+
ScavengableNMethodsData data = gc_data(cur);
debug_only(data.clear_marked());
- assert(data.not_marked(), "");
assert(data.on_list(), "else shouldn't be on this list");
- bool is_live = (!cur->is_zombie() && !cur->is_unloaded());
- LogTarget(Trace, gc, nmethod) lt;
- if (lt.is_enabled()) {
- LogStream ls(lt);
- CompileTask::print(&ls, cur,
- is_live ? "scavengable root " : "dead scavengable root", /*short_form:*/ true);
- }
- if (is_live) {
- // Perform cur->oops_do(f), maybe just once per nmethod.
- f->do_code_blob(cur);
+ if (cl != NULL) {
+ cl->do_code_blob(cur);
}
+
nmethod* const next = data.next();
- // The scavengable nmethod list must contain all methods with scavengable
- // oops. It is safe to include more nmethod on the list, but we do not
- // expect any live non-scavengable nmethods on the list.
- if (fix_relocations) {
- if (!is_live || !has_scavengable_oops(cur)) {
- unlist_nmethod(cur, prev);
- } else {
- prev = cur;
- }
+
+ if (!has_scavengable_oops(cur)) {
+ unlist_nmethod(cur, prev);
+ } else {
+ prev = cur;
}
+
cur = next;
}
@@ -215,15 +175,24 @@
debug_only(verify_unlisted_nmethods(NULL));
}
+void ScavengableNMethods::prune_nmethods() {
+ nmethods_do_and_prune(NULL /* No closure */);
+}
+
+// Walk the list of methods which might contain oops to the java heap.
+void ScavengableNMethods::nmethods_do(CodeBlobToOopClosure* cl) {
+ nmethods_do_and_prune(cl);
+}
+
#ifndef PRODUCT
-void ScavengableNMethods::asserted_non_scavengable_nmethods_do(CodeBlobClosure* f) {
+void ScavengableNMethods::asserted_non_scavengable_nmethods_do(CodeBlobClosure* cl) {
// While we are here, verify the integrity of the list.
mark_on_list_nmethods();
for (nmethod* cur = _head; cur != NULL; cur = gc_data(cur).next()) {
assert(gc_data(cur).on_list(), "else shouldn't be on this list");
gc_data(cur).clear_marked();
}
- verify_unlisted_nmethods(f);
+ verify_unlisted_nmethods(cl);
}
#endif // PRODUCT
@@ -233,8 +202,6 @@
assert((prev == NULL && _head == nm) ||
(prev != NULL && gc_data(prev).next() == nm), "precondition");
- CodeCache::print_trace("unlist_nmethod", nm);
-
ScavengableNMethodsData data = gc_data(nm);
if (prev == NULL) {
@@ -246,33 +213,6 @@
data.clear_on_list();
}
-void ScavengableNMethods::prune_nmethods() {
- assert_locked_or_safepoint(CodeCache_lock);
-
- debug_only(mark_on_list_nmethods());
-
- nmethod* last = NULL;
- nmethod* cur = _head;
- while (cur != NULL) {
- nmethod* next = gc_data(cur).next();
- debug_only(gc_data(cur).clear_marked());
- assert(gc_data(cur).on_list(), "else shouldn't be on this list");
-
- if (!cur->is_zombie() && !cur->is_unloaded() && has_scavengable_oops(cur)) {
- // Keep it. Advance 'last' to prevent deletion.
- last = cur;
- } else {
- // Prune it from the list, so we don't have to look at it any more.
- CodeCache::print_trace("prune_nmethods", cur);
- unlist_nmethod(cur, last);
- }
- cur = next;
- }
-
- // Check for stray marks.
- debug_only(verify_unlisted_nmethods(NULL));
-}
-
#ifndef PRODUCT
// Temporarily mark nmethods that are claimed to be on the scavenge list.
void ScavengableNMethods::mark_on_list_nmethods() {
@@ -288,15 +228,15 @@
// If the closure is given, run it on the unlisted nmethods.
// Also make sure that the effects of mark_on_list_nmethods is gone.
-void ScavengableNMethods::verify_unlisted_nmethods(CodeBlobClosure* f_or_null) {
+void ScavengableNMethods::verify_unlisted_nmethods(CodeBlobClosure* cl) {
NMethodIterator iter(NMethodIterator::only_alive);
while(iter.next()) {
nmethod* nm = iter.method();
verify_nmethod(nm);
- if (f_or_null != NULL && !gc_data(nm).on_list()) {
- f_or_null->do_code_blob(nm);
+ if (cl != NULL && !gc_data(nm).on_list()) {
+ cl->do_code_blob(nm);
}
}
}
--- a/src/hotspot/share/gc/shared/scavengableNMethods.hpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/shared/scavengableNMethods.hpp Thu Mar 21 18:04:01 2019 +0000
@@ -45,26 +45,24 @@
static void register_nmethod(nmethod* nm);
static void unregister_nmethod(nmethod* nm);
static void verify_nmethod(nmethod* nm);
- static void flush_nmethod(nmethod* nm);
+ // Remove nmethods that no longer have scavengable oops.
static void prune_nmethods();
- // Apply f to every live code blob in scavengable nmethods. Prune nmethods
- // from the list of scavengable nmethods if f->fix_relocations() and a nmethod
- // no longer has scavengable oops. If f->fix_relocations(), then f must copy
- // objects to their new location immediately to avoid fixing nmethods on the
- // basis of the old object locations.
- static void scavengable_nmethods_do(CodeBlobToOopClosure* f);
+ // Apply closure to every scavengable nmethod.
+ // Remove nmethods that no longer have scavengable oops.
+ static void nmethods_do(CodeBlobToOopClosure* cl);
- static void asserted_non_scavengable_nmethods_do(CodeBlobClosure* f = NULL) PRODUCT_RETURN;
+ static void asserted_non_scavengable_nmethods_do(CodeBlobClosure* cl) PRODUCT_RETURN;
private:
+ static void nmethods_do_and_prune(CodeBlobToOopClosure* cl);
static void unlist_nmethod(nmethod* nm, nmethod* prev);
static bool has_scavengable_oops(nmethod* nm);
static void mark_on_list_nmethods() PRODUCT_RETURN;
- static void verify_unlisted_nmethods(CodeBlobClosure* f_or_null) PRODUCT_RETURN;
+ static void verify_unlisted_nmethods(CodeBlobClosure* cl) PRODUCT_RETURN;
};
#endif // SHARE_GC_SHARED_SCAVENGABLENMETHODS_HPP
--- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.hpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.hpp Thu Mar 21 18:04:01 2019 +0000
@@ -226,7 +226,10 @@
template <typename T>
static void oop_store_in_heap(T* addr, oop value) {
- ShenandoahBarrierSet::barrier_set()->write_ref_field_pre_work(addr, value);
+ const bool keep_alive = (decorators & AS_NO_KEEPALIVE) == 0;
+ if (keep_alive) {
+ ShenandoahBarrierSet::barrier_set()->write_ref_field_pre_work(addr, value);
+ }
Raw::oop_store(addr, value);
}
--- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp Thu Mar 21 18:04:01 2019 +0000
@@ -58,7 +58,8 @@
expected = res;
} while ((! oopDesc::equals_raw(compare_value, expected)) && oopDesc::equals_raw(resolve_forwarded(compare_value), resolve_forwarded(expected)));
if (oopDesc::equals_raw(expected, compare_value)) {
- if (ShenandoahSATBBarrier && !CompressedOops::is_null(compare_value)) {
+ const bool keep_alive = (decorators & AS_NO_KEEPALIVE) == 0;
+ if (keep_alive && ShenandoahSATBBarrier && !CompressedOops::is_null(compare_value)) {
ShenandoahBarrierSet::barrier_set()->enqueue(compare_value);
}
}
@@ -70,7 +71,8 @@
inline oop ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_atomic_xchg_in_heap(oop new_value, T* addr) {
oop previous = Raw::oop_atomic_xchg(new_value, addr);
if (ShenandoahSATBBarrier) {
- if (!CompressedOops::is_null(previous)) {
+ const bool keep_alive = (decorators & AS_NO_KEEPALIVE) == 0;
+ if (keep_alive && !CompressedOops::is_null(previous)) {
ShenandoahBarrierSet::barrier_set()->enqueue(previous);
}
}
--- a/src/hotspot/share/gc/z/vmStructs_z.hpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/z/vmStructs_z.hpp Thu Mar 21 18:04:01 2019 +0000
@@ -24,7 +24,9 @@
#ifndef SHARE_GC_Z_VMSTRUCTS_Z_HPP
#define SHARE_GC_Z_VMSTRUCTS_Z_HPP
+#include "gc/z/zAttachedArray.hpp"
#include "gc/z/zCollectedHeap.hpp"
+#include "gc/z/zForwarding.hpp"
#include "gc/z/zGranuleMap.hpp"
#include "gc/z/zHeap.hpp"
#include "gc/z/zPageAllocator.hpp"
@@ -52,7 +54,8 @@
const int* _ZObjectAlignmentSmall;
};
-typedef ZGranuleMap<ZPageTableEntry> ZGranuleMapForPageTable;
+typedef ZGranuleMap<ZPage*> ZGranuleMapForPageTable;
+typedef ZAttachedArray<ZForwarding, ZForwardingEntry> ZAttachedArrayForForwarding;
#define VM_STRUCTS_ZGC(nonstatic_field, volatile_nonstatic_field, static_field) \
static_field(ZGlobalsForVMStructs, _instance_p, ZGlobalsForVMStructs*) \
@@ -67,27 +70,24 @@
nonstatic_field(ZCollectedHeap, _heap, ZHeap) \
\
nonstatic_field(ZHeap, _page_allocator, ZPageAllocator) \
- nonstatic_field(ZHeap, _pagetable, ZPageTable) \
+ nonstatic_field(ZHeap, _page_table, ZPageTable) \
\
nonstatic_field(ZPage, _type, const uint8_t) \
nonstatic_field(ZPage, _seqnum, uint32_t) \
nonstatic_field(ZPage, _virtual, const ZVirtualMemory) \
volatile_nonstatic_field(ZPage, _top, uintptr_t) \
- volatile_nonstatic_field(ZPage, _refcount, uint32_t) \
- nonstatic_field(ZPage, _forwarding, ZForwardingTable) \
\
nonstatic_field(ZPageAllocator, _physical, ZPhysicalMemoryManager) \
nonstatic_field(ZPageAllocator, _used, size_t) \
\
nonstatic_field(ZPageTable, _map, ZGranuleMapForPageTable) \
\
- nonstatic_field(ZGranuleMapForPageTable, _map, ZPageTableEntry* const) \
+ nonstatic_field(ZGranuleMapForPageTable, _map, ZPage** const) \
\
nonstatic_field(ZVirtualMemory, _start, uintptr_t) \
nonstatic_field(ZVirtualMemory, _end, uintptr_t) \
\
- nonstatic_field(ZForwardingTable, _table, ZForwardingTableEntry*) \
- nonstatic_field(ZForwardingTable, _size, size_t) \
+ nonstatic_field(ZForwarding, _entries, const ZAttachedArrayForForwarding) \
\
nonstatic_field(ZPhysicalMemoryManager, _max_capacity, const size_t) \
nonstatic_field(ZPhysicalMemoryManager, _capacity, size_t)
@@ -117,11 +117,12 @@
declare_toplevel_type(ZPage) \
declare_toplevel_type(ZPageAllocator) \
declare_toplevel_type(ZPageTable) \
- declare_toplevel_type(ZPageTableEntry) \
+ declare_toplevel_type(ZAttachedArrayForForwarding) \
declare_toplevel_type(ZGranuleMapForPageTable) \
declare_toplevel_type(ZVirtualMemory) \
declare_toplevel_type(ZForwardingTable) \
- declare_toplevel_type(ZForwardingTableEntry) \
+ declare_toplevel_type(ZForwarding) \
+ declare_toplevel_type(ZForwardingEntry) \
declare_toplevel_type(ZPhysicalMemoryManager)
#endif // SHARE_GC_Z_VMSTRUCTS_Z_HPP
--- a/src/hotspot/share/gc/z/zArray.hpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/z/zArray.hpp Thu Mar 21 18:04:01 2019 +0000
@@ -51,6 +51,7 @@
T at(size_t index) const;
void add(T value);
+ void transfer(ZArray<T>* from);
void clear();
};
--- a/src/hotspot/share/gc/z/zArray.inline.hpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/z/zArray.inline.hpp Thu Mar 21 18:04:01 2019 +0000
@@ -80,6 +80,17 @@
}
template <typename T>
+inline void ZArray<T>::transfer(ZArray<T>* from) {
+ assert(_array == NULL, "Should be empty");
+ _array = from->_array;
+ _size = from->_size;
+ _capacity = from->_capacity;
+ from->_array = NULL;
+ from->_size = 0;
+ from->_capacity = 0;
+}
+
+template <typename T>
inline void ZArray<T>::clear() {
_size = 0;
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/z/zAttachedArray.hpp Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef SHARE_GC_Z_ZATTACHEDARRAY_HPP
+#define SHARE_GC_Z_ZATTACHEDARRAY_HPP
+
+#include "utilities/globalDefinitions.hpp"
+
+template <typename ObjectT, typename ArrayT>
+class ZAttachedArray {
+private:
+ const uint32_t _length;
+
+ static size_t object_size();
+
+public:
+ static void* alloc(size_t length);
+ static void free(ObjectT* obj);
+
+ ZAttachedArray(size_t length);
+
+ uint32_t length() const;
+ ArrayT* operator()(const ObjectT* obj) const;
+};
+
+#endif // SHARE_GC_Z_ZATTACHEDARRAY_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/z/zAttachedArray.inline.hpp Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef SHARE_GC_Z_ZATTACHEDARRAY_INLINE_HPP
+#define SHARE_GC_Z_ZATTACHEDARRAY_INLINE_HPP
+
+#include "gc/z/zAttachedArray.hpp"
+#include "memory/allocation.hpp"
+#include "utilities/align.hpp"
+
+template <typename ObjectT, typename ArrayT>
+inline size_t ZAttachedArray<ObjectT, ArrayT>::object_size() {
+ return align_up(sizeof(ObjectT), sizeof(ArrayT));
+}
+
+template <typename ObjectT, typename ArrayT>
+inline void* ZAttachedArray<ObjectT, ArrayT>::alloc(size_t length) {
+ const size_t array_size = sizeof(ArrayT) * length;
+ char* const addr = AllocateHeap(object_size() + array_size, mtGC);
+ ::new (addr + object_size()) ArrayT[length];
+ return addr;
+}
+
+template <typename ObjectT, typename ArrayT>
+inline void ZAttachedArray<ObjectT, ArrayT>::free(ObjectT* obj) {
+ FreeHeap(obj);
+}
+
+template <typename ObjectT, typename ArrayT>
+inline ZAttachedArray<ObjectT, ArrayT>::ZAttachedArray(size_t length) :
+ _length(length) {}
+
+template <typename ObjectT, typename ArrayT>
+inline uint32_t ZAttachedArray<ObjectT, ArrayT>::length() const {
+ return _length;
+}
+
+template <typename ObjectT, typename ArrayT>
+inline ArrayT* ZAttachedArray<ObjectT, ArrayT>::operator()(const ObjectT* obj) const {
+ return reinterpret_cast<ArrayT*>(reinterpret_cast<uintptr_t>(obj) + object_size());
+}
+
+#endif // SHARE_GC_Z_ZATTACHEDARRAY_INLINE_HPP
--- a/src/hotspot/share/gc/z/zBarrier.cpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/z/zBarrier.cpp Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -98,27 +98,13 @@
uintptr_t ZBarrier::remap(uintptr_t addr) {
assert(!ZAddress::is_good(addr), "Should not be good");
assert(!ZAddress::is_weak_good(addr), "Should not be weak good");
-
- if (ZHeap::heap()->is_relocating(addr)) {
- // Forward
- return ZHeap::heap()->forward_object(addr);
- }
-
- // Remap
- return ZAddress::good(addr);
+ return ZHeap::heap()->remap_object(addr);
}
uintptr_t ZBarrier::relocate(uintptr_t addr) {
assert(!ZAddress::is_good(addr), "Should not be good");
assert(!ZAddress::is_weak_good(addr), "Should not be weak good");
-
- if (ZHeap::heap()->is_relocating(addr)) {
- // Relocate
- return ZHeap::heap()->relocate_object(addr);
- }
-
- // Remap
- return ZAddress::good(addr);
+ return ZHeap::heap()->relocate_object(addr);
}
uintptr_t ZBarrier::relocate_or_mark(uintptr_t addr) {
--- a/src/hotspot/share/gc/z/zDebug.gdb Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/z/zDebug.gdb Thu Mar 21 18:04:01 2019 +0000
@@ -53,17 +53,17 @@
printf "Mark: 0x%016llx\tKlass: %s\n", (uintptr_t)$obj->_mark, (char*)$obj->_metadata->_klass->_name->_body
end
-# Print heap page by pagetable index
+# Print heap page by page table index
define zpp
- set $page = (ZPage*)((uintptr_t)ZHeap::_heap._pagetable._map._map[($arg0)] & ~1)
+ set $page = (ZPage*)((uintptr_t)ZHeap::_heap._page_table._map._map[($arg0)] & ~1)
printf "Page %p\n", $page
print *$page
end
-# Print pagetable
+# Print page_table
define zpt
printf "Pagetable (first 128 slots)\n"
- x/128gx ZHeap::_heap._pagetable._map._map
+ x/128gx ZHeap::_heap._page_table._map._map
end
# Print live map
@@ -100,7 +100,7 @@
set $addr = $arg0
set $obj = ((uintptr_t)$addr & ZAddressOffsetMask)
set $page_index = $obj >> ZGranuleSizeShift
- set $page_entry = (uintptr_t)ZHeap::_heap._pagetable._map._map[$page_index]
+ set $page_entry = (uintptr_t)ZHeap::_heap._page_table._map._map[$page_index]
set $page = (ZPage*)($page_entry & ~1)
set $page_start = (uintptr_t)$page._virtual._start
set $page_end = (uintptr_t)$page._virtual._end
--- a/src/hotspot/share/gc/z/zDriver.cpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/z/zDriver.cpp Thu Mar 21 18:04:01 2019 +0000
@@ -43,9 +43,7 @@
static const ZStatPhasePause ZPhasePauseMarkEnd("Pause Mark End");
static const ZStatPhaseConcurrent ZPhaseConcurrentProcessNonStrongReferences("Concurrent Process Non-Strong References");
static const ZStatPhaseConcurrent ZPhaseConcurrentResetRelocationSet("Concurrent Reset Relocation Set");
-static const ZStatPhaseConcurrent ZPhaseConcurrentDestroyDetachedPages("Concurrent Destroy Detached Pages");
static const ZStatPhaseConcurrent ZPhaseConcurrentSelectRelocationSet("Concurrent Select Relocation Set");
-static const ZStatPhaseConcurrent ZPhaseConcurrentPrepareRelocationSet("Concurrent Prepare Relocation Set");
static const ZStatPhasePause ZPhasePauseRelocateStart("Pause Relocate Start");
static const ZStatPhaseConcurrent ZPhaseConcurrentRelocated("Concurrent Relocate");
static const ZStatCriticalPhase ZCriticalPhaseGCLockerStall("GC Locker Stall", false /* verbose */);
@@ -300,11 +298,6 @@
ZHeap::heap()->reset_relocation_set();
}
-void ZDriver::concurrent_destroy_detached_pages() {
- ZStatTimer timer(ZPhaseConcurrentDestroyDetachedPages);
- ZHeap::heap()->destroy_detached_pages();
-}
-
void ZDriver::pause_verify() {
if (VerifyBeforeGC || VerifyDuringGC || VerifyAfterGC) {
VM_Verify op;
@@ -317,11 +310,6 @@
ZHeap::heap()->select_relocation_set();
}
-void ZDriver::concurrent_prepare_relocation_set() {
- ZStatTimer timer(ZPhaseConcurrentPrepareRelocationSet);
- ZHeap::heap()->prepare_relocation_set();
-}
-
void ZDriver::pause_relocate_start() {
pause<VM_ZRelocateStart>();
}
@@ -384,22 +372,16 @@
// Phase 5: Concurrent Reset Relocation Set
concurrent_reset_relocation_set();
- // Phase 6: Concurrent Destroy Detached Pages
- concurrent_destroy_detached_pages();
-
- // Phase 7: Pause Verify
+ // Phase 6: Pause Verify
pause_verify();
- // Phase 8: Concurrent Select Relocation Set
+ // Phase 7: Concurrent Select Relocation Set
concurrent_select_relocation_set();
- // Phase 9: Concurrent Prepare Relocation Set
- concurrent_prepare_relocation_set();
-
- // Phase 10: Pause Relocate Start
+ // Phase 8: Pause Relocate Start
pause_relocate_start();
- // Phase 11: Concurrent Relocate
+ // Phase 9: Concurrent Relocate
concurrent_relocate();
}
--- a/src/hotspot/share/gc/z/zDriver.hpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/z/zDriver.hpp Thu Mar 21 18:04:01 2019 +0000
@@ -43,10 +43,8 @@
void concurrent_mark_continue();
void concurrent_process_non_strong_references();
void concurrent_reset_relocation_set();
- void concurrent_destroy_detached_pages();
void pause_verify();
void concurrent_select_relocation_set();
- void concurrent_prepare_relocation_set();
void pause_relocate_start();
void concurrent_relocate();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/z/zForwarding.cpp Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "precompiled.hpp"
+#include "gc/z/zForwarding.inline.hpp"
+#include "gc/z/zPage.inline.hpp"
+#include "gc/z/zUtils.inline.hpp"
+#include "memory/allocation.hpp"
+#include "utilities/debug.hpp"
+
+ZForwarding* ZForwarding::create(ZPage* page) {
+ // Allocate table for linear probing. The size of the table must be
+ // a power of two to allow for quick and inexpensive indexing/masking.
+ // The table is sized to have a load factor of 50%, i.e. sized to have
+ // double the number of entries actually inserted.
+ assert(page->live_objects() > 0, "Invalid value");
+ const uint32_t nentries = ZUtils::round_up_power_of_2(page->live_objects() * 2);
+ return ::new (AttachedArray::alloc(nentries)) ZForwarding(page, nentries);
+}
+
+void ZForwarding::destroy(ZForwarding* forwarding) {
+ AttachedArray::free(forwarding);
+}
+
+ZForwarding::ZForwarding(ZPage* page, uint32_t nentries) :
+ _virtual(page->virtual_memory()),
+ _object_alignment_shift(page->object_alignment_shift()),
+ _entries(nentries),
+ _page(page),
+ _refcount(1),
+ _pinned(false) {}
+
+void ZForwarding::verify() const {
+ guarantee(_refcount > 0, "Invalid refcount");
+ guarantee(_page != NULL, "Invalid page");
+
+ uint32_t live_objects = 0;
+
+ for (ZForwardingCursor i = 0; i < _entries.length(); i++) {
+ const ZForwardingEntry entry = at(&i);
+ if (entry.is_empty()) {
+ // Skip empty entries
+ continue;
+ }
+
+ // Check from index
+ guarantee(entry.from_index() < _page->object_max_count(), "Invalid from index");
+
+ // Check for duplicates
+ for (ZForwardingCursor j = i + 1; j < _entries.length(); j++) {
+ const ZForwardingEntry other = at(&j);
+ guarantee(entry.from_index() != other.from_index(), "Duplicate from");
+ guarantee(entry.to_offset() != other.to_offset(), "Duplicate to");
+ }
+
+ live_objects++;
+ }
+
+ // Check number of non-empty entries
+ guarantee(live_objects == _page->live_objects(), "Invalid number of entries");
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/z/zForwarding.hpp Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef SHARE_GC_Z_ZFORWARDING_HPP
+#define SHARE_GC_Z_ZFORWARDING_HPP
+
+#include "gc/z/zAttachedArray.hpp"
+#include "gc/z/zForwardingEntry.hpp"
+#include "gc/z/zVirtualMemory.hpp"
+
+class ZPage;
+
+typedef uint32_t ZForwardingCursor;
+
+class ZForwarding {
+ friend class VMStructs;
+ friend class ZForwardingTest;
+
+private:
+ typedef ZAttachedArray<ZForwarding, ZForwardingEntry> AttachedArray;
+
+ const ZVirtualMemory _virtual;
+ const size_t _object_alignment_shift;
+ const AttachedArray _entries;
+ ZPage* _page;
+ volatile uint32_t _refcount;
+ volatile bool _pinned;
+
+ bool inc_refcount();
+ bool dec_refcount();
+
+ ZForwardingEntry* entries() const;
+ ZForwardingEntry at(ZForwardingCursor* cursor) const;
+ ZForwardingEntry first(uintptr_t from_index, ZForwardingCursor* cursor) const;
+ ZForwardingEntry next(ZForwardingCursor* cursor) const;
+
+ ZForwarding(ZPage* page, uint32_t nentries);
+
+public:
+ static ZForwarding* create(ZPage* page);
+ static void destroy(ZForwarding* forwarding);
+
+ uintptr_t start() const;
+ size_t size() const;
+ size_t object_alignment_shift() const;
+ ZPage* page() const;
+
+ bool is_pinned() const;
+ void set_pinned();
+
+ bool retain_page();
+ void release_page();
+
+ ZForwardingEntry find(uintptr_t from_index) const;
+ ZForwardingEntry find(uintptr_t from_index, ZForwardingCursor* cursor) const;
+ uintptr_t insert(uintptr_t from_index, uintptr_t to_offset, ZForwardingCursor* cursor);
+
+ void verify() const;
+};
+
+#endif // SHARE_GC_Z_ZFORWARDING_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/z/zForwarding.inline.hpp Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef SHARE_GC_Z_ZFORWARDING_INLINE_HPP
+#define SHARE_GC_Z_ZFORWARDING_INLINE_HPP
+
+#include "gc/z/zAttachedArray.inline.hpp"
+#include "gc/z/zForwarding.hpp"
+#include "gc/z/zGlobals.hpp"
+#include "gc/z/zHash.inline.hpp"
+#include "gc/z/zHeap.hpp"
+#include "gc/z/zVirtualMemory.inline.hpp"
+#include "runtime/atomic.hpp"
+#include "utilities/debug.hpp"
+
+inline uintptr_t ZForwarding::start() const {
+ return _virtual.start();
+}
+
+inline size_t ZForwarding::size() const {
+ return _virtual.size();
+}
+
+inline size_t ZForwarding::object_alignment_shift() const {
+ return _object_alignment_shift;
+}
+
+inline ZPage* ZForwarding::page() const {
+ return _page;
+}
+
+inline bool ZForwarding::is_pinned() const {
+ return Atomic::load(&_pinned);
+}
+
+inline void ZForwarding::set_pinned() {
+ Atomic::store(true, &_pinned);
+}
+
+inline bool ZForwarding::inc_refcount() {
+ uint32_t refcount = Atomic::load(&_refcount);
+
+ while (refcount > 0) {
+ const uint32_t old_refcount = refcount;
+ const uint32_t new_refcount = old_refcount + 1;
+ const uint32_t prev_refcount = Atomic::cmpxchg(new_refcount, &_refcount, old_refcount);
+ if (prev_refcount == old_refcount) {
+ return true;
+ }
+
+ refcount = prev_refcount;
+ }
+
+ return false;
+}
+
+inline bool ZForwarding::dec_refcount() {
+ assert(_refcount > 0, "Invalid state");
+ return Atomic::sub(1u, &_refcount) == 0u;
+}
+
+inline bool ZForwarding::retain_page() {
+ return inc_refcount();
+}
+
+inline void ZForwarding::release_page() {
+ if (dec_refcount()) {
+ ZHeap::heap()->free_page(_page, true /* reclaimed */);
+ _page = NULL;
+ }
+}
+
+inline ZForwardingEntry* ZForwarding::entries() const {
+ return _entries(this);
+}
+
+inline ZForwardingEntry ZForwarding::at(ZForwardingCursor* cursor) const {
+ return Atomic::load(entries() + *cursor);
+}
+
+inline ZForwardingEntry ZForwarding::first(uintptr_t from_index, ZForwardingCursor* cursor) const {
+ const uint32_t mask = _entries.length() - 1;
+ const uint32_t hash = ZHash::uint32_to_uint32((uint32_t)from_index);
+ *cursor = hash & mask;
+ return at(cursor);
+}
+
+inline ZForwardingEntry ZForwarding::next(ZForwardingCursor* cursor) const {
+ const uint32_t mask = _entries.length() - 1;
+ *cursor = (*cursor + 1) & mask;
+ return at(cursor);
+}
+
+inline ZForwardingEntry ZForwarding::find(uintptr_t from_index) const {
+ ZForwardingCursor dummy;
+ return find(from_index, &dummy);
+}
+
+inline ZForwardingEntry ZForwarding::find(uintptr_t from_index, ZForwardingCursor* cursor) const {
+ // Reading entries in the table races with the atomic CAS done for
+ // insertion into the table. This is safe because each entry is at
+ // most updated once (from -1 to something else).
+ ZForwardingEntry entry = first(from_index, cursor);
+ while (!entry.is_empty()) {
+ if (entry.from_index() == from_index) {
+ // Match found, return matching entry
+ return entry;
+ }
+
+ entry = next(cursor);
+ }
+
+ // Match not found, return empty entry
+ return entry;
+}
+
+inline uintptr_t ZForwarding::insert(uintptr_t from_index, uintptr_t to_offset, ZForwardingCursor* cursor) {
+ const ZForwardingEntry new_entry(from_index, to_offset);
+ const ZForwardingEntry old_entry; // Empty
+
+ for (;;) {
+ const ZForwardingEntry prev_entry = Atomic::cmpxchg(new_entry, entries() + *cursor, old_entry);
+ if (prev_entry.is_empty()) {
+ // Success
+ return to_offset;
+ }
+
+ // Find next empty or matching entry
+ ZForwardingEntry entry = at(cursor);
+ while (!entry.is_empty()) {
+ if (entry.from_index() == from_index) {
+ // Match found, return already inserted address
+ return entry.to_offset();
+ }
+
+ entry = next(cursor);
+ }
+ }
+}
+
+#endif // SHARE_GC_Z_ZFORWARDING_INLINE_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/z/zForwardingEntry.hpp Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef SHARE_GC_Z_ZFORWARDINGENTRY_HPP
+#define SHARE_GC_Z_ZFORWARDINGENTRY_HPP
+
+#include "gc/z/zBitField.hpp"
+#include "memory/allocation.hpp"
+#include "metaprogramming/primitiveConversions.hpp"
+
+//
+// Forwarding entry layout
+// -----------------------
+//
+// 6 4 4 0
+// 3 2 1 0
+// +------------------------+-----------------------------------------------+
+// |11111111 11111111 111111|11 11111111 11111111 11111111 11111111 11111111|
+// +------------------------+-----------------------------------------------+
+// | |
+// | * 41-0 To Object Offset (42-bits)
+// |
+// * 63-42 From Object Index (22-bits)
+//
+
+class ZForwardingEntry {
+ friend struct PrimitiveConversions;
+
+private:
+ typedef ZBitField<uint64_t, size_t, 0, 42> field_to_offset;
+ typedef ZBitField<uint64_t, size_t, 42, 22> field_from_index;
+
+ uint64_t _entry;
+
+ static uintptr_t empty() {
+ return (uintptr_t)-1;
+ }
+
+public:
+ ZForwardingEntry() :
+ _entry(empty()) {}
+
+ ZForwardingEntry(size_t from_index, size_t to_offset) :
+ _entry(field_from_index::encode(from_index) |
+ field_to_offset::encode(to_offset)) {}
+
+ bool is_empty() const {
+ return _entry == empty();
+ }
+
+ size_t to_offset() const {
+ return field_to_offset::decode(_entry);
+ }
+
+ size_t from_index() const {
+ return field_from_index::decode(_entry);
+ }
+};
+
+// Needed to allow atomic operations on ZForwardingEntry
+template <>
+struct PrimitiveConversions::Translate<ZForwardingEntry> : public TrueType {
+ typedef ZForwardingEntry Value;
+ typedef uint64_t Decayed;
+
+ static Decayed decay(Value v) {
+ return v._entry;
+ }
+
+ static Value recover(Decayed d) {
+ ZForwardingEntry entry;
+ entry._entry = d;
+ return entry;
+ }
+};
+
+#endif // SHARE_GC_Z_ZFORWARDINGENTRY_HPP
--- a/src/hotspot/share/gc/z/zForwardingTable.cpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/z/zForwardingTable.cpp Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -22,63 +22,27 @@
*/
#include "precompiled.hpp"
+#include "gc/z/zAddress.inline.hpp"
+#include "gc/z/zForwarding.inline.hpp"
#include "gc/z/zForwardingTable.inline.hpp"
-#include "gc/z/zUtils.inline.hpp"
-#include "memory/allocation.inline.hpp"
+#include "gc/z/zGranuleMap.inline.hpp"
#include "utilities/debug.hpp"
-void ZForwardingTable::setup(size_t live_objects) {
- assert(is_null(), "Should be empty");
- assert(live_objects > 0, "Invalid size");
+ZForwardingTable::ZForwardingTable() :
+ _map() {}
- // Allocate table for linear probing. The size of the table must be
- // a power of two to allow for quick and inexpensive indexing/masking.
- // The table is sized to have a load factor of 50%, i.e. sized to have
- // double the number of entries actually inserted.
- _size = ZUtils::round_up_power_of_2(live_objects * 2);
- _table = MallocArrayAllocator<ZForwardingTableEntry>::allocate(_size, mtGC);
+void ZForwardingTable::insert(ZForwarding* forwarding) {
+ const uintptr_t addr = ZAddress::good(forwarding->start());
+ const size_t size = forwarding->size();
- // Construct table entries
- for (size_t i = 0; i < _size; i++) {
- ::new (_table + i) ZForwardingTableEntry();
- }
+ assert(get(addr) == NULL, "Invalid entry");
+ _map.put(addr, size, forwarding);
}
-void ZForwardingTable::reset() {
- // Destruct table entries
- for (size_t i = 0; i < _size; i++) {
- (_table + i)->~ZForwardingTableEntry();
- }
-
- // Free table
- MallocArrayAllocator<ZForwardingTableEntry>::free(_table);
- _table = NULL;
- _size = 0;
-}
-
-void ZForwardingTable::verify(size_t object_max_count, size_t live_objects) const {
- size_t count = 0;
+void ZForwardingTable::remove(ZForwarding* forwarding) {
+ const uintptr_t addr = ZAddress::good(forwarding->start());
+ const size_t size = forwarding->size();
- for (size_t i = 0; i < _size; i++) {
- const ZForwardingTableEntry entry = _table[i];
- if (entry.is_empty()) {
- // Skip empty entries
- continue;
- }
-
- // Check from index
- guarantee(entry.from_index() < object_max_count, "Invalid from index");
-
- // Check for duplicates
- for (size_t j = i + 1; j < _size; j++) {
- const ZForwardingTableEntry other = _table[j];
- guarantee(entry.from_index() != other.from_index(), "Duplicate from");
- guarantee(entry.to_offset() != other.to_offset(), "Duplicate to");
- }
-
- count++;
- }
-
- // Check number of non-null entries
- guarantee(live_objects == count, "Count mismatch");
+ assert(get(addr) == forwarding, "Invalid entry");
+ _map.put(addr, size, NULL);
}
--- a/src/hotspot/share/gc/z/zForwardingTable.hpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/z/zForwardingTable.hpp Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -24,36 +24,21 @@
#ifndef SHARE_GC_Z_ZFORWARDINGTABLE_HPP
#define SHARE_GC_Z_ZFORWARDINGTABLE_HPP
-#include "gc/z/zForwardingTableEntry.hpp"
-#include "memory/allocation.hpp"
+#include "gc/z/zGranuleMap.hpp"
-typedef size_t ZForwardingTableCursor;
+class ZForwarding;
class ZForwardingTable {
- friend class VMStructs;
- friend class ZForwardingTableTest;
-
private:
- ZForwardingTableEntry* _table;
- size_t _size;
-
- ZForwardingTableEntry at(ZForwardingTableCursor* cursor) const;
- ZForwardingTableEntry first(uintptr_t from_index, ZForwardingTableCursor* cursor) const;
- ZForwardingTableEntry next(ZForwardingTableCursor* cursor) const;
+ ZGranuleMap<ZForwarding*> _map;
public:
ZForwardingTable();
- ~ZForwardingTable();
- bool is_null() const;
- void setup(size_t live_objects);
- void reset();
+ ZForwarding* get(uintptr_t addr) const;
- ZForwardingTableEntry find(uintptr_t from_index) const;
- ZForwardingTableEntry find(uintptr_t from_index, ZForwardingTableCursor* cursor) const;
- uintptr_t insert(uintptr_t from_index, uintptr_t to_offset, ZForwardingTableCursor* cursor);
-
- void verify(size_t object_max_count, size_t live_objects) const;
+ void insert(ZForwarding* forwarding);
+ void remove(ZForwarding* forwarding);
};
#endif // SHARE_GC_Z_ZFORWARDINGTABLE_HPP
--- a/src/hotspot/share/gc/z/zForwardingTable.inline.hpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/z/zForwardingTable.inline.hpp Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,85 +25,10 @@
#define SHARE_GC_Z_ZFORWARDINGTABLE_INLINE_HPP
#include "gc/z/zForwardingTable.hpp"
-#include "gc/z/zGlobals.hpp"
-#include "gc/z/zHash.inline.hpp"
-#include "runtime/atomic.hpp"
-#include "utilities/debug.hpp"
-
-inline ZForwardingTable::ZForwardingTable() :
- _table(NULL),
- _size(0) {}
-
-inline ZForwardingTable::~ZForwardingTable() {
- assert(is_null(), "Should be empty");
-}
-
-inline ZForwardingTableEntry ZForwardingTable::at(ZForwardingTableCursor* cursor) const {
- return _table[*cursor];
-}
-
-inline ZForwardingTableEntry ZForwardingTable::first(uintptr_t from_index, ZForwardingTableCursor* cursor) const {
- const size_t mask = _size - 1;
- const size_t hash = ZHash::uint32_to_uint32((uint32_t)from_index);
- *cursor = hash & mask;
- return at(cursor);
-}
-
-inline ZForwardingTableEntry ZForwardingTable::next(ZForwardingTableCursor* cursor) const {
- const size_t mask = _size - 1;
- *cursor = (*cursor + 1) & mask;
- return at(cursor);
-}
-
-inline bool ZForwardingTable::is_null() const {
- return _table == NULL;
-}
-
-inline ZForwardingTableEntry ZForwardingTable::find(uintptr_t from_index) const {
- ZForwardingTableCursor dummy;
- return find(from_index, &dummy);
-}
+#include "gc/z/zGranuleMap.inline.hpp"
-inline ZForwardingTableEntry ZForwardingTable::find(uintptr_t from_index, ZForwardingTableCursor* cursor) const {
- // Reading entries in the table races with the atomic CAS done for
- // insertion into the table. This is safe because each entry is at
- // most updated once (from -1 to something else).
- ZForwardingTableEntry entry = first(from_index, cursor);
- while (!entry.is_empty()) {
- if (entry.from_index() == from_index) {
- // Match found, return matching entry
- return entry;
- }
-
- entry = next(cursor);
- }
-
- // Match not found, return empty entry
- return entry;
-}
-
-inline uintptr_t ZForwardingTable::insert(uintptr_t from_index, uintptr_t to_offset, ZForwardingTableCursor* cursor) {
- const ZForwardingTableEntry new_entry(from_index, to_offset);
- const ZForwardingTableEntry old_entry; // empty
-
- for (;;) {
- const ZForwardingTableEntry prev_entry = Atomic::cmpxchg(new_entry, _table + *cursor, old_entry);
- if (prev_entry.is_empty()) {
- // Success
- return to_offset;
- }
-
- // Find next empty or matching entry
- ZForwardingTableEntry entry = at(cursor);
- while (!entry.is_empty()) {
- if (entry.from_index() == from_index) {
- // Match found, return already inserted address
- return entry.to_offset();
- }
-
- entry = next(cursor);
- }
- }
+inline ZForwarding* ZForwardingTable::get(uintptr_t addr) const {
+ return _map.get(addr);
}
#endif // SHARE_GC_Z_ZFORWARDINGTABLE_INLINE_HPP
--- a/src/hotspot/share/gc/z/zForwardingTableEntry.hpp Thu Mar 21 08:41:10 2019 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#ifndef SHARE_GC_Z_ZFORWARDINGTABLEENTRY_HPP
-#define SHARE_GC_Z_ZFORWARDINGTABLEENTRY_HPP
-
-#include "gc/z/zBitField.hpp"
-#include "memory/allocation.hpp"
-#include "metaprogramming/primitiveConversions.hpp"
-
-//
-// Forwarding table entry layout
-// -----------------------------
-//
-// 6 4 4 0
-// 3 2 1 0
-// +------------------------+-----------------------------------------------+
-// |11111111 11111111 111111|11 11111111 11111111 11111111 11111111 11111111|
-// +------------------------+-----------------------------------------------+
-// | |
-// | * 41-0 To Object Offset (42-bits)
-// |
-// * 63-42 From Object Index (22-bits)
-//
-
-class ZForwardingTableEntry {
- friend struct PrimitiveConversions;
-
-private:
- typedef ZBitField<uint64_t, size_t, 0, 42> field_to_offset;
- typedef ZBitField<uint64_t, size_t, 42, 22> field_from_index;
-
- uint64_t _entry;
-
- static uintptr_t empty() {
- return (uintptr_t)-1;
- }
-
-public:
- ZForwardingTableEntry() :
- _entry(empty()) {}
-
- ZForwardingTableEntry(size_t from_index, size_t to_offset) :
- _entry(field_from_index::encode(from_index) |
- field_to_offset::encode(to_offset)) {}
-
- bool is_empty() const {
- return _entry == empty();
- }
-
- size_t to_offset() const {
- return field_to_offset::decode(_entry);
- }
-
- size_t from_index() const {
- return field_from_index::decode(_entry);
- }
-};
-
-// Needed to allow atomic operations on ZForwardingTableEntry
-template <>
-struct PrimitiveConversions::Translate<ZForwardingTableEntry> : public TrueType {
- typedef ZForwardingTableEntry Value;
- typedef uint64_t Decayed;
-
- static Decayed decay(Value v) {
- return v._entry;
- }
-
- static Value recover(Decayed d) {
- ZForwardingTableEntry entry;
- entry._entry = d;
- return entry;
- }
-};
-
-#endif // SHARE_GC_Z_ZFORWARDINGTABLEENTRY_HPP
--- a/src/hotspot/share/gc/z/zGranuleMap.hpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/z/zGranuleMap.hpp Thu Mar 21 18:04:01 2019 +0000
@@ -46,6 +46,7 @@
T get(uintptr_t addr) const;
void put(uintptr_t addr, T value);
+ void put(uintptr_t addr, size_t size, T value);
};
template <typename T>
@@ -58,6 +59,7 @@
ZGranuleMapIterator(const ZGranuleMap<T>* map);
bool next(T* value);
+ bool next(T** value);
};
#endif // SHARE_GC_Z_ZGRANULEMAP_HPP
--- a/src/hotspot/share/gc/z/zGranuleMap.inline.hpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/z/zGranuleMap.inline.hpp Thu Mar 21 18:04:01 2019 +0000
@@ -66,6 +66,17 @@
}
template <typename T>
+inline void ZGranuleMap<T>::put(uintptr_t addr, size_t size, T value) {
+ assert(is_aligned(size, ZGranuleSize), "Misaligned");
+
+ const size_t start_index = index_for_addr(addr);
+ const size_t end_index = start_index + (size >> ZGranuleSizeShift);
+ for (size_t index = start_index; index < end_index; index++) {
+ _map[index] = value;
+ }
+}
+
+template <typename T>
inline ZGranuleMapIterator<T>::ZGranuleMapIterator(const ZGranuleMap<T>* map) :
_map(map),
_next(0) {}
@@ -81,4 +92,15 @@
return false;
}
+template <typename T>
+inline bool ZGranuleMapIterator<T>::next(T** value) {
+ if (_next < _map->size()) {
+ *value = _map->_map + _next++;
+ return true;
+ }
+
+ // End of map
+ return false;
+}
+
#endif // SHARE_GC_Z_ZGRANULEMAP_INLINE_HPP
--- a/src/hotspot/share/gc/z/zHeap.cpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/z/zHeap.cpp Thu Mar 21 18:04:01 2019 +0000
@@ -63,8 +63,9 @@
_workers(),
_object_allocator(_workers.nworkers()),
_page_allocator(heap_min_size(), heap_max_size(), heap_max_reserve_size()),
- _pagetable(),
- _mark(&_workers, &_pagetable),
+ _page_table(),
+ _forwarding_table(),
+ _mark(&_workers, &_page_table),
_reference_processor(&_workers),
_weak_roots_processor(&_workers),
_relocate(&_workers),
@@ -172,7 +173,7 @@
return false;
}
- const ZPage* const page = _pagetable.get(addr);
+ const ZPage* const page = _page_table.get(addr);
if (page != NULL) {
return page->is_in(addr);
}
@@ -181,12 +182,12 @@
}
uintptr_t ZHeap::block_start(uintptr_t addr) const {
- const ZPage* const page = _pagetable.get(addr);
+ const ZPage* const page = _page_table.get(addr);
return page->block_start(addr);
}
bool ZHeap::block_is_obj(uintptr_t addr) const {
- const ZPage* const page = _pagetable.get(addr);
+ const ZPage* const page = _page_table.get(addr);
return page->block_is_obj(addr);
}
@@ -220,8 +221,8 @@
ZPage* ZHeap::alloc_page(uint8_t type, size_t size, ZAllocationFlags flags) {
ZPage* const page = _page_allocator.alloc_page(type, size, flags);
if (page != NULL) {
- // Update pagetable
- _pagetable.insert(page);
+ // Insert page table entry
+ _page_table.insert(page);
}
return page;
@@ -234,33 +235,44 @@
log_trace(gc)("Undo page allocation, thread: " PTR_FORMAT " (%s), page: " PTR_FORMAT ", size: " SIZE_FORMAT,
ZThread::id(), ZThread::name(), p2i(page), page->size());
- release_page(page, false /* reclaimed */);
+ free_page(page, false /* reclaimed */);
}
-bool ZHeap::retain_page(ZPage* page) {
- return page->inc_refcount();
+void ZHeap::free_page(ZPage* page, bool reclaimed) {
+ // Remove page table entry
+ _page_table.remove(page);
+
+ // Free page
+ _page_allocator.free_page(page, reclaimed);
}
-void ZHeap::release_page(ZPage* page, bool reclaimed) {
- if (page->dec_refcount()) {
- _page_allocator.free_page(page, reclaimed);
+void ZHeap::before_flip() {
+ if (ZVerifyViews) {
+ // Unmap all pages
+ _page_allocator.unmap_all_pages();
}
}
-void ZHeap::flip_views() {
- // For debugging only
- if (ZUnmapBadViews) {
- // Flip pages
- ZPageTableIterator iter(&_pagetable);
+void ZHeap::after_flip() {
+ if (ZVerifyViews) {
+ // Map all pages
+ ZPageTableIterator iter(&_page_table);
for (ZPage* page; iter.next(&page);) {
- if (!page->is_detached()) {
- _page_allocator.flip_page(page);
- }
+ _page_allocator.map_page(page);
}
+ }
+}
- // Flip pre-mapped memory
- _page_allocator.flip_pre_mapped();
- }
+void ZHeap::flip_to_marked() {
+ before_flip();
+ ZAddressMasks::flip_to_marked();
+ after_flip();
+}
+
+void ZHeap::flip_to_remapped() {
+ before_flip();
+ ZAddressMasks::flip_to_remapped();
+ after_flip();
}
void ZHeap::mark_start() {
@@ -270,8 +282,7 @@
ZStatSample(ZSamplerHeapUsedBeforeMark, used());
// Flip address view
- ZAddressMasks::flip_to_marked();
- flip_views();
+ flip_to_marked();
// Retire allocating pages
_object_allocator.retire_pages();
@@ -391,25 +402,14 @@
_reference_processor.enqueue_references();
}
-void ZHeap::destroy_detached_pages() {
- ZList<ZPage> list;
-
- _page_allocator.flush_detached_pages(&list);
+void ZHeap::select_relocation_set() {
+ // Do not allow pages to be deleted
+ _page_allocator.enable_deferred_delete();
- for (ZPage* page = list.remove_first(); page != NULL; page = list.remove_first()) {
- // Remove pagetable entry
- _pagetable.remove(page);
-
- // Delete the page
- _page_allocator.destroy_page(page);
- }
-}
-
-void ZHeap::select_relocation_set() {
// Register relocatable pages with selector
ZRelocationSetSelector selector;
- ZPageTableIterator iter(&_pagetable);
- for (ZPage* page; iter.next(&page);) {
+ ZPageTableIterator pt_iter(&_page_table);
+ for (ZPage* page; pt_iter.next(&page);) {
if (!page->is_relocatable()) {
// Not relocatable, don't register
continue;
@@ -423,13 +423,22 @@
selector.register_garbage_page(page);
// Reclaim page immediately
- release_page(page, true /* reclaimed */);
+ free_page(page, true /* reclaimed */);
}
}
+ // Allow pages to be deleted
+ _page_allocator.disable_deferred_delete();
+
// Select pages to relocate
selector.select(&_relocation_set);
+ // Setup forwarding table
+ ZRelocationSetIterator rs_iter(&_relocation_set);
+ for (ZForwarding* forwarding; rs_iter.next(&forwarding);) {
+ _forwarding_table.insert(forwarding);
+ }
+
// Update statistics
ZStatRelocation::set_at_select_relocation_set(selector.relocating());
ZStatHeap::set_at_select_relocation_set(selector.live(),
@@ -437,26 +446,15 @@
reclaimed());
}
-void ZHeap::prepare_relocation_set() {
+void ZHeap::reset_relocation_set() {
+ // Reset forwarding table
ZRelocationSetIterator iter(&_relocation_set);
- for (ZPage* page; iter.next(&page);) {
- // Prepare for relocation
- page->set_forwarding();
-
- // Update pagetable
- _pagetable.set_relocating(page);
+ for (ZForwarding* forwarding; iter.next(&forwarding);) {
+ _forwarding_table.remove(forwarding);
}
-}
-void ZHeap::reset_relocation_set() {
- ZRelocationSetIterator iter(&_relocation_set);
- for (ZPage* page; iter.next(&page);) {
- // Reset relocation information
- page->reset_forwarding();
-
- // Update pagetable
- _pagetable.clear_relocating(page);
- }
+ // Reset relocation set
+ _relocation_set.reset();
}
void ZHeap::relocate_start() {
@@ -466,8 +464,7 @@
_unload.finish();
// Flip address view
- ZAddressMasks::flip_to_remapped();
- flip_views();
+ flip_to_remapped();
// Enter relocate phase
ZGlobalPhase = ZPhaseRelocate;
@@ -480,25 +477,6 @@
_relocate.start();
}
-uintptr_t ZHeap::relocate_object(uintptr_t addr) {
- assert(ZGlobalPhase == ZPhaseRelocate, "Relocate not allowed");
- ZPage* const page = _pagetable.get(addr);
- const bool retained = retain_page(page);
- const uintptr_t new_addr = page->relocate_object(addr);
- if (retained) {
- release_page(page, true /* reclaimed */);
- }
-
- return new_addr;
-}
-
-uintptr_t ZHeap::forward_object(uintptr_t addr) {
- assert(ZGlobalPhase == ZPhaseMark ||
- ZGlobalPhase == ZPhaseMarkCompleted, "Forward not allowed");
- ZPage* const page = _pagetable.get(addr);
- return page->forward_object(addr);
-}
-
void ZHeap::relocate() {
// Relocate relocation set
const bool success = _relocate.relocate(&_relocation_set);
@@ -545,11 +523,18 @@
print_on(st);
st->cr();
- ZPageTableIterator iter(&_pagetable);
+ // Do not allow pages to be deleted
+ _page_allocator.enable_deferred_delete();
+
+ // Print all pages
+ ZPageTableIterator iter(&_page_table);
for (ZPage* page; iter.next(&page);) {
page->print_on(st);
}
+ // Allow pages to be deleted
+ _page_allocator.enable_deferred_delete();
+
st->cr();
}
--- a/src/hotspot/share/gc/z/zHeap.hpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/z/zHeap.hpp Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@
#include "gc/shared/gcTimer.hpp"
#include "gc/z/zAllocationFlags.hpp"
#include "gc/z/zArray.hpp"
+#include "gc/z/zForwardingTable.hpp"
#include "gc/z/zList.hpp"
#include "gc/z/zLock.hpp"
#include "gc/z/zMark.hpp"
@@ -54,7 +55,8 @@
ZWorkers _workers;
ZObjectAllocator _object_allocator;
ZPageAllocator _page_allocator;
- ZPageTable _pagetable;
+ ZPageTable _page_table;
+ ZForwardingTable _forwarding_table;
ZMark _mark;
ZReferenceProcessor _reference_processor;
ZWeakRootsProcessor _weak_roots_processor;
@@ -67,8 +69,13 @@
size_t heap_max_size() const;
size_t heap_max_reserve_size() const;
+ void before_flip();
+ void after_flip();
+
+ void flip_to_marked();
+ void flip_to_remapped();
+
void out_of_memory();
- void flip_views();
void fixup_partial_loads();
public:
@@ -118,8 +125,7 @@
// Page allocation
ZPage* alloc_page(uint8_t type, size_t size, ZAllocationFlags flags);
void undo_alloc_page(ZPage* page);
- bool retain_page(ZPage* page);
- void release_page(ZPage* page, bool reclaimed);
+ void free_page(ZPage* page, bool reclaimed);
// Object allocation
uintptr_t alloc_tlab(size_t size);
@@ -138,19 +144,14 @@
void mark_flush_and_free(Thread* thread);
bool mark_end();
- // Post-marking & Pre-relocation
- void destroy_detached_pages();
-
// Relocation set
void select_relocation_set();
- void prepare_relocation_set();
void reset_relocation_set();
// Relocation
- bool is_relocating(uintptr_t addr) const;
void relocate_start();
uintptr_t relocate_object(uintptr_t addr);
- uintptr_t forward_object(uintptr_t addr);
+ uintptr_t remap_object(uintptr_t addr);
void relocate();
// Iteration
--- a/src/hotspot/share/gc/z/zHeap.inline.hpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/z/zHeap.inline.hpp Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,8 @@
#define SHARE_GC_Z_ZHEAP_INLINE_HPP
#include "gc/z/zAddress.inline.hpp"
+#include "gc/z/zForwarding.inline.hpp"
+#include "gc/z/zForwardingTable.inline.hpp"
#include "gc/z/zHeap.hpp"
#include "gc/z/zMark.inline.hpp"
#include "gc/z/zOop.inline.hpp"
@@ -42,17 +44,13 @@
return &_reference_processor;
}
-inline bool ZHeap::is_relocating(uintptr_t addr) const {
- return _pagetable.is_relocating(addr);
-}
-
inline bool ZHeap::is_object_live(uintptr_t addr) const {
- ZPage* page = _pagetable.get(addr);
+ ZPage* page = _page_table.get(addr);
return page->is_object_live(addr);
}
inline bool ZHeap::is_object_strongly_live(uintptr_t addr) const {
- ZPage* page = _pagetable.get(addr);
+ ZPage* page = _page_table.get(addr);
return page->is_object_strongly_live(addr);
}
@@ -85,10 +83,43 @@
}
inline void ZHeap::undo_alloc_object_for_relocation(uintptr_t addr, size_t size) {
- ZPage* const page = _pagetable.get(addr);
+ ZPage* const page = _page_table.get(addr);
_object_allocator.undo_alloc_object_for_relocation(page, addr, size);
}
+inline uintptr_t ZHeap::relocate_object(uintptr_t addr) {
+ assert(ZGlobalPhase == ZPhaseRelocate, "Relocate not allowed");
+
+ ZForwarding* const forwarding = _forwarding_table.get(addr);
+ if (forwarding == NULL) {
+ // Not forwarding
+ return ZAddress::good(addr);
+ }
+
+ // Relocate object
+ const bool retained = forwarding->retain_page();
+ const uintptr_t new_addr = _relocate.relocate_object(forwarding, addr);
+ if (retained) {
+ forwarding->release_page();
+ }
+
+ return new_addr;
+}
+
+inline uintptr_t ZHeap::remap_object(uintptr_t addr) {
+ assert(ZGlobalPhase == ZPhaseMark ||
+ ZGlobalPhase == ZPhaseMarkCompleted, "Forward not allowed");
+
+ ZForwarding* const forwarding = _forwarding_table.get(addr);
+ if (forwarding == NULL) {
+ // Not forwarding
+ return ZAddress::good(addr);
+ }
+
+ // Forward object
+ return _relocate.forward_object(forwarding, addr);
+}
+
inline bool ZHeap::is_alloc_stalled() const {
return _page_allocator.is_alloc_stalled();
}
--- a/src/hotspot/share/gc/z/zMark.cpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/z/zMark.cpp Thu Mar 21 18:04:01 2019 +0000
@@ -56,9 +56,9 @@
static const ZStatSubPhase ZSubPhaseConcurrentMarkTryTerminate("Concurrent Mark Try Terminate");
static const ZStatSubPhase ZSubPhaseMarkTryComplete("Pause Mark Try Complete");
-ZMark::ZMark(ZWorkers* workers, ZPageTable* pagetable) :
+ZMark::ZMark(ZWorkers* workers, ZPageTable* page_table) :
_workers(workers),
- _pagetable(pagetable),
+ _page_table(page_table),
_allocator(),
_stripes(),
_terminate(),
@@ -307,7 +307,7 @@
}
bool ZMark::try_mark_object(ZMarkCache* cache, uintptr_t addr, bool finalizable) {
- ZPage* const page = _pagetable->get(addr);
+ ZPage* const page = _page_table->get(addr);
if (page->is_allocating()) {
// Newly allocated objects are implicitly marked
return false;
--- a/src/hotspot/share/gc/z/zMark.hpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/z/zMark.hpp Thu Mar 21 18:04:01 2019 +0000
@@ -42,7 +42,7 @@
private:
ZWorkers* const _workers;
- ZPageTable* const _pagetable;
+ ZPageTable* const _page_table;
ZMarkStackAllocator _allocator;
ZMarkStripeSet _stripes;
ZMarkTerminate _terminate;
@@ -101,7 +101,7 @@
void verify_all_stacks_empty() const;
public:
- ZMark(ZWorkers* workers, ZPageTable* pagetable);
+ ZMark(ZWorkers* workers, ZPageTable* page_table);
bool is_initialized() const;
--- a/src/hotspot/share/gc/z/zNMethodAllocator.cpp Thu Mar 21 08:41:10 2019 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include "precompiled.hpp"
-#include "gc/z/zArray.inline.hpp"
-#include "gc/z/zNMethodAllocator.hpp"
-#include "memory/allocation.hpp"
-
-ZArray<void*> ZNMethodAllocator::_deferred_frees;
-bool ZNMethodAllocator::_defer_frees(false);
-
-void ZNMethodAllocator::immediate_free(void* data) {
- FREE_C_HEAP_ARRAY(uint8_t, data);
-}
-
-void ZNMethodAllocator::deferred_free(void* data) {
- _deferred_frees.add(data);
-}
-
-void* ZNMethodAllocator::allocate(size_t size) {
- return NEW_C_HEAP_ARRAY(uint8_t, size, mtGC);
-}
-
-void ZNMethodAllocator::free(void* data) {
- if (data == NULL) {
- return;
- }
-
- if (_defer_frees) {
- deferred_free(data);
- } else {
- immediate_free(data);
- }
-}
-
-void ZNMethodAllocator::activate_deferred_frees() {
- assert(_deferred_frees.is_empty(), "precondition");
- _defer_frees = true;
-}
-
-void ZNMethodAllocator::deactivate_and_process_deferred_frees() {
- _defer_frees = false;
-
- ZArrayIterator<void*> iter(&_deferred_frees);
- for (void* data; iter.next(&data);) {
- immediate_free(data);
- }
- _deferred_frees.clear();
-}
--- a/src/hotspot/share/gc/z/zNMethodAllocator.hpp Thu Mar 21 08:41:10 2019 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#ifndef SHARE_GC_Z_ZNMETHODALLOCATOR_HPP
-#define SHARE_GC_Z_ZNMETHODALLOCATOR_HPP
-
-#include "memory/allocation.hpp"
-#include "gc/z/zArray.hpp"
-
-class ZNMethodAllocator : public AllStatic {
-private:
- static ZArray<void*> _deferred_frees;
- static bool _defer_frees;
-
- static void immediate_free(void* data);
- static void deferred_free(void* data);
-
-public:
- static void* allocate(size_t size);
- static void free(void* data);
-
- static void activate_deferred_frees();
- static void deactivate_and_process_deferred_frees();
-};
-
-#endif // SHARE_GC_Z_ZNMETHODALLOCATOR_HPP
--- a/src/hotspot/share/gc/z/zNMethodData.cpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/z/zNMethodData.cpp Thu Mar 21 18:04:01 2019 +0000
@@ -22,6 +22,7 @@
*/
#include "precompiled.hpp"
+#include "gc/z/zAttachedArray.inline.hpp"
#include "gc/z/zLock.inline.hpp"
#include "gc/z/zNMethodData.hpp"
#include "memory/allocation.hpp"
@@ -31,40 +32,29 @@
#include "utilities/debug.hpp"
#include "utilities/growableArray.hpp"
-size_t ZNMethodDataOops::header_size() {
- const size_t size = sizeof(ZNMethodDataOops);
- assert(is_aligned(size, sizeof(oop*)), "Header misaligned");
- return size;
-}
-
ZNMethodDataOops* ZNMethodDataOops::create(const GrowableArray<oop*>& immediates, bool has_non_immediates) {
- // Allocate memory for the ZNMethodDataOops object
- // plus the immediate oop* array that follows right after.
- const size_t size = ZNMethodDataOops::header_size() + (sizeof(oop*) * immediates.length());
- void* const mem = NEW_C_HEAP_ARRAY(uint8_t, size, mtGC);
- return ::new (mem) ZNMethodDataOops(immediates, has_non_immediates);
+ return ::new (AttachedArray::alloc(immediates.length())) ZNMethodDataOops(immediates, has_non_immediates);
}
void ZNMethodDataOops::destroy(ZNMethodDataOops* oops) {
- FREE_C_HEAP_ARRAY(uint8_t, oops);
+ AttachedArray::free(oops);
}
ZNMethodDataOops::ZNMethodDataOops(const GrowableArray<oop*>& immediates, bool has_non_immediates) :
- _nimmediates(immediates.length()),
+ _immediates(immediates.length()),
_has_non_immediates(has_non_immediates) {
// Save all immediate oops
- for (size_t i = 0; i < _nimmediates; i++) {
+ for (size_t i = 0; i < immediates_count(); i++) {
immediates_begin()[i] = immediates.at(i);
}
}
size_t ZNMethodDataOops::immediates_count() const {
- return _nimmediates;
+ return _immediates.length();
}
oop** ZNMethodDataOops::immediates_begin() const {
- // The immediate oop* array starts immediately after this object
- return (oop**)((uintptr_t)this + header_size());
+ return _immediates(this);
}
oop** ZNMethodDataOops::immediates_end() const {
--- a/src/hotspot/share/gc/z/zNMethodData.hpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/z/zNMethodData.hpp Thu Mar 21 18:04:01 2019 +0000
@@ -21,23 +21,24 @@
* questions.
*/
+#ifndef SHARE_GC_Z_ZNMETHODDATA_HPP
+#define SHARE_GC_Z_ZNMETHODDATA_HPP
+
+#include "gc/z/zAttachedArray.hpp"
#include "gc/z/zLock.hpp"
#include "memory/allocation.hpp"
#include "oops/oopsHierarchy.hpp"
#include "utilities/globalDefinitions.hpp"
-#ifndef SHARE_GC_Z_ZNMETHODDATA_HPP
-#define SHARE_GC_Z_ZNMETHODDATA_HPP
-
class nmethod;
template <typename T> class GrowableArray;
class ZNMethodDataOops {
private:
- const size_t _nimmediates;
- bool _has_non_immediates;
+ typedef ZAttachedArray<ZNMethodDataOops, oop*> AttachedArray;
- static size_t header_size();
+ const AttachedArray _immediates;
+ const bool _has_non_immediates;
ZNMethodDataOops(const GrowableArray<oop*>& immediates, bool has_non_immediates);
--- a/src/hotspot/share/gc/z/zNMethodTable.cpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/z/zNMethodTable.cpp Thu Mar 21 18:04:01 2019 +0000
@@ -30,12 +30,12 @@
#include "gc/z/zGlobals.hpp"
#include "gc/z/zHash.inline.hpp"
#include "gc/z/zLock.inline.hpp"
-#include "gc/z/zNMethodAllocator.hpp"
#include "gc/z/zNMethodData.hpp"
#include "gc/z/zNMethodTable.hpp"
#include "gc/z/zNMethodTableEntry.hpp"
#include "gc/z/zNMethodTableIteration.hpp"
#include "gc/z/zOopClosures.inline.hpp"
+#include "gc/z/zSafeDelete.inline.hpp"
#include "gc/z/zTask.hpp"
#include "gc/z/zWorkers.hpp"
#include "logging/log.hpp"
@@ -51,15 +51,7 @@
size_t ZNMethodTable::_nregistered = 0;
size_t ZNMethodTable::_nunregistered = 0;
ZNMethodTableIteration ZNMethodTable::_iteration;
-
-ZNMethodTableEntry* ZNMethodTable::create(size_t size) {
- void* const mem = ZNMethodAllocator::allocate(size * sizeof(ZNMethodTableEntry));
- return ::new (mem) ZNMethodTableEntry[size];
-}
-
-void ZNMethodTable::destroy(ZNMethodTableEntry* table) {
- ZNMethodAllocator::free(table);
-}
+ZSafeDelete<ZNMethodTableEntry[]> ZNMethodTable::_safe_delete;
size_t ZNMethodTable::first_index(const nmethod* nm, size_t size) {
assert(is_power_of_2(size), "Invalid size");
@@ -128,7 +120,7 @@
_nunregistered, percent_of(_nunregistered, _size), 0.0);
// Allocate new table
- ZNMethodTableEntry* const new_table = ZNMethodTable::create(new_size);
+ ZNMethodTableEntry* const new_table = new ZNMethodTableEntry[new_size];
// Transfer all registered entries
for (size_t i = 0; i < _size; i++) {
@@ -139,7 +131,7 @@
}
// Free old table
- ZNMethodTable::destroy(_table);
+ _safe_delete(_table);
// Install new table
_table = new_table;
@@ -219,8 +211,8 @@
void ZNMethodTable::nmethods_do_begin() {
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
- // Make sure we don't free data while iterating
- ZNMethodAllocator::activate_deferred_frees();
+ // Do not allow the table to be deleted while iterating
+ _safe_delete.enable_deferred_delete();
// Prepare iteration
_iteration.nmethods_do_begin(_table, _size);
@@ -232,8 +224,8 @@
// Finish iteration
_iteration.nmethods_do_end();
- // Process deferred frees
- ZNMethodAllocator::deactivate_and_process_deferred_frees();
+ // Allow the table to be deleted
+ _safe_delete.disable_deferred_delete();
// Notify iteration done
CodeCache_lock->notify_all();
--- a/src/hotspot/share/gc/z/zNMethodTable.hpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/z/zNMethodTable.hpp Thu Mar 21 18:04:01 2019 +0000
@@ -25,6 +25,7 @@
#define SHARE_GC_Z_ZNMETHODTABLE_HPP
#include "gc/z/zNMethodTableIteration.hpp"
+#include "gc/z/zSafeDelete.hpp"
#include "memory/allocation.hpp"
class nmethod;
@@ -34,11 +35,12 @@
class ZNMethodTable : public AllStatic {
private:
- static ZNMethodTableEntry* _table;
- static size_t _size;
- static size_t _nregistered;
- static size_t _nunregistered;
- static ZNMethodTableIteration _iteration;
+ static ZNMethodTableEntry* _table;
+ static size_t _size;
+ static size_t _nregistered;
+ static size_t _nunregistered;
+ static ZNMethodTableIteration _iteration;
+ static ZSafeDelete<ZNMethodTableEntry[]> _safe_delete;
static ZNMethodTableEntry* create(size_t size);
static void destroy(ZNMethodTableEntry* table);
--- a/src/hotspot/share/gc/z/zPage.cpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/z/zPage.cpp Thu Mar 21 18:04:01 2019 +0000
@@ -22,35 +22,19 @@
*/
#include "precompiled.hpp"
-#include "gc/shared/collectedHeap.hpp"
-#include "gc/z/zAddress.inline.hpp"
-#include "gc/z/zForwardingTable.inline.hpp"
-#include "gc/z/zHeap.inline.hpp"
-#include "gc/z/zLiveMap.inline.hpp"
-#include "gc/z/zMark.hpp"
#include "gc/z/zPage.inline.hpp"
#include "gc/z/zPhysicalMemory.inline.hpp"
-#include "gc/z/zStat.hpp"
-#include "gc/z/zThread.hpp"
-#include "gc/z/zUtils.inline.hpp"
-#include "logging/log.hpp"
-#include "runtime/orderAccess.hpp"
+#include "gc/z/zVirtualMemory.inline.hpp"
#include "utilities/align.hpp"
#include "utilities/debug.hpp"
-#include "utilities/globalDefinitions.hpp"
-
-static const ZStatCounter ZCounterRelocationContention("Contention", "Relocation Contention", ZStatUnitOpsPerSecond);
ZPage::ZPage(uint8_t type, ZVirtualMemory vmem, ZPhysicalMemory pmem) :
_type(type),
- _pinned(0),
_numa_id((uint8_t)-1),
_seqnum(0),
_virtual(vmem),
_top(start()),
_livemap(object_max_count()),
- _refcount(0),
- _forwarding(),
_physical(pmem) {
assert(!_physical.is_null(), "Should not be null");
assert(!_virtual.is_null(), "Should not be null");
@@ -61,111 +45,20 @@
}
ZPage::~ZPage() {
- assert(!is_active(), "Should not be active");
- assert(is_detached(), "Should be detached");
+ assert(_physical.is_null(), "Should be null");
}
void ZPage::reset() {
- assert(!is_active(), "Should not be active");
- assert(!is_pinned(), "Should not be pinned");
- assert(!is_detached(), "Should not be detached");
-
_seqnum = ZGlobalSeqNum;
_top = start();
_livemap.reset();
-
- // Make sure we don't make the page active before
- // the reset of the above fields are visible.
- OrderAccess::storestore();
-
- _refcount = 1;
-}
-
-uintptr_t ZPage::relocate_object_inner(uintptr_t from_index, uintptr_t from_offset) {
- ZForwardingTableCursor cursor;
-
- // Lookup address in forwarding table
- const ZForwardingTableEntry entry = _forwarding.find(from_index, &cursor);
- if (entry.from_index() == from_index) {
- // Already relocated, return new address
- return entry.to_offset();
- }
-
- // Not found in forwarding table, relocate object
- assert(is_object_marked(from_offset), "Should be marked");
-
- if (is_pinned()) {
- // In-place forward
- return _forwarding.insert(from_index, from_offset, &cursor);
- }
-
- // Allocate object
- const uintptr_t from_good = ZAddress::good(from_offset);
- const size_t size = ZUtils::object_size(from_good);
- const uintptr_t to_good = ZHeap::heap()->alloc_object_for_relocation(size);
- if (to_good == 0) {
- // Failed, in-place forward
- return _forwarding.insert(from_index, from_offset, &cursor);
- }
-
- // Copy object
- ZUtils::object_copy(from_good, to_good, size);
-
- // Update forwarding table
- const uintptr_t to_offset = ZAddress::offset(to_good);
- const uintptr_t to_offset_final = _forwarding.insert(from_index, to_offset, &cursor);
- if (to_offset_final == to_offset) {
- // Relocation succeeded
- return to_offset;
- }
-
- // Relocation contention
- ZStatInc(ZCounterRelocationContention);
- log_trace(gc)("Relocation contention, thread: " PTR_FORMAT " (%s), page: " PTR_FORMAT
- ", entry: " SIZE_FORMAT ", oop: " PTR_FORMAT ", size: " SIZE_FORMAT,
- ZThread::id(), ZThread::name(), p2i(this), cursor, from_good, size);
-
- // Try undo allocation
- ZHeap::heap()->undo_alloc_object_for_relocation(to_good, size);
-
- return to_offset_final;
-}
-
-uintptr_t ZPage::relocate_object(uintptr_t from) {
- assert(ZHeap::heap()->is_relocating(from), "Should be relocating");
-
- const uintptr_t from_offset = ZAddress::offset(from);
- const uintptr_t from_index = (from_offset - start()) >> object_alignment_shift();
- const uintptr_t to_offset = relocate_object_inner(from_index, from_offset);
- if (from_offset == to_offset) {
- // In-place forwarding, pin page
- set_pinned();
- }
-
- return ZAddress::good(to_offset);
-}
-
-uintptr_t ZPage::forward_object(uintptr_t from) {
- assert(ZHeap::heap()->is_relocating(from), "Should be relocated");
-
- // Lookup address in forwarding table
- const uintptr_t from_offset = ZAddress::offset(from);
- const uintptr_t from_index = (from_offset - start()) >> object_alignment_shift();
- const ZForwardingTableEntry entry = _forwarding.find(from_index);
- assert(entry.from_index() == from_index, "Should be forwarded");
-
- return ZAddress::good(entry.to_offset());
}
void ZPage::print_on(outputStream* out) const {
- out->print_cr(" %-6s " PTR_FORMAT " " PTR_FORMAT " " PTR_FORMAT " %s%s%s%s%s%s",
+ out->print_cr(" %-6s " PTR_FORMAT " " PTR_FORMAT " " PTR_FORMAT " %s%s",
type_to_string(), start(), top(), end(),
is_allocating() ? " Allocating" : "",
- is_relocatable() ? " Relocatable" : "",
- is_forwarding() ? " Forwarding" : "",
- is_pinned() ? " Pinned" : "",
- is_detached() ? " Detached" : "",
- !is_active() ? " Inactive" : "");
+ is_relocatable() ? " Relocatable" : "");
}
void ZPage::print() const {
--- a/src/hotspot/share/gc/z/zPage.hpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/z/zPage.hpp Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -24,7 +24,6 @@
#ifndef SHARE_GC_Z_ZPAGE_HPP
#define SHARE_GC_Z_ZPAGE_HPP
-#include "gc/z/zForwardingTable.hpp"
#include "gc/z/zList.hpp"
#include "gc/z/zLiveMap.hpp"
#include "gc/z/zPhysicalMemory.hpp"
@@ -38,7 +37,6 @@
private:
// Always hot
const uint8_t _type; // Page type
- volatile uint8_t _pinned; // Pinned flag
uint8_t _numa_id; // NUMA node affinity
uint32_t _seqnum; // Allocation sequence number
const ZVirtualMemory _virtual; // Virtual start/end address
@@ -46,14 +44,10 @@
ZLiveMap _livemap; // Live map
// Hot when relocated and cached
- volatile uint32_t _refcount; // Page reference count
- ZForwardingTable _forwarding; // Forwarding table
ZPhysicalMemory _physical; // Physical memory for page
ZListNode<ZPage> _node; // Page list node
const char* type_to_string() const;
- uint32_t object_max_count() const;
- uintptr_t relocate_object_inner(uintptr_t from_index, uintptr_t from_offset);
bool is_object_marked(uintptr_t addr) const;
bool is_object_strongly_marked(uintptr_t addr) const;
@@ -62,6 +56,7 @@
ZPage(uint8_t type, ZVirtualMemory vmem, ZPhysicalMemory pmem);
~ZPage();
+ uint32_t object_max_count() const;
size_t object_alignment_shift() const;
size_t object_alignment() const;
@@ -79,36 +74,24 @@
void reset();
- bool inc_refcount();
- bool dec_refcount();
-
bool is_in(uintptr_t addr) const;
uintptr_t block_start(uintptr_t addr) const;
bool block_is_obj(uintptr_t addr) const;
- bool is_active() const;
bool is_allocating() const;
bool is_relocatable() const;
- bool is_detached() const;
bool is_mapped() const;
void set_pre_mapped();
- bool is_pinned() const;
- void set_pinned();
-
- bool is_forwarding() const;
- void set_forwarding();
- void reset_forwarding();
- void verify_forwarding() const;
-
bool is_marked() const;
bool is_object_live(uintptr_t addr) const;
bool is_object_strongly_live(uintptr_t addr) const;
bool mark_object(uintptr_t addr, bool finalizable, bool& inc_live);
void inc_live_atomic(uint32_t objects, size_t bytes);
+ uint32_t live_objects() const;
size_t live_bytes() const;
void object_iterate(ObjectClosure* cl);
@@ -119,9 +102,6 @@
bool undo_alloc_object(uintptr_t addr, size_t size);
bool undo_alloc_object_atomic(uintptr_t addr, size_t size);
- uintptr_t relocate_object(uintptr_t from);
- uintptr_t forward_object(uintptr_t from);
-
void print_on(outputStream* out) const;
void print() const;
};
--- a/src/hotspot/share/gc/z/zPage.inline.hpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/z/zPage.inline.hpp Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,6 @@
#define SHARE_GC_Z_ZPAGE_INLINE_HPP
#include "gc/z/zAddress.inline.hpp"
-#include "gc/z/zForwardingTable.inline.hpp"
#include "gc/z/zGlobals.hpp"
#include "gc/z/zLiveMap.inline.hpp"
#include "gc/z/zMark.hpp"
@@ -35,6 +34,7 @@
#include "gc/z/zVirtualMemory.inline.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/atomic.hpp"
+#include "runtime/orderAccess.hpp"
#include "utilities/align.hpp"
#include "utilities/debug.hpp"
@@ -132,20 +132,6 @@
return _numa_id;
}
-inline bool ZPage::inc_refcount() {
- for (uint32_t prev_refcount = _refcount; prev_refcount > 0; prev_refcount = _refcount) {
- if (Atomic::cmpxchg(prev_refcount + 1, &_refcount, prev_refcount) == prev_refcount) {
- return true;
- }
- }
- return false;
-}
-
-inline bool ZPage::dec_refcount() {
- assert(is_active(), "Should be active");
- return Atomic::sub(1u, &_refcount) == 0;
-}
-
inline bool ZPage::is_in(uintptr_t addr) const {
const uintptr_t offset = ZAddress::offset(addr);
return offset >= start() && offset < top();
@@ -163,20 +149,12 @@
return ZAddress::offset(addr) < top();
}
-inline bool ZPage::is_active() const {
- return _refcount > 0;
-}
-
inline bool ZPage::is_allocating() const {
- return is_active() && _seqnum == ZGlobalSeqNum;
+ return _seqnum == ZGlobalSeqNum;
}
inline bool ZPage::is_relocatable() const {
- return is_active() && _seqnum < ZGlobalSeqNum;
-}
-
-inline bool ZPage::is_detached() const {
- return _physical.is_null();
+ return _seqnum < ZGlobalSeqNum;
}
inline bool ZPage::is_mapped() const {
@@ -190,32 +168,6 @@
_seqnum = 1;
}
-inline bool ZPage::is_pinned() const {
- return _pinned;
-}
-
-inline void ZPage::set_pinned() {
- _pinned = 1;
-}
-
-inline bool ZPage::is_forwarding() const {
- return !_forwarding.is_null();
-}
-
-inline void ZPage::set_forwarding() {
- assert(is_marked(), "Should be marked");
- _forwarding.setup(_livemap.live_objects());
-}
-
-inline void ZPage::reset_forwarding() {
- _forwarding.reset();
- _pinned = 0;
-}
-
-inline void ZPage::verify_forwarding() const {
- _forwarding.verify(object_max_count(), _livemap.live_objects());
-}
-
inline bool ZPage::is_marked() const {
assert(is_relocatable(), "Invalid page state");
return _livemap.is_marked();
@@ -253,6 +205,11 @@
_livemap.inc_live_atomic(objects, bytes);
}
+inline uint32_t ZPage::live_objects() const {
+ assert(is_marked(), "Should be marked");
+ return _livemap.live_objects();
+}
+
inline size_t ZPage::live_bytes() const {
assert(is_marked(), "Should be marked");
return _livemap.live_bytes();
--- a/src/hotspot/share/gc/z/zPageAllocator.cpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/z/zPageAllocator.cpp Thu Mar 21 18:04:01 2019 +0000
@@ -31,6 +31,7 @@
#include "gc/z/zPageAllocator.hpp"
#include "gc/z/zPageCache.inline.hpp"
#include "gc/z/zPreMappedMemory.inline.hpp"
+#include "gc/z/zSafeDelete.inline.hpp"
#include "gc/z/zStat.hpp"
#include "gc/z/zTracer.inline.hpp"
#include "runtime/init.hpp"
@@ -96,7 +97,7 @@
_allocated(0),
_reclaimed(0),
_queue(),
- _detached() {}
+ _safe_delete() {}
bool ZPageAllocator::is_initialized() const {
return _physical.is_initialized() &&
@@ -242,34 +243,27 @@
_pre_mapped.clear();
}
-void ZPageAllocator::map_page(ZPage* page) {
- // Map physical memory
- _physical.map(page->physical_memory(), page->start());
-}
-
-void ZPageAllocator::detach_page(ZPage* page) {
- // Detach the memory mapping.
+void ZPageAllocator::destroy_page(ZPage* page) {
+ // Detach virtual and physical memory
detach_memory(page->virtual_memory(), page->physical_memory());
- // Add to list of detached pages
- _detached.insert_last(page);
+ // Delete page safely
+ _safe_delete(page);
}
-void ZPageAllocator::destroy_page(ZPage* page) {
- assert(page->is_detached(), "Invalid page state");
-
- // Free virtual memory
- {
- ZLocker<ZLock> locker(&_lock);
- _virtual.free(page->virtual_memory());
+void ZPageAllocator::map_page(ZPage* page) {
+ // Map physical memory
+ if (!page->is_mapped()) {
+ _physical.map(page->physical_memory(), page->start());
+ } else if (ZVerifyViews) {
+ _physical.debug_map(page->physical_memory(), page->start());
}
-
- delete page;
}
-void ZPageAllocator::flush_detached_pages(ZList<ZPage>* list) {
- ZLocker<ZLock> locker(&_lock);
- list->transfer(&_detached);
+void ZPageAllocator::unmap_all_pages() {
+ ZPhysicalMemory pmem(ZPhysicalMemorySegment(0 /* start */, ZAddressOffsetMax));
+ _physical.debug_unmap(pmem, 0 /* offset */);
+ pmem.clear();
}
void ZPageAllocator::flush_cache(size_t size) {
@@ -278,7 +272,7 @@
_cache.flush(&list, size);
for (ZPage* page = list.remove_first(); page != NULL; page = list.remove_first()) {
- detach_page(page);
+ destroy_page(page);
}
}
@@ -398,9 +392,7 @@
}
// Map page if needed
- if (!page->is_mapped()) {
- map_page(page);
- }
+ map_page(page);
// Reset page. This updates the page's sequence number and must
// be done after page allocation, which potentially blocked in
@@ -445,6 +437,9 @@
void ZPageAllocator::detach_memory(const ZVirtualMemory& vmem, ZPhysicalMemory& pmem) {
const uintptr_t addr = vmem.start();
+ // Free virtual memory
+ _virtual.free(vmem);
+
// Unmap physical memory
_physical.unmap(pmem, addr);
@@ -455,27 +450,6 @@
pmem.clear();
}
-void ZPageAllocator::flip_page(ZPage* page) {
- const ZPhysicalMemory& pmem = page->physical_memory();
- const uintptr_t addr = page->start();
-
- // Flip physical mapping
- _physical.flip(pmem, addr);
-}
-
-void ZPageAllocator::flip_pre_mapped() {
- if (_pre_mapped.available() == 0) {
- // Nothing to flip
- return;
- }
-
- const ZPhysicalMemory& pmem = _pre_mapped.physical_memory();
- const ZVirtualMemory& vmem = _pre_mapped.virtual_memory();
-
- // Flip physical mapping
- _physical.flip(pmem, vmem.start());
-}
-
void ZPageAllocator::free_page(ZPage* page, bool reclaimed) {
ZLocker<ZLock> locker(&_lock);
@@ -489,6 +463,14 @@
satisfy_alloc_queue();
}
+void ZPageAllocator::enable_deferred_delete() const {
+ _safe_delete.enable_deferred_delete();
+}
+
+void ZPageAllocator::disable_deferred_delete() const {
+ _safe_delete.disable_deferred_delete();
+}
+
bool ZPageAllocator::is_alloc_stalled() const {
assert(SafepointSynchronize::is_at_safepoint(), "Should be at safepoint");
return !_queue.is_empty();
--- a/src/hotspot/share/gc/z/zPageAllocator.hpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/z/zPageAllocator.hpp Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -30,6 +30,7 @@
#include "gc/z/zPageCache.hpp"
#include "gc/z/zPhysicalMemory.hpp"
#include "gc/z/zPreMappedMemory.hpp"
+#include "gc/z/zSafeDelete.hpp"
#include "gc/z/zVirtualMemory.hpp"
#include "memory/allocation.hpp"
@@ -39,19 +40,19 @@
friend class VMStructs;
private:
- ZLock _lock;
- ZVirtualMemoryManager _virtual;
- ZPhysicalMemoryManager _physical;
- ZPageCache _cache;
- const size_t _max_reserve;
- ZPreMappedMemory _pre_mapped;
- size_t _used_high;
- size_t _used_low;
- size_t _used;
- size_t _allocated;
- ssize_t _reclaimed;
- ZList<ZPageAllocRequest> _queue;
- ZList<ZPage> _detached;
+ ZLock _lock;
+ ZVirtualMemoryManager _virtual;
+ ZPhysicalMemoryManager _physical;
+ ZPageCache _cache;
+ const size_t _max_reserve;
+ ZPreMappedMemory _pre_mapped;
+ size_t _used_high;
+ size_t _used_low;
+ size_t _used;
+ size_t _allocated;
+ ssize_t _reclaimed;
+ ZList<ZPageAllocRequest> _queue;
+ mutable ZSafeDelete<ZPage> _safe_delete;
static ZPage* const gc_marker;
@@ -63,8 +64,8 @@
size_t try_ensure_unused_for_pre_mapped(size_t size);
ZPage* create_page(uint8_t type, size_t size);
- void map_page(ZPage* page);
- void detach_page(ZPage* page);
+ void destroy_page(ZPage* page);
+
void flush_pre_mapped();
void flush_cache(size_t size);
@@ -97,13 +98,13 @@
void reset_statistics();
ZPage* alloc_page(uint8_t type, size_t size, ZAllocationFlags flags);
- void flip_page(ZPage* page);
void free_page(ZPage* page, bool reclaimed);
- void destroy_page(ZPage* page);
- void flush_detached_pages(ZList<ZPage>* list);
+ void enable_deferred_delete() const;
+ void disable_deferred_delete() const;
- void flip_pre_mapped();
+ void map_page(ZPage* page);
+ void unmap_all_pages();
bool is_alloc_stalled() const;
void check_out_of_memory();
--- a/src/hotspot/share/gc/z/zPageCache.cpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/z/zPageCache.cpp Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -118,10 +118,6 @@
}
void ZPageCache::free_page(ZPage* page) {
- assert(!page->is_active(), "Invalid page state");
- assert(!page->is_pinned(), "Invalid page state");
- assert(!page->is_detached(), "Invalid page state");
-
const uint8_t type = page->type();
if (type == ZPageTypeSmall) {
_small.get(page->numa_id()).insert_first(page);
--- a/src/hotspot/share/gc/z/zPageTable.cpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/z/zPageTable.cpp Thu Mar 21 18:04:01 2019 +0000
@@ -23,6 +23,7 @@
#include "precompiled.hpp"
#include "gc/z/zAddress.inline.hpp"
+#include "gc/z/zGranuleMap.inline.hpp"
#include "gc/z/zPage.inline.hpp"
#include "gc/z/zPageTable.inline.hpp"
#include "runtime/orderAccess.hpp"
@@ -31,65 +32,22 @@
ZPageTable::ZPageTable() :
_map() {}
-ZPageTableEntry ZPageTable::get_entry(ZPage* page) const {
+void ZPageTable::insert(ZPage* page) {
const uintptr_t addr = ZAddress::good(page->start());
- return _map.get(addr);
-}
+ const size_t size = page->size();
-void ZPageTable::put_entry(ZPage* page, ZPageTableEntry entry) {
- // Make sure a newly created page is globally visible before
- // updating the pagetable.
+ // Make sure a newly created page is
+ // visible before updating the page table.
OrderAccess::storestore();
- const uintptr_t start = ZAddress::good(page->start());
- const uintptr_t end = start + page->size();
- for (uintptr_t addr = start; addr < end; addr += ZGranuleSize) {
- _map.put(addr, entry);
- }
-}
-
-void ZPageTable::insert(ZPage* page) {
- assert(get_entry(page).page() == NULL ||
- get_entry(page).page() == page, "Invalid entry");
-
- // Cached pages stays in the pagetable and we must not re-insert
- // those when they get re-allocated because they might also be
- // relocating and we don't want to clear their relocating bit.
- if (get_entry(page).page() == NULL) {
- ZPageTableEntry entry(page, false /* relocating */);
- put_entry(page, entry);
- }
-
- assert(get_entry(page).page() == page, "Invalid entry");
+ assert(get(addr) == NULL, "Invalid entry");
+ _map.put(addr, size, page);
}
void ZPageTable::remove(ZPage* page) {
- assert(get_entry(page).page() == page, "Invalid entry");
-
- ZPageTableEntry entry;
- put_entry(page, entry);
-
- assert(get_entry(page).page() == NULL, "Invalid entry");
-}
-
-void ZPageTable::set_relocating(ZPage* page) {
- assert(get_entry(page).page() == page, "Invalid entry");
- assert(!get_entry(page).relocating(), "Invalid entry");
-
- ZPageTableEntry entry(page, true /* relocating */);
- put_entry(page, entry);
+ const uintptr_t addr = ZAddress::good(page->start());
+ const size_t size = page->size();
- assert(get_entry(page).page() == page, "Invalid entry");
- assert(get_entry(page).relocating(), "Invalid entry");
+ assert(get(addr) == page, "Invalid entry");
+ _map.put(addr, size, NULL);
}
-
-void ZPageTable::clear_relocating(ZPage* page) {
- assert(get_entry(page).page() == page, "Invalid entry");
- assert(get_entry(page).relocating(), "Invalid entry");
-
- ZPageTableEntry entry(page, false /* relocating */);
- put_entry(page, entry);
-
- assert(get_entry(page).page() == page, "Invalid entry");
- assert(!get_entry(page).relocating(), "Invalid entry");
-}
--- a/src/hotspot/share/gc/z/zPageTable.hpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/z/zPageTable.hpp Thu Mar 21 18:04:01 2019 +0000
@@ -25,7 +25,6 @@
#define SHARE_GC_Z_ZPAGETABLE_HPP
#include "gc/z/zGranuleMap.hpp"
-#include "gc/z/zPageTableEntry.hpp"
#include "memory/allocation.hpp"
class ZPage;
@@ -35,30 +34,24 @@
friend class ZPageTableIterator;
private:
- ZGranuleMap<ZPageTableEntry> _map;
-
- ZPageTableEntry get_entry(ZPage* page) const;
- void put_entry(ZPage* page, ZPageTableEntry entry);
+ ZGranuleMap<ZPage*> _map;
public:
ZPageTable();
ZPage* get(uintptr_t addr) const;
+
void insert(ZPage* page);
void remove(ZPage* page);
-
- bool is_relocating(uintptr_t addr) const;
- void set_relocating(ZPage* page);
- void clear_relocating(ZPage* page);
};
class ZPageTableIterator : public StackObj {
private:
- ZGranuleMapIterator<ZPageTableEntry> _iter;
- ZPage* _prev;
+ ZGranuleMapIterator<ZPage*> _iter;
+ ZPage* _prev;
public:
- ZPageTableIterator(const ZPageTable* pagetable);
+ ZPageTableIterator(const ZPageTable* page_table);
bool next(ZPage** page);
};
--- a/src/hotspot/share/gc/z/zPageTable.inline.hpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/z/zPageTable.inline.hpp Thu Mar 21 18:04:01 2019 +0000
@@ -29,25 +29,18 @@
#include "gc/z/zPageTable.hpp"
inline ZPage* ZPageTable::get(uintptr_t addr) const {
- return _map.get(addr).page();
+ return _map.get(addr);
}
-inline bool ZPageTable::is_relocating(uintptr_t addr) const {
- return _map.get(addr).relocating();
-}
-
-inline ZPageTableIterator::ZPageTableIterator(const ZPageTable* pagetable) :
- _iter(&pagetable->_map),
+inline ZPageTableIterator::ZPageTableIterator(const ZPageTable* page_table) :
+ _iter(&page_table->_map),
_prev(NULL) {}
inline bool ZPageTableIterator::next(ZPage** page) {
- ZPageTableEntry entry;
-
- while (_iter.next(&entry)) {
- ZPage* const next = entry.page();
- if (next != NULL && next != _prev) {
+ for (ZPage* entry; _iter.next(&entry);) {
+ if (entry != NULL && entry != _prev) {
// Next page found
- *page = _prev = next;
+ *page = _prev = entry;
return true;
}
}
--- a/src/hotspot/share/gc/z/zPageTableEntry.hpp Thu Mar 21 08:41:10 2019 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#ifndef SHARE_GC_Z_ZPAGETABLEENTRY_HPP
-#define SHARE_GC_Z_ZPAGETABLEENTRY_HPP
-
-#include "gc/z/zBitField.hpp"
-#include "memory/allocation.hpp"
-
-//
-// Page table entry layout
-// -----------------------
-//
-// 6
-// 3 1 0
-// +----------------------------------------------------------------------+-+
-// |11111111 11111111 11111111 11111111 11111111 11111111 11111111 1111111|1|
-// +----------------------------------------------------------------------+-+
-// | |
-// | 0-0 Relocating Flag (1-bit) *
-// |
-// |
-// |
-// * 63-1 Page address (63-bits)
-//
-
-class ZPage;
-
-class ZPageTableEntry {
-private:
- typedef ZBitField<uint64_t, bool, 0, 1> field_relocating;
- typedef ZBitField<uint64_t, ZPage*, 1, 63, 1> field_page;
-
- uint64_t _entry;
-
-public:
- ZPageTableEntry() :
- _entry(0) {}
-
- ZPageTableEntry(ZPage* page, bool relocating) :
- _entry(field_page::encode(page) |
- field_relocating::encode(relocating)) {}
-
- bool relocating() const {
- return field_relocating::decode(_entry);
- }
-
- ZPage* page() const {
- return field_page::decode(_entry);
- }
-};
-
-#endif // SHARE_GC_Z_ZPAGETABLEENTRY_HPP
--- a/src/hotspot/share/gc/z/zPhysicalMemory.cpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/z/zPhysicalMemory.cpp Thu Mar 21 18:04:01 2019 +0000
@@ -179,6 +179,10 @@
_backing.unmap(pmem, offset);
}
-void ZPhysicalMemoryManager::flip(ZPhysicalMemory pmem, uintptr_t offset) {
- _backing.flip(pmem, offset);
+void ZPhysicalMemoryManager::debug_map(ZPhysicalMemory pmem, uintptr_t offset) {
+ _backing.debug_map(pmem, offset);
}
+
+void ZPhysicalMemoryManager::debug_unmap(ZPhysicalMemory pmem, uintptr_t offset) {
+ _backing.debug_unmap(pmem, offset);
+}
--- a/src/hotspot/share/gc/z/zPhysicalMemory.hpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/z/zPhysicalMemory.hpp Thu Mar 21 18:04:01 2019 +0000
@@ -94,7 +94,9 @@
void map(ZPhysicalMemory pmem, uintptr_t offset);
void unmap(ZPhysicalMemory pmem, uintptr_t offset);
- void flip(ZPhysicalMemory pmem, uintptr_t offset);
+
+ void debug_map(ZPhysicalMemory pmem, uintptr_t offset);
+ void debug_unmap(ZPhysicalMemory pmem, uintptr_t offset);
};
#endif // SHARE_GC_Z_ZPHYSICALMEMORY_HPP
--- a/src/hotspot/share/gc/z/zRelocate.cpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/z/zRelocate.cpp Thu Mar 21 18:04:01 2019 +0000
@@ -24,15 +24,20 @@
#include "precompiled.hpp"
#include "gc/z/zAddress.inline.hpp"
#include "gc/z/zBarrier.inline.hpp"
+#include "gc/z/zForwarding.inline.hpp"
#include "gc/z/zHeap.hpp"
#include "gc/z/zOopClosures.inline.hpp"
#include "gc/z/zPage.hpp"
#include "gc/z/zRelocate.hpp"
#include "gc/z/zRelocationSet.inline.hpp"
#include "gc/z/zRootsIterator.hpp"
+#include "gc/z/zStat.hpp"
#include "gc/z/zTask.hpp"
#include "gc/z/zThreadLocalAllocBuffer.hpp"
#include "gc/z/zWorkers.hpp"
+#include "logging/log.hpp"
+
+static const ZStatCounter ZCounterRelocationContention("Contention", "Relocation Contention", ZStatUnitOpsPerSecond);
ZRelocate::ZRelocate(ZWorkers* workers) :
_workers(workers) {}
@@ -78,16 +83,89 @@
_workers->run_parallel(&task);
}
+uintptr_t ZRelocate::relocate_object_inner(ZForwarding* forwarding, uintptr_t from_index, uintptr_t from_offset) const {
+ ZForwardingCursor cursor;
+
+ // Lookup forwarding entry
+ const ZForwardingEntry entry = forwarding->find(from_index, &cursor);
+ if (entry.from_index() == from_index) {
+ // Already relocated, return new address
+ return entry.to_offset();
+ }
+
+ assert(ZHeap::heap()->is_object_live(ZAddress::good(from_offset)), "Should be live");
+
+ if (forwarding->is_pinned()) {
+ // In-place forward
+ return forwarding->insert(from_index, from_offset, &cursor);
+ }
+
+ // Allocate object
+ const uintptr_t from_good = ZAddress::good(from_offset);
+ const size_t size = ZUtils::object_size(from_good);
+ const uintptr_t to_good = ZHeap::heap()->alloc_object_for_relocation(size);
+ if (to_good == 0) {
+ // Failed, in-place forward
+ return forwarding->insert(from_index, from_offset, &cursor);
+ }
+
+ // Copy object
+ ZUtils::object_copy(from_good, to_good, size);
+
+ // Insert forwarding entry
+ const uintptr_t to_offset = ZAddress::offset(to_good);
+ const uintptr_t to_offset_final = forwarding->insert(from_index, to_offset, &cursor);
+ if (to_offset_final == to_offset) {
+ // Relocation succeeded
+ return to_offset;
+ }
+
+ // Relocation contention
+ ZStatInc(ZCounterRelocationContention);
+ log_trace(gc)("Relocation contention, thread: " PTR_FORMAT " (%s), forwarding: " PTR_FORMAT
+ ", entry: " UINT32_FORMAT ", oop: " PTR_FORMAT ", size: " SIZE_FORMAT,
+ ZThread::id(), ZThread::name(), p2i(forwarding), cursor, from_good, size);
+
+ // Try undo allocation
+ ZHeap::heap()->undo_alloc_object_for_relocation(to_good, size);
+
+ return to_offset_final;
+}
+
+uintptr_t ZRelocate::relocate_object(ZForwarding* forwarding, uintptr_t from_addr) const {
+ const uintptr_t from_offset = ZAddress::offset(from_addr);
+ const uintptr_t from_index = (from_offset - forwarding->start()) >> forwarding->object_alignment_shift();
+ const uintptr_t to_offset = relocate_object_inner(forwarding, from_index, from_offset);
+
+ if (from_offset == to_offset) {
+ // In-place forwarding, pin page
+ forwarding->set_pinned();
+ }
+
+ return ZAddress::good(to_offset);
+}
+
+uintptr_t ZRelocate::forward_object(ZForwarding* forwarding, uintptr_t from_addr) const {
+ const uintptr_t from_offset = ZAddress::offset(from_addr);
+ const uintptr_t from_index = (from_offset - forwarding->start()) >> forwarding->object_alignment_shift();
+ const ZForwardingEntry entry = forwarding->find(from_index);
+
+ assert(entry.from_index() == from_index, "Should be forwarded");
+ return ZAddress::good(entry.to_offset());
+}
+
class ZRelocateObjectClosure : public ObjectClosure {
private:
- ZPage* const _page;
+ ZRelocate* const _relocate;
+ ZForwarding* const _forwarding;
public:
- ZRelocateObjectClosure(ZPage* page) :
- _page(page) {}
+ ZRelocateObjectClosure(ZRelocate* relocate, ZForwarding* forwarding) :
+ _relocate(relocate),
+ _forwarding(forwarding) {}
virtual void do_object(oop o) {
- _page->relocate_object(ZOop::to_address(o));
+ _relocate->relocate_object(_forwarding, ZOop::to_address(o));
}
};
@@ -95,21 +173,21 @@
bool success = true;
// Relocate pages in the relocation set
- for (ZPage* page; iter->next(&page);) {
+ for (ZForwarding* forwarding; iter->next(&forwarding);) {
// Relocate objects in page
- ZRelocateObjectClosure cl(page);
- page->object_iterate(&cl);
+ ZRelocateObjectClosure cl(this, forwarding);
+ forwarding->page()->object_iterate(&cl);
if (ZVerifyForwarding) {
- page->verify_forwarding();
+ forwarding->verify();
}
- if (page->is_pinned()) {
+ if (forwarding->is_pinned()) {
// Relocation failed, page is now pinned
success = false;
} else {
// Relocation succeeded, release page
- ZHeap::heap()->release_page(page, true /* reclaimed */);
+ forwarding->release_page();
}
}
--- a/src/hotspot/share/gc/z/zRelocate.hpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/z/zRelocate.hpp Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -28,17 +28,24 @@
#include "gc/z/zWorkers.hpp"
#include "memory/allocation.hpp"
+class ZForwarding;
+
class ZRelocate {
friend class ZRelocateTask;
private:
ZWorkers* const _workers;
+ ZForwarding* forwarding_for_page(ZPage* page) const;
+ uintptr_t relocate_object_inner(ZForwarding* forwarding, uintptr_t from_index, uintptr_t from_offset) const;
bool work(ZRelocationSetParallelIterator* iter);
public:
ZRelocate(ZWorkers* workers);
+ uintptr_t relocate_object(ZForwarding* forwarding, uintptr_t from_addr) const;
+ uintptr_t forward_object(ZForwarding* forwarding, uintptr_t from_addr) const;
+
void start();
bool relocate(ZRelocationSet* relocation_set);
};
--- a/src/hotspot/share/gc/z/zRelocationSet.cpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/z/zRelocationSet.cpp Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -22,24 +22,35 @@
*/
#include "precompiled.hpp"
+#include "gc/z/zForwarding.hpp"
#include "gc/z/zRelocationSet.hpp"
-#include "memory/allocation.inline.hpp"
+#include "memory/allocation.hpp"
ZRelocationSet::ZRelocationSet() :
- _pages(NULL),
- _npages(0) {}
+ _forwardings(NULL),
+ _nforwardings(0) {}
-void ZRelocationSet::populate(const ZPage* const* group0, size_t ngroup0,
- const ZPage* const* group1, size_t ngroup1) {
- _npages = ngroup0 + ngroup1;
- _pages = REALLOC_C_HEAP_ARRAY(ZPage*, _pages, _npages, mtGC);
+void ZRelocationSet::populate(ZPage* const* group0, size_t ngroup0,
+ ZPage* const* group1, size_t ngroup1) {
+ _nforwardings = ngroup0 + ngroup1;
+ _forwardings = REALLOC_C_HEAP_ARRAY(ZForwarding*, _forwardings, _nforwardings, mtGC);
- if (_pages != NULL) {
- if (group0 != NULL) {
- memcpy(_pages, group0, ngroup0 * sizeof(ZPage*));
- }
- if (group1 != NULL) {
- memcpy(_pages + ngroup0, group1, ngroup1 * sizeof(ZPage*));
- }
+ size_t j = 0;
+
+ // Populate group 0
+ for (size_t i = 0; i < ngroup0; i++) {
+ _forwardings[j++] = ZForwarding::create(group0[i]);
+ }
+
+ // Populate group 1
+ for (size_t i = 0; i < ngroup1; i++) {
+ _forwardings[j++] = ZForwarding::create(group1[i]);
}
}
+
+void ZRelocationSet::reset() {
+ for (size_t i = 0; i < _nforwardings; i++) {
+ ZForwarding::destroy(_forwardings[i]);
+ _forwardings[i] = NULL;
+ }
+}
--- a/src/hotspot/share/gc/z/zRelocationSet.hpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/z/zRelocationSet.hpp Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,20 +26,22 @@
#include "memory/allocation.hpp"
+class ZForwarding;
class ZPage;
class ZRelocationSet {
template <bool> friend class ZRelocationSetIteratorImpl;
private:
- ZPage** _pages;
- size_t _npages;
+ ZForwarding** _forwardings;
+ size_t _nforwardings;
public:
ZRelocationSet();
- void populate(const ZPage* const* group0, size_t ngroup0,
- const ZPage* const* group1, size_t ngroup1);
+ void populate(ZPage* const* group0, size_t ngroup0,
+ ZPage* const* group1, size_t ngroup1);
+ void reset();
};
template <bool parallel>
@@ -51,7 +53,7 @@
public:
ZRelocationSetIteratorImpl(ZRelocationSet* relocation_set);
- bool next(ZPage** page);
+ bool next(ZForwarding** forwarding);
};
// Iterator types
--- a/src/hotspot/share/gc/z/zRelocationSet.inline.hpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/z/zRelocationSet.inline.hpp Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -33,20 +33,20 @@
_next(0) {}
template <bool parallel>
-inline bool ZRelocationSetIteratorImpl<parallel>::next(ZPage** page) {
- const size_t npages = _relocation_set->_npages;
+inline bool ZRelocationSetIteratorImpl<parallel>::next(ZForwarding** forwarding) {
+ const size_t nforwardings = _relocation_set->_nforwardings;
if (parallel) {
- if (_next < npages) {
+ if (_next < nforwardings) {
const size_t next = Atomic::add(1u, &_next) - 1u;
- if (next < npages) {
- *page = _relocation_set->_pages[next];
+ if (next < nforwardings) {
+ *forwarding = _relocation_set->_forwardings[next];
return true;
}
}
} else {
- if (_next < npages) {
- *page = _relocation_set->_pages[_next++];
+ if (_next < nforwardings) {
+ *forwarding = _relocation_set->_forwardings[_next++];
return true;
}
}
--- a/src/hotspot/share/gc/z/zRelocationSetSelector.cpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/z/zRelocationSetSelector.cpp Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -44,10 +44,10 @@
_fragmentation(0) {}
ZRelocationSetSelectorGroup::~ZRelocationSetSelectorGroup() {
- FREE_C_HEAP_ARRAY(const ZPage*, _sorted_pages);
+ FREE_C_HEAP_ARRAY(ZPage*, _sorted_pages);
}
-void ZRelocationSetSelectorGroup::register_live_page(const ZPage* page, size_t garbage) {
+void ZRelocationSetSelectorGroup::register_live_page(ZPage* page, size_t garbage) {
if (garbage > _fragmentation_limit) {
_registered_pages.add(page);
} else {
@@ -67,13 +67,13 @@
size_t partitions[npartitions];
// Allocate destination array
- _sorted_pages = REALLOC_C_HEAP_ARRAY(const ZPage*, _sorted_pages, npages, mtGC);
+ _sorted_pages = REALLOC_C_HEAP_ARRAY(ZPage*, _sorted_pages, npages, mtGC);
debug_only(memset(_sorted_pages, 0, npages * sizeof(ZPage*)));
// Calculate partition slots
memset(partitions, 0, sizeof(partitions));
- ZArrayIterator<const ZPage*> iter1(&_registered_pages);
- for (const ZPage* page; iter1.next(&page);) {
+ ZArrayIterator<ZPage*> iter1(&_registered_pages);
+ for (ZPage* page; iter1.next(&page);) {
const size_t index = page->live_bytes() >> partition_size_shift;
partitions[index]++;
}
@@ -87,8 +87,8 @@
}
// Sort pages into partitions
- ZArrayIterator<const ZPage*> iter2(&_registered_pages);
- for (const ZPage* page; iter2.next(&page);) {
+ ZArrayIterator<ZPage*> iter2(&_registered_pages);
+ for (ZPage* page; iter2.next(&page);) {
const size_t index = page->live_bytes() >> partition_size_shift;
const size_t finger = partitions[index]++;
assert(_sorted_pages[finger] == NULL, "Invalid finger");
@@ -140,7 +140,7 @@
// Update statistics
_relocating = from_size;
for (size_t i = _nselected; i < npages; i++) {
- const ZPage* const page = _sorted_pages[i];
+ ZPage* const page = _sorted_pages[i];
_fragmentation += page->size() - page->live_bytes();
}
@@ -148,7 +148,7 @@
_name, selected_from, selected_to, npages - _nselected);
}
-const ZPage* const* ZRelocationSetSelectorGroup::selected() const {
+ZPage* const* ZRelocationSetSelectorGroup::selected() const {
return _sorted_pages;
}
@@ -171,7 +171,7 @@
_garbage(0),
_fragmentation(0) {}
-void ZRelocationSetSelector::register_live_page(const ZPage* page) {
+void ZRelocationSetSelector::register_live_page(ZPage* page) {
const uint8_t type = page->type();
const size_t live = page->live_bytes();
const size_t garbage = page->size() - live;
@@ -188,7 +188,7 @@
_garbage += garbage;
}
-void ZRelocationSetSelector::register_garbage_page(const ZPage* page) {
+void ZRelocationSetSelector::register_garbage_page(ZPage* page) {
_garbage += page->size();
}
--- a/src/hotspot/share/gc/z/zRelocationSetSelector.hpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/z/zRelocationSetSelector.hpp Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -32,16 +32,16 @@
class ZRelocationSetSelectorGroup {
private:
- const char* const _name;
- const size_t _page_size;
- const size_t _object_size_limit;
- const size_t _fragmentation_limit;
+ const char* const _name;
+ const size_t _page_size;
+ const size_t _object_size_limit;
+ const size_t _fragmentation_limit;
- ZArray<const ZPage*> _registered_pages;
- const ZPage** _sorted_pages;
- size_t _nselected;
- size_t _relocating;
- size_t _fragmentation;
+ ZArray<ZPage*> _registered_pages;
+ ZPage** _sorted_pages;
+ size_t _nselected;
+ size_t _relocating;
+ size_t _fragmentation;
void semi_sort();
@@ -51,10 +51,10 @@
size_t object_size_limit);
~ZRelocationSetSelectorGroup();
- void register_live_page(const ZPage* page, size_t garbage);
+ void register_live_page(ZPage* page, size_t garbage);
void select();
- const ZPage* const* selected() const;
+ ZPage* const* selected() const;
size_t nselected() const;
size_t relocating() const;
size_t fragmentation() const;
@@ -71,8 +71,8 @@
public:
ZRelocationSetSelector();
- void register_live_page(const ZPage* page);
- void register_garbage_page(const ZPage* page);
+ void register_live_page(ZPage* page);
+ void register_garbage_page(ZPage* page);
void select(ZRelocationSet* relocation_set);
size_t live() const;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/z/zSafeDelete.hpp Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef SHARE_GC_Z_ZSAFEDELETE_HPP
+#define SHARE_GC_Z_ZSAFEDELETE_HPP
+
+#include "gc/z/zArray.hpp"
+#include "gc/z/zLock.hpp"
+#include "metaprogramming/removeExtent.hpp"
+
+template <typename T>
+class ZSafeDelete {
+private:
+ typedef typename RemoveExtent<T>::type ItemT;
+
+ ZLock _lock;
+ uint64_t _enabled;
+ ZArray<ItemT*> _deferred;
+
+ bool deferred_delete(ItemT* item);
+ void immediate_delete(ItemT* item);
+
+public:
+ ZSafeDelete();
+
+ void enable_deferred_delete();
+ void disable_deferred_delete();
+
+ void operator()(ItemT* item);
+};
+
+#endif // SHARE_GC_Z_ZSAFEDELETE_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/z/zSafeDelete.inline.hpp Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef SHARE_GC_Z_ZSAFEDELETE_INLINE_HPP
+#define SHARE_GC_Z_ZSAFEDELETE_INLINE_HPP
+
+#include "gc/z/zArray.inline.hpp"
+#include "gc/z/zSafeDelete.hpp"
+#include "metaprogramming/isArray.hpp"
+#include "utilities/debug.hpp"
+
+template <typename T>
+ZSafeDelete<T>::ZSafeDelete() :
+ _lock(),
+ _enabled(0),
+ _deferred() {}
+
+template <typename T>
+bool ZSafeDelete<T>::deferred_delete(ItemT* item) {
+ ZLocker<ZLock> locker(&_lock);
+ if (_enabled > 0) {
+ _deferred.add(item);
+ return true;
+ }
+
+ return false;
+}
+
+template <typename T>
+void ZSafeDelete<T>::immediate_delete(ItemT* item) {
+ if (IsArray<T>::value) {
+ delete [] item;
+ } else {
+ delete item;
+ }
+}
+
+template <typename T>
+void ZSafeDelete<T>::enable_deferred_delete() {
+ ZLocker<ZLock> locker(&_lock);
+ _enabled++;
+}
+
+template <typename T>
+void ZSafeDelete<T>::disable_deferred_delete() {
+ ZArray<ItemT*> deferred;
+
+ {
+ ZLocker<ZLock> locker(&_lock);
+ assert(_enabled > 0, "Invalid state");
+ if (--_enabled == 0) {
+ deferred.transfer(&_deferred);
+ }
+ }
+
+ ZArrayIterator<ItemT*> iter(&deferred);
+ for (ItemT* item; iter.next(&item);) {
+ immediate_delete(item);
+ }
+}
+
+template <typename T>
+void ZSafeDelete<T>::operator()(ItemT* item) {
+ if (!deferred_delete(item)) {
+ immediate_delete(item);
+ }
+}
+
+#endif // SHARE_GC_Z_ZSAFEDELETE_INLINE_HPP
--- a/src/hotspot/share/gc/z/z_globals.hpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/gc/z/z_globals.hpp Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -70,8 +70,8 @@
diagnostic(bool, ZProactive, true, \
"Enable proactive GC cycles") \
\
- diagnostic(bool, ZUnmapBadViews, false, \
- "Unmap bad (inactive) heap views") \
+ diagnostic(bool, ZVerifyViews, false, \
+ "Verify heap view accesses") \
\
diagnostic(bool, ZVerifyMarking, false, \
"Verify marking stacks") \
--- a/src/hotspot/share/runtime/arguments.cpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/runtime/arguments.cpp Thu Mar 21 18:04:01 2019 +0000
@@ -530,6 +530,7 @@
{ "UseMembar", JDK_Version::jdk(10), JDK_Version::jdk(12), JDK_Version::undefined() },
{ "CompilationPolicyChoice", JDK_Version::jdk(13), JDK_Version::jdk(14), JDK_Version::undefined() },
{ "FailOverToOldVerifier", JDK_Version::jdk(13), JDK_Version::jdk(14), JDK_Version::undefined() },
+ { "AllowJNIEnvProxy", JDK_Version::jdk(13), JDK_Version::jdk(14), JDK_Version::jdk(15) },
{ "ThreadLocalHandshakes", JDK_Version::jdk(13), JDK_Version::jdk(14), JDK_Version::jdk(15) },
// --- Deprecated alias flags (see also aliased_jvm_flags) - sorted by obsolete_in then expired_in:
--- a/src/hotspot/share/runtime/globals.hpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/runtime/globals.hpp Thu Mar 21 18:04:01 2019 +0000
@@ -861,7 +861,7 @@
"by the application (Solaris & Linux only)") \
\
product(bool, AllowJNIEnvProxy, false, \
- "Allow JNIEnv proxies for jdbx") \
+ "(Deprecated) Allow JNIEnv proxies for jdbx") \
\
product(bool, RestoreMXCSROnJNICalls, false, \
"Restore MXCSR when returning from JNI calls") \
@@ -1234,7 +1234,7 @@
"exit") \
\
product(bool, PrintFlagsRanges, false, \
- "Print VM flags and their ranges and exit VM") \
+ "Print VM flags and their ranges") \
\
diagnostic(bool, SerializeVMOutput, true, \
"Use a mutex to serialize output to tty and LogFile") \
--- a/src/hotspot/share/utilities/globalDefinitions_gcc.hpp Thu Mar 21 08:41:10 2019 +0000
+++ b/src/hotspot/share/utilities/globalDefinitions_gcc.hpp Thu Mar 21 18:04:01 2019 +0000
@@ -270,8 +270,8 @@
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53017
//
// GCC versions older than 4.6.4 would fail even with "+0", and needs additional
-// cast to typeof(x) to work around the similar bug.
+// cast to __typeof__(x) to work around the similar bug.
//
-#define ATTRIBUTE_ALIGNED(x) __attribute__((aligned((typeof(x))x+0)))
+#define ATTRIBUTE_ALIGNED(x) __attribute__((aligned((__typeof__(x))x+0)))
#endif // SHARE_UTILITIES_GLOBALDEFINITIONS_GCC_HPP
--- a/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/Metrics.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/Metrics.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -124,13 +124,13 @@
/**
* createSubSystem objects and initialize mount points
*/
- private static void createSubSystem(Metrics metric, String [] mountentry) {
+ private static void createSubSystem(Metrics metric, String[] mountentry) {
if (mountentry.length < 5) return;
Path p = Paths.get(mountentry[4]);
- String subsystemName = p.getFileName().toString();
+ String[] subsystemNames = p.getFileName().toString().split(",");
- if (subsystemName != null) {
+ for (String subsystemName: subsystemNames) {
switch (subsystemName) {
case "memory":
metric.setMemorySubSystem(new SubSystem(mountentry[3], mountentry[4]));
@@ -138,11 +138,6 @@
case "cpuset":
metric.setCpuSetSubSystem(new SubSystem(mountentry[3], mountentry[4]));
break;
- case "cpu,cpuacct":
- case "cpuacct,cpu":
- metric.setCpuSubSystem(new SubSystem(mountentry[3], mountentry[4]));
- metric.setCpuAcctSubSystem(new SubSystem(mountentry[3], mountentry[4]));
- break;
case "cpuacct":
metric.setCpuAcctSubSystem(new SubSystem(mountentry[3], mountentry[4]));
break;
@@ -162,7 +157,7 @@
/**
* setSubSystemPath based on the contents of /proc/self/cgroup
*/
- private static void setSubSystemPath(Metrics metric, String [] entry) {
+ private static void setSubSystemPath(Metrics metric, String[] entry) {
String controller;
String base;
SubSystem subsystem = null;
@@ -298,15 +293,15 @@
public long getCpuPeriod() {
- return SubSystem.getLongValue(cpuacct, "cpu.cfs_period_us");
+ return SubSystem.getLongValue(cpu, "cpu.cfs_period_us");
}
public long getCpuQuota() {
- return SubSystem.getLongValue(cpuacct, "cpu.cfs_quota_us");
+ return SubSystem.getLongValue(cpu, "cpu.cfs_quota_us");
}
public long getCpuShares() {
- long retval = SubSystem.getLongValue(cpuacct, "cpu.shares");
+ long retval = SubSystem.getLongValue(cpu, "cpu.shares");
if (retval == 0 || retval == 1024)
return -1;
else
@@ -314,15 +309,15 @@
}
public long getCpuNumPeriods() {
- return SubSystem.getLongEntry(cpuacct, "cpu.stat", "nr_periods");
+ return SubSystem.getLongEntry(cpu, "cpu.stat", "nr_periods");
}
public long getCpuNumThrottled() {
- return SubSystem.getLongEntry(cpuacct, "cpu.stat", "nr_throttled");
+ return SubSystem.getLongEntry(cpu, "cpu.stat", "nr_throttled");
}
public long getCpuThrottledTime() {
- return SubSystem.getLongEntry(cpuacct, "cpu.stat", "throttled_time");
+ return SubSystem.getLongEntry(cpu, "cpu.stat", "throttled_time");
}
public long getEffectiveCpuCount() {
--- a/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/SubSystem.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/SubSystem.java Thu Mar 21 18:04:01 2019 +0000
@@ -48,7 +48,7 @@
public void setPath(String cgroupPath) {
if (root != null && cgroupPath != null) {
if (root.equals("/")) {
- if (cgroupPath.equals("/")) {
+ if (!cgroupPath.equals("/")) {
path = mountPoint + cgroupPath;
}
else {
--- a/src/java.base/share/classes/com/sun/crypto/provider/PBKDF2KeyImpl.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/com/sun/crypto/provider/PBKDF2KeyImpl.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -113,12 +113,7 @@
} else if (keyLength < 0) {
throw new InvalidKeySpecException("Key length is negative");
}
- this.prf = Mac.getInstance(prfAlgo);
- // SunPKCS11 requires a non-empty PBE password
- if (passwdBytes.length == 0 &&
- this.prf.getProvider().getName().startsWith("SunPKCS11")) {
- this.prf = Mac.getInstance(prfAlgo, SunJCE.getInstance());
- }
+ this.prf = Mac.getInstance(prfAlgo, SunJCE.getInstance());
this.key = deriveKey(prf, passwdBytes, salt, iterCount, keyLength);
} catch (NoSuchAlgorithmException nsae) {
// not gonna happen; re-throw just in case
@@ -207,7 +202,7 @@
}
}
} catch (GeneralSecurityException gse) {
- throw new RuntimeException("Error deriving PBKDF2 keys");
+ throw new RuntimeException("Error deriving PBKDF2 keys", gse);
}
return key;
}
--- a/src/java.base/share/classes/java/io/DataInput.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/io/DataInput.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -48,7 +48,7 @@
* may be thrown if the input stream has been
* closed.
*
- * <h3><a id="modified-utf-8">Modified UTF-8</a></h3>
+ * <h2><a id="modified-utf-8">Modified UTF-8</a></h2>
* <p>
* Implementations of the DataInput and DataOutput interfaces represent
* Unicode strings in a format that is a slight modification of UTF-8.
--- a/src/java.base/share/classes/java/io/File.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/io/File.java Thu Mar 21 18:04:01 2019 +0000
@@ -128,7 +128,7 @@
* created, the abstract pathname represented by a <code>File</code> object
* will never change.
*
- * <h3>Interoperability with {@code java.nio.file} package</h3>
+ * <h2>Interoperability with {@code java.nio.file} package</h2>
*
* <p> The <a href="../../java/nio/file/package-summary.html">{@code java.nio.file}</a>
* package defines interfaces and classes for the Java virtual machine to access
--- a/src/java.base/share/classes/java/lang/Character.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/lang/Character.java Thu Mar 21 18:04:01 2019 +0000
@@ -44,7 +44,7 @@
* and for converting characters from uppercase to lowercase and vice
* versa.
*
- * <h3><a id="conformance">Unicode Conformance</a></h3>
+ * <h2><a id="conformance">Unicode Conformance</a></h2>
* <p>
* The fields and methods of class {@code Character} are defined in terms
* of character information from the Unicode Standard, specifically the
@@ -59,7 +59,7 @@
* {@code U+32FF}, from the first version of the Unicode Standard
* after 11.0 that assigns the code point.
*
- * <h3><a id="unicode">Unicode Character Representations</a></h3>
+ * <h2><a id="unicode">Unicode Character Representations</a></h2>
*
* <p>The {@code char} data type (and therefore the value that a
* {@code Character} object encapsulates) are based on the
--- a/src/java.base/share/classes/java/lang/ClassLoader.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/lang/ClassLoader.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -126,7 +126,7 @@
* duration of the class loading process (see {@link #loadClass
* loadClass} methods).
*
- * <h3> <a id="builtinLoaders">Run-time Built-in Class Loaders</a></h3>
+ * <h2> <a id="builtinLoaders">Run-time Built-in Class Loaders</a></h2>
*
* The Java run-time has the following built-in class loaders:
*
--- a/src/java.base/share/classes/java/lang/ModuleLayer.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/lang/ModuleLayer.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -120,7 +120,7 @@
* in this class causes a {@link NullPointerException NullPointerException} to
* be thrown. </p>
*
- * <h3> Example usage: </h3>
+ * <h2> Example usage: </h2>
*
* <p> This example creates a configuration by resolving a module named
* "{@code myapp}" with the configuration for the boot layer as the parent. It
--- a/src/java.base/share/classes/java/lang/Process.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/lang/Process.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -206,20 +206,20 @@
public boolean waitFor(long timeout, TimeUnit unit)
throws InterruptedException
{
- long startTime = System.nanoTime();
- long rem = unit.toNanos(timeout);
+ long remainingNanos = unit.toNanos(timeout); // throw NPE before other conditions
+ if (hasExited())
+ return true;
+ if (timeout <= 0)
+ return false;
+ long deadline = System.nanoTime() + remainingNanos;
do {
- try {
- exitValue();
+ Thread.sleep(Math.min(TimeUnit.NANOSECONDS.toMillis(remainingNanos) + 1, 100));
+ if (hasExited())
return true;
- } catch(IllegalThreadStateException ex) {
- if (rem > 0)
- Thread.sleep(
- Math.min(TimeUnit.NANOSECONDS.toMillis(rem) + 1, 100));
- }
- rem = unit.toNanos(timeout) - (System.nanoTime() - startTime);
- } while (rem > 0);
+ remainingNanos = deadline - System.nanoTime();
+ } while (remainingNanos > 0);
+
return false;
}
@@ -320,11 +320,20 @@
* @since 1.8
*/
public boolean isAlive() {
+ return !hasExited();
+ }
+
+ /**
+ * This is called from the default implementation of
+ * {@code waitFor(long, TimeUnit)}, which is specified to poll
+ * {@code exitValue()}.
+ */
+ private boolean hasExited() {
try {
exitValue();
+ return true;
+ } catch (IllegalThreadStateException e) {
return false;
- } catch(IllegalThreadStateException e) {
- return true;
}
}
--- a/src/java.base/share/classes/java/lang/doc-files/ValueBased.html Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/lang/doc-files/ValueBased.html Thu Mar 21 18:04:01 2019 +0000
@@ -5,7 +5,7 @@
<link rel="stylesheet" type="text/css" href="../../../../stylesheet.css" title="Style">
</head>
<body>
-<h2 id="ValueBased">Value-based Classes</h2>
+<h1 id="ValueBased">Value-based Classes</h1>
Some classes, such as <code>java.util.Optional</code> and
<code>java.time.LocalDateTime</code>, are <em>value-based</em>. Instances of a
--- a/src/java.base/share/classes/java/lang/doc-files/threadPrimitiveDeprecation.html Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/lang/doc-files/threadPrimitiveDeprecation.html Thu Mar 21 18:04:01 2019 +0000
@@ -1,6 +1,6 @@
<!doctype html>
<!--
- Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
This code is free software; you can redistribute it and/or modify it
@@ -29,9 +29,9 @@
<link rel="stylesheet" type="text/css" href="../../../../stylesheet.css" title="Style">
</head>
<body>
-<h2>Java Thread Primitive Deprecation</h2>
+<h1>Java Thread Primitive Deprecation</h1>
<hr>
-<h3>Why is <code>Thread.stop</code> deprecated?</h3>
+<h2>Why is <code>Thread.stop</code> deprecated?</h2>
<p>Because it is inherently unsafe. Stopping a thread causes it to
unlock all the monitors that it has locked. (The monitors are
unlocked as the <code>ThreadDeath</code> exception propagates up
@@ -46,8 +46,8 @@
manifest itself at any time after the actual damage occurs, even
hours or days in the future.</p>
<hr>
-<h3>Couldn't I just catch the <code>ThreadDeath</code> exception
-and fix the damaged object?</h3>
+<h2>Couldn't I just catch the <code>ThreadDeath</code> exception
+and fix the damaged object?</h2>
<p>In theory, perhaps, but it would <em>vastly</em> complicate the
task of writing correct multithreaded code. The task would be
nearly insurmountable for two reasons:</p>
@@ -62,7 +62,7 @@
</ol>
In sum, it just isn't practical.
<hr>
-<h3>What should I use instead of <code>Thread.stop</code>?</h3>
+<h2>What should I use instead of <code>Thread.stop</code>?</h2>
<p>Most uses of <code>stop</code> should be replaced by code that
simply modifies some variable to indicate that the target thread
should stop running. The target thread should check this variable
@@ -117,8 +117,8 @@
}
</pre>
<hr>
-<h3>How do I stop a thread that waits for long periods (e.g., for
-input)?</h3>
+<h2>How do I stop a thread that waits for long periods (e.g., for
+input)?</h2>
<p>That's what the <code>Thread.interrupt</code> method is for. The
same "state based" signaling mechanism shown above can be used, but
the state change (<code>blinker = null</code>, in the previous
@@ -145,8 +145,8 @@
This ensures that the Thread will reraise the
<code>InterruptedException</code> as soon as it is able.
<hr>
-<h3>What if a thread doesn't respond to
-<code>Thread.interrupt</code>?</h3>
+<h2>What if a thread doesn't respond to
+<code>Thread.interrupt</code>?</h2>
<p>In some cases, you can use application specific tricks. For
example, if a thread is waiting on a known socket, you can close
the socket to cause the thread to return immediately.
@@ -158,8 +158,8 @@
operations for which thread.stop and thread.interrupt do not work
properly.</p>
<hr>
-<h3>Why are <code>Thread.suspend</code> and
-<code>Thread.resume</code> deprecated?</h3>
+<h2>Why are <code>Thread.suspend</code> and
+<code>Thread.resume</code> deprecated?</h2>
<p><code>Thread.suspend</code> is inherently deadlock-prone. If the
target thread holds a lock on the monitor protecting a critical
system resource when it is suspended, no thread can access this
@@ -168,8 +168,8 @@
to calling <code>resume</code>, deadlock results. Such deadlocks
typically manifest themselves as "frozen" processes.</p>
<hr>
-<h3>What should I use instead of <code>Thread.suspend</code> and
-<code>Thread.resume</code>?</h3>
+<h2>What should I use instead of <code>Thread.suspend</code> and
+<code>Thread.resume</code>?</h2>
<p>As with <code>Thread.stop</code>, the prudent approach is to
have the "target thread" poll a variable indicating the desired
state of the thread (active or suspended). When the desired state
@@ -283,8 +283,8 @@
}
</pre>
<hr size="3" noshade="noshade" />
-<h3>Can I combine the two techniques to produce a thread that may
-be safely "stopped" or "suspended"?</h3>
+<h2>Can I combine the two techniques to produce a thread that may
+be safely "stopped" or "suspended"?</h2>
Yes, it's reasonably straightforward. The one subtlety is that the
target thread may already be suspended at the time that another
thread tries to stop it. If the <code>stop</code> method merely sets
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandle.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandle.java Thu Mar 21 18:04:01 2019 +0000
@@ -52,7 +52,7 @@
* {@linkplain java.lang.invoke.MethodHandles#dropArguments deletion},
* and {@linkplain java.lang.invoke.MethodHandles#filterArguments substitution}.
*
- * <h1>Method handle contents</h1>
+ * <h2>Method handle contents</h2>
* Method handles are dynamically and strongly typed according to their parameter and return types.
* They are not distinguished by the name or the defining class of their underlying methods.
* A method handle must be invoked using a symbolic type descriptor which matches
@@ -89,7 +89,7 @@
* from its specific class, as the method handle class hierarchy (if any)
* may change from time to time or across implementations from different vendors.
*
- * <h1>Method handle compilation</h1>
+ * <h2>Method handle compilation</h2>
* A Java method call expression naming {@code invokeExact} or {@code invoke}
* can invoke a method handle from Java source code.
* From the viewpoint of source code, these methods can take any arguments
@@ -121,7 +121,7 @@
* The ambiguity with the type {@code Void} is harmless, since there are no references of type
* {@code Void} except the null reference.
*
- * <h1>Method handle invocation</h1>
+ * <h2>Method handle invocation</h2>
* The first time an {@code invokevirtual} instruction is executed
* it is linked by symbolically resolving the names in the instruction
* and verifying that the method call is statically legal.
@@ -164,7 +164,7 @@
* (<em>Note:</em> The adjusted method handle {@code M2} is not directly observable,
* and implementations are therefore not required to materialize it.)
*
- * <h1>Invocation checking</h1>
+ * <h2>Invocation checking</h2>
* In typical programs, method handle type matching will usually succeed.
* But if a match fails, the JVM will throw a {@link WrongMethodTypeException},
* either directly (in the case of {@code invokeExact}) or indirectly as if
@@ -205,7 +205,7 @@
* They should not be passed to untrusted code unless their use from
* the untrusted code would be harmless.
*
- * <h1>Method handle creation</h1>
+ * <h2>Method handle creation</h2>
* Java code can create a method handle that directly accesses
* any method, constructor, or field that is accessible to that code.
* This is done via a reflective, capability-based API called
@@ -263,7 +263,7 @@
* of an {@code invokevirtual} or {@code invokeinterface} instruction on
* a private method (as applicable).
*
- * <h1>Usage examples</h1>
+ * <h2>Usage examples</h2>
* Here are some examples of usage:
* <blockquote><pre>{@code
Object x, y; String s; int i;
@@ -309,7 +309,7 @@
* be a method which calls {@link java.util.Objects#equals(Object,Object) Objects.equals}
* on its arguments, and asserts that the result is true.
*
- * <h1>Exceptions</h1>
+ * <h2>Exceptions</h2>
* The methods {@code invokeExact} and {@code invoke} are declared
* to throw {@link java.lang.Throwable Throwable},
* which is to say that there is no static restriction on what a method handle
@@ -322,7 +322,7 @@
* throwables locally, rethrowing only those which are legal in the context,
* and wrapping ones which are illegal.
*
- * <h1><a id="sigpoly"></a>Signature polymorphism</h1>
+ * <h2><a id="sigpoly"></a>Signature polymorphism</h2>
* The unusual compilation and linkage behavior of
* {@code invokeExact} and plain {@code invoke}
* is referenced by the term <em>signature polymorphism</em>.
@@ -347,7 +347,7 @@
* Tools which determine symbolic linkage are required to accept such
* untransformed descriptors, without reporting linkage errors.
*
- * <h1>Interoperation between method handles and the Core Reflection API</h1>
+ * <h2>Interoperation between method handles and the Core Reflection API</h2>
* Using factory methods in the {@link java.lang.invoke.MethodHandles.Lookup Lookup} API,
* any class member represented by a Core Reflection API object
* can be converted to a behaviorally equivalent method handle.
@@ -389,7 +389,7 @@
* to call {@code invokeExact} or plain {@code invoke},
* for any specified type descriptor .
*
- * <h1>Interoperation between method handles and Java generics</h1>
+ * <h2>Interoperation between method handles and Java generics</h2>
* A method handle can be obtained on a method, constructor, or field
* which is declared with Java generic types.
* As with the Core Reflection API, the type of the method handle
@@ -416,7 +416,7 @@
* genericity with a Java type parameter.</li>
* </ul>
*
- * <h1><a id="maxarity"></a>Arity limits</h1>
+ * <h2><a id="maxarity"></a>Arity limits</h2>
* The JVM imposes on all methods and constructors of any kind an absolute
* limit of 255 stacked arguments. This limit can appear more restrictive
* in certain cases:
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandleInfo.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleInfo.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -35,7 +35,7 @@
* A symbolic reference obtained by cracking a direct method handle
* into its consitutent symbolic parts.
* To crack a direct method handle, call {@link Lookup#revealDirect Lookup.revealDirect}.
- * <h1><a id="directmh"></a>Direct Method Handles</h1>
+ * <h2><a id="directmh"></a>Direct Method Handles</h2>
* A <em>direct method handle</em> represents a method, constructor, or field without
* any intervening argument bindings or other transformations.
* The method, constructor, or field referred to by a direct method handle is called
@@ -58,7 +58,7 @@
* to convert a {@link Field} into a method handle.
* </ul>
*
- * <h1>Restrictions on Cracking</h1>
+ * <h2>Restrictions on Cracking</h2>
* Given a suitable {@code Lookup} object, it is possible to crack any direct method handle
* to recover a symbolic reference for the underlying method, constructor, or field.
* Cracking must be done via a {@code Lookup} object equivalent to that which created
@@ -77,7 +77,7 @@
* handle with symbolic information (or caller binding) from an unexpected scope.
* Use {@link java.lang.invoke.MethodHandles#reflectAs} to override this limitation.
*
- * <h1><a id="refkinds"></a>Reference kinds</h1>
+ * <h2><a id="refkinds"></a>Reference kinds</h2>
* The <a href="MethodHandles.Lookup.html#lookups">Lookup Factory Methods</a>
* correspond to all major use cases for methods, constructors, and fields.
* These use cases may be distinguished using small integers as follows:
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -268,7 +268,7 @@
* This includes all methods, constructors, and fields which are allowed to the lookup class,
* even private ones.
*
- * <h1><a id="lookups"></a>Lookup Factory Methods</h1>
+ * <h2><a id="lookups"></a>Lookup Factory Methods</h2>
* The factory methods on a {@code Lookup} object correspond to all major
* use cases for methods, constructors, and fields.
* Each method handle created by a factory method is the functional
@@ -395,7 +395,7 @@
* <a href="MethodHandle.html#maxarity">too many parameters.</a>
* </ul>
*
- * <h1><a id="access"></a>Access checking</h1>
+ * <h2><a id="access"></a>Access checking</h2>
* Access checks are applied in the factory methods of {@code Lookup},
* when a method handle is created.
* This is a key difference from the Core Reflection API, since
@@ -529,7 +529,7 @@
* whose <a href="MethodHandles.Lookup.html#equiv">bytecode behaviors</a> and Java language access permissions
* can be reliably determined and emulated by method handles.
*
- * <h1><a id="secmgr"></a>Security manager interactions</h1>
+ * <h2><a id="secmgr"></a>Security manager interactions</h2>
* Although bytecode instructions can only refer to classes in
* a related class loader, this API can search for methods in any
* class, as long as a reference to its {@code Class} object is
@@ -588,7 +588,7 @@
* or else that is being accessed from a lookup class that has
* rights to access the member or class.
*
- * <h1><a id="callsens"></a>Caller sensitive methods</h1>
+ * <h2><a id="callsens"></a>Caller sensitive methods</h2>
* A small number of Java methods have a special property called caller sensitivity.
* A <em>caller-sensitive</em> method can behave differently depending on the
* identity of its immediate caller.
--- a/src/java.base/share/classes/java/lang/invoke/MutableCallSite.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/MutableCallSite.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -197,7 +197,7 @@
* processed before the method returns abnormally.
* Which elements these are (if any) is implementation-dependent.
*
- * <h1>Java Memory Model details</h1>
+ * <h4>Java Memory Model details</h4>
* In terms of the Java Memory Model, this operation performs a synchronization
* action which is comparable in effect to the writing of a volatile variable
* by the current thread, and an eventual volatile read by every other thread
--- a/src/java.base/share/classes/java/lang/invoke/VarHandle.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/VarHandle.java Thu Mar 21 18:04:01 2019 +0000
@@ -234,7 +234,7 @@
* precise phrasing of the specification of access mode methods and memory fence
* methods may accompany future updates of the Java Language Specification.
*
- * <h1>Compiling invocation of access mode methods</h1>
+ * <h2>Compiling invocation of access mode methods</h2>
* A Java method call expression naming an access mode method can invoke a
* VarHandle from Java source code. From the viewpoint of source code, these
* methods can take any arguments and their polymorphic result (if expressed)
@@ -266,7 +266,7 @@
* except the null reference.
*
*
- * <h1><a id="invoke">Performing invocation of access mode methods</a></h1>
+ * <h2><a id="invoke">Performing invocation of access mode methods</a></h2>
* The first time an {@code invokevirtual} instruction is executed it is linked
* by symbolically resolving the names in the instruction and verifying that
* the method call is statically legal. This also holds for calls to access mode
@@ -329,7 +329,7 @@
* Where, in this case, the method handle is bound to the VarHandle instance.
*
*
- * <h1>Invocation checking</h1>
+ * <h2>Invocation checking</h2>
* In typical programs, VarHandle access mode type matching will usually
* succeed. But if a match fails, the JVM will throw a
* {@link WrongMethodTypeException}.
@@ -364,7 +364,7 @@
* untrusted code unless their use from the untrusted code would be harmless.
*
*
- * <h1>VarHandle creation</h1>
+ * <h2>VarHandle creation</h2>
* Java code can create a VarHandle that directly accesses any field that is
* accessible to that code. This is done via a reflective, capability-based
* API called {@link java.lang.invoke.MethodHandles.Lookup
@@ -383,7 +383,7 @@
* class outside the current package, the receiver argument will be narrowed to
* the type of the accessing class.
*
- * <h1>Interoperation between VarHandles and the Core Reflection API</h1>
+ * <h2>Interoperation between VarHandles and the Core Reflection API</h2>
* Using factory methods in the {@link java.lang.invoke.MethodHandles.Lookup
* Lookup} API, any field represented by a Core Reflection API object
* can be converted to a behaviorally equivalent VarHandle.
@@ -428,7 +428,7 @@
* any specified access mode type and is equivalent in behaviour to
* {@link java.lang.invoke.MethodHandles#varHandleInvoker}.
*
- * <h1>Interoperation between VarHandles and Java generics</h1>
+ * <h2>Interoperation between VarHandles and Java generics</h2>
* A VarHandle can be obtained for a variable, such as a field, which is
* declared with Java generic types. As with the Core Reflection API, the
* VarHandle's variable type will be constructed from the erasure of the
--- a/src/java.base/share/classes/java/lang/invoke/package-info.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/package-info.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -53,12 +53,12 @@
* </li>
* </ul>
*
- * <h1><a id="jvm_mods"></a>Dynamic resolution of call sites and constants</h1>
+ * <h2><a id="jvm_mods"></a>Dynamic resolution of call sites and constants</h2>
* The following low-level information summarizes relevant parts of the
* Java Virtual Machine specification. For full details, please see the
* current version of that specification.
*
- * <h2><a id="indyinsn"></a>Dynamically-computed call sites</h2>
+ * <h3><a id="indyinsn"></a>Dynamically-computed call sites</h3>
* An {@code invokedynamic} instruction is originally in an unlinked state.
* In this state, there is no target method for the instruction to invoke.
* <p>
@@ -74,7 +74,7 @@
* The constant pool reference also specifies the invocation's name and method type descriptor,
* just like {@code invokestatic} and the other invoke instructions.
*
- * <h2><a id="condycon"></a>Dynamically-computed constants</h2>
+ * <h3><a id="condycon"></a>Dynamically-computed constants</h3>
* The constant pool may contain constants tagged {@code CONSTANT_Dynamic},
* equipped with bootstrap methods which perform their resolution.
* Such a <em>dynamic constant</em> is originally in an unresolved state.
@@ -90,7 +90,7 @@
* (Roughly speaking, a dynamically-computed constant is to a dynamically-computed call site
* as a {@code CONSTANT_Fieldref} is to a {@code CONSTANT_Methodref}.)
*
- * <h2><a id="bsm"></a>Execution of bootstrap methods</h2>
+ * <h3><a id="bsm"></a>Execution of bootstrap methods</h3>
* Resolving a dynamically-computed call site or constant
* starts with resolving constants from the constant pool for the
* following items:
@@ -136,7 +136,7 @@
* subsequent attempts to execute the {@code invokedynamic} instruction or load the
* dynamically-computed constant.
*
- * <h2>Timing of resolution</h2>
+ * <h3>Timing of resolution</h3>
* An {@code invokedynamic} instruction is linked just before its first execution.
* A dynamically-computed constant is resolved just before the first time it is used
* (by pushing it on the stack or linking it as a bootstrap method parameter).
@@ -171,7 +171,7 @@
* just before its first invocation.
* There is no way to undo the effect of a completed bootstrap method call.
*
- * <h2>Types of bootstrap methods</h2>
+ * <h3>Types of bootstrap methods</h3>
* For a dynamically-computed call site, the bootstrap method is invoked with parameter
* types {@code MethodHandles.Lookup}, {@code String}, {@code MethodType}, and the types
* of any static arguments; the return type is {@code CallSite}.
--- a/src/java.base/share/classes/java/lang/module/Configuration.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/lang/module/Configuration.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -75,7 +75,7 @@
* ModuleLayer.boot().configuration()}. The configuration for the boot layer
* will often be the parent when creating new configurations. </p>
*
- * <h3> Example </h3>
+ * <h2> Example </h2>
*
* <p> The following example uses the {@link
* #resolve(ModuleFinder,ModuleFinder,Collection) resolve} method to resolve a
--- a/src/java.base/share/classes/java/lang/module/package-info.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/lang/module/package-info.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -34,7 +34,7 @@
* will cause a {@code NullPointerException}, unless otherwise specified. </p>
*
*
- * <h1><a id="resolution"></a>{@index "Module Resolution"}</h1>
+ * <h2><a id="resolution"></a>{@index "Module Resolution"}</h2>
*
* <p> Resolution is the process of computing how modules depend on each other.
* The process occurs at compile time and run time. </p>
@@ -45,7 +45,7 @@
* The readability graph embodies how modules depend on each other, which in
* turn controls access across module boundaries. </p>
*
- * <h2> Step 1: Recursive enumeration </h2>
+ * <h3> Step 1: Recursive enumeration </h3>
*
* <p> Recursive enumeration takes a set of module names, looks up each of their
* module declarations, and for each module declaration, recursively enumerates:
@@ -91,7 +91,7 @@
*
* <p> Otherwise, resolution proceeds to step 2. </p>
*
- * <h2> Step 2: Computing the readability graph </h2>
+ * <h3> Step 2: Computing the readability graph </h3>
*
* <p> A 'requires' directive (irrespective of 'transitive') expresses that
* one module depends on some other module. The effect of the 'transitive'
@@ -147,7 +147,7 @@
* <p> Otherwise, resolution succeeds, and the result of resolution is the
* readability graph.
*
- * <h2> Root modules </h2>
+ * <h3> Root modules </h3>
*
* <p> The set of root modules at compile-time is usually the set of modules
* being compiled. At run-time, the set of root modules is usually the
@@ -158,7 +158,7 @@
* that is observable on the upgrade module path or among the system modules,
* and that exports at least one package without qualification. </p>
*
- * <h2> Observable modules </h2>
+ * <h3> Observable modules </h3>
*
* <p> The set of observable modules at both compile-time and run-time is
* determined by searching several different paths, and also by searching
@@ -183,7 +183,7 @@
*
* </ol>
*
- * <h2> 'requires' directives with 'static' modifier </h2>
+ * <h3> 'requires' directives with 'static' modifier </h3>
*
* <p> 'requires' directives that have the 'static' modifier express an optional
* dependence at run time. If a module declares that it 'requires static M' then
@@ -191,7 +191,7 @@
* However, if M is recursively enumerated at step 1 then all modules that are
* enumerated and `requires static M` will read M. </p>
*
- * <h2> Completeness </h2>
+ * <h3> Completeness </h3>
*
* <p> Resolution may be partial at compile-time in that the complete transitive
* closure may not be required to compile a set of modules. Minimally, the
--- a/src/java.base/share/classes/java/lang/reflect/Proxy.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/lang/reflect/Proxy.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -156,7 +156,7 @@
* like they do for instances of {@code java.lang.Object}.
* </ul>
*
- * <h3><a id="membership">Package and Module Membership of Proxy Class</a></h3>
+ * <h2><a id="membership">Package and Module Membership of Proxy Class</a></h2>
*
* The package and module to which a proxy class belongs are chosen such that
* the accessibility of the proxy class is in line with the accessibility of
--- a/src/java.base/share/classes/java/net/ContentHandler.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/net/ContentHandler.java Thu Mar 21 18:04:01 2019 +0000
@@ -47,7 +47,7 @@
* If no content handler could be {@linkplain URLConnection#getContent() found},
* URLConnection will look for a content handler in a user-definable set of places.
* Users can define a vertical-bar delimited set of class prefixes
- * to search through by defining the <i>{@link java.net.URLConnection#contentPathProp}</i>
+ * to search through by defining the <i>{@value java.net.URLConnection#contentPathProp}</i>
* property. The class name must be of the form:
* <blockquote>
* <i>{package-prefix}.{major}.{minor}</i>
--- a/src/java.base/share/classes/java/net/HttpConnectSocketImpl.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/net/HttpConnectSocketImpl.java Thu Mar 21 18:04:01 2019 +0000
@@ -114,14 +114,17 @@
if (endpoint == null || !(endpoint instanceof InetSocketAddress))
throw new IllegalArgumentException("Unsupported address type");
final InetSocketAddress epoint = (InetSocketAddress)endpoint;
- final String destHost = epoint.isUnresolved() ? epoint.getHostName()
- : epoint.getAddress().getHostAddress();
+ String destHost = epoint.isUnresolved() ? epoint.getHostName()
+ : epoint.getAddress().getHostAddress();
final int destPort = epoint.getPort();
SecurityManager security = System.getSecurityManager();
if (security != null)
security.checkConnect(destHost, destPort);
+ if (destHost.contains(":"))
+ destHost = "[" + destHost + "]";
+
// Connect to the HTTP proxy server
String urlString = "http://" + destHost + ":" + destPort;
Socket httpSocket = privilegedDoTunnel(urlString, timeout);
--- a/src/java.base/share/classes/java/net/Inet4Address.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/net/Inet4Address.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -36,7 +36,7 @@
* and <a href="http://www.ietf.org/rfc/rfc2365.txt"><i>RFC 2365:
* Administratively Scoped IP Multicast</i></a>
*
- * <h3> <a id="format">Textual representation of IP addresses</a> </h3>
+ * <h2> <a id="format">Textual representation of IP addresses</a> </h2>
*
* Textual representation of IPv4 address used as input to methods
* takes one of the following forms:
@@ -70,7 +70,7 @@
* <p> For methods that return a textual representation as output
* value, the first form, i.e. a dotted-quad string, is used.
*
- * <h4> The Scope of a Multicast Address </h4>
+ * <h3> The Scope of a Multicast Address </h3>
*
* Historically the IPv4 TTL field in the IP header has doubled as a
* multicast scope field: a TTL of 0 means node-local, 1 means
--- a/src/java.base/share/classes/java/net/Inet6Address.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/net/Inet6Address.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -38,7 +38,7 @@
* Defined by <a href="http://www.ietf.org/rfc/rfc2373.txt">
* <i>RFC 2373: IP Version 6 Addressing Architecture</i></a>.
*
- * <h3> <a id="format">Textual representation of IP addresses</a> </h3>
+ * <h2> <a id="format">Textual representation of IP addresses</a> </h2>
*
* Textual representation of IPv6 address used as input to methods
* takes one of the following forms:
@@ -116,7 +116,7 @@
* form because it is unambiguous when used in combination with other
* textual data.
*
- * <h4> Special IPv6 address </h4>
+ * <h3> Special IPv6 address </h3>
*
* <blockquote>
* <table class="borderless">
@@ -135,7 +135,7 @@
* address.</td></tr>
* </table></blockquote>
*
- * <h4><a id="scoped">Textual representation of IPv6 scoped addresses</a></h4>
+ * <h3><a id="scoped">Textual representation of IPv6 scoped addresses</a></h3>
*
* <p> The textual representation of IPv6 addresses as described above can be
* extended to specify IPv6 scoped addresses. This extension to the basic
--- a/src/java.base/share/classes/java/net/InetAddress.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/net/InetAddress.java Thu Mar 21 18:04:01 2019 +0000
@@ -71,7 +71,7 @@
* with a host name or whether it has already done reverse host name
* resolution).
*
- * <h3> Address types </h3>
+ * <h2> Address types </h2>
*
* <table class="striped" style="margin-left:2em">
* <caption style="display:none">Description of unicast and multicast address types</caption>
@@ -105,7 +105,7 @@
* </tbody>
* </table>
*
- * <h4> IP address scope </h4>
+ * <h3> IP address scope </h3>
*
* <p> <i>Link-local</i> addresses are designed to be used for addressing
* on a single link for purposes such as auto-address configuration,
@@ -116,7 +116,7 @@
*
* <p> <i>Global</i> addresses are unique across the internet.
*
- * <h4> Textual representation of IP addresses </h4>
+ * <h3> Textual representation of IP addresses </h3>
*
* The textual representation of an IP address is address family specific.
*
@@ -130,7 +130,7 @@
* <P>There is a <a href="doc-files/net-properties.html#Ipv4IPv6">couple of
* System Properties</a> affecting how IPv4 and IPv6 addresses are used.</P>
*
- * <h4> Host Name Resolution </h4>
+ * <h3> Host Name Resolution </h3>
*
* Host name-to-IP address <i>resolution</i> is accomplished through
* the use of a combination of local machine configuration information
@@ -145,7 +145,7 @@
* <p> The InetAddress class provides methods to resolve host names to
* their IP addresses and vice versa.
*
- * <h4> InetAddress Caching </h4>
+ * <h3> InetAddress Caching </h3>
*
* The InetAddress class has a cache to store successful as well as
* unsuccessful host name resolutions.
--- a/src/java.base/share/classes/java/net/NetPermission.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/net/NetPermission.java Thu Mar 21 18:04:01 2019 +0000
@@ -43,7 +43,7 @@
* signify a wildcard match. For example: "foo.*" and "*" signify a wildcard
* match, while "*foo" and "a*b" do not.
* <P>
- * The following table lists all the possible NetPermission target names,
+ * The following table lists the standard NetPermission target names,
* and for each provides a description of what the permission allows
* and a discussion of the risks of granting code the permission.
*
@@ -158,6 +158,10 @@
</tbody>
* </table>
*
+ * @implNote
+ * Implementations may define additional target names, but should use naming
+ * conventions such as reverse domain name notation to avoid name clashes.
+ *
* @see java.security.BasicPermission
* @see java.security.Permission
* @see java.security.Permissions
--- a/src/java.base/share/classes/java/net/URI.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/net/URI.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -64,7 +64,7 @@
* and relativizing URI instances. Instances of this class are immutable.
*
*
- * <h3> URI syntax and components </h3>
+ * <h2> URI syntax and components </h2>
*
* At the highest level a URI reference (hereinafter simply "URI") in string
* form has the syntax
@@ -168,7 +168,7 @@
* will be defined and the user-information and port components may be defined.
*
*
- * <h4> Operations on URI instances </h4>
+ * <h3> Operations on URI instances </h3>
*
* The key operations supported by this class are those of
* <i>normalization</i>, <i>resolution</i>, and <i>relativization</i>.
@@ -247,7 +247,7 @@
* yields the relative URI {@code sample/a/index.html#28}.
*
*
- * <h4> Character categories </h4>
+ * <h3> Character categories </h3>
*
* RFC 2396 specifies precisely which characters are permitted in the
* various components of a URI reference. The following categories, most of
@@ -298,7 +298,7 @@
* characters.
*
*
- * <h4> Escaped octets, quotation, encoding, and decoding </h4>
+ * <h3> Escaped octets, quotation, encoding, and decoding </h3>
*
* RFC 2396 allows escaped octets to appear in the user-info, path, query, and
* fragment components. Escaping serves two purposes in URIs:
@@ -390,7 +390,7 @@
* </ul>
*
*
- * <h4> Identities </h4>
+ * <h3> Identities </h3>
*
* For any URI <i>u</i>, it is always the case that
*
@@ -426,7 +426,7 @@
* authority.
*
*
- * <h4> URIs, URLs, and URNs </h4>
+ * <h3> URIs, URLs, and URNs </h3>
*
* A URI is a uniform resource <i>identifier</i> while a URL is a uniform
* resource <i>locator</i>. Hence every URL is a URI, abstractly speaking, but
--- a/src/java.base/share/classes/java/text/ChoiceFormat.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/text/ChoiceFormat.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -151,7 +151,7 @@
* }</pre>
* </blockquote>
*
- * <h3><a id="synchronization">Synchronization</a></h3>
+ * <h2><a id="synchronization">Synchronization</a></h2>
*
* <p>
* Choice formats are not synchronized.
--- a/src/java.base/share/classes/java/text/CompactNumberFormat.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/text/CompactNumberFormat.java Thu Mar 21 18:04:01 2019 +0000
@@ -73,7 +73,7 @@
* String result = fmt.format(1000);
* </pre></blockquote>
*
- * <h3><a id="compact_number_style">Style</a></h3>
+ * <h2><a id="compact_number_style">Style</a></h2>
* <p>
* A number can be formatted in the compact forms with two different
* styles, {@link NumberFormat.Style#SHORT SHORT}
@@ -88,7 +88,7 @@
* {@link NumberFormat.Style#LONG LONG} style instance in same locale
* formats {@code 10000} as {@code "10 thousand"}.
*
- * <h3><a id="compact_number_patterns">Compact Number Patterns</a></h3>
+ * <h2><a id="compact_number_patterns">Compact Number Patterns</a></h2>
* <p>
* The compact number patterns are represented in a series of patterns where each
* pattern is used to format a range of numbers. An example of
@@ -151,7 +151,7 @@
* unless noted otherwise, if they are to appear in the prefix or suffix
* as literals. For example, 0\u0915'.'.
*
- * <h3>Formatting</h3>
+ * <h2>Formatting</h2>
* The default formatting behavior returns a formatted string with no fractional
* digits, however users can use the {@link #setMinimumFractionDigits(int)}
* method to include the fractional part.
@@ -165,14 +165,14 @@
* {@link java.text.DecimalFormat DecimalFormat}
* for the specified locale is used.
*
- * <h3>Parsing</h3>
+ * <h2>Parsing</h2>
* The default parsing behavior does not allow a grouping separator until
* grouping used is set to {@code true} by using
* {@link #setGroupingUsed(boolean)}. The parsing of the fractional part
* depends on the {@link #isParseIntegerOnly()}. For example, if the
* parse integer only is set to true, then the fractional part is skipped.
*
- * <h3>Rounding</h3>
+ * <h2>Rounding</h2>
* {@code CompactNumberFormat} provides rounding modes defined in
* {@link java.math.RoundingMode} for formatting. By default, it uses
* {@link java.math.RoundingMode#HALF_EVEN RoundingMode.HALF_EVEN}.
--- a/src/java.base/share/classes/java/text/DateFormat.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/text/DateFormat.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -140,7 +140,7 @@
* on the screen.
* </ul>
*
- * <h3><a id="synchronization">Synchronization</a></h3>
+ * <h2><a id="synchronization">Synchronization</a></h2>
*
* <p>
* Date formats are not synchronized.
--- a/src/java.base/share/classes/java/text/DecimalFormat.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/text/DecimalFormat.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -84,7 +84,7 @@
* the <code>NumberFormat</code> factory methods, the pattern and symbols are
* read from localized <code>ResourceBundle</code>s.
*
- * <h3>Patterns</h3>
+ * <h2>Patterns</h2>
*
* <code>DecimalFormat</code> patterns have the following syntax:
* <blockquote><pre>
@@ -154,7 +154,7 @@
* used. So <code>"#,##,###,####"</code> == <code>"######,####"</code> ==
* <code>"##,####,####"</code>.
*
- * <h4><a id="special_pattern_character">Special Pattern Characters</a></h4>
+ * <h3><a id="special_pattern_character">Special Pattern Characters</a></h3>
*
* <p>Many characters in a pattern are taken literally; they are matched during
* parsing and output unchanged during formatting. Special characters, on the
@@ -245,7 +245,7 @@
* </table>
* </blockquote>
*
- * <h4>Scientific Notation</h4>
+ * <h3>Scientific Notation</h3>
*
* <p>Numbers in scientific notation are expressed as the product of a mantissa
* and a power of ten, for example, 1234 can be expressed as 1.234 x 10^3. The
@@ -292,13 +292,13 @@
* <li>Exponential patterns may not contain grouping separators.
* </ul>
*
- * <h4>Rounding</h4>
+ * <h3>Rounding</h3>
*
* <code>DecimalFormat</code> provides rounding modes defined in
* {@link java.math.RoundingMode} for formatting. By default, it uses
* {@link java.math.RoundingMode#HALF_EVEN RoundingMode.HALF_EVEN}.
*
- * <h4>Digits</h4>
+ * <h3>Digits</h3>
*
* For formatting, <code>DecimalFormat</code> uses the ten consecutive
* characters starting with the localized zero digit defined in the
@@ -328,7 +328,7 @@
* and <code>isParseIntegerOnly()</code> are false.
* </ul>
*
- * <h4><a id="synchronization">Synchronization</a></h4>
+ * <h3><a id="synchronization">Synchronization</a></h3>
*
* <p>
* Decimal formats are generally not synchronized.
@@ -336,7 +336,7 @@
* If multiple threads access a format concurrently, it must be synchronized
* externally.
*
- * <h4>Example</h4>
+ * <h3>Example</h3>
*
* <blockquote><pre>{@code
* <strong>// Print out a number using the localized number, integer, currency,
--- a/src/java.base/share/classes/java/text/Format.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/text/Format.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -58,7 +58,7 @@
* no separator in between, and in this case the <code>parseObject</code> could
* not tell which digits belong to which number.
*
- * <h3>Subclassing</h3>
+ * <h2>Subclassing</h2>
*
* <p>
* The Java Platform provides three specialized subclasses of <code>Format</code>--
@@ -115,7 +115,7 @@
* the field. For examples of these constants, see <code>ERA_FIELD</code> and its
* friends in {@link DateFormat}.
*
- * <h4><a id="synchronization">Synchronization</a></h4>
+ * <h3><a id="synchronization">Synchronization</a></h3>
*
* <p>
* Formats are generally not synchronized.
--- a/src/java.base/share/classes/java/text/MessageFormat.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/text/MessageFormat.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -68,7 +68,7 @@
* behavior is defined by the pattern that you provide as well as the
* subformats used for inserted arguments.
*
- * <h3><a id="patterns">Patterns and Their Interpretation</a></h3>
+ * <h2><a id="patterns">Patterns and Their Interpretation</a></h2>
*
* <code>MessageFormat</code> uses patterns of the following form:
* <blockquote><pre>
@@ -220,7 +220,7 @@
* </tbody>
* </table>
*
- * <h4>Usage Information</h4>
+ * <h3>Usage Information</h3>
*
* <p>
* Here are some examples of usage.
@@ -326,7 +326,7 @@
* // result now equals {new String("z")}
* </pre></blockquote>
*
- * <h4><a id="synchronization">Synchronization</a></h4>
+ * <h3><a id="synchronization">Synchronization</a></h3>
*
* <p>
* Message formats are not synchronized.
--- a/src/java.base/share/classes/java/text/NumberFormat.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/text/NumberFormat.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -175,7 +175,7 @@
* numbers: "(12)" for -12.
* </ol>
*
- * <h3><a id="synchronization">Synchronization</a></h3>
+ * <h2><a id="synchronization">Synchronization</a></h2>
*
* <p>
* Number formats are generally not synchronized.
--- a/src/java.base/share/classes/java/text/SimpleDateFormat.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/text/SimpleDateFormat.java Thu Mar 21 18:04:01 2019 +0000
@@ -74,7 +74,7 @@
* For more information on using these methods, see
* {@link DateFormat}.
*
- * <h3>Date and Time Patterns</h3>
+ * <h2>Date and Time Patterns</h2>
* <p>
* Date and time formats are specified by <em>date and time pattern</em>
* strings.
@@ -370,7 +370,7 @@
* <code>SimpleDateFormat</code> does not deal with the localization of text
* other than the pattern letters; that's up to the client of the class.
*
- * <h4>Examples</h4>
+ * <h3>Examples</h3>
*
* The following examples show how date and time patterns are interpreted in
* the U.S. locale. The given date and time are 2001-07-04 12:08:56 local time
@@ -421,7 +421,7 @@
* </table>
* </blockquote>
*
- * <h4><a id="synchronization">Synchronization</a></h4>
+ * <h3><a id="synchronization">Synchronization</a></h3>
*
* <p>
* Date formats are not synchronized.
--- a/src/java.base/share/classes/java/time/Instant.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/time/Instant.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -108,7 +108,7 @@
* For both the epoch-second and nanosecond parts, a larger value is always later on the time-line
* than a smaller value.
*
- * <h3>Time-scale</h3>
+ * <h2>Time-scale</h2>
* <p>
* The length of the solar day is the standard way that humans measure time.
* This has traditionally been subdivided into 24 hours of 60 minutes of 60 seconds,
--- a/src/java.base/share/classes/java/time/ZoneId.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/time/ZoneId.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -111,7 +111,7 @@
* Similarly, a comparison of two IDs only examines the ID, whereas
* a comparison of two rules examines the entire data set.
*
- * <h3>Time-zone IDs</h3>
+ * <h2>Time-zone IDs</h2>
* The ID is unique within the system.
* There are three types of ID.
* <p>
@@ -147,7 +147,7 @@
* The recommended format for region IDs from groups other than TZDB is 'group~region'.
* Thus if IATA data were defined, Utrecht airport would be 'IATA~UTC'.
*
- * <h3>Serialization</h3>
+ * <h2>Serialization</h2>
* This class can be serialized and stores the string zone ID in the external form.
* The {@code ZoneOffset} subclass uses a dedicated format that only stores the
* offset from UTC/Greenwich.
--- a/src/java.base/share/classes/java/time/chrono/ChronoLocalDate.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/time/chrono/ChronoLocalDate.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -99,7 +99,7 @@
* The chronology defines how the calendar system operates and the meaning of
* the standard fields.
*
- * <h3>When to use this interface</h3>
+ * <h2>When to use this interface</h2>
* The design of the API encourages the use of {@code LocalDate} rather than this
* interface, even in the case where the application needs to deal with multiple
* calendar systems.
--- a/src/java.base/share/classes/java/time/chrono/ChronoLocalDateImpl.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/time/chrono/ChronoLocalDateImpl.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -121,7 +121,7 @@
* first, last);
* </pre>
*
- * <h3>Adding Calendars</h3>
+ * <h2>Adding Calendars</h2>
* <p> The set of calendars is extensible by defining a subclass of {@link ChronoLocalDate}
* to represent a date instance and an implementation of {@code Chronology}
* to be the factory for the ChronoLocalDate subclass.
--- a/src/java.base/share/classes/java/time/chrono/ChronoLocalDateTime.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/time/chrono/ChronoLocalDateTime.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -102,7 +102,7 @@
* The chronology defines how the calendar system operates and the meaning of
* the standard fields.
*
- * <h3>When to use this interface</h3>
+ * <h2>When to use this interface</h2>
* The design of the API encourages the use of {@code LocalDateTime} rather than this
* interface, even in the case where the application needs to deal with multiple
* calendar systems. The rationale for this is explored in detail in {@link ChronoLocalDate}.
--- a/src/java.base/share/classes/java/time/chrono/ChronoZonedDateTime.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/time/chrono/ChronoZonedDateTime.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -103,7 +103,7 @@
* The chronology defines how the calendar system operates and the meaning of
* the standard fields.
*
- * <h3>When to use this interface</h3>
+ * <h2>When to use this interface</h2>
* The design of the API encourages the use of {@code ZonedDateTime} rather than this
* interface, even in the case where the application needs to deal with multiple
* calendar systems. The rationale for this is explored in detail in {@link ChronoLocalDate}.
--- a/src/java.base/share/classes/java/time/chrono/Chronology.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/time/chrono/Chronology.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -133,7 +133,7 @@
* <li> {@link #date(TemporalAccessor) date(TemporalAccessor)}
* </ul>
*
- * <h3 id="addcalendars">Adding New Calendars</h3>
+ * <h2 id="addcalendars">Adding New Calendars</h2>
* The set of available chronologies can be extended by applications.
* Adding a new calendar system requires the writing of an implementation of
* {@code Chronology}, {@code ChronoLocalDate} and {@code Era}.
--- a/src/java.base/share/classes/java/time/format/DateTimeFormatter.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/time/format/DateTimeFormatter.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -150,7 +150,7 @@
* class for formatting. The {@link #toFormat()} method returns an
* implementation of {@code java.text.Format}.
*
- * <h3 id="predefined">Predefined Formatters</h3>
+ * <h2 id="predefined">Predefined Formatters</h2>
* <table class="striped" style="text-align:left">
* <caption>Predefined Formatters</caption>
* <thead>
@@ -258,7 +258,7 @@
* </tbody>
* </table>
*
- * <h3 id="patterns">Patterns for Formatting and Parsing</h3>
+ * <h2 id="patterns">Patterns for Formatting and Parsing</h2>
* Patterns are based on a simple sequence of letters and symbols.
* A pattern is used to create a Formatter using the
* {@link #ofPattern(String)} and {@link #ofPattern(String, Locale)} methods.
@@ -434,7 +434,7 @@
* that you want to output directly to ensure that future changes do not break
* your application.
*
- * <h3 id="resolving">Resolving</h3>
+ * <h2 id="resolving">Resolving</h2>
* Parsing is implemented as a two-phase operation.
* First, the text is parsed using the layout defined by the formatter, producing
* a {@code Map} of field to value, a {@code ZoneId} and a {@code Chronology}.
--- a/src/java.base/share/classes/java/time/temporal/IsoFields.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/time/temporal/IsoFields.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -91,7 +91,7 @@
* <p>
* This class defines fields and units that are specific to the ISO calendar system.
*
- * <h3>Quarter of year</h3>
+ * <h2>Quarter of year</h2>
* The ISO-8601 standard is based on the standard civic 12 month year.
* This is commonly divided into four quarters, often abbreviated as Q1, Q2, Q3 and Q4.
* <p>
@@ -107,7 +107,7 @@
* <li>{@link ChronoField#YEAR YEAR} - the standard ISO year
* </ul>
*
- * <h3>Week based years</h3>
+ * <h2>Week based years</h2>
* The ISO-8601 standard was originally intended as a data interchange format,
* defining a string format for dates and times. However, it also defines an
* alternate way of expressing the date, based on the concept of week-based-year.
--- a/src/java.base/share/classes/java/time/temporal/JulianFields.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/time/temporal/JulianFields.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -115,7 +115,7 @@
* the Julian Day value is validated against the range of valid values.
* In {@linkplain ResolverStyle#LENIENT lenient mode} no validation occurs.
*
- * <h3>Astronomical and Scientific Notes</h3>
+ * <h4>Astronomical and Scientific Notes</h4>
* The standard astronomical definition uses a fraction to indicate the time-of-day,
* where each day is counted from midday to midday. For example,
* a fraction of 0 represents midday, a fraction of 0.25
@@ -169,7 +169,7 @@
* the Modified Julian Day value is validated against the range of valid values.
* In {@linkplain ResolverStyle#LENIENT lenient mode} no validation occurs.
*
- * <h3>Astronomical and Scientific Notes</h3>
+ * <h4>Astronomical and Scientific Notes</h4>
* <pre>
* | ISO date | Modified Julian Day | Decimal MJD |
* | 1970-01-01T00:00 | 40,587 | 40,587.0 |
--- a/src/java.base/share/classes/java/time/temporal/Temporal.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/time/temporal/Temporal.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -92,7 +92,7 @@
* of this interface may be in calendar systems other than ISO.
* See {@link java.time.chrono.ChronoLocalDate} for a fuller discussion of the issues.
*
- * <h3>When to implement</h3>
+ * <h2>When to implement</h2>
* <p>
* A class should implement this interface if it meets three criteria:
* <ul>
--- a/src/java.base/share/classes/java/time/temporal/WeekFields.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/time/temporal/WeekFields.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -120,7 +120,7 @@
* </ul>
* Together these two values allow a year or month to be divided into weeks.
*
- * <h3>Week of Month</h3>
+ * <h2>Week of Month</h2>
* One field is used: week-of-month.
* The calculation ensures that weeks never overlap a month boundary.
* The month is divided into periods where each period starts on the defined first day-of-week.
@@ -145,14 +145,14 @@
* </tbody>
* </table>
*
- * <h3>Week of Year</h3>
+ * <h2>Week of Year</h2>
* One field is used: week-of-year.
* The calculation ensures that weeks never overlap a year boundary.
* The year is divided into periods where each period starts on the defined first day-of-week.
* The earliest period is referred to as week 0 if it has less than the minimal number of days
* and week 1 if it has at least the minimal number of days.
*
- * <h3>Week Based Year</h3>
+ * <h2>Week Based Year</h2>
* Two fields are used for week-based-year, one for the
* {@link #weekOfWeekBasedYear() week-of-week-based-year} and one for
* {@link #weekBasedYear() week-based-year}. In a week-based-year, each week
--- a/src/java.base/share/classes/java/util/Calendar.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/util/Calendar.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -97,7 +97,7 @@
* concrete subclass, such as <code>ERA</code>. See individual field
* documentation and subclass documentation for details.
*
- * <h3>Getting and Setting Calendar Field Values</h3>
+ * <h2>Getting and Setting Calendar Field Values</h2>
*
* <p>The calendar field values can be set by calling the <code>set</code>
* methods. Any field values set in a <code>Calendar</code> will not be
@@ -106,7 +106,7 @@
* <code>get</code>, <code>getTimeInMillis</code>, <code>getTime</code>,
* <code>add</code> and <code>roll</code> involves such calculation.
*
- * <h4>Leniency</h4>
+ * <h3>Leniency</h3>
*
* <p><code>Calendar</code> has two modes for interpreting the calendar
* fields, <em>lenient</em> and <em>non-lenient</em>. When a
@@ -125,7 +125,7 @@
* calculating its time or calendar field values if any out-of-range field
* value has been set.
*
- * <h4><a id="first_week">First Week</a></h4>
+ * <h3><a id="first_week">First Week</a></h3>
*
* <code>Calendar</code> defines a locale-specific seven day week using two
* parameters: the first day of the week and the minimal days in first week
@@ -150,7 +150,7 @@
* designate the week before week 1 of a year as week <code><i>n</i></code> of
* the previous year.
*
- * <h4>Calendar Fields Resolution</h4>
+ * <h3>Calendar Fields Resolution</h3>
*
* When computing a date and time from the calendar fields, there
* may be insufficient information for the computation (such as only
@@ -210,7 +210,7 @@
* runtime. Use {@link DateFormat}
* to format dates.
*
- * <h4>Field Manipulation</h4>
+ * <h3>Field Manipulation</h3>
*
* The calendar fields can be changed using three methods:
* <code>set()</code>, <code>add()</code>, and <code>roll()</code>.
--- a/src/java.base/share/classes/java/util/Formatter.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/util/Formatter.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -140,7 +140,7 @@
* // -> s == "Duke's Birthday: May 23, 1995"
* </pre></blockquote>
*
- * <h3><a id="org">Organization</a></h3>
+ * <h2><a id="org">Organization</a></h2>
*
* <p> This specification is divided into two sections. The first section, <a
* href="#summary">Summary</a>, covers the basic formatting concepts. This
@@ -150,13 +150,13 @@
* details. It is intended for users who want more precise specification of
* formatting behavior.
*
- * <h3><a id="summary">Summary</a></h3>
+ * <h2><a id="summary">Summary</a></h2>
*
* <p> This section is intended to provide a brief overview of formatting
* concepts. For precise behavioral details, refer to the <a
* href="#detail">Details</a> section.
*
- * <h4><a id="syntax">Format String Syntax</a></h4>
+ * <h3><a id="syntax">Format String Syntax</a></h3>
*
* <p> Every method which produces formatted output requires a <i>format
* string</i> and an <i>argument list</i>. The format string is a {@link
@@ -236,7 +236,7 @@
*
* </ul>
*
- * <h4> Conversions </h4>
+ * <h3> Conversions </h3>
*
* <p> Conversions are divided into the following categories:
*
@@ -376,7 +376,7 @@
* <p> Any characters not explicitly defined as conversions are illegal and are
* reserved for future extensions.
*
- * <h4><a id="dt">Date/Time Conversions</a></h4>
+ * <h3><a id="dt">Date/Time Conversions</a></h3>
*
* <p> The following date and time conversion suffix characters are defined for
* the {@code 't'} and {@code 'T'} conversions. The types are similar to but
@@ -550,7 +550,7 @@
* <p> Any characters not explicitly defined as date/time conversion suffixes
* are illegal and are reserved for future extensions.
*
- * <h4> Flags </h4>
+ * <h3> Flags </h3>
*
* <p> The following table summarizes the supported flags. <i>y</i> means the
* flag is supported for the indicated argument types.
@@ -636,13 +636,13 @@
* <p> Any characters not explicitly defined as flags are illegal and are
* reserved for future extensions.
*
- * <h4> Width </h4>
+ * <h3> Width </h3>
*
* <p> The width is the minimum number of characters to be written to the
* output. For the line separator conversion, width is not applicable; if it
* is provided, an exception will be thrown.
*
- * <h4> Precision </h4>
+ * <h3> Precision </h3>
*
* <p> For general argument types, the precision is the maximum number of
* characters to be written to the output.
@@ -657,7 +657,7 @@
* and line separator conversions, the precision is not applicable; if a
* precision is provided, an exception will be thrown.
*
- * <h4> Argument Index </h4>
+ * <h3> Argument Index </h3>
*
* <p> The argument index is a decimal integer indicating the position of the
* argument in the argument list. The first argument is referenced by
@@ -676,7 +676,7 @@
* </pre></blockquote>
*
* <hr>
- * <h3><a id="detail">Details</a></h3>
+ * <h2><a id="detail">Details</a></h2>
*
* <p> This section is intended to provide behavioral details for formatting,
* including conditions and exceptions, supported data types, localization, and
@@ -717,7 +717,7 @@
* invocation, then the {@link java.util.Locale.Category#FORMAT default locale}
* is used.
*
- * <h4><a id="dgen">General</a></h4>
+ * <h3><a id="dgen">General</a></h3>
*
* <p> The following general conversions may be applied to any argument type:
*
@@ -814,7 +814,7 @@
* the precision. If the precision is not specified then there is no explicit
* limit on the number of characters.
*
- * <h4><a id="dchar">Character</a></h4>
+ * <h3><a id="dchar">Character</a></h3>
*
* This conversion may be applied to {@code char} and {@link Character}. It
* may also be applied to the types {@code byte}, {@link Byte},
@@ -853,7 +853,7 @@
* <p> The precision is not applicable. If the precision is specified then an
* {@link IllegalFormatPrecisionException} will be thrown.
*
- * <h4><a id="dnum">Numeric</a></h4>
+ * <h3><a id="dnum">Numeric</a></h3>
*
* <p> Numeric conversions are divided into the following categories:
*
@@ -1547,7 +1547,7 @@
* href="#floatDPrec">precision</a> is the same as defined for Float and
* Double.
*
- * <h4><a id="ddt">Date/Time</a></h4>
+ * <h3><a id="ddt">Date/Time</a></h3>
*
* <p> This conversion may be applied to {@code long}, {@link Long}, {@link
* Calendar}, {@link Date} and {@link TemporalAccessor TemporalAccessor}
@@ -1796,7 +1796,7 @@
* <p> The precision is not applicable. If the precision is specified then an
* {@link IllegalFormatPrecisionException} will be thrown.
*
- * <h4><a id="dper">Percent</a></h4>
+ * <h3><a id="dper">Percent</a></h3>
*
* <p> The conversion does not correspond to any argument.
*
@@ -1824,7 +1824,7 @@
* </tbody>
* </table>
*
- * <h4><a id="dls">Line Separator</a></h4>
+ * <h3><a id="dls">Line Separator</a></h3>
*
* <p> The conversion does not correspond to any argument.
*
@@ -1843,7 +1843,7 @@
* {@link IllegalFormatFlagsException}, {@link IllegalFormatWidthException},
* and {@link IllegalFormatPrecisionException}, respectively will be thrown.
*
- * <h4><a id="dpos">Argument Index</a></h4>
+ * <h3><a id="dpos">Argument Index</a></h3>
*
* <p> Format specifiers can reference arguments in three ways:
*
--- a/src/java.base/share/classes/java/util/GregorianCalendar.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/util/GregorianCalendar.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -91,7 +91,7 @@
* adjustment may be made if desired for dates that are prior to the Gregorian
* changeover and which fall between January 1 and March 24.
*
- * <h3><a id="week_and_year">Week Of Year and Week Year</a></h3>
+ * <h2><a id="week_and_year">Week Of Year and Week Year</a></h2>
*
* <p>Values calculated for the {@link Calendar#WEEK_OF_YEAR
* WEEK_OF_YEAR} field range from 1 to 53. The first week of a
@@ -133,7 +133,7 @@
* ends on January 10, 1998; the first three days of 1998 then are
* part of week 53 of 1997 and their week year is 1997.
*
- * <h4>Week Of Month</h4>
+ * <h3>Week Of Month</h3>
*
* <p>Values calculated for the <code>WEEK_OF_MONTH</code> field range from 0
* to 6. Week 1 of a month (the days with <code>WEEK_OF_MONTH =
@@ -153,7 +153,7 @@
* <code>getMinimalDaysInFirstWeek()</code> is changed to 3, then January 1
* through January 3 have a <code>WEEK_OF_MONTH</code> of 1.
*
- * <h4>Default Fields Values</h4>
+ * <h3>Default Fields Values</h3>
*
* <p>The <code>clear</code> method sets calendar field(s)
* undefined. <code>GregorianCalendar</code> uses the following
--- a/src/java.base/share/classes/java/util/Locale.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/util/Locale.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -190,7 +190,7 @@
* requirement (is well-formed), but does not validate the value
* itself. See {@link Builder} for details.
*
- * <h3><a id="def_locale_extension">Unicode locale/language extension</a></h3>
+ * <h2><a id="def_locale_extension">Unicode locale/language extension</a></h2>
*
* <p>UTS#35, "Unicode Locale Data Markup Language" defines optional
* attributes and keywords to override or refine the default behavior
@@ -230,17 +230,17 @@
* implementations in a Java Runtime Environment might not support any
* particular Unicode locale attributes or key/type pairs.
*
- * <h4>Creating a Locale</h4>
+ * <h3>Creating a Locale</h3>
*
* <p>There are several different ways to create a <code>Locale</code>
* object.
*
- * <h5>Builder</h5>
+ * <h4>Builder</h4>
*
* <p>Using {@link Builder} you can construct a <code>Locale</code> object
* that conforms to BCP 47 syntax.
*
- * <h5>Constructors</h5>
+ * <h4>Constructors</h4>
*
* <p>The <code>Locale</code> class provides three constructors:
* <blockquote>
@@ -254,12 +254,12 @@
* with language, country and variant, but you cannot specify
* script or extensions.
*
- * <h5>Factory Methods</h5>
+ * <h4>Factory Methods</h4>
*
* <p>The method {@link #forLanguageTag} creates a <code>Locale</code>
* object for a well-formed BCP 47 language tag.
*
- * <h5>Locale Constants</h5>
+ * <h4>Locale Constants</h4>
*
* <p>The <code>Locale</code> class provides a number of convenient constants
* that you can use to create <code>Locale</code> objects for commonly used
@@ -271,7 +271,7 @@
* </pre>
* </blockquote>
*
- * <h4><a id="LocaleMatching">Locale Matching</a></h4>
+ * <h3><a id="LocaleMatching">Locale Matching</a></h3>
*
* <p>If an application or a system is internationalized and provides localized
* resources for multiple locales, it sometimes needs to find one or more
@@ -292,7 +292,7 @@
* language ranges: basic and extended. See
* {@link Locale.LanguageRange Locale.LanguageRange} for details.
*
- * <h5>Filtering</h5>
+ * <h4>Filtering</h4>
*
* <p>The filtering operation returns all matching language tags. It is defined
* in RFC 4647 as follows:
@@ -310,7 +310,7 @@
* {@link Locale.FilteringMode} is a parameter to specify how filtering should
* be done.
*
- * <h5>Lookup</h5>
+ * <h4>Lookup</h4>
*
* <p>The lookup operation returns the best matching language tags. It is
* defined in RFC 4647 as follows:
@@ -342,7 +342,7 @@
* an {@link Iterator} over a {@link Collection} of language tags is treated as
* the best matching one.
*
- * <h4>Use of Locale</h4>
+ * <h3>Use of Locale</h3>
*
* <p>Once you've created a <code>Locale</code> you can query it for information
* about itself. Use <code>getCountry</code> to get the country (or region)
@@ -385,7 +385,7 @@
* <STRONG>just</STRONG> a mechanism for identifying objects,
* <STRONG>not</STRONG> a container for the objects themselves.
*
- * <h4>Compatibility</h4>
+ * <h3>Compatibility</h3>
*
* <p>In order to maintain compatibility with existing usage, Locale's
* constructors retain their behavior prior to the Java Runtime
@@ -410,7 +410,7 @@
* Clients desiring a string representation of the complete locale can
* then always rely on <code>toLanguageTag</code> for this purpose.
*
- * <h5><a id="special_cases_constructor">Special cases</a></h5>
+ * <h4><a id="special_cases_constructor">Special cases</a></h4>
*
* <p>For compatibility reasons, two
* non-conforming locales are treated as special cases. These are
@@ -435,7 +435,7 @@
* constructor is called with the arguments "th", "TH", "TH", the
* extension "u-nu-thai" is automatically added.
*
- * <h5>Serialization</h5>
+ * <h4>Serialization</h4>
*
* <p>During serialization, writeObject writes all fields to the output
* stream, including extensions.
@@ -444,7 +444,7 @@
* in <a href="#special_cases_constructor">Special Cases</a>, only
* for the two cases th_TH_TH and ja_JP_JP.
*
- * <h5>Legacy language codes</h5>
+ * <h4>Legacy language codes</h4>
*
* <p>Locale's constructor has always converted three language codes to
* their earlier, obsoleted forms: {@code he} maps to {@code iw},
@@ -462,7 +462,7 @@
* lookup mechanism also implements this mapping, so that resources
* can be named using either convention, see {@link ResourceBundle.Control}.
*
- * <h5>Three-letter language/country(region) codes</h5>
+ * <h4>Three-letter language/country(region) codes</h4>
*
* <p>The Locale constructors have always specified that the language
* and the country param be two characters in length, although in
--- a/src/java.base/share/classes/java/util/ResourceBundle.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/util/ResourceBundle.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -204,18 +204,18 @@
* known concrete subclasses {@code ListResourceBundle} and
* {@code PropertyResourceBundle} are thread-safe.
*
- * <h3><a id="resource-bundle-modules">Resource Bundles and Named Modules</a></h3>
+ * <h2><a id="resource-bundle-modules">Resource Bundles and Named Modules</a></h2>
*
* Resource bundles can be deployed in modules in the following ways:
*
- * <h4>Resource bundles together with an application</h4>
+ * <h3>Resource bundles together with an application</h3>
*
* Resource bundles can be deployed together with an application in the same
* module. In that case, the resource bundles are loaded
* by code in the module by calling the {@link #getBundle(String)}
* or {@link #getBundle(String, Locale)} method.
*
- * <h4><a id="service-providers">Resource bundles as service providers</a></h4>
+ * <h3><a id="service-providers">Resource bundles as service providers</a></h3>
*
* Resource bundles can be deployed in one or more <em>service provider modules</em>
* and they can be located using {@link ServiceLoader}.
@@ -232,7 +232,7 @@
* provide resource bundles in any format such XML which replaces the need
* of {@link Control ResourceBundle.Control}.
*
- * <h4><a id="other-modules">Resource bundles in other modules and class path</a></h4>
+ * <h3><a id="other-modules">Resource bundles in other modules and class path</a></h3>
*
* Resource bundles in a named module may be <em>encapsulated</em> so that
* it cannot be located by code in other modules. Resource bundles
@@ -255,7 +255,7 @@
* resource bundle provider</a>, it does not fall back to the
* class loader search.
*
- * <h4>Resource bundles in automatic modules</h4>
+ * <h3>Resource bundles in automatic modules</h3>
*
* A common format of resource bundles is in {@linkplain PropertyResourceBundle
* .properties} file format. Typically {@code .properties} resource bundles
@@ -300,7 +300,7 @@
* the first one returned from {@link ServiceLoader} will be used.
* A custom {@link Control} implementation is ignored by named modules.
*
- * <h3>Cache Management</h3>
+ * <h2>Cache Management</h2>
*
* Resource bundle instances created by the <code>getBundle</code> factory
* methods are cached by default, and the factory methods return the same
@@ -316,7 +316,7 @@
* Control#needsReload(String, Locale, String, ClassLoader, ResourceBundle,
* long) ResourceBundle.Control.needsReload} for details.
*
- * <h3>Example</h3>
+ * <h2>Example</h2>
*
* The following is a very simple example of a <code>ResourceBundle</code>
* subclass, <code>MyResources</code>, that manages two resources (for a larger number of
--- a/src/java.base/share/classes/java/util/Scanner.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/util/Scanner.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -155,7 +155,7 @@
* {@link #reset} method will reset the value of the scanner's radix to
* {@code 10} regardless of whether it was previously changed.
*
- * <h3> <a id="localized-numbers">Localized numbers</a> </h3>
+ * <h2> <a id="localized-numbers">Localized numbers</a> </h2>
*
* <p> An instance of this class is capable of scanning numbers in the standard
* formats as well as in the formats of the scanner's locale. A scanner's
@@ -216,7 +216,7 @@
* getInfinity()}
* </dl></blockquote>
*
- * <h4> <a id="number-syntax">Number syntax</a> </h4>
+ * <h3> <a id="number-syntax">Number syntax</a> </h3>
*
* <p> The strings that can be parsed as numbers by an instance of this class
* are specified in terms of the following regular-expression grammar, where
--- a/src/java.base/share/classes/java/util/ServiceLoader.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/util/ServiceLoader.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -69,7 +69,7 @@
* service providers (based on the functionality they expose through the service),
* and handling the possibility that no service providers are located.
*
- * <h3> Obtaining a service loader </h3>
+ * <h2> Obtaining a service loader </h2>
*
* <p> An application obtains a service loader for a given service by invoking
* one of the static {@code load} methods of {@code ServiceLoader}. If the
@@ -141,7 +141,7 @@
* <li> {@code get()} yields an instance of {@code CodecFactory} </li>
* </ol>
*
- * <h3> Designing services </h3>
+ * <h2> Designing services </h2>
*
* <p> A service is a single type, usually an interface or abstract class. A
* concrete class can be used, but this is not recommended. The type may have
@@ -167,7 +167,7 @@
* or complicated to produce certain codecs. </p></li>
* </ol>
*
- * <h3> <a id="developing-service-providers">Developing service providers</a> </h3>
+ * <h2> <a id="developing-service-providers">Developing service providers</a> </h2>
*
* <p> A service provider is a single type, usually a concrete class. An
* interface or abstract class is permitted because it may declare a static
@@ -188,7 +188,7 @@
* the service loader's stream, without knowledge of the service providers'
* locations.
*
- * <h3> Deploying service providers as modules </h3>
+ * <h2> Deploying service providers as modules </h2>
*
* <p> A service provider that is developed in a module must be specified in a
* <i>provides</i> directive in the module declaration. The provides directive
@@ -253,7 +253,7 @@
* the service provider) will be instantiated by an entity (that is, a service
* loader) which is outside the class's package.
*
- * <h3> Deploying service providers on the class path </h3>
+ * <h2> Deploying service providers on the class path </h2>
*
* A service provider that is packaged as a JAR file for the class path is
* identified by placing a <i>provider-configuration file</i> in the resource
@@ -293,7 +293,7 @@
* not necessarily the class loader which ultimately locates the
* provider-configuration file.
*
- * <h3> Timing of provider discovery </h3>
+ * <h2> Timing of provider discovery </h2>
*
* <p> Service providers are loaded and instantiated lazily, that is, on demand.
* A service loader maintains a cache of the providers that have been loaded so
@@ -306,7 +306,7 @@
* locates any remaining providers. Caches are cleared via the {@link #reload
* reload} method.
*
- * <h3> <a id="errors">Errors</a> </h3>
+ * <h2> <a id="errors">Errors</a> </h2>
*
* <p> When using the service loader's {@code iterator}, the {@link
* Iterator#hasNext() hasNext} and {@link Iterator#next() next} methods will
@@ -361,7 +361,7 @@
*
* </ul>
*
- * <h3> Security </h3>
+ * <h2> Security </h2>
*
* <p> Service loaders always execute in the security context of the caller
* of the iterator or stream methods and may also be restricted by the security
@@ -370,7 +370,7 @@
* the methods of the iterators which they return, from within a privileged
* security context.
*
- * <h3> Concurrency </h3>
+ * <h2> Concurrency </h2>
*
* <p> Instances of this class are not safe for use by multiple concurrent
* threads.
--- a/src/java.base/share/classes/java/util/TimeZone.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/util/TimeZone.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -114,7 +114,7 @@
* </pre></blockquote>
* For example, TimeZone.getTimeZone("GMT-8").getID() returns "GMT-08:00".
*
- * <h3>Three-letter time zone IDs</h3>
+ * <h2>Three-letter time zone IDs</h2>
*
* For compatibility with JDK 1.1.x, some other three-letter time zone IDs
* (such as "PST", "CTT", "AST") are also supported. However, <strong>their
--- a/src/java.base/share/classes/java/util/doc-files/coll-designfaq.html Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/util/doc-files/coll-designfaq.html Thu Mar 21 18:04:01 2019 +0000
@@ -1,6 +1,6 @@
<!DOCTYPE html>
<!--
- Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
This code is free software; you can redistribute it and/or modify it
@@ -29,14 +29,14 @@
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
-<h2>Java Collections API Design FAQ</h2>
+<h1>Java Collections API Design FAQ</h1>
<!-- Body text begins here -->
<hr>
This document answers frequently asked questions concerning the
design of the Java collections framework. It is derived from the
large volume of traffic on the collections-comments alias. It
serves as a design rationale for the collections framework.
-<h3>Core Interfaces - General Questions</h3>
+<h2>Core Interfaces - General Questions</h2>
<ol>
<li><a href="#a1"><b>Why don't you support immutability directly in
the core collection interfaces so that you can do away with
@@ -50,7 +50,7 @@
<li><a href="#a28"><b>Why didn't you use "Beans-style names" for
consistency?</b></a></li>
</ol>
-<h3>Collection Interface</h3>
+<h2>Collection Interface</h2>
<ol>
<li><a href="#a5"><b>Why doesn't Collection extend Cloneable and
Serializable?</b></a></li>
@@ -67,7 +67,7 @@
<li><a href="#a10"><b>Why don't you provide an Iterator.add
method?</b></a></li>
</ol>
-<h3>List Interface</h3>
+<h2>List Interface</h2>
<ol>
<li><a href="#a11"><b>Why don't you rename the List interface to
Sequence; doesn't "list" generally suggest "linked list"? Also,
@@ -75,12 +75,12 @@
<li><a href="#a12"><b>Why don't you rename List's set method to
replace, to avoid confusion with Set.</b></a></li>
</ol>
-<h3>Map Interface</h3>
+<h2>Map Interface</h2>
<ol>
<li><a href="#a14"><b>Why doesn't Map extend
Collection?</b></a></li>
</ol>
-<h3>Iterator Interface</h3>
+<h2>Iterator Interface</h2>
<ol>
<li><a href="#a18"><b>Why doesn't Iterator extend
Enumeration?</b></a></li>
@@ -88,7 +88,7 @@
that allows you to look at the next element in an iteration without
advancing the iterator?</b></a></li>
</ol>
-<h3>Miscellaneous</h3>
+<h2>Miscellaneous</h2>
<ol>
<li><a href="#a23"><b>Why did you write a new collections framework
instead of adopting JGL (a preexisting collections package from
@@ -102,7 +102,7 @@
modified?</b></a></li>
</ol>
<hr>
-<h3>Core Interfaces - General Questions</h3>
+<h2>Core Interfaces - General Questions</h2>
<ol>
<li><a id="a1"><b>Why don't you support immutability
directly in the core collection interfaces so that you can do away
@@ -204,7 +204,7 @@
Beans style.</li>
</ol>
<hr>
-<h3>Collection Interface</h3>
+<h2>Collection Interface</h2>
<ol>
<li><a id="a5"><b>Why doesn't Collection extend Cloneable
and Serializable?</b></a>
@@ -264,7 +264,7 @@
</li>
</ol>
<hr>
-<h3>List Interface</h3>
+<h2>List Interface</h2>
<ol>
<li><a id="a11"><b>Why don't you rename the List
interface to Sequence; doesn't "list" generally suggest "linked
@@ -288,7 +288,7 @@
</li>
</ol>
<hr>
-<h3>Map Interface</h3>
+<h2>Map Interface</h2>
<ol>
<li><a id="a14"><b>Why doesn't Map extend
Collection?</b></a>
@@ -314,7 +314,7 @@
</li>
</ol>
<hr>
-<h3>Iterator Interface</h3>
+<h2>Iterator Interface</h2>
<ol>
<li><a id="a18"><b>Why doesn't Iterator extend
Enumeration?</b></a>
@@ -335,7 +335,7 @@
</li>
</ol>
<hr>
-<h3>Miscellaneous</h3>
+<h2>Miscellaneous</h2>
<ol>
<li><a id="a23"><b>Why did you write a new collections
framework instead of adopting JGL (a preexisting collections
--- a/src/java.base/share/classes/java/util/regex/Pattern.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/util/regex/Pattern.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -77,7 +77,7 @@
* such use.
*
*
- * <h3><a id="sum">Summary of regular-expression constructs</a></h3>
+ * <h2><a id="sum">Summary of regular-expression constructs</a></h2>
*
* <table class="borderless">
* <caption style="display:none">Regular expression constructs, and what they match</caption>
@@ -378,7 +378,7 @@
* <hr>
*
*
- * <h3><a id="bs">Backslashes, escapes, and quoting</a></h3>
+ * <h2><a id="bs">Backslashes, escapes, and quoting</a></h2>
*
* <p> The backslash character ({@code '\'}) serves to introduce escaped
* constructs, as defined in the table above, as well as to quote characters
@@ -406,7 +406,7 @@
* {@code (hello)} the string literal {@code "\\(hello\\)"}
* must be used.
*
- * <h3><a id="cc">Character Classes</a></h3>
+ * <h2><a id="cc">Character Classes</a></h2>
*
* <p> Character classes may appear within other character classes, and
* may be composed by the union operator (implicit) and the intersection
@@ -449,7 +449,7 @@
* character class, while the expression {@code -} becomes a range
* forming metacharacter.
*
- * <h3><a id="lt">Line terminators</a></h3>
+ * <h2><a id="lt">Line terminators</a></h2>
*
* <p> A <i>line terminator</i> is a one- or two-character sequence that marks
* the end of a line of the input character sequence. The following are
@@ -484,9 +484,9 @@
* except at the end of input. When in {@link #MULTILINE} mode {@code $}
* matches just before a line terminator or the end of the input sequence.
*
- * <h3><a id="cg">Groups and capturing</a></h3>
+ * <h2><a id="cg">Groups and capturing</a></h2>
*
- * <h4><a id="gnumber">Group number</a></h4>
+ * <h3><a id="gnumber">Group number</a></h3>
* <p> Capturing groups are numbered by counting their opening parentheses from
* left to right. In the expression {@code ((A)(B(C)))}, for example, there
* are four such groups: </p>
@@ -505,7 +505,7 @@
* subsequence may be used later in the expression, via a back reference, and
* may also be retrieved from the matcher once the match operation is complete.
*
- * <h4><a id="groupname">Group name</a></h4>
+ * <h3><a id="groupname">Group name</a></h3>
* <p>A capturing group can also be assigned a "name", a {@code named-capturing group},
* and then be back-referenced later by the "name". Group names are composed of
* the following characters. The first character must be a {@code letter}.
@@ -534,7 +534,7 @@
* that do not capture text and do not count towards the group total, or
* <i>named-capturing</i> group.
*
- * <h3> Unicode support </h3>
+ * <h2> Unicode support </h2>
*
* <p> This class is in conformance with Level 1 of <a
* href="http://www.unicode.org/reports/tr18/"><i>Unicode Technical
@@ -688,7 +688,7 @@
* available through the same <code>\p{</code><i>prop</i><code>}</code> syntax where
* the specified property has the name <code>java<i>methodname</i></code></a>.
*
- * <h3> Comparison to Perl 5 </h3>
+ * <h2> Comparison to Perl 5 </h2>
*
* <p>The {@code Pattern} engine performs traditional NFA-based matching
* with ordered alternation as occurs in Perl 5.
--- a/src/java.base/share/classes/java/util/spi/LocaleServiceProvider.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/util/spi/LocaleServiceProvider.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -42,7 +42,7 @@
* interfaces to offer support for locales beyond the set of locales
* supported by the Java runtime environment itself.
*
- * <h3>Packaging of Locale Sensitive Service Provider Implementations</h3>
+ * <h2>Packaging of Locale Sensitive Service Provider Implementations</h2>
* Implementations of these locale sensitive services can be made available
* by adding them to the application's class path. A provider identifies itself with a
* provider-configuration file in the resource directory META-INF/services,
@@ -75,7 +75,7 @@
* </pre>
* which is the fully qualified class name of the class implementing
* <code>DateFormatProvider</code>.
- * <h4>Invocation of Locale Sensitive Services</h4>
+ * <h3>Invocation of Locale Sensitive Services</h3>
* <p>
* Locale sensitive factory methods and methods for name retrieval in the
* <code>java.text</code> and <code>java.util</code> packages invoke
--- a/src/java.base/share/classes/java/util/spi/ResourceBundleProvider.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/share/classes/java/util/spi/ResourceBundleProvider.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -35,7 +35,7 @@
* factory methods to locate and load the service providers that are deployed as
* modules via {@link java.util.ServiceLoader ServiceLoader}.
*
- * <h3>Developing resource bundle services</h3>
+ * <h2>Developing resource bundle services</h2>
*
* A service for a resource bundle of a given <em>{@code baseName}</em> must have
* a fully-qualified class name of the form:
@@ -55,7 +55,7 @@
* }
* }</pre></blockquote>
*
- * <h3>Deploying resource bundle service providers</h3>
+ * <h2>Deploying resource bundle service providers</h2>
*
* Resource bundles can be deployed in one or more service providers
* in modules. For example, a provider for a service
@@ -114,7 +114,7 @@
* provides com.example.app.spi.MyResourcesProvider with com.example.impl.MyResourcesProviderImpl;
* </pre>
*
- * <h3><a id="obtain-resource-bundle">Obtaining resource bundles from providers</a></h3>
+ * <h2><a id="obtain-resource-bundle">Obtaining resource bundles from providers</a></h2>
*
* The module declaration of the <em>consumer module</em> that calls one of the
* {@code ResourceBundle.getBundle} factory methods to obtain a resource
--- a/src/java.base/unix/native/libjava/UnixFileSystem_md.c Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/unix/native/libjava/UnixFileSystem_md.c Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -168,7 +168,9 @@
default: assert(0);
}
WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {
- if (access(path, mode) == 0) {
+ int res;
+ RESTARTABLE(access(path, mode), res);
+ if (res == 0) {
rv = JNI_TRUE;
}
} END_PLATFORM_STRING(env, path);
@@ -188,6 +190,7 @@
WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {
int amode = 0;
int mode;
+ int res;
switch (access) {
case java_io_FileSystem_ACCESS_READ:
if (owneronly)
@@ -215,7 +218,8 @@
mode |= amode;
else
mode &= ~amode;
- if (chmod(path, mode) >= 0) {
+ RESTARTABLE(chmod(path, mode), res);
+ if (res == 0) {
rv = JNI_TRUE;
}
}
@@ -355,13 +359,15 @@
closedir(dir);
/* Copy the final results into an appropriately-sized array */
- old = rv;
- rv = (*env)->NewObjectArray(env, len, str_class, NULL);
- if (rv == NULL) {
- return NULL;
- }
- if (JNU_CopyObjectArray(env, rv, old, len) < 0) {
- return NULL;
+ if (len < maxlen) {
+ old = rv;
+ rv = (*env)->NewObjectArray(env, len, str_class, NULL);
+ if (rv == NULL) {
+ return NULL;
+ }
+ if (JNU_CopyObjectArray(env, rv, old, len) < 0) {
+ return NULL;
+ }
}
return rv;
@@ -446,8 +452,10 @@
WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {
int mode;
+ int res;
if (statMode(path, &mode)) {
- if (chmod(path, mode & ~(S_IWUSR | S_IWGRP | S_IWOTH)) >= 0) {
+ RESTARTABLE(chmod(path, mode & ~(S_IWUSR | S_IWGRP | S_IWOTH)), res);
+ if (res == 0) {
rv = JNI_TRUE;
}
}
@@ -466,6 +474,7 @@
struct statfs fsstat;
#else
struct statvfs64 fsstat;
+ int res;
#endif
memset(&fsstat, 0, sizeof(fsstat));
#ifdef MACOSX
@@ -488,7 +497,8 @@
}
}
#else
- if (statvfs64(path, &fsstat) == 0) {
+ RESTARTABLE(statvfs64(path, &fsstat), res);
+ if (res == 0) {
switch(t) {
case java_io_FileSystem_SPACE_TOTAL:
rv = jlong_mul(long_to_jlong(fsstat.f_frsize),
--- a/src/java.base/unix/native/libjava/io_util_md.h Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.base/unix/native/libjava/io_util_md.h Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -93,11 +93,10 @@
/*
* Retry the operation if it is interrupted
*/
-#define RESTARTABLE(_cmd, _result) do { \
- do { \
- _result = _cmd; \
- } while((_result == -1) && (errno == EINTR)); \
-} while(0)
+#define RESTARTABLE(_cmd, _result) \
+ do { \
+ _result = _cmd; \
+ } while ((_result == -1) && (errno == EINTR))
void fileDescriptorClose(JNIEnv *env, jobject this);
--- a/src/java.instrument/share/native/libinstrument/InvocationAdapter.c Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.instrument/share/native/libinstrument/InvocationAdapter.c Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -558,32 +558,32 @@
environment = getJPLISEnvironment(jvmtienv);
/* process the premain calls on the all the JPL agents */
- if ( environment != NULL ) {
- jthrowable outstandingException = NULL;
- /*
- * Add the jarfile to the system class path
- */
- JPLISAgent * agent = environment->mAgent;
- if (appendClassPath(agent, agent->mJarfile)) {
- fprintf(stderr, "Unable to add %s to system class path - "
- "the system class loader does not define the "
- "appendToClassPathForInstrumentation method or the method failed\n",
- agent->mJarfile);
- free((void *)agent->mJarfile);
- abortJVM(jnienv, JPLIS_ERRORMESSAGE_CANNOTSTART);
- }
+ if (environment == NULL) {
+ abortJVM(jnienv, JPLIS_ERRORMESSAGE_CANNOTSTART ", getting JPLIS environment failed");
+ }
+ jthrowable outstandingException = NULL;
+ /*
+ * Add the jarfile to the system class path
+ */
+ JPLISAgent * agent = environment->mAgent;
+ if (appendClassPath(agent, agent->mJarfile)) {
+ fprintf(stderr, "Unable to add %s to system class path - "
+ "the system class loader does not define the "
+ "appendToClassPathForInstrumentation method or the method failed\n",
+ agent->mJarfile);
free((void *)agent->mJarfile);
- agent->mJarfile = NULL;
+ abortJVM(jnienv, JPLIS_ERRORMESSAGE_CANNOTSTART ", appending to system class path failed");
+ }
+ free((void *)agent->mJarfile);
+ agent->mJarfile = NULL;
- outstandingException = preserveThrowable(jnienv);
- success = processJavaStart( environment->mAgent,
- jnienv);
- restoreThrowable(jnienv, outstandingException);
- }
+ outstandingException = preserveThrowable(jnienv);
+ success = processJavaStart( environment->mAgent, jnienv);
+ restoreThrowable(jnienv, outstandingException);
/* if we fail to start cleanly, bring down the JVM */
if ( !success ) {
- abortJVM(jnienv, JPLIS_ERRORMESSAGE_CANNOTSTART);
+ abortJVM(jnienv, JPLIS_ERRORMESSAGE_CANNOTSTART ", processJavaStart failed");
}
}
--- a/src/java.instrument/share/native/libinstrument/JPLISAgent.c Thu Mar 21 08:41:10 2019 +0000
+++ b/src/java.instrument/share/native/libinstrument/JPLISAgent.c Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -389,17 +389,17 @@
*/
/*
- * First make our emergency fallback InternalError throwable.
+ * First make our fallback InternalError throwable.
*/
result = initializeFallbackError(jnienv);
- jplis_assert(result);
+ jplis_assert_msg(result, "fallback init failed");
/*
* Now make the InstrumentationImpl instance.
*/
if ( result ) {
result = createInstrumentationImpl(jnienv, agent);
- jplis_assert(result);
+ jplis_assert_msg(result, "instrumentation instance creation failed");
}
@@ -409,7 +409,7 @@
*/
if ( result ) {
result = setLivePhaseEventHandlers(agent);
- jplis_assert(result);
+ jplis_assert_msg(result, "setting of live phase VM handlers failed");
}
/*
@@ -419,6 +419,7 @@
result = startJavaAgent(agent, jnienv,
agent->mAgentClassName, agent->mOptionsString,
agent->mPremainCaller);
+ jplis_assert_msg(result, "agent load/premain call failed");
}
/*
--- a/src/jdk.crypto.ec/share/classes/sun/security/ec/ECDSASignature.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/ECDSASignature.java Thu Mar 21 18:04:01 2019 +0000
@@ -410,10 +410,10 @@
// DER OID
byte[] encodedParams = ECUtil.encodeECParameterSpec(null, params);
- int keySize = params.getCurve().getField().getFieldSize();
+ int orderLength = params.getOrder().bitLength();
- // seed is twice the key size (in bytes) plus 1
- byte[] seed = new byte[(((keySize + 7) >> 3) + 1) * 2];
+ // seed is twice the order length (in bytes) plus 1
+ byte[] seed = new byte[(((orderLength + 7) >> 3) + 1) * 2];
random.nextBytes(seed);
--- a/src/jdk.crypto.ec/share/native/libsunec/impl/ec.c Thu Mar 21 08:41:10 2019 +0000
+++ b/src/jdk.crypto.ec/share/native/libsunec/impl/ec.c Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*
* This library is free software; you can redistribute it and/or
@@ -660,6 +660,7 @@
SECItem kGpoint = { siBuffer, NULL, 0};
int flen = 0; /* length in bytes of the field size */
unsigned olen; /* length in bytes of the base point order */
+ unsigned int orderBitSize;
#if EC_DEBUG
char mpstr[256];
@@ -762,10 +763,11 @@
SECITEM_TO_MPINT(*digest, &s); /* s = HASH(M) */
/* In the definition of EC signing, digests are truncated
- * to the length of n in bits.
+ * to the order length
* (see SEC 1 "Elliptic Curve Digit Signature Algorithm" section 4.1.*/
- if (digest->len*8 > (unsigned int)ecParams->fieldID.size) {
- mpl_rsh(&s,&s,digest->len*8 - ecParams->fieldID.size);
+ orderBitSize = mpl_significant_bits(&n);
+ if (digest->len*8 > orderBitSize) {
+ mpl_rsh(&s,&s,digest->len*8 - orderBitSize);
}
#if EC_DEBUG
@@ -898,6 +900,7 @@
int slen; /* length in bytes of a half signature (r or s) */
int flen; /* length in bytes of the field size */
unsigned olen; /* length in bytes of the base point order */
+ unsigned int orderBitSize;
#if EC_DEBUG
char mpstr[256];
@@ -977,11 +980,12 @@
SECITEM_TO_MPINT(*digest, &u1); /* u1 = HASH(M) */
/* In the definition of EC signing, digests are truncated
- * to the length of n in bits.
+ * to the order length, in bits.
* (see SEC 1 "Elliptic Curve Digit Signature Algorithm" section 4.1.*/
/* u1 = HASH(M') */
- if (digest->len*8 > (unsigned int)ecParams->fieldID.size) {
- mpl_rsh(&u1,&u1,digest->len*8- ecParams->fieldID.size);
+ orderBitSize = mpl_significant_bits(&n);
+ if (digest->len*8 > orderBitSize) {
+ mpl_rsh(&u1,&u1,digest->len*8- orderBitSize);
}
#if EC_DEBUG
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZHeap.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZHeap.java Thu Mar 21 18:04:01 2019 +0000
@@ -48,7 +48,7 @@
Type type = db.lookupType("ZHeap");
pageAllocatorFieldOffset = type.getAddressField("_page_allocator").getOffset();
- pageTableFieldOffset = type.getAddressField("_pagetable").getOffset();
+ pageTableFieldOffset = type.getAddressField("_page_table").getOffset();
}
public ZHeap(Address addr) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/IntegerStampShiftTest.java Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+
+package org.graalvm.compiler.core.test;
+
+import org.junit.Test;
+
+public class IntegerStampShiftTest extends GraalCompilerTest {
+
+ public static int unsignedShiftPositiveInt(boolean f) {
+ int h = f ? 0x7FFFFFF0 : 0x7FFFFF00;
+ return h >>> 8;
+ }
+
+ @Test
+ public void testUnsignedShiftPositiveInt() {
+ test("unsignedShiftPositiveInt", false);
+ }
+
+ public static int unsignedShiftNegativeInt(boolean f) {
+ int h = f ? 0xFFFFFFF0 : 0xFFFFFF00;
+ return h >>> 8;
+ }
+
+ @Test
+ public void testUnsignedShiftNegativeInt() {
+ test("unsignedShiftNegativeInt", false);
+ }
+
+ public static long unsignedShiftPositiveLong(boolean f) {
+ long h = f ? 0x7FFFFFFFFFFFFFF0L : 0x7FFFFFFFFFFFFF00L;
+ return h >>> 8;
+ }
+
+ @Test
+ public void testUnsignedShiftPositiveLong() {
+ test("unsignedShiftPositiveLong", false);
+ }
+
+ public static long unsignedShiftNegativeLong(boolean f) {
+ long h = f ? 0xFFFFFFFFFFFFFFF0L : 0xFFFFFFFFFFFFFF00L;
+ return h >>> 8;
+ }
+
+ @Test
+ public void testUnsignedShiftNegativeLong() {
+ test("unsignedShiftNegativeLong", false);
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilationWrapper.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilationWrapper.java Thu Mar 21 18:04:01 2019 +0000
@@ -25,7 +25,7 @@
package org.graalvm.compiler.core;
import static org.graalvm.compiler.core.CompilationWrapper.ExceptionAction.ExitVM;
-import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAction;
+import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAsFailure;
import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationFailureAction;
import static org.graalvm.compiler.core.GraalCompilerOptions.ExitVMOnException;
import static org.graalvm.compiler.core.GraalCompilerOptions.MaxCompilationProblemsPerAction;
@@ -45,14 +45,13 @@
import org.graalvm.compiler.debug.DiagnosticsOutputDirectory;
import org.graalvm.compiler.debug.PathUtilities;
import org.graalvm.compiler.debug.TTY;
-import org.graalvm.compiler.options.EnumOptionKey;
import org.graalvm.compiler.options.OptionValues;
import jdk.vm.ci.code.BailoutException;
/**
* Wrapper for a compilation that centralizes what action to take based on
- * {@link GraalCompilerOptions#CompilationBailoutAction} and
+ * {@link GraalCompilerOptions#CompilationBailoutAsFailure} and
* {@link GraalCompilerOptions#CompilationFailureAction} when an uncaught exception occurs during
* compilation.
*/
@@ -71,14 +70,17 @@
* Print nothing to the console.
*/
Silent,
+
/**
* Print a stack trace to the console.
*/
Print,
+
/**
* An exception causes the compilation to be retried with extra diagnostics enabled.
*/
Diagnose,
+
/**
* Same as {@link #Diagnose} except that the VM process is exited after retrying.
*/
@@ -122,27 +124,30 @@
protected abstract T handleException(Throwable t);
/**
- * Gets the action to take based on the value of {@code actionKey} in {@code options}.
+ * Gets the action to take based on the value of
+ * {@link GraalCompilerOptions#CompilationBailoutAsFailure},
+ * {@link GraalCompilerOptions#CompilationFailureAction} and
+ * {@link GraalCompilerOptions#ExitVMOnException} in {@code options}.
*
- * Subclasses can override this to choose a different action based on factors such as whether
- * {@code actionKey} has been explicitly set in {@code options} for example.
+ * Subclasses can override this to choose a different action.
*
* @param cause the cause of the bailout or failure
*/
- protected ExceptionAction lookupAction(OptionValues options, EnumOptionKey<ExceptionAction> actionKey, Throwable cause) {
- if (actionKey == CompilationFailureAction) {
- if (ExitVMOnException.getValue(options)) {
- assert CompilationFailureAction.getDefaultValue() != ExceptionAction.ExitVM;
- assert ExitVMOnException.getDefaultValue() != true;
- if (CompilationFailureAction.hasBeenSet(options) && CompilationFailureAction.getValue(options) != ExceptionAction.ExitVM) {
- TTY.printf("WARNING: Ignoring %s=%s since %s=true has been explicitly specified.%n",
- CompilationFailureAction.getName(), CompilationFailureAction.getValue(options),
- ExitVMOnException.getName());
- }
- return ExceptionAction.ExitVM;
+ protected ExceptionAction lookupAction(OptionValues options, Throwable cause) {
+ if (cause instanceof BailoutException && !CompilationBailoutAsFailure.getValue(options)) {
+ return ExceptionAction.Silent;
+ }
+ if (ExitVMOnException.getValue(options)) {
+ assert CompilationFailureAction.getDefaultValue() != ExceptionAction.ExitVM;
+ assert ExitVMOnException.getDefaultValue() != true;
+ if (CompilationFailureAction.hasBeenSet(options) && CompilationFailureAction.getValue(options) != ExceptionAction.ExitVM) {
+ TTY.printf("WARNING: Ignoring %s=%s since %s=true has been explicitly specified.%n",
+ CompilationFailureAction.getName(), CompilationFailureAction.getValue(options),
+ ExitVMOnException.getName());
}
+ return ExceptionAction.ExitVM;
}
- return actionKey.getValue(options);
+ return CompilationFailureAction.getValue(options);
}
/**
@@ -173,15 +178,6 @@
} catch (Throwable cause) {
OptionValues initialOptions = initialDebug.getOptions();
- String causeType = "failure";
- EnumOptionKey<ExceptionAction> actionKey;
- if (cause instanceof BailoutException) {
- actionKey = CompilationBailoutAction;
- causeType = "bailout";
- } else {
- actionKey = CompilationFailureAction;
- causeType = "failure";
- }
synchronized (CompilationFailureAction) {
// Serialize all compilation failure handling.
// This prevents retry compilation storms and interleaving
@@ -191,9 +187,9 @@
// forced crash (i.e., use of GraalCompilerOptions.CrashAt)
// is truncated.
- ExceptionAction action = lookupAction(initialOptions, actionKey, cause);
+ ExceptionAction action = lookupAction(initialOptions, cause);
- action = adjustAction(initialOptions, actionKey, action);
+ action = adjustAction(initialOptions, action);
if (action == ExceptionAction.Silent) {
return handleException(cause);
@@ -204,16 +200,14 @@
try (PrintStream ps = new PrintStream(baos)) {
ps.printf("%s: Compilation of %s failed: ", Thread.currentThread(), this);
cause.printStackTrace(ps);
- ps.printf("To disable compilation %s notifications, set %s to %s (e.g., -Dgraal.%s=%s).%n",
- causeType,
- actionKey.getName(), ExceptionAction.Silent,
- actionKey.getName(), ExceptionAction.Silent);
- ps.printf("To capture more information for diagnosing or reporting a compilation %s, " +
+ ps.printf("To disable compilation failure notifications, set %s to %s (e.g., -Dgraal.%s=%s).%n",
+ CompilationFailureAction.getName(), ExceptionAction.Silent,
+ CompilationFailureAction.getName(), ExceptionAction.Silent);
+ ps.printf("To capture more information for diagnosing or reporting a compilation failure, " +
"set %s to %s or %s (e.g., -Dgraal.%s=%s).%n",
- causeType,
- actionKey.getName(), ExceptionAction.Diagnose,
+ CompilationFailureAction.getName(), ExceptionAction.Diagnose,
ExceptionAction.ExitVM,
- actionKey.getName(), ExceptionAction.Diagnose);
+ CompilationFailureAction.getName(), ExceptionAction.Diagnose);
}
TTY.print(baos.toString());
return handleException(cause);
@@ -249,15 +243,13 @@
try (PrintStream ps = new PrintStream(baos)) {
ps.printf("%s: Compilation of %s failed:%n", Thread.currentThread(), this);
cause.printStackTrace(ps);
- ps.printf("To disable compilation %s notifications, set %s to %s (e.g., -Dgraal.%s=%s).%n",
- causeType,
- actionKey.getName(), ExceptionAction.Silent,
- actionKey.getName(), ExceptionAction.Silent);
- ps.printf("To print a message for a compilation %s without retrying the compilation, " +
+ ps.printf("To disable compilation failure notifications, set %s to %s (e.g., -Dgraal.%s=%s).%n",
+ CompilationFailureAction.getName(), ExceptionAction.Silent,
+ CompilationFailureAction.getName(), ExceptionAction.Silent);
+ ps.printf("To print a message for a compilation failure without retrying the compilation, " +
"set %s to %s (e.g., -Dgraal.%s=%s).%n",
- causeType,
- actionKey.getName(), ExceptionAction.Print,
- actionKey.getName(), ExceptionAction.Print);
+ CompilationFailureAction.getName(), ExceptionAction.Print,
+ CompilationFailureAction.getName(), ExceptionAction.Print);
if (dumpPath != null) {
ps.println("Retrying compilation of " + this);
} else {
@@ -320,7 +312,7 @@
* Adjusts {@code initialAction} if necessary based on
* {@link GraalCompilerOptions#MaxCompilationProblemsPerAction}.
*/
- private ExceptionAction adjustAction(OptionValues initialOptions, EnumOptionKey<ExceptionAction> actionKey, ExceptionAction initialAction) {
+ private ExceptionAction adjustAction(OptionValues initialOptions, ExceptionAction initialAction) {
ExceptionAction action = initialAction;
int maxProblems = MaxCompilationProblemsPerAction.getValue(initialOptions);
if (action != ExceptionAction.ExitVM) {
@@ -329,7 +321,7 @@
int problems = problemsHandledPerAction.getOrDefault(action, 0);
if (problems >= maxProblems) {
if (problems == maxProblems) {
- TTY.printf("Warning: adjusting %s from %s to %s after %s (%d) failed compilations%n", actionKey, action, action.quieter(),
+ TTY.printf("Warning: adjusting %s from %s to %s after %s (%d) failed compilations%n", CompilationFailureAction, action, action.quieter(),
MaxCompilationProblemsPerAction, maxProblems);
// Ensure that the message above is only printed once
problemsHandledPerAction.put(action, problems + 1);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompilerOptions.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompilerOptions.java Thu Mar 21 18:04:01 2019 +0000
@@ -44,13 +44,12 @@
"suffix will raise a bailout exception and a ':PermanentBailout' " +
"suffix will raise a permanent bailout exception.", type = OptionType.Debug)
public static final OptionKey<String> CrashAt = new OptionKey<>(null);
- @Option(help = "file:doc-files/CompilationBailoutActionHelp.txt", type = OptionType.User)
- public static final EnumOptionKey<ExceptionAction> CompilationBailoutAction = new EnumOptionKey<>(ExceptionAction.Silent);
- @Option(help = "Specifies the action to take when compilation fails with a bailout exception. " +
- "The accepted values are the same as for CompilationBailoutAction.", type = OptionType.User)
- public static final EnumOptionKey<ExceptionAction> CompilationFailureAction = new EnumOptionKey<>(ExceptionAction.Diagnose);
- @Option(help = "The maximum number of compilation failures or bailouts to handle with the action specified " +
- "by CompilationFailureAction or CompilationBailoutAction before changing to a less verbose action. " +
+ @Option(help = "Treat compilation bailouts like compilation failures.", type = OptionType.User)
+ public static final OptionKey<Boolean> CompilationBailoutAsFailure = new OptionKey<>(false);
+ @Option(help = "file:doc-files/CompilationFailureActionHelp.txt", type = OptionType.User)
+ public static final EnumOptionKey<ExceptionAction> CompilationFailureAction = new EnumOptionKey<>(ExceptionAction.Silent);
+ @Option(help = "The maximum number of compilation failures to handle with the action specified " +
+ "by CompilationFailureAction before changing to a less verbose action. " +
"This does not apply to the ExitVM action.", type = OptionType.User)
public static final OptionKey<Integer> MaxCompilationProblemsPerAction = new OptionKey<>(2);
@Option(help = "Alias for CompilationFailureAction=ExitVM.", type = OptionType.User)
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/doc-files/CompilationBailoutActionHelp.txt Thu Mar 21 08:41:10 2019 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,6 +0,0 @@
-Specifies the action to take when compilation fails with a bailout exception.
-The accepted values are:
- Silent - Print nothing to the console.
- Print - Print a stack trace to the console.
- Diagnose - Retry the compilation with extra diagnostics.
- ExitVM - Same as Diagnose except that the VM process exits after retrying.
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/doc-files/CompilationFailureActionHelp.txt Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,6 @@
+Specifies the action to take when compilation fails.
+The accepted values are:
+ Silent - Print nothing to the console.
+ Print - Print a stack trace to the console.
+ Diagnose - Retry the compilation with extra diagnostics.
+ ExitVM - Same as Diagnose except that the VM process exits after retrying.
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64ArrayEqualsStub.java Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.graalvm.compiler.hotspot.amd64;
+
+import org.graalvm.compiler.api.replacements.Snippet;
+import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
+import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage;
+import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
+import org.graalvm.compiler.hotspot.stubs.SnippetStub;
+import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.compiler.replacements.nodes.ArrayEqualsNode;
+import jdk.internal.vm.compiler.word.Pointer;
+
+import jdk.vm.ci.meta.JavaKind;
+
+public final class AMD64ArrayEqualsStub extends SnippetStub {
+
+ public static final ForeignCallDescriptor STUB_BOOLEAN_ARRAY_EQUALS = new ForeignCallDescriptor(
+ "booleanArraysEquals", boolean.class, Pointer.class, Pointer.class, int.class);
+ public static final ForeignCallDescriptor STUB_BYTE_ARRAY_EQUALS = new ForeignCallDescriptor(
+ "byteArraysEquals", boolean.class, Pointer.class, Pointer.class, int.class);
+ public static final ForeignCallDescriptor STUB_CHAR_ARRAY_EQUALS = new ForeignCallDescriptor(
+ "charArraysEquals", boolean.class, Pointer.class, Pointer.class, int.class);
+ public static final ForeignCallDescriptor STUB_SHORT_ARRAY_EQUALS = new ForeignCallDescriptor(
+ "shortArraysEquals", boolean.class, Pointer.class, Pointer.class, int.class);
+ public static final ForeignCallDescriptor STUB_INT_ARRAY_EQUALS = new ForeignCallDescriptor(
+ "intArraysEquals", boolean.class, Pointer.class, Pointer.class, int.class);
+ public static final ForeignCallDescriptor STUB_LONG_ARRAY_EQUALS = new ForeignCallDescriptor(
+ "longArraysEquals", boolean.class, Pointer.class, Pointer.class, int.class);
+ public static final ForeignCallDescriptor STUB_FLOAT_ARRAY_EQUALS = new ForeignCallDescriptor(
+ "floatArraysEquals", boolean.class, Pointer.class, Pointer.class, int.class);
+ public static final ForeignCallDescriptor STUB_DOUBLE_ARRAY_EQUALS = new ForeignCallDescriptor(
+ "doubleArraysEquals", boolean.class, Pointer.class, Pointer.class, int.class);
+
+ public AMD64ArrayEqualsStub(ForeignCallDescriptor foreignCallDescriptor, OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) {
+ super(foreignCallDescriptor.getName(), options, providers, linkage);
+ }
+
+ @Snippet
+ private static boolean booleanArraysEquals(Pointer array1, Pointer array2, int length) {
+ return ArrayEqualsNode.equals(array1, array2, length, JavaKind.Boolean);
+ }
+
+ @Snippet
+ private static boolean byteArraysEquals(Pointer array1, Pointer array2, int length) {
+ return ArrayEqualsNode.equals(array1, array2, length, JavaKind.Byte);
+ }
+
+ @Snippet
+ private static boolean charArraysEquals(Pointer array1, Pointer array2, int length) {
+ return ArrayEqualsNode.equals(array1, array2, length, JavaKind.Char);
+ }
+
+ @Snippet
+ private static boolean shortArraysEquals(Pointer array1, Pointer array2, int length) {
+ return ArrayEqualsNode.equals(array1, array2, length, JavaKind.Short);
+ }
+
+ @Snippet
+ private static boolean intArraysEquals(Pointer array1, Pointer array2, int length) {
+ return ArrayEqualsNode.equals(array1, array2, length, JavaKind.Int);
+ }
+
+ @Snippet
+ private static boolean longArraysEquals(Pointer array1, Pointer array2, int length) {
+ return ArrayEqualsNode.equals(array1, array2, length, JavaKind.Long);
+ }
+
+ @Snippet
+ private static boolean floatArraysEquals(Pointer array1, Pointer array2, int length) {
+ return ArrayEqualsNode.equals(array1, array2, length, JavaKind.Float);
+ }
+
+ @Snippet
+ private static boolean doubleArraysEquals(Pointer array1, Pointer array2, int length) {
+ return ArrayEqualsNode.equals(array1, array2, length, JavaKind.Double);
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java Thu Mar 21 18:04:01 2019 +0000
@@ -25,6 +25,7 @@
package org.graalvm.compiler.hotspot.amd64;
import static jdk.vm.ci.common.InitTimer.timer;
+import static org.graalvm.compiler.serviceprovider.JavaVersionUtil.JAVA_SPECIFICATION_VERSION;
import java.util.ArrayList;
import java.util.List;
@@ -160,7 +161,7 @@
HotSpotConstantReflectionProvider constantReflection, HotSpotHostForeignCallsProvider foreignCalls, HotSpotMetaAccessProvider metaAccess,
HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes) {
Plugins plugins = HotSpotGraphBuilderPlugins.create(compilerConfiguration, config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, replacements);
- AMD64GraphBuilderPlugins.register(plugins, replacements.getDefaultReplacementBytecodeProvider(), (AMD64) target.arch, false);
+ AMD64GraphBuilderPlugins.register(plugins, replacements.getDefaultReplacementBytecodeProvider(), (AMD64) target.arch, false, JAVA_SPECIFICATION_VERSION >= 9);
return plugins;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -121,6 +121,22 @@
link(new AMD64ArrayIndexOfStub(AMD64ArrayIndexOf.STUB_INDEX_OF_4_CHARS, options, providers,
registerStubCall(AMD64ArrayIndexOf.STUB_INDEX_OF_4_CHARS, LEAF, REEXECUTABLE, NO_LOCATIONS)));
+ link(new AMD64ArrayEqualsStub(AMD64ArrayEqualsStub.STUB_BOOLEAN_ARRAY_EQUALS, options, providers,
+ registerStubCall(AMD64ArrayEqualsStub.STUB_BOOLEAN_ARRAY_EQUALS, LEAF, REEXECUTABLE, NO_LOCATIONS)));
+ link(new AMD64ArrayEqualsStub(AMD64ArrayEqualsStub.STUB_BYTE_ARRAY_EQUALS, options, providers,
+ registerStubCall(AMD64ArrayEqualsStub.STUB_BYTE_ARRAY_EQUALS, LEAF, REEXECUTABLE, NO_LOCATIONS)));
+ link(new AMD64ArrayEqualsStub(AMD64ArrayEqualsStub.STUB_CHAR_ARRAY_EQUALS, options, providers,
+ registerStubCall(AMD64ArrayEqualsStub.STUB_CHAR_ARRAY_EQUALS, LEAF, REEXECUTABLE, NO_LOCATIONS)));
+ link(new AMD64ArrayEqualsStub(AMD64ArrayEqualsStub.STUB_SHORT_ARRAY_EQUALS, options, providers,
+ registerStubCall(AMD64ArrayEqualsStub.STUB_SHORT_ARRAY_EQUALS, LEAF, REEXECUTABLE, NO_LOCATIONS)));
+ link(new AMD64ArrayEqualsStub(AMD64ArrayEqualsStub.STUB_INT_ARRAY_EQUALS, options, providers,
+ registerStubCall(AMD64ArrayEqualsStub.STUB_INT_ARRAY_EQUALS, LEAF, REEXECUTABLE, NO_LOCATIONS)));
+ link(new AMD64ArrayEqualsStub(AMD64ArrayEqualsStub.STUB_LONG_ARRAY_EQUALS, options, providers,
+ registerStubCall(AMD64ArrayEqualsStub.STUB_LONG_ARRAY_EQUALS, LEAF, REEXECUTABLE, NO_LOCATIONS)));
+ link(new AMD64ArrayEqualsStub(AMD64ArrayEqualsStub.STUB_FLOAT_ARRAY_EQUALS, options, providers,
+ registerStubCall(AMD64ArrayEqualsStub.STUB_FLOAT_ARRAY_EQUALS, LEAF, REEXECUTABLE, NO_LOCATIONS)));
+ link(new AMD64ArrayEqualsStub(AMD64ArrayEqualsStub.STUB_DOUBLE_ARRAY_EQUALS, options, providers,
+ registerStubCall(AMD64ArrayEqualsStub.STUB_DOUBLE_ARRAY_EQUALS, LEAF, REEXECUTABLE, NO_LOCATIONS)));
super.initialize(providers, options);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -676,4 +676,32 @@
protected StrategySwitchOp createStrategySwitchOp(SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Variable key, AllocatableValue temp) {
return new AMD64HotSpotStrategySwitchOp(strategy, keyTargets, defaultTarget, key, temp);
}
+
+ @Override
+ public ForeignCallLinkage lookupArrayEqualsStub(JavaKind kind, int constantLength) {
+ if (constantLength >= 0 && constantLength * kind.getByteCount() < 2 * getMaxVectorSize()) {
+ // Yield constant-length arrays comparison assembly
+ return null;
+ }
+ switch (kind) {
+ case Boolean:
+ return getForeignCalls().lookupForeignCall(AMD64ArrayEqualsStub.STUB_BOOLEAN_ARRAY_EQUALS);
+ case Byte:
+ return getForeignCalls().lookupForeignCall(AMD64ArrayEqualsStub.STUB_BYTE_ARRAY_EQUALS);
+ case Char:
+ return getForeignCalls().lookupForeignCall(AMD64ArrayEqualsStub.STUB_CHAR_ARRAY_EQUALS);
+ case Short:
+ return getForeignCalls().lookupForeignCall(AMD64ArrayEqualsStub.STUB_SHORT_ARRAY_EQUALS);
+ case Int:
+ return getForeignCalls().lookupForeignCall(AMD64ArrayEqualsStub.STUB_INT_ARRAY_EQUALS);
+ case Long:
+ return getForeignCalls().lookupForeignCall(AMD64ArrayEqualsStub.STUB_LONG_ARRAY_EQUALS);
+ case Float:
+ return getForeignCalls().lookupForeignCall(AMD64ArrayEqualsStub.STUB_FLOAT_ARRAY_EQUALS);
+ case Double:
+ return getForeignCalls().lookupForeignCall(AMD64ArrayEqualsStub.STUB_DOUBLE_ARRAY_EQUALS);
+ default:
+ return null;
+ }
+ }
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.jdk9.test/src/org/graalvm/compiler/hotspot/jdk9/test/StringUTF16ToBytesGetCharsTest.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.jdk9.test/src/org/graalvm/compiler/hotspot/jdk9/test/StringUTF16ToBytesGetCharsTest.java Thu Mar 21 18:04:01 2019 +0000
@@ -26,8 +26,6 @@
import static org.junit.Assume.assumeFalse;
-import jdk.vm.ci.code.InstalledCode;
-import jdk.vm.ci.meta.ResolvedJavaMethod;
import org.graalvm.compiler.core.common.CompilationIdentifier;
import org.graalvm.compiler.hotspot.replacements.StringUTF16Substitutions;
import org.graalvm.compiler.nodes.StructuredGraph;
@@ -35,9 +33,11 @@
import org.graalvm.compiler.replacements.arraycopy.ArrayCopyCallNode;
import org.graalvm.compiler.replacements.test.MethodSubstitutionTest;
import org.graalvm.compiler.test.AddExports;
-import org.junit.Before;
import org.junit.Test;
+import jdk.vm.ci.code.InstalledCode;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+
/**
* Test substitutions for (innate) methods StringUTF16.toBytes and StringUTF16.getChars provided by
* {@link StringUTF16Substitutions}.
@@ -48,8 +48,7 @@
private static final int N = 1000;
private static final int N_OVERFLOW = 10;
- @Before
- public void checkAMD64() {
+ public StringUTF16ToBytesGetCharsTest() {
assumeFalse(Java8OrEarlier);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/BigIntegerIntrinsicsTest.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/BigIntegerIntrinsicsTest.java Thu Mar 21 18:04:01 2019 +0000
@@ -21,6 +21,8 @@
* questions.
*/
+
+
package org.graalvm.compiler.hotspot.test;
import java.lang.reflect.InvocationTargetException;
@@ -193,8 +195,7 @@
Object invokeCode(Object... args) {
try {
return testcode.executeVarargs(args);
- }
- catch (InvalidInstalledCodeException e) {
+ } catch (InvalidInstalledCodeException e) {
// Ensure the installed code is valid, possibly recompiled.
testcode = getCode(testmethod);
@@ -208,8 +209,7 @@
private Object invokeSafe(ResolvedJavaMethod method, Object receiver, Object... args) {
try {
return invoke(method, receiver, args);
- } catch (IllegalAccessException | InvocationTargetException |
- IllegalArgumentException | InstantiationException e) {
+ } catch (IllegalAccessException | InvocationTargetException | IllegalArgumentException | InstantiationException e) {
throw new RuntimeException(e);
}
}
@@ -220,8 +220,7 @@
private InstalledCode testcode;
}
- private static GraalHotSpotVMConfig config =
- ((HotSpotGraalRuntimeProvider) Graal.getRequiredCapability(RuntimeProvider.class)).getVMConfig();
+ private static GraalHotSpotVMConfig config = ((HotSpotGraalRuntimeProvider) Graal.getRequiredCapability(RuntimeProvider.class)).getVMConfig();
private static BigInteger bigTwo = BigInteger.valueOf(2);
private static Random rnd = new Random(17);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java Thu Mar 21 18:04:01 2019 +0000
@@ -26,7 +26,7 @@
import static java.util.Collections.singletonList;
import static org.graalvm.compiler.core.CompilationWrapper.ExceptionAction.Print;
-import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAction;
+import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAsFailure;
import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationFailureAction;
import static org.graalvm.compiler.core.test.ReflectionOptionDescriptors.extractEntries;
import static org.graalvm.compiler.debug.MemUseTrackerKey.getCurrentThreadAllocatedBytes;
@@ -215,7 +215,7 @@
compilationOptionsCopy.putAll(compilationOptions);
// We want to see stack traces when a method fails to compile
- CompilationBailoutAction.putIfAbsent(compilationOptionsCopy, Print);
+ CompilationBailoutAsFailure.putIfAbsent(compilationOptionsCopy, true);
CompilationFailureAction.putIfAbsent(compilationOptionsCopy, Print);
// By default only report statistics for the CTW threads themselves
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorldTest.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorldTest.java Thu Mar 21 18:04:01 2019 +0000
@@ -24,7 +24,7 @@
package org.graalvm.compiler.hotspot.test;
-import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAction;
+import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAsFailure;
import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationFailureAction;
import jdk.internal.vm.compiler.collections.EconomicMap;
@@ -44,7 +44,7 @@
@Test
public void testJDK() throws Throwable {
- ExceptionAction originalBailoutAction = CompilationBailoutAction.getValue(getInitialOptions());
+ boolean originalBailoutAction = CompilationBailoutAsFailure.getValue(getInitialOptions());
ExceptionAction originalFailureAction = CompilationFailureAction.getValue(getInitialOptions());
// Compile a couple classes in rt.jar
HotSpotJVMCIRuntime runtime = HotSpotJVMCIRuntime.runtime();
@@ -52,7 +52,7 @@
OptionValues initialOptions = getInitialOptions();
EconomicMap<OptionKey<?>, Object> compilationOptions = CompileTheWorld.parseOptions("Inline=false");
new CompileTheWorld(runtime, (HotSpotGraalCompiler) runtime.getCompiler(), CompileTheWorld.SUN_BOOT_CLASS_PATH, 1, 5, null, null, false, initialOptions, compilationOptions).compile();
- assert CompilationBailoutAction.getValue(initialOptions) == originalBailoutAction;
+ assert CompilationBailoutAsFailure.getValue(initialOptions) == originalBailoutAction;
assert CompilationFailureAction.getValue(initialOptions) == originalFailureAction;
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTestBase.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTestBase.java Thu Mar 21 18:04:01 2019 +0000
@@ -31,7 +31,6 @@
import org.graalvm.compiler.bytecode.BytecodeDisassembler;
import org.graalvm.compiler.bytecode.BytecodeStream;
import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecode;
-import org.graalvm.compiler.core.CompilationWrapper.ExceptionAction;
import org.graalvm.compiler.core.GraalCompilerOptions;
import org.graalvm.compiler.core.target.Backend;
import org.graalvm.compiler.core.test.GraalCompilerTest;
@@ -134,8 +133,8 @@
OptionValues goptions = options;
// Silence diagnostics for permanent bailout errors as they
// are expected for some OSR tests.
- if (!GraalCompilerOptions.CompilationBailoutAction.hasBeenSet(options)) {
- goptions = new OptionValues(options, GraalCompilerOptions.CompilationBailoutAction, ExceptionAction.Silent);
+ if (!GraalCompilerOptions.CompilationBailoutAsFailure.hasBeenSet(options)) {
+ goptions = new OptionValues(options, GraalCompilerOptions.CompilationBailoutAsFailure, false);
}
// ensure eager resolving
StructuredGraph graph = parseEager(method, AllowAssumptions.YES, goptions);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java Thu Mar 21 18:04:01 2019 +0000
@@ -26,7 +26,7 @@
import static org.graalvm.compiler.core.CompilationWrapper.ExceptionAction.Diagnose;
import static org.graalvm.compiler.core.CompilationWrapper.ExceptionAction.ExitVM;
-import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAction;
+import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAsFailure;
import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationFailureAction;
import static org.graalvm.compiler.core.phases.HighTier.Options.Inline;
import static org.graalvm.compiler.java.BytecodeParserOptions.InlineDuringParsing;
@@ -47,7 +47,6 @@
import org.graalvm.compiler.debug.DebugDumpScope;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.debug.TimerKey;
-import org.graalvm.compiler.options.EnumOptionKey;
import org.graalvm.compiler.options.OptionKey;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.printer.GraalDebugHandlersFactory;
@@ -145,25 +144,34 @@
}
@Override
- protected ExceptionAction lookupAction(OptionValues values, EnumOptionKey<ExceptionAction> actionKey, Throwable cause) {
- // Respect current action if it has been explicitly set.
- if (!actionKey.hasBeenSet(values)) {
- if (actionKey == CompilationFailureAction) {
- // Automatically exit on non-bailout during bootstrap
- // or when assertions are enabled.
- if (Assertions.assertionsEnabled() || compiler.getGraalRuntime().isBootstrapping()) {
- return ExitVM;
- }
- } else if (actionKey == CompilationBailoutAction && ((BailoutException) cause).isPermanent()) {
- // Get more info for permanent bailouts during bootstrap
- // or when assertions are enabled.
- assert CompilationBailoutAction.getDefaultValue() == ExceptionAction.Silent;
- if (Assertions.assertionsEnabled() || compiler.getGraalRuntime().isBootstrapping()) {
- return Diagnose;
+ protected ExceptionAction lookupAction(OptionValues values, Throwable cause) {
+ if (cause instanceof BailoutException) {
+ BailoutException bailout = (BailoutException) cause;
+ if (bailout.isPermanent()) {
+ // Respect current action if it has been explicitly set.
+ if (!CompilationBailoutAsFailure.hasBeenSet(values)) {
+ // Get more info for permanent bailouts during bootstrap
+ // or when assertions are enabled.
+ if (Assertions.assertionsEnabled() || compiler.getGraalRuntime().isBootstrapping()) {
+ return Diagnose;
+ }
+
}
}
+ if (!CompilationBailoutAsFailure.getValue(values)) {
+ return super.lookupAction(values, cause);
+ }
}
- return super.lookupAction(values, actionKey, cause);
+
+ // Respect current action if it has been explicitly set.
+ if (!CompilationFailureAction.hasBeenSet(values)) {
+ // Automatically exit on failure during bootstrap
+ // or when assertions are enabled.
+ if (Assertions.assertionsEnabled() || compiler.getGraalRuntime().isBootstrapping()) {
+ return ExitVM;
+ }
+ }
+ return super.lookupAction(values, cause);
}
@SuppressWarnings("try")
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalOptionValues.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalOptionValues.java Thu Mar 21 18:04:01 2019 +0000
@@ -41,6 +41,7 @@
import jdk.vm.ci.common.InitTimer;
import jdk.vm.ci.common.NativeImageReinitialize;
+import jdk.vm.ci.services.Services;
/**
* The {@link #defaultOptions()} method returns the options values initialized in a HotSpot VM. The
@@ -89,15 +90,14 @@
}
/**
- * Global options. The values for these options are initialized by parsing the file denoted by
- * the {@code VM.getSavedProperty(String) saved} system property named
- * {@value #GRAAL_OPTIONS_FILE_PROPERTY_NAME} if the file exists followed by parsing the options
- * encoded in saved system properties whose names start with
- * {@value #GRAAL_OPTION_PROPERTY_PREFIX}. Key/value pairs are parsed from the aforementioned
- * file with {@link Properties#load(java.io.Reader)}.
+ * Gets and parses options based on {@linkplain Services#getSavedProperties() saved system
+ * properties}. The values for these options are initialized by parsing the file denoted by the
+ * {@value #GRAAL_OPTIONS_FILE_PROPERTY_NAME} property followed by parsing the options encoded
+ * in properties whose names start with {@value #GRAAL_OPTION_PROPERTY_PREFIX}. Key/value pairs
+ * are parsed from the aforementioned file with {@link Properties#load(java.io.Reader)}.
*/
@SuppressWarnings("try")
- private static OptionValues initializeOptions() {
+ public static EconomicMap<OptionKey<?>, Object> parseOptions() {
EconomicMap<OptionKey<?>, Object> values = OptionValues.newOptionMap();
try (InitTimer t = timer("InitializeOptions")) {
@@ -142,7 +142,17 @@
}
OptionsParser.parseOptions(optionSettings, values, loader);
- return new OptionValues(values);
+ return values;
}
}
+
+ /**
+ * Substituted by
+ * {@code com.oracle.svm.graal.hotspot.libgraal.Target_org_graalvm_compiler_hotspot_HotSpotGraalOptionValues}
+ * to update {@code com.oracle.svm.core.option.RuntimeOptionValues.singleton()} instead of
+ * creating a new {@link OptionValues} object.
+ */
+ private static OptionValues initializeOptions() {
+ return new OptionValues(parseOptions());
+ }
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ArrayIndexOfOp.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ArrayIndexOfOp.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, 2019 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGeneratorTool.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGeneratorTool.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -269,6 +269,11 @@
Variable emitArrayEquals(JavaKind kind, Value array1, Value array2, Value length, int constantLength, boolean directPointers);
@SuppressWarnings("unused")
+ default ForeignCallLinkage lookupArrayEqualsStub(JavaKind kind, int constantLength) {
+ return null;
+ }
+
+ @SuppressWarnings("unused")
default Variable emitArrayEquals(JavaKind kind1, JavaKind kind2, Value array1, Value array2, Value length, int constantLength, boolean directPointers) {
throw GraalError.unimplemented("Array.equals with different types substitution is not implemented on this architecture");
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/UnsignedRightShiftNode.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/UnsignedRightShiftNode.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -24,6 +24,7 @@
package org.graalvm.compiler.nodes.calc;
+import jdk.vm.ci.code.CodeUtil;
import org.graalvm.compiler.core.common.type.ArithmeticOpTable;
import org.graalvm.compiler.core.common.type.ArithmeticOpTable.ShiftOp.UShr;
import org.graalvm.compiler.core.common.type.IntegerStamp;
@@ -84,10 +85,13 @@
Stamp xStampGeneric = forX.stamp(view);
if (xStampGeneric instanceof IntegerStamp) {
IntegerStamp xStamp = (IntegerStamp) xStampGeneric;
+ long xMask = CodeUtil.mask(xStamp.getBits());
+ long xLowerBound = xStamp.lowerBound() & xMask;
+ long xUpperBound = xStamp.upperBound() & xMask;
- if (xStamp.lowerBound() >>> amount == xStamp.upperBound() >>> amount) {
+ if (xLowerBound >>> amount == xUpperBound >>> amount) {
// The result of the shift is constant.
- return ConstantNode.forIntegerKind(stamp.getStackKind(), xStamp.lowerBound() >>> amount);
+ return ConstantNode.forIntegerKind(stamp.getStackKind(), xLowerBound >>> amount);
}
if (amount == xStamp.getBits() - 1 && xStamp.lowerBound() == -1 && xStamp.upperBound() == 0) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64GraphBuilderPlugins.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64GraphBuilderPlugins.java Thu Mar 21 18:04:01 2019 +0000
@@ -32,7 +32,6 @@
import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.LOG10;
import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.SIN;
import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.TAN;
-import static org.graalvm.compiler.serviceprovider.JavaVersionUtil.JAVA_SPECIFICATION_VERSION;
import static org.graalvm.compiler.serviceprovider.JavaVersionUtil.Java11OrEarlier;
import static org.graalvm.compiler.serviceprovider.JavaVersionUtil.Java8OrEarlier;
@@ -71,7 +70,7 @@
public class AMD64GraphBuilderPlugins {
- public static void register(Plugins plugins, BytecodeProvider replacementsBytecodeProvider, AMD64 arch, boolean explicitUnsafeNullChecks) {
+ public static void register(Plugins plugins, BytecodeProvider replacementsBytecodeProvider, AMD64 arch, boolean explicitUnsafeNullChecks, boolean emitJDK9StringSubstitutions) {
InvocationPlugins invocationPlugins = plugins.getInvocationPlugins();
invocationPlugins.defer(new Runnable() {
@Override
@@ -83,8 +82,10 @@
new JavaKind[]{JavaKind.Int, JavaKind.Long, JavaKind.Object, JavaKind.Boolean, JavaKind.Byte, JavaKind.Short, JavaKind.Char, JavaKind.Float, JavaKind.Double});
registerUnsafePlugins(invocationPlugins, replacementsBytecodeProvider, explicitUnsafeNullChecks);
registerStringPlugins(invocationPlugins, replacementsBytecodeProvider);
- registerStringLatin1Plugins(invocationPlugins, replacementsBytecodeProvider);
- registerStringUTF16Plugins(invocationPlugins, replacementsBytecodeProvider);
+ if (emitJDK9StringSubstitutions) {
+ registerStringLatin1Plugins(invocationPlugins, replacementsBytecodeProvider);
+ registerStringUTF16Plugins(invocationPlugins, replacementsBytecodeProvider);
+ }
registerMathPlugins(invocationPlugins, arch, replacementsBytecodeProvider);
registerArraysEqualsPlugins(invocationPlugins, replacementsBytecodeProvider);
}
@@ -215,30 +216,26 @@
}
private static void registerStringLatin1Plugins(InvocationPlugins plugins, BytecodeProvider replacementsBytecodeProvider) {
- if (JAVA_SPECIFICATION_VERSION >= 9) {
- Registration r = new Registration(plugins, "java.lang.StringLatin1", replacementsBytecodeProvider);
- r.setAllowOverwrite(true);
- r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "compareTo", byte[].class, byte[].class);
- r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "compareToUTF16", byte[].class, byte[].class);
- r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "inflate", byte[].class, int.class, char[].class, int.class, int.class);
- r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "inflate", byte[].class, int.class, byte[].class, int.class, int.class);
- r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "indexOf", byte[].class, int.class, int.class);
- r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "indexOf", byte[].class, int.class, byte[].class, int.class, int.class);
- }
+ Registration r = new Registration(plugins, "java.lang.StringLatin1", replacementsBytecodeProvider);
+ r.setAllowOverwrite(true);
+ r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "compareTo", byte[].class, byte[].class);
+ r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "compareToUTF16", byte[].class, byte[].class);
+ r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "inflate", byte[].class, int.class, char[].class, int.class, int.class);
+ r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "inflate", byte[].class, int.class, byte[].class, int.class, int.class);
+ r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "indexOf", byte[].class, int.class, int.class);
+ r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "indexOf", byte[].class, int.class, byte[].class, int.class, int.class);
}
private static void registerStringUTF16Plugins(InvocationPlugins plugins, BytecodeProvider replacementsBytecodeProvider) {
- if (JAVA_SPECIFICATION_VERSION >= 9) {
- Registration r = new Registration(plugins, "java.lang.StringUTF16", replacementsBytecodeProvider);
- r.setAllowOverwrite(true);
- r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "compareTo", byte[].class, byte[].class);
- r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "compareToLatin1", byte[].class, byte[].class);
- r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "compress", char[].class, int.class, byte[].class, int.class, int.class);
- r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "compress", byte[].class, int.class, byte[].class, int.class, int.class);
- r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "indexOfCharUnsafe", byte[].class, int.class, int.class, int.class);
- r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "indexOfUnsafe", byte[].class, int.class, byte[].class, int.class, int.class);
- r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "indexOfLatin1Unsafe", byte[].class, int.class, byte[].class, int.class, int.class);
- }
+ Registration r = new Registration(plugins, "java.lang.StringUTF16", replacementsBytecodeProvider);
+ r.setAllowOverwrite(true);
+ r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "compareTo", byte[].class, byte[].class);
+ r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "compareToLatin1", byte[].class, byte[].class);
+ r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "compress", char[].class, int.class, byte[].class, int.class, int.class);
+ r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "compress", byte[].class, int.class, byte[].class, int.class, int.class);
+ r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "indexOfCharUnsafe", byte[].class, int.class, int.class, int.class);
+ r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "indexOfUnsafe", byte[].class, int.class, byte[].class, int.class, int.class);
+ r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "indexOfLatin1Unsafe", byte[].class, int.class, byte[].class, int.class, int.class);
}
private static void registerUnsafePlugins(InvocationPlugins plugins, BytecodeProvider replacementsBytecodeProvider, boolean explicitUnsafeNullChecks) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ArrayEqualsNode.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ArrayEqualsNode.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,11 +26,14 @@
import static org.graalvm.compiler.nodeinfo.InputType.Memory;
+import org.graalvm.compiler.api.replacements.Snippet;
+import org.graalvm.compiler.core.common.spi.ForeignCallLinkage;
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.graph.spi.Canonicalizable;
import org.graalvm.compiler.graph.spi.CanonicalizerTool;
+import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
import org.graalvm.compiler.nodeinfo.NodeCycles;
import org.graalvm.compiler.nodeinfo.NodeInfo;
import org.graalvm.compiler.nodeinfo.NodeSize;
@@ -48,11 +51,14 @@
import org.graalvm.compiler.nodes.spi.VirtualizerTool;
import org.graalvm.compiler.nodes.util.GraphUtil;
import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
+import org.graalvm.compiler.options.Option;
+import org.graalvm.compiler.options.OptionKey;
import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.meta.ConstantReflectionProvider;
import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.Value;
// JaCoCo Exclude
@@ -63,6 +69,13 @@
@NodeInfo(cycles = NodeCycles.CYCLES_UNKNOWN, size = NodeSize.SIZE_128)
public final class ArrayEqualsNode extends FixedWithNextNode implements LIRLowerable, Canonicalizable, Virtualizable, MemoryAccess {
+ public static class Options {
+ // @formatter:off
+ @Option(help = "Use Array equals stubs instead of embedding all the emitted code.")
+ public static final OptionKey<Boolean> ArrayEqualsStubs = new OptionKey<>(true);
+ // @formatter:on
+ }
+
public static final NodeClass<ArrayEqualsNode> TYPE = NodeClass.create(ArrayEqualsNode.class);
/** {@link JavaKind} of the arrays to compare. */
protected final JavaKind kind;
@@ -178,7 +191,7 @@
}
@NodeIntrinsic
- static native boolean equals(Object array1, Object array2, int length, @ConstantNodeParameter JavaKind kind);
+ public static native boolean equals(Object array1, Object array2, int length, @ConstantNodeParameter JavaKind kind);
public static boolean equals(boolean[] array1, boolean[] array2, int length) {
return equals(array1, array2, length, JavaKind.Boolean);
@@ -214,11 +227,25 @@
@Override
public void generate(NodeLIRBuilderTool gen) {
+ LIRGeneratorTool tool = gen.getLIRGeneratorTool();
int constantLength = -1;
if (length.isConstant()) {
constantLength = length.asJavaConstant().asInt();
}
- Value result = gen.getLIRGeneratorTool().emitArrayEquals(kind, gen.operand(array1), gen.operand(array2), gen.operand(length), constantLength, false);
+
+ if (Options.ArrayEqualsStubs.getValue(graph().getOptions())) {
+ ResolvedJavaMethod method = graph().method();
+ if (method != null && method.getAnnotation(Snippet.class) == null) {
+ ForeignCallLinkage linkage = tool.lookupArrayEqualsStub(kind, constantLength);
+ if (linkage != null) {
+ Value result = tool.emitForeignCall(linkage, null, gen.operand(array1), gen.operand(array2), gen.operand(length));
+ gen.setResult(this, result);
+ return;
+ }
+ }
+ }
+
+ Value result = tool.emitArrayEquals(kind, gen.operand(array1), gen.operand(array2), gen.operand(length), constantLength, false);
gen.setResult(this, result);
}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/BaseConfiguration.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/BaseConfiguration.java Thu Mar 21 18:04:01 2019 +0000
@@ -837,39 +837,47 @@
tagletManager = tagletManager == null ?
new TagletManager(nosince, showversion, showauthor, javafx, this) :
tagletManager;
- for (List<String> args : customTagStrs) {
- if (args.get(0).equals("-taglet")) {
- tagletManager.addCustomTag(args.get(1), getFileManager(), tagletpath);
- continue;
+ JavaFileManager fileManager = getFileManager();
+ Messages messages = getMessages();
+ try {
+ tagletManager.initTagletPath(fileManager, tagletpath);
+ tagletManager.loadTaglets(fileManager);
+
+ for (List<String> args : customTagStrs) {
+ if (args.get(0).equals("-taglet")) {
+ tagletManager.addCustomTag(args.get(1), fileManager);
+ continue;
+ }
+ List<String> tokens = tokenize(args.get(1), TagletManager.SIMPLE_TAGLET_OPT_SEPARATOR, 3);
+ switch (tokens.size()) {
+ case 1:
+ String tagName = args.get(1);
+ if (tagletManager.isKnownCustomTag(tagName)) {
+ //reorder a standard tag
+ tagletManager.addNewSimpleCustomTag(tagName, null, "");
+ } else {
+ //Create a simple tag with the heading that has the same name as the tag.
+ StringBuilder heading = new StringBuilder(tagName + ":");
+ heading.setCharAt(0, Character.toUpperCase(tagName.charAt(0)));
+ tagletManager.addNewSimpleCustomTag(tagName, heading.toString(), "a");
+ }
+ break;
+
+ case 2:
+ //Add simple taglet without heading, probably to excluding it in the output.
+ tagletManager.addNewSimpleCustomTag(tokens.get(0), tokens.get(1), "");
+ break;
+
+ case 3:
+ tagletManager.addNewSimpleCustomTag(tokens.get(0), tokens.get(2), tokens.get(1));
+ break;
+
+ default:
+ messages.error("doclet.Error_invalid_custom_tag_argument", args.get(1));
+ }
}
- List<String> tokens = tokenize(args.get(1), TagletManager.SIMPLE_TAGLET_OPT_SEPARATOR, 3);
- switch (tokens.size()) {
- case 1:
- String tagName = args.get(1);
- if (tagletManager.isKnownCustomTag(tagName)) {
- //reorder a standard tag
- tagletManager.addNewSimpleCustomTag(tagName, null, "");
- } else {
- //Create a simple tag with the heading that has the same name as the tag.
- StringBuilder heading = new StringBuilder(tagName + ":");
- heading.setCharAt(0, Character.toUpperCase(tagName.charAt(0)));
- tagletManager.addNewSimpleCustomTag(tagName, heading.toString(), "a");
- }
- break;
-
- case 2:
- //Add simple taglet without heading, probably to excluding it in the output.
- tagletManager.addNewSimpleCustomTag(tokens.get(0), tokens.get(1), "");
- break;
-
- case 3:
- tagletManager.addNewSimpleCustomTag(tokens.get(0), tokens.get(2), tokens.get(1));
- break;
-
- default:
- Messages messages = getMessages();
- messages.error("doclet.Error_invalid_custom_tag_argument", args.get(1));
- }
+ } catch (IOException e) {
+ messages.error("doclet.taglet_could_not_set_location", e.toString());
}
}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties Thu Mar 21 08:41:10 2019 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties Thu Mar 21 18:04:01 2019 +0000
@@ -56,6 +56,8 @@
doclet.Notice_taglet_conflict_warn=Note: Custom tags that could override future standard tags: {0}. To avoid potential overrides, use at least one period character (.) in custom tag names.
doclet.Error_taglet_not_registered=Error - Exception {0} thrown while trying to register Taglet {1}...
doclet.Error_invalid_custom_tag_argument=Error - {0} is an invalid argument to the -tag option...
+doclet.taglet_could_not_set_location = Could not set the taglet path: {0}
+doclet.not_standard_file_manager = Cannot set taglet path; the file manager is not a StandardJavaFileManager
doclet.Author=Author:
doclet.DefaultValue=Default value:
doclet.PropertyDescription=Property description:
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/TagletManager.java Thu Mar 21 08:41:10 2019 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/TagletManager.java Thu Mar 21 18:04:01 2019 +0000
@@ -204,45 +204,78 @@
}
/**
- * Add a new {@code Taglet}. Print a message to indicate whether or not
+ * Initializes the location TAGLET_PATH which is used to locate the custom taglets.
+ * @param fileManager the filemanager to load classes and resources.
+ * @param tagletPath the path to the custom taglet.
+ * @throws IOException if an error occurs while setting the location.
+ */
+ public void initTagletPath(JavaFileManager fileManager, String tagletPath) throws IOException {
+ if (fileManager instanceof StandardJavaFileManager) {
+ StandardJavaFileManager sfm = (StandardJavaFileManager)fileManager;
+ if (tagletPath != null) {
+ List<File> paths = new ArrayList<>();
+ for (String pathname : tagletPath.split(File.pathSeparator)) {
+ paths.add(new File(pathname));
+ }
+ sfm.setLocation(TAGLET_PATH, paths);
+ } else if (!sfm.hasLocation(TAGLET_PATH)) {
+ sfm.setLocation(TAGLET_PATH, Collections.emptyList());
+ }
+ } else if (tagletPath != null) {
+ messages.error("doclet.not_standard_file_manager");
+ }
+ }
+
+ /**
+ * Adds a new {@code Taglet}. Print a message to indicate whether or not
* the Taglet was registered properly.
* @param classname the name of the class representing the custom tag.
* @param fileManager the filemanager to load classes and resources.
- * @param tagletPath the path to the class representing the custom tag.
*/
- public void addCustomTag(String classname, JavaFileManager fileManager, String tagletPath) {
+ public void addCustomTag(String classname, JavaFileManager fileManager) {
try {
ClassLoader tagClassLoader;
- if (!fileManager.hasLocation(TAGLET_PATH)) {
- List<File> paths = new ArrayList<>();
- if (tagletPath != null) {
- for (String pathname : tagletPath.split(File.pathSeparator)) {
- paths.add(new File(pathname));
- }
- }
- if (fileManager instanceof StandardJavaFileManager) {
- ((StandardJavaFileManager) fileManager).setLocation(TAGLET_PATH, paths);
- }
- }
tagClassLoader = fileManager.getClassLoader(TAGLET_PATH);
Class<? extends jdk.javadoc.doclet.Taglet> customTagClass =
tagClassLoader.loadClass(classname).asSubclass(jdk.javadoc.doclet.Taglet.class);
jdk.javadoc.doclet.Taglet instance = customTagClass.getConstructor().newInstance();
- instance.init(docEnv, doclet);
- Taglet newLegacy = new UserTaglet(instance);
- String tname = newLegacy.getName();
- Taglet t = allTaglets.get(tname);
- if (t != null) {
- allTaglets.remove(tname);
+ registerTaglet(instance);
+ } catch (ReflectiveOperationException exc) {
+ messages.error("doclet.Error_taglet_not_registered", exc.getClass().getName(),
+ classname);
+ }
+ }
+
+ /**
+ * Loads taglets from a taglet path using service loader.
+ * @param fileManager the filemanager to load the taglets.
+ * @throws IOException if an error occurs while getting the service loader.
+ */
+ public void loadTaglets(JavaFileManager fileManager) throws IOException {
+ Iterable<? extends File> location = ((StandardJavaFileManager)fileManager).getLocation(TAGLET_PATH);
+ if (location != null && location.iterator().hasNext()) {
+ ServiceLoader<jdk.javadoc.doclet.Taglet> serviceLoader =
+ fileManager.getServiceLoader(TAGLET_PATH, jdk.javadoc.doclet.Taglet.class);
+ Iterator<jdk.javadoc.doclet.Taglet> iterator = serviceLoader.iterator();
+ while (iterator.hasNext()) {
+ jdk.javadoc.doclet.Taglet taglet = iterator.next();
+ registerTaglet(taglet);
}
- allTaglets.put(tname, newLegacy);
- messages.notice("doclet.Notice_taglet_registered", classname);
- } catch (Exception exc) {
- messages.error("doclet.Error_taglet_not_registered", exc.getClass().getName(), classname);
}
}
/**
+ * Registers the {@code Taglet}. Prints a message if a {@code Taglet} got registered properly.
+ * @param instance the {@code Taglet} instance.
+ */
+ private void registerTaglet(jdk.javadoc.doclet.Taglet instance) {
+ instance.init(docEnv, doclet);
+ Taglet newLegacy = new UserTaglet(instance);
+ allTaglets.put(newLegacy.getName(), newLegacy);
+ messages.notice("doclet.Notice_taglet_registered", instance.getClass().getName());
+ }
+
+ /**
* Add a new {@code SimpleTaglet}. If this tag already exists
* and the header passed as an argument is null, move tag to the back of the
* list. If this tag already exists and the header passed as an argument is
--- a/src/utils/hsdis/Makefile Thu Mar 21 08:41:10 2019 +0000
+++ b/src/utils/hsdis/Makefile Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# The Universal Permissive License (UPL), Version 1.0
@@ -201,6 +201,10 @@
$(TARGET_DIR)/opcodes/libopcodes.a \
$(TARGET_DIR)/libiberty/libiberty.a
+ifneq ($(MINGW),)
+LIBRARIES += $(TARGET_DIR)/zlib/libz.a
+endif
+
DEMO_TARGET = $(TARGET_DIR)/hsdis-demo
DEMO_SOURCE = hsdis-demo.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/gtest/gc/z/test_zForwarding.cpp Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "precompiled.hpp"
+#include "gc/z/zAddress.inline.hpp"
+#include "gc/z/zForwarding.inline.hpp"
+#include "gc/z/zGlobals.hpp"
+#include "gc/z/zPage.inline.hpp"
+#include "unittest.hpp"
+
+using namespace testing;
+
+#define CAPTURE_DELIM "\n"
+#define CAPTURE1(expression) #expression << " evaluates to " << expression
+#define CAPTURE2(e0, e1) CAPTURE1(e0) << CAPTURE_DELIM << CAPTURE1(e1)
+
+#define CAPTURE(expression) CAPTURE1(expression)
+
+class ZForwardingTest : public Test {
+public:
+ // Helper functions
+
+ static bool is_power_of_2(uint32_t value) {
+ return ::is_power_of_2((intptr_t)value);
+ }
+
+ class SequenceToFromIndex : AllStatic {
+ public:
+ static uintptr_t even(uint32_t sequence_number) {
+ return sequence_number * 2;
+ }
+ static uintptr_t odd(uint32_t sequence_number) {
+ return even(sequence_number) + 1;
+ }
+ static uintptr_t one_to_one(uint32_t sequence_number) {
+ return sequence_number;
+ }
+ };
+
+ // Test functions
+
+ static void setup(ZForwarding* forwarding) {
+ EXPECT_PRED1(is_power_of_2, forwarding->_entries.length()) << CAPTURE(forwarding->_entries.length());
+ }
+
+ static void find_empty(ZForwarding* forwarding) {
+ uint32_t size = forwarding->_entries.length();
+ uint32_t entries_to_check = size * 2;
+
+ for (uint32_t i = 0; i < entries_to_check; i++) {
+ uintptr_t from_index = SequenceToFromIndex::one_to_one(i);
+
+ EXPECT_TRUE(forwarding->find(from_index).is_empty()) << CAPTURE2(from_index, size);
+ }
+
+ EXPECT_TRUE(forwarding->find(uintptr_t(-1)).is_empty()) << CAPTURE(size);
+ }
+
+ static void find_full(ZForwarding* forwarding) {
+ uint32_t size = forwarding->_entries.length();
+ uint32_t entries_to_populate = size;
+
+ // Populate
+ for (uint32_t i = 0; i < entries_to_populate; i++) {
+ uintptr_t from_index = SequenceToFromIndex::one_to_one(i);
+
+ ZForwardingCursor cursor;
+ ZForwardingEntry entry = forwarding->find(from_index, &cursor);
+ ASSERT_TRUE(entry.is_empty()) << CAPTURE2(from_index, size);
+
+ forwarding->insert(from_index, from_index, &cursor);
+ }
+
+ // Verify
+ for (uint32_t i = 0; i < entries_to_populate; i++) {
+ uintptr_t from_index = SequenceToFromIndex::one_to_one(i);
+
+ ZForwardingEntry entry = forwarding->find(from_index);
+ ASSERT_FALSE(entry.is_empty()) << CAPTURE2(from_index, size);
+
+ ASSERT_EQ(entry.from_index(), from_index) << CAPTURE(size);
+ ASSERT_EQ(entry.to_offset(), from_index) << CAPTURE(size);
+ }
+ }
+
+ static void find_every_other(ZForwarding* forwarding) {
+ uint32_t size = forwarding->_entries.length();
+ uint32_t entries_to_populate = size / 2;
+
+ // Populate even from indices
+ for (uint32_t i = 0; i < entries_to_populate; i++) {
+ uintptr_t from_index = SequenceToFromIndex::even(i);
+
+ ZForwardingCursor cursor;
+ ZForwardingEntry entry = forwarding->find(from_index, &cursor);
+ ASSERT_TRUE(entry.is_empty()) << CAPTURE2(from_index, size);
+
+ forwarding->insert(from_index, from_index, &cursor);
+ }
+
+ // Verify populated even indices
+ for (uint32_t i = 0; i < entries_to_populate; i++) {
+ uintptr_t from_index = SequenceToFromIndex::even(i);
+
+ ZForwardingCursor cursor;
+ ZForwardingEntry entry = forwarding->find(from_index, &cursor);
+ ASSERT_FALSE(entry.is_empty()) << CAPTURE2(from_index, size);
+
+ ASSERT_EQ(entry.from_index(), from_index) << CAPTURE(size);
+ ASSERT_EQ(entry.to_offset(), from_index) << CAPTURE(size);
+ }
+
+ // Verify empty odd indices
+ //
+ // This check could be done on a larger range of sequence numbers,
+ // but currently entries_to_populate is used.
+ for (uint32_t i = 0; i < entries_to_populate; i++) {
+ uintptr_t from_index = SequenceToFromIndex::odd(i);
+
+ ZForwardingEntry entry = forwarding->find(from_index);
+
+ ASSERT_TRUE(entry.is_empty()) << CAPTURE2(from_index, size);
+ }
+ }
+
+ static void test(void (*function)(ZForwarding*), uint32_t size) {
+ // Create page
+ const ZVirtualMemory vmem(0, ZPageSizeSmall);
+ const ZPhysicalMemory pmem(ZPhysicalMemorySegment(0, ZPageSizeSmall));
+ ZPage page(ZPageTypeSmall, vmem, pmem);
+
+ page.reset();
+
+ const size_t object_size = 16;
+ const uintptr_t object = page.alloc_object(object_size);
+
+ ZGlobalSeqNum++;
+
+ bool dummy = false;
+ page.mark_object(ZAddress::marked(object), dummy, dummy);
+
+ const uint32_t live_objects = size;
+ const uint32_t live_bytes = live_objects * object_size;
+ page.inc_live_atomic(live_objects, live_bytes);
+
+ // Setup forwarding
+ ZForwarding* const forwarding = ZForwarding::create(&page);
+
+ // Actual test function
+ (*function)(forwarding);
+
+ // Teardown forwarding
+ ZForwarding::destroy(forwarding);
+
+ // Teardown page
+ page.physical_memory().clear();
+ }
+
+ // Run the given function with a few different input values.
+ static void test(void (*function)(ZForwarding*)) {
+ test(function, 1);
+ test(function, 2);
+ test(function, 3);
+ test(function, 4);
+ test(function, 7);
+ test(function, 8);
+ test(function, 1023);
+ test(function, 1024);
+ test(function, 1025);
+ }
+};
+
+TEST_F(ZForwardingTest, setup) {
+ test(&ZForwardingTest::setup);
+}
+
+TEST_F(ZForwardingTest, find_empty) {
+ test(&ZForwardingTest::find_empty);
+}
+
+TEST_F(ZForwardingTest, find_full) {
+ test(&ZForwardingTest::find_full);
+}
+
+TEST_F(ZForwardingTest, find_every_other) {
+ test(&ZForwardingTest::find_every_other);
+}
--- a/test/hotspot/gtest/gc/z/test_zForwardingTable.cpp Thu Mar 21 08:41:10 2019 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,185 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include "precompiled.hpp"
-#include "gc/z/zForwardingTable.inline.hpp"
-#include "unittest.hpp"
-
-using namespace testing;
-
-#define CAPTURE_DELIM "\n"
-#define CAPTURE1(expression) #expression << " evaluates to " << expression
-#define CAPTURE2(e0, e1) CAPTURE1(e0) << CAPTURE_DELIM << CAPTURE1(e1)
-
-#define CAPTURE(expression) CAPTURE1(expression)
-
-class ZForwardingTableTest : public Test {
-public:
- // Helper functions
-
- static bool is_power_of_2(size_t value) {
- return ::is_power_of_2((intptr_t)value);
- }
-
- class SequenceToFromIndex : AllStatic {
- public:
- static uintptr_t even(uint32_t sequence_number) {
- return sequence_number * 2;
- }
- static uintptr_t odd(uint32_t sequence_number) {
- return even(sequence_number) + 1;
- }
- static uintptr_t one_to_one(uint32_t sequence_number) {
- return sequence_number;
- }
- };
-
- // Test functions
-
- static void setup(ZForwardingTable& table) {
- EXPECT_PRED1(is_power_of_2, table._size) << CAPTURE(table._size);
- }
-
- static void find_empty(ZForwardingTable& table) {
- size_t size = table._size;
- size_t entries_to_check = size * 2;
-
- for (uint32_t i = 0; i < entries_to_check; i++) {
- uintptr_t from_index = SequenceToFromIndex::one_to_one(i);
-
- EXPECT_TRUE(table.find(from_index).is_empty()) << CAPTURE2(from_index, size);
- }
-
- EXPECT_TRUE(table.find(uintptr_t(-1)).is_empty()) << CAPTURE(size);
- }
-
- static void find_full(ZForwardingTable& table) {
- size_t size = table._size;
- size_t entries_to_populate = size;
-
- // Populate
- for (uint32_t i = 0; i < entries_to_populate; i++) {
- uintptr_t from_index = SequenceToFromIndex::one_to_one(i);
-
- ZForwardingTableCursor cursor;
- ZForwardingTableEntry entry = table.find(from_index, &cursor);
- ASSERT_TRUE(entry.is_empty()) << CAPTURE2(from_index, size);
-
- table.insert(from_index, from_index, &cursor);
- }
-
- // Verify
- for (uint32_t i = 0; i < entries_to_populate; i++) {
- uintptr_t from_index = SequenceToFromIndex::one_to_one(i);
-
- ZForwardingTableEntry entry = table.find(from_index);
- ASSERT_FALSE(entry.is_empty()) << CAPTURE2(from_index, size);
-
- ASSERT_EQ(entry.from_index(), from_index) << CAPTURE(size);
- ASSERT_EQ(entry.to_offset(), from_index) << CAPTURE(size);
- }
- }
-
- static void find_every_other(ZForwardingTable& table) {
- size_t size = table._size;
- size_t entries_to_populate = size / 2;
-
- // Populate even from indices
- for (uint32_t i = 0; i < entries_to_populate; i++) {
- uintptr_t from_index = SequenceToFromIndex::even(i);
-
- ZForwardingTableCursor cursor;
- ZForwardingTableEntry entry = table.find(from_index, &cursor);
- ASSERT_TRUE(entry.is_empty()) << CAPTURE2(from_index, size);
-
- table.insert(from_index, from_index, &cursor);
- }
-
- // Verify populated even indices
- for (uint32_t i = 0; i < entries_to_populate; i++) {
- uintptr_t from_index = SequenceToFromIndex::even(i);
-
- ZForwardingTableCursor cursor;
- ZForwardingTableEntry entry = table.find(from_index, &cursor);
- ASSERT_FALSE(entry.is_empty()) << CAPTURE2(from_index, size);
-
- ASSERT_EQ(entry.from_index(), from_index) << CAPTURE(size);
- ASSERT_EQ(entry.to_offset(), from_index) << CAPTURE(size);
- }
-
- // Verify empty odd indices
- //
- // This check could be done on a larger range of sequence numbers,
- // but currently entries_to_populate is used.
- for (uint32_t i = 0; i < entries_to_populate; i++) {
- uintptr_t from_index = SequenceToFromIndex::odd(i);
-
- ZForwardingTableEntry entry = table.find(from_index);
-
- ASSERT_TRUE(entry.is_empty()) << CAPTURE2(from_index, size);
- }
- }
-
- static void test(void (*function)(ZForwardingTable&), uint32_t size) {
- // Setup
- ZForwardingTable table;
- table.setup(size);
- ASSERT_FALSE(table.is_null());
-
- // Actual test function
- (*function)(table);
-
- // Teardown
- table.reset();
- ASSERT_TRUE(table.is_null());
- }
-
- // Run the given function with a few different input values.
- static void test(void (*function)(ZForwardingTable&)) {
- test(function, 1);
- test(function, 2);
- test(function, 3);
- test(function, 4);
- test(function, 7);
- test(function, 8);
- test(function, 1023);
- test(function, 1024);
- test(function, 1025);
- }
-};
-
-TEST_F(ZForwardingTableTest, setup) {
- test(&ZForwardingTableTest::setup);
-}
-
-TEST_F(ZForwardingTableTest, find_empty) {
- test(&ZForwardingTableTest::find_empty);
-}
-
-TEST_F(ZForwardingTableTest, find_full) {
- test(&ZForwardingTableTest::find_full);
-}
-
-TEST_F(ZForwardingTableTest, find_every_other) {
- test(&ZForwardingTableTest::find_every_other);
-}
--- a/test/hotspot/jtreg/ProblemList-zgc.txt Thu Mar 21 08:41:10 2019 +0000
+++ b/test/hotspot/jtreg/ProblemList-zgc.txt Thu Mar 21 18:04:01 2019 +0000
@@ -27,4 +27,16 @@
#
#############################################################################
+serviceability/sa/ClhsdbInspect.java 8220624 generic-all
+serviceability/sa/ClhsdbJdis.java 8220624 generic-all
+serviceability/sa/ClhsdbJhisto.java 8220624 generic-all
+serviceability/sa/ClhsdbJstack.java 8220624 generic-all
+serviceability/sa/ClhsdbPrintAs.java 8220624 generic-all
+serviceability/sa/ClhsdbPstack.java 8220624 generic-all
+serviceability/sa/ClhsdbSource.java 8220624 generic-all
+serviceability/sa/TestClhsdbJstackLock.java 8220624 generic-all
+serviceability/sa/TestHeapDumpForInvokeDynamic.java 8220624 generic-all
+serviceability/sa/TestHeapDumpForLargeArray.java 8220624 generic-all
+serviceability/sa/TestUniverse.java 8220624 generic-all
+serviceability/sa/TestJmapCore.java 8220624 generic-all
serviceability/sa/TestJmapCoreMetaspace.java 8219443 generic-all
--- a/test/hotspot/jtreg/TEST.groups Thu Mar 21 08:41:10 2019 +0000
+++ b/test/hotspot/jtreg/TEST.groups Thu Mar 21 18:04:01 2019 +0000
@@ -281,11 +281,6 @@
-runtime/modules/ModuleStress/ExportModuleStressTest.java \
-runtime/modules/ModuleStress/ModuleStressGC.java \
-runtime/NMT \
- -runtime/RedefineObject/TestRedefineObject.java \
- -runtime/RedefineTests/RedefineLeak.java \
- -runtime/RedefineTests/RedefinePreviousVersions.java \
- -runtime/RedefineTests/RedefineRunningMethods.java \
- -runtime/RedefineTests/RedefineRunningMethodsWithBacktrace.java \
-runtime/ReservedStack \
-runtime/SelectionResolution/AbstractMethodErrorTest.java \
-runtime/SelectionResolution/IllegalAccessErrorTest.java \
@@ -329,6 +324,12 @@
tier1_serviceability = \
serviceability/dcmd/compiler \
-serviceability/dcmd/compiler/CompilerQueueTest.java \
+ serviceability/jvmti/RedefineClasses \
+ -serviceability/jvmti/RedefineClasses/RedefineLeak.java \
+ -serviceability/jvmti/RedefineClasses/RedefinePreviousVersions.java \
+ -serviceability/jvmti/RedefineClasses/RedefineRunningMethods.java \
+ -serviceability/jvmti/RedefineClasses/RedefineRunningMethodsWithBacktrace.java \
+ -serviceability/jvmti/RedefineClasses/TestRedefineObject.java \
serviceability/logging \
serviceability/sa \
-serviceability/sa/ClhsdbScanOops.java \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/c1/Test8211100.java Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8211100
+ * @summary hotspot C1 issue with comparing long numbers on x86 32-bit
+ *
+ * @run main/othervm -XX:+PrintCompilation -XX:CompileOnly=compiler.c1.Test8211100::test
+ * -XX:CompileCommand=quiet compiler.c1.Test8211100
+ */
+
+package compiler.c1;
+
+public class Test8211100 {
+ private static final int ITERATIONS = 100_000;
+
+ public static void main(String[] args) {
+ for (int i = 0; i < ITERATIONS; i++) {
+ test(4558828911L,
+ 4294967296L);
+ }
+ }
+
+ private static void test(long one, long two) {
+ while (true) {
+ if (one >= two) {
+ break;
+ }
+ }
+ }
+}
--- a/test/hotspot/jtreg/compiler/gcbarriers/UnsafeIntrinsicsTest.java Thu Mar 21 08:41:10 2019 +0000
+++ b/test/hotspot/jtreg/compiler/gcbarriers/UnsafeIntrinsicsTest.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,7 @@
* @modules java.base/jdk.internal.misc:+open
* @summary Validate barriers after Unsafe getReference, CAS and swap (GetAndSet)
* @requires vm.gc.Z & !vm.graal.enabled
- * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -XX:+UnlockDiagnosticVMOptions -XX:+ZUnmapBadViews -XX:ZCollectionInterval=1 -XX:-CreateCoredumpOnCrash -XX:CompileCommand=dontinline,*::mergeImpl* compiler.gcbarriers.UnsafeIntrinsicsTest
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -XX:+UnlockDiagnosticVMOptions -XX:+ZVerifyViews -XX:ZCollectionInterval=1 -XX:-CreateCoredumpOnCrash -XX:CompileCommand=dontinline,*::mergeImpl* compiler.gcbarriers.UnsafeIntrinsicsTest
*/
package compiler.gcbarriers;
--- a/test/hotspot/jtreg/gc/shenandoah/options/TestLoopMiningArguments.java Thu Mar 21 08:41:10 2019 +0000
+++ b/test/hotspot/jtreg/gc/shenandoah/options/TestLoopMiningArguments.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2018, Red Hat, Inc. All rights reserved.
+ * Copyright (c) 2017, 2019, Red Hat, Inc. All rights reserved.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
@@ -53,50 +53,6 @@
}
public static void main(String[] args) throws Exception {
- testDefaultGC();
- testShenandoah();
- }
-
- public static void testDefaultGC() throws Exception {
- testWith("Default GC should have CLS enabled, LSM = 1000",
- true, 1000);
-
- testWith("Default GC with +CLS should set LSM = 1",
- true, 1,
- "-XX:+UseCountedLoopSafepoints"
- );
-
- testWith("Default GC with +CLS should not override LSM>1",
- true, 10,
- "-XX:LoopStripMiningIter=10",
- "-XX:+UseCountedLoopSafepoints"
- );
-
- testWith("Default GC with +CLS should not override LSM=1",
- true, 1,
- "-XX:LoopStripMiningIter=1",
- "-XX:+UseCountedLoopSafepoints"
- );
-
- testWith("Default GC with +CLS should override LSM=0 to 1",
- true, 1,
- "-XX:LoopStripMiningIter=0",
- "-XX:+UseCountedLoopSafepoints"
- );
-
- testWith("Default GC with -CLS should set LSM = 0",
- false, 0,
- "-XX:-UseCountedLoopSafepoints"
- );
-
- testWith("Default GC with -CLS should override LSM to 0",
- false, 0,
- "-XX:LoopStripMiningIter=10",
- "-XX:-UseCountedLoopSafepoints"
- );
- }
-
- public static void testShenandoah() throws Exception {
testWith("Shenandoah should have CLS and LSM enabled",
true, 1000,
"-XX:+UnlockExperimentalVMOptions",
--- a/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java Thu Mar 21 08:41:10 2019 +0000
+++ b/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -46,6 +46,7 @@
{"InitialRAMFraction", "64"},
{"TLABStats", "false"},
{"ThreadLocalHandshakes", "true"},
+ {"AllowJNIEnvProxy", "true"},
// deprecated alias flags (see also aliased_jvm_flags):
{"DefaultMaxRAMFraction", "4"},
--- a/test/hotspot/jtreg/runtime/RedefineObject/Agent.java Thu Mar 21 08:41:10 2019 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,83 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-import java.security.*;
-import java.lang.instrument.*;
-import java.lang.reflect.*;
-
-public class Agent implements ClassFileTransformer {
- public synchronized byte[] transform(final ClassLoader classLoader,
- final String className,
- Class<?> classBeingRedefined,
- ProtectionDomain protectionDomain,
- byte[] classfileBuffer) {
- System.out.println("Transforming class " + className);
- return classfileBuffer;
- }
-
- public static void redefine(String agentArgs, Instrumentation instrumentation, Class to_redefine) {
-
- try {
- instrumentation.retransformClasses(to_redefine);
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- }
-
- public static void premain(String agentArgs, Instrumentation instrumentation) {
- Agent transformer = new Agent();
- instrumentation.addTransformer(transformer, true);
-
- // Redefine java/lang/Object and java/lang/reflect/Method.invoke and
- // java/lang/ClassLoader
- Class object_class = Object.class;
- redefine(agentArgs, instrumentation, object_class);
-
- Class method_class = Method.class;
- redefine(agentArgs, instrumentation, method_class);
-
- Class loader_class = ClassLoader.class;
- redefine(agentArgs, instrumentation, loader_class);
-
- instrumentation.removeTransformer(transformer);
- }
-
- public static void main(String[] args) {
- byte[] ba = new byte[0];
-
- // If it survives 100 GC's, it's good.
- for (int i = 0; i < 100 ; i++) {
- System.gc();
- ba.clone();
- }
- try {
- // Use java/lang/reflect/Method.invoke to call
- WalkThroughInvoke a = new WalkThroughInvoke();
- Class aclass = WalkThroughInvoke.class;
- Method m = aclass.getMethod("stackWalk");
- m.invoke(a);
- } catch (Exception x) {
- x.printStackTrace();
- }
- }
-}
--- a/test/hotspot/jtreg/runtime/RedefineObject/TestRedefineObject.java Thu Mar 21 08:41:10 2019 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-import java.io.PrintWriter;
-
-import jdk.test.lib.JDKToolFinder;
-import jdk.test.lib.process.ProcessTools;
-import jdk.test.lib.process.OutputAnalyzer;
-
-/*
- * Test to redefine java/lang/Object and verify that it doesn't crash on vtable
- * call on basic array type.
- * Test to redefine java/lang/ClassLoader and java/lang/reflect/Method to make
- * sure cached versions used afterward are the current version.
- *
- * @test
- * @bug 8005056
- * @bug 8009728
- * @library /test/lib
- * @modules java.base/jdk.internal.misc
- * java.instrument
- * java.management
- * @build Agent
- * @run driver ClassFileInstaller Agent
- * @run main TestRedefineObject
- * @run main/othervm -javaagent:agent.jar -Xlog:redefine+class+load=debug,redefine+class+timer=info Agent
- */
-public class TestRedefineObject {
- public static void main(String[] args) throws Exception {
-
- PrintWriter pw = new PrintWriter("MANIFEST.MF");
- pw.println("Premain-Class: Agent");
- pw.println("Can-Retransform-Classes: true");
- pw.close();
-
- ProcessBuilder pb = new ProcessBuilder();
- pb.command(new String[] { JDKToolFinder.getJDKTool("jar"), "cmf", "MANIFEST.MF", "agent.jar", "Agent.class"});
- pb.start().waitFor();
- }
-}
--- a/test/hotspot/jtreg/runtime/RedefineObject/WalkThroughInvoke.java Thu Mar 21 08:41:10 2019 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-import java.lang.reflect.*;
-
-public class WalkThroughInvoke {
- public void stackWalk() {
- try {
- Class b = Object.class;
- SecurityManager sm = new SecurityManager();
- // Walks the stack with Method.invoke in the stack (which is the
- // purpose of the test) before it gets an AccessControlException.
- sm.checkPermission(new RuntimePermission("accessDeclaredMembers"));
- } catch (java.security.AccessControlException e) {
- // Ignoring an 'AccessControlException' exception since
- // it is expected as part of this test.
- }
- }
-};
--- a/test/hotspot/jtreg/runtime/RedefineTests/ModifyAnonymous.java Thu Mar 21 08:41:10 2019 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,203 +0,0 @@
-/*
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @library /test/lib
- * @summary Test that retransforming and redefining anonymous classes gets UnmodifiableClassException
- * @modules java.base/jdk.internal.misc
- * @modules java.instrument
- * jdk.jartool/sun.tools.jar
- * @run main ModifyAnonymous buildagent
- * @run main/othervm -javaagent:redefineagent.jar ModifyAnonymous
- */
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.PrintWriter;
-import java.lang.RuntimeException;
-import java.lang.instrument.ClassDefinition;
-import java.lang.instrument.ClassFileTransformer;
-import java.lang.instrument.IllegalClassFormatException;
-import java.lang.instrument.Instrumentation;
-import java.security.ProtectionDomain;
-
-import jdk.test.lib.compiler.InMemoryJavaCompiler;
-
-public class ModifyAnonymous {
-
- public static class LambdaTransformer implements ClassFileTransformer {
- @Override
- public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
- ProtectionDomain protectionDomain, byte[] classfileBuffer)
- throws IllegalClassFormatException {
- return null;
- }
- }
-
- static Instrumentation inst = null;
- static volatile boolean done = false;
-
- public static void premain(String args, Instrumentation instrumentation) {
-
- inst = instrumentation;
- System.out.println("javaagent in da house!");
- instrumentation.addTransformer(new LambdaTransformer());
- }
-
- private static void buildAgent() {
- try {
- ClassFileInstaller.main("ModifyAnonymous");
- } catch (Exception e) {
- throw new RuntimeException("Could not write agent classfile", e);
- }
-
- try {
- PrintWriter pw = new PrintWriter("MANIFEST.MF");
- pw.println("Premain-Class: ModifyAnonymous");
- pw.println("Agent-Class: ModifyAnonymous");
- pw.println("Can-Retransform-Classes: true");
- pw.println("Can-Redefine-Classes: true");
- pw.close();
- } catch (FileNotFoundException e) {
- throw new RuntimeException("Could not write manifest file for the agent", e);
- }
-
- sun.tools.jar.Main jarTool = new sun.tools.jar.Main(System.out, System.err, "jar");
- if (!jarTool.run(new String[] { "-cmf", "MANIFEST.MF", "redefineagent.jar", "ModifyAnonymous.class" })) {
- throw new RuntimeException("Could not write the agent jar file");
- }
- }
-
- public static class InstanceMethodCallSiteApp {
-
- public static void test() throws InterruptedException {
- for (int i = 0; i < 2; i++) {
- InstanceMethodCallSiteApp app = new InstanceMethodCallSiteApp();
- Runnable r = app::doWork; // this creates an anonymous class
- while (!done) {
- r.run();
- Thread.sleep(10);
- }
- }
- }
-
- public void doWork() {
- System.out.print(".");
- }
- }
-
- static void runTest() {
- PrintWriter pw;
- String logName = System.getProperty("test.classes") +
- File.separator + "loadedClasses.log";
- // Create a log file to capture the names of the classes in the
- // allLoadedClasses array. The log file is for assisting in debugging
- // in case a null class is encountered in the allLoadedClasses array.
- try {
- pw = new PrintWriter(new FileOutputStream(
- new File(logName), true));
- } catch (FileNotFoundException e) {
- throw new RuntimeException("Could not write loaded classes to log", e);
- }
- while (!done) {
- Class[] allLoadedClasses = inst.getAllLoadedClasses();
- int len = allLoadedClasses.length;
- pw.println(" allLoadedClasses length: " + len);
- for (int idx = 0; idx < len; idx++) {
- Class cls = allLoadedClasses[idx];
- pw.println(" " + idx + " " +
- ((cls != null) ? cls.getName() : "null"));
- }
- for (int idx = 0; idx < len; idx++) {
- Class clazz = allLoadedClasses[idx];
- if (clazz == null) {
- pw.flush();
- pw.close();
- throw new RuntimeException("null class encountered");
- }
- final String name = clazz.getName();
- if (name.contains("$$Lambda$") && name.contains("App")) {
- if (inst.isModifiableClass(clazz)) {
- pw.flush();
- pw.close();
- throw new RuntimeException ("Class should not be modifiable");
- }
- // Try to modify them anyway.
- try {
- System.out.println("retransform called for " + name);
- inst.retransformClasses(clazz);
- } catch(java.lang.instrument.UnmodifiableClassException t) {
- System.out.println("PASSED: expecting UnmodifiableClassException");
- t.printStackTrace();
- }
- try {
- System.out.println("redefine called for " + name);
- String newclass = "class Dummy {}";
- byte[] bytecode = InMemoryJavaCompiler.compile("Dummy", newclass);
- ClassDefinition cld = new ClassDefinition(clazz, bytecode);
- inst.redefineClasses(new ClassDefinition[] { cld });
- } catch(java.lang.instrument.UnmodifiableClassException t) {
- System.out.println("PASSED: expecting UnmodifiableClassException");
- t.printStackTrace();
- } catch(java.lang.ClassNotFoundException e) {
- pw.flush();
- pw.close();
- throw new RuntimeException ("ClassNotFoundException thrown");
- }
- done = true;
- }
- }
- }
- pw.flush();
- pw.close();
- }
-
- public static void main(String argv[]) throws InterruptedException, RuntimeException {
- if (argv.length == 1 && argv[0].equals("buildagent")) {
- buildAgent();
- return;
- }
-
- if (inst == null) {
- throw new RuntimeException("Instrumentation object was null");
- }
-
- new Thread() {
- public void run() {
- runTest();
- }
- }.start();
-
- // Test that NCDFE is not thrown for anonymous class:
- // ModifyAnonymous$InstanceMethodCallSiteApp$$Lambda$18
- try {
- ModifyAnonymous test = new ModifyAnonymous();
- InstanceMethodCallSiteApp.test();
- } catch (NoClassDefFoundError e) {
- throw new RuntimeException("FAILED: NoClassDefFoundError thrown for " + e.getMessage());
- }
- System.out.println("PASSED: NoClassDefFound error not thrown");
- }
-}
--- a/test/hotspot/jtreg/runtime/RedefineTests/RedefineAddLambdaExpression.java Thu Mar 21 08:41:10 2019 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,78 +0,0 @@
-/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 8193524
- * @summary Redefine a class' public static method that contains a lambda expression
- * @library /test/lib
- * @modules java.base/jdk.internal.misc
- * @modules java.compiler
- * java.instrument
- * jdk.jartool/sun.tools.jar
- * @run main RedefineClassHelper
- * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class*=trace RedefineAddLambdaExpression
- */
-
-interface MathOperation {
- public int operation(int a, int b);
-}
-
-class B {
- public static int operate(int a, int b, MathOperation mathOperation) {
- return mathOperation.operation(a, b);
- }
- static int test_math(String p) {
- MathOperation addition = (int a, int b) -> a + b;
- return operate(10, 5, addition);
- }
-}
-
-public class RedefineAddLambdaExpression {
-
- public static String newB =
- "class B {" +
- " public static int operate(int a, int b, MathOperation mathOperation) {" +
- " return mathOperation.operation(a, b);" +
- " }" +
- " static int test_math(String p) {" +
- " MathOperation addition = (int a, int b) -> a + b;" +
- " System.out.println(p + \" from class B's test_math method\");" +
- " MathOperation subtraction = (int a, int b) -> a - b;" +
- " return operate(10, 5, subtraction);" +
- " }" +
- "}";
-
- public static void main(String[] args) throws Exception {
- int res = B.test_math("Hello");
- System.out.println("Result = " + res);
- if (res != 15) {
- throw new Error("test_math returned " + res + " expected " + 15);
- }
- RedefineClassHelper.redefineClass(B.class, newB);
-
- res = B.test_math("Hello");
- if (res != 5)
- throw new Error("test_math returned " + res + " expected " + 5);
- }
-}
--- a/test/hotspot/jtreg/runtime/RedefineTests/RedefineAnnotations.java Thu Mar 21 08:41:10 2019 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,414 +0,0 @@
-/*
- * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @library /test/lib
- * @summary Test that type annotations are retained after a retransform
- * @modules java.base/jdk.internal.misc
- * @modules java.base/jdk.internal.org.objectweb.asm
- * java.instrument
- * jdk.jartool/sun.tools.jar
- * @run main RedefineAnnotations buildagent
- * @run main/othervm -javaagent:redefineagent.jar RedefineAnnotations
- */
-
-import static jdk.test.lib.Asserts.assertTrue;
-import java.io.FileNotFoundException;
-import java.io.PrintWriter;
-import java.lang.NoSuchFieldException;
-import java.lang.NoSuchMethodException;
-import java.lang.RuntimeException;
-import java.lang.annotation.Annotation;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import java.lang.instrument.ClassFileTransformer;
-import java.lang.instrument.IllegalClassFormatException;
-import java.lang.instrument.Instrumentation;
-import java.lang.instrument.UnmodifiableClassException;
-import java.lang.reflect.AnnotatedArrayType;
-import java.lang.reflect.AnnotatedParameterizedType;
-import java.lang.reflect.AnnotatedType;
-import java.lang.reflect.AnnotatedWildcardType;
-import java.lang.reflect.Executable;
-import java.lang.reflect.TypeVariable;
-import java.security.ProtectionDomain;
-import java.util.Arrays;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import jdk.internal.org.objectweb.asm.ClassReader;
-import jdk.internal.org.objectweb.asm.ClassVisitor;
-import jdk.internal.org.objectweb.asm.ClassWriter;
-import jdk.internal.org.objectweb.asm.FieldVisitor;
-import static jdk.internal.org.objectweb.asm.Opcodes.ASM7;
-
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.TYPE_USE)
-@interface TestAnn {
- String site();
-}
-
-public class RedefineAnnotations {
- static Instrumentation inst;
- public static void premain(String agentArgs, Instrumentation inst) {
- RedefineAnnotations.inst = inst;
- }
-
- static class Transformer implements ClassFileTransformer {
-
- public byte[] asm(ClassLoader loader, String className,
- Class<?> classBeingRedefined,
- ProtectionDomain protectionDomain, byte[] classfileBuffer)
- throws IllegalClassFormatException {
-
- ClassWriter cw = new ClassWriter(0);
- ClassVisitor cv = new ReAddDummyFieldsClassVisitor(ASM7, cw) { };
- ClassReader cr = new ClassReader(classfileBuffer);
- cr.accept(cv, 0);
- return cw.toByteArray();
- }
-
- public class ReAddDummyFieldsClassVisitor extends ClassVisitor {
-
- LinkedList<F> fields = new LinkedList<>();
-
- public ReAddDummyFieldsClassVisitor(int api, ClassVisitor cv) {
- super(api, cv);
- }
-
- @Override public FieldVisitor visitField(int access, String name,
- String desc, String signature, Object value) {
- if (name.startsWith("dummy")) {
- // Remove dummy field
- fields.addLast(new F(access, name, desc, signature, value));
- return null;
- }
- return cv.visitField(access, name, desc, signature, value);
- }
-
- @Override public void visitEnd() {
- F f;
- while ((f = fields.pollFirst()) != null) {
- // Re-add dummy fields
- cv.visitField(f.access, f.name, f.desc, f.signature, f.value);
- }
- }
-
- private class F {
- private int access;
- private String name;
- private String desc;
- private String signature;
- private Object value;
- F(int access, String name, String desc, String signature, Object value) {
- this.access = access;
- this.name = name;
- this.desc = desc;
- this.signature = signature;
- this.value = value;
- }
- }
- }
-
- @Override public byte[] transform(ClassLoader loader, String className,
- Class<?> classBeingRedefined,
- ProtectionDomain protectionDomain, byte[] classfileBuffer)
- throws IllegalClassFormatException {
-
- if (className.contains("TypeAnnotatedTestClass")) {
- try {
- // Here we remove and re-add the dummy fields. This shuffles the constant pool
- return asm(loader, className, classBeingRedefined, protectionDomain, classfileBuffer);
- } catch (Throwable e) {
- // The retransform native code that called this method does not propagate
- // exceptions. Instead of getting an uninformative generic error, catch
- // problems here and print it, then exit.
- e.printStackTrace();
- System.exit(1);
- }
- }
- return null;
- }
- }
-
- private static void buildAgent() {
- try {
- ClassFileInstaller.main("RedefineAnnotations");
- } catch (Exception e) {
- throw new RuntimeException("Could not write agent classfile", e);
- }
-
- try {
- PrintWriter pw = new PrintWriter("MANIFEST.MF");
- pw.println("Premain-Class: RedefineAnnotations");
- pw.println("Agent-Class: RedefineAnnotations");
- pw.println("Can-Retransform-Classes: true");
- pw.close();
- } catch (FileNotFoundException e) {
- throw new RuntimeException("Could not write manifest file for the agent", e);
- }
-
- sun.tools.jar.Main jarTool = new sun.tools.jar.Main(System.out, System.err, "jar");
- if (!jarTool.run(new String[] { "-cmf", "MANIFEST.MF", "redefineagent.jar", "RedefineAnnotations.class" })) {
- throw new RuntimeException("Could not write the agent jar file");
- }
- }
-
- public static void main(String argv[]) throws NoSuchFieldException, NoSuchMethodException {
- if (argv.length == 1 && argv[0].equals("buildagent")) {
- buildAgent();
- return;
- }
-
- if (inst == null) {
- throw new RuntimeException("Instrumentation object was null");
- }
-
- RedefineAnnotations test = new RedefineAnnotations();
- test.testTransformAndVerify();
- }
-
- // Class type annotations
- private Annotation classTypeParameterTA;
- private Annotation extendsTA;
- private Annotation implementsTA;
-
- // Field type annotations
- private Annotation fieldTA;
- private Annotation innerTA;
- private Annotation[] arrayTA = new Annotation[4];
- private Annotation[] mapTA = new Annotation[5];
-
- // Method type annotations
- private Annotation returnTA, methodTypeParameterTA, formalParameterTA, throwsTA;
-
- private void testTransformAndVerify()
- throws NoSuchFieldException, NoSuchMethodException {
-
- Class<TypeAnnotatedTestClass> c = TypeAnnotatedTestClass.class;
- Class<?> myClass = c;
-
- /*
- * Verify that the expected annotations are where they should be before transform.
- */
- verifyClassTypeAnnotations(c);
- verifyFieldTypeAnnotations(c);
- verifyMethodTypeAnnotations(c);
-
- try {
- inst.addTransformer(new Transformer(), true);
- inst.retransformClasses(myClass);
- } catch (UnmodifiableClassException e) {
- throw new RuntimeException(e);
- }
-
- /*
- * Verify that the expected annotations are where they should be after transform.
- * Also verify that before and after are equal.
- */
- verifyClassTypeAnnotations(c);
- verifyFieldTypeAnnotations(c);
- verifyMethodTypeAnnotations(c);
- }
-
- private void verifyClassTypeAnnotations(Class c) {
- Annotation anno;
-
- anno = c.getTypeParameters()[0].getAnnotations()[0];
- verifyTestAnn(classTypeParameterTA, anno, "classTypeParameter");
- classTypeParameterTA = anno;
-
- anno = c.getAnnotatedSuperclass().getAnnotations()[0];
- verifyTestAnn(extendsTA, anno, "extends");
- extendsTA = anno;
-
- anno = c.getAnnotatedInterfaces()[0].getAnnotations()[0];
- verifyTestAnn(implementsTA, anno, "implements");
- implementsTA = anno;
- }
-
- private void verifyFieldTypeAnnotations(Class c)
- throws NoSuchFieldException, NoSuchMethodException {
-
- verifyBasicFieldTypeAnnotations(c);
- verifyInnerFieldTypeAnnotations(c);
- verifyArrayFieldTypeAnnotations(c);
- verifyMapFieldTypeAnnotations(c);
- }
-
- private void verifyBasicFieldTypeAnnotations(Class c)
- throws NoSuchFieldException, NoSuchMethodException {
-
- Annotation anno = c.getDeclaredField("typeAnnotatedBoolean").getAnnotatedType().getAnnotations()[0];
- verifyTestAnn(fieldTA, anno, "field");
- fieldTA = anno;
- }
-
- private void verifyInnerFieldTypeAnnotations(Class c)
- throws NoSuchFieldException, NoSuchMethodException {
-
- AnnotatedType at = c.getDeclaredField("typeAnnotatedInner").getAnnotatedType();
- Annotation anno = at.getAnnotations()[0];
- verifyTestAnn(innerTA, anno, "inner");
- innerTA = anno;
- }
-
- private void verifyArrayFieldTypeAnnotations(Class c)
- throws NoSuchFieldException, NoSuchMethodException {
-
- Annotation anno;
- AnnotatedType at;
-
- at = c.getDeclaredField("typeAnnotatedArray").getAnnotatedType();
- anno = at.getAnnotations()[0];
- verifyTestAnn(arrayTA[0], anno, "array1");
- arrayTA[0] = anno;
-
- for (int i = 1; i <= 3; i++) {
- at = ((AnnotatedArrayType) at).getAnnotatedGenericComponentType();
- anno = at.getAnnotations()[0];
- verifyTestAnn(arrayTA[i], anno, "array" + (i + 1));
- arrayTA[i] = anno;
- }
- }
-
- private void verifyMapFieldTypeAnnotations(Class c)
- throws NoSuchFieldException, NoSuchMethodException {
-
- Annotation anno;
- AnnotatedType atBase;
- AnnotatedType atParameter;
- atBase = c.getDeclaredField("typeAnnotatedMap").getAnnotatedType();
-
- anno = atBase.getAnnotations()[0];
- verifyTestAnn(mapTA[0], anno, "map1");
- mapTA[0] = anno;
-
- atParameter =
- ((AnnotatedParameterizedType) atBase).
- getAnnotatedActualTypeArguments()[0];
- anno = ((AnnotatedWildcardType) atParameter).getAnnotations()[0];
- verifyTestAnn(mapTA[1], anno, "map2");
- mapTA[1] = anno;
-
- anno =
- ((AnnotatedWildcardType) atParameter).
- getAnnotatedUpperBounds()[0].getAnnotations()[0];
- verifyTestAnn(mapTA[2], anno, "map3");
- mapTA[2] = anno;
-
- atParameter =
- ((AnnotatedParameterizedType) atBase).
- getAnnotatedActualTypeArguments()[1];
- anno = ((AnnotatedParameterizedType) atParameter).getAnnotations()[0];
- verifyTestAnn(mapTA[3], anno, "map4");
- mapTA[3] = anno;
-
- anno =
- ((AnnotatedParameterizedType) atParameter).
- getAnnotatedActualTypeArguments()[0].getAnnotations()[0];
- verifyTestAnn(mapTA[4], anno, "map5");
- mapTA[4] = anno;
- }
-
- private void verifyMethodTypeAnnotations(Class c)
- throws NoSuchFieldException, NoSuchMethodException {
- Annotation anno;
- Executable typeAnnotatedMethod =
- c.getDeclaredMethod("typeAnnotatedMethod", TypeAnnotatedTestClass.class);
-
- anno = typeAnnotatedMethod.getAnnotatedReturnType().getAnnotations()[0];
- verifyTestAnn(returnTA, anno, "return");
- returnTA = anno;
-
- anno = typeAnnotatedMethod.getTypeParameters()[0].getAnnotations()[0];
- verifyTestAnn(methodTypeParameterTA, anno, "methodTypeParameter");
- methodTypeParameterTA = anno;
-
- anno = typeAnnotatedMethod.getAnnotatedParameterTypes()[0].getAnnotations()[0];
- verifyTestAnn(formalParameterTA, anno, "formalParameter");
- formalParameterTA = anno;
-
- anno = typeAnnotatedMethod.getAnnotatedExceptionTypes()[0].getAnnotations()[0];
- verifyTestAnn(throwsTA, anno, "throws");
- throwsTA = anno;
- }
-
- private static void verifyTestAnn(Annotation verifyAgainst, Annotation anno, String expectedSite) {
- verifyTestAnnSite(anno, expectedSite);
-
- // When called before transform verifyAgainst will be null, when called
- // after transform it will be the annotation from before the transform
- if (verifyAgainst != null) {
- assertTrue(anno.equals(verifyAgainst),
- "Annotations do not match before and after." +
- " Before: \"" + verifyAgainst + "\", After: \"" + anno + "\"");
- }
- }
-
- private static void verifyTestAnnSite(Annotation testAnn, String expectedSite) {
- String expectedAnn = "@TestAnn(site=\"" + expectedSite + "\")";
- assertTrue(testAnn.toString().equals(expectedAnn),
- "Expected \"" + expectedAnn + "\", got \"" + testAnn + "\"");
- }
-
- public static class TypeAnnotatedTestClass <@TestAnn(site="classTypeParameter") S,T>
- extends @TestAnn(site="extends") Thread
- implements @TestAnn(site="implements") Runnable {
-
- public @TestAnn(site="field") boolean typeAnnotatedBoolean;
-
- public
- RedefineAnnotations.
- @TestAnn(site="inner") TypeAnnotatedTestClass
- typeAnnotatedInner;
-
- public
- @TestAnn(site="array4") boolean
- @TestAnn(site="array1") []
- @TestAnn(site="array2") []
- @TestAnn(site="array3") []
- typeAnnotatedArray;
-
- public @TestAnn(site="map1") Map
- <@TestAnn(site="map2") ? extends @TestAnn(site="map3") String,
- @TestAnn(site="map4") List<@TestAnn(site="map5") Object>> typeAnnotatedMap;
-
- public int dummy1;
- public int dummy2;
- public int dummy3;
-
- @TestAnn(site="return") <@TestAnn(site="methodTypeParameter") U,V> Class
- typeAnnotatedMethod(@TestAnn(site="formalParameter") TypeAnnotatedTestClass arg)
- throws @TestAnn(site="throws") ClassNotFoundException {
-
- @TestAnn(site="local_variable_type") int foo = 0;
- throw new ClassNotFoundException();
- }
-
- public void run() {}
- }
-}
--- a/test/hotspot/jtreg/runtime/RedefineTests/RedefineDeleteJmethod.java Thu Mar 21 08:41:10 2019 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,94 +0,0 @@
-/*
- * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 8181171
- * @summary Test deleting static method pointing to by a jmethod
- * @library /test/lib
- * @modules java.base/jdk.internal.misc
- * @modules java.compiler
- * java.instrument
- * jdk.jartool/sun.tools.jar
- * @run main RedefineClassHelper
- * @run main/native/othervm -javaagent:redefineagent.jar -Xlog:redefine+class*=trace RedefineDeleteJmethod
- */
-
-class B {
- private static int deleteMe() { System.out.println("deleteMe called"); return 5; }
- public static int callDeleteMe() { return deleteMe(); }
-}
-
-public class RedefineDeleteJmethod {
-
- public static String newB =
- "class B {" +
- "public static int callDeleteMe() { return 6; }" +
- "}";
-
- public static String newerB =
- "class B {" +
- "private static int deleteMe() { System.out.println(\"deleteMe (2) called\"); return 7; }" +
- "public static int callDeleteMe() { return deleteMe(); }" +
- "}";
-
-
- static {
- System.loadLibrary("RedefineDeleteJmethod");
- }
-
- static native int jniCallDeleteMe();
-
- static void test(int expected, boolean nsme_expected) throws Exception {
- // Call through static method
- int res = B.callDeleteMe();
- System.out.println("Result = " + res);
- if (res != expected) {
- throw new Error("returned " + res + " expected " + expected);
- }
-
- // Call through jmethodID, saved from first call.
- try {
- res = jniCallDeleteMe();
- if (nsme_expected) {
- throw new RuntimeException("Failed, NoSuchMethodError expected");
- }
- if (res != expected) {
- throw new Error("returned " + res + " expected " + expected);
- }
- } catch (NoSuchMethodError ex) {
- if (!nsme_expected) {
- throw new RuntimeException("Failed, NoSuchMethodError not expected");
- }
- System.out.println("Passed, NoSuchMethodError expected");
- }
- }
-
- public static void main(String[] args) throws Exception {
- test(5, false);
- RedefineClassHelper.redefineClass(B.class, newB);
- test(6, true);
- RedefineClassHelper.redefineClass(B.class, newerB);
- test(7, true);
- }
-}
--- a/test/hotspot/jtreg/runtime/RedefineTests/RedefineDoubleDelete.java Thu Mar 21 08:41:10 2019 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +0,0 @@
-/*
- * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 8178870 8010319
- * @summary Redefine class with CFLH twice to test deleting the cached_class_file
- * @library /test/lib
- * @modules java.base/jdk.internal.misc
- * @modules java.compiler
- * java.instrument
- * jdk.jartool/sun.tools.jar
- * @run main RedefineClassHelper
- * @run main/othervm/native -Xlog:redefine+class+load+exceptions -agentlib:RedefineDoubleDelete -javaagent:redefineagent.jar RedefineDoubleDelete
- */
-
-// package access top-level class to avoid problem with RedefineClassHelper
-// and nested types.
-
-// The ClassFileLoadHook for this class turns foo into faa and prints out faa.
-class RedefineDoubleDelete_B {
- int faa() { System.out.println("foo"); return 1; }
-}
-
-public class RedefineDoubleDelete {
-
- // Class gets a redefinition error because it adds a data member
- public static String newB =
- "class RedefineDoubleDelete_B {" +
- " int count1 = 0;" +
- "}";
-
- public static String newerB =
- "class RedefineDoubleDelete_B { " +
- " int faa() { System.out.println(\"baa\"); return 2; }" +
- "}";
-
- public static void main(String args[]) throws Exception {
-
- RedefineDoubleDelete_B b = new RedefineDoubleDelete_B();
- int val = b.faa();
- if (val != 1) {
- throw new RuntimeException("return value wrong " + val);
- }
-
- // Redefine B twice to get cached_class_file in both B scratch classes
- try {
- RedefineClassHelper.redefineClass(RedefineDoubleDelete_B.class, newB);
- } catch (java.lang.UnsupportedOperationException e) {
- // this is expected
- }
- try {
- RedefineClassHelper.redefineClass(RedefineDoubleDelete_B.class, newB);
- } catch (java.lang.UnsupportedOperationException e) {
- // this is expected
- }
-
- // Do a full GC.
- System.gc();
-
- // Redefine with a compatible class
- RedefineClassHelper.redefineClass(RedefineDoubleDelete_B.class, newerB);
- val = b.faa();
- if (val != 2) {
- throw new RuntimeException("return value wrong " + val);
- }
-
- // Do another full GC to clean things up.
- System.gc();
- }
-}
--- a/test/hotspot/jtreg/runtime/RedefineTests/RedefineFinalizer.java Thu Mar 21 08:41:10 2019 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 6904403 8010319
- * @summary Don't assert if we redefine finalize method
- * @library /test/lib
- * @modules java.base/jdk.internal.misc
- * @modules java.compiler
- * java.instrument
- * jdk.jartool/sun.tools.jar
- * @run main RedefineClassHelper
- * @run main/othervm -javaagent:redefineagent.jar RedefineFinalizer
- */
-
-/*
- * Regression test for hitting:
- *
- * assert(f == k->has_finalizer()) failed: inconsistent has_finalizer
- *
- * when redefining finalizer method
- */
-
-
-// package access top-level class to avoid problem with RedefineClassHelper
-// and nested types.
-class RedefineFinalizer_B {
- protected void finalize() {
- // should be empty
- }
-}
-
-public class RedefineFinalizer {
-
- public static String newB =
- "class RedefineFinalizer_B {" +
- " protected void finalize() { " +
- " System.out.println(\"Finalizer called\");" +
- " }" +
- "}";
-
- public static void main(String[] args) throws Exception {
- RedefineClassHelper.redefineClass(RedefineFinalizer_B.class, newB);
-
- A a = new A();
- }
-
- static class A extends RedefineFinalizer_B {
- }
-}
--- a/test/hotspot/jtreg/runtime/RedefineTests/RedefineInterfaceCall.java Thu Mar 21 08:41:10 2019 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 8174962 8010319
- * @summary Redefine class with interface method call
- * @library /test/lib
- * @modules java.base/jdk.internal.misc
- * @modules java.compiler
- * java.instrument
- * jdk.jartool/sun.tools.jar
- * @run main RedefineClassHelper
- * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class+update*=trace RedefineInterfaceCall
- */
-
-import static jdk.test.lib.Asserts.assertEquals;
-
-interface I1 { default int m() { return 0; } }
-interface I2 extends I1 {}
-
-// package access top-level class to avoid problem with RedefineClassHelper
-// and nested types.
-class RedefineInterfaceCall_C implements I2 {
- public int test(I2 i) {
- return i.m(); // invokeinterface cpCacheEntry
- }
-}
-
-public class RedefineInterfaceCall {
-
- static String newI1 =
- "interface I1 { default int m() { return 1; } }";
-
- static String newC =
- "class RedefineInterfaceCall_C implements I2 { " +
- " public int test(I2 i) { " +
- " return i.m(); " +
- " } " +
- "} ";
-
- static int test(I2 i) {
- return i.m(); // invokeinterface cpCacheEntry
- }
-
- public static void main(String[] args) throws Exception {
- RedefineInterfaceCall_C c = new RedefineInterfaceCall_C();
-
- assertEquals(test(c), 0);
- assertEquals(c.test(c), 0);
-
- RedefineClassHelper.redefineClass(RedefineInterfaceCall_C.class, newC);
-
- assertEquals(c.test(c), 0);
-
- RedefineClassHelper.redefineClass(I1.class, newI1);
-
- assertEquals(test(c), 1);
- assertEquals(c.test(c), 1);
-
- RedefineClassHelper.redefineClass(RedefineInterfaceCall_C.class, newC);
-
- assertEquals(c.test(c), 1);
- }
-}
--- a/test/hotspot/jtreg/runtime/RedefineTests/RedefineInterfaceMethods.java Thu Mar 21 08:41:10 2019 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,108 +0,0 @@
-/*
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 8081800 8010319
- * @summary Redefine private and default interface methods
- * @library /test/lib
- * @modules java.base/jdk.internal.misc
- * @modules java.compiler
- * java.instrument
- * jdk.jartool/sun.tools.jar
- * @run main RedefineClassHelper
- * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class*=trace RedefineInterfaceMethods
- */
-
-// package access top-level class to avoid problem with RedefineClassHelper
-// and nested types.
-
-interface RedefineInterfaceMethods_B {
- int ORIGINAL_RETURN = 1;
- int NEW_RETURN = 2;
- private int privateMethod() {
- return ORIGINAL_RETURN;
- }
- public default int defaultMethod() {
- return privateMethod();
- }
-}
-
-public class RedefineInterfaceMethods {
-
- static final int RET = -2;
-
- public static String redefinedPrivateMethod =
- "interface RedefineInterfaceMethods_B {" +
- " int ORIGINAL_RETURN = 1;" +
- " int NEW_RETURN = 2;" +
- " private int privateMethod() {" +
- " return NEW_RETURN;" +
- " }" +
- " public default int defaultMethod() {" +
- " return privateMethod();" +
- " }" +
- "}";
-
- public static String redefinedDefaultMethod =
- "interface RedefineInterfaceMethods_B {" +
- " int ORIGINAL_RETURN = 1;" +
- " int NEW_RETURN = 2;" +
- " private int privateMethod() {" +
- " return ORIGINAL_RETURN;" +
- " }" +
- " public default int defaultMethod() {" +
- " return RedefineInterfaceMethods.RET;" +
- " }" +
- "}";
-
- static class Impl implements RedefineInterfaceMethods_B {
- }
-
-
- public static void main(String[] args) throws Exception {
-
- Impl impl = new Impl();
-
- int res = impl.defaultMethod();
- if (res != RedefineInterfaceMethods_B.ORIGINAL_RETURN)
- throw new Error("defaultMethod returned " + res +
- " expected " + RedefineInterfaceMethods_B.ORIGINAL_RETURN);
-
- RedefineClassHelper.redefineClass(RedefineInterfaceMethods_B.class, redefinedPrivateMethod);
-
- res = impl.defaultMethod();
- if (res != RedefineInterfaceMethods_B.NEW_RETURN)
- throw new Error("defaultMethod returned " + res +
- " expected " + RedefineInterfaceMethods_B.NEW_RETURN);
-
- System.gc();
-
- RedefineClassHelper.redefineClass(RedefineInterfaceMethods_B.class, redefinedDefaultMethod);
-
- res = impl.defaultMethod();
- if (res != RET)
- throw new Error("defaultMethod returned " + res +
- " expected " + RET);
- }
-}
--- a/test/hotspot/jtreg/runtime/RedefineTests/RedefineLeak.java Thu Mar 21 08:41:10 2019 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,112 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @library /test/lib
- * @summary Test that redefinition reuses metaspace blocks that are freed
- * @modules java.base/jdk.internal.misc
- * @modules java.instrument
- * jdk.jartool/sun.tools.jar
- * @run main RedefineLeak buildagent
- * @run main/othervm/timeout=6000 RedefineLeak runtest
- */
-
-import java.io.FileNotFoundException;
-import java.io.PrintWriter;
-import java.lang.RuntimeException;
-import java.lang.instrument.ClassFileTransformer;
-import java.lang.instrument.Instrumentation;
-import java.security.ProtectionDomain;
-import java.lang.instrument.IllegalClassFormatException;
-import jdk.test.lib.process.ProcessTools;
-import jdk.test.lib.process.OutputAnalyzer;
-
-public class RedefineLeak {
- static class Tester {}
-
- static class LoggingTransformer implements ClassFileTransformer {
- static int transformCount = 0;
-
- public LoggingTransformer() {}
-
- public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined,
- ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
-
- transformCount++;
- if (transformCount % 1000 == 0) System.out.println("transformCount:" + transformCount);
- return null;
- }
- }
-
- public static void premain(String agentArgs, Instrumentation inst) throws Exception {
- LoggingTransformer t = new LoggingTransformer();
- inst.addTransformer(t, true);
- {
- Class demoClass = Class.forName("RedefineLeak$Tester");
-
- for (int i = 0; i < 10000; i++) {
- inst.retransformClasses(demoClass);
- }
- }
- System.gc();
- }
- private static void buildAgent() {
- try {
- ClassFileInstaller.main("RedefineLeak");
- } catch (Exception e) {
- throw new RuntimeException("Could not write agent classfile", e);
- }
-
- try {
- PrintWriter pw = new PrintWriter("MANIFEST.MF");
- pw.println("Premain-Class: RedefineLeak");
- pw.println("Agent-Class: RedefineLeak");
- pw.println("Can-Redefine-Classes: true");
- pw.println("Can-Retransform-Classes: true");
- pw.close();
- } catch (FileNotFoundException e) {
- throw new RuntimeException("Could not write manifest file for the agent", e);
- }
-
- sun.tools.jar.Main jarTool = new sun.tools.jar.Main(System.out, System.err, "jar");
- if (!jarTool.run(new String[] { "-cmf", "MANIFEST.MF", "redefineagent.jar", "RedefineLeak.class" })) {
- throw new RuntimeException("Could not write the agent jar file");
- }
- }
- public static void main(String argv[]) throws Exception {
- if (argv.length == 1 && argv[0].equals("buildagent")) {
- buildAgent();
- return;
- }
- if (argv.length == 1 && argv[0].equals("runtest")) {
- // run outside of jtreg to not OOM on jtreg classes that are loaded after metaspace is full
- String[] javaArgs1 = { "-XX:MetaspaceSize=12m", "-XX:MaxMetaspaceSize=12m",
- "-javaagent:redefineagent.jar", "RedefineLeak"};
- ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(javaArgs1);
-
- OutputAnalyzer output = new OutputAnalyzer(pb.start());
- output.shouldContain("transformCount:10000");
- }
- }
-}
--- a/test/hotspot/jtreg/runtime/RedefineTests/RedefinePreviousVersions.java Thu Mar 21 08:41:10 2019 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,131 +0,0 @@
-/*
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 8165246 8010319
- * @summary Test has_previous_versions flag and processing during class unloading.
- * @requires vm.opt.final.ClassUnloading
- * @library /test/lib
- * @modules java.base/jdk.internal.misc
- * @modules java.compiler
- * java.instrument
- * jdk.jartool/sun.tools.jar
- * @run main RedefineClassHelper
- * @run main/othervm RedefinePreviousVersions test
- */
-
-import jdk.test.lib.process.ProcessTools;
-import jdk.test.lib.process.OutputAnalyzer;
-
-// package access top-level classes to avoid problem with RedefineClassHelper
-// and nested types.
-
-class RedefinePreviousVersions_B { }
-
-class RedefinePreviousVersions_Running {
- public static volatile boolean stop = false;
- public static volatile boolean running = false;
- static void localSleep() {
- try {
- Thread.sleep(10); // sleep for 10 ms
- } catch(InterruptedException ie) {
- }
- }
-
- public static void infinite() {
- running = true;
- while (!stop) { localSleep(); }
- }
-}
-
-
-
-public class RedefinePreviousVersions {
-
- public static String newB =
- "class RedefinePreviousVersions_B {" +
- "}";
-
- public static String newRunning =
- "class RedefinePreviousVersions_Running {" +
- " public static volatile boolean stop = true;" +
- " public static volatile boolean running = true;" +
- " static void localSleep() { }" +
- " public static void infinite() { }" +
- "}";
-
- public static void main(String[] args) throws Exception {
-
- if (args.length > 0) {
-
- // java -javaagent:redefineagent.jar -Xlog:stuff RedefinePreviousVersions
- ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( "-javaagent:redefineagent.jar",
- "-Xlog:redefine+class+iklass+add=trace,redefine+class+iklass+purge=trace",
- "RedefinePreviousVersions");
- new OutputAnalyzer(pb.start())
- .shouldContain("Class unloading: has_previous_versions = false")
- .shouldContain("Class unloading: has_previous_versions = true")
- .shouldHaveExitValue(0);
- return;
- }
-
- // Redefine a class and create some garbage
- // Since there are no methods running, the previous version is never added to the
- // previous_version_list and the flag _has_previous_versions should stay false
- RedefineClassHelper.redefineClass(RedefinePreviousVersions_B.class, newB);
-
- for (int i = 0; i < 10 ; i++) {
- String s = new String("some garbage");
- System.gc();
- }
-
- // Start a class that has a method running
- new Thread() {
- public void run() {
- RedefinePreviousVersions_Running.infinite();
- }
- }.start();
-
- while (!RedefinePreviousVersions_Running.running) {
- Thread.sleep(10); // sleep for 10 ms
- }
-
- // Since a method of newRunning is running, this class should be added to the previous_version_list
- // of Running, and _has_previous_versions should return true at class unloading.
- RedefineClassHelper.redefineClass(RedefinePreviousVersions_Running.class, newRunning);
-
- for (int i = 0; i < 10 ; i++) {
- String s = new String("some garbage");
- System.gc();
- }
-
- // purge should clean everything up, except Xcomp it might not.
- RedefinePreviousVersions_Running.stop = true;
-
- for (int i = 0; i < 10 ; i++) {
- String s = new String("some garbage");
- System.gc();
- }
- }
-}
--- a/test/hotspot/jtreg/runtime/RedefineTests/RedefineRunningMethods.java Thu Mar 21 08:41:10 2019 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,150 +0,0 @@
-/*
- * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 8055008 8197901 8010319
- * @summary Redefine EMCP and non-EMCP methods that are running in an infinite loop
- * @library /test/lib
- * @modules java.base/jdk.internal.misc
- * @modules java.compiler
- * java.instrument
- * jdk.jartool/sun.tools.jar
- * @run main RedefineClassHelper
- * @run main/othervm/timeout=180 -javaagent:redefineagent.jar -Xlog:redefine+class+iklass+add=trace,redefine+class+iklass+purge=trace,class+loader+data=debug,safepoint+cleanup,gc+phases=debug:rt.log RedefineRunningMethods
- */
-
-
-// package access top-level class to avoid problem with RedefineClassHelper
-// and nested types.
-class RedefineRunningMethods_B {
- static int count1 = 0;
- static int count2 = 0;
- public static volatile boolean stop = false;
- static void localSleep() {
- try{
- Thread.currentThread().sleep(10);//sleep for 10 ms
- } catch(InterruptedException ie) {
- }
- }
-
- public static void infinite() {
- while (!stop) { count1++; localSleep(); }
- }
- public static void infinite_emcp() {
- while (!stop) { count2++; localSleep(); }
- }
-}
-
-public class RedefineRunningMethods {
-
- public static String newB =
- "class RedefineRunningMethods_B {" +
- " static int count1 = 0;" +
- " static int count2 = 0;" +
- " public static volatile boolean stop = false;" +
- " static void localSleep() { " +
- " try{ " +
- " Thread.currentThread().sleep(10);" +
- " } catch(InterruptedException ie) { " +
- " } " +
- " } " +
- " public static void infinite() { " +
- " System.out.println(\"infinite called\");" +
- " }" +
- " public static void infinite_emcp() { " +
- " while (!stop) { count2++; localSleep(); }" +
- " }" +
- "}";
-
- public static String evenNewerB =
- "class RedefineRunningMethods_B {" +
- " static int count1 = 0;" +
- " static int count2 = 0;" +
- " public static volatile boolean stop = false;" +
- " static void localSleep() { " +
- " try{ " +
- " Thread.currentThread().sleep(1);" +
- " } catch(InterruptedException ie) { " +
- " } " +
- " } " +
- " public static void infinite() { }" +
- " public static void infinite_emcp() { " +
- " System.out.println(\"infinite_emcp now obsolete called\");" +
- " }" +
- "}";
-
-
- public static void main(String[] args) throws Exception {
-
- new Thread() {
- public void run() {
- RedefineRunningMethods_B.infinite();
- }
- }.start();
-
- new Thread() {
- public void run() {
- RedefineRunningMethods_B.infinite_emcp();
- }
- }.start();
-
- RedefineClassHelper.redefineClass(RedefineRunningMethods_B.class, newB);
-
- System.gc();
-
- RedefineRunningMethods_B.infinite();
-
- // Start a thread with the second version of infinite_emcp running
- new Thread() {
- public void run() {
- RedefineRunningMethods_B.infinite_emcp();
- }
- }.start();
-
- for (int i = 0; i < 20 ; i++) {
- String s = new String("some garbage");
- System.gc();
- }
-
- RedefineClassHelper.redefineClass(RedefineRunningMethods_B.class, evenNewerB);
- System.gc();
-
- for (int i = 0; i < 20 ; i++) {
- RedefineRunningMethods_B.infinite();
- String s = new String("some garbage");
- System.gc();
- }
-
- RedefineRunningMethods_B.infinite_emcp();
-
- // purge should clean everything up.
- RedefineRunningMethods_B.stop = true;
-
- for (int i = 0; i < 20 ; i++) {
- RedefineRunningMethods_B.infinite();
- String s = new String("some garbage");
- System.gc();
- }
- }
-}
--- a/test/hotspot/jtreg/runtime/RedefineTests/RedefineRunningMethodsWithBacktrace.java Thu Mar 21 08:41:10 2019 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,196 +0,0 @@
-/*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 8087315 8010319
- * @summary Get old method's stack trace elements after GC
- * @library /test/lib
- * @modules java.base/jdk.internal.misc
- * @modules java.compiler
- * java.instrument
- * jdk.jartool/sun.tools.jar
- * @run main RedefineClassHelper
- * @run main/othervm -javaagent:redefineagent.jar RedefineRunningMethodsWithBacktrace
- */
-
-import static jdk.test.lib.Asserts.*;
-
-// package access top-level class to avoid problem with RedefineClassHelper
-// and nested types.
-
-class RedefineRunningMethodsWithBacktrace_B {
- static int count1 = 0;
- static int count2 = 0;
- public static volatile boolean stop = false;
- static void localSleep() {
- try {
- Thread.sleep(10);//sleep for 10 ms
- } catch(InterruptedException ie) {
- }
- }
-
- public static void infinite() {
- while (!stop) { count1++; localSleep(); }
- }
- public static void throwable() {
- // add some stuff to the original constant pool
- String s1 = new String ("string1");
- String s2 = new String ("string2");
- String s3 = new String ("string3");
- String s4 = new String ("string4");
- String s5 = new String ("string5");
- String s6 = new String ("string6");
- String s7 = new String ("string7");
- String s8 = new String ("string8");
- String s9 = new String ("string9");
- String s10 = new String ("string10");
- String s11 = new String ("string11");
- String s12 = new String ("string12");
- String s13 = new String ("string13");
- String s14 = new String ("string14");
- String s15 = new String ("string15");
- String s16 = new String ("string16");
- String s17 = new String ("string17");
- String s18 = new String ("string18");
- String s19 = new String ("string19");
- throw new RuntimeException("throwable called");
- }
-}
-
-public class RedefineRunningMethodsWithBacktrace {
-
- public static String newB =
- "class RedefineRunningMethodsWithBacktrace_B {" +
- " static int count1 = 0;" +
- " static int count2 = 0;" +
- " public static volatile boolean stop = false;" +
- " static void localSleep() { " +
- " try{ " +
- " Thread.sleep(10);" +
- " } catch(InterruptedException ie) { " +
- " } " +
- " } " +
- " public static void infinite() { " +
- " System.out.println(\"infinite called\");" +
- " }" +
- " public static void throwable() { " +
- " throw new RuntimeException(\"throwable called\");" +
- " }" +
- "}";
-
- public static String evenNewerB =
- "class RedefineRunningMethodsWithBacktrace_B {" +
- " static int count1 = 0;" +
- " static int count2 = 0;" +
- " public static volatile boolean stop = false;" +
- " static void localSleep() { " +
- " try{ " +
- " Thread.sleep(1);" +
- " } catch(InterruptedException ie) { " +
- " } " +
- " } " +
- " public static void infinite() { }" +
- " public static void throwable() { " +
- " throw new RuntimeException(\"throwable called\");" +
- " }" +
- "}";
-
- private static void touchRedefinedMethodInBacktrace(Throwable throwable) {
- System.out.println("touchRedefinedMethodInBacktrace: ");
- throwable.printStackTrace(); // this actually crashes with the bug in
- // java_lang_StackTraceElement::create()
-
- // Make sure that we can convert the backtrace, which is referring to
- // the redefined method, to a StrackTraceElement[] without crashing.
- StackTraceElement[] stackTrace = throwable.getStackTrace();
- for (int i = 0; i < stackTrace.length; i++) {
- StackTraceElement frame = stackTrace[i];
- assertNotNull(frame.getClassName(),
- "\nTest failed: trace[" + i + "].getClassName() returned null");
- assertNotNull(frame.getMethodName(),
- "\nTest failed: trace[" + i + "].getMethodName() returned null");
- }
- }
-
- private static Throwable getThrowableInB() {
- Throwable t = null;
- try {
- RedefineRunningMethodsWithBacktrace_B.throwable();
- } catch (Exception e) {
- t = e;
- // Don't print here because Throwable will cache the constructed stacktrace
- // e.printStackTrace();
- }
- return t;
- }
-
-
- public static void main(String[] args) throws Exception {
-
- new Thread() {
- public void run() {
- RedefineRunningMethodsWithBacktrace_B.infinite();
- }
- }.start();
-
- Throwable t1 = getThrowableInB();
-
- RedefineClassHelper.redefineClass(RedefineRunningMethodsWithBacktrace_B.class, newB);
-
- System.gc();
-
- Throwable t2 = getThrowableInB();
-
- RedefineRunningMethodsWithBacktrace_B.infinite();
-
- for (int i = 0; i < 20 ; i++) {
- String s = new String("some garbage");
- System.gc();
- }
-
- RedefineClassHelper.redefineClass(RedefineRunningMethodsWithBacktrace_B.class, evenNewerB);
- System.gc();
-
- Throwable t3 = getThrowableInB();
-
- for (int i = 0; i < 20 ; i++) {
- RedefineRunningMethodsWithBacktrace_B.infinite();
- String s = new String("some garbage");
- System.gc();
- }
-
- touchRedefinedMethodInBacktrace(t1);
- touchRedefinedMethodInBacktrace(t2);
- touchRedefinedMethodInBacktrace(t3);
-
- // purge should clean everything up.
- RedefineRunningMethodsWithBacktrace_B.stop = true;
-
- for (int i = 0; i < 20 ; i++) {
- RedefineRunningMethodsWithBacktrace_B.infinite();
- String s = new String("some garbage");
- System.gc();
- }
- }
-}
--- a/test/hotspot/jtreg/runtime/RedefineTests/RedefineRunningMethodsWithResolutionErrors.java Thu Mar 21 08:41:10 2019 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,144 +0,0 @@
-/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 8076110
- * @summary Redefine running methods that have cached resolution errors
- * @library /test/lib
- * @modules java.base/jdk.internal.misc
- * @modules java.base/jdk.internal.org.objectweb.asm
- * java.instrument
- * jdk.jartool/sun.tools.jar
- * @run main RedefineClassHelper
- * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class+iklass+add=trace,redefine+class+iklass+purge=trace RedefineRunningMethodsWithResolutionErrors
- */
-
-import jdk.internal.org.objectweb.asm.ClassWriter;
-import jdk.internal.org.objectweb.asm.Label;
-import jdk.internal.org.objectweb.asm.MethodVisitor;
-import jdk.internal.org.objectweb.asm.Opcodes;
-
-import java.lang.reflect.InvocationTargetException;
-
-public class RedefineRunningMethodsWithResolutionErrors extends ClassLoader implements Opcodes {
-
- @Override
- protected Class<?> findClass(String name) throws ClassNotFoundException {
- if (name.equals("C")) {
- byte[] b = loadC(false);
- return defineClass(name, b, 0, b.length);
- } else {
- return super.findClass(name);
- }
- }
-
- private static byte[] loadC(boolean redefine) {
- ClassWriter cw = new ClassWriter(0);
-
- cw.visit(52, ACC_SUPER | ACC_PUBLIC, "C", null, "java/lang/Object", null);
- {
- MethodVisitor mv;
-
- mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "m", "()V", null, null);
- mv.visitCode();
-
- // First time we run we will:
- // 1) Cache resolution errors
- // 2) Redefine the class / method
- // 3) Try to read the resolution errors that were cached
- //
- // The redefined method will never run, throw error to be sure
- if (redefine) {
- createThrowRuntimeExceptionCode(mv, "The redefined method was called");
- } else {
- createMethodBody(mv);
- }
- mv.visitMaxs(3, 0);
- mv.visitEnd();
- }
- cw.visitEnd();
- return cw.toByteArray();
- }
-
- private static void createMethodBody(MethodVisitor mv) {
- Label classExists = new Label();
-
- // Cache resolution errors
- createLoadNonExistentClassCode(mv, classExists);
-
- // Redefine our own class and method
- mv.visitMethodInsn(INVOKESTATIC, "RedefineRunningMethodsWithResolutionErrors", "redefine", "()V");
-
- // Provoke the same error again to make sure the resolution error cache works
- createLoadNonExistentClassCode(mv, classExists);
-
- // Test passed
- mv.visitInsn(RETURN);
-
- mv.visitFrame(F_SAME, 0, new Object[0], 0, new Object[0]);
- mv.visitLabel(classExists);
-
- createThrowRuntimeExceptionCode(mv, "Loaded class that shouldn't exist (\"NonExistentClass\")");
- }
-
- private static void createLoadNonExistentClassCode(MethodVisitor mv, Label classExists) {
- Label tryLoadBegin = new Label();
- Label tryLoadEnd = new Label();
- Label catchLoadBlock = new Label();
- mv.visitTryCatchBlock(tryLoadBegin, tryLoadEnd, catchLoadBlock, "java/lang/NoClassDefFoundError");
-
- // Try to load a class that does not exist to provoke resolution errors
- mv.visitLabel(tryLoadBegin);
- mv.visitMethodInsn(INVOKESTATIC, "NonExistentClass", "nonExistentMethod", "()V");
- mv.visitLabel(tryLoadEnd);
-
- // No NoClassDefFoundError means NonExistentClass existed, which shouldn't happen
- mv.visitJumpInsn(GOTO, classExists);
-
- mv.visitFrame(F_SAME1, 0, new Object[0], 1, new Object[] { "java/lang/NoClassDefFoundError" });
- mv.visitLabel(catchLoadBlock);
-
- // Ignore the expected NoClassDefFoundError
- mv.visitInsn(POP);
- }
-
- private static void createThrowRuntimeExceptionCode(MethodVisitor mv, String msg) {
- mv.visitTypeInsn(NEW, "java/lang/RuntimeException");
- mv.visitInsn(DUP);
- mv.visitLdcInsn(msg);
- mv.visitMethodInsn(INVOKESPECIAL, "java/lang/RuntimeException", "<init>", "(Ljava/lang/String;)V");
- mv.visitInsn(ATHROW);
- }
-
- private static Class<?> c;
-
- public static void redefine() throws Exception {
- RedefineClassHelper.redefineClass(c, loadC(true));
- }
-
- public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
- c = Class.forName("C", true, new RedefineRunningMethodsWithResolutionErrors());
- c.getMethod("m").invoke(null);
- }
-}
--- a/test/hotspot/jtreg/runtime/RedefineTests/RedefineSubtractLambdaExpression.java Thu Mar 21 08:41:10 2019 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,78 +0,0 @@
-/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 8193524
- * @summary Redefine a class' public static method that contains a lambda expression
- * @library /test/lib
- * @modules java.base/jdk.internal.misc
- * @modules java.compiler
- * java.instrument
- * jdk.jartool/sun.tools.jar
- * @run main RedefineClassHelper
- * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class*=trace RedefineSubtractLambdaExpression
- */
-
-interface MathOperation {
- public int operation(int a, int b);
-}
-
-class B {
- public static int operate(int a, int b, MathOperation mathOperation) {
- return mathOperation.operation(a, b);
- }
- static int test_math(String p) {
- System.out.println(p + " from class B's test_math method");
- MathOperation subtraction = (int a, int b) -> a - b;
- MathOperation addition = (int a, int b) -> a + b;
- return operate(10, 5, addition);
- }
-}
-
-public class RedefineSubtractLambdaExpression {
-
- public static String newB =
- "class B {" +
- " public static int operate(int a, int b, MathOperation mathOperation) {" +
- " return mathOperation.operation(a, b);" +
- " }" +
- " static int test_math(String p) {" +
- " MathOperation subtraction = (int a, int b) -> a - b;" +
- " return operate(10, 5, subtraction);" +
- " }" +
- "}";
-
- public static void main(String[] args) throws Exception {
- int res = B.test_math("Hello");
- System.out.println("Result = " + res);
- if (res != 15) {
- throw new Error("test_math returned " + res + " expected " + 15);
- }
- RedefineClassHelper.redefineClass(B.class, newB);
-
- res = B.test_math("Hello");
- if (res != 5)
- throw new Error("test_math returned " + res + " expected " + 5);
- }
-}
--- a/test/hotspot/jtreg/runtime/RedefineTests/TestMultipleClasses.java Thu Mar 21 08:41:10 2019 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,120 +0,0 @@
-/*
- * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 8139551
- * @summary Scalability problem with redefinition - multiple code cache walks
- * @library /test/lib
- * @modules java.base/jdk.internal.misc
- * @modules java.compiler
- * java.instrument
- * jdk.jartool/sun.tools.jar
- * @run main RedefineClassHelper
- * @run main/othervm/timeout=180 -javaagent:redefineagent.jar -XX:CompileThreshold=100 -Xlog:redefine+class+nmethod=debug TestMultipleClasses
- */
-
-import java.lang.instrument.*;
-import java.lang.reflect.*;
-import jdk.test.lib.compiler.InMemoryJavaCompiler;
-
-public class TestMultipleClasses extends ClassLoader {
-
- public static String B(int count) {
- return new String("public class B" + count + " {" +
- " public static void compiledMethod() { " +
- " try{" +
- " Thread.sleep(1); " +
- " } catch(InterruptedException ie) {" +
- " }" +
- " }" +
- "}");
- }
-
- static String newB(int count) {
- return new String("public class B" + count + " {" +
- " public static void compiledMethod() { " +
- " System.out.println(\"compiledMethod called " + count + "\");" +
- " }" +
- "}");
- }
-
- static int index = 0;
-
- @Override
- protected Class<?> findClass(String name) throws ClassNotFoundException {
- if (name.equals("B" + index)) {
- byte[] b = InMemoryJavaCompiler.compile(name, B(index));
- return defineClass(name, b, 0, b.length);
- } else {
- return super.findClass(name);
- }
- }
-
- static void runCompiledMethodMethods(Class c, int count) throws Exception {
- // Run for a while so they compile.
- Object o = c.newInstance();
- Method m = c.getMethod("compiledMethod");
- for (int i = 0; i < count; i++) {
- m.invoke(o);
- }
- }
-
- public static void main(String[] args) throws Exception {
-
- final int numberOfClasses = 20;
- Class[] classes = new Class[numberOfClasses];
- byte[][] newClass = new byte[numberOfClasses][];
- ClassDefinition[] defs = new ClassDefinition[numberOfClasses];
-
- TestMultipleClasses loader = new TestMultipleClasses();
-
- // Load and start all the classes.
- for (index = 0; index < numberOfClasses; index++) {
- String name = new String("B" + index);
- Class c = loader.findClass(name);
-
- runCompiledMethodMethods(c, 500);
- // Make class definition for redefinition
- classes[index] = c;
- newClass[index] = InMemoryJavaCompiler.compile(c.getName(), newB(index));
- defs[index] = new ClassDefinition(c, newClass[index]);
- }
-
- long startTime = System.currentTimeMillis();
-
- // Redefine all classes.
- RedefineClassHelper.instrumentation.redefineClasses(defs);
-
- long endTime = System.currentTimeMillis();
-
- System.out.println("Redefinition took " + (endTime - startTime) + " milliseconds");
-
- System.gc();
-
- // Run all new classes.
- for (index = 0; index < numberOfClasses; index++) {
- runCompiledMethodMethods(classes[index], 1);
- }
- }
-}
--- a/test/hotspot/jtreg/runtime/RedefineTests/libRedefineDeleteJmethod.c Thu Mar 21 08:41:10 2019 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include <jni.h>
-
-jmethodID mid;
-jclass cls;
-static int count = 0;
-
-JNIEXPORT jint JNICALL
-Java_RedefineDeleteJmethod_jniCallDeleteMe(JNIEnv* env, jobject obj) {
-
- if (count == 0) {
- count++;
- cls = (*env)->FindClass(env, "B");
- if (NULL == cls) {
- (*env)->FatalError(env, "could not find class");
- }
-
- mid = (*env)->GetStaticMethodID(env, cls, "deleteMe", "()I");
- if (NULL == mid) {
- (*env)->FatalError(env, "could not find method");
- }
- }
-
- return (*env)->CallStaticIntMethod(env, cls, mid);
-}
--- a/test/hotspot/jtreg/runtime/RedefineTests/libRedefineDoubleDelete.c Thu Mar 21 08:41:10 2019 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,164 +0,0 @@
-/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include "jvmti.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef JNI_ENV_ARG
-
-#ifdef __cplusplus
-#define JNI_ENV_ARG(x, y) y
-#define JNI_ENV_PTR(x) x
-#else
-#define JNI_ENV_ARG(x,y) x, y
-#define JNI_ENV_PTR(x) (*x)
-#endif
-
-#endif
-
-#define TranslateError(err) "JVMTI error"
-
-static jvmtiEnv *jvmti = NULL;
-
-static jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved);
-
-JNIEXPORT
-jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
- return Agent_Initialize(jvm, options, reserved);
-}
-
-JNIEXPORT
-jint JNICALL Agent_OnAttach(JavaVM *jvm, char *options, void *reserved) {
- return Agent_Initialize(jvm, options, reserved);
-}
-
-JNIEXPORT
-jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
- return JNI_VERSION_9;
-}
-
-
-static jint newClassDataLen = 0;
-static unsigned char* newClassData = NULL;
-
-static jint
-getBytecodes(jvmtiEnv *jvmti_env,
- jint class_data_len, const unsigned char* class_data) {
- int i;
- jint res;
-
- newClassDataLen = class_data_len;
- res = (*jvmti_env)->Allocate(jvmti_env, newClassDataLen, &newClassData);
- if (res != JNI_OK) {
- printf(" Unable to allocate bytes\n");
- return JNI_ERR;
- }
- for (i = 0; i < newClassDataLen; i++) {
- newClassData[i] = class_data[i];
- // Rewrite oo in class to aa
- if (i > 0 && class_data[i] == 'o' && class_data[i-1] == 'o') {
- newClassData[i] = newClassData[i-1] = 'a';
- }
- }
- printf(" ... copied bytecode: %d bytes\n", (int)newClassDataLen);
- return JNI_OK;
-}
-
-
-static void JNICALL
-Callback_ClassFileLoadHook(jvmtiEnv *jvmti_env, JNIEnv *env,
- jclass class_being_redefined,
- jobject loader, const char* name, jobject protection_domain,
- jint class_data_len, const unsigned char* class_data,
- jint *new_class_data_len, unsigned char** new_class_data) {
- if (name != NULL && strcmp(name, "RedefineDoubleDelete$B") == 0) {
- if (newClassData == NULL) {
- jint res = getBytecodes(jvmti_env, class_data_len, class_data);
- if (res == JNI_ERR) {
- printf(">>> ClassFileLoadHook event: class name %s FAILED\n", name);
- return;
- }
- // Only change for first CFLH event.
- *new_class_data_len = newClassDataLen;
- *new_class_data = newClassData;
- }
- printf(">>> ClassFileLoadHook event: class name %s\n", name);
- }
-}
-
-static
-jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
- jint res, size;
- jvmtiCapabilities caps;
- jvmtiEventCallbacks callbacks;
- jvmtiError err;
-
- res = JNI_ENV_PTR(jvm)->GetEnv(JNI_ENV_ARG(jvm, (void **) &jvmti),
- JVMTI_VERSION_9);
- if (res != JNI_OK || jvmti == NULL) {
- printf(" Error: wrong result of a valid call to GetEnv!\n");
- return JNI_ERR;
- }
-
- printf("Enabling following capabilities: can_generate_all_class_hook_events, "
- "can_retransform_classes, can_redefine_classes");
- memset(&caps, 0, sizeof(caps));
- caps.can_generate_all_class_hook_events = 1;
- caps.can_retransform_classes = 1;
- caps.can_redefine_classes = 1;
- printf("\n");
-
- err = (*jvmti)->AddCapabilities(jvmti, &caps);
- if (err != JVMTI_ERROR_NONE) {
- printf(" Error in AddCapabilites: %s (%d)\n", TranslateError(err), err);
- return JNI_ERR;
- }
-
- size = (jint)sizeof(callbacks);
-
- memset(&callbacks, 0, sizeof(callbacks));
- callbacks.ClassFileLoadHook = Callback_ClassFileLoadHook;
-
- err = (*jvmti)->SetEventCallbacks(jvmti, &callbacks, size);
- if (err != JVMTI_ERROR_NONE) {
- printf(" Error in SetEventCallbacks: %s (%d)\n", TranslateError(err), err);
- return JNI_ERR;
- }
-
- err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, NULL);
- if (err != JVMTI_ERROR_NONE) {
- printf(" Error in SetEventNotificationMode: %s (%d)\n", TranslateError(err), err);
- return JNI_ERR;
- }
-
- return JNI_OK;
-}
-
-#ifdef __cplusplus
-}
-#endif
--- a/test/hotspot/jtreg/runtime/appcds/redefineClass/RedefineBasicTest.java Thu Mar 21 08:41:10 2019 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/redefineClass/RedefineBasicTest.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -24,10 +24,10 @@
/*
* @test
- * @summary Run /runtime/RedefineTests/RedefineRunningMethods in AppCDS mode to
+ * @summary Run /serviceability/jvmti/RedefineClasses/RedefineRunningMethods in AppCDS mode to
* make sure class redefinition works with CDS.
* @requires vm.cds
- * @library /test/lib /test/hotspot/jtreg/runtime/RedefineTests /test/hotspot/jtreg/runtime/appcds
+ * @library /test/lib /test/hotspot/jtreg/serviceability/jvmti/RedefineClasses /test/hotspot/jtreg/runtime/appcds
* @modules java.compiler
* java.instrument
* jdk.jartool/sun.tools.jar
--- a/test/hotspot/jtreg/runtime/appcds/redefineClass/RedefineRunningMethods_Shared.java Thu Mar 21 08:41:10 2019 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/redefineClass/RedefineRunningMethods_Shared.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -24,10 +24,10 @@
/*
* @test
- * @summary Run /runtime/RedefineTests/RedefineRunningMethods in AppCDS mode to
+ * @summary Run /serviceability/jvmti/RedefineClasses/RedefineRunningMethods in AppCDS mode to
* make sure class redefinition works with CDS.
* @requires vm.cds
- * @library /test/lib /test/hotspot/jtreg/runtime/RedefineTests /test/hotspot/jtreg/runtime/appcds
+ * @library /test/lib /test/hotspot/jtreg/serviceability/jvmti/RedefineClasses /test/hotspot/jtreg/runtime/appcds
* @modules java.base/jdk.internal.misc
* @modules java.compiler
* java.instrument
--- a/test/hotspot/jtreg/runtime/logging/RedefineClasses.java Thu Mar 21 08:41:10 2019 +0000
+++ b/test/hotspot/jtreg/runtime/logging/RedefineClasses.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
* @test
* @bug 8197901 8209758
* @summary Redefine classes with enabling logging to verify Klass:external_name() during GC.
- * @comment This test is simplified version of runtime/RedefineTests/RedefineRunningMethods.java.
+ * @comment This test is simplified version of serviceability/jvmti/RedefineClasses/RedefineRunningMethods.java.
* @library /test/lib
* @modules java.compiler
* java.instrument
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/Agent.java Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+import java.security.*;
+import java.lang.instrument.*;
+import java.lang.reflect.*;
+
+public class Agent implements ClassFileTransformer {
+ public synchronized byte[] transform(final ClassLoader classLoader,
+ final String className,
+ Class<?> classBeingRedefined,
+ ProtectionDomain protectionDomain,
+ byte[] classfileBuffer) {
+ System.out.println("Transforming class " + className);
+ return classfileBuffer;
+ }
+
+ public static void redefine(String agentArgs, Instrumentation instrumentation, Class to_redefine) {
+
+ try {
+ instrumentation.retransformClasses(to_redefine);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ }
+
+ public static void premain(String agentArgs, Instrumentation instrumentation) {
+ Agent transformer = new Agent();
+ instrumentation.addTransformer(transformer, true);
+
+ // Redefine java/lang/Object and java/lang/reflect/Method.invoke and
+ // java/lang/ClassLoader
+ Class object_class = Object.class;
+ redefine(agentArgs, instrumentation, object_class);
+
+ Class method_class = Method.class;
+ redefine(agentArgs, instrumentation, method_class);
+
+ Class loader_class = ClassLoader.class;
+ redefine(agentArgs, instrumentation, loader_class);
+
+ instrumentation.removeTransformer(transformer);
+ }
+
+ public static void main(String[] args) {
+ byte[] ba = new byte[0];
+
+ // If it survives 100 GC's, it's good.
+ for (int i = 0; i < 100 ; i++) {
+ System.gc();
+ ba.clone();
+ }
+ try {
+ // Use java/lang/reflect/Method.invoke to call
+ WalkThroughInvoke a = new WalkThroughInvoke();
+ Class aclass = WalkThroughInvoke.class;
+ Method m = aclass.getMethod("stackWalk");
+ m.invoke(a);
+ } catch (Exception x) {
+ x.printStackTrace();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/ModifyAnonymous.java Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @library /test/lib
+ * @summary Test that retransforming and redefining anonymous classes gets UnmodifiableClassException
+ * @modules java.base/jdk.internal.misc
+ * @modules java.instrument
+ * jdk.jartool/sun.tools.jar
+ * @run main ModifyAnonymous buildagent
+ * @run main/othervm -javaagent:redefineagent.jar ModifyAnonymous
+ */
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.PrintWriter;
+import java.lang.RuntimeException;
+import java.lang.instrument.ClassDefinition;
+import java.lang.instrument.ClassFileTransformer;
+import java.lang.instrument.IllegalClassFormatException;
+import java.lang.instrument.Instrumentation;
+import java.security.ProtectionDomain;
+
+import jdk.test.lib.compiler.InMemoryJavaCompiler;
+
+public class ModifyAnonymous {
+
+ public static class LambdaTransformer implements ClassFileTransformer {
+ @Override
+ public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
+ ProtectionDomain protectionDomain, byte[] classfileBuffer)
+ throws IllegalClassFormatException {
+ return null;
+ }
+ }
+
+ static Instrumentation inst = null;
+ static volatile boolean done = false;
+
+ public static void premain(String args, Instrumentation instrumentation) {
+
+ inst = instrumentation;
+ System.out.println("javaagent in da house!");
+ instrumentation.addTransformer(new LambdaTransformer());
+ }
+
+ private static void buildAgent() {
+ try {
+ ClassFileInstaller.main("ModifyAnonymous");
+ } catch (Exception e) {
+ throw new RuntimeException("Could not write agent classfile", e);
+ }
+
+ try {
+ PrintWriter pw = new PrintWriter("MANIFEST.MF");
+ pw.println("Premain-Class: ModifyAnonymous");
+ pw.println("Agent-Class: ModifyAnonymous");
+ pw.println("Can-Retransform-Classes: true");
+ pw.println("Can-Redefine-Classes: true");
+ pw.close();
+ } catch (FileNotFoundException e) {
+ throw new RuntimeException("Could not write manifest file for the agent", e);
+ }
+
+ sun.tools.jar.Main jarTool = new sun.tools.jar.Main(System.out, System.err, "jar");
+ if (!jarTool.run(new String[] { "-cmf", "MANIFEST.MF", "redefineagent.jar", "ModifyAnonymous.class" })) {
+ throw new RuntimeException("Could not write the agent jar file");
+ }
+ }
+
+ public static class InstanceMethodCallSiteApp {
+
+ public static void test() throws InterruptedException {
+ for (int i = 0; i < 2; i++) {
+ InstanceMethodCallSiteApp app = new InstanceMethodCallSiteApp();
+ Runnable r = app::doWork; // this creates an anonymous class
+ while (!done) {
+ r.run();
+ Thread.sleep(10);
+ }
+ }
+ }
+
+ public void doWork() {
+ System.out.print(".");
+ }
+ }
+
+ static void runTest() {
+ PrintWriter pw;
+ String logName = System.getProperty("test.classes") +
+ File.separator + "loadedClasses.log";
+ // Create a log file to capture the names of the classes in the
+ // allLoadedClasses array. The log file is for assisting in debugging
+ // in case a null class is encountered in the allLoadedClasses array.
+ try {
+ pw = new PrintWriter(new FileOutputStream(
+ new File(logName), true));
+ } catch (FileNotFoundException e) {
+ throw new RuntimeException("Could not write loaded classes to log", e);
+ }
+ while (!done) {
+ Class[] allLoadedClasses = inst.getAllLoadedClasses();
+ int len = allLoadedClasses.length;
+ pw.println(" allLoadedClasses length: " + len);
+ for (int idx = 0; idx < len; idx++) {
+ Class cls = allLoadedClasses[idx];
+ pw.println(" " + idx + " " +
+ ((cls != null) ? cls.getName() : "null"));
+ }
+ for (int idx = 0; idx < len; idx++) {
+ Class clazz = allLoadedClasses[idx];
+ if (clazz == null) {
+ pw.flush();
+ pw.close();
+ throw new RuntimeException("null class encountered");
+ }
+ final String name = clazz.getName();
+ if (name.contains("$$Lambda$") && name.contains("App")) {
+ if (inst.isModifiableClass(clazz)) {
+ pw.flush();
+ pw.close();
+ throw new RuntimeException ("Class should not be modifiable");
+ }
+ // Try to modify them anyway.
+ try {
+ System.out.println("retransform called for " + name);
+ inst.retransformClasses(clazz);
+ } catch(java.lang.instrument.UnmodifiableClassException t) {
+ System.out.println("PASSED: expecting UnmodifiableClassException");
+ t.printStackTrace();
+ }
+ try {
+ System.out.println("redefine called for " + name);
+ String newclass = "class Dummy {}";
+ byte[] bytecode = InMemoryJavaCompiler.compile("Dummy", newclass);
+ ClassDefinition cld = new ClassDefinition(clazz, bytecode);
+ inst.redefineClasses(new ClassDefinition[] { cld });
+ } catch(java.lang.instrument.UnmodifiableClassException t) {
+ System.out.println("PASSED: expecting UnmodifiableClassException");
+ t.printStackTrace();
+ } catch(java.lang.ClassNotFoundException e) {
+ pw.flush();
+ pw.close();
+ throw new RuntimeException ("ClassNotFoundException thrown");
+ }
+ done = true;
+ }
+ }
+ }
+ pw.flush();
+ pw.close();
+ }
+
+ public static void main(String argv[]) throws InterruptedException, RuntimeException {
+ if (argv.length == 1 && argv[0].equals("buildagent")) {
+ buildAgent();
+ return;
+ }
+
+ if (inst == null) {
+ throw new RuntimeException("Instrumentation object was null");
+ }
+
+ new Thread() {
+ public void run() {
+ runTest();
+ }
+ }.start();
+
+ // Test that NCDFE is not thrown for anonymous class:
+ // ModifyAnonymous$InstanceMethodCallSiteApp$$Lambda$18
+ try {
+ ModifyAnonymous test = new ModifyAnonymous();
+ InstanceMethodCallSiteApp.test();
+ } catch (NoClassDefFoundError e) {
+ throw new RuntimeException("FAILED: NoClassDefFoundError thrown for " + e.getMessage());
+ }
+ System.out.println("PASSED: NoClassDefFound error not thrown");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineAddLambdaExpression.java Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8193524
+ * @summary Redefine a class' public static method that contains a lambda expression
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * @modules java.compiler
+ * java.instrument
+ * jdk.jartool/sun.tools.jar
+ * @run main RedefineClassHelper
+ * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class*=trace RedefineAddLambdaExpression
+ */
+
+interface MathOperation {
+ public int operation(int a, int b);
+}
+
+class B {
+ public static int operate(int a, int b, MathOperation mathOperation) {
+ return mathOperation.operation(a, b);
+ }
+ static int test_math(String p) {
+ MathOperation addition = (int a, int b) -> a + b;
+ return operate(10, 5, addition);
+ }
+}
+
+public class RedefineAddLambdaExpression {
+
+ public static String newB =
+ "class B {" +
+ " public static int operate(int a, int b, MathOperation mathOperation) {" +
+ " return mathOperation.operation(a, b);" +
+ " }" +
+ " static int test_math(String p) {" +
+ " MathOperation addition = (int a, int b) -> a + b;" +
+ " System.out.println(p + \" from class B's test_math method\");" +
+ " MathOperation subtraction = (int a, int b) -> a - b;" +
+ " return operate(10, 5, subtraction);" +
+ " }" +
+ "}";
+
+ public static void main(String[] args) throws Exception {
+ int res = B.test_math("Hello");
+ System.out.println("Result = " + res);
+ if (res != 15) {
+ throw new Error("test_math returned " + res + " expected " + 15);
+ }
+ RedefineClassHelper.redefineClass(B.class, newB);
+
+ res = B.test_math("Hello");
+ if (res != 5)
+ throw new Error("test_math returned " + res + " expected " + 5);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineAnnotations.java Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,414 @@
+/*
+ * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @library /test/lib
+ * @summary Test that type annotations are retained after a retransform
+ * @modules java.base/jdk.internal.misc
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ * java.instrument
+ * jdk.jartool/sun.tools.jar
+ * @run main RedefineAnnotations buildagent
+ * @run main/othervm -javaagent:redefineagent.jar RedefineAnnotations
+ */
+
+import static jdk.test.lib.Asserts.assertTrue;
+import java.io.FileNotFoundException;
+import java.io.PrintWriter;
+import java.lang.NoSuchFieldException;
+import java.lang.NoSuchMethodException;
+import java.lang.RuntimeException;
+import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.instrument.ClassFileTransformer;
+import java.lang.instrument.IllegalClassFormatException;
+import java.lang.instrument.Instrumentation;
+import java.lang.instrument.UnmodifiableClassException;
+import java.lang.reflect.AnnotatedArrayType;
+import java.lang.reflect.AnnotatedParameterizedType;
+import java.lang.reflect.AnnotatedType;
+import java.lang.reflect.AnnotatedWildcardType;
+import java.lang.reflect.Executable;
+import java.lang.reflect.TypeVariable;
+import java.security.ProtectionDomain;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import jdk.internal.org.objectweb.asm.ClassReader;
+import jdk.internal.org.objectweb.asm.ClassVisitor;
+import jdk.internal.org.objectweb.asm.ClassWriter;
+import jdk.internal.org.objectweb.asm.FieldVisitor;
+import static jdk.internal.org.objectweb.asm.Opcodes.ASM7;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE_USE)
+@interface TestAnn {
+ String site();
+}
+
+public class RedefineAnnotations {
+ static Instrumentation inst;
+ public static void premain(String agentArgs, Instrumentation inst) {
+ RedefineAnnotations.inst = inst;
+ }
+
+ static class Transformer implements ClassFileTransformer {
+
+ public byte[] asm(ClassLoader loader, String className,
+ Class<?> classBeingRedefined,
+ ProtectionDomain protectionDomain, byte[] classfileBuffer)
+ throws IllegalClassFormatException {
+
+ ClassWriter cw = new ClassWriter(0);
+ ClassVisitor cv = new ReAddDummyFieldsClassVisitor(ASM7, cw) { };
+ ClassReader cr = new ClassReader(classfileBuffer);
+ cr.accept(cv, 0);
+ return cw.toByteArray();
+ }
+
+ public class ReAddDummyFieldsClassVisitor extends ClassVisitor {
+
+ LinkedList<F> fields = new LinkedList<>();
+
+ public ReAddDummyFieldsClassVisitor(int api, ClassVisitor cv) {
+ super(api, cv);
+ }
+
+ @Override public FieldVisitor visitField(int access, String name,
+ String desc, String signature, Object value) {
+ if (name.startsWith("dummy")) {
+ // Remove dummy field
+ fields.addLast(new F(access, name, desc, signature, value));
+ return null;
+ }
+ return cv.visitField(access, name, desc, signature, value);
+ }
+
+ @Override public void visitEnd() {
+ F f;
+ while ((f = fields.pollFirst()) != null) {
+ // Re-add dummy fields
+ cv.visitField(f.access, f.name, f.desc, f.signature, f.value);
+ }
+ }
+
+ private class F {
+ private int access;
+ private String name;
+ private String desc;
+ private String signature;
+ private Object value;
+ F(int access, String name, String desc, String signature, Object value) {
+ this.access = access;
+ this.name = name;
+ this.desc = desc;
+ this.signature = signature;
+ this.value = value;
+ }
+ }
+ }
+
+ @Override public byte[] transform(ClassLoader loader, String className,
+ Class<?> classBeingRedefined,
+ ProtectionDomain protectionDomain, byte[] classfileBuffer)
+ throws IllegalClassFormatException {
+
+ if (className.contains("TypeAnnotatedTestClass")) {
+ try {
+ // Here we remove and re-add the dummy fields. This shuffles the constant pool
+ return asm(loader, className, classBeingRedefined, protectionDomain, classfileBuffer);
+ } catch (Throwable e) {
+ // The retransform native code that called this method does not propagate
+ // exceptions. Instead of getting an uninformative generic error, catch
+ // problems here and print it, then exit.
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+ return null;
+ }
+ }
+
+ private static void buildAgent() {
+ try {
+ ClassFileInstaller.main("RedefineAnnotations");
+ } catch (Exception e) {
+ throw new RuntimeException("Could not write agent classfile", e);
+ }
+
+ try {
+ PrintWriter pw = new PrintWriter("MANIFEST.MF");
+ pw.println("Premain-Class: RedefineAnnotations");
+ pw.println("Agent-Class: RedefineAnnotations");
+ pw.println("Can-Retransform-Classes: true");
+ pw.close();
+ } catch (FileNotFoundException e) {
+ throw new RuntimeException("Could not write manifest file for the agent", e);
+ }
+
+ sun.tools.jar.Main jarTool = new sun.tools.jar.Main(System.out, System.err, "jar");
+ if (!jarTool.run(new String[] { "-cmf", "MANIFEST.MF", "redefineagent.jar", "RedefineAnnotations.class" })) {
+ throw new RuntimeException("Could not write the agent jar file");
+ }
+ }
+
+ public static void main(String argv[]) throws NoSuchFieldException, NoSuchMethodException {
+ if (argv.length == 1 && argv[0].equals("buildagent")) {
+ buildAgent();
+ return;
+ }
+
+ if (inst == null) {
+ throw new RuntimeException("Instrumentation object was null");
+ }
+
+ RedefineAnnotations test = new RedefineAnnotations();
+ test.testTransformAndVerify();
+ }
+
+ // Class type annotations
+ private Annotation classTypeParameterTA;
+ private Annotation extendsTA;
+ private Annotation implementsTA;
+
+ // Field type annotations
+ private Annotation fieldTA;
+ private Annotation innerTA;
+ private Annotation[] arrayTA = new Annotation[4];
+ private Annotation[] mapTA = new Annotation[5];
+
+ // Method type annotations
+ private Annotation returnTA, methodTypeParameterTA, formalParameterTA, throwsTA;
+
+ private void testTransformAndVerify()
+ throws NoSuchFieldException, NoSuchMethodException {
+
+ Class<TypeAnnotatedTestClass> c = TypeAnnotatedTestClass.class;
+ Class<?> myClass = c;
+
+ /*
+ * Verify that the expected annotations are where they should be before transform.
+ */
+ verifyClassTypeAnnotations(c);
+ verifyFieldTypeAnnotations(c);
+ verifyMethodTypeAnnotations(c);
+
+ try {
+ inst.addTransformer(new Transformer(), true);
+ inst.retransformClasses(myClass);
+ } catch (UnmodifiableClassException e) {
+ throw new RuntimeException(e);
+ }
+
+ /*
+ * Verify that the expected annotations are where they should be after transform.
+ * Also verify that before and after are equal.
+ */
+ verifyClassTypeAnnotations(c);
+ verifyFieldTypeAnnotations(c);
+ verifyMethodTypeAnnotations(c);
+ }
+
+ private void verifyClassTypeAnnotations(Class c) {
+ Annotation anno;
+
+ anno = c.getTypeParameters()[0].getAnnotations()[0];
+ verifyTestAnn(classTypeParameterTA, anno, "classTypeParameter");
+ classTypeParameterTA = anno;
+
+ anno = c.getAnnotatedSuperclass().getAnnotations()[0];
+ verifyTestAnn(extendsTA, anno, "extends");
+ extendsTA = anno;
+
+ anno = c.getAnnotatedInterfaces()[0].getAnnotations()[0];
+ verifyTestAnn(implementsTA, anno, "implements");
+ implementsTA = anno;
+ }
+
+ private void verifyFieldTypeAnnotations(Class c)
+ throws NoSuchFieldException, NoSuchMethodException {
+
+ verifyBasicFieldTypeAnnotations(c);
+ verifyInnerFieldTypeAnnotations(c);
+ verifyArrayFieldTypeAnnotations(c);
+ verifyMapFieldTypeAnnotations(c);
+ }
+
+ private void verifyBasicFieldTypeAnnotations(Class c)
+ throws NoSuchFieldException, NoSuchMethodException {
+
+ Annotation anno = c.getDeclaredField("typeAnnotatedBoolean").getAnnotatedType().getAnnotations()[0];
+ verifyTestAnn(fieldTA, anno, "field");
+ fieldTA = anno;
+ }
+
+ private void verifyInnerFieldTypeAnnotations(Class c)
+ throws NoSuchFieldException, NoSuchMethodException {
+
+ AnnotatedType at = c.getDeclaredField("typeAnnotatedInner").getAnnotatedType();
+ Annotation anno = at.getAnnotations()[0];
+ verifyTestAnn(innerTA, anno, "inner");
+ innerTA = anno;
+ }
+
+ private void verifyArrayFieldTypeAnnotations(Class c)
+ throws NoSuchFieldException, NoSuchMethodException {
+
+ Annotation anno;
+ AnnotatedType at;
+
+ at = c.getDeclaredField("typeAnnotatedArray").getAnnotatedType();
+ anno = at.getAnnotations()[0];
+ verifyTestAnn(arrayTA[0], anno, "array1");
+ arrayTA[0] = anno;
+
+ for (int i = 1; i <= 3; i++) {
+ at = ((AnnotatedArrayType) at).getAnnotatedGenericComponentType();
+ anno = at.getAnnotations()[0];
+ verifyTestAnn(arrayTA[i], anno, "array" + (i + 1));
+ arrayTA[i] = anno;
+ }
+ }
+
+ private void verifyMapFieldTypeAnnotations(Class c)
+ throws NoSuchFieldException, NoSuchMethodException {
+
+ Annotation anno;
+ AnnotatedType atBase;
+ AnnotatedType atParameter;
+ atBase = c.getDeclaredField("typeAnnotatedMap").getAnnotatedType();
+
+ anno = atBase.getAnnotations()[0];
+ verifyTestAnn(mapTA[0], anno, "map1");
+ mapTA[0] = anno;
+
+ atParameter =
+ ((AnnotatedParameterizedType) atBase).
+ getAnnotatedActualTypeArguments()[0];
+ anno = ((AnnotatedWildcardType) atParameter).getAnnotations()[0];
+ verifyTestAnn(mapTA[1], anno, "map2");
+ mapTA[1] = anno;
+
+ anno =
+ ((AnnotatedWildcardType) atParameter).
+ getAnnotatedUpperBounds()[0].getAnnotations()[0];
+ verifyTestAnn(mapTA[2], anno, "map3");
+ mapTA[2] = anno;
+
+ atParameter =
+ ((AnnotatedParameterizedType) atBase).
+ getAnnotatedActualTypeArguments()[1];
+ anno = ((AnnotatedParameterizedType) atParameter).getAnnotations()[0];
+ verifyTestAnn(mapTA[3], anno, "map4");
+ mapTA[3] = anno;
+
+ anno =
+ ((AnnotatedParameterizedType) atParameter).
+ getAnnotatedActualTypeArguments()[0].getAnnotations()[0];
+ verifyTestAnn(mapTA[4], anno, "map5");
+ mapTA[4] = anno;
+ }
+
+ private void verifyMethodTypeAnnotations(Class c)
+ throws NoSuchFieldException, NoSuchMethodException {
+ Annotation anno;
+ Executable typeAnnotatedMethod =
+ c.getDeclaredMethod("typeAnnotatedMethod", TypeAnnotatedTestClass.class);
+
+ anno = typeAnnotatedMethod.getAnnotatedReturnType().getAnnotations()[0];
+ verifyTestAnn(returnTA, anno, "return");
+ returnTA = anno;
+
+ anno = typeAnnotatedMethod.getTypeParameters()[0].getAnnotations()[0];
+ verifyTestAnn(methodTypeParameterTA, anno, "methodTypeParameter");
+ methodTypeParameterTA = anno;
+
+ anno = typeAnnotatedMethod.getAnnotatedParameterTypes()[0].getAnnotations()[0];
+ verifyTestAnn(formalParameterTA, anno, "formalParameter");
+ formalParameterTA = anno;
+
+ anno = typeAnnotatedMethod.getAnnotatedExceptionTypes()[0].getAnnotations()[0];
+ verifyTestAnn(throwsTA, anno, "throws");
+ throwsTA = anno;
+ }
+
+ private static void verifyTestAnn(Annotation verifyAgainst, Annotation anno, String expectedSite) {
+ verifyTestAnnSite(anno, expectedSite);
+
+ // When called before transform verifyAgainst will be null, when called
+ // after transform it will be the annotation from before the transform
+ if (verifyAgainst != null) {
+ assertTrue(anno.equals(verifyAgainst),
+ "Annotations do not match before and after." +
+ " Before: \"" + verifyAgainst + "\", After: \"" + anno + "\"");
+ }
+ }
+
+ private static void verifyTestAnnSite(Annotation testAnn, String expectedSite) {
+ String expectedAnn = "@TestAnn(site=\"" + expectedSite + "\")";
+ assertTrue(testAnn.toString().equals(expectedAnn),
+ "Expected \"" + expectedAnn + "\", got \"" + testAnn + "\"");
+ }
+
+ public static class TypeAnnotatedTestClass <@TestAnn(site="classTypeParameter") S,T>
+ extends @TestAnn(site="extends") Thread
+ implements @TestAnn(site="implements") Runnable {
+
+ public @TestAnn(site="field") boolean typeAnnotatedBoolean;
+
+ public
+ RedefineAnnotations.
+ @TestAnn(site="inner") TypeAnnotatedTestClass
+ typeAnnotatedInner;
+
+ public
+ @TestAnn(site="array4") boolean
+ @TestAnn(site="array1") []
+ @TestAnn(site="array2") []
+ @TestAnn(site="array3") []
+ typeAnnotatedArray;
+
+ public @TestAnn(site="map1") Map
+ <@TestAnn(site="map2") ? extends @TestAnn(site="map3") String,
+ @TestAnn(site="map4") List<@TestAnn(site="map5") Object>> typeAnnotatedMap;
+
+ public int dummy1;
+ public int dummy2;
+ public int dummy3;
+
+ @TestAnn(site="return") <@TestAnn(site="methodTypeParameter") U,V> Class
+ typeAnnotatedMethod(@TestAnn(site="formalParameter") TypeAnnotatedTestClass arg)
+ throws @TestAnn(site="throws") ClassNotFoundException {
+
+ @TestAnn(site="local_variable_type") int foo = 0;
+ throw new ClassNotFoundException();
+ }
+
+ public void run() {}
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineDeleteJmethod.java Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8181171
+ * @summary Test deleting static method pointing to by a jmethod
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * @modules java.compiler
+ * java.instrument
+ * jdk.jartool/sun.tools.jar
+ * @run main RedefineClassHelper
+ * @run main/native/othervm -javaagent:redefineagent.jar -Xlog:redefine+class*=trace RedefineDeleteJmethod
+ */
+
+class B {
+ private static int deleteMe() { System.out.println("deleteMe called"); return 5; }
+ public static int callDeleteMe() { return deleteMe(); }
+}
+
+public class RedefineDeleteJmethod {
+
+ public static String newB =
+ "class B {" +
+ "public static int callDeleteMe() { return 6; }" +
+ "}";
+
+ public static String newerB =
+ "class B {" +
+ "private static int deleteMe() { System.out.println(\"deleteMe (2) called\"); return 7; }" +
+ "public static int callDeleteMe() { return deleteMe(); }" +
+ "}";
+
+
+ static {
+ System.loadLibrary("RedefineDeleteJmethod");
+ }
+
+ static native int jniCallDeleteMe();
+
+ static void test(int expected, boolean nsme_expected) throws Exception {
+ // Call through static method
+ int res = B.callDeleteMe();
+ System.out.println("Result = " + res);
+ if (res != expected) {
+ throw new Error("returned " + res + " expected " + expected);
+ }
+
+ // Call through jmethodID, saved from first call.
+ try {
+ res = jniCallDeleteMe();
+ if (nsme_expected) {
+ throw new RuntimeException("Failed, NoSuchMethodError expected");
+ }
+ if (res != expected) {
+ throw new Error("returned " + res + " expected " + expected);
+ }
+ } catch (NoSuchMethodError ex) {
+ if (!nsme_expected) {
+ throw new RuntimeException("Failed, NoSuchMethodError not expected");
+ }
+ System.out.println("Passed, NoSuchMethodError expected");
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ test(5, false);
+ RedefineClassHelper.redefineClass(B.class, newB);
+ test(6, true);
+ RedefineClassHelper.redefineClass(B.class, newerB);
+ test(7, true);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineDoubleDelete.java Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8178870 8010319
+ * @summary Redefine class with CFLH twice to test deleting the cached_class_file
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * @modules java.compiler
+ * java.instrument
+ * jdk.jartool/sun.tools.jar
+ * @run main RedefineClassHelper
+ * @run main/othervm/native -Xlog:redefine+class+load+exceptions -agentlib:RedefineDoubleDelete -javaagent:redefineagent.jar RedefineDoubleDelete
+ */
+
+// package access top-level class to avoid problem with RedefineClassHelper
+// and nested types.
+
+// The ClassFileLoadHook for this class turns foo into faa and prints out faa.
+class RedefineDoubleDelete_B {
+ int faa() { System.out.println("foo"); return 1; }
+}
+
+public class RedefineDoubleDelete {
+
+ // Class gets a redefinition error because it adds a data member
+ public static String newB =
+ "class RedefineDoubleDelete_B {" +
+ " int count1 = 0;" +
+ "}";
+
+ public static String newerB =
+ "class RedefineDoubleDelete_B { " +
+ " int faa() { System.out.println(\"baa\"); return 2; }" +
+ "}";
+
+ public static void main(String args[]) throws Exception {
+
+ RedefineDoubleDelete_B b = new RedefineDoubleDelete_B();
+ int val = b.faa();
+ if (val != 1) {
+ throw new RuntimeException("return value wrong " + val);
+ }
+
+ // Redefine B twice to get cached_class_file in both B scratch classes
+ try {
+ RedefineClassHelper.redefineClass(RedefineDoubleDelete_B.class, newB);
+ } catch (java.lang.UnsupportedOperationException e) {
+ // this is expected
+ }
+ try {
+ RedefineClassHelper.redefineClass(RedefineDoubleDelete_B.class, newB);
+ } catch (java.lang.UnsupportedOperationException e) {
+ // this is expected
+ }
+
+ // Do a full GC.
+ System.gc();
+
+ // Redefine with a compatible class
+ RedefineClassHelper.redefineClass(RedefineDoubleDelete_B.class, newerB);
+ val = b.faa();
+ if (val != 2) {
+ throw new RuntimeException("return value wrong " + val);
+ }
+
+ // Do another full GC to clean things up.
+ System.gc();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineFinalizer.java Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6904403 8010319
+ * @summary Don't assert if we redefine finalize method
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * @modules java.compiler
+ * java.instrument
+ * jdk.jartool/sun.tools.jar
+ * @run main RedefineClassHelper
+ * @run main/othervm -javaagent:redefineagent.jar RedefineFinalizer
+ */
+
+/*
+ * Regression test for hitting:
+ *
+ * assert(f == k->has_finalizer()) failed: inconsistent has_finalizer
+ *
+ * when redefining finalizer method
+ */
+
+
+// package access top-level class to avoid problem with RedefineClassHelper
+// and nested types.
+class RedefineFinalizer_B {
+ protected void finalize() {
+ // should be empty
+ }
+}
+
+public class RedefineFinalizer {
+
+ public static String newB =
+ "class RedefineFinalizer_B {" +
+ " protected void finalize() { " +
+ " System.out.println(\"Finalizer called\");" +
+ " }" +
+ "}";
+
+ public static void main(String[] args) throws Exception {
+ RedefineClassHelper.redefineClass(RedefineFinalizer_B.class, newB);
+
+ A a = new A();
+ }
+
+ static class A extends RedefineFinalizer_B {
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineInterfaceCall.java Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8174962 8010319
+ * @summary Redefine class with interface method call
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * @modules java.compiler
+ * java.instrument
+ * jdk.jartool/sun.tools.jar
+ * @run main RedefineClassHelper
+ * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class+update*=trace RedefineInterfaceCall
+ */
+
+import static jdk.test.lib.Asserts.assertEquals;
+
+interface I1 { default int m() { return 0; } }
+interface I2 extends I1 {}
+
+// package access top-level class to avoid problem with RedefineClassHelper
+// and nested types.
+class RedefineInterfaceCall_C implements I2 {
+ public int test(I2 i) {
+ return i.m(); // invokeinterface cpCacheEntry
+ }
+}
+
+public class RedefineInterfaceCall {
+
+ static String newI1 =
+ "interface I1 { default int m() { return 1; } }";
+
+ static String newC =
+ "class RedefineInterfaceCall_C implements I2 { " +
+ " public int test(I2 i) { " +
+ " return i.m(); " +
+ " } " +
+ "} ";
+
+ static int test(I2 i) {
+ return i.m(); // invokeinterface cpCacheEntry
+ }
+
+ public static void main(String[] args) throws Exception {
+ RedefineInterfaceCall_C c = new RedefineInterfaceCall_C();
+
+ assertEquals(test(c), 0);
+ assertEquals(c.test(c), 0);
+
+ RedefineClassHelper.redefineClass(RedefineInterfaceCall_C.class, newC);
+
+ assertEquals(c.test(c), 0);
+
+ RedefineClassHelper.redefineClass(I1.class, newI1);
+
+ assertEquals(test(c), 1);
+ assertEquals(c.test(c), 1);
+
+ RedefineClassHelper.redefineClass(RedefineInterfaceCall_C.class, newC);
+
+ assertEquals(c.test(c), 1);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineInterfaceMethods.java Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8081800 8010319
+ * @summary Redefine private and default interface methods
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * @modules java.compiler
+ * java.instrument
+ * jdk.jartool/sun.tools.jar
+ * @run main RedefineClassHelper
+ * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class*=trace RedefineInterfaceMethods
+ */
+
+// package access top-level class to avoid problem with RedefineClassHelper
+// and nested types.
+
+interface RedefineInterfaceMethods_B {
+ int ORIGINAL_RETURN = 1;
+ int NEW_RETURN = 2;
+ private int privateMethod() {
+ return ORIGINAL_RETURN;
+ }
+ public default int defaultMethod() {
+ return privateMethod();
+ }
+}
+
+public class RedefineInterfaceMethods {
+
+ static final int RET = -2;
+
+ public static String redefinedPrivateMethod =
+ "interface RedefineInterfaceMethods_B {" +
+ " int ORIGINAL_RETURN = 1;" +
+ " int NEW_RETURN = 2;" +
+ " private int privateMethod() {" +
+ " return NEW_RETURN;" +
+ " }" +
+ " public default int defaultMethod() {" +
+ " return privateMethod();" +
+ " }" +
+ "}";
+
+ public static String redefinedDefaultMethod =
+ "interface RedefineInterfaceMethods_B {" +
+ " int ORIGINAL_RETURN = 1;" +
+ " int NEW_RETURN = 2;" +
+ " private int privateMethod() {" +
+ " return ORIGINAL_RETURN;" +
+ " }" +
+ " public default int defaultMethod() {" +
+ " return RedefineInterfaceMethods.RET;" +
+ " }" +
+ "}";
+
+ static class Impl implements RedefineInterfaceMethods_B {
+ }
+
+
+ public static void main(String[] args) throws Exception {
+
+ Impl impl = new Impl();
+
+ int res = impl.defaultMethod();
+ if (res != RedefineInterfaceMethods_B.ORIGINAL_RETURN)
+ throw new Error("defaultMethod returned " + res +
+ " expected " + RedefineInterfaceMethods_B.ORIGINAL_RETURN);
+
+ RedefineClassHelper.redefineClass(RedefineInterfaceMethods_B.class, redefinedPrivateMethod);
+
+ res = impl.defaultMethod();
+ if (res != RedefineInterfaceMethods_B.NEW_RETURN)
+ throw new Error("defaultMethod returned " + res +
+ " expected " + RedefineInterfaceMethods_B.NEW_RETURN);
+
+ System.gc();
+
+ RedefineClassHelper.redefineClass(RedefineInterfaceMethods_B.class, redefinedDefaultMethod);
+
+ res = impl.defaultMethod();
+ if (res != RET)
+ throw new Error("defaultMethod returned " + res +
+ " expected " + RET);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineLeak.java Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @library /test/lib
+ * @summary Test that redefinition reuses metaspace blocks that are freed
+ * @modules java.base/jdk.internal.misc
+ * @modules java.instrument
+ * jdk.jartool/sun.tools.jar
+ * @run main RedefineLeak buildagent
+ * @run main/othervm/timeout=6000 RedefineLeak runtest
+ */
+
+import java.io.FileNotFoundException;
+import java.io.PrintWriter;
+import java.lang.RuntimeException;
+import java.lang.instrument.ClassFileTransformer;
+import java.lang.instrument.Instrumentation;
+import java.security.ProtectionDomain;
+import java.lang.instrument.IllegalClassFormatException;
+import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.process.OutputAnalyzer;
+
+public class RedefineLeak {
+ static class Tester {}
+
+ static class LoggingTransformer implements ClassFileTransformer {
+ static int transformCount = 0;
+
+ public LoggingTransformer() {}
+
+ public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined,
+ ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
+
+ transformCount++;
+ if (transformCount % 1000 == 0) System.out.println("transformCount:" + transformCount);
+ return null;
+ }
+ }
+
+ public static void premain(String agentArgs, Instrumentation inst) throws Exception {
+ LoggingTransformer t = new LoggingTransformer();
+ inst.addTransformer(t, true);
+ {
+ Class demoClass = Class.forName("RedefineLeak$Tester");
+
+ for (int i = 0; i < 10000; i++) {
+ inst.retransformClasses(demoClass);
+ }
+ }
+ System.gc();
+ }
+ private static void buildAgent() {
+ try {
+ ClassFileInstaller.main("RedefineLeak");
+ } catch (Exception e) {
+ throw new RuntimeException("Could not write agent classfile", e);
+ }
+
+ try {
+ PrintWriter pw = new PrintWriter("MANIFEST.MF");
+ pw.println("Premain-Class: RedefineLeak");
+ pw.println("Agent-Class: RedefineLeak");
+ pw.println("Can-Redefine-Classes: true");
+ pw.println("Can-Retransform-Classes: true");
+ pw.close();
+ } catch (FileNotFoundException e) {
+ throw new RuntimeException("Could not write manifest file for the agent", e);
+ }
+
+ sun.tools.jar.Main jarTool = new sun.tools.jar.Main(System.out, System.err, "jar");
+ if (!jarTool.run(new String[] { "-cmf", "MANIFEST.MF", "redefineagent.jar", "RedefineLeak.class" })) {
+ throw new RuntimeException("Could not write the agent jar file");
+ }
+ }
+ public static void main(String argv[]) throws Exception {
+ if (argv.length == 1 && argv[0].equals("buildagent")) {
+ buildAgent();
+ return;
+ }
+ if (argv.length == 1 && argv[0].equals("runtest")) {
+ // run outside of jtreg to not OOM on jtreg classes that are loaded after metaspace is full
+ String[] javaArgs1 = { "-XX:MetaspaceSize=12m", "-XX:MaxMetaspaceSize=12m",
+ "-javaagent:redefineagent.jar", "RedefineLeak"};
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(javaArgs1);
+
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+ output.shouldContain("transformCount:10000");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefinePreviousVersions.java Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8165246 8010319
+ * @summary Test has_previous_versions flag and processing during class unloading.
+ * @requires vm.opt.final.ClassUnloading
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * @modules java.compiler
+ * java.instrument
+ * jdk.jartool/sun.tools.jar
+ * @run main RedefineClassHelper
+ * @run main/othervm RedefinePreviousVersions test
+ */
+
+import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.process.OutputAnalyzer;
+
+// package access top-level classes to avoid problem with RedefineClassHelper
+// and nested types.
+
+class RedefinePreviousVersions_B { }
+
+class RedefinePreviousVersions_Running {
+ public static volatile boolean stop = false;
+ public static volatile boolean running = false;
+ static void localSleep() {
+ try {
+ Thread.sleep(10); // sleep for 10 ms
+ } catch(InterruptedException ie) {
+ }
+ }
+
+ public static void infinite() {
+ running = true;
+ while (!stop) { localSleep(); }
+ }
+}
+
+
+
+public class RedefinePreviousVersions {
+
+ public static String newB =
+ "class RedefinePreviousVersions_B {" +
+ "}";
+
+ public static String newRunning =
+ "class RedefinePreviousVersions_Running {" +
+ " public static volatile boolean stop = true;" +
+ " public static volatile boolean running = true;" +
+ " static void localSleep() { }" +
+ " public static void infinite() { }" +
+ "}";
+
+ public static void main(String[] args) throws Exception {
+
+ if (args.length > 0) {
+
+ // java -javaagent:redefineagent.jar -Xlog:stuff RedefinePreviousVersions
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( "-javaagent:redefineagent.jar",
+ "-Xlog:redefine+class+iklass+add=trace,redefine+class+iklass+purge=trace",
+ "RedefinePreviousVersions");
+ new OutputAnalyzer(pb.start())
+ .shouldContain("Class unloading: has_previous_versions = false")
+ .shouldContain("Class unloading: has_previous_versions = true")
+ .shouldHaveExitValue(0);
+ return;
+ }
+
+ // Redefine a class and create some garbage
+ // Since there are no methods running, the previous version is never added to the
+ // previous_version_list and the flag _has_previous_versions should stay false
+ RedefineClassHelper.redefineClass(RedefinePreviousVersions_B.class, newB);
+
+ for (int i = 0; i < 10 ; i++) {
+ String s = new String("some garbage");
+ System.gc();
+ }
+
+ // Start a class that has a method running
+ new Thread() {
+ public void run() {
+ RedefinePreviousVersions_Running.infinite();
+ }
+ }.start();
+
+ while (!RedefinePreviousVersions_Running.running) {
+ Thread.sleep(10); // sleep for 10 ms
+ }
+
+ // Since a method of newRunning is running, this class should be added to the previous_version_list
+ // of Running, and _has_previous_versions should return true at class unloading.
+ RedefineClassHelper.redefineClass(RedefinePreviousVersions_Running.class, newRunning);
+
+ for (int i = 0; i < 10 ; i++) {
+ String s = new String("some garbage");
+ System.gc();
+ }
+
+ // purge should clean everything up, except Xcomp it might not.
+ RedefinePreviousVersions_Running.stop = true;
+
+ for (int i = 0; i < 10 ; i++) {
+ String s = new String("some garbage");
+ System.gc();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineRunningMethods.java Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8055008 8197901 8010319
+ * @summary Redefine EMCP and non-EMCP methods that are running in an infinite loop
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * @modules java.compiler
+ * java.instrument
+ * jdk.jartool/sun.tools.jar
+ * @run main RedefineClassHelper
+ * @run main/othervm/timeout=180 -javaagent:redefineagent.jar -Xlog:redefine+class+iklass+add=trace,redefine+class+iklass+purge=trace,class+loader+data=debug,safepoint+cleanup,gc+phases=debug:rt.log RedefineRunningMethods
+ */
+
+
+// package access top-level class to avoid problem with RedefineClassHelper
+// and nested types.
+class RedefineRunningMethods_B {
+ static int count1 = 0;
+ static int count2 = 0;
+ public static volatile boolean stop = false;
+ static void localSleep() {
+ try{
+ Thread.currentThread().sleep(10);//sleep for 10 ms
+ } catch(InterruptedException ie) {
+ }
+ }
+
+ public static void infinite() {
+ while (!stop) { count1++; localSleep(); }
+ }
+ public static void infinite_emcp() {
+ while (!stop) { count2++; localSleep(); }
+ }
+}
+
+public class RedefineRunningMethods {
+
+ public static String newB =
+ "class RedefineRunningMethods_B {" +
+ " static int count1 = 0;" +
+ " static int count2 = 0;" +
+ " public static volatile boolean stop = false;" +
+ " static void localSleep() { " +
+ " try{ " +
+ " Thread.currentThread().sleep(10);" +
+ " } catch(InterruptedException ie) { " +
+ " } " +
+ " } " +
+ " public static void infinite() { " +
+ " System.out.println(\"infinite called\");" +
+ " }" +
+ " public static void infinite_emcp() { " +
+ " while (!stop) { count2++; localSleep(); }" +
+ " }" +
+ "}";
+
+ public static String evenNewerB =
+ "class RedefineRunningMethods_B {" +
+ " static int count1 = 0;" +
+ " static int count2 = 0;" +
+ " public static volatile boolean stop = false;" +
+ " static void localSleep() { " +
+ " try{ " +
+ " Thread.currentThread().sleep(1);" +
+ " } catch(InterruptedException ie) { " +
+ " } " +
+ " } " +
+ " public static void infinite() { }" +
+ " public static void infinite_emcp() { " +
+ " System.out.println(\"infinite_emcp now obsolete called\");" +
+ " }" +
+ "}";
+
+
+ public static void main(String[] args) throws Exception {
+
+ new Thread() {
+ public void run() {
+ RedefineRunningMethods_B.infinite();
+ }
+ }.start();
+
+ new Thread() {
+ public void run() {
+ RedefineRunningMethods_B.infinite_emcp();
+ }
+ }.start();
+
+ RedefineClassHelper.redefineClass(RedefineRunningMethods_B.class, newB);
+
+ System.gc();
+
+ RedefineRunningMethods_B.infinite();
+
+ // Start a thread with the second version of infinite_emcp running
+ new Thread() {
+ public void run() {
+ RedefineRunningMethods_B.infinite_emcp();
+ }
+ }.start();
+
+ for (int i = 0; i < 20 ; i++) {
+ String s = new String("some garbage");
+ System.gc();
+ }
+
+ RedefineClassHelper.redefineClass(RedefineRunningMethods_B.class, evenNewerB);
+ System.gc();
+
+ for (int i = 0; i < 20 ; i++) {
+ RedefineRunningMethods_B.infinite();
+ String s = new String("some garbage");
+ System.gc();
+ }
+
+ RedefineRunningMethods_B.infinite_emcp();
+
+ // purge should clean everything up.
+ RedefineRunningMethods_B.stop = true;
+
+ for (int i = 0; i < 20 ; i++) {
+ RedefineRunningMethods_B.infinite();
+ String s = new String("some garbage");
+ System.gc();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineRunningMethodsWithBacktrace.java Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8087315 8010319
+ * @summary Get old method's stack trace elements after GC
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * @modules java.compiler
+ * java.instrument
+ * jdk.jartool/sun.tools.jar
+ * @run main RedefineClassHelper
+ * @run main/othervm -javaagent:redefineagent.jar RedefineRunningMethodsWithBacktrace
+ */
+
+import static jdk.test.lib.Asserts.*;
+
+// package access top-level class to avoid problem with RedefineClassHelper
+// and nested types.
+
+class RedefineRunningMethodsWithBacktrace_B {
+ static int count1 = 0;
+ static int count2 = 0;
+ public static volatile boolean stop = false;
+ static void localSleep() {
+ try {
+ Thread.sleep(10);//sleep for 10 ms
+ } catch(InterruptedException ie) {
+ }
+ }
+
+ public static void infinite() {
+ while (!stop) { count1++; localSleep(); }
+ }
+ public static void throwable() {
+ // add some stuff to the original constant pool
+ String s1 = new String ("string1");
+ String s2 = new String ("string2");
+ String s3 = new String ("string3");
+ String s4 = new String ("string4");
+ String s5 = new String ("string5");
+ String s6 = new String ("string6");
+ String s7 = new String ("string7");
+ String s8 = new String ("string8");
+ String s9 = new String ("string9");
+ String s10 = new String ("string10");
+ String s11 = new String ("string11");
+ String s12 = new String ("string12");
+ String s13 = new String ("string13");
+ String s14 = new String ("string14");
+ String s15 = new String ("string15");
+ String s16 = new String ("string16");
+ String s17 = new String ("string17");
+ String s18 = new String ("string18");
+ String s19 = new String ("string19");
+ throw new RuntimeException("throwable called");
+ }
+}
+
+public class RedefineRunningMethodsWithBacktrace {
+
+ public static String newB =
+ "class RedefineRunningMethodsWithBacktrace_B {" +
+ " static int count1 = 0;" +
+ " static int count2 = 0;" +
+ " public static volatile boolean stop = false;" +
+ " static void localSleep() { " +
+ " try{ " +
+ " Thread.sleep(10);" +
+ " } catch(InterruptedException ie) { " +
+ " } " +
+ " } " +
+ " public static void infinite() { " +
+ " System.out.println(\"infinite called\");" +
+ " }" +
+ " public static void throwable() { " +
+ " throw new RuntimeException(\"throwable called\");" +
+ " }" +
+ "}";
+
+ public static String evenNewerB =
+ "class RedefineRunningMethodsWithBacktrace_B {" +
+ " static int count1 = 0;" +
+ " static int count2 = 0;" +
+ " public static volatile boolean stop = false;" +
+ " static void localSleep() { " +
+ " try{ " +
+ " Thread.sleep(1);" +
+ " } catch(InterruptedException ie) { " +
+ " } " +
+ " } " +
+ " public static void infinite() { }" +
+ " public static void throwable() { " +
+ " throw new RuntimeException(\"throwable called\");" +
+ " }" +
+ "}";
+
+ private static void touchRedefinedMethodInBacktrace(Throwable throwable) {
+ System.out.println("touchRedefinedMethodInBacktrace: ");
+ throwable.printStackTrace(); // this actually crashes with the bug in
+ // java_lang_StackTraceElement::create()
+
+ // Make sure that we can convert the backtrace, which is referring to
+ // the redefined method, to a StrackTraceElement[] without crashing.
+ StackTraceElement[] stackTrace = throwable.getStackTrace();
+ for (int i = 0; i < stackTrace.length; i++) {
+ StackTraceElement frame = stackTrace[i];
+ assertNotNull(frame.getClassName(),
+ "\nTest failed: trace[" + i + "].getClassName() returned null");
+ assertNotNull(frame.getMethodName(),
+ "\nTest failed: trace[" + i + "].getMethodName() returned null");
+ }
+ }
+
+ private static Throwable getThrowableInB() {
+ Throwable t = null;
+ try {
+ RedefineRunningMethodsWithBacktrace_B.throwable();
+ } catch (Exception e) {
+ t = e;
+ // Don't print here because Throwable will cache the constructed stacktrace
+ // e.printStackTrace();
+ }
+ return t;
+ }
+
+
+ public static void main(String[] args) throws Exception {
+
+ new Thread() {
+ public void run() {
+ RedefineRunningMethodsWithBacktrace_B.infinite();
+ }
+ }.start();
+
+ Throwable t1 = getThrowableInB();
+
+ RedefineClassHelper.redefineClass(RedefineRunningMethodsWithBacktrace_B.class, newB);
+
+ System.gc();
+
+ Throwable t2 = getThrowableInB();
+
+ RedefineRunningMethodsWithBacktrace_B.infinite();
+
+ for (int i = 0; i < 20 ; i++) {
+ String s = new String("some garbage");
+ System.gc();
+ }
+
+ RedefineClassHelper.redefineClass(RedefineRunningMethodsWithBacktrace_B.class, evenNewerB);
+ System.gc();
+
+ Throwable t3 = getThrowableInB();
+
+ for (int i = 0; i < 20 ; i++) {
+ RedefineRunningMethodsWithBacktrace_B.infinite();
+ String s = new String("some garbage");
+ System.gc();
+ }
+
+ touchRedefinedMethodInBacktrace(t1);
+ touchRedefinedMethodInBacktrace(t2);
+ touchRedefinedMethodInBacktrace(t3);
+
+ // purge should clean everything up.
+ RedefineRunningMethodsWithBacktrace_B.stop = true;
+
+ for (int i = 0; i < 20 ; i++) {
+ RedefineRunningMethodsWithBacktrace_B.infinite();
+ String s = new String("some garbage");
+ System.gc();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineRunningMethodsWithResolutionErrors.java Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8076110
+ * @summary Redefine running methods that have cached resolution errors
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ * java.instrument
+ * jdk.jartool/sun.tools.jar
+ * @run main RedefineClassHelper
+ * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class+iklass+add=trace,redefine+class+iklass+purge=trace RedefineRunningMethodsWithResolutionErrors
+ */
+
+import jdk.internal.org.objectweb.asm.ClassWriter;
+import jdk.internal.org.objectweb.asm.Label;
+import jdk.internal.org.objectweb.asm.MethodVisitor;
+import jdk.internal.org.objectweb.asm.Opcodes;
+
+import java.lang.reflect.InvocationTargetException;
+
+public class RedefineRunningMethodsWithResolutionErrors extends ClassLoader implements Opcodes {
+
+ @Override
+ protected Class<?> findClass(String name) throws ClassNotFoundException {
+ if (name.equals("C")) {
+ byte[] b = loadC(false);
+ return defineClass(name, b, 0, b.length);
+ } else {
+ return super.findClass(name);
+ }
+ }
+
+ private static byte[] loadC(boolean redefine) {
+ ClassWriter cw = new ClassWriter(0);
+
+ cw.visit(52, ACC_SUPER | ACC_PUBLIC, "C", null, "java/lang/Object", null);
+ {
+ MethodVisitor mv;
+
+ mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "m", "()V", null, null);
+ mv.visitCode();
+
+ // First time we run we will:
+ // 1) Cache resolution errors
+ // 2) Redefine the class / method
+ // 3) Try to read the resolution errors that were cached
+ //
+ // The redefined method will never run, throw error to be sure
+ if (redefine) {
+ createThrowRuntimeExceptionCode(mv, "The redefined method was called");
+ } else {
+ createMethodBody(mv);
+ }
+ mv.visitMaxs(3, 0);
+ mv.visitEnd();
+ }
+ cw.visitEnd();
+ return cw.toByteArray();
+ }
+
+ private static void createMethodBody(MethodVisitor mv) {
+ Label classExists = new Label();
+
+ // Cache resolution errors
+ createLoadNonExistentClassCode(mv, classExists);
+
+ // Redefine our own class and method
+ mv.visitMethodInsn(INVOKESTATIC, "RedefineRunningMethodsWithResolutionErrors", "redefine", "()V");
+
+ // Provoke the same error again to make sure the resolution error cache works
+ createLoadNonExistentClassCode(mv, classExists);
+
+ // Test passed
+ mv.visitInsn(RETURN);
+
+ mv.visitFrame(F_SAME, 0, new Object[0], 0, new Object[0]);
+ mv.visitLabel(classExists);
+
+ createThrowRuntimeExceptionCode(mv, "Loaded class that shouldn't exist (\"NonExistentClass\")");
+ }
+
+ private static void createLoadNonExistentClassCode(MethodVisitor mv, Label classExists) {
+ Label tryLoadBegin = new Label();
+ Label tryLoadEnd = new Label();
+ Label catchLoadBlock = new Label();
+ mv.visitTryCatchBlock(tryLoadBegin, tryLoadEnd, catchLoadBlock, "java/lang/NoClassDefFoundError");
+
+ // Try to load a class that does not exist to provoke resolution errors
+ mv.visitLabel(tryLoadBegin);
+ mv.visitMethodInsn(INVOKESTATIC, "NonExistentClass", "nonExistentMethod", "()V");
+ mv.visitLabel(tryLoadEnd);
+
+ // No NoClassDefFoundError means NonExistentClass existed, which shouldn't happen
+ mv.visitJumpInsn(GOTO, classExists);
+
+ mv.visitFrame(F_SAME1, 0, new Object[0], 1, new Object[] { "java/lang/NoClassDefFoundError" });
+ mv.visitLabel(catchLoadBlock);
+
+ // Ignore the expected NoClassDefFoundError
+ mv.visitInsn(POP);
+ }
+
+ private static void createThrowRuntimeExceptionCode(MethodVisitor mv, String msg) {
+ mv.visitTypeInsn(NEW, "java/lang/RuntimeException");
+ mv.visitInsn(DUP);
+ mv.visitLdcInsn(msg);
+ mv.visitMethodInsn(INVOKESPECIAL, "java/lang/RuntimeException", "<init>", "(Ljava/lang/String;)V");
+ mv.visitInsn(ATHROW);
+ }
+
+ private static Class<?> c;
+
+ public static void redefine() throws Exception {
+ RedefineClassHelper.redefineClass(c, loadC(true));
+ }
+
+ public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
+ c = Class.forName("C", true, new RedefineRunningMethodsWithResolutionErrors());
+ c.getMethod("m").invoke(null);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineSubtractLambdaExpression.java Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8193524
+ * @summary Redefine a class' public static method that contains a lambda expression
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * @modules java.compiler
+ * java.instrument
+ * jdk.jartool/sun.tools.jar
+ * @run main RedefineClassHelper
+ * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class*=trace RedefineSubtractLambdaExpression
+ */
+
+interface MathOperation {
+ public int operation(int a, int b);
+}
+
+class B {
+ public static int operate(int a, int b, MathOperation mathOperation) {
+ return mathOperation.operation(a, b);
+ }
+ static int test_math(String p) {
+ System.out.println(p + " from class B's test_math method");
+ MathOperation subtraction = (int a, int b) -> a - b;
+ MathOperation addition = (int a, int b) -> a + b;
+ return operate(10, 5, addition);
+ }
+}
+
+public class RedefineSubtractLambdaExpression {
+
+ public static String newB =
+ "class B {" +
+ " public static int operate(int a, int b, MathOperation mathOperation) {" +
+ " return mathOperation.operation(a, b);" +
+ " }" +
+ " static int test_math(String p) {" +
+ " MathOperation subtraction = (int a, int b) -> a - b;" +
+ " return operate(10, 5, subtraction);" +
+ " }" +
+ "}";
+
+ public static void main(String[] args) throws Exception {
+ int res = B.test_math("Hello");
+ System.out.println("Result = " + res);
+ if (res != 15) {
+ throw new Error("test_math returned " + res + " expected " + 15);
+ }
+ RedefineClassHelper.redefineClass(B.class, newB);
+
+ res = B.test_math("Hello");
+ if (res != 5)
+ throw new Error("test_math returned " + res + " expected " + 5);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RetransformClassesZeroLength.java Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8198393
+ * @summary Instrumentation.retransformClasses(new Class[0]) should be NOP
+ * @library /test/lib
+ * @modules java.instrument
+ * @compile RetransformClassesZeroLength.java
+ * @run main RetransformClassesZeroLength
+ */
+
+import java.lang.instrument.ClassFileTransformer;
+import java.lang.instrument.IllegalClassFormatException;
+import java.lang.instrument.Instrumentation;
+import java.lang.instrument.UnmodifiableClassException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.security.ProtectionDomain;
+
+import jdk.test.lib.process.ProcessTools;
+
+
+public class RetransformClassesZeroLength {
+
+ private static String manifest =
+ "Premain-Class: " + RetransformClassesZeroLength.Agent.class.getName() + "\n"
+ + "Can-Retransform-Classes: true\n";
+
+ private static String CP = System.getProperty("test.classes");
+
+ public static void main(String args[]) throws Throwable {
+ String agentJar = buildAgent();
+ ProcessTools.executeProcess(
+ ProcessTools.createJavaProcessBuilder(
+ "-javaagent:" + agentJar,
+ "-version")
+ ).shouldHaveExitValue(0);
+ }
+
+ private static String buildAgent() throws Exception {
+ Path jar = Files.createTempFile(Paths.get("."), null, ".jar");
+ String jarPath = jar.toAbsolutePath().toString();
+ ClassFileInstaller.writeJar(jarPath,
+ ClassFileInstaller.Manifest.fromString(manifest),
+ RetransformClassesZeroLength.class.getName());
+ return jarPath;
+ }
+
+
+ public static class Agent implements ClassFileTransformer {
+ public static void premain(String args, Instrumentation inst) {
+ inst.addTransformer(new NoOpTransformer());
+ try {
+ inst.retransformClasses(new Class[0]);
+ } catch (UnmodifiableClassException ex) {
+ throw new AssertionError(ex);
+ }
+ }
+ }
+
+ private static class NoOpTransformer implements ClassFileTransformer {
+ @Override
+ public byte[] transform(ClassLoader loader,
+ String className,
+ Class<?> classBeingRedefined,
+ ProtectionDomain protectionDomain,
+ byte[] classfileBuffer
+ ) throws IllegalClassFormatException {
+ return null; // no transform
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/TestLambdaFormRetransformation.java Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8008678
+ * @summary JSR 292: constant pool reconstitution must support pseudo strings
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * java.instrument
+ * java.management
+ * jdk.jartool/sun.tools.jar
+ * @compile -XDignore.symbol.file TestLambdaFormRetransformation.java
+ * @run main TestLambdaFormRetransformation
+ */
+
+import java.io.IOException;
+import java.lang.instrument.ClassFileTransformer;
+import java.lang.instrument.IllegalClassFormatException;
+import java.lang.instrument.Instrumentation;
+import java.lang.instrument.UnmodifiableClassException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.security.ProtectionDomain;
+import java.util.Arrays;
+
+import jdk.test.lib.process.ExitCode;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+
+public class TestLambdaFormRetransformation {
+ private static String MANIFEST = String.format("Manifest-Version: 1.0\n" +
+ "Premain-Class: %s\n" +
+ "Can-Retransform-Classes: true\n",
+ Agent.class.getName());
+
+ private static String CP = System.getProperty("test.classes");
+
+ public static void main(String args[]) throws Throwable {
+ Path agent = TestLambdaFormRetransformation.buildAgent();
+ OutputAnalyzer oa = ProcessTools.executeTestJvm("-javaagent:" +
+ agent.toAbsolutePath().toString(), "-version");
+ oa.shouldHaveExitValue(ExitCode.OK.value);
+ }
+
+ private static Path buildAgent() throws IOException {
+ Path manifest = TestLambdaFormRetransformation.createManifest();
+ Path jar = Files.createTempFile(Paths.get("."), null, ".jar");
+
+ String[] args = new String[] {
+ "-cfm",
+ jar.toAbsolutePath().toString(),
+ manifest.toAbsolutePath().toString(),
+ "-C",
+ TestLambdaFormRetransformation.CP,
+ Agent.class.getName() + ".class"
+ };
+
+ sun.tools.jar.Main jarTool = new sun.tools.jar.Main(System.out, System.err, "jar");
+
+ if (!jarTool.run(args)) {
+ throw new Error("jar failed: args=" + Arrays.toString(args));
+ }
+ return jar;
+ }
+
+ private static Path createManifest() throws IOException {
+ Path manifest = Files.createTempFile(Paths.get("."), null, ".mf");
+ byte[] manifestBytes = TestLambdaFormRetransformation.MANIFEST.getBytes();
+ Files.write(manifest, manifestBytes);
+ return manifest;
+ }
+}
+
+class Agent implements ClassFileTransformer {
+ private static Runnable lambda = () -> {
+ System.out.println("I'll crash you!");
+ };
+
+ public static void premain(String args, Instrumentation instrumentation) {
+ if (!instrumentation.isRetransformClassesSupported()) {
+ System.out.println("Class retransformation is not supported.");
+ return;
+ }
+ System.out.println("Calling lambda to ensure that lambda forms were created");
+
+ Agent.lambda.run();
+
+ System.out.println("Registering class file transformer");
+
+ instrumentation.addTransformer(new Agent());
+
+ for (Class c : instrumentation.getAllLoadedClasses()) {
+ if (c.getName().contains("LambdaForm") &&
+ instrumentation.isModifiableClass(c)) {
+ System.out.format("We've found a modifiable lambda form: %s%n", c.getName());
+ try {
+ instrumentation.retransformClasses(c);
+ } catch (UnmodifiableClassException e) {
+ throw new AssertionError("Modification of modifiable class " +
+ "caused UnmodifiableClassException", e);
+ }
+ }
+ }
+ }
+
+ public static void main(String args[]) {
+ }
+
+ @Override
+ public byte[] transform(ClassLoader loader,
+ String className,
+ Class<?> classBeingRedefined,
+ ProtectionDomain protectionDomain,
+ byte[] classfileBuffer
+ ) throws IllegalClassFormatException {
+ System.out.println("Transforming " + className);
+ return classfileBuffer.clone();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/TestMultipleClasses.java Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8139551
+ * @summary Scalability problem with redefinition - multiple code cache walks
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * @modules java.compiler
+ * java.instrument
+ * jdk.jartool/sun.tools.jar
+ * @run main RedefineClassHelper
+ * @run main/othervm/timeout=180 -javaagent:redefineagent.jar -XX:CompileThreshold=100 -Xlog:redefine+class+nmethod=debug TestMultipleClasses
+ */
+
+import java.lang.instrument.*;
+import java.lang.reflect.*;
+import jdk.test.lib.compiler.InMemoryJavaCompiler;
+
+public class TestMultipleClasses extends ClassLoader {
+
+ public static String B(int count) {
+ return new String("public class B" + count + " {" +
+ " public static void compiledMethod() { " +
+ " try{" +
+ " Thread.sleep(1); " +
+ " } catch(InterruptedException ie) {" +
+ " }" +
+ " }" +
+ "}");
+ }
+
+ static String newB(int count) {
+ return new String("public class B" + count + " {" +
+ " public static void compiledMethod() { " +
+ " System.out.println(\"compiledMethod called " + count + "\");" +
+ " }" +
+ "}");
+ }
+
+ static int index = 0;
+
+ @Override
+ protected Class<?> findClass(String name) throws ClassNotFoundException {
+ if (name.equals("B" + index)) {
+ byte[] b = InMemoryJavaCompiler.compile(name, B(index));
+ return defineClass(name, b, 0, b.length);
+ } else {
+ return super.findClass(name);
+ }
+ }
+
+ static void runCompiledMethodMethods(Class c, int count) throws Exception {
+ // Run for a while so they compile.
+ Object o = c.newInstance();
+ Method m = c.getMethod("compiledMethod");
+ for (int i = 0; i < count; i++) {
+ m.invoke(o);
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+
+ final int numberOfClasses = 20;
+ Class[] classes = new Class[numberOfClasses];
+ byte[][] newClass = new byte[numberOfClasses][];
+ ClassDefinition[] defs = new ClassDefinition[numberOfClasses];
+
+ TestMultipleClasses loader = new TestMultipleClasses();
+
+ // Load and start all the classes.
+ for (index = 0; index < numberOfClasses; index++) {
+ String name = new String("B" + index);
+ Class c = loader.findClass(name);
+
+ runCompiledMethodMethods(c, 500);
+ // Make class definition for redefinition
+ classes[index] = c;
+ newClass[index] = InMemoryJavaCompiler.compile(c.getName(), newB(index));
+ defs[index] = new ClassDefinition(c, newClass[index]);
+ }
+
+ long startTime = System.currentTimeMillis();
+
+ // Redefine all classes.
+ RedefineClassHelper.instrumentation.redefineClasses(defs);
+
+ long endTime = System.currentTimeMillis();
+
+ System.out.println("Redefinition took " + (endTime - startTime) + " milliseconds");
+
+ System.gc();
+
+ // Run all new classes.
+ for (index = 0; index < numberOfClasses; index++) {
+ runCompiledMethodMethods(classes[index], 1);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/TestRedefineObject.java Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+import java.io.PrintWriter;
+
+import jdk.test.lib.JDKToolFinder;
+import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.process.OutputAnalyzer;
+
+/*
+ * Test to redefine java/lang/Object and verify that it doesn't crash on vtable
+ * call on basic array type.
+ * Test to redefine java/lang/ClassLoader and java/lang/reflect/Method to make
+ * sure cached versions used afterward are the current version.
+ *
+ * @test
+ * @bug 8005056
+ * @bug 8009728
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * java.instrument
+ * java.management
+ * @build Agent
+ * @run driver ClassFileInstaller Agent
+ * @run main TestRedefineObject
+ * @run main/othervm -javaagent:agent.jar -Xlog:redefine+class+load=debug,redefine+class+timer=info Agent
+ */
+public class TestRedefineObject {
+ public static void main(String[] args) throws Exception {
+
+ PrintWriter pw = new PrintWriter("MANIFEST.MF");
+ pw.println("Premain-Class: Agent");
+ pw.println("Can-Retransform-Classes: true");
+ pw.close();
+
+ ProcessBuilder pb = new ProcessBuilder();
+ pb.command(new String[] { JDKToolFinder.getJDKTool("jar"), "cmf", "MANIFEST.MF", "agent.jar", "Agent.class"});
+ pb.start().waitFor();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/TestRedefineWithUnresolvedClass.java Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Redefine a class with an UnresolvedClass reference in the constant pool.
+ * @bug 8035150
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * java.compiler
+ * java.instrument
+ * java.management
+ * jdk.jartool/sun.tools.jar
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
+ * @build UnresolvedClassAgent
+ * @run main TestRedefineWithUnresolvedClass
+ */
+
+import java.io.File;
+import java.util.Arrays;
+
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+
+public class TestRedefineWithUnresolvedClass {
+
+ final static String slash = File.separator;
+ final static String testClasses = System.getProperty("test.classes") + slash;
+
+ public static void main(String... args) throws Throwable {
+ // delete this class to cause a NoClassDefFoundError
+ File unresolved = new File(testClasses, "MyUnresolvedClass.class");
+ if (unresolved.exists() && !unresolved.delete()) {
+ throw new Exception("Could not delete: " + unresolved);
+ }
+
+ // build the javaagent
+ buildJar("UnresolvedClassAgent");
+
+ // launch a VM with the javaagent
+ launchTest();
+ }
+
+ private static void buildJar(String jarName) throws Throwable {
+ String testSrc = System.getProperty("test.src", "?") + slash;
+
+ String jarPath = String.format("%s%s.jar", testClasses, jarName);
+ String manifestPath = String.format("%s%s.mf", testSrc, jarName);
+ String className = String.format("%s.class", jarName);
+
+ String[] args = new String[] {"-cfm", jarPath, manifestPath, "-C", testClasses, className};
+
+ System.out.println("Running jar " + Arrays.toString(args));
+ sun.tools.jar.Main jarTool = new sun.tools.jar.Main(System.out, System.err, "jar");
+ if (!jarTool.run(args)) {
+ throw new Exception("jar failed: args=" + Arrays.toString(args));
+ }
+ }
+
+ private static void launchTest() throws Throwable {
+ String[] args = {
+ "-javaagent:" + testClasses + "UnresolvedClassAgent.jar",
+ "-Dtest.classes=" + testClasses,
+ "UnresolvedClassAgent" };
+ OutputAnalyzer output = ProcessTools.executeTestJvm(args);
+ output.shouldHaveExitValue(0);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/UnresolvedClassAgent.java Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.DataInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.lang.instrument.ClassDefinition;
+import java.lang.instrument.Instrumentation;
+
+/*
+ * This class is present during compilation, but will be deleted before execution.
+ */
+class MyUnresolvedClass {
+ static void bar() {
+ }
+}
+
+class MyRedefinedClass {
+ static void foo() {
+ MyUnresolvedClass.bar();
+ }
+}
+
+public class UnresolvedClassAgent {
+ public static void main(String... args) {
+ }
+
+ public static void premain(String args, Instrumentation inst) throws Exception {
+ try {
+ MyRedefinedClass.foo();
+ } catch(NoClassDefFoundError err) {
+ System.out.println("NoClassDefFoundError (expected)");
+ }
+
+ File f = new File(System.getProperty("test.classes"), "MyRedefinedClass.class");
+ byte[] buf = new byte[(int)f.length()];
+ try (DataInputStream dis = new DataInputStream(new FileInputStream(f))) {
+ dis.readFully(buf);
+ }
+ ClassDefinition cd = new ClassDefinition(MyRedefinedClass.class, buf);
+ inst.redefineClasses(new ClassDefinition[] {cd});
+
+ try {
+ MyRedefinedClass.foo();
+ } catch(NoClassDefFoundError err) {
+ System.out.println("NoClassDefFoundError (expected again)");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/UnresolvedClassAgent.mf Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Premain-Class: UnresolvedClassAgent
+Can-Redefine-Classes: true
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/WalkThroughInvoke.java Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+import java.lang.reflect.*;
+
+public class WalkThroughInvoke {
+ public void stackWalk() {
+ try {
+ Class b = Object.class;
+ SecurityManager sm = new SecurityManager();
+ // Walks the stack with Method.invoke in the stack (which is the
+ // purpose of the test) before it gets an AccessControlException.
+ sm.checkPermission(new RuntimePermission("accessDeclaredMembers"));
+ } catch (java.security.AccessControlException e) {
+ // Ignoring an 'AccessControlException' exception since
+ // it is expected as part of this test.
+ }
+ }
+};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/libRedefineDeleteJmethod.c Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <jni.h>
+
+jmethodID mid;
+jclass cls;
+static int count = 0;
+
+JNIEXPORT jint JNICALL
+Java_RedefineDeleteJmethod_jniCallDeleteMe(JNIEnv* env, jobject obj) {
+
+ if (count == 0) {
+ count++;
+ cls = (*env)->FindClass(env, "B");
+ if (NULL == cls) {
+ (*env)->FatalError(env, "could not find class");
+ }
+
+ mid = (*env)->GetStaticMethodID(env, cls, "deleteMe", "()I");
+ if (NULL == mid) {
+ (*env)->FatalError(env, "could not find method");
+ }
+ }
+
+ return (*env)->CallStaticIntMethod(env, cls, mid);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/libRedefineDoubleDelete.c Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "jvmti.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef JNI_ENV_ARG
+
+#ifdef __cplusplus
+#define JNI_ENV_ARG(x, y) y
+#define JNI_ENV_PTR(x) x
+#else
+#define JNI_ENV_ARG(x,y) x, y
+#define JNI_ENV_PTR(x) (*x)
+#endif
+
+#endif
+
+#define TranslateError(err) "JVMTI error"
+
+static jvmtiEnv *jvmti = NULL;
+
+static jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved);
+
+JNIEXPORT
+jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
+ return Agent_Initialize(jvm, options, reserved);
+}
+
+JNIEXPORT
+jint JNICALL Agent_OnAttach(JavaVM *jvm, char *options, void *reserved) {
+ return Agent_Initialize(jvm, options, reserved);
+}
+
+JNIEXPORT
+jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
+ return JNI_VERSION_9;
+}
+
+
+static jint newClassDataLen = 0;
+static unsigned char* newClassData = NULL;
+
+static jint
+getBytecodes(jvmtiEnv *jvmti_env,
+ jint class_data_len, const unsigned char* class_data) {
+ int i;
+ jint res;
+
+ newClassDataLen = class_data_len;
+ res = (*jvmti_env)->Allocate(jvmti_env, newClassDataLen, &newClassData);
+ if (res != JNI_OK) {
+ printf(" Unable to allocate bytes\n");
+ return JNI_ERR;
+ }
+ for (i = 0; i < newClassDataLen; i++) {
+ newClassData[i] = class_data[i];
+ // Rewrite oo in class to aa
+ if (i > 0 && class_data[i] == 'o' && class_data[i-1] == 'o') {
+ newClassData[i] = newClassData[i-1] = 'a';
+ }
+ }
+ printf(" ... copied bytecode: %d bytes\n", (int)newClassDataLen);
+ return JNI_OK;
+}
+
+
+static void JNICALL
+Callback_ClassFileLoadHook(jvmtiEnv *jvmti_env, JNIEnv *env,
+ jclass class_being_redefined,
+ jobject loader, const char* name, jobject protection_domain,
+ jint class_data_len, const unsigned char* class_data,
+ jint *new_class_data_len, unsigned char** new_class_data) {
+ if (name != NULL && strcmp(name, "RedefineDoubleDelete$B") == 0) {
+ if (newClassData == NULL) {
+ jint res = getBytecodes(jvmti_env, class_data_len, class_data);
+ if (res == JNI_ERR) {
+ printf(">>> ClassFileLoadHook event: class name %s FAILED\n", name);
+ return;
+ }
+ // Only change for first CFLH event.
+ *new_class_data_len = newClassDataLen;
+ *new_class_data = newClassData;
+ }
+ printf(">>> ClassFileLoadHook event: class name %s\n", name);
+ }
+}
+
+static
+jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
+ jint res, size;
+ jvmtiCapabilities caps;
+ jvmtiEventCallbacks callbacks;
+ jvmtiError err;
+
+ res = JNI_ENV_PTR(jvm)->GetEnv(JNI_ENV_ARG(jvm, (void **) &jvmti),
+ JVMTI_VERSION_9);
+ if (res != JNI_OK || jvmti == NULL) {
+ printf(" Error: wrong result of a valid call to GetEnv!\n");
+ return JNI_ERR;
+ }
+
+ printf("Enabling following capabilities: can_generate_all_class_hook_events, "
+ "can_retransform_classes, can_redefine_classes");
+ memset(&caps, 0, sizeof(caps));
+ caps.can_generate_all_class_hook_events = 1;
+ caps.can_retransform_classes = 1;
+ caps.can_redefine_classes = 1;
+ printf("\n");
+
+ err = (*jvmti)->AddCapabilities(jvmti, &caps);
+ if (err != JVMTI_ERROR_NONE) {
+ printf(" Error in AddCapabilites: %s (%d)\n", TranslateError(err), err);
+ return JNI_ERR;
+ }
+
+ size = (jint)sizeof(callbacks);
+
+ memset(&callbacks, 0, sizeof(callbacks));
+ callbacks.ClassFileLoadHook = Callback_ClassFileLoadHook;
+
+ err = (*jvmti)->SetEventCallbacks(jvmti, &callbacks, size);
+ if (err != JVMTI_ERROR_NONE) {
+ printf(" Error in SetEventCallbacks: %s (%d)\n", TranslateError(err), err);
+ return JNI_ERR;
+ }
+
+ err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, NULL);
+ if (err != JVMTI_ERROR_NONE) {
+ printf(" Error in SetEventNotificationMode: %s (%d)\n", TranslateError(err), err);
+ return JNI_ERR;
+ }
+
+ return JNI_OK;
+}
+
+#ifdef __cplusplus
+}
+#endif
--- a/test/hotspot/jtreg/serviceability/jvmti/RetransformClassesZeroLength.java Thu Mar 21 08:41:10 2019 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,95 +0,0 @@
-/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/**
- * @test
- * @bug 8198393
- * @summary Instrumentation.retransformClasses(new Class[0]) should be NOP
- * @library /test/lib
- * @modules java.instrument
- * @compile RetransformClassesZeroLength.java
- * @run main RetransformClassesZeroLength
- */
-
-import java.lang.instrument.ClassFileTransformer;
-import java.lang.instrument.IllegalClassFormatException;
-import java.lang.instrument.Instrumentation;
-import java.lang.instrument.UnmodifiableClassException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.security.ProtectionDomain;
-
-import jdk.test.lib.process.ProcessTools;
-
-
-public class RetransformClassesZeroLength {
-
- private static String manifest =
- "Premain-Class: " + RetransformClassesZeroLength.Agent.class.getName() + "\n"
- + "Can-Retransform-Classes: true\n";
-
- private static String CP = System.getProperty("test.classes");
-
- public static void main(String args[]) throws Throwable {
- String agentJar = buildAgent();
- ProcessTools.executeProcess(
- ProcessTools.createJavaProcessBuilder(
- "-javaagent:" + agentJar,
- "-version")
- ).shouldHaveExitValue(0);
- }
-
- private static String buildAgent() throws Exception {
- Path jar = Files.createTempFile(Paths.get("."), null, ".jar");
- String jarPath = jar.toAbsolutePath().toString();
- ClassFileInstaller.writeJar(jarPath,
- ClassFileInstaller.Manifest.fromString(manifest),
- RetransformClassesZeroLength.class.getName());
- return jarPath;
- }
-
-
- public static class Agent implements ClassFileTransformer {
- public static void premain(String args, Instrumentation inst) {
- inst.addTransformer(new NoOpTransformer());
- try {
- inst.retransformClasses(new Class[0]);
- } catch (UnmodifiableClassException ex) {
- throw new AssertionError(ex);
- }
- }
- }
-
- private static class NoOpTransformer implements ClassFileTransformer {
- @Override
- public byte[] transform(ClassLoader loader,
- String className,
- Class<?> classBeingRedefined,
- ProtectionDomain protectionDomain,
- byte[] classfileBuffer
- ) throws IllegalClassFormatException {
- return null; // no transform
- }
- }
-}
--- a/test/hotspot/jtreg/serviceability/jvmti/TestLambdaFormRetransformation.java Thu Mar 21 08:41:10 2019 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,141 +0,0 @@
-/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/**
- * @test
- * @bug 8008678
- * @summary JSR 292: constant pool reconstitution must support pseudo strings
- * @library /test/lib
- * @modules java.base/jdk.internal.misc
- * java.instrument
- * java.management
- * jdk.jartool/sun.tools.jar
- * @compile -XDignore.symbol.file TestLambdaFormRetransformation.java
- * @run main TestLambdaFormRetransformation
- */
-
-import java.io.IOException;
-import java.lang.instrument.ClassFileTransformer;
-import java.lang.instrument.IllegalClassFormatException;
-import java.lang.instrument.Instrumentation;
-import java.lang.instrument.UnmodifiableClassException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.security.ProtectionDomain;
-import java.util.Arrays;
-
-import jdk.test.lib.process.ExitCode;
-import jdk.test.lib.process.OutputAnalyzer;
-import jdk.test.lib.process.ProcessTools;
-
-public class TestLambdaFormRetransformation {
- private static String MANIFEST = String.format("Manifest-Version: 1.0\n" +
- "Premain-Class: %s\n" +
- "Can-Retransform-Classes: true\n",
- Agent.class.getName());
-
- private static String CP = System.getProperty("test.classes");
-
- public static void main(String args[]) throws Throwable {
- Path agent = TestLambdaFormRetransformation.buildAgent();
- OutputAnalyzer oa = ProcessTools.executeTestJvm("-javaagent:" +
- agent.toAbsolutePath().toString(), "-version");
- oa.shouldHaveExitValue(ExitCode.OK.value);
- }
-
- private static Path buildAgent() throws IOException {
- Path manifest = TestLambdaFormRetransformation.createManifest();
- Path jar = Files.createTempFile(Paths.get("."), null, ".jar");
-
- String[] args = new String[] {
- "-cfm",
- jar.toAbsolutePath().toString(),
- manifest.toAbsolutePath().toString(),
- "-C",
- TestLambdaFormRetransformation.CP,
- Agent.class.getName() + ".class"
- };
-
- sun.tools.jar.Main jarTool = new sun.tools.jar.Main(System.out, System.err, "jar");
-
- if (!jarTool.run(args)) {
- throw new Error("jar failed: args=" + Arrays.toString(args));
- }
- return jar;
- }
-
- private static Path createManifest() throws IOException {
- Path manifest = Files.createTempFile(Paths.get("."), null, ".mf");
- byte[] manifestBytes = TestLambdaFormRetransformation.MANIFEST.getBytes();
- Files.write(manifest, manifestBytes);
- return manifest;
- }
-}
-
-class Agent implements ClassFileTransformer {
- private static Runnable lambda = () -> {
- System.out.println("I'll crash you!");
- };
-
- public static void premain(String args, Instrumentation instrumentation) {
- if (!instrumentation.isRetransformClassesSupported()) {
- System.out.println("Class retransformation is not supported.");
- return;
- }
- System.out.println("Calling lambda to ensure that lambda forms were created");
-
- Agent.lambda.run();
-
- System.out.println("Registering class file transformer");
-
- instrumentation.addTransformer(new Agent());
-
- for (Class c : instrumentation.getAllLoadedClasses()) {
- if (c.getName().contains("LambdaForm") &&
- instrumentation.isModifiableClass(c)) {
- System.out.format("We've found a modifiable lambda form: %s%n", c.getName());
- try {
- instrumentation.retransformClasses(c);
- } catch (UnmodifiableClassException e) {
- throw new AssertionError("Modification of modifiable class " +
- "caused UnmodifiableClassException", e);
- }
- }
- }
- }
-
- public static void main(String args[]) {
- }
-
- @Override
- public byte[] transform(ClassLoader loader,
- String className,
- Class<?> classBeingRedefined,
- ProtectionDomain protectionDomain,
- byte[] classfileBuffer
- ) throws IllegalClassFormatException {
- System.out.println("Transforming " + className);
- return classfileBuffer.clone();
- }
-}
--- a/test/hotspot/jtreg/serviceability/jvmti/TestRedefineWithUnresolvedClass.java Thu Mar 21 08:41:10 2019 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,88 +0,0 @@
-/*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @summary Redefine a class with an UnresolvedClass reference in the constant pool.
- * @bug 8035150
- * @library /test/lib
- * @modules java.base/jdk.internal.misc
- * java.compiler
- * java.instrument
- * java.management
- * jdk.jartool/sun.tools.jar
- * jdk.internal.jvmstat/sun.jvmstat.monitor
- * @build UnresolvedClassAgent
- * @run main TestRedefineWithUnresolvedClass
- */
-
-import java.io.File;
-import java.util.Arrays;
-
-import jdk.test.lib.process.OutputAnalyzer;
-import jdk.test.lib.process.ProcessTools;
-
-public class TestRedefineWithUnresolvedClass {
-
- final static String slash = File.separator;
- final static String testClasses = System.getProperty("test.classes") + slash;
-
- public static void main(String... args) throws Throwable {
- // delete this class to cause a NoClassDefFoundError
- File unresolved = new File(testClasses, "MyUnresolvedClass.class");
- if (unresolved.exists() && !unresolved.delete()) {
- throw new Exception("Could not delete: " + unresolved);
- }
-
- // build the javaagent
- buildJar("UnresolvedClassAgent");
-
- // launch a VM with the javaagent
- launchTest();
- }
-
- private static void buildJar(String jarName) throws Throwable {
- String testSrc = System.getProperty("test.src", "?") + slash;
-
- String jarPath = String.format("%s%s.jar", testClasses, jarName);
- String manifestPath = String.format("%s%s.mf", testSrc, jarName);
- String className = String.format("%s.class", jarName);
-
- String[] args = new String[] {"-cfm", jarPath, manifestPath, "-C", testClasses, className};
-
- System.out.println("Running jar " + Arrays.toString(args));
- sun.tools.jar.Main jarTool = new sun.tools.jar.Main(System.out, System.err, "jar");
- if (!jarTool.run(args)) {
- throw new Exception("jar failed: args=" + Arrays.toString(args));
- }
- }
-
- private static void launchTest() throws Throwable {
- String[] args = {
- "-javaagent:" + testClasses + "UnresolvedClassAgent.jar",
- "-Dtest.classes=" + testClasses,
- "UnresolvedClassAgent" };
- OutputAnalyzer output = ProcessTools.executeTestJvm(args);
- output.shouldHaveExitValue(0);
- }
-}
--- a/test/hotspot/jtreg/serviceability/jvmti/UnresolvedClassAgent.java Thu Mar 21 08:41:10 2019 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-import java.io.DataInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.lang.instrument.ClassDefinition;
-import java.lang.instrument.Instrumentation;
-
-/*
- * This class is present during compilation, but will be deleted before execution.
- */
-class MyUnresolvedClass {
- static void bar() {
- }
-}
-
-class MyRedefinedClass {
- static void foo() {
- MyUnresolvedClass.bar();
- }
-}
-
-public class UnresolvedClassAgent {
- public static void main(String... args) {
- }
-
- public static void premain(String args, Instrumentation inst) throws Exception {
- try {
- MyRedefinedClass.foo();
- } catch(NoClassDefFoundError err) {
- System.out.println("NoClassDefFoundError (expected)");
- }
-
- File f = new File(System.getProperty("test.classes"), "MyRedefinedClass.class");
- byte[] buf = new byte[(int)f.length()];
- try (DataInputStream dis = new DataInputStream(new FileInputStream(f))) {
- dis.readFully(buf);
- }
- ClassDefinition cd = new ClassDefinition(MyRedefinedClass.class, buf);
- inst.redefineClasses(new ClassDefinition[] {cd});
-
- try {
- MyRedefinedClass.foo();
- } catch(NoClassDefFoundError err) {
- System.out.println("NoClassDefFoundError (expected again)");
- }
- }
-}
--- a/test/hotspot/jtreg/serviceability/jvmti/UnresolvedClassAgent.mf Thu Mar 21 08:41:10 2019 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-Manifest-Version: 1.0
-Premain-Class: UnresolvedClassAgent
-Can-Redefine-Classes: true
--- a/test/jdk/ProblemList.txt Thu Mar 21 08:41:10 2019 +0000
+++ b/test/jdk/ProblemList.txt Thu Mar 21 18:04:01 2019 +0000
@@ -843,8 +843,6 @@
# jdk_util
-java/util/Arrays/TimSortStackSize2.java 8220613 generic-all
-
############################################################################
# jdk_instrument
--- a/test/jdk/TEST.ROOT Thu Mar 21 08:41:10 2019 +0000
+++ b/test/jdk/TEST.ROOT Thu Mar 21 18:04:01 2019 +0000
@@ -22,7 +22,9 @@
javax/management sun/awt sun/java2d javax/xml/jaxp/testng/validation java/lang/ProcessHandle
# Tests that cannot run concurrently
-exclusiveAccess.dirs=java/rmi/Naming java/util/prefs sun/management/jmxremote sun/tools/jstatd sun/security/mscapi java/util/stream java/util/Arrays/largeMemory java/util/BitSet/stream javax/rmi
+exclusiveAccess.dirs=java/rmi/Naming java/util/prefs sun/management/jmxremote sun/tools/jstatd \
+sun/security/mscapi java/util/stream java/util/Arrays/largeMemory java/util/BitSet/stream javax/rmi
+
# Group definitions
groups=TEST.groups
@@ -42,6 +44,7 @@
vm.compiler1.enabled \
vm.compiler2.enabled \
vm.cds \
+ vm.debug \
vm.hasSA \
vm.hasSAandCanAttach \
vm.hasJFR \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/Process/WaitFor.java Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8220684
+ * @summary Process.waitFor(long, TimeUnit) can return false for a process
+ * that exited within the timeout
+ * @run main/othervm WaitFor
+ */
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.concurrent.TimeUnit;
+
+public class WaitFor {
+ public static void main(String[] args) throws Throwable {
+ int failCnt = 0;
+ for (int i = 0; i < 30; ++i) {
+ Process proc = new MyProcess(new ProcessBuilder("true").start());
+ boolean exited = proc.waitFor(100, TimeUnit.MILLISECONDS);
+ if (!exited && !proc.isAlive()) failCnt++;
+ }
+ if (failCnt > 10) {
+ throw new RuntimeException(failCnt + " processes were still alive"
+ + " after timeout");
+ }
+ }
+}
+
+/**
+ * This class uses the default implementation of java.lang.Process#waitFor(long,
+ * TimeUnit), and delegates all other calls to the actual implementation of
+ * Process.
+ */
+class MyProcess extends Process {
+ Process impl;
+ public MyProcess(Process impl) { this.impl = impl; }
+ public OutputStream getOutputStream() { return impl.getOutputStream(); }
+ public InputStream getInputStream() { return impl.getInputStream(); }
+ public InputStream getErrorStream() { return impl.getErrorStream(); }
+ public int waitFor() throws InterruptedException { return impl.waitFor(); }
+ public int exitValue() { return impl.exitValue(); }
+ public void destroy() { impl.destroy(); }
+ public ProcessHandle toHandle() { return impl.toHandle(); }
+}
--- a/test/jdk/java/net/Socket/HttpProxy.java Thu Mar 21 08:41:10 2019 +0000
+++ b/test/jdk/java/net/Socket/HttpProxy.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,11 +23,12 @@
/*
* @test
- * @bug 6370908
+ * @bug 6370908 8220663
* @summary Add support for HTTP_CONNECT proxy in Socket class
* @modules java.base/sun.net.www
* @run main HttpProxy
* @run main/othervm -Djava.net.preferIPv4Stack=true HttpProxy
+ * @run main/othervm -Djava.net.preferIPv6Addresses=true HttpProxy
*/
import java.io.IOException;
@@ -40,6 +41,9 @@
import java.net.Proxy;
import java.net.ServerSocket;
import java.net.Socket;
+import java.net.SocketAddress;
+import java.util.ArrayList;
+import java.util.List;
import sun.net.www.MessageHeader;
public class HttpProxy {
@@ -50,9 +54,10 @@
public static void main(String[] args) throws Exception {
String host;
int port;
+ ConnectProxyTunnelServer proxy = null;
if (args.length == 0) {
// Start internal proxy
- ConnectProxyTunnelServer proxy = new ConnectProxyTunnelServer();
+ proxy = new ConnectProxyTunnelServer();
proxy.start();
host = "localhost";
port = proxy.getLocalPort();
@@ -66,8 +71,13 @@
return;
}
- HttpProxy p = new HttpProxy(host, port);
- p.test();
+ try {
+ HttpProxy p = new HttpProxy(host, port);
+ p.test();
+ } finally {
+ if (proxy != null)
+ proxy.close();
+ }
}
public HttpProxy(String proxyHost, int proxyPort) {
@@ -79,26 +89,37 @@
InetSocketAddress proxyAddress = new InetSocketAddress(proxyHost, proxyPort);
Proxy httpProxy = new Proxy(Proxy.Type.HTTP, proxyAddress);
- try (ServerSocket ss = new ServerSocket(0);
- Socket sock = new Socket(httpProxy)) {
- sock.setSoTimeout(SO_TIMEOUT);
- sock.setTcpNoDelay(false);
+ try (ServerSocket ss = new ServerSocket(0)) {
+ List<InetSocketAddress> externalAddresses = new ArrayList<>();
+ externalAddresses.add(
+ new InetSocketAddress(InetAddress.getLocalHost(), ss.getLocalPort()));
- InetSocketAddress externalAddress =
- new InetSocketAddress(InetAddress.getLocalHost(), ss.getLocalPort());
+ if (!"true".equals(System.getProperty("java.net.preferIPv4Stack"))) {
+ byte[] bytes = new byte[] {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
+ var address = InetAddress.getByAddress(bytes);
+ externalAddresses.add(
+ new InetSocketAddress(address, ss.getLocalPort()));
+ }
- out.println("Trying to connect to server socket on " + externalAddress);
- sock.connect(externalAddress);
- try (Socket externalSock = ss.accept()) {
- // perform some simple checks
- check(sock.isBound(), "Socket is not bound");
- check(sock.isConnected(), "Socket is not connected");
- check(!sock.isClosed(), "Socket should not be closed");
- check(sock.getSoTimeout() == SO_TIMEOUT,
- "Socket should have a previously set timeout");
- check(sock.getTcpNoDelay() == false, "NODELAY should be false");
+ for (SocketAddress externalAddress : externalAddresses) {
+ try (Socket sock = new Socket(httpProxy)) {
+ sock.setSoTimeout(SO_TIMEOUT);
+ sock.setTcpNoDelay(false);
- simpleDataExchange(sock, externalSock);
+ out.println("Trying to connect to server socket on " + externalAddress);
+ sock.connect(externalAddress);
+ try (Socket externalSock = ss.accept()) {
+ // perform some simple checks
+ check(sock.isBound(), "Socket is not bound");
+ check(sock.isConnected(), "Socket is not connected");
+ check(!sock.isClosed(), "Socket should not be closed");
+ check(sock.getSoTimeout() == SO_TIMEOUT,
+ "Socket should have a previously set timeout");
+ check(sock.getTcpNoDelay() == false, "NODELAY should be false");
+
+ simpleDataExchange(sock, externalSock);
+ }
+ }
}
}
}
@@ -108,7 +129,7 @@
}
static Exception unexpected(Exception e) {
- out.println("Unexcepted Exception: " + e);
+ out.println("Unexpected Exception: " + e);
e.printStackTrace();
return e;
}
@@ -164,9 +185,10 @@
return i1 * 256 + i2;
}
- static class ConnectProxyTunnelServer extends Thread {
+ static class ConnectProxyTunnelServer extends Thread implements AutoCloseable {
private final ServerSocket ss;
+ private volatile boolean closed;
public ConnectProxyTunnelServer() throws IOException {
ss = new ServerSocket(0);
@@ -174,13 +196,20 @@
@Override
public void run() {
- try (Socket clientSocket = ss.accept()) {
- processRequest(clientSocket);
+ try {
+ while (!closed) {
+ try (Socket clientSocket = ss.accept()) {
+ processRequest(clientSocket);
+ }
+ }
} catch (Exception e) {
- out.println("Proxy Failed: " + e);
- e.printStackTrace();
+ if (!closed) {
+ out.println("Proxy Failed: " + e);
+ e.printStackTrace();
+ }
} finally {
- try { ss.close(); } catch (IOException x) { unexpected(x); }
+ if (!closed)
+ try { ss.close(); } catch (IOException x) { unexpected(x); }
}
}
@@ -191,6 +220,12 @@
return ss.getLocalPort();
}
+ @Override
+ public void close() throws Exception {
+ closed = true;
+ ss.close();
+ }
+
/*
* Processes the CONNECT request
*/
@@ -200,7 +235,7 @@
if (!statusLine.startsWith("CONNECT")) {
out.println("proxy server: processes only "
- + "CONNECT method requests, recieved: "
+ + "CONNECT method requests, received: "
+ statusLine);
return;
}
@@ -246,12 +281,19 @@
int endi = connectStr.lastIndexOf(' ');
String connectInfo = connectStr.substring(starti+1, endi).trim();
// retrieve server name and port
- endi = connectInfo.indexOf(':');
+ endi = connectInfo.lastIndexOf(':');
String name = connectInfo.substring(0, endi);
+
+ if (name.contains(":")) {
+ if (!(name.startsWith("[") && name.endsWith("]"))) {
+ throw new IOException("Invalid host:" + name);
+ }
+ name = name.substring(1, name.length() - 1);
+ }
int port = Integer.parseInt(connectInfo.substring(endi+1));
return new InetSocketAddress(name, port);
} catch (Exception e) {
- out.println("Proxy recieved a request: " + connectStr);
+ out.println("Proxy received a request: " + connectStr);
throw unexpected(e);
}
}
--- a/test/jdk/java/net/URL/HandlerLoop.java Thu Mar 21 08:41:10 2019 +0000
+++ b/test/jdk/java/net/URL/HandlerLoop.java Thu Mar 21 18:04:01 2019 +0000
@@ -32,7 +32,7 @@
* @summary Test bootstrap problem when a URLStreamHandlerFactory is loaded
* by the application class loader.
* @modules java.base/sun.net.www.protocol.file
- * @run main HandlerLoop
+ * @run main/othervm HandlerLoop
*/
public class HandlerLoop {
--- a/test/jdk/java/util/Arrays/TimSortStackSize2.java Thu Mar 21 08:41:10 2019 +0000
+++ b/test/jdk/java/util/Arrays/TimSortStackSize2.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -28,6 +28,7 @@
* @library /test/lib
* @modules java.management
* java.base/jdk.internal
+ * @requires (vm.debug == false)
* @build TimSortStackSize2
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
--- a/test/jdk/java/util/Scanner/ScanTest.java Thu Mar 21 08:41:10 2019 +0000
+++ b/test/jdk/java/util/Scanner/ScanTest.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -24,7 +24,7 @@
/**
* @test
* @bug 4313885 4926319 4927634 5032610 5032622 5049968 5059533 6223711 6277261 6269946 6288823
- * 8072722 8139414 8166261
+ * 8072722 8139414 8166261 8172695
* @summary Basic tests of java.util.Scanner methods
* @key randomness
* @modules jdk.localedata
@@ -49,26 +49,12 @@
private static File inputFile = new File(System.getProperty("test.src", "."), "input.txt");
public static void main(String[] args) throws Exception {
-
- Locale reservedLocale = Locale.getDefault();
- String lang = reservedLocale.getLanguage();
+ Locale defaultLocale = Locale.getDefault();
try {
- if (!"en".equals(lang) &&
- !"zh".equals(lang) &&
- !"ko".equals(lang) &&
- !"ja".equals(lang)) {
- //Before we have resource to improve the test to be ready for
- //arbitrary locale, force the default locale to be "English"
- //for now. First we check whether the "English" locale is
- //available on the system as it could be absent due to varying
- //configurations.
- if (!Arrays.asList(Locale.getAvailableLocales())
- .contains(Locale.ENGLISH)) {
- throw new RuntimeException
- ("The \"English\" Locale is unavailable on this system");
- }
- Locale.setDefault(Locale.ENGLISH);
- }
+ // Before we have resource to improve the test to be ready for
+ // arbitrary locale, force the default locale to be ROOT for now.
+ Locale.setDefault(Locale.US);
+
skipTest();
findInLineTest();
findWithinHorizonTest();
@@ -128,7 +114,7 @@
System.err.println("OKAY: All tests passed.");
} finally {
// restore the default locale
- Locale.setDefault(reservedLocale);
+ Locale.setDefault(defaultLocale);
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/crypto/SecretKeyFactory/SecKeyFacSunJCEPrf.java Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8218723
+ * @summary Use SunJCE Mac in SecretKeyFactory PBKDF2 implementation
+ * @library evilprov.jar
+ * @library /test/lib
+ * @build jdk.test.lib.Convert
+ * @run main/othervm SecKeyFacSunJCEPrf
+ */
+
+import java.util.Arrays;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.PBEKeySpec;
+import java.security.Provider;
+import java.security.Security;
+import com.evilprovider.*;
+import jdk.test.lib.Convert;
+
+public class SecKeyFacSunJCEPrf {
+
+ // One of the PBKDF2 HMAC-SHA1 test vectors from RFC 6070
+ private static final byte[] SALT = "salt".getBytes();
+ private static final char[] PASS = "password".toCharArray();
+ private static final int ITER = 4096;
+ private static final byte[] EXP_OUT = Convert.hexStringToByteArray(
+ "4B007901B765489ABEAD49D926F721D065A429C1");
+
+ public static void main(String[] args) throws Exception {
+ // Instantiate the Evil Provider and insert it in the
+ // most-preferred position.
+ Provider evilProv = new EvilProvider();
+ System.out.println("3rd Party Provider: " + evilProv);
+ Security.insertProviderAt(evilProv, 1);
+
+ SecretKeyFactory pbkdf2 =
+ SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1", "SunJCE");
+ PBEKeySpec pbks = new PBEKeySpec(PASS, SALT, ITER, 160);
+
+ SecretKey secKey1 = pbkdf2.generateSecret(pbks);
+ System.out.println("PBKDF2WithHmacSHA1:\n" +
+ Convert.byteArrayToHexString(secKey1.getEncoded()));
+ if (Arrays.equals(secKey1.getEncoded(), EXP_OUT)) {
+ System.out.println("Test Vector Passed");
+ } else {
+ System.out.println("Test Vector Failed");
+ System.out.println("Expected Output:\n" +
+ Convert.byteArrayToHexString(EXP_OUT));
+ throw new RuntimeException();
+ }
+ }
+}
+
Binary file test/jdk/javax/crypto/SecretKeyFactory/evilprov.jar has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/crypto/SecretKeyFactory/evilprov/Makefile Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,55 @@
+#
+# Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+# Java paths
+#JAVA_BASE=PATH_TO_JAVA_IMG_DIR
+JAVABIN=$(JAVA_BASE)/bin
+JAVAC=$(JAVABIN)/javac
+JAVA=$(JAVABIN)/java
+JAR=$(JAVABIN)/jar
+JARSIGNER=$(JAVABIN)/jarsigner
+
+# Compile-time flags and paths
+JFLAGS=-Xlint:all
+SRCPATH=com/evilprovider
+CLASSDST=classes
+
+PROVJAR=evilprov.jar
+KSTORE=PATH_TO_KEYSTORE
+KALIAS=PLACE_SIGNING_ALIAS_HERE
+MODVER=1.0
+
+all: $(PROVJAR)
+
+%.class: %.java
+ mkdir -p $(CLASSDST)
+ $(JAVAC) -d $(CLASSDST) $(JFLAGS) $<
+
+$(PROVJAR): $(SRCPATH)/EvilHmacSHA1.class $(SRCPATH)/EvilProvider.class module-info.class
+ $(JAR) --create --file $(PROVJAR) --module-version $(MODVER) -C $(CLASSDST) .
+
+signed: $(PROVJAR)
+ jarsigner -keystore $(KSTORE) $(PROVJAR).jar $(KALIAS)
+
+clean:
+ rm -rf $(CLASSDST) $(PROVJAR)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/crypto/SecretKeyFactory/evilprov/README Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,15 @@
+Everything in this directory is dedicated to building the EvilProvider
+used with the SecKeyFacSunJCEPRF test (JDK-8218723).
+
+The makefile does require a JDK image path to be provided through the
+JAVA_BASE makefile variable. As an example:
+
+make JAVA_BASE=/usr/java/jdk-11.0.1 evilprov
+
+Since the EvilProvider is a modular jar, JDK 9 or later should be used.
+
+For OpenJDK, no signing is required. If signing is required (for use
+with Oracle JDK, for instance), you must obtain a JCE signing certificate
+and place it in a keystore, then run the "signed" makefile target (it will
+build the jar file if it does not already exist).
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/crypto/SecretKeyFactory/evilprov/com/evilprovider/EvilHmacSHA1.java Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.evilprovider;
+
+import java.security.*;
+import java.security.spec.*;
+import java.nio.ByteBuffer;
+
+import javax.crypto.*;
+
+public final class EvilHmacSHA1 extends MacSpi {
+ private final Mac internalMac;
+
+ public EvilHmacSHA1() throws GeneralSecurityException {
+ internalMac = Mac.getInstance("HmacSHA1", "SunJCE");
+ }
+
+ @Override
+ protected byte[] engineDoFinal() {
+ return internalMac.doFinal();
+ }
+
+ @Override
+ protected int engineGetMacLength() {
+ return internalMac.getMacLength();
+ }
+
+ @Override
+ protected void engineInit(Key key, AlgorithmParameterSpec spec)
+ throws InvalidKeyException, InvalidAlgorithmParameterException {
+ SecretKey sKey;
+ if (key instanceof SecretKey) {
+ sKey = (SecretKey)key;
+ } else {
+ throw new IllegalArgumentException("Key must be a SecretKey");
+ }
+
+ byte[] sKeyEnc = sKey.getEncoded();
+ int keyBits = sKeyEnc.length * 8;
+ if (keyBits < 160) {
+ throw new IllegalArgumentException("Key must be at least 160 bits");
+ }
+
+ // Pass through to init
+ internalMac.init(key, spec);
+ }
+
+ @Override
+ protected void engineReset() {
+ internalMac.reset();
+ }
+
+ @Override
+ protected void engineUpdate(byte input) {
+ internalMac.update(input);
+ }
+
+ @Override
+ protected void engineUpdate(byte[] input, int offset, int len) {
+ internalMac.update(input, offset, len);
+ }
+
+ @Override
+ protected void engineUpdate(ByteBuffer input) {
+ internalMac.update(input);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/crypto/SecretKeyFactory/evilprov/com/evilprovider/EvilProvider.java Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.evilprovider;
+
+import java.security.*;
+
+public final class EvilProvider extends Provider {
+
+ private static final long serialVersionUID = 11223344550000L;
+
+ public EvilProvider() {
+ super("EvilProvider", "1.0", "Evil Provider");
+ putService(new Provider.Service(this, "Mac", "HmacSHA1",
+ "com.evilprovider.EvilHmacSHA1", null, null));
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/crypto/SecretKeyFactory/evilprov/module-info.java Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Provides the evil provider
+ *
+ * @provides java.security.Provider
+ *
+ * @moduleGraph
+ */
+module jdk.evilprovider {
+ provides java.security.Provider with com.evilprovider.EvilProvider;
+}
--- a/test/jdk/sun/net/www/protocol/http/StackTraceTest.java Thu Mar 21 08:41:10 2019 +0000
+++ b/test/jdk/sun/net/www/protocol/http/StackTraceTest.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -21,22 +21,30 @@
* questions.
*/
-/**
+/*
* @test
* @bug 4773417 5003746
+ * @library /test/lib
+ * @build jdk.test.lib.Utils
+ * @run main StackTraceTest
* @summary HttpURLConnection.getInputStream() produces IOException with
* bad stack trace; HttpURLConnection.getInputStream loses
* exception message, exception class
*/
import java.net.*;
import java.io.IOException;
+import jdk.test.lib.Utils;
public class StackTraceTest {
public static void main(String[] args) throws Exception {
- URL url;
- try (ServerSocket ss = new ServerSocket(0)) { // refusing socket
- url = new URL("http://localhost:" + ss.getLocalPort() + "/");
- }
+ InetSocketAddress refusing = Utils.refusingEndpoint();
+ int port = refusing.getPort();
+ String host = refusing.getAddress().getHostAddress();
+ if (host.contains(":"))
+ host = "[" + host + "]";
+ URL url = URI.create("http://" + host + ":" + port + "/").toURL();
+ System.out.println("URL: " + url);
+
URLConnection uc = url.openConnection();
// Trigger implicit connection by trying to retrieve bogus
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/security/ec/SignatureDigestTruncate.java Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import jdk.test.lib.Convert;
+
+import java.security.*;
+import java.security.spec.*;
+import java.math.*;
+import java.util.*;
+
+/*
+ * @test
+ * @bug 8147502
+ * @summary Test that digests are properly truncated before the signature
+ * is applied. The digest should be truncated to the bit length of the
+ * group order.
+ * @library /test/lib
+ * @build jdk.test.lib.Convert
+ * @run main SignatureDigestTruncate
+ */
+public class SignatureDigestTruncate {
+
+ /*
+ * A SecureRandom that produces nextBytes in a way that causes the nonce
+ * to be set to the value supplied to the constructor. This class
+ * is specific to the way that the native ECDSA implementation in
+ * SunEC produces nonces from random input. It may not work for all
+ * test cases, and it will need to be updated when the behavior of
+ * SunEC changes.
+ */
+ private static class FixedRandom extends SecureRandom {
+
+ private final byte[] val;
+
+ public FixedRandom(byte[] val) {
+ // SunEC adds one to the value returned, so subtract one here in
+ // order to get back to the correct value.
+ BigInteger biVal = new BigInteger(1, val);
+ biVal = biVal.subtract(BigInteger.ONE);
+ byte[] temp = biVal.toByteArray();
+ this.val = new byte[val.length];
+ int inStartPos = Math.max(0, temp.length - val.length);
+ int outStartPos = Math.max(0, val.length - temp.length);
+ System.arraycopy(temp, inStartPos, this.val, outStartPos,
+ temp.length - inStartPos);
+ }
+
+ @Override
+ public void nextBytes(byte[] bytes) {
+ // SunEC samples (n + 1) * 2 bytes, but only n*2 bytes are used by
+ // the native implementation. So the value must be offset slightly.
+ Arrays.fill(bytes, (byte) 0);
+ int copyLength = Math.min(val.length, bytes.length - 2);
+ System.arraycopy(val, 0, bytes, bytes.length - copyLength - 2,
+ copyLength);
+ }
+ }
+
+ private static void assertEquals(byte[] expected, byte[] actual,
+ String name) {
+ if (!Arrays.equals(actual, expected)) {
+ System.out.println("expect: "
+ + Convert.byteArrayToHexString(expected));
+ System.out.println("actual: "
+ + Convert.byteArrayToHexString(actual));
+ throw new RuntimeException("Incorrect " + name + " value");
+ }
+ }
+
+ private static void runTest(String alg, String curveName,
+ String privateKeyStr, String msgStr, String kStr, String sigStr)
+ throws Exception {
+
+ System.out.println("Testing " + alg + " with " + curveName);
+
+ byte[] privateKey = Convert.hexStringToByteArray(privateKeyStr);
+ byte[] msg = Convert.hexStringToByteArray(msgStr);
+ byte[] k = Convert.hexStringToByteArray(kStr);
+ byte[] expectedSig = Convert.hexStringToByteArray(sigStr);
+
+ AlgorithmParameters params =
+ AlgorithmParameters.getInstance("EC", "SunEC");
+ params.init(new ECGenParameterSpec(curveName));
+ ECParameterSpec ecParams =
+ params.getParameterSpec(ECParameterSpec.class);
+
+ KeyFactory kf = KeyFactory.getInstance("EC", "SunEC");
+ BigInteger s = new BigInteger(1, privateKey);
+ ECPrivateKeySpec privKeySpec = new ECPrivateKeySpec(s, ecParams);
+ PrivateKey privKey = kf.generatePrivate(privKeySpec);
+
+ Signature sig = Signature.getInstance(alg, "SunEC");
+ sig.initSign(privKey, new FixedRandom(k));
+ sig.update(msg);
+ byte[] computedSig = sig.sign();
+ assertEquals(expectedSig, computedSig, "signature");
+ }
+
+ public static void main(String[] args) throws Exception {
+ runTest("SHA384withECDSAinP1363Format", "sect283r1",
+ "abcdef10234567", "010203040506070809",
+ "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d" +
+ "1e1f20212223",
+ "01d7544b5d3935216bd45e2f8042537e1e0296a11e0eb96666199281b409" +
+ "42abccd5358a035de8a314d3e6c2a97614daebf5fb1313540eec3f9a3272" +
+ "068aa10922ccae87d255c84c");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/security/pkcs11/tls/tls12/TestTLS12.java Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,474 @@
+/*
+ * Copyright (c) 2019, Red Hat, Inc.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8029661
+ * @summary Test TLS 1.2
+ * @modules java.base/sun.security.internal.spec
+ * java.base/sun.security.util
+ * java.base/com.sun.crypto.provider
+ * @library /test/lib ../..
+ * @run main/othervm/timeout=120 TestTLS12
+ */
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+import java.security.KeyStore;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.security.SecureRandom;
+import java.security.Security;
+
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.crypto.Cipher;
+import javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.SSLEngineResult;
+import javax.net.ssl.SSLEngineResult.HandshakeStatus;
+import javax.net.ssl.SSLParameters;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.TrustManagerFactory;
+
+import sun.security.internal.spec.TlsMasterSecretParameterSpec;
+import sun.security.internal.spec.TlsPrfParameterSpec;
+import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec;
+
+public final class TestTLS12 extends SecmodTest {
+
+ private static final boolean enableDebug = true;
+
+ private static Provider sunPKCS11NSSProvider;
+ private static Provider sunJCEProvider;
+ private static KeyStore ks;
+ private static KeyStore ts;
+ private static char[] passphrase = "JAHshj131@@".toCharArray();
+ private static RSAPrivateKey privateKey;
+ private static RSAPublicKey publicKey;
+
+ public static void main(String[] args) throws Exception {
+ try {
+ initialize();
+ } catch (Exception e) {
+ System.out.println("Test skipped: failure during" +
+ " initialization");
+ if (enableDebug) {
+ System.out.println(e);
+ }
+ return;
+ }
+
+ if (shouldRun()) {
+ // Test against JCE
+ testTlsAuthenticationCodeGeneration();
+
+ // Self-integrity test (complete TLS 1.2 communication)
+ new testTLS12SunPKCS11Communication().run();
+
+ System.out.println("Test PASS - OK");
+ } else {
+ System.out.println("Test skipped: TLS 1.2 mechanisms" +
+ " not supported by current SunPKCS11 back-end");
+ }
+ }
+
+ private static boolean shouldRun() {
+ if (sunPKCS11NSSProvider == null) {
+ return false;
+ }
+ try {
+ KeyGenerator.getInstance("SunTls12MasterSecret",
+ sunPKCS11NSSProvider);
+ KeyGenerator.getInstance(
+ "SunTls12RsaPremasterSecret", sunPKCS11NSSProvider);
+ KeyGenerator.getInstance("SunTls12Prf", sunPKCS11NSSProvider);
+ } catch (NoSuchAlgorithmException e) {
+ return false;
+ }
+ return true;
+ }
+
+ private static void testTlsAuthenticationCodeGeneration()
+ throws Exception {
+ // Generate RSA Pre-Master Secret in SunPKCS11 provider
+ SecretKey rsaPreMasterSecret = null;
+ @SuppressWarnings("deprecation")
+ TlsRsaPremasterSecretParameterSpec rsaPreMasterSecretSpec =
+ new TlsRsaPremasterSecretParameterSpec(0x0303, 0x0303);
+ {
+ KeyGenerator rsaPreMasterSecretKG = KeyGenerator.getInstance(
+ "SunTls12RsaPremasterSecret", sunPKCS11NSSProvider);
+ rsaPreMasterSecretKG.init(rsaPreMasterSecretSpec, null);
+ rsaPreMasterSecret = rsaPreMasterSecretKG.generateKey();
+ }
+
+ // Get RSA Pre-Master Secret in plain (from SunPKCS11 provider)
+ byte[] rsaPlainPreMasterSecret = null;
+ {
+ Cipher rsaPreMasterSecretWrapperCipher =
+ Cipher.getInstance("RSA/ECB/PKCS1Padding",
+ sunPKCS11NSSProvider);
+ rsaPreMasterSecretWrapperCipher.init(Cipher.WRAP_MODE, publicKey,
+ new SecureRandom());
+ byte[] rsaEncryptedPreMasterSecret =
+ rsaPreMasterSecretWrapperCipher.wrap(rsaPreMasterSecret);
+ Cipher rsaPreMasterSecretUnwrapperCipher =
+ Cipher.getInstance("RSA/ECB/PKCS1Padding", sunJCEProvider);
+ rsaPreMasterSecretUnwrapperCipher.init(Cipher.UNWRAP_MODE,
+ privateKey, rsaPreMasterSecretSpec);
+ rsaPlainPreMasterSecret = rsaPreMasterSecretUnwrapperCipher.unwrap(
+ rsaEncryptedPreMasterSecret, "TlsRsaPremasterSecret",
+ Cipher.SECRET_KEY).getEncoded();
+
+ if (enableDebug) {
+ System.out.println("rsaPlainPreMasterSecret:");
+ for (byte b : rsaPlainPreMasterSecret) {
+ System.out.printf("%02X, ", b);
+ }
+ System.out.println("");
+ }
+ }
+
+ // Generate Master Secret
+ SecretKey sunPKCS11MasterSecret = null;
+ SecretKey jceMasterSecret = null;
+ {
+ KeyGenerator sunPKCS11MasterSecretGenerator =
+ KeyGenerator.getInstance("SunTls12MasterSecret",
+ sunPKCS11NSSProvider);
+ KeyGenerator jceMasterSecretGenerator = KeyGenerator.getInstance(
+ "SunTls12MasterSecret", sunJCEProvider);
+ @SuppressWarnings("deprecation")
+ TlsMasterSecretParameterSpec sunPKCS11MasterSecretSpec =
+ new TlsMasterSecretParameterSpec(rsaPreMasterSecret, 3, 3,
+ new byte[32], new byte[32], "SHA-256", 32, 64);
+ @SuppressWarnings("deprecation")
+ TlsMasterSecretParameterSpec jceMasterSecretSpec =
+ new TlsMasterSecretParameterSpec(
+ new SecretKeySpec(rsaPlainPreMasterSecret,
+ "Generic"), 3, 3, new byte[32],
+ new byte[32], "SHA-256", 32, 64);
+ sunPKCS11MasterSecretGenerator.init(sunPKCS11MasterSecretSpec,
+ null);
+ jceMasterSecretGenerator.init(jceMasterSecretSpec, null);
+ sunPKCS11MasterSecret =
+ sunPKCS11MasterSecretGenerator.generateKey();
+ jceMasterSecret = jceMasterSecretGenerator.generateKey();
+ if (enableDebug) {
+ System.out.println("Master Secret (SunJCE):");
+ if (jceMasterSecret != null) {
+ for (byte b : jceMasterSecret.getEncoded()) {
+ System.out.printf("%02X, ", b);
+ }
+ System.out.println("");
+ }
+ }
+ }
+
+ // Generate authentication codes
+ byte[] sunPKCS11AuthenticationCode = null;
+ byte[] jceAuthenticationCode = null;
+ {
+ // Generate SunPKCS11 authentication code
+ {
+ @SuppressWarnings("deprecation")
+ TlsPrfParameterSpec sunPKCS11AuthenticationCodeSpec =
+ new TlsPrfParameterSpec(sunPKCS11MasterSecret,
+ "client finished", "a".getBytes(), 12,
+ "SHA-256", 32, 64);
+ KeyGenerator sunPKCS11AuthCodeGenerator =
+ KeyGenerator.getInstance("SunTls12Prf",
+ sunPKCS11NSSProvider);
+ sunPKCS11AuthCodeGenerator.init(
+ sunPKCS11AuthenticationCodeSpec);
+ sunPKCS11AuthenticationCode =
+ sunPKCS11AuthCodeGenerator.generateKey().getEncoded();
+ }
+
+ // Generate SunJCE authentication code
+ {
+ @SuppressWarnings("deprecation")
+ TlsPrfParameterSpec jceAuthenticationCodeSpec =
+ new TlsPrfParameterSpec(jceMasterSecret,
+ "client finished", "a".getBytes(), 12,
+ "SHA-256", 32, 64);
+ KeyGenerator jceAuthCodeGenerator =
+ KeyGenerator.getInstance("SunTls12Prf",
+ sunJCEProvider);
+ jceAuthCodeGenerator.init(jceAuthenticationCodeSpec);
+ jceAuthenticationCode =
+ jceAuthCodeGenerator.generateKey().getEncoded();
+ }
+
+ if (enableDebug) {
+ System.out.println("SunPKCS11 Authentication Code: ");
+ for (byte b : sunPKCS11AuthenticationCode) {
+ System.out.printf("%02X, ", b);
+ }
+ System.out.println("");
+ System.out.println("SunJCE Authentication Code: ");
+ for (byte b : jceAuthenticationCode) {
+ System.out.printf("%02X, ", b);
+ }
+ System.out.println("");
+ }
+ }
+
+ if (sunPKCS11AuthenticationCode == null ||
+ jceAuthenticationCode == null ||
+ sunPKCS11AuthenticationCode.length == 0 ||
+ jceAuthenticationCode.length == 0 ||
+ !Arrays.equals(sunPKCS11AuthenticationCode,
+ jceAuthenticationCode)) {
+ throw new Exception("Authentication codes from JCE" +
+ " and SunPKCS11 differ.");
+ }
+ }
+
+ private static class testTLS12SunPKCS11Communication {
+ public static void run() throws Exception {
+ SSLEngine[][] enginesToTest = getSSLEnginesToTest();
+
+ for (SSLEngine[] engineToTest : enginesToTest) {
+
+ SSLEngine clientSSLEngine = engineToTest[0];
+ SSLEngine serverSSLEngine = engineToTest[1];
+
+ // SSLEngine code based on RedhandshakeFinished.java
+
+ boolean dataDone = false;
+
+ ByteBuffer clientOut = null;
+ ByteBuffer clientIn = null;
+ ByteBuffer serverOut = null;
+ ByteBuffer serverIn = null;
+ ByteBuffer cTOs;
+ ByteBuffer sTOc;
+
+ SSLSession session = clientSSLEngine.getSession();
+ int appBufferMax = session.getApplicationBufferSize();
+ int netBufferMax = session.getPacketBufferSize();
+
+ clientIn = ByteBuffer.allocate(appBufferMax + 50);
+ serverIn = ByteBuffer.allocate(appBufferMax + 50);
+
+ cTOs = ByteBuffer.allocateDirect(netBufferMax);
+ sTOc = ByteBuffer.allocateDirect(netBufferMax);
+
+ clientOut = ByteBuffer.wrap(
+ "Hi Server, I'm Client".getBytes());
+ serverOut = ByteBuffer.wrap(
+ "Hello Client, I'm Server".getBytes());
+
+ SSLEngineResult clientResult;
+ SSLEngineResult serverResult;
+
+ while (!dataDone) {
+ clientResult = clientSSLEngine.wrap(clientOut, cTOs);
+ runDelegatedTasks(clientResult, clientSSLEngine);
+ serverResult = serverSSLEngine.wrap(serverOut, sTOc);
+ runDelegatedTasks(serverResult, serverSSLEngine);
+ cTOs.flip();
+ sTOc.flip();
+
+ if (enableDebug) {
+ System.out.println("Client -> Network");
+ printTlsNetworkPacket("", cTOs);
+ System.out.println("");
+ System.out.println("Server -> Network");
+ printTlsNetworkPacket("", sTOc);
+ System.out.println("");
+ }
+
+ clientResult = clientSSLEngine.unwrap(sTOc, clientIn);
+ runDelegatedTasks(clientResult, clientSSLEngine);
+ serverResult = serverSSLEngine.unwrap(cTOs, serverIn);
+ runDelegatedTasks(serverResult, serverSSLEngine);
+
+ cTOs.compact();
+ sTOc.compact();
+
+ if (!dataDone &&
+ (clientOut.limit() == serverIn.position()) &&
+ (serverOut.limit() == clientIn.position())) {
+ checkTransfer(serverOut, clientIn);
+ checkTransfer(clientOut, serverIn);
+ dataDone = true;
+ }
+ }
+ }
+ }
+
+ static void printTlsNetworkPacket(String prefix, ByteBuffer bb) {
+ ByteBuffer slice = bb.slice();
+ byte[] buffer = new byte[slice.remaining()];
+ slice.get(buffer);
+ for (int i = 0; i < buffer.length; i++) {
+ System.out.printf("%02X, ", (byte)(buffer[i] & (byte)0xFF));
+ if (i % 8 == 0 && i % 16 != 0) {
+ System.out.print(" ");
+ }
+ if (i % 16 == 0) {
+ System.out.println("");
+ }
+ }
+ System.out.flush();
+ }
+
+ private static void checkTransfer(ByteBuffer a, ByteBuffer b)
+ throws Exception {
+ a.flip();
+ b.flip();
+ if (!a.equals(b)) {
+ throw new Exception("Data didn't transfer cleanly");
+ }
+ a.position(a.limit());
+ b.position(b.limit());
+ a.limit(a.capacity());
+ b.limit(b.capacity());
+ }
+
+ private static void runDelegatedTasks(SSLEngineResult result,
+ SSLEngine engine) throws Exception {
+
+ if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
+ Runnable runnable;
+ while ((runnable = engine.getDelegatedTask()) != null) {
+ runnable.run();
+ }
+ HandshakeStatus hsStatus = engine.getHandshakeStatus();
+ if (hsStatus == HandshakeStatus.NEED_TASK) {
+ throw new Exception(
+ "handshake shouldn't need additional tasks");
+ }
+ }
+ }
+
+ private static SSLEngine[][] getSSLEnginesToTest() throws Exception {
+ SSLEngine[][] enginesToTest = new SSLEngine[2][2];
+ String[][] preferredSuites = new String[][]{ new String[] {
+ "TLS_RSA_WITH_AES_128_CBC_SHA256"
+ }, new String[] {
+ "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256"
+ }};
+ for (int i = 0; i < enginesToTest.length; i++) {
+ enginesToTest[i][0] = createSSLEngine(true);
+ enginesToTest[i][1] = createSSLEngine(false);
+ enginesToTest[i][0].setEnabledCipherSuites(preferredSuites[i]);
+ enginesToTest[i][1].setEnabledCipherSuites(preferredSuites[i]);
+ }
+ return enginesToTest;
+ }
+
+ static private SSLEngine createSSLEngine(boolean client)
+ throws Exception {
+ SSLEngine ssle;
+ KeyManagerFactory kmf = KeyManagerFactory.getInstance("PKIX", "SunJSSE");
+ kmf.init(ks, passphrase);
+
+ TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX", "SunJSSE");
+ tmf.init(ts);
+
+ SSLContext sslCtx = SSLContext.getInstance("TLSv1.2", "SunJSSE");
+ sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
+ ssle = sslCtx.createSSLEngine("localhost", 443);
+ ssle.setUseClientMode(client);
+ SSLParameters sslParameters = ssle.getSSLParameters();
+ ssle.setSSLParameters(sslParameters);
+
+ return ssle;
+ }
+ }
+
+ private static void initialize() throws Exception {
+ if (initSecmod() == false) {
+ return;
+ }
+ String configName = BASE + SEP + "nss.cfg";
+ sunPKCS11NSSProvider = getSunPKCS11(configName);
+ System.out.println("SunPKCS11 provider: " + sunPKCS11NSSProvider);
+
+ List<Provider> installedProviders = new LinkedList<>();
+ for (Provider p : Security.getProviders()){
+ installedProviders.add(p);
+ Security.removeProvider(p.getName());
+ }
+ Security.addProvider(sunPKCS11NSSProvider);
+ for (Provider p : installedProviders){
+ String providerName = p.getName();
+ if (providerName.equals("SunJSSE") ||
+ providerName.equals("SUN") ||
+ providerName.equals("SunJCE")) {
+ Security.addProvider(p);
+ if (providerName.equals("SunJCE")) {
+ sunJCEProvider = p;
+ }
+ }
+ }
+
+ ks = KeyStore.getInstance("PKCS11", sunPKCS11NSSProvider);
+ ks.load(null, "test12".toCharArray());
+ ts = ks;
+
+ KeyStore ksPlain = readTestKeyStore();
+ privateKey = (RSAPrivateKey)ksPlain.getKey("rh_rsa_sha256",
+ passphrase);
+ publicKey = (RSAPublicKey)ksPlain.getCertificate(
+ "rh_rsa_sha256").getPublicKey();
+
+ // Extended Master Secret is not currently supported in SunPKCS11
+ // cryptographic provider
+ System.setProperty("jdk.tls.useExtendedMasterSecret", "false");
+ String disabledAlgorithms =
+ Security.getProperty("jdk.tls.disabledAlgorithms");
+ if (disabledAlgorithms.length() > 0) {
+ disabledAlgorithms += ", ";
+ }
+ // RSASSA-PSS is not currently supported in SunPKCS11
+ // cryptographic provider
+ disabledAlgorithms += "RSASSA-PSS";
+ Security.setProperty("jdk.tls.disabledAlgorithms", disabledAlgorithms);
+ }
+
+ private static KeyStore readTestKeyStore() throws Exception {
+ File file = new File(System.getProperty("test.src", "."), "keystore");
+ InputStream in = new FileInputStream(file);
+ KeyStore ks = KeyStore.getInstance("JKS");
+ ks.load(in, "passphrase".toCharArray());
+ in.close();
+ return ks;
+ }
+}
Binary file test/jdk/sun/security/pkcs11/tls/tls12/cert8.db has changed
Binary file test/jdk/sun/security/pkcs11/tls/tls12/key3.db has changed
Binary file test/jdk/sun/security/pkcs11/tls/tls12/keystore has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/security/pkcs11/tls/tls12/nss.cfg Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,19 @@
+
+name = NSSKeyStore
+
+nssSecmodDirectory = ${pkcs11test.nss.db}
+
+nssLibraryDirectory = ${pkcs11test.nss.libdir}
+
+nssModule = fips
+
+# NSS needs CKA_NETSCAPE_DB for DSA and DH private keys
+# just put an arbitrary value in there to make it happy
+
+attributes(*,CKO_PRIVATE_KEY,CKK_DSA) = {
+ CKA_NETSCAPE_DB = 0h00
+}
+
+attributes(*,CKO_PRIVATE_KEY,CKK_DH) = {
+ CKA_NETSCAPE_DB = 0h00
+}
Binary file test/jdk/sun/security/pkcs11/tls/tls12/secmod.db has changed
--- a/test/jdk/sun/security/tools/jarsigner/warnings/NoTimestampTest.java Thu Mar 21 08:41:10 2019 +0000
+++ b/test/jdk/sun/security/tools/jarsigner/warnings/NoTimestampTest.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@
import java.security.cert.X509Certificate;
import java.util.Date;
import java.util.Locale;
+import java.util.TimeZone;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.util.JarUtils;
@@ -46,6 +47,7 @@
* and checks that proper warnings are shown.
*/
public static void main(String[] args) throws Throwable {
+
Locale reservedLocale = Locale.getDefault();
Locale.setDefault(Locale.US);
@@ -61,6 +63,9 @@
private void start() throws Throwable {
String timezone = System.getProperty("user.timezone");
System.out.println(String.format("Timezone = %s", timezone));
+ if (timezone != null) {
+ TimeZone.setDefault(TimeZone.getTimeZone(timezone));
+ }
// create a jar file that contains one class file
Utils.createFiles(FIRST_FILE);
@@ -73,10 +78,11 @@
"-validity", Integer.toString(VALIDITY));
Date expirationDate = getCertExpirationDate();
+ System.out.println("Cert expiration: " + expirationDate);
// sign jar file
OutputAnalyzer analyzer = jarsigner(
- "-J-Duser.timezone=" + timezone,
+ userTimezoneOpt(timezone),
"-keystore", KEYSTORE,
"-storepass", PASSWORD,
"-keypass", PASSWORD,
@@ -90,7 +96,7 @@
// verify signed jar
analyzer = jarsigner(
- "-J-Duser.timezone=" + timezone,
+ userTimezoneOpt(timezone),
"-verify",
"-keystore", KEYSTORE,
"-storepass", PASSWORD,
@@ -103,7 +109,7 @@
// verify signed jar in strict mode
analyzer = jarsigner(
- "-J-Duser.timezone=" + timezone,
+ userTimezoneOpt(timezone),
"-verify",
"-strict",
"-keystore", KEYSTORE,
@@ -117,6 +123,10 @@
System.out.println("Test passed");
}
+ private static String userTimezoneOpt(String timezone) {
+ return timezone == null ? null : "-J-Duser.timezone=" + timezone;
+ }
+
private static Date getCertExpirationDate() throws Exception {
KeyStore ks = KeyStore.getInstance("JKS");
try (InputStream in = new FileInputStream(KEYSTORE)) {
--- a/test/jdk/sun/security/tools/jarsigner/warnings/Test.java Thu Mar 21 08:41:10 2019 +0000
+++ b/test/jdk/sun/security/tools/jarsigner/warnings/Test.java Thu Mar 21 18:04:01 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -21,12 +21,13 @@
* questions.
*/
-import jdk.test.lib.process.OutputAnalyzer;
-import jdk.test.lib.process.ProcessTools;
-
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.stream.Collectors;
+
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
/**
* Base class.
@@ -259,7 +260,9 @@
cmd.add(tool);
cmd.add("-J-Duser.language=en");
cmd.add("-J-Duser.country=US");
- cmd.addAll(Arrays.asList(args));
+ cmd.addAll(Arrays.asList(args).stream().filter(arg -> {
+ return arg != null && !arg.isEmpty();
+ }).collect(Collectors.toList()));
return ProcessTools.executeCommand(cmd.toArray(new String[cmd.size()]));
}
}
--- a/test/langtools/jdk/javadoc/doclet/MetaTag/MetaTag.java Thu Mar 21 08:41:10 2019 +0000
+++ b/test/langtools/jdk/javadoc/doclet/MetaTag/MetaTag.java Thu Mar 21 18:04:01 2019 +0000
@@ -93,14 +93,19 @@
"<meta name=\"keywords\" content=\"Overview, Sample Packages\">");
// NOTE: Hopefully, this regression test is not run at midnight. If the output
- // was generated yesterday and this test is run today, the test will fail.
- checkOutput("overview-summary.html", found,
- "<meta name=\"" + metaNameDate + "\" content=\"" + date() + "\">");
+ // was generated yesterday and this test is run today, this check could fail ...
+ // so make sure the date has not changed since the test started
+ String date = date();
+ if (date.equals(startDate)) {
+ checkOutput("overview-summary.html", found,
+ "<meta name=\"" + metaNameDate + "\" content=\"" + date + "\">");
+ }
}
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
+ private static final String startDate = date();
- String date() {
+ static String date() {
return dateFormat.format(new Date());
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testAutoLoadTaglets/TestAutoLoadTaglets.java Thu Mar 21 18:04:01 2019 +0000
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8219958
+ * @summary Automatically load taglets from a jar file
+ * @library /tools/lib ../../lib
+ * @modules
+ * jdk.javadoc/jdk.javadoc.internal.tool
+ * jdk.compiler/com.sun.tools.javac.api
+ * jdk.compiler/com.sun.tools.javac.main
+ * @build javadoc.tester.* toolbox.ToolBox builder.ClassBuilder toolbox.JarTask
+ * @run main/othervm TestAutoLoadTaglets
+ */
+
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import builder.ClassBuilder;
+import toolbox.JarTask;
+import toolbox.JavacTask;
+import toolbox.ToolBox;
+
+import javadoc.tester.JavadocTester;
+
+public class TestAutoLoadTaglets extends JavadocTester {
+
+ final ToolBox tb;
+
+ public static void main(String... args) throws Exception {
+ TestAutoLoadTaglets tester = new TestAutoLoadTaglets();
+ tester.runTests(m -> new Object[]{Paths.get(m.getName())});
+ }
+
+ TestAutoLoadTaglets() {
+ tb = new ToolBox();
+ }
+
+ @Test
+ public void test(Path base) throws Exception {
+ Path srcDir = base.resolve("src");
+ Path outDir = base.resolve("out");
+
+ createTagletsJar(base, srcDir);
+
+ new ClassBuilder(tb, "pkg.A")
+ .setComments("test {@taglet1} and {@taglet2}")
+ .setModifiers("public", "class")
+ .write(srcDir);
+
+ javadoc("-d", outDir.toString(),
+ "-sourcepath", srcDir.toString(),
+ "-tagletpath", "taglets.jar",
+ "pkg");
+
+ checkExit(Exit.OK);
+
+ checkOutput("pkg/A.html", true,
+ "test user taglet taglet1 and user taglet taglet2");
+ }
+
+ private void createTagletsJar(Path base, Path srcDir) throws Exception {
+ Path classes = base.resolve("classes");
+ tb.createDirectories(classes);
+ createTaglets(srcDir);
+
+ new JavacTask(tb).files(srcDir.resolve("Taglet1.java"), srcDir.resolve("Taglet2.java"))
+ .outdir(classes).run();
+
+ Path services = classes.resolve("META-INF").resolve("services").resolve("jdk.javadoc.doclet.Taglet");
+ tb.writeFile(services,
+ "Taglet1\n"
+ + "Taglet2");
+
+ new JarTask(tb, srcDir).run("cf", "taglets.jar", "-C", classes.toString(), ".");
+ }
+
+ private void createTaglets(Path srcDir) throws Exception {
+ for (int i = 1; i < 3; i++) {
+ tb.writeJavaFiles(srcDir,
+ "import com.sun.source.doctree.DocTree;\n"
+ + "import jdk.javadoc.doclet.Taglet;\n"
+ + "import javax.lang.model.element.Element;\n"
+ + "import java.util.List;\n"
+ + "import java.util.Set;\n"
+ + "public class Taglet" + i + " implements Taglet {\n"
+ + " @Override\n"
+ + " public Set<Location> getAllowedLocations() {\n"
+ + " return null;\n"
+ + " }\n"
+ + " @Override\n"
+ + " public boolean isInlineTag() {\n"
+ + " return true;\n"
+ + " }\n"
+ + " @Override\n"
+ + " public String getName() {\n"
+ + " return \"taglet" + i + "\";\n"
+ + " }\n"
+ + " @Override\n"
+ + " public String toString(List<? extends DocTree> tags, Element "
+ + "element) {\n"
+ + " return \"user taglet taglet" + i + "\";\n"
+ + " }\n"
+ + "}\n");
+ }
+ }
+
+}