TypeCode objects are invoked.
*
* @return the singleton ORB
+ *
+ * @implNote
+ * When configured via the system property, or orb.properties,
+ * the system-wide singleton ORB is located via the
+ * system class loader.
*/
public static synchronized ORB init() {
if (singleton == null) {
@@ -354,6 +358,10 @@ abstract public class ORB {
* method; may be null
* @param props application-specific properties; may be null
* @return the newly-created ORB instance
+ *
+ * @implNote
+ * When configured via the system property, or orb.properties,
+ * the ORB is located via the thread context class loader.
*/
public static ORB init(String[] args, Properties props) {
//
@@ -392,6 +400,10 @@ abstract public class ORB {
* @param app the applet; may be null
* @param props applet-specific properties; may be null
* @return the newly-created ORB instance
+ *
+ * @implNote
+ * When configured via the system property, or orb.properties,
+ * the ORB is located via the thread context class loader.
*/
public static ORB init(Applet app, Properties props) {
String className;
diff --git a/hotspot/.hgtags b/hotspot/.hgtags
index 4d511d872c6..ec88eae37e7 100644
--- a/hotspot/.hgtags
+++ b/hotspot/.hgtags
@@ -441,3 +441,4 @@ af46576a8d7cb4003028b8ee8bf408cfe227315b jdk9-b32
464ab653fbb17eb518d8ef60f8df301de7ef00d0 jdk9-b36
b1c2dd843f247a1db19e1e85eb62ca405f72dc26 jdk9-b37
c363a8b87e477ee45d6d3cb2a36cb365141bc596 jdk9-b38
+9cb75e5e394827ccbaf2e15524108a412dc4ddc5 jdk9-b39
diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/CodeCacheSweeperThread.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/CodeCacheSweeperThread.java
new file mode 100644
index 00000000000..72877516b65
--- /dev/null
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/CodeCacheSweeperThread.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2000, 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.
+ *
+ */
+
+package sun.jvm.hotspot.runtime;
+
+import java.io.*;
+import java.util.*;
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.types.*;
+
+public class CodeCacheSweeperThread extends JavaThread {
+ public CodeCacheSweeperThread(Address addr) {
+ super(addr);
+ }
+
+ public boolean isJavaThread() { return false; }
+ public boolean isHiddenFromExternalView() { return true; }
+ public boolean isCodeCacheSweeperThread() { return true; }
+
+}
diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/JavaThread.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/JavaThread.java
index 926c11c4bad..a6f04042184 100644
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/JavaThread.java
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/JavaThread.java
@@ -118,9 +118,10 @@ public class JavaThread extends Thread {
return VM.getVM().getThreads().createJavaThreadWrapper(threadAddr);
}
- /** NOTE: for convenience, this differs in definition from the
- underlying VM. Only "pure" JavaThreads return true;
- CompilerThreads and JVMDIDebuggerThreads return false. FIXME:
+ /** NOTE: for convenience, this differs in definition from the underlying VM.
+ Only "pure" JavaThreads return true; CompilerThreads, the CodeCacheSweeperThread,
+ JVMDIDebuggerThreads return false.
+ FIXME:
consider encapsulating platform-specific functionality in an
object instead of using inheritance (which is the primary reason
we can't traverse CompilerThreads, etc; didn't want to have, for
diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/Thread.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/Thread.java
index 03c426ba84a..5b47b2a40e2 100644
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/Thread.java
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/Thread.java
@@ -111,14 +111,15 @@ public class Thread extends VMObject {
return allocatedBytesField.getValue(addr);
}
- public boolean isVMThread() { return false; }
- public boolean isJavaThread() { return false; }
- public boolean isCompilerThread() { return false; }
- public boolean isHiddenFromExternalView() { return false; }
- public boolean isJvmtiAgentThread() { return false; }
- public boolean isWatcherThread() { return false; }
+ public boolean isVMThread() { return false; }
+ public boolean isJavaThread() { return false; }
+ public boolean isCompilerThread() { return false; }
+ public boolean isCodeCacheSweeperThread() { return false; }
+ public boolean isHiddenFromExternalView() { return false; }
+ public boolean isJvmtiAgentThread() { return false; }
+ public boolean isWatcherThread() { return false; }
public boolean isConcurrentMarkSweepThread() { return false; }
- public boolean isServiceThread() { return false; }
+ public boolean isServiceThread() { return false; }
/** Memory operations */
public void oopsDo(AddressVisitor oopVisitor) {
diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/Threads.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/Threads.java
index b4b5903d139..3b6a53c5302 100644
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/Threads.java
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/Threads.java
@@ -120,6 +120,7 @@ public class Threads {
virtualConstructor.addMapping("JavaThread", JavaThread.class);
if (!VM.getVM().isCore()) {
virtualConstructor.addMapping("CompilerThread", CompilerThread.class);
+ virtualConstructor.addMapping("CodeCacheSweeperThread", CodeCacheSweeperThread.class);
}
// for now, use JavaThread itself. fix it later with appropriate class if needed
virtualConstructor.addMapping("SurrogateLockerThread", JavaThread.class);
@@ -164,7 +165,7 @@ public class Threads {
return thread;
} catch (Exception e) {
throw new RuntimeException("Unable to deduce type of thread from address " + threadAddr +
- " (expected type JavaThread, CompilerThread, ServiceThread, JvmtiAgentThread, or SurrogateLockerThread)", e);
+ " (expected type JavaThread, CompilerThread, ServiceThread, JvmtiAgentThread, SurrogateLockerThread, or CodeCacheSweeperThread)", e);
}
}
@@ -201,7 +202,7 @@ public class Threads {
public List getPendingThreads(ObjectMonitor monitor) {
List pendingThreads = new ArrayList();
for (JavaThread thread = first(); thread != null; thread = thread.next()) {
- if (thread.isCompilerThread()) {
+ if (thread.isCompilerThread() || thread.isCodeCacheSweeperThread()) {
continue;
}
ObjectMonitor pending = thread.getCurrentPendingMonitor();
diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/soql/sa.js b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/soql/sa.js
index 14a8e9aa137..58515933a3e 100644
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/soql/sa.js
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/soql/sa.js
@@ -836,6 +836,7 @@ vmType2Class["InterpreterCodelet"] = sapkg.interpreter.InterpreterCodelet;
// Java Threads
vmType2Class["JavaThread"] = sapkg.runtime.JavaThread;
vmType2Class["CompilerThread"] = sapkg.runtime.CompilerThread;
+vmType2Class["CodeCacheSweeperThread"] = sapkg.runtime.CodeCacheSweeperThread;
vmType2Class["SurrogateLockerThread"] = sapkg.runtime.JavaThread;
vmType2Class["DebuggerThread"] = sapkg.runtime.DebuggerThread;
diff --git a/hotspot/make/solaris/makefiles/vm.make b/hotspot/make/solaris/makefiles/vm.make
index 59f2b575642..da906bcfad8 100644
--- a/hotspot/make/solaris/makefiles/vm.make
+++ b/hotspot/make/solaris/makefiles/vm.make
@@ -143,7 +143,7 @@ else
LIBS += -lsocket -lsched -ldl $(LIBM) -lthread -lc -ldemangle
endif # sparcWorks
-LIBS += -lkstat -lpicl
+LIBS += -lkstat
# By default, link the *.o into the library, not the executable.
LINK_INTO$(LINK_INTO) = LIBJVM
diff --git a/hotspot/make/windows/makefiles/compile.make b/hotspot/make/windows/makefiles/compile.make
index a4d1c0d4c3e..8523bfd2eb6 100644
--- a/hotspot/make/windows/makefiles/compile.make
+++ b/hotspot/make/windows/makefiles/compile.make
@@ -158,7 +158,7 @@ LD=link.exe
!endif
LD_FLAGS= $(LD_FLAGS) kernel32.lib user32.lib gdi32.lib winspool.lib \
comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib \
- uuid.lib Wsock32.lib winmm.lib /nologo /machine:$(MACHINE) /opt:REF \
+ uuid.lib Wsock32.lib winmm.lib version.lib /nologo /machine:$(MACHINE) /opt:REF \
/opt:ICF,8
!if "$(ENABLE_FULL_DEBUG_SYMBOLS)" == "1"
LD_FLAGS= $(LD_FLAGS) /map /debug
diff --git a/hotspot/src/cpu/sparc/vm/interpreterRT_sparc.cpp b/hotspot/src/cpu/sparc/vm/interpreterRT_sparc.cpp
index 8cbe422a4af..0e1d6c992cd 100644
--- a/hotspot/src/cpu/sparc/vm/interpreterRT_sparc.cpp
+++ b/hotspot/src/cpu/sparc/vm/interpreterRT_sparc.cpp
@@ -237,7 +237,7 @@ IRT_ENTRY(address, InterpreterRuntime::slow_signature_handler(
// handle arguments
// Warning: We use reg arg slot 00 temporarily to return the RegArgSignature
// back to the code that pops the arguments into the CPU registers
- SlowSignatureHandler(m, (address)from, m->is_static() ? to+2 : to+1, to).iterate(UCONST64(-1));
+ SlowSignatureHandler(m, (address)from, m->is_static() ? to+2 : to+1, to).iterate((uint64_t)CONST64(-1));
// return result handler
return Interpreter::result_handler(m->result_type());
IRT_END
diff --git a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp
index 62bb56fe97f..6235c90df13 100644
--- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp
@@ -60,10 +60,10 @@ static jlong* double_quadword(jlong *adr, jlong lo, jlong hi) {
static jlong fp_signmask_pool[(4+1)*2]; // 4*128bits(data) + 128bits(alignment)
// Static initialization during VM startup.
-static jlong *float_signmask_pool = double_quadword(&fp_signmask_pool[1*2], CONST64(0x7FFFFFFF7FFFFFFF), CONST64(0x7FFFFFFF7FFFFFFF));
-static jlong *double_signmask_pool = double_quadword(&fp_signmask_pool[2*2], CONST64(0x7FFFFFFFFFFFFFFF), CONST64(0x7FFFFFFFFFFFFFFF));
-static jlong *float_signflip_pool = double_quadword(&fp_signmask_pool[3*2], CONST64(0x8000000080000000), CONST64(0x8000000080000000));
-static jlong *double_signflip_pool = double_quadword(&fp_signmask_pool[4*2], CONST64(0x8000000000000000), CONST64(0x8000000000000000));
+static jlong *float_signmask_pool = double_quadword(&fp_signmask_pool[1*2], CONST64(0x7FFFFFFF7FFFFFFF), CONST64(0x7FFFFFFF7FFFFFFF));
+static jlong *double_signmask_pool = double_quadword(&fp_signmask_pool[2*2], CONST64(0x7FFFFFFFFFFFFFFF), CONST64(0x7FFFFFFFFFFFFFFF));
+static jlong *float_signflip_pool = double_quadword(&fp_signmask_pool[3*2], (jlong)UCONST64(0x8000000080000000), (jlong)UCONST64(0x8000000080000000));
+static jlong *double_signflip_pool = double_quadword(&fp_signmask_pool[4*2], (jlong)UCONST64(0x8000000000000000), (jlong)UCONST64(0x8000000000000000));
diff --git a/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp b/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp
index 580964a7cd9..a0d54665375 100644
--- a/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp
@@ -1597,7 +1597,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
__ movl(rdx, 0x80000000);
__ xorl(rax, rax);
#else
- __ mov64(rax, CONST64(0x8000000000000000));
+ __ mov64(rax, UCONST64(0x8000000000000000));
#endif // _LP64
__ jmp(do_return);
diff --git a/hotspot/src/cpu/x86/vm/interpreterRT_x86_32.cpp b/hotspot/src/cpu/x86/vm/interpreterRT_x86_32.cpp
index eb66640c338..0e68dd011d3 100644
--- a/hotspot/src/cpu/x86/vm/interpreterRT_x86_32.cpp
+++ b/hotspot/src/cpu/x86/vm/interpreterRT_x86_32.cpp
@@ -135,7 +135,7 @@ IRT_ENTRY(address, InterpreterRuntime::slow_signature_handler(JavaThread* thread
methodHandle m(thread, (Method*)method);
assert(m->is_native(), "sanity check");
// handle arguments
- SlowSignatureHandler(m, (address)from, to + 1).iterate(UCONST64(-1));
+ SlowSignatureHandler(m, (address)from, to + 1).iterate((uint64_t)CONST64(-1));
// return result handler
return Interpreter::result_handler(m->result_type());
IRT_END
diff --git a/hotspot/src/cpu/x86/vm/interpreterRT_x86_64.cpp b/hotspot/src/cpu/x86/vm/interpreterRT_x86_64.cpp
index 959ed6e3208..40cc9d71aa7 100644
--- a/hotspot/src/cpu/x86/vm/interpreterRT_x86_64.cpp
+++ b/hotspot/src/cpu/x86/vm/interpreterRT_x86_64.cpp
@@ -487,7 +487,7 @@ IRT_ENTRY(address,
assert(m->is_native(), "sanity check");
// handle arguments
- SlowSignatureHandler(m, (address)from, to + 1).iterate(UCONST64(-1));
+ SlowSignatureHandler(m, (address)from, to + 1).iterate((uint64_t)CONST64(-1));
// return result handler
return Interpreter::result_handler(m->result_type());
diff --git a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp
index e73f93c705f..8d575c2d4bd 100644
--- a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp
@@ -865,14 +865,19 @@ void VM_Version::get_processor_features() {
if (supports_bmi1()) {
// tzcnt does not require VEX prefix
if (FLAG_IS_DEFAULT(UseCountTrailingZerosInstruction)) {
- UseCountTrailingZerosInstruction = true;
+ if (!UseBMI1Instructions && !FLAG_IS_DEFAULT(UseBMI1Instructions)) {
+ // Don't use tzcnt if BMI1 is switched off on command line.
+ UseCountTrailingZerosInstruction = false;
+ } else {
+ UseCountTrailingZerosInstruction = true;
+ }
}
} else if (UseCountTrailingZerosInstruction) {
warning("tzcnt instruction is not available on this CPU");
FLAG_SET_DEFAULT(UseCountTrailingZerosInstruction, false);
}
- // BMI instructions use an encoding with VEX prefix.
+ // BMI instructions (except tzcnt) use an encoding with VEX prefix.
// VEX prefix is generated only when AVX > 0.
if (supports_bmi1() && supports_avx()) {
if (FLAG_IS_DEFAULT(UseBMI1Instructions)) {
diff --git a/hotspot/src/cpu/zero/vm/interpreterRT_zero.cpp b/hotspot/src/cpu/zero/vm/interpreterRT_zero.cpp
index e23e3eaa93b..8fb45375262 100644
--- a/hotspot/src/cpu/zero/vm/interpreterRT_zero.cpp
+++ b/hotspot/src/cpu/zero/vm/interpreterRT_zero.cpp
@@ -155,7 +155,7 @@ IRT_ENTRY(address,
intptr_t *buf = (intptr_t *) stack->alloc(required_words * wordSize);
SlowSignatureHandlerGenerator sshg(methodHandle(thread, method), buf);
- sshg.generate(UCONST64(-1));
+ sshg.generate((uint64_t)CONST64(-1));
SignatureHandler *handler = sshg.handler();
handler->finalize();
diff --git a/hotspot/src/os/aix/vm/os_aix.cpp b/hotspot/src/os/aix/vm/os_aix.cpp
index bec34838920..d0765c4c1fc 100644
--- a/hotspot/src/os/aix/vm/os_aix.cpp
+++ b/hotspot/src/os/aix/vm/os_aix.cpp
@@ -1641,7 +1641,8 @@ void os::jvm_path(char *buf, jint buflen) {
char* rp = realpath((char *)dlinfo.dli_fname, buf);
assert(rp != NULL, "error in realpath(): maybe the 'path' argument is too long?");
- strcpy(saved_jvm_path, buf);
+ strncpy(saved_jvm_path, buf, sizeof(saved_jvm_path));
+ saved_jvm_path[sizeof(saved_jvm_path) - 1] = '\0';
}
void os::print_jni_name_prefix_on(outputStream* st, int args_size) {
@@ -3829,11 +3830,6 @@ jint os::init_2(void) {
return JNI_OK;
}
-// this is called at the end of vm_initialization
-void os::init_3(void) {
- return;
-}
-
// Mark the polling page as unreadable
void os::make_polling_page_unreadable(void) {
if (!guard_memory((char*)_polling_page, Aix::page_size())) {
@@ -4137,15 +4133,6 @@ int os::available(int fd, jlong *bytes) {
return 1;
}
-int os::socket_available(int fd, jint *pbytes) {
- // Linux doc says EINTR not returned, unlike Solaris
- int ret = ::ioctl(fd, FIONREAD, pbytes);
-
- //%% note ioctl can return 0 when successful, JVM_SocketAvailable
- // is expected to return 0 on failure and 1 on success to the jdk.
- return (ret < 0) ? 0 : 1;
-}
-
// Map a block of memory.
char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset,
char *addr, size_t bytes, bool read_only,
diff --git a/hotspot/src/os/aix/vm/os_aix.inline.hpp b/hotspot/src/os/aix/vm/os_aix.inline.hpp
index bb3232bfbc7..5602342b4ff 100644
--- a/hotspot/src/os/aix/vm/os_aix.inline.hpp
+++ b/hotspot/src/os/aix/vm/os_aix.inline.hpp
@@ -178,92 +178,14 @@ inline int os::raw_send(int fd, char* buf, size_t nBytes, uint flags) {
return os::send(fd, buf, nBytes, flags);
}
-inline int os::timeout(int fd, long timeout) {
- julong prevtime,newtime;
- struct timeval t;
-
- gettimeofday(&t, NULL);
- prevtime = ((julong)t.tv_sec * 1000) + t.tv_usec / 1000;
-
- for(;;) {
- struct pollfd pfd;
-
- pfd.fd = fd;
- pfd.events = POLLIN | POLLERR;
-
- int res = ::poll(&pfd, 1, timeout);
-
- if (res == OS_ERR && errno == EINTR) {
-
- // On Linux any value < 0 means "forever"
-
- if(timeout >= 0) {
- gettimeofday(&t, NULL);
- newtime = ((julong)t.tv_sec * 1000) + t.tv_usec / 1000;
- timeout -= newtime - prevtime;
- if(timeout <= 0)
- return OS_OK;
- prevtime = newtime;
- }
- } else
- return res;
- }
-}
-
-inline int os::listen(int fd, int count) {
- return ::listen(fd, count);
-}
-
inline int os::connect(int fd, struct sockaddr* him, socklen_t len) {
RESTARTABLE_RETURN_INT(::connect(fd, him, len));
}
-inline int os::accept(int fd, struct sockaddr* him, socklen_t* len) {
- // Linux doc says this can't return EINTR, unlike accept() on Solaris.
- // But see attachListener_linux.cpp, LinuxAttachListener::dequeue().
- return (int)::accept(fd, him, len);
-}
-
-inline int os::recvfrom(int fd, char* buf, size_t nBytes, uint flags,
- sockaddr* from, socklen_t* fromlen) {
- RESTARTABLE_RETURN_INT((int)::recvfrom(fd, buf, nBytes, flags, from, fromlen));
-}
-
-inline int os::sendto(int fd, char* buf, size_t len, uint flags,
- struct sockaddr* to, socklen_t tolen) {
- RESTARTABLE_RETURN_INT((int)::sendto(fd, buf, len, flags, to, tolen));
-}
-
-inline int os::socket_shutdown(int fd, int howto) {
- return ::shutdown(fd, howto);
-}
-
-inline int os::bind(int fd, struct sockaddr* him, socklen_t len) {
- return ::bind(fd, him, len);
-}
-
-inline int os::get_sock_name(int fd, struct sockaddr* him, socklen_t* len) {
- return ::getsockname(fd, him, len);
-}
-
-inline int os::get_host_name(char* name, int namelen) {
- return ::gethostname(name, namelen);
-}
-
inline struct hostent* os::get_host_by_name(char* name) {
return ::gethostbyname(name);
}
-inline int os::get_sock_opt(int fd, int level, int optname,
- char* optval, socklen_t* optlen) {
- return ::getsockopt(fd, level, optname, optval, optlen);
-}
-
-inline int os::set_sock_opt(int fd, int level, int optname,
- const char* optval, socklen_t optlen) {
- return ::setsockopt(fd, level, optname, optval, optlen);
-}
-
inline bool os::supports_monotonic_clock() {
// mread_real_time() is monotonic on AIX (see os::javaTimeNanos() comments)
return true;
diff --git a/hotspot/src/os/aix/vm/perfMemory_aix.cpp b/hotspot/src/os/aix/vm/perfMemory_aix.cpp
index 36644f0f679..8850fe705e2 100644
--- a/hotspot/src/os/aix/vm/perfMemory_aix.cpp
+++ b/hotspot/src/os/aix/vm/perfMemory_aix.cpp
@@ -506,6 +506,7 @@ static void cleanup_sharedmem_resources(const char* dirname) {
if (!is_directory_secure(dirname)) {
// the directory is not a secure directory
+ os::closedir(dirp);
return;
}
@@ -853,6 +854,9 @@ static void mmap_attach_shared(const char* user, int vmid, PerfMemory::PerfMemor
//
if (!is_directory_secure(dirname)) {
FREE_C_HEAP_ARRAY(char, dirname, mtInternal);
+ if (luser != user) {
+ FREE_C_HEAP_ARRAY(char, luser, mtInternal);
+ }
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"Process not found");
}
diff --git a/hotspot/src/os/bsd/vm/os_bsd.cpp b/hotspot/src/os/bsd/vm/os_bsd.cpp
index 95e026651ac..a42e3bf19ba 100644
--- a/hotspot/src/os/bsd/vm/os_bsd.cpp
+++ b/hotspot/src/os/bsd/vm/os_bsd.cpp
@@ -1875,6 +1875,7 @@ void os::jvm_path(char *buf, jint buflen) {
}
strncpy(saved_jvm_path, buf, MAXPATHLEN);
+ saved_jvm_path[MAXPATHLEN - 1] = '\0';
}
void os::print_jni_name_prefix_on(outputStream* st, int args_size) {
@@ -3635,9 +3636,6 @@ jint os::init_2(void) {
return JNI_OK;
}
-// this is called at the end of vm_initialization
-void os::init_3(void) { }
-
// Mark the polling page as unreadable
void os::make_polling_page_unreadable(void) {
if (!guard_memory((char*)_polling_page, Bsd::page_size())) {
@@ -3958,21 +3956,6 @@ int os::available(int fd, jlong *bytes) {
return 1;
}
-int os::socket_available(int fd, jint *pbytes) {
- if (fd < 0) {
- return OS_OK;
- }
-
- int ret;
-
- RESTARTABLE(::ioctl(fd, FIONREAD, pbytes), ret);
-
- //%% note ioctl can return 0 when successful, JVM_SocketAvailable
- // is expected to return 0 on failure and 1 on success to the jdk.
-
- return (ret == OS_ERR) ? 0 : 1;
-}
-
// Map a block of memory.
char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset,
char *addr, size_t bytes, bool read_only,
@@ -4133,7 +4116,18 @@ void os::pause() {
}
-// Refer to the comments in os_solaris.cpp park-unpark.
+// Refer to the comments in os_solaris.cpp park-unpark. The next two
+// comment paragraphs are worth repeating here:
+//
+// Assumption:
+// Only one parker can exist on an event, which is why we allocate
+// them per-thread. Multiple unparkers can coexist.
+//
+// _Event serves as a restricted-range semaphore.
+// -1 : thread is blocked, i.e. there is a waiter
+// 0 : neutral: thread is running or ready,
+// could have been signaled after a wait started
+// 1 : signaled - thread is running or ready
//
// Beware -- Some versions of NPTL embody a flaw where pthread_cond_timedwait() can
// hang indefinitely. For instance NPTL 0.60 on 2.4.21-4ELsmp is vulnerable.
@@ -4218,6 +4212,11 @@ static struct timespec* compute_abstime(struct timespec* abstime,
}
void os::PlatformEvent::park() { // AKA "down()"
+ // Transitions for _Event:
+ // -1 => -1 : illegal
+ // 1 => 0 : pass - return immediately
+ // 0 => -1 : block; then set _Event to 0 before returning
+
// Invariant: Only the thread associated with the Event/PlatformEvent
// may call park().
// TODO: assert that _Assoc != NULL or _Assoc == Self
@@ -4255,6 +4254,11 @@ void os::PlatformEvent::park() { // AKA "down()"
}
int os::PlatformEvent::park(jlong millis) {
+ // Transitions for _Event:
+ // -1 => -1 : illegal
+ // 1 => 0 : pass - return immediately
+ // 0 => -1 : block; then set _Event to 0 before returning
+
guarantee(_nParked == 0, "invariant");
int v;
@@ -4318,11 +4322,11 @@ int os::PlatformEvent::park(jlong millis) {
void os::PlatformEvent::unpark() {
// Transitions for _Event:
- // 0 :=> 1
- // 1 :=> 1
- // -1 :=> either 0 or 1; must signal target thread
- // That is, we can safely transition _Event from -1 to either
- // 0 or 1.
+ // 0 => 1 : just return
+ // 1 => 1 : just return
+ // -1 => either 0 or 1; must signal target thread
+ // That is, we can safely transition _Event from -1 to either
+ // 0 or 1.
// See also: "Semaphores in Plan 9" by Mullender & Cox
//
// Note: Forcing a transition from "-1" to "1" on an unpark() means
@@ -4345,15 +4349,16 @@ void os::PlatformEvent::unpark() {
status = pthread_mutex_unlock(_mutex);
assert_status(status == 0, status, "mutex_unlock");
if (AnyWaiters != 0) {
+ // Note that we signal() *after* dropping the lock for "immortal" Events.
+ // This is safe and avoids a common class of futile wakeups. In rare
+ // circumstances this can cause a thread to return prematurely from
+ // cond_{timed}wait() but the spurious wakeup is benign and the victim
+ // will simply re-test the condition and re-park itself.
+ // This provides particular benefit if the underlying platform does not
+ // provide wait morphing.
status = pthread_cond_signal(_cond);
assert_status(status == 0, status, "cond_signal");
}
-
- // Note that we signal() _after dropping the lock for "immortal" Events.
- // This is safe and avoids a common class of futile wakeups. In rare
- // circumstances this can cause a thread to return prematurely from
- // cond_{timed}wait() but the spurious wakeup is benign and the victim will
- // simply re-test the condition and re-park itself.
}
diff --git a/hotspot/src/os/bsd/vm/os_bsd.inline.hpp b/hotspot/src/os/bsd/vm/os_bsd.inline.hpp
index 1eafb9c76e9..3afb5c21a83 100644
--- a/hotspot/src/os/bsd/vm/os_bsd.inline.hpp
+++ b/hotspot/src/os/bsd/vm/os_bsd.inline.hpp
@@ -181,91 +181,14 @@ inline int os::raw_send(int fd, char* buf, size_t nBytes, uint flags) {
return os::send(fd, buf, nBytes, flags);
}
-inline int os::timeout(int fd, long timeout) {
- julong prevtime,newtime;
- struct timeval t;
-
- gettimeofday(&t, NULL);
- prevtime = ((julong)t.tv_sec * 1000) + t.tv_usec / 1000;
-
- for(;;) {
- struct pollfd pfd;
-
- pfd.fd = fd;
- pfd.events = POLLIN | POLLERR;
-
- int res = ::poll(&pfd, 1, timeout);
-
- if (res == OS_ERR && errno == EINTR) {
-
- // On Bsd any value < 0 means "forever"
-
- if(timeout >= 0) {
- gettimeofday(&t, NULL);
- newtime = ((julong)t.tv_sec * 1000) + t.tv_usec / 1000;
- timeout -= newtime - prevtime;
- if(timeout <= 0)
- return OS_OK;
- prevtime = newtime;
- }
- } else
- return res;
- }
-}
-
-inline int os::listen(int fd, int count) {
- return ::listen(fd, count);
-}
-
inline int os::connect(int fd, struct sockaddr* him, socklen_t len) {
RESTARTABLE_RETURN_INT(::connect(fd, him, len));
}
-inline int os::accept(int fd, struct sockaddr* him, socklen_t* len) {
- // At least OpenBSD and FreeBSD can return EINTR from accept.
- RESTARTABLE_RETURN_INT(::accept(fd, him, len));
-}
-
-inline int os::recvfrom(int fd, char* buf, size_t nBytes, uint flags,
- sockaddr* from, socklen_t* fromlen) {
- RESTARTABLE_RETURN_INT((int)::recvfrom(fd, buf, nBytes, flags, from, fromlen));
-}
-
-inline int os::sendto(int fd, char* buf, size_t len, uint flags,
- struct sockaddr *to, socklen_t tolen) {
- RESTARTABLE_RETURN_INT((int)::sendto(fd, buf, len, flags, to, tolen));
-}
-
-inline int os::socket_shutdown(int fd, int howto) {
- return ::shutdown(fd, howto);
-}
-
-inline int os::bind(int fd, struct sockaddr* him, socklen_t len) {
- return ::bind(fd, him, len);
-}
-
-inline int os::get_sock_name(int fd, struct sockaddr* him, socklen_t* len) {
- return ::getsockname(fd, him, len);
-}
-
-inline int os::get_host_name(char* name, int namelen) {
- return ::gethostname(name, namelen);
-}
-
inline struct hostent* os::get_host_by_name(char* name) {
return ::gethostbyname(name);
}
-inline int os::get_sock_opt(int fd, int level, int optname,
- char *optval, socklen_t* optlen) {
- return ::getsockopt(fd, level, optname, optval, optlen);
-}
-
-inline int os::set_sock_opt(int fd, int level, int optname,
- const char* optval, socklen_t optlen) {
- return ::setsockopt(fd, level, optname, optval, optlen);
-}
-
inline bool os::supports_monotonic_clock() {
#ifdef __APPLE__
return true;
diff --git a/hotspot/src/os/bsd/vm/perfMemory_bsd.cpp b/hotspot/src/os/bsd/vm/perfMemory_bsd.cpp
index 631366e2944..5cd6cf4e3dd 100644
--- a/hotspot/src/os/bsd/vm/perfMemory_bsd.cpp
+++ b/hotspot/src/os/bsd/vm/perfMemory_bsd.cpp
@@ -506,6 +506,7 @@ static void cleanup_sharedmem_resources(const char* dirname) {
if (!is_directory_secure(dirname)) {
// the directory is not a secure directory
+ os::closedir(dirp);
return;
}
@@ -872,6 +873,9 @@ static void mmap_attach_shared(const char* user, int vmid, PerfMemory::PerfMemor
//
if (!is_directory_secure(dirname)) {
FREE_C_HEAP_ARRAY(char, dirname, mtInternal);
+ if (luser != user) {
+ FREE_C_HEAP_ARRAY(char, luser, mtInternal);
+ }
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"Process not found");
}
diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp
index 3d82d976f37..202e3612171 100644
--- a/hotspot/src/os/linux/vm/os_linux.cpp
+++ b/hotspot/src/os/linux/vm/os_linux.cpp
@@ -163,35 +163,6 @@ static pthread_mutex_t dl_mutex;
// Declarations
static void unpackTime(timespec* absTime, bool isAbsolute, jlong time);
-#ifdef JAVASE_EMBEDDED
-class MemNotifyThread: public Thread {
- friend class VMStructs;
- public:
- virtual void run();
-
- private:
- static MemNotifyThread* _memnotify_thread;
- int _fd;
-
- public:
-
- // Constructor
- MemNotifyThread(int fd);
-
- // Tester
- bool is_memnotify_thread() const { return true; }
-
- // Printing
- char* name() const { return (char*)"Linux MemNotify Thread"; }
-
- // Returns the single instance of the MemNotifyThread
- static MemNotifyThread* memnotify_thread() { return _memnotify_thread; }
-
- // Create and start the single instance of MemNotifyThread
- static void start();
-};
-#endif // JAVASE_EMBEDDED
-
// utility functions
static int SR_initialize();
@@ -384,7 +355,10 @@ void os::init_system_properties_values() {
// Found the full path to libjvm.so.
// Now cut the path to The following is the source of the "task.xml" resource:
+The following is the source of the "tasks.xml" resource:
+The following is the outer XML file
+The following is the source of the "data.xml" resource:
+The following is the source of the "tasks.xml" resource:
+The following is the source of the "tasks.xml" resource:
+The following is the source of the "data.xml" resource:
+The following is the source of the "task.xml" resource:
+The following is the source of the "tasks.xml" resource:
+The following is the outer XML file
+The following is the source of the "data.xml" resource:
+The following is the source of the "tasks.xml" resource:
+This is an AUTOMATIC test, simply wait for completion
+ + + + diff --git a/jdk/test/java/awt/Frame/DisposeStressTest/DisposeStressTest.java b/jdk/test/java/awt/Frame/DisposeStressTest/DisposeStressTest.java new file mode 100644 index 00000000000..7e13bc3e3ba --- /dev/null +++ b/jdk/test/java/awt/Frame/DisposeStressTest/DisposeStressTest.java @@ -0,0 +1,247 @@ +/* + * 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. + */ + + +/* + test + @bug 4051487 4145670 8062021 + @summary Tests that disposing of an empty Frame or a Frame with a MenuBar + while it is being created does not crash the VM. + @author dpm area=Threads + @run applet/timeout=7200 DisposeStressTest.html +*/ + +// Note there is no @ in front of test above. This is so that the +// harness will not mistake this file as a test file. It should +// only see the html file as a test file. (the harness runs all +// valid test files, so it would run this test twice if this file +// were valid as well as the html file.) +// Also, note the area= after Your Name in the author tag. Here, you +// should put which functional area the test falls in. See the +// AWT-core home page -> test areas and/or -> AWT team for a list of +// areas. +// Note also the 'DisposeStressTest.html' in the run tag. This should +// be changed to the name of the test. + + +/** + * DisposeStressTest.java + * + * summary: + */ + +import java.applet.Applet; +import java.awt.*; + + +//Automated tests should run as applet tests if possible because they +// get their environments cleaned up, including AWT threads, any +// test created threads, and any system resources used by the test +// such as file descriptors. (This is normally not a problem as +// main tests usually run in a separate VM, however on some platforms +// such as the Mac, separate VMs are not possible and non-applet +// tests will cause problems). Also, you don't have to worry about +// synchronisation stuff in Applet tests they way you do in main +// tests... + + +public class DisposeStressTest extends Applet + { + //Declare things used in the test, like buttons and labels here + + public void init() + { + //Create instructions for the user here, as well as set up + // the environment -- set the layout manager, add buttons, + // etc. + + this.setLayout (new BorderLayout ()); + + String[] instructions = + { + "This is an AUTOMATIC test", + "simply wait until it is done" + }; + Sysout.createDialog( ); + Sysout.printInstructions( instructions ); + + }//End init() + + public void start () + { + for (int i = 0; i < 1000; i++) { + Frame f = new Frame(); + f.setBounds(10, 10, 10, 10); + f.show(); + f.dispose(); + + Frame f2 = new Frame(); + f2.setBounds(10, 10, 100, 100); + MenuBar bar = new MenuBar(); + Menu menu = new Menu(); + menu.add(new MenuItem("foo")); + bar.add(menu); + f2.setMenuBar(bar); + f2.show(); + f2.dispose(); + } + }// start() + + }// class DisposeStressTest + + +/**************************************************** + Standard Test Machinery + DO NOT modify anything below -- it's a standard + chunk of code whose purpose is to make user + interaction uniform, and thereby make it simpler + to read and understand someone else's test. + ****************************************************/ + +/** + This is part of the standard test machinery. + It creates a dialog (with the instructions), and is the interface + for sending text messages to the user. + To print the instructions, send an array of strings to Sysout.createDialog + WithInstructions method. Put one line of instructions per array entry. + To display a message for the tester to see, simply call Sysout.println + with the string to be displayed. + This mimics System.out.println but works within the test harness as well + as standalone. + */ + +class Sysout + { + private static TestDialog dialog; + + public static void createDialogWithInstructions( String[] instructions ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + dialog.printInstructions( instructions ); + dialog.show(); + println( "Any messages for the tester will display here." ); + } + + public static void createDialog( ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + String[] defInstr = { "Instructions will appear here. ", "" } ; + dialog.printInstructions( defInstr ); + dialog.show(); + println( "Any messages for the tester will display here." ); + } + + + public static void printInstructions( String[] instructions ) + { + dialog.printInstructions( instructions ); + } + + + public static void println( String messageIn ) + { + dialog.displayMessage( messageIn ); + } + + }// Sysout class + +/** + This is part of the standard test machinery. It provides a place for the + test instructions to be displayed, and a place for interactive messages + to the user to be displayed. + To have the test instructions displayed, see Sysout. + To have a message to the user be displayed, see Sysout. + Do not call anything in this dialog directly. + */ +class TestDialog extends Dialog + { + + TextArea instructionsText; + TextArea messageText; + int maxStringLength = 80; + + //DO NOT call this directly, go through Sysout + public TestDialog( Frame frame, String name ) + { + super( frame, name ); + int scrollBoth = TextArea.SCROLLBARS_BOTH; + instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth ); + add( "North", instructionsText ); + + messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); + add("South", messageText); + + pack(); + + show(); + }// TestDialog() + + //DO NOT call this directly, go through Sysout + public void printInstructions( String[] instructions ) + { + //Clear out any current instructions + instructionsText.setText( "" ); + + //Go down array of instruction strings + + String printStr, remainingStr; + for( int i=0; i < instructions.length; i++ ) + { + //chop up each into pieces maxSringLength long + remainingStr = instructions[ i ]; + while( remainingStr.length() > 0 ) + { + //if longer than max then chop off first max chars to print + if( remainingStr.length() >= maxStringLength ) + { + //Try to chop on a word boundary + int posOfSpace = remainingStr. + lastIndexOf( ' ', maxStringLength - 1 ); + + if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; + + printStr = remainingStr.substring( 0, posOfSpace + 1 ); + remainingStr = remainingStr.substring( posOfSpace + 1 ); + } + //else just print + else + { + printStr = remainingStr; + remainingStr = ""; + } + + instructionsText.append( printStr + "\n" ); + + }// while + + }// for + + }//printInstructions() + + //DO NOT call this directly, go through Sysout + public void displayMessage( String messageIn ) + { + messageText.append( messageIn + "\n" ); + } + + }// TestDialog class diff --git a/jdk/test/java/awt/TrayIcon/SecurityCheck/NoPermissionTest/tray.policy b/jdk/test/java/awt/TrayIcon/SecurityCheck/NoPermissionTest/tray.policy new file mode 100644 index 00000000000..da9ee9c0c5c --- /dev/null +++ b/jdk/test/java/awt/TrayIcon/SecurityCheck/NoPermissionTest/tray.policy @@ -0,0 +1,3 @@ +//NoPermission Test +grant{ +}; diff --git a/jdk/test/java/awt/geom/AffineTransform/GetTypeOptimization.java b/jdk/test/java/awt/geom/AffineTransform/GetTypeOptimization.java new file mode 100644 index 00000000000..c26c14671ac --- /dev/null +++ b/jdk/test/java/awt/geom/AffineTransform/GetTypeOptimization.java @@ -0,0 +1,307 @@ +/* + * Copyright (c) 2002, 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 4418285 + * @summary Tests that transforms modified with degenerate operations + * continue to return their more optimal type from getType(). + * This test also confirms that isIdentity() returns the + * optimal value under all histories of modification. + * @run main GetTypeOptimization + */ + +import java.awt.geom.AffineTransform; +import java.util.Random; + +public class GetTypeOptimization { + static int TYPE_IDENTITY = AffineTransform.TYPE_IDENTITY; + static int TYPE_TRANSLATION = AffineTransform.TYPE_TRANSLATION; + static int TYPE_UNIFORM_SCALE = AffineTransform.TYPE_UNIFORM_SCALE; + static int TYPE_GENERAL_SCALE = AffineTransform.TYPE_GENERAL_SCALE; + static int TYPE_FLIP = AffineTransform.TYPE_FLIP; + static int TYPE_QUADRANT_ROTATION = AffineTransform.TYPE_QUADRANT_ROTATION; + static int TYPE_GENERAL_ROTATION = AffineTransform.TYPE_GENERAL_ROTATION; + static int TYPE_GENERAL_TRANSFORM = AffineTransform.TYPE_GENERAL_TRANSFORM; + + public static Random rand = new Random(); + + public static boolean verbose; + public static int numerrors; + + public static void main(String argv[]) { + verbose = (argv.length != 0); + + checkBug4418285(); + + checkAtType(new AffineTransform()); + checkAtType(AffineTransform.getTranslateInstance(0, 0)); + checkAtType(AffineTransform.getScaleInstance(1, 1)); + checkAtType(AffineTransform.getShearInstance(0, 0)); + checkAtType(AffineTransform.getRotateInstance(0)); + checkAtType(AffineTransform.getRotateInstance(0, 0, 0)); + for (int i = 90; i <= 360; i += 90) { + double angle = Math.toRadians(i); + checkAtType(AffineTransform.getRotateInstance(angle)); + checkAtType(AffineTransform.getRotateInstance(angle, 0, 0)); + } + + AffineTransform at = new AffineTransform(); + checkAtType(at); + + at.setToIdentity(); checkAtType(at); + at.setToTranslation(0.0, 0.0); checkAtType(at); + at.setToScale(1.0, 1.0); checkAtType(at); + at.setToShear(0.0, 0.0); checkAtType(at); + at.setToRotation(0); checkAtType(at); + at.setToRotation(0, 0, 0); checkAtType(at); + for (int i = 90; i <= 360; i += 90) { + double angle = Math.toRadians(i); + at.setToRotation(angle); checkAtType(at); + at.setToRotation(angle, 0, 0); checkAtType(at); + } + + at.setToIdentity(); at.scale(1, 1); checkAtType(at); + at.setToIdentity(); at.translate(0, 0); checkAtType(at); + at.setToIdentity(); at.shear(0, 0); checkAtType(at); + at.setToIdentity(); at.rotate(0); checkAtType(at); + for (int i = 90; i <= 360; i += 90) { + double angle = Math.toRadians(i); + at.setToIdentity(); at.rotate(angle); checkAtType(at); + at.setToIdentity(); at.rotate(angle, 0, 0); checkAtType(at); + } + + at.setToIdentity(); + for (int i = 0; i < 4; i++) { + at.rotate(Math.toRadians(90)); checkAtType(at); + } + + at.setToIdentity(); + at.scale(2, 2); checkAtType(at); + at.scale(.5, .5); checkAtType(at); + + for (int n = 1; n <= 3; n++) { + for (int i = 0; i < 500; i++) { + checkAtType(makeRandomTransform(n)); + } + } + if (numerrors != 0) { + if (!verbose) { + System.err.println("Rerun test with an argument for details"); + } + throw new RuntimeException(numerrors+" tests failed!"); + } + } + + public static void checkBug4418285() { + AffineTransform id = + new AffineTransform (); + AffineTransform translate0 = + AffineTransform.getTranslateInstance (0, 0); + if (id.isIdentity() != translate0.isIdentity() || + id.getType() != translate0.getType()) + { + numerrors++; + if (verbose) { + System.err.println("id= " + id + + ", isIdentity()=" + + id.isIdentity()); + System.err.println("translate0=" + translate0 + + ", isIdentity()=" + + translate0.isIdentity()); + System.err.println("equals=" + id.equals (translate0)); + System.err.println(); + } + } + } + + public static AffineTransform makeRandomTransform(int numops) { + AffineTransform at = new AffineTransform(); + while (--numops >= 0) { + switch (rand.nextInt(4)) { + case 0: + at.scale(rand.nextDouble() * 5 - 2.5, + rand.nextDouble() * 5 - 2.5); + break; + case 1: + at.shear(rand.nextDouble() * 5 - 2.5, + rand.nextDouble() * 5 - 2.5); + break; + case 2: + at.rotate(rand.nextDouble() * Math.PI * 2); + break; + case 3: + at.translate(rand.nextDouble() * 50 - 25, + rand.nextDouble() * 50 - 25); + break; + default: + throw new InternalError("bad case!"); + } + } + return at; + } + + public static void checkAtType(AffineTransform at) { + int reftype = getRefType(at); + boolean isident = isIdentity(at); + for (int i = 0; i < 5; i++) { + boolean atisident = at.isIdentity(); + int attype = at.getType(); + if (isident != atisident || reftype != attype) { + numerrors++; + if (verbose) { + System.err.println(at+".isIdentity() == "+atisident); + System.err.println(at+".getType() == "+attype); + System.err.println("should be "+isident+", "+reftype); + new Throwable().printStackTrace(); + System.err.println(); + } + break; + } + } + } + + public static boolean isIdentity(AffineTransform at) { + return (at.getScaleX() == 1 && + at.getScaleY() == 1 && + at.getShearX() == 0 && + at.getShearY() == 0 && + at.getTranslateX() == 0 && + at.getTranslateY() == 0); + + } + + public static int getRefType(AffineTransform at) { + double m00 = at.getScaleX(); + double m11 = at.getScaleY(); + double m01 = at.getShearX(); + double m10 = at.getShearY(); + if (m00 * m01 + m10 * m11 != 0) { + // Transformed unit vectors are not perpendicular... + return TYPE_GENERAL_TRANSFORM; + } + int type = ((at.getTranslateX() != 0 || at.getTranslateY() != 0) + ? TYPE_TRANSLATION : TYPE_IDENTITY); + boolean sgn0, sgn1; + if (m01 == 0 && m10 == 0) { + sgn0 = (m00 >= 0.0); + sgn1 = (m11 >= 0.0); + if (sgn0 == sgn1) { + if (sgn0) { + // Both scaling factors non-negative - simple scale + if (m00 != m11) { + type |= TYPE_GENERAL_SCALE; + } else if (m00 != 1.0) { + type |= TYPE_UNIFORM_SCALE; + } + } else { + // Both scaling factors negative - 180 degree rotation + type |= TYPE_QUADRANT_ROTATION; + if (m00 != m11) { + type |= TYPE_GENERAL_SCALE; + } else if (m00 != -1.0) { + type |= TYPE_UNIFORM_SCALE; + } + } + } else { + // Scaling factor signs different - flip about some axis + type |= TYPE_FLIP; + if (m00 != -m11) { + type |= TYPE_GENERAL_SCALE; + } else if (m00 != 1.0 && m00 != -1.0) { + type |= TYPE_UNIFORM_SCALE; + } + } + } else if (m00 == 0 && m11 == 0) { + sgn0 = (m01 >= 0.0); + sgn1 = (m10 >= 0.0); + if (sgn0 != sgn1) { + // Different signs - simple 90 degree rotation + if (m01 != -m10) { + type |= (TYPE_QUADRANT_ROTATION | TYPE_GENERAL_SCALE); + } else if (m01 != 1.0 && m01 != -1.0) { + type |= (TYPE_QUADRANT_ROTATION | TYPE_UNIFORM_SCALE); + } else { + type |= TYPE_QUADRANT_ROTATION; + } + } else { + // Same signs - 90 degree rotation plus an axis flip too + if (m01 == m10) { + if (m01 == 0) { + // All four m[01][01] elements are 0 + type |= TYPE_UNIFORM_SCALE; + } else { + // Note - shouldn't (1,1) be no scale at all? + type |= (TYPE_QUADRANT_ROTATION | + TYPE_FLIP | + TYPE_UNIFORM_SCALE); + } + } else { + type |= (TYPE_QUADRANT_ROTATION | + TYPE_FLIP | + TYPE_GENERAL_SCALE); + } + } + } else { + if (m00 * m11 >= 0.0) { + // sgn(m00) == sgn(m11) therefore sgn(m01) == -sgn(m10) + // This is the "unflipped" (right-handed) state + if (m00 != m11 || m01 != -m10) { + type |= (TYPE_GENERAL_ROTATION | TYPE_GENERAL_SCALE); + } else if (m00 == 0) { + // then m11 == 0 also + if (m01 == -m10) { + type |= (TYPE_QUADRANT_ROTATION | TYPE_UNIFORM_SCALE); + } else { + type |= (TYPE_QUADRANT_ROTATION | TYPE_GENERAL_SCALE); + } + } else if (m00 * m11 - m01 * m10 != 1.0) { + type |= (TYPE_GENERAL_ROTATION | TYPE_UNIFORM_SCALE); + } else { + type |= TYPE_GENERAL_ROTATION; + } + } else { + // sgn(m00) == -sgn(m11) therefore sgn(m01) == sgn(m10) + // This is the "flipped" (left-handed) state + if (m00 != -m11 || m01 != m10) { + type |= (TYPE_GENERAL_ROTATION | + TYPE_FLIP | + TYPE_GENERAL_SCALE); + } else if (m01 == 0) { + if (m00 == 1.0 || m00 == -1.0) { + type |= TYPE_FLIP; + } else { + type |= (TYPE_FLIP | TYPE_UNIFORM_SCALE); + } + } else if (m00 * m11 - m01 * m10 != 1.0) { + type |= (TYPE_GENERAL_ROTATION | + TYPE_FLIP | + TYPE_UNIFORM_SCALE); + } else { + type |= (TYPE_GENERAL_ROTATION | TYPE_FLIP); + } + } + } + return type; + } +} diff --git a/jdk/test/java/awt/geom/AffineTransform/TestInvertMethods.java b/jdk/test/java/awt/geom/AffineTransform/TestInvertMethods.java new file mode 100644 index 00000000000..6d260a1ad89 --- /dev/null +++ b/jdk/test/java/awt/geom/AffineTransform/TestInvertMethods.java @@ -0,0 +1,483 @@ +/* + * Copyright (c) 2005, 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 4987374 + * @summary Unit test for inversion methods: + * + * AffineTransform.createInverse(); + * AffineTransform.invert(); + * + * @author flar + * @run main TestInvertMethods + */ + +import java.awt.geom.AffineTransform; +import java.awt.geom.NoninvertibleTransformException; + +/* + * Instances of the inner class Tester are "nodes" which take an input + * AffineTransform (AT), modify it in some way and pass the modified + * AT onto another Tester node. + * + * There is one particular Tester node of note called theVerifier. + * This is a leaf node which takes the input AT and tests the various + * inversion methods on that matrix. + * + * Most of the other Tester nodes will perform a single affine operation + * on their input, such as a rotate by various angles, or a scale by + * various predefined scale values, and then pass the modified AT on + * to the next node in the chain which may be a verifier or another + * modifier. + * + * The Tester instances can also be chained together using the chain + * method so that we can test not only matrices modified by some single + * affine operation (scale, rotate, etc.) but also composite matrices + * that represent multiple operations concatenated together. + */ +public class TestInvertMethods { + public static boolean verbose; + + public static final double MAX_ULPS = 2.0; + public static double MAX_TX_ULPS = MAX_ULPS; + public static double maxulps = 0.0; + public static double maxtxulps = 0.0; + public static int numtests = 0; + + public static void main(String argv[]) { + Tester rotate = new Tester.Rotate(); + Tester scale = new Tester.Scale(); + Tester shear = new Tester.Shear(); + Tester translate = new Tester.Translate(); + + if (argv.length > 1) { + // This next line verifies that chaining works correctly... + scale.chain(translate.chain(new Tester.Debug())).test(false); + return; + } + + verbose = (argv.length > 0); + + new Tester.Identity().test(true); + translate.test(true); + scale.test(true); + rotate.test(true); + shear.test(true); + scale.chain(translate).test(true); + rotate.chain(translate).test(true); + shear.chain(translate).test(true); + translate.chain(scale).test(true); + translate.chain(rotate).test(true); + translate.chain(shear).test(true); + translate.chain(scale.chain(rotate.chain(shear))).test(false); + shear.chain(rotate.chain(scale.chain(translate))).test(false); + + System.out.println(numtests+" tests performed"); + System.out.println("Max scale and shear difference: "+maxulps+" ulps"); + System.out.println("Max translate difference: "+maxtxulps+" ulps"); + } + + public abstract static class Tester { + public static AffineTransform IdentityTx = new AffineTransform(); + + /* + * This is the leaf node that performs inversion testing + * on the incoming AffineTransform. + */ + public static final Tester theVerifier = new Tester() { + public void test(AffineTransform at, boolean full) { + numtests++; + AffineTransform inv1, inv2; + boolean isinvertible = + (Math.abs(at.getDeterminant()) >= Double.MIN_VALUE); + try { + inv1 = at.createInverse(); + if (!isinvertible) missingNTE("createInverse", at); + } catch (NoninvertibleTransformException e) { + inv1 = null; + if (isinvertible) extraNTE("createInverse", at); + } + inv2 = new AffineTransform(at); + try { + inv2.invert(); + if (!isinvertible) missingNTE("invert", at); + } catch (NoninvertibleTransformException e) { + if (isinvertible) extraNTE("invert", at); + } + if (verbose) System.out.println("at = "+at); + if (isinvertible) { + if (verbose) System.out.println(" inv1 = "+inv1); + if (verbose) System.out.println(" inv2 = "+inv2); + if (!inv1.equals(inv2)) { + report(at, inv1, inv2, + "invert methods do not agree"); + } + inv1.concatenate(at); + inv2.concatenate(at); + // "Fix" some values that don't always behave + // well with all the math that we've done up + // to this point. + // See the note on the concatfix method below. + concatfix(inv1); + concatfix(inv2); + if (verbose) System.out.println(" at*inv1 = "+inv1); + if (verbose) System.out.println(" at*inv2 = "+inv2); + if (!compare(inv1, IdentityTx)) { + report(at, inv1, IdentityTx, + "createInverse() check failed"); + } + if (!compare(inv2, IdentityTx)) { + report(at, inv2, IdentityTx, + "invert() check failed"); + } + } else { + if (verbose) System.out.println(" is not invertible"); + } + if (verbose) System.out.println(); + } + + void missingNTE(String methodname, AffineTransform at) { + throw new RuntimeException("Noninvertible was not "+ + "thrown from "+methodname+ + " for: "+at); + } + + void extraNTE(String methodname, AffineTransform at) { + throw new RuntimeException("Unexpected Noninvertible "+ + "thrown from "+methodname+ + " for: "+at); + } + }; + + /* + * The inversion math may work out fairly exactly, but when + * we concatenate the inversions back with the original matrix + * in an attempt to restore them to the identity matrix, + * then we can end up compounding errors to a fairly high + * level, particularly if the component values had mantissas + * that were repeating fractions. This function therefore + * "fixes" the results of concatenating the inversions back + * with their original matrices to get rid of small variations + * in the values that should have ended up being 0.0. + */ + public void concatfix(AffineTransform at) { + double m00 = at.getScaleX(); + double m10 = at.getShearY(); + double m01 = at.getShearX(); + double m11 = at.getScaleY(); + double m02 = at.getTranslateX(); + double m12 = at.getTranslateY(); + if (Math.abs(m02) < 1E-10) m02 = 0.0; + if (Math.abs(m12) < 1E-10) m12 = 0.0; + if (Math.abs(m01) < 1E-15) m01 = 0.0; + if (Math.abs(m10) < 1E-15) m10 = 0.0; + at.setTransform(m00, m10, + m01, m11, + m02, m12); + } + + public void test(boolean full) { + test(IdentityTx, full); + } + + public void test(AffineTransform init, boolean full) { + test(init, theVerifier, full); + } + + public void test(AffineTransform init, Tester next, boolean full) { + next.test(init, full); + } + + public Tester chain(Tester next) { + return new Chain(this, next); + } + + /* + * Utility node used to chain together two other nodes for + * implementing the "chain" method. + */ + public static class Chain extends Tester { + Tester prev; + Tester next; + + public Chain(Tester prev, Tester next) { + this.prev = prev; + this.next = next; + } + + public void test(AffineTransform init, boolean full) { + prev.test(init, next, full); + } + + public Tester chain(Tester next) { + this.next = this.next.chain(next); + return this; + } + } + + /* + * Utility node for testing. + */ + public static class Fail extends Tester { + public void test(AffineTransform init, Tester next, boolean full) { + throw new RuntimeException("Debug: Forcing failure"); + } + } + + /* + * Utility node for testing that chaining works. + */ + public static class Debug extends Tester { + public void test(AffineTransform init, Tester next, boolean full) { + new Throwable().printStackTrace(); + next.test(init, full); + } + } + + /* + * NOP node. + */ + public static class Identity extends Tester { + public void test(AffineTransform init, Tester next, boolean full) { + if (verbose) System.out.println("*Identity = "+init); + next.test(init, full); + } + } + + /* + * Affine rotation node. + */ + public static class Rotate extends Tester { + public void test(AffineTransform init, Tester next, boolean full) { + int inc = full ? 10 : 45; + for (int i = -720; i <= 720; i += inc) { + AffineTransform at2 = new AffineTransform(init); + at2.rotate(Math.toRadians(i)); + if (verbose) System.out.println("*Rotate("+i+") = "+at2); + next.test(at2, full); + } + } + } + + public static final double SMALL_VALUE = .0001; + public static final double LARGE_VALUE = 10000; + + /* + * Affine scale node. + */ + public static class Scale extends Tester { + public double fullvals[] = { + // Noninvertibles + 0.0, 0.0, + 0.0, 1.0, + 1.0, 0.0, + + // Invertibles + SMALL_VALUE, SMALL_VALUE, + SMALL_VALUE, 1.0, + 1.0, SMALL_VALUE, + + SMALL_VALUE, LARGE_VALUE, + LARGE_VALUE, SMALL_VALUE, + + LARGE_VALUE, LARGE_VALUE, + LARGE_VALUE, 1.0, + 1.0, LARGE_VALUE, + + 0.5, 0.5, + 1.0, 1.0, + 2.0, 2.0, + Math.PI, Math.E, + }; + public double abbrevvals[] = { + 0.0, 0.0, + 1.0, 1.0, + 2.0, 3.0, + }; + + public void test(AffineTransform init, Tester next, boolean full) { + double scales[] = (full ? fullvals : abbrevvals); + for (int i = 0; i < scales.length; i += 2) { + AffineTransform at2 = new AffineTransform(init); + at2.scale(scales[i], scales[i+1]); + if (verbose) System.out.println("*Scale("+scales[i]+", "+ + scales[i+1]+") = "+at2); + next.test(at2, full); + } + } + } + + /* + * Affine shear node. + */ + public static class Shear extends Tester { + public double fullvals[] = { + 0.0, 0.0, + 0.0, 1.0, + 1.0, 0.0, + + // Noninvertible + 1.0, 1.0, + + SMALL_VALUE, SMALL_VALUE, + SMALL_VALUE, LARGE_VALUE, + LARGE_VALUE, SMALL_VALUE, + LARGE_VALUE, LARGE_VALUE, + + Math.PI, Math.E, + }; + public double abbrevvals[] = { + 0.0, 0.0, + 0.0, 1.0, + 1.0, 0.0, + + // Noninvertible + 1.0, 1.0, + }; + + public void test(AffineTransform init, Tester next, boolean full) { + double shears[] = (full ? fullvals : abbrevvals); + for (int i = 0; i < shears.length; i += 2) { + AffineTransform at2 = new AffineTransform(init); + at2.shear(shears[i], shears[i+1]); + if (verbose) System.out.println("*Shear("+shears[i]+", "+ + shears[i+1]+") = "+at2); + next.test(at2, full); + } + } + } + + /* + * Affine translate node. + */ + public static class Translate extends Tester { + public double fullvals[] = { + 0.0, 0.0, + 0.0, 1.0, + 1.0, 0.0, + + SMALL_VALUE, SMALL_VALUE, + SMALL_VALUE, LARGE_VALUE, + LARGE_VALUE, SMALL_VALUE, + LARGE_VALUE, LARGE_VALUE, + + Math.PI, Math.E, + }; + public double abbrevvals[] = { + 0.0, 0.0, + 0.0, 1.0, + 1.0, 0.0, + Math.PI, Math.E, + }; + + public void test(AffineTransform init, Tester next, boolean full) { + double translates[] = (full ? fullvals : abbrevvals); + for (int i = 0; i < translates.length; i += 2) { + AffineTransform at2 = new AffineTransform(init); + at2.translate(translates[i], translates[i+1]); + if (verbose) System.out.println("*Translate("+ + translates[i]+", "+ + translates[i+1]+") = "+at2); + next.test(at2, full); + } + } + } + } + + public static void report(AffineTransform orig, + AffineTransform at1, AffineTransform at2, + String message) + { + System.out.println(orig+", type = "+orig.getType()); + System.out.println(at1+", type = "+at1.getType()); + System.out.println(at2+", type = "+at2.getType()); + System.out.println("ScaleX values differ by "+ + ulps(at1.getScaleX(), + at2.getScaleX())+" ulps"); + System.out.println("ScaleY values differ by "+ + ulps(at1.getScaleY(), + at2.getScaleY())+" ulps"); + System.out.println("ShearX values differ by "+ + ulps(at1.getShearX(), + at2.getShearX())+" ulps"); + System.out.println("ShearY values differ by "+ + ulps(at1.getShearY(), + at2.getShearY())+" ulps"); + System.out.println("TranslateX values differ by "+ + ulps(at1.getTranslateX(), + at2.getTranslateX())+" ulps"); + System.out.println("TranslateY values differ by "+ + ulps(at1.getTranslateY(), + at2.getTranslateY())+" ulps"); + throw new RuntimeException(message); + } + + public static boolean compare(AffineTransform at1, AffineTransform at2) { + maxulps = Math.max(maxulps, ulps(at1.getScaleX(), at2.getScaleX())); + maxulps = Math.max(maxulps, ulps(at1.getScaleY(), at2.getScaleY())); + maxulps = Math.max(maxulps, ulps(at1.getShearX(), at2.getShearX())); + maxulps = Math.max(maxulps, ulps(at1.getShearY(), at2.getShearY())); + maxtxulps = Math.max(maxtxulps, + ulps(at1.getTranslateX(), at2.getTranslateX())); + maxtxulps = Math.max(maxtxulps, + ulps(at1.getTranslateY(), at2.getTranslateY())); + return (getModifiedType(at1) == getModifiedType(at2) && + (compare(at1.getScaleX(), at2.getScaleX(), MAX_ULPS)) && + (compare(at1.getScaleY(), at2.getScaleY(), MAX_ULPS)) && + (compare(at1.getShearX(), at2.getShearX(), MAX_ULPS)) && + (compare(at1.getShearY(), at2.getShearY(), MAX_ULPS)) && + (compare(at1.getTranslateX(), + at2.getTranslateX(), MAX_TX_ULPS)) && + (compare(at1.getTranslateY(), + at2.getTranslateY(), MAX_TX_ULPS))); + } + + public static final int ANY_SCALE_MASK = + (AffineTransform.TYPE_UNIFORM_SCALE | + AffineTransform.TYPE_GENERAL_SCALE); + public static int getModifiedType(AffineTransform at) { + int type = at.getType(); + // Some of the vector methods can introduce a tiny uniform scale + // at some angles... + if ((type & ANY_SCALE_MASK) != 0) { + maxulps = Math.max(maxulps, ulps(at.getDeterminant(), 1.0)); + if (ulps(at.getDeterminant(), 1.0) <= MAX_ULPS) { + // Really tiny - we will ignore it + type &= ~ ANY_SCALE_MASK; + } + } + return type; + } + + public static boolean compare(double val1, double val2, double maxulps) { + if (Math.abs(val1 - val2) < 1E-15) return true; + return (ulps(val1, val2) <= maxulps); + } + + public static double ulps(double val1, double val2) { + double diff = Math.abs(val1 - val2); + double ulpmax = Math.min(Math.ulp(val1), Math.ulp(val2)); + return (diff / ulpmax); + } +} diff --git a/jdk/test/java/awt/geom/AffineTransform/TestRotateMethods.java b/jdk/test/java/awt/geom/AffineTransform/TestRotateMethods.java new file mode 100644 index 00000000000..0664eacdd64 --- /dev/null +++ b/jdk/test/java/awt/geom/AffineTransform/TestRotateMethods.java @@ -0,0 +1,352 @@ +/* + * Copyright (c) 2004, 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 4980035 + * @summary Unit test for new methods: + * + * AffineTransform.getRotateInstance(double x, double y); + * AffineTransform.setToRotation(double x, double y); + * AffineTransform.rotate(double x, double y); + * + * AffineTransform.getQuadrantRotateInstance(int numquads); + * AffineTransform.setToQuadrantRotation(int numquads); + * AffineTransform.quadrantRotate(int numquads); + * + * @author flar + * @run main TestRotateMethods + */ + +import java.awt.geom.AffineTransform; +import java.awt.geom.Point2D; + +public class TestRotateMethods { + /* The maximum errors allowed, measured in double precision "ulps" + * Note that for most fields, the tests are extremely accurate - to + * within 3 ulps of the smaller value in the comparison + * For the translation components, the tests are still very accurate, + * but the absolute number of ulps can be noticeably higher when we + * use one of the rotate methods that takes an anchor point. + * Since a double precision value has 56 bits of precision, even + * 1024 ulps is extremely small as a ratio of the value. + */ + public static final double MAX_ULPS = 3.0; + public static final double MAX_ANCHOR_TX_ULPS = 1024.0; + public static double MAX_TX_ULPS = MAX_ULPS; + + // Vectors for quadrant rotations + public static final double quadxvec[] = { 1.0, 0.0, -1.0, 0.0 }; + public static final double quadyvec[] = { 0.0, 1.0, 0.0, -1.0 }; + + // Run tests once for each type of method: + // tx = AffineTransform.get+ Refer to bug report 4112270 for spec of keyboard navigation. Check all combinations of navigational keys in all four modes shift and control verifying each change to the selection against the spec. + If it does, press "pass", otherwise press "fail". +
+ Select a cell by double clicking it, press tab. Check that the focus moves to the next cell. + If it does, press "pass", otherwise press "fail". +