From 2989b5405dee12590af1b8d9275d7cecb5fdcf8b Mon Sep 17 00:00:00 2001 From: Jaroslav Bachorik Date: Fri, 30 Jan 2015 22:01:32 +0100 Subject: [PATCH 01/25] 8071641: java/lang/management/ThreadMXBean/SynchronizationStatistics.java intermittently failed with NPE Reviewed-by: sjiang, dfuchs --- .../ThreadMXBean/SynchronizationStatistics.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/jdk/test/java/lang/management/ThreadMXBean/SynchronizationStatistics.java b/jdk/test/java/lang/management/ThreadMXBean/SynchronizationStatistics.java index f998b7e2375..6cb4bfb0720 100644 --- a/jdk/test/java/lang/management/ThreadMXBean/SynchronizationStatistics.java +++ b/jdk/test/java/lang/management/ThreadMXBean/SynchronizationStatistics.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2015, 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 @@ public class SynchronizationStatistics { } private static void waitForThreadState(Thread t, Thread.State state) throws InterruptedException { - while (!t.isInterrupted() && t.getState() != state) { + while (t.getState() != state) { Thread.sleep(3); } } @@ -109,7 +109,9 @@ public class SynchronizationStatistics { synchronized(lock1) { p.arriveAndAwaitAdvance(); // phase[1] waitForThreadState(lt, Thread.State.BLOCKED); - lockName = mbean.getThreadInfo(tid).getLockName(); + do { + lockName = mbean.getThreadInfo(tid).getLockName(); + } while (lockName == null); } p.arriveAndAwaitAdvance(); // phase[2] @@ -159,7 +161,9 @@ public class SynchronizationStatistics { synchronized(lock1) { p.arriveAndAwaitAdvance(); // phase[1] waitForThreadState(lt, Thread.State.BLOCKED); - lockName = mbean.getThreadInfo(tid).getLockName(); + do { + lockName = mbean.getThreadInfo(tid).getLockName(); + } while (lockName == null); } p.arriveAndAwaitAdvance(); // phase[2] @@ -168,7 +172,9 @@ public class SynchronizationStatistics { synchronized(lock2) { p.arriveAndAwaitAdvance(); // phase [3] waitForThreadState(lt, Thread.State.BLOCKED); - lockName = mbean.getThreadInfo(tid).getLockName(); + do { + lockName = mbean.getThreadInfo(tid).getLockName(); + } while (lockName == null); } p.arriveAndAwaitAdvance(); // phase [4] testBlocked(ti, () -> mbean.getThreadInfo(tid), lockName, lock2); From 45a6ed8315939ff5922e2ddbc0b3f8451554ce92 Mon Sep 17 00:00:00 2001 From: Katja Kantserova Date: Fri, 30 Jan 2015 09:31:18 +0100 Subject: [PATCH 02/25] 8068613: Wrong number of objects pending finalization start Repeat until expected result, instead of fail after sleep() Reviewed-by: sla --- .../lang/management/MemoryMXBean/Pending.java | 71 ++++++------------- 1 file changed, 22 insertions(+), 49 deletions(-) diff --git a/jdk/test/java/lang/management/MemoryMXBean/Pending.java b/jdk/test/java/lang/management/MemoryMXBean/Pending.java index 678bc7e4ca7..f468aa36449 100644 --- a/jdk/test/java/lang/management/MemoryMXBean/Pending.java +++ b/jdk/test/java/lang/management/MemoryMXBean/Pending.java @@ -39,7 +39,7 @@ import java.lang.management.*; public class Pending { final static int NO_REF_COUNT = 600; - final static int REF_COUNT = 600; + final static int REF_COUNT = 500; final static int TOTAL_FINALIZABLE = (NO_REF_COUNT + REF_COUNT); private static int finalized = 0; private static MemoryMXBean mbean @@ -83,31 +83,22 @@ public class Pending { // Clean the memory and remove all objects that are pending // finalization System.gc(); - Runtime.getRuntime().runFinalization(); - - // Let the finalizer to finish - try { - Thread.sleep(200); - } catch (Exception e) { - throw e; - } - - // Create a number of new objects but no references to them - int startCount = mbean.getObjectPendingFinalizationCount(); + Snapshot snapshot = getSnapshotAfterFinalization(); System.out.println("Number of objects pending for finalization:"); - System.out.println(" Before creating object: " + startCount + - " finalized = " + finalized); + System.out.println(" Before creating object: " + snapshot); printFinalizerInstanceCount(); + // Create objects without saving reference. Should be removed at next GC. for (int i = 0; i < NO_REF_COUNT; i++) { new MyObject(); } - Snapshot snapshot = getSnapshot(); + snapshot = getSnapshot(); System.out.println(" Afer creating objects with no ref: " + snapshot); printFinalizerInstanceCount(); + // Create objects and save references. objs = new Object[REF_COUNT]; for (int i = 0; i < REF_COUNT; i++) { objs[i] = new MyObject(); @@ -139,9 +130,8 @@ public class Pending { + TOTAL_FINALIZABLE); } - if (startCount != 0 || snapshot.curPending != 0) { + if (snapshot.curPending != 0) { throw new RuntimeException("Wrong number of objects pending " - + "finalization start = " + startCount + " end = " + snapshot); } @@ -161,29 +151,8 @@ public class Pending { snapshot.curFinalized != expectedTotal && i <= MAX_GC_LOOP; i++) { System.gc(); + snapshot = getSnapshotAfterFinalization(); - // Pause to give a chance to Finalizer thread to run - pause(); - - printFinalizerInstanceCount(); - // Race condition may occur; attempt to check this - // a few times before throwing exception. - for (int j = 0; j < 5; j++) { - // poll for another current pending count - snapshot = getSnapshot(); - if (snapshot.curFinalized == expectedTotal || - snapshot.curPending != 0) { - break; - } - } - System.out.println(" After GC " + i + ": " + snapshot); - - Runtime.getRuntime().runFinalization(); - - // Pause to give a chance to Finalizer thread to run - pause(); - - snapshot = getSnapshot(); if (snapshot.curFinalized == expectedTotal && snapshot.curPending != 0) { throw new RuntimeException( @@ -237,17 +206,21 @@ public class Pending { } } - private static Object pauseObj = new Object(); - private static void pause() { - // Enter lock a without blocking - synchronized (pauseObj) { - try { - // may need to tune this timeout for different platforms - pauseObj.wait(20); - } catch (Exception e) { - System.err.println("Unexpected exception."); - e.printStackTrace(System.err); + // Repeat getSnapshot until no pending finalization. + private static Snapshot getSnapshotAfterFinalization() throws Exception { + int loopCount = 0; + Snapshot snapshot = null; + while (loopCount < 100) { + Runtime.getRuntime().runFinalization(); + Thread.sleep(50); + snapshot = getSnapshot(); + if (snapshot.curPending == 0) { + return snapshot; } + ++loopCount; + System.out.println("Waiting for curPending to be 0. snapshot=" + snapshot); } + String msg = "Objects pending finalization is not 0. snapshot=%s"; + throw new RuntimeException(String.format(msg, snapshot)); } } From 5eb21ad94f4e3f81b20aaf72160fd93b98bb2746 Mon Sep 17 00:00:00 2001 From: Alexander Kulyakthin Date: Mon, 2 Feb 2015 09:37:53 +0100 Subject: [PATCH 03/25] 8071464: Clear up SVC jdk/test/* JRE layout dependencies other than those on tools.jar Reviewed-by: sla --- jdk/test/com/sun/jdi/ShellScaffold.sh | 12 ++---------- jdk/test/demo/jvmti/DemoRun.java | 7 ++----- 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/jdk/test/com/sun/jdi/ShellScaffold.sh b/jdk/test/com/sun/jdi/ShellScaffold.sh index d2fd876a509..cf0cdbe43d0 100644 --- a/jdk/test/com/sun/jdi/ShellScaffold.sh +++ b/jdk/test/com/sun/jdi/ShellScaffold.sh @@ -259,7 +259,7 @@ setup() ;; esac - if [ -r $jdk/bin/dt_shmem.dll -o -r $jdk/jre/bin/dt_shmem.dll ] ; then + if [ -r $jdk/bin/dt_shmem.dll ] ; then transport=dt_shmem address=kkkk.$$ else @@ -933,18 +933,10 @@ dojstack() debuggeeCmd=`$jdk/bin/jps -v | $grep $debuggeeKeyword` realDebuggeePid=`echo "$debuggeeCmd" | sed -e 's@ .*@@'` if [ ! -z "$realDebuggeePid" ] ; then - if [ -r "$jdk/lib/sa-jdi.jar" ] ; then - # disableVersionCheck can be removed after 6475822 - # is fixed. - moption="-m -J-Dsun.jvm.hotspot.runtime.VM.disableVersionCheck" - else - moption= - fi - echo "-- debuggee process info ----------------------" >&2 echo " $debuggeeCmd" >&2 echo "-- debuggee threads: jstack $moption $realDebuggeePid" >&2 - $jdk/bin/$jstack $moption $realDebuggeePid >&2 + $jdk/bin/$jstack $realDebuggeePid >&2 echo "=============================================" >&2 echo >&2 fi diff --git a/jdk/test/demo/jvmti/DemoRun.java b/jdk/test/demo/jvmti/DemoRun.java index 907e5ce97e7..ea1296a7b8a 100644 --- a/jdk/test/demo/jvmti/DemoRun.java +++ b/jdk/test/demo/jvmti/DemoRun.java @@ -115,10 +115,7 @@ public class DemoRun { */ public void runit(String class_name, String vm_options[]) { - String jre_home = System.getProperty("java.home"); - String sdk_home = (jre_home.endsWith("jre") ? - (jre_home + File.separator + "..") : - jre_home ); + String sdk_home = System.getProperty("java.home"); String cdir = System.getProperty("test.classes", "."); String os_arch = System.getProperty("os.arch"); String os_name = System.getProperty("os.name"); @@ -126,7 +123,7 @@ public class DemoRun { String libsuffix = os_name.contains("Windows")?".dll": os_name.contains("OS X")?".dylib":".so"; boolean hprof = demo_name.equals("hprof"); - String java = jre_home + String java = sdk_home + File.separator + "bin" + File.separator + "java"; /* Array of strings to be passed in for exec: From d9fe0af0483e5954ba1d68107fb448669724a464 Mon Sep 17 00:00:00 2001 From: Jaroslav Bachorik Date: Tue, 3 Feb 2015 16:46:05 +0100 Subject: [PATCH 04/25] 8066708: JMXStartStopTest fails to connect to port 38112 Reviewed-by: smarks, dsamersoff, olagneau --- .../jmxremote/startstop/JMXStartStopTest.java | 599 ++++++++++-------- 1 file changed, 346 insertions(+), 253 deletions(-) diff --git a/jdk/test/sun/management/jmxremote/startstop/JMXStartStopTest.java b/jdk/test/sun/management/jmxremote/startstop/JMXStartStopTest.java index bc755ac411e..a516acfd449 100644 --- a/jdk/test/sun/management/jmxremote/startstop/JMXStartStopTest.java +++ b/jdk/test/sun/management/jmxremote/startstop/JMXStartStopTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, 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,7 +23,9 @@ import java.io.File; import java.io.IOException; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.net.BindException; import java.net.ConnectException; import java.net.ServerSocket; import java.rmi.RemoteException; @@ -31,15 +33,15 @@ import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import java.util.ArrayList; import java.util.Arrays; -import java.util.Iterator; import java.util.List; import java.util.Objects; +import java.util.Random; import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; +import java.util.stream.Collectors; import javax.management.*; import javax.management.remote.*; @@ -47,6 +49,8 @@ import javax.net.ssl.SSLHandshakeException; import jdk.testlibrary.ProcessTools; import jdk.testlibrary.JDKToolLauncher; +import sun.management.Agent; +import sun.management.AgentConfigurationError; /** * @test @@ -54,65 +58,55 @@ import jdk.testlibrary.JDKToolLauncher; * @library /lib/testlibrary * @build jdk.testlibrary.* JMXStartStopTest JMXStartStopDoSomething * @run main/othervm/timeout=600 -XX:+UsePerfData JMXStartStopTest - * @summary Makes sure that enabling/disabling the management agent through - * JCMD achieves the desired results + * @summary Makes sure that enabling/disabling the management agent through JCMD + * achieves the desired results */ public class JMXStartStopTest { + private static final String TEST_SRC = System.getProperty("test.src"); private static final boolean verbose = false; /** - * Dynamically allocates two distinct ports using {@linkplain java.net.ServerSocket} - * It keeps each of those ports blocked until it is first accessed by its getter + * Dynamically allocates distinct ports from the ephemeral range 49152-65535 */ private static class PortAllocator { - private final int port1, port2; - private final ServerSocket ss1, ss2; - PortAllocator() { - try { - ss1 = new ServerSocket(0); - ss2 = new ServerSocket(0); - port1 = ss1.getLocalPort(); - port2 = ss2.getLocalPort(); - } catch (IOException e) { - throw new Error("Error while obtaining free ports", e); - } - } - public int getPort1() { - if (!ss1.isClosed()) { - try { - ss1.close(); - } catch (IOException e) { - // just ignore - } - } - return port1; - } + private final static int LOWER_BOUND = 49152; + private final static int UPPER_BOUND = 65535; - public int getPort2() { - if (!ss2.isClosed()) { - try { - ss2.close(); - } catch (IOException e) { - // just ignore + private final static Random RND = new Random(System.currentTimeMillis()); + + private static int[] allocatePorts(final int numPorts) { + int[] ports = new int[numPorts]; + for (int i = 0; i < numPorts; i++) { + int port = -1; + while (port == -1) { + port = RND.nextInt(UPPER_BOUND - LOWER_BOUND + 1) + LOWER_BOUND; + for (int j = 0; j < i; j++) { + if (ports[j] == port) { + port = -1; + break; + } + } } + System.err.println("*** port = " + port); + ports[i] = port; } - return port2; + return ports; } } - private static void dbg_print(String msg){ + private static void dbg_print(String msg) { if (verbose) { - System.out.println("DBG: " +msg); + System.out.println("DBG: " + msg); } } private static int listMBeans(MBeanServerConnection server, - ObjectName pattern, - QueryExp query) - throws Exception { + ObjectName pattern, + QueryExp query) + throws Exception { Set names = server.queryNames(pattern,query); for (ObjectName name : names) { @@ -131,9 +125,8 @@ public class JMXStartStopTest { return names.size(); } - private static void testConnectLocal(long pid) - throws Exception { + throws Exception { String jmxUrlStr = null; @@ -208,12 +201,12 @@ public class JMXStartStopTest { String jmxUrlStr = (rmiPort != 0) ? String.format( - "service:jmx:rmi://localhost:%d/jndi/rmi://localhost:%d/jmxrmi", - rmiPort, + "service:jmx:rmi://localhost:%d/jndi/rmi://localhost:%d/jmxrmi", + rmiPort, port) : String.format( - "service:jmx:rmi:///jndi/rmi://localhost:%d/jmxrmi", - port); + "service:jmx:rmi:///jndi/rmi://localhost:%d/jmxrmi", + port); JMXServiceURL url = new JMXServiceURL(jmxUrlStr); @@ -292,7 +285,21 @@ public class JMXStartStopTest { if (m.getName().startsWith("test_")) { long t1 = System.currentTimeMillis(); try { - m.invoke(null); + boolean retry = false; + do { + try { + m.invoke(null); + retry = false; + } catch (InvocationTargetException e) { + if (e.getCause() instanceof BindException || + e.getCause() instanceof java.rmi.ConnectException) { + System.out.println("Failed to allocate ports. Retrying ..."); + retry = true; + } else { + throw e; + } + } + } while (retry); System.out.println("=== PASSED"); } catch (Throwable e) { failures.add(new Failure(e, m.getName() + " failed")); @@ -326,13 +333,23 @@ public class JMXStartStopTest { public synchronized void start() throws InterruptedException, IOException, TimeoutException { if (started.compareAndSet(false, true)) { try { + AtomicBoolean error = new AtomicBoolean(false); p = ProcessTools.startProcess( - "JMXStartStopDoSomething", - pb, - (line) -> line.equals("main enter"), - 5, - TimeUnit.SECONDS + "JMXStartStopDoSomething{" + name + "}", + pb, + (line) -> { + boolean ok = line.equals("main enter"); + error.set(line.contains("BindException")); + + return ok || error.get(); + }, + 5, + TimeUnit.SECONDS ); + if (error.get()) { + throw new BindException("Starting process failed due to " + + "the requested port not being available"); + } pid = p.getPid(); } catch (TimeoutException e) { p.destroy(); @@ -347,7 +364,7 @@ public class JMXStartStopTest { } public synchronized void stop() - throws IOException, InterruptedException { + throws IOException, InterruptedException { if (started.compareAndSet(true, false)) { p.getOutputStream().write(0); p.getOutputStream().flush(); @@ -374,16 +391,16 @@ public class JMXStartStopTest { * @throws TimeoutException */ private static Something doSomething(String name, String ... args) - throws Exception { + throws Exception { List pbArgs = new ArrayList<>(Arrays.asList( - "-cp", - System.getProperty("test.class.path") + "-cp", + System.getProperty("test.class.path") )); pbArgs.addAll(Arrays.asList(args)); pbArgs.add("JMXStartStopDoSomething"); ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( - pbArgs.toArray(new String[pbArgs.size()]) + pbArgs.toArray(new String[pbArgs.size()]) ); Something s = new Something(pb, name); s.start(); @@ -399,7 +416,7 @@ public class JMXStartStopTest { */ private static void jcmd(String ... command) throws IOException, InterruptedException { if (command.length == 0) { - jcmd(null, (Consumer)null); + jcmd(null, c->{}); } else { jcmd(null, command); } @@ -408,7 +425,7 @@ public class JMXStartStopTest { /** * Run the "jcmd" command * - * @param c {@linkplain Consumer} instance; may be null + * @param c {@linkplain Consumer} instance * @param command Command with parameters; space separated string * @throws IOException * @throws InterruptedException @@ -419,8 +436,9 @@ public class JMXStartStopTest { /** * Run the "jcmd" command + * * @param target The target application name (or PID) - * @param c {@linkplain Consumer} instance; may be null + * @param c {@linkplain Consumer} instance * @param command Command with parameters; space separated string * @throws IOException * @throws InterruptedException @@ -430,21 +448,37 @@ public class JMXStartStopTest { JDKToolLauncher l = JDKToolLauncher.createUsingTestJDK("jcmd"); l.addToolArg(target); - for(String cmd : command) { + for (String cmd : command) { l.addToolArg(cmd); } + + AtomicBoolean portUnavailable = new AtomicBoolean(false); Process p = ProcessTools.startProcess( "jcmd", new ProcessBuilder(l.getCommand()), - c + line -> { + if (line.contains("BindException") || + line.contains(Agent.getText(AgentConfigurationError.CONNECTOR_SERVER_IO_ERROR))) { + portUnavailable.set(true); + } else { + c.accept(line); + } + } ); p.waitFor(); dbg_print("[jcmd] --------"); + if (portUnavailable.get()) { + String cmd = Arrays.asList(l.getCommand()).stream() + .collect( + Collectors.joining(" ", "", ": Unable to bind address") + ); + throw new BindException(cmd); + } } private static final String CMD_STOP = "ManagementAgent.stop"; - private static final String CMD_START= "ManagementAgent.start"; + private static final String CMD_START = "ManagementAgent.start"; private static final String CMD_START_LOCAL = "ManagementAgent.start_local"; static void test_01() throws Exception { @@ -452,22 +486,22 @@ public class JMXStartStopTest { // restart on other port System.out.println("**** Test one ****"); - PortAllocator pa = new PortAllocator(); + int ports[] = PortAllocator.allocatePorts(2); Something s = doSomething( - "test_01", - "-Dcom.sun.management.jmxremote.port=" + pa.getPort1(), - "-Dcom.sun.management.jmxremote.authenticate=false", - "-Dcom.sun.management.jmxremote.ssl=false"); + "test_01", + "-Dcom.sun.management.jmxremote.port=" + ports[0], + "-Dcom.sun.management.jmxremote.authenticate=false", + "-Dcom.sun.management.jmxremote.ssl=false"); try { - testConnect(pa.getPort1()); + testConnect(ports[0]); jcmd(CMD_STOP); - testNoConnect(pa.getPort1()); + testNoConnect(ports[0]); - jcmd(CMD_START, "jmxremote.port=" + pa.getPort2()); - testConnect(pa.getPort2()); + jcmd(CMD_START, "jmxremote.port=" + ports[1]); + testConnect(ports[1]); } finally { s.stop(); } @@ -479,15 +513,15 @@ public class JMXStartStopTest { System.out.println("**** Test two ****"); + int[] ports = PortAllocator.allocatePorts(1); Something s = doSomething("test_02"); - PortAllocator pa = new PortAllocator(); try { jcmd(CMD_START, - "jmxremote.port=" + pa.getPort1(), - "jmxremote.authenticate=false", - "jmxremote.ssl=false"); + "jmxremote.port=" + ports[0], + "jmxremote.authenticate=false", + "jmxremote.ssl=false"); - testConnect(pa.getPort1()); + testConnect(ports[0]); } finally { // debugPortUsage(pa); s.stop(); @@ -500,25 +534,25 @@ public class JMXStartStopTest { System.out.println("**** Test three ****"); + int[] ports = PortAllocator.allocatePorts(2); Something s = doSomething("test_03"); - PortAllocator pa = new PortAllocator(); try { jcmd(CMD_START, - "jmxremote.port=" + pa.getPort1(), - "jmxremote.authenticate=false", - "jmxremote.ssl=false"); + "jmxremote.port=" + ports[0], + "jmxremote.authenticate=false", + "jmxremote.ssl=false"); // Second agent shouldn't start jcmd(CMD_START, - "jmxremote.port=" + pa.getPort2(), - "jmxremote.authenticate=false", - "jmxremote.ssl=false"); + "jmxremote.port=" + ports[1], + "jmxremote.authenticate=false", + "jmxremote.ssl=false"); // First agent should connect - testConnect(pa.getPort1()); + testConnect(ports[0]); // Second agent should not connect - testNoConnect(pa.getPort2()); + testNoConnect(ports[1]); } finally { s.stop(); } @@ -530,16 +564,16 @@ public class JMXStartStopTest { System.out.println("**** Test four ****"); + int[] ports = PortAllocator.allocatePorts(2); Something s = doSomething("test_04"); - PortAllocator pa = new PortAllocator(); try { jcmd(CMD_START, - "jmxremote.port=" + pa.getPort1(), - "jmxremote.rmi.port=" + pa.getPort2(), - "jmxremote.authenticate=false", - "jmxremote.ssl=false"); + "jmxremote.port=" + ports[0], + "jmxremote.rmi.port=" + ports[1], + "jmxremote.authenticate=false", + "jmxremote.ssl=false"); - testConnect(pa.getPort1(), pa.getPort2()); + testConnect(ports[0], ports[1]); } finally { s.stop(); } @@ -550,13 +584,12 @@ public class JMXStartStopTest { // but should leave remote server disabled System.out.println("**** Test five ****"); - + int[] ports = PortAllocator.allocatePorts(1); Something s = doSomething("test_05"); - PortAllocator pa = new PortAllocator(); try { jcmd(CMD_START_LOCAL); - testNoConnect(pa.getPort1()); + testNoConnect(ports[0]); testConnectLocal(s.getPid()); } finally { s.stop(); @@ -566,94 +599,36 @@ public class JMXStartStopTest { static void test_06() throws Exception { // Run an app without JMX enabled // start JMX by jcmd on one port, specify rmi port explicitly - // attempt to start it again - // 1) with the same port - // 2) with other port - // 3) attempt to stop it twice + // attempt to start it again with the same port // Check for valid messages in the output System.out.println("**** Test six ****"); + int[] ports = PortAllocator.allocatePorts(2); Something s = doSomething("test_06"); - PortAllocator pa = new PortAllocator(); try { jcmd(CMD_START, - "jmxremote.port=" + pa.getPort1(), - "jmxremote.authenticate=false", - "jmxremote.ssl=false"); + "jmxremote.port=" + ports[0], + "jmxremote.authenticate=false", + "jmxremote.ssl=false"); - testConnect(pa.getPort1(), pa.getPort2()); + testConnect(ports[0], ports[1]); - final AtomicInteger checks = new AtomicInteger(); + final AtomicBoolean checks = new AtomicBoolean(false); jcmd( - line -> { - if (line.contains("java.lang.RuntimeException: Invalid agent state")) { - checks.getAndUpdate((op) -> op | 1); - } - }, - CMD_START, - "jmxremote.port=" + pa.getPort1(), - "jmxremote.authenticate=false", - "jmxremote.ssl=false"); + line -> { + if (line.contains("java.lang.RuntimeException: Invalid agent state")) { + checks.set(true); + } + }, + CMD_START, + "jmxremote.port=" + ports[0], + "jmxremote.authenticate=false", + "jmxremote.ssl=false"); - jcmd( - line -> { - if (line.contains("java.lang.RuntimeException: Invalid agent state")) { - checks.getAndUpdate((op) -> op | 2); - } - }, - CMD_START, - "jmxremote.port=" + pa.getPort2(), - "jmxremote.authenticate=false", - "jmxremote.ssl=false"); - - jcmd(CMD_STOP); - jcmd(CMD_STOP); - - int busyPort; - try (ServerSocket ss = new ServerSocket(0)) - { - busyPort = ss.getLocalPort(); - int retryCntr = 1; - do { - final boolean[] retry = new boolean[]{false}; - jcmd( - line -> { - boolean match = line.contains("Port already in use: " + - busyPort); - System.out.println("[match] " + line + " => " + match); - if (match) { - checks.getAndUpdate((op) -> op | 4); - retry[0] = false; - } else if (line.contains("Exception thrown by the agent")) { - retry[0] = true; - } - }, - CMD_START, - "jmxremote.port=" + ss.getLocalPort(), - "jmxremote.rmi.port=" + pa.getPort2(), - "jmxremote.authenticate=false", - "jmxremote.ssl=false" - ); - if (!retry[0]) { - break; - } - System.out.println("Attempt " + retryCntr + " >>>"); - System.out.println("Unexpected reply from the agent. Retrying in 500ms ..."); - Thread.sleep(500); - } while (retryCntr++ < 10); - } - if ((checks.get() & 1) == 0) { - throw new Exception("Starting agent on port " + pa.getPort1() + " should " + - "report an invalid agent state"); - } - if ((checks.get() & 2) == 0) { - throw new Exception("Starting agent on poprt " + pa.getPort2() + " should " + - "report an invalid agent state"); - } - if ((checks.get() & 4) == 0) { - throw new Exception("Starting agent on port " + busyPort + " should " + - "report port in use"); + if (!checks.get()) { + throw new Exception("Starting agent on port " + ports[0] + " should " + + "report an invalid agent state"); } } finally { s.stop(); @@ -661,68 +636,188 @@ public class JMXStartStopTest { } static void test_07() throws Exception { - // Run an app without JMX enabled, but with some properties set - // in command line. - // make sure these properties overridden corectly + // Run an app without JMX enabled + // start JMX by jcmd on one port, specify rmi port explicitly + // attempt to start it again with other port + // Check for valid messages in the output System.out.println("**** Test seven ****"); - Something s = doSomething( - "test_07", - "-Dcom.sun.management.jmxremote.authenticate=false", - "-Dcom.sun.management.jmxremote.ssl=true"); - PortAllocator pa = new PortAllocator(); - + int[] ports = PortAllocator.allocatePorts(2); + Something s = doSomething("test_07"); try { - testNoConnect(pa.getPort1()); + jcmd(CMD_START, + "jmxremote.port=" + ports[0], + "jmxremote.authenticate=false", + "jmxremote.ssl=false"); + + testConnect(ports[0], ports[1]); + + final AtomicBoolean checks = new AtomicBoolean(false); + jcmd( - CMD_START, - "jmxremote.port=" + pa.getPort2(), - "jmxremote.authenticate=false", - "jmxremote.ssl=false" - ); - testConnect(pa.getPort2()); + line -> { + if (line.contains("java.lang.RuntimeException: Invalid agent state")) { + checks.set(true); + } + }, + CMD_START, + "jmxremote.port=" + ports[1], + "jmxremote.authenticate=false", + "jmxremote.ssl=false"); + + if (!checks.get()) { + throw new Exception("Starting agent on poprt " + ports[1] + " should " + + "report an invalid agent state"); + } } finally { s.stop(); } } static void test_08() throws Exception { - // Run an app with JMX enabled and with some properties set - // in command line. - // stop JMX agent and then start it again with different property values - // make sure these properties overridden corectly + // Run an app without JMX enabled + // start JMX by jcmd on one port, specify rmi port explicitly + // attempt to stop it twice + // Check for valid messages in the output System.out.println("**** Test eight ****"); - PortAllocator pa = new PortAllocator(); - - Something s = doSomething( - "test_08", - "-Dcom.sun.management.jmxremote.port=" + pa.getPort1(), - "-Dcom.sun.management.jmxremote.authenticate=false", - "-Dcom.sun.management.jmxremote.ssl=true"); + int[] ports = PortAllocator.allocatePorts(2); + Something s = doSomething("test_08"); try { - testNoConnect(pa.getPort1()); + jcmd(CMD_START, + "jmxremote.port=" + ports[0], + "jmxremote.authenticate=false", + "jmxremote.ssl=false"); + + testConnect(ports[0], ports[1]); jcmd(CMD_STOP); - - testNoConnect(pa.getPort1()); - - jcmd( - CMD_START, - "jmxremote.port=" + pa.getPort2(), - "jmxremote.authenticate=false", - "jmxremote.ssl=false" - ); - - testConnect(pa.getPort2()); + jcmd(CMD_STOP); } finally { s.stop(); } } static void test_09() throws Exception { + // Run an app without JMX enabled + // attempt to start JMX using a non-available port + // Check for valid messages in the output + + System.out.println("**** Test nine ****"); + + Something s = doSomething("test_09"); + + try (ServerSocket ss = new ServerSocket(0)) { + int localPort = ss.getLocalPort(); + int[] ports; + do { + ports = PortAllocator.allocatePorts(1); + } while (localPort == ports[0]); + + final AtomicBoolean checks = new AtomicBoolean(false); + + int retryCntr = 1; + do { + final AtomicBoolean retry = new AtomicBoolean(false); + + try { + jcmd( + line -> { + if (line.contains(Agent.getText(AgentConfigurationError.AGENT_EXCEPTION))) { + retry.set(true); + } + }, + CMD_START, + "jmxremote.port=" + ports[0], + "jmxremote.rmi.port=" + localPort, + "jmxremote.authenticate=false", + "jmxremote.ssl=false" + ); + } catch (BindException e) { + checks.set(true); + } + if (!retry.get()) { + break; + } + System.out.println("Attempt " + retryCntr + " >>>"); + System.out.println("Unexpected reply from the agent. Retrying in 500ms ..."); + Thread.sleep(500); + } while (retryCntr++ < 10); + + if (!checks.get()) { + throw new Exception("Starting agent on port " + ports[0] + " should " + + "report port in use"); + } + } finally { + s.stop(); + } + + } + + static void test_10() throws Exception { + // Run an app without JMX enabled, but with some properties set + // in command line. + // make sure these properties overridden corectly + + System.out.println("**** Test ten ****"); + + int[] ports = PortAllocator.allocatePorts(2); + Something s = doSomething( + "test_10", + "-Dcom.sun.management.jmxremote.authenticate=false", + "-Dcom.sun.management.jmxremote.ssl=true"); + + try { + testNoConnect(ports[0]); + jcmd( + CMD_START, + "jmxremote.port=" + ports[1], + "jmxremote.authenticate=false", + "jmxremote.ssl=false" + ); + testConnect(ports[1]); + } finally { + s.stop(); + } + } + + static void test_11() throws Exception { + // Run an app with JMX enabled and with some properties set + // in command line. + // stop JMX agent and then start it again with different property values + // make sure these properties overridden corectly + + System.out.println("**** Test eleven ****"); + int[] ports = PortAllocator.allocatePorts(2); + Something s = doSomething( + "test_11", + "-Dcom.sun.management.jmxremote.port=" + ports[0], + "-Dcom.sun.management.jmxremote.authenticate=false", + "-Dcom.sun.management.jmxremote.ssl=true"); + + try { + testNoConnect(ports[0]); + + jcmd(CMD_STOP); + + testNoConnect(ports[0]); + + jcmd( + CMD_START, + "jmxremote.port=" + ports[1], + "jmxremote.authenticate=false", + "jmxremote.ssl=false" + ); + + testConnect(ports[1]); + } finally { + s.stop(); + } + } + + static void test_12() throws Exception { // Run an app with JMX enabled and with some properties set // in command line. // stop JMX agent and then start it again with different property values @@ -730,87 +825,85 @@ public class JMXStartStopTest { // in command line // make sure these properties overridden corectly - System.out.println("**** Test nine ****"); + System.out.println("**** Test twelve ****"); - Something s = doSomething("test_09", - "-Dcom.sun.management.config.file=" + - TEST_SRC + File.separator + "management_cl.properties", - "-Dcom.sun.management.jmxremote.authenticate=false" + int[] ports = PortAllocator.allocatePorts(2); + Something s = doSomething("test_12", + "-Dcom.sun.management.config.file=" + + TEST_SRC + File.separator + "management_cl.properties", + "-Dcom.sun.management.jmxremote.authenticate=false" ); - PortAllocator pa = new PortAllocator(); try { - testNoConnect(pa.getPort1()); + testNoConnect(ports[0]); jcmd(CMD_STOP); - testNoConnect(pa.getPort1()); + testNoConnect(ports[0]); jcmd(CMD_START, - "config.file=" + TEST_SRC + File.separator + - "management_jcmd.properties", - "jmxremote.authenticate=false", - "jmxremote.port=" + pa.getPort2() + "config.file=" + TEST_SRC + File.separator + + "management_jcmd.properties", + "jmxremote.authenticate=false", + "jmxremote.port=" + ports[1] ); - testConnect(pa.getPort2()); + testConnect(ports[1]); } finally { s.stop(); } } - static void test_10() throws Exception { + static void test_13() throws Exception { // Run an app with JMX enabled and with some properties set // in command line. // stop JMX agent and then start it again with different property values // stop JMX agent again and then start it without property value // make sure these properties overridden corectly - System.out.println("**** Test ten ****"); - PortAllocator pa = new PortAllocator(); - + System.out.println("**** Test thirteen ****"); + int[] ports = PortAllocator.allocatePorts(1); Something s = doSomething( - "test_10", - "-Dcom.sun.management.jmxremote.port=" + pa.getPort1(), - "-Dcom.sun.management.jmxremote.authenticate=false", - "-Dcom.sun.management.jmxremote.ssl=true"); + "test_13", + "-Dcom.sun.management.jmxremote.port=" + ports[0], + "-Dcom.sun.management.jmxremote.authenticate=false", + "-Dcom.sun.management.jmxremote.ssl=true"); try { - testNoConnect(pa.getPort1()); + testNoConnect(ports[0]); jcmd(CMD_STOP); jcmd(CMD_START, - "jmxremote.ssl=false", - "jmxremote.port=" + pa.getPort1() + "jmxremote.ssl=false", + "jmxremote.port=" + ports[0] ); - testConnect(pa.getPort1()); + testConnect(ports[0]); jcmd(CMD_STOP); jcmd(CMD_START, - "jmxremote.port=" + pa.getPort1() + "jmxremote.port=" + ports[0] ); - testNoConnect(pa.getPort1()); + testNoConnect(ports[0]); } finally { s.stop(); } } - static void test_11() throws Exception { + static void test_14() throws Exception { // Run an app with JMX enabled // stop remote agent // make sure local agent is not affected - System.out.println("**** Test eleven ****"); - PortAllocator pa = new PortAllocator(); - + System.out.println("**** Test fourteen ****"); + int[] ports = PortAllocator.allocatePorts(1); Something s = doSomething( - "test_11", - "-Dcom.sun.management.jmxremote.port=" + pa.getPort1(), - "-Dcom.sun.management.jmxremote.authenticate=false", - "-Dcom.sun.management.jmxremote.ssl=false"); + "test_14", + "-Dcom.sun.management.jmxremote.port=" + ports[0], + "-Dcom.sun.management.jmxremote.authenticate=false", + "-Dcom.sun.management.jmxremote.ssl=false"); try { - testConnect(pa.getPort1()); + testConnect(ports[0]); jcmd(CMD_STOP); testConnectLocal(s.getPid()); } finally { @@ -818,17 +911,17 @@ public class JMXStartStopTest { } } - static void test_12() throws Exception { + static void test_15() throws Exception { // Run an app with JMX disabled // start local agent only - System.out.println("**** Test twelve ****"); + System.out.println("**** Test fifteen ****"); - Something s = doSomething("test_12"); - PortAllocator pa = new PortAllocator(); + int[] ports = PortAllocator.allocatePorts(1); + Something s = doSomething("test_15"); try { - testNoConnect(pa.getPort1()); + testNoConnect(ports[0]); jcmd(CMD_START + "_local"); testConnectLocal(s.getPid()); From ee2ba7946a5cbe49098aa236befc4e7fad25e307 Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Fri, 6 Feb 2015 11:38:29 +0800 Subject: [PATCH 05/25] 8072615: test/lib/testlibrary/jdk/testlibrary/SimpleSSLContext.java wrong on Windows Reviewed-by: xuelei --- jdk/test/lib/testlibrary/jdk/testlibrary/SimpleSSLContext.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/test/lib/testlibrary/jdk/testlibrary/SimpleSSLContext.java b/jdk/test/lib/testlibrary/jdk/testlibrary/SimpleSSLContext.java index 57a74fcf794..4fedb362c5c 100644 --- a/jdk/test/lib/testlibrary/jdk/testlibrary/SimpleSSLContext.java +++ b/jdk/test/lib/testlibrary/jdk/testlibrary/SimpleSSLContext.java @@ -56,7 +56,7 @@ public class SimpleSSLContext { */ public SimpleSSLContext () throws IOException { String paths = System.getProperty("test.src.path"); - StringTokenizer st = new StringTokenizer(paths,":"); + StringTokenizer st = new StringTokenizer(paths, File.pathSeparator); boolean securityExceptions = false; while (st.hasMoreTokens()) { String path = st.nextToken(); From c9bf298a67f5402f5f73434bca0d70b38dbdb296 Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Fri, 6 Feb 2015 09:57:28 +0100 Subject: [PATCH 06/25] 8071329: Stop exporting INCLUDE and LIB when building on windows Reviewed-by: ihse --- jdk/make/launcher/Launcher-jdk.runtime.gmk | 38 ++++------------------ 1 file changed, 6 insertions(+), 32 deletions(-) diff --git a/jdk/make/launcher/Launcher-jdk.runtime.gmk b/jdk/make/launcher/Launcher-jdk.runtime.gmk index 220c2ff40e8..96c02be5689 100644 --- a/jdk/make/launcher/Launcher-jdk.runtime.gmk +++ b/jdk/make/launcher/Launcher-jdk.runtime.gmk @@ -66,19 +66,6 @@ UNPACKEXE_LANG := C ifeq ($(OPENJDK_TARGET_OS), solaris) UNPACKEXE_LANG := C++ endif -UNPACKEXE_DEBUG_SYMBOLS := true -# On windows, unpack200 is linked completely differently to all other -# executables, using the compiler with the compiler arguments. -# It's also linked incrementally, producing a .ilk file that needs to -# be kept away. -ifeq ($(OPENJDK_TARGET_OS), windows) - BUILD_UNPACKEXE_LDEXE := $(CC) - EXE_OUT_OPTION_save := $(EXE_OUT_OPTION) - EXE_OUT_OPTION := -Fe - # With the current way unpack200 is built, debug symbols aren't supported - # anyway. - UNPACKEXE_DEBUG_SYMBOLS := false -endif # The linker on older SuSE distros (e.g. on SLES 10) complains with: # "Invalid version tag `SUNWprivate_1.1'. Only anonymous version tag is allowed in executable." @@ -93,49 +80,36 @@ $(eval $(call SetupNativeCompilation,BUILD_UNPACKEXE, \ SRC := $(UNPACKEXE_SRC), \ LANG := $(UNPACKEXE_LANG), \ OPTIMIZATION := LOW, \ - CFLAGS := $(UNPACKEXE_CFLAGS) $(CXXFLAGS_JDKEXE) \ - -DFULL, \ + CFLAGS := $(UNPACKEXE_CFLAGS) $(CXXFLAGS_JDKEXE) -DFULL, \ CFLAGS_release := -DPRODUCT, \ CFLAGS_linux := -fPIC, \ CFLAGS_solaris := -KPIC, \ CFLAGS_macosx := -fPIC, \ MAPFILE := $(UNPACK_MAPFILE),\ - LDFLAGS := $(UNPACKEXE_ZIPOBJS), \ - LDFLAGS_windows := $(CXXFLAGS_JDKEXE), \ - LDFLAGS_unix := $(LDFLAGS_JDKEXE) $(LDFLAGS_CXX_JDK) \ + LDFLAGS := $(UNPACKEXE_ZIPOBJS) \ + $(LDFLAGS_JDKEXE) $(LDFLAGS_CXX_JDK) \ $(call SET_SHARED_LIBRARY_NAME,$(LIBRARY_PREFIX)unpack$(SHARED_LIBRARY_SUFFIX)) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ LDFLAGS_linux := -lc, \ LDFLAGS_solaris := $(UNPACKEXE_LDFLAGS_solaris) -lc, \ LDFLAGS_SUFFIX := $(LIBCXX), \ OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/unpackexe$(OUTPUT_SUBDIR), \ - OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/unpackexe$(OUTPUT_SUBDIR), \ + OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/modules_cmds/$(MODULE), \ PROGRAM := unpack200, \ VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \ RC_FLAGS := $(RC_FLAGS) \ -D "JDK_FNAME=unpack200.exe" \ -D "JDK_INTERNAL_NAME=unpack200" \ -D "JDK_FTYPE=0x1L", \ - DEBUG_SYMBOLS := $(UNPACKEXE_DEBUG_SYMBOLS), \ + DEBUG_SYMBOLS := true, \ MANIFEST := $(JDK_TOPDIR)/src/jdk.runtime/windows/native/unpack200/unpack200_proto.exe.manifest)) -ifeq ($(OPENJDK_TARGET_OS), windows) - EXE_OUT_OPTION := $(EXE_OUT_OPTION_save) -endif - ifneq ($(USE_EXTERNAL_LIBZ), true) $(BUILD_UNPACKEXE): $(UNPACKEXE_ZIPOBJS) endif -# Build into object dir and copy executable afterwards to avoid .ilk file in -# image. The real fix would be clean up linking of unpack200 using -# -link -incremental:no -# like all other launchers. -$(SUPPORT_OUTPUTDIR)/modules_cmds/$(MODULE)/unpack200$(EXE_SUFFIX): $(BUILD_UNPACKEXE) - $(call install-file) - -TARGETS += $(SUPPORT_OUTPUTDIR)/modules_cmds/$(MODULE)/unpack200$(EXE_SUFFIX) +TARGETS += $(BUILD_UNPACKEXE) ################################################################################ From 980fb58833d51d504527498eff872c081fd5495c Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Fri, 6 Feb 2015 08:05:44 -0800 Subject: [PATCH 07/25] 8072495: (fs) Path.relativize() gives incorrect result for empty path on Windows Correct handling of empty path in Windows version of relativize() Reviewed-by: alanb, dfuchs --- .../java.base/windows/classes/sun/nio/fs/WindowsPath.java | 4 ++++ jdk/test/java/nio/file/Path/PathOps.java | 6 ++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsPath.java b/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsPath.java index afa24e40cf3..689564dc3bb 100644 --- a/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsPath.java +++ b/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsPath.java @@ -391,6 +391,10 @@ class WindowsPath implements Path { if (!this.root.equalsIgnoreCase(other.root)) throw new IllegalArgumentException("'other' has different root"); + // this path is the empty path + if (this.isEmpty()) + return other; + int bn = this.getNameCount(); int cn = other.getNameCount(); diff --git a/jdk/test/java/nio/file/Path/PathOps.java b/jdk/test/java/nio/file/Path/PathOps.java index f237f68ccaa..4aa1369c4f3 100644 --- a/jdk/test/java/nio/file/Path/PathOps.java +++ b/jdk/test/java/nio/file/Path/PathOps.java @@ -22,7 +22,7 @@ */ /* @test - * @bug 4313887 6838333 6925932 7006126 8037945 + * @bug 4313887 6838333 6925932 7006126 8037945 8072495 * @summary Unit test for java.nio.file.Path path operations */ @@ -516,7 +516,9 @@ public class PathOps { .relativize("\\\\server\\share\\bar", "..\\bar") .relativize("\\\\server\\share\\foo", ""); test("") - .relativize("", ""); + .relativize("", "") + .relativize("a", "a") + .relativize("a\\b\\c", "a\\b\\c"); // normalize test("C:\\") From 8d8f34b9a629e1c99a6a874843dfb1aa2e47a824 Mon Sep 17 00:00:00 2001 From: Roger Riggs Date: Fri, 6 Feb 2015 17:29:11 -0500 Subject: [PATCH 08/25] 8067800: Unexpected DateTimeException in the java.time.chrono.HijrahChronology.isLeapYear Check the year range consistently with other Hijrah date years Reviewed-by: lancea, scolebourne --- .../classes/java/time/chrono/Chronology.java | 7 +++++++ .../java/time/chrono/HijrahChronology.java | 6 +++--- .../time/chrono/TestUmmAlQuraChronology.java | 20 +++++++++++++++++++ 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/time/chrono/Chronology.java b/jdk/src/java.base/share/classes/java/time/chrono/Chronology.java index 7088af36f3c..fbcdcec3472 100644 --- a/jdk/src/java.base/share/classes/java/time/chrono/Chronology.java +++ b/jdk/src/java.base/share/classes/java/time/chrono/Chronology.java @@ -538,7 +538,14 @@ public interface Chronology extends Comparable { *
    *
  • a leap-year must imply a year-length longer than a non leap-year. *
  • a chronology that does not support the concept of a year must return false. + *
  • the correct result must be returned for all years within the + * valid range of years for the chronology. *
+ *

+ * Outside the range of valid years an implementation is free to return + * either a best guess or false. + * An implementation must not throw an exception, even if the year is + * outside the range of valid years. * * @param prolepticYear the proleptic-year to check, not validated for range * @return true if the year is a leap year diff --git a/jdk/src/java.base/share/classes/java/time/chrono/HijrahChronology.java b/jdk/src/java.base/share/classes/java/time/chrono/HijrahChronology.java index 5dfee287fd8..0e79b696db3 100644 --- a/jdk/src/java.base/share/classes/java/time/chrono/HijrahChronology.java +++ b/jdk/src/java.base/share/classes/java/time/chrono/HijrahChronology.java @@ -475,10 +475,10 @@ public final class HijrahChronology extends AbstractChronology implements Serial @Override public boolean isLeapYear(long prolepticYear) { checkCalendarInit(); - int epochMonth = yearToEpochMonth((int) prolepticYear); - if (epochMonth < 0 || epochMonth > maxEpochDay) { - throw new DateTimeException("Hijrah date out of range"); + if (prolepticYear < getMinimumYear() || prolepticYear > getMaximumYear()) { + return false; } + int epochMonth = yearToEpochMonth((int) prolepticYear); int len = getYearLength((int) prolepticYear); return (len > 354); } diff --git a/jdk/test/java/time/test/java/time/chrono/TestUmmAlQuraChronology.java b/jdk/test/java/time/test/java/time/chrono/TestUmmAlQuraChronology.java index 9fbe6d1c017..ff64add432b 100644 --- a/jdk/test/java/time/test/java/time/chrono/TestUmmAlQuraChronology.java +++ b/jdk/test/java/time/test/java/time/chrono/TestUmmAlQuraChronology.java @@ -30,6 +30,7 @@ import static java.time.temporal.ChronoField.DAY_OF_YEAR; import static java.time.temporal.ChronoField.MONTH_OF_YEAR; import static java.time.temporal.ChronoField.YEAR; import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; import static org.testng.Assert.fail; @@ -71,6 +72,7 @@ import org.testng.annotations.Test; /** * Tests for the Umm alQura chronology and data. * Note: The dates used for testing are just a sample of calendar data. + * @bug 8067800 */ @Test public class TestUmmAlQuraChronology { @@ -530,6 +532,24 @@ public class TestUmmAlQuraChronology { assertEquals(date.isLeapYear(), leapyear); } + // Data provider to verify that a given hijrah year is outside the range of supported years + // The values are dependent on the currently configured UmmAlQura calendar data + @DataProvider(name="OutOfRangeLeapYears") + Object[][] data_invalid_leapyears() { + return new Object[][] { + {1299}, + {1601}, + {Integer.MAX_VALUE}, + {Integer.MIN_VALUE}, + }; + } + + @Test(dataProvider="OutOfRangeLeapYears") + public void test_notLeapYears(int y) { + assertFalse(HijrahChronology.INSTANCE.isLeapYear(y), "Out of range leap year"); + } + + // Date samples to convert HijrahDate to LocalDate and vice versa @DataProvider(name="samples") Object[][] data_samples() { From c8528fd41032e19da29994f45887e2aab935bcde Mon Sep 17 00:00:00 2001 From: Mandy Chung Date: Fri, 6 Feb 2015 15:42:07 -0800 Subject: [PATCH 09/25] 8057645: Deprivilege JAX-WS, JAXB, JAF to extension class loader Reviewed-by: alanb, dfuchs, lancea, mkos --- .../classes/build/tools/module/boot.modules | 4 ---- .../classes/build/tools/module/ext.modules | 4 ++++ .../java.base/share/conf/security/java.policy | 23 +++++++++++++++++++ 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/jdk/make/src/classes/build/tools/module/boot.modules b/jdk/make/src/classes/build/tools/module/boot.modules index d51fbfb4913..7c7748e4167 100644 --- a/jdk/make/src/classes/build/tools/module/boot.modules +++ b/jdk/make/src/classes/build/tools/module/boot.modules @@ -1,7 +1,5 @@ java.base java.desktop -java.activation -java.annotations.common java.compiler java.corba java.instrument @@ -18,9 +16,7 @@ java.sql java.sql.rowset java.transaction java.xml -java.xml.bind java.xml.crypto -java.xml.ws jdk.charsets jdk.deploy jdk.deploy.osx diff --git a/jdk/make/src/classes/build/tools/module/ext.modules b/jdk/make/src/classes/build/tools/module/ext.modules index ac6b6a2ac2f..882ead8ce76 100644 --- a/jdk/make/src/classes/build/tools/module/ext.modules +++ b/jdk/make/src/classes/build/tools/module/ext.modules @@ -1,3 +1,7 @@ +java.activation +java.annotations.common +java.xml.bind +java.xml.ws jdk.crypto.ec jdk.crypto.mscapi jdk.crypto.pkcs11 diff --git a/jdk/src/java.base/share/conf/security/java.policy b/jdk/src/java.base/share/conf/security/java.policy index 3cfcb22a1c0..2ca6ec7f1b2 100644 --- a/jdk/src/java.base/share/conf/security/java.policy +++ b/jdk/src/java.base/share/conf/security/java.policy @@ -55,6 +55,29 @@ grant codeBase "jrt:/jdk.crypto.pkcs11" { permission java.io.FilePermission "<>", "read"; }; +grant codeBase "jrt:/java.xml.ws" { + permission java.lang.RuntimePermission "accessClassInPackage.com.sun.xml.internal.*"; + permission java.lang.RuntimePermission "accessClassInPackage.com.sun.istack.internal"; + permission java.lang.RuntimePermission "accessClassInPackage.com.sun.istack.internal.*"; + permission java.lang.RuntimePermission "accessClassInPackage.com.sun.org.apache.xerces.internal.*"; + permission java.lang.RuntimePermission "accessDeclaredMembers"; + permission java.lang.reflect.ReflectPermission "suppressAccessChecks"; + permission java.util.PropertyPermission "*", "read"; +}; + +grant codeBase "jrt:/java.xml.bind" { + permission java.lang.RuntimePermission "accessClassInPackage.com.sun.xml.internal.*"; + permission java.lang.RuntimePermission "accessClassInPackage.com.sun.istack.internal"; + permission java.lang.RuntimePermission "accessClassInPackage.com.sun.istack.internal.*"; + permission java.lang.RuntimePermission "accessDeclaredMembers"; + permission java.lang.reflect.ReflectPermission "suppressAccessChecks"; + permission java.util.PropertyPermission "*", "read"; +}; + +grant codeBase "jrt:/java.activation" { + permission java.security.AllPermission; +}; + // default permissions granted to all domains grant { From 81f4c6102a5c0385bdc0331e3067608f009cf494 Mon Sep 17 00:00:00 2001 From: Xueming Shen Date: Mon, 9 Feb 2015 11:37:56 -0800 Subject: [PATCH 10/25] 8030179: java/nio/Buffer/Chars.java, testcases seems all pass but jtreg/testng failed with java.lang.AssertionError Fix the surrogate corner case in SingleByte charset encoder Reviewed-by: psandoz, alanb --- .../share/classes/sun/nio/cs/SingleByte.java | 15 ++-- .../classes/sun/nio/cs/StreamEncoder.java | 37 ++++---- jdk/test/sun/nio/cs/StreamEncoderOut.java | 90 +++++++++++++++++++ 3 files changed, 116 insertions(+), 26 deletions(-) create mode 100644 jdk/test/sun/nio/cs/StreamEncoderOut.java diff --git a/jdk/src/java.base/share/classes/sun/nio/cs/SingleByte.java b/jdk/src/java.base/share/classes/sun/nio/cs/SingleByte.java index bf9146c40f7..093d1aaea3a 100644 --- a/jdk/src/java.base/share/classes/sun/nio/cs/SingleByte.java +++ b/jdk/src/java.base/share/classes/sun/nio/cs/SingleByte.java @@ -160,22 +160,18 @@ public class SingleByte byte[] da = dst.array(); int dp = dst.arrayOffset() + dst.position(); int dl = dst.arrayOffset() + dst.limit(); + int len = Math.min(dl - dp, sl - sp); - CoderResult cr = CoderResult.UNDERFLOW; - if ((dl - dp) < (sl - sp)) { - sl = sp + (dl - dp); - cr = CoderResult.OVERFLOW; - } - - while (sp < sl) { + while (len-- > 0) { char c = sa[sp]; int b = encode(c); if (b == UNMAPPABLE_ENCODING) { if (Character.isSurrogate(c)) { if (sgp == null) sgp = new Surrogate.Parser(); - if (sgp.parse(c, sa, sp, sl) < 0) + if (sgp.parse(c, sa, sp, sl) < 0) { return withResult(sgp.error(), src, sp, dst, dp); + } return withResult(sgp.unmappableResult(), src, sp, dst, dp); } return withResult(CoderResult.unmappableForLength(1), @@ -184,7 +180,8 @@ public class SingleByte da[dp++] = (byte)b; sp++; } - return withResult(cr, src, sp, dst, dp); + return withResult(sp < sl ? CoderResult.OVERFLOW : CoderResult.UNDERFLOW, + src, sp, dst, dp); } private CoderResult encodeBufferLoop(CharBuffer src, ByteBuffer dst) { diff --git a/jdk/src/java.base/share/classes/sun/nio/cs/StreamEncoder.java b/jdk/src/java.base/share/classes/sun/nio/cs/StreamEncoder.java index a3aaf3675d9..fd72238d89f 100644 --- a/jdk/src/java.base/share/classes/sun/nio/cs/StreamEncoder.java +++ b/jdk/src/java.base/share/classes/sun/nio/cs/StreamEncoder.java @@ -243,8 +243,11 @@ public class StreamEncoder extends Writer if (cr.isUnderflow()) { if (lcb.hasRemaining()) { leftoverChar = lcb.get(); - if (cb != null && cb.hasRemaining()) - flushLeftoverChar(cb, endOfInput); + if (cb != null && cb.hasRemaining()) { + lcb.clear(); + lcb.put(leftoverChar).put(cb.get()).flip(); + continue; + } return; } break; @@ -265,24 +268,24 @@ public class StreamEncoder extends Writer CharBuffer cb = CharBuffer.wrap(cbuf, off, len); if (haveLeftoverChar) - flushLeftoverChar(cb, false); + flushLeftoverChar(cb, false); while (cb.hasRemaining()) { - CoderResult cr = encoder.encode(cb, bb, false); - if (cr.isUnderflow()) { - assert (cb.remaining() <= 1) : cb.remaining(); - if (cb.remaining() == 1) { - haveLeftoverChar = true; - leftoverChar = cb.get(); + CoderResult cr = encoder.encode(cb, bb, false); + if (cr.isUnderflow()) { + assert (cb.remaining() <= 1) : cb.remaining(); + if (cb.remaining() == 1) { + haveLeftoverChar = true; + leftoverChar = cb.get(); + } + break; } - break; - } - if (cr.isOverflow()) { - assert bb.position() > 0; - writeBytes(); - continue; - } - cr.throwException(); + if (cr.isOverflow()) { + assert bb.position() > 0; + writeBytes(); + continue; + } + cr.throwException(); } } diff --git a/jdk/test/sun/nio/cs/StreamEncoderOut.java b/jdk/test/sun/nio/cs/StreamEncoderOut.java new file mode 100644 index 00000000000..90a22512311 --- /dev/null +++ b/jdk/test/sun/nio/cs/StreamEncoderOut.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2015, 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 8030179 + @summary test if the charset encoder deails with surrogate correctly + * @run testng/othervm -esa StreamEncoderOut + */ +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.nio.charset.Charset; +import java.util.stream.Stream; + +import static java.util.stream.Collectors.joining; + +@Test +public class StreamEncoderOut { + + enum Input { + HIGH("\ud834"), + LOW("\udd1e"), + HIGH_LOW("\ud834\udd1e"); + + final String value; + + Input(String value) { + this.value = value; + } + + @Override + public String toString() { + return name() + " : \'" + value + "\""; + } + } + + @DataProvider(name = "CharsetAndString") + // [Charset, Input] + public static Object[][] makeStreamTestData() { + // Cross product of supported charsets and inputs + return Charset.availableCharsets().values().stream(). + filter(Charset::canEncode). + flatMap(cs -> Stream.of(Input.values()).map(i -> new Object[]{cs, i})). + toArray(Object[][]::new); + } + + private static String generate(String s, int n) { + return Stream.generate(() -> s).limit(n).collect(joining()); + } + + static final OutputStream DEV_NULL = new OutputStream() { + @Override + public void write(byte b[], int off, int len) throws IOException {} + + @Override + public void write(int b) throws IOException {} + }; + + @Test(dataProvider = "CharsetAndString") + public void test(Charset cs, Input input) throws IOException { + OutputStreamWriter w = new OutputStreamWriter(DEV_NULL, cs); + String t = generate(input.value, 8193); + for (int i = 0; i < 10; i++) { + w.append(t); + } + } +} From 5c350798952ec9a2f8ee8e6816805040feaa4aed Mon Sep 17 00:00:00 2001 From: Florian Weimer Date: Mon, 9 Feb 2015 13:32:42 -0800 Subject: [PATCH 11/25] 8069072: GHASH performance improvement Eliminate allocations and vectorize Reviewed-by: mullan, ascarpino --- .../com/sun/crypto/provider/GHASH.java | 145 +++++++++------ .../crypto/provider/Cipher/AES/TestGHASH.java | 166 ++++++++++++++++++ 2 files changed, 253 insertions(+), 58 deletions(-) create mode 100644 jdk/test/com/sun/crypto/provider/Cipher/AES/TestGHASH.java diff --git a/jdk/src/java.base/share/classes/com/sun/crypto/provider/GHASH.java b/jdk/src/java.base/share/classes/com/sun/crypto/provider/GHASH.java index 8b0ba28e898..ee747c8e36c 100644 --- a/jdk/src/java.base/share/classes/com/sun/crypto/provider/GHASH.java +++ b/jdk/src/java.base/share/classes/com/sun/crypto/provider/GHASH.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015 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 @@ -28,9 +29,7 @@ package com.sun.crypto.provider; -import java.util.Arrays; -import java.security.*; -import static com.sun.crypto.provider.AESConstants.AES_BLOCK_SIZE; +import java.security.ProviderException; /** * This class represents the GHASH function defined in NIST 800-38D @@ -44,62 +43,90 @@ import static com.sun.crypto.provider.AESConstants.AES_BLOCK_SIZE; */ final class GHASH { - private static final byte P128 = (byte) 0xe1; //reduction polynomial - - private static boolean getBit(byte[] b, int pos) { - int p = pos / 8; - pos %= 8; - int i = (b[p] >>> (7 - pos)) & 1; - return i != 0; + private static long getLong(byte[] buffer, int offset) { + long result = 0; + int end = offset + 8; + for (int i = offset; i < end; ++i) { + result = (result << 8) + (buffer[i] & 0xFF); + } + return result; } - private static void shift(byte[] b) { - byte temp, temp2; - temp2 = 0; - for (int i = 0; i < b.length; i++) { - temp = (byte) ((b[i] & 0x01) << 7); - b[i] = (byte) ((b[i] & 0xff) >>> 1); - b[i] = (byte) (b[i] | temp2); - temp2 = temp; + private static void putLong(byte[] buffer, int offset, long value) { + int end = offset + 8; + for (int i = end - 1; i >= offset; --i) { + buffer[i] = (byte) value; + value >>= 8; } } - // Given block X and Y, returns the muliplication of X * Y - private static byte[] blockMult(byte[] x, byte[] y) { - if (x.length != AES_BLOCK_SIZE || y.length != AES_BLOCK_SIZE) { - throw new RuntimeException("illegal input sizes"); - } - byte[] z = new byte[AES_BLOCK_SIZE]; - byte[] v = y.clone(); - // calculate Z1-Z127 and V1-V127 - for (int i = 0; i < 127; i++) { + private static final int AES_BLOCK_SIZE = 16; + + // Multiplies state0, state1 by V0, V1. + private void blockMult(long V0, long V1) { + long Z0 = 0; + long Z1 = 0; + long X; + + // Separate loops for processing state0 and state1. + X = state0; + for (int i = 0; i < 64; i++) { // Zi+1 = Zi if bit i of x is 0 - if (getBit(x, i)) { - for (int n = 0; n < z.length; n++) { - z[n] ^= v[n]; - } - } - boolean lastBitOfV = getBit(v, 127); - shift(v); - if (lastBitOfV) v[0] ^= P128; + long mask = X >> 63; + Z0 ^= V0 & mask; + Z1 ^= V1 & mask; + + // Save mask for conditional reduction below. + mask = (V1 << 63) >> 63; + + // V = rightshift(V) + long carry = V0 & 1; + V0 = V0 >>> 1; + V1 = (V1 >>> 1) | (carry << 63); + + // Conditional reduction modulo P128. + V0 ^= 0xe100000000000000L & mask; + X <<= 1; } + + X = state1; + for (int i = 64; i < 127; i++) { + // Zi+1 = Zi if bit i of x is 0 + long mask = X >> 63; + Z0 ^= V0 & mask; + Z1 ^= V1 & mask; + + // Save mask for conditional reduction below. + mask = (V1 << 63) >> 63; + + // V = rightshift(V) + long carry = V0 & 1; + V0 = V0 >>> 1; + V1 = (V1 >>> 1) | (carry << 63); + + // Conditional reduction. + V0 ^= 0xe100000000000000L & mask; + X <<= 1; + } + // calculate Z128 - if (getBit(x, 127)) { - for (int n = 0; n < z.length; n++) { - z[n] ^= v[n]; - } - } - return z; + long mask = X >> 63; + Z0 ^= V0 & mask; + Z1 ^= V1 & mask; + + // Save result. + state0 = Z0; + state1 = Z1; } // hash subkey H; should not change after the object has been constructed - private final byte[] subkeyH; + private final long subkeyH0, subkeyH1; // buffer for storing hash - private byte[] state; + private long state0, state1; // variables for save/restore calls - private byte[] stateSave = null; + private long stateSave0, stateSave1; /** * Initializes the cipher in the specified mode with the given key @@ -114,8 +141,8 @@ final class GHASH { if ((subkeyH == null) || subkeyH.length != AES_BLOCK_SIZE) { throw new ProviderException("Internal error"); } - this.subkeyH = subkeyH; - this.state = new byte[AES_BLOCK_SIZE]; + this.subkeyH0 = getLong(subkeyH, 0); + this.subkeyH1 = getLong(subkeyH, 8); } /** @@ -124,31 +151,33 @@ final class GHASH { * this object for different data w/ the same H. */ void reset() { - Arrays.fill(state, (byte) 0); + state0 = 0; + state1 = 0; } /** * Save the current snapshot of this GHASH object. */ void save() { - stateSave = state.clone(); + stateSave0 = state0; + stateSave1 = state1; } /** * Restores this object using the saved snapshot. */ void restore() { - state = stateSave; + state0 = stateSave0; + state1 = stateSave1; } private void processBlock(byte[] data, int ofs) { if (data.length - ofs < AES_BLOCK_SIZE) { throw new RuntimeException("need complete block"); } - for (int n = 0; n < state.length; n++) { - state[n] ^= data[ofs + n]; - } - state = blockMult(state, subkeyH); + state0 ^= getLong(data, ofs); + state1 ^= getLong(data, ofs + 8); + blockMult(subkeyH0, subkeyH1); } void update(byte[] in) { @@ -169,10 +198,10 @@ final class GHASH { } byte[] digest() { - try { - return state.clone(); - } finally { - reset(); - } + byte[] result = new byte[AES_BLOCK_SIZE]; + putLong(result, 0, state0); + putLong(result, 8, state1); + reset(); + return result; } } diff --git a/jdk/test/com/sun/crypto/provider/Cipher/AES/TestGHASH.java b/jdk/test/com/sun/crypto/provider/Cipher/AES/TestGHASH.java new file mode 100644 index 00000000000..8d05806dc5f --- /dev/null +++ b/jdk/test/com/sun/crypto/provider/Cipher/AES/TestGHASH.java @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2015, 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 8069072 + * @summary Test vectors for com.sun.crypto.provider.GHASH + */ +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.nio.ByteBuffer; + +public class TestGHASH { + + private final Constructor GHASH; + private final Method UPDATE; + private final Method DIGEST; + + TestGHASH(String className) throws Exception { + Class cls = Class.forName(className); + GHASH = cls.getDeclaredConstructor(byte[].class); + GHASH.setAccessible(true); + UPDATE = cls.getDeclaredMethod("update", byte[].class); + UPDATE.setAccessible(true); + DIGEST = cls.getDeclaredMethod("digest"); + DIGEST.setAccessible(true); + } + + + private Object newGHASH(byte[] H) throws Exception { + return GHASH.newInstance(H); + } + + private void updateGHASH(Object hash, byte[] data) + throws Exception { + UPDATE.invoke(hash, data); + } + + private byte[] digestGHASH(Object hash) throws Exception { + return (byte[]) DIGEST.invoke(hash); + } + + private static final String HEX_DIGITS = "0123456789abcdef"; + + private static String hex(byte[] bs) { + StringBuilder sb = new StringBuilder(2 * bs.length); + for (byte b : bs) { + sb.append(HEX_DIGITS.charAt((b >> 4) & 0xF)); + sb.append(HEX_DIGITS.charAt(b & 0xF)); + } + return sb.toString(); + } + + private static byte[] bytes(String hex) { + if ((hex.length() & 1) != 0) { + throw new AssertionError(); + } + byte[] result = new byte[hex.length() / 2]; + for (int i = 0; i < result.length; ++i) { + int a = HEX_DIGITS.indexOf(hex.charAt(2 * i)); + int b = HEX_DIGITS.indexOf(hex.charAt(2 * i + 1)); + if ((a | b) < 0) { + if (a < 0) { + throw new AssertionError( + "bad character " + (int) hex.charAt(2 * i)); + } + throw new AssertionError( + "bad character " + (int) hex.charAt(2 * i + 1)); + } + result[i] = (byte) ((a << 4) | b); + } + return result; + } + + private static byte[] bytes(long L0, long L1) { + return ByteBuffer.allocate(16) + .putLong(L0) + .putLong(L1) + .array(); + } + + private void check(int testCase, String H, String A, + String C, String expected) throws Exception { + int lenA = A.length() * 4; + while ((A.length() % 32) != 0) { + A += '0'; + } + int lenC = C.length() * 4; + while ((C.length() % 32) != 0) { + C += '0'; + } + + Object hash = newGHASH(bytes(H)); + updateGHASH(hash, bytes(A)); + updateGHASH(hash, bytes(C)); + updateGHASH(hash, bytes(lenA, lenC)); + byte[] digest = digestGHASH(hash); + String actual = hex(digest); + if (!expected.equals(actual)) { + throw new AssertionError(String.format("%d: expected %s, got %s", + testCase, expected, actual)); + } + } + + public static void main(String[] args) throws Exception { + TestGHASH test; + if (args.length == 0) { + test = new TestGHASH("com.sun.crypto.provider.GHASH"); + } else { + test = new TestGHASH(args[0]); + } + + // Test vectors from David A. McGrew, John Viega, + // "The Galois/Counter Mode of Operation (GCM)", 2005. + // + + test.check(1, "66e94bd4ef8a2c3b884cfa59ca342b2e", "", "", + "00000000000000000000000000000000"); + test.check(2, + "66e94bd4ef8a2c3b884cfa59ca342b2e", "", + "0388dace60b6a392f328c2b971b2fe78", + "f38cbb1ad69223dcc3457ae5b6b0f885"); + test.check(3, + "b83b533708bf535d0aa6e52980d53b78", "", + "42831ec2217774244b7221b784d0d49c" + + "e3aa212f2c02a4e035c17e2329aca12e" + + "21d514b25466931c7d8f6a5aac84aa05" + + "1ba30b396a0aac973d58e091473f5985", + "7f1b32b81b820d02614f8895ac1d4eac"); + test.check(4, + "b83b533708bf535d0aa6e52980d53b78", + "feedfacedeadbeeffeedfacedeadbeef" + "abaddad2", + "42831ec2217774244b7221b784d0d49c" + + "e3aa212f2c02a4e035c17e2329aca12e" + + "21d514b25466931c7d8f6a5aac84aa05" + + "1ba30b396a0aac973d58e091", + "698e57f70e6ecc7fd9463b7260a9ae5f"); + test.check(5, "b83b533708bf535d0aa6e52980d53b78", + "feedfacedeadbeeffeedfacedeadbeef" + "abaddad2", + "61353b4c2806934a777ff51fa22a4755" + + "699b2a714fcdc6f83766e5f97b6c7423" + + "73806900e49f24b22b097544d4896b42" + + "4989b5e1ebac0f07c23f4598", + "df586bb4c249b92cb6922877e444d37b"); + } +} From 0d5c151c9463cc5bda65a06e8851fff5fb39bd89 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Mon, 9 Feb 2015 15:33:56 -0800 Subject: [PATCH 12/25] 8041395: Doclint regression in java.net.SocketOption Reviewed-by: lancea --- .../java.base/share/classes/java/net/DatagramSocket.java | 4 +++- .../share/classes/java/net/DatagramSocketImpl.java | 8 ++++++-- .../java.base/share/classes/java/net/ServerSocket.java | 4 +++- jdk/src/java.base/share/classes/java/net/Socket.java | 4 +++- jdk/src/java.base/share/classes/java/net/SocketImpl.java | 4 +++- 5 files changed, 18 insertions(+), 6 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/net/DatagramSocket.java b/jdk/src/java.base/share/classes/java/net/DatagramSocket.java index 5d978e596e2..77a12f247a0 100644 --- a/jdk/src/java.base/share/classes/java/net/DatagramSocket.java +++ b/jdk/src/java.base/share/classes/java/net/DatagramSocket.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2015, 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 @@ -1308,6 +1308,7 @@ class DatagramSocket implements java.io.Closeable { /** * Sets the value of a socket option. * + * @param The type of the socket option value * @param name The socket option * @param value The value of the socket option. A value of {@code null} * may be valid for some options. @@ -1342,6 +1343,7 @@ class DatagramSocket implements java.io.Closeable { /** * Returns the value of a socket option. * + * @param The type of the socket option value * @param name The socket option * * @return The value of the socket option. diff --git a/jdk/src/java.base/share/classes/java/net/DatagramSocketImpl.java b/jdk/src/java.base/share/classes/java/net/DatagramSocketImpl.java index 2abaaf9a237..0726dc4cce7 100644 --- a/jdk/src/java.base/share/classes/java/net/DatagramSocketImpl.java +++ b/jdk/src/java.base/share/classes/java/net/DatagramSocketImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2015, 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 @@ -267,6 +267,7 @@ public abstract class DatagramSocketImpl implements SocketOptions { /** * Called to set a socket option. * + * @param The type of the socket option value * @param name The socket option * * @param value The value of the socket option. A value of {@code null} @@ -276,7 +277,7 @@ public abstract class DatagramSocketImpl implements SocketOptions { * support the option * * @throws NullPointerException if name is {@code null} - * + * @throws IOException if an I/O problem occurs while attempting to set the option * @since 1.9 */ protected void setOption(SocketOption name, T value) throws IOException { @@ -308,12 +309,15 @@ public abstract class DatagramSocketImpl implements SocketOptions { /** * Called to get a socket option. * + * @return the socket option + * @param The type of the socket option value * @param name The socket option * * @throws UnsupportedOperationException if the DatagramSocketImpl does not * support the option * * @throws NullPointerException if name is {@code null} + * @throws IOException if an I/O problem occurs while attempting to set the option * * @since 1.9 */ diff --git a/jdk/src/java.base/share/classes/java/net/ServerSocket.java b/jdk/src/java.base/share/classes/java/net/ServerSocket.java index 32f1b907517..af0c5152d9a 100644 --- a/jdk/src/java.base/share/classes/java/net/ServerSocket.java +++ b/jdk/src/java.base/share/classes/java/net/ServerSocket.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2015, 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 @@ -924,6 +924,7 @@ class ServerSocket implements java.io.Closeable { /** * Sets the value of a socket option. * + * @param The type of the socket option value * @param name The socket option * @param value The value of the socket option. A value of {@code null} * may be valid for some options. @@ -957,6 +958,7 @@ class ServerSocket implements java.io.Closeable { /** * Returns the value of a socket option. * + * @param The type of the socket option value * @param name The socket option * * @return The value of the socket option. diff --git a/jdk/src/java.base/share/classes/java/net/Socket.java b/jdk/src/java.base/share/classes/java/net/Socket.java index e637b32baa7..a0ca24e5224 100644 --- a/jdk/src/java.base/share/classes/java/net/Socket.java +++ b/jdk/src/java.base/share/classes/java/net/Socket.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2015, 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 @@ -1727,6 +1727,7 @@ class Socket implements java.io.Closeable { /** * Sets the value of a socket option. * + * @param The type of the socket option value * @param name The socket option * @param value The value of the socket option. A value of {@code null} * may be valid for some options. @@ -1758,6 +1759,7 @@ class Socket implements java.io.Closeable { /** * Returns the value of a socket option. * + * @param The type of the socket option value * @param name The socket option * * @return The value of the socket option. diff --git a/jdk/src/java.base/share/classes/java/net/SocketImpl.java b/jdk/src/java.base/share/classes/java/net/SocketImpl.java index 962d20167de..600c68457af 100644 --- a/jdk/src/java.base/share/classes/java/net/SocketImpl.java +++ b/jdk/src/java.base/share/classes/java/net/SocketImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2015, 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 @@ -362,6 +362,7 @@ public abstract class SocketImpl implements SocketOptions { /** * Called to set a socket option. * + * @param The type of the socket option value * @param name The socket option * * @param value The value of the socket option. A value of {@code null} @@ -397,6 +398,7 @@ public abstract class SocketImpl implements SocketOptions { /** * Called to get a socket option. * + * @param The type of the socket option value * @param name The socket option * * @return the value of the named option From 127d4e1aecf0fec0fdc6adf1132a5acd78729e70 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Mon, 9 Feb 2015 17:49:26 -0800 Subject: [PATCH 13/25] 8069277: Doclint regression in java/security/KeyStore.java Reviewed-by: weijun --- .../share/classes/java/security/KeyStore.java | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/security/KeyStore.java b/jdk/src/java.base/share/classes/java/security/KeyStore.java index 34c246f4b86..71df7dbd5a2 100644 --- a/jdk/src/java.base/share/classes/java/security/KeyStore.java +++ b/jdk/src/java.base/share/classes/java/security/KeyStore.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, 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 @@ -1618,11 +1618,13 @@ public class KeyStore { * integrity check. * *

- * This method traverses the list of registered security {@link Providers}, - * starting with the most preferred Provider. - * For each {@link KeyStoreSpi} implementation supported by a Provider, - * it invokes the {@link engineProbe} method to determine if it supports - * the specified keystore. + * This method traverses the list of registered security + * {@linkplain Provider providers}, starting with the most + * preferred Provider. + * For each {@link KeyStoreSpi} implementation supported by a + * Provider, it invokes the {@link + * KeyStoreSpi#engineProbe(InputStream) engineProbe} method to + * determine if it supports the specified keystore. * A new KeyStore object is returned that encapsulates the KeyStoreSpi * implementation from the first Provider that supports the specified file. * @@ -1672,11 +1674,12 @@ public class KeyStore { * unlock the keystore data or perform an integrity check. * *

- * This method traverses the list of registered security {@link Providers}, - * starting with the most preferred Provider. - * For each {@link KeyStoreSpi} implementation supported by a Provider, - * it invokes the {@link engineProbe} method to determine if it supports - * the specified keystore. + * This method traverses the list of registered security {@linkplain + * Provider providers}, starting with the most preferred Provider. + * For each {@link KeyStoreSpi} implementation supported by a + * Provider, it invokes the {@link + * KeyStoreSpi#engineProbe(InputStream) engineProbe} method to + * determine if it supports the specified keystore. * A new KeyStore object is returned that encapsulates the KeyStoreSpi * implementation from the first Provider that supports the specified file. * From 31d47aea0fb91f723a6f1038af7296700bcd946f Mon Sep 17 00:00:00 2001 From: Athijegannathan Sundararajan Date: Tue, 10 Feb 2015 14:44:33 +0530 Subject: [PATCH 14/25] 8068587: ScriptEngineFactory.getParameter() should specify NPE for a null key Reviewed-by: alanb, lagergren --- .../share/classes/javax/script/ScriptEngineFactory.java | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/src/java.scripting/share/classes/javax/script/ScriptEngineFactory.java b/jdk/src/java.scripting/share/classes/javax/script/ScriptEngineFactory.java index 7692a0aaec7..2afe0c25769 100644 --- a/jdk/src/java.scripting/share/classes/javax/script/ScriptEngineFactory.java +++ b/jdk/src/java.scripting/share/classes/javax/script/ScriptEngineFactory.java @@ -138,6 +138,7 @@ public interface ScriptEngineFactory { * @return The value for the given parameter. Returns null if no * value is assigned to the key. * + * @throws NullPointerException if the key is null. */ public Object getParameter(String key); From 7c67f47c4d304d207b4c7f3d2a71db6c8871c04a Mon Sep 17 00:00:00 2001 From: Paul Sandoz Date: Tue, 10 Feb 2015 11:18:51 +0100 Subject: [PATCH 15/25] 8050819: Please add java.util.Stream.ofNullable(T object) Reviewed-by: alanb, smarks --- .../classes/java/util/stream/Stream.java | 15 ++++++++++ .../java/util/stream/StreamBuilderTest.java | 30 ++++++++++++++++--- 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/util/stream/Stream.java b/jdk/src/java.base/share/classes/java/util/stream/Stream.java index bd915796272..0070658b01f 100644 --- a/jdk/src/java.base/share/classes/java/util/stream/Stream.java +++ b/jdk/src/java.base/share/classes/java/util/stream/Stream.java @@ -987,6 +987,21 @@ public interface Stream extends BaseStream> { return StreamSupport.stream(new Streams.StreamBuilderImpl<>(t), false); } + /** + * Returns a sequential {@code Stream} containing a single element, if + * non-null, otherwise returns an empty {@code Stream}. + * + * @param t the single element + * @param the type of stream elements + * @return a stream with a single element if the specified element + * is non-null, otherwise an empty stream + * @since 1.9 + */ + public static Stream ofNullable(T t) { + return t == null ? Stream.empty() + : StreamSupport.stream(new Streams.StreamBuilderImpl<>(t), false); + } + /** * Returns a sequential ordered stream whose elements are the specified values. * diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/StreamBuilderTest.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/StreamBuilderTest.java index 352f3cc7099..a6fb7e0e398 100644 --- a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/StreamBuilderTest.java +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/StreamBuilderTest.java @@ -54,9 +54,31 @@ public class StreamBuilderTest extends OpTestCase { } + @Test + public void testOfNullableWithNonNull() { + TestData.OfRef data = TestData.Factory.ofSupplier("{1}", + () -> Stream.ofNullable(1)); + + withData(data). + stream(s -> s). + expectedResult(Collections.singletonList(1)). + exercise(); + } + + @Test + public void testOfNullableWithNull() { + TestData.OfRef data = TestData.Factory.ofSupplier("{null})", + () -> Stream.ofNullable(null)); + + withData(data). + stream(s -> s). + expectedResult(Collections.emptyList()). + exercise(); + } + @Test public void testSingleton() { - TestData.OfRef data = TestData.Factory.ofSupplier("[0, 1)", + TestData.OfRef data = TestData.Factory.ofSupplier("{1}", () -> Stream.of(1)); withData(data). @@ -118,7 +140,7 @@ public class StreamBuilderTest extends OpTestCase { @Test public void testIntSingleton() { - TestData.OfInt data = TestData.Factory.ofIntSupplier("[0, 1)", + TestData.OfInt data = TestData.Factory.ofIntSupplier("{1}", () -> IntStream.of(1)); withData(data). @@ -180,7 +202,7 @@ public class StreamBuilderTest extends OpTestCase { @Test public void testLongSingleton() { - TestData.OfLong data = TestData.Factory.ofLongSupplier("[0, 1)", + TestData.OfLong data = TestData.Factory.ofLongSupplier("{1}", () -> LongStream.of(1)); withData(data). @@ -242,7 +264,7 @@ public class StreamBuilderTest extends OpTestCase { @Test public void testDoubleSingleton() { - TestData.OfDouble data = TestData.Factory.ofDoubleSupplier("[0, 1)", () -> DoubleStream.of(1)); + TestData.OfDouble data = TestData.Factory.ofDoubleSupplier("{1}", () -> DoubleStream.of(1)); withData(data). stream(s -> s). From 3bf803f0c91e899cf6fb218e4b96fcfa2b105a4d Mon Sep 17 00:00:00 2001 From: Amy Lu Date: Tue, 10 Feb 2015 12:28:02 -0500 Subject: [PATCH 16/25] 8069255: Suppress deprecation warnings in jdk.rmic module (jdk repo) Reviewed-by: rriggs --- .../jdk.rmic/share/classes/sun/rmi/rmic/BatchEnvironment.java | 3 ++- jdk/src/jdk.rmic/share/classes/sun/rmi/rmic/Main.java | 4 ++-- .../jdk.rmic/share/classes/sun/tools/java/BinaryClass.java | 3 ++- .../share/classes/sun/tools/java/ClassDefinition.java | 3 ++- .../share/classes/sun/tools/java/MemberDefinition.java | 3 ++- jdk/src/jdk.rmic/share/classes/sun/tools/java/Scanner.java | 3 ++- 6 files changed, 12 insertions(+), 7 deletions(-) diff --git a/jdk/src/jdk.rmic/share/classes/sun/rmi/rmic/BatchEnvironment.java b/jdk/src/jdk.rmic/share/classes/sun/rmi/rmic/BatchEnvironment.java index 0a4e5435e5f..fff8bb02a0b 100644 --- a/jdk/src/jdk.rmic/share/classes/sun/rmi/rmic/BatchEnvironment.java +++ b/jdk/src/jdk.rmic/share/classes/sun/rmi/rmic/BatchEnvironment.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2015, 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 @@ -61,6 +61,7 @@ import sun.tools.java.ClassPath; * they are subject to change or removal without notice. */ +@SuppressWarnings("deprecation") public class BatchEnvironment extends sun.tools.javac.BatchEnvironment { /** instance of Main which created this environment */ diff --git a/jdk/src/jdk.rmic/share/classes/sun/rmi/rmic/Main.java b/jdk/src/jdk.rmic/share/classes/sun/rmi/rmic/Main.java index de93258d7c8..288ad5270b8 100644 --- a/jdk/src/jdk.rmic/share/classes/sun/rmi/rmic/Main.java +++ b/jdk/src/jdk.rmic/share/classes/sun/rmi/rmic/Main.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2015, 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,7 +676,7 @@ public class Main implements sun.rmi.rmic.Constants { * Compile a single class. * Fallthrough is intentional */ - @SuppressWarnings("fallthrough") + @SuppressWarnings({"fallthrough", "deprecation"}) public boolean compileClass (ClassDeclaration c, ByteArrayOutputStream buf, BatchEnvironment env) diff --git a/jdk/src/jdk.rmic/share/classes/sun/tools/java/BinaryClass.java b/jdk/src/jdk.rmic/share/classes/sun/tools/java/BinaryClass.java index b7d75e44799..6824a855a48 100644 --- a/jdk/src/jdk.rmic/share/classes/sun/tools/java/BinaryClass.java +++ b/jdk/src/jdk.rmic/share/classes/sun/tools/java/BinaryClass.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2015, 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 @@ -39,6 +39,7 @@ import java.util.Enumeration; * supported API. Code that depends on them does so at its own risk: * they are subject to change or removal without notice. */ +@SuppressWarnings("deprecation") public final class BinaryClass extends ClassDefinition implements Constants { BinaryConstantPool cpool; diff --git a/jdk/src/jdk.rmic/share/classes/sun/tools/java/ClassDefinition.java b/jdk/src/jdk.rmic/share/classes/sun/tools/java/ClassDefinition.java index f096205c0f4..039eaa139e0 100644 --- a/jdk/src/jdk.rmic/share/classes/sun/tools/java/ClassDefinition.java +++ b/jdk/src/jdk.rmic/share/classes/sun/tools/java/ClassDefinition.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2015, 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 @@ -41,6 +41,7 @@ import sun.tools.tree.UplevelReference; * supported API. Code that depends on them does so at its own risk: * they are subject to change or removal without notice. */ +@SuppressWarnings("deprecation") public class ClassDefinition implements Constants { diff --git a/jdk/src/jdk.rmic/share/classes/sun/tools/java/MemberDefinition.java b/jdk/src/jdk.rmic/share/classes/sun/tools/java/MemberDefinition.java index c7060e729d0..c426e9e66ac 100644 --- a/jdk/src/jdk.rmic/share/classes/sun/tools/java/MemberDefinition.java +++ b/jdk/src/jdk.rmic/share/classes/sun/tools/java/MemberDefinition.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2015, 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,6 +44,7 @@ import java.util.HashMap; * supported API. Code that depends on them does so at its own risk: * they are subject to change or removal without notice. */ +@SuppressWarnings("deprecation") public class MemberDefinition implements Constants { protected long where; diff --git a/jdk/src/jdk.rmic/share/classes/sun/tools/java/Scanner.java b/jdk/src/jdk.rmic/share/classes/sun/tools/java/Scanner.java index 7dfa6ee37c8..e2112102ae8 100644 --- a/jdk/src/jdk.rmic/share/classes/sun/tools/java/Scanner.java +++ b/jdk/src/jdk.rmic/share/classes/sun/tools/java/Scanner.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2015, 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,6 +58,7 @@ import java.util.Hashtable; * @author Arthur van Hoff */ +@SuppressWarnings("deprecation") public class Scanner implements Constants { /** From 42d24e8ed5663bc09d7bb8f36d38ad94c9d05524 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Tue, 10 Feb 2015 11:34:13 -0800 Subject: [PATCH 17/25] 8072843: Typo in the description of the j.l.r.Executable.getAnnotatedReceiverType Reviewed-by: lancea --- .../java.base/share/classes/java/lang/reflect/Executable.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/src/java.base/share/classes/java/lang/reflect/Executable.java b/jdk/src/java.base/share/classes/java/lang/reflect/Executable.java index ee82de46946..45a2525ec0f 100644 --- a/jdk/src/java.base/share/classes/java/lang/reflect/Executable.java +++ b/jdk/src/java.base/share/classes/java/lang/reflect/Executable.java @@ -662,7 +662,7 @@ public abstract class Executable extends AccessibleObject * * If this {@code Executable} object represents a static method or * represents a constructor of a top level, static member, local, or - * anoymous class, then the return value is null. + * anonymous class, then the return value is null. * * @return an object representing the receiver type of the method or * constructor represented by this {@code Executable} or {@code null} if From 4c95aedcd9159b77184bbbcd2fc79f73773dace2 Mon Sep 17 00:00:00 2001 From: Rob McKenna Date: Tue, 10 Feb 2015 23:32:48 +0000 Subject: [PATCH 18/25] 8065553: Failed Java web start via IPv6 (Java7u71 or later) Reviewed-by: xuelei --- .../sun/security/util/HostnameChecker.java | 13 ++++++++++ .../HostnameMatcher/TestHostnameChecker.java | 6 +++++ .../security/util/HostnameMatcher/cert5.crt | 24 +++++++++++++++++++ 3 files changed, 43 insertions(+) create mode 100644 jdk/test/sun/security/util/HostnameMatcher/cert5.crt diff --git a/jdk/src/java.base/share/classes/sun/security/util/HostnameChecker.java b/jdk/src/java.base/share/classes/sun/security/util/HostnameChecker.java index 1a6f3c2a446..88d98573951 100644 --- a/jdk/src/java.base/share/classes/sun/security/util/HostnameChecker.java +++ b/jdk/src/java.base/share/classes/sun/security/util/HostnameChecker.java @@ -26,6 +26,8 @@ package sun.security.util; import java.io.IOException; +import java.net.InetAddress; +import java.net.UnknownHostException; import java.util.*; import java.security.Principal; @@ -148,6 +150,17 @@ public class HostnameChecker { String ipAddress = (String)next.get(1); if (expectedIP.equalsIgnoreCase(ipAddress)) { return; + } else { + // compare InetAddress objects in order to ensure + // equality between a long IPv6 address and its + // abbreviated form. + try { + if (InetAddress.getByName(expectedIP).equals( + InetAddress.getByName(ipAddress))) { + return; + } + } catch (UnknownHostException e) { + } catch (SecurityException e) {} } } } diff --git a/jdk/test/sun/security/util/HostnameMatcher/TestHostnameChecker.java b/jdk/test/sun/security/util/HostnameMatcher/TestHostnameChecker.java index 7603a460f79..d5ef752f000 100644 --- a/jdk/test/sun/security/util/HostnameMatcher/TestHostnameChecker.java +++ b/jdk/test/sun/security/util/HostnameMatcher/TestHostnameChecker.java @@ -187,6 +187,9 @@ public class TestHostnameChecker { in = new FileInputStream(new File(PATH, "cert4.crt")); X509Certificate cert4 = (X509Certificate)cf.generateCertificate(in); in.close(); + in = new FileInputStream(new File(PATH, "cert5.crt")); + X509Certificate cert5 = (X509Certificate)cf.generateCertificate(in); + in.close(); HostnameChecker checker = HostnameChecker.getInstance( HostnameChecker.TYPE_TLS); @@ -202,6 +205,9 @@ public class TestHostnameChecker { check(checker, "5.6.7.8", cert3, true); check(checker, "foo.bar.com", cert4, true); check(checker, "altfoo.bar.com", cert4, true); + check(checker, "2001:db8:3c4d:15::1a2f:1a2b", cert5, true); + check(checker, "2001:0db8:3c4d:0015:0000:0000:1a2f:1a2b", cert5, true); + check(checker, "2002:db8:3c4d:15::1a2f:1a2b", cert5, false); checker = HostnameChecker.getInstance( HostnameChecker.TYPE_LDAP); diff --git a/jdk/test/sun/security/util/HostnameMatcher/cert5.crt b/jdk/test/sun/security/util/HostnameMatcher/cert5.crt new file mode 100644 index 00000000000..6cca37c87be --- /dev/null +++ b/jdk/test/sun/security/util/HostnameMatcher/cert5.crt @@ -0,0 +1,24 @@ +-----BEGIN CERTIFICATE----- +MIIECDCCAvCgAwIBAgIJAJaBmuUlfY8sMA0GCSqGSIb3DQEBBQUAMIGmMQswCQYD +VQQGEwJVUzETMBEGA1UECAwKU29tZS1TdGF0ZTESMBAGA1UEBwwJU29tZS1DaXR5 +MSowKAYDVQQKDCFVbmNvbmZpZ3VyZWQgT3BlblNTTCBJbnN0YWxsYXRpb24xEDAO +BgNVBAsMB3NlY3Rpb24xMDAuBgNVBAMMJzIwMDE6MGRiODozYzRkOjAwMTU6MDAw +MDowMDAwOjFhMmY6MWEyYjAeFw0xNTAyMTAxODMzMjBaFw0xNTAzMTIxODMzMjBa +MIGmMQswCQYDVQQGEwJVUzETMBEGA1UECAwKU29tZS1TdGF0ZTESMBAGA1UEBwwJ +U29tZS1DaXR5MSowKAYDVQQKDCFVbmNvbmZpZ3VyZWQgT3BlblNTTCBJbnN0YWxs +YXRpb24xEDAOBgNVBAsMB3NlY3Rpb24xMDAuBgNVBAMMJzIwMDE6MGRiODozYzRk +OjAwMTU6MDAwMDowMDAwOjFhMmY6MWEyYjCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAMcigWxmeF6Dmo3xAw3y/8d3vB8Th4YsmvwXb9DxwNWV+B3vxJgq +ww6T6VBxrle1bgu/RtZDJwLf5vMhVElxuuE86di2qyurKFbpe29C9xnCxuMlXpje +X2pNknz4ZzOqD4opmIAFjXZ2Xp1kLt+HJX7ABoz7Uga+IbVfDRPPf2KOqYNpBQkp +dgI5VOZDQNVNb+8vdXDwyanMQ0TgPXKL4BQIkGB4RM8sgpPMUvB+tEB7zmUtgSco +2a5M84wIhxv85CmFFoTVSzXsRCDhVAZj0aHRkkmAsMSmzPa4HiPnuVRV740oQjDy +oMGLndaEs2nxIqckUFHOHcSTf0/wmcvPbIsCAwEAAaM3MDUwCQYDVR0TBAIwADAL +BgNVHQ8EBAMCBeAwGwYDVR0RBBQwEocQIAENuDxNABUAAAAAGi8aKzANBgkqhkiG +9w0BAQUFAAOCAQEAtnelRbYPPZRgTd4oxOiPqwc01EE9JgtkFWlooCwVUDChOR2k +us1qlhKsvbN2Tcsm1Ss3p0Uxk/g1o2/mY8rA/dJ8qiN6jbfjpEi8b2MirP5tQSE0 +QNXbVGr5FnLbuUmn+82pB0vBSaq7gxehbV6S7dteyQUnb2imltC5wS9PwYb8wWx7 +IpyXWt0jkYkC8KJEevVYI7qtwpjYhyc1FqwzUiPmdqGz2AFLQ4RgTXJi93SPoyKM +s65oPV+r6/0qwnslScxVfszHxxFn1Yfsc5Oseare1MnlNzH69PmWs523C/fBvnB2 +MsHKLPdoN7uSpBLB7j46g5jQG/ceri/cquZKYA== +-----END CERTIFICATE----- From 28d199d088809fc5498a4ada2dd9bb95f87d921f Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Wed, 11 Feb 2015 09:59:30 +0100 Subject: [PATCH 19/25] 8072834: jrt-fs.jar missing META-INF/services/java.nio.file.spi.FileSystemProvider Reviewed-by: ihse --- jdk/make/Tools.gmk | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/jdk/make/Tools.gmk b/jdk/make/Tools.gmk index 32174efec0c..0165341c491 100644 --- a/jdk/make/Tools.gmk +++ b/jdk/make/Tools.gmk @@ -147,6 +147,15 @@ $(eval $(call SetupJavaCompilation,BUILD_INTERIM_JIMAGE, \ EXCLUDES := jdk/internal/jimage/concurrent, \ BIN := $(BUILDTOOLS_OUTPUTDIR)/interim_jimage_classes)) +# Because of the explicit INCLUDES in the compilation setup above, the service provider +# file will not be copied unless META-INF/services would also be added to the INCLUDES. +# Adding META-INF/services would include all files in that directory when only the one +# is needed, which is why this explicit copy is defined instead. +$(eval $(call SetupCopyFiles,COPY_JIMAGE_SERVICE_PROVIDER, \ + SRC := $(JDK_TOPDIR)/src/java.base/share/classes, \ + DEST := $(BUILDTOOLS_OUTPUTDIR)/interim_jimage_classes, \ + FILES := META-INF/services/java.nio.file.spi.FileSystemProvider)) + ########################################################################################## # Tools needed on solaris because OBJCOPY is broken. @@ -173,7 +182,7 @@ ifeq ($(OPENJDK_TARGET_OS), solaris) PROGRAM := fix_empty_sec_hdr_flags)) endif -$(BUILD_TOOLS_JDK): $(BUILD_INTERIM_JIMAGE) +$(BUILD_TOOLS_JDK): $(BUILD_INTERIM_JIMAGE) $(COPY_JIMAGE_SERVICE_PROVIDER) java-tools: $(BUILD_TOOLS_JDK) From 9807a1372d141bdd0ed75352228f7622651cfabe Mon Sep 17 00:00:00 2001 From: Shaun Spiller Date: Wed, 11 Feb 2015 07:40:43 -0800 Subject: [PATCH 20/25] 8064562: (doc) errors in java.io.PushbackInputStream API documentation Update the documentation as suggested to reflect reality. Reviewed-by: lancea, rriggs --- .../classes/java/io/PushbackInputStream.java | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/io/PushbackInputStream.java b/jdk/src/java.base/share/classes/java/io/PushbackInputStream.java index d70c73b19c9..fc5439e625b 100644 --- a/jdk/src/java.base/share/classes/java/io/PushbackInputStream.java +++ b/jdk/src/java.base/share/classes/java/io/PushbackInputStream.java @@ -28,9 +28,10 @@ package java.io; /** * A PushbackInputStream adds * functionality to another input stream, namely - * the ability to "push back" or "unread" - * one byte. This is useful in situations where - * it is convenient for a fragment of code + * the ability to "push back" or "unread" bytes, + * by storing pushed-back bytes in an internal buffer. + * This is useful in situations where + * it is convenient for a fragment of code * to read an indefinite number of data bytes * that are delimited by a particular byte * value; after reading the terminating byte, @@ -77,11 +78,9 @@ class PushbackInputStream extends FilterInputStream { /** * Creates a PushbackInputStream * with a pushback buffer of the specified size, - * and saves its argument, the input stream + * and saves its argument, the input stream * in, for later use. Initially, - * there is no pushed-back byte (the field - * pushBack is initialized to - * -1). + * the pushback buffer is empty. * * @param in the input stream from which bytes will be read. * @param size the size of the pushback buffer. @@ -99,11 +98,9 @@ class PushbackInputStream extends FilterInputStream { /** * Creates a PushbackInputStream - * and saves its argument, the input stream + * with a 1-byte pushback buffer, and saves its argument, the input stream * in, for later use. Initially, - * there is no pushed-back byte (the field - * pushBack is initialized to - * -1). + * the pushback buffer is empty. * * @param in the input stream from which bytes will be read. */ From b856eeaa98edeee258d20a0806e21359a93d14cd Mon Sep 17 00:00:00 2001 From: Johannes Scheerer Date: Tue, 10 Feb 2015 10:44:38 +0100 Subject: [PATCH 21/25] 8072611: (process) ProcessBuilder redirecting output to file should work with long file names (win) Reviewed-by: rriggs, simonis --- .../windows/native/libjava/ProcessImpl_md.c | 23 +----- .../windows/native/libjava/io_util_md.h | 3 +- .../RedirectWithLongFilename.java | 79 +++++++++++++++++++ 3 files changed, 83 insertions(+), 22 deletions(-) create mode 100644 jdk/test/java/lang/ProcessBuilder/RedirectWithLongFilename.java diff --git a/jdk/src/java.base/windows/native/libjava/ProcessImpl_md.c b/jdk/src/java.base/windows/native/libjava/ProcessImpl_md.c index 51e24a01129..1bb5896be5f 100644 --- a/jdk/src/java.base/windows/native/libjava/ProcessImpl_md.c +++ b/jdk/src/java.base/windows/native/libjava/ProcessImpl_md.c @@ -30,6 +30,7 @@ #include "jvm.h" #include "jni_util.h" #include "io_util.h" +#include "io_util_md.h" #include #include @@ -467,26 +468,6 @@ Java_java_lang_ProcessImpl_closeHandle(JNIEnv *env, jclass ignored, jlong handle return (jboolean) CloseHandle((HANDLE) handle); } -/** - * Returns a copy of the Unicode characters of a string. Fow now this - * function doesn't handle long path names and other issues. - */ -static WCHAR* getPath(JNIEnv *env, jstring ps) { - WCHAR *pathbuf = NULL; - const jchar *chars = (*(env))->GetStringChars(env, ps, NULL); - if (chars != NULL) { - size_t pathlen = wcslen(chars); - pathbuf = (WCHAR*)malloc((pathlen + 6) * sizeof(WCHAR)); - if (pathbuf == NULL) { - JNU_ThrowOutOfMemoryError(env, NULL); - } else { - wcscpy(pathbuf, chars); - } - (*env)->ReleaseStringChars(env, ps, chars); - } - return pathbuf; -} - JNIEXPORT jlong JNICALL Java_java_lang_ProcessImpl_openForAtomicAppend(JNIEnv *env, jclass ignored, jstring path) { @@ -495,7 +476,7 @@ Java_java_lang_ProcessImpl_openForAtomicAppend(JNIEnv *env, jclass ignored, jstr const DWORD disposition = OPEN_ALWAYS; const DWORD flagsAndAttributes = FILE_ATTRIBUTE_NORMAL; HANDLE h; - WCHAR *pathbuf = getPath(env, path); + WCHAR *pathbuf = pathToNTPath(env, path, JNI_FALSE); if (pathbuf == NULL) { /* Exception already pending */ return -1; diff --git a/jdk/src/java.base/windows/native/libjava/io_util_md.h b/jdk/src/java.base/windows/native/libjava/io_util_md.h index cf925078e94..d85cdd3dead 100644 --- a/jdk/src/java.base/windows/native/libjava/io_util_md.h +++ b/jdk/src/java.base/windows/native/libjava/io_util_md.h @@ -33,7 +33,8 @@ /* * Prototypes for functions in io_util_md.c called from io_util.c, - * FileDescriptor.c, FileInputStream.c, FileOutputStream.c + * FileDescriptor.c, FileInputStream.c, FileOutputStream.c, + * ProcessImpl_md.c */ WCHAR* pathToNTPath(JNIEnv *env, jstring path, jboolean throwFNFE); WCHAR* fileToNTPath(JNIEnv *env, jobject file, jfieldID id); diff --git a/jdk/test/java/lang/ProcessBuilder/RedirectWithLongFilename.java b/jdk/test/java/lang/ProcessBuilder/RedirectWithLongFilename.java new file mode 100644 index 00000000000..c13dda33f8a --- /dev/null +++ b/jdk/test/java/lang/ProcessBuilder/RedirectWithLongFilename.java @@ -0,0 +1,79 @@ +/* + * Copyright 2015 SAP SE. 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 8072611 + * @summary ProcessBuilder Redirect to file appending on Windows should work with long file names + * @author Thomas Stuefe + */ + +import java.io.File; +import java.lang.ProcessBuilder.Redirect; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +public class RedirectWithLongFilename { + + public static void main(String[] args) throws Exception { + + // windows only + if (!Basic.Windows.is()) { + return; + } + + // Redirect ProcessBuilder output to a file whose pathlen is > 255. + Path tmpDir = Paths.get(System.getProperty("java.io.tmpdir")); + File dir2 = null; + File longFileName = null; + + try { + dir2 = Files.createTempDirectory(tmpDir, "RedirectWithLongFilename").toFile(); + dir2.mkdirs(); + longFileName = new File(dir2, + "012345678901234567890123456789012345678901234567890123456789" + + "012345678901234567890123456789012345678901234567890123456789" + + "012345678901234567890123456789012345678901234567890123456789" + + "012345678901234567890123456789012345678901234567890123456789" + + "0123456789"); + + ProcessBuilder pb = new ProcessBuilder("hostname.exe"); + pb.redirectOutput(Redirect.appendTo(longFileName)); + Process p = pb.start(); + p.waitFor(); + + if (longFileName.exists()) { + System.out.println("OK"); + } else { + throw new RuntimeException("Test failed."); + } + + } finally { + longFileName.delete(); + dir2.delete(); + } + + } + +} From 14b8722c45241f7ff6426c418921af6a9aedc725 Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Wed, 11 Feb 2015 17:20:39 -0800 Subject: [PATCH 22/25] 8066842: java.math.BigDecimal.divide(BigDecimal, RoundingMode) produces incorrect result Replace divWord() with non-truncating alternatives Reviewed-by: psandoz, darcy --- .../share/classes/java/math/BigDecimal.java | 78 +++++++++++++------ .../java/math/BigDecimal/DivideTests.java | 58 +++++++++++++- 2 files changed, 109 insertions(+), 27 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/math/BigDecimal.java b/jdk/src/java.base/share/classes/java/math/BigDecimal.java index 1ea1e8276c5..f4fffc871a4 100644 --- a/jdk/src/java.base/share/classes/java/math/BigDecimal.java +++ b/jdk/src/java.base/share/classes/java/math/BigDecimal.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2015, 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 @@ -4814,41 +4814,61 @@ public class BigDecimal extends Number implements Comparable { if (dividendHi >= divisor) { return null; } + final int shift = Long.numberOfLeadingZeros(divisor); divisor <<= shift; final long v1 = divisor >>> 32; final long v0 = divisor & LONG_MASK; - long q1, q0; - long r_tmp; - long tmp = dividendLo << shift; long u1 = tmp >>> 32; long u0 = tmp & LONG_MASK; tmp = (dividendHi << shift) | (dividendLo >>> 64 - shift); long u2 = tmp & LONG_MASK; - tmp = divWord(tmp,v1); - q1 = tmp & LONG_MASK; - r_tmp = tmp >>> 32; + long q1, r_tmp; + if (v1 == 1) { + q1 = tmp; + r_tmp = 0; + } else if (tmp >= 0) { + q1 = tmp / v1; + r_tmp = tmp - q1 * v1; + } else { + long[] rq = divRemNegativeLong(tmp, v1); + q1 = rq[1]; + r_tmp = rq[0]; + } + while(q1 >= DIV_NUM_BASE || unsignedLongCompare(q1*v0, make64(r_tmp, u1))) { q1--; r_tmp += v1; if (r_tmp >= DIV_NUM_BASE) break; } + tmp = mulsub(u2,u1,v1,v0,q1); u1 = tmp & LONG_MASK; - tmp = divWord(tmp,v1); - q0 = tmp & LONG_MASK; - r_tmp = tmp >>> 32; + long q0; + if (v1 == 1) { + q0 = tmp; + r_tmp = 0; + } else if (tmp >= 0) { + q0 = tmp / v1; + r_tmp = tmp - q0 * v1; + } else { + long[] rq = divRemNegativeLong(tmp, v1); + q0 = rq[1]; + r_tmp = rq[0]; + } + while(q0 >= DIV_NUM_BASE || unsignedLongCompare(q0*v0,make64(r_tmp,u0))) { q0--; r_tmp += v1; if (r_tmp >= DIV_NUM_BASE) break; } + if((int)q1 < 0) { // result (which is positive and unsigned here) // can't fit into long due to sign bit is used for value @@ -4871,10 +4891,13 @@ public class BigDecimal extends Number implements Comparable { } } } + long q = make64(q1,q0); q*=sign; + if (roundingMode == ROUND_DOWN && scale == preferredScale) return valueOf(q, scale); + long r = mulsub(u1, u0, v1, v0, q0) >>> shift; if (r != 0) { boolean increment = needIncrement(divisor >>> shift, roundingMode, sign, q, r); @@ -4917,28 +4940,35 @@ public class BigDecimal extends Number implements Comparable { } } - private static long divWord(long n, long dLong) { - long r; - long q; - if (dLong == 1) { - q = (int)n; - return (q & LONG_MASK); - } + /** + * Calculate the quotient and remainder of dividing a negative long by + * another long. + * + * @param n the numerator; must be negative + * @param d the denominator; must not be unity + * @return a two-element {@long} array with the remainder and quotient in + * the initial and final elements, respectively + */ + private static long[] divRemNegativeLong(long n, long d) { + assert n < 0 : "Non-negative numerator " + n; + assert d != 1 : "Unity denominator"; + // Approximate the quotient and remainder - q = (n >>> 1) / (dLong >>> 1); - r = n - q*dLong; + long q = (n >>> 1) / (d >>> 1); + long r = n - q * d; // Correct the approximation while (r < 0) { - r += dLong; + r += d; q--; } - while (r >= dLong) { - r -= dLong; + while (r >= d) { + r -= d; q++; } - // n - q*dlong == r && 0 <= r 0) { throw new RuntimeException("Incurred " + failures + - " failures while testing exact divide."); + " failures while testing division."); } } } From c7a16db14520c946d7b209fe78efa3da62e60090 Mon Sep 17 00:00:00 2001 From: Katja Kantserova Date: Thu, 12 Feb 2015 10:28:14 +0100 Subject: [PATCH 23/25] 8072856: Eliminate ProcessTools.getProcessId dependency on sun.management.VMManagement Reviewed-by: jbachorik, dfuchs, mchung --- .../testlibrary/jdk/testlibrary/ProcessTools.java | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/jdk/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java b/jdk/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java index 2ed5fcac880..fedcd91f796 100644 --- a/jdk/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java +++ b/jdk/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java @@ -218,19 +218,8 @@ public final class ProcessTools { * @return Process id */ public static int getProcessId() throws Exception { - - // Get the current process id using a reflection hack RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean(); - Field jvm = runtime.getClass().getDeclaredField("jvm"); - - jvm.setAccessible(true); - VMManagement mgmt = (sun.management.VMManagement) jvm.get(runtime); - - Method pid_method = mgmt.getClass().getDeclaredMethod("getProcessId"); - - pid_method.setAccessible(true); - - int pid = (Integer) pid_method.invoke(mgmt); + int pid = Integer.parseInt(runtime.getName().split("@")[0]); return pid; } From 892b06056c33ac73735f737c03a72ab5835d5e4f Mon Sep 17 00:00:00 2001 From: Lev Priima Date: Thu, 12 Feb 2015 10:34:35 -0500 Subject: [PATCH 24/25] 8072909: TimSort fails with ArrayIndexOutOfBoundsException on worst case long arrays Reviewed-by: rriggs, dholmes --- .../classes/java/util/ComparableTimSort.java | 2 +- .../share/classes/java/util/TimSort.java | 2 +- .../java/util/Arrays/TimSortStackSize2.java | 169 ++++++++++++++++++ 3 files changed, 171 insertions(+), 2 deletions(-) create mode 100644 jdk/test/java/util/Arrays/TimSortStackSize2.java diff --git a/jdk/src/java.base/share/classes/java/util/ComparableTimSort.java b/jdk/src/java.base/share/classes/java/util/ComparableTimSort.java index e7c7ac020bd..6237b3fd2e6 100644 --- a/jdk/src/java.base/share/classes/java/util/ComparableTimSort.java +++ b/jdk/src/java.base/share/classes/java/util/ComparableTimSort.java @@ -147,7 +147,7 @@ class ComparableTimSort { */ int stackLen = (len < 120 ? 5 : len < 1542 ? 10 : - len < 119151 ? 24 : 40); + len < 119151 ? 24 : 49); runBase = new int[stackLen]; runLen = new int[stackLen]; } diff --git a/jdk/src/java.base/share/classes/java/util/TimSort.java b/jdk/src/java.base/share/classes/java/util/TimSort.java index 9966f74df37..af66d8092c5 100644 --- a/jdk/src/java.base/share/classes/java/util/TimSort.java +++ b/jdk/src/java.base/share/classes/java/util/TimSort.java @@ -177,7 +177,7 @@ class TimSort { */ int stackLen = (len < 120 ? 5 : len < 1542 ? 10 : - len < 119151 ? 24 : 40); + len < 119151 ? 24 : 49); runBase = new int[stackLen]; runLen = new int[stackLen]; } diff --git a/jdk/test/java/util/Arrays/TimSortStackSize2.java b/jdk/test/java/util/Arrays/TimSortStackSize2.java new file mode 100644 index 00000000000..86194320f59 --- /dev/null +++ b/jdk/test/java/util/Arrays/TimSortStackSize2.java @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2015, 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 8072909 + * @run main/othervm TimSortStackSize2 67108864 + * not for regular execution on all platforms: + * run main/othervm -Xmx8g TimSortStackSize2 1073741824 + * run main/othervm -Xmx32g TimSortStackSize2 2147483644 + * @summary Test TimSort stack size on big arrays + */ +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; + +public class TimSortStackSize2 { + + public static void main(String[] args) { + int lengthOfTest = Integer.parseInt(args[0]); + boolean passed = true; + try { + Arrays.sort(new TimSortStackSize2(lengthOfTest).createArray(), + new Comparator() { + @SuppressWarnings("unchecked") + public int compare(Object first, Object second) { + return ((Comparable)first).compareTo(second); + } + }); + System.out.println("TimSort OK"); + } catch (ArrayIndexOutOfBoundsException e){ + System.out.println("TimSort broken"); + e.printStackTrace(); + passed = false; + } + try { + Arrays.sort(new TimSortStackSize2(lengthOfTest).createArray()); + System.out.println("ComparableTimSort OK"); + } catch (ArrayIndexOutOfBoundsException e){ + System.out.println("ComparableTimSort broken:"); + e.printStackTrace(); + passed = false; + } + if ( !passed ){ + throw new RuntimeException(); + } + } + + private static final int MIN_MERGE = 32; + private final int minRun; + private final int length; + private final List runs = new ArrayList(); + + public TimSortStackSize2(int len) { + this.length = len; + minRun = minRunLength(len); + fillRunsJDKWorstCase(); + } + + private static int minRunLength(int n) { + assert n >= 0; + int r = 0; // Becomes 1 if any 1 bits are shifted off + while (n >= MIN_MERGE) { + r |= (n & 1); + n >>= 1; + } + return n + r; + } + + /** + * Adds a sequence x_1, ..., x_n of run lengths to runs such that:
+ * 1. X = x_1 + ... + x_n
+ * 2. x_j >= minRun for all j
+ * 3. x_1 + ... + x_{j-2} < x_j < x_1 + ... + x_{j-1} for all j
+ * These conditions guarantee that TimSort merges all x_j's one by one + * (resulting in X) using only merges on the second-to-last element. + * @param X The sum of the sequence that should be added to runs. + */ + private void generateJDKWrongElem(long X) { + for(long newTotal; X >= 2*minRun+1; X = newTotal) { + //Default strategy + newTotal = X/2 + 1; + //Specialized strategies + if(3*minRun+3 <= X && X <= 4*minRun+1) { + // add x_1=MIN+1, x_2=MIN, x_3=X-newTotal to runs + newTotal = 2*minRun+1; + } else if(5*minRun+5 <= X && X <= 6*minRun+5) { + // add x_1=MIN+1, x_2=MIN, x_3=MIN+2, x_4=X-newTotal to runs + newTotal = 3*minRun+3; + } else if(8*minRun+9 <= X && X <= 10*minRun+9) { + // add x_1=MIN+1, x_2=MIN, x_3=MIN+2, x_4=2MIN+2, x_5=X-newTotal to runs + newTotal = 5*minRun+5; + } else if(13*minRun+15 <= X && X <= 16*minRun+17) { + // add x_1=MIN+1, x_2=MIN, x_3=MIN+2, x_4=2MIN+2, x_5=3MIN+4, x_6=X-newTotal to runs + newTotal = 8*minRun+9; + } + runs.add(0, X-newTotal); + } + runs.add(0, X); + } + + /** + * Fills runs with a sequence of run lengths of the form
+ * Y_n x_{n,1} x_{n,2} ... x_{n,l_n}
+ * Y_{n-1} x_{n-1,1} x_{n-1,2} ... x_{n-1,l_{n-1}}
+ * ...
+ * Y_1 x_{1,1} x_{1,2} ... x_{1,l_1}
+ * The Y_i's are chosen to satisfy the invariant throughout execution, + * but the x_{i,j}'s are merged (by TimSort.mergeCollapse) + * into an X_i that violates the invariant. + * X is the sum of all run lengths that will be added to runs. + */ + private void fillRunsJDKWorstCase() { + long runningTotal = 0; + long Y = minRun + 4; + long X = minRun; + + while(runningTotal+Y+X <= length) { + runningTotal += X + Y; + generateJDKWrongElem(X); + runs.add(0,Y); + + // X_{i+1} = Y_i + x_{i,1} + 1, since runs.get(1) = x_{i,1} + X = Y + runs.get(1) + 1; + + // Y_{i+1} = X_{i+1} + Y_i + 1 + Y += X + 1; + } + + if(runningTotal + X <= length) { + runningTotal += X; + generateJDKWrongElem(X); + } + + runs.add(length-runningTotal); + } + + private Integer[] createArray() { + Integer[] a = new Integer[length]; + Arrays.fill(a, 0); + int endRun = -1; + for(long len : runs) + a[endRun+=len] = 1; + a[length-1]=0; + return a; + } + +} From 5d4cdb23e5de1896e041262b31472dd763b39197 Mon Sep 17 00:00:00 2001 From: Roger Riggs Date: Thu, 12 Feb 2015 12:06:36 -0500 Subject: [PATCH 25/25] 8072034: (process) ProcessBuilder.start and Runtime.exec UnsupportedOperationException editorial cleanup Reviewed-by: alanb --- .../java.base/share/classes/java/lang/ProcessBuilder.java | 6 +++--- jdk/src/java.base/share/classes/java/lang/Runtime.java | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/lang/ProcessBuilder.java b/jdk/src/java.base/share/classes/java/lang/ProcessBuilder.java index a62594383fc..72b260309d6 100644 --- a/jdk/src/java.base/share/classes/java/lang/ProcessBuilder.java +++ b/jdk/src/java.base/share/classes/java/lang/ProcessBuilder.java @@ -951,9 +951,6 @@ public final class ProcessBuilder * {@code command} array as its argument. This may result in * a {@link SecurityException} being thrown. * - *

If the operating system does not support the creation of - * processes, an {@link UnsupportedOperationException} will be thrown. - * *

Starting an operating system process is highly system-dependent. * Among the many things that can go wrong are: *

    @@ -967,6 +964,9 @@ public final class ProcessBuilder * of the exception is system-dependent, but it will always be a * subclass of {@link IOException}. * + *

    If the operating system does not support the creation of + * processes, an {@link UnsupportedOperationException} will be thrown. + * *

    Subsequent modifications to this process builder will not * affect the returned {@link Process}. * diff --git a/jdk/src/java.base/share/classes/java/lang/Runtime.java b/jdk/src/java.base/share/classes/java/lang/Runtime.java index 98bfe2887b5..114f6cb968f 100644 --- a/jdk/src/java.base/share/classes/java/lang/Runtime.java +++ b/jdk/src/java.base/share/classes/java/lang/Runtime.java @@ -564,9 +564,6 @@ public class Runtime { * cmdarray as its argument. This may result in a * {@link SecurityException} being thrown. * - *

    If the operating system does not support the creation of - * processes, an {@link UnsupportedOperationException} will be thrown. - * *

    Starting an operating system process is highly system-dependent. * Among the many things that can go wrong are: *

      @@ -579,6 +576,9 @@ public class Runtime { * of the exception is system-dependent, but it will always be a * subclass of {@link IOException}. * + *

      If the operating system does not support the creation of + * processes, an {@link UnsupportedOperationException} will be thrown. + * * * @param cmdarray array containing the command to call and * its arguments.